[PR #65] [MERGED] feat(containers): honor Config.User as lxc.init.uid/gid #64

Closed
opened 2026-10-15 12:51:44 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/games-on-whales/LXC2Docker/pull/65
Author: @JBailes
Created: 6/6/2026
Status: ✅ Merged
Merged: 6/6/2026
Merged by: @JBailes

Base: main ← Head: fix/honor-container-user


📝 Commits (1)

  • 04ee142 feat(containers): honor Config.User as lxc.init.uid/gid

📊 Changes

3 files changed (+190 additions, -0 deletions)

View changed files

📝 internal/api/containers.go (+7 -0)
📝 internal/lxc/config.go (+127 -0)
📝 internal/lxc/config_test.go (+56 -0)

📄 Description

Problem

The daemon stores and echoes a container's User (Config.User) but never applies it — every container's PID 1 runs as root regardless of the requested user. Anything depending on the requested uid/gid silently runs as root.

This surfaced running a postgres container on a volume whose backing store forces a non-root owner (a SmoothNAS smoothfs tier that forces uid 1000): the stock postgres entrypoint drops to the postgres user (uid 999), but the data dir is owned by the forced uid → initdb: could not access directory ... Permission denied. Setting --user 1000:1000 had no effect because the daemon ignored it (verified: a container created with User=1000:1000 still ran as uid 0).

Fix

Translate the requested user spec (uid, uid:gid, user, or user:group) into lxc.init.uid / lxc.init.gid when generating both the LXC and PVE container configs. Names are resolved against the container rootfs's /etc/passwd and /etc/group (matching how Docker resolves an image's USER); a user given without a group inherits its passwd primary GID. An empty or unresolvable spec leaves PID 1 as root.

Scope: only an explicitly requested User is applied. The image's own USER is deliberately not auto-applied — the daemon has always run containers as root, and silently honoring image USER would change the runtime identity of every existing image (breaking those whose volumes were provisioned for root). Callers wanting the image USER can read it from inspect and pass it explicitly.

Test

TestInitUserConfigItems covers numeric (uid, uid:gid), name resolution (user → uid + primary gid), mixed name/numeric, numeric-uid-not-in-passwd (gid omitted → LXC defaults to 0), and unresolvable specs. Full internal/lxc + internal/api suites pass; go vet clean.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/games-on-whales/LXC2Docker/pull/65 **Author:** [@JBailes](https://github.com/JBailes) **Created:** 6/6/2026 **Status:** ✅ Merged **Merged:** 6/6/2026 **Merged by:** [@JBailes](https://github.com/JBailes) **Base:** `main` ← **Head:** `fix/honor-container-user` --- ### 📝 Commits (1) - [`04ee142`](https://github.com/games-on-whales/LXC2Docker/commit/04ee142dd925d14b2e8c40b2683b571a73505c92) feat(containers): honor Config.User as lxc.init.uid/gid ### 📊 Changes **3 files changed** (+190 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `internal/api/containers.go` (+7 -0) 📝 `internal/lxc/config.go` (+127 -0) 📝 `internal/lxc/config_test.go` (+56 -0) </details> ### 📄 Description ## Problem The daemon stores and echoes a container's `User` (Config.User) but never **applies** it — every container's PID 1 runs as root regardless of the requested user. Anything depending on the requested uid/gid silently runs as root. This surfaced running a **postgres** container on a volume whose backing store forces a non-root owner (a SmoothNAS smoothfs tier that forces uid 1000): the stock postgres entrypoint drops to the `postgres` user (uid 999), but the data dir is owned by the forced uid → `initdb: could not access directory ... Permission denied`. Setting `--user 1000:1000` had no effect because the daemon ignored it (verified: a container created with `User=1000:1000` still ran as uid 0). ## Fix Translate the requested user spec (`uid`, `uid:gid`, `user`, or `user:group`) into **`lxc.init.uid` / `lxc.init.gid`** when generating both the LXC and PVE container configs. Names are resolved against the container rootfs's `/etc/passwd` and `/etc/group` (matching how Docker resolves an image's USER); a user given without a group inherits its passwd primary GID. An empty or unresolvable spec leaves PID 1 as root. **Scope:** only an *explicitly requested* `User` is applied. The image's own `USER` is deliberately **not** auto-applied — the daemon has always run containers as root, and silently honoring image USER would change the runtime identity of every existing image (breaking those whose volumes were provisioned for root). Callers wanting the image USER can read it from inspect and pass it explicitly. ## Test `TestInitUserConfigItems` covers numeric (`uid`, `uid:gid`), name resolution (user → uid + primary gid), mixed name/numeric, numeric-uid-not-in-passwd (gid omitted → LXC defaults to 0), and unresolvable specs. Full `internal/lxc` + `internal/api` suites pass; `go vet` clean. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/LXC2Docker#64
No description provided.