{ config, lib, pkgs, ... }:
with lib;
let
inherit (pkgs) plymouth nixos-icons;
cfg = config.boot.plymouth;
nixosBreezePlymouth = pkgs.plasma5Packages.breeze-plymouth.override {
logoFile = cfg.logo;
logoName = "nixos";
osName = "NixOS";
osVersion = config.system.nixos.release;
};
plymouthLogos = pkgs.runCommand "plymouth-logos" { inherit (cfg) logo; } ''
mkdir -p $out
# For themes that are compiled with PLYMOUTH_LOGO_FILE
mkdir -p $out/etc/plymouth
ln -s $logo $out/etc/plymouth/logo.png
# Logo for bgrt theme
# Note this is technically an abuse of watermark for the bgrt theme
# See: https://gitlab.freedesktop.org/plymouth/plymouth/-/issues/95#note_813768
mkdir -p $out/share/plymouth/themes/spinner
ln -s $logo $out/share/plymouth/themes/spinner/watermark.png
# Logo for spinfinity theme
# See: https://gitlab.freedesktop.org/plymouth/plymouth/-/issues/106
mkdir -p $out/share/plymouth/themes/spinfinity
ln -s $logo $out/share/plymouth/themes/spinfinity/header-image.png
'';
themesEnv = pkgs.buildEnv {
name = "plymouth-themes";
paths = [
plymouth
plymouthLogos
] ++ cfg.themePackages;
};
configFile = pkgs.writeText "plymouthd.conf" ''
[Daemon]
ShowDelay=0
DeviceTimeout=8
Theme=${cfg.theme}
${cfg.extraConfig}
'';
in
{
options = {
boot.plymouth = {
enable = mkEnableOption "Plymouth boot splash screen";
font = mkOption {
default = "${pkgs.dejavu_fonts.minimal}/share/fonts/truetype/DejaVuSans.ttf";
type = types.path;
description = ''
Font file made available for displaying text on the splash screen.
'';
};
themePackages = mkOption {
default = lib.optional (cfg.theme == "breeze") nixosBreezePlymouth;
type = types.listOf types.package;
description = ''
Extra theme packages for plymouth.
'';
};
theme = mkOption {
default = "bgrt";
type = types.str;
description = ''
Splash screen theme.
'';
};
logo = mkOption {
type = types.path;
default = "${nixos-icons}/share/icons/hicolor/128x128/apps/nix-snowflake.png";
defaultText = ''pkgs.fetchurl {
url = "https://nixos.org/logo/nixos-hires.png";
sha256 = "1ivzgd7iz0i06y36p8m5w48fd8pjqwxhdaavc0pxs7w1g7mcy5si";
}'';
description = ''
Logo which is displayed on the splash screen.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Literal string to append to configFile
and the config file generated by the plymouth module.
'';
};
};
};
config = mkIf cfg.enable {
boot.kernelParams = [ "splash" ];
# To be discoverable by systemd.
environment.systemPackages = [ plymouth ];
environment.etc."plymouth/plymouthd.conf".source = configFile;
environment.etc."plymouth/plymouthd.defaults".source = "${plymouth}/share/plymouth/plymouthd.defaults";
environment.etc."plymouth/logo.png".source = cfg.logo;
environment.etc."plymouth/themes".source = "${themesEnv}/share/plymouth/themes";
# XXX: Needed because we supply a different set of plugins in initrd.
environment.etc."plymouth/plugins".source = "${plymouth}/lib/plymouth";
systemd.packages = [ plymouth ];
systemd.services.plymouth-kexec.wantedBy = [ "kexec.target" ];
systemd.services.plymouth-halt.wantedBy = [ "halt.target" ];
systemd.services.plymouth-quit-wait.wantedBy = [ "multi-user.target" ];
systemd.services.plymouth-quit.wantedBy = [ "multi-user.target" ];
systemd.services.plymouth-poweroff.wantedBy = [ "poweroff.target" ];
systemd.services.plymouth-reboot.wantedBy = [ "reboot.target" ];
systemd.services.plymouth-read-write.wantedBy = [ "sysinit.target" ];
systemd.services.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ];
systemd.paths.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ];
boot.initrd.extraUtilsCommands = ''
copy_bin_and_libs ${plymouth}/bin/plymouth
copy_bin_and_libs ${plymouth}/bin/plymouthd
# Check if the actual requested theme is here
if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then
echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages"
exit 1
fi
moduleName="$(sed -n 's,ModuleName *= *,,p' ${themesEnv}/share/plymouth/themes/${cfg.theme}/${cfg.theme}.plymouth)"
mkdir -p $out/lib/plymouth/renderers
# module might come from a theme
cp ${themesEnv}/lib/plymouth/{text,details,label,$moduleName}.so $out/lib/plymouth
cp ${plymouth}/lib/plymouth/renderers/{drm,frame-buffer}.so $out/lib/plymouth/renderers
mkdir -p $out/share/plymouth/themes
cp ${plymouth}/share/plymouth/plymouthd.defaults $out/share/plymouth
# Copy themes into working directory for patching
mkdir themes
# Use -L to copy the directories proper, not the symlinks to them.
# Copy all themes because they're not large assets, and bgrt depends on the ImageDir of
# the spinner theme.
cp -r -L ${themesEnv}/share/plymouth/themes/* themes
# Patch out any attempted references to the theme or plymouth's themes directory
chmod -R +w themes
find themes -type f | while read file
do
sed -i "s,/nix/.*/share/plymouth/themes,$out/share/plymouth/themes,g" $file
done
# Install themes
cp -r themes/* $out/share/plymouth/themes
# Install logo
mkdir -p $out/etc/plymouth
cp -r -L ${themesEnv}/etc/plymouth $out
# Setup font
mkdir -p $out/share/fonts
cp ${cfg.font} $out/share/fonts
mkdir -p $out/etc/fonts
cat > $out/etc/fonts/fonts.conf <
$out/share/fonts
EOF
'';
boot.initrd.extraUtilsCommandsTest = ''
$out/bin/plymouthd --help >/dev/null
$out/bin/plymouth --help >/dev/null
'';
boot.initrd.extraUdevRulesCommands = ''
cp ${config.systemd.package}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out
sed -i '/loginctl/d' $out/71-seat.rules
'';
# We use `mkAfter` to ensure that LUKS password prompt would be shown earlier than the splash screen.
boot.initrd.preLVMCommands = mkAfter ''
mkdir -p /etc/plymouth
mkdir -p /run/plymouth
ln -s ${configFile} /etc/plymouth/plymouthd.conf
ln -s $extraUtils/share/plymouth/plymouthd.defaults /etc/plymouth/plymouthd.defaults
ln -s $extraUtils/share/plymouth/logo.png /etc/plymouth/logo.png
ln -s $extraUtils/share/plymouth/themes /etc/plymouth/themes
ln -s $extraUtils/lib/plymouth /etc/plymouth/plugins
ln -s $extraUtils/etc/fonts /etc/fonts
plymouthd --mode=boot --pid-file=/run/plymouth/pid --attach-to-session
plymouth show-splash
'';
boot.initrd.postMountCommands = ''
plymouth update-root-fs --new-root-dir="$targetRoot"
'';
# `mkBefore` to ensure that any custom prompts would be visible.
boot.initrd.preFailCommands = mkBefore ''
plymouth quit --wait
'';
};
}