{ 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 ''; }; }