Claude für Admins: 6 Serveraufgaben sicher prüfen
Claude hilft bei sechs Serveraufgaben: Logs fehlerhafter Units lesen, systemd-Units entwerfen und nginx- sowie Compose-Dateien prüfen. Sensible Daten nie einfügen.
Claude für Systemadministratoren: erst beraten, dann ausführen
Claude eignet sich für Systemadministratoren am besten als Prüfinstanz. Sie fügen einen Logauszug, eine Konfigurationsdatei, einen unbekannten Befehl oder eine Fehlermeldung ein und erhalten eine Erklärung, die Sie prüfen können, bevor Sie etwas auf dem Server ändern. Eine falsche Antwort bleibt folgenlos, solange Sie sie nicht ausführen. Deshalb besteht das Sicherheitsmodell darin, das Modell auf der beratenden Seite dieser Grenze zu halten.
Auf einem gemieteten Linux-VPS (Virtual Private Server) fallen jede Woche sechs Aufgaben an. Für jede Aufgabe finden Sie unten ein funktionierendes Prompt-Muster, den Befehl zum Überprüfen der Antwort und das erwartete Fehlverhalten. Für keine dieser Aufgaben benötigt das Modell Zugriff auf Ihren Server.
Die Reihenfolge ist auf einem Produktivsystem wichtig: Lesen Sie die Erklärung, führen Sie die Prüfung selbst aus und entscheiden Sie anschließend. Auf einer Test-VM ist autonome Ausführung vertretbar. Auf dem Server, der Ihre Kundendienste bereitstellt, ist eine Prüfung die bessere Wahl, weil das Modell den Zustand, über den es Vermutungen anstellt, nicht sehen kann.
Was Sie niemals einfügen dürfen
Alles im Prompt verlässt Ihren Server. Vier Kategorien bleiben auf dem Server:
- Private Schlüssel:
~/.ssh/id_ed25519,/etc/ssh/ssh_host_*_keyund alle TLS-Schlüssel unter/etc/letsencrypt/live/. - Zugangsdaten-Dateien:
.env,~/.aws/credentials,/root/.docker/config.jsonsowie Datenbankpasswörter in Dateien oder Logzeilen. - Kontodaten:
/etc/shadowund/etc/gshadow. Für keine Frage zur Systemadministration wird ein Passwort-Hash benötigt. - Alles, was Ihren Benutzern gehört: E-Mail-Adressen, Bestellzeilen, Anforderungsprotokolle mit Session-Cookies oder personenbezogenen Daten (PII, personally identifiable information).
Öffentliche Schlüssel können Sie problemlos einfügen. Private Schlüssel dürfen Sie nicht einfügen. Die beiden Dateien sehen auf den ersten Blick ähnlich aus. Lesen Sie deshalb die erste Zeile, bevor Sie eine Datei kopieren: Eine Datei, deren erste Zeile BEGIN OPENSSH PRIVATE KEY enthält, gehört niemals in einen Prompt. SSH-Schlüsselmaterial korrekt unterscheiden ist dafür allein zehn Minuten wert.
Schwärzen Sie Inhalte vor dem Einfügen, statt darauf zu vertrauen, ein einzelnes Token in 200 Zeilen zu erkennen:
sudo journalctl -u myapp -n 200 --no-pager | sed -E 's/(token|secret|password|api[_-]?key)[=:][^[:space:]]+/\1=REDACTED/gI'Eine Besonderheit betrifft Docker. docker compose config setzt Ihre .env-Werte in die ausgegebene Ausgabe ein. Diese Ausgabe ist daher ein Geheimnis, auch wenn die Datei auf dem Datenträger selbst keine geheimen Daten enthielt. Verwenden Sie docker compose config -q. Dieser Befehl validiert die Konfiguration und gibt nichts aus. Die übergreifenden Regeln dazu, was ein Agent sehen darf, behandelt Geheimnisse aus AI-Agenten heraushalten auf der Umgebungsebene.
Aufgabe 1: Warum ist dieser Dienst fehlgeschlagen?
Beginnen Sie mit den beiden Befehlen, die die Antwort enthalten:
systemctl status myapp.service --no-pager
sudo journalctl -u myapp.service -b -n 100 --no-pager -o short-isoFügen Sie beide Befehle zusammen mit dem Kontext ein, den das Modell nicht erraten kann: Distribution und Version, was Sie zuletzt geändert haben, ob der Dienst zuvor jemals funktioniert hat und vor wie langer Zeit er ausgefallen ist. Fragen Sie zuerst nach dem Mechanismus.
Ubuntu 24.04.myapp.servicefunktionierte, bis ich vor einer Stunde die Unit bearbeitet habe. Hier sindsystemctl statusund die letzten 100 Zeilen des Journals. Welche Zeile ist der erste tatsächliche Fehler, und was bedeutet er? Noch keine Lösung.
„Noch keine Lösung“ erfüllt in diesem Prompt eine wichtige Funktion. Logs verbergen den ersten Fehler häufig unter den Wiederholungsversuchen, die er ausgelöst hat. Ein Modell, das nach einer Lösung gefragt wird, erklärt deshalb möglicherweise die letzte gefundene Zeile. Die relevante Zeile steht meist etwa 20 Zeilen über diesen Folgefehlern.
Das Ergebnis ist eine Zeile wie Main PID: 1841 (code=exited, status=203/EXEC). Der Exit-Status 203/EXEC bedeutet, dass der Kernel die in ExecStart angegebene Datei nicht ausführen konnte: Entweder existiert der Pfad nicht oder die Datei ist vorhanden, aber nicht ausführbar. Eine #!-Zeile mit einem nicht installierten Interpreter erzeugt denselben Status. All das lässt sich mit ls -l und head -1 prüfen.
Fehlermodus: eine erfundene Ursache. Wenn Sie zu wenig einfügen, füllt das Modell die Lücke mit etwas Allgemeinem, beispielsweise „Der Port wird bereits verwendet“. Stellen Sie stattdessen eine Rückfrage: „Welche Zeile aus meinen Angaben belegt das?“ Eine Ursache, auf die niemand im Text verweisen kann, ist eine Vermutung.
Aufgabe 2: Eine systemd-Unit oder einen Cron-Eintrag erstellen
Geben Sie die für eine Unit-Datei erforderlichen Informationen an: den exakten Befehl, den Benutzer, unter dem sie ausgeführt wird, das Arbeitsverzeichnis, ob sie auf das Netzwerk warten muss und was bei einem Exit-Status ungleich 0 geschehen soll. Prüfen Sie anschließend die Ausgabe, bevor Sie etwas aktivieren.
sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl start myapp.service
systemctl status myapp.service --no-pagersystemd-analyze verify analysiert die Datei genauso wie systemd und erkennt dadurch Fehler, die beim Lesen leicht übersehen werden. Eine falsch geschriebene Direktive erzeugt /etc/systemd/system/myapp.service:7: Unknown key name 'Enviroment' in section 'Service', ignoring.. Fehlt ein Binary, wird Command /usr/local/bin/myapp is not executable: No such file or directory ausgegeben. Während daemon-reload bleiben beide Prüfungen ohne Ausgabe. Deshalb kann eine Unit problemlos geladen werden und trotzdem beim Start sofort fehlschlagen.
Zwei Fehler beim Erstellen von Units treten immer wieder auf. Der erste ist After=network.target. Das bedeutet lediglich, dass der Netzwerk-Stack konfiguriert ist, nicht dass bereits eine IP-Adresse vorhanden ist. Ein Dienst, der an eine bestimmte IP-Adresse gebunden wird, schlägt beim Booten dann mit bind: Cannot assign requested address fehl. Die Korrektur besteht aus Wants=network-online.target zusammen mit After=network-online.target. Der zweite Fehler ist Type=simple bei einem Programm, das sich selbst daemonisiert: systemd behandelt den ersten Prozess als Dienst, der übergeordnete Prozess beendet sich sofort, und die Unit wird als beendet markiert, während der eigentliche Prozess weiterhin nicht verwaltet läuft.
Bei einem Zeitplan sollten Sie ihn prüfen, statt ihn nur zu lesen:
systemd-analyze calendar 'Mon *-*-* 04:00:00'Dabei werden die normalisierte Form und der nächste Zeitpunkt ausgegeben, zu dem der Ausdruck ausgeführt wird. Damit lässt sich eindeutig feststellen, was der Ausdruck bedeutet. Wenn Sie zwischen einem Timer und einer Crontab wählen, erläutert systemd-Dienste und Timer auf einem VPS die jeweiligen Vor- und Nachteile.
Cron enthält eine Falle, auf die Sie kein Modell hinweist, wenn Sie nicht danach fragen. Cron führt Jobs mit einer minimalen Umgebung aus. Daher entspricht PATH ungefähr /usr/bin:/bin, und Ihr Shell-Profil wird nie gelesen. Ein Job, der funktioniert, wenn Sie ihn in Ihr Terminal einfügen, schlägt unter Cron mit /bin/sh: 1: docker: not found fehl, weil sich dieses Binary in /usr/local/bin befindet. Verwenden Sie in Crontabs absolute Pfade.
Job 3: Eine nginx- oder Compose-Datei vor dem Produktivbetrieb prüfen
Dieser Job bietet den größten Nutzen. Fügen Sie die Datei ein, beschreiben Sie ihren Zweck, und bitten Sie um eine zeilenweise Erklärung, was sie tatsächlich macht.
Dieser vhost sollexample.comüber HTTPS bereitstellen und/apian einen lokalen Dienst auf Port 8080 weiterleiten. Lesen Sie die Datei zurück und nennen Sie alles, was nicht dieser Beschreibung entspricht.
Führen Sie anschließend das Tool aus, das die Syntax kennt:
sudo nginx -t
docker compose config -qnginx -t gibt nginx: configuration file /etc/nginx/nginx.conf test is successful aus oder nennt die Datei und die Zeile, wie in nginx: [emerg] unknown directive "proxy_pas" in /etc/nginx/conf.d/app.conf:12. docker compose config -q gibt nichts aus, wenn die Datei syntaktisch korrekt ist, und etwas Eindeutiges wie yaml: line 7: did not find expected key, wenn die Einrückung nicht stimmt.
Keines der beiden Tools prüft die Absicht. Eine Konfiguration, die nginx -t erfolgreich durchläuft, kann trotzdem an den falschen Port weiterleiten oder auf 0.0.0.0 lauschen, obwohl Sie 127.0.0.1 gemeint haben. Genau diese Lücke ist der Bereich, in dem das Modell seinen Nutzen zeigt. Hier versagt es aber auch: Wenn Sie es auffordern, eine einzelne Direktive zu ändern, gibt es häufig die gesamte Datei neu aus und lässt dabei unbemerkt zwei Ihrer Direktiven weg. Bitten Sie um die geänderten Zeilen und den Grund für jede Änderung. Bearbeiten Sie die Datei anschließend von Hand.
Prüfen Sie, was tatsächlich nach außen erreichbar ist:
sudo ss -tulpnOhne sudo sehen Sie die Listening-Sockets, aber nicht die Prozesse, denen sie gehören. Wenn diese Ausgabe unerwartet ist, ist welche Bedeutung Ports haben und wie Linux sie bindet die kürzere Erklärung.
Job 4: Einen unbekannten Befehl erklären, bevor Sie ihn ausführen
Fügen Sie den Befehl ein und stellen Sie dazu vier Fragen: Was bewirkt jedes Flag, was schreibt der Befehl, was löscht er, und was geschieht, wenn ich ihn zweimal ausführe? Die letzte Frage verhindert mehr Schäden als die anderen.
Nehmen Sie find /var/log -name '*.gz' -mtime +7 -delete. Eine gute Antwort erklärt, dass -mtime +7 vollständige Zeiträume von 24 Stunden zählt und den Bruchteil verwirft. Dadurch werden Dateien gefunden, die mindestens acht Tage alt sind, nicht sieben. Sie erklärt außerdem, dass find seinen Ausdruck von links nach rechts auswertet. Wenn Sie deshalb -delete vor -name verschieben, löscht der Befehl alles unterhalb des Startpfads. Dieser zweite Punkt steht als Warnung in der find-Handbuchseite. Er hat bereits das /var/log von Benutzern gekostet.
Oder nehmen Sie rsync -a --delete /srv/app/ /backup/app/. Der abschließende Schrägstrich am Quellpfad bedeutet „der Inhalt dieses Verzeichnisses“. Lassen Sie ihn weg, erhalten Sie /backup/app/app/. Fügen Sie --delete hinzu, werden alle Elemente im Ziel gelöscht, die in der Quelle fehlen. Das ist für einen Spiegel korrekt und führt zu einer Katastrophe, wenn der Quellpfad falsch ist.
Prüfen Sie dies mit dem Tool und nicht mit dem Modell:
rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7Führen Sie den find ohne -delete aus. Dann erhalten Sie eine Liste statt eines Datenverlusts.
Fehlermodus: Erfundene Flags. Bei Tools mit dreißig Jahren Dokumentation ist das Modell zuverlässig. Bei herstellerspezifischen CLIs (Befehlszeilenschnittstellen) und neuen Subcommands ist es deutlich unzuverlässiger. Dort erzeugt es ein Flag, das plausibel aussieht, aber nicht existiert. --help klärt das in einer Sekunde. Auch die Quotierung ist eine Schwachstelle. Wenn ein Befehl einen $(...)-Ausdruck kapselt, lesen Sie wie die Befehlsausführung vor dem Start des Befehls erweitert wird, statt der Erklärung blind zu vertrauen.
Aufgabe 5: Ihre Shell-History in ein Runbook umwandeln
Sie haben gerade zwei Stunden damit verbracht, etwas zum Laufen zu bringen. Dieses Wissen steht jetzt in Ihrem Scrollback und ist nächsten Monat nicht mehr verfügbar.
history 200 > /tmp/session.txtLesen Sie diese Datei und löschen Sie jede Zeile, die ein Passwort, einen Token oder eine Kundenkennung enthält, bevor Sie sie weitergeben. Die Shell-History ist eine der zuverlässigsten Stellen, um ein Secret auf einem Linux-System zu finden, weil jeder mindestens einmal einen Wert direkt in einen Befehl eingibt. Setzen Sie HISTCONTROL=ignorespace in Ihrer ~/.bashrc. Dann wird ein Befehl mit einem führenden Leerzeichen überhaupt nicht in die History geschrieben.
Der Prompt, der ein brauchbares Runbook erzeugt, fordert Prüfungen an, nicht nur Schritte:
Dies ist eine Shell-Sitzung, in der eine frische Debian-13-Installation zu einer funktionierenden Postgres-Installation eingerichtet wurde. Dokumentieren Sie sie als nummeriertes Runbook. Verwenden Sie pro Schritt genau einen Befehl. Geben Sie nach jedem Schritt den Befehl an, der den erfolgreichen Abschluss nachweist, und beschreiben Sie, wie eine gesunde Ausgabe aussieht. Kennzeichnen Sie jeden Schritt, der von meinem spezifischen Host abhing.
Fehlerbild: eine aufgeräumte Darstellung. In Ihrer Sitzung gab es einen Schritt, den Sie vor der Korrektur zweimal falsch ausgeführt haben. Genau diesen Schritt glättet das Modell, weil das Transkript ohne ihn übersichtlicher wirkt. Vergleichen Sie das Runbook mit Ihrer History und fügen Sie die Korrektur wieder ein. Das Modell erfindet außerdem plausible Prüfungsbefehle. Führen Sie daher jede von ihm angegebene Prüfung aus, bevor Sie die Datei speichern. Wenn das Runbook den ersten Boot-Vorgang behandelt, lesen Sie es gegen die ersten zehn Minuten auf einem neuen VPS, damit Sie nicht eine schlechtere Version eines bereits gelösten Problems dokumentieren.
Aufgabe 6: Eine Fehlermeldung in eine Lösung umwandeln
Fügen Sie die exakte Zeichenfolge, den Befehl, der sie erzeugt hat, und die eine Änderung ein, die Sie unmittelbar davor vorgenommen haben. Bitten Sie um eine Rangfolge der Ursachen und um einen unterscheidenden Befehl für jede Ursache. Dadurch muss die Antwort überprüfbar sein.
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use). Ordne die wahrscheinlichen Ursachen und gib mir pro Ursache einen Befehl, der sie bestätigt oder ausschließt.
Bei diesem Fehler ist der Mechanismus eindeutig: Ein anderer Prozess verwendet bereits Port 80, und sudo ss -tulpn | grep ':80 ' identifiziert ihn. Häufig handelt es sich um einen zweiten nginx-Masterprozess, der nach einem fehlgeschlagenen Reload zurückgeblieben ist, oder um Apache, der als Abhängigkeit eingebunden und von seinem eigenen Paket gestartet wurde.
Fehlermuster: Eine Lösung behebt das Problem, indem sie die Ursache verbirgt. chmod 777, --privileged, das Deaktivieren von SELinux und das Ausführen des Dienstes als root lassen den Fehler zwar verschwinden. Lehnen Sie jede Lösung ab, die Berechtigungen erweitert, solange das Modell nicht erklärt hat, warum die eingeschränkte Berechtigung fehlgeschlagen ist. Diese Erklärung ist die eigentliche Antwort. Eine Umgehung sorgt lediglich dafür, dass der Fehler nicht mehr sichtbar ist.
Was es zuverlässig falsch macht
- Es kann Ihren Server nicht sehen. Jede Antwort basiert ausschließlich auf dem, was Sie eingefügt haben. Es weist Sie nicht darauf hin, wenn der Auszug zu kurz war.
- Bei Versionen kommt es zu Abweichungen. Paketnamen und Standardoptionen ändern sich zwischen Distributionen und Releases. Das Modell bildet daraus einen Durchschnitt.
- Es formuliert auch falsche Aussagen flüssig. Ein erfundener Mechanismus klingt genau wie ein korrekter. Deshalb wird jede oben genannte Ursache mit einem Befehl überprüft.
- In langen Sitzungen verliert es den Zusammenhang. Informationen vom Anfang eines zweistündigen Gesprächs beeinflussen die Antworten am Ende nicht mehr ausreichend.
Das letzte Problem ist eher ein Problem der Arbeitsweise als des Modells. Kontext in einer langen Claude-Code-Sitzung verwalten ist die praktische Lösung: kürzere Sitzungen und jeweils nur eine Aufgabe.
Den Agent auf dem Server selbst ausführen
Alle bisherigen Schritte bestehen aus Copy-and-Paste-Befehlen. Das Modell greift daher nie auf Ihren Rechner zu. Sobald es auf dem Server läuft, Dateien liest und Befehle ausführt, verändert sich das Risikoprofil: Ein falscher Befehl kann nun einen Dienst ausfallen lassen. Verwenden Sie dafür einen eigenen Benutzer ohne privilegierte Rechte statt root. Lassen Sie den Agenten beim Kennenlernen seiner Arbeitsweise nicht auf dem Produktionsserver laufen. Erstellen Sie außerdem vorher einen Snapshot. Claude Code sicher auf einem VPS ausführen behandelt die Sandbox und das Berechtigungsmodell. Claude Code innerhalb von tmux steuern löst den anderen Teil des Problems: Wenn eine SSH- (Secure-Shell-)Sitzung abbricht, beendet sie einen Agenten im Vordergrund mitten in seiner Arbeit. Richten Sie das Konto so ein wie ein Dienstkonto. Benutzer mit geringsten Berechtigungen auf einem VPS beschreibt dieses Vorgehen ausführlich.
FAQ
Kann Claude meine Server-Logs direkt lesen?
Nicht selbstständig. Die Chat-Oberfläche sieht nur den Text, den Sie einfügen. Claude Code kann als Kommandozeilenwerkzeug auf dem Server Dateien lesen und Befehle mit den Berechtigungen des Benutzers ausführen, der es gestartet hat. Das ist eine weitreichendere Vertrauensentscheidung. Für eine gewöhnliche Supportfrage ist es schneller und sicherer, einen bereinigten 100-Zeilen-Auszug einzufügen, als einem Agenten Shell-Zugriff zu geben.
Was sollte ich niemals von einem Server einfügen?
Private Schlüssel, .env-Dateien und andere Credential-Speicher, /etc/shadow sowie beliebige Daten Ihrer Benutzer. Entfernen Sie Tokens aus Log-Auszügen, bevor diese den Prompt erreichen. Ein weniger offensichtlicher Fall: Die Ausgabe von docker compose config enthält Ihre .env-Werte in interpolierter Form. Verwenden Sie daher docker compose config -q. Damit wird die Datei validiert und keine Ausgabe erzeugt.
Ist es sicher, Claude Befehle auf einem produktiven VPS ausführen zu lassen?
Behandeln Sie Claude wie einen neuen Administrator ohne Kontext: Lesen ist unproblematisch, Schreibzugriffe müssen geprüft werden. Bitten Sie Claude in der Produktion um eine Erklärung und führen Sie den Befehl selbst aus. Wenn ein Agent Befehle ausführen soll, geben Sie ihm ein eigenes unprivilegiertes Konto ohne pauschales sudo. Beginnen Sie auf einem Staging-System, auf dem ein Fehler einen Neuaufbau statt eines Ausfalls verursacht.
Warum schlägt Claude ein nicht vorhandenes Flag vor?
Weil Claude plausiblen Text vorhersagt und ein plausibles Flag genauso aussieht wie ein echtes. Das kommt besonders bei herstellerspezifischen CLIs und neueren Subcommands vor, deren Dokumentation im Modell unvollständig oder inzwischen geändert ist. --help und man sind maßgeblich. Jeder Befehl, der Daten löscht oder überschreibt, sollte zuerst mit einem Probelauf ausgeführt werden.
Wie prüfe ich eine systemd-Unit, bevor ich sie aktiviere?
Führen Sie sudo systemd-analyze verify /etc/systemd/system/myapp.service aus. Der Befehl analysiert die Datei mit dem systemd-eigenen Parser, meldet unbekannte Direktiven mit ihren Zeilennummern und weist auf ein fehlendes oder nicht ausführbares ExecStart-Binary hin. Führen Sie anschließend daemon-reload und start aus und lesen Sie systemctl status, bevor Sie die Unit mit enable aktivieren. Eine Unit kann zwar fehlerfrei geladen werden und trotzdem beim ersten Start fehlschlagen.