Skip to content

PUID PGID support - #236

Open
ChoosenMEME wants to merge 3 commits into
Suwayomi:mainfrom
ChoosenMEME:puid-pgid-support
Open

PUID PGID support#236
ChoosenMEME wants to merge 3 commits into
Suwayomi:mainfrom
ChoosenMEME:puid-pgid-support

Conversation

@ChoosenMEME

Copy link
Copy Markdown

Closes #218

What

Adds PUID/PGID environment variables (default 1000:1000) to run the server as an arbitrary UID/GID, following the pattern established by the LinuxServer.io images:

  • The container now starts as root; a new docker_entrypoint.sh remaps the suwayomi user to the requested IDs, fixes the ownership of /home/suwayomi (most importantly the mounted data directory) and then drops privileges before starting the server — the server itself never runs as root.
  • Privileges are dropped with setpriv (util-linux), the equivalent of gosu/su-exec that is already present in the image, so no new dependency is added.
  • Only files with a mismatched owner are chowned, so startups with large libraries stay fast; with the default PUID/PGID nothing is modified at all, which keeps read-only containers working.

Compatibility

  • No env vars set → behaves as before, the server runs as 1000:1000.
  • docker run --user / compose user: / k8s runAsUser → the entrypoint detects it is not root, skips the remapping and execs the server directly as that user (the previous behavior, now documented and explicitly supported; a warning is logged if PUID/PGID are also set).
  • Kubernetes pods with runAsNonRoot: true but no runAsUser will now fail admission since the image no longer declares USER suwayomi; such setups need an explicit runAsUser: 1000.
  • The entrypoint is installed to /usr/local/bin (root-owned, 755) rather than the world-writable /home/suwayomi, since it is executed as root.

Testing

Built the image locally and verified:

  • PUID=1050/PGID=1051: java process runs as 1050:1051 (audio/video supplementary groups kept via --init-groups), data dir including pre-existing root-owned files chowned, API responds
  • switching PUID between runs on the same volume (1050 → 2000 → back to default 1000): all files re-owned each time, existing database reused, server healthy
  • --user 1234:1234 with PUID also set: server runs as 1234, PUID ignored with a warning
  • high UID (101000), PUID=0 (explicitly run as root), invalid input (PUID=abc → clear error message, exit code 1)
  • docker restart idempotency

The container CI workflow now also passes PUID/PGID=1050 in the env-var test and asserts that server.conf ends up owned by the remapped UID/GID (it is created after the privilege drop, so its owner proves which user the server ran as).

The image hardcoded the suwayomi user (UID/GID 1000:1000) with
ownership baked in at build time, so data directories owned by a
different host user only worked through the undocumented and fragile
"--user" override.

Following the pattern established by the LinuxServer.io images, the
container now starts as root: a new entrypoint remaps the suwayomi
user to the requested PUID/PGID (default 1000:1000, so existing
setups are unaffected), hands files with a mismatched owner in
/home/suwayomi over to it and then drops privileges before starting
the server. Privileges are dropped via setpriv, util-linux'
equivalent of gosu/su-exec, which avoids adding a dependency.

Only files with a wrong owner are touched so that startups with big
libraries stay fast, and with the default PUID/PGID nothing is
modified at all, which keeps read-only containers working.

Overriding the container user (eg docker run --user) behaves like
before: the entrypoint detects that it is not root, skips the
remapping and runs the server directly as that user. The entrypoint
lives in /usr/local/bin instead of the world-writable /home/suwayomi
since it is executed as root.
Add the new variables to the environment variable table, explain the
root-start/privilege-drop mechanics and how forcing the container
user from the outside (--user, user:, runAsUser) disables them, and
show commented examples in the compose files and the Podman quadlet
template, including how PUID/PGID interact with UserNS=keep-id for
host users whose UID is not 1000.
Pass PUID/PGID=1050 in the environment variable test and verify that
server.conf ends up owned by the remapped UID/GID. Since server.conf
is created by the server after the privilege drop, its owner proves
the server actually ran as the requested user.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FR] Support custom PUID/PGID for flexible user mapping

1 participant