Terminal-Automatisierung
Hugo-Blog ohne Passwort per SFTP-Key automatisch veröffentlichen

          _______
         |.-----.|
         ||x . x||
         ||_.-._||
         `--)-(--`
        __[=== o]___
       |:::::::::::|\
       `-=========-`()

Früher habe ich einen Blogbeitrag geschrieben, hugo getippt, FileZilla gestartet, Passwort eingegeben und alles hochgeladen. Jetzt genügt die Eingabe eines einzigen Terminal-Befehls. Danach passiert alles automatisch.

WARNUNG

Ich habe lange mit KI gebraucht, um diesen Arbeitsfluss zu bauen. Trotzdem garantiere ich nicht, dass diese Anleitung funktioniert. Sie ist als Erinnerung für mich gedacht. Mit Hetzner hat es funktioniert.

Inhaltsverzeichnis

1. Was Du brauchst

brew install lftp

Hinweis, falls Dein Hosting mehrere Benutzer erlaubt: Manche Hoster bieten neben Deinem Hauptbenutzer zusätzliche FTP-/SFTP-Unterbenutzer an. Key-Login funktioniert bei einigen Hostern jedoch nur mit dem Hauptbenutzer, nicht mit Unterbenutzern – das kann Dir später eine irreführende Fehlermeldung bescheren, auch wenn eigentlich alles korrekt eingerichtet ist. Mehr dazu in Schritt 3 und 5.

2. Einen Schlüssel erzeugen

Statt eines Passworts kannst Du Dich mit einem sogenannten Schlüssel bei Deinem Server anmelden. Das ist im Prinzip ein sehr langes, zufälliges Codepaar: eine Hälfte bleibt geheim auf Deinem Mac, die andere Hälfte trägst Du bei Deinem Hoster ein. Wenn beide Hälften zusammenpassen, lässt der Server Dich rein – ganz ohne dass Du ein Passwort eintippst.

Leg am besten für jeden Dienst einen eigenen Schlüssel an. Grund: Falls Du einen Schlüssel mal austauschen musst, betrifft das dann nur den einen Dienst und nicht alle auf einmal.

So erzeugst Du den Schlüssel:

ssh-keygen -t ed25519 -C "deploy-deinprojekt"

-t ed25519 legt fest, mit welchem Verfahren der Schlüssel gebaut wird.1 Das Programm schlägt Dir danach automatisch den Dateinamen id_ed25519 vor, weil dieser Name direkt vom gewählten Verfahren stammt.

Diesen Vorschlag solltest Du aber nicht einfach übernehmen, sondern einen eigenen Namen eintragen – sonst kann es passieren, dass Du Dir später einen bereits vorhandenen Schlüssel versehentlich überschreibst, oder dass Du nach einer Weile nicht mehr weißt, welcher Schlüssel wofür war.

Trag also bei der folgenden Abfrage den kompletten Pfad ein, nicht nur einen Namen:

Enter file in which to save the key (/Users/deinBenutzername/.ssh/id_ed25519): /Users/deinBenutzername/.ssh/id_ed25519_deinprojekt

Wichtig dabei: Vor dem eigentlichen Namen muss wirklich /Users/deinBenutzername/.ssh/ stehen (bzw. ~/.ssh/). Trägst Du nur einen Namen ohne diesen Pfad ein – zum Beispiel nur deploy-website statt ~/.ssh/deploy-website –, speichert das Programm die Datei nicht im .ssh-Ordner, sondern dort, wo Dein Terminal gerade steht, meist direkt in Deinem Benutzerordner.

Ein späteres ls -la ~/.ssh/ zeigt die Datei dann nicht an, weil sie schlicht woanders liegt. Falls Dir das passiert: Mit find ~ -maxdepth 2 -name "DEIN-NAME*" findest Du sie wieder und kannst sie mit mv DEIN-NAME ~/.ssh/DEIN-NAME (und dasselbe für die .pub-Datei) in den .ssh-Ordner verschieben.

Direkt danach fragt Dich das Programm zweimal nacheinander nach einer sogenannten Passphrase – einmal zur Eingabe, einmal zur Bestätigung. Die Passphrase ist einfach ein zusätzliches Passwort, das die geheime Hälfte des Schlüssels auf Deinem Mac schützt, falls jemand Zugriff auf Deinen Rechner bekommt.

Hier hast Du eine Wahl: Trägst Du eine Passphrase ein, musst Du sie einmalig Deinem Mac anvertrauen (nächster Schritt), damit Du sie später nicht bei jedem Deploy erneut eingeben musst. Lässt Du sie leer, ist der Schlüssel unverschlüsselt nutzbar – bequemer, aber wer Zugriff auf Deinen Mac hat, kann den Schlüssel dann sofort benutzen. Für ein Script, das nur automatisiert läuft, ist Leer-Lassen eine gängige und vertretbare Wahl.

Falls Du eine Passphrase vergibst, sag Deinem Mac, dass er sie sich sicher merken soll:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519_deinprojekt

Kommt hier die Fehlermeldung No such file or directory, ist das ein starkes Zeichen dafür, dass die Datei beim vorigen Schritt ohne vollständigen Pfad gespeichert wurde – siehe den Hinweis oben.

Achtung: Falls Du die Passphrase später vergisst, gibt es keine Möglichkeit, sie wiederherzustellen. Der Schlüssel ist dann unbrauchbar. Einzige Lösung: einen komplett neuen Schlüssel erzeugen (Schritt 2 wiederholen) und bei Deinem Hoster den alten löschen sowie den neuen eintragen.

3. Den Schlüssel hinterlegen

Jetzt trägst Du die »öffentliche« Hälfte Deines Schlüssels bei Deinem Hoster ein – die darf jeder sehen, sie allein reicht nicht aus, um sich anzumelden. Lass sie Dir anzeigen:

cat ~/.ssh/id_ed25519_deinprojekt.pub

Die ganze Ausgabe von cat gehört zum Schlüssel und ist technisch eine einzige Zeile, auch wenn sie im Terminal über mehrere Bildschirmzeilen umbricht. Sie besteht aus drei durch Leerzeichen getrennten Teilen: dem Verfahrenstyp (ssh-ed25519), dem eigentlichen langen Zeichen-Block und einem Kommentar am Ende (z. B. deploy-deinprojekt). Kopier alle drei Teile zusammen und achte darauf, dass beim Einfügen keine zusätzlichen Zeilenumbrüche oder Leerzeichen am Anfang oder Ende entstehen – sonst erkennt der Server den Schlüssel nicht korrekt.

Trag den Inhalt anschließend im Backend Deines Hosters unter »Öffentliche SFTP-Schlüssel« ein – bei den meisten Hostern findest Du diesen Bereich unter Einstellungen oder Logindaten.

Falls Dein Hoster ein anderes Schlüsselformat verlangt: Manche Hoster erwarten den öffentlichen Schlüssel nicht im bei OpenSSH gebräuchlichen Format, sondern im sogenannten SSH Public Key Format (RFC4716). Meldet Dein Hoster beim Eintragen einen Formatfehler, konvertierst Du den Schlüssel so:

ssh-keygen -e -f ~/.ssh/id_ed25519_deinprojekt.pub > ~/.ssh/id_ed25519_deinprojekt_rfc4716.pub

Trag dann den Inhalt dieser neuen Datei ein, nicht den der ursprünglichen .pub-Datei.

Falls Du nur einen Zusatz-/Unterbenutzer zur Verfügung hast: Prüf vorher, ob Dein Hoster Key-Login für Unterbenutzer überhaupt unterstützt – bei manchen Hostern geht das nur mit dem Hauptbenutzer des Accounts. Trägst Du den Schlüssel beim Unterbenutzer ein, obwohl das nicht unterstützt wird, bekommst Du später scheinbar grundlos einen Login-Fehler, obwohl der Schlüssel korrekt aussieht (siehe Fehlerdiagnose in Schritt 5). Nutze in diesem Fall stattdessen den Hauptbenutzer, sofern der Zugriff auf den Zielordner hat.

4. Eine Abkürzung für die Verbindung einrichten

Damit Du nicht jedes Mal Servername, Benutzername und Schlüssel-Pfad eintippen musst, legst Du eine kleine Konfigurationsdatei an, die das für Dich merkt:

cat >> ~/.ssh/config << 'EOF'
Host deinAlias
    HostName deinServer.example.com
    User deinUser
    IdentityFile ~/.ssh/id_ed25519_deinprojekt
    UseKeychain yes
    AddKeysToAgent yes
EOF
chmod 600 ~/.ssh/config

Trag hier Deinen echten Servernamen und Benutzernamen ein (deinServer.example.com und deinUser sind nur Platzhalter). UseKeychain yes und AddKeysToAgent yes sorgen dafür, dass Dein Mac sich die Passphrase merkt, falls Du eine vergeben hast – ohne diese beiden Zeilen würdest Du bei jedem neuen Terminal-Fenster erneut danach gefragt.

Diesen Alias (deinAlias) nutzt Du ab jetzt überall, wo Du Dich mit dem Server verbindest – Du musst Dir also weder Hostname noch Benutzername noch Schlüssel-Pfad merken.

5. Verbindung ausprobieren

sftp deinAlias

Beim allerersten Verbindungsversuch fragt Dich das Terminal, ob es dem Server vertrauen soll – das ist eine einmalige Sicherheitsabfrage, bestätige sie mit »yes«.

Schau Dir danach an, ob Du im richtigen Ordner landest:

sftp> pwd
sftp> cd /pfad/zu/deinem/webroot
sftp> ls
sftp> exit

Das ist wichtig, damit das Script nicht Dateien im falschen Ordner löschen kann. Das passiert, wenn der Pfad nicht stimmt.

Falls dabei etwas nicht klappt, hier die häufigsten Ursachen der Reihe nach:

Falls SFTP nach einem Passwort statt der Passphrase fragt: Das kann verwirrend sein, ist aber meist kein Fehler – es fragt dann nicht nach dem Server-Passwort, sondern nach der Passphrase Deines Schlüssels. Prüfen kannst Du das mit ssh -v deinAlias: Steht in der Ausgabe Server accepts key, hat die Anmeldung schon geklappt, und die Frage kam nur von Deinem Mac. Löse es mit ssh-add --apple-use-keychain ~/.ssh/id_ed25519_deinprojekt.

Falls die Meldung »agent refused operation« erscheint, wenn Du versuchst, einen Schlüssel zu entfernen: Das heißt meist nur, dass der Schlüssel gar nicht aktuell geladen war – es gibt also nichts zu entfernen, und Du kannst die Meldung ignorieren.

Falls Du »Login incorrect« oder »Permission denied« bekommst, obwohl der Schlüssel korrekt hinterlegt scheint:** Prüf zuerst, ob privater und öffentlicher Schlüssel wirklich zusammengehören:

ssh-keygen -y -f ~/.ssh/id_ed25519_deinprojekt
cat ~/.ssh/id_ed25519_deinprojekt.pub

Beide Ausgaben müssen bis auf den Kommentar am Ende identisch sein. Stimmen sie überein, prüf als Nächstes mit ssh -v deinAlias, wie weit die Anmeldung kommt. Zeigt das Protokoll Server accepts key, gefolgt von Next authentication method: password, hat der Server den Schlüssel zwar grundsätzlich erkannt, die eigentliche Anmeldung damit aber verweigert. Das deutet – neben einem Tippfehler im Benutzernamen in Deiner ~/.ssh/config – häufig auf die beiden Fälle aus Schritt 3 hin: falsches Schlüsselformat oder ein Unterbenutzer, der keinen Key-Login unterstützt. Kontrollier in diesem Fall auch die Dateirechte Deines privaten Schlüssels; sie sollten -rw------- lauten:

ls -la ~/.ssh/id_ed25519_deinprojekt
chmod 600 ~/.ssh/id_ed25519_deinprojekt

6. Das Automatisierungs-Script schreiben

Jetzt baust Du eine kleine Datei, die alle nötigen Schritte nacheinander ausführt. Das Script kommt in den bin-Ordner in Deinem Benutzerverzeichnis. Bei den meisten besteht dieser Ordner schon; falls nicht, legst Du ihn so an:

mkdir -p ~/bin

Gehe in das Verzeichnis mit cd ~/bin und erstelle anschließend Dein Automatisierungs-Script deploy_deinprojekt.sh mit

touch deploy_deinprojekt.sh

und öffne die Datei mit

open deploy_deinprojekt.sh

Mit open deploy_deinprojekt.sh sollte sich jetzt ein Editor öffnen. Kopiere das folgende Script hinein und passe es an.

Trag bei SITE_DIR Deinen eigenen Hugo-Projektordner ein, und bei REMOTE_DIR das korrekte Zielverzeichnis auf dem Server:

#!/bin/bash
# ~/bin/deploy_deinprojekt.sh
set -euo pipefail

SITE_DIR="$HOME/Documents/deinprojekt"
REMOTE_DIR="/pfad/zu/deinem/webroot"

cd "$SITE_DIR"
hugo --minify

lftp sftp://deinAlias <<EOF
set xfer:log yes
mirror --reverse --delete --verbose=3 "$SITE_DIR/public/" "$REMOTE_DIR"
bye
EOF

echo "Deploy fertig: $(date)"

Was hier passiert: Das Script wechselt in Deinen Website-Ordner, baut die Seite neu mit hugo --minify, und überträgt dann alles im Unterordner public zum Server. Weil lftp hier direkt über sftp://deinAlias verbindet, holt es sich Benutzername, Server und Schlüssel automatisch aus Deiner ~/.ssh/config – Du musst nichts davon im Script wiederholen.

set xfer:log yes protokolliert jede übertragene Datei einzeln, --verbose=3 gibt zusätzlich ausführliche Details zum Ablauf aus. Läuft das Script direkt im Terminal (nicht im Hintergrund), zeigt lftp außerdem automatisch einen Fortschrittsbalken pro Datei an – dafür musst Du nichts extra einstellen.

Der Befehl mirror --reverse --delete sorgt dafür, dass der Server danach genauso aussieht wie Dein lokaler public-Ordner – inklusive dem Löschen von Dateien, die Du lokal entfernt hast.

Bevor das Script funktioniert, musst Du es noch ausführbar machen – sonst bekommst Du später eine Fehlermeldung wie »Permission denied«:

chmod +x ~/bin/deploy_deinprojekt.sh

Vorsicht: Genau dieses automatische Löschen ist riskant, wenn sich im Pfad REMOTE_DIR ein Tippfehler einschleicht – dann räumt das Script womöglich den falschen Ordner leer. Teste deshalb vor dem ersten echten Durchlauf mit einem Testlauf, der nichts wirklich verändert:

mirror --reverse --delete --dry-run --verbose "$SITE_DIR/public/" "$REMOTE_DIR"

Erst wenn die angezeigte Liste genau das zeigt, was Du erwartest, entfernst Du --dry-run und lässt es echt laufen.

Und noch eine Warnung.

Kleine Falle: Achte auf den Schrägstrich am Ende von public/. Mit Schrägstrich werden die Dateien aus dem Ordner übertragen, ohne Schrägstrich würde das Script versuchen, den Ordner selbst als Ganzes hochzuladen – das willst Du hier nicht.

7. Eine Kurzform einrichten

Zum Schluss richtest Du ein Alias ein. Das ist ein kurzes Wort, das Du ins Terminal tippst. Das startet dann das obige Script.

# in ~/.zshrc
alias deploy-deinprojekt="~/bin/deploy_deinprojekt.sh"

Führ danach source ~/.zshrc aus, oder öffne einfach ein neues Terminal-Fenster. Ab jetzt reicht:

deploy-deinprojekt

…und Deine Website wird gebaut und automatisch hochgeladen.


  1. Mehr Informationen zum Schlüssel findest Du unter SSH-Key erstellen: ed25519 in 12 Schritten 2026 ↩︎