Arch Linux - Einrichten eines NFS4 Servers

Bild: NFS Logo Der Network File Service/Serviceist eine der nativen Methoden zur Freigabe von Dateien und Anwendungen über das Netzwerk in der Linux/UNIX-Welt. Der Dienst NFS, der ursprünglich von Sun Microsystems entwickelt wurde, ermöglicht es auf Dateien in einem Netzwerk zuzugreifen, die sich auf einem entfernten Rechner befinden, genauso wie auf lokal gespeicherten Dateien des Clients. Es ist also ein äußert praktisches Werkzeug, für die Speicherung und Nutzung großer Datenmengen unter Benutzern in einem Netzwerk bzw. von unterschiedlichen Anwendungen auf verteilten Applikations-Servern.

Weitere Hintergründe und Erklärungen finden sich in dem gut dokumentierten Wikipedia-Artikel.

In diesem Artikel wollen wir im Detail auf folgende generelle Themen bzw. auf ArchLinux spezifische Konfigurationsoptionen eingehen:

  • Vergleich zwischen NFSv2, NFSv3 und NFSv4
  • Konfiguration von NFS-Server und -Client mit NFSv4 unter Archlinux.
  • Persistenter und nicht-persistenter Zugriff auf NFS-Freigaben unter Linux

Version 2 des Protokolls (definiert in RFC 1094, März 1989) lief ursprünglich ausschließlich via UDP1). Die Virtual File System-Schnittstelle ermöglicht eine modulare Implementierung, was sich in einem einfachen Protokoll widerspiegelt. Bis Anfang 1986 wurden Implementierungen für Betriebssysteme wie System V Release 2, DOS und VAX/VMS unter Verwendung von Eunice demonstriert. NFSv2 erlaubte aufgrund von 32-Bit-Beschränkungen nur das Lesen der ersten 2 GB einer Datei.

  • Mount-Anfragen werden nur auf Host-Basis und nicht auf Benutzerbasis gewährt.
  • Diese Version verwendet TCP2) oder UDP3) als Transportprotokoll.
  • Clients der Version 2 haben eine Dateigrößenbeschränkung von weniger als 2 GB, auf die sie zugreifen können, da auf Grund der 32-Bit-Beschränkungen nur das Lesen der ersten 2 GB einer Datei möglich ist.

Mit Version 3 RFC 1813, dessen Hauptmotivation es war, das Leistungsproblem der synchronen Schreiboperation in NFS Version 2 zu beheben, wurde im Juli 1995 unter anderem Folgende Punkte eingeführt:

  • Unterstützung für 64-Bit-Dateigrößen und -Offsets, um Dateien mit einer Größe von mehr als 2 Gigabyte (GB) verarbeiten zu können;
  • Unterstützung für asynchrone Schreibvorgänge auf dem Server, um die Schreibleistung zu verbessern;
  • zusätzliche Dateiattribute in vielen Antworten, um ein erneutes Abrufen dieser Attribute zu vermeiden;
  • eine READDIRPLUS-Operation, um beim Durchsuchen eines Verzeichnisses neben den Dateinamen auch Datei-Handles und Attribute abzurufen;
  • Mount-Requests werden zudem auf Host-Basis und nicht auf Benutzerbasis bewilligt.

Ein großer Vorteil von NFSv4 gegenüber seinen Vorgängern besteht vor allem darin, daß für den Betrieb des Dienstes nur ein einziger UDP- oder TCP-Port (2049) verwendet wird, was die Nutzung des Protokolls über Firewalls hinweg vereinfacht. NFS Version 4.2 RFC 7862 wurde im November 2016 veröffentlicht und enthält folgende neue Funktionen: serverseitiges Klonen und Kopieren, Speicherplatzreservierung und Sparse-Dateien, sowie weitere Optimierungen.

  • Diese Version des Protokolls nutzt ein zustandsbehaftetes Protokoll wie TCP oder das SCTP4) als Transportprotokoll.
  • Die Dienste der RPC-Bindungsprotokolle (wie rpc.mountd, rpc.lockd und rpc.statd) sind in dieser Version von NFS daher nicht mehr erforderlich, da ihre Funktionalität in den Server integriert wurde - NFSv4 vereint diese zuvor getrennten NFS-Protokolle in einer einzigen Protokollspezifikation.
  • Es bietet Unterstützung für ACL-Attribute (File Access Control List) und kann sowohl Version-2- als auch Version-3-Clients unterstützen.
  • NFSv4 führt das Konzept des Pseudo-Dateisystems ein, welche es NFSv4-Clients ermöglicht, die auf dem NFSv4-Server exportierten Dateisysteme als ein einziges Dateisystem zu sehen und darauf zuzugreifen.

Unter Archlinux wird auf dem Server wie auch auf den Clients lediglich das Paket nfs-utils benötigt. Dieses Paket installieren wir uns nun auf unserem Server.

 $ sudo pacman -S nfs-utils

bzw.

 # pacman -S nfs-utils

Wollen wir wissen was uns dieses Paket alles in unser System gespült hat, hilft ein Blick in die Dateiliste des Paketes.

 # pacman -Qil nfs-utils

Details des Paketes nfs-utils

Hilfe findet man wie immer in den zugehörigen man-Pages. Werfen wir kurz einen Blick in die nfs-Manpage.

 # man nfs

Ausgabe des Befehlös man nfs

Selbiges machen wir auch mit dem Befehl exportfs indem wir in dessen Man-Page bei Bedarf einen Blick werfen.

 # man exportfs

Ausgabe des Befehlsaufrufes man exportfs

pseudo-Root-NFS-Verzeichnis

Wie schon beim Vergleich der NFS-Versionen angemerkt, wurde mit NFSv4 das Konzept des Pseudo-Dateisystems eingeführt, welche es NFSv4-Clients ermöglicht, die auf dem NFSv4-Server exportierten Dateisysteme als ein einziges Dateisystem zu sehen und darauf zuzugreifen. Diesen Konfigurationspunkt wollen wir nun als erstes erledigen.

Eine bewährte Sicherheitspraxis besteht darin, Freigaben relativ zum sogenannten NFS-Stammverzeichnis zu definieren, wodurch Benutzer auf diesen Mountpoint beschränkt bleiben. Hierzu verwendet man sogenannte Bind-Mounts mit denen dann der Mountpoint der Freigabe mit dem eigentlichen Verzeichnis an einer anderen Stelle im Dateisystem verknüpft wird. Durch Konfiguration dieses pseudo-root Verzeichnisses für NFS Exports wird der exportierte Pfad unabhängig vom echten Pfad auf dem Server, was auch ggf. bei einem Umzug von Verzeichnissen und Dateien sehr hilfreich sein kann.

Im ersten Schritt erstellen wir nun unser Export-Verzeichnis /exports welches später alle Verzeichnis-Exports enthalten soll und fassen dort dann alle Daten mittels Bind-Mounts zusammen.

 # mkdir /exports

In unserem Konfigurationsbeispiel wollen wir das Verzeichnis /usr/local/src/ auf unserem NFS-Server, via NFS anderen Hosts zur Verfügung stellen, ebenso wie das Verzeichnis /srv/nfs.

  • Als erstes Verknüpfen wir also das Verzeichnis /usr/local/src/ mit dem Unterverzeichnis /exports/src. Das betreffende Unterverzeichnis erstellen wir nun noch.
     # mkdir /exports/src

    Anschließend binden wir die beiden Verzeichnisse zusammen.

     # mount --bind /usr/local/src/ /exports/src
  • Gleiches machen wir nun noch mit der NFS-Partition:
     # mount --bind /srv/nfs /exports
  • Das Verzeichnis /proc/mount enthält eine Liste aller auf dem System gemounteten Dateisysteme. Wir können seinen Inhalt mit dem Befehl cat lesen, um auf die Liste zuzugreifen. Werfen wir also kurz einen Blick in die nun gemounteten Dateisysteme.
     # cat /proc/mounts | grep exports 
    /dev/sda2 /exports/src btrfs rw,relatime,space_cache=v2,subvolid=256,subvol=/@ 0 0
    /dev/sda3 /exports btrfs rw,relatime,space_cache=v2,subvolid=256,subvol=/@nfs 0 0
  • Damit nun bei einem Neustart des Servers unser Pseudo-Root-NFS-Verzeichnis automatisch zur Verfügung steht, tragen wir diese am Ende der Konfigurationsdatei /etc/fstab ein.
     # vim /etc/fstab
    ...
    
    /exports                                  /srv/nfs                none        bind                                     0 0
    /exports/src                              /usr/local/src          none        bind                                     0 0 

Export der Verzeichnisse für die Clients

Nun konfigurieren wir den eigentlichen Verzeichnis-Export für unsere Client-Maschinen. Wie immer erstellen wir zunächst eine Kopie der Konfigurationsdatei des Archlinux-Paketes.

 # cp -av /etc/exports /etc/exports.orig

Anschließend exportieren wir als erstes unser pseudo-Root-NFS-Verzeichnis /exports. Hierzu bearbeiten wir die Konfigurationsdatei /etc/exports wie folgt.

 # vim /etc/exports
/etc/exports
# Pseudo-root für NFSv4
/exports                               10.0.10.239/32(rw,no_subtree_check,fsid=root,crossmnt)
 
# Export des Unterverzeichnisses 'src'
/exports/src                           10.0.10.239/32(rw,async,sec=sys,no_subtree_check)

Mit nachfolgendem Befehl können wir die exportierten Verzeichnisse anhand der oben vorgenommenen Konfiguration aktualisieren.

 # exportfs -rv
exporting 10.0.10.239/32:/exports/src
exporting 10.0.10.239/32:/exports

Nach erfolgreicher Änderung der exportierten Verzeichnisse bzw. auch jederzeit zur Überprüfung kann man bei Bedarf die aktuell aktiven exportierten Verzeichnisse wie folgt abfragen.

 # exportfs -v
/exports      	10.0.10.239/32(sync,wdelay,hide,crossmnt,no_subtree_check,fsid=0,sec=sys,rw,root_squash,no_all_squash)
/exports/src  	10.0.10.239/32(async,wdelay,hide,no_subtree_check,sec=sys,rw,root_squash,no_all_squash)

Firewall/Paketfilter - firewalld

Bevor wir nun unseren NFSv4 Server starten, müssen wir natürlich sicherstellen, daß auf dem betreffendem Host auch die Kommunikationsbeziehungen entsprechend erlaubt sind!

Wie auch schon früher bei CentOS ab Release 7 bzw. den nachfolgenden Release-Kandidaten Stream von RHEL nutzen wir auch unter Arch Linux den dynamischen firewalld Service. Ein großer Vorteil der dynamischen Paketfilterregeln ist unter anderem, daß zur Aktivierung der neuen Firewall-Regel(n) nicht der Daemon durchgestartet werden muß und somit alle aktiven Verbindungen kurz getrennt werden. Sondern unsere Änderungen können on-the-fly aktiviert oder auch wieder deaktiviert werden.

In folgendem Konfigurationsbeispiel gehen wir von einem Host aus, der zwei Firewall-Zonen hält, einmal die Zone nfs und einmal die Zone intra. In beiden Zonen sollen später Client-Systeme exportierte Verzeichnisse in ihr Dateisystem einbinden können.

Damit unsere Clients Verbindungen zu dem geöffneten 2049/TCP des NFSv4-Servers aufbauen können, müssen wir für diese noch Änderungen am Paketfilter firewalld vornehmen.

 # firewall-cmd --permanent --zone=nfs --add-service=nfs
success
 # firewall-cmd --permanent --zone=intra --add-service=nfs
success

Oder wir schalten gezielt einen Host einer Zone für den Dienst nfs frei:

 # firewall-cmd --permanent --zone=intra --add-rich-rule='rule family="ipv4" source address="10.0.10.68/24" service name="nfs" accept'
success

Anschließend können wir den Firewall-Daemon einmal neu laden und überprüfen, ob die Regeln auch entsprechend unserer Definition, gezogen haben.

 # firewall-cmd --reload
success

Werfen wir noch kurz einen Blick in die Zone nfs:

 # firewall-cmd --zone=nfs --list-services
nfs ssh

Gleiches gilt natürlich für die Zone intra:

 # firewall-cmd --zone=intra --list-services
nfs ssh

Da wir ausschließlich das Protokoll NFSv4 nutzen und somit zur Verfügung stellen wollen, starten wir hierzu den betreffenden Dienst.

 # systemctl start nfsv4-server.service

Im Journal wird uns der Start entsprechend protokolliert.

 # journal -f

Protokollierung des nfsd im journal

Bei Bedarf können wir natürlich auch den Status unseres Daemons jederzeit abfragen.

 # systemctl status nfsv4-server.service

 nfsv4-server.service - NFSv4 server and services
     Loaded: loaded (/usr/lib/systemd/system/nfsv4-server.service; disabled; preset: disabled)
   Active:active (running) since Tue 2026-04-07 16:17:43 CEST; 1min 27s ago
 Invocation: 85c5016d8c9442d5965cf9640c043b7e
    Process: 1557 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
    Process: 1558 ExecStart=/usr/sbin/rpc.nfsd -N 3 (code=exited, status=0/SUCCESS)
   Main PID: 1558 (code=exited, status=0/SUCCESS)
   Mem peak: 2.1M
        CPU: 22ms

Apr 07 16:17:43 nfs-arch systemd[1]: Starting NFSv4 server and services...
Apr 07 16:17:43 nfs-arch systemd[1]: Finished NFSv4 server and services.

Alternativ dazu können wir auch einen Blick in die Prozeß-Liste werfen um uns zu vergewissern ob der Daemon läuft.

 # ps auxwf | grep nfsv4-server
root        1656  0.0  0.0   6728  4460 pts/1    S+   16:35   0:00  |                       \_ grep --color=auto nfsv4-server

Wir können jetzt auch schon mit Hilfe des Utility ss abfragen ob der nfsv4-server den Port 2049 auf den zugehörigen Adressen geöffnet hat.

 # ss -tulpn
Netid   State    Recv-Q   Send-Q     Local Address:Port       Peer Address:Port   Process                                      
tcp     LISTEN   0        4096             0.0.0.0:2049            0.0.0.0:*                                                   
tcp     LISTEN   0        4096                [::]:2049               [::]:*

manuelles Mounten auf dem Zielsystem

Zum Testen unseres Servers binden wir nun auf dem hierzu berechtigten Client mit der IPv4 10.0.10.239/24 das bzw. die exportierten Verzeichnisse ein.

Der Befehl mount liefert leider oft nicht die allerbesten detaillierten Fehlermeldungen aus, was uns bei der ggf. nötigen Fehlersuche die Sache nicht ganz leicht macht. Daher verwenden wir die Option -v um ggf,. an mehr Informationen zu kommen. Ferner ist man gut beraten, explizit die Version, also in unserem Fall -t nfs4 oder auch -o vers=4 zu verwenden.

Wir binden also das Verzeichnis srv unserer Pseudo-Root-NFS-Umgebung des NFS-Servers 10.0.10.2 wir folgt ein:

 # mount -v -t nfs4 10.0.10.2:/src /mnt/src
mount.nfs4: timeout set for Tue Apr  7 16:53:53 2026
mount.nfs4: trying text-based options 'vers=4.2,addr=10.0.10.2,clientaddr=10.0.10.239'

Ein erfolgreicher Mount mit NFSv4.2 liefert also obige Ausgabe.

Man beachte die Angabe des Exports auf dem Server relativ zum pseudo-root und auch die Ausgabe der verwendeten NFS-Version!

Zum Testen legen wir nun eine Testdatei an, hierzu schreiben wir einfach das aktuelle Datum in die Datei testdatei.txt und „schenken diese unseren Adminuser django.

 # date > /usr/local/src/testdatei.txt ; chown django: /usr/local/src/testdatei.txt

Auf unserem Clientrechner sehen wir nun auch diese Datei:

 # ls -alF /mnt/
total 4
drwxr-xr-x 1 root   root    26 Apr  7 17:00 ./
drwxr-xr-x 1 root   root   202 Apr  7 16:48 ../
-rw-r--r-- 1 django django  33 Apr  7 17:01 testdatei.txt

Mounten via /ety/fstab auf dem Zielsystem

Natürlich wollen und werden wir auf unseren Zielsystemen nicht manuell die Verzeichnisse einbinden, sondern die Zielsysteme sollen automatisch die exportierten Verzeichnisse einbinden. Auch hier ist es nun wichtig, daß das NFS-Export-Stammverzeichnis des Servers weggelassen wird.

 # vim /etc/fstab
...

10.0.10.2:/arch-mirror    /mnt/arch-mirror				nfs defaults,timeo=900,retrans=5,_netdev	0 0
10.0.10.2:/backups        /mnt/backups					nfs defaults,timeo=900,retrans=5,_netdev	0 0
10.0.10.2:/repository     /mnt/repository				nfs defaults,timeo=900,retrans=5,_netdev	0 0
10.0.10.2:/src            /mnt/src					nfs defaults,timeo=900,retrans=5,_netdev	0 0

Damit unser System Kenntnis von unseren Erweiterungen in der /etc/fstab bekommt, ist es notwendig den systemd einmal neu zu laden:

 # systemctl daemon-reload

Anschließend können wir unsere am NFS-Server exportierten Verzeichnisse mounten.

# mount -a

Eine Prüfung des nun zur Verfügung stehenden Speicherplatzes zeigt uns folgender Befehl:

 # df -h
Filesystem              Size  Used Avail Use% Mounted on
dev                     7.8G     0  7.8G   0% /dev
run                     7.8G  1.7M  7.8G   1% /run
efivarfs                154K   78K   72K  53% /sys/firmware/efi/efivars
/dev/mapper/root        238G   81G  156G  35% /
tmpfs                   7.8G   12M  7.8G   1% /dev/shm
none                    1.0M     0  1.0M   0% /run/credentials/systemd-journald.service
tmpfs                   7.8G   24M  7.8G   1% /tmp
/dev/mapper/root        238G   81G  156G  35% /var/cache/pacman/pkg
/dev/mapper/root        238G   81G  156G  35% /home
/dev/nvme0n1p1         1022M   50M  973M   5% /boot
/dev/mapper/root        238G   81G  156G  35% /var/log
tmpfs                   1.6G  132K  1.6G   1% /run/user/1000
10.0.10.2:/arch-mirror   11T  6.0M   11T   1% /mnt/arch-mirror
10.0.10.2:/backups       11T  6.0M   11T   1% /mnt/backups
10.0.10.2:/repository    11T  6.0M   11T   1% /mnt/repository
10.0.10.2:/src           11T  6.0M   11T   1% /mnt/src

Am Ende sehen wir unsere vier NFS-Verzeichnisse die wir eingebunden haben.

Da wir unsere Systeme mit Hilfe von Ansible orchestrieren werden, brauchen wir uns um UID und GID keine großen Gedanken machen. Wir können somit unter anderem auf das NFSv4 IDMapping verzichten!

Auf unseren Clients gibt es nun mehrere Varianten die vom Server exportierten Verzeichnisse einzubinden.

/etc/fstab

Die, sagen wir mal klassische Variante der Einbindung via /etc/fstab, eignet sich vor allem für „stationäre“ Clientmaschinen und Hosts, welche schon beim Bootvorgang eine entsprechende Netzwerkverbindung nutzen können. Im Abschnitt Mounten via /etx/fstab auf dem Zielsystem haben wir bereits diese Variante beleuchtet.

autofs

Auf einem Mobilen Gerät wie einem Laptop wird man in aller Regel für die Netzwerkverbindungen Dinge wie den NetzwerkManager einbinden, mit dem man dann nach Anmeldung am Desktop auswählt, welche Art von Netzwerkverbindung man nutzen möchte, wie z.B. LAN, WLAN oder Mobilfunk. Hier eignet sich die Einbindung via /etc/fstab nicht, da ja beim Booten noch keine Netzwerkverbindung besteht und somit der Auto- bzw. Re-Mount nicht möglich ist und den Bootvorgang unnötig in die Länge zieht.

Zur Einrichtung des autots-mounts wird das AUR-Paket autofs benötigt. Nun über Sinn und Qualität der Pakete im AUR-Repo kann man trefflich streiten, aber nachdem der Paketmaintainer zwar sein Paket mit einem PGP-Schlüssel signiert, es aber versäumt hat diesen Schlüssel z.B. auf einem Keyserver zu hinterlegen, werden wir hier diesen Weg nicht weiter verfolgen, da wir auf Sicherheit und Vertraulichkeit unserer Daten doch einen hohen stellen! Bei Bedarf findet man im Arch-Wiki entsprechende Informationen.

systemd automount

Da wir uns aus Sicherheitsgründen nicht für die vorgenannte Variante via autofs entschieden haben, werden wir nun auf unserem mobilen Gerät die automatische Einbindung via systemd beschreiten. Im nachfolgenden Konfigurationsbeispiel wollen wir das exportierte Verzeichnis /exports/backup von unserem NFSv4-Server mit der IP-Adresse 10.0.10.2 einbinden.

Zunächst installieren wir auf unserem Clientrechner das Paket nfs-utils.

 $ sudo pacman -S nfs-utils

bzw.

 # pacman -S nfs-utils

Wir benötigen je Share, den wir vom NFS-Server mounten wollen, jeweils zwei Dateien:

  • mount-Unit : Hier wird definiert:
    • What: - Die Quelle, also von welchem NFS-Servewr wir welches Share einbinden wollen.
    • Where: - Wo im Dateisystem wollen wir das Share des NFS-Servers lokal einbinden?
    • Type: - Welche NFS-Version wollen wir verwenden?
    • Options: - Optionen die für das Share gelten sollen.

Wir legen uns also nun diese Mount-Systemd-Unit-Datei an.

 # vim /etc/systemd/system/mnt-backups.mount
/etc/systemd/system/mnt-backups.mount
[Unit]
Description=Mount NFS share backups
Documentation=https://dokuwiki.nausch.org/doku.php/linux:nfs#systemd_automount
 
[Mount]
What=10.0.10.2:/backups
Where=/mnt/backups
Type=nfs4
Options=_netdev,hard,rw
 
[Install]
WantedBy=multi-user.target

Der Type=nfs4 erklärt sich von selbst, wir benutzen NFS-Version 4. Die Options= haben dabei folgende Bedeutung:

  • _netdev weist das System an, zu warten, bis das Netzwerk verfügbar ist, bevor versucht wird, die Freigabe einzuhängen.
  • hard : Legt das Wiederherstellungsverhalten des NFS-Clients fest, nachdem eine NFS-Anfrage abgelaufen ist. Bei der Option hard werden NFS-Anfragen unbegrenzt oft wiederholt.
  • rw definiert, daß das Dateisystem mit Lese- und Schreibzugriff eingebunden werden soll.

Die zweite Unit mit der Endung .automount macht genau das, was der Name besagt: Sie liest die gerade beschriebene .mount-Unit und hängt die dort benannte Freigabe ein.

 # vim /etc/systemd/system/mnt-backups.automount
/etc/systemd/system/mnt-backups.automount
[Unit]
Description=Automount NFS share backups
Documentation=https://dokuwiki.nausch.org/doku.php/linux:nfs#systemd_automount
Requires=NetworkManager.service
After=network-online.target
Wants=network-online.target
 
[Automount]
Where=/mnt/backups
TimeoutIdleSec=10min
 
[Install]
WantedBy=multi-user.target

Der TimeoutIdleSec=10min definiert eine Zeitüberschreitung bei Inaktivität. Sobald die eingebundene Freigabe für die angegebene Zeit inaktiv war, versucht systemd, sie zu deaktivieren.

Achtung :
Keinesfalls bei den Mountpoints im Dateisystem Namen mit einem - verwenden! Denn aus den Namen wird der Mountpoint gebildet, indem / durch ein - ersetzt wird. Der volle Verzeichnis-Datei-Name, den wir bei der Option Where in der Automount-Unit angeben muss zum Unit-Namen passen. In unserem Konfigurationsbeispiel Where=/mnt/backups wird der Unit-Name dann mnt-backups.automount.
Würde man hingegen als Mountpoint /mnt/backup-2026 verwenden sowie den Unit-Namen entsprechend mnt-backup-2026 wird uns der systemd eine entsprechende Fehlermeldung auswerfen: mnt-backup-2026.automount: Where= setting doesn't match unit name. Refusing.

Bevor wir nun unsere neue Automount-Unit aktivieren, informieren wir den systemd über die neuen Unit-files durch einen Reload des systemd.

 # systemctl daemon-reload

Nach einem erfolgreichen Neustart unseres Client-Rechners werfen wir zunächst einen Blick in die gemounteten Dateiverzeichnisse.

 # bat /proc/mounts

Ausgabe des Befehls bat /proc/mounts

Wir sehen also, es ist unser NFS-Verzeichnis nicht gemountet.

Nun greifen wir auf unser Freigabeverzeichnis /mnt/backups zu.

 $ cd /mnt/backups

Im Journal wird der Zugriffsversuch und der Mount des Freigabeverzeichnisses entsprechend protokolliert:

Apr 14 16:00:27 pml010068 systemd[1]: mnt-backups.automount: Got automount request for /mnt/backups, triggered by 10290 (vim)
Apr 14 16:00:27 pml010068 systemd[1]: Mounting NFSv4 share backups...
Apr 14 16:00:27 pml010068 systemd[1]: Mounted NFSv4 share backups.
Apr 14 16:00:27 pml010068 nfsrahead[10301]: setting /mnt/backups readahead to 128

Auf dem NFS-Server sehen wir diesen Zugriff im journal:

Apr 14 16:00:31 nfs-arch nfsv4.exportd[9926]: v4.2 client attached: 0x37b6efbb69dd1f27 from "10.0.10.68:686"

Greifen wir 10 Minuten nicht auf das Verzeichni zu, wird die freigabe wieder entfernt:

Apr 14 16:01:02 pml010068 systemd[1]: snapperd.service: Deactivated successfully.
Apr 14 16:10:28 pml010068 systemd[1]: Unmounting NFSv4 share backups...
Apr 14 16:10:28 pml010068 systemd[1]: mnt-backups.mount: Deactivated successfully.
Apr 14 16:10:28 pml010068 systemd[1]: Unmounted NFSv4 share backups.

Der automatische unmount unseres Verzeichnisses wir auf dem NFS-Server entsprechend protokolliert:

Apr 14 16:01:32 nfs-arch nfsv4.exportd[9926]: v4.2 client detached: 0x37b6efbb69dd1f27 from "10.0.10.68:686"

Wie auch schon bei der Einrichtung anderer Server-Diensten wollen wir auch hier weder eine manuelle Installation und Konfiguration unseres NFSv4-Servers sehen noch betreiben. Setzen wir einen neue virtuellen Server unter Arch Linux neu auf, oder wollen wir bei einem bestehenden Host die Konfiguration aktualisieren, verwenden wir wie zuvor schon angeschnitten Ansible als Orchestrierungswerkzeug. So ist sichergestellt, daß all unsere Hosts entsprechend gleich aufgebaut, konfiguriert und betrieben werden, es also keine Bastel-/Frickellösung geben wird!

Folgende Übersicht zeigt die Infrastrukturumgebung für unser Konfigurationsbeispiel, welches wir nun mit Hilfe von Ansible orchestrieren wollen.

Bild: Übersicht der exemplarischen Infrastruktur für unser Konfigurationsbeispiel

Der NFS-Server hat hier folgende Eigenschaften:

  • IP-Adressen: 10.0.10.2 und fd00:0:0:7:10:0:10:2
  • Partition/Verzeichnis in dem die Dateien physikalisch abgespeichert werden: /srv/nfs
  • zu exportierende Verzeichnisse:
    • archmirror
    • backups
    • repository
    • src

Wir haben zwei unterschiedliche Client-Rechner:

  • Büro Thinclient NitroPC mit
    • IP-Adressen: 10.0.10.60 und fd00:0:0:7:10:0:10:60
    • Server-Verzeichnisse die eingebunden werden sollen:
      • archmirror
      • backups
      • src
  • Büro Thinclient NitroPAD mit
    • IP-Adressen: 10.0.10.70 und fd00:0:0:7:10:0:10:70
    • Server-Verzeichnisse die eingebunden werden sollen:
      • archmirror
      • backups
      • repository

Der ungeduldigen Leser kann auch direkt zur Tat schreiten und das manuelle Anlegen der Inventory-Hülle, des Playbooks und der zugehörigen Rolle überspringen und diese Aufgaben mit folgendem Befehl sozusagen auf einem Rutsch erledigen:

 $ mkdir -p ~/devel/ansible ; wget https://gitlab.nausch.org/django/example_nfs/-/archive/main/example_nfs-main.tar.gz \
         -O - | tar -xz --strip-components=1 -C ~/devel/ansible

Nach Anpassung der Daten im Inventory kann man anschließend direkt zur Ausführung schreiten.

Vorbereitung - (Server-)Daten im Inventory

Bei unserem Konfigurationsbeispiel hier gehen wir von den vorgenannten Parametern aus.

Die Konfigurationsdatei unseres inventory in unsere, Ansible-Verzeichnis beinhaltet demnach unter anderem:

 $ vim inventories/production/hosts

inventories/production/hosts

Jeder Node hat im Inventory-Verzeichnis dann jeweils eine Datei hostconfig mit den jeweiligen generellen Hostdaten, sowie der NFS-Server pml010002 eine nfs_server mit den NFS-Server-Daten und die beiden Client-Hosts dann jeweils eine eigenständige nfs_client-Datei mit den Client spezifischen NFS-Parametern.

NFS-Server pml010002
 $ vim inventories/production/host_vars/pml010002/hostconfig

inventories/production/host_vars/pml010002/hostconfig

 $ vim inventories/production/host_vars/pml010002/nfs_server

inventories/production/host_vars/pml010002/nfs_server

NFS-Client pml010060
 $ vim inventories/production/host_vars/pml010060/hostconfig

inventories/production/host_vars/pml010060/hostconfig

 $ vim inventories/production/host_vars/pml010060/nfs_client

inventories/production/host_vars/pml010060/nfs_client

NFS-Client pml010070
 $ vim inventories/production/host_vars/pml010070/hostconfig

inventories/production/host_vars/pml010070/hostconfig

 $ vim inventories/production/host_vars/pml010070/nfs_client

inventories/production/host_vars/pml010070/nfs_client

globale Parameter

Parameter die für alle Hosts gelten sollen legen wir unter group_vars/all/nfs ab.

 $ vim inventories/production/group_vars/all/nfs

inventories/production/group_vars/all/nfs

Unser Beispiels-Inventory hat also nunmehr folgenden Aufbau:

inventories/production/
├── group_vars
│   └── all
│       └── nfs
├── hosts
└── host_vars
    ├── pml010002
    │   ├── hostconfig
    │   └── nfs_server
    ├── pml010060
    │   ├── hostconfig
    │   └── nfs_client
    └── pml010070
        ├── hostconfig
        └── nfs_client

7 directories, 8 files

Playbooks

In diesem Konfigurationsbeispiel haben wir zwei Playbooks, einmal eines für den NFS-Server und 1x eines für die Clients.

playbooks/
├── arch_nfs_client.yml
└── arch_nfs_server.yml

1 directory, 2 files

Das Playbook arch_nfs_server.yml zum Installieren und Konfigurieren des NFSv4-Servers ist wie immer schlank, unscheinbar und unspektakulär, beinhaltet aber Hinweise zur Aufgabe und wie es aufzurufen ist.

 $ vim playbooks/arch_nfs_server.yml

playbooks/arch_nfs_server.yml

Gleiches gilt für das Playbook arch_nfs_client.yml, welches wir für die Konfiguration der NFS-Clientspezifischen Parametern auf den beiden Client-Rechnern verwenden.

 $ vim playbooks/arch_nfs_client.yml

playbooks/arch_nfs_client.yml

Rolle: arch_nfs_server

Für die Konfiguration des NFSv4-Servers verwenden wir eine eigene Rolle arch_nfs_server, die wir bei unserem zuvor angelegten Playbooks später einfach mit aufrufen werden. Hierzu kopieren wir uns zunächst die Mustervorlage common, welche wir bei der initialen Ansible-Einrichtung angelegt hatten.

 $ cp -avr roles/common/ roles/arch_nfs_server

Ausgabe von cp -avr roles/common/ roles/arch_nfs_server

Bei Bedarf können wir uns die Struktur die somit angelegt wurde mit nachfolgendem Befehl anzeigen lassen.

 $ tree roles/arch_nfs_server/

Ausgabe von tree roles/arch_nfs_server/

Wie wir sehen ist die Rolle durchaus überschaubar, im Task main.yaml verweisen wir lediglich auf die folgenden Tasks:

 $ vim roles/arch_nfs_server/tasks/main.yml

roles/arch_nfs_server/tasks/main.yml

Die Installation des benötigten ArchLinux-Paketes für den NFSv4-Daemon wird in der ersten Task-Gruppe mit dem tag packages vorgenommen.

 $ vim roles/arch_nfs_server/tasks/packages.yml

roles/arch_nfs_server/tasks/packages.yml

Für die Konfiguration des NFSv4-Servers, wie im Abschnitt Konfiguration des NFSv4-Servers erklärt, werden die nötigen Schritte in der Task-Gruppe mit dem tag nfs_server_config definiert.

 $ vim roles/arch_nfs_server/tasks/nfs_server_config.yml

roles/arch_nfs_server/tasks/nfs_server_config.yml

Die Konfigurationsdatei auf dem Zielhost /etc/exports wird mit Hilfe des Jinja2 Templates exports.j2 sauber formatiert angelegt.

 $ vim roles/arch_nfs_server/templates/exports.j2

roles/arch_nfs_server/templates/exports.j2

Werden Änderungen an der /etc/fstab vorgenommen, so wird über den Handler Reload systemd ein Reload das Systemd initiiert. Änderungen an der Shares des Servers, die in der Datei /etc/exports definiert werden, wiederum werden dem NFS-Server Durch den Befehl exportfs -r. Die Konfiguration der beiden Handler erfolgt mit Hilfe der Datei main.yml im Unterverzeichnis handlers.

 $ vim roles/arch_nfs_server/handlers/main.yml

roles/arch_nfs_server/handlers/main.yml

Zum Schluß konfigurieren wir abschließend noch die Paketfilter-Regeln für unseren Firewall-Daemon firewalld.

 $ vim roles/arch_nfs_server/tasks/firewalld_config.yml

roles/arch_nfs_server/tasks/firewalld_config.yml

Rolle: arch_nfs_sclient

Für die Konfiguration des NFSv4-clients verwenden wir eine weitere Rolle arch_nfs_client, die wir bei unserem zuvor angelegten Playbooks später einfach mit aufrufen werden. Hierzu kopieren wir uns zunächst die Mustervorlage common, welche wir bei der initialen Ansible-Einrichtung angelegt hatten.

 $ cp -avr roles/common/ roles/arch_nfs_client

Ausgabe von cp -avr roles/common/ roles/arch_nfs_client

Bei Bedarf können wir uns die Struktur die somit angelegt wurde mit nachfolgendem Befehl anzeigen lassen.

 $ tree roles/arch_nfs_client/

Ausgabe von tree roles/arch_nfs_client/

Wie wir sehen ist auch diese Rolle durchaus überschaubar, im Task main.yaml verweisen wir lediglich auf die folgenden Tasks:

 $ vim roles/arch_nfs_client/tasks/main.yml

roles/arch_nfs_client/tasks/main.yml

Die Installation des benötigten ArchLinux-Paketes für den NFSv4-Client wird in der ersten Task-Gruppe mit dem tag packages vorgenommen.

 $ vim roles/arch_nfs_client/tasks/packages.yml

roles/arch_nfs_client /tasks/packages.yml

Für die Konfiguration des NFSv4-Clients, wie im Abschnitt Konfiguration des NFSv4-Clients erklärt, werden die nötigen Schritte in der Task-Gruppe mit dem tag nfs_client_config definiert.

 $ vim roles/arch_nfs_client/tasks/nfs_client_config.yml

roles/arch_nfs_client/tasks/nfs_client_config.yml

Die benötigten Systemd-Unit-Files auf dem Zielhost im Verzeichnis /etc/systemd/system werden mit Hilfe der beiden Jinja2 Templates automount.j2 und mount.j2 angelegt.

 $ vim roles/arch_nfs_client/templates/automount.j2

roles/arch_nfs_client/templates/automount.j2

 $ vim roles/arch_nfs_client/templates/mount.j2

roles/arch_nfs_client/templates/mount.j2

Werden Änderungen an den Systemd-Unit-Files vorgenommen, so wird über den Handler Reload systemd ein Reload das Systemd initiiert. Die Konfiguration des Handlers erfolgt mit Hilfe der Datei main.yml im Unterverzeichnis handlers.

 $ vim roles/arch_nfs_client/handlers/main.yml

roles/arch_nfs_client/handlers/main.yml

Ausführung - Playbooklauf

Die orchestrierte Variante der Installation und Konfiguration unseres NFSv4-Servers gestaltet sich ab sofort sehr einfach, brauchen wir doch lediglich die Konfigurationswerte im Inventory zu hinterlegen und zu pflegen und letztendlich das Playbook entsprechend aufzurufen:

 $ ansible-playbook playbooks/arch_nfs_server.yml --limit pml010002
[22:12:48] Gathering Facts
↳  pml010002 | SUCCESS | 2.40s
[22:12:51] arch_nfs_server : Installation der benötigten Pakete.
↳  pml010002 | SUCCESS | 17ms
[22:12:51]     ↳ packages: Installation der benötigten Pakete.
↳  pml010002 | SUCCESS | 1.92s
[22:12:53] arch_nfs_server : Konfiguration des NFS Servers.
↳  pml010002 | SUCCESS | 23ms
[22:12:53]     ↳ nfs_server_config: Benutzerdefinierte Export-Stammverzeichnisse unter /srv/nfs anlegen.
↳  pml010002 | CHANGED | 2.04s
[22:12:55]     ↳ nfs_server_config: Pseudo-Root-NFS-Verzeichnis anlegen.
↳  pml010002 | CHANGED | 380ms
[22:12:55]     ↳ nfs_server_config: Export-Verzeichnisse unter /exports anlegen.
↳  pml010002 | CHANGED | 1.88s
[22:12:57]     ↳ nfs_server_config: Änderungen an der /etc/fstab mit blockinfile vornehmen.
↳  pml010002 | SUCCESS | 452ms
[22:12:58]     ↳ nfs_server_config: Checken ob es bereits eine Backupdatei von /etc/exports gibt.
↳  pml010002 | SUCCESS | 564ms
[22:12:58]     ↳ nfs_server_config: Backupdatei der Exports Konfigurationsdatei /etc/exports erstellen.
pml010002 | SKIPPED | 23ms
[22:12:58]     ↳ nfs_server_config: Exports Konfigurationsdatei aus Template erzeugen.
↳  pml010002 | SUCCESS | 921ms
[22:12:59]     ↳ nfs_server_config: Systemd Service des NFSv4-Servers starten und aktivieren.
↳  pml010002 | SUCCESS | 823ms
[22:13:00] arch_nfs_server : Konfiguration des Paketfilters auf Basis firewalld.
↳  pml010002 | SUCCESS | 21ms
[22:13:00]     ↳ firewalld_config: Installation des Firewall-Daemons.
↳  pml010002 | SUCCESS | 1.29s
[22:13:01]     ↳ firewalld_config: Sicherstellen, dass der Firewall-Daemon reboot(-fest) starten.
↳  pml010002 | CHANGED | 893ms
[22:13:02]     ↳ firewalld_config: Firewall-Zone für Zone intra anlegen.
↳  pml010002 | SUCCESS | 710ms
[22:13:04]     ↳ firewalld_config: Firewall Daemon neu laden mit: firewall-cmd --reload.
↳  pml010002 | CHANGED | 626ms
[22:13:04]     ↳ firewalld_config: Interface net0 der Firwall-Zone intra zuordnen.
↳  pml010002 | SUCCESS | 516ms
[22:13:05]     ↳ firewalld_config: Service Rules SSH für Zone intra definieren.
↳  pml010002 | SUCCESS | 1.07s
[22:13:06]     ↳ firewalld_config: Service Rules IPv6 echo-request für Zone intra definieren.
↳  pml010002 | SUCCESS | 1.07s
[22:13:08]     ↳ firewalld_config: Service Rules NFS für Zone intra definieren.
↳  pml010002 | SUCCESS | 4.30s
[22:13:12] system
-- Play recap --
pml010002                  : ok=20   changed=5    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 

Gleiches gilt natürlich auch für die Konfiguration der NFS-Clients, die wir ab sofort mit Hilfe unseres Ansible Playbooks betanken können.

 $ ansible-playbook playbooks/arch_nfs_client.yml --limit pml010095
[22:23:00] Gathering Facts
↳  pml010095 | SUCCESS | 1.47s
[22:23:02] arch_nfs_client : Installation der benötigten Pakete.
↳  pml010095 | SUCCESS | 24ms
[22:23:02]     ↳ packages: Installation der benötigten Pakete.
↳  pml010095 | SUCCESS | 1.26s
[22:23:03] arch_nfs_client : Konfiguration des NFS Servers.
↳  pml010095 | SUCCESS | 39ms
[22:23:03]     ↳ nfs_client_config: Export-Verzeichnisse unter /mnt anlegen.
↳  pml010095 | CHANGED | 1.67s
[22:23:05]     ↳ nfs_client_config: Automount systemd Unit Datei(en) für NFS-Shares erzeugen und kopieren.
↳  pml010095 | CHANGED | 3.96s
[22:23:09]     ↳ nfs_client_config: Mount systemd Unit Datei(en) für NFS-Shares erzeugen und kopieren.
↳  pml010095 | CHANGED | 3.58s
[22:23:13]     ↳ nfs_client_config: Systemd Service Automount der Shares starten.
↳  pml010095 | CHANGED | 3.18s
triggering handler | arch_nfs_client : Reload systemd 
↳  pml010095 | SUCCESS | 3.94s
[22:23:16] system
-- Play recap --
pml010095                  : ok=9    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

Links


1) , 3)
User Datagram Protocol
2)
Transmission Control Protocol
4)
Stream Control Transmission Protocol
Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
  • linux/nfs.txt
  • Zuletzt geändert: 10.07.2026 14:14.
  • von django