15,048
edits
| Line 9: | Line 9: | ||
'''Error Message''' | '''Error Message''' | ||
After | After running the command: | ||
<pre> | |||
git clone [email protected]:your-org/your-repo.git /opt/your-app | |||
</pre> | |||
you may see the following error: | |||
<pre> | <pre> | ||
| Line 17: | Line 23: | ||
Please make sure you have the correct access rights and the repository exists. | Please make sure you have the correct access rights and the repository exists. | ||
</pre> | |||
A similar error may also occur when running: | |||
<pre> | |||
git pull | |||
</pre> | |||
or: | |||
<pre> | |||
sudo git pull | |||
</pre> | </pre> | ||
'''Cause''' | '''Cause''' | ||
This error occurs when Git cannot authenticate with GitHub over SSH. | This error occurs when Git cannot authenticate with GitHub over SSH. | ||
Common causes include: | |||
* The SSH key does not exist on the server. | |||
* The SSH key has not been added to GitHub. | |||
* The SSH key is added to the wrong GitHub account or the wrong repository. | |||
* The repository is private and the key does not have access. | |||
* The server has multiple SSH keys, but Git is using the wrong one. | |||
* The key is a GitHub Deploy Key that belongs to another repository. | |||
* `sudo git clone` or `sudo git pull` is being used, causing Git to use the `root` user's SSH key instead of the deploy user's SSH key. | |||
For example, if you run: | |||
<pre> | |||
ssh -T [email protected] | |||
</pre> | |||
and see: | |||
<pre> | |||
Hi other-org/other-repo! You've successfully authenticated, but GitHub does not provide shell access. | |||
</pre> | |||
it means the current SSH key is valid, but it is linked to another repository's Deploy Key. In that case, GitHub may return: | |||
<pre> | |||
ERROR: Repository not found. | |||
</pre> | |||
even if the target repository URL is correct. | |||
'''Recommended Solution — Use a dedicated SSH alias for the project''' | |||
This is the safest approach when the server has multiple GitHub Deploy Keys. | |||
Assume: | |||
<pre> | |||
Deploy user: your-user | |||
App path: /opt/your-app | |||
Private key: /home/your-user/.ssh/id_ed25519_your_app | |||
Public key: /home/your-user/.ssh/id_ed25519_your_app.pub | |||
Repository: [email protected]:your-org/your-repo.git | |||
</pre> | |||
'''Step 1 — Check the key exists''' | |||
<pre> | |||
ls -l ~/.ssh/id_ed25519_your_app* | |||
</pre> | |||
Expected result: | |||
<pre> | |||
/home/your-user/.ssh/id_ed25519_your_app | |||
/home/your-user/.ssh/id_ed25519_your_app.pub | |||
</pre> | |||
If the key does not exist, create one: | |||
<pre> | |||
ssh-keygen -t ed25519 -C "your-app-deploy-key" -f ~/.ssh/id_ed25519_your_app | |||
</pre> | |||
'''Step 2 — Add the public key to GitHub''' | |||
Print the public key: | |||
<pre> | |||
cat ~/.ssh/id_ed25519_your_app.pub | |||
</pre> | |||
Add it to the target repository: | |||
<pre> | |||
GitHub Repository | |||
→ Settings | |||
→ Deploy keys | |||
→ Add deploy key | |||
</pre> | |||
If the server only needs to clone or pull the repository, do not enable write access. | |||
''' | '''Step 3 — Configure SSH alias''' | ||
Edit the SSH config file: | |||
<pre> | <pre> | ||
Host github | nano ~/.ssh/config | ||
</pre> | |||
Add: | |||
<pre> | |||
Host github-your-app | |||
HostName github.com | HostName github.com | ||
User git | User git | ||
IdentityFile / | IdentityFile ~/.ssh/id_ed25519_your_app | ||
IdentitiesOnly yes | |||
</pre> | |||
Fix SSH file permissions: | |||
<pre> | |||
chmod 700 ~/.ssh | |||
chmod 600 ~/.ssh/config ~/.ssh/id_ed25519_your_app | |||
chmod 644 ~/.ssh/id_ed25519_your_app.pub | |||
</pre> | </pre> | ||
Explanation: | |||
# <code>~/.ssh</code> should be accessible only by the current user | |||
# <code>~/.ssh/config/</code> should be readable/writable only by the current user | |||
# <code>~/.ssh/id_ed25519_your_app</code> private key should be readable only by the current user | |||
# <code>~/.ssh/id_ed25519_your_app.pub</code> public key can be readable by others | |||
'''Step 4 — Test the SSH alias''' | |||
Run: | |||
<pre> | <pre> | ||
ssh -T - | ssh -T github-your-app | ||
</pre> | </pre> | ||
Expected result: | |||
<pre> | <pre> | ||
Hi your-org/your- | Hi your-org/your-repo! You've successfully authenticated, but GitHub does not provide shell access. | ||
</pre> | </pre> | ||
The message: | |||
<pre> | |||
GitHub does not provide shell access. | |||
</pre> | |||
is expected. It means SSH authentication works, but GitHub does not allow interactive shell login. | |||
If the result shows another repository, for example: | |||
<pre> | |||
Hi other-org/other-repo! You've successfully authenticated, but GitHub does not provide shell access. | |||
</pre> | |||
then the alias is not using the intended key, or the key was added to the wrong repository. | |||
'''Step 5 — Clone using the SSH alias''' | |||
Instead of: | |||
<pre> | |||
git clone [email protected]:your-org/your-repo.git /opt/your-app | |||
</pre> | |||
use: | |||
<pre> | |||
git clone git@github-your-app:your-org/your-repo.git /opt/your-app | |||
</pre> | |||
If `/opt/your-app` requires root permission to create, prefer creating the directory first and assigning ownership to the deploy user: | |||
<pre> | |||
sudo mkdir -p /opt/your-app | |||
sudo chown -R your-user:your-user /opt/your-app | |||
git clone git@github-your-app:your-org/your-repo.git /opt/your-app | |||
</pre> | |||
This avoids using `sudo git clone`. | |||
'''Step 6 — If the repository already exists, update the remote URL''' | |||
Check the current remote: | |||
<pre> | |||
cd /opt/your-app | |||
git remote -v | |||
</pre> | |||
If it uses the default GitHub host: | |||
<pre> | |||
origin [email protected]:your-org/your-repo.git (fetch) | |||
origin [email protected]:your-org/your-repo.git (push) | |||
</pre> | |||
change it to use the SSH alias: | |||
<pre> | |||
git remote set-url origin git@github-your-app:your-org/your-repo.git | |||
</pre> | |||
Verify: | |||
<pre> | |||
git remote -v | |||
</pre> | |||
Expected result: | |||
<pre> | |||
origin git@github-your-app:your-org/your-repo.git (fetch) | |||
origin git@github-your-app:your-org/your-repo.git (push) | |||
</pre> | |||
Then run: | |||
<pre> | |||
git pull | |||
</pre> | |||
'''Avoid using sudo with Git''' | |||
Avoid: | |||
<pre> | |||
sudo git clone [email protected]:your-org/your-repo.git /opt/your-app | |||
sudo git pull | |||
</pre> | |||
Because `sudo` runs Git as `root`, Git may use root's SSH keys instead of the deploy user's SSH keys. | |||
If the app directory is owned by `root`, fix ownership instead: | |||
<pre> | |||
sudo chown -R your-user:your-user /opt/your-app | |||
</pre> | |||
Then run Git commands as the deploy user: | |||
<pre> | |||
cd /opt/your-app | |||
git pull | |||
</pre> | |||
'''Related Issue: dubious ownership''' | |||
If Git shows: | |||
<pre> | |||
fatal: detected dubious ownership in repository at '/opt/your-app' | |||
</pre> | |||
it means the current user and the repository owner do not match. | |||
Check: | |||
<pre> | |||
ls -ld /opt/your-app | |||
whoami | |||
</pre> | |||
If the app should be maintained by the deploy user, fix ownership: | |||
<pre> | |||
sudo chown -R your-user:your-user /opt/your-app | |||
</pre> | |||
Alternatively, mark the directory as safe: | |||
<pre> | |||
git config --global --add safe.directory /opt/your-app | |||
</pre> | |||
For deployment directories, fixing ownership is usually cleaner if the deploy user is expected to run `git pull`. | |||
'''Alternative Solution — Pass the SSH key inline''' | |||
You can also override the SSH command directly. | |||
First, test the key: | |||
<pre> | |||
ssh -T -i /path/to/.ssh/your_key_name -o IdentitiesOnly=yes [email protected] | |||
</pre> | |||
Expected result: | |||
<pre> | |||
Hi your-org/your-repo! You've successfully authenticated, but GitHub does not provide shell access. | |||
</pre> | |||
Then clone: | |||
<pre> | |||
GIT_SSH_COMMAND='ssh -i /path/to/.ssh/your_key_name -o IdentitiesOnly=yes' \ | |||
git clone [email protected]:your-org/your-repo.git /opt/your-app | |||
</pre> | |||
If you need to run this with `sudo`, preserve the environment explicitly: | |||
<pre> | <pre> | ||
| Line 59: | Line 336: | ||
</pre> | </pre> | ||
However, this is usually less clean than using an SSH alias, especially for long-term maintenance. | |||
'''Notice''' | |||
<pre> | |||
-o IdentitiesOnly=yes | |||
</pre> | |||
forces SSH to use only the specified key and prevents SSH from trying other keys loaded in the agent. This is important on servers with multiple Deploy Keys. | |||
'''Summary''' | |||
Recommended long-term setup: | |||
<pre> | |||
# 1. Create or confirm a dedicated deploy key | |||
ls ~/.ssh/id_ed25519_your_app* | |||
# 2. Add the public key to the target GitHub repository Deploy Keys | |||
cat ~/.ssh/id_ed25519_your_app.pub | |||
# 3. Configure SSH alias | |||
nano ~/.ssh/config | |||
# 4. Test alias | |||
ssh -T github-your-app | |||
# 5. Clone or update remote using alias | |||
git clone git@github-your-app:your-org/your-repo.git /opt/your-app | |||
# or, for an existing repo | |||
cd /opt/your-app | |||
git remote set-url origin git@github-your-app:your-org/your-repo.git | |||
git pull | |||
</pre> | |||
The key lesson is: when multiple Deploy Keys exist on the same server, avoid relying on `[email protected]`. Use a project-specific SSH alias such as: | |||
<pre> | |||
git@github-your-app:your-org/your-repo.git | |||
</pre> | |||
so Git always uses the correct SSH key. | |||
=== Git Submodule Pull Failed: unable to create file — File exists === | === Git Submodule Pull Failed: unable to create file — File exists === | ||