Die Linux-Dateisystemhierarchie verstehen (FHS)
$
/etc
Linux · Dateisystem · FHS · Administration
Die Linux-Dateisystemhierarchie verstehen (FHS)
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.

14 Min. Lesezeit FHS · /etc · /var · /usr · /opt · /srv Debian · RHEL · systemd

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.

11. FAQ: Die Linux-Dateisystemhierarchie (FHS)

1Was ist der Filesystem Hierarchy Standard (FHS)?
Eine von der Linux Foundation gepflegte Konvention, die festlegt, wofür jedes Top-Level-Verzeichnis gedacht ist. Der Kernel erzwingt ihn nicht, Paketmanager und systemd setzen ihn aber voraus.
2Muss sich jede Linux-Distribution an den FHS halten?
Nicht verpflichtend, aber Debian, Ubuntu, RHEL und Fedora folgen ihm weitgehend, weil Paketmanager und systemd darauf aufbauen. Abweichungen gibt es vor allem bei Details wie /srv.
3Was ist der Unterschied zwischen /etc und /var?
/etc enthält statische, host-spezifische Konfiguration. /var enthält variable Laufzeitdaten wie Logs, Cache und Datenbankinhalte, die sich laufend verändern.
4Wofür ist /usr da, und warum nichts von Hand ändern?
/usr enthält paketverwaltete Software. Manuelle Änderungen werden beim nächsten Update überschrieben. Selbst kompilierte Software gehört nach /usr/local.
5Wann verwende ich /opt und wann /srv?
/opt für in sich geschlossene Drittanbieter-Pakete mit eigener Struktur. /srv für Daten, die das System nach außen bereitstellt, etwa Webinhalte oder Repositories.
6Was gehört in /run, im Unterschied zu /var/run?
/run enthält Laufzeitdaten seit dem letzten Boot als tmpfs im Arbeitsspeicher. /var/run ist der ältere Pfad und heute meist ein Symlink auf /run.
7Warum bricht Paketmanagement bei Abweichung vom FHS?
dpkg/rpm verlassen sich auf vorhersehbare Pfade für Installation und Deinstallation. Abweichungen können zu Kollisionen zwischen Paketen und verwaisten Dateien führen.
8Wohin gehört Magento-Code auf einem sauberen Server?
Nach /var/www/magento oder /srv/www/magento, niemals in ein Benutzer-Home-Verzeichnis. /home ist für persönliche Nutzerdaten gedacht.
9Wohin gehören Magento-Logs und Cache-Dateien?
var/log und var/cache im Projekt sollten als Symlinks auf /var/log/magento und /var/cache/magento zeigen, damit Standard-Tools automatisch greifen.
10Was ist usrmerge und warum ist /bin ein Symlink?
usrmerge macht /bin, /sbin und /lib zu Symlinks auf /usr-Pendants, für einen einheitlicheren, weniger fragmentierten Pfad-Baum.