distros/skills/bootc-config/SKILL.md
Bootc system configuration: tty1 autologin, graphical target, pipewire/wireplumber enablement, and the systemd-user supervisord autostart unit that brings up supervisord-managed desktop services on bootc. Canonical home for any bootc-side boot wiring. Use when working with bootc images, autologin, systemd graphical target, or the supervisord-under-systemd autostart pattern.
npx skillsauth add overthinkos/overthink-plugins bootc-configInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Property | Value |
|----------|-------|
| Install files | task:, candy.yml |
sway-systemd (RPM) -- Sway systemd integration/etc/systemd/system/[email protected]/autologin.conf so the user account logs in automatically on the first virtual console.systemctl set-default graphical.target so the OS boots into the desktop, not multi-user.pipewire.socket and wireplumber.service for every user session via systemctl --global enable./etc/systemd/user/supervisord.service + systemctl --global enable supervisord.service.user — writes the sentinel file /var/lib/systemd/linger/user so the user's systemd instance starts at boot even without an interactive login.Each systemctl cmd is suffixed || true because the directives succeed on live systems but may fail harmlessly during offline bootc assembly.
The selkies-desktop and openclaw metalayers compose supervisord service: fragments for every desktop program (labwc, chrome, swaync, waybar, selkies, traefik, …). On container images that's fine: ENTRYPOINT=supervisord starts the whole tree as PID 1. On bootc images, systemd is PID 1 and nothing wraps supervisord by default — the desktop would never come up.
This layer ships the missing wiring: a systemd user unit at /etc/systemd/user/supervisord.service that runs /usr/bin/supervisord -c /etc/supervisord.conf -n, guarded by ConditionFileIsExecutable=/usr/bin/supervisord + ConditionPathExists=/etc/supervisord.conf so it no-ops on bootc images that don't use supervisord. It's systemctl --global enabled so every user session started via tty1 autologin brings the desktop tier up.
StandardOutput=file:/tmp/supervisord-stdout.log is load-bearingThe unit declares:
StandardOutput=file:/tmp/supervisord-stdout.log
StandardError=file:/tmp/supervisord-stderr.log
These aren't for log collection — they're required for supervisord's per-program stdout_logfile=/dev/fd/1 entries to resolve. Under a systemd user service without this redirect, fd 1 points at the journal pipe; per-program dispatchers call open("/dev/fd/1") on that pipe and get ENXIO: No such device or address, causing every program to enter FATAL with the message unknown error making dispatchers for <name>: ENXIO. Redirecting stdout to a real file makes /dev/fd/1 openable. Also: the supervisord header template was separately changed from logfile=/dev/stdout to logfile=/tmp/supervisord.log for the same reason — see /charly-infrastructure:supervisord.
loginctl enable-linger user is the usual way to enable linger, but it requires a running logind — which the offline bootc builder doesn't have. The equivalent effect is writing an empty file at /var/lib/systemd/linger/user. Existence alone enables linger at boot. This layer uses a mkdir: + cmd: touch pair to plant the sentinel (empty content doesn't pass write: validation).
# box.yml — this layer is included transitively via bootc-base
my-bootc-image:
base: "quay.io/fedora/fedora-bootc:43"
bootc: true
distro: ["fedora:43", fedora] # external bases need this — see /charly-image:image
layers:
- bootc-base
- <other desktop layers>
Part of the /charly-distros:bootc-base composition layer. Used transitively in every bootc image:
/charly-distros:bazzite — canonical worked example (exercises every piece of the supervisord + tty1 autologin + graphical target flow end-to-end)/charly-distros:aurora/charly-distros:bootc-base -- composition that includes this layer + sshd + qemu-guest-agent/charly-coder:sshd -- SSH server (also in bootc-base; NOPASSWD-sudo test handles the dual USER=root/1000 context)/charly-distros:qemu-guest-agent -- QEMU agent (also in bootc-base)/charly-infrastructure:supervisord -- the init system that this layer wires into systemd on bootc/charly-selkies:selkies-desktop-layer -- the 19-sublayer desktop metalayer that this autostart brings up/charly-vm:vm -- VM lifecycle + the /dev:/dev mount requirement for bootc install to-disk/charly-image:image -- the external-base distro: requirement/charly-build:generate -- the empty-systemd-services-stage fix that makes bootc images with only packaged systemd units (unified service: entries using use_packaged:) build cleanly/charly-eval:eval -- dual-mode USER context authoring gotcha (test #11)/charly-image:layer -- layer authoring referenceUse when the user asks about:
StandardOutput=file: trick)/var/lib/systemd/linger/user sentinel-file patternunknown error making dispatchers for <name>: ENXIO in supervisord logstools
Use when authoring or modifying a charly PLUGIN — a candy with a `plugin:` block that contributes Providers (verbs/kinds/deploy-targets/steps/builders/commands), its own CUE schema, builtin (compiled-in) or external (out-of-tree git repo). Covers the unified Provider model, the per-plugin CUE-schema contract (single source → Go params for dev + schema-over-Describe RPC for runtime), the SDK, and the loader.
tools
The CUE data-validation / configuration CLI (cue), pinned to v0.16.1. Use when working with the cue candy, installing the cue binary into a box or onto a target:local dev host, or running the offline schema-vendoring pipeline that feeds charly's egress validation.
tools
CUE EGRESS validation — validating (and, where it adds value, generating) the config files charly WRITES to a system BEFORE the bytes hit disk. MUST be invoked before working on charly/egress.go, the vendored schemas under candy/plugin-egress/egress-schemas/vendor/, the ValidateEgress / registerVendoredEgressKind path, the offline `task cue:vendor` pipeline, or adding an egress schema for any written artifact (cloud-init, k8s manifests, traefik routes, runtime config, install ledger, systemd/quadlet units, ssh_config, libvirt XML).
tools
Kubernetes cluster-probe declarative check verb — the `kube:` check verb (nodes, pods, ingress, storage class, addon health, apply/delete, and arbitrary resource GETs) served out-of-process by the candy/plugin-kube plugin (vendored client-go; no external kubectl required).