What it is
A host-level systemd service on the media LXC that runs rclone mount against a WebDAV endpoint. The result is a host-level FUSE mount that Plex, Seanime, and Riven bind into their containers and read like any other media library.
zurg is the bridge between the upstream media API and a WebDAV server. rclone is the bridge between WebDAV and a kernel FUSE mount. Together they turn "remote files" into "directories on disk" without downloading the catalogue to the host.
Why I run it (this way, specifically)
The original design had rclone as a sibling container in the media stack — clean, self-contained, lived inside one compose file. It didn't work, for a reason I had to learn the hard way:
FUSE file-descriptor lifetime is tied to the rclone process. When the rclone container restarts, the FUSE FD it created in the kernel goes away. Consumer containers' bind mounts are kernel references to that specific FD. New rclone creates a new FUSE mount with a new FD — but the consumers are still pointing at the dead one. Every docker compose up -d that touched the rclone service broke Plex, Seanime, and Riven simultaneously.
Bind-mount propagation (rshared and friends) does not fix this. The consumer mounts were peers of the previous shared peer group, not the new one. The propagation worked perfectly; the consumers were just peers of the wrong thing.
The fix is to decouple the FUSE mount from Docker's lifecycle entirely. rclone now runs as a host systemd service. Consumer containers bind-mount the host path managed by that service, which is alive as long as the systemd service is. docker compose up -d no longer touches rclone, full stop.
How it works
zurg container (WebDAV server)
│
│ host-level rclone (systemd) FUSE-mounts the WebDAV
▼
host FUSE mount
│
│ bind-mounted into Plex / Seanime / Riven
▼
consumer containers see the media catalogue
The systemd unit has a few non-obvious requirements:
MountFlags=sharedin the[Service]section. Without it, the FUSE mount only exists inside the service's private mount namespace — invisible to Docker and to normal mount inspection. This setting cost 30+ minutes of diagnosis the first time.- An
ExecStartPrethat polls until zurg's WebDAV port is reachable. On a fresh LXC boot, rclone can race ahead of zurg's container starting and enter a tight restart loop trying to read the empty WebDAV. Type=simple(notType=notify) becauserclone mountdoesn't send sd_notify ready signals.- An explicit unmount on stop, otherwise the mount ends up in a "Transport endpoint is not connected" zombie state and the next start fails.