Repository navigation
feat: allow running the Docker image as a non-root user - #11469
nicololuescher wants to merge 2 commits into
Conversation
The image runs as root and every runtime path assumes it: the directories under /opt/infrahub, /prom_shared and /remote are root-owned, the git settings are in root's ~/.gitconfig, and the task worker creates its own git config file in /opt/infrahub at startup. Run with another uid, the worker cannot write that file and repository operations later lack the credential helper, and the task manager cannot build its UI files inside the virtualenv. - Add an `infrahub` user (uid 1000, gid 0). - Make the runtime directories owned by group 0 with the owner's permissions, so uid 1000 or an arbitrary uid in group 0 can write them. - Write the image's git settings to the system config instead of root's. - Point PREFECT_UI_STATIC_DIRECTORY at a writable directory. - Document running as a non-root user with Docker Compose and Helm. The default user stays root, so existing deployments and volumes are unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
This is my first PR here, so the CI workflows are waiting for approval. Could a maintainer approve the runs? Happy to add a non-root run to the Docker integration tests if you'd like one in this PR. |
|
I built the image from this PR (289da9e) and ran the stack on Docker and on rootless Podman 6.1.4 (macOS, arm64). One change and one gap in the guide are suggested below, followed by three observations. Test results on the PR as it is
Suggested change: make
|
Hey @nicololuescher, thanks for your contribution. I just approved the workflows so they can run. |
Merging this PR will not alter performance1 warning
Comparing |
… $HOME - `chown -R infrahub:0` instead of `chgrp -R 0`, so uid 1000 with any gid can write, as well as any uid in group 0. - `HOME=/home/infrahub` for every user, so a uid without a passwd entry no longer gets HOME=/ (Prefect could not create ~/.prefect). - The image's git settings go back to `--global` ($HOME/.gitconfig): the task worker replaces that file with its own at startup, so `credential.helper` is set once again instead of in both the system and the global scope. - Guide: which user and group combinations work, `chown` in the upgrade step, and a Podman tab for bind mounts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @DharmaBytesX for testing this so thoroughly, on Podman too! I pushed fab33b6:
For the Podman tab I installed Podman here (4.9.3 rootless with
The details of what I tested (Docker as |
|
Thanks for the changes. I tested fab33b6 on a clean
Not tested: Kubernetes and amd64. |
Why
The Infrahub image only works as root. Its runtime directories are root-owned, the git settings are in root's
~/.gitconfig, and the task worker writes its own git config file into/opt/infrahubat startup (git.global_config_file). Clusters that requirerunAsNonRoot(Pod Security Standards "restricted", OpenShift, Kyverno or Gatekeeper policies) cannot run the server and the task worker without patching the image.What goes wrong with another uid today:
/opt/infrahub/.gitconfig, logsFailed to set git user.name …(and the other keys), keeps running, and repository operations later lack the credential helper;Failed to create V1 UI static directory … [Errno 13] Permission denied.Goal: the image can run as a non-root user without changes. Non-goal: changing the default user. It stays root, so existing deployments and volumes are untouched.
Supersedes #11468, which targeted
stable; this is a feature, so it goes todevelop.What changed
development/Dockerfile:infrahubuser: uid 1000, gid 0, home/home/infrahub./prom_shared,/remote,/opt/infrahub(and its subdirectories) and/home/infrahubare owned byinfrahub:0, and group 0 has the owner's permissions (chown -R infrahub:0+chmod -R g=u). uid 1000 with any gid can write them, and so can an arbitrary uid in group 0 as OpenShift assigns.HOME=/home/infrahubfor every user, so a uid without a passwd entry gets a writable home instead of/(Prefect creates~/.prefect).--global, now in/home/infrahub/.gitconfig, so they apply to whichever user runs the container. At startup the task worker pointsGIT_CONFIG_GLOBALat its own file and writes the same settings there, as before, socredential.helperis set once.PREFECT_UI_STATIC_DIRECTORY=/opt/infrahub/prefect-ui, a writable directory, for the task manager. prefect-helm sets its own value (/ui_buildon a scratch volume), which still takes precedence.Docs: a new guide, Run Infrahub as a non-root user (
deploy-manage/install-configure/production-deployment/non-root.mdx, Docker Compose, Podman and Helm), linked from the production deployment overview and the sidebar.What stays the same: the default user is root; no code, schema or config-model changes; volume mount points are unchanged.
How to test
Results on
develop(Docker 29.9.2, upstreamdocker-compose.yml, image from this branch), each as a fresh stack, for1000:0,1000:1000,1000700000:0and root:id -uas set in infrahub-server, task-worker and task-manager;Permission denied,Errno 13,Failed to set gitorFailed to create the Prefect homein any log, and both task workers logSet git config file to /opt/infrahub/.gitconfig;credential.helperin each task worker's effective git config (the first commit of this PR had two:systemandglobal; the released 1.11.10 image has one);/opt/infrahub/git(owned by the running uid) and resolves the commit. The demo repository then stops aterror-importbecause it references aCoreGroup(backbone_services) that only exists with its demo data loaded; this is unrelated to the user.Also checked:
0:0 644); then the guide's Step 1 command; then this image as1000:1000on the same volumes: healthy, reads the old files, writes new ones, the schema is still there.docker run --user …, every runtime path): root,1000:0,1000:1000,12345:0and1000700000:0write all of them;1000860000:1000860000writes none, as the guide says;/.venvstays root-only.podman-compose1.6.0 (Ubuntu 24.04, runc):1000:0and as12345:0: work;userns_mode: "keep-id:uid=1000"andx-podman: {in_pod: false}: work, and the files on the host belong to the host user;user: "1000:0"withoutkeep-id(the host directories appear root-owned) andkeep-id:uid=503,gid=20(Errno 13on/prom_shared, as in the review);keep-id:uid=1000,gid=0starts no container at all on this Podman/runc, whatever the image, which is why the guide does not use it;in_pod: false,podman-composerefusesuserns_mode(--userns and --pod cannot be set together).Docs:
markdownlint-cli20.23.3 and Vale 3.12.0 (the CI versions) report no issues on the new and changed pages.Why group 0
The
infrahubuser's primary group isroot(gid 0) on purpose. OpenShift runs containers with an arbitrary uid that is always a member of the root group, and Red Hat's image guidelines ask for exactly this layout: directories the image writes to "must be owned by the root group and be read/writable by that group", set withchgrp -R 0andchmod -R g=u(OpenShift: Support arbitrary user ids; the section is unchanged in the current docs source). Using one group for uid 1000 and for an arbitrary uid keeps a single supported layout. The directories are additionally owned by uid 1000, so a deployment that sets a different gid for uid 1000 (1000:1000) can write them too.Group 0 is not root privilege. The kernel treats a process as privileged only when its effective user ID is 0. Every other process "is subject to full permission checking based on the process's credentials (usually: effective UID, effective GID, and supplementary group list)" (capabilities(7)). Group 0 therefore only grants what the group permission bits of a file allow. In this image, outside the directories this PR opens up, that is:
/usr/share/man/*directories and/var/cache/debconf/tmp.cifrom the Debian base image, and the empty lock file/.venv/.lock;The virtualenv, the system binaries and
/etcstay read-only for the group. Per Red Hat's warning in the same section, the PR does not widen permissions on sensitive paths such as/etc/passwd.How to review
development/Dockerfileis the whole runtime change.Impact & rollout
HOMEis/home/infrahubfor root too, so the image's git settings move from/root/.gitconfigto/home/infrahub/.gitconfigand Prefect's home from/root/.prefectto/home/infrahub/.prefect; the task worker uses its own git config file as before.PREFECT_UI_STATIC_DIRECTORY=/opt/infrahub/prefect-ui.1000:0once (chown -R 1000:0+chmod -R g=u); the new guide covers it.Checklist
changelog/+docker-non-root.added.md, created withtowncrier create)