bin/hive-podman-preflight-ids.sh diagnoses the three host conditions rootless
Podman needs that have nothing to do with the engine version and everything to
do with how the box was prepared. Part of
#4188; implements
#4208.
It is read-only. In particular it never writes to /etc/subuid or
/etc/subgid: delegating a subordinate range is a host-administration decision
with security consequences, made by someone who knows which ranges are already
spoken for — not by a preflight running as an unprivileged user. It starts no
container, moves no storage, installs nothing, and contacts no registry.
HIVE_DEPLOY_RUNTIME=podman bin/hive-podman-preflight-ids.sh| Exit | Meaning |
|---|---|
0 |
No failing check. Warnings may still be present. |
64 |
HIVE_DEPLOY_RUNTIME names something other than docker or podman. |
78 |
At least one failing check. |
With the Docker default selected — HIVE_DEPLOY_RUNTIME unset or set to
docker — the script reports that it was skipped and exits 0 without running
a single Podman command. Docker deployments are unaffected.
Related layers: the engine, connection, root mode, and cgroup checks are #4207; SELinux, mounts, secrets, and ports are #4209 — see Podman preflight: SELinux, mounts, secrets, and ports.
Rootless containers map container UIDs onto a range the host has delegated to
the user. With no range, podman run fails with "cannot find UID/GID for
user" — after it has already created the container. With a range too small,
the container starts and then breaks on the first file owned by a UID past the
end of it, which is much harder to recognise.
The tables are read directly rather than taken from podman info. The engine
reports the mappings it resolved, which on a host using a non-file source
(SSSD, a directory service) can be correct while the files are empty — and can
be stale relative to a file edited since the engine last started. The files are
what an administrator edits and what the remediation changes, so the files are
what gets reported.
| Finding | Level |
|---|---|
A range of at least HIVE_PODMAN_MIN_SUBID_COUNT (default 65536) in both tables |
pass |
| No entry for the user in either table | fail |
| An entry smaller than the threshold | warn |
| A table that cannot be read | warn |
| Rootful engine | pass — subordinate IDs are not in the picture |
Several ranges for one user add up, so a host that delegates two 32768-wide ranges reads as 65536.
Remediation for a missing range, which an administrator runs:
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 <user>
podman system migratePick ranges that do not overlap another user's. Preflight will not choose for you and will not edit the tables.
Container storage needs a local filesystem with the ownership and extended-
attribute semantics overlayfs relies on. On NFS it does not have them: layers
fail to extract, or extract and then behave incorrectly. Operators hit this
when the home directory is on NFS, because rootless storage defaults under
$HOME.
| Filesystem | Level |
|---|---|
Local (btrfs, ext4, xfs, overlay, …) |
pass |
nfs, nfs4, cifs, smb, fuse.sshfs, 9p, ceph, glusterfs, afs, lustre, gpfs |
fail |
tmpfs, ramfs |
warn — works, but images are lost on reboot and consume RAM |
| Undeterminable | warn |
Remediation for an unsupported filesystem:
# rootless: ~/.config/containers/storage.conf rootful: /etc/containers/storage.conf
[storage]
graphroot = "/var/lib/my-local-disk/containers/storage"then reset the container store — see podman-system-reset(1) — which destroys
existing local containers and images.
A rootless container reaches the network through a helper (pasta or
slirp4netns) driven by a backend (netavark, or the retired cni). The
engine names the helper it intends to use; whether that helper is installed is
a separate question, and the answer only shows up as a container with no
network.
| Finding | Level |
|---|---|
Backend netavark |
pass |
Backend cni |
warn — retired upstream in favour of netavark |
| Helper named by the engine and present on the host | pass |
| Helper named by the engine but not installed | fail |
| Engine reports no helper | warn |
| Rootful engine | pass — no helper process is involved |
| Variable | Default | Purpose |
|---|---|---|
HIVE_PODMAN_MIN_SUBID_COUNT |
65536 |
Smallest delegated range treated as sufficient. |
HIVE_PODMAN_SUBUID_FILE |
/etc/subuid |
Table to read. Parameterised for the contract tests. |
HIVE_PODMAN_SUBGID_FILE |
/etc/subgid |
Table to read. Parameterised for the contract tests. |
bin/test_hive_podman_preflight_ids.sh (61 assertions) mocks every input — a stub podman
answering the info templates, a stub stat answering the filesystem type,
and subid tables the case writes — so the whole matrix runs on a host with no
NFS mount, no privileges, and no Podman, and never executes a container
command. PATH is the fake bin alone, which is what makes "slirp4netns is not
installed" a fact of the fixture rather than a fact of the machine running the
tests.
bash bin/test_hive_podman_preflight_ids.sh