docs/linux/systemd-mount-units.md

307 lines
9.1 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Systemd Mount Units
[Systemd Mount Units](https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html) sind Konfigurationsdateien, mit denen Dateisysteme automatisch gemountet werden können vergleichbar mit Einträgen in der klassischen /etc/fstab, jedoch deutlich flexibler und besser in das moderne Systemstartverhalten integriert.
Sie ermöglichen es, Mount-Vorgänge exakt zu steuern inklusive Abhängigkeiten, automatischem Mount bei Zugriff und zuverlässiger Fehlerbehandlung.
[Systemd Automount Units](https://www.freedesktop.org/software/systemd/man/latest/systemd.automount.html) sind Konfigurationsdateien, welche Dateisysteme bei Bedarf verbinden. Diese werden beim ersten Aufrufen der Resource ausgeführt.
[CIFS (Common Internet File System)](https://docs.kernel.org/5.19/filesystems/cifs/index.html) ist ein Netzwerkprotokoll, das vor allem von Windows-Systemen zur Freigabe von Dateien und Ordnern verwendet wird. In Linux-Systemen können CIFS-Freigaben mit Hilfe von mount.cifs eingebunden werden ideal z.B. für den Zugriff auf NAS-Laufwerke, Windows-Server oder Samba-Freigaben. In Kombination mit systemd Mount Units lassen sich solche Netzwerklaufwerke zuverlässig, sicher und bei Bedarf automatisch einbinden.
## Ziele
In diesem Artikel wird beschrieben, wie CIFS-Netzwerkfreigaben mit Hilfe von systemd Mount- und Automount-Units unter Linux eingebunden werden können.
Dies wird am Beispiel eines `SMB` Servers im lokalen Netzwerk erleutert.
> [!NOTE]
> Diese Anleitung berücksichtigt unveränderliche (immutable) Distributionen wir SteamOS oder Fedora Atomic Desktops.
> Daher werden ausschließlich systemd Services genutzt und auf systemd Hooks verzichtet, da diese in immutablen Verzeichnissen definiert werden.
> Die Verwendung einer immutable Distribution führt in einigen Fällen zu einer anderen Verzeichnisstruktur. Diese werden in dieser Anleitung verwendet.
> Die folgenden Pfade würden bei einer traditionellen Distribution abweichen:
> | Immutable | Standard |
> | ----------------------- | ----------------------- |
> | /var/mnt | /mnt |
> | /var/usrlocal/bin | /usr/local/bin |
## Anleitung
### Schritt 1: Anmeldedaten sicher speichern
Lege eine Datei an, welche die SMB-Anmeldedaten enthält:
```bash
sudo cat > /etc/smb-credentials <<EOF
username=user
password=pw
EOF
```
> Ersetze `user` und `pw` durch die tatsächlichen Zugangsdaten.
Sichere die Datei mit den richtigen Berechtigungen:
```bash
sudo chmod 600 /etc/smb-credentials
sudo chown root:root /etc/smb-credentials
```
Diese Datei enthält sensible Informationen. Es sollte sichergestellt werden, dass nur `root` darauf Zugriff hat.
### Schritt 2: Mountpunkte anlegen
Erstelle die benötigten Verzeichnisse für die Netzwerkfreigaben:
```bash
sudo mkdir -p /var/mnt/Dokumente # weitere Mounts ergänzen
```
### Schritt 3: systemd Mount- und Automount-Units erstellen
Für jede Freigabe werden zwei Dateien benötigt:
- eine .mount-Unit
- eine .automount-Unit
Die Namen können dabei frei gewählt werden. Sie müssen lediglich pro Unit übereinstimmen und die korrekte oben genannte Dateiendung haben.
#### Beispiel: CIFS-Freigabe für `/var/mnt/Dokumente`:
#### Mount-Unit: `/etc/systemd/system/var-mnt-Dokumente.mount`
```bash
sudo nano /etc/systemd/system/var-mnt-Dokumente.mount
```
```ini
[Unit]
Description=CIFS Mount für Dokumente
After=network-online.target
Wants=network-online.target
[Mount]
What=//10.0.0.3/Dokumente
Where=/var/mnt/Dokumente
Type=cifs
Options=credentials=/etc/smb-credentials,file_mode=0777,dir_mode=0777,nofail,_netdev,iocharset=utf8,vers=3.0
[Install]
WantedBy=multi-user.target
```
#### Automount-Unit: `/etc/systemd/system/var-mnt-Dokumente.automount`
```bash
sudo nano /etc/systemd/system/var-mnt-Dokumente.automount
```
```ini
[Unit]
Description=Automount für CIFS Dokumente
[Automount]
Where=/var/mnt/Dokumente
TimeoutSec=30
[Install]
WantedBy=multi-user.target
```
### Schritt 4: Aktivieren und Starten
Nach dem Erstellen wird die Automount-Unit aktiviert (die Mount-Unit wird dann automatisch eingebunden):
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now var-mnt-Dokumente.automount
```
Optional den Status prüfen:
```bash
systemctl status var-mnt-Dokumente.automount
```
## Automount-Triggering
Systemd automounts werden erst getriggert, wenn auf den Mountpoint zugegriffen wird. Damit die CIFS-Freigaben in Dolphin unter "Fremdgeräte" erscheinen, müssen sie einmalig ausgelöst werden.
Hierzu kann ein Script erstellt werden, welches nach dem Start des PCs prüft, ob die Freigabe verfügbar ist und den Mount-Point anschließend durch einen ls-Zugriff triggert.
![Alternativtext](/linux/img/mounts-in-dolphin2.png)
### Schritt 1: Trigger-Skript erstellen
Der Speicherort des Skripts ist beliebig, er muss lediglich im Systemd Service angegeben werden und sollte persistent sein.
```bash
sudo nano /var/usrlocal/bin/mounts-connect.sh
```
```sh
#!/usr/bin/env bash
# /var/usrlocal/bin/mounts-connect.sh
# ----- Konfiguration -----
# Zielhost oder IP für Ping-Check
TARGET_HOST="10.0.0.3"
# Maximale Anzahl an Ping-Versuchen (bei 2 Sekunden Pause pro Versuch)
MAX_TRIES=30
# Array mit allen Automount-Pfaden
AUTOMOUNTS=(
"/var/mnt/Dokumente"
# weitere Mounts ergänzen
)
# ----- Script-Start -----
count=0
# 1. Warteschleife für Netzwerkverfügbarkeit mit Abbruch nach MAX_TRIES
until ping -c 1 -W 1 "${TARGET_HOST}" &> /dev/null; do
((count++))
if (( count >= MAX_TRIES )); then
echo "Host ${TARGET_HOST} not reachable after ${MAX_TRIES} tries cancelled." >&2
exit 1
fi
sleep 2
done
# Kurze Stabilisierungspause
sleep 5
# 2. Automounts triggern
echo "Triggering automounts on ${TARGET_HOST}..."
for mountpath in "${AUTOMOUNTS[@]}"; do
if [ -d "${mountpath}" ]; then
ls "${mountpath}" &> /dev/null &&
echo "${mountpath} triggered" ||
echo "Error while triggering ${mountpath}" >&2
else
echo "Path ${mountpath} does not exist" >&2
fi
done
echo "All Automounts triggered."
exit 0
```
Das Skript ausführbar machen:
```bash
sudo chmod +x /var/usrlocal/bin/mounts-connect.sh
```
### Schritt 2: Systemd Service erstellen
```bash
sudo nano /etc/systemd/system/mounts-connect.service
```
```ini
[Unit]
Description=Trigger CIFS Automounts for Dolphin
After=network-online.target
Wants=network-online.target
Before=graphical.target
[Service]
Type=oneshot
ExecStart=/var/usrlocal/bin/mounts-connect.sh
User=root
RemainAfterExit=yes
TimeoutStartSec=60
[Install]
WantedBy=multi-user.target
```
Hier ist wichtig, dass der Service erst ausgeführt wird, wenn das network-online target erreicht ist, kurz bevor das grafical target erreicht würde.
Das Skript hat ein Timeout damit es bei fehlender Verbindung nicht ewig versucht, die Resource zu pingen.
### Schritt 3: Service aktivieren
```bash
sudo systemctl daemon-reload
sudo systemctl enable mounts-connect.service
```
## CIFS/SMB Mounts und Standby
Nach dem Standby (Suspend-to-RAM) verlieren die Mounts manchmal die Verbindung, was dazu führt, dass Dolphin und andere Programme beim Zugriff „einfrieren“ und die Verbindung zu den SMB-Shares schließlich fehlschlägt.
Während des Standbys wird die Netzwerkverbindung getrennt. Nach dem Aufwachen ist das Netzwerk nicht sofort oder nicht im gleichen Zustand wiederhergestellt. Die bestehenden Mounts werden dadurch „taub“ und reagieren nicht mehr auf Anfragen.
Systemd-automount erkennt den Verbindungsverlust nicht immer und versucht weiterhin, den Mount zu nutzen, was zu langen Timeouts führt
### Lösung:
Die robusteste Methode ist, die Mounts beim Suspend automatisch auszuhängen und nach dem Resume neu einzuhängen. Hierzu können systemd Services als trigger das `suspend.target` verwenden. Hierzu müssen zwei Services erstellt werden:
- Unmount-Service mit `Before=suspend.target`
- Mount-Service mit `After=suspend.target`
Zum Wiederverbinden der Mounts verwenden wir das bereits zuvor erstellte `mounts-connect.sh` Skript.
### Schritt 1: Unmount Service erstellen
```bash
sudo nano /etc/systemd/system/mounts-disconnect.service
```
```ini
[Unit]
Description=Disconnect CIFS mounts before suspend
Before=suspend.target
[Service]
Type=oneshot
ExecStart=/usr/bin/umount -l /var/mnt/Dokumente
#ExecStart=/usr/bin/umount -l (weitere...)
[Install]
WantedBy=suspend.target
```
### Schritt 2: Bestehenden Trigger-Service erweitern
Der bestehende `mounts-connect.service` kann um den `After=suspend.target` Trigger erweitert werden:
```ini
[Unit]
Description=Trigger CIFS Automounts for Dolphin
-- After=network-online.target
++ After=network-online.target suspend.target
Wants=network-online.target
Before=graphical.target
[Service]
Type=oneshot
ExecStart=/var/usrlocal/bin/mounts-connect.sh
User=root
RemainAfterExit=yes
TimeoutStartSec=60
[Install]
-- WantedBy=multi-user.target
++ WantedBy=multi-user.target suspend.target
```
### Schritt 3: Services neu laden und aktivieren
```bash
sudo systemctl daemon-reload
sudo systemctl enable mounts-disconnect.service
sudo systemctl enable mounts-connect.service
```