↓Zum Hauptinhalt springen

Zwei Rechner, ein Setup – mit Forgejo, chezmoi und ghorg

·5 min
Zwei Rechner, eine Arbeitsumgebung: gleicher Editor, gleiche Shell, gleiche Repos – synchronisiert über meine eigene Forgejo-Instanz statt über Microsoft oder GitHub.

Ich arbeite an zwei Rechnern – einem Notebook und einem Desktop, beide mit CachyOS. Alles, was ich an Code und Konfiguration habe, liegt auf meiner eigenen Forgejo-Instanz unter git.minifisch.at. So sieht das Ganze am Ende aus:

flowchart LR subgraph forgejo["Forgejo – git.minifisch.at"] dot["chezmoi-Repo
(Dotfiles)"] repos["Projekt-Repos"] end subgraph nb["Notebook"] nbk[("Keyring
Token")] end subgraph dt["Desktop"] dtk[("Keyring
Token")] end dot <-- "chezmoi" --> nb dot <-- "chezmoi" --> dt repos -- "ghorg clone" --> nb repos -- "ghorg clone" --> dt

VS Code ohne Telemetrie und KI-Spielereien #

Angefangen hat es mit einer frischen VS-Code-Installation. Als Erstes flog alles raus, was nach Hause telefoniert: Telemetrie, Experimente, die Online-Suche in den Einstellungen und automatische Updates (die kommen bei mir ohnehin über pacman). Auch die eingebauten Chat- und Copilot-Funktionen sind deaktiviert – dafür gibt es inzwischen einen offiziellen Hauptschalter:

{
  "telemetry.telemetryLevel": "off",
  "workbench.enableExperiments": false,
  "update.mode": "manual",
  "chat.disableAIFeatures": true
}

Die naheliegende Lösung zum Synchronisieren wäre der eingebaute Settings Sync. Der braucht aber ein Microsoft- oder GitHub-Konto und läuft über deren Server – genau das wollte ich gerade loswerden.

Dotfiles mit chezmoi #

Stattdessen nutze ich chezmoi, das ich ohnehin schon für meine Dotfiles im Einsatz hatte. Das Quell-Repo liegt auf Forgejo, und mit autoCommit und autoPush landet jede Änderung sofort dort. Neu dazugekommen sind:

  • ~/.config/Code/User/settings.json – die VS-Code-Einstellungen, inklusive aller Einstellungen von Erweiterungen
  • ~/.gitconfig – meine Git-Identität
  • ~/.zshrc – war schon drin, hat aber ein paar neue Funktionen bekommen (dazu gleich mehr)

Auf dem anderen Rechner reicht dann ein chezmoi update, und alles ist auf demselben Stand.

Stolperfalle: Ändert man eine Einstellung direkt in VS Code, ändert sich nur die echte Datei, nicht die Kopie in chezmoi. Entweder man übernimmt sie danach mit chezmoi add … oder man bearbeitet gleich die Quelle mit chezmoi edit --apply …. Hauptsache, man bleibt bei einem der beiden Wege.

Alle Repos auf einmal: ghorg #

Von GitLab kannte ich glab, mit dem man alle Repos einer Gruppe auf einmal klonen kann. Für Forgejo gibt es mit forgejo-cli (fj) ein sehr gutes Kommandozeilen-Tool für Issues, Pull Requests und Releases. Was fj aber nicht kann: Repos auflisten. Jeder Befehl arbeitet mit genau einem Repo, das man beim Namen nennt.

Fürs Massen-Klonen nutze ich deshalb ghorg. Forgejo ist mit der Gitea-API kompatibel, also läuft es über das gitea-Backend. Die Konfiguration unter ~/.config/ghorg/conf.yaml sieht ungefähr so aus:

GHORG_SCM_TYPE: gitea
GHORG_SCM_BASE_URL: https://git.minifisch.at
GHORG_CLONE_TYPE: user
GHORG_CLONE_PROTOCOL: ssh
GHORG_ABSOLUTE_PATH_TO_CLONE_TO: /home/patrick/dev
GHORG_SKIP_ARCHIVED: true
GHORG_CONCURRENCY: 4

Ein ghorg clone minifisch legt damit alle meine Repos unter ~/dev/minifisch/<repo> ab. Das Schöne daran: Führt man den Befehl erneut aus, aktualisiert er alle vorhandenen Klone und holt neue Repos dazu. Damit ist er gleichzeitig mein „Bring diesen Rechner auf Stand“-Befehl.

minifisch ist in Forgejo ein Benutzer, keine Organisation – deshalb clone-type: user. Beim ersten Mal lohnt sich außerdem ein --dry-run, und --no-clean sorgt dafür, dass ghorg bestehende Repos nicht zurücksetzt.

Das Token im Keyring statt in einer Datei #

ghorg braucht ein Forgejo-Token mit Leserechten. In die Konfigurationsdatei wollte ich es nicht schreiben.

Ein Token im Klartext hat in einer von chezmoi verwalteten Datei nichts verloren: Mit autoPush landet es sofort im Git-Repo auf Forgejo.

Also liegt das Token im Keyring des Systems:

secret-tool store --label='ghorg forgejo' service ghorg host git.minifisch.at

Eine kleine Funktion in der .zshrc holt es bei jedem Aufruf ab:

ghorg() {
  local token
  token=$(secret-tool lookup service ghorg host git.minifisch.at) || {
    echo "Kein Token im Keyring. Speichern mit:" >&2
    echo "  secret-tool store --label='ghorg forgejo' service ghorg host git.minifisch.at" >&2
    return 1
  }
  GHORG_GITEA_TOKEN="$token" command ghorg "$@"
}

Die Funktion enthält kein Geheimnis und darf deshalb mit chezmoi synchronisiert werden. Jeder Rechner bekommt sein eigenes Token – so kann ich eines davon jederzeit einzeln widerrufen.

Ordnung auf der Platte und im Editor #

Die Repos liegen jetzt so wie auf dem Server: ~/dev/<besitzer>/<repo>. Geöffnet wird von der Kommandozeile aus, ein Repo pro Fenster – also schlicht code ~/dev/minifisch/webpage. Einstellungen, die nur ein Projekt betreffen, liegen im .vscode/-Ordner des jeweiligen Repos und kommen damit über Forgejo automatisch mit.

Einen Workspace im Sinne einer .code-workspace-Datei brauche ich nur dann, wenn eine Aufgabe wirklich mehrere Repos gleichzeitig betrifft. Was ich vermeide: ganz ~/dev als einen Ordner öffnen. Mit vielen verschachtelten Git-Repos wird die Quellcodeverwaltung in VS Code schnell unübersichtlich.

Damit ich keine Pfade tippen muss, gibt es noch einen kleinen Auswahldialog mit fzf:

dev() {
  local repo
  repo=$(fd -H -t d --prune -g .git "${DEV_ROOT:-$HOME/dev}" -x echo {//} | sort |
    fzf --query="$*" --select-1 --preview 'git -C {} log --oneline -10') && code "$repo"
}

dev zeigt alle Repos unter ~/dev mit den letzten Commits in der Vorschau, dev web öffnet direkt das passende Repo, wenn es nur einen Treffer gibt.

Was bewusst nicht synchronisiert wird #

Nicht alles gehört in ein Git-Repo:

  • Vertrauenswürdige Ordner in VS Code: Die liegen im internen Zustand von VS Code (eine SQLite-Datenbank), die jeder Rechner ständig selbst neu schreibt. Außerdem ist „diesem Ordner vertraue ich“ eine Sicherheitsentscheidung, die ich pro Rechner treffen möchte.
  • Erweiterungen selbst: Deren Einstellungen kommen über settings.json mit, installieren tue ich sie aber auf jedem Rechner selbst.
  • Das Forgejo-Token: pro Rechner im eigenen Keyring.

Fazit #

  • chezmoi synchronisiert die Konfiguration.
  • ghorg holt die Repos auf jeden Rechner.
  • fj übernimmt die Arbeit mit Forgejo selbst.
  • Der Keyring hält das Token aus allen Dateien heraus.

Alles läuft über meine eigene Infrastruktur, und ein neuer Rechner ist mit chezmoi init --apply, einem Token im Keyring und einem ghorg clone minifisch in wenigen Minuten eingerichtet.