nix-git/modules/initrd-contact-info.nix
2024-11-17 22:33:21 +01:00

161 lines
6.0 KiB
Nix

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