From a4de921c1ca46608e1185d60d3cfc7fdd634928d Mon Sep 17 00:00:00 2001 From: Administrator Date: Sun, 1 Feb 2026 20:45:52 +0000 Subject: [PATCH] docs: create ZNAS-NFS-Exports --- ZNAS-NFS-Exports.md | 243 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 ZNAS-NFS-Exports.md diff --git a/ZNAS-NFS-Exports.md b/ZNAS-NFS-Exports.md new file mode 100644 index 0000000..51f94a7 --- /dev/null +++ b/ZNAS-NFS-Exports.md @@ -0,0 +1,243 @@ +--- +title: ZFS-NFS-Exports +description: Exporting NFS shares from ZFS datasets +published: true +date: 2026-02-01T20:45:40.210Z +tags: +editor: markdown +dateCreated: 2026-02-01T20:45:40.210Z +--- + +# NFS + ZFS Configuration Fix + +## Problems Identified + +1. **Boot order issue**: NFS was starting before ZFS mounted the datasets +2. **Autofs recursive loop**: The server was NFS-mounting its own exports back to itself via autofs, creating conflicts +3. **Mountpoint mismatch**: ZFS datasets were mounting to `/srv/vault/*` but NFS was trying to export from `/export/*` using bind mounts that didn't work properly +4. **Child dataset mountpoints**: When the parent dataset mountpoint changed, child datasets still had old mountpoints and weren't visible + +## Complete Solution + +### Step 1: Stop and Disable Autofs on NFS Server +```bash +sudo systemctl stop autofs +sudo systemctl disable autofs +``` + +**Note**: Autofs should only run on NFS clients, not on the server itself. + +### Step 2: Set ZFS Datasets to Mount Directly to `/export/*` + +Instead of using bind mounts, configure ZFS to mount directly to the export paths: +```bash +sudo zfs set mountpoint=/export vault +sudo zfs set mountpoint=/export/Data vault/Data +sudo zfs set mountpoint=/export/Green vault/Green +sudo zfs set mountpoint=/export/Docker vault/docker +sudo zfs set mountpoint=/export/Common vault/Common +``` + +### Step 3: Configure Child Dataset Mountpoints + +For any child datasets (subdirectories under parent datasets), set their mountpoints explicitly: +```bash +sudo zfs set mountpoint=/export/Data/media/books vault/Data/media_books +sudo zfs set mountpoint=/export/Data/media/comics vault/Data/media_comics +``` + +### Step 4: Unmount and Remount Datasets + +Unmount children first, then parents, then remount all: +```bash +# Unmount child datasets first +sudo zfs unmount vault/Data/media_books +sudo zfs unmount vault/Data/media_comics + +# Unmount parent datasets +sudo zfs unmount vault/Data +sudo zfs unmount vault/Green +sudo zfs unmount vault/docker +sudo zfs unmount vault/Common + +# Remount all +sudo zfs mount -a +``` + +### Step 5: Configure NFS Exports + +Edit `/etc/exports`: +```bash +sudo nano /etc/exports +``` + +Content: +```bash +# /etc/exports: the access control list for filesystems which may be exported +# to NFS clients. See exports(5). + +# NFSv4 - pseudo filesystem root +/export *(ro,fsid=0,crossmnt,no_subtree_check) + +# Shares beneath the NFSv4 root +/export/Common *(fsid=4,rw,no_subtree_check,insecure) +/export/Data *(fsid=5,rw,no_subtree_check,insecure,crossmnt,nohide) +/export/Docker *(fsid=29,rw,no_root_squash,sync,no_subtree_check,insecure) +/export/Green *(fsid=30,rw,no_root_squash,no_subtree_check,insecure) +``` + +**Key options explained**: +- `crossmnt`: Allows NFS to cross filesystem mount boundaries +- `nohide`: Makes child mounts visible through parent exports +- `no_subtree_check`: Improves reliability and performance + +### Step 6: Configure NFS to Wait for ZFS at Boot + +Create systemd override for NFS server: +```bash +sudo mkdir -p /etc/systemd/system/nfs-server.service.d/ +sudo nano /etc/systemd/system/nfs-server.service.d/override.conf +``` + +Add this content: +```ini +[Unit] +After=zfs-import.target zfs-mount.service local-fs.target +Requires=zfs-import.target zfs-mount.service +``` + +This ensures NFS waits for ZFS to be fully mounted before starting. + +### Step 7: Reload and Restart Services +```bash +sudo systemctl daemon-reload +sudo exportfs -ra +sudo systemctl restart nfs-server +``` + +### Step 8: Verify Configuration + +On the server: +```bash +# Check ZFS mounts +zfs list -r vault + +# Check what's actually mounted +mount | grep export + +# Verify NFS exports +sudo exportfs -v + +# Check content is visible +ls -la /export/Data/media/books/ +``` + +On the client: +```bash +# Show available exports +showmount -e 192.168.5.10 + +# Mount NFS share +sudo mount -t nfs4 192.168.5.10:/ /mnt/znas + +# Verify content +ls -la /mnt/znas/Data/media/books/ +``` + +## Adding New Datasets + +When creating new datasets that need to be exported via NFS: +```bash +# Create dataset with correct mountpoint from the start +sudo zfs create -o mountpoint=/export/Data/new_folder vault/Data/new_folder + +# The dataset will automatically mount and be visible via NFS +# due to the crossmnt and nohide options on the parent export + +# Verify it's visible +ls -la /export/Data/new_folder/ +``` + +**No need to**: +- Modify `/etc/exports` (unless you need special permissions) +- Create bind mounts in `/etc/fstab` +- Restart NFS (it will see the new mount automatically) + +## Troubleshooting + +### Datasets not visible via NFS +```bash +# Verify dataset is mounted +zfs list | grep dataset_name + +# Check NFS can read it +sudo -u nobody ls -la /export/path/to/dataset/ + +# Restart NFS +sudo exportfs -ra +sudo systemctl restart nfs-server +``` + +### Client shows empty directories +```bash +# On client, clear NFS cache +sudo umount -f /mnt/znas +sudo mount -t nfs4 192.168.5.10:/ /mnt/znas + +# Or mount with no caching to test +sudo mount -t nfs4 -o noac,lookupcache=none 192.168.5.10:/ /mnt/znas +``` + +### After reboot, exports are empty +```bash +# Verify ZFS mounted before NFS started +systemctl status zfs-mount.service +systemctl status nfs-server.service + +# Check the override is in place +systemctl cat nfs-server.service | grep -A5 Unit +``` + +## Important Notes + +- **Do not use bind mounts** in `/etc/fstab` for ZFS datasets - let ZFS handle mounting directly +- **Keep autofs disabled** on the NFS server to prevent recursive mount loops +- **Child datasets** must have their mountpoints explicitly set to be visible +- **The `crossmnt` and `nohide` options** are critical for NFSv4 to traverse ZFS dataset boundaries +- **Always set mountpoints when creating datasets** to avoid having to fix them later + +## Configuration Files Reference + +### /etc/fstab + +Should **NOT** contain bind mounts for `/export/*`. ZFS handles mounting directly. + +Only keep system mounts: +```bash +# / was on /dev/nvme0n1p2 during curtin installation +/dev/disk/by-uuid/40c60952-0340-4a78-81f9-5b2193da26c6 / btrfs defaults 0 1 +# /boot was on /dev/nvme0n1p3 during curtin installation +/dev/disk/by-uuid/4abb4efa-0b2b-4e4a-bcaf-78227db4628f /boot ext4 defaults 0 1 +/dev/disk/by-uuid/d07437a0-3d0e-417a-a88e-438c603c2237 none swap sw 0 0 +# /srv was on /dev/nvme0n1p5 during curtin installation +/dev/disk/by-uuid/c66e81ff-436e-4d6f-980b-6f4875ea7c8e /srv btrfs defaults 0 1 +``` + +### /etc/systemd/system/nfs-server.service.d/override.conf +```ini +[Unit] +After=zfs-import.target zfs-mount.service local-fs.target +Requires=zfs-import.target zfs-mount.service +``` + +### /etc/exports +```bash +# NFSv4 - pseudo filesystem root +/export *(ro,fsid=0,crossmnt,no_subtree_check) + +# Shares beneath the NFSv4 root +/export/Common *(fsid=4,rw,no_subtree_check,insecure) +/export/Data *(fsid=5,rw,no_subtree_check,insecure,crossmnt,nohide) +/export/Docker *(fsid=29,rw,no_root_squash,sync,no_subtree_check,insecure) +/export/Green *(fsid=30,rw,no_root_squash,no_subtree_check,insecure) +``` \ No newline at end of file