Skip to content

Instantly share code, notes, and snippets.

@cgwalters
Created April 7, 2025 19:20
Show Gist options
  • Save cgwalters/e64539a4f83f264a21f60ded134ad3db to your computer and use it in GitHub Desktop.
Save cgwalters/e64539a4f83f264a21f60ded134ad3db to your computer and use it in GitHub Desktop.
From d392d548ce9380a68e9319a9f2445740430cfaf5 Mon Sep 17 00:00:00 2001
From: Colin Walters <[email protected]>
Date: Fri, 4 Apr 2025 19:50:46 -0400
Subject: [PATCH] wip
Signed-off-by: Colin Walters <[email protected]>
---
docs/src/building/users-and-groups.md | 78 ++++++++++++++++-----------
1 file changed, 46 insertions(+), 32 deletions(-)
diff --git a/docs/src/building/users-and-groups.md b/docs/src/building/users-and-groups.md
index 6f05f40b..92f84a12 100644
--- a/docs/src/building/users-and-groups.md
+++ b/docs/src/building/users-and-groups.md
@@ -55,31 +55,59 @@ credentials from a [CRD](https://kubernetes.io/docs/tasks/extend-kubernetes/cust
hosted in the API server. (To do things like this
it's suggested to reuse the kubelet credentials)
-### Adding users and credentials statically in the container build
+### System users and groups (added via packages, etc)
-Relative to package-oriented systems, a new ability is to inject
-users and credentials as part of a derived build:
+It is common for packages (deb/rpm/etc) to allocate system users
+or groups as part of e.g `apt|dnf install <server package>` such as Apache or MySQL,
+and this is often done by directly invoking `useradd` or `groupadd` as part
+of package pre/post installation scripts.
-```dockerfile
-RUN useradd someuser
-```
+With the`shadow-utils` implementation of `useradd` and the default glibc `files` this will
+result in changes to the traditional `/etc/passwd` and `/etc/shadow` files
+as part of the container build.
-However, it is important to understand some two very important issues
-with this as it exists today (the `shadow-utils` implementation of `useradd`)
-and the default glibc `files` backend for the traditional `/etc/passwd`
-and `/etc/shadow` files.
+#### System drift from local /etc/passwd modifications
-It is common for user/group IDs are allocated dynamically, and this can result in "drift" (see below).
+When the system is initially installed, the `/etc/passwd` in the container image will be
+applied and contain desired users.
-Further, if `/etc/passwd` is modified locally (because there is a machine-local user),
-then any added users injected via `useradd` *will not appear* on subsequent updates by default (they will be
+By default (without `etc = transient`, see below), the `/etc` directory is machine-local
+persistent state. If subsequently `/etc/passwd` is modified local to the machine
+(as is common for e.g. setting a root password) then any new changes in the container
+image (such as users from new packages) *will not appear* on subsequent updates by default (they will be
in `/usr/etc/passwd` instead - the default image version).
-These "system users" that may be created by packaging tools invoking `useradd` (e.g. `apt|dnf install httpd`) that do
-not also install a `sysusers.d` file. Currently for example, this is the case with
-the CentOS Stream 9 `httpd` package. Per below, the general solution to this
-is to avoid invoking `useradd` in container builds, and prefer one of the below
-solutions.
+The general best fix for this is to use `systemd-sysusers` instead of allocating
+a user/group at build time at all.
+
+##### Using systemd-sysusers
+
+See [systemd-sysusers](https://www.freedesktop.org/software/systemd/man/latest/systemd-sysusers.html).
+For example in your derived build:
+
+```
+COPY mycustom-user.conf /usr/lib/sysusers.d
+```
+
+A key aspect of how this works is that `sysusers` will make changes
+to the traditional `/etc/passwd` file as necessary on boot instead
+of at build time. If `/etc` is persistent, this can avoid uid/gid drift (but
+in the general case it does mean that uid/gid allocation can
+depend on how a specific machine was upgraded over time).
+
+#### System drift from dynamic allocations
+
+Any invocation of `useradd` or `groupadd` that does not allocate a *fixed* UID/GID may
+be subject to "drift" in subsequent rebuilds by default.
+
+One possibility is to explicitly force these user/group allocations into a static
+state, via `systemd-sysusers` (per above) or explicitly adding the users with
+static IDs *before* a dpkg/RPM installation script operates on it:
+
+```
+RUN <<EORUN
+set -xeuo pipefail
+useradd
#### User and group home directories and `/var`
@@ -96,20 +124,6 @@ This is significantly better than the pattern of allocating users/groups
at "package install time" (e.g. [Fedora package user/group guidelines](https://docs.fedoraproject.org/en-US/packaging-guidelines/UsersAndGroups/)) because
it avoids potential UID/GID drift (see below).
-#### Using systemd-sysusers
-
-See [systemd-sysusers](https://www.freedesktop.org/software/systemd/man/latest/systemd-sysusers.html). For example in your derived build:
-
-```
-COPY mycustom-user.conf /usr/lib/sysusers.d
-```
-
-A key aspect of how this works is that `sysusers` will make changes
-to the traditional `/etc/passwd` file as necessary on boot. If
-`/etc` is persistent, this can avoid uid/gid drift (but
-in the general case it does mean that uid/gid allocation can
-depend on how a specific machine was upgraded over time).
-
#### Using systemd JSON user records
See [JSON user records](https://systemd.io/USER_RECORD/). Unlike `sysusers`,
--
2.47.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment