Skip to content

Commit 9b643dc

Browse files
Kabuki94claude
andcommitted
feat(mios-dev): overlay-builder.sh creates mios user + service accounts on MiOS-DEV
Closes the manifesto requirement that MiOS-DEV mirror a deployed MiOS host's container-hosting surface: "MiOS-DEV should have the mios user appended as it will be needed for this MiOS-DEV machine to hosts it's containers (mirroring the layered containers in MiOS at build time; guacamole, ollama, forgejo, cockpit etc-etc). Everything is present in the MiOS-DEV machine as a testbed/development platform FOR MiOS itself." Previously: overlay-builder.sh only rsynced files (CLI, MOTD, paths.sh, docs) onto the podman machine and explicitly skipped sysusers.d / tmpfiles.d / systemd units citing "would conflict with podman-machine init." That left MiOS-DEV without the mios user + service accounts + /var/lib/<service>/ dirs the MiOS Quadlets need to run rootless. Result: MiOS-DEV could only HOST the canonical MiOS file overlay; it could not actually RUN the MiOS Quadlet stack the way a deployed host does. Operator can't `systemctl --user enable mios-forge.service` if the mios-forge user / /var/lib/mios-forge/ doesn't exist. This commit adds three integrated steps to overlay-builder.sh, all keeping the original "don't touch podman-machine vendor files" rule: 1. SYSUSERS (etc-layer override) Drops the MiOS sysusers.d files into /etc/sysusers.d/ instead of /usr/lib/sysusers.d/ (where podman-machine-os's vendor file 20-podman-machine.conf lives). systemd-sysusers materializes: - mios login user (uid 1000) with group memberships: wheel, libvirt, kvm, video, render, input, dialout, docker - mios-virt 800 - mios-guacamole 810, mios-guacd 811, mios-postgres 812 - mios-pxe-hub 813, mios-crowdsec 814 - mios-ollama 815, mios-forge 816 - cockpit (auto-allocate) - kvm/video/render/libvirt/input/dialout/docker groups Idempotent: existing entries with matching UID/GID are left alone. 2. TMPFILES (etc-layer override) Same /etc/tmpfiles.d/ pattern. systemd-tmpfiles --create materializes /var/lib/mios-{ai,forge,forge-runner,ollama,pxe-hub,guacamole,infra}/ with the right owner so the Quadlet bind-mounts have somewhere to land on the podman-machine FS. 3. /var/home/mios + subuid/subgid + loginctl enable-linger mios Establishes the same /var/home/<user> convention FCOS/atomic-desktops use; seeds from /etc/skel; appends 'mios:524288:65536' to /etc/subuid and /etc/subgid for rootless container userns mapping; enables linger so systemd --user services (the Quadlets) start at boot without an active login session. Net effect for the operator ─────────────────────────── - After `sudo bash automation/overlay-builder.sh /path/to/MiOS-repo` (or the auto-invocation from build-mios.ps1's Invoke-MachineSSH path), MiOS-DEV is a CONTAINER-HOSTING substrate. The operator can: sudo -u mios podman info systemctl --user --machine=mios@ start mios-forge.service systemctl --user --machine=mios@ start ollama.service - MiOS-DEV becomes the genuine "testbed/development platform FOR MiOS itself" the manifesto describes -- it runs the same Quadlets the built MiOS image will run, so an operator iterating on Quadlet changes can validate against MiOS-DEV before triggering the OCI build pipeline. - Idempotent: re-runs of overlay-builder.sh re-apply identically; no state loss, no UID drift. What this commit explicitly does NOT do (still off-limits per the podman-machine-init compatibility rule): - Does not install systemd unit files into /usr/lib/systemd/system - Does not install kargs.d (kernel cmdline is the podman-machine kernel's, not MiOS bootc's) - Does not install SELinux modules (WSL substrate is permissive) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 52e6a50 commit 9b643dc

1 file changed

Lines changed: 131 additions & 14 deletions

File tree

automation/overlay-builder.sh

Lines changed: 131 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,50 @@
11
#!/usr/bin/env bash
2-
# 'MiOS' BUILDER overlay -- makes the build-host WSL2 podman machine
3-
# look and feel like a Live 'MiOS' environment without breaking the
4-
# podman-machine OS plumbing underneath.
2+
# 'MiOS' MiOS-DEV overlay -- makes the build-host podman machine look and
3+
# feel like a Live 'MiOS' environment so it can host the same Quadlets the
4+
# deployed image runs (manifesto: "MiOS-DEV is the source upon what MiOS
5+
# itself is based upon ... mios user appended for hosting the layered
6+
# containers; guacamole, ollama, forgejo, cockpit etc-etc").
57
#
6-
# Run inside the BUILDER, from the MiOS repo working tree:
8+
# Run inside MiOS-DEV, from the MiOS repo working tree:
79
# sudo bash automation/overlay-builder.sh /path/to/MiOS-repo
810
#
9-
# What it does (idempotent, --ignore-existing throughout):
11+
# What it does (idempotent throughout):
1012
# * rsync usr/share/mios/, usr/lib/mios/, usr/libexec/mios/, usr/bin/mios
1113
# onto / so the canonical 'MiOS' CLI / docs / paths.sh / motd binary all
1214
# exist at the expected paths
1315
# * rsync usr/lib/profile.d/mios-*.sh + etc/profile.d/mios-*.sh so login
1416
# shells get the 'MiOS' MOTD + WSLg env exports
1517
# * rsync /etc/skel skeleton from the repo if present
1618
# * rsync etc/mios/ (vendor host config templates)
17-
# * NOT touched: systemd units, drop-ins, tmpfiles.d, sysusers.d, kargs.d,
18-
# SELinux modules -- these would conflict with the podman-machine init
19-
# and must only land in the bootc image proper.
19+
# * COPY MiOS sysusers.d into /etc/sysusers.d/ + run systemd-sysusers,
20+
# creating the 'mios' login user (uid 1000) and the service accounts
21+
# (mios-ollama, mios-forge, mios-guacamole, mios-pxe-hub,
22+
# mios-crowdsec, mios-guacd, mios-postgres -- 810-829 range; mios-virt
23+
# 800; cockpit). Drops into /etc (host-layer override) instead of
24+
# /usr/lib (vendor layer) to avoid colliding with podman-machine-os's
25+
# own /usr/lib/sysusers.d/20-podman-machine.conf.
26+
# * COPY MiOS tmpfiles.d into /etc/tmpfiles.d/ + run systemd-tmpfiles
27+
# --create so /var/lib/<service>/ dirs the Quadlets bind-mount exist
28+
# with the right ownership.
29+
# * Establish /var/home/mios (FCOS atomic-desktops home convention)
30+
# seeded from /etc/skel.
31+
# * Append /etc/subuid + /etc/subgid entries so the mios user can run
32+
# rootless podman containers (which is how MiOS-DEV mirrors a deployed
33+
# MiOS host's Quadlet hosting).
2034
#
21-
# After running, opening any new shell in BUILDER shows the 'MiOS' MOTD and
22-
# `mios` is on PATH.
35+
# What it explicitly does NOT do (would conflict with podman-machine init):
36+
# * Install systemd unit files (the podman-machine OS owns /usr/lib/
37+
# systemd/system; Quadlets land in /etc/containers/systemd/ which is
38+
# separate)
39+
# * Install kargs.d (kernel command line is the podman-machine kernel,
40+
# not bootc; MiOS kargs only matter on a deployed bootc host)
41+
# * Install SELinux policy modules (MiOS-DEV runs in WSL where SELinux
42+
# is permissive at best)
43+
#
44+
# After running, opening any new shell in MiOS-DEV shows the 'MiOS' MOTD,
45+
# `mios` is on PATH, and `id mios` returns uid 1000. `loginctl enable-linger
46+
# mios` then enables rootless container hosting so the operator can
47+
# `systemctl --user start mios-forge.service` or any other MiOS Quadlet.
2348

2449
set -euo pipefail
2550

@@ -82,12 +107,104 @@ _rsync_in "etc/mios/" "/etc/mios/"
82107
find /usr/libexec/mios -type f -exec chmod +x {} + 2>/dev/null || true
83108
chmod +x /usr/bin/mios 2>/dev/null || true
84109

85-
# Re-run tmpfiles for /usr/lib/mios subdirs (logs, scratch). These are
86-
# declared in usr/lib/tmpfiles.d/mios.conf in the bootc image; on BUILDER
87-
# we just create them imperatively because the tmpfiles.d file isn't
88-
# overlaid (would clash with podman-machine).
110+
# ── sysusers: create the mios login user + service accounts so MiOS-DEV
111+
# can host the same Quadlets as a deployed MiOS host. Drop into
112+
# /etc/sysusers.d/ (host-layer override) instead of /usr/lib/sysusers.d/
113+
# (vendor layer) so we coexist with podman-machine-os's vendor file
114+
# /usr/lib/sysusers.d/20-podman-machine.conf without overwriting it.
115+
echo "[overlay-builder] Setting up MiOS sysusers (etc-layer override)..."
116+
install -d -m 0755 /etc/sysusers.d
117+
_sysusers_added=0
118+
for sf in usr/lib/sysusers.d/10-mios.conf \
119+
usr/lib/sysusers.d/30-mios-tmpfiles-prereq.conf \
120+
usr/lib/sysusers.d/50-mios.conf \
121+
usr/lib/sysusers.d/50-mios-ai.conf \
122+
usr/lib/sysusers.d/50-mios-gpu.conf \
123+
usr/lib/sysusers.d/50-mios-services.conf \
124+
; do
125+
[[ -f "$sf" ]] || continue
126+
install -m 0644 "$sf" "/etc/sysusers.d/$(basename "$sf")"
127+
echo "[overlay-builder] /etc/sysusers.d/$(basename "$sf")"
128+
_sysusers_added=$((_sysusers_added + 1))
129+
done
130+
if (( _sysusers_added > 0 )); then
131+
# systemd-sysusers materializes the entries into /etc/passwd + /etc/group.
132+
# Idempotent: existing users with matching UID/GID are left alone.
133+
systemd-sysusers 2>&1 | sed 's/^/[overlay-builder] sysusers: /' || true
134+
fi
135+
136+
# ── tmpfiles: create /var/lib/<service>/ dirs the Quadlets bind-mount.
137+
# Same /etc-layer override pattern. mios-services.conf, mios-ollama.conf,
138+
# mios-forge.conf etc. declare per-service writable state directories that
139+
# the matching Quadlets expect to find pre-created with the right owner.
140+
echo "[overlay-builder] Setting up MiOS tmpfiles.d (etc-layer override)..."
141+
install -d -m 0755 /etc/tmpfiles.d
142+
_tmpfiles_added=0
143+
for tf in usr/lib/tmpfiles.d/mios.conf \
144+
usr/lib/tmpfiles.d/mios-services.conf \
145+
usr/lib/tmpfiles.d/mios-ollama.conf \
146+
usr/lib/tmpfiles.d/mios-forge.conf \
147+
usr/lib/tmpfiles.d/mios-forge-runner.conf \
148+
usr/lib/tmpfiles.d/mios-ai.conf \
149+
usr/lib/tmpfiles.d/mios-pxe-hub.conf \
150+
usr/lib/tmpfiles.d/mios-guacamole.conf \
151+
usr/lib/tmpfiles.d/mios-infra.conf \
152+
usr/lib/tmpfiles.d/mios-user.conf \
153+
; do
154+
[[ -f "$tf" ]] || continue
155+
install -m 0644 "$tf" "/etc/tmpfiles.d/$(basename "$tf")"
156+
echo "[overlay-builder] /etc/tmpfiles.d/$(basename "$tf")"
157+
_tmpfiles_added=$((_tmpfiles_added + 1))
158+
done
89159
install -d -m 0755 /usr/lib/mios/logs
90160
install -d -m 0755 /var/lib/mios
161+
if (( _tmpfiles_added > 0 )); then
162+
# --create materializes declared paths; --remove would clean up paths
163+
# marked for removal (we skip that to be conservative -- the Quadlet
164+
# mounts that touch /var should never see "missing" as their state).
165+
systemd-tmpfiles --create 2>&1 | sed 's/^/[overlay-builder] tmpfiles: /' || true
166+
fi
167+
168+
# ── /var/home/mios -- FCOS / atomic-desktops home convention
169+
# (the deployed MiOS image uses /var/home/mios as the operator's $HOME so
170+
# /etc 3-way merge doesn't have to deal with home-dir state). Establish
171+
# the same on MiOS-DEV so configs match across substrates.
172+
install -d -m 0755 /var/home
173+
if id mios >/dev/null 2>&1; then
174+
install -d -m 0755 -o mios -g mios /var/home/mios 2>/dev/null || \
175+
install -d -m 0755 /var/home/mios
176+
if [[ -d /etc/skel ]] && [[ ! -e /var/home/mios/.bashrc ]]; then
177+
rsync -aH --ignore-existing /etc/skel/ /var/home/mios/ 2>/dev/null || true
178+
chown -R mios:mios /var/home/mios 2>/dev/null || true
179+
echo "[overlay-builder] /var/home/mios seeded from /etc/skel"
180+
fi
181+
fi
182+
183+
# ── subuid / subgid for rootless podman as the mios user.
184+
# Rootless containers need an unprivileged uid/gid range available for
185+
# user-namespace mapping. Standard convention: 524288 + 65536 (one
186+
# 64K-uid range, starting outside the host's regular uid space). The
187+
# mios-services accounts (810-829) don't need their own subuid ranges
188+
# because they're nologin shell-less daemons that do not run rootless
189+
# containers themselves.
190+
if ! grep -q '^mios:' /etc/subuid 2>/dev/null; then
191+
echo 'mios:524288:65536' >> /etc/subuid
192+
echo "[overlay-builder] /etc/subuid: mios:524288:65536 added"
193+
fi
194+
if ! grep -q '^mios:' /etc/subgid 2>/dev/null; then
195+
echo 'mios:524288:65536' >> /etc/subgid
196+
echo "[overlay-builder] /etc/subgid: mios:524288:65536 added"
197+
fi
198+
199+
# ── Linger so the mios user can run systemd --user services (the
200+
# Quadlets) without a logged-in session. Required for `systemctl --user
201+
# enable mios-forge.service` etc. to actually start at boot.
202+
if command -v loginctl >/dev/null 2>&1 && id mios >/dev/null 2>&1; then
203+
loginctl enable-linger mios 2>/dev/null || true
204+
echo "[overlay-builder] loginctl enable-linger mios"
205+
fi
91206

92207
echo "[overlay-builder] Overlay complete."
93208
echo "[overlay-builder] Open a fresh shell to see the 'MiOS' MOTD."
209+
echo "[overlay-builder] Verify mios user: id mios; subuid grep mios /etc/subuid"
210+
echo "[overlay-builder] Container-host probe: sudo -u mios podman info"

0 commit comments

Comments
 (0)