Logrotate einrichten: Linux-Logs richtig verwalten

Configure logrotate to automatically rotate, compress, and manage Linux log files with practical examples for Nginx, Docker, and system logs.

Logrotate einrichten: Linux-Logs richtig verwalten

Logs sind eines der Sachen, die unsichtbar sind, bis sie dir den Server killen. In meinem ersten Jahr auf einem eigenen VPS lief der nginx-Access-Log über Monate ohne Rotation — bis /var/log die Disk zu 100 % gefüllt hatte und der Mailserver still starb. Logrotate lernen ist deshalb ein Thema, bei dem der "lerne es vorher"-Tipp ernst gemeint ist.

Das Gute: Logrotate ist auf jedem Debian-basierten System vorinstalliert, läuft täglich via Cron, und die meisten Pakete bringen ihre eigenen Config-Dateien mit. Man muss es nur verstehen, wenn man eigene Services logged oder die Defaults anpassen will.

Was Logrotate macht

Einmal täglich (meist 3 Uhr morgens via /etc/cron.daily/logrotate) durchläuft Logrotate alle Configs in /etc/logrotate.d/ und prüft pro Datei: ist sie groß oder alt genug, um rotiert zu werden? Wenn ja, wird sie umbenannt (access.log → access.log.1), optional komprimiert, und eine neue leere Datei angelegt.

Alte Rotationen werden gelöscht, wenn die konfigurierte Anzahl überschritten wird.

Eine Standard-Config

/etc/logrotate.d/myapp:

/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 myapp myapp
    sharedscripts
    postrotate
        systemctl reload myapp
    endscript
}

Was die einzelnen Zeilen tun:

  • daily — einmal pro Tag rotieren. Alternativen: weekly, monthly, size 100M
  • rotate 14 — 14 alte Dateien aufheben, dann löschen
  • compress — alte Rotationen mit gzip komprimieren
  • delaycompress — die letzte Rotation noch nicht komprimieren (wichtig für Services, die noch in die alte Datei schreiben könnten)
  • missingok — keinen Fehler werfen, wenn die Datei nicht existiert
  • notifempty — nicht rotieren, wenn die Datei leer ist
  • create 0640 myapp myapp — neue Datei mit diesen Permissions und User/Group anlegen
  • postrotate — Script nach der Rotation ausführen, z.B. Service reloaden

Warum "copytruncate" meistens falsch ist

Es gibt einen weiteren Modus: copytruncate. Statt die Datei umzubenennen, wird sie kopiert und dann auf 0 gekürzt. Das klingt gut, weil der Service nicht reloaded werden muss, und funktioniert für einfache Apps.

Aber: zwischen cp und truncate schreibt der Service weiter in die Datei. Diese Writes gehen verloren, weil truncate sie verschiebt — und der Kernel die Datei-Position des Service nicht zurücksetzt. Resultat: sporadischer Daten-Verlust, der in produktiven Logs sehr schwer zu diagnostizieren ist.

Wenn der Service SIGHUP oder reload unterstützt, ist postrotate mit Reload die richtige Wahl. copytruncate nur als letzten Ausweg.

nginx-Beispiel

nginx bringt seine eigene Logrotate-Config mit in /etc/logrotate.d/nginx:

/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        invoke-rc.d nginx rotate >/dev/null 2>&1
    endscript
}

nginx -s reopen öffnet die Log-Files neu, ohne den Service neu zu starten — das ist das, was invoke-rc.d nginx rotate im Hintergrund macht.

Docker-Container-Logs

Docker schreibt Container-Logs nach /var/lib/docker/containers/<id>/<id>-json.log. Ohne Begrenzung können die enorm wachsen. Die Lösung ist nicht Logrotate, sondern Dockers eigene Log-Driver-Konfiguration:

/etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "5"
  }
}

Docker-Daemon neu starten, fertig. Jeder neue Container nutzt diese Defaults. Für existierende Container: docker compose up -d --force-recreate.

Logrotate über Docker-Logs drüberlaufen zu lassen ist möglich, aber fragil — Dockers internes Buffering kommt oft mit externer Rotation nicht klar.

Testen, dass es läuft

logrotate -d /etc/logrotate.d/myapp    # dry run
logrotate -f /etc/logrotate.d/myapp    # force rotation

-d (debug) zeigt, was Logrotate tun würde, ohne es zu tun. -f (force) rotiert jetzt, egal ob die Conditions erfüllt sind.

Wichtig: Logrotate speichert State in /var/lib/logrotate/status. Wenn du manuell eine Datei rotiert hast und Logrotate "verwirrt" wirkt, darin nachschauen.

Was ich mittlerweile immer mache

Bei jedem neuen Service frage ich mich: wo logged der hin? Wie groß werden die Logs? Schon bei der Installation eine Logrotate-Config anlegen, nicht erst wenn die Disk voll ist. 5 Minuten jetzt sparen einen Notfall später.

Außerdem: Disk-Space-Monitoring mit Alert bei 80 %. Logrotate löst das Wachstums-Problem, aber nicht den einmaligen Einbruch, wenn ein Service plötzlich 10 GB pro Stunde logged (Bug, Debug-Mode aktiviert, etc.). Dann kommt man mit Logrotate nicht hinterher.