lenec ru

← все посты

Permission denied (publickey) при git push — как починить

13K

Делаешь git push, а в ответ:

git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Сообщение конкретное: SSH-сервер не принял твой ключ. Не пароль, не сам репозиторий, не сетевую связность — именно публичный ключ. Дальше нужно понять, на каком из шагов цепочка ломается.

Алгоритм, по которому я разбираю

Шаг 1: видит ли SSH сервер вообще

Проверяю, доходит ли запрос до GitHub:

ssh -T git@github.com

На GitLab — git@gitlab.com, на Bitbucket — git@bitbucket.org.

Если ответ — что-то вроде «Hi username! You've successfully authenticated» — связь и ключ в порядке, проблема в другом (доступ к конкретному репозиторию). Если Permission denied — пошли разбираться с ключами.

Шаг 2: какой ключ ssh пытается использовать

ssh -vT git@github.com 2>&1 | grep -E 'Offering|identity|debug1: send'

В выводе видишь, какие ключи клиент предлагает серверу. Если там нет твоего id_ed25519, или нужного ключа от рабочего аккаунта — проблема в конфигурации.

Шаг 3: загружен ли ключ в ssh-agent

ssh-add -l

Если ответ The agent has no identities — добавляешь:

ssh-add ~/.ssh/id_ed25519

Если файла нет, его нужно создать.

Создание ключа с нуля

ssh-keygen -t ed25519 -C "me@example.com"

Жмёшь Enter на путь, придумываешь passphrase (можно пустую, но лучше поставить).

Копируешь публичный ключ:

cat ~/.ssh/id_ed25519.pub

На macOS — pbcopy < ~/.ssh/id_ed25519.pub, на Linux с xclip — xclip -sel clip < ~/.ssh/id_ed25519.pub.

Идёшь в настройки GitHub: Settings → SSH and GPG keys → New SSH key. Вставляешь содержимое .pub-файла. Никогда — не приватный ~/.ssh/id_ed25519!

Несколько аккаунтов: рабочий и личный

Самый частый сценарий, в котором всё ломается. У тебя личный ключ id_ed25519 и рабочий id_ed25519_work. Ты делаешь git push в рабочий репозиторий, а ssh по умолчанию предлагает личный, и сервер не пускает.

Решение — конфиг ~/.ssh/config:

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

Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes

Дальше для рабочего репозитория используешь хост github-work:

git remote set-url origin git@github-work:my-org/secret-app.git

SSH прочитает конфиг, поймёт, что для github-work нужен id_ed25519_work, и пушнёт от рабочего аккаунта.

Опция IdentitiesOnly yes важна. Без неё ssh всё равно перебирает все ключи из агента и может предложить личный первым, спалив тем самым твой коммит на рабочий аккаунт.

Шаг 4: права на файлы

SSH очень строгий по правам. Если на ~/.ssh или приватном ключе слишком открытые права, ssh откажется его использовать и не скажет внятно почему.

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/config

Если ключ лежит в шаренной папке или вытащен из чужого архива — права обычно слетают. Лечится одной строкой выше.

Шаг 5: ключ типа RSA и SHA-1

GitHub в 2022-м перестал принимать RSA-ключи, подписанные только SHA-1. Если у тебя старый id_rsa, может прилетать как раз Permission denied (publickey).

Проверка типа:

ssh-keygen -lf ~/.ssh/id_rsa.pub

Если RSA и сомневаешься в свежести — генерируй ed25519. Это короче, безопаснее и точно поддерживается.

Особый случай: использование HTTPS вместо SSH

Иногда проще не воевать с ключами, а ходить по HTTPS с личным токеном. Особенно на корпоративных машинах, где SSH-исходящие закрыты фаерволом.

git remote set-url origin https://github.com/user/repo.git

При первом push потребует логин — указываешь имя пользователя и Personal Access Token вместо пароля. Можно положить в credential helper, чтобы каждый раз не спрашивал.

Я обычно использую gh auth login, чтобы не возиться с токенами руками — он сам ставит правильный credential helper.

Дебаг последней инстанции

GIT_SSH_COMMAND="ssh -vvv" git push 2>&1 | head -100

Тройной -vvv заставит ssh подробно логировать всё: какие ключи он пробует, какие сервер отвечает, на каком этапе обрывается. По этому выводу всегда видно, в чём загвоздка — ключа нет в агенте, права не те, конфиг не подцепил, ключ просто не загружен в GitHub.

Чек-лист

  • ssh -T git@github.com — связь и identity сервера в порядке.
  • ssh-add -l — ключ в агенте.
  • Публичный ключ загружен в настройки GitHub/GitLab/Bitbucket.
  • Права на ~/.ssh и приватный ключ — 700/600.
  • Если несколько аккаунтов — конфиг с IdentitiesOnly yes.
  • RSA на старом ключе — генерируй ed25519.

Permission denied (publickey) — это не загадка. Это конкретный мессадж: «я не понял, кто ты». Каждый из шагов выше отвечает на один вопрос — где именно ssh потерял твою личность. Расставляешь чек-марки по списку — и пуш проходит.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.