Da GitHub nicht mehr den selben SSH-Schlüssel für zwei verschiedene Konten zulässt, ist die Verwendung von zwei verschiedenen Konten (z. B. einem privaten und einem Firmenkonto) etwas komplizierter. Mit dem Standard ssh-keygen geht es nicht mehr.

Lernziel

Ziel dieses Beitrags ist es auf meinem Macbook Pro mit macOS Monterey auf mehrer GitHub- bzw GitLab-Konten mit jeweils eigenen SSH-Schlüssel zugreifen zu können.

Vorraussetzungen

  • Eigenes Schlüsselpaar für jeden Account (siehe Artikel)
  • macOS Monterey (bisher nur hier getestet)
  • Grundlagenwissen iTerm2 bzw. Terminal

Anleitung

Bereinigen von ssh-Verzeichnis & SSH-Agenten (Optional)

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

Der SSH-Schlüssel

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 Beitrag).

# Schlüssel für mein privaten GitHub-Account:
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/ed25519_privat-github -C "privat@github.com"

# Schlüssel für mein firmen GitHub-Account:
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/ed25519_firma-github -C "firma@github.com"

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.

Konfigurationsdatei für SSH-Schlüssel anpassen

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.

SSH-Schlüssel zum SSH-Agenten hinzufügen

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

Login via SSH-Schlüssel überprüfen

Ich gebe folgenden Befehl in iTerm2 ein:

ssh -T git@github.com-privat

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.

Git-Projekte anpassen

Im nächsten Schritt muss ich mein Git-Projekt anpassen.

Git-Projekt clonen

# Privates Git-Projekt clonen
git clone git@github.com-privat:username/projekt.git

# Firmen Git-Projekt clonen
git clone git@github.com-firma:username/projekt.git

Vorhandes Git-Projekt anpassen

Ich wechsle 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 = git@github.com: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 = git@github.com-privat:username/project.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
        remote = origin
        merge = refs/heads/main

Git-Projekt den Name & Email mitgeben

Nun sollte ich dem jeweiligen Git-Projekt noch einen Namen und eine Email-Adresse mitgeben. Hierfür gibt es mehrere Möglichkeiten.

Einfachste Methode

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 "meine@email.de" 

Damit ist lokal im Git-Projekt nun die Email und der Name gesetzt.

Aufwendigere Methode

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 = meine@email.de
        # 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
user.email=meine@email.de
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
remote.origin.url=git@github.com-firma: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.

Quellen

  • https://medium.com/@dinesh.papineni/configure-multiple-github-accounts-with-ssh-keys-on-macos-d8873867d311
  • https://gist.github.com/jmcaldera/e445ff878c81e16d0c19b4049f009703
  • https://medium.nextlevelswift.com/creating-two-ssh-keys-on-mac-for-two-different-github-accounts-b2456734e8f1
  • https://www.tecmint.com/fix-ssh-too-many-authentication-failures-error/

Bildquellen