fix(docker): make supervisord config portable across rootful + rootless keep-id#593
Merged
Merged
Conversation
…ss keep-id Removes `user=root` from the [supervisord] section in both production and development supervisord configs, and rewrites the entrypoint comment to explain why. Background: under rootless podman + userns_mode: keep-id, container PID 1 runs as the host user (UID 1000) instead of root. The previous design explicitly forced supervisord to drop privileges to root (`user=root`), which works under rootful daemons (PID 1 is root, has CAP_SETUID) but fails under rootless + keep-id — supervisord sees `user=root` in its config, tries to setuid(0), lacks CAP_SETUID, and exits with "Error: Can't drop privilege as nonroot user" (per supervisord options.py: refuses to drop privileges when not running as root). Fix: omit `user=` from the [supervisord] section so supervisord inherits PID 1's UID (root in rootful; UID 1000 in rootless + keep-id). The backend and frontend programs still drop to the unprivileged deeptutor user via per-program `user=deeptutor` — setuid(1000) works because either PID 1 is root (rootful) or PID 1 is already UID 1000 (rootless keep-id, where the setuid is a no-op). /dev/fd/1,2 ownership matches PID 1's UID in both runtimes, so supervisord's stdout/stderr writes succeed without an explicit setuid dance. Verified locally: clean heredoc indentation; supervisord config parses; both [supervisord] sections confirmed without `user=root`. Closes the rootless-podman + read-only-rootfs follow-up to PR HKUDS#577 (reported by the user after HKUDS#577 + HKUDS#586 merged).
Contributor
Author
|
@pancacake ping... |
vaskoyudha
added a commit
to vaskoyudha/deeptutor-for-programmer-fork
that referenced
this pull request
Jul 25, 2026
fix(docker): make supervisord config portable across rootful + rootless keep-id
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Removes
user=rootfrom the[supervisord]section in both production and development supervisord configs. Supervisord now inherits PID 1's UID (root under rootful daemons; UID 1000 under rootless podman +userns_mode: keep-id) instead of forcing a privilege drop.Bug
Under rootless podman +
userns_mode: keep-id, container PID 1 is the host user (UID 1000). The previoususer=rootline in the[supervisord]section makes supervisord exit at startup with:Source: supervisord's
options.pyrefuses to drop privileges when not running as root (if self.user and not os.geteuid() == 0: self.usage(...)). Rootful daemons worked because PID 1 is root withCAP_SETUID; rootless + keep-id has neither.Fix
Omit
user=from[supervisord]. Supervisord runs as PID 1's UID. Children still drop to UID 1000 via the existing per-programuser=deeptutor:/dev/fd/1,2ownership matches PID 1's UID in both runtimes, so the supervisord stdout/stderr writes work without an explicit setuid dance.Diff
- user=root(removed from both production and development
[supervisord]blocks, plus an entrypoint comment rewrite explaining the new design)Test plan
[supervisord]sections confirmed withoutuser=rootpodman build -t deeptutor:pr-test -f Dockerfile --target production .succeedspodman compose -f compose.yaml up -dbrings both services up healthyRelated
deeptutoruser; this PR fixes the supervisord config the original PR set up)BACKEND_HOST/FRONTEND_HOSTenv-configurable bindings (orthogonal; combined with this PR, rootless keep-id + host-mode works end-to-end)Discovered while
Trying to run the user's host-mode +
BACKEND_HOST=127.0.0.1+FRONTEND_HOST=127.0.0.1setup againstghcr.io/hkuds/deeptutor:latest. The image started, the entrypoint env-setup lines printed (📌 API Base URL, 📌 Auth enabled, …), then died at the supervisord gate with the message above. Diagnosed by reading the supervisord config heredoc, the entrypoint heredoc, and the supervisordoptions.pysource.