docs: update NAS connection strategies for Immich and nas_library/nas_family mounts

This commit is contained in:
2026-03-14 02:10:52 +00:00
parent b2d7f82c53
commit 9dee75e2a0
+123
View File
@@ -0,0 +1,123 @@
# NAS Connection Strategies
Summary of how each service connects to the unRAID NAS (192.168.1.192 / 192.168.1.4).
---
## Strategy Overview
| Strategy | Services | Reliability | Notes |
|----------|----------|-------------|-------|
| Docker NFS named volume | Plex, qBittorrent, Audiobookshelf | ⚠️ Fragile | Soft mount; stale handles on drive spin-down |
| systemd permanent mount + bind | Calibre (import), oCIS, Immich | ✅ Solid | Hard NFS; permanent; no idle cycling |
| systemd automount + bind | Backrest, Filebrowser-Colleen-HD | ✅ Solid | CIFS; TimeoutIdleSec=0; never unmounts once triggered |
| Local SSD + lsyncd sync | Calibre (library) | ✅ Best | SQLite never touches NFS; NAS copy is read-only replica |
---
## Per-Service Details
### Plex
- **Strategy**: Docker NFS named volume (`nas_media`, external)
- **NAS path**: `192.168.1.192:/mnt/user/media`
- **Mount options**: `nfsvers=4,soft,nolock,timeo=14,rsize=8192,wsize=8192`
- **Container path**: `/data`
- **Risk**: `soft` + `timeo=14` means EIO after 14 retries × 0.1s = ~1.4s timeout. If unRAID drives spin down, Plex gets I/O errors. Works in practice because Plex opens/closes file handles per-request rather than holding them open.
### qBittorrent (all 3 instances: open, vpn, vpn2)
- **Strategy**: Docker NFS named volume (`nas_media`, same as Plex)
- **NAS path**: `192.168.1.192:/mnt/user/media`
- **Container path**: `/data`
- **Risk**: Same as Plex. Active downloads write continuously — more exposure to spin-down EIO than Plex.
### Calibre
- **Strategy (library)**: Local SSD + lsyncd one-way sync to NAS
- Local: `/srv/calibre/library` → container `/config/Calibre Library`
- lsyncd syncs to `/mnt/nas_books/calibre/Calibre Library` within ~15 seconds
- SQLite (`metadata.db`, `notes.db`) never touches NFS — eliminates `apsw.IOError`
- **Strategy (import)**: systemd permanent NFS mount + Docker bind mount
- Host: `/mnt/nas_books/calibre-import` (permanent NFS, no automount)
- Container: `/calibre-import`
- NAS path: `192.168.1.192:/mnt/user/media/books`
- **Mount options**: `nfsvers=3,hard,rw,noatime`
- **Why permanent (not automount)**: Docker bind mounts snapshot the mount reference at container start. If autofs cycles between restarts, the container gets a stale handle. Permanent mount avoids this entirely.
- **Manual book add** (when auto-add fails):
```bash
docker stop calibre
docker run --rm \
-v /srv/calibre/library:/config/Calibre\ Library \
-v /mnt/nas_books/calibre-import:/calibre-import \
lscr.io/linuxserver/calibre:latest \
sh -c "cd /opt/calibre && LD_LIBRARY_PATH=/opt/calibre ./calibredb add \
--library-path '/config/Calibre Library' '/calibre-import/<book>' 2>&1"
docker start calibre
```
### Filebrowser-Colleen-HD
- **Strategy**: systemd CIFS automount + Docker bind mount
- **Host mount**: `/mnt/nas_backup` (CIFS `//192.168.1.192/backup`)
- **Container path**: `/folder`
- **Mount options**: `vers=3.0,uid=0,gid=0,noperm,noserverino,soft,TimeoutIdleSec=0`
- **Why CIFS**: Container runs as root; CIFS with `uid=0,gid=0` maps all files to root
- **TimeoutIdleSec=0**: Never auto-unmounts once triggered; safe for persistent container access
### Backrest (backup service)
- **Strategy**: systemd CIFS automount + Docker bind mount (same mount as Filebrowser)
- **Host mount**: `/mnt/nas_backup/nas-docker-data`
- **Container path**: `/backup-export`
- **Same CIFS mount as Filebrowser-Colleen-HD** (`mnt-nas_backup`)
### oCIS (ownCloud Infinite Scale)
- **Strategy**: systemd permanent NFS mount + Docker bind mount
- **Host mount**: `/mnt/nas_owncloud` (permanent NFS, no automount)
- **Container path**: `/var/lib/ocis/storage/users`
- **NAS path**: `192.168.1.192:/mnt/user/owncloud`
- **Mount options**: `nfsvers=3,hard,rw,noatime`
- **Local config/index**: `/srv/ocis/data` and `/srv/ocis/config` stay on local SSD
### Immich
- **Strategy**: systemd permanent NFS mount + Docker bind mount
- **Host mount**: `/mnt/nas_family` (NFS `192.168.1.192:/mnt/user/family`)
- **Container path**: `/usr/src/app/upload` → `/mnt/nas_family/immich-library`
- **Mount options**: `nfsvers=3,hard,rw,noatime`
- **Why permanent (not automount)**: Drive doesn't spin down; permanent mount avoids any autofs cycling risk
- **Database**: PostgreSQL on local SSD (`/var/lib/postgresql/data`) — correct, not on NFS
### Audiobookshelf
- **Strategy**: Docker NFS named volume
- **NAS path**: `192.168.1.192:/mnt/user/media/audiobooks`
- **Container path**: `/audiobooks`
- **Config/metadata**: Local SSD (`/srv/audiobookshelf/`) — correct
---
## systemd Mount Units
| Unit | Type | Share | Status |
|------|------|-------|--------|
| `mnt-nas_books.mount` | NFS permanent | `:/mnt/user/media/books` | enabled, always up |
| `mnt-nas_owncloud.mount` | NFS permanent | `:/mnt/user/owncloud` | enabled, always up |
| `mnt-nas_family.mount` | NFS permanent | `:/mnt/user/family` | enabled, always up |
| `mnt-nas_library.mount` | CIFS automount | `//192.168.1.192/library` | triggered on access, TimeoutIdleSec=0 |
| `mnt-nas_library.automount` | CIFS automount | — | enabled |
| `mnt-nas_backup.mount` | CIFS automount | `//192.168.1.192/backup` | triggered on access, TimeoutIdleSec=0 |
| `mnt-nas_backup.automount` | CIFS automount | — | enabled |
---
## Known Issues & Gotchas
- **Docker NFS named volumes**: The `nas_media` volume uses `soft,nolock,timeo=14,nfsvers=4`. This is fragile — short timeout means EIO on spin-up. Plex/qBittorrent survive because they open/close handles per request. If either starts having I/O errors, migrate to the systemd permanent mount pattern.
- **Docker bind mounts + automount = stale handles**: Docker snapshots the mount reference at container start. If autofs cycles (unmount + remount) between container restarts, the container's bind mount goes stale while the host sees the path fine. Fix: use permanent `.mount` (no `.automount`) for any share that Docker containers bind-mount.
- **SQLite on NFS**: Never store SQLite databases (calibre `metadata.db`/`notes.db`, any app DB) on NFS. Even with `hard` mounts and NLM locking, transient NFS errors cause `SQLITE_IOERR`. Keep SQLite on local SSD; sync non-SQLite files to NAS if sharing is needed.
- **CIFS vs NFS for file permissions**: CIFS enforces server-side ACLs based on the SMB user. Files created via NFS by uid=99 with mode 600 are inaccessible via CIFS. Use NFS when container needs uid-mapped access to NFS-created files.
- **lsyncd for NAS sync**: inotify-based, syncs within ~15 seconds of any write. Config at `/etc/lsyncd/lsyncd.conf.lua`. Log at `/var/log/lsyncd.log`.
---
## Recommended Migration (future)
Plex, qBittorrent, Immich, and Audiobookshelf all use the fragile Docker NFS named volume pattern. The safer pattern is systemd permanent mount + Docker bind mount (as used by calibre-import and oCIS). This would involve:
1. Create `/mnt/nas_media` systemd permanent mount unit
2. Update compose files to use bind mounts instead of the external `nas_media` volume
3. `docker volume rm nas_media` after redeployment