14 - NFS Setup
Date: 2026-02-11 Updated: 2026-04-08 (replace SSHFS automount with systemd service) Updated: 2026-08-11 (add Windows SMB client section) Hostname: pve IP address: 192.168.0.109
Overview¶
NFS is used in both directions:
- Proxmox → LAN: exports the media storage pool so Nobara (and others) can mount it
- Nobara → Proxmox: exports a backup HDD so Proxmox can rsync LXC backups onto it
The Windows side of the dual-boot machine uses SMB instead - see Windows Client (SMB) below.
Proxmox as NFS Server¶
Proxmox exports its storage to the local network.
Install NFS server¶
/etc/exports¶
/mnt/storage 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash,fsid=1)
/mnt/disk1 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash,fsid=2)
/mnt/disk2 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash,fsid=3)
/mnt/disk3 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash,fsid=4)
/mnt/disk4 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash,fsid=5)
Apply and verify¶
Enable NFS server at boot¶
Note: the service name is nfs-server (not nfs-kernel-server) on recent Debian/Proxmox versions.
Nobara PC as NFS Server (backup target)¶
Nobara exports its backup HDD so Proxmox can rsync LXC dump files onto it.
Nobara /etc/exports¶
Only the Proxmox host (192.168.0.109) has access - not the whole LAN.
Apply on Nobara¶
Proxmox mounts it in /etc/fstab¶
192.168.0.100:/mnt/hdd/Backup /mnt/pve/nobara-backup nfs soft,timeo=600,retrans=3,_netdev,x-systemd.automount 0 0
soft- an unreachable server returns an I/O error to the application instead of blocking it forever.hardwould make rsync wait indefinitely, and a wedged NFS mount on pve can take the backup jobs with ittimeo=600+retrans=3- about six minutes of tolerance before that I/O errorx-systemd.automount- mounts on first access, not at boot
timeo is in deciseconds, which cost four weekly syncs¶
This line read timeo=30 until 2026-10-04, written in the belief that it meant 30
seconds. From man 5 nfs on the host itself:
timeo=n The time in deciseconds (tenths of a second) the NFS client waits for a
response before it retries an NFS request.
For NFS over TCP the default timeo value is 600 (60 seconds).
So the value was 3 seconds, a twentieth of the TCP default, and with
retrans=3 and linear backoff the mount handed rsync an Input/output error (5)
after roughly 18 seconds of server silence. Against a 3.5-hour rsync onto a USB
HDD on a KDE desktop that is nowhere near enough: 2026-09-07, 09-14, 09-20 and
09-27 all ended rc=1, each with the same signature in
/var/log/nobara-sync.log:
rsync: [Receiver] ERROR: cannot stat destination "/mnt/pve/nobara-backup/proxmox-host/": Input/output error (5)
rsync: [receiver] close failed on ".../vzdump-lxc-109-2026_09_11-02_11_01.tar.zst.WWYvZe": Input/output error (5)
rsync error: error in socket IO (code 10) at io.c(849) [sender=3.4.1]
Two things that look like the cause and are not. The kernel logs
nfs: server 192.168.0.100 not responding, timed out in bursts, which reads like
a network fault - on 2026-10-04 those bursts fell between 08:06 and 08:07 and the
desktop's own uptime showed it booted at 08:07, so they were the machine starting,
not dropping. And the desktop has a known SSH freeze issue, which makes "it froze
again" the easy answer - but its journal held no suspend, hibernate or resume event
on any of the failure days.
Changing this does not affect the live mount. The options come from the
systemd-generated unit, so after editing /etc/fstab:
systemctl daemon-reload
systemctl cat 'mnt-pve-nobara\x2dbackup.mount' | grep ^Options # the new value
findmnt -o OPTIONS /mnt/pve/nobara-backup # still the old one
Only an unmount and remount switches the running mount over, which means waiting for any sync in flight to finish.
Outcome: the first rc=0 in four weeks¶
The sync running when the fstab was edited finished at 15:00:30 on 2026-10-04,
four hours after its 11:00 start, with rc=0 - the first success since
2026-09-13. It still ran on the old 3-second mount from end to end, so it proves
the backlog cleared, not that timeo=600 works; the first real test of that is
the next run.
rc=0 on its own does not prove a complete mirror. It says rsync did not
error. What says the backup exists is comparing both ends:
| Source | Destination | |
|---|---|---|
| proxmox dumps | 870G | 870G |
| proxmox-host | 26G | 26G |
files in dump/ |
732 | 732 |
The deficit that produced the 230 GB estimate is gone, and the live mount now
reports soft,timeo=600,retrans=3.
Two things worth copying from how this was done, and one worth not copying.
Swapping the mount needs a unit, not a shell. The remount could only happen after the sync finished, which turned out to be 82 minutes away - longer than an interactive wait. A transient unit on the host does it without depending on any session staying open:
systemd-run --unit=nobara-remount-after-sync --collect bash -c '
while kill -0 <sync-pid> 2>/dev/null; do sleep 30; done
umount /mnt/pve/nobara-backup && ls /mnt/pve/nobara-backup >/dev/null
findmnt -o OPTIONS -n /mnt/pve/nobara-backup'
The same pattern, with the lock file instead of the mount, bridges the one run
that predates the flock: a holder tied to the running script's PID keeps the
lock until that PID exits, so the next slot is skipped rather than starting a
second rsync against a destination the first is still writing.
What not to copy: an unescaped $(date) inside the unit's command. It is
expanded by the shell that builds the systemd-run line, not by the unit when it
eventually runs, so the log opened with the timestamp of unit creation - 82
minutes before the work it was labelling. The ordering had to be re-established
from a different line in the same log, the one quoting Sync done (rc=0), which
could only have been read after the sync wrote it. A log line that timestamps
itself wrong is worse than one with no timestamp, because it is believed.
Nobara as NFS Client (mounts Proxmox storage)¶
Do not use /etc/fstab for these mounts. Hard fstab NFS entries freeze Nobara's boot if Proxmox is offline. Use systemd automount instead.
Install NFS client on Nobara¶
Create mount points¶
Create systemd mount + automount units¶
Run as root (sudo -i) to avoid heredoc indentation issues:
for share in storage disk1 disk2 disk3 disk4; do
cat > /etc/systemd/system/mnt-${share}.mount << EOF
[Unit]
Description=NFS /mnt/${share} from Proxmox
After=network-online.target
Wants=network-online.target
[Mount]
What=192.168.0.109:/mnt/${share}
Where=/mnt/${share}
Type=nfs
Options=noauto,nfsvers=4,soft,timeo=30,retrans=3,_netdev
[Install]
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/mnt-${share}.automount << EOF
[Unit]
Description=Automount /mnt/${share}
[Automount]
Where=/mnt/${share}
TimeoutIdleSec=600
[Install]
WantedBy=multi-user.target
EOF
done
Enable and start¶
systemctl daemon-reload
systemctl enable --now mnt-storage.automount mnt-disk1.automount mnt-disk2.automount mnt-disk3.automount mnt-disk4.automount
Verify¶
The first ls triggers the automount. All 5 shares should appear in df -h.
How it works¶
- The
.automountunit watches the directory - First access triggers the mount automatically
- After 600 seconds (10 min) of inactivity it unmounts
- If Proxmox is offline:
soft+timeo=30+retrans=3gives up after roughly 18 seconds, not the ~90 this document claimed until 2026-10-04 -timeocounts deciseconds, so 30 is 3 seconds (see the correction above)
This direction keeps the short timeout on purpose. The opposite mount, pve
writing to the desktop, was raised to timeo=600 because an unattended rsync
should wait out a busy server rather than abort after 18 seconds. Here a human is
waiting on a file manager, so failing fast beats a window frozen for six minutes.
Same option, opposite correct value, because the client is a person in one case
and a batch job in the other.
Nobara SSHFS Mount (LXC 109 claude-mgmt)¶
Nobara mounts /root from LXC 109 (claude-mgmt) via SSHFS. NFS server cannot run inside an unprivileged LXC, so SSHFS is used instead.
Prerequisites¶
Root's SSH key on Nobara must be in LXC 109's authorized_keys. Since LXC 109 has password auth disabled, add it via the existing user key:
sudo ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N ""
sudo cat /root/.ssh/id_ed25519.pub | ssh root@192.168.0.204 "cat >> /root/.ssh/authorized_keys"
Also add LXC 109 to root's known_hosts on Nobara:
Create mount point¶
Note: no hyphen in claudemgmt - systemd unit file names encode hyphens as \x2d which causes shell escaping issues.
Create systemd service¶
A service unit is used instead of mount+automount. The automount approach caused Dolphin and the KDE desktop to lag/freeze for up to 15 seconds on each access attempt when LXC 109 was offline (the mount unit blocked D-Bus via systemd-hostnamed). The service approach with reconnect mounts once and maintains the connection in the background.
sudo tee /etc/systemd/system/mnt-claudemgmt.service << 'EOF'
[Unit]
Description=SSHFS /root from LXC 109 claude-mgmt
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStartPre=/bin/bash -c 'ssh -o ConnectTimeout=3 -o BatchMode=yes root@192.168.0.204 exit 2>/dev/null'
ExecStart=/usr/bin/sshfs root@192.168.0.204:/root /mnt/claudemgmt \
-f \
-o allow_other \
-o IdentityFile=/home/nex/.ssh/id_ed25519 \
-o reconnect \
-o ServerAliveInterval=5 \
-o ServerAliveCountMax=2
ExecStop=/bin/fusermount3 -u /mnt/claudemgmt
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.target
EOF
Enable and start¶
Should show: homelab learning youtube
How it works¶
- At boot:
ExecStartPrechecks SSH connectivity (3s timeout). If LXC 109 is down, fails fast and retries every 30 seconds. - When connected: SSHFS runs in foreground (
-f), systemd owns the process. - If LXC 109 goes down:
reconnect+ServerAliveInterval=5, ServerAliveCountMax=2detects the drop in 10 seconds, retries in background. File accesses return I/O errors immediately - no desktop freeze. - When LXC 109 comes back: reconnect re-establishes automatically, no manual intervention needed.
- If reconnect gives up: process exits,
Restart=on-failurerestarts the service after 30 seconds.
Windows Client (SMB)¶
The dual-boot desktop (192.168.0.100) reaches the same storage over SMB when booted to Windows, not over NFS.
Why SMB and not NFS¶
The Windows "Client for NFS" is an optional feature, speaks NFSv2/v3 only, and has no real UID mapping - every write lands as an anonymous UID unless you set AnonymousUid/AnonymousGid in the registry. Samba was already running on the Proxmox host, so the Windows side needed no new server component at all.
Shares on the Proxmox host¶
Defined in /etc/samba/smb.conf:
| Share | Path | Access |
|---|---|---|
Storage |
/mnt/storage |
smbuser, normal permissions |
Media |
/mnt/storage/media |
smbuser, normal permissions |
Downloads |
/mnt/storage/media/downloads |
smbuser, normal permissions |
AllDisks |
/mnt |
smbuser, runs as root - full access everywhere |
The AllDisks share¶
The default shares cannot write everywhere: /mnt/storage itself is root:root 755, and the immich/ and syncthing/ subtrees are owned by UID 100000/101000 because unprivileged LXCs use a +100000 offset. AllDisks solves this by running as root:
[AllDisks]
comment = All Disks (disk1-4, storage) - full access
path = /mnt
browseable = yes
read only = no
valid users = @users
force user = root
force group = root
inherit owner = unix only
create mask = 0664
directory mask = 0775
inherit owner = unix only is the part that matters. Without it, everything created from Windows would be owned by host root, which appears as nobody inside an unprivileged container - the Immich and Syncthing containers could then read but not modify their own files. With it, new files inherit the parent directory's owner, so container-owned subtrees stay container-owned.
This is a root-equivalent share. Anyone who can authenticate as smbuser can overwrite or delete anything under /mnt, including .snapraid.content. It is LAN-only and guest access is denied (valid users blocks the map to guest = bad user fallback).
Mounting from Windows¶
In an Administrator prompt:
The password is not in this repository - it is in private/.env, which is gitignored. The same smbuser account is used by the Home Assistant backup job writing to \\192.168.0.109\Storage\backup\proxmox, so resetting it with smbpasswd -a smbuser requires updating the HA side too, or those backups fail silently.
To store the credential separately instead of passing it inline:
cmdkey /add:192.168.0.109 /user:smbuser /pass:<password>
net use Z: \\192.168.0.109\AllDisks /persistent:yes
If net use still prompts for a username after cmdkey, the stored credential was rejected - Windows falls back to prompting rather than reporting the failure. Clear it with cmdkey /delete:192.168.0.109 and verify the password from the Proxmox host before retrying:
NT_STATUS_LOGON_FAILURE there means the password is wrong. To rule out a disabled account rather than a bad password, check the flags - [U] is a normal enabled user, [D] is disabled:
Applying smb.conf changes¶
smbd re-reads smb.conf when a client opens a new connection, so a share edit takes effect on the next mount without a restart. systemctl reload smbd only matters for sessions that are already open. Validate first:
Notes¶
fsid=is required for non-root filesystem exports on Proxmoxno_root_squashallows root access from the client- Nobara runs NFSv4 only (no rpcbind) -
showmount -ewill fail from Proxmox, but mounts work fine - Nobara is not always on - the soft mount on Proxmox ensures it never freezes the host
- If NFS shares stop working after a Proxmox reboot: check
systemctl status nfs-serveron the Proxmox host - it may needsystemctl start nfs-server - Automount units must not have
After=network-online.target- this creates an ordering cycle withlocal-fs.targeton Fedora/Nobara and causes the unit to silently fail at boot. Network dependency belongs only in the.mountunit, not the.automountunit. Access-triggered automounts work correctly without it since the network is already up when the user first accesses the path.