Mini-VPS optimiert mit Claude Code

Als mein kleiner VPS heute Morgen einfach einfror und ich ihn neu starten musste, beschloss ich, das Problem endlich richtig anzugehen — gemeinsam mit Claude Code direkt im Terminal.

Der Patient

Ein kleiner VPS mit 1 CPU, 896 MB RAM, 10 GB Disk. Drauf läuft ein nginx Reverse-Proxy, der ein knappes Dutzend Dienste nach außen exponiert: Blogs, ein Mastodon-Server, ein paar Kollaborationstools. Leichte Kost — eigentlich.

Die Diagnose

Claude hat sofort den Finger in die Wunde gelegt:

  • Kein Swap — beim ersten RAM-Engpass friert das System ein, statt langsam zu werden
  • RAM: 71 MB frei bei 896 MB gesamt
  • Hauptverbraucher: Node.js (90 MB), diverse Systemdienste,
    und snapd — das auf einem Server schlicht nichts verloren hat

Was wir gemeinsam erledigt haben

1. Swap einrichten

2 GB Swap-Datei angelegt, in /etc/fstab eingetragen. Der Server überlebt jetzt RAM-Spitzen, statt einzufrieren. Sofortiger Effekt.

2. snapd aufräumen

Erst geprüft, ob snapd wirklich genutzt wird — tatsächlich war hugo als Snap installiert. Nach Installation via apt konnte snapd sauber entfernt werden. Ergebnis: ~140 MB RAM wieder frei.

3. Nginx Security-Headers verifiziert

Alle 17 vhosts geprüft: X-Frame-Options, X-Content-Type-Options, Strict-Transport-Security, Referrer-Policy — überall gesetzt, teils via zentralem Snippet, teils direkt. Kein vhost ohne Headers.

4. fail2ban von 1 auf 4 Jails erweitert

Vorher: nur SSH, mit schwachen Defaults (10 Minuten Ban nach 5 Versuchen).

Jetzt:

  • sshd — maxretry 3, Ban 24 Stunden
  • nginx-http-auth — Brute-Force auf Login-Seiten
  • nginx-botsearch — Scanner die nach /wp-admin, /.env etc. suchen
  • nginx-bad-request — Garbage-Requests und fehlerhafte HTTP-Anfragen

Dazu Increment-Banning: Wer wiederkommt, wird progressiv länger gesperrt — 1h → 2h → 4h → bis zu einer Woche.

Kleines Detail das uns fast entgangen wäre: die nginx-Jails lasen gar keine Logs, weil backend = systemd gesetzt war — nginx schreibt aber in Dateien, nicht ins Journal. Nach dem Fix auf backend = auto wurden sofort 6 Log-Dateien überwacht und erste Treffer gezählt.

5. Disk von 87 % auf 78 % befreit

Das systemd-Journal hatte ohne Limit 885 MB angesammelt. Nach journalctl --vacuum-size=200M und einem dauerhaften Limit in journald.conf.d/size.conf waren ~700 MB auf einen Schlag weg.

Das Ergebnis

Vorher Nachher
Kein Swap → System friert ein 2 GB Swap, persistent
71 MB RAM frei ~220 MB frei
1 fail2ban-Jail, schwache Defaults 4 Jails, Increment-Banning
Disk 87 % voll Disk 78 %, Journal limitiert
snapd läuft ungenutzt sauber entfernt

Was mich begeistert hat

Claude hat nicht einfach Befehle rausgefeuert. Es wurde immer erst geprüft — läuft hugo wirklich über snap? Liest der Jail wirklich die richtigen Log-Dateien? Warum zeigt nginx-bad-request keine Treffer?

Jeder Schritt wurde erklärt, jede Änderung begründet. Das Ergebnis ist kein Cargo-Cult-Serversetup, sondern eines das ich verstehe und selbst weiterentwickeln kann.

Ein kleiner VPS, ein Vormittag, ein deutlich besserer Server.
Ich bin wirklich begeistert.

Share