max / alloy
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
7 files changed,
+259 insertions,
-21 deletions
| @@ -2245,25 +2245,6 @@ | |||
| 2245 | 2245 | fi; \ | |
| 2246 | 2246 | echo "langs: /usr/share/locale grew $((grown / 1048576)) MB over the base" | |
| 2247 | 2247 | ||
| 2248 | - | # ===================================================================== | |
| 2249 | - | # System user for greetd. greetd drops privileges to this account | |
| 2250 | - | # before spawning tuigreet; without it greetd exits with | |
| 2251 | - | # "configured default session user 'greeter' not found". Fedora | |
| 2252 | - | # bootc's minimal user database does not include it. | |
| 2253 | - | # ===================================================================== | |
| 2254 | - | # | |
| 2255 | - | # Client-only. `useradd` would succeed on either profile, which is exactly | |
| 2256 | - | # why this needs a branch rather than being left alone: a system account for | |
| 2257 | - | # a greeter that is not installed is the sort of thing nobody notices and | |
| 2258 | - | # nobody can explain later. The `else` asserts it is really absent. | |
| 2259 | - | RUN if [ "$PROFILE" = client ]; then \ | |
| 2260 | - | useradd -M -r -s /sbin/nologin greeter; \ | |
| 2261 | - | else \ | |
| 2262 | - | getent passwd greeter >/dev/null \ | |
| 2263 | - | && { echo "profile=server has a greeter account but no greeter" >&2; exit 1; }; \ | |
| 2264 | - | echo "greeter: no account on this profile"; \ | |
| 2265 | - | fi | |
| 2266 | - | ||
| 2267 | 2248 | # ===================================================================== | |
| 2268 | 2249 | # Register nushell as a legitimate login shell. | |
| 2269 | 2250 | # ===================================================================== | |
| @@ -2335,6 +2316,62 @@ | |||
| 2335 | 2316 | COPY usr/ /usr/ | |
| 2336 | 2317 | COPY --from=rust-build /staged-skel/ / | |
| 2337 | 2318 | ||
| 2319 | + | # ===================================================================== | |
| 2320 | + | # What has to reach a machine that UPGRADED into this image, not only | |
| 2321 | + | # one installed from it: the /var declarations and the greeter account. | |
| 2322 | + | # ===================================================================== | |
| 2323 | + | # Both halves are here for one reason. /var and /etc are per-machine on a bootc | |
| 2324 | + | # system: `bootc install` copies the image's copies into the stateroot, and an | |
| 2325 | + | # upgrade re-syncs /usr and leaves both alone. So anything that exists only | |
| 2326 | + | # because a package's %post or a `useradd` ran during a build lands on fresh | |
| 2327 | + | # installs and on nothing else. systemd-tmpfiles and systemd-sysusers run at | |
| 2328 | + | # every boot, and a declaration each is what closes the gap. `bootc container | |
| 2329 | + | # lint` is what names the two cases, under `var-tmpfiles` and `sysusers`, and | |
| 2330 | + | # since 2026-08-26 the lint at the bottom of this file is fatal — so a package | |
| 2331 | + | # added later that drops a new /var directory or a new account stops the build | |
| 2332 | + | # here rather than warning into a log nobody reads. | |
| 2333 | + | # | |
| 2334 | + | # The account is created here rather than up beside the greetd install because | |
| 2335 | + | # its definition arrives with `COPY usr/ /usr/` just above, and nothing between | |
| 2336 | + | # the two needs it. It was a bare `useradd` until 2026-08-26; the sysusers file | |
| 2337 | + | # is now the single definition, and this runs it. | |
| 2338 | + | # | |
| 2339 | + | # The client half is a separate file because it cannot merely be inert on | |
| 2340 | + | # `server`: `d /var/lib/geoclue 0755 geoclue geoclue` and the three greetd | |
| 2341 | + | # lines name users that arrive with packages this profile does not install, and | |
| 2342 | + | # systemd-tmpfiles fails a line whose user does not resolve. So it is deleted | |
| 2343 | + | # rather than shipped and ignored, and the `else` proves the deletion happened. | |
| 2344 | + | # | |
| 2345 | + | # --dry-run --create on each file is the check that matters, and it is the same | |
| 2346 | + | # one the flatpak rule gets further down: a tmpfiles line with a typo in it is | |
| 2347 | + | # accepted by every build step except the boot it silently does nothing on. | |
| 2348 | + | RUN set -eux; \ | |
| 2349 | + | greeter=/usr/lib/sysusers.d/50-alloy-greeter.conf; \ | |
| 2350 | + | common=/usr/lib/tmpfiles.d/50-alloy-var.conf; \ | |
| 2351 | + | client=/usr/lib/tmpfiles.d/50-alloy-var-client.conf; \ | |
| 2352 | + | [ -f "$common" ] || { echo "$common did not land; every /var directory in this image is undeclared" >&2; exit 1; }; \ | |
| 2353 | + | systemd-tmpfiles --dry-run --create "$common" >/dev/null \ | |
| 2354 | + | || { echo "systemd-tmpfiles rejects $common" >&2; exit 1; }; \ | |
| 2355 | + | if [ "$PROFILE" = client ]; then \ | |
| 2356 | + | [ -f "$client" ] || { echo "$client did not land" >&2; exit 1; }; \ | |
| 2357 | + | systemd-tmpfiles --dry-run --create "$client" >/dev/null \ | |
| 2358 | + | || { echo "systemd-tmpfiles rejects $client" >&2; exit 1; }; \ | |
| 2359 | + | grep -q '^L .*/xdg-desktop-portal\.service .*/dev/null$' "$client" \ | |
| 2360 | + | || { echo "$client no longer masks the greeter's xdg-desktop-portal; greetd's %post is the only thing writing that symlink and it runs on the build host" >&2; exit 1; }; \ | |
| 2361 | + | [ -f "$greeter" ] || { echo "$greeter did not land; the greeter account has no definition" >&2; exit 1; }; \ | |
| 2362 | + | systemd-sysusers "$greeter"; \ | |
| 2363 | + | getent passwd greeter >/dev/null \ | |
| 2364 | + | || { echo "systemd-sysusers accepted $greeter but created no greeter account; greetd would exit with 'configured default session user not found'" >&2; exit 1; }; \ | |
| 2365 | + | else \ | |
| 2366 | + | rm -f "$client" "$greeter"; \ | |
| 2367 | + | [ ! -e "$client" ] && [ ! -e "$greeter" ] \ | |
| 2368 | + | || { echo "profile=server still carries the client /var declarations or the greeter account definition, neither of which has packages here" >&2; exit 1; }; \ | |
| 2369 | + | getent passwd greeter >/dev/null \ | |
| 2370 | + | && { echo "profile=server has a greeter account but no greeter" >&2; exit 1; }; \ | |
| 2371 | + | echo "greeter: no account on this profile"; \ | |
| 2372 | + | fi; \ | |
| 2373 | + | echo "var: tmpfiles declarations present and accepted for profile=$PROFILE" | |
| 2374 | + | ||
| 2338 | 2375 | # ===================================================================== | |
| 2339 | 2376 | # The Firefox configuration is what pays for picking Firefox. | |
| 2340 | 2377 | # ===================================================================== | |
| @@ -4214,8 +4251,85 @@ | |||
| 4214 | 4251 | echo "fonts: no font stack on this profile, which is what a headless machine draws with"; \ | |
| 4215 | 4252 | fi | |
| 4216 | 4253 | ||
| 4254 | + | # ===================================================================== | |
| 4255 | + | # The build host's leavings, deleted rather than declared. | |
| 4256 | + | # ===================================================================== | |
| 4257 | + | # Everything above declares the /var content this image is supposed to carry. | |
| 4258 | + | # This is the other half: content that is in the image only because dnf, | |
| 4259 | + | # semodule, ldconfig and authselect ran on the machine that built it, and that | |
| 4260 | + | # no running machine needs. | |
| 4261 | + | # | |
| 4262 | + | # It is last on purpose. Anything below it that reached for dnf would put the | |
| 4263 | + | # caches back after the sweep, and the lint that follows is the thing that | |
| 4264 | + | # would say so. | |
| 4265 | + | # | |
| 4266 | + | # What each line is, and why deleting it is safe rather than merely quiet: | |
| 4267 | + | # | |
| 4268 | + | # /run and /tmp are tmpfs at boot, so their content is unreachable on a | |
| 4269 | + | # running machine no matter what. What is in there is dnf's lock directory | |
| 4270 | + | # and the intermediate .cil files semodule writes while compiling policy. | |
| 4271 | + | # | |
| 4272 | + | # /var/log/dnf5.log* is the BUILD HOST's package log: which packages were | |
| 4273 | + | # installed when, from which repo URLs. It is not this machine's history and | |
| 4274 | + | # nothing reads it, but it does ship to every install. | |
| 4275 | + | # | |
| 4276 | + | # /var/lib/dnf and /var/cache/libdnf5 are dnf's own state and cache. The | |
| 4277 | + | # `countme` stamps in there are upstream's install-counting telemetry, and | |
| 4278 | + | # the pubring copies are repo keys dnf re-fetches. MEASURED 2026-08-26: dnf | |
| 4279 | + | # answers a query with both trees deleted and recreates what it needs. | |
| 4280 | + | # | |
| 4281 | + | # /var/cache/ldconfig/aux-cache and the appstream .xb catalogs are caches | |
| 4282 | + | # with a generator behind each of them. | |
| 4283 | + | # | |
| 4284 | + | # /var/lib/authselect/checksum records the state of the PAM files authselect | |
| 4285 | + | # generated, so it can notice a hand edit. MEASURED 2026-08-26: with it gone | |
| 4286 | + | # `authselect check` still answers "Current configuration is valid" and | |
| 4287 | + | # `authselect current` still names the profile and all four features. | |
| 4288 | + | # | |
| 4289 | + | # WHAT THIS DOES NOT DO is make the pulled image smaller. These files were | |
| 4290 | + | # written in layers far above, and deleting them here writes a whiteout rather | |
| 4291 | + | # than reclaiming the bytes. What it changes is the filesystem `bootc install` | |
| 4292 | + | # writes to a disk, which is the one an installed machine actually carries. | |
| 4293 | + | # Reclaiming the registry bytes would mean cleaning inside the layer that made | |
| 4294 | + | # the mess, which is a different and much larger change to this file. | |
| 4295 | + | # | |
| 4296 | + | # The sweep of /run tolerates failures, and the lint below is why that is not a | |
| 4297 | + | # hole. podman bind-mounts the host's /run/systemd/resolve/stub-resolv.conf into | |
| 4298 | + | # the build container to give it DNS, so a plain `rm -rf /run/*` dies on a busy | |
| 4299 | + | # mount and takes the build with it. Those mounts are not image content — they | |
| 4300 | + | # are absent from the lint's own reading of a built image — so the right move is | |
| 4301 | + | # to sweep what can be swept and let `bootc container lint --fatal-warnings` | |
| 4302 | + | # below be the assertion about what is left. It reads the finished filesystem, | |
| 4303 | + | # which is the thing being claimed about, rather than this loop's exit status. | |
| 4304 | + | RUN set -eux; \ | |
| 4305 | + | find /run /tmp -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null || true; \ | |
| 4306 | + | rm -f /var/log/dnf5.log*; \ | |
| 4307 | + | rm -rf /var/lib/dnf /var/cache/libdnf5; \ | |
| 4308 | + | rm -f /var/cache/ldconfig/aux-cache; \ | |
| 4309 | + | rm -f /var/cache/swcatalog/cache/*.xb; \ | |
| 4310 | + | rm -f /var/lib/authselect/checksum; \ | |
| 4311 | + | authselect check >/dev/null \ | |
| 4312 | + | || { echo "authselect stopped validating once its checksum was removed; keep the file and declare it instead" >&2; exit 1; }; \ | |
| 4313 | + | echo "sweep: build-host caches, logs and /run content removed" | |
| 4314 | + | ||
| 4217 | 4315 | # ===================================================================== | |
| 4218 | 4316 | # bootc validation — fails the build if the image isn't a valid | |
| 4219 | 4317 | # bootable container. | |
| 4220 | 4318 | # ===================================================================== | |
| 4221 | - | RUN bootc container lint | |
| 4319 | + | # --fatal-warnings since 2026-08-26. Without it this was the one validation | |
| 4320 | + | # step in a file otherwise dense with hard assertions that could not fail the | |
| 4321 | + | # build, and it spent an unknown number of builds reporting three warnings on | |
| 4322 | + | # `server` and four on `client` that nothing read. That is the same shape of | |
| 4323 | + | # problem as a sweep grid nobody opens: a detector whose output reaches no one | |
| 4324 | + | # is not a control. | |
| 4325 | + | # | |
| 4326 | + | # --no-truncate because the default prints five entries per lint and then a | |
| 4327 | + | # count, which on a failing build is the half of the list you need hidden | |
| 4328 | + | # behind the half you have. The output is only read when it has already | |
| 4329 | + | # stopped the build, so there is nothing to keep short. | |
| 4330 | + | # | |
| 4331 | + | # --skip is deliberately not used. It exists, and gating with the known | |
| 4332 | + | # warnings suppressed was the cheaper option; it was refused because a skip | |
| 4333 | + | # list is a second place to record which warnings are acceptable, and it goes | |
| 4334 | + | # stale silently the moment the reason for one of them is fixed. | |
| 4335 | + | RUN bootc container lint --fatal-warnings --no-truncate |
| @@ -104,7 +104,7 @@ | |||
| 104 | 104 | 6. **Rendered tree:** everything in the image that carries a color is not in the repo as a finished file. `templates/` holds it with the palette left as tokens, and `skelgen` renders it against the two Akari themes into a second tree that mirrors `/` the same way the config tree does. Themed skeleton files render twice: the light one lands at `etc/skel/<rel>`, the dark one at `usr/share/alloy/skel-night/<rel>`, and `alloy theme apply` copies whichever the user's mode file names into `$HOME` at login. The build asserts the two trees are a bijection and that they do not overlap the repo's own `etc/skel`, because a themed file that quietly loses its dark render leaves a light sway border on a dark desktop and nothing else. | |
| 105 | 105 | 7. **Systemd presets:** which services are enabled by default (syncthing off by default, gammastep off until enrolled, alloy-hinged conditionally on FW12, etc.). | |
| 106 | 106 | 8. **Branding:** os-release, plymouth splash. The build stamps the image's build number into os-release here; see [Version fields](#version-fields). It stamps the profile in the same way, rewriting the committed `VARIANT="<profile>"` and `VARIANT_ID=<profile>` placeholders to `Client`/`client` or `Server`/`server`, and failing if either placeholder survives. Only the profile: the tag variants (`firewall-server`, `usbgate-server`) are names chosen by whoever runs the build, and the Containerfile is never told which one it is making. | |
| 107 | - | 9. **Validation:** `bootc container lint` runs at build. | |
| 107 | + | 9. **Validation:** `bootc container lint --fatal-warnings` runs at build. Fatal since 2026-08-26: it was advisory before that, and spent an unknown number of builds reporting three warnings on `server` and four on `client` that nothing read. Two of its checks constrain what the image may carry, and both are about the upgrade path rather than about tidiness. `var-tmpfiles` wants every directory in `/var` declared in a `tmpfiles.d` file, and `sysusers` wants every account in `/etc/passwd` declared in a `sysusers.d` file, because `/var` and `/etc` are per-machine: `bootc install` copies the image's copies into the stateroot, while an upgrade re-syncs `/usr` and leaves both alone. Content that exists only because a package's `%post` or a `useradd` ran during a build therefore reaches a fresh install and never reaches a machine that upgrades into the image. Alloy's declarations are `usr/lib/tmpfiles.d/50-alloy-var.conf` (plus a `-client` half deleted on `server`, whose lines name users only that profile has) and `usr/lib/sysusers.d/50-alloy-greeter.conf`. **A package added here that drops a new `/var` directory or a new account fails the build until it gets a line in one of them.** The build host's own leavings are deleted rather than declared, in the sweep immediately above the lint: dnf's caches and log, the ldconfig aux-cache, the appstream catalogs, authselect's checksum, and everything under `/run`. | |
| 108 | 108 | ||
| 109 | 109 | **A package added here gets a line in `crates/alloy/credits.toml`.** The installer's last screen names the projects Alloy ships and their licenses, off a hand-curated manifest rather than a generated closure, so nothing adds itself. The manifest is embedded in the console binary with `include_str!`, which means the page cannot go missing on installer media or a read-only deployment and also means a manifest edit needs a rebuild. Its own header says which license to record: for anything packaged out of Rust or Go, Fedora's `%{LICENSE}` is the whole vendored closure rather than the project's own terms, so read upstream's LICENSE for those and use `rpm -q --qf '%{LICENSE}'` only for the C packages. | |
| 110 | 110 |
| @@ -1,5 +1,25 @@ | |||
| 1 | 1 | %global debug_package %{nil} | |
| 2 | 2 | ||
| 3 | + | # Timestamps here are a constant, not the clock. | |
| 4 | + | # | |
| 5 | + | # Fedora sets %%source_date_epoch_from_changelog by default and this spec had no | |
| 6 | + | # %%changelog, so SOURCE_DATE_EPOCH went unset and every build stamped BUILDTIME | |
| 7 | + | # and every file mtime with the second rpmbuild happened to run. MEASURED | |
| 8 | + | # 2026-08-26: two builds of the same binary, seconds apart, produced RPMs that | |
| 9 | + | # differ. rpmbuild said so on every build too, in a warning nobody read. | |
| 10 | + | # | |
| 11 | + | # It defeats what build/rpm is for downstream. A rebuild lockfile that pins the | |
| 12 | + | # config exactly (GoingsOn 6e1f433a) would still hand back a different RPM every | |
| 13 | + | # run, and a mirrored layered set (7ee5a694) could not tell a re-cut package from | |
| 14 | + | # a changed one. | |
| 15 | + | # | |
| 16 | + | # So the %%changelog at the bottom carries a date, not a history. The date is | |
| 17 | + | # fixed on purpose and nothing reads the entry as a log: what changed between two | |
| 18 | + | # builds is the version, and the version is in the file name. The clamp that | |
| 19 | + | # applies it to file mtimes is already Fedora's default; using it for BUILDTIME | |
| 20 | + | # as well is not, hence the line below. | |
| 21 | + | %global use_source_date_epoch_as_buildtime 1 | |
| 22 | + | ||
| 3 | 23 | Name: alloy | |
| 4 | 24 | Version: %{alloy_version} | |
| 5 | 25 | Release: 1%{?dist} | |
| @@ -53,3 +73,6 @@ | |||
| 53 | 73 | %{_bindir}/alloy | |
| 54 | 74 | ||
| 55 | 75 | %changelog | |
| 76 | + | * Wed Aug 26 2026 Make Creative <info@makenot.work> - 0-0 | |
| 77 | + | - The date above is the package epoch, fixed so two builds of one binary | |
| 78 | + | produce one RPM. See the header; this is not a change log. |
| @@ -1,5 +1,25 @@ | |||
| 1 | 1 | %global debug_package %{nil} | |
| 2 | 2 | ||
| 3 | + | # Timestamps here are a constant, not the clock. | |
| 4 | + | # | |
| 5 | + | # Fedora sets %%source_date_epoch_from_changelog by default and this spec had no | |
| 6 | + | # %%changelog, so SOURCE_DATE_EPOCH went unset and every build stamped BUILDTIME | |
| 7 | + | # and every file mtime with the second rpmbuild happened to run. MEASURED | |
| 8 | + | # 2026-08-26: two builds of the same binary, seconds apart, produced RPMs that | |
| 9 | + | # differ. rpmbuild said so on every build too, in a warning nobody read. | |
| 10 | + | # | |
| 11 | + | # It defeats what build/rpm is for downstream. A rebuild lockfile that pins the | |
| 12 | + | # config exactly (GoingsOn 6e1f433a) would still hand back a different RPM every | |
| 13 | + | # run, and a mirrored layered set (7ee5a694) could not tell a re-cut package from | |
| 14 | + | # a changed one. | |
| 15 | + | # | |
| 16 | + | # So the %%changelog at the bottom carries a date, not a history. The date is | |
| 17 | + | # fixed on purpose and nothing reads the entry as a log: what changed between two | |
| 18 | + | # builds is the version, and the version is in the file name. The clamp that | |
| 19 | + | # applies it to file mtimes is already Fedora's default; using it for BUILDTIME | |
| 20 | + | # as well is not, hence the line below. | |
| 21 | + | %global use_source_date_epoch_as_buildtime 1 | |
| 22 | + | ||
| 3 | 23 | Name: shop | |
| 4 | 24 | Version: %{shop_version} | |
| 5 | 25 | Release: 1%{?dist} | |
| @@ -68,3 +88,6 @@ | |||
| 68 | 88 | %{_bindir}/shop | |
| 69 | 89 | ||
| 70 | 90 | %changelog | |
| 91 | + | * Wed Aug 26 2026 Make Creative <info@makenot.work> - 0-0 | |
| 92 | + | - The date above is the package epoch, fixed so two builds of one binary | |
| 93 | + | produce one RPM. See the header; this is not a change log. |
| @@ -1,0 +1,18 @@ | |||
| 1 | + | # The account greetd drops to before spawning tuigreet. Without it greetd exits | |
| 2 | + | # with "configured default session user 'greeter' not found", and Fedora bootc's | |
| 3 | + | # minimal user database does not carry one. | |
| 4 | + | # | |
| 5 | + | # A sysusers file rather than the `useradd` this used to be, and the difference | |
| 6 | + | # is the upgrade path rather than tidiness. /etc is per-machine on a bootc | |
| 7 | + | # system: an account baked into the image's /etc/passwd reaches a fresh install | |
| 8 | + | # and never reaches a machine that upgrades into the image carrying it. Fedora | |
| 9 | + | # runs systemd-sysusers on every boot, so a declaration here lands on both. | |
| 10 | + | # `bootc container lint` is what names the difference, under `sysusers`. | |
| 11 | + | # | |
| 12 | + | # Client-only. It is deleted on `server`, which has no greeter to drop to, and | |
| 13 | + | # the Containerfile asserts the account is absent there. | |
| 14 | + | # | |
| 15 | + | # Home is `-`, which resolves to /, because there is no /home/greeter and there | |
| 16 | + | # should not be: greetd keeps the greeter's own state under /var/lib/greetd, | |
| 17 | + | # which the greetd package owns. | |
| 18 | + | u greeter - "greetd greeter" - /sbin/nologin |
| @@ -1,0 +1,37 @@ | |||
| 1 | + | # The client profile's half of 50-alloy-var.conf. See that file for why /var | |
| 2 | + | # content needs declaring at all. | |
| 3 | + | # | |
| 4 | + | # Deleted on `server`, and it has to be rather than merely being harmless there: | |
| 5 | + | # the geoclue and greetd lines name users that arrive with their packages, and | |
| 6 | + | # systemd-tmpfiles fails a line whose user does not resolve. The Containerfile | |
| 7 | + | # removes it in the profile block and asserts it is gone. | |
| 8 | + | # | |
| 9 | + | # Modes and owners are the ones the packages themselves created, read back off a | |
| 10 | + | # built image rather than chosen here. A line that widens one of them would be a | |
| 11 | + | # permissions change nobody asked for, wearing a lint fix as a disguise. | |
| 12 | + | # | |
| 13 | + | # The symlink at the bottom is not a directory and not ours: greetd's %post | |
| 14 | + | # writes it to mask xdg-desktop-portal for the greeter's session, so a login | |
| 15 | + | # screen does not start a portal. It is the one entry here with behaviour behind | |
| 16 | + | # it, which is exactly why it cannot be left to a scriptlet that only ever runs | |
| 17 | + | # on the machine that built the image. | |
| 18 | + | # | |
| 19 | + | #Type Path Mode User Group Age Argument | |
| 20 | + | d /var/cache/libX11 0755 root root - - | |
| 21 | + | d /var/cache/libX11/compose 0755 root root - - | |
| 22 | + | d /var/cache/swcatalog 0755 root root - - | |
| 23 | + | d /var/cache/swcatalog/cache 0755 root root - - | |
| 24 | + | d /var/cache/swcatalog/gv 0755 root root - - | |
| 25 | + | d /var/cache/swcatalog/icons 0755 root root - - | |
| 26 | + | d /var/cache/swcatalog/xml 0755 root root - - | |
| 27 | + | d /var/lib/color 0755 root root - - | |
| 28 | + | d /var/lib/color/icc 0755 root root - - | |
| 29 | + | d /var/lib/flatpak 0755 root root - - | |
| 30 | + | d /var/lib/fprint 0700 root root - - | |
| 31 | + | d /var/lib/geoclue 0755 geoclue geoclue - - | |
| 32 | + | d /var/lib/greetd/.config 0755 greetd greetd - - | |
| 33 | + | d /var/lib/greetd/.config/systemd 0755 greetd greetd - - | |
| 34 | + | d /var/lib/greetd/.config/systemd/user 0755 greetd greetd - - | |
| 35 | + | d /var/log/speech-dispatcher 0700 root root - - | |
| 36 | + | d /var/spool/cups 0710 root root - - | |
| 37 | + | L /var/lib/greetd/.config/systemd/user/xdg-desktop-portal.service - - - - /dev/null |
| @@ -1,0 +1,23 @@ | |||
| 1 | + | # Directories in /var that packages create at install time and then rely on at | |
| 2 | + | # runtime, declared so they exist on a machine that upgraded into this image | |
| 3 | + | # rather than only on one installed from it. | |
| 4 | + | # | |
| 5 | + | # /var is per-machine on a bootc system. `bootc install` copies the image's /var | |
| 6 | + | # into the stateroot, so a fresh install gets everything; an upgrade re-syncs | |
| 7 | + | # /usr and leaves /var alone, so a directory that arrives in a later image never | |
| 8 | + | # appears on a machine already running. Anything under /var that has to be there | |
| 9 | + | # needs a tmpfiles line, and `bootc container lint` fails the build on one that | |
| 10 | + | # does not have one (`var-tmpfiles`). | |
| 11 | + | # | |
| 12 | + | # This file is the part both profiles need. The client's own set is in | |
| 13 | + | # 50-alloy-var-client.conf, which is deleted on `server` — several of its lines | |
| 14 | + | # name users that only exist alongside the packages that create them, and | |
| 15 | + | # systemd-tmpfiles errors at boot on a line naming a user that is not there. | |
| 16 | + | # | |
| 17 | + | # What is NOT here: dnf's caches, /var/log/dnf5.log, the ldconfig aux-cache and | |
| 18 | + | # authselect's checksum. Those are the build host's leavings rather than | |
| 19 | + | # anything a running machine needs, and the Containerfile deletes them before | |
| 20 | + | # the lint instead of declaring them. | |
| 21 | + | # | |
| 22 | + | #Type Path Mode User Group Age Argument | |
| 23 | + | d /var/cache/tailscale 0755 root root - - |