# Submodule "Permission denied (publickey)" over SSH in CI

> Fix git submodule "git@github.com: Permission denied (publickey)" in CI - a submodule declared with an SSH URL has no deploy key or SSH agent on the runner.

Source: https://latchkey.dev/learn/git/gcs-submodule-permission-denied-publickey-in-ci  
Updated: 2026-06-30

A submodule uses an SSH remote (`git@github.com:...`) and the runner has no private key SSH can present, so GitHub rejects the connection with "Permission denied (publickey)". HTTPS auth does not apply to SSH remotes.

## Diagnose it: depth, refs, or credentials?

```Terminal
git rev-parse --is-shallow-repository
git rev-parse --abbrev-ref HEAD    # prints HEAD when detached
git log --oneline -3
git remote -v
```

> `actions/checkout` fetches depth 1 on a detached HEAD. Anything diffing against a base, reading a branch name, or running `git describe` needs `fetch-depth: 0`.

## FAQ

### What causes Submodule "Permission denied (publickey)" over SSH in CI?

There are 2 common causes: no ssh deploy key is loaded on the runner and the token-based checkout does not cover ssh submodules. The submodule remote is SSH, but nothing added a private key to an agent, so SSH offers no key and the server denies publickey auth.

### How do I fix Submodule "Permission denied (publickey)" over SSH in CI?

There are 2 fixes depending on which cause you have: load a deploy key with ssh-key on checkout and rewrite ssh submodule urls to authenticated https. Work through them in order, since the first is the most common.

### What does Submodule "Permission denied (publickey)" over SSH in CI actually mean?

The parent repo checks out, then submodule update fails with "git@github.com: Permission denied (publickey).

### How do I stop Submodule "Permission denied (publickey)" over SSH in CI happening again?

Pick one auth style for submodules: deploy key for SSH URLs, or token plus insteadOf for HTTPS. The prevention section lists 3 changes that keep it from recurring.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
