Files
docker-infrastructure/NAS-CONNECTION-STRATEGIES.md
T

124 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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