User ID, unprivileged LXC und Samba in Einklang bringen
Wenn man Proxmox unprivilegierte LXC Container verwendet und dann in so einem Container auf Daten außerhalb des Containers zugreifen möchte (zum Beispiel auf einen Netzwerkshare), dann funktioniert das nicht ohne Weiteres. Das liegt daran, dass aus Sicherheitsgründen die User in einem Container automatisch eine User ID (UID) und eine Group ID (GID) in einem Bereich oberhalb von 100.000 erhalten. Wem das nichts sagt, macht nichts, denn diese UNIX-User-Nummerierung ist praktisch ein Urgestein der Computergeschichte und reicht in die 1970er zurück, in Zeiten wo man sich noch einen UNIX “Guru oder Zauberer” gesucht hat und diesen an “die Maschine gekettet” hat, wie in diesem “Computer Chronicles” Video aus dem Jahr 1985 bereits auf die wilde Urzeit der Computerei zurückgeblickt wurde. Aber auch im Jahr 2024 bleibt einem der Umgang mit UID und GID nicht aus, wenn man mit Linux, MacOS oder Docker Container zu tun hat.
Was ist das Problem?
Wo tritt das Problem also konkret auf einem Heimserver auf? Wenn man zum Beispiel einen Streamingserver wie Jellyfin in einem LXC Container betreibt und dessen Mediendateien über TrueNAS zur Verfügung gestellt werden. Jetzt kann der User im Container keine Dateien erstellen, ändern, oder löschen. Das Problem ist aufgetreten als ich auf eine Lösung mit TrueNAS und Netzwerkshares umgestiegen bin. Die einfachste, aber unsichere, Lösung ist, einfach jedem Benutzer volle Schreibrechte zu geben. Das möchte ich aber nicht, daher muss eine Alternative her.
User Mapping ist ein verwirrender Zwirn
Glücklicherweise bietet Proxmox eine umfangreiche (wenn auch manchmal etwas veraltete) Dokumentation. So gibt es auch eine für die unprivilegierten LXC Container, wo genau dieses Problem, und noch wichtiger, die Lösung beschrieben wird. Leider lässt sich dieser Ansatz nicht auf meinen Fall anwenden, denn der Container bekommt seinen Zugang auf den Netzwerkshare über einen Mountpoint vom Proxmox Host und im Container wird mit root gearbeitet (was wiederum eine Altlast ist). Wenn ich jetzt den User root (mit der UID/GID 0:0) auf den richtigen User mappe, dann bringt das das restliche Mapping durcheinander. Und das war der Grund weshalb ich dieses Problem für ein paar Wochen auf Eis gelegt habe. Zumindest bin ich etwas schlauer geworden und weiß, dass man sich gut überlegen soll, wie Netzwerkshares eingebunden werden, und dass es nicht vorteilhaft ist, wenn man in einem Container mit root arbeitet (auch wenn der Container unprivilegiert ist und deshalb zwar eh keinen Unfug außerhalb machen kann).
Update: Die Lösung besteht darin nicht die Proxmox GUI zu verwenden
Die Lösung des Problems könnte darin bestehen, überhaupt nicht die Tools der grafischen Oberfläche von Proxmox zu verwenden, sondern die Netzwerkshares über die CLI zu konfigurieren. Diese Seite hat eine Anleitung, die wie auf das Problem zugeschnitten zu sein scheint.
Samba the old fashioned way
Um den Samba-Netzwerkshare über die CLI zu starten, muss man zuerst ein Credentials-File erstellen, am besten im Ordner /root
, da dort niemand unbefugter Zutritt hat:
nano /root/.smbcredentials
In der Config wird dann User und Passwort, welches in TrueNAS für den Share erstellt wurde, hinterlegt:
username=myusername
password=mypassword
Dann Berechtigungen beschränken auf (nur der Besitzer, sprich root, darf darauf zugreifen) mit:
chmod 700 /root/.smbcredentials
Die Grenzen des statischen fstab
Eintragens
Jetzt kommt der fstab
Eintrag dran. In dieser Konfigurationsdatei werden alle Festplatten und Netzwerkshares eingetragen, die bei jedem Systemstart zur Verfügung stehen sollen. Hier passt die Anleitung jedoch nicht mehr, denn diese geht davon aus, dass man zwei physische Geräte hat (einmal Proxmox und dann noch ein separates Kastl mit dem Netzwerkshare). Ich habe jedoch alles in einem Rechner kombiniert, wenn man also den fstab
-Eintrag…
//192.168.0.60/media /mnt/nas/media cifs credentials=/root/.smbcredentials,uid=100000,gid=100000 0 0
… so wie er ist einträgt, dann wird man beim nächsten Start von Proxmox nicht glücklich werden. Denn die Einträge in fstab
werden beim Systemstart ausgeführt, also zu einem Zeitpunkt wo noch gar keine VMs laufen. Im schlimmsten Fall bootet Proxmox gar nicht mehr, oder wenn man die nofail
Option aktiviert hat, hat man halt kein Netzwerkshare zur Verfügung.
Systemd hat die Lösung parat
Was ich bisher nicht gewusst habe, war, dass man mit Systemd auch direkt in den fstab-Einträgen arbeiten kann. Die Arch Linux Wiki hat dazu einen umfangreichen Artikel, wo man alle Einstellungsmöglichkeiten sehen kann.
Mit diesem Zusatz zum fstab
-Eintrag…
x-systemd.automount,x-systemd.mount-timeout=30,_netdev
… sagt man den System erstens, dass nur gemountet werden soll, wenn auch notwendig (sprich wenn der LXC Container darauf zugreifen möchte) und, dass 30 Sekunden gewartet werden soll. Letzteres ist gibt diesem Mountversuch dann so lange Zeit um die Verbindung aufzubauen, es bricht also nicht sofort ab, falls der Netzwerkshare (noch) nicht zur Verfügung steht.
Der angepasste fstab
-Eintrag sieht dann so aus:
//192.168.0.60/Media /mnt/pve/truenas-jellybox-media cifs credentials=/root/.smbcredentials,uid=100000,gid=100000,iocharset=utf8,file_mode=0777,dir_mode=0777,x-systemd.automount,x-systemd.mount-timeout=30,_netdev 0 0
Anmerkung: ich habe zuerst fälschlicherweise statt //192.168.0.60/Media
den Dateipfad angegeben, mehr dazu unten.
Der in der grafischen Oberfläche eingetragene Netzwerkshare…
… kann entfernt werden. Und dann kann man noch manuell unmounten. Zuerst in der Proxmox Host-Shell überprüfen ob der Share noch da ist mit df -h
. Dann überprüfen, ob eh keine Prozesse mehr drauf zugreifen mit lsof /mnt/pve/netzwerksharename
und mit umount /mnt/pve/netzwerksharename
aushängen.
Manuelles Mounten zum Testen
Mit mount -a
kann man schließlich den neuen fstab
Eintrag mounten. Oder so sollte es gehen, wenn es funktionieren würde. Aber ich bekomme nur:
Mit dmesg | tail
kommt man dem Problem auf die Spur:
Ah, ich habe den Fehler gefunden, beim SMB-Share gibt man nicht den Pfad sondern nur den Namen des Shares an, jetzt funktioniert es und hat auch die richtigen Berechtigungen, nämlich auf User 100000:
Mountpoint im Container einrichten und fertig
Der alte Mountpoint…
… in meinem Fall gar nicht gelöscht werden. Falls der Eintrag noch fehlt, kann man ihn mit diesem Befehl auch per Terminal hinzufügen:
pct set <container_id> -mp0 /mnt/pve/wos-a-immer-media,mp=/mnt/media
Das war’s und der Netzwerkshare lässt ich wieder beschreiben!