Support mounting host/remote directories into worker containers #85

Closed
opened 2026-07-21 13:17:37 +02:00 by lz · 0 comments
Owner

Problem

Nexus workers are Docker containers wrapping a git worktree, and there is currently no way to give a worker access to a directory outside that worktree — in particular a directory that lives on a different host.

This blocks any project whose data lives elsewhere in the estate. Concrete driver: the myuzik media-workflow app is developed in a Nexus worker on this host, but the beets music library it reads lives on the ds9.lan Synology NAS. In production myuzik is co-located with the library (a plain compose bind-mount), but the dev worker is remote from the data, and Nexus can't bridge that today.

Confirmed environment facts

From inside a worker (10.0.0.x) probing the NAS:

ds9.lan → 10.0.0.3
port 22   OPEN   (ssh)
port 2049 OPEN   (NFS)
port 445  OPEN   (SMB/CIFS)
port 5000/5001 OPEN (DSM)
worker container has NO mount tooling (no mount.nfs / mount.cifs / sshfs)

So connectivity is not the constraint. The design question is where the mount happens and what privileges it costs the worker.

Let a worker/session declare named Docker volumes with driver_opts, and use Docker's built-in local driver with type=nfs (or type=cifs). Nexus creates the volume via the Docker API before container start; the NFS/SMB handshake happens in the worker host's Docker daemon, not in the container.

Why this is the clean primitive:

  • Worker container stays unprivileged — no SYS_ADMIN, no /dev/fuse, no mount binaries baked into the worker image.
  • It's a general capability (any worker, any export), not data-specific.
  • Cross-host by construction; the host kernel's NFS/CIFS client does the work.

Example the feature would need to emit at container-create time:

volumes:
  ds9-library:
    driver: local
    driver_opts:
      type: nfs
      o: "addr=10.0.0.3,ro,nfsvers=4"
      device: ":/volume1/music/library"
# → mounted read-only into the worker at a declared path

Alternatives considered (and why not)

  • Mount NFS/CIFS/SSHFS inside the container. Forces SYS_ADMIN (+/dev/fuse for sshfs) and mount tooling into every worker image. Strictly worse as a platform primitive. Rejected.
  • Plain host bind-mount (-v /host/path:/c). Only works when the data is already on the worker's Docker host — doesn't solve the cross-host case, which is the whole point here.
  • SSHFS is the one option that needs zero server-side config (reuses existing ssh), but the in-container caps cost rules it out as the default.

Safety / constraints

  • Default mounts to read-only. Several intended datasets are single-writer (e.g. a beets/SQLite library — a second writer corrupts it). RW should be opt-in and deliberate.
  • CIFS needs credentials → needs a secret-handling story (env/secret ref, not plaintext in a worker spec).
  • Server-side export/share permission (e.g. the DSM NFS rule allowing 10.0.0.x) is operator config, out of scope for Nexus itself.

Open questions

  • Scope of the mount declaration: per-session, or per-worker-template reused across sessions?
  • Do we surface the mount in the operator UI (like preview/artifact approvals need consent), or is it config-only?
  • Lifecycle: are these volumes torn down with the worker, or persistent/reusable across worker restarts?
## Problem Nexus workers are Docker containers wrapping a git worktree, and there is currently **no way to give a worker access to a directory outside that worktree** — in particular a directory that lives on a *different host*. This blocks any project whose data lives elsewhere in the estate. Concrete driver: the **myuzik** media-workflow app is developed in a Nexus worker on this host, but the beets music library it reads lives on the `ds9.lan` Synology NAS. In production myuzik is co-located with the library (a plain compose bind-mount), but the *dev worker is remote from the data*, and Nexus can't bridge that today. ## Confirmed environment facts From inside a worker (`10.0.0.x`) probing the NAS: ``` ds9.lan → 10.0.0.3 port 22 OPEN (ssh) port 2049 OPEN (NFS) port 445 OPEN (SMB/CIFS) port 5000/5001 OPEN (DSM) worker container has NO mount tooling (no mount.nfs / mount.cifs / sshfs) ``` So connectivity is not the constraint. The design question is *where the mount happens* and *what privileges it costs the worker*. ## Recommended design — daemon-level named volumes, unprivileged worker Let a worker/session declare **named Docker volumes with `driver_opts`**, and use Docker's built-in `local` driver with `type=nfs` (or `type=cifs`). Nexus creates the volume via the Docker API before container start; the NFS/SMB handshake happens **in the worker host's Docker daemon**, not in the container. Why this is the clean primitive: - Worker container stays **unprivileged** — no `SYS_ADMIN`, no `/dev/fuse`, no mount binaries baked into the worker image. - It's a **general** capability (any worker, any export), not data-specific. - Cross-host by construction; the host kernel's NFS/CIFS client does the work. Example the feature would need to emit at container-create time: ```yaml volumes: ds9-library: driver: local driver_opts: type: nfs o: "addr=10.0.0.3,ro,nfsvers=4" device: ":/volume1/music/library" # → mounted read-only into the worker at a declared path ``` ## Alternatives considered (and why not) - **Mount NFS/CIFS/SSHFS *inside* the container.** Forces `SYS_ADMIN` (+`/dev/fuse` for sshfs) and mount tooling into every worker image. Strictly worse as a platform primitive. Rejected. - **Plain host bind-mount** (`-v /host/path:/c`). Only works when the data is already on the worker's Docker host — doesn't solve the cross-host case, which is the whole point here. - SSHFS is the one option that needs *zero* server-side config (reuses existing ssh), but the in-container caps cost rules it out as the default. ## Safety / constraints - **Default mounts to read-only.** Several intended datasets are single-writer (e.g. a beets/SQLite library — a second writer corrupts it). RW should be opt-in and deliberate. - CIFS needs credentials → needs a secret-handling story (env/secret ref, not plaintext in a worker spec). - Server-side export/share permission (e.g. the DSM NFS rule allowing `10.0.0.x`) is operator config, out of scope for Nexus itself. ## Open questions - Scope of the mount declaration: per-session, or per-worker-template reused across sessions? - Do we surface the mount in the operator UI (like preview/artifact approvals need consent), or is it config-only? - Lifecycle: are these volumes torn down with the worker, or persistent/reusable across worker restarts?
lz closed this issue 2026-07-22 19:15:32 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lz/agent-nexus#85
No description provided.