From 3f3a3328d2cbe81cc8afe3d8335522be4ad25769 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Fri, 24 May 2024 14:03:22 -0400 Subject: [PATCH] sd-card --- .sops.yaml | 2 +- NOTES | 11 ++- home-manager/_mixins/cli/default.nix | 2 +- home-manager/_mixins/console/default.nix | 1 - home-manager/_mixins/users/gburd/default.nix | 5 +- sdcard/configuration.nix | 98 ++++++++++++++++++++ sdcard/rpi3.nix | 60 ++++++++++++ sdcard/sd-image-init.nix | 63 +++++++++++++ 8 files changed, 236 insertions(+), 6 deletions(-) create mode 100644 sdcard/configuration.nix create mode 100644 sdcard/rpi3.nix create mode 100644 sdcard/sd-image-init.nix diff --git a/.sops.yaml b/.sops.yaml index 6ad9b4a..9bbd5c7 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -11,7 +11,7 @@ keys: creation_rules: - - path_regex: nixos/floki/secrets.ya?ml$ + - path_regex: nixos/workstation/floki/secrets.ya?ml$ key_groups: - age: - *floki diff --git a/NOTES b/NOTES index cbc81c0..8f5455d 100644 --- a/NOTES +++ b/NOTES @@ -1,3 +1,10 @@ +nix flake lock --update-input nixpkgs +sudo nixos-rebuild dry-activate --flake .#floki +sudo nixos-rebuild switch --flake .#floki +home-manager build --debug --flake .#gburd@floki +home-manager switch -b bkup --flake .#gburd@floki +nix-build '' -A config.system.build.sdImage -I nixos-config=./sdcard/rpi2.nix + # Major differences: * sops/age for secrets * persistence/impermanence @@ -8,7 +15,7 @@ * generate age public key from host's existing SSH keypair nix-shell -p ssh-to-age --run 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age' * trigger first encryption of a secrets file - EDITOR=vi sops --config .sops.yaml --encrypt --in-place hosts/common/secrets.yaml + EDITOR=vi sops --config .sops.yaml --encrypt --in-place nixos/_mixins/secrets.yaml * edit secrets in that file later * When SOPS complains about your ~/.gnupg/secring.pgp file not being there try: export GPG_TTY=$(tty) @@ -95,7 +102,7 @@ export GPG_TTY=$(tty) gpg-connect-agent reloadagent /bye echo test | gpg --clearsign gpg --list-keys -EDITOR=vi sops --config .sops.yaml nixos/common/secrets.yaml +EDITOR=vi sops --config .sops.yaml nixos/_mixins/secrets.yaml sudo nixos-install --flake .#hostname reboot home-manager switch --flake .#username@hostname diff --git a/home-manager/_mixins/cli/default.nix b/home-manager/_mixins/cli/default.nix index 0f589cc..1c03d3f 100644 --- a/home-manager/_mixins/cli/default.nix +++ b/home-manager/_mixins/cli/default.nix @@ -16,7 +16,7 @@ ]; home.packages = with pkgs; [ - comma # Install and run programs by sticking a , before them + comma # Install and run programs by sticking a "," (comma) before them distrobox # Nice escape hatch, integrates docker images with my environment bc # Calculator diff --git a/home-manager/_mixins/console/default.nix b/home-manager/_mixins/console/default.nix index 971feb7..f357694 100644 --- a/home-manager/_mixins/console/default.nix +++ b/home-manager/_mixins/console/default.nix @@ -121,7 +121,6 @@ shellAliases = { diff = "diffr"; glow = "glow --pager"; - htop = "btm --basic --tree --hide_table_gap --dot_marker --mem_as_value"; ip = "ip --color --brief"; top = "btm --basic --tree --hide_table_gap --dot_marker --mem_as_value"; tree = "eza --tree"; diff --git a/home-manager/_mixins/users/gburd/default.nix b/home-manager/_mixins/users/gburd/default.nix index 8e5523f..fcb3caf 100644 --- a/home-manager/_mixins/users/gburd/default.nix +++ b/home-manager/_mixins/users/gburd/default.nix @@ -7,7 +7,7 @@ in imports = [ inputs.impermanence.nixosModules.home-manager.impermanence ../../cli - #../../console/charm-freeze.nix + ../../console ] ++ lib.optional (builtins.pathExists (./. + "/hosts/${hostname}.nix")) ./hosts/${hostname}.nix ++ lib.optional (builtins.pathExists (./. + "/hosts/${hostname}/default.nix")) ./hosts/${hostname}/default.nix @@ -16,14 +16,17 @@ in home = { file."ws/devshells".source = inputs.devshells; + file.".ssh/config".text = " Host github.com HostName github.com User git "; + sessionVariables = { # ... }; + file.".config/nixpkgs/config.nix".text = '' { allowUnfree = true; diff --git a/sdcard/configuration.nix b/sdcard/configuration.nix new file mode 100644 index 0000000..697f8ef --- /dev/null +++ b/sdcard/configuration.nix @@ -0,0 +1,98 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ + # Include the results of the hardware scan. + ./hardware-configuration.nix + # Needed to continue SD image initialization after installer removes its own unit. + ./sd-image-init.nix + ]; + + # Create a swap file. Raspberry pi 3B has only 1G of ram, and nixos-rebuild takes a *lot* of ram to evaluate + # the nixpgks store (someone even recommended me to evaluate the store on my laptop, either via binfmt to + # emulate Aarch64 or to use the rasp as a remote builder to keep the evaluation locally). When the system runs + # out of RAM, it freezes. + swapDevices = [ + { + device = "/swapfile"; + # create a smaller file on qemu, just to test + size = if (config ? virtualisation.qemu) then 127 else 2048; + } + ]; + + # Use the extlinux boot loader. (NixOS wants to enable GRUB by default) + boot.loader.grub.enable = false; + # Enables the generation of /boot/extlinux/extlinux.conf + boot.loader.generic-extlinux-compatible.enable = true; + boot.consoleLogLevel = 7; + + # Apparently also needed for some parts of the pi to work. + hardware.enableRedistributableFirmware = true; + + # Otherwise the hdmi disconnects during the boot and reconnect at the end + # looks like it is still not enough... + # Don't enable it with qemu + boot.initrd.kernelModules = lib.mkIf (!(config ? virtualisation.qemu)) [ "vc4" "bcm2835_dma" "i2c_bcm2835" "ahci"]; + + # K900 said that I should always try to stay as much as possible on mainline… which makes sense. + # K900 also recommended to use kernel 6.0.2 (default is 5.*), + boot.kernelPackages = pkgs.linuxPackages_latest; + # also get errors on rpi3 (can't boot, kernel error) and it will not work in qemu since it's arm + # boot.kernelPackages = pkgs.linuxPackages_rpi3; + + # https://github.com/NixOS/nixpkgs/issues/154163#issuecomment-1008362877 + nixpkgs.overlays = [ + (final: super: { + makeModulesClosure = x: + super.makeModulesClosure (x // { allowMissing = true; }); + }) + ]; + + boot.kernelParams = [ "cma=32M" "console=tty0,115200n8" ]; + + users.users.nixos = { + isNormalUser = true; + extraGroups = [ "wheel" "networkmanager" "video" ]; + initialPassword = "nixos"; + }; + services.mingetty.autologinUser = "nixos"; + + # The installer starts with a "nixos" user to allow installation, so add the + # SSH key to that user. Note that the key is, at the time of writing, put in + # `/etc/ssh/authorized_keys.d` + users.extraUsers.nixos.openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGSNy/vMr2Zk9pvfjQnxiU9F8CGQJwCiXDxPecKG9/q+ Greg Burd - 2023-01-23" + ]; + + # Enable OpenSSH out of the box. + services.sshd.enable = true; + + # Use a default root SSH login. + services.openssh.settings.PermitRootLogin = "yes"; + users.users.root = { + initialHashedPassword = "$6$xO61wiVZ3tg9Wryx$lBTmF6N7ed7gpeJdVK8vzExdDecDWiLAvYxNazW72LQST3iMaYQck071V9ACCMgeFrjSXt7G/w5UjlpOF1F6q."; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGSNy/vMr2Zk9pvfjQnxiU9F8CGQJwCiXDxPecKG9/q+ Greg Burd - 2023-01-23" + ]; + }; + + networking.wireless.enable = false; + + # The global useDHCP flag is deprecated, therefore explicitly set to false here. + # Per-interface useDHCP will be mandatory in the future, so this generated config + # replicates the default behaviour. + networking.useDHCP = false; + networking.interfaces.eth0.useDHCP = true; + networking.interfaces.wlan0.useDHCP = true; + + # NTP time sync. + services.timesyncd.enable = true; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.05"; # Did you read the comment? +} diff --git a/sdcard/rpi3.nix b/sdcard/rpi3.nix new file mode 100644 index 0000000..a3d51bb --- /dev/null +++ b/sdcard/rpi3.nix @@ -0,0 +1,60 @@ +{ config, pkgs, ... }: { + nixpkgs.hostPlatform.system = "aarch64-linux"; + nixpkgs.buildPlatform.system = "x86_64-linux"; + + imports = [ + + ./sd-image-init.nix + ]; + + nixpkgs.overlays = [ + (final: super: { + makeModulesClosure = x: + super.makeModulesClosure (x // { allowMissing = true; }); + }) + ]; + + # bzip2 compression takes loads of time with emulation, skip it. Enable this + # if you're low on space. + sdImage.compressImage = false; + + sdImage.populateRootCommands = '' + mkdir -p ./files/etc/sd-image-metadata/ + ${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel}/sd-image/configuration.nix -d ./fies/etc/sd-image-metadata + #cp /configuration.nix ./files/etc/sd-image-metadata/configuration.nix + #cp /sd-image-init.nix ./files/etc/sd-image-metadata/sd-image-init.nix + ''; + + # OpenSSH is forced to have an empty `wantedBy` on the installer system[1], + # this won't allow it to be automatically started. Override it with the normal + # value. + # [1] https://github.com/NixOS/nixpkgs/blob/9e5aa25/nixos/modules/profiles/installation-device.nix#L76 + systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ]; + + # Enable OpenSSH out of the box. + services.sshd.enable = true; + + # Use a default root SSH login. + services.openssh.settings.PermitRootLogin = "yes"; + users.users.root = { + initialHashedPassword = "$6$xO61wiVZ3tg9Wryx$lBTmF6N7ed7gpeJdVK8vzExdDecDWiLAvYxNazW72LQST3iMaYQck071V9ACCMgeFrjSXt7G/w5UjlpOF1F6q."; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGSNy/vMr2Zk9pvfjQnxiU9F8CGQJwCiXDxPecKG9/q+ Greg Burd - 2023-01-23" + ]; + }; + + # NTP time sync. + services.timesyncd.enable = true; + + # Since the latest kernel can't boot on RPI 3B+ + boot.kernelPackages = pkgs.linuxPackages_rpi3; + + hardware.enableRedistributableFirmware = true; + networking.wireless.enable = false; + networking.useDHCP = true; + hardware.bluetooth.powerOnBoot = false; + + environment.systemPackages = with pkgs; [ git gnupg neovim ]; + + system.stateVersion = "23.05"; +} diff --git a/sdcard/sd-image-init.nix b/sdcard/sd-image-init.nix new file mode 100644 index 0000000..a648328 --- /dev/null +++ b/sdcard/sd-image-init.nix @@ -0,0 +1,63 @@ +{ config, pkgs, ... }: + +{ + # Adapted from https://github.com/NixOS/nixpkgs/blob/e89ecac0a26cdf4546298c565e880f00d4ab8649/nixos/modules/virtualisation/amazon-init.nix + systemd.services.sd-image-init = { + description = "Reconfigure the system from SD image userdata on startup"; + + wantedBy = [ "multi-user.target" ]; + after = [ "multi-user.target" ]; + requires = [ "network-online.target" ]; + + restartIfChanged = false; + unitConfig.X-StopOnRemoval = false; + + script = '' + #!${pkgs.runtimeShell} -eu + + echo "attempting to fetch configuration from SD image user data..." + + export HOME=/root + export PATH=${pkgs.lib.makeBinPath [ config.nix.package pkgs.systemd pkgs.gnugrep pkgs.git pkgs.gnutar pkgs.gzip pkgs.gnused config.system.build.nixos-rebuild config.system.build.nixos-generate-config]}:$PATH + export NIX_PATH=nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels + + userData=/etc/sd-image-metadata/configuration.nix + userDataExtra=/etc/sd-image-metadata/sd-image-init.nix + + if [ -s "$userData" ]; then + # If the user-data looks like it could be a nix expression, + # copy it over. Also, look for a magic three-hash comment and set + # that as the channel. + if sed '/^\(#\|SSH_HOST_.*\)/d' < "$userData" | grep -q '\S'; then + channels="$(grep '^###' "$userData" | sed 's|###\s*||')" + while IFS= read -r channel; do + echo "writing channel: $channel" + done < <(printf "%s\n" "$channels") + + if [[ -n "$channels" ]]; then + printf "%s" "$channels" > /root/.nix-channels + nix-channel --update + fi + + echo "generating hardware configuration" + nixos-generate-config + echo "setting configuration from SD image user data" + cp "$userData" "$userDataExtra" /etc/nixos/ + else + echo "user data does not appear to be a Nix expression; ignoring" + exit + fi + else + echo "no user data is available" + exit + fi + + nixos-rebuild switch + ''; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + }; +}