diff --git a/README.md b/README.md index 8ca36d3..99e1088 100644 --- a/README.md +++ b/README.md @@ -149,35 +149,72 @@ docker compose up --build -d # rebuild after pulling code changes Anyone who can run `docker` commands effectively has root on the host (container volume mounts can reach the whole filesystem) — being in the `docker` group is root-equivalent. For a production server, it's worth confining this stack to a dedicated, unprivileged system user running its own **rootless Docker** daemon, instead of using a system-wide install or adding the user to the `docker` group. -Rootless Docker runs as a completely independent daemon — separate socket (`/run/user//docker.sock`) and storage (`~/.local/share/docker` vs. `/var/lib/docker`) — so it coexists fine with an existing system-wide Docker install on the same host. Just make sure `DOCKER_HOST`/`PATH` point at the rootless daemon when operating on this stack, and that the ports you publish in step 4 below aren't already in use elsewhere. +Rootless Docker runs as a completely independent daemon — separate socket and storage (`~/.local/share/docker` vs. `/var/lib/docker`) — so it coexists fine with an existing system-wide Docker install on the same host. Just make sure `DOCKER_HOST`/`PATH` point at the rootless daemon when operating on this stack, and that the ports you publish in step 4 below aren't already in use elsewhere. -**1. Create the user and enable lingering** (so its services keep running without an active login session): +**1. Create the user:** ```sh sudo adduser --disabled-password --gecos "" rss-svc -sudo loginctl enable-linger rss-svc ``` +> The "normal" rootless Docker setup runs the daemon as a **per-user systemd service** kept alive via `loginctl enable-linger`, which depends on `systemd-logind`/D-Bus. Minimal headless images (DietPi included) often disable or strip those out — and whether re-enabling them survives the distro's own update mechanism is genuinely unclear. Rather than depend on that, the steps below run rootless Docker as an ordinary **system-level** unit with `User=rss-svc` — no logind, no D-Bus, no lingering, nothing that can be reset out from under you. + **2. Install rootless Docker for that user:** ```sh -sudo apt install -y uidmap dbus-user-session -sudo machinectl shell rss-svc@ -curl -fsSL https://get.docker.com/rootless | sh +sudo apt install -y uidmap +sudo -u rss-svc -H curl -fsSL https://get.docker.com/rootless -o /tmp/install-rootless.sh +sudo -u rss-svc -H sh /tmp/install-rootless.sh ``` -Add to `~/.bashrc` (as `rss-svc`): +Add to `~/.bashrc` (as `rss-svc` — e.g. `sudo -u rss-svc -H bash`): ```sh export PATH=/home/rss-svc/bin:$PATH -export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock +export XDG_RUNTIME_DIR=/run/rss-svc-docker +export DOCKER_HOST=unix:///run/rss-svc-docker/docker.sock ``` -Enable the daemon as a persistent user service, then re-login (or `exec $SHELL`) so the exports above take effect: +Now create the system unit at `/etc/systemd/system/docker-rss-svc.service`: + +```ini +[Unit] +Description=Rootless Docker daemon (rss-svc) +After=network.target + +[Service] +User=rss-svc +Group=rss-svc +Environment=PATH=/home/rss-svc/bin:/usr/bin:/bin +Environment=XDG_RUNTIME_DIR=%t/rss-svc-docker +RuntimeDirectory=rss-svc-docker +RuntimeDirectoryMode=0700 +RuntimeDirectoryPreserve=yes +ExecStart=/home/rss-svc/bin/dockerd-rootless.sh +Restart=always +RestartSec=2 +Delegate=yes +Type=notify +NotifyAccess=all +KillMode=mixed +TasksMax=infinity +LimitNOFILE=1048576 + +[Install] +WantedBy=multi-user.target +``` + +`RuntimeDirectory=` makes systemd create `/run/rss-svc-docker` (owned by `rss-svc`, mode `0700`) on every boot — that's the `XDG_RUNTIME_DIR` rootless Docker needs, supplied without any session manager. Then enable and start it: ```sh -systemctl --user enable docker -systemctl --user start docker +sudo systemctl daemon-reload +sudo systemctl enable --now docker-rss-svc +``` + +Verify it came up (as `rss-svc`, with the `.bashrc` exports loaded): + +```sh +docker info ``` **3. Deploy the stack as `rss-svc`:**