From 1e5f745767cf1359add1a89bcc37f3a6434c25b1 Mon Sep 17 00:00:00 2001 From: Madeleine Sydney Date: Wed, 11 Dec 2024 19:20:40 -0700 Subject: [PATCH] init --- .dir-locals.el | 11 + .gitignore | 10 + .projectile | 0 README.org | 292 ++++++++++++++++++ flake.lock | 64 ++++ hosts/nixos-testbed/disko-config.nix | 155 ++++++++++ .../nixos-testbed/hardware-configuration.nix | 24 ++ hosts/nixos-testbed/system.nix | 1 + 8 files changed, 557 insertions(+) create mode 100644 .dir-locals.el create mode 100644 .gitignore create mode 100644 .projectile create mode 100644 README.org create mode 100644 flake.lock create mode 100644 hosts/nixos-testbed/disko-config.nix create mode 100644 hosts/nixos-testbed/hardware-configuration.nix create mode 100644 hosts/nixos-testbed/system.nix diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..b26fb42 --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,11 @@ +((nil + . ((eval . (defun dots/install-to-vm (clean-first?) + (interactive "P") + (let ((dest "/ssh:root@192.168.122.116:/nixos") + (root (project-root (project-current)))) + (progn + (when clean-first? + (delete-directory dest t)) + (org-babel-tangle-file (file-name-concat root "README.org")) + (copy-file root dest) + (message "Finished installing to VM!")))))))) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1364a37 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# A list of files generated from README.org can be gathered and inserted by +# evaluating the following snippet: +# (mapc (lambda (target) +# (insert (concat (file-relative-name target) +# "\n"))) +# (org-babel-tangle-file "README.org")) + +hosts/nixos-testbed/configuration.nix +modules/system/impermanence.nix +flake.nix diff --git a/.projectile b/.projectile new file mode 100644 index 0000000..e69de29 diff --git a/README.org b/README.org new file mode 100644 index 0000000..9fdf3fb --- /dev/null +++ b/README.org @@ -0,0 +1,292 @@ +#+PROPERTY: header-args :noweb no-export :results silent :comments both :tangle no +#+STARTUP: overview +#+title: Madeleine's dots for the literate (=sydnix=) + +* Top-level flake + +#+begin_src nix :tangle flake.nix +{ + description = "Madeleine's dots for the literate (sydnix)"; + + inputs = { + <> + + disko.url = "github:nix-community/disko"; + + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { nixpkgs, ... }@inputs: { + nixosConfigurations = ( + <> + ); + }; +} +#+end_src + +* Features + +What are referred to as /features/ here largely correspond to Nix modules, but are +not limited to Nix modules. + +** Impermanence + +*** Flake input + +#+begin_src nix :noweb-ref flake-inputs +impermanence.url = "github:nix-community/impermanence"; +#+end_src + +*** Top-level module + +#+begin_src nix :tangle modules/system/impermanence.nix +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.sydnix.impermanence; +in { + options = { + sydnix.impermanence = { + <> + }; + }; + + config = mkIf cfg.enable (mkMerge [ + + ]); +} +#+end_src + +*** Options + +**** =enable= + +#+begin_src nix :noweb-ref sydnix-impermanence-options +enable = mkOption { + type = types.bool; + default = false; +}; +#+end_src + +* Machines + +For every ~./hosts/NAME/configuration.nix~, define the system under the name ~NAME~. + +#+begin_src nix :noweb-ref flake-outputs-nixos +let mkHost = k: v: nixpkgs.lib.nixosSystem { + specialArgs = inputs; + system = import ./hosts/${k}/system.nix; + modules = [ + ./hosts/${k}/configuration.nix + # Directory name should always match host name. + ({ ... }: { networking.hostName = k; }) + ]; + }; +in +builtins.mapAttrs mkHost (builtins.readDir ./hosts) +#+end_src + +** =nixos-testbed= + +#+begin_src nix :tangle hosts/nixos-testbed/configuration.nix +{ config, pkgs, lib, disko, ... }: +{ + imports = [ + ./hardware-configuration.nix + ./disko-config.nix + disko.nixosModules.disko + ]; + + # boot.initrd.postDeviceCommands = '' + # if zfs list -t snapshot -H -o name \ + # | grep -qE '^rpool/local/root@previous$'; then + # zfs destroy -r rpool/local/root@previous \ + # && echo ">> >> previous previous snapshot destroyed << <<" + # else + # echo ">> >> no previous previous snapshot found << <<" + # fi + + # zfs snapshot -r rpool/local/root@previous \ + # && echo ">> >> pre-rollback snapshot taken << <<" + + # zfs rollback -r rpool/local/root@blank \ + # && echo ">> >> rollback complete << <<" + # ''; + + # boot.initrd.supportedFilesystems = [ "zfs" ]; + # boot.supportedFilesystems = [ "zfs" ]; + + boot.initrd.enable = true; + boot.initrd.systemd.enable = true; + + boot.initrd.systemd.initrdBin = with pkgs; [ + zfs + coreutils + gnugrep + gawk + ]; + + boot.initrd.systemd.services.erase-darlings = { + description = "Rollback filesystem to a blank state on boot"; + wantedBy = [ + "initrd.target" + ]; + after = [ + # "zfs-import.service" + "zfs-import-rpool.service" + ]; + before = [ + "sysroot.mount" + ]; + path = [ pkgs.zfs ]; + unitConfig.DefaultDependencies = "no"; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = /* bash */ '' + zfs rollback -r rpool/local/root@blank \ + && echo ">> >> rollback complete << <<" + ''; + }; + + systemd.services.erase-home-darlings = { + description = "Rollback home to a blank state on boot"; + wantedBy = [ + "multi-user.target" + ]; + before = [ + # "basic.target" + ]; + after = [ + "home.mount" + ]; + path = [ pkgs.zfs pkgs.coreutils pkgs.gnugrep pkgs.gawk pkgs.util-linux ]; + # unitConfig.DefaultDependencies = "no"; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + stopIfChanged = false; + restartIfChanged = false; + script = /* bash */ '' + set -xe + set -o pipefail + + command -v findmnt || echo "can't find findmnt on PATH" + command -v awk || echo "can't find awk on PATH" + + # findmnt -no TARGET rpool/darlings/persist + PREVDIR=$(findmnt -no TARGET rpool/darlings/persist)/previous + # PREVDIR=/sysroot/persist/previous + + echo "PREVDIR=$PREVDIR" + mkdir -p $PREVDIR/home + + [ -e $PREVDIR/home/3 ] && rm -rf $PREVDIR/home/3 + [ -e $PREVDIR/home/2 ] && mv $PREVDIR/home/2 $PREVDIR/home/3 + [ -e $PREVDIR/home/1 ] && mv $PREVDIR/home/1 $PREVDIR/home/2 + + DIFFFILE="$(mktemp "erase-home-darlings-zfs-diff-XXXXXX")" + + zfs diff -HF rpool/local/home@blank rpool/local/home \ + > "$DIFFFILE" + awk '{if ($2 == "F" || $2 == "/") print $3}' < "$DIFFFILE" \ + | while read -r line; do + DEST="$PREVDIR/home/1/$(dirname "$line")/$(basename "$line")" + mkdir -p "$(dirname "$DEST")" + mv "$line" "$DEST" && \ + echo "$line -> $DEST" + done \ + && echo ">> previous home backed up to $PREVDIR/home/1 <<" + + zfs rollback -r rpool/local/home@blank \ + && echo ">> home rolled back <<" + ''; + }; + + # boot.loader.grub = { + # enable = true; + # device = "nodev"; + # # device = "/dev/vda"; + # efiSupport = true; + # efiInstallAsRemovable = true; + # }; + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = false; + + # networking.hostName = "nixos-testbed"; + networking.hostId = "238e9b1e"; # head -c 8 /etc/machine-id + + time.timeZone = "America/Denver"; + + i18n.defaultLocale = "en_US.UTF-8"; + console = { + font = "Lat2-Terminus16"; + # keyMap = "us"; + useXkbConfig = true; # use xkb.options in tty. + }; + + services.xserver.enable = true; + # services.displayManager.sddm.enable = true; + # services.desktopManager.plasma6.enable = true; + + services.xserver.xkb.layout = "us"; + services.xserver.xkb.options = "caps:escape"; + + users.users.crumb = { + isNormalUser = true; + extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + # Change this immediately after installation! + initialPassword = "password123"; + }; + + environment.systemPackages = with pkgs; [ + neovim + ]; + + services.openssh.enable = true; + services.openssh.settings.PermitRootLogin = "yes"; + + # This option defines the first version of NixOS you have installed on this + # particular machine, and is used to maintain compatibility with application + # data (e.g. databases) created on older NixOS versions. + # + # Most users should NEVER change this value after the initial install, for any + # reason, even if you've upgraded your system to a new NixOS release. + # + # This value does NOT affect the Nixpkgs version your packages and OS are + # pulled from, so changing it will NOT upgrade your system - see + # https://nixos.org/manual/nixos/stable/#sec-upgrading for how to actually do + # that. + # + # This value being lower than the current NixOS release does NOT mean your + # system is out of date, out of support, or vulnerable. + # + # Do NOT change this value unless you have manually inspected all the changes + # it would make to your configuration, and migrated your data accordingly. + # + # For more information, see `man configuration.nix` or + # https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "24.05"; # Did you read the comment? +} +#+end_src + +** =guix-rebound= + +The primary desktop of a girl done with her plebian phase, and done with Guix's +bullshit. + +* References + +- My darling dearest Faye's =wishsys= }:D +- [[https://github.com/rasendubi/dotfiles][rasendubi/dotfiles]] +- [[https://github.com/hlissner/dotfiles/][hlissner/dotfiles]] +- [[https://github.com/Shawn8901/nix-configuration/tree/af71d51998a6772a300f842795b947e27202fa73][Shawn8901/nix-configuration]] diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..f9e4cac --- /dev/null +++ b/flake.lock @@ -0,0 +1,64 @@ +{ + "nodes": { + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1731235328, + "narHash": "sha256-NjavpgE9/bMe/ABvZpyHIUeYF1mqR5lhaep3wB79ucs=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "60bb110917844d354f3c18e05450606a435d2d10", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "impermanence": { + "locked": { + "lastModified": 1731242966, + "narHash": "sha256-B3C3JLbGw0FtLSWCjBxU961gLNv+BOOBC6WvstKLYMw=", + "owner": "nix-community", + "repo": "impermanence", + "rev": "3ed3f0eaae9fcc0a8331e77e9319c8a4abd8a71a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "impermanence", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1731245184, + "narHash": "sha256-vmLS8+x+gHRv1yzj3n+GTAEObwmhxmkkukB2DwtJRdU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "aebe249544837ce42588aa4b2e7972222ba12e8f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "home-manager": "home-manager", + "impermanence": "impermanence", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/hosts/nixos-testbed/disko-config.nix b/hosts/nixos-testbed/disko-config.nix new file mode 100644 index 0000000..f6cb82c --- /dev/null +++ b/hosts/nixos-testbed/disko-config.nix @@ -0,0 +1,155 @@ +# sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/latest -- --mode disko /nixos/hosts/nixos-testbed/disko-config.nix +# time sudo nixos-install --flake /nixos#nixos-testbed +{ lib, ... }: +{ + # imports = [ inputs.disko.nixosModules.disko ]; + boot.zfs.extraPools = [ "rpool" ]; + boot.zfs.devNodes = "/dev/disk/by-path"; + boot.initrd.supportedFilesystems = [ "zfs" ]; + boot.supportedFilesystems = [ "zfs" ]; + + disko.devices = { + disk = { + broot = { + type = "disk"; + device = "/dev/vda"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "512M"; + # start = "1MiB"; + # end = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" ]; + }; + }; + root = { + # start = "512M"; + # end = "100%"; + size = "100%"; + content = { + type = "zfs"; + pool = "rpool"; + }; + }; + }; + }; + }; + }; + zpool = { + rpool = { + type = "zpool"; + + # Workaround: cannot import 'rpool': I/O error in disko tests + # options.cachefile = "none"; + + # rootFsOptions = { + # # I don't know. + # # https://wiki.archlinux.org/title/Systemd#systemd-tmpfiles-setup.service_fails_to_start_at_boot + # acltype = "posixacl"; + # # atime = "off"; + # # compression = "zstd"; + # mountpoint = "none"; + # # xattr = "sa"; + # "com.sun:auto-snapshot" = "false"; + # }; + + # mountpoint = "/"; + + datasets = + let dataset = options: + let default = { + type = "zfs_fs"; + mountOptions = [ "noauto" ]; + options = { + "com.sun:auto-snapshot" = "false"; + }; + }; + in lib.recursiveUpdate default options; + in + { + "local" = dataset {}; + "darlings" = dataset {}; + "local/root" = dataset { + mountpoint = "/"; + postCreateHook = '' + zfs list -t snapshot -H -o name \ + | grep -E '^rpool/local/root@blank$' \ + || zfs snapshot rpool/local/root@blank + ''; + }; + "local/nix" = dataset { mountpoint = "/nix"; }; + "local/home" = dataset { + mountpoint = "/home"; + postCreateHook = '' + zfs list -t snapshot -H -o name \ + | grep -E '^rpool/local/home@blank$' \ + || zfs snapshot rpool/local/home@blank + ''; + }; + "darlings/persist" = dataset { mountpoint = "/persist"; }; + "darlings/home" = dataset { + mountpoint = "/persist/home"; + }; + "reserved" = dataset { + mountpoint = null; + options = { + canmount = "off"; + mountpoint = "none"; + reservation = "5GiB"; + }; + }; + # "local" = { + # type = "zfs_fs"; + # options.mountpoint = "none"; + # }; + # "safe" = { + # type = "zfs_fs"; + # options.mountpoint = "none"; + # }; + # "local/root" = { + # type = "zfs_fs"; + # options.mountpoint = "legacy"; + # mountpoint = "/"; + # options."com.sun:auto-snapshot" = "false"; + # postCreateHook = '' + # zfs list -t snapshot -H -o name \ + # | grep -E '^rpool/local/root@blank$' \ + # || zfs snapshot rpool/local/root@blank + # ''; + # }; + # "local/home" = { + + # }; + # "local/nix" = { + # type = "zfs_fs"; + # options.mountpoint = "legacy"; + # mountpoint = "/nix"; + # options."com.sun:auto-snapshot" = "false"; + # }; + # "safe/persist" = { + # type = "zfs_fs"; + # options.mountpoint = "legacy"; + # mountpoint = "/persist"; + # options."com.sun:auto-snapshot" = "false"; + # }; + # # zfs uses copy on write and requires some free space to delete files when the disk is completely filled + # "reserved" = lib.recursiveUpdate (dataset "reserved") { + # mountpoint = null; + # options = { + # canmount = "off"; + # mountpoint = "none"; + # reservation = "5GiB"; + # }; + # type = "zfs_fs"; + # }; + }; + }; + }; + }; +} diff --git a/hosts/nixos-testbed/hardware-configuration.nix b/hosts/nixos-testbed/hardware-configuration.nix new file mode 100644 index 0000000..f198f81 --- /dev/null +++ b/hosts/nixos-testbed/hardware-configuration.nix @@ -0,0 +1,24 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/profiles/qemu-guest.nix") + ]; + + boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/hosts/nixos-testbed/system.nix b/hosts/nixos-testbed/system.nix new file mode 100644 index 0000000..132026a --- /dev/null +++ b/hosts/nixos-testbed/system.nix @@ -0,0 +1 @@ +"x86_64-linux"