Headless, doch nicht kopflos
Autor: Gerd Raudenbusch
Stand: 07.06.2026
Ein einfacher Rechner mit Linux und angeschlossenem Festspeicher und Backup-Strategie - und schon kann es eigentlich losgehen, ihn als Dateiserver, Musikserver oder Medienserver im Heimnetz einzusetzen.
Doch was muss getan werden, dass die Festplatte nicht schon in jüngster Zeit aufgrund der vielen Schreibzugriffe defekt wird? Welche Protokolle muss der Rechner sprechen, damit andere Geräte - Fernseher, Radios, Rechner - ihn im Heimnetz sofort finden können?
Inhalt
- Optimierung von Schreibzugriffen und Energieeinstellungen auf Festspeicher-Medien
- Optimierung des Schreibens von Log-Dateien
- Automatische Paketaktualisierungen mit apt
- Heimnetzwerk-Multimedia-Protokolle
- Dienste für den Heimserver des Heimnetzes
Optimierung von Schreibzugriffen und Energieeinstellungen auf Festspeicher-Medien
Der eigene NAS oder Medienserver zu Hause wird oft Headless betrieben, bzw. man deaktiviert den Bildschirm oder die GUI. Damit die Festspeicher-Medien solcher Server möglichst lange hält, macht es Sinn, die Einstellungen der Festplatte und des Dateisystems dafür zu optimieren.
Minimierung der Festplatten-Schreibzugriffe
Um die Festplatten auf dem NAS maximal zu schonen, müssen vor allem
unnötige Schreibvorgänge minimiert und der Parkmodus aktivieret werden.
Dies kann auch auf LUKS-Partitionen angewendet werden. Dazu werden
zusätzliche mount-Optionen in der Datei /etc/fstab
zugefügt. Die perfekte Kombination:
zram + noatime + journald volatile führt ohne
Benutzerinteraktion zu 0 Schreibzugriffen auf
Festplatten.
Anpassung der Mount-Flags
Wichtige Mount-Optionen in der fstab:
noatime– am wichtigsten! Keine Zugriffszeit-Updates (spart 80% Schreibzugriffe) und sollte auf jeden Fall für alle Mounts in/etc/fstabaktiviert werdennodiratime– Verzeichnis-Zugriffszeiten deaktivierencommit=60– Journal alle 60s statt 5s schreibenbarrier=0– Write barrier deaktivieren (schneller, aber minimal riskanter)errors=remount-robeibehalten (kritisches Root-FS)barrier=0am System-FS vorsichtig, bei Stromausfall besteht minimal höheres Risiko
| Option | Schreibzugriffe | Crash-Sicherheit | NAS/Server |
|---|---|---|---|
barrier=1 (default) |
Normal | Hoch | ✅ sicher |
barrier=0 |
-30% | Mittel | ⚠️ akzeptabel |
commit=60 |
-80% | Hoch | ✅ immer |
Empfehlung NAS: barrier=0 OK (UPS
empfohlen) Empfehlung Root: barrier=1
lassen oder relatime
- relatime ist als Kompromiss sicherer:
relatime,noatime,nodiratime(stattdefaults) - Sicherere Variante für Root:
/dev/mapper/vgubuntu-root / ext4 errors=remount-ro,relatime,nodiratime,commit=60 0 1- Variante für NAS-Platte
# Für ext4 Dateisysteme (typisch für Ubuntu NAS)
UUID=xxxx-xxxx /mnt/nas ext4 defaults,noatime,nodiratime,commit=60,barrier=0 0 2Aktivierung des Energiesparmodus der Festplatten
hdparmist ein Linux-Kommandozeilenwerkzeug, mit dem man
Parameter von ATA/SATA-Festplatten und SSDs anzeigen und ändern sowie
einfache Leistungstests durchführen kann. Typische Einsatzzwecke
sind:
- Cache- und Power-Management abfragen oder setzen.
- DMA- und Acoustic-Management konfigurieren.
- Laufwerksinfos auslesen, zum Beispiel mit
sudo hdparm -I /dev/sdafür die Festplattedev/sda
Es kann mit sudo apt install hdparm installiert werden.
Wenn der Energiesparmodus aktiv ist, dann enthält die Ausgabe von
hdparm -I die Zeile
Power Management feature set. Das ist zu Beginn meist nicht
der Fall, und es muss zunächst die Konfiguration angepasst werden mit
vi /etc/hdparm.conf:
# Alle Festplatten
/dev/disk/by-id/ata-*
{
spindown_time = 24 # 120 Sekunden (24*5s)
apm = 127 # 127 ist als mittlerer Wert ein Kompromiss zwischen Energie sparen und Performance leisten
}Aktivierung des S.M.A.R.T Parkmodus für Festplatten
smartctl gehört zu smartmontools und ist primär für
S.M.A.R.T.-Diagnose, Laufwerkszustand und einige Gerätefunktionen
gedacht. Es kann mit sudo apt install smartmontools
installiert werden.
sudo smartctl -s apm,127 /dev/sdasetzt ebenfalls für /dev/sda den APM-Wert auf 127.sudo smartctl -s standby,24 /dev/sdakonfiguriert den Standby-Modus
Nicht jedes Laufwerk reagiert auf die Befehle hdparm und
smartctl gleich; bei manchen Geräten funktioniert einer
besser als der andere. Beide können APM beeinflussen,
aber smartctl ist stärker auf Diagnose und Überwachung
ausgerichtet, während hdparm stärker die klassische
Laufwerkskonfiguration fokussiert.
Überprüfung der optimierten Schreibzugriffe
- Der Befehl
sudo mount -aremountet alle Mountpunkte iostat -dx 2zeigt die Schreibzugriffe pro Sekundefor d in /dev/sd?; do echo "=== $d ==="; sudo hdparm -I $d | grep -i apm; donezeigt den APM-Status aller Disksmount | grep "noatime"; cat /proc/mounts | grep noatimezeigt die Mountpunkte mitnoatime-Optionsudo hdparm -I /dev/sda | grep -i powerprüft die Powermanagement-Einstellungen
Benutzung von RAM-Disk und Swap
Eine RAM-Disk ist einfach Speicher, der sich wie ein Laufwerk verhält. Sie ist super schnell, aber nur für flüchtige Daten geeignet, weil sie beim Ausschalten leer ist. Swap ist das klassische Auslagern von Speicher auf eine langsamere Speicherseite, damit das System bei vollem RAM weiterarbeiten kann. Das ist langsamer als RAM, aber wichtig für Stabilität. zram ist ein komprimierter Bereich im RAM, der als Swap benutzt wird. Dadurch passen mehr Daten in den Arbeitsspeicher, ohne dass sofort auf Platte ausgelagert werden muss. zswap sitzt zwischen RAM und echtem Swap und hält ausgelagerte Seiten zunächst komprimiert im Speicher, bevor sie bei Bedarf doch auf Disk geschrieben werden.
- RAM-Disk = schnelles Laufwerk im RAM
- Swap = klassisches Auslagern auf langsamere Speicher
- zram = komprimierter Swap direkt im RAM
- zswap = komprimierter Zwischenspeicher vor dem normalen Swap.
| Begriff | Was es ist | Wo liegt es | Hauptzweck | Vorteil | Nachteil |
|---|---|---|---|---|---|
| RAM-Disk | Ein Speicherbereich, der wie ein Laufwerk benutzt wird | Im Arbeitsspeicher | Sehr schnelle temporäre Dateien | Extrem schnell | Daten gehen beim Ausschalten verloren, belegt echten RAM |
| Swap | Auslagerungsspeicher für selten genutzte Speicherseiten | Meist auf SSD/HDD, manchmal als Datei oder Partition | RAM entlasten, Speicherengpässe abfedern | Verhindert eher Abstürze bei Speicherdruck | Deutlich langsamer als RAM |
| zram | Komprimiertes Swap-Gerät im RAM | Im Arbeitsspeicher | Mehr effektiver Speicher ohne Disk-I/O | Schnell, spart Disk-Zugriffe | Verbraucht CPU für Kompression, nutzt echten RAM |
| zswap | Komprimierter Puffer vor dem normalen Swap | Im RAM als Cache, dahinter normaler Swap auf Disk | Disk-Swap reduzieren | Nutzt vorhandenen Swap weiter und puffert komprimiert | Ebenfalls CPU-Overhead, funktioniert nur mit echtem Swap im Hintergrund |
Die Verlegung von Swap-Speicher auf eine RAM-Disk macht nicht deswegen Sinn, weil der Swap den RAM ersetzt, sondern weil Linux ihn auch dann sinnvoll nutzt, wenn noch freier RAM da ist. Denn Linux hält gern Daten im RAM, die gerade nicht aktiv gebraucht werden, und räumt sie bei Bedarf wieder ab. Swap hilft dabei, selten genutzte Speicherbereiche auszulagern, damit mehr RAM für wirklich wichtige Arbeit bleibt. Das ist besonders nützlich, wenn:
- Programme viel Speicher reservieren, aber nur einen Teil davon aktiv nutzen.
- Das System kurzfristige Speicher-Spitzen abfangen soll, ohne Prozesse sofort zu beenden.
- Man Abstürze durch knappen RAM vermeiden will.
Die Idee ist also nicht, Swap dauerhaft komplett im RAM zu halten, sondern ihn als komprimierten oder ausgelagerten Bereich im Arbeitsspeicher zu organisieren. Dann bleibt mehr "echter" RAM für laufende Anwendungen übrig, obwohl die Auslagerung technisch weiterhin im Speicher statt auf Platte liegt. Der Vorteil liegt nicht in mehr Kapazität im physikalischen Sinn, sondern:
- weniger I/O auf langsame Laufwerke,
- schnellere Reaktion als klassische Festplatten-Swap,
- bessere Kontrolle bei Speicherdruck.
Sinnvoll, bei:
- Systemen mit wenig RAM.
- SSD-schonenden Setups.
- Geräten, bei denen man eher seltene Speicherinhalte komprimiert statt auf Disk schreibt.
Weniger sinnvoll, wenn:
- sowieso genug RAM vorhanden ist.
- die zusätzliche Kompression CPU-Zeit kostet, die du lieber für Anwendungen hättest.
- du hauptsächlich maximale Performance ohne Speicherdruck-Optimierung willst.
Swap ist also kein Ersatz für RAM, sondern ein Sicherheitsnetz und ein Werkzeug für Speicherverwaltung. „Swap ins RAM verlegen“ kann sich lohnen, wenn du damit langsame Plattenzugriffe vermeidest und Speicher effizienter nutzt, aber es ist keine Magie gegen echten RAM-Mangel.
Folgende Schritte sind notwendig, um zram zu
nutzen:
- Festplatten-Swap komplett deaktivieren
# Aktuelle Swap deaktivieren
sudo swapoff -a
# Swap aus fstab auskommentieren oder löschen
sudo nano /etc/fstab
# Zeile mit "swap" oder "/swapfile" mit # auskommentieren
# Ubuntu systemd-swapfile deaktivieren
sudo systemctl disable --now systemd-swapfile.service
sudo systemctl mask systemd-swapfile.service- zram (RAM-Swap) einrichten
sudo apt update
sudo apt install zram-config- zram konfigurieren
sudo apt install zram-tools
Die Datei `/etc/default/zramswap` folgendermaßen anpassen:
```bash
#
# Faustregel:
# RAM < 04GB? --> zram auf 75% stellen
# RAM > 16GB? --> zram optional, oder swappiness=1
# Sonst: zram auf 50%
#
SIZE=2048 # zram-Größe = 50% des RAM bei 4GB RAM
ALGO=lz4 # Schnellste Kompression
PRIORITY=100 # Höher als Festplatten-Swap- Aktivierung des zram
sudo systemctl enable zramswap
sudo systemctl start zramswap- Swappiness optimieren
# Minimales Swappen (nur bei RAM-Mangel)
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
# Sofort anwenden
sudo sysctl vm.swappiness=10- Funktionsprüfung
# Swap-Status
free -h
swapon --show
# zram prüfen
cat /sys/block/zram0/mm_stat
zramctlErwartete Beispiel-Ausgabe nach Einrichtung:
total used free shared buff/cache available
Mem: 7.7G 1.2G 4.1G 20M 2.4G 6.2G
Swap: 2.0G 0B 2.0G
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 lz4 2G 0B 0B 0B 4 [SWAP]
- Test nach Reboot
reboot
free -h
swapon --show # Sollte nur zram zeigen- Swappiness finalisieren
cat << EOF | sudo tee -a /etc/sysctl.conf
vm.swappiness=5
vm.vfs_cache_pressure=50
vm.dirty_ratio=15
vm.dirty_background_ratio=5
EOF
sudo sysctl -p- Automatische zram-Größenanpassung (nice-to-have)
Die Datei /etc/default/zramswap anpassen:
# Automatisch 50% RAM
ALLOCATION=$(($(free | awk '/Mem:/ {print int($2/1024/2)}'))- Abschließender Test unter Last (empfohlen)
# 60s Stress-Test – beobachte free -h
stress --vm 4 --vm-bytes 3G --timeout 60s &
watch -n1 free -hOptimierung des Schreibens von Log-Dateien
ACHTUNG: Die Umleitung von Log-Dateien ins RAM bedeutet, daß sie nach einem Neustart weg sind! Diese Entscheidung ist Geschmacksache und hat Vor- und Nachteile. RAM-Logging ist schnell und schont die Datenträger, aber Logs gehen beim Reboot verloren und der Platz ist begrenzt. Daher sind die Schritte in diesem Kapiel individuell zu überdenken.
Umleiten von journald (systemd-Logs) ins RAM
Vorteile von journald im RAM
- Standardmäßig oft schon im RAM – viele Systeme
schreiben automatisch in
/run/log/journal - Sehr schnell – keine I/O-Verzögerung beim Schreiben der Logs
- Schont Festplatte/SD-Karte – weniger Schreibzugriffe, wichtig bei SD-Karten oder SSDs
- Logs bis zum Reboot verfügbar – auch ohne
Platten-Speicher sind sie über
journalctlabrufbar - Kein Sync nötig – journald schreibt asynchron, keine häufige Synchronisation
- Standardmäßig oft schon im RAM – viele Systeme
schreiben automatisch in
Nachteile von journald im RAM
- Logs gehen beim Reboot verloren – wenn
storage=volatile, sind sie nach Neustart weg - RAM-Verbrauch kann stark wachsen – journald kann mehrere GB RAM verbrauchen
- OOM-Killer-Risiko – in Containern kann der Memory-Limit gesprengt werden und OOM-Kills verursachen
- Begrenzter Platz – tmpfs auf
/runhat oft nur wenige 100 MB - Watchdog-Timeout-Gefahr – bei langsamer Schreibgeschwindigkeit kann systemd journald abstürzen lassen
- Limits müssen gesetzt werden – ohne
RuntimeMaxUseinjournald.confkann journald RAM komplett aufbrauchen
- Logs gehen beim Reboot verloren – wenn
Wichtige Einstellungen in
journald.confStorage=volatile– speichert nur im RAM (/run/log/journal)RuntimeMaxUse=128M– begrenzt RAM für Logs (z. B. 128 MB)MaxRetentionSec=1month– löscht Logs automatisch nach Zeit
Grobe Empfehlung nach Einsatzgebiet
- Desktop / Home –
storage=volatileokay, aberRuntimeMaxUsesetzen - Server / Produktion –
storage=persistent→ Logs auf Platte behalten - Raspberry Pi / SD-Karte –
storage=volatile+ tägliches Backup der Logs - Container (LXC) –
RuntimeMaxUseunbedingt setzen, sonst OOM-Kill
- Desktop / Home –
**Umsetzung:
/etc/systemd/journald.confbearbeiten:
[Journal]
Storage=volatile
RuntimeMaxUse=128M
RuntimeKeepFree=32M
MaxRetentionSec=1month- Prüfen des journald-Ziels Der Befehl
systemctl status systemd-journald --no-pager | grep -i "Journal"gibt entweder "Volatile" oder "Persistent" aus
tmpfs für temporäre Dateien nutzen
Zeile in /etc/fstab |
Wirkung |
|---|---|
tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0 |
Hängt /tmp als tmpfs ein, alle können schreiben, temporäre Dateien gehen beim Reboot verloren |
tmpfs /var/log tmpfs defaults,noatime,mode=0755 0 0 |
Hängt das Standardverzeichnis für Linux-Logdateien
/var/log als tmpfs ein, Logdateien gehen beim Reboot
verloren, nur Besitzer darf schreiben |
tmpfs /var/tmp tmpfs defaults,noatime,mode=1777 0 0 |
Hängt /var/tmp als tmpfs ein (wie /tmp). Vorsicht:
/var/tmp ist eigentlich für persistente temporäre Dateien
gedacht, die einen Neustart überleben sollen (z.B. Installer) |
Wartungsaufgaben für journal und temp
- Cronjobs einrichten mit
sudo crontab -e:
# Automatisches Journal leeren
echo '0 2 * * * root journalctl --vacuum-time=7d' | sudo tee /etc/cron.d/clean-journal
# Temp leeren
echo '0 3 * * * root rm -rf /tmp/* /var/tmp/*' | sudo tee /etc/cron.d/clean-tmpSchreibzugriffe von Samba optimieren
Es macht Sinn, die Schreibzugriffe von Samba zu optimieren. Dazu kann die
Datei /etc/samba/smb.conf folgendermaßen angepasst
werden:
[global]
strict locking = no
strict sync = no
sync always = noAutomatische Paketaktualisierungen mit apt
Optimalerweise aktualisiert der Heimserver sein Betriebssystem selbständig. Das Schlagwort unter Debian-basierten Systemen dafür ist "unattended upgrades" (="unaufgeforderte Aktualisierungen"). Dies wird wiefolgt eingerichtet:
sudo apt update
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
sudo systemctl enable --now unattended-upgradesNun kann die Datei /etc/apt/apt.conf.d/10periodic für
die tägliche Ausführung angepasst werden:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";Die automatische Aktualisierung des Kernel kann problematisch sein,
da es in manchen Fällen zu Problemen auf der
/boot-Partition kommen kann. Diese sollten manuell gemacht
werden und es sollte danach zumindest geprüft werden, ob das System
potentiell noch bootbar ist und die in /boot gesetzten
Links zum Kernel und initramfs noch in Ordnung sind, bevor der Neustart
mit einem aktualisierten Kernel durchgeführt wird.
Dazu muss die Datei
/etc/apt/apt.conf.d/50unattended-upgrades ergänzt werden
unter Unattended-Upgrade::Package-Blacklist:
Unattended-Upgrade::Package-Blacklist {
"linux-image.*";
"linux-headers.*";
"linux-modules.*";
"linux-kernel.*";
};Dies verhindert Updates für Kernel, Headers und Module. Nur andere
Pakete (z. B. Sicherheitsfixes) werden installiert. Die Timer können
überprüft werden mit
systemctl status apt-daily.timer apt-daily-upgrade.timer.
Standardmäßig laufen sie täglich (z. B. um 6 Uhr mit
Zufallsverzögerung). Logs finden sich in
/var/log/unattended-upgrades/.
Heimnetzwerk-Multimedia-Protokolle
| Kategorie | Zweck |
|---|---|
| Zeroconf | Automatische Netzwerk-Konfiguration ohne manuelle Einrichtung |
| Service Discovery | Automatische Erkennung von Geräten und Diensten im Netzwerk |
| Media Streaming | Übertragung von Audio/Video in Echtzeit |
| File Sharing | Dateiübertragung und -freigabe |
Für Heimnetzwerk-Medien (Video, Audio, Bilder) sind die wichtigsten:
| Anwendung | Protokoll |
|---|---|
| automatische Erkennung (Service Discovery) | mDNS / Bonjour / Avahi |
| Medienstreaming (TV, Stereoanlage) | DLNA / UPnP-AV |
| Apple-Streaming | AirPlay |
| Dateifreigabe (Windows) | SMB/CIFS |
| Dateifreigabe (Linux) | NFS |
| Datei-Transfer | FTP / SFTP / WebDAV |
Dateitransfer-Protokolle für den Heimserver
Protokoll-Übersicht
| Protokoll | Beschreibung |
|---|---|
| SMB (Server Message Block) | Windows-Standard für Datei- und Druckfreigaben (auch CIFS genannt) |
| NFS (Network File System) | Unix/Linux-Standard für Netzlaufwerke |
| FTP (File Transfer Protocol) | Klassisches Dateitransfer-Protokoll, früher ungesichert, heute oft als FTPS |
| SFTP (SSH File Transfer Protocol) | Verschlüsseltes FTP über SSH |
| WebDAV | Erweiterung von HTTP für Dateisynchronisation |
Datei-Zugriff per Samba
Samba ist eine Open-Source-Software, die es Linux- und Unix-Systemen ermöglicht, mit Windows-Netzwerken zu kommunizieren, also Dateien, Drucker und andere Ressourcen in einem gemischten Netzwerk freizugeben. Windows-Netzwerke nutzen das SMB/CIFS-Protokoll für Datei- und Druckfreigaben, Linux hat das nicht standardmäßig integriert. So implementiert Samba auch für Linux MB/CIFS.
sudo apt install sambainstalliert den Dienstsmbd- Samba-Benutzer sind gleichzeitig Systembenutzer. Einen zusätzlichen
Benutzer (nur für Samba) fügt man mit dem Befehl
sudo useradd -s /bin/false <benutzername>zu. - Das Paswort für einen Samba-Benutzer vergibt man mit:
sudo smbpasswd -a <benutzername> - Die Samba-Konfiguration prüft man mit
testparm -s - Den Samba-Dienst startet man neu mit
# sudo systemctl restart smbd; sudo systemctl restart nmbd - Den Samba-Client auf Ubuntu installiert man mit
sudo apt install smbclient - Eine Verbindung damit stellt man z.B. so her:
smbclient //<ip>/<freigabe> -U <Benutzer> - Für eine neue Freigabe eines Verzeichnisses hängt man einen solchen
Block an die Konfigurationsdatei
/etc/samba/smb.conf:
[Bilder]
path = /pfad-zum-ordner
browseable = yes # wenn ein Inhaltsverzeichnis gezeigt werden soll
read only = yes # wenn der Inhalt nur lesbar sein soll
valid users = nas # erlaubte Samba-Benutzer für diese FreigabeDatei-Zugriff per WebDAV
WebDAV (Web-based Distributed
Authoring and Versioning) ist eine von vielen Applikationen verwendete
Erweiterung von HTTP/1.1, die das Web vom reinen Informationsabruf zu
einem beschreibbaren Speichermedium macht. WebDAV lässt sich problemlos dockern. Hier
das Kontrollskript webdav.sh dazu:
#!/bin/bash
#
tag="latest"
if [ "${2}" != "" ]; then
tag="${2}"
fi
name=$(basename ${0} |cut -d "." -f1)
img="sfuhrm/docker-nginx-webdav"
#img="bytemark/webdav"
options="--restart unless-stopped \
-d \
-p 80:80 \
-v /media/deineplatte:/media/data \
-e LOCATION=/webdav \
-e USERNAME=username \
-e PASSWORD=password \
-m 1g"
menu () {
while true; do
cmd=(dialog --clear --backtitle "WebDAV menu" --title "WebDAV menu" --menu "Choice:" 22 120 12)
options=(
1 "Start container"
2 "Stop container"
3 "Restart container"
)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
case "$choice" in
1) clear; ${0} start; echo "Press any key."; read ;;
2) clear; ${0} stop; echo "Press any key."; read ;;
3) clear; ${0} restart; echo "Press any key."; read ;;
*) clear; return ;;
esac
done
}
echo "Container: ${name}"
if [ "${1}" == "" ]; then
menu
elif [ "${1}" == "start" ]; then
echo "Starting"
docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "stop" ]; then
echo "Stopping"
docker rm -f ${name}
elif [ "${1}" == "restart" ]; then
docker rm -f ${name} && docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "pull" ]; then
docker pull ${img}:${tag}
elif [ "${1}" == "login" ]; then
docker exec -it ${name} /bin/bash
elif [ "${1}" == "commit" ]; then
docker commit ${name} ${img}:${tag}
elif [ "${1}" == "load" ]; then
echo "Loading"
docker load < ${name}.tar.gz
elif [ "${1}" == "save" ]; then
echo "Saving"
docker save ${img}:${tag} | gzip > ${name}.tar.gz
else
echo "Unknown : ${1}"
exit 1
fiService-Discovery-Protokolle für den Heimserver
Protokoll-Übersicht
| Protokoll | Beschreibung |
|---|---|
| UPnP-AV (Universal Plug and Play Audio/Video) | Der Standard, nach dem die meisten Streaming-Geräte arbeiten |
| DLNA (Digital Living Network Alliance) | Erweitert UPnP-AV, legt Standardformate und Protokolle für Media-Wiedergabe fest |
| AirPlay (Apple) | proprietäres Protokoll für Audio/Video-Streaming von Apple-Geräten |
| Chromecast (Google) | Google-Protokoll zum Streamen von Inhalten auf TV und Lautsprecher |
| RTP (Real-Time Transport Protocol) | Übertragung von Audio/Video-Streams in Echtzeit |
Medienzugriff per DLNA
DLNA ist ein Vernetzungsstandard für digitale Geräte im Heimnetzwerk. Das Ziel ist, Multimedia-Daten (Fotos, Videos, Musik) zwischen Geräten unterschiedlicher Hersteller problemlos übertragen zu können. Der Verband wurde 2003 gegründet und umfasst große Hersteller wie Sony, Intel, Samsung und viele weitere. Die Funktionsweise ist einfach: DLNA-Geräte kommunizieren automatisch über das Netzwerk, ohne dass man jedes Gerät manuell konfigurieren muss. Typische DLNA-geräte sind Smart-TVs, PCs, Smartphones, Blu-ray-Player, AV-Receiver und Spielkonsolen. DLNA ist wie eine Art "Übersetzungs-Software", die es ermöglicht, dass beispielsweise das TV die Musik vom Medienserver streamen kann, ohne dass man sich um technische Kompatibilitäten kümmern muss.
MiniDLNA ist ein leichter Open-Source-DLNA-Server, der auch als ReadyMedia bekannt ist. Es macht jeden Linux- oder Unix-Rechner zu einem Medienserver für DLNA-kompatible Geräte. MiniDLNA verbraucht sehr wenig RAM und CPU, funktioniert sofort nach der Installation und ist für ressourcenschonende Systeme (wie Raspberry Pi) sehr beliebt. Die Software stellt eine Medienbibliothek (Fotos, Videos, Musik) im Netzwerk bereit. MiniDLNA ist also die Software, die es ermöglicht, dass DLNA-fähige Geräte (z.B. Smart-TV oder Handy) Musik, Videos und Fotos streamen können.
- Beispielkonfiguration für minidlna:
media_dir=A,/pfad-zu-deiner-Musik
media_dir=P,/pfad-zu-deinen-Bildern
media_dir=V,/pfad-zu-deinen-Videos
db_dir=/var/cache/minidlna
log_dir=/var/log/minidlna
port=8200
friendly_name=Mein Medienserver
inotify=yes
album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg
album_art_names=AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg
album_art_names=Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpgBojnour und mDNS
mDNS (Multicast DNS) ist ein Netzwerkprotokoll zur
Namensauflösung in kleinen lokalen Netzwerken ohne zentralen DNS-Server.
Wenn ein Gerät im Netzwerk eine IP-Adresse zu einem Hostnamen finden
möchte, muss es nicht gegen einen zentralen DNS-Server (wie
8.8.8.8 von Google) fragen, sondern sendet die Anfrage an
alle Geräte im lokalen Netzwerk.
Ein Gerät sendet eine DNS-Anfrage per Multicast an
alle Teilnehmer im Netzwerk. Die Anfrage geht an die spezielle
Multicast-Adresse 224.0.0.251 auf Port 5353.
Die Empfänger der Anfrage können diese per Multicast beantworten. Wenn
das gesuchte Gerät im Netzwerk ist, antwortet es mit seiner
IP-Adresse.
Hostnamen enden bei mDNS mit .local (z.
B. mein-pc.local, printer.local).
Wichtige Eigenschaften:
- Standard: Definiert in RFC 6762 und RFC 6763
- Ziel: Keine zentrale DNS-Server-Konfiguration nötig – jedes Gerät funktioniert sofort
- Protokoll: Nutzt UDP (kein TCP), da Multicast schneller und effizienter ist
- Anwendung: Automatisches Erkennen von Druckern, Dateifreigaben, AirPlay-Geräten, Smart-Home-Geräten
- Implementierungen: Apple Bonjour, Windows 10+ (eingebaut), Avahi (Linux)
mDNS ist wie ein „Ruf im Netzwerk". Statt an einen zentralen
DNS-Server zu fragen, ruft das Gerät laut „Wer ist
mein-pc.local?" und alle hören mit. Wenn das richtige Gerät
antwortet, weiß man die IP-Adresse.
Bonjour ist Apple's Software, die mDNS zur Geräteerkennung verwendet. Ein Bonjour-Client kann einen Avahi-Server sehen, da beide mDNS + DNS-SD verwenden. Avahi ist die Linux-Version von Bonjour und beide interagieren perfekt miteinander.
Avahi ist eine freie Open-Source-Implementierung von mDNS und DNS-SD (DNS Service Discovery) für Linux-Systeme. Es ermöglicht die automatische Vernetzung von Geräten im lokalen Netzwerk ohne manuelle Konfiguration.
- Ziel: Dienste und Rechner im lokalen Netzwerk ohne Konfiguration entdecken
- Technologie: Nutzt mDNS (Multicast-DNS) und DNS-SD (DNS Service Discovery)
- IP-Adresse: IP-Adresse ist uninteressant – Anwendungen suchen sich selbst das passende Programm
- Apple-Äquivalent: Fortsetzung von Bonjour (Apple) für Linux
- Verfügbarkeit: In den meisten Linux-Distributionen standardmäßig enthalten
- API: Nutzt D-Bus als primäre Schnittstelle für Programme
- Daemon: Der
avahi-daemonveröffentlicht und erkennt Dienste im Netzwerk
Vorteile von mDNS mit Avahi:
- Zero Configuration – keine manuelle Eingabe von IP-Adressen in Clients nötig, sie finden die Server selbständig
- Diensteerkennung – Drucker, Chat, Dateien, Medien werden automatisch gefunden
- Plug & Play – System sofort nach Netzwerkanschluß nutzbar
- Ressourcenschonend – geringer RAM- und CPU-Verbrauch
Mit
sudo apt update && sudo apt install avahi-daemon avahi-utils
kann Avahi installiert werden. Mit
sudo systemctl enable avahi-daemon: sudo systemctl start avahi-daemon
wird der Dienst gestartet. Mit
sudo apt-get install avahi-discover
Beispielkonfiguration:
[server]
use-ipv4=yes
use-ipv6=no
[reflector]
enable-reflector=yes
reflect-ipv=noDienste für den Heimserver des Heimnetzes
Git Repository (ohne Gitlab)
Git ist ein verteiltes Versionskontrollsystem, das sich zum weltweiten Standard für die Versionskontrolle entwickelt hat. Es wird verwendet, um Änderungen in Dateien – insbesondere Quellcode von Softwareprojekten – intelligent nachzuverfolgen und zu verwalten.
Die folgenden Befehle erstellen ein neues Git-Repository ohne Oberfläche. Als Versionskontrollsystem macht Git insbesondere Sinn für alle menschenlesbaren Dateien.
- Git-Verzeichnis erstellen:
sudo mkdir -p /media/nas/home_git_repositories/ - Rechte setzen:
sudo chown git:git /media/nas/home_git_repositories/; sudo chmod 755 /media/nas/home_git_repositories/ sudo find /media/nas/home_git_repositories/ -type d -exec chmod 775 {} \; sudo find /media/nas/home_git_repositories/ -type f -exec chmod 664 {} \;- Verzeichnis besiedeln:
sudo cp -r /etc/skel/. /media/nas/home_git_repositories/ - Benutzer erstellen :
sudo useradd -m -d /media/nas/home_git_repositories/ -s /bin/bash git
Git Repository (mit Gitlab)
Gitlab ist eine Weboberfläche für
Git, die viele Vorteile bietet, wenn intensiv und vielleicht zu Mehreren
mit Git gearbeitet wird. Gitlab kann
bequem im Docker betrieben werden. Das folgende Shellskript
gitlab.sh ist ein Kontrollskript für ein gedockertes Gitlab:
#!/bin/bash
# gitlab.sh control script
tag="latest"
if [ "${2}" != "" ]; then
tag="${2}"
fi
name=$(basename ${0} |cut -d "." -f1)
img="gitlab/gitlab-ce" # URL zu Repository
options="--detach \
--hostname $(hostname) \
--publish 2443:443 --publish 2080:80 --publish 2022:22 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
--shm-size 256m"
#########################
echo "Container: ${name}"
menu () {
while true; do
cmd=(dialog --clear --backtitle "Gitlab menu" --title "Gitlab menu" --menu "Choice:" 22 120 12)
options=(
1 "Start container"
2 "Stop container"
3 "Restart container"
)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
case "$choice" in
1) clear; ${0} start; echo "Press any key."; read ;;
2) clear; ${0} stop; echo "Press any key."; read ;;
3) clear; ${0} restart; echo "Press any key."; read ;;
*) clear; return ;;
esac
done
}
if [ "${1}" == "" ]; then
menu
elif [ "${1}" == "start" ]; then
echo "Starting"
docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "stop" ]; then
echo "Stopping"
docker rm -f ${name}
elif [ "${1}" == "restart" ]; then
docker rm -f ${name} && docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "login" ]; then
docker exec -it ${name} /bin/bash
elif [ "${1}" == "pull" ]; then
docker pull ${img}:${tag}
elif [ "${1}" == "commit" ]; then
docker commit ${name} ${img}:${tag}
elif [ "${1}" == "load" ]; then
echo "Loading"
docker load < ${name}.tar.gz
elif [ "${1}" == "save" ]; then
echo "Saving"
docker save ${img}:${tag} | gzip > ${name}.tar.gz
else
echo "Unknown : ${1}"
exit 1
ficopyparty
Copyparty ist ein in 2019
entstandener Open-Source-Portabler Python-Dateiserver (von 9001 auf
GitHub, FOSS), der alles kann: HTTP/Web-UI, WebDAV, FTP/FTPS, TFTP,
Zeroconf, Medien-Indexing, Deduplizierung und unterbrechungsfreie
Uploads – in nur einer einzigen Datei. Hier ist das
Kontrollskript copyparty.sh
#!/bin/bash
# copyparty.sh docker control script
tag="latest"
if [ "${2}" != "" ]; then
tag="${2}"
fi
name=$(basename ${0} |cut -d "." -f1)
img="copyparty/ac"
options="--restart unless-stopped \
-d \
-p 3923:3923 \
-v /dein-medienverzeichnis:/media \
-v /opt/copyparty/config:/cfg/config.conf:ro \
-v /opt/copyparty/database:/cfg/hists \
-m 1g"
#########################
menu () {
while true; do
cmd=(dialog --clear --backtitle "Owncloud menu" --title "Owncloud menu" --menu "Choice:" 22 120 12)
options=(
1 "Start container"
2 "Stop container"
3 "Restart container"
)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
case "$choice" in
1) clear; ${0} start; echo "Press any key."; read ;;
2) clear; ${0} stop; echo "Press any key."; read ;;
3) clear; ${0} restart; echo "Press any key."; read ;;
*) clear; return ;;
esac
done
}
echo "Container: ${name}"
if [ "${1}" == "" ]; then
menu
elif [ "${1}" == "init" ]; then
mkdir -p /opt/copyparty/config
mkdir -p /opy/copyparty/database
cat > /opt/copyparty/config/copyparty.conf << 'EOF'
[accounts]
benuzuer: passwort
[/]
/media
accs:
rwda: benutzer
EOF
elif [ "${1}" == "start" ]; then
echo "Starting"
docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "stop" ]; then
echo "Stopping"
docker rm -f ${name}
elif [ "${1}" == "restart" ]; then
docker rm -f ${name} && docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "pull" ]; then
docker pull ${img}:${tag}
elif [ "${1}" == "login" ]; then
docker exec -it ${name} /bin/bash
elif [ "${1}" == "commit" ]; then
docker commit ${name} ${img}:${tag}
elif [ "${1}" == "load" ]; then
echo "Loading"
docker load < ${name}.tar.gz
elif [ "${1}" == "save" ]; then
echo "Saving"
docker save ${img}:${tag} | gzip > ${name}.tar.gz
else
echo "Unknown : ${1}"
exit 1
fifilebrowser
filebrowser ist ein
Open-Source-Web-Filemanager unter MIT-Lizenz, der seit 2015 als
einfaches, schnelles One-Binary-Tool existiert und über reine
HTTP/Web-UI nur Dateien hoch- und herunterladen kann, aber kein WebDAV
beherrscht. Hier ist das Kontrollskript filebrowser.sh
#!/bin/bash
#filebrowser.sh
tag="latest"
if [ "${2}" != "" ]; then
tag="${2}"
fi
name=$(basename ${0} |cut -d "." -f1)
img="filebrowser/filebrowser"
options="--restart unless-stopped \
-d \
-p 3000:80 \
-v /media/nas:/srv \
-v /opt/filebrowser/config:/config \
-v /opt/filebrowser/database:/database \
-m 1g"
#########################
mkdir -p /opt/filebrowser/config
mkdir -p /opt/filebrowser/database
menu () {
while true; do
cmd=(dialog --clear --backtitle "Owncloud menu" --title "Owncloud menu" --menu "Choice:" 22 120 12)
options=(
1 "Start container"
2 "Stop container"
3 "Restart container"
)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
case "$choice" in
1) clear; ${0} start; echo "Press any key."; read ;;
2) clear; ${0} stop; echo "Press any key."; read ;;
3) clear; ${0} restart; echo "Press any key."; read ;;
*) clear; return ;;
esac
done
}
echo "Container: ${name}"
if [ "${1}" == "" ]; then
menu
elif [ "${1}" == "init" ]; then
docker run --rm filebrowser/filebrowser fb --init # Create container
docker run --rm -v $HOME/.filebrowser:/config filebrowser/filebrowser \
fb --baseurl /admin \
--username admin \
--password admin \
--create
elif [ "${1}" == "start" ]; then
echo "Starting"
docker run --name ${name} ${options} ${img}:${tag} #sleep infinity
elif [ "${1}" == "stop" ]; then
echo "Stopping"
docker rm -f ${name}
elif [ "${1}" == "restart" ]; then
docker rm -f ${name} && docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "pull" ]; then
docker pull ${img}:${tag}
elif [ "${1}" == "login" ]; then
docker exec -it ${name} /bin/bash
elif [ "${1}" == "commit" ]; then
docker commit ${name} ${img}:${tag}
elif [ "${1}" == "load" ]; then
echo "Loading"
docker load < ${name}.tar.gz
elif [ "${1}" == "save" ]; then
echo "Saving"
docker save ${img}:${tag} | gzip > ${name}.tar.gz
else
echo "Unknown : ${1}"
exit 1
fiJellyfin Medienserver
Jellyfin ist, wie kodi oder Plex, ein kostenloser
Open-Source-Medien-Server, der eine Reihe von Multimedia-Anwendungen zum
Organisieren, Verwalten und Freigeben digitaler Mediendateien bietet.
Auch ein Jellyfin lässt sich
problemlos dockern. Hier ist das Kontrollskript
jellyfin.sh
#!/bin/bash
# jellyfin.sh
#
tag="latest"
if [ "${2}" != "" ]; then
tag="${2}"
fi
name=$(basename ${0} |cut -d "." -f1)
img="jellyfin/jellyfin"
mkdir -p /opt/jellyfin/cache
mkdir -p /opt/jellyfin/config
options="-d \
--name jellyfin \
-p 8096:8096/tcp \
-p 7359:7359/udp \
-p 1900:1900/udp \
-e MALLOC_TRIM_THRESHOLD_=100000 \
--user 1000:1000 \
--net=host \
--volume /opt/jellyfin/config:/config \
--volume /opt/jellyfin/cache:/cache \
--mount type=bind,source=/media/nas,target=/media \
--restart=unless-stopped \
-m 1g"
menu () {
while true; do
cmd=(dialog --clear --backtitle "Jellyfin menu" --title "Jellyfin menu" --menu "Choice:" 22 120 12)
options=(
1 "Start container"
2 "Stop container"
3 "Restart container"
)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
case "$choice" in
1) clear; ${0} start; echo "Press any key."; read ;;
2) clear; ${0} stop; echo "Press any key."; read ;;
3) clear; ${0} restart; echo "Press any key."; read ;;
*) clear; return ;;
esac
done
}
echo "Container: ${name}"
if [ "${1}" == "" ]; then
menu
elif [ "${1}" == "start" ]; then
echo "Starting"
docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "stop" ]; then
echo "Stopping"
docker rm -f ${name}
elif [ "${1}" == "restart" ]; then
docker rm -f ${name} && docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "login" ]; then
docker exec -it ${name} /bin/bash
elif [ "${1}" == "pull" ]; then
docker pull ${img}:${tag}
elif [ "${1}" == "commit" ]; then
docker commit ${name} ${img}:${tag}
elif [ "${1}" == "load" ]; then
echo "Loading"
docker load < ${name}.tar.gz
elif [ "${1}" == "save" ]; then
echo "Saving"
docker save ${img}:${tag} | gzip > ${name}.tar.gz
else
echo "Unknown : ${1}"
exit 1
fiNavidrome
Navidrome ist ein selbst
gehosteter, Open-Source-Musikserver und Streamer, mit dem die eigene
Musiksammlung von überall streambar ist, ähnlich wie Spotify oder Apple
Music, aber privat. Navidrome
indiziert die Musik und macht sie verfügbar über Web-Player im Browser,
Mobile Apps (iOS, Android) und Subsonic-kompatible Clients. Mit Jellyfin nicht unbedingt notwendig,
dafür aber sehr leichtgewichtig. Hier das Kontrollskript
navidrome.sh für ein gedockertes Navitrome:
#!/bin/bash
# navidrome.sh
#
tag="latest"
if [ "${2}" != "" ]; then
tag="${2}"
fi
name=$(basename ${0} |cut -d "." -f1)
img="deluan/navidrome"
mkdir -p /opt/navidrome/data
options="-d \
-p 4533:4533 \
--user $(id -u):$(id -g) \
--volume /media/ordner-mit-deiner-musik:/music:ro \
--volume /opt/navidrome/data:/data \
--mount type=bind,source=/media/nas,target=/media \
--restart=unless-stopped \
-m 1g"
menu () {
while true; do
cmd=(dialog --clear --backtitle "Navidrome menu" --title "Jellyfin menu" --menu "Choice:" 22 120 12)
options=(
1 "Start container"
2 "Stop container"
3 "Restart container"
)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
case "$choice" in
1) clear; ${0} start; echo "Press any key."; read ;;
2) clear; ${0} stop; echo "Press any key."; read ;;
3) clear; ${0} restart; echo "Press any key."; read ;;
*) clear; return ;;
esac
done
}
echo "Container: ${name}"
if [ "${1}" == "" ]; then
menu
elif [ "${1}" == "start" ]; then
echo "Starting"
docker run --name ${name} ${options} ${img}:${tag} #sleep infinity
elif [ "${1}" == "stop" ]; then
echo "Stopping"
docker rm -f ${name}
elif [ "${1}" == "restart" ]; then
docker rm -f ${name} && docker run --name ${name} ${options} ${img}:${tag}
elif [ "${1}" == "login" ]; then
docker exec -it ${name} /bin/bash
elif [ "${1}" == "pull" ]; then
docker pull ${img}:${tag}
elif [ "${1}" == "commit" ]; then
docker commit ${name} ${img}:${tag}
elif [ "${1}" == "load" ]; then
echo "Loading"
docker load < ${name}.tar.gz
elif [ "${1}" == "save" ]; then
echo "Saving"
docker save ${img}:${tag} | gzip > ${name}.tar.gz
else
echo "Unknown : ${1}"
exit 1
fi