# Display contact information during boot. https://discourse.nixos.org/t/display-contact-info-in-nixos-boot-stage-1/38118/4 { config, pkgs, lib, ... }: let # TODO: Once `lib.string.trim` is available in stable nix, remove the below. # Copied from https://github.com/NixOS/nixpkgs/blob/5633bcff0c6162b9e4b5f1264264611e950c8ec7/lib/strings.nix#L362-L434 trim = trimWith { start = true; end = true; }; trimWith = { start ? false, end ? false, }: let # Define our own whitespace character class instead of using # `[:space:]`, which is not well-defined. chars = " \t\r\n"; # To match up until trailing whitespace, we need to capture a # group that ends with a non-whitespace character. regex = if start && end then "[${chars}]*(.*[^${chars}])[${chars}]*" else if start then "[${chars}]*(.*)" else if end then "(.*[^${chars}])[${chars}]*" else "(.*)"; in s: let # If the string was empty or entirely whitespace, # then the regex may not match and `res` will be `null`. res = lib.match regex s; in lib.optionalString (res != null) (lib.head res); contact_name = "Daniel Langbein"; # The file `phone-number` contains only one line with our phone number, e.g. +49 0173 ... # Be aware that the phone number will be written to the nix store in plaintext! # TODO: strip the read string (no tailing newlines) contact_phone = trim (builtins.readFile ../secrets/phone-number); contact_mail = "daniel@systemli.org"; # https://wiki.nixos.org/wiki/Shell_Scripts contact-info-str = pkgs.stdenv.mkDerivation rec { name = "Contact information string"; # disable unpackPhase etc phases = "buildPhase"; builder = pkgs.writeShellScript "builder.sh" '' set -eu -o pipefail echo -e "If found, please contact:\n${contact_name}\n${contact_phone}\n${contact_mail}" \ | cowsay --bold --aurora -f dragon > $out ''; nativeBuildInputs = with pkgs; [ coreutils neo-cowsay ]; PATH = lib.makeBinPath nativeBuildInputs; }; contact-info-img = pkgs.stdenv.mkDerivation rec{ name = "Contact information image"; nativeBuildInputs = with pkgs; [ imagemagick liberation_ttf ]; phases = "installPhase"; # magick add label: https://imagemagick.org/Usage/text/#label # magick font list: magick -list font | grep Font installPhase = '' set -eu -o pipefail mkdir -p $out #export XDG_CACHE_HOME="$out/.cache" magick -background black -fill 'hsb(120, 255, 63.75)' -font ${pkgs.liberation_ttf}/share/fonts/truetype/LiberationSans-Regular.ttf -pointsize 92 'label:If found, please contact:\n${contact_name}\n${contact_phone}\n${contact_mail}' $out/img.png ''; }; in { # We found no non-graphical solution to print the contact info with systemd initrd. # Workaround: Run a dummy service that has the contact info as service name ... # # Alternative: Use Plymouth for a graphical boot splash screen. # TODO: Only on graphical installations! # # To see the splash screen. https://wiki.archlinux.org/title/Plymouth#Installation #boot.kernelParams = [ "splash" ]; # boot.plymouth = lib.mkIf (config.boot.initrd.systemd.enable) { enable = true; #theme = "breeze"; logo = "${contact-info-img}/img.png"; }; # Print contact info as text during boot. boot.initrd.preDeviceCommands = lib.mkIf (! config.boot.initrd.systemd.enable) '' cat <<'EOF' ${builtins.readFile contact-info-str} EOF ''; # TODO: cleanup # # TODO: systemd service output is not displayed during boot. onyl [info] service xxx started # # # https://github.com/oxalica/nixpkgs/blob/3562c1d5c6ff868924fe95ba7b51344f3c141311/nixos/modules/config/console.nix#L158 # boot.initrd.systemd.storePaths = [ # "${config.boot.initrd.systemd.package.kbd}/bin/some-foo-package" # ]; # # boot.initrd.systemd.services."If-found-please-send-email-to___${mail}___" = lib.mkIf (config.boot.initrd.systemd.enable) { # description = "Display part of the contact information inside service name"; # wantedBy = [ "initrd.target" ]; # after = [ "systemd-vconsole-setup.service" ]; # before = [ "cryptsetup-pre.target" "local-fs-pre.target" ]; # unitConfig.DefaultDependencies = "no"; # serviceConfig.Type = "oneshot"; # script = '' # wall TESTING-SOMETHING-OUT # ''; # }; # # # Soruces: # # - https://discourse.nixos.org/t/zfs-rollback-not-working-using-boot-initrd-systemd/37195/3 # # - https://github.com/cole-h/nixos-config/blob/26f77d5d24e5859a1bb690cff63371d1ebf7d707/hosts/nixos/scadrial/modules/boot/remote-unlock.nix#L57-L69 # boot.initrd.systemd.services."contact-info" = lib.mkIf (config.boot.initrd.systemd.enable) { # description = "Display contact information"; # wantedBy = [ # "initrd.target" # ]; # after = [ # "systemd-vconsole-setup.service" # ]; # before = [ # # Flowchart displaying the ordering of targets: https://www.freedesktop.org/software/systemd/man/latest/bootup.html # # cryptsetup-pre.target and local-fs-pre.target don't depend on each other but are instead orthogonal # # # This passive target unit may be pulled in by services that want to run before any encrypted block device is set up. # # https://www.freedesktop.org/software/systemd/man/systemd.special#cryptsetup-pre.target # "cryptsetup-pre.target" # # # This target unit is automatically ordered before all local mount points marked with auto. # # https://www.freedesktop.org/software/systemd/man/systemd.special#local-fs-pre.target # "local-fs-pre.target" # # # If the root device can be mounted at /sysroot, the sysroot.mount unit becomes active and initrd-root-fs.target is reached. # # https://man7.org/linux/man-pages/man7/bootup.7.html # #"sysroot.mount" # ]; ## path = with pkgs; [ ## neo-cowsay ## ]; # unitConfig.DefaultDependencies = "no"; # serviceConfig.Type = "oneshot"; # script = '' # cat <<'EOF' # ${builtins.readFile contact-info-str} # EOF # ''; # }; }