SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-08-25

Claude für Admins: 6 Serveraufgaben sicher lösen

Claude hilft bei sechs Serveraufgaben: Logs fehlgeschlagener Units lesen, systemd-Units entwerfen sowie nginx- und Compose-Dateien prüfen. Geheimnisse nie einfügen.

Claude für Systemadministratoren: Erst Beratung, dann Ausführung

Claude eignet sich für Systemadministratoren am besten als Reviewer. 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 verursacht keine Folgen, solange Sie sie nicht ausführen. Das Modell auf der beratenden Seite dieser Grenze zu halten, ist daher das gesamte Sicherheitsmodell.

Auf einem gemieteten Linux-VPS (virtueller privater Server) fallen jede Woche sechs Aufgaben an. Für jede davon gibt es ein funktionierendes Prompt-Muster, den Befehl, der die Antwort bestätigt, und das erwartete Fehlerbild. Keine dieser Aufgaben erfordert Zugriff des Modells auf Ihren Server. Sie können Inhalte aus einem Browser-Tab oder aus einem Fenster auf Ihrem eigenen Desktop einfügen, da Claude unter Linux nativ sowohl als Desktop-App als auch als CLI ausgeführt wird.

Die Reihenfolge ist auf einem Produktivserver wichtig: Lesen Sie zuerst die Erklärung, führen Sie die Prüfung selbst aus und entscheiden Sie dann. Auf einer Test-VM ist Autonomie unproblematisch. Auf dem Server, der Ihre Kundendienste bereitstellt, ist eine Prüfung besser, weil das Modell den Zustand, über den es Vermutungen anstellt, nicht sehen kann.

Was Sie niemals einfügen dürfen

Alles in der Eingabe verlässt Ihren Server. Vier Kategorien bleiben auf dem Server:

  • Private Schlüssel: ~/.ssh/id_ed25519, /etc/ssh/ssh_host_*_key und alle TLS-Schlüssel (Transport Layer Security) unter /etc/letsencrypt/live/.
  • Zugangsdaten-Dateien: .env, ~/.aws/credentials, /root/.docker/config.json sowie Datenbankpasswörter in beliebigen Dateien oder Logzeilen.
  • Kontodaten: /etc/shadow und /etc/gshadow. Für keine Frage zur Systemadministration wird ein Passwort-Hash benötigt.
  • Alles, was Ihren Benutzern gehört: E-Mail-Adressen, Bestellzeilen, Request-Logs mit Session-Cookies oder personenbezogenen Daten (PII, Personally Identifiable Information).

Öffentliche Schlüssel können Sie unbedenklich einfügen. Private Schlüssel dürfen Sie nicht einfügen. Die beiden Dateien sehen auf den ersten Blick ähnlich aus. Lesen Sie daher die erste Zeile, bevor Sie eine Datei kopieren: Eine Datei, deren erste Zeile BEGIN OPENSSH PRIVATE KEY enthält, gehört niemals in eine Eingabe. Ihre SSH-Schlüsseldateien korrekt zu unterscheiden ist allein zehn Minuten wert.

Schwärzen Sie die Daten vor dem Einfügen, anstatt 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 gibt es bei Docker. docker compose config setzt Ihre .env-Werte in die ausgegebene Konfiguration ein. Dadurch ist die Ausgabe ein Geheimnis, obwohl die Datei auf dem Datenträger keine Geheimnisse enthielt. Verwenden Sie docker compose config -q. Der Befehl prüft die Konfiguration und gibt nichts aus. Die übergreifenden Regeln dazu, was ein Agent sehen darf, behandelt Geheimnisse aus AI-Agenten herauszuhalten aus Sicht der Umgebung.

Job 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-iso

Fügen Sie beide Befehle zusammen mit dem Kontext ein, den das Modell nicht erraten kann: Distribution und Version, die letzte Änderung, ob der Dienst jemals funktioniert hat und wie lange der Fehler bereits besteht. Fragen Sie zuerst nach dem Mechanismus.

Ubuntu 24.04. myapp.service funktionierte, bis ich vor einer Stunde die Unit bearbeitet habe. Hier sind systemctl status und die letzten 100 Journal-Zeilen. 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 oft unter den dadurch ausgelösten Wiederholungsversuchen. Wenn ein Modell nach einer Lösung gefragt wird, erklärt es daher häufig die letzte angezeigte Zeile. Die relevante Zeile steht normalerweise etwa zwanzig Zeilen vor den 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, die einen nicht installierten Interpreter angibt, erzeugt denselben Status. All das lässt sich mit ls -l und head -1 prüfen.

Fehlermuster: eine erfundene Ursache. Wenn Sie zu wenig einfügen, füllt das Modell die Lücke mit einer allgemeinen Vermutung, zum Beispiel „Der Port wird bereits verwendet“. Stellen Sie stattdessen eine Rückfrage: „Welche Zeile in meinen Angaben stützt diese Aussage?“ 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 Fakten an, die eine Unit-Datei benötigt: 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 die Unit aktivieren.

sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl start myapp.service
systemctl status myapp.service --no-pager

systemd-analyze verify analysiert die Datei so, wie systemd sie verarbeitet. Dadurch werden Fehler erkannt, die beim Lesen leicht übersehen werden. Eine falsch geschriebene Direktive gibt /etc/systemd/system/myapp.service:7: Unknown key name 'Enviroment' in section 'Service', ignoring. aus. Eine fehlende Binärdatei gibt Command /usr/local/bin/myapp is not executable: No such file or directory aus. Während daemon-reload bleiben beide Prüfungen still. Deshalb kann eine Unit problemlos geladen werden und trotzdem beim Start sofort fehlschlagen.

Zwei Fehler treten beim Erstellen von Unit-Dateien immer wieder auf. Der erste ist After=network.target. Damit ist nur gemeint, dass der Netzwerk-Stack konfiguriert ist, nicht dass bereits eine Adresse vorhanden ist. Ein Dienst, der an eine bestimmte IP-Adresse gebunden wird, schlägt beim Booten daher 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 in den Hintergrund verschiebt: systemd behandelt den ersten Prozess als Dienst, der übergeordnete Prozess wird sofort beendet, und die Unit wird als beendet markiert, während der eigentliche Prozess nicht verwaltet weiterläuft. Diesen Fehler wird ein Modell besonders wahrscheinlich vorschlagen, weil es anhand Ihres Befehls nicht erkennen kann, ob die Binärdatei einen weiteren Prozess forkt. Deshalb sollten Sie wissen, was jeder Type=-Wert systemd zusichert, bevor Sie den Entwurf übernehmen.

Bei einem Zeitplan sollten Sie ihn prüfen, statt ihn nur zu lesen:

systemd-analyze calendar 'Mon *-*-* 04:00:00'

Das gibt die normalisierte Form und den nächsten Zeitpunkt aus, 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, behandelt systemd-Dienste und Timer auf einem VPS die jeweiligen Vor- und Nachteile.

Cron hat eine Falle, vor der Sie kein Modell warnt, wenn Sie nicht danach fragen. Cron führt Jobs mit einer minimalen Umgebung aus. Daher ist PATH ungefähr /usr/bin:/bin, und Ihr Shell-Profil wird niemals eingelesen. 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 diese Binärdatei in /usr/local/bin befindet. Verwenden Sie in Crontabs absolute Pfade. Wenn die ausdrückliche Angabe von Benutzer, Umgebung und Abhängigkeiten in einer Unit-Datei im Vergleich zu einer einzelnen Crontab-Zeile übertrieben wirkt, erklären die Probleme, für deren Lösung systemd entwickelt wurde, woher diese ausführliche Konfiguration stammt.

Job 3: Eine nginx- oder Compose-Datei prüfen, bevor sie produktiv eingesetzt wird

Dieser Job bietet den größten Nutzen. Fügen Sie die Datei ein, beschreiben Sie ihr vorgesehenes Verhalten und bitten Sie um eine zeilenweise Erklärung dessen, was sie tatsächlich tut.

Dieser VHost soll example.com über HTTPS bereitstellen und /api an einen lokalen Dienst auf Port 8080 weiterleiten. Lesen Sie die Datei zurück und nennen Sie alles, was nicht zu dieser Beschreibung passt.

Führen Sie anschließend das Tool aus, das die Syntax kennt:

sudo nginx -t
docker compose config -q

nginx -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 beabsichtigte Funktion. 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 vorgesehen haben. Diese Lücke ist der Bereich, in dem das Modell seinen Nutzen zeigt. Genau dort versagt es aber auch: Wenn Sie es bitten, eine einzelne Direktive zu korrigieren, gibt es häufig die gesamte Datei neu formatiert zurück, wobei zwei Ihrer Direktiven unbemerkt fehlen. Bitten Sie um die geänderten Zeilen und die Begründung 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 -tulpn

Ohne sudo sehen Sie die Listening-Sockets, aber nicht die Prozesse, denen sie gehören. Wenn Sie diese Ausgabe überrascht, ist was Ports sind und wie Linux sie bindet die kürzere Erklärung.

Aufgabe 4: Erklären Sie einen unbekannten Befehl, bevor Sie ihn ausführen

Fügen Sie den Befehl ein und stellen Sie vier Fragen dazu: Was bewirkt jedes Flag, wohin schreibt der Befehl, was löscht er, und was passiert, 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 erfasst, die mindestens acht Tage alt sind, nicht sieben. Sie erklärt außerdem, dass find seinen Ausdruck von links nach rechts auswertet. Wenn Sie -delete daher vor -name setzen, löscht der Befehl alles unterhalb des Startpfads. Dieser zweite Punkt steht als Warnung in der find-Manpage. Er hat bereits dazu geführt, dass Menschen ihre /var/log verloren haben.

Oder nehmen Sie rsync -a --delete /srv/app/ /backup/app/. Der abschließende Schrägstrich am Quellpfad bedeutet „der Inhalt dieses Verzeichnisses“. Wenn Sie ihn weglassen, erhalten Sie /backup/app/app/. Wenn Sie --delete hinzufügen, werden alle Elemente am 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.

Überprüfen Sie die Aussage mit dem Tool, nicht mit dem Modell:

rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7

Führen Sie den find ohne -delete aus. Dann erhalten Sie eine Liste statt eines Datenverlusts.

Fehlerbild: erfundene Flags. Bei Tools mit einer Dokumentationshistorie von 30 Jahren ist das Modell zuverlässig. Bei Hersteller-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 innerhalb einer Sekunde. Auch die Anführungszeichen sind eine Schwachstelle. Wenn ein Befehl einen $(...)-Ausdruck enthält, lesen Sie wie die Befehlsersetzung vor der Ausführung des Befehls erweitert wird, statt der Erklärung zu vertrauen.

Job 5: Aus Ihrer Shell-Historie ein Runbook erstellen

Sie haben gerade zwei Stunden damit verbracht, etwas zum Laufen zu bringen. Dieses Wissen steht in Ihrem Scrollback und ist nächsten Monat nicht mehr verfügbar.

history 200 > /tmp/session.txt

Lesen Sie diese Datei und löschen Sie jede Zeile, die ein Passwort, ein Token oder eine Kundenkennung enthält, bevor die Datei an einen anderen Ort gelangt. Die Shell-Historie ist eine der zuverlässigsten Stellen, um ein Secret auf einer Linux-Box zu finden, weil jeder mindestens einmal eines inline eingibt. Setzen Sie HISTCONTROL=ignorespace in Ihrer ~/.bashrc. Ein Befehl, den Sie mit einem vorangestellten Leerzeichen eingeben, wird dann überhaupt nicht in die Historie geschrieben.

Der Prompt, der ein brauchbares Runbook erzeugt, fordert Prüfungen an, nicht nur Schritte:

Dies ist eine Shell-Sitzung, in der eine neue Debian-13-Box zu einer funktionierenden Postgres-Installation eingerichtet wurde. Schreiben Sie daraus ein 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 fehlerfreie Ausgabe aussieht. Kennzeichnen Sie jeden Schritt, der von meinem konkreten Host abhing.

Fehlermodus: eine aufgeräumte Geschichte. Ihre Sitzung enthielt einen Schritt, den Sie vor der Korrektur zweimal falsch ausgeführt haben. Genau diesen Schritt glättet das Modell, weil das Transkript ohne ihn sauberer aussieht. Vergleichen Sie das Runbook mit Ihrer Historie und fügen Sie die Korrektur wieder ein. Außerdem erfindet das Modell plausible Prüfungsbefehle. Führen Sie daher jede von ihm angegebene Prüfung aus, bevor Sie die Datei speichern. Wenn das Runbook den ersten Bootvorgang behandelt, vergleichen Sie es mit den ersten zehn Minuten auf einem neuen VPS, damit Sie nicht eine schlechtere Version eines bereits gelösten Problems dokumentieren.

Job 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 vor ihrem Auftreten 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). Ordnen Sie die wahrscheinlichen Ursachen nach ihrer Wahrscheinlichkeit und nennen Sie 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 ' nennt den Prozess. 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.

Fehlermodus: Eine Lösung behebt den Fehler, 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. Ein Workaround sorgt nur 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, dass 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 dann flüssig, wenn es falsch liegt. Ein erfundener Mechanismus liest sich genau wie ein korrekter. Deshalb wird jede oben genannte Ursache mit einem Befehl ergänzt, der sie prü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 Arbeitsproblem als ein Modellproblem. Kontext in einer langen Claude Code-Sitzung verwalten ist die praktische Lösung: kürzere Sitzungen und jeweils nur eine Aufgabe.

Den Agenten direkt auf dem Server ausführen

Alles oben lässt sich per Copy-and-paste ausführen, sodass das Modell Ihre Maschine nicht berührt. Sobald es auf dem Server läuft, Dateien liest und Befehle ausführt, ändert sich das Risikoprofil: Ein falscher Befehl kann nun einen Dienst ausfallen lassen. Geben Sie dem Agenten einen eigenen unprivilegierten Benutzer statt root, halten Sie ihn während der Einarbeitung von der Produktionsumgebung fern und erstellen Sie vorher einen Snapshot. Claude Code sicher auf einem VPS ausführen behandelt Sandboxing und das Berechtigungsmodell. Claude Code innerhalb von tmux steuern löst die andere Hälfte des Problems, da eine abgebrochene SSH- (Secure-Shell-) Sitzung einen Agenten im Vordergrund mitten bei der Arbeit beendet. Richten Sie das Konto so ein, wie Sie jedes Dienstkonto einrichten würden. Benutzer mit geringsten Berechtigungen auf einem VPS beschreibt dieses Vorgehen ausführlich.

FAQ

Kann Claude meine Server-Logs direkt lesen?

Nicht von selbst. 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 Auszug mit 100 Zeilen 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 Speicher für Zugangsdaten, /etc/shadow sowie Daten, die Ihren Benutzern gehören. Entfernen Sie Token aus Logauszügen, bevor diese den Prompt erreichen. Ein weniger offensichtlicher Fall: Die Ausgabe von docker compose config enthält Ihre .env-Werte in aufgelöster Form. Verwenden Sie daher docker compose config -q. Dieser Befehl validiert die Datei und gibt nichts aus.

Ist es sicher, Claude auf einem produktiven VPS Befehle ausführen zu lassen?

Behandeln Sie Claude wie einen neuen Administrator ohne Kontext: Lesen ist in Ordnung, Änderungen müssen geprüft werden. Bitten Sie Claude auf produktiven Systemen um eine Erklärung und führen Sie den Befehl selbst aus. Wenn ein Agent Befehle ausführen soll, geben Sie ihm ein dediziertes Konto ohne privilegierte Rechte und ohne pauschalen sudo-Zugriff. 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 passiert besonders häufig bei herstellerspezifischen CLIs und neueren Subcommands, für die die 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 in einem Dry-Run 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 eine fehlende oder nicht ausführbare ExecStart-Binärdatei 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 fehlerfrei geladen werden und trotzdem beim ersten Start fehlschlagen.