splash: the boot menu's look and the Plymouth splash, from one palette
Edit on GitHubModules: modules/nixos/core/boot-appearance.nix
and the package pkgs/boot-theme. Both are OFF on the host
until the migration turns them on.
One palette, by name
my.boot.theme is a preset NAME from modules/home/desktop/palette-presets.nix, the desktop's own
file (rule 11), defaulting to its default (Tokyo Night). Not the home-manager my.theme.palette:
the boot screens are the SYSTEM's, and reaching into one user's home-manager config from a NixOS
module has no precedent here. The price is that a base16: theme on the desktop does not reach
the boot; a curated preset does.
boot-theme renders everything at build time, nothing at boot:
| Output | What it is |
|---|---|
limine/wallpaper.png | 1920x1080 in bg, the official NixOS logo (from nixos-icons) at 144 px, centered in the top third |
share/plymouth/themes/nixos-minimal/ | a script theme: the logo, three dots, the per-mode title and the log pane |
288 KiB in all (22/10/2026). The logo comes from the pinned nixpkgs, so nothing is fetched.
The Limine menu
Limine draws its own text menu; the theme only gives it a canvas and colors. It centers the entry
tree on its own (common/menu.c), so the logo sits in the band between the top line and the tree,
and the terminal background is fully transparent (term_background ff<bg>) so its cells never
paint over the logo. The built-in font at 2x2, since 1x is unreadable at 1080p. If the firmware
refuses 1920x1080, wallpaper_style: centered with the same bg as backdrop keeps the color
around it. No custom font: the built-in one always loads, which is what "usable if the wallpaper
or font fails" asks.
Plymouth
A script theme (pkgs/boot-theme/nixos-minimal.script, 22/10/2026), after a first version on the
two-step plugin. Both draw the logo, three dots that brighten in turn (a loop, indeterminate on
purpose, since boot has no honest percentage) and Shutting down or Restarting in those modes.
The script adds what two-step cannot: a pane with the last 8 lines systemd logged, asked for so
a boot or a shutdown can be read without leaving the splash.
-
Where the lines come from. systemd tells Plymouth only which units FINISHED starting (
manager_send_unit_plymouth, systemd 260): no failures, no stops, nothing at shutdown. A pane fed by that alone would show only good news, soplymouth-log(boot) andplymouth-log-shutdown(reboot, poweroff) runjournalctl --follow _PID=1and pass each line throughplymouth display-message. Bookkeeping is dropped: skipped conditions, CPU accounting, clean exits, signals. -
Colors by the verb: Started, Finished, Reached, Mounted in green with a check; Stopping, Stopped in yellow; Starting, Mounting dimmed; anything with
failed/Failed/errorin red; a unit name (foo.service) in the accent. Older lines fade, long ones end in an ellipsis. The font is the UI family's fixed-width cut (JetBrainsMonoNerdFontMono), so the columns line up. -
Centering: the script plugin centers the smaller head inside the larger one (
script-lib-sprite.c), so everything is placed from the center and fits the 1080 p LG too. -
How each feeder ends. At boot, when the splash goes
display-messagestops answering and the loop exits 0. At shutdown, the final SIGTERM ends it. Neither orders anything after itself. -
Three traps vm-limine caught, kept so they stay caught:
Conflicts=plymouth-quitmade systemd drop the quit job and the boot wait forever; withpipefail, the closed pipe at the normal end marked the unit failed; andConditionPathExists=/run/plymouth/pidskipped the shutdown feeder, since the shutdown splash keeps no pid file there (the script pings instead). -
Seen on the B580 on 25/10/2026: the pane showed under the logo at boot and at shutdown, both feeders ending clean (
plymouth-logResult=success). -
Not proven: the red line on screen. In the drill the failing unit's line comes in the last half second before poweroff, after the last frame; the color rule is the same code as the green and yellow lines that were seen.
-
Handoff:
plymouth-quitends the splash, and only then does LightDM start (display-manageris orderedAfter=plymouth-quit.service). Without that order both ran at once: on 26/10/2026 LightDM sentdeactivatewhile plymouthd was already quitting, plymouthd died with SIGSEGV inon_deactivate(ply_device_manager_pause) andplymouth-start.servicewas left failed. The desktop came up anyway; it was a race, seen once in five boots. With the order, LightDM finds no splash and leaves Plymouth alone. nixpkgs'lightdm.nixstill startsplymouth-quitas the display manager'sonFailure. -
The GPU:
xeis already in the initrd for early KMS (intel-arc-b580), so the splash draws on the real driver, not onsimpledrm. Seen on the B580 on 22/10/2026, at boot and at poweroff, with no black screen (stage C1 of the migration). -
Two monitors: the splash shows on both, but the LG's rotation is Hyprland's and does not exist yet at boot, so on the LG it is sideways. Expected, and only for those seconds.
-
Diagnostics stay: no
quietwas added,loglevel=4stays, Escape switches to the text console. To boot without it: Limine's editor is off under Secure Boot, so it is an older generation from the menu or a rebuild withmy.boot.splash.enableoff. -
No added delay: nothing waits for the animation; it is shown for exactly as long as boot or shutdown takes.