SSH из GitLab CI не доверяет серверу: передаём проверенный known_hosts
Ручное подключение к серверу проходит, а новая CI-job завершается с Host key verification failed. В контейнере нет истории доверенных серверов с ноутбука разработчика, и SSH не может интерактивно спросить, принимать ли неизвестный ключ. Приватный ключ для входа уже настроен, но он решает другую задачу: сервер проверяет клиента, а клиент ещё должен проверить сервер.
Для автоматического подключения полезно заранее подготовить known_hosts с проверенным публичным ключом нужного сервера. Тогда job получает определённое ожидание и останавливается, если удалённая сторона предъявляет другой ключ. Это особенно важно для деплоя: отказ проверки лучше, чем отправка команды неизвестному узлу с похожим адресом.
Передать готовый файл доверия
Получите ключ через доверенный административный канал и сверяйте его fingerprint с ожидаемым сервером. Затем сохраните содержимое known_hosts в GitLab как переменную типа File с именем SSH_KNOWN_HOSTS. Переменная будет содержать путь к файлу, а не его текст. В контейнерной job подготовка выглядит так:
before_script: - mkdir -p ~/.ssh - chmod 700 ~/.ssh - cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts - chmod 644 ~/.ssh/known_hosts
Это дополнение к настройке самого SSH-клиента и приватного ключа, а не полный pipeline деплоя. Образ задания должен содержать openssh-client. Для проверки можно выполнить безопасную удалённую команду вроде проверки версии приложения, прежде чем подключать изменение файлов или перезапуск сервиса.
Не формируйте доверие командой ssh-keyscan прямо перед соединением в той же job. Такой шаг получает ключ по текущей сети и сразу объявляет его правильным. Он делает запуск неинтерактивным, но не даёт независимой проверки идентичности сервера. SSH_KNOWN_HOSTS должен поступать из заранее проверенной настройки, а не из ответа того узла, который job как раз пытается проверить.
Согласовать имя и порт
Запись known_hosts должна соответствовать адресу, которым реально пользуется ssh. Подключение по имени и по IP может требовать разных записей. Для нестандартного порта используется соответствующая форма имени с портом. Поэтому при смене SSH_HOST или порта проверьте и файл доверия, а не только переменную приватного ключа.
На тестовом сервере проверьте успешное подключение с правильной записью и отказ с подменённой. Вторая проверка подтверждает, что защита действительно действует. Не добавляйте StrictHostKeyChecking=no ради зелёного pipeline: тогда исчезает именно тот контроль, который мы сейчас настраиваем.
После плановой переустановки сервера изменение ключа нужно подтвердить и обновить в переменной как отдельное действие. Не удаляйте старую запись автоматически при любом предупреждении. Для CI новый known_hosts — часть конфигурации выпуска, поэтому полезно записать владельца настройки и процедуру проверки fingerprint. Тогда чистый runner подключается предсказуемо, а неожиданная смена удалённого ключа остаётся заметным событием.
Продолжить практику
Исправление одной job полезно закрепить в полном процессе выпуска. В программе курса «GitLab CI/CD: автоматизация сборки и деплоя» — pipeline учебного приложения с проверками, тестами, сборкой Docker-образа, registry и staging. Отдельно разбираются runners, секреты, нестабильные запуски и возврат к предыдущему образу. Такой проект помогает увидеть, как решение внутри одной job влияет на выпуск версии и дальнейший откат.
Источник: официальная документация.
Другие задачи по теме: Окружение задания и повторяемый pipeline.
Продолжить на практике
- GitLab CI/CD: автоматизация сборки и деплоя ↗
От первого .gitlab-ci.yml до pipeline, который тестирует код, собирает образ и выкладывает приложение. Runners, artifacts, cache, registry, окружения и безопасный откат — на одном практическом проекте.
