English Version
- Own key pair for each account (see article)
- macOS Monterey (so far only tested here)
- Basic knowledge iTerm2 or Terminal
Sometimes it makes sense to clean up everything so far. This is optional for me. Since I have already paid attention to which key I generate and use, this is not necessary for me. Nevertheless I want to describe the steps here. Navigate to the ssh location:
cd ~/.ssh
Now I clean up the existing configuration by deleting the config
, known_hosts
and other ssh files with public and private keys using rm filename
.
Now I still need to clean the SSH agent with:
ssh-add -D
First, I have a single location for SSH keys on my Macbook: ~/.ssh
. Here I also find the default key id_rsa
. I create a separate key pair for each account on GitHub (and GitLab) (see article).
# Key for my private GitHub account:
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/ed25519_privat-github -C "[email protected]"
# Key for my company GitHub account:
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/ed25519_firma-github -C "[email protected]"
With this I created two new key pairs named ed25519_privat-github
and ed25519_firma-github
.
The public and private key can now be found in ~/.ssh
. Next, I copy the public key into the respective GitHub or GitLab account. The new key can be added at https://github.com/settings/keys or https://gitlab.com/-/profile/keys.
# Copy public key from private GitHub to clipboard
pbcopy < ~/.ssh/ed25519_privat-github.pub
Now the account trusts the particular .pub key, but my Macbook still sends the id_rsa key when I run an ssh git command. My Macbook does not know that there is a new key with a different name, and even if it knew, it would not try all the keys found in ~/.ssh
.
The solution is a configuration file in '~/.ssh`. To create this, I run nano config in the .ssh directory:
nano ~/.ssh/config
Here I now define all the keys I need.
# private GitHub account
Host github.com-privat
HostName github.com
AddKeysToAgent yes
UseKeyChain yes
IdentityFile ~/.ssh/ed25519_privat-github
ServerAliveInterval 600
TCPKeepAlive yes
IPQoS=throughput
# company GitHub account
Host github.com-firma
HostName github.com
AddKeysToAgent yes
UseKeyChain yes
IdentityFile ~/.ssh/ed25519_firma-github
ServerAliveInterval 600
TCPKeepAlive yes
IPQoS=throughput
Note: I have added additional lines to the configuration here to maintain the server connection and to avoid disconnections. This helps with the following errors:
Broken pipe fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
This configuration file now causes my Macbook to use the private SSH key to access the host github.com-private and to use the company SSH key now for the host github.com-company.
First I start the SSH agent in my iTerm2:
eval "$(ssh-agent -s)"
Add key to SSH agent:
ssh-add --apple-use-keychain ~/.ssh/ed25519_privat-github
ssh-add --apple-use-keychain ~/.ssh/ed25519_firma-github-ad
Verify that the keys are stored in the SSH agent:
ssh-add -l
Note: The SSH agent on the Mac loses the keys on reboot. I can work around this by simply running this command when I restart my Macbook:
ssh-add --apple-load-keychain
I enter the following command in iTerm2:
ssh -T [email protected]
Now when I am asked to add the hosts to my know_hosts file, I confirm this with yes
.
The authenticity of host 'github.com (140.82.121.3)' can't be established.
ED25519 key fingerprint is <key>.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
I should now see a confirmation that I am connected:
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
Hi <username>! You've successfully authenticated, but GitHub does not provide shell access.
I now perform these steps for all accounts or assigned SSH keys.
The next step is to customize my Git project.
Before: [email protected]:username/projekt.git
After: [email protected]:username/projekt.git
# Clone private git project
git clone [email protected]:username/projekt.git
# Companies Git project clone
git clone [email protected]:username/projekt.git
I switch to the existing Git project and edit the configuration with
nano .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = [email protected]:username/project.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
I update the remote URL to the newly created account reference:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = [email protected]:username/project.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
Now I should give the respective Git project a name and an email address. There are several possibilities for this.
Change to the Git project directory
cd Git-Project
Now I add the name and the email address belonging to the account
git config user.name "My Name"
git config user.email "[email protected]"
This means that locally in the Git project the email and the name are now set.
I change back to my user directory
cd
Now I create a Git configuration file for myself:
nano .gitconfig
In this I define an explicit .gitconfig
file for each explicit path, in which name and email address is then stored:
[includeIf "gitdir:~/Developer/GitLab.com/Firma/"]
path = ~/Developer/GitLab.com/Firma/.gitconfig
[includeIf "gitdir:~/Developer/GitHub.com/Privat/"]
path = ~/Developer/GitHub.com/Privat/.gitconfig
[core]
excludesfile = ~/.gitignore_global
In this case I have mapped my personal development environment. Under the folder ~/Developer/GitLab.com/Firma/
are all my Git projects from my company account. Under ~/Developer/GitHub.com/Privat/
are my Git projects from my private account.
Nun lege ich in jedem Ordner noch die oben definierte .gitconfig
an
cd ~/Developer/GitLab.com/Firma/
nano .gitconfig
There I now store the configurations for the company Git projects:
[user]
# Insert GitHub deposited email
email = [email protected]
# Insert name
name = Max Mustermann
# Insert GitHub username
username = myusername
[github]
# Insert GitHub username
user = "myusername"
Now I check if all configurations are available. To do this, I switch to an already cloned project and check the configuration:
cd ~/Developer/GitLab.com/Firma/project
git config --list
The result should look like this:
credential.helper=osxkeychain
includeif.gitdir:~/Developer/GitHub.com/Privat/.path=~/Developer/GitHub.com/Privat/.gitconfig
[email protected]
user.name=Max Mustermann
user.username=meinusername
github.user=meinusername
includeif.gitdir:~/Developer/GitHub.com/Firma/.path=~/Developer/GitHub.com/Firma/.gitconfig
core.excludesfile=~/.gitignore_global
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
[email protected]:firma/project.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
This way, when cloning a git repository, I save myself from always having to add email and username to the .git/config
(as with the simple method).
This is a copy of my German post I wrote on my blog: https://psycho0verload.it/2022/05/22/mehrere-ssh-schluessel-fuer-verschiedene-github-konten-auf-macos-monterey-12-4/
Deutsche Version
- Vorraussetzungen
- Anleitung
- Quelle
- Eigenes Schlüsselpaar für jeden Account (siehe Artikel)
- macOS Monterey (bisher nur hier getestet)
- Grundlagenwissen iTerm2 bzw. Terminal
Manchmal macht es Sinn alles bisherige aufzuräumen. Dies ist für mich optional. Da ich selbst vorher schon darauf geachtet habe welchen Schlüssel ich generiere und benutze fällt das für mich weg. Trotzdem möchte ich die Schritte hier kurz beschreiben. Navigieren zum ssh-Speicherort:
cd ~/.ssh
Nun bereinige ich die bestehende Konfiguration, indem ich die config
, known_hosts
und andere ssh-Dateien mit öffentlichen und privaten Schlüsseln mittels rm dateiname
löschen.
Nun muss ich noch den SSH-Agenten reinigen mit:
ssh-add -D
Zunächst habe ich auf meinem Macbook einen einzigen Speicherort für SSH-Schlüssel: ~/.ssh
. Hier find ich auch den Standardschlüssel id_rsa
. Ich lege für jeden Account auf GitHub (und GitLab) einen eigenes Schlüsselpaar an (siehe Artikel).
# Schlüssel für mein privaten GitHub-Account:
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/ed25519_privat-github -C "[email protected]"
# Schlüssel für mein firmen GitHub-Account:
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/ed25519_firma-github -C "[email protected]"
Damit habe ich zwei neue Schlüsselpaare mit den Namen ed25519_privat-github
und ed25519_firma-github
angelegt.
Der öffentliche und der private Schlüssel ist nun unter ~/.ssh
zu finden. Als nächstes kopiere ich den öffentlichen Schlüssel in den jeweiligen GitHub- oder GitLab-Account. Der neue Schlüssel kann unter https://github.com/settings/keys bzw. https://gitlab.com/-/profile/keys hinzugefügt werden.
# Öffentlichen Schlüssel vom privaten GitHub in die Zwischenablage kopieren
pbcopy < ~/.ssh/ed25519_privat-github.pub
Jetzt vertraut der Account dem jeweiligen .pub-Schlüssel, aber mein Macbook sendet immer noch den id_rsa-Schlüssel, wenn ich einen ssh-Git-Befehl ausführe. Mein Macbook weiß nicht, dass es einen neuen Schlüssel mit anderem Namen gibt, und selbst wenn er es wüsste, würde er nicht alle Schlüssel, die unter ~/.ssh
zufinden sind, durchprobieren.
Die Lösung ist eine Konfigurationsdatei in '~/.ssh`. Um diese zu erstellen, führe ich nano config im .ssh-Verzeichnis aus:
nano ~/.ssh/config
Hier definiere ich nun alle Schlüssel, die ich benötige.
# privater GitHub-Account
Host github.com-privat
HostName github.com
AddKeysToAgent yes
UseKeyChain yes
IdentityFile ~/.ssh/ed25519_privat-github
ServerAliveInterval 600
TCPKeepAlive yes
IPQoS=throughput
# firmen GitHub-Account
Host github.com-firma
HostName github.com
AddKeysToAgent yes
UseKeyChain yes
IdentityFile ~/.ssh/ed25519_firma-github
ServerAliveInterval 600
TCPKeepAlive yes
IPQoS=throughput
Hinweis: Ich habe hier zusätzliche Zeilen zur Konfiguration hinzugefügt, um die Serververbindung aufrechtzuerhalten und um Verbindungsabbrüche zu vermeiden. Dies hilft bei folgende Fehler:
Broken pipe fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
Diese Konfigurationsdatei bewirkt nun, dass meinem Macbook den privaten SSH-Schlüssel für den Zugriff auf den Host github.com-privat verwendet und den firmen SSH-Schlüssel nun für den Host github.com-firma verwendet.
Als erstes starte ich den SSH-Agenten in meinem iTerm2:
eval "$(ssh-agent -s)"
Schlüssel zum SSH-Agenten hinzufügen:
ssh-add --apple-use-keychain ~/.ssh/ed25519_privat-github
ssh-add --apple-use-keychain ~/.ssh/ed25519_firma-github-ad
Überprüfen, dass die Schlüssel im SSH-Agent gespeichert sind:
ssh-add -l
Hinweis: Der SSH-Agent auf dem Mac verliert die Schlüssel beim Neustart. Ich kann das umgehen, indem ich beim Neustart meines Macbooks einfach diesen Befehl ausführe:
ssh-add --apple-load-keychain
Ich gebe folgenden Befehl in iTerm2 ein:
ssh -T [email protected]
Wenn ich nun aufgefordert werde, die Hosts zu meiner know_hosts-Datei hinzuzufügen, bestätige ich das mit yes
The authenticity of host 'github.com (140.82.121.3)' can't be established.
ED25519 key fingerprint is <key>.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Ich sollte nun eine Bestätigung sehen, dass ich verbunden bin:
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
Hi <username>! You've successfully authenticated, but GitHub does not provide shell access.
Diese Schritte führe ich nun für alles Accounts bzw. zugeordnete SSH-Schlüssel durch.
Im nächsten Schritt muss ich mein Git-Projekt anpassen.
Vorher: [email protected]:username/projekt.git
Nachher: [email protected]:username/projekt.git
# Privates Git-Projekt clonen
git clone [email protected]:username/projekt.git
# Firmen Git-Projekt clonen
git clone [email protected]:username/projekt.git
Ich wechsel zum vorhandenen Git-Projekt und bearbeite die Konfiguration mit
nano .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = [email protected]:username/project.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
Ich aktualisiere den Remote-URL auf die neu erstellte Konto-Referenz:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = [email protected]:username/project.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
Nun sollte ich dem jeweiligen Git-Projekt noch einen Namen und eine Email-Adresse mitgeben. Hierfür gibt es mehrere Möglichkeiten.
In das Git-Projekt-Verzeichnis wechseln
cd Git-Projekt
Nun füge ich den Name und die zum Account gehörende Email-Adresse hinzu
git config user.name "Mein Name"
git config user.email "[email protected]"
Damit ist lokal im Git-Projekt nun die Email und der Name gesetzt.
Ich wechsele wieder in mein User-Verzeichnis
cd
Nun lege ich mir eine Git-Konfigurationsdatei an:
nano .gitconfig
In dieser definiere ich für einen expliziten Pfad jeweils eine explizite .gitconfig-Datei in welcher Name und Email-Adresse dann hinterlegt wird:
[includeIf "gitdir:~/Developer/GitLab.com/Firma/"]
path = ~/Developer/GitLab.com/Firma/.gitconfig
[includeIf "gitdir:~/Developer/GitHub.com/Privat/"]
path = ~/Developer/GitHub.com/Privat/.gitconfig
[core]
excludesfile = ~/.gitignore_global
In diesem Fall habe ich meine persönliche Entwicklungsumgebung abgebildet. Unter dem Ordner ~/Developer/GitLab.com/Firma/
befinden sich bei mir alle Git-Projekte meines Firmen-Accounts. Unter ~/Developer/GitHub.com/Privat/
dementsprechen meine Git-Projekt von meinem Privaten-Account.
Nun lege ich in jedem Ordner noch die oben definierte .gitconfig
an
cd ~/Developer/GitLab.com/Firma/
nano .gitconfig
Dort hinterlege ich nun die Konfiguartionen für die Firmen-Git-Projekte:
[user]
# GitHub hinterlege Email einfügen
email = [email protected]
# Name einfügen
name = Max Mustermann
# GitHub Username einfügen
username = meinusername
[github]
# GitHub Username einfügen
user = "meinusername"
Nun kontrolliere ich noch ob alle Konfigurationen verfügbar sind. Dafür wechsele ich in ein bereits geclontes Projekt und überprüfe die Konfiguration:
cd ~/Developer/GitLab.com/Firma/project
git config --list
Das Ergebnis sollte so aussehen:
credential.helper=osxkeychain
includeif.gitdir:~/Developer/GitHub.com/Privat/.path=~/Developer/GitHub.com/Privat/.gitconfig
[email protected]
user.name=Max Mustermann
user.username=meinusername
github.user=meinusername
includeif.gitdir:~/Developer/GitHub.com/Firma/.path=~/Developer/GitHub.com/Firma/.gitconfig
core.excludesfile=~/.gitignore_global
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
[email protected]:firma/project.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
So erspare ich mir beim clonen eines Git-Repositories, dass ich immer die .git/config
um Email und Benutzername ergänzen muss (wie bei der einfachen Methode).
Dies ist eine Kopie meines deutschen Beitrages den ich in meinem Blog geschrieben habe: https://psycho0verload.it/2022/05/22/mehrere-ssh-schluessel-fuer-verschiedene-github-konten-auf-macos-monterey-12-4/