Служба хостинга репозиториев: доступ по ssh не работает
Хостинг репозиториев может обслуживать доступ по ssh двумя способами: встроенным сервером на своём порту или через системный сервер с отдельным пользователем. Смешение двух схем даёт отказы, которые выглядят как проблема с ключами.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Встроенный сервер не слушает порт
При включённом встроенном сервере он должен слушать свой порт. Если порт занят или отключён, клиенты получают отказ соединения.
-
Ключи пользователя службы недоступны
При работе через системный сервер ключи лежат в домашнем каталоге отдельного пользователя. Изоляция unit-файла может закрыть к ним доступ.
-
Служба запускается раньше базы данных
При внешней базе служба стартует первой, не находит её и завершается. Клиенты видят отказ соединения, хотя причина в порядке запуска.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Кто слушает порты доступа по ssh.
sudo ss -tlnp | grep -E ":22|:2222"Сообщения службы при запуске.
journalctl -u gitea -n 30 --no-pagerПользователь, изоляция и порядок запуска.
systemctl show gitea -p User -p ProtectHome -p AfterРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- При включённом встроенном сервере он должен слушать свой порт. Если порт занят или отключён, клиенты получают отказ соединения.
- Как проверить
-
Посмотрите настройки и слушателей.
sudo grep -A5 "^\[server\]" /etc/gitea/app.ini 2>/dev/null | head sudo ss -tlnp | grep -E ":22|:2222"
- Как исправить
- Разведите порты встроенного и системного серверов ssh либо выберите одну схему. Держать оба на одном порту нельзя.
- Почему происходит
- При работе через системный сервер ключи лежат в домашнем каталоге отдельного пользователя. Изоляция unit-файла может закрыть к ним доступ.
- Как проверить
-
Посмотрите права на ключи и параметры изоляции.
sudo ls -la /var/lib/gitea/.ssh/ 2>/dev/null systemctl show gitea -p ProtectHome -p User -p ReadWritePaths
- Как исправить
-
Отключите защиту домашних каталогов для этой службы или перенесите ключи в каталог состояния и разрешите к нему запись.
[Service] ProtectHome=no StateDirectory=gitea
- Почему происходит
- При внешней базе служба стартует первой, не находит её и завершается. Клиенты видят отказ соединения, хотя причина в порядке запуска.
- Как проверить
-
Посмотрите порядок запуска и сообщение при старте.
systemctl show gitea -p After -p Wants journalctl -u gitea -n 20 --no-pager | grep -iE "database|connection"
- Как исправить
-
Добавьте зависимость от базы и перезапуск при сбое: ожидание готовности базы надёжнее ожидания её запуска.
[Unit] After=postgresql.service Wants=postgresql.service [Service] Restart=on-failure RestartSec=5
Пример вывода
Встроенный сервер не поднялся: порт занят системным. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
gitea[6300]: Failed to start SSH server: listen tcp 0.0.0.0:22: bind: address already in use
gitea[6300]: [FATAL] Unable to start SSH server
systemd[1]: gitea.service: Main process exited, code=exited, status=1/FAILURE
Связанные ошибки
- Address already in use при запуске службы Порт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- sshd: отказ аутентификации из-за прав на файлы Вход по ключу не работает: слишком широкие права на домашний каталог или authorized_keys. Разбор через журнал sshd.
- Служба не запускается вместе с зависимостью After= без Wants= не запускает зависимость. Разбор частой путаницы между порядком и необходимостью.
- Apache: could not bind to address Apache не занимает порт: конфликт с nginx, порт занят, нет прав на привилегированный порт.
- BIND: порт 53 занят systemd-resolved named не может занять порт 53: его держит локальный разрешатель имён. Как развести их по адресам.
- Caddy не занимает порты 80 и 443 без прав Служба падает при открытии слушателя: нет возможности занимать привилегированные порты.
- Connection closed by authenticating user: вход обрывается Клиент отключается на этапе проверки подлинности: не тот ключ, перебор или ограничение по адресу.
- PostgreSQL: could not bind IPv4 address Кластер PostgreSQL не занимает порт: адрес занят другим экземпляром или остался файл сокета. Разбор.
Где встречается чаще всего
Источники
- Документация Gitea: настройки сервера
-
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено включением встроенного сервера на занятом порту.