Context
Some OCI rocks (e.g. indico) have Pebble service definitions that specify user: _daemon_. Pebble needs root to setuid to that user when starting services. Other rocks (e.g. fastapi-demo) are "rootless" — their services have no user: field, so pebble and services all run as the same user.
jjx needs to decide how to handle this: always run containers as root, or try to detect which rocks need root and only escalate for those.
What's possible and not possible
- Docker + host user: works for rootless rocks. Fails for rootful rocks because pebble can't
setuid to _daemon_ without root, and can't write to the rock's _daemon_-owned filesystem.
- Docker + root (
0:0): works for both rootless and rootful rocks. Pebble can setuid and write anywhere. But: files created in bind-mounted volumes (.jjx/) are owned by root, and the host user can't clean them up with rm -rf .jjx.
- Podman rootless +
0:0: works for both. Container root maps to the host user, so all files are host-owned — no cleanup problem.
- Podman rootless + host user: doesn't work at all — the host UID is outside the container's subuid range, so podman rejects it.
chmod 777 on .jjx/: would let the host user delete root-owned files inside it on Docker, making always-root viable. The directory doesn't have the sticky bit, so this is safe.
Key considerations
- Simplicity: always-root means one code path. Detecting which rocks need root requires inspecting pebble layers and maintaining a conditional — more moving parts.
- Podman compatibility: podman rootless requires
0:0 anyway, so always-root aligns with future podman support without needing a runtime-conditional user resolution.
- Docker cleanup: the only downside of always-root on Docker is root-owned files in
.jjx/. A chmod 777 on the directory solves this completely.
- Security: running as root inside a Docker container is a minor security consideration, but jjx already runs containers with
--network bridge and no special capabilities — the attack surface is the same as any container-based dev tool.
- Real Juju fidelity: real Juju runs workload pods as root and pebble starts services as the specified user. Always-root matches this exactly.
Recommendation
Always run as root (0:0). It simplifies the code (one path, no detection logic), matches real Juju's behavior, and is required for podman rootless anyway. The only cost — root-owned files in .jjx/ on Docker — is solved with a single chmod 777 on the .jjx/ directory.
Context
Some OCI rocks (e.g. indico) have Pebble service definitions that specify
user: _daemon_. Pebble needs root tosetuidto that user when starting services. Other rocks (e.g. fastapi-demo) are "rootless" — their services have nouser:field, so pebble and services all run as the same user.jjx needs to decide how to handle this: always run containers as root, or try to detect which rocks need root and only escalate for those.
What's possible and not possible
setuidto_daemon_without root, and can't write to the rock's_daemon_-owned filesystem.0:0): works for both rootless and rootful rocks. Pebble cansetuidand write anywhere. But: files created in bind-mounted volumes (.jjx/) are owned by root, and the host user can't clean them up withrm -rf .jjx.0:0: works for both. Container root maps to the host user, so all files are host-owned — no cleanup problem.chmod 777on.jjx/: would let the host user delete root-owned files inside it on Docker, making always-root viable. The directory doesn't have the sticky bit, so this is safe.Key considerations
0:0anyway, so always-root aligns with future podman support without needing a runtime-conditional user resolution..jjx/. Achmod 777on the directory solves this completely.--network bridgeand no special capabilities — the attack surface is the same as any container-based dev tool.Recommendation
Always run as root (
0:0). It simplifies the code (one path, no detection logic), matches real Juju's behavior, and is required for podman rootless anyway. The only cost — root-owned files in.jjx/on Docker — is solved with a singlechmod 777on the.jjx/directory.