wo Konfiguration, Logs und Programme wirklich hingehören
Wer /etc, /var, /usr und /opt durcheinanderbringt, baut Server, die sich nicht automatisieren, nicht sauber packen und nicht vorhersehbar warten lassen. Der Filesystem Hierarchy Standard definiert, wofür jedes Top-Level-Verzeichnis unter Linux gedacht ist, und wer sich daran hält, bekommt Systeme, die mit Paketmanagern, systemd und Automatisierungswerkzeugen reibungslos zusammenarbeiten, statt gegen sie zu kämpfen.
Inhaltsverzeichnis
- 1. Was der FHS ist und warum er zählt
- 2. /etc: Konfiguration zentral und vorhersehbar
- 3. /var: Variable Daten, Logs und Datenbanken
- 4. /usr: Programme, Bibliotheken und die Trennung von /usr und /
- 5. /opt und /srv: Optionale Software und Service-Daten
- 6. /home, /tmp und weitere Top-Level-Verzeichnisse
- 7. Warum die Konvention für Paketmanagement zählt
- 8. Automatisierung: FHS als Vertragsbasis für Skripte und Tools
- 9. Typische FHS-Verstöße und PHP-/Magento-Anwendungen richtig platzieren
- 10. Zusammenfassung
- 11. FAQ
1. Was der FHS ist und warum er zählt
Der Filesystem Hierarchy Standard, kurz FHS, ist keine Vorgabe des Linux-Kernels, sondern eine von der Linux Foundation gepflegte Konvention, die festlegt, wofür jedes Top-Level-Verzeichnis unter /, /etc, /var, /usr und weitere gedacht ist. Der Kernel selbst würde klaglos akzeptieren, wenn Konfigurationsdateien in /home landen oder Logdateien im Anwendungsordner liegen, aber genau das führt zu Servern, die sich nicht mehr vorhersehbar administrieren lassen. Der FHS ist damit weniger eine technische Grenze als ein sozialer Vertrag zwischen Distributionen, Paketmanagern, systemd-Einheiten und den Administratoren, die täglich mit diesen Systemen arbeiten.
Für Entwickler, die von der Anwendungsebene kommen, wirkt der FHS zunächst wie unnötige Bürokratie. In der Praxis zeigt sich aber schnell, warum die Konvention zählt: Backup-Skripte, Monitoring-Agenten, Log-Rotation und Deployment-Automatisierung gehen implizit davon aus, dass Konfiguration unter /etc, Laufzeitdaten unter /var und installierte Software unter /usr oder /opt liegen. Wer diese Erwartung bricht, muss jedes Werkzeug einzeln umkonfigurieren, statt sich auf sinnvolle Standardwerte verlassen zu können.
2. /etc: Konfiguration zentral und vorhersehbar
Der Name /etc stand ursprünglich für "et cetera", wird heute aber meist als "editable text configuration" gelesen, und genau das beschreibt seinen Zweck: host-spezifische, textbasierte Konfigurationsdateien, die ein Administrator lesen und anpassen kann, ohne ein Programm neu zu kompilieren. Systemd-Unit-Overrides landen unter /etc/systemd/system, Webserver-Vhosts unter /etc/apache2/sites-available oder /etc/nginx/sites-available, PHP-FPM-Pools unter /etc/php/8.4/fpm/pool.d. Keine Binärdateien, keine ausführbaren Programme im eigentlichen Sinn, nur wenige Ausnahmen wie Init-Skripte in /etc/init.d.
Die Regel für /etc lautet: alles, was den Betrieb einer bestimmten Maschine oder Anwendung individuell macht, gehört hierher, niemals in den Anwendungscode selbst. Ein Magento-Projekt, das Datenbank-Zugangsdaten oder Umgebungsvariablen direkt im Deployment-Verzeichnis statt in einer von /etc referenzierten Datei ablegt, verliert genau diese Trennung. Die Rechte sind hier meist restriktiv: root:root mit 644 für die meisten Dateien, 640 für alles mit Zugangsdaten, damit nur berechtigte Prozesse lesen können.
#!/usr/bin/env bash
# Explore /etc the way an admin would before touching a config file
set -euo pipefail
# List config files for a specific service, sorted by modification time
find /etc/php/8.4/fpm/pool.d -maxdepth 1 -name "*.conf" -printf "%T@ %p\n" \
| sort -n | cut -d' ' -f2-
# Confirm ownership and permissions before editing anything under /etc
stat -c "%A %U:%G %n" /etc/nginx/sites-available/*.conf
# Tighten permissions on a file that contains credentials
install -o root -g www-data -m 640 .env.example /etc/magento/production.env
# Reload the service after an /etc change, never restart blindly
systemctl reload php8.4-fpm
3. /var: Variable Daten, Logs und Datenbanken
/var enthält alles, was sich während des Betriebs verändert: Logdateien unter /var/log, Zwischenspeicher unter /var/cache, Warteschlangen unter /var/spool und persistente Anwendungsdaten unter /var/lib, etwa die MySQL-Datenverzeichnisse unter /var/lib/mysql. Der entscheidende Unterschied zu /etc: Inhalte in /var wachsen und schrumpfen laufend, während Konfigurationsdateien in /etc sich nur bei bewussten Änderungen ändern. Diese Trennung ist der Grund, warum viele Server /var auf ein eigenes, größeres Storage-Volume legen, während /etc auf dem Systemlaufwerk bleibt.
Für Backup-Strategien ist diese Unterscheidung besonders wichtig: /etc sichert man klein und häufig, weil Konfigurationsänderungen selten, aber kritisch sind. /var braucht andere Regeln, weil Log-Rotation und Wachstumsüberwachung nötig sind, um die Partition nicht volllaufen zu lassen. logrotate liest seine Regeln aus /etc/logrotate.d, wendet sie aber auf Dateien unter /var/log an, ein gutes Beispiel dafür, wie /etc und /var im FHS zusammenspielen, ohne sich zu vermischen.
; /etc/logrotate.d/magento: rules live in /etc, target files live in /var
/var/log/magento/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 640 www-data www-data
sharedscripts
postrotate
systemctl reload php8.4-fpm > /dev/null 2>&1 || true
endscript
}
; /etc/logrotate.d/nginx-access: same pattern for the webserver
/var/log/nginx/*.log {
weekly
rotate 8
compress
missingok
create 640 www-data adm
}
4. /usr: Programme, Bibliotheken und die Trennung von /usr und /
/usr, historisch für "Unix System Resources", enthält den überwiegenden Teil der installierten Software: Programme unter /usr/bin, Bibliotheken unter /usr/lib, Dokumentation unter /usr/share/doc und Header-Dateien für Entwicklung unter /usr/include. Ursprünglich war /usr als eigene, potenziell read-only mountbare Partition gedacht, die sich sogar über mehrere Rechner im Netzwerk teilen ließ, während /, /etc und /var lokal blieben. Diese strikte Trennung ist heute seltener geworden, aber das Prinzip bleibt: Inhalte unter /usr werden vom Paketmanager verwaltet, nicht von Hand editiert.
Moderne Distributionen haben mit dem sogenannten usrmerge /bin, /sbin und /lib zu Symlinks auf ihre Pendants unter /usr gemacht, sodass /bin/bash tatsächlich auf /usr/bin/bash zeigt. Wer selbst kompilierte Software installiert, die nicht über den Paketmanager läuft, gehört nach /usr/local, niemals direkt nach /usr, weil sonst Konflikte mit späteren Paket-Updates drohen. Diese Konvention ist einer der am häufigsten übersehenen Teile des FHS, gerade wenn Entwickler schnell ein selbstgebautes Tool systemweit verfügbar machen wollen.
#!/usr/bin/env bash
set -euo pipefail
# List every file a package installed, all under FHS-compliant paths
dpkg -L php8.4-fpm | grep -E '^/(etc|usr|var)/' | head -20
# Confirm the usrmerge symlink chain on a modern distro
readlink -f /bin/bash # -> /usr/bin/bash
readlink -f /sbin/iptables # -> /usr/sbin/iptables
# Self-built software: install into /usr/local, never /usr directly
./configure --prefix=/usr/local
make -j"$(nproc)"
sudo make install
# Verify no accidental writes landed outside the expected prefix
find /usr/local -newer /usr/local/.timestamp -type f 2>/dev/null || true
5. /opt und /srv: Optionale Software und Service-Daten
/opt ist für in sich geschlossene Drittanbieter-Software gedacht, die nicht der üblichen FHS-internen Aufteilung folgt, sondern ihre eigene Verzeichnisstruktur mitbringt, üblicherweise unter /opt/anbietername/produktname, etwa /opt/google/chrome oder /opt/gitlab. Der Vorteil: Ein solches Paket lässt sich rückstandslos entfernen, indem man einfach seinen Ordner löscht, ohne verstreute Dateien in /usr/bin oder /usr/lib aufräumen zu müssen. Genau deshalb bevorzugen viele kommerzielle Anwendungen /opt gegenüber der feingranularen FHS-Verteilung.
/srv ist dagegen für Daten gedacht, die dieses System für andere bereitstellt, etwa /srv/www für Webinhalte, /srv/ftp für FTP-Freigaben oder /srv/git für gehostete Repositories. In der Praxis wird /srv seltener konsequent genutzt als /opt, viele Distributionen und Hosting-Setups etablieren stattdessen eigene Konventionen wie /var/www. Wichtig ist die begriffliche Trennung: /srv beschreibt Daten, die nach außen bereitgestellt werden, /var beschreibt internen Betriebszustand des Systems selbst, auch wenn die Grenze in der Praxis oft verschwimmt.
6. /home, /tmp und weitere Top-Level-Verzeichnisse
/home enthält die persönlichen Verzeichnisse aller Benutzer, während /root als eigenes Home-Verzeichnis für den Superuser dient, bewusst getrennt von /home, damit root sich auch anmelden kann, wenn /home auf einer separaten, eventuell nicht gemounteten Partition liegt. /tmp ist für kurzlebige, temporäre Dateien gedacht, die beim Neustart oder durch systemd-tmpfiles regelmäßig gelöscht werden, /var/tmp dagegen für temporäre Dateien, die einen Neustart überdauern sollen.
/run, seit einigen Jahren fest im FHS verankert, ersetzt das ältere /var/run und enthält Laufzeitdaten seit dem letzten Boot: PID-Dateien, Unix-Sockets, Locks. Da /run als tmpfs im Arbeitsspeicher liegt, wird es bei jedem Neustart automatisch geleert, ein eingebauter Schutz gegen verwaiste PID-Dateien nach einem Absturz. /boot enthält Kernel und Bootloader, /dev die Gerätedateien, /proc und /sys sind virtuelle, vom Kernel erzeugte Schnittstellen, in die man niemals von Hand Dateien kopiert, sondern nur über die dafür vorgesehenen Mechanismen schreibt.
7. Warum die Konvention für Paketmanagement zählt
dpkg und rpm verlassen sich vollständig auf FHS-Pfade, um zu wissen, wohin eine Datei beim Installieren gehört und wie sie beim Deinstallieren rückstandslos wieder entfernt werden kann. Der Befehl dpkg -L paketname listet exakt auf, welche Dateien ein Paket unter welchen FHS-Pfaden abgelegt hat, und apt remove kann sich darauf verlassen, dass genau diese Liste vollständig ist. Ohne diese Vorhersehbarkeit müsste jedes Paket sein eigenes Cleanup-Skript mitbringen und hoffen, dass es wirklich jede installierte Datei findet.
Die Konvention verhindert außerdem Kollisionen zwischen Paketen: Binärdateien landen in /usr/bin, Konfiguration in /etc, Dokumentation in /usr/share/doc, und weil sich alle Pakete an diese Aufteilung halten, können hunderte Pakete koexistieren, ohne sich gegenseitig zu überschreiben. Genau deshalb existiert /usr/local als expliziter Ausweichort für manuell oder selbst kompilierte Software, damit sie niemals mit paketverwalteten Dateien in Konflikt gerät, wenn später ein apt upgrade dieselbe Software aus dem Repository installiert.
8. Automatisierung: FHS als Vertragsbasis für Skripte und Tools
Ansible-Playbooks, systemd-Units, Monitoring-Agenten wie Filebeat oder der Prometheus Node Exporter und Backup-Skripte gehen standardmäßig von FHS-konformen Pfaden aus: Logs unter /var/log, Konfiguration unter /etc, PID-Dateien unter /run. Wer diese Erwartung erfüllt, kann Standardkonfigurationen praktisch unverändert übernehmen. Wer sie bricht, weil zum Beispiel Logs im Anwendungsverzeichnis unter /opt/myapp/logs landen, muss für jedes einzelne Werkzeug einen abweichenden Pfad konfigurieren, was die Wartungslast über die Zeit spürbar erhöht.
Bei der Automatisierung mehrerer Server über verschiedene Distributionen hinweg zahlt sich FHS-Konformität besonders aus: Ein Ansible-Playbook, das Log-Rotation für /var/log/app konfiguriert, funktioniert identisch auf Debian, Ubuntu und RHEL, weil alle drei denselben FHS-Pfad respektieren. Sobald eine Anwendung eigene, distributionsspezifische Pfade erfindet, muss die Automatisierung diese Abweichung explizit abbilden, was Playbooks komplexer und fehleranfälliger macht, gerade bei heterogenen Serverflotten.
# ansible/roles/magento-server/tasks/main.yml
# Relies entirely on standard FHS paths, no custom locations needed
---
- name: Ensure FHS-compliant log directory exists
ansible.builtin.file:
path: /var/log/magento
state: directory
owner: www-data
group: www-data
mode: "0750"
- name: Deploy application config into /etc, never into the codebase
ansible.builtin.template:
src: templates/production.env.j2
dest: /etc/magento/production.env
owner: root
group: www-data
mode: "0640"
notify: reload php-fpm
- name: Symlink application var/log to the system-wide FHS location
ansible.builtin.file:
src: /var/log/magento
dest: /srv/www/magento/var/log
state: link
force: true
- name: Install logrotate rule from a version-controlled template
ansible.builtin.template:
src: templates/logrotate-magento.j2
dest: /etc/logrotate.d/magento
mode: "0644"
9. Typische FHS-Verstöße und PHP-/Magento-Anwendungen richtig platzieren
Der häufigste Verstoß in PHP- und Magento-Projekten: Logdateien, Cache und temporäre Uploads landen im Anwendungsverzeichnis selbst, statt unter /var/log, /var/cache oder /run verwaltet zu werden. Das mag lokal praktisch wirken, bricht aber, sobald Log-Shipper oder Monitoring-Agenten mit ihren Standardpfaden arbeiten und die Anwendung schlicht nicht finden. Ein zweiter klassischer Fehler: Produktionscode landet im Home-Verzeichnis eines Deploy-Users, etwa /home/deploy/magento-live, obwohl /home für persönliche Nutzerdaten und nicht für Server-Workloads gedacht ist.
Auf einem sauber organisierten Server gehört Magento-Code nach /var/www/magento oder, wenn der Hosting-Stack die /srv-Konvention konsequent nutzt, nach /srv/www/magento. Die var/log- und var/cache-Verzeichnisse innerhalb des Magento-Projekts sollten als Symlinks auf /var/log/magento beziehungsweise /var/cache/magento zeigen, damit Log-Rotation und Monitoring automatisch greifen. Medien-Uploads unter pub/media gehören auf ein separates Volume mit eigener Backup-Strategie, damit ein Code-Deployment niemals versehentlich Kundendaten überschreibt oder verwirft.
| Bereich | Verstoß gegen den FHS | FHS-konforme Lösung | Warum das zählt |
|---|---|---|---|
| Anwendungscode | /home/deploy/magento-live |
/var/www/magento oder /srv/www/magento |
Home-Verzeichnisse sind für Nutzer gedacht, nicht für Produktionscode |
| Logdateien | var/log/ im Projektordner |
Symlink auf /var/log/magento |
logrotate und Monitoring erwarten Logs unter /var/log |
| Uploads/Medien | Im Webroot ohne Trennung vom Code | Eigenes Volume, getrennte Backup-Strategie | Code-Deploys dürfen Kundendaten nie überschreiben |
| Temporäre Dateien | Eigener tmp/-Ordner im Projekt |
/var/tmp mit tmpfiles.d-Regeln |
Automatisches Aufräumen durch systemd-tmpfiles |
| PID-/Lock-Dateien | Fest verdrahtet, z. B. /home/deploy/app.pid |
/run/magento/ (tmpfs, von systemd verwaltet) |
/run wird bei jedem Boot geleert, keine Stale-PIDs |
Wer diese Zuordnung konsequent umsetzt, profitiert doppelt: Standardwerkzeuge wie logrotate, systemd-tmpfiles und Monitoring-Agenten funktionieren ohne Zusatzkonfiguration, und ein Wechsel des Hosting-Anbieters oder der Distribution wird deutlich risikoärmer, weil die Anwendung keine impliziten Annahmen über nicht-standardisierte Pfade mitbringt.
{
"deploy_target": "production",
"paths": {
"code": "/var/www/magento",
"config": "/etc/magento/production.env",
"log": "/var/log/magento",
"cache": "/var/cache/magento",
"media": "/var/www/magento-media",
"pid": "/run/magento/deploy.pid"
},
"post_deploy": [
"bin/magento setup:upgrade",
"bin/magento cache:flush",
"systemctl reload php8.4-fpm"
],
"note": "Every path below is a stock FHS location, no custom mounts required"
}
Mironsoft
Server-Architektur, Deployment-Automatisierung und Linux-Administration für Magento
Server, die dem FHS folgen statt gegen ihn zu arbeiten?
Wir bringen Magento- und PHP-Deployments in eine saubere, FHS-konforme Struktur, richten Log-Rotation, Backups und Automatisierung entlang der Standard-Pfade ein und machen eure Server damit portabel und wartbar.
Server-Audit
Bestehende Pfad-Struktur gegen den FHS prüfen und Risiken priorisieren
Deployment-Refactoring
Logs, Cache und Konfiguration sauber nach /var, /etc und /run trennen
Automatisierung
Ansible-Playbooks und systemd-Units auf FHS-Standardpfaden aufbauen
10. Zusammenfassung
Der Filesystem Hierarchy Standard löst ein einfaches, aber weitreichendes Problem: Ohne eine gemeinsame Konvention müsste jedes Werkzeug, jedes Paket und jedes Skript individuell wissen, wo auf einem bestimmten System welche Datei liegt. /etc bündelt Konfiguration, /var bündelt variable Laufzeitdaten, /usr bündelt installierte Software, /opt bündelt in sich geschlossene Drittanbieter-Pakete, /srv bündelt nach außen bereitgestellte Daten. Wer diese Zuordnung respektiert, bekommt Systeme, die sich mit Standardwerkzeugen administrieren, sichern und automatisieren lassen, ohne dass jede Abweichung manuell dokumentiert werden muss.
Für PHP- und Magento-Projekte zahlt sich FHS-Konformität besonders bei Logging, Backup und Deployment-Automatisierung aus. Ein Server, der Code, Konfiguration und variable Daten sauber nach FHS trennt, lässt sich mit Ansible, systemd und Standard-Monitoring ohne Sonderlocken betreiben, und ein späterer Wechsel von Distribution oder Hosting-Anbieter wird deutlich risikoärmer, weil keine impliziten, nicht dokumentierten Pfadannahmen im Code stecken.
Die Linux-Dateisystemhierarchie (FHS) - Das Wichtigste auf einen Blick
/etc vs. /var vs. /usr
/etc ist Konfiguration, /var sind variable Laufzeitdaten, /usr ist paketverwaltete Software. Nie vermischen.
/opt vs. /srv
/opt für in sich geschlossene Drittanbieter-Pakete, /srv für Daten, die dieses System nach außen bereitstellt.
Paketmanagement
dpkg/rpm verlassen sich auf FHS-Pfade für sauberes Installieren und rückstandsloses Entfernen.
PHP/Magento-Praxis
Code nach /var/www oder /srv/www, Logs symlinken auf /var/log, Medien auf ein separates Volume.