git

GitLab Permission denied (publickey): SSH-ключ, agent и типичные ошибки

Ошибка git@gitlab.com: Permission denied (publickey). fatal: Could not read from remote repository значит одно: GitLab не принял ваш SSH-ключ. Репозиторий при этом может существовать, доступ по HTTPS — работать, а git fetch/git push по SSH — нет. Ниже рабочий чеклист для Windows, macOS и Linux без «магии».

Что проверить за 2 минуты

  1. Вы действительно ходите по SSH, а не по HTTPS: remote вида git@gitlab.com:group/project.git.
  2. Ключ есть локально: файлы ~/.ssh/id_ed25519 + id_ed25519.pub (или id_rsa / id_rsa.pub).
  3. Публичный ключ добавлен в GitLab: Preferences → SSH Keys (или ключ деплоя в настройках проекта).
  4. ssh-agent знает приватный ключ (особенно на Windows и при нескольких ключах).

1. Создать ключ (если ещё нет)

Предпочтительный алгоритм сейчас — Ed25519:

ssh-keygen -t ed25519 -C "you@example.com" -f ~/.ssh/id_ed25519

Парольную фразу лучше задать. На старых системах, где Ed25519 не принимают, используйте RSA 4096:

ssh-keygen -t rsa -b 4096 -C "you@example.com" -f ~/.ssh/id_rsa

В GitLab вставляют только содержимое .pub. Приватный ключ никуда не копируют.

2. Добавить ключ в GitLab

# Linux / macOS
cat ~/.ssh/id_ed25519.pub

# Windows (Git Bash / PowerShell)
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub

Откройте https://gitlab.com/-/user_settings/ssh_keys (self-hosted — свой URL), вставьте ключ целиком, начиная с ssh-ed25519 или ssh-rsa, сохраните. Для CI/сервера чаще используют Deploy Key в настройках конкретного репозитория — он не равен личному ключу аккаунта.

3. Проверить соединение

ssh -T git@gitlab.com

Ожидаемый ответ вроде Welcome to GitLab, @username!. Если снова Permission denied — смотрите подробно:

ssh -vT git@gitlab.com

В логе ищите строки Offering public key и Authentication succeeded. Если ключ не предлагается — проблема в agent/config, а не в GitLab.

4. ssh-agent и несколько ключей

На Linux/macOS:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

На Windows с OpenSSH-сервисом agent обычно уже есть; в Git Bash:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

Если ключей несколько (работа / личка / self-hosted), зафиксируйте Host в ~/.ssh/config:

Host gitlab.com
  HostName gitlab.com
  User git
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes

Host gitlab.company.local
  HostName gitlab.company.local
  User git
  IdentityFile ~/.ssh/id_company
  IdentitiesOnly yes

IdentitiesOnly yes критичен: иначе ssh перебирает слишком много ключей, и сервер может ответить denied до нужного.

5. Частые причины на практике

  • Ключ добавлен не в тот аккаунт — клон под другим пользователем GitLab.
  • Вставлен приватный ключ вместо .pub — GitLab отвергнет.
  • Ключ истёк / отозван — в UI SSH Keys проверьте срок и список.
  • Self-hosted на нестандартном порту — в config укажите Port 2222.
  • Корпоративный прокси / firewall режет 22/tcp — иногда дают SSH на 443; уточните у админов.
  • Wrong remote URL — опечатка в group/project; тогда после успешного SSH будет уже «repository not found».
  • Права на файлы ключа слишком открытые (Linux): chmod 600 ~/.ssh/id_ed25519, chmod 700 ~/.ssh.

6. Временный обход через HTTPS

Если нужно срочно пушнуть, можно переключить remote на HTTPS и использовать personal access token вместо пароля:

git remote -v
git remote set-url origin https://gitlab.com/group/project.git
git push

Это обход, не замена SSH на серверах CI и на BitrixVM, где ключ удобнее токена в интерактиве.

Вывод

Permission denied (publickey) почти никогда не лечится «переустановкой Git». Цепочка одна: локальный ключ → agent/config → публичный ключ в GitLab → ssh -T успешен → remote на git@.... Пройдите её сверху вниз с ssh -vT, и ошибка уходит за один проход.