A homelab with three Proxmox nodes, a dozen LXC containers, and fifty Docker services quickly outgrows local storage. Backups scatter across machines. Media libraries duplicate. Container volumes pin data to specific hosts, making migration painful.
NFS (Network File System) solves this. A single shared storage pool accessible from every Proxmox host, every LXC container, and every Docker container means your data lives in one place — and you only need to back up one place.
This guide walks through deploying NFS shared storage from scratch: server setup on Debian/Ubuntu, Proxmox storage integration, Docker volume mounts, LXC bind mounts, and performance tuning for realistic homelab networks.
Why NFS Instead of Samba or iSCSI?
For a homelab storage backend, three protocols dominate:
| Protocol | Best For | Overhead | Docker Support | Proxmox Integration |
|---|---|---|---|---|
| NFSv4 | Linux-to-Linux, concurrent reads | Low | Native volume driver | First-class storage type |
| SMB/CIFS | Mixed OS (Windows clients) | Moderate | Requires CSI driver | Additional mount config |
| iSCSI | Block-level VMs, databases | Low (block) | Not supported | LVM/block storage only |
In a Linux-only homelab running Proxmox and Docker, NFSv4 is the
natural choice — native kernel client, sub-millisecond latency on
modern networks, no additional software, and first-class support in
both Proxmox (pvesm) and Docker (volume --driver local --type nfs).
Step 1: NFS Server Setup on Debian/Ubuntu
A minimal VM or LXC container with a large attached disk makes the best NFS server in a Proxmox homelab. Dedicated hardware is better for performance but unnecessary for most home labs.
Install and Configure
|
|
Configure Exports
Edit /etc/exports:
|
|
Export options explained:
rw— read-write accesssync— writes acknowledged after disk commit (safer, slightly slower)async— writes acknowledged before disk commit (faster, minor crash risk)no_subtree_check— disables subtree checking, improves reliabilityno_root_squash— allows root on client to keep root privileges (required for Proxmox backups. For Docker/LXC, useroot_squashfor security and map UIDs instead)
Apply and Verify
|
|
Firewall rule if using UFW:
|
|
Secure with NFSv4 Only
Modern NFSv4.2 is more secure than v3 — single protocol port, strong auth, and Kerberos support. Disable v3 on the server:
|
|
Restart:
|
|
NFSv4 uses TCP port 2049. No more rpcbind portmap surprises.
Step 2: Add NFS Storage to Proxmox
Proxmox supports NFS as a first-class storage backend. Adding an NFS share makes it available for VM/CT backups, ISO templates, container storage, and even live VM disks.
Via Web UI
- Navigate to Datacenter → Storage → Add → NFS
- Fill in:
- ID:
nfs-backups - Server:
10.0.20.10(your NFS server IP) - Export:
/srv/nfs/backups - Content:
VZDump backup,ISO image,Container template
- ID:
- Click Add
Via CLI
|
|
Verify
|
|
Mount Options for Proxmox NFS
Add these to /etc/pve/storage.cfg under the NFS section:
|
|
hard— retry indefinitely on server outage (preferred for backups; usesoftfor non-critical data)intr— allow interrupt of hung operations (Linux 5.x+, signals work withhardmounts)timeo=600— 60-second timeout before retryretrans=3— retry 3 times before major timeoutnoatime— skip access time updates, reduces NFS traffic
Step 3: Mount NFS Shares in LXC Containers
LXC containers benefit from NFS for shared data that multiple containers access — media libraries, download directories, shared configurations.
Bind Mount Inside a Privileged Container
On the Proxmox host, edit the container’s config:
|
|
Then inside the container:
|
|
For Unprivileged Containers (Best Practice)
Unprivileged containers require UID mapping so the container’s root maps to a non-root user on the host. Mount the NFS share on the Proxmox host first, then bind-mount it into the container:
|
|
This avoids UID mapping issues because the mount happens at the kernel level on the host, then is bind-mounted into the container’s namespace.
Step 4: Docker NFS Volume Mounts
Docker supports NFS natively through the local volume driver with
type: nfs. This is the cleanest way to share storage across Docker
hosts without any CSI plugins.
In Docker Compose
|
|
With Docker Run
|
|
NFS Volume Options for Docker
| Option | Purpose | Recommended |
|---|---|---|
nolock |
Disable NFS locking (Docker doesn’t support lockd) |
Always set |
soft |
Report I/O error instead of hanging | Docker volumes |
vers=4.2 |
Use NFSv4.2 for best performance | Always |
noatime |
Skip access time updates | Media/read-only |
rsize=1048576 |
Read buffer size (1 MB) | 1GbE+ networks |
wsize=1048576 |
Write buffer size (1 MB) | 1GbE+ networks |
Full Example: Jellyfin with NFS Media
|
|
Step 5: NFS Performance Tuning
NFS performance in a homelab depends on three knobs: network, server storage, and mount options.
rsize/wsize — The Single Biggest Lever
NFS read and write buffer sizes default to 1 MB in modern kernels, but older clients may negotiate smaller. Set them explicitly:
|
|
On 1GbE networks (125 MB/s theoretical), 1 MB buffers are optimal. On 10GbE, increase to 2 MB:
|
|
Server-Side Tuning
|
|
Apply:
|
|
NFS Server Thread Count
On the NFS server, each nfsd kernel thread handles one concurrent
request. For a homelab with fewer than 10 clients, 8 threads is
plenty. For 20+ concurrent services hitting the same server:
|
|
Storage Backend Matters
The NFS server’s disk subsystem is the actual bottleneck. ZFS with ARC and L2ARC provides excellent NFS performance:
|
|
recordsize=1M— matches NFS rsize, reduces fragmentationatime=off— eliminates access-time writes on every readcompression=lz4— near-zero overhead compression
Benchmarking NFS Performance
Before and after tuning, benchmark from a client:
|
|
Expected results on 1GbE:
- Sequential read: 110–118 MB/s (near wire speed)
- Sequential write: 100–112 MB/s (sync=slow, async=faster)
- 4K random read: 8,000–15,000 IOPS (depends on server storage)
If sequential throughput is below 80 MB/s on 1GbE, check:
- Switch or cable negotiation (
ethtool eth0) - NFS version negotiation (
mount | grep nfs— confirm v4.2) - rsize/wsize values
- Server disk utilization (
iostat -x 1)
Step 6: Backup Strategy for NFS Storage
Centralizing storage means you only need to back up one server. NFS volumes are not a backup themselves — the server’s disks can fail too.
Automated Snapshot with ZFS
If the NFS server runs on ZFS:
|
|
Rsync to Off-Site
For critical data (Docker configs, databases), rsync from the NFS server to an off-site destination:
|
|
Common Pitfalls and Solutions
Permission Denied on Docker NFS Volumes
Problem: Container writes to NFS volume fail with “Permission denied”.
Fix: Ensure UID/GID in the container matches the NFS server’s file
ownership. NFS maps root (UID 0) to nobody by default unless you
enable no_root_squash on the export.
|
|
Then in the Docker compose service, set PUID=1000 PGID=1000 matching
the server.
LXC Container Can’t Mount NFS
Problem: mount.nfs: access denied inside an unprivileged container.
Fix: Mount NFS on the Proxmox host, then bind-mount it into the
container via mp0: in the CT config. Unprivileged containers lack
the CAP_SYS_ADMIN needed for direct NFS mounts.
NFS Volume Not Available at Docker Start
Problem: Container starts before the NFS server is reachable, volume mount fails.
Fix: Add restart: unless-stopped to the compose service and
configure the Docker host to mount NFS volumes early:
|
|
The _netdev option tells systemd to wait for networking before
mounting.
Poor Write Performance with sync
Problem: Writes are slow (20 MB/s on 1GbE).
Fix: The export uses sync by default. Switch to async for
workloads where a tiny data loss window on crash is acceptable
(e.g., media libraries, download directories):
|
|
For databases and critical data, keep sync and add a ZFS SLOG
device to absorb the synchronous write overhead.
Full Reference: NFS Server Checklist
|
|
Summary
Centralized NFS shared storage transforms a multi-node homelab from a collection of isolated machines into a unified cluster where data flows freely between Proxmox, LXC containers, and Docker services:
- Start with a dedicated NFS server — a simple Debian VM or LXC with a ZFS dataset provides all the performance most homelabs need.
- Use NFSv4.2 exclusively — single port (TCP 2049), better performance, and simpler firewall rules than NFSv3.
- Add NFS storage to Proxmox for unified VM/CT backup targets and ISO/CT template storage accessible from all nodes.
- Mount NFS on the Proxmox host then bind-mount into unprivileged LXC containers to avoid UID mapping complexity.
- Use Docker’s native NFS volume driver with
driver_optsfor per-service NFS mounts — no CSI plugins required. - Tune rsize/wsize for your network — 1 MB for 1GbE, 2 MB for 10GbE.
- Benchmark before and after tuning with
ddandfio— if throughput is below 80% of wire speed, something is misconfigured. - Back up the NFS server — centralization concentrates risk. ZFS snapshots plus off-site rsync cover both local corruption and physical disaster.
A properly configured NFS setup is the backbone of a scalable homelab. It takes an hour to stand up and saves you weeks of scattered storage management over the life of your lab.