Repository navigation
GitHub Authentication
GitHub Mirror Backup uses two separate authentication mechanisms:
Purpose | Authentication -- | -- Repository discovery | GitHub Personal Access Token Git repository transfer | SSH keyThis separation is intentional. The Personal Access Token is used only for the GitHub API, while Git itself communicates with GitHub through SSH.
The script needs an access token to query the repositories available to the authenticated account.
A GitHub Classic Personal Access Token can be used for this purpose.
The token must be able to read the repositories you want to back up.
For a classic token, the repo scope provides access to private repositories.
Never put the token directly into the backup script.
Store it in a separate file instead.
Create the configuration directory:
mkdir -p ~/.config/github
chmod 700 ~/.config/github
Create the token file:
nano ~/.config/github/token
Put the token into the file as a single line.
Then restrict the file permissions:
chmod 600 ~/.config/github/token
The resulting layout should look like:
~/.config/github/
└── token
The backup script reads this file automatically.
Git operations use SSH rather than HTTPS.
The machine running the backup therefore needs an SSH key registered with GitHub.
Check whether a key already exists:
ls -la ~/.ssh/
Common key types include:
id_ed25519
id_ed25519.pub
If necessary, create a new Ed25519 key:
ssh-keygen -t ed25519 -C "github-backup"
Do not put the private key into the GitHub repository.
Display the public key:
cat ~/.ssh/id_ed25519.pub
Copy the entire line and add it to the SSH keys section of your GitHub account.
The public key can safely be registered with GitHub.
The private key must remain on the backup machine.
Run:
ssh -T git@github.com
A successful authentication produces a message similar to:
Hi USERNAME! You've successfully authenticated, but GitHub does not provide shell access.
This is expected.
GitHub does not provide an interactive shell through this SSH endpoint. The message confirms that authentication itself succeeded.
The backup script performs the API authentication automatically.
You can manually test the token with:
curl -fsSL \
-H "Authorization: Bearer $(cat ~/.config/github/token)" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/user
A successful response contains the authenticated GitHub account information.
Do not paste the response containing private account information into public issue trackers.
The API and Git transport solve different problems.
The API answers:
"Which repositories can this account access?"
The script uses it to discover repositories, including private repositories and repositories accessible through organizations or collaboration.
SSH answers:
"How do I download the actual Git repository?"
The script uses each repository's SSH URL:
git@github.com:owner/repository.git
This means the Personal Access Token is not used as a Git password.
The token is deliberately not passed as a command-line argument.
Instead, the script supplies the authorization header to curl through standard input.
This avoids exposing the token in the process command line.
The token is also not written into Git remote URLs.
For example, the script does not create remotes like:
https://TOKEN@github.com/owner/repository.git
Instead, the remote remains an SSH URL:
git@github.com:owner/repository.git
The token file should only be readable by its owner:
chmod 600 ~/.config/github/token
The SSH private key should have similarly restrictive permissions:
chmod 600 ~/.ssh/id_ed25519
The public key can remain readable:
chmod 644 ~/.ssh/id_ed25519.pub
Run:
ssh -vT git@github.com
Check that:
the correct private key exists
the corresponding public key is registered with GitHub
the SSH agent is available if the key requires one
network access to GitHub SSH is available
Check that the token file exists:
ls -l ~/.config/github/token
Check that it contains exactly one token:
wc -l ~/.config/github/token
Then test the API request again.
The script checks both identities.
For example:
API account csiber
SSH account another-user
This is reported as a mismatch.
This matters because the API may discover repositories belonging to one account while the SSH key belongs to another account with different repository permissions.
The complete authentication flow is therefore:
GitHub
│
┌────────┴─────────┐
│ │
REST API SSH
│ │
PAT token SSH key
│ │
▼ ▼
Repository Git repository
discovery transfer
│ │
└────────┬─────────┘
▼
Local mirror
Keeping these two authentication paths separate makes the backup process easier to understand and avoids putting long-lived API credentials into Git configuration.