diff --git a/.github/README.md b/.github/README.md index 9fcbec2..236919b 100644 --- a/.github/README.md +++ b/.github/README.md @@ -49,8 +49,8 @@ Otherwise, the files that are possibly of biggest interest are found here: - [SwarselSystems.org](../SwarselSystems.org) - [flake.nix](../flake.nix) -- [early-init.el](../programs/emacs/early-init.el) -- [init.el](../programs/emacs/init.el) +- [early-init.el](../files/emacs/early-init.el) +- [init.el](../files/emacs/init.el) ### Getting started @@ -112,7 +112,7 @@ Alternatively, to install this from any NixOS live ISO, run `nix run --experimen |🚪 **DM** | [greetd](https://github.com/Swarsel/.dotfiles/tree/main/modules/nixos/common/login.nix) | |🪟 **WM** | [SwayFX](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/sway.nix) | |⛩️ **Bar** | [Waybar](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/waybar.nix) | -|✒️ **Editor** | [Emacs](https://github.com/Swarsel/.dotfiles/tree/main/programs/emacs/init.el) | +|✒️ **Editor** | [Emacs](https://github.com/Swarsel/.dotfiles/tree/main/files/emacs/init.el) | |🖥️ **Terminal**| [Kitty](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/kitty.nix) | |🚀 **Launcher**| [Fuzzel](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/fuzzel.nix) | |🚨 **Alerts** | [Mako](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/mako.nix) | diff --git a/SwarselSystems.org b/SwarselSystems.org index 24bb9f8..2141ffc 100644 --- a/SwarselSystems.org +++ b/SwarselSystems.org @@ -1,5 +1,5 @@ #+title: SwarselSystems: NixOS + Emacs Configuration -#+PROPERTY: header-args:emacs-lisp :tangle programs/emacs/init.el :mkdirp yes +#+PROPERTY: header-args:emacs-lisp :tangle files/emacs/init.el :mkdirp yes #+PROPERTY: header-args:nix :mkdirp yes #+PROPERTY: header-args:nix-ts :mkdirp yes #+PROPERTY: header-args:shell :mkdirp yes @@ -245,7 +245,7 @@ Here I give a brief overview over the hostmachines that I am using. This is held |🚪 **DM** | [greetd](https://github.com/Swarsel/.dotfiles/tree/main/modules/nixos/common/login.nix) | |🪟 **WM** | [SwayFX](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/sway.nix) | |⛩️ **Bar** | [Waybar](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/waybar.nix) | - |✒️ **Editor** | [Emacs](https://github.com/Swarsel/.dotfiles/tree/main/programs/emacs/init.el) | + |✒️ **Editor** | [Emacs](https://github.com/Swarsel/.dotfiles/tree/main/files/emacs/init.el) | |🖥️ **Terminal**| [Kitty](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/kitty.nix) | |🚀 **Launcher**| [Fuzzel](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/fuzzel.nix) | |🚨 **Alerts** | [Mako](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/mako.nix) | @@ -481,6 +481,7 @@ When setting this option normally, the password would normally be written world- ./nix/templates.nix ./nix/formatter.nix ./nix/modules.nix + ./nix/iso.nix ]; systems = [ "x86_64-linux" @@ -867,7 +868,7 @@ The structure of =globals.nix.enc= requires a toplevel =globals=. homeConfigurations = mkHalfHostConfigs (lib.swarselsystems.readHosts "home") "home" lib.swarselsystems.pkgsFor.x86_64-linux; nixOnDroidConfigurations = mkHalfHostConfigs (lib.swarselsystems.readHosts "android") "android" lib.swarselsystems.pkgsFor.aarch64-linux; - diskoConfigurations.default = import "${self}/templates/hosts/nixos/disk-config.nix"; + diskoConfigurations.default = import "${self}/files/templates/hosts/nixos/disk-config.nix"; nodes = config.nixosConfigurations // config.darwinConfigurations; @@ -930,7 +931,7 @@ The structure of =globals.nix.enc= requires a toplevel =globals=. pfsense = mkRouter "pfSense" { info = "HUNSN RM02"; - image = "${self}/topology-images/hunsn.png"; + image = "${self}/files/topology-images/hunsn.png"; interfaceGroups = [ [ "eth2" @@ -979,7 +980,7 @@ The structure of =globals.nix.enc= requires a toplevel =globals=. wifi-ap = mkSwitch "Wi-Fi AP" { info = "Huawei"; - image = "${self}/topology-images/huawei.png"; + image = "${self}/files/topology-images/huawei.png"; interfaceGroups = [ [ "eth1" @@ -990,7 +991,7 @@ The structure of =globals.nix.enc= requires a toplevel =globals=. switch-livingroom = mkSwitch "Switch Livingroom" { info = "TL-SG108"; - image = "${self}/topology-images/TL-SG108.png"; + image = "${self}/files/topology-images/TL-SG108.png"; interfaceGroups = [ [ "eth1" @@ -1012,13 +1013,13 @@ The structure of =globals.nix.enc= requires a toplevel =globals=. nswitch = mkDevice "Nintendo Switch" { info = "Nintendo Switch"; - image = "${self}/topology-images/nintendo-switch.png"; + image = "${self}/files/topology-images/nintendo-switch.png"; interfaces.eth1 = { }; }; pc = mkDevice "Windows Gaming Server" { info = "i7-4790k, GTX970, 32GB RAM"; - image = "${self}/topology-images/pc.png"; + image = "${self}/files/topology-images/pc.png"; interfaces.eth1 = { }; }; @@ -1026,7 +1027,7 @@ The structure of =globals.nix.enc= requires a toplevel =globals=. switch-bedroom = mkSwitch "Switch Bedroom" { info = "TL-SG1005D"; - image = "${self}/topology-images/TL-SG1005D.png"; + image = "${self}/files/topology-images/TL-SG1005D.png"; interfaceGroups = [ [ "eth1" @@ -1041,7 +1042,7 @@ The structure of =globals.nix.enc= requires a toplevel =globals=. printer = mkDevice "Printer" { info = "DELL C2665dnf"; - image = "${self}/topology-images/DELL-C2665dnf.png"; + image = "${self}/files/topology-images/DELL-C2665dnf.png"; interfaces.eth1 = { }; }; @@ -1224,7 +1225,7 @@ This file defines the templates that are being exposed by the flake. These can b (name: { inherit name; value = { - path = "${self}/templates/${name}"; + path = "${self}/files/templates/${name}"; description = "${name} project "; }; }) @@ -1429,6 +1430,30 @@ Lastly, I add some of my own library functions to be used alongside the function }; } #+end_src +** Installer iso + +#+begin_src nix-ts :tangle nix/iso.nix + { inputs, ... }: + { + perSystem = { pkgs, system, ... }: + { + # nix build --print-out-paths --no-link .#images..live-iso + packages.live-iso = inputs.nixos-generators.nixosGenerate { + inherit pkgs; + modules = [ + inputs.home-manager.nixosModules.home-manager + ./installer-config.nix + ]; + format = + { + x86_64-linux = "install-iso"; + aarch64-linux = "sd-aarch64-installer"; + } + .${system}; + }; + }; + } +#+end_src * System :PROPERTIES: :CUSTOM_ID: h:02cd20be-1ffa-4904-9d5a-da5a89ba1421 @@ -1456,7 +1481,7 @@ This is the template that I use for new deployments of personal machines. Server :CUSTOM_ID: h:859aec97-65a2-4633-b7d8-73d4ccf89cc5 :END: -#+begin_src nix-ts :tangle templates/hosts/nixos/default.nix +#+begin_src nix-ts :tangle files/templates/hosts/nixos/default.nix { self, inputs, pkgs, lib, globals, ... }: let modulesPath = "${self}/modules"; @@ -1498,7 +1523,7 @@ This is the template that I use for new deployments of personal machines. Server swarselsystems = lib.recursiveUpdate { - wallpaper = self + /wallpaper/lenovowp.png; + wallpaper = self + /files/wallpaper/lenovowp.png; hasBluetooth = true; hasFingerprint = true; isImpermanence = true; @@ -1526,7 +1551,7 @@ This is the template that I use for new deployments of personal machines. Server Acceptance of arbitraty argumments is here needed because =disko= passes =diskoFile= to this file. -#+begin_src nix-ts :tangle templates/hosts/nixos/disk-config.nix +#+begin_src nix-ts :tangle files/templates/hosts/nixos/disk-config.nix { lib, pkgs, config, rootDisk, ... }: let type = "btrfs"; @@ -1698,7 +1723,7 @@ My work machine. Built for more security, this is the gold standard of my config { info = "Framework Laptop 16, 7940HS, RX7700S, 64GB RAM"; firewall = lib.mkForce true; - wallpaper = self + /wallpaper/lenovowp.png; + wallpaper = self + /files/wallpaper/lenovowp.png; hasBluetooth = true; hasFingerprint = true; isImpermanence = false; @@ -2844,7 +2869,7 @@ This is a slim setup for developing base configuration. I do not track the hardw swarselsystems = lib.recursiveUpdate { info = "~SwarselSystems~ remote install helper"; - wallpaper = self + /wallpaper/lenovowp.png; + wallpaper = self + /files/wallpaper/lenovowp.png; isImpermanence = true; isCrypted = false; isSecureBoot = false; @@ -3014,154 +3039,122 @@ This is a slim setup for developing base configuration. I do not track the hardw This is a live environment ISO that I use to bootstrap new systems. It only loads a minimal configuration and no graphical interface. After booting this image on a host, find out its IP and bootstrap the system using the =bootstrap= utility. -For added convenience, the live environment displays a helpful text on login, we define it here (will be put into =/etc/issue=): -#+begin_src bash :tangle programs/etc/issue :mkdirp yes - ~SwarselSystems~ - IP of primary interface: \4 - The Password for all users & root is 'setup'. - Install the system remotely by running 'bootstrap -n -d ' on a machine with deployed secrets. - Alternatively, run 'swarsel-install -n ' for a local install. For your convenience, an example call is in the bash history (press up on the keyboard to access). +#+begin_src nix-ts :tangle nix/installer-config.nix +{ pkgs, lib, ... }: +{ -#+end_src - -Also, an initial bash history is provided to allow for a very quick local deployment: - -#+begin_src shell :tangle programs/bash/.bash_history - swarsel-install -n chaostheatre -#+end_src - - -#+begin_src nix-ts :tangle nix/iso.nix - { self, pkgs, inputs, config, lib, modulesPath, ... }: - let - pubKeys = lib.filesystem.listFilesRecursive "${self}/secrets/keys/ssh"; - in - { - - imports = [ - "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" - "${modulesPath}/installer/cd-dvd/channel.nix" - - "${self}/modules/iso/minimal.nix" - "${self}/modules/nixos/common/sharedsetup.nix" - "${self}/modules/nixos/common/topology.nix" - "${self}/modules/home/common/sharedsetup.nix" - - "${self}/modules/nixos/common/globals.nix" - - - inputs.home-manager.nixosModules.home-manager - { - home-manager.users."setup".imports = [ - "${self}/modules/home/common/settings.nix" - "${self}/modules/home/common/sharedsetup.nix" - ]; - } - ]; - - config = { - swarselsystems = { - info = "~SwarselSystems~ installer ISO"; - }; - home-manager.users."setup" = { - home = { - stateVersion = "23.05"; - file = { - ".bash_history" = { - source = self + /programs/bash/.bash_history; - }; - }; - }; - swarselsystems = { - modules.general = lib.mkForce true; - }; - }; - home-manager.users.root.home = { - stateVersion = "23.05"; - file = { - ".bash_history" = { - source = self + /programs/bash/.bash_history; - }; - }; - }; - - # environment.etc."issue".text = "\x1B[32m~SwarselSystems~\x1B[0m\nIP of primary interface: \x1B[31m\\4\x1B[0m\nThe Password for all users & root is '\x1B[31msetup\x1B[0m'.\nInstall the system remotely by running '\x1B[33mbootstrap -n -d [--impermanence] [--encryption]\x1B[0m' on a machine with deployed secrets.\nAlternatively, run '\x1B[33mswarsel-install -d -f \x1B[0m' for a local install.\n"; - environment.etc."issue".source = "${self}/programs/etc/issue"; - networking.dhcpcd.runHook = "${pkgs.utillinux}/bin/agetty --reload"; - - isoImage = { - makeEfiBootable = true; - makeUsbBootable = true; - squashfsCompression = "zstd -Xcompression-level 3"; - }; - - nixpkgs = { - hostPlatform = lib.mkDefault "x86_64-linux"; - config.allowUnfree = true; - }; - - services.getty.autologinUser = lib.mkForce "setup"; - - users = { - allowNoPasswordLogin = true; - groups.swarsel = { }; - users = { - setup = { - name = "setup"; - group = "setup"; - isNormalUser = true; - password = "setup"; # this is overwritten after install - openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key); - extraGroups = [ "wheel" ]; - }; - root = { - # password = lib.mkForce config.users.users.swarsel.password; # this is overwritten after install - openssh.authorizedKeys.keys = config.users.users."setup".openssh.authorizedKeys.keys; - }; - }; - }; - - boot = { - loader.systemd-boot.enable = lib.mkForce true; - loader.efi.canTouchEfiVariables = true; - }; - - programs.bash.shellAliases = { - "swarsel-install" = "nix run github:Swarsel/.dotfiles#swarsel-install --"; - }; - - system.activationScripts.cache = { + config = { + home-manager.users.root.home = { + stateVersion = "23.05"; + file = { + ".bash_history" = { text = '' - mkdir -p -m=0777 /home/setup/.local/state/nix/profiles - mkdir -p -m=0777 /home/setup/.local/state/home-manager/gcroots - mkdir -p -m=0777 /home/setup/.local/share/nix/ - printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /home/setup/.local/share/nix/trusted-settings.json > /dev/null - mkdir -p /root/.local/share/nix/ - printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /root/.local/share/nix/trusted-settings.json > /dev/null + swarsel-install -n chaostheatre ''; }; - systemd = { - services.sshd.wantedBy = lib.mkForce [ "multi-user.target" ]; - targets = { - sleep.enable = false; - suspend.enable = false; - hibernate.enable = false; - hybrid-sleep.enable = false; - }; - }; + }; + }; - system.stateVersion = lib.mkForce "23.05"; + nix.settings = { + experimental-features = [ "nix-command" "flakes" ]; + }; - networking = { - hostName = "drugstore"; - wireless.enable = false; + boot = { + supportedFilesystems = lib.mkForce [ "brtfs" "vfat" ]; + loader.systemd-boot = { + enable = true; + }; + }; + + services = { + qemuGuest.enable = true; + openssh = { + enable = true; + settings.PermitRootLogin = "yes"; + authorizedKeysFiles = lib.mkForce [ + "/etc/ssh/authorized_keys.d/%u" + ]; + }; + }; + + environment.systemPackages = with pkgs; [ + curl + git + gnupg + rsync + ssh-to-age + sops + vim + just + sbctl + ]; + + programs = { + git.enable = true; + }; + + fileSystems."/boot".options = [ "umask=0077" ]; + + environment.etc."issue".text = '' + ~SwarselSystems~ + IP of primary interface: \4 + The Password for all users & root is 'setup'. + Install the system remotely by running 'bootstrap -n -d ' on a machine with deployed secrets. + Alternatively, run 'swarsel-install -n ' for a local install. For your convenience, an example call is in the bash history (press up on the keyboard to access). + ''; + + networking = { + hostName = "drugstore"; + wireless.enable = false; + dhcpcd.runHook = "${pkgs.utillinux}/bin/agetty --reload"; + networkmanager.enable = true; + }; + + services.getty.autologinUser = lib.mkForce "root"; + + users = { + allowNoPasswordLogin = true; + users = { + root = { + password = "setup"; # this is overwritten after install + initialHashedPassword = lib.mkForce null; + openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDd0XXoLfRE0AyasxscEBwMqOnLWPqwz+etGqzVNeSw/RcgnxOi903mlVjCH+jzWMSe2GVSgzgM20j/r9sfE2P1z+wq/RODFS04JM0ltUoFkkm/IDZXQ2piOk7AoVi5ajdx4EiBnXY87jvxh5cCgQltkj3ouPF7FVN/MaN21IgWYB8NgkaVGft//OplodlDQNot17c0sFMibY0HcquwmHhqKOtKM1gT98+jZl0rd1rCqXFOvkesW6FPC4nzirPai+Hizp5gncrkJOZmLLqrjVx6PfpQzqzIhoUn1YS5CpyfXnKZUgx2Oi8SENmWOZ9DxYvDklgEttob37E2bIXbUhOw/u4I3olGFgCsKL6jg0N+d5teEaCZFnzlOp0UMWiUo7lVqq7Bwl3rNka2pxEdZ9v/1+m9cJiP7h6pnKmccVGku57iGIDnsnoTrmo1qbAje+EsmPYbc+qMnTDvOdSHTOXnjsyTd+ADklvMHCUAuf6ku4ktQEhlZxU3PvYvKHa1cTCEXxLWjytIgHgTgab9M5IH29Q55LSRRQBzUdkwjOG6KhsqG+xEE6038EbXr0MGKTm01AFmeVZWewmkSLu2UdoOMiw8mTSQhQFfp2QruYHnh7oJCo7ttKT1sLoRX+TfgQm1ryn/orhReg2GFfmbiLGxaJGVNvjqCxqrIFQXx4ZDHw== cardno:22_412_399" ]; }; }; - } + }; + + programs.bash.shellAliases = { + "swarsel-install" = "nix run github:Swarsel/.dotfiles#swarsel-install --"; + }; + + system.activationScripts.cache = { + text = '' + mkdir -p -m=0777 /home/setup/.local/state/nix/profiles + mkdir -p -m=0777 /home/setup/.local/state/home-manager/gcroots + mkdir -p -m=0777 /home/setup/.local/share/nix/ + printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /home/setup/.local/share/nix/trusted-settings.json > /dev/null + mkdir -p /root/.local/share/nix/ + printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /root/.local/share/nix/trusted-settings.json > /dev/null + ''; + }; + systemd = { + services.sshd.wantedBy = lib.mkForce [ "multi-user.target" ]; + targets = { + sleep.enable = false; + suspend.enable = false; + hibernate.enable = false; + hybrid-sleep.enable = false; + }; + }; + + system.stateVersion = lib.mkForce "23.05"; + + }; +} -#+end_src + #+end_src **** Home-manager only (default non-NixOS) :PROPERTIES: @@ -3196,7 +3189,7 @@ This is the "reference implementation" of a setup that runs without NixOS, only }; programs.zsh.initContent = " - export GPG_TTY=\"$(tty)\" + export GPG_TTY=\"$(tty)\" export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) gpgconf --launch gpg-agent "; @@ -3204,7 +3197,7 @@ This is the "reference implementation" of a setup that runs without NixOS, only swarselsystems = { isLaptop = true; isNixos = false; - wallpaper = self + /wallpaper/surfacewp.png; + wallpaper = self + /files/wallpaper/surfacewp.png; }; } @@ -3239,65 +3232,65 @@ I also set the =WLR_RENDERER_ALLOW_SOFTWARE=1= to allow this configuration to ru }; }; in - { + { - imports = [ - ./hardware-configuration.nix - ./disk-config.nix - { - _module.args.diskDevice = config.swarselsystems.rootDisk; - } - "${self}/hosts/nixos/chaostheatre/options.nix" - inputs.home-manager.nixosModules.home-manager - { - home-manager.users."${mainUser}".imports = [ - "${self}/modules/home/common/settings.nix" - "${self}/hosts/nixos/chaostheatre/options-home.nix" - "${self}/modules/home/common/sharedsetup.nix" - ]; - } - ]; + imports = [ + ./hardware-configuration.nix + ./disk-config.nix + { + _module.args.diskDevice = config.swarselsystems.rootDisk; + } + "${self}/hosts/nixos/chaostheatre/options.nix" + inputs.home-manager.nixosModules.home-manager + { + home-manager.users."${mainUser}".imports = [ + "${self}/modules/home/common/settings.nix" + "${self}/hosts/nixos/chaostheatre/options-home.nix" + "${self}/modules/home/common/sharedsetup.nix" + ]; + } + ]; - environment.variables = { - WLR_RENDERER_ALLOW_SOFTWARE = 1; - }; + environment.variables = { + WLR_RENDERER_ALLOW_SOFTWARE = 1; + }; - services.qemuGuest.enable = true; + services.qemuGuest.enable = true; - boot = { - loader.systemd-boot.enable = lib.mkForce true; - loader.efi.canTouchEfiVariables = true; - kernelPackages = lib.mkDefault pkgs.linuxPackages_latest; - }; + boot = { + loader.systemd-boot.enable = lib.mkForce true; + loader.efi.canTouchEfiVariables = true; + kernelPackages = lib.mkDefault pkgs.linuxPackages_latest; + }; - networking = { - hostName = "chaostheatre"; - firewall.enable = true; - }; + networking = { + hostName = "chaostheatre"; + firewall.enable = true; + }; - swarselsystems = lib.recursiveUpdate - { - info = "~SwarselSystems~ demo host"; - wallpaper = self + /wallpaper/lenovowp.png; - initialSetup = true; - isImpermanence = true; - isCrypted = true; - isSecureBoot = false; - isSwap = true; - swapSize = "4G"; - rootDisk = "/dev/vda"; - } - sharedOptions; - - home-manager.users.${mainUser} = { - home.stateVersion = lib.mkForce "23.05"; swarselsystems = lib.recursiveUpdate { - isNixos = true; + info = "~SwarselSystems~ demo host"; + wallpaper = self + /files/wallpaper/lenovowp.png; + initialSetup = true; + isImpermanence = true; + isCrypted = true; + isSecureBoot = false; + isSwap = true; + swapSize = "4G"; + rootDisk = "/dev/vda"; } sharedOptions; - }; - } + + home-manager.users.${mainUser} = { + home.stateVersion = lib.mkForce "23.05"; + swarselsystems = lib.recursiveUpdate + { + isNixos = true; + } + sharedOptions; + }; + } #+end_src @@ -3308,134 +3301,134 @@ I also set the =WLR_RENDERER_ALLOW_SOFTWARE=1= to allow this configuration to ru :END: #+begin_src nix-ts :tangle hosts/nixos/chaostheatre/disk-config.nix -# NOTE: ... is needed because dikso passes diskoFile -{ lib -, pkgs -, config -, diskDevice ? config.swarselsystem.rootDisk -, ... -}: -let - type = "btrfs"; - extraArgs = [ "-L" "nixos" "-f" ]; # force overwrite - subvolumes = { - "/root" = { - mountpoint = "/"; - mountOptions = [ - "subvol=root" - "compress=zstd" - "noatime" - ]; + # NOTE: ... is needed because dikso passes diskoFile + { lib + , pkgs + , config + , diskDevice ? config.swarselsystem.rootDisk + , ... + }: + let + type = "btrfs"; + extraArgs = [ "-L" "nixos" "-f" ]; # force overwrite + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "subvol=root" + "compress=zstd" + "noatime" + ]; + }; + "/home" = lib.mkIf config.swarselsystems.isImpermanence { + mountpoint = "/home"; + mountOptions = [ + "subvol=home" + "compress=zstd" + "noatime" + ]; + }; + "/persist" = lib.mkIf config.swarselsystems.isImpermanence { + mountpoint = "/persist"; + mountOptions = [ + "subvol=persist" + "compress=zstd" + "noatime" + ]; + }; + "/log" = lib.mkIf config.swarselsystems.isImpermanence { + mountpoint = "/var/log"; + mountOptions = [ + "subvol=log" + "compress=zstd" + "noatime" + ]; + }; + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "subvol=nix" + "compress=zstd" + "noatime" + ]; + }; + "/swap" = lib.mkIf config.swarselsystems.isSwap { + mountpoint = "/.swapvol"; + swap.swapfile.size = config.swarselsystems.swapSize; + }; }; - "/home" = lib.mkIf config.swarselsystems.isImpermanence { - mountpoint = "/home"; - mountOptions = [ - "subvol=home" - "compress=zstd" - "noatime" - ]; - }; - "/persist" = lib.mkIf config.swarselsystems.isImpermanence { - mountpoint = "/persist"; - mountOptions = [ - "subvol=persist" - "compress=zstd" - "noatime" - ]; - }; - "/log" = lib.mkIf config.swarselsystems.isImpermanence { - mountpoint = "/var/log"; - mountOptions = [ - "subvol=log" - "compress=zstd" - "noatime" - ]; - }; - "/nix" = { - mountpoint = "/nix"; - mountOptions = [ - "subvol=nix" - "compress=zstd" - "noatime" - ]; - }; - "/swap" = lib.mkIf config.swarselsystems.isSwap { - mountpoint = "/.swapvol"; - swap.swapfile.size = config.swarselsystems.swapSize; - }; - }; -in -{ - disko.devices = { - disk = { - disk0 = { - type = "disk"; - device = diskDevice; - content = { - type = "gpt"; - partitions = { - ESP = { - priority = 1; - name = "ESP"; - size = "512M"; - type = "EF00"; - content = { - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - mountOptions = [ "defaults" ]; - }; - }; - root = lib.mkIf (!config.swarselsystems.isCrypted) { - size = "100%"; - content = { - inherit type subvolumes extraArgs; - postCreateHook = lib.mkIf config.swarselsystems.isImpermanence '' - MNTPOINT=$(mktemp -d) - mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5 - trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT - btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank - ''; - }; - }; - luks = lib.mkIf config.swarselsystems.isCrypted { - size = "100%"; - content = { - type = "luks"; - name = "cryptroot"; - passwordFile = "/tmp/disko-password"; # this is populated by bootstrap.sh - settings = { - allowDiscards = true; - # https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36 - crypttabExtraOpts = [ - "fido2-device=auto" - "token-timeout=10" - ]; + in + { + disko.devices = { + disk = { + disk0 = { + type = "disk"; + device = diskDevice; + content = { + type = "gpt"; + partitions = { + ESP = { + priority = 1; + name = "ESP"; + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "defaults" ]; + }; }; - content = { - inherit type subvolumes extraArgs; - postCreateHook = lib.mkIf config.swarselsystems.isImpermanence '' - MNTPOINT=$(mktemp -d) - mount "/dev/mapper/cryptroot" "$MNTPOINT" -o subvolid=5 + root = lib.mkIf (!config.swarselsystems.isCrypted) { + size = "100%"; + content = { + inherit type subvolumes extraArgs; + postCreateHook = lib.mkIf config.swarselsystems.isImpermanence '' + MNTPOINT=$(mktemp -d) + mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5 trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank - ''; + ''; + }; + }; + luks = lib.mkIf config.swarselsystems.isCrypted { + size = "100%"; + content = { + type = "luks"; + name = "cryptroot"; + passwordFile = "/tmp/disko-password"; # this is populated by bootstrap.sh + settings = { + allowDiscards = true; + # https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36 + crypttabExtraOpts = [ + "fido2-device=auto" + "token-timeout=10" + ]; + }; + content = { + inherit type subvolumes extraArgs; + postCreateHook = lib.mkIf config.swarselsystems.isImpermanence '' + MNTPOINT=$(mktemp -d) + mount "/dev/mapper/cryptroot" "$MNTPOINT" -o subvolid=5 + trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT + btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank + ''; + }; + }; }; }; }; }; }; }; - }; - }; - fileSystems."/persist".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true; - fileSystems."/home".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true; + fileSystems."/persist".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true; + fileSystems."/home".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true; - environment.systemPackages = [ - pkgs.yubikey-manager - ]; -} + environment.systemPackages = [ + pkgs.yubikey-manager + ]; + } #+end_src ***** NixOS dummy options configuration @@ -3472,9 +3465,9 @@ Here we have NixOS options. All options are split into smaller files that are lo let importNames = lib.swarselsystems.readNix "modules/nixos"; in - { - imports = lib.swarselsystems.mkImports importNames "modules/nixos"; - } + { + imports = lib.swarselsystems.mkImports importNames "modules/nixos"; + } #+end_src @@ -3498,13 +3491,13 @@ This section is for setting things that should be used on hosts that are using t importNames = lib.swarselsystems.readNix "modules/nixos/common"; modulesPath = "${self}/modules"; in - { - imports = lib.swarselsystems.mkImports importNames "modules/nixos/common" ++ [ - "${modulesPath}/home/common/sharedsetup.nix" - ]; + { + imports = lib.swarselsystems.mkImports importNames "modules/nixos/common" ++ [ + "${modulesPath}/home/common/sharedsetup.nix" + ]; - } + } #+end_src @@ -3555,29 +3548,29 @@ This section is for setting things that should be used on hosts that are using t attrsForEachOption = f: lib.foldl' (acc: path: lib.recursiveUpdate acc (lib.setAttrByPath path (f path))) { } forwardedOptions; in - { - options.nodes = lib.mkOption { - description = "Options forwarded to the given node."; - default = { }; - type = lib.types.attrsOf ( - lib.types.submodule { - options = attrsForEachOption mkForwardedOption; - } - ); - }; + { + options.nodes = lib.mkOption { + description = "Options forwarded to the given node."; + default = { }; + type = lib.types.attrsOf ( + lib.types.submodule { + options = attrsForEachOption mkForwardedOption; + } + ); + }; - config = - let - getConfig = - path: otherNode: + config = + let + getConfig = + path: otherNode: let cfg = outputs.nixosConfigurations.${otherNode}.config.nodes.${nodeName} or null; in - lib.optionals (cfg != null) (lib.getAttrFromPath path cfg); - mergeConfigFromOthers = path: lib.mkMerge (lib.concatMap (getConfig path) (lib.attrNames outputs.nixosConfigurations)); - in - attrsForEachOption mergeConfigFromOthers; - } + lib.optionals (cfg != null) (lib.getAttrFromPath path cfg); + mergeConfigFromOthers = path: lib.mkMerge (lib.concatMap (getConfig path) (lib.attrNames outputs.nixosConfigurations)); + in + attrsForEachOption mergeConfigFromOthers; + } #+end_src **** Global options (automatically active) @@ -3591,53 +3584,53 @@ This section is for setting things that should be used on hosts that are using t inherit (lib) mkOption types - ; + ; in - { - options = { - globals = mkOption { - default = { }; - type = types.submodule { - options = { - user = { - name = mkOption { - type = types.str; + { + options = { + globals = mkOption { + default = { }; + type = types.submodule { + options = { + user = { + name = mkOption { + type = types.str; + }; + work = mkOption { + type = types.str; + }; }; - work = mkOption { - type = types.str; - }; - }; - services = mkOption { - type = types.attrsOf ( - types.submodule { - options = { - domain = mkOption { - type = types.str; + services = mkOption { + type = types.attrsOf ( + types.submodule { + options = { + domain = mkOption { + type = types.str; + }; }; - }; - } - ); - }; + } + ); + }; - domains = { - main = mkOption { - type = types.str; + domains = { + main = mkOption { + type = types.str; + }; }; }; }; }; - }; - _globalsDefs = mkOption { - type = types.unspecified; - default = options.globals.definitions; - readOnly = true; - internal = true; + _globalsDefs = mkOption { + type = types.unspecified; + default = options.globals.definitions; + readOnly = true; + internal = true; + }; }; - }; - } + } #+end_src **** Meta options (automatically active) @@ -3735,26 +3728,26 @@ We disable the warnings that trigger when rebuilding with a dirty flake. At this Also, the system state version is set here. No need to touch it. A breakdown of the flags being set: - - =nixpgks.config.allowUnfree=: allows packages with an unfree license to be built - - nix.settings: - - experimental-features: - - nix-command: Enables the =nix= command from nix 2.4 - - flakes: Enables flakes to be used - - ca-derivations: Enables content-addressed derivations, which stops unnecessary rebuiluds - to be used with my TODO private hydra and the binary cache =cache.ngi0.nixos.org= in [[#h:aee5ec75-7ca6-40d8-b6ac-a3e7e33a474b][flake.nix template]] - - cgroups: allows the use of cgroups in builds - - pipe-operators: Enables 'piping' instead of the classic currying syntax - =fun arg= can be expressed as =arg |> fun=. Associatively, it is weaker than functions: =a |> b |> d c |> e = e ((d c) (b a))= - - trusted-users: these users have elevated privileges in nix (mostly used to acknowledge binary caches) - root is added per default here - - connect-timeout: normally, nix tries to reach the cache for 300 seconds for each derivation per cache. This setting lets me change that - - bash-prompt-prefix: adds a prefix to shells spawned by =nix develop= - - [min,max]-free: amounts of space where intermittent GC will be run during builds - - flake registry: URI of the global flake registry (I disable it) - - auto-optimise-store: create hardlinks in the nix store to save space - - warn-dirty: I do not need to see the warning when I have uncommited changes - - max-jobs: How many build jobs should be run in parallel. =auto= sets this to the number of CPUs (which is all) - on systems with many cores this can lead to OOM situations. The default is now =1=, but used to be =auto=, I set this manually just to be safe in the future. - - use-cgroups: Actually run builds within cgroups - - nix.channel.enable: whether to use channels - - nix.registry: Sets the registry for this flake, which I set to its inputs. This allows me to use e.g. =nixpkgs= directly in =nix repl= - - nix.nixPath: Basically the same as =nix.registry=, but for the legacy nix commands +- =nixpgks.config.allowUnfree=: allows packages with an unfree license to be built +- nix.settings: + - experimental-features: + - nix-command: Enables the =nix= command from nix 2.4 + - flakes: Enables flakes to be used + - ca-derivations: Enables content-addressed derivations, which stops unnecessary rebuiluds - to be used with my TODO private hydra and the binary cache =cache.ngi0.nixos.org= in [[#h:aee5ec75-7ca6-40d8-b6ac-a3e7e33a474b][flake.nix template]] + - cgroups: allows the use of cgroups in builds + - pipe-operators: Enables 'piping' instead of the classic currying syntax - =fun arg= can be expressed as =arg |> fun=. Associatively, it is weaker than functions: =a |> b |> d c |> e = e ((d c) (b a))= + - trusted-users: these users have elevated privileges in nix (mostly used to acknowledge binary caches) - root is added per default here + - connect-timeout: normally, nix tries to reach the cache for 300 seconds for each derivation per cache. This setting lets me change that + - bash-prompt-prefix: adds a prefix to shells spawned by =nix develop= + - [min,max]-free: amounts of space where intermittent GC will be run during builds + - flake registry: URI of the global flake registry (I disable it) + - auto-optimise-store: create hardlinks in the nix store to save space + - warn-dirty: I do not need to see the warning when I have uncommited changes + - max-jobs: How many build jobs should be run in parallel. =auto= sets this to the number of CPUs (which is all) - on systems with many cores this can lead to OOM situations. The default is now =1=, but used to be =auto=, I set this manually just to be safe in the future. + - use-cgroups: Actually run builds within cgroups +- nix.channel.enable: whether to use channels +- nix.registry: Sets the registry for this flake, which I set to its inputs. This allows me to use e.g. =nixpkgs= directly in =nix repl= +- nix.nixPath: Basically the same as =nix.registry=, but for the legacy nix commands #+begin_src nix-ts :tangle modules/nixos/common/settings.nix { lib, pkgs, config, outputs, inputs, ... }: @@ -3777,44 +3770,44 @@ A breakdown of the flags being set: let flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs; in - { - settings = { - experimental-features = [ - "nix-command" - "flakes" - "ca-derivations" - "cgroups" - "pipe-operators" - ]; - trusted-users = [ "@wheel" "${config.swarselsystems.mainUser}" ]; - connect-timeout = 5; - bash-prompt-prefix = "$SHLVL:\\w "; - bash-prompt = "$(if [[ $? -gt 0 ]]; then printf \"\"; else printf \"\"; fi)\[\e[1m\]λ\[\e[0m\] "; - fallback = true; - min-free = 128000000; - max-free = 1000000000; - flake-registry = ""; - auto-optimise-store = true; - warn-dirty = false; - max-jobs = 1; - use-cgroups = lib.mkIf config.swarselsystems.isLinux true; + { + settings = { + experimental-features = [ + "nix-command" + "flakes" + "ca-derivations" + "cgroups" + "pipe-operators" + ]; + trusted-users = [ "@wheel" "${config.swarselsystems.mainUser}" ]; + connect-timeout = 5; + bash-prompt-prefix = "$SHLVL:\\w "; + bash-prompt = "$(if [[ $? -gt 0 ]]; then printf \"\"; else printf \"\"; fi)\[\e[1m\]λ\[\e[0m\] "; + fallback = true; + min-free = 128000000; + max-free = 1000000000; + flake-registry = ""; + auto-optimise-store = true; + warn-dirty = false; + max-jobs = 1; + use-cgroups = lib.mkIf config.swarselsystems.isLinux true; + }; + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 10d"; + }; + optimise = { + automatic = true; + dates = "weekly"; + }; + channel.enable = false; + registry = rec { + nixpkgs.flake = inputs.nixpkgs; + p = nixpkgs; + }; + nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs; }; - gc = { - automatic = true; - dates = "weekly"; - options = "--delete-older-than 10d"; - }; - optimise = { - automatic = true; - dates = "weekly"; - }; - channel.enable = false; - registry = rec { - nixpkgs.flake = inputs.nixpkgs; - p = nixpkgs; - }; - nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs; - }; services.dbus.implementation = "broker"; @@ -3839,28 +3832,28 @@ We enable the use of =home-manager= as a NixoS module. A nice trick here is the let mainUser = globals.user.name; in - { - options.swarselsystems.modules.home-manager = lib.mkEnableOption "home-manager"; - config = lib.mkIf config.swarselsystems.modules.home-manager { - home-manager = lib.mkIf config.swarselsystems.withHomeManager { - useGlobalPkgs = true; - useUserPackages = true; - verbose = true; - users."${mainUser}".imports = [ - "${self}/profiles/home" - "${self}/modules/home" - ]; - sharedModules = [ - inputs.nix-index-database.hmModules.nix-index - inputs.sops-nix.homeManagerModules.sops - { - home.stateVersion = lib.mkDefault config.system.stateVersion; - } - ]; - extraSpecialArgs = { inherit (inputs) self nixgl; inherit inputs outputs globals nodes; }; + { + options.swarselsystems.modules.home-manager = lib.mkEnableOption "home-manager"; + config = lib.mkIf config.swarselsystems.modules.home-manager { + home-manager = lib.mkIf config.swarselsystems.withHomeManager { + useGlobalPkgs = true; + useUserPackages = true; + verbose = true; + users."${mainUser}".imports = [ + "${self}/profiles/home" + "${self}/modules/home" + ]; + sharedModules = [ + inputs.nix-index-database.hmModules.nix-index + inputs.sops-nix.homeManagerModules.sops + { + home.stateVersion = lib.mkDefault config.system.stateVersion; + } + ]; + extraSpecialArgs = { inherit (inputs) self nixgl; inherit inputs outputs globals nodes; }; + }; }; - }; - } + } #+end_src **** User setup, Make users non-mutable @@ -3878,24 +3871,24 @@ For that reason, make sure that =sops-nix= is properly working before setting th let sopsFile = self + /secrets/general/secrets.yaml; in - { - options.swarselsystems.modules.users = lib.mkEnableOption "user config"; - config = lib.mkIf config.swarselsystems.modules.users { - sops.secrets.swarseluser = lib.mkIf (!config.swarselsystems.isPublic) { inherit sopsFile; neededForUsers = true; }; + { + options.swarselsystems.modules.users = lib.mkEnableOption "user config"; + config = lib.mkIf config.swarselsystems.modules.users { + sops.secrets.swarseluser = lib.mkIf (!config.swarselsystems.isPublic) { inherit sopsFile; neededForUsers = true; }; - users = { - mutableUsers = lib.mkIf (!config.swarselsystems.initialSetup) false; - users."${config.swarselsystems.mainUser}" = { - isNormalUser = true; - description = "Leon S"; - password = lib.mkIf config.swarselsystems.initialSetup "setup"; - hashedPasswordFile = lib.mkIf (!config.swarselsystems.initialSetup) config.sops.secrets.swarseluser.path; - extraGroups = [ "networkmanager" "syncthing" "docker" "wheel" "lp" "audio" "video" "vboxusers" "libvirtd" "scanner" ]; - packages = with pkgs; [ ]; + users = { + mutableUsers = lib.mkIf (!config.swarselsystems.initialSetup) false; + users."${config.swarselsystems.mainUser}" = { + isNormalUser = true; + description = "Leon S"; + password = lib.mkIf config.swarselsystems.initialSetup "setup"; + hashedPasswordFile = lib.mkIf (!config.swarselsystems.initialSetup) config.sops.secrets.swarseluser.path; + extraGroups = [ "networkmanager" "syncthing" "docker" "wheel" "lp" "audio" "video" "vboxusers" "libvirtd" "scanner" ]; + packages = with pkgs; [ ]; + }; }; }; - }; - } + } #+end_src **** Setup login keymap @@ -5938,7 +5931,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t topology.self.services.${serviceName} = { name = "Kavita"; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; globals.services.${serviceName}.domain = serviceDomain; @@ -6284,7 +6277,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t topology.self.services.${serviceName} = { name = lib.toUpper serviceName; info = "http://localhost:${builtins.toString servicePort}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; services.${serviceName} = { @@ -7114,7 +7107,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= readarr = { name = "Readarr"; info = "https://${serviceDomain}/readarr"; - icon = "${self}/topology/images/readarr.png"; + icon = "${self}/files/topology-images/readarr.png"; }; sonarr.info = "https://${serviceDomain}/sonarr"; lidarr.info = "https://${serviceDomain}/lidarr"; @@ -7821,7 +7814,7 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with topology.self.services.${serviceName} = { name = "FreshRSS"; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; globals.services.${serviceName}.domain = serviceDomain; @@ -8058,7 +8051,7 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with topology.self.services.${serviceName} = { name = lib.mkForce "Anki Sync Server"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; info = "https://${serviceDomain}"; }; @@ -8645,7 +8638,7 @@ To get other URLs (token, etc.), use https:///oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid/ toolkit.legacyUserProfileCustomizations.styleshe config = lib.mkIf config.swarselsystems.modules.symlink { home.file = { "init.el" = lib.mkDefault { - source = self + /programs/emacs/init.el; + source = self + /files/emacs/init.el; target = ".emacs.d/init.el"; }; "early-init.el" = { - source = self + /programs/emacs/early-init.el; + source = self + /files/emacs/early-init.el; target = ".emacs.d/early-init.el"; }; # on NixOS, Emacs does not find the aspell dicts easily. Write the configuration manually ".aspell.conf" = { - source = self + /programs/config/.aspell.conf; + source = self + /files/config/.aspell.conf; target = ".aspell.conf"; }; ".gitmessage" = { - source = self + /programs/git/.gitmessage; + source = self + /files/git/.gitmessage; target = ".gitmessage"; }; }; xdg.configFile = { - "tridactyl/tridactylrc".source = self + /programs/firefox/tridactyl/tridactylrc; - "tridactyl/themes/base16-codeschool.css".source = self + /programs/firefox/tridactyl/themes/base16-codeschool.css; - "tridactyl/themes/swarsel.css".source = self + /programs/firefox/tridactyl/themes/swarsel.css; - "swayidle/config".source = self + /programs/swayidle/config; + "tridactyl/tridactylrc".source = self + /files/firefox/tridactyl/tridactylrc; + "tridactyl/themes/base16-codeschool.css".source = self + /files/firefox/tridactyl/themes/base16-codeschool.css; + "tridactyl/themes/swarsel.css".source = self + /files/firefox/tridactyl/themes/swarsel.css; + "swayidle/config".source = self + /files/swayidle/config; }; }; } @@ -11079,7 +10994,7 @@ nix-index provides a way to find out which packages are provided by which deriva let commandNotFound = pkgs.runCommandLocal "command-not-found.sh" { } '' mkdir -p $out/etc/profile.d - substitute ${self + /scripts/command-not-found.sh} \ + substitute ${self + /files/scripts/command-not-found.sh} \ $out/etc/profile.d/command-not-found.sh \ --replace-fail @nix-locate@ ${pkgs.nix-index}/bin/nix-locate \ --replace-fail @tput@ ${pkgs.ncurses}/bin/tput @@ -11615,8 +11530,8 @@ Currently I only use it as before with =initExtra= though. ]; xdg.configFile = { - "zellij/config.kdl".text = import "${self}/programs/zellij/config.kdl.nix" { inherit config; }; - "zellij/layouts/default.kdl".text = import "${self}/programs/zellij/layouts/default.kdl.nix" { inherit config pkgs; }; + "zellij/config.kdl".text = import "${self}/files/zellij/config.kdl.nix" { inherit config; }; + "zellij/layouts/default.kdl".text = import "${self}/files/zellij/layouts/default.kdl.nix" { inherit config pkgs; }; }; }; @@ -11908,7 +11823,7 @@ Lastly, I am defining some more packages here that the parser has problems findi programs.emacs = { enable = true; package = pkgs.emacsWithPackagesFromUsePackage { - config = self + /programs/emacs/init.el; + config = self + /files/emacs/init.el; package = pkgs.emacs-git-pgtk; alwaysEnsure = true; alwaysTangle = true; @@ -12296,7 +12211,7 @@ The rest of the related configuration is found here: }; }; }; - style = builtins.readFile (self + /programs/waybar/style.css); + style = builtins.readFile (self + /files/waybar/style.css); }; }; } @@ -12844,10 +12759,10 @@ Currently, I am too lazy to explain every option here, but most of it is very se # output = lib.mapAttrs' lib.swarselsystems.eachMonitor monitors; output = { "${config.swarselsystems.sharescreen}" = { - bg = "${self}/wallpaper/lenovowp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/lenovowp.png ${config.stylix.imageScalingMode}"; }; "Philips Consumer Electronics Company PHL BDM3270 AU11806002320" = { - bg = "${self}/wallpaper/standwp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/standwp.png ${config.stylix.imageScalingMode}"; }; }; input = config.swarselsystems.standardinputs; @@ -13252,7 +13167,7 @@ As for the `home.sessionVariables`, it should be noted that environment variable config = lib.mkIf config.swarselsystems.modules.server.dotfiles { home.file = { "init.el" = lib.mkForce { - source = self + /programs/emacs/server.el; + source = self + /files/emacs/server.el; target = ".emacs.d/init.el"; }; }; @@ -13387,13 +13302,13 @@ The rest of the settings is at [[#h:bbf2ecb6-c8ff-4462-b5d5-d45b28604ddf][work]] wayland.windowManager.sway.config = { output = { "Applied Creative Technology Transmitter QUATTRO201811" = { - bg = "${self}/wallpaper/navidrome.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/navidrome.png ${config.stylix.imageScalingMode}"; }; "Hewlett Packard HP Z24i CN44250RDT" = { - bg = "${self}/wallpaper/op6wp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/op6wp.png ${config.stylix.imageScalingMode}"; }; "HP Inc. HP 732pk CNC4080YL5" = { - bg = "${self}/wallpaper/botanicswp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/botanicswp.png ${config.stylix.imageScalingMode}"; }; }; }; @@ -13850,7 +13765,7 @@ Note: The structure of generating the packages was changed in commit =2cf03a3 re This app allows me, in conjunction with my Yubikey, to quickly enter passwords when the need arises. Normal and TOTP passwords are supported, and they can either be printed directly or copied to the clipboard. -#+begin_src shell :tangle scripts/pass-fuzzel.sh :mkdirp yes +#+begin_src shell :tangle files/scripts/pass-fuzzel.sh :mkdirp yes # Adapted from https://code.kulupu.party/thesuess/home-manager/src/branch/main/modules/river.nix shopt -s nullglob globstar @@ -13909,7 +13824,7 @@ This app allows me, in conjunction with my Yubikey, to quickly enter passwords w writeShellApplication { inherit name; runtimeInputs = [ libnotify (pass.withExtensions (exts: [ exts.pass-otp ])) fuzzel wtype ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14070,7 +13985,7 @@ This app starts a configuratble timer and uses TTS to say something once the tim This is a shorthand for calling emacsclient mostly. Also, it hides the kittyterm scratchpad window that I sometimes use for calling a command quickly, in case it is on the screen. After emacs closes, the kittyterm window is then shown again if it was visible earlier. -#+begin_src shell :tangle scripts/e.sh +#+begin_src shell :tangle files/scripts/e.sh wait=0 while :; do case ${1:-} in @@ -14101,7 +14016,7 @@ This is a shorthand for calling emacsclient mostly. Also, it hides the kittyterm writeShellApplication { inherit name; runtimeInputs = [ emacs30-pgtk sway jq ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14114,7 +14029,7 @@ This is a shorthand for calling emacsclient mostly. Also, it hides the kittyterm The normal =command-not-found.sh= uses the outdated =nix-shell= commands as suggestions. This version supplies me with the more modern =nixpkgs#= version. -#+begin_src shell :tangle scripts/command-not-found.sh +#+begin_src shell :tangle files/scripts/command-not-found.sh # Adapted from https://github.com/bennofs/nix-index/blob/master/command-not-found.sh command_not_found_handle() { if [ -n "${MC_SID-}" ] || ! [ -t 1 ]; then @@ -14157,7 +14072,7 @@ The normal =command-not-found.sh= uses the outdated =nix-shell= commands as sugg This app checks for different apps that I keep around in the scratchpad for quick viewing and hiding (messengers and music players mostly) and then behaves like the kittyterm hider that I described in [[#h:1834df06-9238-4efa-9af6-851dafe66c68][e]]. -#+begin_src shell :tangle scripts/swarselcheck.sh +#+begin_src shell :tangle files/scripts/swarselcheck.sh kitty=0 element=0 vesktop=0 @@ -14227,7 +14142,7 @@ This app checks for different apps that I keep around in the scratchpad for quic writeShellApplication { inherit name; runtimeInputs = [ kitty element-desktop vesktop spotify-player jq ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14237,7 +14152,7 @@ This app checks for different apps that I keep around in the scratchpad for quic :CUSTOM_ID: h:564c102c-e335-4f17-a613-c5a436bb4864 :END: -#+begin_src shell :tangle scripts/swarselzellij.sh +#+begin_src shell :tangle files/scripts/swarselzellij.sh KITTIES=$(($(pgrep -P 1 kitty | wc -l) - 1)) if ((KITTIES < 1)); then @@ -14252,7 +14167,7 @@ This app checks for different apps that I keep around in the scratchpad for quic writeShellApplication { inherit name; runtimeInputs = [ kitty ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14264,7 +14179,7 @@ This app checks for different apps that I keep around in the scratchpad for quic This scripts checks if there are uncommited changes in either my dotfile repo, my university repo, or my passfile repo. In that case a warning will be shown in waybar. -#+begin_src shell :tangle scripts/waybarupdate.sh +#+begin_src shell :tangle files/scripts/waybarupdate.sh CFG=$(git --git-dir="$HOME"/.dotfiles/.git --work-tree="$HOME"/.dotfiles/ status -s | wc -l) CSE=$(git --git-dir="$DOCUMENT_DIR_PRIV"/CSE_TUWIEN/.git --work-tree="$DOCUMENT_DIR_PRIV"/CSE_TUWIEN/ status -s | wc -l) PASS=$(($(git --git-dir="$HOME"/.local/share/password-store/.git --work-tree="$HOME"/.local/share/password-store/ status -s | wc -l) + $(git --git-dir="$HOME"/.local/share/password-store/.git --work-tree="$HOME"/.local/share/password-store/ diff origin/main..HEAD | wc -l))) @@ -14296,7 +14211,7 @@ This scripts checks if there are uncommited changes in either my dotfile repo, m writeShellApplication { inherit name; runtimeInputs = [ git ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14308,7 +14223,7 @@ This scripts checks if there are uncommited changes in either my dotfile repo, m This app quickly toggles between 5% and 0% transparency. -#+begin_src shell :tangle scripts/opacitytoggle.sh +#+begin_src shell :tangle files/scripts/opacitytoggle.sh if swaymsg opacity plus 0.01 -q; then swaymsg opacity 1 else @@ -14321,7 +14236,7 @@ This app quickly toggles between 5% and 0% transparency. writeShellApplication { inherit name; runtimeInputs = [ sway ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14332,7 +14247,7 @@ This app quickly toggles between 5% and 0% transparency. This utility is used to compare the current state of the root directory with the blanket state that is stored in /root-blank (the snapshot that is restored on each reboot of an impermanence machine). Using this, I can find files that I will lose once I reboot - if there are important files in that list, I can then easily add them to the persist options. -#+begin_src shell :tangle scripts/fs-diff.sh +#+begin_src shell :tangle files/scripts/fs-diff.sh set -euo pipefail OLD_TRANSID=$(sudo btrfs subvolume find-new /mnt/root-blank 9999999) @@ -14359,7 +14274,7 @@ This utility is used to compare the current state of the root directory with the { self, name, writeShellApplication }: writeShellApplication { inherit name; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14412,7 +14327,7 @@ This application moves the wl-mirror app to the T workspace and makes it fullscr :END: -#+begin_src shell :tangle scripts/screenshare.sh +#+begin_src shell :tangle files/scripts/screenshare.sh headless="false" while [[ $# -gt 0 ]]; do @@ -14445,7 +14360,7 @@ This application moves the wl-mirror app to the T workspace and makes it fullscr writeShellApplication { inherit name; runtimeInputs = [ sway ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14456,8 +14371,8 @@ This application moves the wl-mirror app to the T workspace and makes it fullscr This program sets up a new NixOS host remotely. It also takes care of secret management on the new host. -#+begin_src shell :tangle scripts/swarsel-bootstrap.sh - # highly inspired by https://github.com/EmergentMind/nix-config/blob/dev/scripts/bootstrap-nixos.sh +#+begin_src shell :tangle files/scripts/swarsel-bootstrap.sh + # highly inspired by https://github.com/EmergentMind/nix-config/blob/dev/files/scripts/bootstrap-nixos.sh set -eo pipefail target_hostname="" @@ -14804,7 +14719,7 @@ This program sets up a new NixOS host remotely. It also takes care of secret man writeShellApplication { inherit name; runtimeInputs = [ openssh ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14813,7 +14728,7 @@ This program sets up a new NixOS host remotely. It also takes care of secret man :CUSTOM_ID: h:1eabdc59-8832-44ca-a22b-11f848ab150a :END: -#+begin_src shell :tangle scripts/swarsel-rebuild.sh +#+begin_src shell :tangle files/scripts/swarsel-rebuild.sh set -eo pipefail target_config="chaostheatre" @@ -14922,7 +14837,7 @@ This program sets up a new NixOS host remotely. It also takes care of secret man writeShellApplication { inherit name; runtimeInputs = [ git ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -14933,7 +14848,7 @@ This program sets up a new NixOS host remotely. It also takes care of secret man Autoformatting always puts the =EOF= with indentation, which makes shfmt check fail. When editing this block, unindent them manually. -#+begin_src shell :tangle scripts/swarsel-install.sh +#+begin_src shell :tangle files/scripts/swarsel-install.sh set -eo pipefail target_config="chaostheatre" @@ -15144,7 +15059,7 @@ Autoformatting always puts the =EOF= with indentation, which makes shfmt check f writeShellApplication { inherit name; runtimeInputs = [ git ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -15153,7 +15068,7 @@ Autoformatting always puts the =EOF= with indentation, which makes shfmt check f :CUSTOM_ID: h:c98a7615-e5da-4f47-8ed1-2b2ea65519e9 :END: -#+begin_src shell :tangle scripts/swarsel-postinstall.sh +#+begin_src shell :tangle files/scripts/swarsel-postinstall.sh set -eo pipefail target_config="chaostheatre" @@ -15237,7 +15152,7 @@ Autoformatting always puts the =EOF= with indentation, which makes shfmt check f writeShellApplication { inherit name; runtimeInputs = [ git ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -15404,7 +15319,7 @@ Autoformatting always puts the =EOF= with indentation, which makes shfmt check f :CUSTOM_ID: h:154b6df4-dd50-4f60-9794-05a140d02994 :END: -#+begin_src shell :tangle scripts/project.sh +#+begin_src shell :tangle files/scripts/project.sh set -euo pipefail if [ ! -d "$(pwd)/.git" ]; then @@ -15418,7 +15333,7 @@ Autoformatting always puts the =EOF= with indentation, which makes shfmt check f { self, name, writeShellApplication }: writeShellApplication { inherit name; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -15449,7 +15364,7 @@ Autoformatting always puts the =EOF= with indentation, which makes shfmt check f A crude script to power on all displays that might be attached. Needed because sometimes displays do not awake from sleep. -#+begin_src shell :tangle scripts/swarsel-displaypower.sh +#+begin_src shell :tangle files/scripts/swarsel-displaypower.sh swaymsg "output * power on" > /dev/null 2>&1 || true swaymsg "output * dpms on" > /dev/null 2>&1 || true #+end_src @@ -15459,7 +15374,7 @@ A crude script to power on all displays that might be attached. Needed because s writeShellApplication { inherit name; runtimeInputs = [ sway ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src @@ -15659,7 +15574,7 @@ AppImage version of mgba in which the lua scripting works. This programs simply runs ssh-keygen on the last host that I tried to ssh into. I need this frequently when working with cloud-init usually. -#+begin_src shell :tangle scripts/sshrm.sh +#+begin_src shell :tangle files/scripts/sshrm.sh HISTFILE="$HOME"/.histfile last_ssh_cmd=$(grep -E "ssh " "$HISTFILE" | sed -E 's/^: [0-9]+:[0-9]+;//' | grep "^ssh " | tail -1) @@ -15678,7 +15593,7 @@ This programs simply runs ssh-keygen on the last host that I tried to ssh into. writeShellApplication { inherit name; runtimeInputs = [ openssh ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } #+end_src ** Profiles @@ -16382,7 +16297,7 @@ In the end, we need to restore those values to values that will work during norm Also packed into the hook function is the line =(fset 'epg-wait-for-status 'ignore)=. This line is needed at the end of the configuration in order to allow for my Yubikey to be used to encrypt and decrypt =.gpg= files. Without it, Emacs will just hang forever and basically crash. -#+begin_src emacs-lisp :tangle programs/emacs/early-init.el :mkdirp yes +#+begin_src emacs-lisp :tangle files/emacs/early-init.el :mkdirp yes (defvar swarsel-file-name-handler-alist file-name-handler-alist) (defvar swarsel-vc-handled-backends vc-handled-backends) @@ -16415,7 +16330,7 @@ We also make require immediate compilation of native code. For the =default-frame-alist=, I used to also set ='(right-divider-width . 4)= and ='(bottom-divider-width . 4)=, but I did not like the look of the divider bar and usually know my splits anyways, so this is no longer set. -#+begin_src emacs-lisp :tangle programs/emacs/early-init.el :mkdirp yes +#+begin_src emacs-lisp :tangle files/emacs/early-init.el :mkdirp yes (tool-bar-mode 0) (menu-bar-mode 0) (scroll-bar-mode 0) @@ -16464,7 +16379,7 @@ These keybinds exist to make Emacs work well in terminal mode. However, most of NOTE: To use these keybinds, you need to enclose the binding in angled brackets (=<>=). Then they can be used normally -#+begin_src emacs-lisp :tangle programs/emacs/early-init.el :mkdirp yes +#+begin_src emacs-lisp :tangle files/emacs/early-init.el :mkdirp yes (add-hook 'after-make-frame-functions @@ -19451,7 +19366,7 @@ This sets up the =dashboard=, which is really quite useless. But, it looks cool dashboard-set-footer nil dashboard-banner-logo-title "Welcome to SwarsEmacs!" dashboard-image-banner-max-height 300 - dashboard-startup-banner "~/.dotfiles/wallpaper/swarsel.png" + dashboard-startup-banner "~/.dotfiles/files/wallpaper/swarsel.png" dashboard-projects-backend 'projectile dashboard-projects-switch-function 'magit-status dashboard-set-navigator t @@ -19556,7 +19471,7 @@ This section now holds some of the configuration files that cannot be defined di On my server, I use a reduced, self-contained emacs configuration that only serves as an elfeed sync server. This is currently unused, however, I am keeping this in here for now as a reference. The big problem here was the bidirectional syncing using =bjm/elfeed-updater=. As I am using this both on a laptop client (using elfeed) as well as on a mobile phone (using elfeed-cljsrn over elfeed-web), I set up a Syncthing service to take care of the feeds as well as the db state. However, I could only either achieve changes propagating properly from the laptop to the server or from the phone to the server. Both would not work. This current state represents the state where from-laptop changes would propagate. To allow from-phone changes, change =(elfeed-db-load)= in =bjm/elfeed-updater= to =(elfeed-db-save)=. -#+begin_src emacs-lisp :tangle programs/emacs/server.el +#+begin_src emacs-lisp :tangle files/emacs/server.el (require 'package) (package-initialize nil) @@ -19648,7 +19563,7 @@ This is the configuration file for tridactyl, which provides keyboard-driven nav The =command= command can be supplied with a =-p= flag that will take a single argmuent which is exposed as =JS_ARG=. I use this in a function that switches to an open tab if it exists and otherwise creates it. -#+begin_src config :tangle programs/firefox/tridactyl/tridactylrc :mkdirp yes +#+begin_src config :tangle files/firefox/tridactyl/tridactylrc :mkdirp yes sanitise tridactyllocal tridactylsync @@ -19783,7 +19698,7 @@ autocmd DocStart vc-impimba-1.m.imp.ac.at/ui/webconsole mode ignore :PROPERTIES: :CUSTOM_ID: h:86f1fd9b-56ee-4fd2-8b35-9ea104d83df0 :END: -#+begin_src config :tangle programs/firefox/tridactyl/themes/swarsel.css :mkdirp yes +#+begin_src config :tangle files/firefox/tridactyl/themes/swarsel.css :mkdirp yes :root { @@ -19956,7 +19871,7 @@ autocmd DocStart vc-impimba-1.m.imp.ac.at/ui/webconsole mode ignore This is the stylesheet used by waybar. -#+begin_src css :tangle programs/waybar/style.css :mkdirp yes +#+begin_src css :tangle files/waybar/style.css :mkdirp yes @define-color foreground #fdf6e3; @define-color background #1a1a1a; @define-color background-alt #292b2e; @@ -20268,7 +20183,7 @@ This file defines a few workflows that I often need to run when working on my co :CUSTOM_ID: h:038feb42-6e1e-4b65-abe9-e26746b72b78 :END: -#+begin_src shell :tangle programs/config/.aspell.conf +#+begin_src shell :tangle files/config/.aspell.conf dict-dir /run/current-system/sw/lib/aspell #+end_src ** nix-plugins.patch @@ -20304,7 +20219,7 @@ index 3a0f90e..bb10f8b 100644 :CUSTOM_ID: h:bed316c9-47ed-494f-8375-998ef1315d7b :END: -#+begin_src shell :tangle programs/zellij/layouts/default.kdl.nix +#+begin_src shell :tangle files/zellij/layouts/default.kdl.nix { config, pkgs }: let inherit (config.lib.stylix) colors; @@ -20471,7 +20386,7 @@ in :CUSTOM_ID: h:ae07e867-fc17-4dd7-bd21-5886265308ee :END: -#+begin_src nix-ts :tangle programs/zellij/config.kdl.nix +#+begin_src nix-ts :tangle files/zellij/config.kdl.nix { config }: '' pane_frames false @@ -20819,7 +20734,7 @@ in :CUSTOM_ID: h:0124a4eb-4ea3-455c-939d-ba4584c703af :END: -#+begin_src shell :tangle programs/vieb/viebrc +#+begin_src shell :tangle files/vieb/viebrc " Options set adblocker=update set adblockernotifications=all @@ -21023,7 +20938,7 @@ set searchwords+=hm~https://home-manager-options.extranix.com/?query=%s :CUSTOM_ID: h:69ea5818-4ebb-436a-a31a-6a2348cf215c :END: -#+begin_src shell :tangle programs/swayidle/config +#+begin_src shell :tangle files/swayidle/config timeout 300 'swaylock -f --screenshots --clock --effect-blur 7x5 --effect-vignette 0.5:0.5 --fade-in 0.2' timeout 600 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' before-sleep 'swaylock -f --screenshots --clock --effect-blur 7x5 --effect-vignette 0.5:0.5 --fade-in 0.2' @@ -21033,7 +20948,7 @@ before-sleep 'swaylock -f --screenshots --clock --effect-blur 7x5 --effect-vigne :CUSTOM_ID: h:2e9b84d7-cb18-4e74-83f8-65ada11a8911 :END: -#+begin_src css :tangle programs/stylix/swarsel.yaml :mkdirp yes +#+begin_src css :tangle files/stylix/swarsel.yaml :mkdirp yes # scheme: "better-contrast" author: "Swarsel" base00: "1D252C" # #1d252c passt @@ -21077,11 +20992,11 @@ base0F: "5EC4FF" # #5EC4FF passt The double source block is intended here to circumvent a org-babel convenience where the first n empty lines of each source block are not taken into the final file. For the .gitmessage I want an empty newline to type into, so this is what I use to achieve that. -#+begin_src shell :tangle programs/git/.gitmessage +#+begin_src shell :tangle files/git/.gitmessage #+end_src -#+begin_src shell :tangle programs/git/.gitmessage +#+begin_src shell :tangle files/git/.gitmessage # max. 50 chars is here: # # [optional scope]: # types: feat, fix, build, chore, ci, docs, style, refactor, perf, test @@ -21097,7 +21012,7 @@ The double source block is intended here to circumvent a org-babel convenience w :CUSTOM_ID: h:a2990def-9a2a-491b-9fee-3057dc324c3c :END: -#+begin_src css :tangle programs/firefox/chrome/userChrome.css :mkdirp yes +#+begin_src css :tangle files/firefox/chrome/userChrome.css :mkdirp yes /* Source file https://github.com/MrOtherGuy/firefox-csshacks/tree/master/chrome/autohide_toolbox.css made available under Mozilla Public License v. 2.0 See the above repository for updates as well as full license text. */ @@ -21325,7 +21240,7 @@ See the above repository for updates as well as full license text. */ :CUSTOM_ID: h:fefc38d9-b3fb-42c5-8a73-ca363e898bb9 :END: -#+begin_src nix-ts :tangle templates/default/flake.nix +#+begin_src nix-ts :tangle files/templates/default/flake.nix { description = "General purpose Flake"; @@ -21362,7 +21277,7 @@ See the above repository for updates as well as full license text. */ :CUSTOM_ID: h:c54fc65b-91ef-4f8f-b0d5-cc0c3cb92b53 :END: -#+begin_src nix-ts :tangle templates/cpp/flake.nix +#+begin_src nix-ts :tangle files/templates/cpp/flake.nix # heavily inspired by https://github.com/nulladmin1/nix-flake-templates/blob/main/cpp-cmake/flake.nix { description = "C++ Flake"; @@ -21431,7 +21346,7 @@ See the above repository for updates as well as full license text. */ :CUSTOM_ID: h:def2d654-e8da-4d8a-8958-b59a60d019f5 :END: -#+begin_src nix-ts :tangle templates/go/flake.nix +#+begin_src nix-ts :tangle files/templates/go/flake.nix # heavily inspired by https://github.com/nulladmin1/nix-flake-templates/blob/main/go-nix/flake.nix { description = "Go Flake"; @@ -21490,7 +21405,7 @@ See the above repository for updates as well as full license text. */ :CUSTOM_ID: h:adccea10-6c72-46aa-8c67-5e06b7606c71 :END: -#+begin_src nix-ts :tangle templates/latex/flake.nix +#+begin_src nix-ts :tangle files/templates/latex/flake.nix # This template is based on https://github.com/Leixb/latex-template/tree/master { description = "LaTeX Flake"; @@ -21575,7 +21490,7 @@ See the above repository for updates as well as full license text. */ :CUSTOM_ID: h:1a918c8d-08b4-4474-8d34-3da502081a16 :END: -#+begin_src nix-ts :tangle templates/python/flake.nix +#+begin_src nix-ts :tangle files/templates/python/flake.nix # based on https://github.com/pyproject-nix/uv2nix/tree/master/templates/hello-world { description = "Python flake using uv2nix"; @@ -21781,7 +21696,7 @@ See the above repository for updates as well as full license text. */ :CUSTOM_ID: h:c03663fd-f7bd-4054-9075-5dacaf2abf76 :END: -#+begin_src nix-ts :tangle templates/rust/flake.nix +#+begin_src nix-ts :tangle files/templates/rust/flake.nix # heavily inspired by https://github.com/nulladmin1/nix-flake-templates/blob/main/rust-fenix-naersk/flake.nix { description = "Rust Flake using Fenix and Naersk"; @@ -21912,8 +21827,8 @@ Here lies defined the readme for GitHub and Forgejo: - [SwarselSystems.org](../SwarselSystems.org) - [flake.nix](../flake.nix) - - [early-init.el](../programs/emacs/early-init.el) - - [init.el](../programs/emacs/init.el) + - [early-init.el](../files/emacs/early-init.el) + - [init.el](../files/emacs/init.el) ### Getting started diff --git a/programs/config/.aspell.conf b/files/config/.aspell.conf similarity index 100% rename from programs/config/.aspell.conf rename to files/config/.aspell.conf diff --git a/programs/emacs/early-init.el b/files/emacs/early-init.el similarity index 100% rename from programs/emacs/early-init.el rename to files/emacs/early-init.el diff --git a/programs/emacs/init.el b/files/emacs/init.el similarity index 99% rename from programs/emacs/init.el rename to files/emacs/init.el index 708d71c..1dbe854 100644 --- a/programs/emacs/init.el +++ b/files/emacs/init.el @@ -1641,7 +1641,7 @@ create a new one." dashboard-set-footer nil dashboard-banner-logo-title "Welcome to SwarsEmacs!" dashboard-image-banner-max-height 300 - dashboard-startup-banner "~/.dotfiles/wallpaper/swarsel.png" + dashboard-startup-banner "~/.dotfiles/files/wallpaper/swarsel.png" dashboard-projects-backend 'projectile dashboard-projects-switch-function 'magit-status dashboard-set-navigator t diff --git a/programs/emacs/server.el b/files/emacs/server.el similarity index 100% rename from programs/emacs/server.el rename to files/emacs/server.el diff --git a/programs/firefox/chrome/userChrome.css b/files/firefox/chrome/userChrome.css similarity index 100% rename from programs/firefox/chrome/userChrome.css rename to files/firefox/chrome/userChrome.css diff --git a/programs/firefox/tridactyl/themes/swarsel.css b/files/firefox/tridactyl/themes/swarsel.css similarity index 100% rename from programs/firefox/tridactyl/themes/swarsel.css rename to files/firefox/tridactyl/themes/swarsel.css diff --git a/programs/firefox/tridactyl/tridactylrc b/files/firefox/tridactyl/tridactylrc similarity index 100% rename from programs/firefox/tridactyl/tridactylrc rename to files/firefox/tridactyl/tridactylrc diff --git a/programs/git/.gitmessage b/files/git/.gitmessage similarity index 100% rename from programs/git/.gitmessage rename to files/git/.gitmessage diff --git a/scripts/command-not-found.sh b/files/scripts/command-not-found.sh similarity index 100% rename from scripts/command-not-found.sh rename to files/scripts/command-not-found.sh diff --git a/scripts/devShell/benchmark b/files/scripts/devShell/benchmark similarity index 100% rename from scripts/devShell/benchmark rename to files/scripts/devShell/benchmark diff --git a/scripts/devShell/compile b/files/scripts/devShell/compile similarity index 100% rename from scripts/devShell/compile rename to files/scripts/devShell/compile diff --git a/scripts/e.sh b/files/scripts/e.sh similarity index 100% rename from scripts/e.sh rename to files/scripts/e.sh diff --git a/scripts/fs-diff.sh b/files/scripts/fs-diff.sh similarity index 100% rename from scripts/fs-diff.sh rename to files/scripts/fs-diff.sh diff --git a/scripts/opacitytoggle.sh b/files/scripts/opacitytoggle.sh similarity index 100% rename from scripts/opacitytoggle.sh rename to files/scripts/opacitytoggle.sh diff --git a/scripts/pass-fuzzel.sh b/files/scripts/pass-fuzzel.sh similarity index 100% rename from scripts/pass-fuzzel.sh rename to files/scripts/pass-fuzzel.sh diff --git a/scripts/project.sh b/files/scripts/project.sh similarity index 100% rename from scripts/project.sh rename to files/scripts/project.sh diff --git a/scripts/screenshare.sh b/files/scripts/screenshare.sh similarity index 100% rename from scripts/screenshare.sh rename to files/scripts/screenshare.sh diff --git a/scripts/sshrm.sh b/files/scripts/sshrm.sh similarity index 100% rename from scripts/sshrm.sh rename to files/scripts/sshrm.sh diff --git a/scripts/swarsel-bootstrap.sh b/files/scripts/swarsel-bootstrap.sh similarity index 99% rename from scripts/swarsel-bootstrap.sh rename to files/scripts/swarsel-bootstrap.sh index 4636428..674a3b0 100644 --- a/scripts/swarsel-bootstrap.sh +++ b/files/scripts/swarsel-bootstrap.sh @@ -1,4 +1,4 @@ -# highly inspired by https://github.com/EmergentMind/nix-config/blob/dev/scripts/bootstrap-nixos.sh +# highly inspired by https://github.com/EmergentMind/nix-config/blob/dev/files/scripts/bootstrap-nixos.sh set -eo pipefail target_hostname="" diff --git a/scripts/swarsel-displaypower.sh b/files/scripts/swarsel-displaypower.sh similarity index 100% rename from scripts/swarsel-displaypower.sh rename to files/scripts/swarsel-displaypower.sh diff --git a/scripts/swarsel-install.sh b/files/scripts/swarsel-install.sh similarity index 100% rename from scripts/swarsel-install.sh rename to files/scripts/swarsel-install.sh diff --git a/scripts/swarsel-postinstall.sh b/files/scripts/swarsel-postinstall.sh similarity index 100% rename from scripts/swarsel-postinstall.sh rename to files/scripts/swarsel-postinstall.sh diff --git a/scripts/swarsel-rebuild.sh b/files/scripts/swarsel-rebuild.sh similarity index 100% rename from scripts/swarsel-rebuild.sh rename to files/scripts/swarsel-rebuild.sh diff --git a/scripts/swarselcheck.sh b/files/scripts/swarselcheck.sh similarity index 100% rename from scripts/swarselcheck.sh rename to files/scripts/swarselcheck.sh diff --git a/scripts/swarselzellij.sh b/files/scripts/swarselzellij.sh similarity index 100% rename from scripts/swarselzellij.sh rename to files/scripts/swarselzellij.sh diff --git a/scripts/waybarupdate.sh b/files/scripts/waybarupdate.sh similarity index 100% rename from scripts/waybarupdate.sh rename to files/scripts/waybarupdate.sh diff --git a/programs/stylix/swarsel.yaml b/files/stylix/swarsel.yaml similarity index 100% rename from programs/stylix/swarsel.yaml rename to files/stylix/swarsel.yaml diff --git a/programs/swayidle/config b/files/swayidle/config similarity index 100% rename from programs/swayidle/config rename to files/swayidle/config diff --git a/templates/cpp/.envrc b/files/templates/cpp/.envrc similarity index 100% rename from templates/cpp/.envrc rename to files/templates/cpp/.envrc diff --git a/templates/cpp/.gitignore b/files/templates/cpp/.gitignore similarity index 100% rename from templates/cpp/.gitignore rename to files/templates/cpp/.gitignore diff --git a/templates/cpp/CMakeLists.txt b/files/templates/cpp/CMakeLists.txt similarity index 100% rename from templates/cpp/CMakeLists.txt rename to files/templates/cpp/CMakeLists.txt diff --git a/templates/cpp/flake.nix b/files/templates/cpp/flake.nix similarity index 100% rename from templates/cpp/flake.nix rename to files/templates/cpp/flake.nix diff --git a/templates/cpp/src/CMakeLists.txt b/files/templates/cpp/src/CMakeLists.txt similarity index 100% rename from templates/cpp/src/CMakeLists.txt rename to files/templates/cpp/src/CMakeLists.txt diff --git a/templates/cpp/src/name.cpp b/files/templates/cpp/src/name.cpp similarity index 100% rename from templates/cpp/src/name.cpp rename to files/templates/cpp/src/name.cpp diff --git a/templates/default/.envrc b/files/templates/default/.envrc similarity index 100% rename from templates/default/.envrc rename to files/templates/default/.envrc diff --git a/templates/default/flake.nix b/files/templates/default/flake.nix similarity index 100% rename from templates/default/flake.nix rename to files/templates/default/flake.nix diff --git a/templates/go/.envrc b/files/templates/go/.envrc similarity index 100% rename from templates/go/.envrc rename to files/templates/go/.envrc diff --git a/templates/go/flake.nix b/files/templates/go/flake.nix similarity index 100% rename from templates/go/flake.nix rename to files/templates/go/flake.nix diff --git a/templates/go/go.mod b/files/templates/go/go.mod similarity index 100% rename from templates/go/go.mod rename to files/templates/go/go.mod diff --git a/templates/go/name/name.go b/files/templates/go/name/name.go similarity index 100% rename from templates/go/name/name.go rename to files/templates/go/name/name.go diff --git a/templates/hosts/nixos/default.nix b/files/templates/hosts/nixos/default.nix similarity index 95% rename from templates/hosts/nixos/default.nix rename to files/templates/hosts/nixos/default.nix index 4d4ecf9..0405388 100644 --- a/templates/hosts/nixos/default.nix +++ b/files/templates/hosts/nixos/default.nix @@ -39,7 +39,7 @@ in swarselsystems = lib.recursiveUpdate { - wallpaper = self + /wallpaper/lenovowp.png; + wallpaper = self + /files/wallpaper/lenovowp.png; hasBluetooth = true; hasFingerprint = true; isImpermanence = true; diff --git a/templates/hosts/nixos/disk-config.nix b/files/templates/hosts/nixos/disk-config.nix similarity index 100% rename from templates/hosts/nixos/disk-config.nix rename to files/templates/hosts/nixos/disk-config.nix diff --git a/templates/latex/.envrc b/files/templates/latex/.envrc similarity index 100% rename from templates/latex/.envrc rename to files/templates/latex/.envrc diff --git a/templates/latex/.gitignore b/files/templates/latex/.gitignore similarity index 100% rename from templates/latex/.gitignore rename to files/templates/latex/.gitignore diff --git a/templates/latex/.latexmkrc b/files/templates/latex/.latexmkrc similarity index 100% rename from templates/latex/.latexmkrc rename to files/templates/latex/.latexmkrc diff --git a/templates/latex/000-main.tex b/files/templates/latex/000-main.tex similarity index 100% rename from templates/latex/000-main.tex rename to files/templates/latex/000-main.tex diff --git a/templates/latex/001-preamble.tex b/files/templates/latex/001-preamble.tex similarity index 100% rename from templates/latex/001-preamble.tex rename to files/templates/latex/001-preamble.tex diff --git a/templates/latex/005-titlepage.tex b/files/templates/latex/005-titlepage.tex similarity index 100% rename from templates/latex/005-titlepage.tex rename to files/templates/latex/005-titlepage.tex diff --git a/templates/latex/010-introduction.tex b/files/templates/latex/010-introduction.tex similarity index 100% rename from templates/latex/010-introduction.tex rename to files/templates/latex/010-introduction.tex diff --git a/templates/latex/990-appendix.tex b/files/templates/latex/990-appendix.tex similarity index 100% rename from templates/latex/990-appendix.tex rename to files/templates/latex/990-appendix.tex diff --git a/templates/latex/biblio.bib b/files/templates/latex/biblio.bib similarity index 100% rename from templates/latex/biblio.bib rename to files/templates/latex/biblio.bib diff --git a/templates/latex/build-document.nix b/files/templates/latex/build-document.nix similarity index 100% rename from templates/latex/build-document.nix rename to files/templates/latex/build-document.nix diff --git a/templates/latex/code/P15601_en_Harrichu_y_and_the_maze.cc b/files/templates/latex/code/P15601_en_Harrichu_y_and_the_maze.cc similarity index 100% rename from templates/latex/code/P15601_en_Harrichu_y_and_the_maze.cc rename to files/templates/latex/code/P15601_en_Harrichu_y_and_the_maze.cc diff --git a/templates/latex/figures/Professortocat_v2.png b/files/templates/latex/figures/Professortocat_v2.png similarity index 100% rename from templates/latex/figures/Professortocat_v2.png rename to files/templates/latex/figures/Professortocat_v2.png diff --git a/templates/latex/figures/institution-logo.pdf b/files/templates/latex/figures/institution-logo.pdf similarity index 100% rename from templates/latex/figures/institution-logo.pdf rename to files/templates/latex/figures/institution-logo.pdf diff --git a/templates/latex/flake.nix b/files/templates/latex/flake.nix similarity index 100% rename from templates/latex/flake.nix rename to files/templates/latex/flake.nix diff --git a/templates/python/.envrc b/files/templates/python/.envrc similarity index 100% rename from templates/python/.envrc rename to files/templates/python/.envrc diff --git a/templates/python/.gitignore b/files/templates/python/.gitignore similarity index 100% rename from templates/python/.gitignore rename to files/templates/python/.gitignore diff --git a/templates/python/README.md b/files/templates/python/README.md similarity index 100% rename from templates/python/README.md rename to files/templates/python/README.md diff --git a/templates/python/flake.nix b/files/templates/python/flake.nix similarity index 100% rename from templates/python/flake.nix rename to files/templates/python/flake.nix diff --git a/templates/python/pyproject.toml b/files/templates/python/pyproject.toml similarity index 100% rename from templates/python/pyproject.toml rename to files/templates/python/pyproject.toml diff --git a/templates/python/src/name/__init__.py b/files/templates/python/src/name/__init__.py similarity index 100% rename from templates/python/src/name/__init__.py rename to files/templates/python/src/name/__init__.py diff --git a/templates/python/tests/test_hello.py b/files/templates/python/tests/test_hello.py similarity index 100% rename from templates/python/tests/test_hello.py rename to files/templates/python/tests/test_hello.py diff --git a/templates/python/uv.lock b/files/templates/python/uv.lock similarity index 100% rename from templates/python/uv.lock rename to files/templates/python/uv.lock diff --git a/templates/rust/.envrc b/files/templates/rust/.envrc similarity index 100% rename from templates/rust/.envrc rename to files/templates/rust/.envrc diff --git a/templates/rust/Cargo.lock b/files/templates/rust/Cargo.lock similarity index 100% rename from templates/rust/Cargo.lock rename to files/templates/rust/Cargo.lock diff --git a/templates/rust/Cargo.toml b/files/templates/rust/Cargo.toml similarity index 100% rename from templates/rust/Cargo.toml rename to files/templates/rust/Cargo.toml diff --git a/templates/rust/flake.nix b/files/templates/rust/flake.nix similarity index 100% rename from templates/rust/flake.nix rename to files/templates/rust/flake.nix diff --git a/templates/rust/src/main.rs b/files/templates/rust/src/main.rs similarity index 100% rename from templates/rust/src/main.rs rename to files/templates/rust/src/main.rs diff --git a/nix/topology-images/DELL-C2665dnf.png b/files/topology-images/DELL-C2665dnf.png similarity index 100% rename from nix/topology-images/DELL-C2665dnf.png rename to files/topology-images/DELL-C2665dnf.png diff --git a/nix/topology-images/TL-SG1005D.png b/files/topology-images/TL-SG1005D.png similarity index 100% rename from nix/topology-images/TL-SG1005D.png rename to files/topology-images/TL-SG1005D.png diff --git a/nix/topology-images/TL-SG108.png b/files/topology-images/TL-SG108.png similarity index 100% rename from nix/topology-images/TL-SG108.png rename to files/topology-images/TL-SG108.png diff --git a/nix/topology-images/ankisync.png b/files/topology-images/ankisync.png similarity index 100% rename from nix/topology-images/ankisync.png rename to files/topology-images/ankisync.png diff --git a/nix/topology-images/croc.png b/files/topology-images/croc.png similarity index 100% rename from nix/topology-images/croc.png rename to files/topology-images/croc.png diff --git a/nix/topology-images/firefly-iii.png b/files/topology-images/firefly-iii.png similarity index 100% rename from nix/topology-images/firefly-iii.png rename to files/topology-images/firefly-iii.png diff --git a/nix/topology-images/freshrss.png b/files/topology-images/freshrss.png similarity index 100% rename from nix/topology-images/freshrss.png rename to files/topology-images/freshrss.png diff --git a/nix/topology-images/huawei.png b/files/topology-images/huawei.png similarity index 100% rename from nix/topology-images/huawei.png rename to files/topology-images/huawei.png diff --git a/nix/topology-images/hunsn.png b/files/topology-images/hunsn.png similarity index 100% rename from nix/topology-images/hunsn.png rename to files/topology-images/hunsn.png diff --git a/nix/topology-images/kavita.png b/files/topology-images/kavita.png similarity index 100% rename from nix/topology-images/kavita.png rename to files/topology-images/kavita.png diff --git a/nix/topology-images/koillection.png b/files/topology-images/koillection.png similarity index 100% rename from nix/topology-images/koillection.png rename to files/topology-images/koillection.png diff --git a/nix/topology-images/microbin.png b/files/topology-images/microbin.png similarity index 100% rename from nix/topology-images/microbin.png rename to files/topology-images/microbin.png diff --git a/nix/topology-images/mpd.png b/files/topology-images/mpd.png similarity index 100% rename from nix/topology-images/mpd.png rename to files/topology-images/mpd.png diff --git a/nix/topology-images/nintendo-switch.png b/files/topology-images/nintendo-switch.png similarity index 100% rename from nix/topology-images/nintendo-switch.png rename to files/topology-images/nintendo-switch.png diff --git a/nix/topology-images/pc.png b/files/topology-images/pc.png similarity index 100% rename from nix/topology-images/pc.png rename to files/topology-images/pc.png diff --git a/nix/topology-images/readarr.png b/files/topology-images/readarr.png similarity index 100% rename from nix/topology-images/readarr.png rename to files/topology-images/readarr.png diff --git a/nix/topology-images/shlink.png b/files/topology-images/shlink.png similarity index 100% rename from nix/topology-images/shlink.png rename to files/topology-images/shlink.png diff --git a/programs/vieb/viebrc b/files/vieb/viebrc similarity index 100% rename from programs/vieb/viebrc rename to files/vieb/viebrc diff --git a/wallpaper/botanicswp.png b/files/wallpaper/botanicswp.png similarity index 100% rename from wallpaper/botanicswp.png rename to files/wallpaper/botanicswp.png diff --git a/wallpaper/lenovowp.png b/files/wallpaper/lenovowp.png similarity index 100% rename from wallpaper/lenovowp.png rename to files/wallpaper/lenovowp.png diff --git a/wallpaper/navidrome.png b/files/wallpaper/navidrome.png similarity index 100% rename from wallpaper/navidrome.png rename to files/wallpaper/navidrome.png diff --git a/wallpaper/op6wp.png b/files/wallpaper/op6wp.png similarity index 100% rename from wallpaper/op6wp.png rename to files/wallpaper/op6wp.png diff --git a/wallpaper/serverwp.png b/files/wallpaper/serverwp.png similarity index 100% rename from wallpaper/serverwp.png rename to files/wallpaper/serverwp.png diff --git a/wallpaper/standwp.png b/files/wallpaper/standwp.png similarity index 100% rename from wallpaper/standwp.png rename to files/wallpaper/standwp.png diff --git a/wallpaper/surfacewp.png b/files/wallpaper/surfacewp.png similarity index 100% rename from wallpaper/surfacewp.png rename to files/wallpaper/surfacewp.png diff --git a/wallpaper/swarsel.png b/files/wallpaper/swarsel.png similarity index 100% rename from wallpaper/swarsel.png rename to files/wallpaper/swarsel.png diff --git a/wallpaper/user.png b/files/wallpaper/user.png similarity index 100% rename from wallpaper/user.png rename to files/wallpaper/user.png diff --git a/programs/waybar/style.css b/files/waybar/style.css similarity index 100% rename from programs/waybar/style.css rename to files/waybar/style.css diff --git a/programs/zellij/config.kdl.nix b/files/zellij/config.kdl.nix similarity index 100% rename from programs/zellij/config.kdl.nix rename to files/zellij/config.kdl.nix diff --git a/programs/zellij/layouts/default.kdl.nix b/files/zellij/layouts/default.kdl.nix similarity index 100% rename from programs/zellij/layouts/default.kdl.nix rename to files/zellij/layouts/default.kdl.nix diff --git a/flake.nix b/flake.nix index cee0490..863994f 100644 --- a/flake.nix +++ b/flake.nix @@ -103,6 +103,7 @@ ./nix/templates.nix ./nix/formatter.nix ./nix/modules.nix + ./nix/iso.nix ]; systems = [ "x86_64-linux" diff --git a/hosts/home/default/default.nix b/hosts/home/default/default.nix index 99bf5ba..9f2b3e4 100644 --- a/hosts/home/default/default.nix +++ b/hosts/home/default/default.nix @@ -23,7 +23,7 @@ }; programs.zsh.initContent = " - export GPG_TTY=\"$(tty)\" + export GPG_TTY=\"$(tty)\" export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) gpgconf --launch gpg-agent "; @@ -31,7 +31,7 @@ swarselsystems = { isLaptop = true; isNixos = false; - wallpaper = self + /wallpaper/surfacewp.png; + wallpaper = self + /files/wallpaper/surfacewp.png; }; } diff --git a/hosts/nixos/chaostheatre/default.nix b/hosts/nixos/chaostheatre/default.nix index 9313d13..873b270 100644 --- a/hosts/nixos/chaostheatre/default.nix +++ b/hosts/nixos/chaostheatre/default.nix @@ -50,7 +50,7 @@ in swarselsystems = lib.recursiveUpdate { info = "~SwarselSystems~ demo host"; - wallpaper = self + /wallpaper/lenovowp.png; + wallpaper = self + /files/wallpaper/lenovowp.png; initialSetup = true; isImpermanence = true; isCrypted = true; diff --git a/hosts/nixos/chaostheatre/disk-config.nix b/hosts/nixos/chaostheatre/disk-config.nix index 5423b03..5131677 100644 --- a/hosts/nixos/chaostheatre/disk-config.nix +++ b/hosts/nixos/chaostheatre/disk-config.nix @@ -81,7 +81,7 @@ in content = { inherit type subvolumes extraArgs; postCreateHook = lib.mkIf config.swarselsystems.isImpermanence '' - MNTPOINT=$(mktemp -d) + MNTPOINT=$(mktemp -d) mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5 trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank @@ -105,7 +105,7 @@ in content = { inherit type subvolumes extraArgs; postCreateHook = lib.mkIf config.swarselsystems.isImpermanence '' - MNTPOINT=$(mktemp -d) + MNTPOINT=$(mktemp -d) mount "/dev/mapper/cryptroot" "$MNTPOINT" -o subvolid=5 trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank diff --git a/hosts/nixos/nbl-imba-2/default.nix b/hosts/nixos/nbl-imba-2/default.nix index c523221..91229a1 100644 --- a/hosts/nixos/nbl-imba-2/default.nix +++ b/hosts/nixos/nbl-imba-2/default.nix @@ -27,7 +27,7 @@ in { info = "Framework Laptop 16, 7940HS, RX7700S, 64GB RAM"; firewall = lib.mkForce true; - wallpaper = self + /wallpaper/lenovowp.png; + wallpaper = self + /files/wallpaper/lenovowp.png; hasBluetooth = true; hasFingerprint = true; isImpermanence = false; diff --git a/hosts/nixos/toto/default.nix b/hosts/nixos/toto/default.nix index 3c99422..47064fa 100644 --- a/hosts/nixos/toto/default.nix +++ b/hosts/nixos/toto/default.nix @@ -58,7 +58,7 @@ in swarselsystems = lib.recursiveUpdate { info = "~SwarselSystems~ remote install helper"; - wallpaper = self + /wallpaper/lenovowp.png; + wallpaper = self + /files/wallpaper/lenovowp.png; isImpermanence = true; isCrypted = false; isSecureBoot = false; diff --git a/index.html b/index.html index d9c88f3..2669981 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + SwarselSystems: NixOS + Emacs Configuration @@ -213,16 +213,24 @@
  • 2. flake.nix
  • 3. System @@ -293,282 +301,271 @@
  • -
  • 3.2. Additions and modifications +
  • 3.2. NixOS
  • -
  • 3.2.4. Library functions
  • -
  • 3.2.5. Auxiliary files +
  • 3.3. Home-manager
  • -
  • 3.3. NixOS +
  • 3.4. Packages @@ -1085,7 +1082,7 @@ Here I give a brief overview over the hostmachines that I am using. This is held |🚪 **DM** | [greetd](https://github.com/Swarsel/.dotfiles/tree/main/modules/nixos/common/login.nix) | |🪟 **WM** | [SwayFX](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/sway.nix) | |⛩️ **Bar** | [Waybar](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/waybar.nix) | -|✒️ **Editor** | [Emacs](https://github.com/Swarsel/.dotfiles/tree/main/programs/emacs/init.el) | +|✒️ **Editor** | [Emacs](https://github.com/Swarsel/.dotfiles/tree/main/files/emacs/init.el) | |🖥️ **Terminal**| [Kitty](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/kitty.nix) | |🚀 **Launcher**| [Fuzzel](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/fuzzel.nix) | |🚨 **Alerts** | [Mako](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/mako.nix) | @@ -1135,7 +1132,7 @@ Handling the flake.nix file used to be a bit of a chore, since it felt like writ

    -These blocks are later inserted here: flake.nix template. Adding new flake inputs is very easy, you just add them to Inputs & Inputs@Outputs first by name in the first source-block, and then the path in the second source-block. Any variables to be set for the host configuration are done in let, and the specific setup is done in either nixosConfigurations (for NixOS systems), homeConfigurations (for home-manager systems), or nixOnDroidConfigurations (for Nix on Android) and darwinConfigurations (for Darwin systems, also known as Macs). There also used to be a [BROKEN LINK: h:6a08495a-8566-4bb5-9fac-b03df01f6c81] section that used to define a Proxmox LXC image when I was still using Proxmox as my main server. An example of the repository at that time would be acc0ad6: Add several NixOS hosts on Proxmox and Oracle Cloud. +These blocks are later inserted here: flake.nix template. Adding new flake inputs is very easy, you just add them to [BROKEN LINK: h:8a411ee2-a58e-4b5b-99bd-4ba772f8f0a2] first by name in the first source-block, and then the path in the second source-block. Any variables to be set for the host configuration are done in [BROKEN LINK: h:df0072bc-853f-438f-bd85-bfc869501015], and the specific setup is done in either [BROKEN LINK: h:9c9b9e3b-8771-44fa-ba9e-5056ae809655] (for NixOS systems), [BROKEN LINK: h:f881aa05-a670-48dd-a57b-2916abdcb692] (for home-manager systems), or [BROKEN LINK: h:5f6ef553-59f9-4239-b6f3-63d33b57f335] (for Nix on Android) and [BROKEN LINK: h:f881aa05-a670-48dd-a57b-2916abdcb692] (for Darwin systems, also known as Macs). There also used to be a [BROKEN LINK: h:6a08495a-8566-4bb5-9fac-b03df01f6c81] section that used to define a Proxmox LXC image when I was still using Proxmox as my main server. An example of the repository at that time would be acc0ad6: Add several NixOS hosts on Proxmox and Oracle Cloud.

    @@ -1157,305 +1154,31 @@ In the start, I enable some public cache repositories. This saves some time duri In outputs = inputs@ [...], the inputs@ makes it so that all inputs are automatically passed to the outputs and can be called as inputs.<name>, whereas explicit arguments may just be called by using <name>. For most flakes this is fully sufficient, as they do not need to be called often and it saves me maintainance effort with this file.

    -
    -
    {
    -  description = "SwarseFlake - Nix Flake for all SwarselSystems";
    +

    +In this section I am creating some attributes that define general concepts of my configuration: +

    - nixConfig = { - extra-substituters = [ - "https://nix-community.cachix.org" - "https://cache.ngi0.nixos.org/" - ]; - extra-trusted-public-keys = [ - "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" - "cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=" - ]; - }; - inputs = { +
      +
    • nixosModules imports self-defined options that I only want to use on NixOS systems. All modules are held as separately as possible, to allow for easier sharing with other people mostly.
    • +
    • homeModules imports modules that are to be used on NixOS and non-NixOS systems. These are mostly used to define outputs (monitors), keyboards and special commands for machines.
    • +
    • packages holds packages that I am building myself. These are mostly shell scripts, but also a few others such as AppImages and firefox addons.
    • +
    • devShells provides a development shell that can be used as a bootstrap for new installs using nix develop while inside the flake directory. It received an overhaul in 0a6cf0e feat: add checks to devShell, since when it is handled using forAllSystems and now including pre-commit-hook checks.
    • +
    • formatter provides the formatter that is to be used on .nix files. It can be called by using nix fmt.
    • +
    • check provides the pre-commit-hook checks that I have explained in [BROKEN LINK: h:cbd5002c-e0fa-434a-951b-e05b179e4e3f].
    • +
    • +overlays imports a few community overlays (such as the emacs-overlay) and also three overlays of my own: +

      +
        +
      1. additions holds derivations that I am adding myself to nixpkgs - i.e. this is where the packages defined in /pkgs get added to nixpkgs.
      2. +
      3. modifications holds derivations that I have performed overrides on. The list of interesting attribute overrides can be found by looking at the source code of a derivation and looking at the start of the file for lines of the form <name> ? <val>. But this can also be used to, for example, fetch a different version of a package instead.
      4. +
      5. nixpkgs-stable holds the newest version of stable nixpkgs. I only use this on packages that seem broken on unstable, which are not many.
      6. +
      7. zjstatus holds some options for zellij, but I have stopped using it since I prefer tmux.
      8. +
      +

      +They are defined in [BROKEN LINK: h:5e3e21e0-57af-4dad-b32f-6400af9b7aab]. The way this is handled was simplified in 647a2ae feat: simplify overlay structure; however, the old structure might be easier to understand as a reference. +

    • +
    - nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; - nixpkgs-kernel.url = "github:NixOS/nixpkgs/063f43f2dbdef86376cc29ad646c45c46e93234c?narHash=sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o%3D"; #specifically pinned for kernel version - nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.05"; - nixpkgs-stable24_05.url = "github:NixOS/nixpkgs/nixos-24.05"; - nixpkgs-stable24_11.url = "github:NixOS/nixpkgs/nixos-24.11"; - systems.url = "github:nix-systems/default"; - home-manager = { - url = "github:nix-community/home-manager"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - emacs-overlay = { - url = "github:nix-community/emacs-overlay"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - nur.url = "github:nix-community/NUR"; - nixgl.url = "github:guibou/nixGL"; - stylix.url = "github:danth/stylix"; - sops-nix.url = "github:Mic92/sops-nix"; - lanzaboote.url = "github:nix-community/lanzaboote"; - nix-on-droid = { - url = "github:nix-community/nix-on-droid/release-24.05"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - nixos-generators = { - url = "github:nix-community/nixos-generators"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - nixos-hardware = { - url = "github:NixOS/nixos-hardware/master"; - }; - nix-alien = { - url = "github:thiagokokada/nix-alien"; - }; - nswitch-rcm-nix = { - url = "github:Swarsel/nswitch-rcm-nix"; - }; - nix-index-database = { - url = "github:nix-community/nix-index-database"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - disko = { - url = "github:nix-community/disko"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - impermanence.url = "github:nix-community/impermanence"; - zjstatus = { - url = "github:dj95/zjstatus"; - }; - fw-fanctrl = { - url = "github:TamtamHero/fw-fanctrl/packaging/nix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - nix-darwin = { - url = "github:lnl7/nix-darwin"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - pre-commit-hooks = { - url = "github:cachix/git-hooks.nix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - nix-secrets = { - url = "git+ssh://git@github.com/Swarsel/nix-secrets.git?ref=main&shallow=1"; - flake = false; - inputs = { }; - }; - vbc-nix = { - url = "git+ssh://git@github.com/vbc-it/vbc-nix.git?ref=main"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - nix-topology.url = "github:oddlama/nix-topology"; - flake-parts.url = "github:hercules-ci/flake-parts"; - }; - outputs = - inputs@{ self - , nixpkgs - , home-manager - , systems - , ... - }: - let - - inherit (self) outputs; - lib = (nixpkgs.lib // home-manager.lib).extend (_: _: { swarselsystems = import ./lib { inherit self lib inputs outputs systems; }; }); - - in - inputs.flake-parts.lib.mkFlake { inherit inputs; } { - imports = [ - ./nix/globals.nix - ]; - flake = { config, ... }: - let - - inherit (self) outputs; - lib = (nixpkgs.lib // home-manager.lib).extend (_: _: { swarselsystems = import ./lib { inherit self lib inputs outputs systems; }; }); - - - linuxUser = "swarsel"; - macUser = "leon.schwarzaeugl"; - - mkFullHost = host: type: { - ${host} = - let - systemFunc = if (type == "nixos") then lib.nixosSystem else inputs.nix-darwin.lib.darwinSystem; - in - systemFunc { - specialArgs = { inherit inputs outputs lib self; inherit (config) globals; }; - modules = [ - { - node.name = host; - node.secretsDir = ./hosts/${type}/${host}/secrets; - } - # put inports here that are for all hosts - inputs.disko.nixosModules.disko - inputs.sops-nix.nixosModules.sops - inputs.impermanence.nixosModules.impermanence - inputs.lanzaboote.nixosModules.lanzaboote - inputs.fw-fanctrl.nixosModules.default - "${self}/hosts/${type}/${host}" - { - _module.args.primaryUser = linuxUser; - } - ] ++ - (if (host == "iso") then [ - inputs.nix-topology.nixosModules.default - ] else - ([ - # put nixos imports here that are for all servers and normal hosts - inputs.nix-topology.nixosModules.default - "${self}/modules/${type}/common" - inputs.stylix.nixosModules.stylix - inputs.nswitch-rcm-nix.nixosModules.nswitch-rcm - ] ++ (if (type == "nixos") then [ - inputs.home-manager.nixosModules.home-manager - "${self}/profiles/nixos" - "${self}/modules/nixos/server" - "${self}/modules/nixos/optional" - { - home-manager.users."${linuxUser}".imports = [ - # put home-manager imports here that are for all normal hosts - "${self}/modules/home/common" - "${self}/modules/home/server" - "${self}/modules/home/optional" - "${self}/profiles/home" - ]; - } - ] else [ - # put nixos imports here that are for darwin hosts - "${self}/modules/darwin/nixos/common" - "${self}/profiles/darwin" - inputs.home-manager.darwinModules.home-manager - { - home-manager.users."${macUser}".imports = [ - # put home-manager imports here that are for darwin hosts - "${self}/modules/darwin/home" - "${self}/modules/home/server" - "${self}/modules/home/optional" - "${self}/profiles/home" - ]; - } - ]) - )); - }; - }; - - mkHalfHost = host: type: pkgs: { - ${host} = - let - systemFunc = if (type == "home") then inputs.home-manager.lib.homeManagerConfiguration else inputs.nix-on-droid.lib.nixOnDroidConfiguration; - in - systemFunc - { - inherit pkgs; - extraSpecialArgs = { inherit inputs outputs lib self; }; - modules = [ "${self}/hosts/${type}/${host}" ]; - }; - }; - - mkFullHostConfigs = hosts: type: lib.foldl (acc: set: acc // set) { } (lib.map (host: mkFullHost host type) hosts); - - mkHalfHostConfigs = hosts: type: pkgs: lib.foldl (acc: set: acc // set) { } (lib.map (host: mkHalfHost host type pkgs) hosts); - - in - { - inherit lib; - - # nixosModules = import ./modules/nixos { inherit lib; }; - # homeModules = import ./modules/home { inherit lib; }; - packages = lib.swarselsystems.forEachLinuxSystem (pkgs: import ./pkgs { inherit lib pkgs; }); - formatter = lib.swarselsystems.forEachSystem (pkgs: pkgs.nixpkgs-fmt); - overlays = import ./overlays { inherit self lib inputs; }; - - apps = lib.swarselsystems.forAllSystems (system: - let - appNames = [ - "swarsel-bootstrap" - "swarsel-install" - "swarsel-rebuild" - "swarsel-postinstall" - ]; - appSet = lib.swarselsystems.mkApps system appNames self; - in - - appSet // { - default = appSet.swarsel-bootstrap; - } - ); - - devShells = lib.swarselsystems.forAllSystems (system: - let - pkgs = lib.swarselsystems.pkgsFor.${system}; - checks = self.checks.${system}; - in - { - default = pkgs.mkShell { - # plugin-files = ${pkgs.nix-plugins.overrideAttrs (o: { - # buildInputs = [pkgs.nixVersions.latest pkgs.boost]; - # patches = (o.patches or []) ++ [ "${self}/nix/nix-plugins.patch" ]; - # })}/lib/nix/plugins - NIX_CONFIG = '' - plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins - extra-builtins-file = ${self + /nix/extra-builtins.nix} - ''; - inherit (checks.pre-commit-check) shellHook; - - buildInputs = checks.pre-commit-check.enabledPackages; - nativeBuildInputs = [ - (builtins.trace "alarm: we pinned nix_2_24 because of https://github.com/shlevy/nix-plugins/issues/20" pkgs.nixVersions.nix_2_24) # Always use the nix version from this flake's nixpkgs version, so that nix-plugins (below) doesn't fail because of different nix versions. - # pkgs.nix - pkgs.home-manager - pkgs.git - pkgs.just - pkgs.age - pkgs.ssh-to-age - pkgs.sops - pkgs.statix - pkgs.deadnix - pkgs.nixpkgs-fmt - ]; - }; - } - ); - - templates = import ./templates { inherit lib; }; - - checks = lib.swarselsystems.forAllSystems (system: - let - pkgs = lib.swarselsystems.pkgsFor.${system}; - in - import ./checks { inherit self inputs system pkgs; } - ); - - diskoConfigurations.default = import .templates/hosts/nixos/disk-config.nix; - - nixosConfigurations = mkFullHostConfigs (lib.swarselsystems.readHosts "nixos") "nixos"; - homeConfigurations = mkHalfHostConfigs (lib.swarselsystems.readHosts "home") "home" lib.swarselsystems.pkgsFor.x86_64-linux; - darwinConfigurations = mkFullHostConfigs (lib.swarselsystems.readHosts "darwin") "darwin"; - nixOnDroidConfigurations = mkHalfHostConfigs (lib.swarselsystems.readHosts "android") "android" lib.swarselsystems.pkgsFor.aarch64-linux; - - topology = lib.swarselsystems.forEachSystem (pkgs: import inputs.nix-topology { - inherit pkgs; - modules = [ - "${self}/topology" - { inherit (self) nixosConfigurations; } - ]; - }); - - nodes = config.nixosConfigurations; - }; - systems = [ - "x86_64-linux" - "aarch64-linux" - "x86_64-darwin" - "aarch64-darwin" - ]; - }; -} -
    -
    -
    - -
    -

    2.2. Inputs

    -

    Here we define inputs and outputs of the flake. First, the following list is for the outputs of the flake.

    @@ -1525,257 +1248,861 @@ This automatically creates a topology diagram of my configuration.
  • -
    -nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    -nixpkgs-kernel.url = "github:NixOS/nixpkgs/063f43f2dbdef86376cc29ad646c45c46e93234c?narHash=sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o%3D"; #specifically pinned for kernel version
    -nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.05";
    -nixpkgs-stable24_05.url = "github:NixOS/nixpkgs/nixos-24.05";
    -nixpkgs-stable24_11.url = "github:NixOS/nixpkgs/nixos-24.11";
    -systems.url = "github:nix-systems/default";
    -home-manager = {
    -  url = "github:nix-community/home-manager";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -emacs-overlay = {
    -  url = "github:nix-community/emacs-overlay";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -nur.url = "github:nix-community/NUR";
    -nixgl.url = "github:guibou/nixGL";
    -stylix.url = "github:danth/stylix";
    -sops-nix.url = "github:Mic92/sops-nix";
    -lanzaboote.url = "github:nix-community/lanzaboote";
    -nix-on-droid = {
    -  url = "github:nix-community/nix-on-droid/release-24.05";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -nixos-generators = {
    -  url = "github:nix-community/nixos-generators";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -nixos-hardware = {
    -  url = "github:NixOS/nixos-hardware/master";
    -};
    -nix-alien = {
    -  url = "github:thiagokokada/nix-alien";
    -};
    -nswitch-rcm-nix = {
    -  url = "github:Swarsel/nswitch-rcm-nix";
    -};
    -nix-index-database = {
    -  url = "github:nix-community/nix-index-database";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -disko = {
    -  url =  "github:nix-community/disko";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -impermanence.url = "github:nix-community/impermanence";
    -zjstatus = {
    -  url = "github:dj95/zjstatus";
    -};
    -fw-fanctrl = {
    -  url = "github:TamtamHero/fw-fanctrl/packaging/nix";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -nix-darwin = {
    -  url = "github:lnl7/nix-darwin";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -pre-commit-hooks = {
    -  url = "github:cachix/git-hooks.nix";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -nix-secrets = {
    -  url = "git+ssh://git@github.com/Swarsel/nix-secrets.git?ref=main&shallow=1";
    -  flake = false;
    -  inputs = { };
    -};
    -vbc-nix = {
    -  url = "git+ssh://git@github.com/vbc-it/vbc-nix.git?ref=main";
    -  inputs.nixpkgs.follows = "nixpkgs";
    -};
    -nix-topology.url = "github:oddlama/nix-topology";
    -flake-parts.url = "github:hercules-ci/flake-parts";
    -
    -
    - - -
    -

    2.3. let

    -
    -

    -Here I define a few variables that I need for my system specifications. There used to be more here, but I managed to optimize my configuration, and only two things remain: -

    -
      -
    • outputs, which is needed for lib
    • -
    • lib: This exposes a common lib for NixOS and home-manager that is extended by my own personal lib functions.
    • -
    +
    {
    +  description = "SwarseFlake - Nix Flake for all SwarselSystems";
     
    -
    -
    -inherit (self) outputs;
    -lib = (nixpkgs.lib // home-manager.lib).extend  (_: _: { swarselsystems = import ./lib { inherit self lib inputs outputs systems; }; });
    -
    -
    -
    -
    -
    -
    -

    2.4. General (outputs)

    -
    -

    -In this section I am creating some attributes that define general concepts of my configuration: -

    - -
      -
    • nixosModules imports self-defined options that I only want to use on NixOS systems. All modules are held as separately as possible, to allow for easier sharing with other people mostly.
    • -
    • homeModules imports modules that are to be used on NixOS and non-NixOS systems. These are mostly used to define outputs (monitors), keyboards and special commands for machines.
    • -
    • packages holds packages that I am building myself. These are mostly shell scripts, but also a few others such as AppImages and firefox addons.
    • -
    • devShells provides a development shell that can be used as a bootstrap for new installs using nix develop while inside the flake directory. It received an overhaul in 0a6cf0e feat: add checks to devShell, since when it is handled using forAllSystems and now including pre-commit-hook checks.
    • -
    • formatter provides the formatter that is to be used on .nix files. It can be called by using nix fmt.
    • -
    • check provides the pre-commit-hook checks that I have explained in Pre-commit-hooks (Checks).
    • -
    • -overlays imports a few community overlays (such as the emacs-overlay) and also three overlays of my own: -

      -
        -
      1. additions holds derivations that I am adding myself to nixpkgs - i.e. this is where the packages defined in /pkgs get added to nixpkgs.
      2. -
      3. modifications holds derivations that I have performed overrides on. The list of interesting attribute overrides can be found by looking at the source code of a derivation and looking at the start of the file for lines of the form <name> ? <val>. But this can also be used to, for example, fetch a different version of a package instead.
      4. -
      5. nixpkgs-stable holds the newest version of stable nixpkgs. I only use this on packages that seem broken on unstable, which are not many.
      6. -
      7. zjstatus holds some options for zellij, but I have stopped using it since I prefer tmux.
      8. -
      -

      -They are defined in Overlays (additions, overrides, nixpkgs-stable). The way this is handled was simplified in 647a2ae feat: simplify overlay structure; however, the old structure might be easier to understand as a reference. -

    • -
    - -
    -
    inherit lib;
    -
    -# nixosModules = import ./modules/nixos { inherit lib; };
    -# homeModules = import ./modules/home { inherit lib; };
    -packages = lib.swarselsystems.forEachLinuxSystem (pkgs: import ./pkgs { inherit lib pkgs; });
    -formatter = lib.swarselsystems.forEachSystem (pkgs: pkgs.nixpkgs-fmt);
    -overlays = import ./overlays { inherit self lib inputs; };
    -
    -apps = lib.swarselsystems.forAllSystems (system:
    -  let
    -    appNames = [
    -      "swarsel-bootstrap"
    -      "swarsel-install"
    -      "swarsel-rebuild"
    -      "swarsel-postinstall"
    +  nixConfig = {
    +    extra-substituters = [
    +      "https://nix-community.cachix.org"
    +      "https://cache.ngi0.nixos.org/"
         ];
    -    appSet = lib.swarselsystems.mkApps system appNames self;
    -  in
    -
    -  appSet // {
    -    default = appSet.swarsel-bootstrap;
    -  }
    -);
    -
    -devShells = lib.swarselsystems.forAllSystems (system:
    -  let
    -    pkgs = lib.swarselsystems.pkgsFor.${system};
    -    checks = self.checks.${system};
    -  in
    -  {
    -    default = pkgs.mkShell {
    -        # plugin-files = ${pkgs.nix-plugins.overrideAttrs (o: {
    -        #   buildInputs = [pkgs.nixVersions.latest pkgs.boost];
    -        #   patches = (o.patches or []) ++ [ "${self}/nix/nix-plugins.patch" ];
    -        # })}/lib/nix/plugins
    -      NIX_CONFIG = ''
    -        plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins
    -        extra-builtins-file = ${self + /nix/extra-builtins.nix}
    -      '';
    -      inherit (checks.pre-commit-check) shellHook;
    -
    -      buildInputs = checks.pre-commit-check.enabledPackages;
    -      nativeBuildInputs = [
    -        (builtins.trace "alarm: we pinned nix_2_24 because of https://github.com/shlevy/nix-plugins/issues/20" pkgs.nixVersions.nix_2_24) # Always use the nix version from this flake's nixpkgs version, so that nix-plugins (below) doesn't fail because of different nix versions.
    -        # pkgs.nix
    -        pkgs.home-manager
    -        pkgs.git
    -        pkgs.just
    -        pkgs.age
    -        pkgs.ssh-to-age
    -        pkgs.sops
    -        pkgs.statix
    -        pkgs.deadnix
    -        pkgs.nixpkgs-fmt
    +    extra-trusted-public-keys = [
    +      "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
    +      "cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA="
    +    ];
    +  };
    +  inputs = {
    +    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    +    nixpkgs-kernel.url = "github:NixOS/nixpkgs/063f43f2dbdef86376cc29ad646c45c46e93234c?narHash=sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o%3D"; #specifically pinned for kernel version
    +    nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.05";
    +    nixpkgs-stable24_05.url = "github:NixOS/nixpkgs/nixos-24.05";
    +    nixpkgs-stable24_11.url = "github:NixOS/nixpkgs/nixos-24.11";
    +    systems.url = "github:nix-systems/default";
    +    home-manager = {
    +      url = "github:nix-community/home-manager";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    emacs-overlay = {
    +      url = "github:nix-community/emacs-overlay";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    nur.url = "github:nix-community/NUR";
    +    nixgl.url = "github:guibou/nixGL";
    +    stylix.url = "github:danth/stylix";
    +    sops-nix.url = "github:Mic92/sops-nix";
    +    lanzaboote.url = "github:nix-community/lanzaboote";
    +    nix-on-droid = {
    +      url = "github:nix-community/nix-on-droid/release-24.05";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    nixos-generators = {
    +      url = "github:nix-community/nixos-generators";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    nixos-hardware = {
    +      url = "github:NixOS/nixos-hardware/master";
    +    };
    +    nix-alien = {
    +      url = "github:thiagokokada/nix-alien";
    +    };
    +    nswitch-rcm-nix = {
    +      url = "github:Swarsel/nswitch-rcm-nix";
    +    };
    +    nix-index-database = {
    +      url = "github:nix-community/nix-index-database";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    disko = {
    +      url = "github:nix-community/disko";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    impermanence.url = "github:nix-community/impermanence";
    +    zjstatus = {
    +      url = "github:dj95/zjstatus";
    +    };
    +    fw-fanctrl = {
    +      url = "github:TamtamHero/fw-fanctrl/packaging/nix";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    nix-darwin = {
    +      url = "github:lnl7/nix-darwin";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    pre-commit-hooks = {
    +      url = "github:cachix/git-hooks.nix";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    nix-secrets = {
    +      url = "git+ssh://git@github.com/Swarsel/nix-secrets.git?ref=main&shallow=1";
    +      flake = false;
    +      inputs = { };
    +    };
    +    vbc-nix = {
    +      url = "git+ssh://git@github.com/vbc-it/vbc-nix.git?ref=main";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +    nix-topology.url = "github:oddlama/nix-topology";
    +    flake-parts.url = "github:hercules-ci/flake-parts";
    +    devshell = {
    +      url = "github:numtide/devshell";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +  };
    +  outputs =
    +    inputs:
    +    inputs.flake-parts.lib.mkFlake { inherit inputs; } {
    +      imports = [
    +        ./nix/globals.nix
    +        ./nix/hosts.nix
    +        ./nix/topology.nix
    +        ./nix/devshell.nix
    +        ./nix/apps.nix
    +        ./nix/packages.nix
    +        ./nix/overlays.nix
    +        ./nix/lib.nix
    +        ./nix/templates.nix
    +        ./nix/formatter.nix
    +        ./nix/modules.nix
    +        ./nix/iso.nix
    +      ];
    +      systems = [
    +        "x86_64-linux"
    +        "aarch64-linux"
    +        "x86_64-darwin"
    +        "aarch64-darwin"
           ];
         };
    -  }
    -);
    -
    -templates = import ./templates { inherit lib; };
    -
    -checks = lib.swarselsystems.forAllSystems (system:
    -  let
    -    pkgs = lib.swarselsystems.pkgsFor.${system};
    -  in
    -  import ./checks { inherit self inputs system pkgs; }
    -);
    -
    -diskoConfigurations.default = import .templates/hosts/nixos/disk-config.nix;
    +}
     
    -
    -

    2.5. Pre-commit-hooks (Checks)

    -
    +
    +

    2.2. Auxiliary files

    +
    +
    +
    +

    2.2.1. extra-builtins

    +
    +
    +
    # adapted from https://github.com/oddlama/nix-config/blob/main/nix/extra-builtins.nix
    +{ exec, ... }:
    +let
    +  assertMsg = pred: msg: pred || builtins.throw msg;
    +  hasSuffix =
    +    suffix: content:
    +    let
    +      lenContent = builtins.stringLength content;
    +      lenSuffix = builtins.stringLength suffix;
    +    in
    +    lenContent >= lenSuffix && builtins.substring (lenContent - lenSuffix) lenContent content == suffix;
    +in
    +{
    +  # Instead of calling sops directly here, we call a wrapper script that will cache the output
    +  # in a predictable path in /tmp, which allows us to only require the password for each encrypted
    +  # file once.
    +  sopsImportEncrypted =
    +    nixFile:
    +      assert assertMsg (builtins.isPath nixFile)
    +        "The file to decrypt must be given as a path (not a string) to prevent impurity.";
    +      assert assertMsg (hasSuffix ".nix.enc" nixFile)
    +        "The content of the decrypted file must be a nix expression and should therefore end in .nix.enc";
    +      exec [
    +        ./sops-decrypt-and-cache.sh
    +        nixFile
    +      ];
    +}
    +
    +
    +
    +
    +
    +
    +

    2.2.2. sops-decrypt-and-cache

    +
    +
    +
    # adapted from https://github.com/oddlama/nix-config/blob/main/nix/rage-decrypt-and-cache.sh
    +set -euo pipefail
    +
    +print_out_path=false
    +if [[ $1 == "--print-out-path" ]]; then
    +    print_out_path=true
    +    shift
    +fi
    +
    +file="$1"
    +shift
    +
    +basename="${file%".enc"}"
    +# store path prefix or ./ if applicable
    +[[ $file == "/nix/store/"* ]] && basename="${basename#*"-"}"
    +[[ $file == "./"* ]] && basename="${basename#"./"}"
    +
    +# Calculate a unique content-based identifier (relocations of
    +# the source file in the nix store should not affect caching)
    +new_name="$(sha512sum "$file")"
    +new_name="${new_name:0:32}-${basename//"/"/"%"}"
    +
    +# Derive the path where the decrypted file will be stored
    +out="/var/tmp/nix-import-encrypted/$UID/$new_name"
    +umask 077
    +mkdir -p "$(dirname "$out")"
    +
    +# Decrypt only if necessary
    +if [[ ! -e $out ]]; then
    +    agekey=$(sudo ssh-to-age -private-key -i /etc/ssh/sops || sudo ssh-to-age -private-key -i /etc/ssh/ssh_host_ed25519_key)
    +    SOPS_AGE_KEY="$agekey" sops decrypt --output "$out" "$file"
    +fi
    +
    +# Print out path or decrypted content
    +if [[ $print_out_path == true ]]; then
    +    echo "$out"
    +else
    +    cat "$out"
    +fi
    +
    +
    +
    +
    +
    +
    +

    2.3. Library functions

    +
    +

    +This section defines all functions of my own that I add to lib. These are used in all places over the config, with many of them being used in flake.nix. +

    + +

    +A breakdown of each function: +

    + +

    +The interesting part is in the start: +

    +
      +
    • first, I define pkgsFor. This function reads all available systems from nixpkgs and generates pkgs for them.
    • +
    • next, forEachSystem is a function that can be called to declare an output for each such defined system.
    • +
    • forAllSystems is a crude function that I use for expressions that depend on system, as the prior two attributes already consumed it at that stage. This is only really used to generate the checks in their own file.
    • +
    • mkFullHostConfigs is the function that dynamically creates all definded hosts. The hosts are defined by placing a directory in hosts/ under either the nixos/ or darwin/ directory. These directories are being read by readHosts and delivered to this funtion in the later call in [BROKEN LINK: h:9c9b9e3b-8771-44fa-ba9e-5056ae809655] or [BROKEN LINK: h:f881aa05-a670-48dd-a57b-2916abdcb692].
    • +
    • mkFullHost: +This is a function that takes a hostname as well as a boolean whether it is NixOS or not, and returns a matching nixosSystem or darwinSystem. This function is only used for systems that can use both NixOS and home-manager options (darwin still counts here as it can use some NixOS options). This is used in mkFullHostConfigs. In more detail, it dynamically creates a nixosConfiguration host, setting its speciaArgs and modules attributes. The modules are populated based on whether this is a NixOS or darwin host. For the latter, I will only ever use machines that I get for testing from work, and for these my username is different, so I implemented an if-condition for it. This could be done more cleanly using variables, but some care needs to be taken with the home-manager imports and this approach works, so for now this is fine. Thanks to this function, the import sections of the host configs are pretty clean for most hosts. +lib.optionals evaluates to an empty list ([]) in case that the conditional is not met.
    • +
    + +
    +
    { self, inputs, ... }:
    +let
    +  swarselsystems =
    +    let
    +      inherit (inputs) systems;
    +      inherit (inputs.nixpkgs) lib;
    +    in
    +    rec {
    +      mkIfElseList = p: yes: no: lib.mkMerge [
    +        (lib.mkIf p yes)
    +        (lib.mkIf (!p) no)
    +      ];
    +
    +      mkIfElse = p: yes: no: if p then yes else no;
    +
    +      pkgsFor = lib.genAttrs (import systems) (system:
    +        import inputs.nixpkgs {
    +          inherit system;
    +          overlays = [ self.overlays.default ];
    +          config.allowUnfree = true;
    +        }
    +      );
    +
    +      toCapitalized = str:
    +        if builtins.stringLength str == 0 then
    +          ""
    +        else
    +          let
    +            first = builtins.substring 0 1 str;
    +            rest = builtins.substring 1 (builtins.stringLength str - 1) str;
    +            upper = lib.toUpper first;
    +            lower = lib.toLower rest;
    +          in
    +          upper + lower;
    +
    +
    +      mkTrueOption = lib.mkOption {
    +        type = lib.types.bool;
    +        default = true;
    +      };
    +
    +      mkStrong = lib.mkOverride 60;
    +
    +      forEachSystem = f: lib.genAttrs (import systems) (system: f pkgsFor.${system});
    +      forEachLinuxSystem = f: lib.genAttrs [ "x86_64-linux" "aarch64-linux" ] (system: f pkgsFor.${system});
    +
    +      readHosts = type: lib.attrNames (builtins.readDir "${self}/hosts/${type}");
    +      readNix = type: lib.filter (name: name != "default.nix") (lib.attrNames (builtins.readDir "${self}/${type}"));
    +
    +
    +
    +
    +      mkModules = names: type: builtins.listToAttrs (map
    +        (name: {
    +          inherit name;
    +          value = import "${self}/modules/${type}/${name}";
    +        })
    +        names);
    +
    +      mkProfiles = names: type: builtins.listToAttrs (map
    +        (name: {
    +          inherit name;
    +          value = import "${self}/profiles/${type}/${name}";
    +        })
    +        names);
    +
    +
    +      mkImports = names: baseDir: lib.map (name: "${self}/${baseDir}/${name}") names;
    +
    +      eachMonitor = _: monitor: {
    +        inherit (monitor) name;
    +        value = builtins.removeAttrs monitor [ "workspace" "name" "output" ];
    +      };
    +
    +      eachOutput = _: monitor: {
    +        inherit (monitor) name;
    +        value = builtins.removeAttrs monitor [ "mode" "name" "scale" "transform" "position" ];
    +      };
    +    };
    +in
    +{
    +  flake = _:
    +    {
    +      lib = (inputs.nixpkgs.lib // inputs.home-manager.lib).extend (_: _: {
    +        inherit swarselsystems;
    +      });
    +    };
    +}
    +
    +
    +
    +
    +
    +

    2.4. Packages (pkgs)

    +
    +

    +This does not use perSystem since some of my custom packages are not able to be built on darwin systems, and I was not yet interested in writing logic for handling that. +

    + +
    +
    { self, ... }:
    +{
    +  flake = _:
    +    let
    +      inherit (self.outputs) lib;
    +    in
    +    {
    +      packages = lib.swarselsystems.forEachLinuxSystem (pkgs: import "${self}/pkgs" { inherit self lib pkgs; });
    +    };
    +}
    +
    +
    +
    +
    +
    +

    2.5. Globals

    +
    +

    +The structure of globals.nix.enc requires a toplevel globals. +

    + +
    +
    # adapted from https://github.com/oddlama/nix-config/blob/main/nix/globals.nix
    +{ inputs, ... }:
    +{
    +  flake = { config, lib, ... }:
    +    {
    +      globals =
    +        let
    +          globalsSystem = lib.evalModules {
    +            prefix = [ "globals" ];
    +            specialArgs = {
    +              inherit lib;
    +              inherit inputs;
    +              inherit (config) nodes;
    +            };
    +            modules = [
    +              ../modules/nixos/common/globals.nix
    +              (
    +                { lib, ... }:
    +                let
    +                  # Try to access the extra builtin we loaded via nix-plugins.
    +                  # Throw an error if that doesn't exist.
    +                  sopsImportEncrypted =
    +                    assert lib.assertMsg (builtins ? extraBuiltins.sopsImportEncrypted)
    +                      "The extra builtin 'sopsImportEncrypted' is not available, so repo.secrets cannot be decrypted. Did you forget to add nix-plugins and point it to `./nix/extra-builtins.nix` ?";
    +                    builtins.extraBuiltins.sopsImportEncrypted;
    +                in
    +
    +                {
    +                  imports = [
    +                    (sopsImportEncrypted ../secrets/repo/globals.nix.enc)
    +                  ];
    +
    +                }
    +              )
    +              (
    +                { lib, ... }:
    +                {
    +                  globals = lib.mkMerge (
    +                    lib.concatLists (
    +                      lib.flip lib.mapAttrsToList config.nodes (
    +                        name: cfg:
    +                          builtins.addErrorContext "while aggregating globals from nixosConfigurations.${name} into flake-level globals:" cfg.config._globalsDefs
    +                      )
    +                    )
    +                  );
    +                }
    +              )
    +            ];
    +          };
    +        in
    +        {
    +          # Make sure the keys of this attrset are trivially evaluatable to avoid infinite recursion,
    +          # therefore we inherit relevant attributes from the config.
    +          inherit (globalsSystem.config.globals)
    +            domains
    +            services
    +            user
    +            ;
    +        };
    +    };
    +}
    +
    +
    +
    +
    +
    +
    +

    2.6. Hosts

    +
    +
    +
    { self, inputs, ... }:
    +{
    +  flake = { config, ... }:
    +    let
    +      inherit (self) outputs;
    +      inherit (outputs) lib;
    +      # lib = (inputs.nixpkgs.lib // inputs.home-manager.lib).extend  (_: _: { swarselsystems = import "${self}/lib" { inherit self lib inputs outputs; inherit (inputs) systems; }; });
    +
    +      mkNixosHost = { minimal }: name:
    +            lib.nixosSystem {
    +              specialArgs = { inherit inputs outputs lib self minimal; inherit (config) globals nodes; };
    +              modules = [
    +                inputs.disko.nixosModules.disko
    +                inputs.sops-nix.nixosModules.sops
    +                inputs.impermanence.nixosModules.impermanence
    +                inputs.lanzaboote.nixosModules.lanzaboote
    +                inputs.nix-topology.nixosModules.default
    +                inputs.home-manager.nixosModules.home-manager
    +                "${self}/hosts/nixos/${name}"
    +                "${self}/profiles/nixos"
    +                "${self}/modules/nixos"
    +                {
    +                  node.name = name;
    +                  node.secretsDir = ../hosts/nixos/${name}/secrets;
    +                }
    +              ];
    +            };
    +
    +      mkDarwinHost = { minimal }: name:
    +            inputs.nix-darwin.lib.darwinSystem {
    +              specialArgs = { inherit inputs outputs lib self minimal; inherit (config) globals nodes; };
    +              modules = [
    +                # inputs.disko.nixosModules.disko
    +                # inputs.sops-nix.nixosModules.sops
    +                # inputs.impermanence.nixosModules.impermanence
    +                # inputs.lanzaboote.nixosModules.lanzaboote
    +                # inputs.fw-fanctrl.nixosModules.default
    +                # inputs.nix-topology.nixosModules.default
    +                inputs.home-manager.darwinModules.home-manager
    +                "${self}/hosts/darwin/${name}"
    +                "${self}/modules/nixos/darwin"
    +                # needed for infrastructure
    +                "${self}/modules/nixos/common/meta.nix"
    +                "${self}/modules/nixos/common/globals.nix"
    +                {
    +                  node.name = name;
    +                  node.secretsDir = ../hosts/darwin/${name}/secrets;
    +                }
    +              ];
    +            };
    +
    +      mkHalfHost = name: type: pkgs: {
    +        ${name} =
    +          let
    +            systemFunc = if (type == "home") then inputs.home-manager.lib.homeManagerConfiguration else inputs.nix-on-droid.lib.nixOnDroidConfiguration;
    +          in
    +            systemFunc
    +              {
    +                inherit pkgs;
    +                extraSpecialArgs = { inherit inputs outputs lib self; };
    +                modules = [ "${self}/hosts/${type}/${name}" ];
    +              };
    +      };
    +
    +      mkHalfHostConfigs = hosts: type: pkgs: lib.foldl (acc: set: acc // set) { } (lib.map (name: mkHalfHost name type pkgs) hosts);
    +      nixosHosts = builtins.attrNames (lib.filterAttrs (_: type: type == "directory") (builtins.readDir "${self}/hosts/nixos"));
    +      darwinHosts = builtins.attrNames (lib.filterAttrs (_: type: type == "directory") (builtins.readDir "${self}/hosts/darwin"));
    +    in
    +      {
    +        nixosConfigurations = lib.genAttrs nixosHosts (mkNixosHost {
    +          minimal = false;
    +        });
    +        nixosConfigurationsMinimal = lib.genAttrs nixosHosts (mkNixosHost {
    +          minimal = true;
    +        });
    +        darwinConfigurations = lib.genAttrs darwinHosts (mkDarwinHost {
    +          minimal = false;
    +        });
    +        darwinConfigurationsMinimal = lib.genAttrs darwinHosts (mkDarwinHost {
    +          minimal = true;
    +        });
    +
    +        # TODO: Build these for all architectures
    +        homeConfigurations = mkHalfHostConfigs (lib.swarselsystems.readHosts "home") "home" lib.swarselsystems.pkgsFor.x86_64-linux;
    +        nixOnDroidConfigurations = mkHalfHostConfigs (lib.swarselsystems.readHosts "android") "android" lib.swarselsystems.pkgsFor.aarch64-linux;
    +
    +        diskoConfigurations.default = import "${self}/files/templates/hosts/nixos/disk-config.nix";
    +
    +        nodes = config.nixosConfigurations // config.darwinConfigurations;
    +
    +      };
    +}
    +
    +
    +
    +
    +
    +

    2.7. Topology

    +
    +
    +
    { self, inputs, ... }:
    +{
    +  imports = [
    +    inputs.nix-topology.flakeModule
    +  ];
    +
    +  perSystem.topology.modules = [
    +    ({ config, ... }:
    +    let
    +      inherit (config.lib.topology)
    +        mkInternet
    +        mkDevice
    +        mkSwitch
    +        mkRouter
    +        mkConnection
    +        ;
    +    in
    +    {
    +      renderer = "elk";
    +
    +      networks = {
    +        home-lan = {
    +          name = "Home LAN";
    +          cidrv4 = "192.168.1.0/24";
    +        };
    +        wg = {
    +          name = "Wireguard Tunnel";
    +          cidrv4 = "192.168.3.0/24";
    +        };
    +      };
    +
    +      nodes = {
    +        internet = mkInternet {
    +          connections = [
    +            (mkConnection "moonside" "wan")
    +            (mkConnection "pfsense" "wan")
    +            (mkConnection "sync" "wan")
    +            (mkConnection "toto" "bootstrapper")
    +            (mkConnection "chaostheatre" "demo host")
    +          ];
    +        };
    +
    +        chaostheatre.interfaces."demo host" = { };
    +        toto.interfaces."bootstrapper" = { };
    +        sync.interfaces.wan = { };
    +        moonside.interfaces.wan = { };
    +
    +        pfsense = mkRouter "pfSense" {
    +          info = "HUNSN RM02";
    +          image = "${self}/files/topology-images/hunsn.png";
    +          interfaceGroups = [
    +            [
    +              "eth2"
    +              "eth3"
    +              "eth4"
    +              "eth5"
    +              "eth6"
    +            ]
    +            [ "wan" ]
    +          ];
    +          interfaces.wg = {
    +            addresses = [ "192.168.3.1" ];
    +            network = "wg";
    +            virtual = true;
    +            type = "wireguard";
    +          };
    +
    +          connections = {
    +            eth2 = mkConnection "switch-livingroom" "eth1";
    +            eth4 = mkConnection "winters" "eth1";
    +            eth3 = mkConnection "switch-bedroom" "eth1";
    +            eth6 = mkConnection "wifi-ap" "eth1";
    +            wg = mkConnection "moonside" "wg";
    +          };
    +          interfaces = {
    +            eth2 = {
    +              addresses = [ "192.168.1.1" ];
    +              network = "home-lan";
    +            };
    +            eth3 = {
    +              addresses = [ "192.168.1.1" ];
    +              network = "home-lan";
    +            };
    +            eth4 = {
    +              addresses = [ "192.168.1.1" ];
    +              network = "home-lan";
    +            };
    +            eth6 = {
    +              addresses = [ "192.168.1.1" ];
    +              network = "home-lan";
    +            };
    +          };
    +        };
    +
    +        winters.interfaces."eth1" = { };
    +
    +        wifi-ap = mkSwitch "Wi-Fi AP" {
    +          info = "Huawei";
    +          image = "${self}/files/topology-images/huawei.png";
    +          interfaceGroups = [
    +            [
    +              "eth1"
    +              "wifi"
    +            ]
    +          ];
    +        };
    +
    +        switch-livingroom = mkSwitch "Switch Livingroom" {
    +          info = "TL-SG108";
    +          image = "${self}/files/topology-images/TL-SG108.png";
    +          interfaceGroups = [
    +            [
    +              "eth1"
    +              "eth2"
    +              "eth3"
    +              "eth4"
    +              "eth5"
    +              "eth6"
    +              "eth7"
    +              "eth8"
    +            ]
    +          ];
    +          connections = {
    +            eth2 = mkConnection "nswitch" "eth1";
    +            eth7 = mkConnection "pc" "eth1";
    +            eth8 = mkConnection "nbl-imba-2" "eth1";
    +          };
    +        };
    +
    +        nswitch = mkDevice "Nintendo Switch" {
    +          info = "Nintendo Switch";
    +          image = "${self}/files/topology-images/nintendo-switch.png";
    +          interfaces.eth1 = { };
    +        };
    +
    +        pc = mkDevice "Windows Gaming Server" {
    +          info = "i7-4790k, GTX970, 32GB RAM";
    +          image = "${self}/files/topology-images/pc.png";
    +          interfaces.eth1 = { };
    +        };
    +
    +        nbl-imba-2.interfaces.eth1 = { };
    +
    +        switch-bedroom = mkSwitch "Switch Bedroom" {
    +          info = "TL-SG1005D";
    +          image = "${self}/files/topology-images/TL-SG1005D.png";
    +          interfaceGroups = [
    +            [
    +              "eth1"
    +              "eth2"
    +              "eth3"
    +              "eth4"
    +              "eth5"
    +            ]
    +          ];
    +          connections.eth2 = mkConnection "printer" "eth1";
    +        };
    +
    +        printer = mkDevice "Printer" {
    +          info = "DELL C2665dnf";
    +          image = "${self}/files/topology-images/DELL-C2665dnf.png";
    +          interfaces.eth1 = { };
    +        };
    +
    +      };
    +
    +    })
    +
    +
    +  ];
    +}
    +
    +
    +
    +
    +
    +
    +

    2.8. Devshell (checks)

    +

    This file defines a number of checks that can either be run by calling nix flake check or while in a nix-shell or nix develop. This helps me make sure that my flake confirms to my self-imposed standards. The GitHub actions perform less checks than are being done here (they are only checking the formatting, as well as statix and deadnix)

    -
    { self, inputs, pkgs, system, ... }:
    +
    { self, inputs, ... }:
     {
    -  pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run {
    -    src = "${self}";
    -    hooks = {
    -      check-added-large-files.enable = true;
    -      check-case-conflicts.enable = true;
    -      check-executables-have-shebangs.enable = true;
    -      check-shebang-scripts-are-executable.enable = false;
    -      check-merge-conflicts.enable = true;
    -      deadnix.enable = true;
    -      detect-private-keys.enable = true;
    -      end-of-file-fixer.enable = true;
    -      fix-byte-order-marker.enable = true;
    -      flake-checker.enable = true;
    -      forbid-new-submodules.enable = true;
    -      mixed-line-endings.enable = true;
    -      nixpkgs-fmt.enable = true;
    -      statix.enable = true;
    -      trim-trailing-whitespace.enable = true;
    +  imports = [
    +    inputs.devshell.flakeModule
    +    inputs.pre-commit-hooks.flakeModule
    +  ];
     
    -      destroyed-symlinks = {
    -        enable = true;
    -        entry = "${inputs.pre-commit-hooks.checks.${system}.pre-commit-hooks}/bin/destroyed-symlinks";
    +  perSystem = { pkgs, system, ... }:
    +    {
    +      pre-commit = {
    +        check.enable = true;
    +        settings = {
    +          addGcRoot = true;
    +          hooks = {
    +            check-added-large-files.enable = true;
    +            check-case-conflicts.enable = true;
    +            check-executables-have-shebangs.enable = true;
    +            check-shebang-scripts-are-executable.enable = false;
    +            check-merge-conflicts.enable = true;
    +            deadnix.enable = true;
    +            detect-private-keys.enable = true;
    +            end-of-file-fixer.enable = true;
    +            fix-byte-order-marker.enable = true;
    +            flake-checker.enable = true;
    +            forbid-new-submodules.enable = true;
    +            mixed-line-endings.enable = true;
    +            nixpkgs-fmt.enable = true;
    +            statix.enable = true;
    +            trim-trailing-whitespace.enable = true;
    +
    +            destroyed-symlinks = {
    +              enable = true;
    +              entry = "${inputs.pre-commit-hooks.checks.${system}.pre-commit-hooks}/bin/destroyed-symlinks";
    +            };
    +
    +            shellcheck = {
    +              enable = true;
    +              entry = "${pkgs.shellcheck}/bin/shellcheck --shell=bash";
    +            };
    +
    +            shfmt = {
    +              enable = true;
    +              entry = "${pkgs.shfmt}/bin/shfmt -i 4 -sr -d -s -l";
    +            };
    +          };
    +        };
           };
     
    -      shellcheck = {
    -        enable = true;
    -        entry = "${pkgs.shellcheck}/bin/shellcheck --shell=bash";
    -      };
    +      devshells.default = {
    +        packages = [
    +          (builtins.trace "alarm: we pinned nix_2_24 because of https://github.com/shlevy/nix-plugins/issues/20" pkgs.nixVersions.nix_2_24) # Always use the nix version from this flake's nixpkgs version, so that nix-plugins (below) doesn't fail because of different nix versions.
    +          pkgs.git
    +          pkgs.just
    +          pkgs.age
    +          pkgs.ssh-to-age
    +          pkgs.sops
    +          pkgs.home-manager
    +          pkgs.nixpkgs-fmt
    +          self.packages.${system}.swarsel-build
    +          self.packages.${system}.swarsel-deploy
    +        ];
     
    -      shfmt = {
    -        enable = true;
    -        entry = "${pkgs.shfmt}/bin/shfmt -i 4 -sr -d -s -l";
    -      };
    +        commands = [
    +          {
    +            package = pkgs.statix;
    +            help = "Lint flake";
    +          }
    +          {
    +            package = pkgs.deadnix;
    +            help = "Check flake for dead code";
    +          }
    +          {
    +            package = pkgs.nix-tree;
    +            help = "Interactively browse dependency graphs of Nix derivations";
    +          }
    +          {
    +            package = pkgs.nvd;
    +            help = "Diff two nix toplevels and show which packages were upgraded";
    +          }
    +          {
    +            package = pkgs.nix-diff;
    +            help = "Explain why two Nix derivations differ";
    +          }
    +          {
    +            package = pkgs.nix-output-monitor;
    +            help = "Nix Output Monitor (a drop-in alternative for `nix` which shows a build graph)";
    +            name = "nom";
    +          }
    +          {
    +            name = "hm";
    +            help = "Manage home-manager config";
    +            command = "home-manager";
    +          }
    +          {
    +            name = "fmt";
    +            help = "Format flake";
    +            command = "nixpkgs-fmt --check \"$FLAKE\"";
    +          }
    +          {
    +            name = "sd";
    +            help = "Build and deploy this nix config to nodes";
    +            command = "swarsel-deploy \"$@\"";
    +          }
    +          {
    +            name = "sl";
    +            help = "Build and deploy a config to nodes";
    +            command = "swarsel-deploy \${1} switch";
    +          }
    +          {
    +            name = "sw";
    +            help = "Build and switch to the host's config locally";
    +            command = "swarsel-deploy $(hostname) switch";
    +          }
    +          {
    +            name = "bld";
    +            help = "Build a number of configurations";
    +            command = "swarel-build \"$@\"";
    +          }
    +          {
    +            name = "c";
    +            help = "Work with the flake git repository";
    +            command = "git --git-dir=$FLAKE/.git --work-tree=$FLAKE/ \"$@\"";
    +          }
    +        ];
     
    +        devshell.startup.pre-commit-install.text = "pre-commit install";
    +
    +        env = [
    +          {
    +            # Additionally configure nix-plugins with our extra builtins file.
    +            # We need this for our repo secrets.
    +            name = "NIX_CONFIG";
    +            value = ''
    +              plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins
    +              extra-builtins-file = ${self + /nix/extra-builtins.nix}
    +            '';
    +          }
    +        ];
    +      };
         };
    -  };
     }
     
    -

    2.6. Templates

    +

    2.9. Templates

    This file defines the templates that are being exposed by the flake. These can be used by running nix flake init -t github:Swarsel/.dotfiles#<TEMPLATE_NAME>. @@ -1783,108 +2110,261 @@ This file defines the templates that are being exposed by the flake. These can b

    -
    { lib, ... }:
    +
    { self, ... }:
    +{
    +  flake = _: {
    +    templates =
    +      let
    +        mkTemplates = names: builtins.listToAttrs (map
    +          (name: {
    +            inherit name;
    +            value = {
    +              path = "${self}/files/templates/${name}";
    +              description = "${name} project ";
    +            };
    +          })
    +          names);
    +        templateNames = [
    +          "python"
    +          "rust"
    +          "go"
    +          "cpp"
    +          "latex"
    +          "default"
    +        ];
    +      in
    +      mkTemplates templateNames;
    +  };
    +}
    +
    +
    +
    +
    +
    +
    +

    2.10. Formatter

    +
    +
    +
    _:
    +{
    +  perSystem = { pkgs, ... }: {
    +    formatter = pkgs.nixpkgs-fmt;
    +  };
    +}
    +
    +
    +
    +
    +
    +
    +

    2.11. Modules

    +
    +
    +
    { self, ... }:
    +{
    +  flake = _:
    +    let
    +      inherit (self.outputs) lib;
    +    in
    +    {
    +      nixosModules.default = import "${self}/modules/nixos" { inherit lib; };
    +      homeModules = import "${self}/modules/home" { inherit lib; };
    +    };
    +}
    +
    +
    +
    +
    +
    +
    +

    2.12. Apps

    +
    +

    +This file defines a number of checks that can either be run by calling nix flake check or while in a nix-shell or nix develop. This helps me make sure that my flake confirms to my self-imposed standards. The GitHub actions perform less checks than are being done here (they are only checking the formatting, as well as statix and deadnix) +

    + +
    +
    { self, ... }:
    +{
    +  perSystem = { system, ... }:
    +    let
    +      mkApps = system: names: self: builtins.listToAttrs (map
    +        (name: {
    +          inherit name;
    +          value = {
    +            type = "app";
    +            program = "${self.packages.${system}.${name}}/bin/${name}";
    +            meta = {
    +              description = "Custom app ${name}.";
    +            };
    +          };
    +        })
    +        names);
    +
    +      appNames = [
    +        "swarsel-bootstrap"
    +        "swarsel-install"
    +        "swarsel-rebuild"
    +        "swarsel-postinstall"
    +      ];
    +
    +      appSet = mkApps system appNames self;
    +    in
    +    {
    +      apps = appSet // {
    +        default = appSet.swarsel-bootstrap;
    +      };
    +    };
    +}
    +
    +
    +
    +
    +
    +

    2.13. Overlays

    +
    +

    +In this section I define packages that I manually want to nixpkgs. This can be useful for packages that are currently awaiting a PR or public packages that I do not want to maintain. +

    + +

    +As such, I also define three additional overlays: +

    + +
      +
    1. additions +These are for the aforementioned added packages
    2. +
    3. modification +These are for packages that are on nixpkgs, but do not fit my usecase, meaning I need to perform modifications on them.
    4. +
    5. nixpkgs-stable +This is simply a mirror of the most recent stable branch of nixpkgs. Useful for packages that are broken on nixpkgs, but do not need to be on bleeding edge anyways.
    6. +
    + +

    +Also, this is where I define all of my own modules. These are mostly used for setting some host-specifics directly than opposed to through multiple options. +

    + +

    +Lastly, I add some of my own library functions to be used alongside the functions provided by nixpkgs and home-manager. +

    + +
    +
    { self, inputs, ... }:
     let
    -  templateNames = [
    -    "python"
    -    "rust"
    -    "go"
    -    "cpp"
    -    "latex"
    -    "default"
    -  ];
    +  inherit (self) outputs;
    +  inherit (outputs) lib;
     in
    -lib.swarselsystems.mkTemplates templateNames
    +{
    +  flake = { config, ... }:
    +    {
    +      overlays = {
    +        default = final: prev:
    +          let
    +            additions = final: _: import "${self}/pkgs" { pkgs = final; inherit self lib; };
     
    +            modifications = final: prev: {
    +              vesktop = prev.vesktop.override {
    +                withSystemVencord = true;
    +              };
    +
    +              firefox = prev.firefox.override {
    +                nativeMessagingHosts = [
    +                  prev.tridactyl-native
    +                  prev.browserpass
    +                  prev.plasma5Packages.plasma-browser-integration
    +                ];
    +              };
    +
    +              mgba = final.swarsel-mgba;
    +
    +              retroarch = prev.retroarch.withCores (cores: with cores; [
    +                snes9x # snes
    +                nestopia # nes
    +                dosbox # dos
    +                scummvm # scumm
    +                vba-m # gb/a
    +                mgba # gb/a
    +                melonds # ds
    +                dolphin # gc/wii
    +              ]);
    +            };
    +
    +            nixpkgs-stable = final: _: {
    +              stable = import inputs.nixpkgs-stable {
    +                inherit (final) system;
    +                config.allowUnfree = true;
    +              };
    +            };
    +
    +            nixpkgs-kernel = final: _: {
    +              kernel = import inputs.nixpkgs-kernel {
    +                inherit (final) system;
    +                config.allowUnfree = true;
    +              };
    +            };
    +
    +            nixpkgs-stable24_05 = final: _: {
    +              stable24_05 = import inputs.nixpkgs-stable24_05 {
    +                inherit (final) system;
    +                config.allowUnfree = true;
    +              };
    +            };
    +
    +            nixpkgs-stable24_11 = final: _: {
    +              stable24_11 = import inputs.nixpkgs-stable24_11 {
    +                inherit (final) system;
    +                config.allowUnfree = true;
    +              };
    +            };
    +
    +            zjstatus = _: prev: {
    +              zjstatus = inputs.zjstatus.packages.${prev.system}.default;
    +            };
    +
    +          in
    +          (additions final prev)
    +          // (modifications final prev)
    +          // (nixpkgs-stable final prev)
    +          // (nixpkgs-kernel final prev)
    +          // (nixpkgs-stable24_05 final prev)
    +          // (nixpkgs-stable24_11 final prev)
    +          // (zjstatus final prev)
    +          // (inputs.vbc-nix.overlays.default final prev)
    +          // (inputs.nur.overlays.default final prev)
    +          // (inputs.emacs-overlay.overlay final prev)
    +          // (inputs.nix-topology.overlays.default final prev)
    +          // (inputs.nixgl.overlay final prev);
    +      };
    +    };
    +}
     
    -
    -

    2.7. nixosConfigurations

    -
    -

    -This section used to be much longer, since I performed all of my imports right here in the past. Since then, I have however refactored and now my important hosts can be defined in little space. Once I have fully transitioned my server to NixOS too this section will become even smaller once more. -

    - -

    -Note: The preceding nixosConfigurations is found in flake.nix template. Also, the method of generating the hosts was changed in commit -3a272b1 feat!: dynamically create hosts, and the deprecated system definitions removed in 7457109 main chore: remove deprecated static host config. See those commits for a state with a simpler config. -

    - - +
    +

    2.14. Installer iso

    +
    -
    -
    -
    -
    -
    -
    -

    2.8. darwinConfigurations

    -
    -

    -And this defines darwin systems (MacOS), which I only have one of, that serves as a template mostly. -

    - -

    -Note: The preceding darwinConfigurations is found in flake.nix template. Also, the method of generating the hosts was changed in commit -3a272b1 feat!: dynamically create hosts, and the deprecated system definitions removed in 7457109 main chore: remove deprecated static host config. See those commits for a state with a simpler config. -

    - -
    -
    -
    -
    -
    -
    -
    -

    2.9. homeConfigurations

    -
    -

    -In contrast, this defines home-manager systems, which I only have one of, that serves as a template mostly. -

    - -
    -
    -# "swarsel@home-manager" = inputs.home-manager.lib.homeManagerConfiguration {
    -#  pkgs = lib.swarselsystems.pkgsFor.x86_64-linux;
    -#  extraSpecialArgs = { inherit inputs outputs; };
    -#   modules = homeModules ++ mixedModules ++ [
    -#     ./hosts/home-manager
    -#   ];
    -# };
    -
    -
    -
    -
    -
    -
    -

    2.10. nixOnDroidConfigurations

    -
    -

    -Nix on Android also demands an own flake output, which is provided here. -

    - -
    -
    -# magicant = inputs.nix-on-droid.lib.nixOnDroidConfiguration {
    -#  pkgs = lib.swarselsystems.pkgsFor.aarch64-linux;
    -#   modules = [
    -#     ./hosts/magicant
    -#   ];
    -# };
    -
    -
    -
    -
    -
    -
    -
    -

    2.11. topologyConfigurations

    -
    -
    -
    -
    +
    { inputs, ... }:
    +{
    +  perSystem = { pkgs, system, ... }:
    +    {
    +      # nix build --print-out-paths --no-link .#images.<target-system>.live-iso
    +      packages.live-iso = inputs.nixos-generators.nixosGenerate {
    +        inherit pkgs;
    +        modules = [
    +          inputs.home-manager.nixosModules.home-manager
    +          ./installer-config.nix
    +        ];
    +        format =
    +          {
    +            x86_64-linux = "install-iso";
    +            aarch64-linux = "sd-aarch64-installer";
    +          }
    +          .${system};
    +      };
    +    };
    +}
     
    @@ -1916,12 +2396,13 @@ This is the template that I use for new deployments of personal machines. Server
    3.1.1.1. Main Configuration
    -
    { self, inputs, pkgs, lib, primaryUser, ... }:
    +
    { self, inputs, pkgs, lib, globals, ... }:
     let
       modulesPath = "${self}/modules";
       sharedOptions = {
         isBtrfs = true;
       };
    +  primaryUser = globals.user.name;
     in
     {
     
    @@ -1956,7 +2437,7 @@ in
     
       swarselsystems = lib.recursiveUpdate
         {
    -      wallpaper = self + /wallpaper/lenovowp.png;
    +      wallpaper = self + /files/wallpaper/lenovowp.png;
           hasBluetooth = true;
           hasFingerprint = true;
           isImpermanence = true;
    @@ -2133,8 +2614,9 @@ My work machine. Built for more security, this is the gold standard of my config
     
    3.1.2.1.1. Main Configuration
    -
    { self, config, inputs, lib, primaryUser, ... }:
    +
    { self, config, inputs, lib, globals, ... }:
     let
    +  primaryUser = globals.user.name;
       sharedOptions = {
         isBtrfs = true;
         isLinux = true;
    @@ -2161,7 +2643,7 @@ in
         {
           info = "Framework Laptop 16, 7940HS, RX7700S, 64GB RAM";
           firewall = lib.mkForce true;
    -      wallpaper = self + /wallpaper/lenovowp.png;
    +      wallpaper = self + /files/wallpaper/lenovowp.png;
           hasBluetooth = true;
           hasFingerprint = true;
           isImpermanence = false;
    @@ -2392,8 +2874,9 @@ This is my main server that I run at home. It handles most tasks that require bi
     
    3.1.2.2.1. Main Configuration
    -
    { lib, config, primaryUser, ... }:
    +
    { lib, config, globals, ... }:
     let
    +  primaryUser = globals.user.name;
       sharedOptions = {
         isBtrfs = false;
         isLinux = true;
    @@ -2506,7 +2989,7 @@ A Mac notebook that I have received from work. I use this machine for getting ac
     

    -
    { lib, ... }:
    +
    { lib, config, ... }:
     let
       inherit (config.repo.secrets.local) workUser;
     in
    @@ -2627,14 +3110,16 @@ All of these are processes that use little cpu but can take a lot of storage. Fo
     
    3.1.3.1.1. Main configuration
    -
    { lib, config, primaryUser, ... }:
    +
    { lib, config, globals, ... }:
     let
    +  primaryUser = globals.user.name;
       sharedOptions = {
         isBtrfs = false;
         isLinux = true;
       };
       inherit (config.repo.secrets.common) workHostName;
       inherit (config.repo.secrets.local.syncthing) dev1 dev2 dev3 loc1;
    +  serviceDomain = config.repo.secrets.common.services.domains.syncthing2;
     in
     {
       imports = [
    @@ -2679,11 +3164,12 @@ in
     
       system.stateVersion = "23.11";
     
    +  globals.services."syncthing-${config.networking.hostName}".domain = serviceDomain;
     
       services = {
         nginx = {
           virtualHosts = {
    -        "sync.swarsel.win" = {
    +        ${serviceDomain} = {
               enableACME = true;
               forceSSL = true;
               acmeRoot = null;
    @@ -2739,7 +3225,7 @@ in
                 type = "receiveonly";
                 versioning = {
                   type = "simple";
    -             params.keep = "5";
    +              params.keep = "5";
                 };
                 devices = [ "winters" "magicant" "${workHostName}" ];
                 id = "yjvni-9eaa7";
    @@ -2860,10 +3346,13 @@ in
     
    3.1.3.2.1. Main Configuration
    -
    { lib, config, primaryUser, ... }:
    +
    { lib, config, globals, ... }:
     let
    +  primaryUser = globals.user.name;
       inherit (config.repo.secrets.common) workHostName;
       inherit (config.repo.secrets.local.syncthing) dev1 dev2 dev3 loc1;
    +  serviceDomain = config.repo.secrets.common.services.domains.syncthing3;
    +
       sharedOptions = {
         isBtrfs = true;
         isLinux = true;
    @@ -2902,7 +3391,7 @@ in
       };
     
       topology.self.interfaces.wg = {
    -    addresses = ["192.168.3.4"];
    +    addresses = [ "192.168.3.4" ];
         renderer.hidePhysicalConnections = true;
         virtual = true;
         type = "wireguard";
    @@ -2945,10 +3434,12 @@ in
     
       system.stateVersion = "23.11";
     
    +  globals.services."syncthing-${config.networking.hostName}".domain = serviceDomain;
    +
       services = {
         nginx = {
           virtualHosts = {
    -        "syncthing.swarsel.win" = {
    +        ${serviceDomain} = {
               enableACME = true;
               forceSSL = true;
               acmeRoot = null;
    @@ -3103,7 +3594,7 @@ in
       boot = {
         initrd = {
           availableKernelModules = [ "xhci_pci" "virtio_pci" "virtio_scsi" "usbhid" ];
    -      kernelModules = [  ];
    +      kernelModules = [ ];
         };
         kernelModules = [ ];
         extraModulePackages = [ ];
    @@ -3266,7 +3757,7 @@ This is a slim setup for developing base configuration. I do not track the hardw
     
    3.1.4.1.1. Main Configuration
    -
    { self, inputs, pkgs, lib, primaryUser, ... }:
    +
    { self, inputs, pkgs, lib, ... }:
     let
       modulesPath = "${self}/modules";
       sharedOptions = {
    @@ -3289,7 +3780,7 @@ in
     
         inputs.home-manager.nixosModules.home-manager
         {
    -      home-manager.users."${primaryUser}".imports = [
    +      home-manager.users."setup".imports = [
             inputs.sops-nix.homeManagerModules.sops
             "${modulesPath}/home/common/sharedsetup.nix"
             "${self}/profiles/home"
    @@ -3326,7 +3817,7 @@ in
       swarselsystems = lib.recursiveUpdate
         {
           info = "~SwarselSystems~ remote install helper";
    -      wallpaper = self + /wallpaper/lenovowp.png;
    +      wallpaper = self + /files/wallpaper/lenovowp.png;
           isImpermanence = true;
           isCrypted = false;
           isSecureBoot = false;
    @@ -3338,7 +3829,7 @@ in
         }
         sharedOptions;
     
    -  home-manager.users."${primaryUser}" = {
    +  home-manager.users."setup" = {
         home.stateVersion = lib.mkForce "23.05";
         swarselsystems = lib.recursiveUpdate
           {
    @@ -3500,135 +3991,89 @@ in
     This is a live environment ISO that I use to bootstrap new systems. It only loads a minimal configuration and no graphical interface. After booting this image on a host, find out its IP and bootstrap the system using the bootstrap utility.
     

    -

    -For added convenience, the live environment displays a helpful text on login, we define it here (will be put into /etc/issue): -

    -
    ~SwarselSystems~
    -                         IP of primary interface: \4
    -                                                             The Password for all users & root is 'setup'.
    -                                                             Install the system remotely by running 'bootstrap -n <CONFIGURATION_NAME> -d <IP_FROM_ABOVE> ' on a machine with deployed secrets.
    -                                                             Alternatively, run 'swarsel-install -n <CONFIGURATION_NAME>' for a local install. For your convenience, an example call is in the bash history (press up on the keyboard to access).
    -
    -
    -
    - -

    -Also, an initial bash history is provided to allow for a very quick local deployment: -

    - -
    -
    swarsel-install -n chaostheatre
    -
    -
    - - -
    -
    { self, pkgs, inputs, config, lib, modulesPath, primaryUser ? "swarsel", ... }:
    -let
    -  pubKeys = lib.filesystem.listFilesRecursive "${self}/secrets/keys/ssh";
    -in
    +
    { pkgs, lib, ... }:
     {
     
    -  imports = [
    -    "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix"
    -    "${modulesPath}/installer/cd-dvd/channel.nix"
    -
    -    "${self}/modules/iso/minimal.nix"
    -    "${self}/modules/nixos/common/sharedsetup.nix"
    -    "${self}/modules/nixos/common/topology.nix"
    -    "${self}/modules/home/common/sharedsetup.nix"
    -
    -    "${self}/modules/nixos/common/globals.nix"
    -
    -
    -    inputs.home-manager.nixosModules.home-manager
    -    {
    -      home-manager.users."${primaryUser}".imports = [
    -        "${self}/modules/home/common/settings.nix"
    -        "${self}/modules/home/common/sharedsetup.nix"
    -      ];
    -    }
    -  ];
    -
    -  options.node = {
    -    name = lib.mkOption {
    -      description = "Node Name.";
    -      type = lib.types.str;
    -    };
    -    secretsDir = lib.mkOption {
    -      description = "Path to the secrets directory for this node.";
    -      type = lib.types.path;
    -      default = ./.;
    -    };
    -  };
       config = {
    -    node.name = lib.mkForce "drugstore";
    -    swarselsystems = {
    -      info = "~SwarselSystems~ installer ISO";
    -    };
    -    home-manager.users."${primaryUser}" = {
    -      home = {
    -        stateVersion = "23.05";
    -        file = {
    -          ".bash_history" = {
    -            source = self + /programs/bash/.bash_history;
    -          };
    -        };
    -      };
    -      swarselsystems = {
    -        modules.general = lib.mkForce true;
    -      };
    -    };
         home-manager.users.root.home = {
           stateVersion = "23.05";
           file = {
             ".bash_history" = {
    -          source = self + /programs/bash/.bash_history;
    +          text = ''
    +            swarsel-install -n chaostheatre
    +          '';
             };
           };
         };
     
    -    # environment.etc."issue".text = "\x1B[32m~SwarselSystems~\x1B[0m\nIP of primary interface: \x1B[31m\\4\x1B[0m\nThe Password for all users & root is '\x1B[31msetup\x1B[0m'.\nInstall the system remotely by running '\x1B[33mbootstrap -n <HOSTNAME> -d <IP_FROM_ABOVE> [--impermanence] [--encryption]\x1B[0m' on a machine with deployed secrets.\nAlternatively, run '\x1B[33mswarsel-install -d <DISK> -f <flake>\x1B[0m' for a local install.\n";
    -    environment.etc."issue".source = "${self}/programs/etc/issue";
    -    networking.dhcpcd.runHook = "${pkgs.utillinux}/bin/agetty --reload";
    -
    -    isoImage = {
    -      makeEfiBootable = true;
    -      makeUsbBootable = true;
    -      squashfsCompression = "zstd -Xcompression-level 3";
    -    };
    -
    -    nixpkgs = {
    -      hostPlatform = lib.mkDefault "x86_64-linux";
    -      config.allowUnfree = true;
    -    };
    -
    -    services.getty.autologinUser = lib.mkForce primaryUser;
    -
    -    users = {
    -      allowNoPasswordLogin = true;
    -      groups.swarsel = { };
    -      users = {
    -        swarsel = {
    -          name = primaryUser;
    -          group = primaryUser;
    -          isNormalUser = true;
    -          password = "setup"; # this is overwritten after install
    -          openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key);
    -          extraGroups = [ "wheel" ];
    -        };
    -        root = {
    -          # password = lib.mkForce config.users.users.swarsel.password; # this is overwritten after install
    -          openssh.authorizedKeys.keys = config.users.users."${primaryUser}".openssh.authorizedKeys.keys;
    -        };
    -      };
    +    nix.settings = {
    +      experimental-features = [ "nix-command" "flakes" ];
         };
     
         boot = {
    -      loader.systemd-boot.enable = lib.mkForce true;
    -      loader.efi.canTouchEfiVariables = true;
    +      supportedFilesystems = lib.mkForce [ "brtfs" "vfat" ];
    +      loader.systemd-boot = {
    +        enable = true;
    +      };
    +    };
    +
    +    services = {
    +      qemuGuest.enable = true;
    +      openssh = {
    +        enable = true;
    +        settings.PermitRootLogin = "yes";
    +        authorizedKeysFiles = lib.mkForce [
    +          "/etc/ssh/authorized_keys.d/%u"
    +        ];
    +      };
    +    };
    +
    +    environment.systemPackages = with pkgs; [
    +      curl
    +      git
    +      gnupg
    +      rsync
    +      ssh-to-age
    +      sops
    +      vim
    +      just
    +      sbctl
    +    ];
    +
    +    programs = {
    +      git.enable = true;
    +    };
    +
    +    fileSystems."/boot".options = [ "umask=0077" ];
    +
    +    environment.etc."issue".text = ''
    +      ~SwarselSystems~
    +                               IP of primary interface: \4
    +                                                                   The Password for all users & root is 'setup'.
    +                                                                   Install the system remotely by running 'bootstrap -n <CONFIGURATION_NAME> -d <IP_FROM_ABOVE> ' on a machine with deployed secrets.
    +                                                                   Alternatively, run 'swarsel-install -n <CONFIGURATION_NAME>' for a local install. For your convenience, an example call is in the bash history (press up on the keyboard to access).
    +    '';
    +
    +    networking = {
    +      hostName = "drugstore";
    +      wireless.enable = false;
    +      dhcpcd.runHook = "${pkgs.utillinux}/bin/agetty --reload";
    +      networkmanager.enable = true;
    +    };
    +
    +    services.getty.autologinUser = lib.mkForce "root";
    +
    +    users = {
    +      allowNoPasswordLogin = true;
    +      users = {
    +        root = {
    +          password = "setup"; # this is overwritten after install
    +          initialHashedPassword = lib.mkForce null;
    +          openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDd0XXoLfRE0AyasxscEBwMqOnLWPqwz+etGqzVNeSw/RcgnxOi903mlVjCH+jzWMSe2GVSgzgM20j/r9sfE2P1z+wq/RODFS04JM0ltUoFkkm/IDZXQ2piOk7AoVi5ajdx4EiBnXY87jvxh5cCgQltkj3ouPF7FVN/MaN21IgWYB8NgkaVGft//OplodlDQNot17c0sFMibY0HcquwmHhqKOtKM1gT98+jZl0rd1rCqXFOvkesW6FPC4nzirPai+Hizp5gncrkJOZmLLqrjVx6PfpQzqzIhoUn1YS5CpyfXnKZUgx2Oi8SENmWOZ9DxYvDklgEttob37E2bIXbUhOw/u4I3olGFgCsKL6jg0N+d5teEaCZFnzlOp0UMWiUo7lVqq7Bwl3rNka2pxEdZ9v/1+m9cJiP7h6pnKmccVGku57iGIDnsnoTrmo1qbAje+EsmPYbc+qMnTDvOdSHTOXnjsyTd+ADklvMHCUAuf6ku4ktQEhlZxU3PvYvKHa1cTCEXxLWjytIgHgTgab9M5IH29Q55LSRRQBzUdkwjOG6KhsqG+xEE6038EbXr0MGKTm01AFmeVZWewmkSLu2UdoOMiw8mTSQhQFfp2QruYHnh7oJCo7ttKT1sLoRX+TfgQm1ryn/orhReg2GFfmbiLGxaJGVNvjqCxqrIFQXx4ZDHw== cardno:22_412_399" ];
    +        };
    +      };
         };
     
         programs.bash.shellAliases = {
    @@ -3637,10 +4082,10 @@ in
     
         system.activationScripts.cache = {
           text = ''
    -        mkdir -p -m=0777 /home/${primaryUser}/.local/state/nix/profiles
    -        mkdir -p -m=0777 /home/${primaryUser}/.local/state/home-manager/gcroots
    -        mkdir -p -m=0777 /home/${primaryUser}/.local/share/nix/
    -        printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /home/${primaryUser}/.local/share/nix/trusted-settings.json > /dev/null
    +          mkdir -p -m=0777 /home/setup/.local/state/nix/profiles
    +        mkdir -p -m=0777 /home/setup/.local/state/home-manager/gcroots
    +        mkdir -p -m=0777 /home/setup/.local/share/nix/
    +        printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /home/setup/.local/share/nix/trusted-settings.json > /dev/null
             mkdir -p /root/.local/share/nix/
             printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /root/.local/share/nix/trusted-settings.json > /dev/null
           '';
    @@ -3657,10 +4102,6 @@ in
     
         system.stateVersion = lib.mkForce "23.05";
     
    -    networking = {
    -      hostName = "drugstore";
    -      wireless.enable = false;
    -    };
       };
     }
     
    @@ -3677,15 +4118,14 @@ This is the "reference implementation" of a setup that runs without NixOS, only
     

    -
    { self, outputs, config, ... }:
    +
    { self, inputs, outputs, ... }:
     {
     
       imports = [
         inputs.stylix.homeManagerModules.stylix
         inputs.sops-nix.homeManagerModules.sops
         inputs.nix-index-database.hmModules.nix-index
    -    ./modules/home/common
    -    "${self}/modules/home/common/sharedsetup.nix"
    +    "${self}/modules/home"
       ];
     
       nixpkgs = {
    @@ -3703,7 +4143,7 @@ This is the "reference implementation" of a setup that runs without NixOS, only
       };
     
       programs.zsh.initContent = "
    -  export GPG_TTY=\"$(tty)\"
    +    export GPG_TTY=\"$(tty)\"
       export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
       gpgconf --launch gpg-agent
             ";
    @@ -3711,7 +4151,7 @@ This is the "reference implementation" of a setup that runs without NixOS, only
       swarselsystems = {
         isLaptop = true;
         isNixos = false;
    -    wallpaper = self + /wallpaper/surfacewp.png;
    +    wallpaper = self + /files/wallpaper/surfacewp.png;
       };
     
     }
    @@ -3736,9 +4176,11 @@ I also set the WLR_RENDERER_ALLOW_SOFTWARE=1 to allow this configur
     
    3.1.4.4.1. Main configuration
    -
    { self, inputs, config, pkgs, lib, primaryUser, ... }:
    +
    { self, inputs, config, pkgs, lib, ... }:
     let
    +  mainUser = "demo";
       sharedOptions = {
    +    inherit mainUser;
         isBtrfs = false;
         isLinux = true;
         isPublic = true;
    @@ -3747,65 +4189,65 @@ let
         };
       };
     in
    -{
    +  {
     
    -  imports = [
    -    ./hardware-configuration.nix
    -    ./disk-config.nix
    -    {
    -      _module.args.diskDevice = config.swarselsystems.rootDisk;
    -    }
    -    "${self}/hosts/nixos/chaostheatre/options.nix"
    -    inputs.home-manager.nixosModules.home-manager
    -    {
    -      home-manager.users."${primaryUser}".imports = [
    -        "${self}/modules/home/common/settings.nix"
    -        "${self}/hosts/nixos/chaostheatre/options-home.nix"
    -        "${self}/modules/home/common/sharedsetup.nix"
    -      ];
    -    }
    -  ];
    +    imports = [
    +      ./hardware-configuration.nix
    +      ./disk-config.nix
    +      {
    +        _module.args.diskDevice = config.swarselsystems.rootDisk;
    +      }
    +      "${self}/hosts/nixos/chaostheatre/options.nix"
    +      inputs.home-manager.nixosModules.home-manager
    +      {
    +        home-manager.users."${mainUser}".imports = [
    +          "${self}/modules/home/common/settings.nix"
    +          "${self}/hosts/nixos/chaostheatre/options-home.nix"
    +          "${self}/modules/home/common/sharedsetup.nix"
    +        ];
    +      }
    +    ];
     
    -  environment.variables = {
    -    WLR_RENDERER_ALLOW_SOFTWARE = 1;
    -  };
    +    environment.variables = {
    +      WLR_RENDERER_ALLOW_SOFTWARE = 1;
    +    };
     
    -  services.qemuGuest.enable = true;
    +    services.qemuGuest.enable = true;
     
    -  boot = {
    -    loader.systemd-boot.enable = lib.mkForce true;
    -    loader.efi.canTouchEfiVariables = true;
    -    kernelPackages = lib.mkDefault pkgs.linuxPackages_latest;
    -  };
    +    boot = {
    +      loader.systemd-boot.enable = lib.mkForce true;
    +      loader.efi.canTouchEfiVariables = true;
    +      kernelPackages = lib.mkDefault pkgs.linuxPackages_latest;
    +    };
     
    -  networking = {
    -    hostName = "chaostheatre";
    -    firewall.enable = true;
    -  };
    +    networking = {
    +      hostName = "chaostheatre";
    +      firewall.enable = true;
    +    };
     
    -  swarselsystems = lib.recursiveUpdate
    -    {
    -      info = "~SwarselSystems~ demo host";
    -      wallpaper = self + /wallpaper/lenovowp.png;
    -      initialSetup = true;
    -      isImpermanence = true;
    -      isCrypted = true;
    -      isSecureBoot = false;
    -      isSwap = true;
    -      swapSize = "4G";
    -      rootDisk = "/dev/vda";
    -    }
    -    sharedOptions;
    -
    -  home-manager.users."${primaryUser}" = {
    -    home.stateVersion = lib.mkForce "23.05";
         swarselsystems = lib.recursiveUpdate
           {
    -        isNixos = true;
    +        info = "~SwarselSystems~ demo host";
    +        wallpaper = self + /files/wallpaper/lenovowp.png;
    +        initialSetup = true;
    +        isImpermanence = true;
    +        isCrypted = true;
    +        isSecureBoot = false;
    +        isSwap = true;
    +        swapSize = "4G";
    +        rootDisk = "/dev/vda";
           }
           sharedOptions;
    -  };
    -}
    +
    +    home-manager.users.${mainUser} = {
    +      home.stateVersion = lib.mkForce "23.05";
    +      swarselsystems = lib.recursiveUpdate
    +        {
    +          isNixos = true;
    +        }
    +        sharedOptions;
    +    };
    +  }
     
     
     
    @@ -3818,10 +4260,10 @@ in
    # NOTE: ... is needed because dikso passes diskoFile
     { lib
    -, pkgs
    -, config
    -, diskDevice ? config.swarselsystem.rootDisk
    -, ...
    +  , pkgs
    +  , config
    +  , diskDevice ? config.swarselsystem.rootDisk
    +  , ...
     }:
     let
       type = "btrfs";
    @@ -3873,61 +4315,62 @@ let
         };
       };
     in
    -{
    -  disko.devices = {
    -    disk = {
    -      disk0 = {
    -        type = "disk";
    -        device = diskDevice;
    -        content = {
    -          type = "gpt";
    -          partitions = {
    -            ESP = {
    -              priority = 1;
    -              name = "ESP";
    -              size = "512M";
    -              type = "EF00";
    -              content = {
    -                type = "filesystem";
    -                format = "vfat";
    -                mountpoint = "/boot";
    -                mountOptions = [ "defaults" ];
    -              };
    -            };
    -            root = lib.mkIf (!config.swarselsystems.isCrypted) {
    -              size = "100%";
    -              content = {
    -                inherit type subvolumes extraArgs;
    -                postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
    -                  MNTPOINT=$(mktemp -d)
    -                  mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5
    -                  trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
    -                  btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
    -                '';
    -              };
    -            };
    -            luks = lib.mkIf config.swarselsystems.isCrypted {
    -              size = "100%";
    -              content = {
    -                type = "luks";
    -                name = "cryptroot";
    -                passwordFile = "/tmp/disko-password"; # this is populated by bootstrap.sh
    -                settings = {
    -                  allowDiscards = true;
    -                  # https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36
    -                  crypttabExtraOpts = [
    -                    "fido2-device=auto"
    -                    "token-timeout=10"
    -                  ];
    +  {
    +    disko.devices = {
    +      disk = {
    +        disk0 = {
    +          type = "disk";
    +          device = diskDevice;
    +          content = {
    +            type = "gpt";
    +            partitions = {
    +              ESP = {
    +                priority = 1;
    +                name = "ESP";
    +                size = "512M";
    +                type = "EF00";
    +                content = {
    +                  type = "filesystem";
    +                  format = "vfat";
    +                  mountpoint = "/boot";
    +                  mountOptions = [ "defaults" ];
                     };
    +              };
    +              root = lib.mkIf (!config.swarselsystems.isCrypted) {
    +                size = "100%";
                     content = {
                       inherit type subvolumes extraArgs;
                       postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
                         MNTPOINT=$(mktemp -d)
    +                  mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5
    +                  trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
    +                  btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
    +                  '';
    +                };
    +              };
    +              luks = lib.mkIf config.swarselsystems.isCrypted {
    +                size = "100%";
    +                content = {
    +                  type = "luks";
    +                  name = "cryptroot";
    +                  passwordFile = "/tmp/disko-password"; # this is populated by bootstrap.sh
    +                  settings = {
    +                    allowDiscards = true;
    +                    # https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36
    +                    crypttabExtraOpts = [
    +                      "fido2-device=auto"
    +                      "token-timeout=10"
    +                    ];
    +                  };
    +                  content = {
    +                    inherit type subvolumes extraArgs;
    +                    postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
    +                      MNTPOINT=$(mktemp -d)
                         mount "/dev/mapper/cryptroot" "$MNTPOINT" -o subvolid=5
                         trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
                         btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
    -                  '';
    +                    '';
    +                  };
                     };
                   };
                 };
    @@ -3935,15 +4378,14 @@ in
             };
           };
         };
    -  };
     
    -  fileSystems."/persist".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
    -  fileSystems."/home".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
    +    fileSystems."/persist".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
    +    fileSystems."/home".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
     
    -  environment.systemPackages = [
    -    pkgs.yubikey-manager
    -  ];
    -}
    +    environment.systemPackages = [
    +      pkgs.yubikey-manager
    +    ];
    +  }
     
    @@ -3973,3228 +4415,34 @@ in
    -
    -

    3.2. Additions and modifications

    -
    -

    -In this section I define packages that I manually want to nixpkgs. This can be useful for packages that are currently awaiting a PR or public packages that I do not want to maintain. -

    - -

    -As such, I also define three additional overlays: -

    - -
      -
    1. additions -These are for the aforementioned added packages
    2. -
    3. modification -These are for packages that are on nixpkgs, but do not fit my usecase, meaning I need to perform modifications on them.
    4. -
    5. nixpkgs-stable -This is simply a mirror of the most recent stable branch of nixpkgs. Useful for packages that are broken on nixpkgs, but do not need to be on bleeding edge anyways.
    6. -
    - -

    -Also, this is where I define all of my own modules. These are mostly used for setting some host-specifics directly than opposed to through multiple options. -

    - -

    -Lastly, I add some of my own library functions to be used alongside the functions provided by nixpkgs and home-manager. -

    -
    -
    -

    3.2.1. Packages

    -
    -

    -This is the central station for self-defined packages. These are all referenced in default.nix. Wherever possible, I am keeping the shell version of these scripts in this file as well and then read it using builtin.readFile in the NixOS configurations. This lets me keep full control in this one file but also keep the separate files uncluttered. -

    - -

    -Note: The structure of generating the packages was changed in commit 2cf03a3 refactor: package and module generation. That commit can be checked out in order to see a simpler version of achieving the same thing. -

    - -
    -
    { lib, pkgs, ... }:
    -let
    -  packageNames = lib.swarselsystems.readNix "pkgs";
    -in
    -lib.swarselsystems.mkPackages packageNames pkgs
    -
    -
    -
    -
    -
    -
    -
    3.2.1.1. pass-fuzzel
    -
    -

    -This app allows me, in conjunction with my Yubikey, to quickly enter passwords when the need arises. Normal and TOTP passwords are supported, and they can either be printed directly or copied to the clipboard. -

    - -
    -
    # Adapted from https://code.kulupu.party/thesuess/home-manager/src/branch/main/modules/river.nix
    -shopt -s nullglob globstar
    -
    -otp=0
    -typeit=0
    -while :; do
    -    case ${1:-} in
    -    -t | --type)
    -        typeit=1
    -        ;;
    -    -o | --otp)
    -        otp=1
    -        ;;
    -    *) break ;;
    -    esac
    -    shift
    -done
    -
    -export PASSWORD_STORE_DIR=~/.local/share/password-store
    -prefix=${PASSWORD_STORE_DIR-~/.local/share/password-store}
    -if [[ $otp -eq 0 ]]; then
    -    password_files=("$prefix"/**/*.gpg)
    -else
    -    password_files=("$prefix"/otp/**/*.gpg)
    -fi
    -password_files=("${password_files[@]#"$prefix"/}")
    -password_files=("${password_files[@]%.gpg}")
    -
    -password=$(printf '%s\n' "${password_files[@]}" | fuzzel --dmenu "$@")
    -
    -[[ -n $password ]] || exit
    -if [[ $otp -eq 0 ]]; then
    -    if [[ $typeit -eq 0 ]]; then
    -        pass show -c "$password" &> /tmp/pass-fuzzel
    -    else
    -        pass show "$password" | {
    -            IFS= read -r pass
    -            printf %s "$pass"
    -        } | wtype -
    -    fi
    -else
    -    if [[ $typeit -eq 0 ]]; then
    -        pass otp -c "$password" &> /tmp/pass-fuzzel
    -    else
    -        pass otp "$password" | {
    -            IFS= read -r pass
    -            printf %s "$pass"
    -        } | wtype -
    -    fi
    -fi
    -notify-send -u critical -a pass -t 1000 "Copied/Typed Password"
    -
    -
    - -
    -
    { self, name, writeShellApplication, libnotify, pass, fuzzel, wtype }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ libnotify (pass.withExtensions (exts: [ exts.pass-otp ])) fuzzel wtype ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.2. cura5
    -
    -

    -The version of cura used to be quite outdated in nixpkgs. I am fetching a newer AppImage here and use that instead. -

    - - -
    -
    # taken from https://github.com/NixOS/nixpkgs/issues/186570#issuecomment-1627797219
    -{ appimageTools, fetchurl, writeScriptBin, pkgs, ... }:
    -
    -
    -let
    -  cura5 = appimageTools.wrapType2 rec {
    -    pname = "cura5";
    -    version = "5.9.0";
    -    src = fetchurl {
    -      url = "https://github.com/Ultimaker/Cura/releases/download/${version}/UltiMaker-Cura-${version}-linux-X64.AppImage";
    -      hash = "sha256-STtVeM4Zs+PVSRO3cI0LxnjRDhOxSlttZF+2RIXnAp4=";
    -    };
    -    extraPkgs = pkgs: with pkgs; [ ];
    -  };
    -in
    -writeScriptBin "cura" ''
    -  #! ${pkgs.bash}/bin/bash
    -  # AppImage version of Cura loses current working directory and treats all paths relative to $HOME.
    -  # So we convert each of the files passed as argument to an absolute path.
    -  # This fixes use cases like `cd /path/to/my/files; cura mymodel.stl anothermodel.stl`.
    -  args=()
    -  for a in "$@"; do
    -      if [ -e "$a" ]; then
    -         a="$(realpath "$a")"
    -      fi
    -      args+=("$a")
    -  done
    -  exec "${cura5}/bin/cura5" "''${args[@]}"
    -''
    -
    -
    -
    -
    -
    -
    -
    3.2.1.3. hm-specialisation
    -
    -

    -This script allows for quick git home-manager specialisation switching. -

    - - -
    -
    { name, writeShellApplication, fzf, findutils, home-manager, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ fzf findutils home-manager ];
    -  text = ''
    -    genpath=$(home-manager generations | head -1 | awk '{print $7}')
    -    dirs=$(find "$genpath/specialisation" -type l 2>/dev/null; [ -d "$genpath" ] && echo "$genpath")
    -    "$(echo "$dirs" | fzf --prompt="Choose home-manager specialisation to activate")"/activate
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    -
    -
    3.2.1.4. cdw
    -
    -

    -This script allows for quick git worktree switching. -

    - - -
    -
    { name, writeShellApplication, fzf, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ fzf ];
    -  text = ''
    -    cd "$(git worktree list | fzf | awk '{print $1}')"
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    -
    -
    3.2.1.5. cdb
    -
    -

    -This script allows for quick git branch switching. -

    - -
    -
    { name, writeShellApplication, fzf, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ fzf ];
    -  text = ''
    -    git checkout "$(git branch --list | grep -v "^\*" | fzf | awk '{print $1}')"
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.6. bak
    -
    -

    -This script lets me quickly backup files by appending .bak to the filename. -

    - - -
    -
    { name, writeShellApplication, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  text = ''
    -    cp -r "$1"{,.bak}
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    -
    -
    3.2.1.7. timer
    -
    -

    -This app starts a configuratble timer and uses TTS to say something once the timer runs out. -

    - - -
    -
    { name, writeShellApplication, speechd, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ speechd ];
    -  text = ''
    -    sleep "$1"; while true; do spd-say "$2"; sleep 0.5; done;
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.8. e
    -
    -

    -This is a shorthand for calling emacsclient mostly. Also, it hides the kittyterm scratchpad window that I sometimes use for calling a command quickly, in case it is on the screen. After emacs closes, the kittyterm window is then shown again if it was visible earlier. -

    - -
    -
    wait=0
    -while :; do
    -    case ${1:-} in
    -    -w | --wait)
    -        wait=1
    -        ;;
    -    *) break ;;
    -    esac
    -    shift
    -done
    -
    -STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep kittyterm || true)
    -if [ "$STR" == "" ]; then
    -    swaymsg '[title="kittyterm"]' scratchpad show
    -    emacsclient -c -a "" "$@"
    -    swaymsg '[title="kittyterm"]' scratchpad show
    -else
    -    if [[ $wait -eq 0 ]]; then
    -        emacsclient -n -c -a "" "$@"
    -    else
    -        emacsclient -c -a "" "$@"
    -    fi
    -fi
    -
    -
    - -
    -
    { self, name, writeShellApplication, emacs30-pgtk, sway, jq }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ emacs30-pgtk sway jq ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.9. command-not-found
    -
    -

    -The normal command-not-found.sh uses the outdated nix-shell commands as suggestions. This version supplies me with the more modern nixpkgs#<name> version. -

    - - -
    -
    # Adapted from https://github.com/bennofs/nix-index/blob/master/command-not-found.sh
    -command_not_found_handle() {
    -    if [ -n "${MC_SID-}" ] || ! [ -t 1 ]; then
    -        >&2 echo "$1: command not found"
    -        return 127
    -    fi
    -
    -    echo -n "searching nix-index..."
    -    ATTRS=$(@nix-locate@ --minimal --no-group --type x --type s --top-level --whole-name --at-root "/bin/$1")
    -
    -    case $(echo -n "$ATTRS" | grep -c "^") in
    -    0)
    -        >&2 echo -ne "$(@tput@ el1)\r"
    -        >&2 echo "$1: command not found"
    -        ;;
    -    *)
    -        >&2 echo -ne "$(@tput@ el1)\r"
    -        >&2 echo "The program ‘$(@tput@ setaf 4)$1$(@tput@ sgr0)’ is currently not installed."
    -        >&2 echo "It is provided by the following derivation(s):"
    -        while read -r ATTR; do
    -            ATTR=${ATTR%.out}
    -            >&2 echo "  $(@tput@ setaf 12)nixpkgs#$(@tput@ setaf 4)$ATTR$(@tput@ sgr0)"
    -        done <<< "$ATTRS"
    -        ;;
    -    esac
    -
    -    return 127
    -}
    -
    -command_not_found_handler() {
    -    command_not_found_handle "$@"
    -    return $?
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.10. swarselcheck
    -
    -

    -This app checks for different apps that I keep around in the scratchpad for quick viewing and hiding (messengers and music players mostly) and then behaves like the kittyterm hider that I described in e. -

    - -
    -
    kitty=0
    -element=0
    -vesktop=0
    -spotifyplayer=0
    -while :; do
    -    case ${1:-} in
    -    -k | --kitty)
    -        kitty=1
    -        ;;
    -    -e | --element)
    -        element=1
    -        ;;
    -    -d | --vesktop)
    -        vesktop=1
    -        ;;
    -    -s | --spotifyplayer)
    -        spotifyplayer=1
    -        ;;
    -    *) break ;;
    -    esac
    -    shift
    -done
    -
    -if [[ $kitty -eq 1 ]]; then
    -    STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep kittyterm || true)
    -    CHECK=$(swaymsg -t get_tree | grep kittyterm || true)
    -    if [ "$CHECK" == "" ]; then
    -        exec kitty -T kittyterm -o confirm_os_window_close=0 zellij attach --create kittyterm &
    -        sleep 1
    -    fi
    -    if [ "$STR" == "" ]; then
    -        exec swaymsg '[title="kittyterm"]' scratchpad show
    -    else
    -        exec swaymsg '[title="kittyterm"]' scratchpad show
    -    fi
    -elif [[ $element -eq 1 ]]; then
    -    STR=$(swaymsg -t get_tree | grep Element || true)
    -    if [ "$STR" == "" ]; then
    -        exec element-desktop
    -    else
    -        exec swaymsg '[app_id=Element]' kill
    -    fi
    -elif [[ $vesktop -eq 1 ]]; then
    -    STR=$(swaymsg -t get_tree | grep vesktop || true)
    -    if [ "$STR" == "" ]; then
    -        exec vesktop
    -    else
    -        exec swaymsg '[app_id=vesktop]' kill
    -    fi
    -elif [[ $spotifyplayer -eq 1 ]]; then
    -    STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep spotifytui || true)
    -    CHECK=$(swaymsg -t get_tree | grep spotifytui || true)
    -    if [ "$CHECK" == "" ]; then
    -        exec kitty -T spotifytui -o confirm_os_window_close=0 spotify_player &
    -        sleep 1
    -    fi
    -    if [ "$STR" == "" ]; then
    -        exec swaymsg '[title="spotifytui"]' scratchpad show
    -    else
    -        exec swaymsg '[title="spotifytui"]' scratchpad show
    -    fi
    -fi
    -
    -
    - -
    -
    { self, name, writeShellApplication, kitty, element-desktop, vesktop, spotify-player, jq }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ kitty element-desktop vesktop spotify-player jq ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.11. swarselzellij
    -
    -
    -
    KITTIES=$(($(pgrep -P 1 kitty | wc -l) - 1))
    -
    -if ((KITTIES < 1)); then
    -    exec kitty -o confirm_os_window_close=0 zellij attach --create main
    -else
    -    exec kitty -o confirm_os_window_close=0 zellij attach --create "temp $KITTIES"
    -fi
    -
    -
    - -
    -
    { self, name, writeShellApplication, kitty }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ kitty ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.12. waybarupdate
    -
    -

    -This scripts checks if there are uncommited changes in either my dotfile repo, my university repo, or my passfile repo. In that case a warning will be shown in waybar. -

    - -
    -
    CFG=$(git --git-dir="$HOME"/.dotfiles/.git --work-tree="$HOME"/.dotfiles/ status -s | wc -l)
    -CSE=$(git --git-dir="$DOCUMENT_DIR_PRIV"/CSE_TUWIEN/.git --work-tree="$DOCUMENT_DIR_PRIV"/CSE_TUWIEN/ status -s | wc -l)
    -PASS=$(($(git --git-dir="$HOME"/.local/share/password-store/.git --work-tree="$HOME"/.local/share/password-store/ status -s | wc -l) + $(git --git-dir="$HOME"/.local/share/password-store/.git --work-tree="$HOME"/.local/share/password-store/ diff origin/main..HEAD | wc -l)))
    -
    -if [[ $CFG != 0 ]]; then
    -    CFG_STR='CONFIG'
    -else
    -    CFG_STR=''
    -fi
    -
    -if [[ $CSE != 0 ]]; then
    -    CSE_STR=' CSE'
    -else
    -    CSE_STR=''
    -fi
    -
    -if [[ $PASS != 0 ]]; then
    -    PASS_STR=' PASS'
    -else
    -    PASS_STR=''
    -fi
    -
    -OUT="$CFG_STR""$CSE_STR""$PASS_STR"
    -echo "$OUT"
    -
    -
    - -
    -
    { self, name, writeShellApplication, git }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ git ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.13. opacitytoggle
    -
    -

    -This app quickly toggles between 5% and 0% transparency. -

    - -
    -
    if swaymsg opacity plus 0.01 -q; then
    -    swaymsg opacity 1
    -else
    -    swaymsg opacity 0.95
    -fi
    -
    -
    - -
    -
    { self, name, writeShellApplication, sway }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ sway ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.14. fs-diff
    -
    -

    -This utility is used to compare the current state of the root directory with the blanket state that is stored in /root-blank (the snapshot that is restored on each reboot of an impermanence machine). Using this, I can find files that I will lose once I reboot - if there are important files in that list, I can then easily add them to the persist options. -

    - -
    -
    set -euo pipefail
    -
    -OLD_TRANSID=$(sudo btrfs subvolume find-new /mnt/root-blank 9999999)
    -OLD_TRANSID=${OLD_TRANSID#transid marker was }
    -
    -sudo btrfs subvolume find-new "/mnt/root" "$OLD_TRANSID" |
    -    sed '$d' |
    -    cut -f17- -d' ' |
    -    sort |
    -    uniq |
    -    while read -r path; do
    -        path="/$path"
    -        if [ -L "$path" ]; then
    -            : # The path is a symbolic link, so is probably handled by NixOS already
    -        elif [ -d "$path" ]; then
    -            : # The path is a directory, ignore
    -        else
    -            echo "$path"
    -        fi
    -    done
    -
    -
    - -
    -
    { self, name, writeShellApplication }:
    -writeShellApplication {
    -  inherit name;
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.15. github-notifications
    -
    -

    -This utility checks if there are updated packages in nixpkgs-unstable. It does so by fully building the most recent configuration, which I do not love, but it has its merits once I am willing to switch to the newer version. -

    - - -
    -
    { name, writeShellApplication, jq, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ jq ];
    -  text = ''
    -    count=$(curl -u Swarsel:"$(cat "$XDG_RUNTIME_DIR/secrets/github_notif")" https://api.github.com/notifications | jq '. | length')
    -
    -    if [[ "$count" != "0" ]]; then
    -        echo "{\"text\":\"$count\"}"
    -    fi
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.16. fullscreen
    -
    -

    -This application moves the wl-mirror app to the T workspace and makes it fullscreen there. -

    - -
    -
    { name, writeShellApplication, sway, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ sway ];
    -  text = ''
    -    swaymsg '[app_id=at.yrlf.wl_mirror] move to workspace 14:T'
    -    swaymsg '[app_id=at.yrlf.wl_mirror] fullscreen'
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.17. screenshare
    -
    -
    -
    -headless="false"
    -while [[ $# -gt 0 ]]; do
    -    case "$1" in
    -    -h)
    -        headless="true"
    -        ;;
    -    *)
    -        echo "Invalid option detected."
    -        ;;
    -    esac
    -    shift
    -done
    -
    -SHARESCREEN="$(nix eval --raw ~/.dotfiles#nixosConfigurations."$(hostname)".config.home-manager.users."$(whoami)".swarselsystems.sharescreen)"
    -
    -if [[ $headless == "true" ]]; then
    -    wl-mirror "$SHARESCREEN"
    -else
    -    wl-mirror "$SHARESCREEN" &
    -    sleep 0.1
    -    swaymsg '[app_id=at.yrlf.wl_mirror] move to workspace 14:T'
    -    swaymsg '[app_id=at.yrlf.wl_mirror] fullscreen'
    -fi
    -
    -
    - - -
    -
    { self, name, writeShellApplication, sway }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ sway ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.18. swarsel-bootstrap
    -
    -

    -This program sets up a new NixOS host remotely. It also takes care of secret management on the new host. -

    - -
    -
    # highly inspired by https://github.com/EmergentMind/nix-config/blob/dev/scripts/bootstrap-nixos.sh
    -set -eo pipefail
    -
    -target_hostname=""
    -target_destination=""
    -target_user="swarsel"
    -ssh_port="22"
    -persist_dir=""
    -disk_encryption=0
    -temp=$(mktemp -d)
    -
    -function help_and_exit() {
    -    echo
    -    echo "Remotely installs SwarselSystem on a target machine including secret deployment."
    -    echo
    -    echo "USAGE: $0 -n <target_hostname> -d <target_destination> [OPTIONS]"
    -    echo
    -    echo "ARGS:"
    -    echo "  -n <target_hostname>                    specify target_hostname of the target host to deploy the nixos config on."
    -    echo "  -d <target_destination>                 specify ip or url to the target host."
    -    echo "                                          target during install process."
    -    echo
    -    echo "OPTIONS:"
    -    echo "  -u <target_user>                        specify target_user with sudo access. nix-config will be cloned to their home."
    -    echo "                                          Default='${target_user}'."
    -    echo "  --port <ssh_port>                       specify the ssh port to use for remote access. Default=${ssh_port}."
    -    echo "  --debug                                 Enable debug mode."
    -    echo "  -h | --help                             Print this help."
    -    exit 0
    -}
    -
    -function cleanup() {
    -    rm -rf "$temp"
    -}
    -trap cleanup exit
    -
    -function red() {
    -    echo -e "\x1B[31m[!] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[31m[!] $($2) \x1B[0m"
    -    fi
    -}
    -function green() {
    -    echo -e "\x1B[32m[+] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[32m[+] $($2) \x1B[0m"
    -    fi
    -}
    -function yellow() {
    -    echo -e "\x1B[33m[*] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[33m[*] $($2) \x1B[0m"
    -    fi
    -}
    -
    -function yes_or_no() {
    -    echo -en "\x1B[32m[+] $* [y/n] (default: y): \x1B[0m"
    -    while true; do
    -        read -rp "" yn
    -        yn=${yn:-y}
    -        case $yn in
    -        [Yy]*) return 0 ;;
    -        [Nn]*) return 1 ;;
    -        esac
    -    done
    -}
    -
    -function update_sops_file() {
    -    key_name=$1
    -    key_type=$2
    -    key=$3
    -
    -    if [ ! "$key_type" == "hosts" ] && [ ! "$key_type" == "users" ]; then
    -        red "Invalid key type passed to update_sops_file. Must be either 'hosts' or 'users'."
    -        exit 1
    -    fi
    -    cd "${git_root}"
    -
    -    SOPS_FILE=".sops.yaml"
    -    sed -i "{
    -                                                # Remove any * and & entries for this host
    -                                                /[*&]$key_name/ d;
    -                                                # Inject a new age: entry
    -                                                # n matches the first line following age: and p prints it, then we transform it while reusing the spacing
    -                                                /age:/{n; p; s/\(.*- \*\).*/\1$key_name/};
    -                                                # Inject a new hosts or user: entry
    -                                                /&$key_type/{n; p; s/\(.*- &\).*/\1$key_name $key/}
    -                                                }" $SOPS_FILE
    -    green "Updating .sops.yaml"
    -    cd -
    -}
    -
    -while [[ $# -gt 0 ]]; do
    -    case "$1" in
    -    -n)
    -        shift
    -        target_hostname=$1
    -        ;;
    -    -d)
    -        shift
    -        target_destination=$1
    -        ;;
    -    -u)
    -        shift
    -        target_user=$1
    -        ;;
    -    --port)
    -        shift
    -        ssh_port=$1
    -        ;;
    -    --debug)
    -        set -x
    -        ;;
    -    -h | --help) help_and_exit ;;
    -    *)
    -        echo "Invalid option detected."
    -        help_and_exit
    -        ;;
    -    esac
    -    shift
    -done
    -
    -green "~SwarselSystems~ remote installer"
    -green "Reading system information for $target_hostname ..."
    -
    -DISK="$(nix eval --raw ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.rootDisk)"
    -green "Root Disk: $DISK"
    -
    -CRYPTED="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isCrypted)"
    -if [[ $CRYPTED == "true" ]]; then
    -    green "Encryption: ✓"
    -    disk_encryption=1
    -else
    -    red "Encryption: X"
    -    disk_encryption=0
    -fi
    -
    -IMPERMANENCE="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isImpermanence)"
    -if [[ $IMPERMANENCE == "true" ]]; then
    -    green "Impermanence: ✓"
    -    persist_dir="/persist"
    -else
    -    red "Impermanence: X"
    -    persist_dir=""
    -fi
    -
    -SWAP="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isSwap)"
    -if [[ $SWAP == "true" ]]; then
    -    green "Swap: ✓"
    -else
    -    red "Swap: X"
    -fi
    -
    -SECUREBOOT="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isSecureBoot)"
    -if [[ $SECUREBOOT == "true" ]]; then
    -    green "Secure Boot: ✓"
    -else
    -    red "Secure Boot: X"
    -fi
    -
    -ssh_cmd="ssh -oport=${ssh_port} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -t $target_user@$target_destination"
    -# ssh_root_cmd=$(echo "$ssh_cmd" | sed "s|${target_user}@|root@|") # uses @ in the sed switch to avoid it triggering on the $ssh_key value
    -ssh_root_cmd=${ssh_cmd/${target_user}@/root@}
    -scp_cmd="scp -oport=${ssh_port} -o StrictHostKeyChecking=no"
    -
    -if [[ -z ${FLAKE} ]]; then
    -    FLAKE=/home/"$target_user"/.dotfiles
    -fi
    -if [ ! -d "$FLAKE" ]; then
    -    cd /home/"$target_user"
    -    yellow "Flake directory not found - cloning repository from GitHub"
    -    git clone git@github.com:Swarsel/.dotfiles.git || (yellow "Could not clone repository via SSH - defaulting to HTTPS" && git clone https://github.com/Swarsel/.dotfiles.git)
    -    FLAKE=/home/"$target_user"/.dotfiles
    -fi
    -
    -cd "$FLAKE"
    -git_root=$(git rev-parse --show-toplevel)
    -# ------------------------
    -green "Wiping known_hosts of $target_destination"
    -sed -i "/$target_hostname/d; /$target_destination/d" ~/.ssh/known_hosts
    -# ------------------------
    -green "Preparing a new ssh_host_ed25519_key pair for $target_hostname."
    -# Create the directory where sshd expects to find the host keys
    -install -d -m755 "$temp/$persist_dir/etc/ssh"
    -# Generate host ssh key pair without a passphrase
    -ssh-keygen -t ed25519 -f "$temp/$persist_dir/etc/ssh/ssh_host_ed25519_key" -C root@"$target_hostname" -N ""
    -# Set the correct permissions so sshd will accept the key
    -chmod 600 "$temp/$persist_dir/etc/ssh/ssh_host_ed25519_key"
    -echo "Adding ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
    -# This will fail if we already know the host, but that's fine
    -ssh-keyscan -p "$ssh_port" "$target_destination" >> ~/.ssh/known_hosts || true
    -# ------------------------
    -# when using luks, disko expects a passphrase on /tmp/disko-password, so we set it for now and will update the passphrase later
    -# via the config
    -if [ "$disk_encryption" -eq 1 ]; then
    -    while true; do
    -        green "Set disk encryption passphrase:"
    -        read -rs luks_passphrase
    -        green "Please confirm passphrase:"
    -        read -rs luks_passphrase_confirm
    -        if [[ $luks_passphrase == "$luks_passphrase_confirm" ]]; then
    -            $ssh_root_cmd "/bin/sh -c 'echo $luks_passphrase > /tmp/disko-password'"
    -            break
    -        else
    -            red "Passwords do not match"
    -        fi
    -    done
    -fi
    -# ------------------------
    -green "Generating hardware-config.nix for $target_hostname and adding it to the nix-config."
    -$ssh_root_cmd "nixos-generate-config --force --no-filesystems --root /mnt"
    -
    -green "Injecting initialSetup"
    -$ssh_root_cmd "sed -i '/  boot.extraModulePackages /a \  swarselsystems.initialSetup = true;' /mnt/etc/nixos/hardware-configuration.nix"
    -
    -mkdir -p "$FLAKE"/hosts/nixos/"$target_hostname"
    -$scp_cmd root@"$target_destination":/mnt/etc/nixos/hardware-configuration.nix "${git_root}"/hosts/nixos/"$target_hostname"/hardware-configuration.nix
    -# ------------------------
    -
    -green "Deploying minimal NixOS installation on $target_destination"
    -SHELL=/bin/sh nix run github:nix-community/nixos-anywhere -- --ssh-port "$ssh_port" --extra-files "$temp" --flake .#"$target_hostname" root@"$target_destination"
    -
    -echo "Updating ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
    -ssh-keyscan -p "$ssh_port" "$target_destination" >> ~/.ssh/known_hosts || true
    -# ------------------------
    -
    -while true; do
    -    read -rp "Press Enter to continue once the remote host has finished booting."
    -    if nc -z "$target_destination" "${ssh_port}" 2> /dev/null; then
    -        green "$target_destination is booted. Continuing..."
    -        break
    -    else
    -        yellow "$target_destination is not yet ready."
    -    fi
    -done
    -
    -# ------------------------
    -
    -if [[ $SECUREBOOT == "true" ]]; then
    -    green "Setting up secure boot keys"
    -    $ssh_root_cmd "mkdir -p /var/lib/sbctl"
    -    read -ra scp_call <<< "${scp_cmd}"
    -    sudo "${scp_call[@]}" -r /var/lib/sbctl root@"$target_destination":/var/lib/
    -    $ssh_root_cmd "sbctl enroll-keys --ignore-immutable --microsoft || true"
    -fi
    -# ------------------------
    -green "Disabling initialSetup"
    -sed -i '/swarselsystems\.initialSetup = true;/d' "$git_root"/hosts/nixos/"$target_hostname"/hardware-configuration.nix
    -
    -if [ -n "$persist_dir" ]; then
    -    $ssh_root_cmd "cp /etc/machine-id $persist_dir/etc/machine-id || true"
    -    $ssh_root_cmd "cp -R /etc/ssh/ $persist_dir/etc/ssh/ || true"
    -fi
    -# ------------------------
    -green "Generating an age key based on the new ssh_host_ed25519_key."
    -target_key=$(
    -    ssh-keyscan -p "$ssh_port" -t ssh-ed25519 "$target_destination" 2>&1 |
    -        grep ssh-ed25519 |
    -        cut -f2- -d" " ||
    -        (
    -            red "Failed to get ssh key. Host down?"
    -            exit 1
    -        )
    -)
    -host_age_key=$(nix shell nixpkgs#ssh-to-age.out -c sh -c "echo $target_key | ssh-to-age")
    -
    -if grep -qv '^age1' <<< "$host_age_key"; then
    -    red "The result from generated age key does not match the expected format."
    -    yellow "Result: $host_age_key"
    -    yellow "Expected format: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    -    exit 1
    -else
    -    echo "$host_age_key"
    -fi
    -
    -green "Updating nix-secrets/.sops.yaml"
    -update_sops_file "$target_hostname" "hosts" "$host_age_key"
    -yellow ".sops.yaml has been updated. There may be superfluous entries, you might need to edit manually."
    -if yes_or_no "Do you want to manually edit .sops.yaml now?"; then
    -    vim "${git_root}"/.sops.yaml
    -fi
    -green "Updating all secrets files to reflect updates .sops.yaml"
    -sops updatekeys --yes --enable-local-keyservice "${git_root}"/secrets/*/secrets.yaml
    -# --------------------------
    -green "Making ssh_host_ed25519_key available to home-manager for user $target_user"
    -sed -i "/$target_hostname/d; /$target_destination/d" ~/.ssh/known_hosts
    -$scp_cmd root@"$target_destination":/etc/ssh/ssh_host_ed25519_key root@"$target_destination":/home/"$target_user"/.ssh/ssh_host_ed25519_key
    -$ssh_root_cmd "mkdir -p /home/$target_user/.ssh; chown $target_user:users /home/$target_user/.ssh/ssh_host_ed25519_key"
    -# __________________________
    -
    -if yes_or_no "Add ssh host fingerprints for git upstream repositories? (This is needed for building the full config)"; then
    -    green "Adding ssh host fingerprints for git{lab,hub}"
    -    $ssh_cmd "mkdir -p /home/$target_user/.ssh/; ssh-keyscan -t ssh-ed25519 gitlab.com github.com swagit.swarsel.win >> /home/$target_user/.ssh/known_hosts"
    -    $ssh_root_cmd "mkdir -p /root/.ssh/; ssh-keyscan -t ssh-ed25519 gitlab.com github.com swagit.swarsel.win >> /root/.ssh/known_hosts"
    -fi
    -# --------------------------
    -
    -if yes_or_no "Do you want to copy your full nix-config and nix-secrets to $target_hostname?"; then
    -    green "Adding ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
    -    ssh-keyscan -p "$ssh_port" "$target_destination" >> ~/.ssh/known_hosts || true
    -    green "Copying full nix-config to $target_hostname"
    -    cd "${git_root}"
    -    just sync "$target_user" "$target_destination"
    -
    -    if [ -n "$persist_dir" ]; then
    -        $ssh_root_cmd "cp -r /home/$target_user/.dotfiles $persist_dir/.dotfiles || true"
    -        $ssh_root_cmd "cp -r /home/$target_user/.ssh $persist_dir/.ssh || true"
    -    fi
    -
    -    if yes_or_no "Do you want to rebuild immediately?"; then
    -        green "Rebuilding nix-config on $target_hostname"
    -        yellow "Reminder: The password is 'setup'"
    -        $ssh_root_cmd "mkdir -p /root/.local/share/nix/; printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' > /root/.local/share/nix/trusted-settings.json"
    -        $ssh_cmd -oForwardAgent=yes "cd .dotfiles && sudo nixos-rebuild --show-trace --flake .#$target_hostname switch"
    -    fi
    -else
    -    echo
    -    green "NixOS was successfully installed!"
    -    echo "Post-install config build instructions:"
    -    echo "To copy nix-config from this machine to the $target_hostname, run the following command from ~/nix-config"
    -    echo "just sync $target_user $target_destination"
    -    echo "To rebuild, sign into $target_hostname and run the following command from ~/nix-config"
    -    echo "cd nix-config"
    -    # see above FIXME:(bootstrap)
    -    echo "sudo nixos-rebuild --show-trace --flake .#$target_hostname switch"
    -    # echo "just rebuild"
    -    echo
    -fi
    -
    -if yes_or_no "You can now commit and push the nix-config, which includes the hardware-configuration.nix for $target_hostname?"; then
    -    cd "${git_root}"
    -    deadnix hosts/nixos/"$target_hostname"/hardware-configuration.nix -qe
    -    nixpkgs-fmt hosts/nixos/"$target_hostname"/hardware-configuration.nix
    -    (pre-commit run --all-files 2> /dev/null || true) &&
    -        git add "$git_root/hosts/nixos/$target_hostname/hardware-configuration.nix" &&
    -        git add "$git_root/.sops.yaml" &&
    -        git add "$git_root/secrets" &&
    -        (git commit -m "feat: deployed $target_hostname" || true) && git push
    -fi
    -
    -
    - - -
    -
    { self, name, writeShellApplication, openssh }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ openssh ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.19. swarsel-rebuild
    -
    -
    -
    set -eo pipefail
    -
    -target_config="chaostheatre"
    -target_user="swarsel"
    -
    -function help_and_exit() {
    -    echo
    -    echo "Builds SwarselSystem configuration."
    -    echo
    -    echo "USAGE: $0 [OPTIONS]"
    -    echo
    -    echo "ARGS:"
    -    echo "  -n <target_config>                       specify nixos config to build."
    -    echo "                                          Default: chaostheatre"
    -    echo "  -u <target_user>                        specify user to deploy for."
    -    echo "                                          Default: swarsel"
    -    echo "  -h | --help                             Print this help."
    -    exit 0
    -}
    -
    -function red() {
    -    echo -e "\x1B[31m[!] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[31m[!] $($2) \x1B[0m"
    -    fi
    -}
    -function green() {
    -    echo -e "\x1B[32m[+] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[32m[+] $($2) \x1B[0m"
    -    fi
    -}
    -function yellow() {
    -    echo -e "\x1B[33m[*] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[33m[*] $($2) \x1B[0m"
    -    fi
    -}
    -
    -while [[ $# -gt 0 ]]; do
    -    case "$1" in
    -    -n)
    -        shift
    -        target_config=$1
    -        ;;
    -    -u)
    -        shift
    -        target_user=$1
    -        ;;
    -    -h | --help) help_and_exit ;;
    -    *)
    -        echo "Invalid option detected."
    -        help_and_exit
    -        ;;
    -    esac
    -    shift
    -done
    -
    -cd /home/"$target_user"
    -
    -if [ ! -d /home/"$target_user"/.dotfiles ]; then
    -    green "Cloning repository from GitHub"
    -    git clone https://github.com/Swarsel/.dotfiles.git
    -else
    -    red "A .dotfiles repository is in the way. Please (re-)move the repository and try again."
    -    exit 1
    -fi
    -
    -local_keys=$(ssh-add -L || true)
    -pub_key=$(cat /home/"$target_user"/.dotfiles/secrets/keys/ssh/yubikey.pub)
    -read -ra pub_arr <<< "$pub_key"
    -
    -cd .dotfiles
    -if [[ $local_keys != *"${pub_arr[1]}"* ]]; then
    -    yellow "The ssh key for this configuration is not available."
    -    green "Adjusting flake.nix so that the configuration is buildable"
    -    sed -i '/nix-secrets = {/,/^[[:space:]]*};/d' flake.nix
    -    sed -i '/vbc-nix = {/,/^[[:space:]]*};/d' flake.nix
    -    sed -i '/[[:space:]]*\/\/ (inputs.vbc-nix.overlays.default final prev)/d' overlays/default.nix
    -    rm modules/home/common/env.nix
    -    rm modules/home/common/gammastep.nix
    -    rm modules/home/common/git.nix
    -    rm modules/home/common/mail.nix
    -    rm modules/home/common/yubikey.nix
    -    rm modules/nixos/server/restic.nix
    -    rm modules/nixos/common/home-manager-extra.nix
    -    rm hosts/nixos/sync/default.nix
    -    rm -rf modules/nixos/server
    -    rm -rf modules/home/server
    -    nix flake update vbc-nix
    -    git add .
    -else
    -    green "Valid SSH key found! Continuing with installation"
    -fi
    -sudo nixos-generate-config --dir /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/
    -git add /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/hardware-configuration.nix
    -
    -green "Installing flake $target_config"
    -sudo nixos-rebuild --show-trace --flake .#"$target_config" boot
    -yellow "Please keep in mind that this is only a demo of the configuration. Things might break unexpectedly."
    -
    -
    - - - -
    -
    { self, name, writeShellApplication, git }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ git ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.20. swarsel-install
    -
    -

    -Autoformatting always puts the EOF with indentation, which makes shfmt check fail. When editing this block, unindent them manually. -

    - -
    -
    set -eo pipefail
    -
    -target_config="chaostheatre"
    -target_hostname="chaostheatre"
    -target_user="swarsel"
    -persist_dir=""
    -target_disk="/dev/vda"
    -disk_encryption=0
    -
    -function help_and_exit() {
    -    echo
    -    echo "Locally installs SwarselSystem on this machine."
    -    echo
    -    echo "USAGE: $0 -n <target_config> -d <target_disk> [OPTIONS]"
    -    echo
    -    echo "ARGS:"
    -    echo "  -n <target_config>                      specify the nixos config to deploy."
    -    echo "                                          Default: chaostheatre"
    -    echo "  -d <target_disk>                        specify disk to install on."
    -    echo "                                          Default: /dev/vda"
    -    echo "  -u <target_user>                        specify user to deploy for."
    -    echo "                                          Default: swarsel"
    -    echo "  -h | --help                             Print this help."
    -    exit 0
    -}
    -
    -function red() {
    -    echo -e "\x1B[31m[!] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[31m[!] $($2) \x1B[0m"
    -    fi
    -}
    -function green() {
    -    echo -e "\x1B[32m[+] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[32m[+] $($2) \x1B[0m"
    -    fi
    -}
    -function yellow() {
    -    echo -e "\x1B[33m[*] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[33m[*] $($2) \x1B[0m"
    -    fi
    -}
    -
    -while [[ $# -gt 0 ]]; do
    -    case "$1" in
    -    -n)
    -        shift
    -        target_config=$1
    -        target_hostname=$1
    -        ;;
    -    -u)
    -        shift
    -        target_user=$1
    -        ;;
    -    -d)
    -        shift
    -        target_disk=$1
    -        ;;
    -    -h | --help) help_and_exit ;;
    -    *)
    -        echo "Invalid option detected."
    -        help_and_exit
    -        ;;
    -    esac
    -    shift
    -done
    -
    -function cleanup() {
    -    sudo rm -rf .cache/nix
    -    sudo rm -rf /root/.cache/nix
    -}
    -trap cleanup exit
    -
    -green "~SwarselSystems~ local installer"
    -
    -cd /home/"$target_user"
    -
    -sudo rm -rf /root/.cache/nix
    -sudo rm -rf .cache/nix
    -sudo rm -rf .dotfiles
    -
    -green "Cloning repository from GitHub"
    -git clone https://github.com/Swarsel/.dotfiles.git
    -
    -local_keys=$(ssh-add -L || true)
    -pub_key=$(cat /home/"$target_user"/.dotfiles/secrets/keys/ssh/yubikey.pub)
    -read -ra pub_arr <<< "$pub_key"
    -
    -cd .dotfiles
    -if [[ $local_keys != *"${pub_arr[1]}"* ]]; then
    -    yellow "The ssh key for this configuration is not available."
    -    green "Adjusting flake.nix so that the configuration is buildable ..."
    -    sed -i '/nix-secrets = {/,/^[[:space:]]*};/d' flake.nix
    -    sed -i '/vbc-nix = {/,/^[[:space:]]*};/d' flake.nix
    -    sed -i '/[[:space:]]*\/\/ (inputs.vbc-nix.overlays.default final prev)/d' overlays/default.nix
    -    rm modules/home/common/env.nix
    -    rm modules/home/common/gammastep.nix
    -    rm modules/home/common/git.nix
    -    rm modules/home/common/mail.nix
    -    rm modules/home/common/yubikey.nix
    -    rm modules/nixos/server/restic.nix
    -    rm modules/nixos/common/home-manager-extra.nix
    -    rm hosts/nixos/sync/default.nix
    -    rm -rf modules/nixos/server
    -    rm -rf modules/home/server
    -    cat > hosts/nixos/chaostheatre/options.nix << EOF
    -        { self, lib, ... }:
    -        {
    -          options = {
    -            swarselsystems = {
    -              modules = {
    -                home-managerExtra = lib.mkEnableOption "dummy option for chaostheatre";
    -              };
    -            };
    -          };
    -        }
    -EOF
    -    cat > hosts/nixos/chaostheatre/options-home.nix << EOF
    -        { self, lib, ... }:
    -        {
    -        options = {
    -          swarselsystems = {
    -            modules = {
    -              yubikey = lib.mkEnableOption "dummy option for chaostheatre";
    -              env = lib.mkEnableOption "dummy option for chaostheatre";
    -              git = lib.mkEnableOption "dummy option for chaostheatre";
    -              mail = lib.mkEnableOption "dummy option for chaostheatre";
    -              gammastep = lib.mkEnableOption "dummy option for chaostheatre";
    -            };
    -          };
    -        };
    -        }
    -EOF
    -    nix flake update vbc-nix
    -    git add .
    -else
    -    green "Valid SSH key found! Continuing with installation"
    -fi
    -
    -green "Reading system information for $target_config ..."
    -DISK="$(nix eval --raw ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.rootDisk)"
    -green "Root Disk in config: $DISK - Root Disk passed in cli: $target_disk"
    -
    -CRYPTED="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isCrypted)"
    -if [[ $CRYPTED == "true" ]]; then
    -    green "Encryption: ✓"
    -    disk_encryption=1
    -else
    -    red "Encryption: X"
    -    disk_encryption=0
    -fi
    -
    -IMPERMANENCE="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isImpermanence)"
    -if [[ $IMPERMANENCE == "true" ]]; then
    -    green "Impermanence: ✓"
    -    persist_dir="/persist"
    -else
    -    red "Impermanence: X"
    -    persist_dir=""
    -fi
    -
    -SWAP="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isSwap)"
    -if [[ $SWAP == "true" ]]; then
    -    green "Swap: ✓"
    -else
    -    red "Swap: X"
    -fi
    -
    -SECUREBOOT="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isSecureBoot)"
    -if [[ $SECUREBOOT == "true" ]]; then
    -    green "Secure Boot: ✓"
    -else
    -    red "Secure Boot: X"
    -fi
    -
    -if [ "$disk_encryption" -eq 1 ]; then
    -    while true; do
    -        green "Set disk encryption passphrase:"
    -        read -rs luks_passphrase
    -        green "Please confirm passphrase:"
    -        read -rs luks_passphrase_confirm
    -        if [[ $luks_passphrase == "$luks_passphrase_confirm" ]]; then
    -            echo "$luks_passphrase" > /tmp/disko-password
    -            break
    -        else
    -            red "Passwords do not match"
    -        fi
    -    done
    -fi
    -
    -green "Setting up disk ..."
    -if [[ $target_config == "chaostheatre" ]]; then
    -    sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/v1.10.0 -- --mode destroy,format,mount --flake .#"$target_config" --yes-wipe-all-disks --arg diskDevice "$target_disk"
    -else
    -    sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/latest -- --mode destroy,format,mount --flake .#"$target_config" --yes-wipe-all-disks
    -fi
    -sudo mkdir -p /mnt/"$persist_dir"/home/"$target_user"/
    -sudo cp -r /home/"$target_user"/.dotfiles /mnt/"$persist_dir"/home/"$target_user"/
    -sudo chown -R 1000:100 /mnt/"$persist_dir"/home/"$target_user"
    -
    -green "Generating hardware configuration ..."
    -sudo nixos-generate-config --root /mnt --no-filesystems --dir /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/
    -
    -green "Injecting initialSetup ..."
    -sudo sed -i '/  boot.extraModulePackages /a \  swarselsystems.initialSetup = true;' /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/hardware-configuration.nix
    -
    -git add /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/hardware-configuration.nix
    -sudo mkdir -p /root/.local/share/nix/
    -printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | sudo tee /root/.local/share/nix/trusted-settings.json > /dev/null
    -green "Installing flake $target_config"
    -sudo nixos-install --flake .#"$target_config"
    -green "Installation finished! Reboot to see changes"
    -
    -
    - - - -
    -
    { self, name, writeShellApplication, git }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ git ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.21. swarsel-postinstall
    -
    -
    -
    set -eo pipefail
    -
    -target_config="chaostheatre"
    -target_user="swarsel"
    -
    -function help_and_exit() {
    -    echo
    -    echo "Locally installs SwarselSystem on this machine."
    -    echo
    -    echo "USAGE: $0 -d <disk> [OPTIONS]"
    -    echo
    -    echo "ARGS:"
    -    echo "  -d <disk>                               specify disk to install on."
    -    echo "  -n <target_config>                      specify the nixos config to deploy."
    -    echo "                                          Default: chaostheatre"
    -    echo "                                          Default: chaostheatre"
    -    echo "  -u <target_user>                        specify user to deploy for."
    -    echo "                                          Default: swarsel"
    -    echo "  -h | --help                             Print this help."
    -    exit 0
    -}
    -
    -function green() {
    -    echo -e "\x1B[32m[+] $1 \x1B[0m"
    -    if [ -n "${2-}" ]; then
    -        echo -e "\x1B[32m[+] $($2) \x1B[0m"
    -    fi
    -}
    -
    -while [[ $# -gt 0 ]]; do
    -    case "$1" in
    -    -n)
    -        shift
    -        target_config=$1
    -        ;;
    -    -u)
    -        shift
    -        target_user=$1
    -        ;;
    -    -h | --help) help_and_exit ;;
    -    *)
    -        echo "Invalid option detected."
    -        help_and_exit
    -        ;;
    -    esac
    -    shift
    -done
    -
    -function cleanup() {
    -    sudo rm -rf .cache/nix
    -    sudo rm -rf /root/.cache/nix
    -}
    -trap cleanup exit
    -
    -sudo rm -rf .cache/nix
    -sudo rm -rf /root/.cache/nix
    -
    -green "~SwarselSystems~ remote post-installer"
    -
    -cd /home/"$target_user"/.dotfiles
    -
    -SECUREBOOT="$(nix eval ~/.dotfiles#nixosConfigurations."$target_config".config.swarselsystems.isSecureBoot)"
    -
    -if [[ $SECUREBOOT == "true" ]]; then
    -    green "Setting up secure boot keys"
    -    sudo mkdir -p /var/lib/sbctl
    -    sbctl create-keys || true
    -    sbctl enroll-keys --ignore-immutable --microsoft || true
    -fi
    -
    -green "Disabling initialSetup"
    -sed -i '/swarselsystems\.initialSetup = true;/d' /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/hardware-configuration.nix
    -sudo nixos-rebuild --flake .#"$target_config" switch
    -green "Post-install finished!"
    -
    -
    - - - -
    -
    { self, name, writeShellApplication, git }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ git ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.22. t2ts
    -
    -
    -
    { name, writeShellApplication, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ ];
    -  text = ''
    -    date -d"$1" +%s
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.23. ts2t
    -
    -
    -
    { name, writeShellApplication, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ ];
    -  text = ''
    -    date -d @"$1" 2>/dev/null || date -r "$1"
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.24. vershell
    -
    -
    -
    { name, writeShellApplication, ... }:
    -
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ ];
    -  text = ''
    -    nix shell github:nixos/nixpkgs/"$1"#"$2";
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.25. eontimer
    -
    -
    -
    { lib
    -, python3
    -, fetchFromGitHub
    -, makeDesktopItem
    -, writeShellScript
    -, ...
    -}:
    -let
    -  wrapper = writeShellScript "eontimer-wrapper" ''
    -    export QT_QPA_PLATFORM=xcb
    -    exec @out@/bin/EonTimer
    -  '';
    -in
    -python3.pkgs.buildPythonApplication rec {
    -  pname = "eontimer";
    -  version = "3.0.0-rc.6";
    -  pyproject = true;
    -
    -  src = fetchFromGitHub {
    -    owner = "DasAmpharos";
    -    repo = "EonTimer";
    -    rev = version;
    -    hash = "sha256-+XN/VGGlEg2gVncRZrWDOZ2bfxt8xyIu22F2wHlG6YI=";
    -  };
    -
    -  build-system = [
    -    python3.pkgs.setuptools
    -    python3.pkgs.wheel
    -  ];
    -
    -  dependencies = with python3.pkgs; [
    -    altgraph
    -    certifi
    -    charset-normalizer
    -    idna
    -    libsass
    -    macholib
    -    packaging
    -    pillow
    -    pipdeptree
    -    platformdirs
    -    pyinstaller
    -    pyinstaller-hooks-contrib
    -    pyside6
    -    requests
    -    setuptools
    -    shiboken6
    -    urllib3
    -  ];
    -
    -  nativeBuildInputs = [
    -    python3.pkgs.pyinstaller
    -  ];
    -
    -  buildPhase = ''
    -    runHook preBuild
    -
    -    pyinstaller --clean --noconfirm EonTimer.spec
    -
    -    runHook postBuild
    -  '';
    -
    -  installPhase = ''
    -    runHook preInstall
    -
    -    mkdir -p $out/bin
    -    mkdir -p $out/share/applications
    -    cp dist/EonTimer $out/bin/
    -    install -Dm755 -T ${wrapper} $out/bin/eontimer
    -    substituteInPlace $out/bin/eontimer --subst-var out
    -
    -    runHook postInstall
    -  '';
    -
    -  postInstall = ''
    -    install -Dm755 -t $out/share/applications ${
    -         makeDesktopItem {
    -           name = "eontimer";
    -           desktopName = "EonTimer";
    -           comment = "Start EonTimer";
    -           exec = "eontimer";
    -         }
    -       }/share/applications/eontimer.desktop
    -  '';
    -
    -
    -
    -  meta = {
    -    description = "Pokémon RNG Timer";
    -    homepage = "https://github.com/DasAmpharos/EonTimer";
    -    license = lib.licenses.mit;
    -    maintainers = with lib.maintainers; [ ];
    -    mainProgram = "eon-timer";
    -  };
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.26. project
    -
    -
    -
    set -euo pipefail
    -
    -if [ ! -d "$(pwd)/.git" ]; then
    -    git init
    -fi
    -nix flake init --template "$FLAKE"#"$1"
    -direnv allow
    -
    -
    - -
    -
    { self, name, writeShellApplication }:
    -writeShellApplication {
    -  inherit name;
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    3.2.1.27. fhs
    -
    -
    -
    { name, pkgs, ... }:
    -let
    -  base = pkgs.appimageTools.defaultFhsEnvArgs;
    -in
    -pkgs.buildFHSEnv (base // {
    -  name = "fhs";
    -  targetPkgs = pkgs: (base.targetPkgs pkgs) ++ [ pkgs.pkg-config ];
    -  profile = "export FHS=1";
    -  runScript = "zsh";
    -  extraOutputsToInstall = [ "dev" ];
    -})
    -
    -
    -
    -
    -
    -
    3.2.1.28. swarsel-displaypower
    -
    -

    -A crude script to power on all displays that might be attached. Needed because sometimes displays do not awake from sleep. -

    - -
    -
    swaymsg "output * power on" > /dev/null 2>&1 || true
    -swaymsg "output * dpms on" > /dev/null 2>&1 || true
    -
    -
    - -
    -
    { self, name, writeShellApplication, sway }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ sway ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.29. swarsel-mgba
    -
    -

    -AppImage version of mgba in which the lua scripting works. -

    - - -
    -
    { appimageTools, fetchurl, ... }:
    -let
    -  pname = "mgba";
    -  version = "0.10.4";
    -  src = fetchurl {
    -    url = "https://github.com/mgba-emu/mgba/releases/download/${version}/mGBA-${version}-appimage-x64.appimage";
    -    hash = "sha256-rDihDfuA8DqxvCe6UeavCzpjeU+fSqUbFnyTNC2dc1I=";
    -  };
    -  appimageContents = appimageTools.extractType2 { inherit pname version src; };
    -in
    -appimageTools.wrapType2 {
    -  inherit pname version src;
    -  extraInstallCommands = ''
    -    install -Dm444 ${appimageContents}/io.mgba.mGBA.desktop -t $out/share/applications
    -    substituteInPlace $out/share/applications/io.mgba.mGBA.desktop \
    -      --replace-fail 'Exec=mgba-qt %f' 'Exec=mgba'
    -    cp -r ${appimageContents}/usr/share/icons $out/share
    -  '';
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.30. swarsel-deploy
    -
    -
    -
    # heavily inspired from https://github.com/oddlama/nix-config/blob/d42cbde676001a7ad8a3cace156e050933a4dcc3/pkgs/deploy.nix
    -{ name, bc, nix-output-monitor, writeShellApplication, ... }:
    -writeShellApplication {
    -  runtimeInputs = [ bc nix-output-monitor ];
    -  inherit name;
    -  text = ''
    -    set -euo pipefail
    -    shopt -s lastpipe # allow cmd | readarray
    -
    -    function die() {
    -        echo "error: $*" >&2
    -        exit 1
    -    }
    -    function show_help() {
    -        echo 'Usage: deploy [OPTIONS] <host,...> [ACTION]'
    -        echo "Builds, pushes and activates nixosConfigurations on target systems."
    -        echo ""
    -        echo 'ACTION:'
    -        echo '  switch          [default] Switch immediately to the new configuration and make it the boot default'
    -        echo '  boot            Make the configuration the new boot default'
    -        echo "  test            Activate the configuration but don't make it the boot default"
    -        echo "  dry-activate    Don't activate, just show what would be done"
    -        echo ""
    -        echo 'OPTIONS: [passed to nix build]'
    -    }
    -
    -    function time_start() {
    -        T_START=$(date +%s.%N)
    -    }
    -
    -    function time_next() {
    -        T_END=$(date +%s.%N)
    -        T_LAST=$(${bc}/bin/bc <<< "scale=1; ($T_END - $T_START)/1")
    -        T_START="$T_END"
    -    }
    -
    -    USER_FLAKE_DIR=$(git rev-parse --show-toplevel 2> /dev/null || pwd) ||
    -        die "Could not determine current working directory. Something went very wrong."
    -    [[ -e "$USER_FLAKE_DIR/flake.nix" ]] ||
    -        die "Could not determine location of your project's flake.nix. Please run this at or below your main directory containing the flake.nix."
    -    cd "$USER_FLAKE_DIR"
    -
    -    [[ $# -gt 0 ]] || {
    -        show_help
    -        exit 1
    -    }
    -
    -    OPTIONS=()
    -    POSITIONAL_ARGS=()
    -    while [[ $# -gt 0 ]]; do
    -        case "$1" in
    -        "help" | "--help" | "-help" | "-h")
    -            show_help
    -            exit 1
    -            ;;
    -
    -        -*) OPTIONS+=("$1") ;;
    -        *) POSITIONAL_ARGS+=("$1") ;;
    -        esac
    -        shift
    -    done
    -
    -    [[ ''${#POSITIONAL_ARGS[@]} -ge 1 ]] ||
    -        die "Missing argument: <hosts...>"
    -    [[ ''${#POSITIONAL_ARGS[@]} -le 2 ]] ||
    -        die "Too many arguments given."
    -
    -    tr , '\n' <<< "''${POSITIONAL_ARGS[0]}" | sort -u | readarray -t HOSTS
    -    ACTION="''${POSITIONAL_ARGS[1]-switch}"
    -
    -    # Expand flake paths for hosts definitions
    -    declare -A TOPLEVEL_FLAKE_PATHS
    -    for host in "''${HOSTS[@]}"; do
    -        TOPLEVEL_FLAKE_PATHS["$host"]=".#nixosConfigurations.$host.config.system.build.toplevel"
    -    done
    -
    -    time_start
    -
    -    # Get outputs of all derivations (should be cached)
    -    declare -A TOPLEVEL_STORE_PATHS
    -    for host in "''${HOSTS[@]}"; do
    -        toplevel="''${TOPLEVEL_FLAKE_PATHS["$host"]}"
    -        # Make sudo call to get prompt out of the way
    -        sudo echo "    Building 📦 $host"
    -        nix build --no-link "''${OPTIONS[@]}" --show-trace --log-format internal-json -v "$toplevel" |& ${nix-output-monitor}/bin/nom --json ||
    -            die "Failed to get derivation path for $host from ''${TOPLEVEL_FLAKE_PATHS["$host"]}"
    -        TOPLEVEL_STORE_PATHS["$host"]=$(nix build --no-link --print-out-paths "''${OPTIONS[@]}" "$toplevel")
    -        time_next
    -        echo "       Built ✅ $host ''${TOPLEVEL_STORE_PATHS["$host"]} in ''${T_LAST}s"
    -    done
    -
    -    current_host=$(hostname)
    -
    -    for host in "''${HOSTS[@]}"; do
    -        store_path="''${TOPLEVEL_STORE_PATHS["$host"]}"
    -
    -        if [ "$host" = "$current_host" ]; then
    -            echo -e "\033[1;36m    Running locally for $host... \033[m"
    -            ssh_prefix="sudo"
    -        else
    -            echo -e "\033[1;36m     Copying \033[m➡️  \033[34m$host\033[m"
    -            nix copy --to "ssh://$host" "$store_path"
    -            time_next
    -            echo -e "\033[1;32m      Copied \033[m✅  \033[34m$host\033[m \033[90min ''${T_LAST}s\033[m"
    -            ssh_prefix="ssh $host --"
    -        fi
    -
    -        echo -e "\033[1;36m    Applying \033[m⚙️  \033[34m$host\033[m"
    -        prev_system=$($ssh_prefix readlink -e /nix/var/nix/profiles/system)
    -        $ssh_prefix /run/current-system/sw/bin/nix-env --profile /nix/var/nix/profiles/system --set "$store_path" ||
    -            die "Failed to set system profile"
    -        $ssh_prefix "$store_path"/bin/switch-to-configuration "$ACTION" ||
    -            echo "Error while activating new system" >&2
    -
    -        if [[ -n $prev_system ]]; then
    -            $ssh_prefix nvd --color always diff "$prev_system" "$store_path" || true
    -        fi
    -
    -        time_next
    -        echo -e "\033[1;32m     Applied \033[m✅  \033[34m$host\033[m \033[90min ''${T_LAST}s\033[m"
    -    done
    -  '';
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.1.31. sshrm
    -
    -

    -This programs simply runs ssh-keygen on the last host that I tried to ssh into. I need this frequently when working with cloud-init usually. -

    - -
    -
    HISTFILE="$HOME"/.histfile
    -
    -last_ssh_cmd=$(grep -E "ssh " "$HISTFILE" | sed -E 's/^: [0-9]+:[0-9]+;//' | grep "^ssh " | tail -1)
    -host=$(echo "$last_ssh_cmd" | sed -E 's/.*ssh ([^@ ]+@)?([^ ]+).*/\2/')
    -
    -if [[ -n $host ]]; then
    -    echo "Removing SSH host key for: $host"
    -    ssh-keygen -R "$host"
    -else
    -    echo "No valid SSH command found in history."
    -fi
    -
    -
    - -
    -
    { self, name, writeShellApplication, openssh }:
    -writeShellApplication {
    -  inherit name;
    -  runtimeInputs = [ openssh ];
    -  text = builtins.readFile "${self}/scripts/${name}.sh";
    -}
    -
    -
    -
    -
    -
    -
    -

    3.2.2. Overlays (additions, overrides, nixpkgs-stable)

    -
    -

    -This file now holds all of the "nixpkgs-changes" that I am using across the configurations. Most notable here are the modifications, where I am editing derivations according to my needs. -

    - -

    -When adding a new entry here, do not forget to add it in the default output of this file, otherwise it will not be exposed to the rest of the system. -

    - -
    -
    { self, inputs, lib, ... }:
    -
    -let
    -  additions = final: _: import "${self}/pkgs" { pkgs = final; inherit lib; };
    -
    -  modifications = final: prev: {
    -    vesktop = prev.vesktop.override {
    -      withSystemVencord = true;
    -    };
    -
    -    firefox = prev.firefox.override {
    -      nativeMessagingHosts = [
    -        prev.tridactyl-native
    -        prev.browserpass
    -        prev.plasma5Packages.plasma-browser-integration
    -      ];
    -    };
    -
    -    mgba = final.swarsel-mgba;
    -
    -    retroarch = prev.retroarch.withCores (cores: with cores; [
    -      snes9x # snes
    -      nestopia # nes
    -      dosbox # dos
    -      scummvm # scumm
    -      vba-m # gb/a
    -      mgba # gb/a
    -      melonds # ds
    -      dolphin # gc/wii
    -    ]);
    -
    -
    -
    -  };
    -
    -  nixpkgs-stable = final: _: {
    -    stable = import inputs.nixpkgs-stable {
    -      inherit (final) system;
    -      config.allowUnfree = true;
    -    };
    -  };
    -
    - nixpkgs-kernel = final: _: {
    -    kernel = import inputs.nixpkgs-kernel {
    -      inherit (final) system;
    -      config.allowUnfree = true;
    -    };
    -  };
    -
    -  nixpkgs-stable24_05 = final: _: {
    -    stable24_05 = import inputs.nixpkgs-stable24_05 {
    -      inherit (final) system;
    -      config.allowUnfree = true;
    -    };
    -  };
    -
    -  nixpkgs-stable24_11 = final: _: {
    -    stable24_11 = import inputs.nixpkgs-stable24_11 {
    -      inherit (final) system;
    -      config.allowUnfree = true;
    -    };
    -  };
    -
    -  zjstatus = _: prev: {
    -    zjstatus = inputs.zjstatus.packages.${prev.system}.default;
    -  };
    -
    -in
    -{
    -  default =
    -    final: prev:
    -
    -    (additions final prev)
    -    // (modifications final prev)
    -    // (nixpkgs-stable final prev)
    -    // (nixpkgs-kernel final prev)
    -    // (nixpkgs-stable24_05 final prev)
    -    // (nixpkgs-stable24_11 final prev)
    -    // (zjstatus final prev)
    -    // (inputs.vbc-nix.overlays.default final prev)
    -    // (inputs.nur.overlays.default final prev)
    -    // (inputs.emacs-overlay.overlay final prev)
    -    // (inputs.nix-topology.overlays.default final prev)
    -    // (inputs.nixgl.overlay final prev);
    -
    -}
    -
    -
    -
    -
    -
    -
    -

    3.2.3. Profiles

    -
    -

    -In this section I define custom modules under the swarsel attribute. These are mostly used to define settings specific to a host. I keep these settings confined to either home-manager or nixos to maintain compatibility with non-NixOS machines. -

    - -

    -Note: The structure of generating the packages was changed in commit 2cf03a3 refactor: package and module generation. That commit can be checked out in order to see a simpler version of achieving the same thing. -

    -
    -
    -
    3.2.3.1. NixOS
    -
    -

    -Modules that need to be loaded on the NixOS level. Note that these will not be available on systems that are not running NixOS. -

    - -
    -
    { lib, ... }:
    -let
    -  profileNames = lib.swarselsystems.readNix "profiles/nixos";
    -in
    -{
    -  imports = lib.swarselsystems.mkImports profileNames "profiles/nixos";
    -}
    -
    -
    -
    -
    -
    3.2.3.1.1. Personal
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.personal = lib.mkEnableOption "is this a personal host";
    -  config = lib.mkIf config.swarselsystems.profiles.personal {
    -    swarselsystems.modules = {
    -      packages = lib.mkDefault true;
    -      general = lib.mkDefault true;
    -      home-manager = lib.mkDefault true;
    -      home-managerExtra = lib.mkDefault true;
    -      xserver = lib.mkDefault true;
    -      users = lib.mkDefault true;
    -      env = lib.mkDefault true;
    -      security = lib.mkDefault true;
    -      systemdTimeout = lib.mkDefault true;
    -      hardware = lib.mkDefault true;
    -      pulseaudio = lib.mkDefault true;
    -      pipewire = lib.mkDefault true;
    -      network = lib.mkDefault true;
    -      time = lib.mkDefault true;
    -      commonSops = lib.mkDefault true;
    -      pii = lib.mkDefault true;
    -      stylix = lib.mkDefault true;
    -      programs = lib.mkDefault true;
    -      zsh = lib.mkDefault true;
    -      syncthing = lib.mkDefault true;
    -      blueman = lib.mkDefault true;
    -      networkDevices = lib.mkDefault true;
    -      gvfs = lib.mkDefault true;
    -      interceptionTools = lib.mkDefault true;
    -      swayosd = lib.mkDefault true;
    -      ppd = lib.mkDefault true;
    -      yubikey = lib.mkDefault true;
    -      ledger = lib.mkDefault true;
    -      keyboards = lib.mkDefault true;
    -      login = lib.mkDefault true;
    -      nix-ld = lib.mkDefault true;
    -      impermanence = lib.mkDefault true;
    -      nvd = lib.mkDefault true;
    -      gnome-keyring = lib.mkDefault true;
    -      sway = lib.mkDefault true;
    -      xdg-portal = lib.mkDefault true;
    -      distrobox = lib.mkDefault true;
    -      appimage = lib.mkDefault true;
    -      lid = lib.mkDefault true;
    -      lowBattery = lib.mkDefault true;
    -      lanzaboote = lib.mkDefault true;
    -
    -      optional = {
    -        gaming = lib.mkDefault true;
    -        virtualbox = lib.mkDefault true;
    -        autologin = lib.mkDefault true;
    -        nswitch-rcm = lib.mkDefault true;
    -      };
    -
    -      server = {
    -        ssh = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.2. Chaostheatre
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.chaostheatre = lib.mkEnableOption "is this a chaostheatre host";
    -  config = lib.mkIf config.swarselsystems.profiles.chaostheatre {
    -    swarselsystems.modules = {
    -      packages = lib.mkDefault true;
    -      general = lib.mkDefault true;
    -      home-manager = lib.mkDefault true;
    -      home-managerExtra = lib.mkDefault false;
    -      xserver = lib.mkDefault true;
    -      users = lib.mkDefault true;
    -      env = lib.mkDefault true;
    -      security = lib.mkDefault true;
    -      systemdTimeout = lib.mkDefault true;
    -      hardware = lib.mkDefault true;
    -      pulseaudio = lib.mkDefault true;
    -      pipewire = lib.mkDefault true;
    -      network = lib.mkDefault true;
    -      time = lib.mkDefault true;
    -      commonSops = lib.mkDefault true;
    -      stylix = lib.mkDefault true;
    -      programs = lib.mkDefault true;
    -      zsh = lib.mkDefault true;
    -      syncthing = lib.mkDefault true;
    -      blueman = lib.mkDefault true;
    -      networkDevices = lib.mkDefault true;
    -      gvfs = lib.mkDefault true;
    -      interceptionTools = lib.mkDefault true;
    -      swayosd = lib.mkDefault true;
    -      ppd = lib.mkDefault true;
    -      yubikey = lib.mkDefault true;
    -      ledger = lib.mkDefault true;
    -      keyboards = lib.mkDefault true;
    -      login = lib.mkDefault true;
    -      nix-ld = lib.mkDefault true;
    -      impermanence = lib.mkDefault true;
    -      nvd = lib.mkDefault true;
    -      gnome-keyring = lib.mkDefault true;
    -      sway = lib.mkDefault true;
    -      xdg-portal = lib.mkDefault true;
    -      distrobox = lib.mkDefault true;
    -      appimage = lib.mkDefault true;
    -      lid = lib.mkDefault true;
    -      lowBattery = lib.mkDefault true;
    -      lanzaboote = lib.mkDefault true;
    -
    -      optional = {
    -        autologin = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.3. toto
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.toto = lib.mkEnableOption "is this a toto (setup) host";
    -  config = lib.mkIf config.swarselsystems.profiles.toto {
    -    swarselsystems.modules = {
    -      general = lib.mkDefault true;
    -      home-manager = lib.mkDefault true;
    -      home-managerExtra = lib.mkDefault true;
    -      xserver = lib.mkDefault true;
    -      users = lib.mkDefault true;
    -      commonSops = lib.mkDefault true;
    -      impermanence = lib.mkDefault true;
    -      lanzaboote = lib.mkDefault true;
    -      server = {
    -        ssh = lib.mkDefault true;
    -      };
    -      optional = {
    -        autologin = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.4. Work
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.work = lib.mkEnableOption "is this a work host";
    -  config = lib.mkIf config.swarselsystems.profiles.work {
    -    swarselsystems.modules = {
    -      optional = {
    -        work = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.5. Framework
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.framework = lib.mkEnableOption "is this a framework brand host";
    -  config = lib.mkIf config.swarselsystems.profiles.framework {
    -    swarselsystems.modules = {
    -      optional = {
    -        framework = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.6. AMD CPU
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.amdcpu = lib.mkEnableOption "is this a host with amd cpu";
    -  config = lib.mkIf config.swarselsystems.profiles.amdcpu {
    -    swarselsystems.modules = {
    -      optional = {
    -        amdcpu = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.7. AMD GPU
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.amdgpu = lib.mkEnableOption "is this a host with amd gpu";
    -  config = lib.mkIf config.swarselsystems.profiles.amdgpu {
    -    swarselsystems.modules = {
    -      optional = {
    -        amdgpu = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.8. Hibernation
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.hibernation = lib.mkEnableOption "is this a host using hibernation";
    -  config = lib.mkIf config.swarselsystems.profiles.hibernation {
    -    swarselsystems.modules = {
    -      optional = {
    -        hibernation = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.9. BTRFS
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.btrfs = lib.mkEnableOption "is this a host using btrfs";
    -  config = lib.mkIf config.swarselsystems.profiles.btrfs {
    -    swarselsystems.modules = {
    -      optional = {
    -        btrfs = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.10. Local Server
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.server.local = lib.mkEnableOption "is this a local server";
    -  config = lib.mkIf config.swarselsystems.profiles.server.local {
    -    swarselsystems = {
    -      modules = {
    -        general = lib.mkDefault true;
    -        pii = lib.mkDefault true;
    -        home-manager = lib.mkDefault true;
    -        home-managerExtra = lib.mkDefault true;
    -        xserver = lib.mkDefault true;
    -        time = lib.mkDefault true;
    -        users = lib.mkDefault true;
    -        server = {
    -          general = lib.mkDefault true;
    -          packages = lib.mkDefault true;
    -          sops = lib.mkDefault true;
    -          nfs = lib.mkDefault true;
    -          nginx = lib.mkDefault true;
    -          ssh = lib.mkDefault true;
    -          kavita = lib.mkDefault true;
    -          restic = lib.mkDefault true;
    -          jellyfin = lib.mkDefault true;
    -          navidrome = lib.mkDefault true;
    -          spotifyd = lib.mkDefault true;
    -          mpd = lib.mkDefault true;
    -          postgresql = lib.mkDefault true;
    -          matrix = lib.mkDefault true;
    -          nextcloud = lib.mkDefault true;
    -          immich = lib.mkDefault true;
    -          paperless = lib.mkDefault true;
    -          transmission = lib.mkDefault true;
    -          syncthing = lib.mkDefault true;
    -          monitoring = lib.mkDefault true;
    -          emacs = lib.mkDefault true;
    -          freshrss = lib.mkDefault true;
    -          jenkins = lib.mkDefault false;
    -          kanidm = lib.mkDefault true;
    -          firefly = lib.mkDefault true;
    -          koillection = lib.mkDefault true;
    -          radicale = lib.mkDefault true;
    -          atuin = lib.mkDefault true;
    -        };
    -      };
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.11. OCI Sync Server
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.server.sync = lib.mkEnableOption "is this a oci sync server";
    -  config = lib.mkIf config.swarselsystems.profiles.server.sync {
    -    swarselsystems = {
    -      modules = {
    -        general = lib.mkDefault true;
    -        nix-ld = lib.mkDefault true;
    -        pii = lib.mkDefault true;
    -        home-manager = lib.mkDefault true;
    -        home-managerExtra = lib.mkDefault true;
    -        xserver = lib.mkDefault true;
    -        time = lib.mkDefault true;
    -        users = lib.mkDefault true;
    -        server = {
    -          general = lib.mkDefault true;
    -          packages = lib.mkDefault true;
    -          sops = lib.mkDefault true;
    -          nginx = lib.mkDefault true;
    -          ssh = lib.mkDefault true;
    -          forgejo = lib.mkDefault true;
    -          ankisync = lib.mkDefault true;
    -        };
    -      };
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.1.12. Moonside
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.server.moonside = lib.mkEnableOption "is this a moonside server";
    -  config = lib.mkIf config.swarselsystems.profiles.server.moonside {
    -    swarselsystems = {
    -      modules = {
    -        general = lib.mkDefault true;
    -        pii = lib.mkDefault true;
    -        home-manager = lib.mkDefault true;
    -        home-managerExtra = lib.mkDefault true;
    -        xserver = lib.mkDefault true;
    -        time = lib.mkDefault true;
    -        users = lib.mkDefault true;
    -        impermanence = lib.mkDefault true;
    -        server = {
    -          general = lib.mkDefault true;
    -          packages = lib.mkDefault true;
    -          sops = lib.mkDefault true;
    -          nginx = lib.mkDefault true;
    -          ssh = lib.mkDefault true;
    -          oauth2Proxy = lib.mkDefault true;
    -          croc = lib.mkDefault true;
    -          microbin = lib.mkDefault true;
    -          shlink = lib.mkDefault true;
    -        };
    -      };
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    -
    3.2.3.2. home-manager
    -
    -

    -This holds modules that are to be used on most hosts. These are also the most important options to configure, as these allow me easy access to monitor, keyboard, and other setups. -

    - -
    -
    { lib, ... }:
    -let
    -  profileNames = lib.swarselsystems.readNix "profiles/home";
    -in
    -{
    -  imports = lib.swarselsystems.mkImports profileNames "profiles/home";
    -}
    -
    -
    -
    -
    -
    3.2.3.2.1. Personal
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.personal = lib.mkEnableOption "is this a personal host";
    -  config = lib.mkIf config.swarselsystems.profiles.personal {
    -    swarselsystems.modules = {
    -      packages = lib.mkDefault true;
    -      ownpackages = lib.mkDefault true;
    -      general = lib.mkDefault true;
    -      nixgl = lib.mkDefault true;
    -      sops = lib.mkDefault true;
    -      yubikey = lib.mkDefault true;
    -      ssh = lib.mkDefault true;
    -      stylix = lib.mkDefault true;
    -      desktop = lib.mkDefault true;
    -      symlink = lib.mkDefault true;
    -      env = lib.mkDefault true;
    -      programs = lib.mkDefault true;
    -      nix-index = lib.mkDefault true;
    -      passwordstore = lib.mkDefault true;
    -      direnv = lib.mkDefault true;
    -      eza = lib.mkDefault true;
    -      atuin = lib.mkDefault true;
    -      git = lib.mkDefault true;
    -      fuzzel = lib.mkDefault true;
    -      starship = lib.mkDefault true;
    -      kitty = lib.mkDefault true;
    -      zsh = lib.mkDefault true;
    -      zellij = lib.mkDefault true;
    -      tmux = lib.mkDefault true;
    -      mail = lib.mkDefault true;
    -      emacs = lib.mkDefault true;
    -      waybar = lib.mkDefault true;
    -      firefox = lib.mkDefault true;
    -      gnome-keyring = lib.mkDefault true;
    -      kdeconnect = lib.mkDefault true;
    -      mako = lib.mkDefault true;
    -      swayosd = lib.mkDefault true;
    -      yubikeytouch = lib.mkDefault true;
    -      sway = lib.mkDefault true;
    -      kanshi = lib.mkDefault true;
    -      gpgagent = lib.mkDefault true;
    -      gammastep = lib.mkDefault true;
    -
    -      optional = {
    -        gaming = lib.mkDefault true;
    -      };
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.2.2. Chaostheatre
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.chaostheatre = lib.mkEnableOption "is this a chaostheatre host";
    -  config = lib.mkIf config.swarselsystems.profiles.chaostheatre {
    -    swarselsystems.modules = {
    -      packages = lib.mkDefault true;
    -      ownpackages = lib.mkDefault true;
    -      general = lib.mkDefault true;
    -      nixgl = lib.mkDefault true;
    -      sops = lib.mkDefault true;
    -      yubikey = lib.mkDefault false;
    -      ssh = lib.mkDefault true;
    -      stylix = lib.mkDefault true;
    -      desktop = lib.mkDefault true;
    -      symlink = lib.mkDefault true;
    -      env = lib.mkDefault false;
    -      programs = lib.mkDefault true;
    -      nix-index = lib.mkDefault true;
    -      direnv = lib.mkDefault true;
    -      eza = lib.mkDefault true;
    -      git = lib.mkDefault false;
    -      fuzzel = lib.mkDefault true;
    -      starship = lib.mkDefault true;
    -      kitty = lib.mkDefault true;
    -      zsh = lib.mkDefault true;
    -      zellij = lib.mkDefault true;
    -      tmux = lib.mkDefault true;
    -      mail = lib.mkDefault false;
    -      emacs = lib.mkDefault true;
    -      waybar = lib.mkDefault true;
    -      firefox = lib.mkDefault true;
    -      gnome-keyring = lib.mkDefault true;
    -      kdeconnect = lib.mkDefault true;
    -      mako = lib.mkDefault true;
    -      swayosd = lib.mkDefault true;
    -      yubikeytouch = lib.mkDefault true;
    -      sway = lib.mkDefault true;
    -      kanshi = lib.mkDefault true;
    -      gpgagent = lib.mkDefault true;
    -      gammastep = lib.mkDefault false;
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.2.3. toto
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.toto = lib.mkEnableOption "is this a toto (setup) host";
    -  config = lib.mkIf config.swarselsystems.profiles.toto {
    -    swarselsystems.modules = {
    -      general = lib.mkDefault true;
    -      sops = lib.mkDefault true;
    -      ssh = lib.mkDefault true;
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.2.4. Work
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.work = lib.mkEnableOption "is this a work host";
    -  config = lib.mkIf config.swarselsystems.profiles.work {
    -    swarselsystems.modules = {
    -      optional = {
    -        work = lib.mkDefault true;
    -      };
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.2.5. Framework
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.framework = lib.mkEnableOption "is this a framework brand host";
    -  config = lib.mkIf config.swarselsystems.profiles.framework {
    -    swarselsystems.modules = {
    -      optional = {
    -        framework = lib.mkDefault true;
    -      };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.2.6. Darwin
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.darwin = lib.mkEnableOption "is this a darwin host";
    -  config = lib.mkIf config.swarselsystems.profiles.darwin {
    -    swarselsystems.modules = {
    -      general = lib.mkDefault true;
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.3.2.7. Local Server
    -
    -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.profiles.server.local = lib.mkEnableOption "is this a local server";
    -  config = lib.mkIf config.swarselsystems.profiles.server.local {
    -    swarselsystems.modules = {
    -      general = lib.mkDefault true;
    -      server = {
    -        dotfiles = lib.mkDefault true;
    -      };
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    -
    -

    3.2.4. Library functions

    -
    -

    -This section defines all functions of my own that I add to lib. These are used in all places over the config, with many of them being used in flake.nix. -

    - -

    -A breakdown of each function: -

    - -

    -The interesting part is in the start: -

    -
      -
    • first, I define pkgsFor. This function reads all available systems from nixpkgs and generates pkgs for them.
    • -
    • next, forEachSystem is a function that can be called to declare an output for each such defined system.
    • -
    • forAllSystems is a crude function that I use for expressions that depend on system, as the prior two attributes already consumed it at that stage. This is only really used to generate the checks in their own file.
    • -
    • mkFullHostConfigs is the function that dynamically creates all definded hosts. The hosts are defined by placing a directory in hosts/ under either the nixos/ or darwin/ directory. These directories are being read by readHosts and delivered to this funtion in the later call in nixosConfigurations or darwinConfigurations.
    • -
    • mkFullHost: -This is a function that takes a hostname as well as a boolean whether it is NixOS or not, and returns a matching nixosSystem or darwinSystem. This function is only used for systems that can use both NixOS and home-manager options (darwin still counts here as it can use some NixOS options). This is used in mkFullHostConfigs. In more detail, it dynamically creates a nixosConfiguration host, setting its speciaArgs and modules attributes. The modules are populated based on whether this is a NixOS or darwin host. For the latter, I will only ever use machines that I get for testing from work, and for these my username is different, so I implemented an if-condition for it. This could be done more cleanly using variables, but some care needs to be taken with the home-manager imports and this approach works, so for now this is fine. Thanks to this function, the import sections of the host configs are pretty clean for most hosts. -lib.optionals evaluates to an empty list ([]) in case that the conditional is not met.
    • -
    -

    -TODO -

    - -
    -
    { self, lib, systems, inputs, ... }:
    -{
    -
    -  mkIfElseList = p: yes: no: lib.mkMerge [
    -    (lib.mkIf p yes)
    -    (lib.mkIf (!p) no)
    -  ];
    -
    -  mkIfElse = p: yes: no: if p then yes else no;
    -
    -  forAllSystems = lib.genAttrs [
    -    "x86_64-linux"
    -    "aarch64-linux"
    -    "x86_64-darwin"
    -    "aarch64-darwin"
    -  ];
    -
    -  pkgsFor = lib.genAttrs (import systems) (system:
    -    import inputs.nixpkgs {
    -      inherit system;
    -      overlays = [ self.overlays.default ];
    -      config.allowUnfree = true;
    -    }
    -  );
    -
    -  toCapitalized = str:
    -    if builtins.stringLength str == 0 then
    -      ""
    -    else
    -      let
    -        first = builtins.substring 0 1 str;
    -        rest = builtins.substring 1 (builtins.stringLength str - 1) str;
    -        upper = lib.toUpper first;
    -        lower = lib.toLower rest;
    -      in
    -        upper + lower;
    -
    -
    -  # mkUser = name: {
    -  #   config.users.users.${name} = {
    -  #     group = name;
    -  #     isSystemUser = true;
    -  #   };
    -
    -  #   config.users.groups.${name} = {};
    -  # };
    -
    -  mkTrueOption = lib.mkOption {
    -    type = lib.types.bool;
    -    default = true;
    -  };
    -
    -  mkStrong = lib.mkOverride 60;
    -
    -  getSecret = filename: lib.strings.trim (builtins.readFile "${filename}");
    -
    -  forEachSystem = f: lib.genAttrs (import systems) (system: f lib.swarselsystems.pkgsFor.${system});
    -  forEachLinuxSystem = f: lib.genAttrs [ "x86_64-linux" "aarch64-linux" ] (system: f lib.swarselsystems.pkgsFor.${system});
    -
    -  readHosts = type: lib.attrNames (builtins.readDir "${self}/hosts/${type}");
    -  readNix = type: lib.filter (name: name != "default.nix") (lib.attrNames (builtins.readDir "${self}/${type}"));
    -
    -  mkApps = system: names: self: builtins.listToAttrs (map
    -    (name: {
    -      inherit name;
    -      value = {
    -        type = "app";
    -        program = "${self.packages.${system}.${name}}/bin/${name}";
    -        meta = {
    -          description = "Custom app ${name}.";
    -        };
    -      };
    -    })
    -    names);
    -
    -  mkPackages = names: pkgs: builtins.listToAttrs (map
    -    (name: {
    -      inherit name;
    -      value = pkgs.callPackage "${self}/pkgs/${name}" { inherit self name; };
    -    })
    -    names);
    -
    -
    -  mkModules = names: type: builtins.listToAttrs (map
    -    (name: {
    -      inherit name;
    -      value = import "${self}/modules/${type}/${name}";
    -    })
    -    names);
    -
    -  mkProfiles = names: type: builtins.listToAttrs (map
    -    (name: {
    -      inherit name;
    -      value = import "${self}/profiles/${type}/${name}";
    -    })
    -    names);
    -
    -  mkTemplates = names: builtins.listToAttrs (map
    -    (name: {
    -      inherit name;
    -      value = {
    -        path = "${self}/templates/${name}";
    -        description = "${name} project ";
    -      };
    -    })
    -    names);
    -
    -  mkImports = names: baseDir: lib.map (name: "${self}/${baseDir}/${name}") names;
    -
    -  eachMonitor = _: monitor: {
    -    inherit (monitor) name;
    -    value = builtins.removeAttrs monitor [ "workspace" "name" "output" ];
    -  };
    -
    -  eachOutput = _: monitor: {
    -    inherit (monitor) name;
    -    value = builtins.removeAttrs monitor [ "mode" "name" "scale" "transform" "position" ];
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -

    3.2.5. Auxiliary files

    -
    -
    -
    -
    3.2.5.1. extra-builtins
    -
    -
    -
    # adapted from https://github.com/oddlama/nix-config/blob/main/nix/extra-builtins.nix
    -{ exec, ... }:
    -let
    -  assertMsg = pred: msg: pred || builtins.throw msg;
    -  hasSuffix =
    -    suffix: content:
    -    let
    -      lenContent = builtins.stringLength content;
    -      lenSuffix = builtins.stringLength suffix;
    -    in
    -    lenContent >= lenSuffix && builtins.substring (lenContent - lenSuffix) lenContent content == suffix;
    -in
    -{
    -  # Instead of calling sops directly here, we call a wrapper script that will cache the output
    -  # in a predictable path in /tmp, which allows us to only require the password for each encrypted
    -  # file once.
    -  sopsImportEncrypted =
    -    nixFile:
    -    assert assertMsg (builtins.isPath nixFile)
    -      "The file to decrypt must be given as a path (not a string) to prevent impurity.";
    -    assert assertMsg (hasSuffix ".nix.enc" nixFile)
    -      "The content of the decrypted file must be a nix expression and should therefore end in .nix.enc";
    -    exec [
    -        ./sops-decrypt-and-cache.sh
    -        nixFile
    -      ];
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.5.2. sops-decrypt-and-cache
    -
    -
    -
    # adapted from https://github.com/oddlama/nix-config/blob/main/nix/rage-decrypt-and-cache.sh
    -set -euo pipefail
    -
    -print_out_path=false
    -if [[ $1 == "--print-out-path" ]]; then
    -    print_out_path=true
    -    shift
    -fi
    -
    -file="$1"
    -shift
    -
    -basename="${file%".enc"}"
    -# store path prefix or ./ if applicable
    -[[ $file == "/nix/store/"* ]] && basename="${basename#*"-"}"
    -[[ $file == "./"* ]] && basename="${basename#"./"}"
    -
    -# Calculate a unique content-based identifier (relocations of
    -# the source file in the nix store should not affect caching)
    -new_name="$(sha512sum "$file")"
    -new_name="${new_name:0:32}-${basename//"/"/"%"}"
    -
    -# Derive the path where the decrypted file will be stored
    -out="/var/tmp/nix-import-encrypted/$UID/$new_name"
    -umask 077
    -mkdir -p "$(dirname "$out")"
    -
    -# Decrypt only if necessary
    -if [[ ! -e $out ]]; then
    -    agekey=$(sudo ssh-to-age -private-key -i /etc/ssh/sops || sudo ssh-to-age -private-key -i /etc/ssh/ssh_host_ed25519_key)
    -    SOPS_AGE_KEY="$agekey" sops decrypt --output "$out" "$file"
    -fi
    -
    -# Print out path or decrypted content
    -if [[ $print_out_path == true ]]; then
    -    echo "$out"
    -else
    -    cat "$out"
    -fi
    -
    -
    -
    -
    -
    -
    3.2.5.3. nix-topology
    -
    -
    -
    { config, ... }:
    -let
    -  inherit (config.lib.topology)
    -    mkInternet
    -    mkDevice
    -    mkSwitch
    -    mkRouter
    -    mkConnection
    -    ;
    -in
    -{
    -  renderer = "elk";
    -
    -  networks = {
    -    home-lan = {
    -      name = "Home LAN";
    -      cidrv4 = "192.168.1.0/24";
    -    };
    -    wg = {
    -      name = "Wireguard Tunnel";
    -      cidrv4 = "192.168.3.0/24";
    -    };
    -  };
    -
    -  nodes = {
    -    internet = mkInternet {
    -      connections = [
    -        (mkConnection "moonside" "wan")
    -        (mkConnection "pfsense" "wan")
    -        (mkConnection "sync" "wan")
    -        (mkConnection "toto" "bootstrapper")
    -        (mkConnection "drugstore" "installer image")
    -        (mkConnection "chaostheatre" "demo host")
    -      ];
    -    };
    -
    -    chaostheatre.interfaces."demo host" = { };
    -    drugstore.interfaces."installer image" = { };
    -    toto.interfaces."bootstrapper" = { };
    -    sync.interfaces.wan = { };
    -    moonside.interfaces.wan = { };
    -
    -    pfsense = mkRouter "pfSense" {
    -      info = "HUNSN RM02";
    -      image = ../topology/images/hunsn.png;
    -      interfaceGroups = [
    -        [
    -          "eth2"
    -          "eth3"
    -          "eth4"
    -          "eth5"
    -          "eth6"
    -        ]
    -        [ "wan" ]
    -      ];
    -      interfaces.wg0 = {
    -        addresses = [ "192.168.3.1" ];
    -        network = "wg";
    -        virtual = true;
    -        type = "wireguard";
    -      };
    -
    -      connections = {
    -        eth2 = mkConnection "switch-livingroom" "eth1";
    -        eth4 = mkConnection "winters" "eth1";
    -        eth3 = mkConnection "switch-bedroom" "eth1";
    -        eth6 = mkConnection "wifi-ap" "eth1";
    -        wg = mkConnection "moonside" "wg";
    -      };
    -      interfaces = {
    -        eth2 = {
    -          addresses = [ "192.168.1.1" ];
    -          network = "home-lan";
    -        };
    -        eth3 = {
    -          addresses = [ "192.168.1.1" ];
    -          network = "home-lan";
    -        };
    -        eth4 = {
    -          addresses = [ "192.168.1.1" ];
    -          network = "home-lan";
    -        };
    -        eth6 = {
    -          addresses = [ "192.168.1.1" ];
    -          network = "home-lan";
    -        };
    -      };
    -    };
    -
    -    winters.interfaces."eth1" = { };
    -
    -    wifi-ap = mkSwitch "Wi-Fi AP" {
    -      info = "Huawei";
    -      image = ../topology/images/huawei.png;
    -      interfaceGroups = [
    -        [
    -          "eth1"
    -          "wifi"
    -        ]
    -      ];
    -    };
    -
    -    switch-livingroom = mkSwitch "Switch Livingroom" {
    -      info = "TL-SG108";
    -      image = ../topology/images/TL-SG108.png;
    -      interfaceGroups = [
    -        [
    -          "eth1"
    -          "eth2"
    -          "eth3"
    -          "eth4"
    -          "eth5"
    -          "eth6"
    -          "eth7"
    -          "eth8"
    -        ]
    -      ];
    -      connections = {
    -        eth2 = mkConnection "nswitch" "eth1";
    -        eth7 = mkConnection "pc" "eth1";
    -        eth8 = mkConnection "nbl-imba-2" "eth1";
    -      };
    -    };
    -
    -    nswitch = mkDevice "Nintendo Switch" {
    -      info = "Nintendo Switch";
    -      image = ../topology/images/nintendo-switch.png;
    -      interfaces.eth1 = { };
    -    };
    -
    -    pc = mkDevice "Windows Gaming Server" {
    -      info = "i7-4790k, GTX970, 32GB RAM";
    -      image = ../topology/images/pc.png;
    -      interfaces.eth1 = { };
    -    };
    -
    -    nbl-imba-2.interfaces.eth1 = { };
    -
    -    switch-bedroom = mkSwitch "Switch Bedroom" {
    -      info = "TL-SG1005D";
    -      image = ../topology/images/TL-SG1005D.png;
    -      interfaceGroups = [
    -        [
    -          "eth1"
    -          "eth2"
    -          "eth3"
    -          "eth4"
    -          "eth5"
    -        ]
    -      ];
    -      connections.eth2 = mkConnection "printer" "eth1";
    -    };
    -
    -    printer = mkDevice "Printer" {
    -      info = "DELL C2665dnf";
    -      image = ../topology/images/DELL-C2665dnf.png;
    -      interfaces.eth1 = { };
    -    };
    -
    -  };
    -
    -}
    -
    -
    -
    -
    -
    -
    -
    3.2.5.4. Globals
    -
    -
    -
    { inputs, ... }:
    -{
    -  flake =
    -    {
    -      config,
    -      lib,
    -      ...
    -    }:
    -    {
    -      globals =
    -        let
    -          globalsSystem = lib.evalModules {
    -            prefix = [ "globals" ];
    -            specialArgs = {
    -              inherit lib;
    -              inherit inputs;
    -              inherit (config) nodes;
    -            };
    -            modules = [
    -              ../modules/nixos/common/globals.nix
    -              (
    -                { lib, ... }:
    -                {
    -                  globals = lib.mkMerge (
    -                    lib.concatLists (
    -                      lib.flip lib.mapAttrsToList config.nodes (
    -                        name: cfg:
    -                        builtins.addErrorContext "while aggregating globals from nixosConfigurations.${name} into flake-level globals:" cfg.config._globalsDefs
    -                      )
    -                    )
    -                  );
    -                }
    -              )
    -            ];
    -          };
    -        in
    -        {
    -          # Make sure the keys of this attrset are trivially evaluatable to avoid infinite recursion,
    -          # therefore we inherit relevant attributes from the config.
    -          inherit (globalsSystem.config.globals)
    -            domains
    -            services
    -            macs
    -            myuser
    -            root
    -            ;
    -        };
    -    };
    -}
    -
    -
    -
    -
    -
    -
    -
    -

    3.3. NixOS

    +

    3.2. NixOS

    Here we have NixOS options. All options are split into smaller files that are loaded by the general default.nix. Common files are used by all user hosts equally, optionals need to be added to the machine's default.nix on a case-by-case basis.

    + +
    +
    { lib, ... }:
    +let
    +  importNames = lib.swarselsystems.readNix "modules/nixos";
    +in
    +  {
    +    imports = lib.swarselsystems.mkImports importNames "modules/nixos";
    +  }
    +
    +
    +
    -

    3.3.1. Common

    +

    3.2.1. Common

    These are system-level settings specific to NixOS machines. All settings that are required on all machines go here.

    -
    3.3.1.1. Imports, non-server settings
    +
    3.2.1.1. Imports

    This section is for setting things that should be used on hosts that are using the default NixOS configuration. This means that servers should NOT import this, as much of these imported modules are user-configured. @@ -7206,20 +4454,176 @@ let importNames = lib.swarselsystems.readNix "modules/nixos/common"; modulesPath = "${self}/modules"; in -{ - imports = lib.swarselsystems.mkImports importNames "modules/nixos/common" ++ [ - "${modulesPath}/home/common/sharedsetup.nix" - ]; + { + imports = lib.swarselsystems.mkImports importNames "modules/nixos/common" ++ [ + "${modulesPath}/home/common/sharedsetup.nix" + ]; -} + } +

    +
    +
    +
    +
    +
    3.2.1.2. Share configuration between nodes (automatically active)
    +
    +
    +
    # adapted from https://github.com/oddlama/nix-config/blob/main/modules/distributed-config.nix
    +{ config, lib, outputs, ... }:
    +let
    +  nodeName = config.node.name;
    +  mkForwardedOption =
    +    path:
    +    lib.mkOption {
    +      type = lib.mkOptionType {
    +        name = "Same type that the receiving option `${lib.concatStringsSep "." path}` normally accepts.";
    +        merge =
    +          _loc: defs:
    +          builtins.filter (x: builtins.isAttrs x -> ((x._type or "") != "__distributed_config_empty")) (
    +            map (x: x.value) defs
    +          );
    +      };
    +      default = {
    +        _type = "__distributed_config_empty";
    +      };
    +      description = ''
    +        Anything specified here will be forwarded to `${lib.concatStringsSep "." path}`
    +        on the given node. Forwarding happens as-is to the raw values,
    +        so validity can only be checked on the receiving node.
    +      '';
    +    };
    +
    +  forwardedOptions = [
    +    [
    +      "services"
    +      "nginx"
    +      "upstreams"
    +    ]
    +    [
    +      "services"
    +      "nginx"
    +      "virtualHosts"
    +    ]
    +  ];
    +
    +  attrsForEachOption =
    +    f: lib.foldl' (acc: path: lib.recursiveUpdate acc (lib.setAttrByPath path (f path))) { } forwardedOptions;
    +in
    +  {
    +    options.nodes = lib.mkOption {
    +      description = "Options forwarded to the given node.";
    +      default = { };
    +      type = lib.types.attrsOf (
    +        lib.types.submodule {
    +          options = attrsForEachOption mkForwardedOption;
    +        }
    +      );
    +    };
    +
    +    config =
    +      let
    +        getConfig =
    +          path: otherNode:
    +        let
    +          cfg = outputs.nixosConfigurations.${otherNode}.config.nodes.${nodeName} or null;
    +        in
    +          lib.optionals (cfg != null) (lib.getAttrFromPath path cfg);
    +        mergeConfigFromOthers = path: lib.mkMerge (lib.concatMap (getConfig path) (lib.attrNames outputs.nixosConfigurations));
    +      in
    +        attrsForEachOption mergeConfigFromOthers;
    +  }
    +
    +
    +
    +
    +
    +
    3.2.1.3. Global options (automatically active)
    +
    +
    +
    { lib, options, ... }:
    +let
    +  inherit (lib)
    +    mkOption
    +    types
    +  ;
    +in
    +  {
    +    options = {
    +      globals = mkOption {
    +        default = { };
    +        type = types.submodule {
    +          options = {
    +            user = {
    +              name = mkOption {
    +                type = types.str;
    +              };
    +              work = mkOption {
    +                type = types.str;
    +              };
    +            };
    +
    +
    +            services = mkOption {
    +              type = types.attrsOf (
    +                types.submodule {
    +                  options = {
    +                    domain = mkOption {
    +                      type = types.str;
    +                    };
    +                  };
    +                }
    +              );
    +            };
    +
    +            domains = {
    +              main = mkOption {
    +                type = types.str;
    +              };
    +            };
    +          };
    +        };
    +      };
    +
    +      _globalsDefs = mkOption {
    +        type = types.unspecified;
    +        default = options.globals.definitions;
    +        readOnly = true;
    +        internal = true;
    +      };
    +    };
    +  }
    +
    +
    +
    +
    +
    +
    3.2.1.4. Meta options (automatically active)
    +
    +
    +
    { lib, ... }:
    +{
    +  options = {
    +    node = {
    +      secretsDir = lib.mkOption {
    +        description = "Path to the secrets directory for this node.";
    +        type = lib.types.path;
    +        default = ./.;
    +      };
    +      name = lib.mkOption {
    +        description = "Node Name.";
    +        type = lib.types.str;
    +      };
    +    };
    +  };
    +}
     
    -
    3.3.1.2. Shared Configuration Options
    +
    3.2.1.5. Shared Configuration Options (automatically active)

    I usually use mutableUsers = false in my NixOS configuration. However, on a new system where sops-keys have not been deployed, this would immediately lock me out of the system. Hence this flag can be used until sops-keys are created. @@ -7258,8 +4662,30 @@ I usually use mutableUsers = false in my NixOS configuration. Howev

    +
    +
    3.2.1.6. Topology (automatically active)
    +
    +
    +
    { self, lib, config, ... }:
    +{
    +  options.swarselsystems.info = lib.mkOption {
    +    type = lib.types.str;
    +    default = "";
    +  };
    +  config.topology = {
    +    id = config.node.name;
    +    self = {
    +      hardware.info = config.swarselsystems.info;
    +      icon = lib.mkIf config.swarselsystems.isLaptop "devices.laptop";
    +    };
    +  };
    +}
    +
    +
    +
    +
    -
    3.3.1.3. General NixOS settings (stateVersion)
    +
    3.2.1.7. General NixOS settings (nix, stateVersion)

    We disable the warnings that trigger when rebuilding with a dirty flake. At this point, I am also disabling channels and pinning the flake registry - the latter lets me use the local version of nixpkgs for commands like nix shell (without it, we will always download the newest version of nixpkgs for these commands). @@ -7320,46 +4746,51 @@ A breakdown of the flags being set: let flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs; in - { - settings = { - experimental-features = [ - "nix-command" - "flakes" - "ca-derivations" - "cgroups" - "pipe-operators" - ]; - trusted-users = [ "@wheel" "${config.swarselsystems.mainUser}" ]; - connect-timeout = 5; - bash-prompt-prefix = "$SHLVL:\\w "; - bash-prompt = "$(if [[ $? -gt 0 ]]; then printf \"\"; else printf \"\"; fi)\[\e[1m\]λ\[\e[0m\] "; - fallback = true; - min-free = 128000000; - max-free = 1000000000; - flake-registry = ""; - auto-optimise-store = true; - warn-dirty = false; - max-jobs = 1; - use-cgroups = lib.mkIf config.swarselsystems.isLinux true; + { + settings = { + experimental-features = [ + "nix-command" + "flakes" + "ca-derivations" + "cgroups" + "pipe-operators" + ]; + trusted-users = [ "@wheel" "${config.swarselsystems.mainUser}" ]; + connect-timeout = 5; + bash-prompt-prefix = "$SHLVL:\\w "; + bash-prompt = "$(if [[ $? -gt 0 ]]; then printf \"\"; else printf \"\"; fi)\[\e[1m\]λ\[\e[0m\] "; + fallback = true; + min-free = 128000000; + max-free = 1000000000; + flake-registry = ""; + auto-optimise-store = true; + warn-dirty = false; + max-jobs = 1; + use-cgroups = lib.mkIf config.swarselsystems.isLinux true; + }; + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 10d"; + }; + optimise = { + automatic = true; + dates = "weekly"; + }; + channel.enable = false; + registry = rec { + nixpkgs.flake = inputs.nixpkgs; + p = nixpkgs; + }; + nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs; }; - gc = { - automatic = true; - dates = "weekly"; - options = "--delete-older-than 10d"; - }; - optimise = { - automatic = true; - dates = "weekly"; - }; - channel.enable = false; - registry = rec { - nixpkgs.flake = inputs.nixpkgs; - p = nixpkgs; - }; - nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs; - }; services.dbus.implementation = "broker"; + + systemd.services.nix-daemon = { + environment.TMPDIR = "/var/tmp"; + }; + system.stateVersion = lib.mkDefault "23.05"; }; } @@ -7367,163 +4798,395 @@ A breakdown of the flags being set:

    -
    -
    3.3.1.4. Share configuration between nodes
    -
    +
    +
    3.2.1.8. Setup home-manager base
    +
    +

    +We enable the use of home-manager as a NixoS module. A nice trick here is the extraSpecialArgs = inputs line, which enables the use of seflf in most parts of the configuration. This is useful to refer to the root of the flake (which is otherwise quite hard while maintaining flake purity). +

    +
    -
    # adapted from https://github.com/oddlama/nix-config/blob/main/modules/distributed-config.nix
    -{ config, lib, outputs, ... }:
    +
    { self, inputs, config, lib, outputs, globals, nodes, ... }:
     let
    -  nodeName = config.node.name;
    -  mkForwardedOption =
    -    path:
    -    lib.mkOption {
    -      type = lib.mkOptionType {
    -        name = "Same type that the receiving option `${lib.concatStringsSep "." path}` normally accepts.";
    -        merge =
    -          _loc: defs:
    -          builtins.filter (x: builtins.isAttrs x -> ((x._type or "") != "__distributed_config_empty")) (
    -            map (x: x.value) defs
    -          );
    -      };
    -      default = {
    -        _type = "__distributed_config_empty";
    -      };
    -      description = ''
    -        Anything specified here will be forwarded to `${lib.concatStringsSep "." path}`
    -        on the given node. Forwarding happens as-is to the raw values,
    -        so validity can only be checked on the receiving node.
    -      '';
    -    };
    -
    -  forwardedOptions = [
    -    [
    -      "services"
    -      "nginx"
    -      "upstreams"
    -    ]
    -    [
    -      "services"
    -      "nginx"
    -      "virtualHosts"
    -    ]
    -  ];
    -
    -  attrsForEachOption =
    -    f: lib.foldl' (acc: path: lib.recursiveUpdate acc (lib.setAttrByPath path (f path))) { } forwardedOptions;
    +  mainUser = globals.user.name;
     in
    -{
    -  options.nodes = lib.mkOption {
    -    description = "Options forwarded to the given node.";
    -    default = { };
    -    type = lib.types.attrsOf (
    -      lib.types.submodule {
    -        options = attrsForEachOption mkForwardedOption;
    -      }
    -    );
    -  };
    +  {
    +    options.swarselsystems.modules.home-manager = lib.mkEnableOption "home-manager";
    +    config = lib.mkIf config.swarselsystems.modules.home-manager {
    +      home-manager = lib.mkIf config.swarselsystems.withHomeManager {
    +        useGlobalPkgs = true;
    +        useUserPackages = true;
    +        verbose = true;
    +        users."${mainUser}".imports = [
    +          "${self}/profiles/home"
    +          "${self}/modules/home"
    +        ];
    +        sharedModules = [
    +          inputs.nix-index-database.hmModules.nix-index
    +          inputs.sops-nix.homeManagerModules.sops
    +          {
    +            home.stateVersion = lib.mkDefault config.system.stateVersion;
    +          }
    +        ];
    +        extraSpecialArgs = { inherit (inputs) self nixgl; inherit inputs outputs globals nodes; };
    +      };
    +    };
    +  }
    +
    +
    +
    +
    +
    +
    3.2.1.9. User setup, Make users non-mutable
    +
    +

    +This ensures that all user-configuration happens here in the config file. +In case of using a fully setup system, this makes also sure that no further user level modifications can be made using CLI utilities (e.g. usermod etc.). Everything must be defined in the flake. +

    - config = - let - getConfig = - path: otherNode: - let - cfg = outputs.nixosConfigurations.${otherNode}.config.nodes.${nodeName} or null; - in - lib.optionals (cfg != null) (lib.getAttrFromPath path cfg); - mergeConfigFromOthers = path: lib.mkMerge (lib.concatMap (getConfig path) (lib.attrNames outputs.nixosConfigurations)); - in - attrsForEachOption mergeConfigFromOthers; +

    +For that reason, make sure that sops-nix is properly working before setting the initialSetup flag, otherwise you might lose user access. +

    + +
    +
    { self, pkgs, config, lib, ... }:
    +let
    +  sopsFile = self + /secrets/general/secrets.yaml;
    +in
    +  {
    +    options.swarselsystems.modules.users = lib.mkEnableOption "user config";
    +    config = lib.mkIf config.swarselsystems.modules.users {
    +      sops.secrets.swarseluser = lib.mkIf (!config.swarselsystems.isPublic) { inherit sopsFile; neededForUsers = true; };
    +
    +      users = {
    +        mutableUsers = lib.mkIf (!config.swarselsystems.initialSetup) false;
    +        users."${config.swarselsystems.mainUser}" = {
    +          isNormalUser = true;
    +          description = "Leon S";
    +          password = lib.mkIf config.swarselsystems.initialSetup "setup";
    +          hashedPasswordFile = lib.mkIf (!config.swarselsystems.initialSetup) config.sops.secrets.swarseluser.path;
    +          extraGroups = [ "networkmanager" "syncthing" "docker" "wheel" "lp" "audio" "video" "vboxusers" "libvirtd" "scanner" ];
    +          packages = with pkgs; [ ];
    +        };
    +      };
    +    };
    +  }
    +
    +
    +
    +
    +
    +
    3.2.1.10. Setup login keymap
    +
    +

    +Next, we setup the keymap in case we are not in a graphical session. At this point, I always resort to us/altgr-intl, as it is comfortable to use and I do not write too much German anyways. +

    + +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.modules.xserver = lib.mkEnableOption "xserver keymap";
    +  config = lib.mkIf config.swarselsystems.modules.packages {
    +    services.xserver = {
    +      xkb = {
    +        layout = "us";
    +        variant = "altgr-intl";
    +      };
    +    };
    +  };
     }
     
    -
    -
    3.3.1.5. Global options
    -
    +
    +
    3.2.1.11. Time, locale settings
    +
    +

    +Setup timezone and locale. I want to use the US layout, but have the rest adapted to my country and timezone. Also, there is an issue with running Windows/Linux dualboot on the same machine where the hardware clock desyncs between the two OS'es. We fix that bug here as well. +

    +
    -
    { lib, options, ... }:
    -let
    -  inherit (lib)
    -    mkOption
    -    types
    -    ;
    -
    -in
    +
    { lib, config, ... }:
     {
    -  options = {
    -    globals = mkOption {
    -      default = { };
    -      type = types.submodule {
    -        options = {
    -          root = {
    -            hashedPassword = mkOption {
    -              type = types.str;
    -              description = "My root user's password hash.";
    -            };
    -          };
    -
    -          myuser = {
    -            name = mkOption {
    -              type = types.str;
    -              description = "My unix username.";
    -            };
    -            hashedPassword = mkOption {
    -              type = types.str;
    -              description = "My unix password hash.";
    -            };
    -          };
    -
    -
    -          services = mkOption {
    -            type = types.attrsOf (
    -              types.submodule {
    -                options = {
    -                  domain = mkOption {
    -                    type = types.str;
    -                    description = "The domain under which this service can be reached";
    -                  };
    -                };
    -              }
    -            );
    -          };
    -
    -          domains = {
    -            me = mkOption {
    -              type = types.str;
    -              description = "My main domain.";
    -            };
    -
    -            personal = mkOption {
    -              type = types.str;
    -              description = "My personal domain.";
    -            };
    -          };
    -
    -          macs = mkOption {
    -            default = { };
    -            type = types.attrsOf types.str;
    -            description = "Known MAC addresses for external devices.";
    -          };
    -        };
    -      };
    +  options.swarselsystems.modules.time = lib.mkEnableOption "time config";
    +  config = lib.mkIf config.swarselsystems.modules.time {
    +    time = {
    +      timeZone = "Europe/Vienna";
    +      # hardwareClockInLocalTime = true;
         };
     
    -    _globalsDefs = mkOption {
    -      type = types.unspecified;
    -      default = options.globals.definitions;
    -      readOnly = true;
    -      internal = true;
    +    i18n = {
    +      defaultLocale = "en_US.UTF-8";
    +      extraLocaleSettings = {
    +        LC_ADDRESS = "de_AT.UTF-8";
    +        LC_IDENTIFICATION = "de_AT.UTF-8";
    +        LC_MEASUREMENT = "de_AT.UTF-8";
    +        LC_MONETARY = "de_AT.UTF-8";
    +        LC_NAME = "de_AT.UTF-8";
    +        LC_NUMERIC = "de_AT.UTF-8";
    +        LC_PAPER = "de_AT.UTF-8";
    +        LC_TELEPHONE = "de_AT.UTF-8";
    +        LC_TIME = "de_AT.UTF-8";
    +      };
         };
       };
     }
    +
    +
    +
    +
    +
    +
    3.2.1.12. PII management
    +
    +
    +
    # largely based on https://github.com/oddlama/nix-config/blob/main/modules/secrets.nix
    +{ config, inputs, lib, ... }:
    +let
    +
    +  # If the given expression is a bare set, it will be wrapped in a function,
    +  # so that the imported file can always be applied to the inputs, similar to
    +  # how modules can be functions or sets.
    +  constSet = x: if builtins.isAttrs x then (_: x) else x;
    +
    +  # Try to access the extra builtin we loaded via nix-plugins.
    +  # Throw an error if that doesn't exist.
    +  sopsImportEncrypted =
    +    assert lib.assertMsg (builtins ? extraBuiltins.sopsImportEncrypted)
    +      "The extra builtin 'sopsImportEncrypted' is not available, so repo.secrets cannot be decrypted. Did you forget to add nix-plugins and point it to `<flakeRoot>/nix/extra-builtins.nix` ?";
    +    builtins.extraBuiltins.sopsImportEncrypted;
    +
    +  # This "imports" an encrypted .nix.age file by evaluating the decrypted content.
    +  importEncrypted =
    +    path:
    +    constSet (
    +      if builtins.pathExists path then
    +        sopsImportEncrypted path
    +      else
    +        { }
    +    );
    +in
    +{
    +  options = {
    +    repo = {
    +      secretFiles = lib.mkOption {
    +        default = { };
    +        type = lib.types.attrsOf lib.types.path;
    +        example = lib.literalExpression "{ local = ./pii.nix.enc; }";
    +        description = ''
    +        This file manages the origin for this machine's repository-secrets. Anything that is
    +        technically not a secret in the classical sense (i.e. that it has to be protected
    +        after it has been deployed), but something you want to keep secret from the public;
    +        Anything that you wouldn't want people to see on GitHub, but that can live unencrypted
    +        on your own devices. Consider it a more ergonomic nix alternative to using git-crypt.
    +
    +        All of these secrets may (and probably will be) put into the world-readable nix-store
    +        on the build and target hosts. You'll most likely want to store personally identifiable
    +        information here, such as:
    +          - MAC Addreses
    +          - Static IP addresses
    +          - Your full name (when configuring your users)
    +          - Your postal address (when configuring e.g. home-assistant)
    +          - ...
    +
    +        Each path given here must be an sops-encrypted .nix file. For each attribute `<name>`,
    +        the corresponding file will be decrypted, imported and exposed as {option}`repo.secrets.<name>`.
    +      '';
    +      };
    +
    +      secrets = lib.mkOption {
    +        readOnly = true;
    +        default = lib.mapAttrs (_: x: importEncrypted x inputs) config.repo.secretFiles;
    +        type = lib.types.unspecified;
    +        description = "Exposes the loaded repo secrets. This option is read-only.";
    +      };
    +    };
    +    swarselsystems.modules.pii = lib.mkEnableOption "enable pii management";
    +  };
    +  config = lib.mkIf config.swarselsystems.modules.pii {
    +    repo.secretFiles =
    +      let
    +        local = config.node.secretsDir + "/pii.nix.enc";
    +      in
    +        (lib.optionalAttrs (lib.pathExists local) { inherit local; }) // {
    +         common = ../../../secrets/repo/pii.nix.enc;
    +      };
    +  };
    +  }
    +
    +
    +
    +
    +
    +
    +
    3.2.1.13. Lanzaboote (secure boot)
    +
    +

    +This dynamically uses systemd boot or Lanzaboote depending on `config.swarselsystems.initialSetup` and `config.swarselsystems.isSecureBoot`. +

    + +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.modules.lanzaboote = lib.mkEnableOption "lanzaboote config";
    +  config = lib.mkIf config.swarselsystems.modules.lanzaboote {
    +    boot = {
    +      loader = {
    +        efi.canTouchEfiVariables = true;
    +        systemd-boot.enable = lib.swarselsystems.mkIfElse (config.swarselsystems.initialSetup || !config.swarselsystems.isSecureBoot) (lib.mkForce true) (lib.mkForce false);
    +      };
    +      lanzaboote = lib.mkIf (!config.swarselsystems.initialSetup && config.swarselsystems.isSecureBoot) {
    +        enable = true;
    +        pkiBundle = "/var/lib/sbctl";
    +        configurationLimit = 6;
    +      };
    +    };
    +  };
    +}
    +
    +
    +
    +
    +
    +
    3.2.1.14. Impermanence
    +
    +

    +This is where the impermanence magic happens. When this is enabled, the root directory is rolled back to a blanket state on each reboot. +

    + +

    +Normally, doing that also resets the lecture that happens on the first use of sudo, so we disable that at this point. Also, here we can set files to be persisted. Do note that you should still pay attention to files that need sudo access, as these need to be copied manually. +

    + +
    +
    { config, lib, ... }:
    +let
    +  mapperTarget = lib.swarselsystems.mkIfElse config.swarselsystems.isCrypted "/dev/mapper/cryptroot" "/dev/disk/by-label/nixos";
    +  inherit (config.swarselsystems) isImpermanence isCrypted;
    +in
    +{
    +  options.swarselsystems.modules.impermanence = lib.mkEnableOption "impermanence config";
    +  config = lib.mkIf config.swarselsystems.modules.impermanence {
    +
    +
    +    security.sudo.extraConfig = lib.mkIf isImpermanence ''
    +      # rollback results in sudo lectures after each reboot
    +      Defaults lecture = never
    +    '';
    +
    +    # This script does the actual wipe of the system
    +    # So if it doesn't run, the btrfs system effectively acts like a normal system
    +    # Taken from https://github.com/NotAShelf/nyx/blob/2a8273ed3f11a4b4ca027a68405d9eb35eba567b/modules/core/common/system/impermanence/default.nix
    +    boot.tmp.useTmpfs = lib.mkIf (!isImpermanence) true;
    +    boot.initrd.systemd = lib.mkIf isImpermanence {
    +      enable = true;
    +      services.rollback = {
    +        description = "Rollback BTRFS root subvolume to a pristine state";
    +        wantedBy = [ "initrd.target" ];
    +        # make sure it's done after encryption
    +        # i.e. LUKS/TPM process
    +        after = lib.swarselsystems.mkIfElseList isCrypted [ "systemd-cryptsetup@cryptroot.service" ] [ "dev-disk-by\\x2dlabel-nixos.device" ];
    +        requires = lib.mkIf (!isCrypted) [ "dev-disk-by\\x2dlabel-nixos.device" ];
    +        # mount the root fs before clearing
    +        before = [ "sysroot.mount" ];
    +        unitConfig.DefaultDependencies = "no";
    +        serviceConfig.Type = "oneshot";
    +        script = ''
    +          mkdir -p /mnt
    +
    +          # We first mount the btrfs root to /mnt
    +          # so we can manipulate btrfs subvolumes.
    +          mount -o subvolid=5 -t btrfs ${mapperTarget} /mnt
    +          btrfs subvolume list -o /mnt/root
    +
    +          # While we're tempted to just delete /root and create
    +          # a new snapshot from /root-blank, /root is already
    +          # populated at this point with a number of subvolumes,
    +          # which makes `btrfs subvolume delete` fail.
    +          # So, we remove them first.
    +          #
    +          # /root contains subvolumes:
    +          # - /root/var/lib/portables
    +          # - /root/var/lib/machines
    +
    +          btrfs subvolume list -o /mnt/root |
    +          cut -f9 -d' ' |
    +          while read subvolume; do
    +            echo "deleting /$subvolume subvolume..."
    +            btrfs subvolume delete "/mnt/$subvolume"
    +          done &&
    +          echo "deleting /root subvolume..." &&
    +          btrfs subvolume delete /mnt/root
    +
    +          echo "restoring blank /root subvolume..."
    +          btrfs subvolume snapshot /mnt/root-blank /mnt/root
    +
    +          # Once we're done rolling back to a blank snapshot,
    +          # we can unmount /mnt and continue on the boot process.
    +          umount /mnt
    +        '';
    +      };
    +    };
    +
    +
    +    environment.persistence."/persist" = lib.mkIf isImpermanence {
    +      hideMounts = true;
    +      directories =
    +        [
    +          "/etc/nix"
    +          "/etc/NetworkManager/system-connections"
    +          "/var/lib/nixos"
    +          "/var/tmp"
    +          {
    +            directory = "/var/tmp/nix-import-encrypted"; # Decrypted repo-secrets can be kept
    +            mode = "1777";
    +          }
    +          # "/etc/secureboot"
    +        ];
    +
    +      files = [
    +        "/etc/ssh/ssh_host_ed25519_key"
    +        "/etc/ssh/ssh_host_ed25519_key.pub"
    +        "/etc/machine-id"
    +      ];
    +    };
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +

    3.2.2. Client

    +
    +
    +
    +
    3.2.2.1. Imports
    +
    +

    +This section is for setting things that should be used on hosts that are using the default NixOS configuration. This means that servers should NOT import this, as much of these imported modules are user-configured. +

    + +
    +
    { lib, inputs, ... }:
    +let
    +  importNames = lib.swarselsystems.readNix "modules/nixos/client";
    +in
    +{
    +  imports = lib.swarselsystems.mkImports importNames "modules/nixos/client" ++ [
    +    inputs.stylix.nixosModules.stylix
    +    inputs.nswitch-rcm-nix.nixosModules.nswitch-rcm
    +  ];
    +}
    +
     
    -
    3.3.1.6. System Packages
    +
    3.2.2.2. System Packages

    Mostly used to install some compilers and lsp's that I want to have available when not using a devShell flake. Most other packages should go in Installed packages. @@ -7618,124 +5281,8 @@ Mostly used to install some compilers and lsp's that I want to have available wh

    -
    -
    3.3.1.7. Setup home-manager base
    -
    -

    -We enable the use of home-manager as a NixoS module. A nice trick here is the extraSpecialArgs = inputs line, which enables the use of seflf in most parts of the configuration. This is useful to refer to the root of the flake (which is otherwise quite hard while maintaining flake purity). -

    - -
    -
    { inputs, config, lib, ... }:
    -{
    -
    -  options.swarselsystems.modules.home-manager = lib.mkEnableOption "home-manager";
    -  config = lib.mkIf config.swarselsystems.modules.home-manager {
    -    home-manager = lib.mkIf config.swarselsystems.withHomeManager {
    -      useGlobalPkgs = true;
    -      useUserPackages = true;
    -      verbose = true;
    -      sharedModules = [
    -        inputs.nix-index-database.hmModules.nix-index
    -        inputs.sops-nix.homeManagerModules.sops
    -      {
    -        home.stateVersion = lib.mkDefault config.system.stateVersion;
    -      }
    -      ];
    -      extraSpecialArgs = { inherit (inputs) self; };
    -    };
    -  };
    -}
    -
    -
    -
    -
    -
    -
    3.3.1.8. Setup home-manager specialArgs
    -
    -

    -This sets up the nix-secrets extraSpeciaArgs. This should not be present on the chaostheatre configuration, which is why I split this section into its own file, which makes removal easier when setting that system up. -

    - -
    -
    { inputs, config, lib, ... }:
    -{
    -  options.swarselsystems.modules.home-managerExtra = lib.mkEnableOption "home-manager extras for non-chaostheatre";
    -  config = lib.mkIf config.swarselsystems.modules.home-managerExtra {
    -    home-manager = lib.mkIf config.swarselsystems.withHomeManager {
    -      extraSpecialArgs = { inherit (inputs) nix-secrets nixgl; };
    -    };
    -  };
    -}
    -
    -
    -
    -
    -
    -
    3.3.1.9. Setup login keymap
    -
    -

    -Next, we setup the keymap in case we are not in a graphical session. At this point, I always resort to us/altgr-intl, as it is comfortable to use and I do not write too much German anyways. -

    - -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.modules.xserver = lib.mkEnableOption "xserver keymap";
    -  config = lib.mkIf config.swarselsystems.modules.packages {
    -    services.xserver = {
    -      xkb = {
    -        layout = "us";
    -        variant = "altgr-intl";
    -      };
    -    };
    -  };
    -}
    -
    -
    -
    -
    -
    -
    3.3.1.10. User setup, Make users non-mutable
    -
    -

    -This ensures that all user-configuration happens here in the config file. -In case of using a fully setup system, this makes also sure that no further user level modifications can be made using CLI utilities (e.g. usermod etc.). Everything must be defined in the flake. -

    - -

    -For that reason, make sure that sops-nix is properly working before setting the initialSetup flag, otherwise you might lose user access. -

    - -
    -
    { self, pkgs, config, lib, ... }:
    -let
    -  sopsFile = self + /secrets/general/secrets.yaml;
    -in
    -{
    -  options.swarselsystems.modules.users = lib.mkEnableOption "user config";
    -  config = lib.mkIf config.swarselsystems.modules.users {
    -    sops.secrets.swarseluser = lib.mkIf (!config.swarselsystems.isPublic) { inherit sopsFile; neededForUsers = true; };
    -
    -    users = {
    -      mutableUsers = lib.mkIf (!config.swarselsystems.initialSetup) false;
    -      users."${config.swarselsystems.mainUser}" = {
    -        isNormalUser = true;
    -        description = "Leon S";
    -        password = lib.mkIf config.swarselsystems.initialSetup "setup";
    -        hashedPasswordFile = lib.mkIf (!config.swarselsystems.initialSetup) config.sops.secrets.swarseluser.path;
    -        extraGroups = [ "networkmanager" "syncthing" "docker" "wheel" "lp" "audio" "video" "vboxusers" "libvirtd" "scanner" ];
    -        packages = with pkgs; [ ];
    -      };
    -    };
    -  };
    -}
    -
    -
    -
    -
    -
    3.3.1.11. Environment setup
    +
    3.2.2.3. Environment setup

    Next, we will setup some environment variables that need to be set on the system-side. We apply some compatibility options for chromium apps on wayland, enable the wordlist and make metadata reading possible for my file explorer (nautilus). @@ -7766,7 +5313,7 @@ Next, we will setup some environment variables that need to be set on the system

    -
    3.3.1.12. Security
    +
    3.2.2.4. Security

    Needed for control over system-wide privileges etc. Also I make sure that the root user has access to SSH_AUTH_SOCK (without this, root will not be able to read my nix-secrets repository). @@ -7800,7 +5347,7 @@ Needed for control over system-wide privileges etc. Also I make sure that the ro

    -
    3.3.1.13. Reduce systemd timeouts
    +
    3.2.2.5. Reduce systemd timeouts

    There is a persistent bug over Linux kernels that makes the user wait 1m30s on system shutdown due to the reason a stop job is running for session 1 of user .... I do not want to wait that long and am confident no important data is lost by doing this. @@ -7823,7 +5370,7 @@ There is a persistent bug over Linux kernels that makes the user wait 1m30s on s

    -
    3.3.1.14. Hardware settings
    +
    3.2.2.6. Hardware settings

    Enable OpenGL, Sound, Bluetooth and various drivers. @@ -7883,7 +5430,7 @@ Enable OpenGL, Sound, Bluetooth and various drivers.

    -
    3.3.1.15. Pulseaudio
    +
    3.2.2.7. Pulseaudio

    This is only used on systems not running Pipewire. @@ -7907,7 +5454,7 @@ This is only used on systems not running Pipewire.

    -
    3.3.1.16. Pipewire
    +
    3.2.2.8. Pipewire

    Pipewire handles communication on Wayland. This enables several sound tools as well as screen sharing in combinaton with xdg-desktop-portal-wlr. @@ -7939,21 +5486,80 @@ Pipewire handles communication on Wayland. This enables several sound tools as w

    -
    3.3.1.17. Common network settings
    +
    3.2.2.9. Common network settings

    Here I only enable networkmanager and a few default networks. The rest of the network config is done separately in System specific configuration.

    -
    { lib, config, ... }:
    +
    { self, lib, config, ... }:
    +let
    +  certsSopsFile = self + /secrets/certs/secrets.yaml;
    +  inherit (config.swarselsystems) mainUser;
    +  iwd = config.networking.networkmanager.wifi.backend == "iwd";
    +in
     {
       options.swarselsystems = {
         modules.network = lib.mkEnableOption "network config";
         firewall = lib.swarselsystems.mkTrueOption;
       };
       config = lib.mkIf config.swarselsystems.modules.network {
    +
    +    sops = {
    +      secrets = lib.mkIf (!config.swarselsystems.isPublic) {
    +        ernest = { };
    +        frauns = { };
    +        hotspot = { };
    +        eduid = { };
    +        edupass = { };
    +        handyhotspot = { };
    +        vpnuser = { };
    +        vpnpass = { };
    +        wireguardpriv = { };
    +        wireguardpub = { };
    +        wireguardendpoint = { };
    +        stashuser = { };
    +        stashpass = { };
    +        githubforgeuser = { };
    +        githubforgepass = { };
    +        gitlabforgeuser = { };
    +        gitlabforgepass = { };
    +        "sweden-aes-128-cbc-udp-dns-crl-verify.pem" = { sopsFile = certsSopsFile; owner = mainUser; };
    +        "sweden-aes-128-cbc-udp-dns-ca.pem" = { sopsFile = certsSopsFile; owner = mainUser; };
    +      };
    +      templates = lib.mkIf (!config.swarselsystems.isPublic) {
    +        "network-manager.env".content = ''
    +          ERNEST=${config.sops.placeholder.ernest}
    +          FRAUNS=${config.sops.placeholder.frauns}
    +          HOTSPOT=${config.sops.placeholder.hotspot}
    +          EDUID=${config.sops.placeholder.eduid}
    +          EDUPASS=${config.sops.placeholder.edupass}
    +          HANDYHOTSPOT=${config.sops.placeholder.handyhotspot}
    +          VPNUSER=${config.sops.placeholder.vpnuser}
    +          VPNPASS=${config.sops.placeholder.vpnpass}
    +          WIREGUARDPRIV=${config.sops.placeholder.wireguardpriv}
    +          WIREGUARDPUB=${config.sops.placeholder.wireguardpub}
    +          WIREGUARDENDPOINT=${config.sops.placeholder.wireguardendpoint}
    +        '';
    +      };
    +    };
    +
         networking = {
    +      wireless.iwd = {
    +        enable = true;
    +        settings = {
    +          IPv6 = {
    +            Enabled = true;
    +          };
    +          Settings = {
    +            AutoConnect = true;
    +          };
    +          DriverQuirks = {
    +            UseDefaultInterface = true;
    +          };
    +        };
    +      };
           nftables.enable = lib.mkDefault true;
           enableIPv6 = lib.mkDefault true;
           firewall = {
    @@ -7970,6 +5576,7 @@ Here I only enable networkmanager and a few default networks. The r
     
           networkmanager = {
             enable = true;
    +        wifi.backend = "iwd";
             ensureProfiles = lib.mkIf (!config.swarselsystems.isPublic) {
               environmentFiles = [
                 "${config.sops.templates."network-manager.env".path}"
    @@ -8023,10 +5630,11 @@ Here I only enable networkmanager and a few default networks. The r
     
                 eduroam = {
                   "802-1x" = {
    -                eap = "ttls;";
    +                eap = if (!iwd) then "ttls;" else "peap;";
                     identity = "$EDUID";
                     password = "$EDUPASS";
                     phase2-auth = "mschapv2";
    +                anonymous-identity = lib.mkIf iwd "anonymous@student.tuwien.ac.at";
                   };
                   connection = {
                     id = "eduroam";
    @@ -8201,91 +5809,8 @@ Here I only enable networkmanager and a few default networks. The r
     
    -
    -
    3.3.1.18. Time, locale settings
    -
    -

    -Setup timezone and locale. I want to use the US layout, but have the rest adapted to my country and timezone. Also, there is an issue with running Windows/Linux dualboot on the same machine where the hardware clock desyncs between the two OS'es. We fix that bug here as well. -

    - -
    -
    { lib, config, ... }:
    -{
    -  options.swarselsystems.modules.time = lib.mkEnableOption "time config";
    -  config = lib.mkIf config.swarselsystems.modules.time {
    -    time = {
    -      timeZone = "Europe/Vienna";
    -      # hardwareClockInLocalTime = true;
    -    };
    -
    -    i18n = {
    -      defaultLocale = "en_US.UTF-8";
    -      extraLocaleSettings = {
    -        LC_ADDRESS = "de_AT.UTF-8";
    -        LC_IDENTIFICATION = "de_AT.UTF-8";
    -        LC_MEASUREMENT = "de_AT.UTF-8";
    -        LC_MONETARY = "de_AT.UTF-8";
    -        LC_NAME = "de_AT.UTF-8";
    -        LC_NUMERIC = "de_AT.UTF-8";
    -        LC_PAPER = "de_AT.UTF-8";
    -        LC_TELEPHONE = "de_AT.UTF-8";
    -        LC_TIME = "de_AT.UTF-8";
    -      };
    -    };
    -  };
    -}
    -
    -
    -
    -
    -
    -
    3.3.1.19. Meta options
    -
    -
    -
    { lib, ... }:
    -{
    -  options = {
    -    node = {
    -      secretsDir = lib.mkOption {
    -        description = "Path to the secrets directory for this node.";
    -        type = lib.types.path;
    -        default = ./.;
    -      };
    -      name = lib.mkOption {
    -        description = "Node Name.";
    -        type = lib.types.str;
    -      };
    -    };
    -  };
    -}
    -
    -
    -
    -
    -
    -
    3.3.1.20. Topology
    -
    -
    -
    { self, lib, config, ... }:
    -{
    -  options.swarselsystems.info = lib.mkOption {
    -    type = lib.types.str;
    -    default = "";
    -  };
    -  config.topology = {
    -    id = config.node.name;
    -    self = {
    -      hardware.info = config.swarselsystems.info;
    -      icon = lib.mkIf config.swarselsystems.isLaptop "devices.laptop";
    -    };
    -  };
    -}
    -
    -
    -
    -
    -
    3.3.1.21. sops
    +
    3.2.2.10. sops

    I use sops-nix to handle secrets that I want to have available on my machines at all times. Procedure to add a new machine: @@ -8299,148 +5824,28 @@ I use sops-nix to handle secrets that I want to have available on my machines at

    -
    { self, config, lib, ... }:
    -let
    -  certsSopsFile = self + /secrets/certs/secrets.yaml;
    -  inherit (config.swarselsystems) mainUser homeDir;
    -in
    +
    { config, lib, ... }:
     {
    -  options.swarselsystems.modules.commonSops = lib.mkEnableOption "sops config";
    -  config = lib.mkIf config.swarselsystems.modules.commonSops {
    +  options.swarselsystems.modules.sops = lib.mkEnableOption "sops config";
    +  config = lib.mkIf config.swarselsystems.modules.sops {
         sops = {
     
    -      age.sshKeyPaths = lib.swarselsystems.mkIfElseList config.swarselsystems.isBtrfs [ "/persist/.ssh/sops" "/persist/.ssh/ssh_host_ed25519_key" ] [ "${homeDir}/.ssh/sops" "/etc/ssh/ssh_host_ed25519_key" ];
    -      defaultSopsFile = lib.swarselsystems.mkIfElseList config.swarselsystems.isBtrfs "/persist/.dotfiles/secrets/general/secrets.yaml" "${homeDir}/.dotfiles/secrets/general/secrets.yaml";
    +      # age.sshKeyPaths = lib.swarselsystems.mkIfElseList config.swarselsystems.isBtrfs [ "/persist/.ssh/sops" "/persist/.ssh/ssh_host_ed25519_key" ] [ "${config.swarselsystems.homeDir}/.ssh/sops" "/etc/ssh/sops" "/etc/ssh/ssh_host_ed25519_key" ];
    +      age.sshKeyPaths = [ "${config.swarselsystems.homeDir}/.ssh/sops" "/etc/ssh/sops" "/etc/ssh/ssh_host_ed25519_key" ];
    +      # defaultSopsFile = lib.swarselsystems.mkIfElseList config.swarselsystems.isBtrfs "/persist/.dotfiles/secrets/general/secrets.yaml" "${config.swarselsystems.flakePath}/secrets/general/secrets.yaml";
    +      defaultSopsFile = "${config.swarselsystems.flakePath}/secrets/general/secrets.yaml";
     
           validateSopsFiles = false;
     
    -      secrets = lib.mkIf (!config.swarselsystems.isPublic) {
    -        ernest = { };
    -        frauns = { };
    -        hotspot = { };
    -        eduid = { };
    -        edupass = { };
    -        handyhotspot = { };
    -        vpnuser = { };
    -        vpnpass = { };
    -        wireguardpriv = { };
    -        wireguardpub = { };
    -        wireguardendpoint = { };
    -        stashuser = { };
    -        stashpass = { };
    -        githubforgeuser = { };
    -        githubforgepass = { };
    -        gitlabforgeuser = { };
    -        gitlabforgepass = { };
    -        "sweden-aes-128-cbc-udp-dns-crl-verify.pem" = { sopsFile = certsSopsFile; owner = mainUser; };
    -        "sweden-aes-128-cbc-udp-dns-ca.pem" = { sopsFile = certsSopsFile; owner = mainUser; };
    -      };
    -      templates = lib.mkIf (!config.swarselsystems.isPublic) {
    -        "network-manager.env".content = ''
    -          ERNEST=${config.sops.placeholder.ernest}
    -          FRAUNS=${config.sops.placeholder.frauns}
    -          HOTSPOT=${config.sops.placeholder.hotspot}
    -          EDUID=${config.sops.placeholder.eduid}
    -          EDUPASS=${config.sops.placeholder.edupass}
    -          HANDYHOTSPOT=${config.sops.placeholder.handyhotspot}
    -          VPNUSER=${config.sops.placeholder.vpnuser}
    -          VPNPASS=${config.sops.placeholder.vpnpass}
    -          WIREGUARDPRIV=${config.sops.placeholder.wireguardpriv}
    -          WIREGUARDPUB=${config.sops.placeholder.wireguardpub}
    -          WIREGUARDENDPOINT=${config.sops.placeholder.wireguardendpoint}
    -        '';
    -      };
         };
       };
     }
    -
    -
    -
    -
    -
    -
    3.3.1.22. PII management
    -
    -
    -
    # largely based on https://github.com/oddlama/nix-config/blob/main/modules/secrets.nix
    -{ config, inputs, lib, ... }:
    -let
    -
    -  # If the given expression is a bare set, it will be wrapped in a function,
    -  # so that the imported file can always be applied to the inputs, similar to
    -  # how modules can be functions or sets.
    -  constSet = x: if builtins.isAttrs x then (_: x) else x;
    -
    -  # Try to access the extra builtin we loaded via nix-plugins.
    -  # Throw an error if that doesn't exist.
    -  sopsImportEncrypted =
    -    assert lib.assertMsg (builtins ? extraBuiltins.sopsImportEncrypted)
    -      "The extra builtin 'sopsImportEncrypted' is not available, so repo.secrets cannot be decrypted. Did you forget to add nix-plugins and point it to `<flakeRoot>/nix/extra-builtins.nix` ?";
    -    builtins.extraBuiltins.sopsImportEncrypted;
    -
    -  # This "imports" an encrypted .nix.age file by evaluating the decrypted content.
    -  importEncrypted =
    -    path:
    -    constSet (
    -      if builtins.pathExists path then
    -        sopsImportEncrypted path
    -      else
    -        { }
    -    );
    -in
    -{
    -  options = {
    -    repo = {
    -      secretFiles = lib.mkOption {
    -        default = { };
    -        type = lib.types.attrsOf lib.types.path;
    -        example = lib.literalExpression "{ local = ./pii.nix.enc; }";
    -        description = ''
    -        This file manages the origin for this machine's repository-secrets. Anything that is
    -        technically not a secret in the classical sense (i.e. that it has to be protected
    -        after it has been deployed), but something you want to keep secret from the public;
    -        Anything that you wouldn't want people to see on GitHub, but that can live unencrypted
    -        on your own devices. Consider it a more ergonomic nix alternative to using git-crypt.
    -
    -        All of these secrets may (and probably will be) put into the world-readable nix-store
    -        on the build and target hosts. You'll most likely want to store personally identifiable
    -        information here, such as:
    -          - MAC Addreses
    -          - Static IP addresses
    -          - Your full name (when configuring your users)
    -          - Your postal address (when configuring e.g. home-assistant)
    -          - ...
    -
    -        Each path given here must be an sops-encrypted .nix file. For each attribute `<name>`,
    -        the corresponding file will be decrypted, imported and exposed as {option}`repo.secrets.<name>`.
    -      '';
    -      };
    -
    -      secrets = lib.mkOption {
    -        readOnly = true;
    -        default = lib.mapAttrs (_: x: importEncrypted x inputs) config.repo.secretFiles;
    -        type = lib.types.unspecified;
    -        description = "Exposes the loaded repo secrets. This option is read-only.";
    -      };
    -    };
    -    swarselsystems.modules.pii = lib.mkEnableOption "enable pii management";
    -  };
    -  config = lib.mkIf config.swarselsystems.modules.pii {
    -    repo.secretFiles =
    -      let
    -        local = config.node.secretsDir + "/pii.nix.enc";
    -      in
    -        (lib.optionalAttrs (lib.pathExists local) { inherit local; }) // {
    -         common = ../../../secrets/repo/pii.nix.enc;
    -      };
    -  };
    -  }
    -
     
    -
    3.3.1.23. Theme (stylix)
    +
    3.2.2.11. Theme (stylix)

    By default, stylix wants to style GRUB as well. However, I think that looks horrible. @@ -8470,7 +5875,7 @@ By default, stylix wants to style

    -
    3.3.1.24. Programs (including zsh setup)
    +
    3.2.2.12. Programs (including zsh setup)

    Some programs profit from being installed through dedicated NixOS settings on system-level; these go here. Notably the zsh setup goes here and cannot be deleted under any circumstances. @@ -8492,7 +5897,7 @@ Some programs profit from being installed through dedicated NixOS settings on sy

    -
    3.3.1.24.1. zsh
    +
    3.2.2.12.1. zsh

    Here I disable global completion to prevent redundant compinit calls and cache invalidation that slow down shell startup (enabled on the home-manager side). @@ -8517,7 +5922,7 @@ Here I disable global completion to prevent redundant compinit calls and cache i

    -
    3.3.1.24.2. syncthing
    +
    3.2.2.12.2. syncthing
    { lib, config, pkgs, ... }:
    @@ -8586,14 +5991,14 @@ in
     
    -
    3.3.1.25. Services
    +
    3.2.2.13. Services

    Setting up some hardware services as well as keyboard related settings. Here we make sure that we can use the CAPS key as a ESC/CTRL double key, which is a lifesaver.

    -
    3.3.1.25.1. blueman
    +
    3.2.2.13.1. blueman

    Enables the blueman service including the nice system tray icon. @@ -8613,7 +6018,7 @@ Enables the blueman service including the nice system tray icon.

    -
    3.3.1.25.2. Network devices
    +
    3.2.2.13.2. Network devices

    In this section we enable compatibility with several network devices I have at home, mainly printers and scanners. @@ -8664,7 +6069,7 @@ Avahi is the service used for the network discovery.

    -
    3.3.1.25.3. enable GVfs
    +
    3.2.2.13.3. enable GVfs

    This is being set to allow myself to use all functions of nautilus in NixOS @@ -8683,7 +6088,7 @@ This is being set to allow myself to use all functions of nautilus in NixOS

    -
    3.3.1.25.4. interception-tools: Make CAPS work as ESC/CTRL
    +
    3.2.2.13.4. interception-tools: Make CAPS work as ESC/CTRL

    This is a super-convenient package that lets my remap my CAPS key to ESC if pressed shortly, and CTRL if being held. @@ -8727,7 +6132,7 @@ This is a super-convenient package that lets my remap my CAPS key t

    -
    3.3.1.25.5. power-profiles-daemon
    +
    3.2.2.13.5. power-profiles-daemon

    This enables power profile management. The available modes are: @@ -8756,7 +6161,7 @@ Most of the time I am using power-saver, however, it is good to be

    -
    3.3.1.25.6. SwayOSD
    +
    3.2.2.13.6. SwayOSD
    { lib, pkgs, config, ... }:
    @@ -8787,11 +6192,11 @@ Most of the time I am using power-saver, however, it is good to be
     
    -
    3.3.1.26. Hardware compatibility settings (Yubikey, Ledger, Keyboards) - udev rules
    +
    3.2.2.14. Hardware compatibility settings (Yubikey, Ledger, Keyboards) - udev rules
    -
    3.3.1.26.1. Yubikey
    +
    3.2.2.14.1. Yubikey

    This takes care of the main Yubikey related configuration on the NixOS side - note that the starting of the gpg-agent is done in the sway settings, to also perform this step of the setup for non NixOS-machines at the same time. @@ -8831,7 +6236,7 @@ Also, since I use a GPG key in sops, it seems that scdaemon creates an instance

    -
    3.3.1.26.2. Ledger
    +
    3.2.2.14.2. Ledger

    This performs the necessary configuration to support this hardware. @@ -8855,7 +6260,7 @@ This performs the necessary configuration to support this hardware.

    -
    3.3.1.26.3. Keyboards
    +
    3.2.2.14.3. Keyboards

    This loads some udev rules that I need for my split keyboards. @@ -8879,7 +6284,7 @@ This loads some udev rules that I need for my split keyboards.

    -
    3.3.1.27. System Login
    +
    3.2.2.15. System Login

    This section houses the greetd related settings. I do not really want to use a display manager, but it is useful to have setup in some ways - in my case for starting sway on system startup. Notably the default user login setting that is commented out here goes into the system specific settings, make sure to update it there @@ -8914,7 +6319,7 @@ This section houses the greetd related settings. I do not really want to use a d

    -
    3.3.1.28. nix-ld
    +
    3.2.2.16. nix-ld

    This provides libraries for binaries that are not patched for use on NixOS. This really makes the biggest gripe with NixOS go away, that being having to run a binary that is only found in a single spot. It is most of the times possible to patch such a file, but this makes such a situation take much less time to resolve. @@ -9046,115 +6451,8 @@ When a program does not work, start with nix-ldd <program>. T

    -
    -
    3.3.1.29. Impermanence
    -
    -

    -This is where the impermanence magic happens. When this is enabled, the root directory is rolled back to a blanket state on each reboot. -

    - -

    -Normally, doing that also resets the lecture that happens on the first use of sudo, so we disable that at this point. Also, here we can set files to be persisted. Do note that you should still pay attention to files that need sudo access, as these need to be copied manually. -

    - -
    -
    { config, lib, ... }:
    -let
    -  mapperTarget = lib.swarselsystems.mkIfElse config.swarselsystems.isCrypted "/dev/mapper/cryptroot" "/dev/disk/by-label/nixos";
    -  inherit (config.swarselsystems) isImpermanence isCrypted;
    -in
    -{
    -  options.swarselsystems.modules.impermanence = lib.mkEnableOption "impermanence config";
    -  config = lib.mkIf config.swarselsystems.modules.impermanence {
    -
    -    security.sudo.extraConfig = lib.mkIf isImpermanence ''
    -      # rollback results in sudo lectures after each reboot
    -      Defaults lecture = never
    -    '';
    -
    -    # This script does the actual wipe of the system
    -    # So if it doesn't run, the btrfs system effectively acts like a normal system
    -    # Taken from https://github.com/NotAShelf/nyx/blob/2a8273ed3f11a4b4ca027a68405d9eb35eba567b/modules/core/common/system/impermanence/default.nix
    -
    -    boot.initrd.systemd.enable = lib.mkIf isImpermanence true;
    -
    -    boot.initrd.systemd.services.rollback = lib.mkIf isImpermanence {
    -      description = "Rollback BTRFS root subvolume to a pristine state";
    -      wantedBy = [ "initrd.target" ];
    -      # make sure it's done after encryption
    -      # i.e. LUKS/TPM process
    -      after = lib.swarselsystems.mkIfElseList isCrypted [ "systemd-cryptsetup@cryptroot.service" ] [ "dev-disk-by\\x2dlabel-nixos.device" ];
    -      requires = lib.mkIf (!isCrypted) [ "dev-disk-by\\x2dlabel-nixos.device" ];
    -      # mount the root fs before clearing
    -      before = [ "sysroot.mount" ];
    -      unitConfig.DefaultDependencies = "no";
    -      serviceConfig.Type = "oneshot";
    -      script = ''
    -        mkdir -p /mnt
    -
    -        # We first mount the btrfs root to /mnt
    -        # so we can manipulate btrfs subvolumes.
    -        mount -o subvolid=5 -t btrfs ${mapperTarget} /mnt
    -        btrfs subvolume list -o /mnt/root
    -
    -        # While we're tempted to just delete /root and create
    -        # a new snapshot from /root-blank, /root is already
    -        # populated at this point with a number of subvolumes,
    -        # which makes `btrfs subvolume delete` fail.
    -        # So, we remove them first.
    -        #
    -        # /root contains subvolumes:
    -        # - /root/var/lib/portables
    -        # - /root/var/lib/machines
    -
    -        btrfs subvolume list -o /mnt/root |
    -        cut -f9 -d' ' |
    -        while read subvolume; do
    -          echo "deleting /$subvolume subvolume..."
    -          btrfs subvolume delete "/mnt/$subvolume"
    -        done &&
    -        echo "deleting /root subvolume..." &&
    -        btrfs subvolume delete /mnt/root
    -
    -        echo "restoring blank /root subvolume..."
    -        btrfs subvolume snapshot /mnt/root-blank /mnt/root
    -
    -        # Once we're done rolling back to a blank snapshot,
    -        # we can unmount /mnt and continue on the boot process.
    -        umount /mnt
    -      '';
    -    };
    -
    -
    -    environment.persistence."/persist" = lib.mkIf isImpermanence {
    -      hideMounts = true;
    -      directories =
    -        [
    -          "/etc/nix"
    -          "/etc/NetworkManager/system-connections"
    -          "/var/lib/nixos"
    -          {
    -            directory = "/var/tmp/nix-import-encrypted"; # Decrypted repo-secrets can be kept
    -            mode = "1777";
    -          }
    -          # "/etc/secureboot"
    -        ];
    -
    -      files = [
    -        "/etc/ssh/ssh_host_ed25519_key"
    -        "/etc/ssh/ssh_host_ed25519_key.pub"
    -        "/etc/machine-id"
    -      ];
    -    };
    -  };
    -
    -}
    -
    -
    -
    -
    -
    3.3.1.30. Summary of nixos-rebuild diff
    +
    3.2.2.17. Summary of nixos-rebuild diff

    This snipped is added to the activation script that is run after every rebuild and shows what packages have been added and removed. This is actually not the optimal place to add that snipped, but the correct spot is in some perl file that I have not had the leisure to take a look at yet. @@ -9179,7 +6477,7 @@ This snipped is added to the activation script that is run after every rebuild a

    -
    3.3.1.31. gnome-keyring
    +
    3.2.2.18. gnome-keyring

    Used for storing sessions in e.g. Nextcloud. Using this on a system level keeps the login information when logging out of the session as well. @@ -9202,7 +6500,7 @@ Used for storing sessions in e.g. Nextcloud. Using this on a system level keeps

    -
    3.3.1.32. Sway
    +
    3.2.2.19. Sway

    This is used to better integrate Sway into the system on NixOS hosts. On the home-manager side, the package attribute will be null for such an host, using the systems derivation instead. @@ -9238,7 +6536,7 @@ This is used to better integrate Sway into the system on NixOS hosts. On the hom

    -
    3.3.1.33. xdg-portal
    +
    3.2.2.20. xdg-portal

    This allows me to use screen sharing on Wayland. The implementation is a bit crude and only the whole screen can be shared. However, most of the time that is all I need to do anyways. @@ -9270,7 +6568,7 @@ This allows me to use screen sharing on Wayland. The implementation is a bit cru

    -
    3.3.1.34. Podmam (distrobox)
    +
    3.2.2.21. Podmam (distrobox)

    I am using distrobox to quickly circumvent isses that I cannot immediately solve on NixOS. It is always the goal to quickly get things working on NixOS, but this prevents me from getting completely stuck. @@ -9298,7 +6596,7 @@ I am using distrobox to quickly circumvent isses that I cannot immediately solve

    -
    3.3.1.35. Appimage
    +
    3.2.2.22. Appimage

    Adds the necessary tools to allow .appimage programs easily. @@ -9321,7 +6619,7 @@ Adds the necessary tools to allow .appimage programs easily.

    -
    3.3.1.36. Handle lid switch correctly
    +
    3.2.2.23. Handle lid switch correctly

    This turns off the display when the lid is closed. @@ -9370,7 +6668,7 @@ This turns off the display when the lid is closed.

    -
    3.3.1.37. Low battery notification
    +
    3.2.2.24. Low battery notification

    Since I hide the waybar completely during normal operation, I run the risk of not noticing when my battery is about to run out. This module sends a notification when the battery level falls below 10%. Written by cafkafk. @@ -9410,28 +6708,24 @@ Since I hide the waybar completely during normal operation, I run the risk of no

    -
    -
    3.3.1.38. Lanzaboote
    -
    +
    +
    3.2.2.25. Auto-login
    +

    -This dynamically uses systemd boot or Lanzaboote depending on `config.swarselsystems.initialSetup` and `config.swarselsystems.isSecureBoot`. +Auto login for the initial session.

    { lib, config, ... }:
    +let
    +  inherit (config.swarselsystems) mainUser;
    +in
     {
    -  options.swarselsystems.modules.lanzaboote = lib.mkEnableOption "lanzaboote config";
    -  config = lib.mkIf config.swarselsystems.modules.lanzaboote {
    -    boot = {
    -      loader = {
    -        efi.canTouchEfiVariables = true;
    -        systemd-boot.enable = lib.swarselsystems.mkIfElse (config.swarselsystems.initialSetup || !config.swarselsystems.isSecureBoot) (lib.mkForce true) (lib.mkForce false);
    -      };
    -      lanzaboote = lib.mkIf (!config.swarselsystems.initialSetup && config.swarselsystems.isSecureBoot) {
    -        enable = true;
    -        pkiBundle = "/var/lib/sbctl";
    -        configurationLimit = 6;
    -      };
    +  options.swarselsystems.modules.autologin = lib.mkEnableOption "optional autologin settings";
    +  config = lib.mkIf config.swarselsystems.modules.autologin {
    +    services = {
    +      getty.autologinUser = mainUser;
    +      greetd.settings.initial_session.user = mainUser;
         };
       };
     }
    @@ -9441,11 +6735,11 @@ This dynamically uses systemd boot or Lanzaboote depending on `config.swarselsys
     
    -

    3.3.2. Server

    +

    3.2.3. Server

    -
    3.3.2.1. Imports
    +
    3.2.3.1. Imports

    First, we enable the use of home-manager as a NixoS module. @@ -9460,30 +6754,19 @@ Also, the system state version is set here. No need to touch it.

    -
    { self, lib, ... }:
    +
    { lib, ... }:
     let
       importNames = lib.swarselsystems.readNix "modules/nixos/server";
    -  modulesPath = "${self}/modules";
     in
     {
    -  imports = lib.swarselsystems.mkImports importNames "modules/nixos/server" ++ [
    -    "${modulesPath}/nixos/common/settings.nix"
    -    "${modulesPath}/nixos/common/home-manager.nix"
    -    "${modulesPath}/nixos/common/home-manager-extra.nix"
    -    "${modulesPath}/nixos/common/xserver.nix"
    -    "${modulesPath}/nixos/common/time.nix"
    -    "${modulesPath}/nixos/common/users.nix"
    -    "${modulesPath}/nixos/common/nix-ld.nix"
    -    "${modulesPath}/nixos/common/sharedsetup.nix"
    -    "${modulesPath}/home/common/sharedsetup.nix"
    -  ];
    +  imports = lib.swarselsystems.mkImports importNames "modules/nixos/server";
     }
     
    -
    3.3.2.2. General NixOS Server settings
    +
    3.2.3.2. General NixOS Server settings

    Here we just define some aliases for rebuilding the system, and we allow some insecure packages that are needed by some server derivations. It would be more elegant to define these in the respective module, but nixpkgs needs to be defined before we can evaluate modules within it, so this must be a top-level configuration. @@ -9532,7 +6815,7 @@ in

    -
    3.3.2.3. System Packages
    +
    3.2.3.3. System Packages
    { lib, config, pkgs, ... }:
    @@ -9557,30 +6840,14 @@ in
     
    -
    -
    3.3.2.4. sops
    -
    -
    -
    { config, lib, ... }:
    -{
    -  options.swarselsystems.modules.server.sops = lib.mkEnableOption "enable sops on server";
    -  config = lib.mkIf config.swarselsystems.modules.server.sops {
    -    sops = {
    -      age.sshKeyPaths = lib.mkDefault [ "/etc/ssh/sops" ];
    -      defaultSopsFile = lib.mkDefault "${config.swarselsystems.flakePath}/secrets/winters/secrets.yaml";
    -      validateSopsFiles = false;
    -    };
    -  };
    -}
    -
    -
    -
    -
    -
    3.3.2.5. nfs/samba (smb)
    +
    3.2.3.4. nfs/samba (smb)
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, globals, ... }:
    +let
    +  nfsUser = globals.user.name;
    +in
     {
       options.swarselsystems.modules.server.nfs = lib.mkEnableOption "enable nfs on server";
       config = lib.mkIf config.swarselsystems.modules.server.nfs {
    @@ -9611,7 +6878,7 @@ in
               path = "/Vault/Eternor";
               writable = "true";
               comment = "Eternor";
    -          "valid users" = "Swarsel";
    +          "valid users" = nfsUser;
             };
           };
     
    @@ -9636,10 +6903,14 @@ in
     
    -
    3.3.2.6. NGINX
    +
    3.2.3.5. NGINX
    { pkgs, lib, config, ... }:
    +let
    +  inherit (config.repo.secrets.common) dnsProvider;
    +  inherit (config.repo.secrets.common.mail) address3;
    +in
     {
       options.swarselsystems.modules.server.nginx = lib.mkEnableOption "enable nginx on server";
       config = lib.mkIf config.swarselsystems.modules.server.nginx {
    @@ -9659,8 +6930,8 @@ in
           acceptTerms = true;
           preliminarySelfsigned = false;
           defaults = {
    -        email = "mrswarsel@gmail.com";
    -        dnsProvider = "cloudflare";
    +        inherit dnsProvider;
    +        email = address3;
             environmentFile = "${config.sops.templates."certs.secret".path}";
           };
         };
    @@ -9681,7 +6952,7 @@ in
     
    -
    3.3.2.7. ssh
    +
    3.2.3.6. ssh

    Here I am forcing startWhenNeeded to false so that the value will not be set to true in containers = this would be a problem because it would delay ssh host key generation. @@ -9725,49 +6996,49 @@ Here I am forcing startWhenNeeded to false so that the value will n

    -
    3.3.2.8. kavita
    +
    3.2.3.7. kavita
    { self, lib, config, pkgs, ... }:
     let
    +  servicePort = 8080;
       serviceName = "kavita";
       serviceUser = "kavita";
       serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    -  servicePort = 8080;
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
         environment.systemPackages = with pkgs; [
           calibre
         ];
     
    -    users.users."${serviceUser}" = {
    +    users.users.${serviceUser} = {
           extraGroups = [ "users" ];
         };
     
         sops.secrets.kavita = { owner = serviceUser; };
     
    -    networking.firewall.allowedTCPPorts = [ 8080 ];
    +    networking.firewall.allowedTCPPorts = [ servicePort ];
     
    -    topology.self.services.kavita = {
    +    topology.self.services.${serviceName} = {
           name = "Kavita";
           info = "https://${serviceDomain}";
    -      icon = "${self}/topology/images/kavita.png";
    +      icon = "${self}/files/topology-images/${serviceName}.png";
         };
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services.kavita = {
    +    services.${serviceName} = {
           enable = true;
           user = serviceUser;
           settings.Port = servicePort;
           tokenKeyFile = config.sops.secrets.kavita.path;
    -      dataDir = "/Vault/data/kavita";
    +      dataDir = "/Vault/data/${serviceName}";
         };
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -9796,20 +7067,20 @@ in
     
    -
    3.3.2.9. jellyfin
    +
    3.2.3.8. jellyfin
    { pkgs, lib, config, ... }:
     let
    -  serviceDomain = "screen.swarsel.win";
       servicePort = 8096;
       serviceName = "jellyfin";
       serviceUser = "jellyfin";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    -    users.users."${serviceUser}" = {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
    +    users.users.${serviceUser} = {
           extraGroups = [ "video" "render" "users" ];
         };
         nixpkgs.config.packageOverrides = pkgs: {
    @@ -9828,7 +7099,7 @@ in
         topology.self.services.${serviceName}.info = "https://${serviceDomain}";
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services.jellyfin = {
    +    services.${serviceName} = {
           enable = true;
           user = serviceUser;
           openFirewall = true; # this works only for the default ports
    @@ -9836,7 +7107,7 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -9866,20 +7137,20 @@ in
     
    -
    3.3.2.10. navidrome
    +
    3.2.3.9. navidrome
    { pkgs, config, lib, ... }:
     let
    -  serviceDomain = "sound.swarsel.win";
       servicePort = 4040;
       serviceName = "navidrome";
       serviceUser = "navidrome";
       serviceGroup = serviceUser;
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
         environment.systemPackages = with pkgs; [
           pciutils
           alsa-utils
    @@ -9888,13 +7159,13 @@ in
     
         users = {
           groups = {
    -        "${serviceGroup}" = {
    +        ${serviceGroup} = {
               gid = 61593;
             };
           };
     
           users = {
    -        "${serviceUser}" = {
    +        ${serviceUser} = {
               isSystemUser = true;
               uid = 61593;
               group = serviceGroup;
    @@ -9907,11 +7178,11 @@ in
           enableAllFirmware = lib.mkForce true;
         };
     
    -    networking.firewall.allowedTCPPorts = [ 4040 ];
    +    networking.firewall.allowedTCPPorts = [ servicePort ];
     
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services.navidrome = {
    +    services.${serviceName} = {
           enable = true;
           openFirewall = true;
           settings = {
    @@ -9953,7 +7224,7 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -9979,19 +7250,19 @@ in
                 in
                 {
                   "/" = {
    -                proxyPass = "http://navidrome";
    +                proxyPass = "http://${serviceName}";
                     proxyWebsockets = true;
                     inherit extraConfig;
                   };
                   "/share" = {
    -                proxyPass = "http://navidrome";
    +                proxyPass = "http://${serviceName}";
                     proxyWebsockets = true;
                     setOauth2Headers = false;
                     bypassAuth = true;
                     inherit extraConfig;
                   };
                   "/rest" = {
    -                proxyPass = "http://navidrome";
    +                proxyPass = "http://${serviceName}";
                     proxyWebsockets = true;
                     setOauth2Headers = false;
                     bypassAuth = true;
    @@ -10010,7 +7281,7 @@ in
     
    -
    3.3.2.11. spotifyd
    +
    3.2.3.10. spotifyd
    { lib, config, ... }:
    @@ -10021,13 +7292,13 @@ let
       serviceGroup = serviceUser;
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    -    users.groups."${serviceGroup}" = {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
    +    users.groups.${serviceGroup} = {
           gid = 65136;
         };
     
    -    users.users."${serviceUser}" = {
    +    users.users.${serviceUser} = {
           isSystemUser = true;
           uid = 65136;
           group = serviceGroup;
    @@ -10059,29 +7330,35 @@ in
     
    -
    3.3.2.12. mpd
    +
    3.2.3.11. mpd
    { self, lib, config, pkgs, ... }:
    +let
    +  servicePort = 3254;
    +  serviceUser = "mpd";
    +  serviceGroup = serviceUser;
    +  serviceName = "mpd";
    +in
     {
    -  options.swarselsystems.modules.server.mpd = lib.mkEnableOption "enable mpd on server";
    -  config = lib.mkIf config.swarselsystems.modules.server.mpd {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
         users = {
           groups = {
             mpd = { };
           };
     
           users = {
    -        mpd = {
    +        ${serviceUser} = {
               isSystemUser = true;
    -          group = "mpd";
    +          group = serviceGroup;
               extraGroups = [ "audio" "utmp" ];
             };
           };
         };
     
         sops = {
    -      secrets.mpdpass = { owner = "mpd"; };
    +      secrets.mpdpass = { owner = serviceUser; group = serviceGroup; mode = "0440"; };
         };
     
         environment.systemPackages = with pkgs; [
    @@ -10090,19 +7367,19 @@ in
           mpv
         ];
     
    -    topology.self.services.mpd = {
    -      name = "MPD";
    -      info = "http://localhost:3254";
    -      icon = "${self}/topology/images/mpd.png";
    +    topology.self.services.${serviceName} = {
    +      name = lib.toUpper serviceName;
    +      info = "http://localhost:${builtins.toString servicePort}";
    +      icon = "${self}/files/topology-images/${serviceName}.png";
         };
     
    -    services.mpd = {
    +    services.${serviceName} = {
           enable = true;
           musicDirectory = "/media";
    -      user = "mpd";
    -      group = "mpd";
    +      user = serviceUser;
    +      group = serviceGroup;
           network = {
    -        port = 3254;
    +        port = servicePort;
             listenAddress = "any";
           };
           credentials = [
    @@ -10125,7 +7402,7 @@ in
     
    -
    3.3.2.13. pipewire
    +
    3.2.3.12. pipewire
    { lib, config, ... }:
    @@ -10153,7 +7430,7 @@ in
     
    -
    3.3.2.14. postgresql
    +
    3.2.3.13. postgresql
    { config, lib, pkgs, ... }:
    @@ -10162,13 +7439,13 @@ let
       postgresVersion = 14;
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
         services = {
    -      postgresql = {
    +      ${serviceName} = {
             enable = true;
             package = pkgs."postgresql_${builtins.toString postgresVersion}";
    -        dataDir = "/Vault/data/postgresql/${builtins.toString postgresVersion}";
    +        dataDir = "/Vault/data/${serviceName}/${builtins.toString postgresVersion}";
           };
         };
       };
    @@ -10178,22 +7455,23 @@ in
     
    -
    3.3.2.15. matrix
    +
    3.2.3.14. matrix
    { lib, config, pkgs, ... }:
     let
    -  matrixDomain = "swatrix.swarsel.win";
    +  servicePort = 8008;
       serviceName = "matrix";
    -  synapsePort = 8008;
    -  synapseUser = "matrix-synapse";
    +  serviceDomain = config.repo.secrets.common.services.domains.matrix;
    +  serviceUser = "matrix-synapse";
    +
    +  federationPort = 8448;
       whatsappPort = 29318;
       telegramPort = 29317;
       signalPort = 29328;
    -
    -  baseUrl = "https://${matrixDomain}";
    +  baseUrl = "https://${serviceDomain}";
       clientConfig."m.homeserver".base_url = baseUrl;
    -  serverConfig."m.server" = "${matrixDomain}:443";
    +  serverConfig."m.server" = "${serviceDomain}:443";
       mkWellKnown = data: ''
         default_type application/json;
         add_header Access-Control-Allow-Origin *;
    @@ -10201,8 +7479,8 @@ let
       '';
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
         environment.systemPackages = with pkgs; [
           matrix-synapse
           lottieconverter
    @@ -10211,24 +7489,24 @@ in
     
         sops = {
           secrets = {
    -        matrixsharedsecret = { owner = synapseUser; };
    -        mautrixtelegram_as = { owner = synapseUser; };
    -        mautrixtelegram_hs = { owner = synapseUser; };
    -        mautrixtelegram_api_id = { owner = synapseUser; };
    -        mautrixtelegram_api_hash = { owner = synapseUser; };
    +        matrixsharedsecret = { owner = serviceUser; };
    +        mautrixtelegram_as = { owner = serviceUser; };
    +        mautrixtelegram_hs = { owner = serviceUser; };
    +        mautrixtelegram_api_id = { owner = serviceUser; };
    +        mautrixtelegram_api_hash = { owner = serviceUser; };
           };
           templates = {
             "matrix_user_register.sh".content = ''
    -          register_new_matrix_user -k ${config.sops.placeholder.matrixsharedsecret} http://localhost:${builtins.toString synapsePort}
    +          register_new_matrix_user -k ${config.sops.placeholder.matrixsharedsecret} http://localhost:${builtins.toString servicePort}
             '';
             matrixshared = {
    -          owner = synapseUser;
    +          owner = serviceUser;
               content = ''
                 registration_shared_secret: ${config.sops.placeholder.matrixsharedsecret}
               '';
             };
             mautrixtelegram = {
    -          owner = synapseUser;
    +          owner = serviceUser;
               content = ''
                 MAUTRIX_TELEGRAM_APPSERVICE_AS_TOKEN=${config.sops.placeholder.mautrixtelegram_as}
                 MAUTRIX_TELEGRAM_APPSERVICE_HS_TOKEN=${config.sops.placeholder.mautrixtelegram_hs}
    @@ -10239,7 +7517,7 @@ in
           };
         };
     
    -    networking.firewall.allowedTCPPorts = [ 8008 8448 ];
    +    networking.firewall.allowedTCPPorts = [ servicePort federationPort ];
     
         systemd = {
           timers."restart-bridges" = {
    @@ -10270,7 +7548,7 @@ in
           };
         };
     
    -    globals.services.${serviceName}.domain = matrixDomain;
    +    globals.services.${serviceName}.domain = serviceDomain;
     
         services = {
           postgresql = {
    @@ -10303,20 +7581,21 @@ in
             enable = true;
             dataDir = "/Vault/data/matrix-synapse";
             settings = {
    -          app_service_config_files = let
    -            inherit (config.services.matrix-synapse) dataDir;
    -          in
    +          app_service_config_files =
    +            let
    +              inherit (config.services.matrix-synapse) dataDir;
    +            in
                 [
    -            "${dataDir}/telegram-registration.yaml"
    -            "${dataDir}/whatsapp-registration.yaml"
    -            "${dataDir}/signal-registration.yaml"
    -            "${dataDir}/doublepuppet.yaml"
    -          ];
    -          server_name = matrixDomain;
    -          public_baseurl = "https://${matrixDomain}";
    +              "${dataDir}/telegram-registration.yaml"
    +              "${dataDir}/whatsapp-registration.yaml"
    +              "${dataDir}/signal-registration.yaml"
    +              "${dataDir}/doublepuppet.yaml"
    +            ];
    +          server_name = serviceDomain;
    +          public_baseurl = "https://${serviceDomain}";
               listeners = [
                 {
    -              port = synapsePort;
    +              port = servicePort;
                   bind_addresses = [
                     "0.0.0.0"
                     # "::1"
    @@ -10344,8 +7623,8 @@ in
             registerToSynapse = false;
             settings = {
               homeserver = {
    -            address = "http://localhost:${builtins.toString synapsePort}";
    -            domain = matrixDomain;
    +            address = "http://localhost:${builtins.toString servicePort}";
    +            domain = serviceDomain;
               };
               appservice = {
                 address = "http://localhost:${builtins.toString telegramPort}";
    @@ -10370,7 +7649,7 @@ in
                 telegram_link_preview = true;
                 permissions = {
                   "*" = "relaybot";
    -              "@swarsel:${matrixDomain}" = "admin";
    +              "@swarsel:${serviceDomain}" = "admin";
                 };
                 animated_sticker = {
                   target = "gif";
    @@ -10390,8 +7669,8 @@ in
             registerToSynapse = false;
             settings = {
               homeserver = {
    -            address = "http://localhost:${builtins.toString synapsePort}";
    -            domain = matrixDomain;
    +            address = "http://localhost:${builtins.toString servicePort}";
    +            domain = serviceDomain;
               };
               appservice = {
                 address = "http://localhost:${builtins.toString whatsappPort}";
    @@ -10416,7 +7695,7 @@ in
                   };
                 };
                 login_shared_secret_map = {
    -              matrixDomain = "as_token:doublepuppet";
    +              ${serviceDomain} = "as_token:doublepuppet";
                 };
                 sync_manual_marked_unread = true;
                 send_presence_on_typing = true;
    @@ -10426,7 +7705,7 @@ in
                 extev_polls = true;
                 permissions = {
                   "*" = "relay";
    -              "@swarsel:${matrixDomain}" = "admin";
    +              "@swarsel:${serviceDomain}" = "admin";
                 };
               };
             };
    @@ -10437,8 +7716,8 @@ in
             registerToSynapse = false;
             settings = {
               homeserver = {
    -            address = "http://localhost:${builtins.toString synapsePort}";
    -            domain = matrixDomain;
    +            address = "http://localhost:${builtins.toString servicePort}";
    +            domain = serviceDomain;
               };
               appservice = {
                 address = "http://localhost:${builtins.toString signalPort}";
    @@ -10452,12 +7731,12 @@ in
               bridge = {
                 displayname_template = "{{or .ContactName .ProfileName .PhoneNumber}} (Signal)";
                 login_shared_secret_map = {
    -              matrixDomain = "as_token:doublepuppet";
    +              ${serviceDomain} = "as_token:doublepuppet";
                 };
                 caption_in_message = true;
                 permissions = {
                   "*" = "relay";
    -              "@swarsel:${matrixDomain}" = "admin";
    +              "@swarsel:${serviceDomain}" = "admin";
                 };
               };
             };
    @@ -10470,14 +7749,14 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
    -            "192.168.1.2:${builtins.toString synapsePort}" = { };
    +            "192.168.1.2:${builtins.toString servicePort}" = { };
               };
             };
           };
           virtualHosts = {
    -        "${matrixDomain}" = {
    +        "${serviceDomain}" = {
               enableACME = true;
               forceSSL = true;
               acmeRoot = null;
    @@ -10529,19 +7808,22 @@ in
     
    -
    3.3.2.16. nextcloud
    +
    3.2.3.15. nextcloud
    { pkgs, lib, config, ... }:
     let
    -  serviceDomain = "stash.swarsel.win";
    +  inherit (config.repo.secrets.local.nextcloud) adminuser;
    +
    +  servicePort = 80;
       serviceUser = "nextcloud";
       serviceGroup = serviceUser;
       serviceName = "nextcloud";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         sops.secrets = {
           nextcloudadminpass = {
    @@ -10560,7 +7842,7 @@ in
         globals.services.${serviceName}.domain = serviceDomain;
     
         services = {
    -      nextcloud = {
    +      ${serviceName} = {
             enable = true;
             settings = {
               trusted_proxies = [ "0.0.0.0" ];
    @@ -10568,8 +7850,8 @@ in
             };
             package = pkgs.nextcloud31;
             hostName = serviceDomain;
    -        home = "/Vault/data/nextcloud";
    -        datadir = "/Vault/data/nextcloud";
    +        home = "/Vault/data/${serviceName}";
    +        datadir = "/Vault/data/${serviceName}";
             https = true;
             configureRedis = true;
             maxUploadSize = "4G";
    @@ -10578,7 +7860,7 @@ in
             };
             extraAppsEnable = true;
             config = {
    -          adminuser = "admin";
    +          inherit adminuser;
               adminpassFile = config.sops.secrets.nextcloudadminpass.path;
               dbtype = "sqlite";
             };
    @@ -10587,9 +7869,9 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
    -            "192.168.1.2:80" = { };
    +            "192.168.1.2:${builtins.toString servicePort}" = { };
               };
             };
           };
    @@ -10613,28 +7895,28 @@ in
     
    -
    3.3.2.17. immich
    +
    3.2.3.16. immich
    { lib, config, globals, ... }:
     let
    -  serviceDomain = "shots.swarsel.win";
       servicePort = 3001;
       serviceUser = "immich";
       serviceName = "immich";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
    -    users.users."${serviceUser}" = {
    +    users.users.${serviceUser} = {
           extraGroups = [ "video" "render" "users" ];
         };
     
         topology.self.services.${serviceName}.info = "https://${serviceDomain}";
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services.immich = {
    +    services.${serviceName} = {
           enable = true;
           host = "0.0.0.0";
           port = servicePort;
    @@ -10649,7 +7931,7 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -10689,7 +7971,7 @@ in
     
    -
    3.3.2.18. paperless (tika, gotenberg)
    +
    3.2.3.17. paperless (tika, gotenberg)

    This is my personal document management system. It automatically pulls documents from several sources, the only manual step for physical documents is to put them in my scanner and use email delivery. @@ -10700,19 +7982,23 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of

    -
    { lib, pkgs, config, ... }:
    +
    { lib, pkgs, config, globals, ... }:
     let
    -  serviceDomain = "scan.swarsel.win";
       servicePort = 28981;
       serviceUser = "paperless";
       serviceGroup = serviceUser;
       serviceName = "paperless";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
    +  tikaPort = 9998;
    +  gotenbergPort = 3002;
    +  kanidmDomain = globals.services.kanidm.domain;
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
    -    users.users."${serviceUser}" = {
    +    users.users.${serviceUser} = {
           extraGroups = [ "users" ];
         };
     
    @@ -10730,25 +8016,25 @@ in
         globals.services.${serviceName}.domain = serviceDomain;
     
         services = {
    -      paperless = {
    +      ${serviceName} = {
             enable = true;
             mediaDir = "/Vault/Eternor/Paperless";
    -        dataDir = "/Vault/data/paperless";
    +        dataDir = "/Vault/data/${serviceName}";
             user = serviceUser;
             port = servicePort;
             passwordFile = config.sops.secrets.paperless_admin.path;
             address = "0.0.0.0";
             settings = {
               PAPERLESS_OCR_LANGUAGE = "deu+eng";
    -          PAPERLESS_URL = "https://scan.swarsel.win";
    +          PAPERLESS_URL = "https://${serviceDomain}";
               PAPERLESS_OCR_USER_ARGS = builtins.toJSON {
                 optimize = 1;
                 invalidate_digital_signatures = true;
                 pdfa_image_compression = "lossless";
               };
               PAPERLESS_TIKA_ENABLED = "true";
    -          PAPERLESS_TIKA_ENDPOINT = "http://localhost:9998";
    -          PAPERLESS_TIKA_GOTENBERG_ENDPOINT = "http://localhost:3002";
    +          PAPERLESS_TIKA_ENDPOINT = "http://localhost:${builtins.toString tikaPort}";
    +          PAPERLESS_TIKA_GOTENBERG_ENDPOINT = "http://localhost:${builtins.toString gotenbergPort}";
               PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect";
               PAPERLESS_SOCIALACCOUNT_PROVIDERS = builtins.toJSON {
                 openid_connect = {
    @@ -10760,7 +8046,7 @@ in
                       client_id = "paperless";
                       # secret will be added by paperless-web.service (see below)
                       #secret = "";
    -                  settings.server_url = "https://sso.swarsel.win/oauth2/openid/${client_id}/.well-known/openid-configuration";
    +                  settings.server_url = "https://${kanidmDomain}/oauth2/openid/${client_id}/.well-known/openid-configuration";
                     }
                   ];
                 };
    @@ -10770,7 +8056,7 @@ in
     
           tika = {
             enable = true;
    -        port = 9998;
    +        port = tikaPort;
             openFirewall = false;
             listenAddress = "127.0.0.1";
             enableOcr = true;
    @@ -10779,7 +8065,7 @@ in
           gotenberg = {
             enable = true;
             package = pkgs.stable.gotenberg;
    -        port = 3002;
    +        port = gotenbergPort;
             bindIP = "127.0.0.1";
             timeout = "600s";
             chromium.package = pkgs.stable.chromium;
    @@ -10799,7 +8085,7 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -10833,12 +8119,14 @@ in
     
    -
    3.3.2.19. transmission
    +
    3.2.3.18. transmission
    { self, pkgs, lib, config, ... }:
     let
    -  serviceDomain = "store.swarsel.win";
    +  serviceName = "transmission";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
       lidarrUser = "lidarr";
       lidarrGroup = lidarrUser;
       lidarrPort = 8686;
    @@ -10856,8 +8144,8 @@ let
       prowlarrPort = 9696;
     in
     {
    -  options.swarselsystems.modules.server.transmission = lib.mkEnableOption "enable transmission and friends on server";
    -  config = lib.mkIf config.swarselsystems.modules.server.transmission {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} and friends on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         # this user/group section is probably unneeded
         users = {
    @@ -10916,7 +8204,7 @@ in
           readarr = {
             name = "Readarr";
             info = "https://${serviceDomain}/readarr";
    -        icon = "${self}/topology/images/readarr.png";
    +        icon = "${self}/files/topology-images/readarr.png";
           };
           sonarr.info = "https://${serviceDomain}/sonarr";
           lidarr.info = "https://${serviceDomain}/lidarr";
    @@ -11020,40 +8308,43 @@ in
     
    -
    3.3.2.20. syncthing
    +
    3.2.3.19. syncthing
    { lib, config, ... }:
     let
       inherit (config.repo.secrets.common) workHostName;
    -  serviceDomain = "storync.swarsel.win";
    +
       servicePort = 8384;
       serviceUser = "syncthing";
       serviceGroup = serviceUser;
       serviceName = "syncthing";
    +  serviceDomain = config.repo.secrets.common.services.domains.syncthing1;
    +
    +  cfg = config.services.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
    -    users.users."${serviceUser}" = {
    +    users.users.${serviceUser} = {
           extraGroups = [ "users" ];
           group = serviceGroup;
           isSystemUser = true;
         };
     
    -    users.groups."${serviceGroup}" = { };
    +    users.groups.${serviceGroup} = { };
     
         networking.firewall.allowedTCPPorts = [ servicePort ];
     
    -    globals.services.${serviceName}.domain = serviceDomain;
    +    globals.services."${serviceName}-${config.networking.hostName}".domain = serviceDomain;
     
    -    services.syncthing = {
    +    services.${serviceName} = rec {
           enable = true;
           user = serviceUser;
           group = serviceGroup;
    -      dataDir = "/Vault/data/syncthing";
    -      configDir = "/Vault/data/syncthing/.config/syncthing";
    +      dataDir = "/Vault/data/${serviceName}";
    +      configDir = "${cfg.dataDir}/.config/${serviceName}";
           guiAddress = "0.0.0.0:${builtins.toString servicePort}";
           openDefaultPorts = true; # opens ports TCP/UDP 22000 and UDP 21027 for discovery
           relay.enable = false;
    @@ -11075,14 +8366,14 @@ in
             };
             folders = {
               "Default Folder" = lib.mkForce {
    -            path = "/Vault/data/syncthing/Sync";
    +            path = "${cfg.dataDir}/Sync";
                 type = "receiveonly";
                 versioning = null;
                 devices = [ "sync@oracle" "magicant" "${workHostName}" "moonside@oracle" ];
                 id = "default";
               };
               "Obsidian" = {
    -            path = "/Vault/data/syncthing/Obsidian";
    +            path = "${cfg.dataDir}/Obsidian";
                 type = "receiveonly";
                 versioning = {
                   type = "simple";
    @@ -11092,7 +8383,7 @@ in
                 id = "yjvni-9eaa7";
               };
               "Org" = {
    -            path = "/Vault/data/syncthing/Org";
    +            path = "${cfg.dataDir}/Org";
                 type = "receiveonly";
                 versioning = {
                   type = "simple";
    @@ -11102,7 +8393,7 @@ in
                 id = "a7xnl-zjj3d";
               };
               "Vpn" = {
    -            path = "/Vault/data/syncthing/Vpn";
    +            path = "${cfg.dataDir}/Vpn";
                 type = "receiveonly";
                 versioning = {
                   type = "simple";
    @@ -11112,7 +8403,7 @@ in
                 id = "hgp9s-fyq3p";
               };
               # "Documents" = {
    -          #   path = "/Vault/data/syncthing/Documents";
    +          #   path = "${cfg.dataDir}/Documents";
               #   type = "receiveonly";
               #   versioning = {
               #     type = "simple";
    @@ -11127,7 +8418,7 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -11156,7 +8447,7 @@ in
     
    -
    3.3.2.21. restic
    +
    3.2.3.20. restic

    This manages backups for my pictures and obsidian files. @@ -11222,37 +8513,42 @@ in

    -
    3.3.2.22. monitoring (Grafana)
    +
    3.2.3.21. monitoring (Grafana, Prometheus)

    This section exposes several metrics that I use to check the health of my server. I need to expand on the exporters section at some point, but for now I have everything I need.

    -
    { self, lib, config, ... }:
    +
    { self, lib, config, globals, ... }:
     let
    -  serviceDomain = "status.swarsel.win";
    +
       servicePort = 3000;
       serviceUser = "grafana";
    -  prometheusUser = "prometheus";
       serviceGroup = serviceUser;
    +  serviceName = "grafana";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
    +  prometheusPort = 9090;
    +  prometheusUser = "prometheus";
       prometheusGroup = prometheusUser;
    -  moduleName = "monitoring";
    +  nextcloudUser = config.repo.secrets.local.nextcloud.adminuser;
       grafanaUpstream = "grafana";
       prometheusUpstream = "prometheus";
    -  prometheusPort = 9090;
       prometheusWebRoot = "prometheus";
    +  kanidmDomain = globals.services.kanidm.domain;
     in
     {
    -  options.swarselsystems.modules.server."${moduleName}" = lib.mkEnableOption "enable ${moduleName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${moduleName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         sops = {
           secrets = {
             grafanaadminpass = { owner = serviceUser; group = serviceGroup; mode = "0440"; };
             prometheusadminpass = { owner = serviceUser; group = serviceGroup; mode = "0440"; };
             kanidm-grafana-client = { owner = serviceUser; group = serviceGroup; mode = "0440"; };
    -        prometheus-admin-hash = { owner = prometheusUser; group = prometheusGroup; mode = "0440"; };
    +        prometheus-admin-hash = { sopsFile = self + /secrets/winters/secrets2.yaml; owner = prometheusUser; group = prometheusGroup; mode = "0440"; };
    +
           };
           templates = {
             "web-config" = {
    @@ -11273,7 +8569,7 @@ in
               extraGroups = [ "nextcloud" ];
             };
     
    -        "${serviceUser}" = {
    +        ${serviceUser} = {
               extraGroups = [ "users" ];
             };
           };
    @@ -11282,12 +8578,12 @@ in
         networking.firewall.allowedTCPPorts = [ servicePort prometheusPort ];
     
         topology.self.services.prometheus.info = "https://${serviceDomain}/${prometheusWebRoot}";
    -    globals.services.${moduleName}.domain = serviceDomain;
    +    globals.services.${serviceName}.domain = serviceDomain;
     
         services = {
    -      grafana = {
    +      ${serviceName} = {
             enable = true;
    -        dataDir = "/Vault/data/grafana";
    +        dataDir = "/Vault/data/${serviceName}";
             provision = {
               enable = true;
               datasources.settings = {
    @@ -11344,9 +8640,9 @@ in
                 client_secret = "$__file{${config.sops.secrets.kanidm-grafana-client.path}}";
                 scopes = "openid email profile";
                 login_attribute_path = "preferred_username";
    -            auth_url = "https://sso.swarsel.win/ui/oauth2";
    -            token_url = "https://sso.swarsel.win/oauth2/token";
    -            api_url = "https://sso.swarsel.win/oauth2/openid/grafana/userinfo";
    +            auth_url = "https://${kanidmDomain}/ui/oauth2";
    +            token_url = "https://${kanidmDomain}/oauth2/token";
    +            api_url = "https://${kanidmDomain}/oauth2/openid/grafana/userinfo";
                 use_pkce = true;
                 use_refresh_token = true;
                 # Allow mapping oauth2 roles to server admin
    @@ -11358,7 +8654,7 @@ in
     
           prometheus = {
             enable = true;
    -        webExternalUrl = "https://status.swarsel.win/${prometheusWebRoot}";
    +        webExternalUrl = "https://${serviceDomain}/${prometheusWebRoot}";
             port = prometheusPort;
             listenAddress = "0.0.0.0";
             globalConfig = {
    @@ -11418,8 +8714,8 @@ in
               nextcloud = lib.mkIf config.swarselsystems.modules.server.nextcloud {
                 enable = true;
                 port = 9205;
    -            url = "https://stash.swarsel.win/ocs/v2.php/apps/serverinfo/api/v1/info";
    -            username = "admin";
    +            url = "https://${serviceDomain}/ocs/v2.php/apps/serverinfo/api/v1/info";
    +            username = nextcloudUser;
                 passwordFile = config.sops.secrets.nextcloudadminpass.path;
               };
             };
    @@ -11470,7 +8766,7 @@ in
     
    -
    3.3.2.23. Jenkins
    +
    3.2.3.22. Jenkins

    This is a WIP Jenkins instance. It is used to automatically build a new system when pushes to the main repository are detected. I have turned this service off for now however, as I actually prefer to start my builds manually. @@ -11479,26 +8775,26 @@ This is a WIP Jenkins instance. It is used to automatically build a new system w

    { pkgs, lib, config, ... }:
     let
    -  serviceDomain = "servant.swarsel.win";
       servicePort = 8088;
       serviceName = "jenkins";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         services.jenkins = {
           enable = true;
           withCLI = true;
    -      port = 8088;
    +      port = servicePort;
           packages = [ pkgs.stdenv pkgs.git pkgs.jdk17 config.programs.ssh.package pkgs.nix ];
           listenAddress = "0.0.0.0";
    -      home = "/Vault/apps/jenkins";
    +      home = "/Vault/apps/${serviceName}";
         };
     
         services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -11528,7 +8824,7 @@ in
     
    -
    3.3.2.24. Emacs elfeed (RSS Server)
    +
    3.2.3.23. Emacs elfeed (RSS Server)

    This was an approach of hosting an RSS server from within emacs. That would have been useful as it would have allowed me to allow my feeds from any device. However, it proved impossible to do bidirectional syncing, so I abandoned this configuration in favor of FreshRSS. @@ -11536,13 +8832,17 @@ This was an approach of hosting an RSS server from within emacs. That would have

    { lib, config, ... }:
    +let
    +  serviceName = "emacs";
    +  servicePort = 9812;
    +in
     {
    -  options.swarselsystems.modules.server.emacs = lib.mkEnableOption "enable emacs server on server";
    -  config = lib.mkIf config.swarselsystems.modules.server.emacs {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} server on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
    -    networking.firewall.allowedTCPPorts = [ 9812 ];
    +    networking.firewall.allowedTCPPorts = [ servicePort ];
     
    -    services.emacs = {
    +    services.${serviceName} = {
           enable = true;
           install = true;
           startWithGraphical = false;
    @@ -11556,18 +8856,18 @@ This was an approach of hosting an RSS server from within emacs. That would have
     
    -
    3.3.2.25. FreshRSS
    +
    3.2.3.24. FreshRSS

    FreshRSS is a more 'classical' RSS aggregator that I can just host as a distinct service. This also has its upsides because I jave more control over the state this way.

    -It serves both a Greader API at https://signpost.swarsel.win/api/greader.php, as well as a Fever API at https://signpost.swarsel.win/api/fever.php. +It serves both a Greader API at https://${servicename}/api/greader.php, as well as a Fever API at https://${servicename}/api/fever.php.

    -I am using this with CapyReader on my phone, set it up as a FreshRSS account with Server URL =https://signpost.swarsel.win/api/greader.php +I am using this with CapyReader on my phone, set it up as a FreshRSS account with Server URL =https://${servicename}/api/greader.php

    @@ -11577,22 +8877,25 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with

    { self, lib, config, ... }:
     let
    +  inherit (config.repo.secrets.local.freshrss) defaultUser;
    +
    +  servicePort = 80;
       serviceName = "freshrss";
    -  serviceDomain = "signpost.swarsel.win";
       serviceUser = "freshrss";
       serviceGroup = serviceName;
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server.freshrss = lib.mkEnableOption "enable freshrss on server";
    -  config = lib.mkIf config.swarselsystems.modules.server.freshrss {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
    -    users.users."${serviceUser}" = {
    +    users.users.${serviceUser} = {
           extraGroups = [ "users" ];
           group = serviceGroup;
           isSystemUser = true;
         };
     
    -    users.groups."${serviceGroup}" = { };
    +    users.groups.${serviceGroup} = { };
     
         sops = {
           secrets = {
    @@ -11606,7 +8909,7 @@ in
           #       content = ''
           #         DATA_PATH=${config.services.freshrss.dataDir}
           #         OIDC_ENABLED=1
    -      #         OIDC_PROVIDER_METADATA_URL=https://sso.swarsel.win/.well-known/openid-configuration
    +      #         OIDC_PROVIDER_METADATA_URL=https://${kanidmDomain}/.well-known/openid-configuration
           #         OIDC_CLIENT_ID=freshrss
           #         OIDC_CLIENT_SECRET=${config.sops.placeholder.kanidm-freshrss-client}
           #         OIDC_CLIENT_CRYPTO_KEY=${config.sops.placeholder.oidc-crypto-key}
    @@ -11624,18 +8927,18 @@ in
         topology.self.services.${serviceName} = {
           name = "FreshRSS";
           info = "https://${serviceDomain}";
    -      icon = "${self}/topology/images/freshrss.png";
    +      icon = "${self}/files/topology-images/${serviceName}.png";
         };
     
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services.freshrss = {
    +    services.${serviceName} = {
    +      inherit defaultUser;
           enable = true;
           virtualHost = serviceDomain;
           baseUrl = "https://${serviceDomain}";
           authType = "form";
           dataDir = "/Vault/data/tt-rss";
    -      defaultUser = "Swarsel";
           passwordFile = config.sops.secrets.fresh.path;
         };
     
    @@ -11645,9 +8948,9 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
    -            "192.168.1.2:80" = { };
    +            "192.168.1.2:${builtins.toString servicePort}" = { };
               };
             };
           };
    @@ -11678,29 +8981,31 @@ in
     
    -
    3.3.2.26. forgejo (git server)
    +
    3.2.3.25. forgejo (git server)
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, globals, ... }:
     let
    -  serviceDomain = "swagit.swarsel.win";
       servicePort = 3000;
       serviceUser = "forgejo";
       serviceGroup = serviceUser;
       serviceName = "forgejo";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
    +  kanidmDomain = globals.services.kanidm.domain;
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         networking.firewall.allowedTCPPorts = [ servicePort ];
     
    -    users.users."${serviceUser}" = {
    +    users.users.${serviceUser} = {
           group = serviceGroup;
           isSystemUser = true;
         };
     
    -    users.groups."${serviceGroup}" = { };
    +    users.groups.${serviceGroup} = { };
     
         sops.secrets = {
           kanidm-forgejo-client = { owner = serviceUser; group = serviceGroup; mode = "0440"; };
    @@ -11708,7 +9013,7 @@ in
     
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services.forgejo = {
    +    services.${serviceName} = {
           enable = true;
           user = serviceUser;
           group = serviceGroup;
    @@ -11750,13 +9055,13 @@ in
           };
         };
     
    -    systemd.services.forgejo = {
    +    systemd.services.${serviceName} = {
           serviceConfig.RestartSec = "60"; # Retry every minute
           preStart =
             let
               exe = lib.getExe config.services.forgejo.package;
               providerName = "kanidm";
    -          clientId = "forgejo";
    +          clientId = serviceName;
               args = lib.escapeShellArgs (
                 lib.concatLists [
                   [
    @@ -11773,7 +9078,7 @@ in
                   ]
                   [
                     "--auto-discover-url"
    -                "https://sso.swarsel.win/oauth2/openid/${clientId}/.well-known/openid-configuration"
    +                "https://${kanidmDomain}/oauth2/openid/${clientId}/.well-known/openid-configuration"
                   ]
                   [
                     "--scopes"
    @@ -11808,7 +9113,7 @@ in
     
         services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -11838,18 +9143,20 @@ in
     
    -
    3.3.2.27. Anki Sync Server
    +
    3.2.3.26. Anki Sync Server
    -
    { lib, config, ... }:
    +
    { self, lib, config, globals, ... }:
     let
    -  serviceDomain = "synki.swarsel.win";
       servicePort = 27701;
       serviceName = "ankisync";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
    +  ankiUser = globals.user.name;
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         networking.firewall.allowedTCPPorts = [ servicePort ];
     
    @@ -11857,6 +9164,7 @@ in
     
         topology.self.services.${serviceName} = {
           name = lib.mkForce "Anki Sync Server";
    +      icon = "${self}/files/topology-images/${serviceName}.png";
           info = "https://${serviceDomain}";
         };
     
    @@ -11869,7 +9177,7 @@ in
           openFirewall = true;
           users = [
             {
    -          username = "Swarsel";
    +          username = ankiUser;
               passwordFile = config.sops.secrets.swarsel.path;
             }
           ];
    @@ -11877,7 +9185,7 @@ in
     
         services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -11907,7 +9215,7 @@ in
     
    -
    3.3.2.28. kanidm
    +
    3.2.3.27. kanidm

    The forgejo configuration is a little broken and will show a 500 error when signing in through kanidm. However, when pressing back and refreshing the page, I am logged in. Currently I cannot be bothered to fix this. @@ -11919,30 +9227,37 @@ A stupid (but simple) way to get the originUrl is to simply set any

    -To get other URLs (token, etc.), use https://<kanidmdomain>/oauth2/openid/%3CclientID%3E/.well-known/oauth-authorization-server, e.g. https://sso.swarsel.win/oauth2/openid/nextcloud/.well-known/oauth-authorization-server, with clienID being the client name as specified in kanidm. +To get other URLs (token, etc.), use https://<kanidmdomain>/oauth2/openid/%3CclientID%3E/.well-known/oauth-authorization-server, e.g. https://<kanidmdomain>/oauth2/openid/nextcloud/.well-known/oauth-authorization-server, with clienID being the client name as specified in kanidm.

    { self, lib, pkgs, config, globals, ... }:
     let
       certsSopsFile = self + /secrets/certs/secrets.yaml;
    -  serviceDomain = "sso.swarsel.win";
    +
       servicePort = 8300;
       serviceUser = "kanidm";
       serviceGroup = serviceUser;
       serviceName = "kanidm";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
       oauth2ProxyDomain = globals.services.oauth2Proxy.domain;
    +  immichDomain = globals.services.immich.domain;
    +  paperlessDomain = globals.services.paperless.domain;
    +  forgejoDomain = globals.services.forgejo.domain;
    +  grafanaDomain = globals.services.grafana.domain;
    +  nextcloudDomain = globals.services.nextcloud.domain;
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
    -    users.users."${serviceUser}" = {
    +    users.users.${serviceUser} = {
           group = serviceGroup;
           isSystemUser = true;
         };
     
    -    users.groups."${serviceGroup}" = { };
    +    users.groups.${serviceGroup} = { };
     
         sops = {
           secrets = {
    @@ -11965,7 +9280,7 @@ in
         globals.services.${serviceName}.domain = serviceDomain;
     
         services = {
    -      kanidm = {
    +      ${serviceName} = {
             package = pkgs.kanidmWithSecretProvisioning;
             enableServer = true;
             serverSettings = {
    @@ -12010,12 +9325,12 @@ in
                   immich = {
                     displayName = "Immich";
                     originUrl = [
    -                  "https://shots.swarsel.win/auth/login"
    -                  "https://shots.swarsel.win/user-settings"
    +                  "https://${immichDomain}/auth/login"
    +                  "https://${immichDomain}/user-settings"
                       "app.immich:///oauth-callback"
    -                  "https://shots.swarsel.win/api/oauth/mobile-redirect"
    +                  "https://${immichDomain}/api/oauth/mobile-redirect"
                     ];
    -                originLanding = "https://shots.swarsel.win/";
    +                originLanding = "https://${immichDomain}/";
                     basicSecretFile = config.sops.secrets.kanidm-immich.path;
                     preferShortUsername = true;
                     enableLegacyCrypto = true; # can use RS256 / HS256, not ES256
    @@ -12027,8 +9342,8 @@ in
                   };
                   paperless = {
                     displayName = "Paperless";
    -                originUrl = "https://scan.swarsel.win/accounts/oidc/kanidm/login/callback/";
    -                originLanding = "https://scan.swarsel.win/";
    +                originUrl = "https://${paperlessDomain}/accounts/oidc/kanidm/login/callback/";
    +                originLanding = "https://${paperlessDomain}/";
                     basicSecretFile = config.sops.secrets.kanidm-paperless.path;
                     preferShortUsername = true;
                     scopeMaps."paperless.access" = [
    @@ -12039,8 +9354,8 @@ in
                   };
                   forgejo = {
                     displayName = "Forgejo";
    -                originUrl = "https://swagit.swarsel.win/user/oauth2/kanidm/callback";
    -                originLanding = "https://swagit.swarsel.win/";
    +                originUrl = "https://${forgejoDomain}/user/oauth2/kanidm/callback";
    +                originLanding = "https://${forgejoDomain}/";
                     basicSecretFile = config.sops.secrets.kanidm-forgejo.path;
                     scopeMaps."forgejo.access" = [
                       "openid"
    @@ -12058,8 +9373,8 @@ in
                   };
                   grafana = {
                     displayName = "Grafana";
    -                originUrl = "https://status.swarsel.win/login/generic_oauth";
    -                originLanding = "https://status.swarsel.win/";
    +                originUrl = "https://${grafanaDomain}/login/generic_oauth";
    +                originLanding = "https://${grafanaDomain}/";
                     basicSecretFile = config.sops.secrets.kanidm-grafana.path;
                     preferShortUsername = true;
                     scopeMaps."grafana.access" = [
    @@ -12078,8 +9393,8 @@ in
                   };
                   nextcloud = {
                     displayName = "Nextcloud";
    -                originUrl = " https://stash.swarsel.win/apps/sociallogin/custom_oidc/kanidm";
    -                originLanding = "https://stash.swarsel.win/";
    +                originUrl = " https://${nextcloudDomain}/apps/sociallogin/custom_oidc/kanidm";
    +                originLanding = "https://${nextcloudDomain}/";
                     basicSecretFile = config.sops.secrets.kanidm-nextcloud.path;
                     allowInsecureClientDisablePkce = true;
                     scopeMaps."nextcloud.access" = [
    @@ -12140,12 +9455,12 @@ in
         };
     
         systemd.services = {
    -      kanidm.serviceConfig.RestartSec = "30";
    +      ${serviceName}.serviceConfig.RestartSec = "30";
         };
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -12174,18 +9489,23 @@ in
     
    -
    3.3.2.29. oauth2-proxy
    +
    3.2.3.28. oauth2-proxy
    { lib, config, globals, ... }:
     let
    +  servicePort = 3004;
    +  serviceUser = "oauth2-proxy";
    +  serviceGroup = serviceUser;
    +  serviceName = "oauth2-proxy";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
       kanidmDomain = globals.services.kanidm.domain;
    -  oauth2ProxyDomain = "soauth.swarsel.win";
    -  oauth2ProxyPort = 3004;
    +  mainDomain = globals.domains.main;
     in
     {
       options = {
    -    swarselsystems.modules.server.oauth2Proxy = lib.mkEnableOption "enable oauth2-proxy on server";
    +    swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
         # largely based on https://github.com/oddlama/nix-config/blob/main/modules/oauth2-proxy.nix
         services.nginx.virtualHosts = lib.mkOption {
           type = lib.types.attrsOf (
    @@ -12293,12 +9613,12 @@ in
           );
         };
       };
    -  config = lib.mkIf config.swarselsystems.modules.server.oauth2Proxy {
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         sops = {
           secrets = {
    -        "oauth2-cookie-secret" = { owner = "oauth2-proxy"; group = "oauth2-proxy"; mode = "0440"; };
    -        "kanidm-oauth2-proxy-client" = { owner = "oauth2-proxy"; group = "oauth2-proxy"; mode = "0440"; };
    +        "oauth2-cookie-secret" = { owner = serviceUser; group = serviceGroup; mode = "0440"; };
    +        "kanidm-oauth2-proxy-client" = { owner = serviceUser; group = serviceGroup; mode = "0440"; };
           };
     
           templates = {
    @@ -12307,34 +9627,34 @@ in
                 OAUTH2_PROXY_CLIENT_SECRET="${config.sops.placeholder.kanidm-oauth2-proxy-client}"
                 OAUTH2_PROXY_COOKIE_SECRET=${config.sops.placeholder.oauth2-cookie-secret}
               '';
    -          owner = "oauth2-proxy";
    -          group = "oauth2-proxy";
    +          owner = serviceUser;
    +          group = serviceGroup;
               mode = "0440";
             };
           };
         };
     
    -    networking.firewall.allowedTCPPorts = [ oauth2ProxyPort ];
    +    networking.firewall.allowedTCPPorts = [ servicePort ];
     
    -    globals.services.oauth2Proxy.domain = oauth2ProxyDomain;
    +    globals.services.oauth2Proxy.domain = serviceDomain;
     
         services = {
    -      oauth2-proxy = {
    +      ${serviceName} = {
             enable = true;
             cookie = {
    -          domain = ".swarsel.win";
    +          domain = ".${mainDomain}";
               secure = true;
               expire = "900m";
               secret = null; # set by service EnvironmentFile
             };
             clientSecret = null; # set by service EnvironmentFile
             reverseProxy = true;
    -        httpAddress = "0.0.0.0:${builtins.toString oauth2ProxyPort}";
    -        redirectURL = "https://${oauth2ProxyDomain}/oauth2/callback";
    +        httpAddress = "0.0.0.0:${builtins.toString servicePort}";
    +        redirectURL = "https://${serviceDomain}/oauth2/callback";
             setXauthrequest = true;
             extraConfig = {
               code-challenge-method = "S256";
    -          whitelist-domain = ".swarsel.win";
    +          whitelist-domain = ".${mainDomain}";
               set-authorization-header = true;
               pass-access-token = true;
               skip-jwt-bearer-tokens = true;
    @@ -12347,16 +9667,16 @@ in
             loginURL = "https://${kanidmDomain}/ui/oauth2";
             redeemURL = "https://${kanidmDomain}/oauth2/token";
             validateURL = "https://${kanidmDomain}/oauth2/openid/oauth2-proxy/userinfo";
    -        clientID = "oauth2-proxy";
    +        clientID = serviceName;
             email.domains = [ "*" ];
           };
         };
     
         systemd.services = {
    -      oauth2-proxy = {
    +      ${serviceName} = {
             # after = [ "kanidm.service" ];
             serviceConfig = {
    -          RuntimeDirectory = "oauth2-proxy";
    +          RuntimeDirectory = serviceName;
               RuntimeDirectoryMode = "0750";
               UMask = "007"; # TODO remove once https://github.com/oauth2-proxy/oauth2-proxy/issues/2141 is fixed
               RestartSec = "60"; # Retry every minute
    @@ -12369,20 +9689,20 @@ in
     
         services.nginx = {
           upstreams = {
    -        oauth2-proxy = {
    +        ${serviceName} = {
               servers = {
    -            "localhost:${builtins.toString oauth2ProxyPort}" = { };
    +            "localhost:${builtins.toString servicePort}" = { };
               };
             };
           };
           virtualHosts = {
    -        "${oauth2ProxyDomain}" = {
    +        "${serviceDomain}" = {
               enableACME = true;
               forceSSL = true;
               acmeRoot = null;
               locations = {
                 "/" = {
    -              proxyPass = "http://oauth2-proxy";
    +              proxyPass = "http://${serviceName}";
                 };
               };
               extraConfig = ''
    @@ -12399,44 +9719,53 @@ in
     
    -
    3.3.2.30. Firefly-III
    +
    3.2.3.29. Firefly-III
    { self, lib, config, ... }:
     let
    +  servicePort = 80;
    +  serviceUser = "firefly-iii";
    +  serviceGroup = serviceUser;
    +  serviceName = "firefly-iii";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
    +  nginxGroup = "nginx";
    +
       cfg = config.services.firefly-iii;
    -  serviceDomain = "stonks.swarsel.win";
    -  fireflyUser = "firefly-iii";
    -  serviceName = "firefly";
     in
     {
    -  options.swarselsystems.modules.server.firefly = lib.mkEnableOption "enable firefly-iii on server";
    -  config = lib.mkIf config.swarselsystems.modules.server.firefly {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
    -    users.users.firefly-iii = {
    -      group = "nginx";
    -      isSystemUser = true;
    +    users = {
    +      groups.${serviceGroup} = { };
    +      users.${serviceUser} = {
    +        group = lib.mkForce serviceGroup;
    +        extraGroups = lib.mkIf cfg.enableNginx [ nginxGroup ];
    +        isSystemUser = true;
    +      };
         };
     
         sops = {
           secrets = {
    -        "firefly-iii-app-key" = { owner = fireflyUser; group = "nginx"; mode = "0440"; };
    +        "firefly-iii-app-key" = { owner = serviceUser; group = if cfg.enableNginx then nginxGroup else serviceGroup; mode = "0440"; };
           };
         };
     
    -    topology.self.services.firefly-iii = {
    +    topology.self.services.${serviceName} = {
           name = "Firefly-III";
           info = "https://${serviceDomain}";
    -      icon = "${self}/topology/images/firefly-iii.png";
    +      icon = "${self}/files/topology-images/${serviceName}.png";
         };
         globals.services.${serviceName}.domain = serviceDomain;
     
         services = {
    -      firefly-iii = {
    +      ${serviceName} = {
             enable = true;
    -        user = fireflyUser;
    -        group = if cfg.enableNginx then "nginx" else fireflyUser;
    -        dataDir = "/Vault/data/firefly-iii";
    +        user = serviceUser;
    +        group = if cfg.enableNginx then nginxGroup else serviceGroup;
    +        dataDir = "/Vault/data/${serviceName}";
             settings = {
               TZ = config.repo.secrets.common.location.timezone;
               APP_URL = "https://${serviceDomain}";
    @@ -12473,9 +9802,9 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
    -            "192.168.1.2:80" = { };
    +            "192.168.1.2:${builtins.toString servicePort}" = { };
               };
             };
           };
    @@ -12508,23 +9837,24 @@ in
     
    -
    3.3.2.31. Koillection
    +
    3.2.3.30. Koillection
    { self, lib, config, ... }:
     let
    -  serviceDomain = "swag.swarsel.win";
       serviceUser = "koillection";
       serviceDB = "koillection";
       serviceName = "koillection";
       servicePort = 2282;
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
       postgresUser = config.systemd.services.postgresql.serviceConfig.User; # postgres
       postgresPort = config.services.postgresql.settings.port; # 5432
       containerRev = "sha256:96693e41a6eb2aae44f96033a090378270f024ddf4e6095edf8d57674f21095d";
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         sops.secrets = {
           koillection-db-password = { owner = postgresUser; group = postgresUser; mode = "0440"; };
    @@ -12534,7 +9864,7 @@ in
         topology.self.services.${serviceName} = {
           name = lib.swarselsystems.toCapitalized serviceName;
           info = "https://${serviceDomain}";
    -      icon = "${self}/topology/images/${serviceName}.png";
    +      icon = "${self}/files/topology-images/${serviceName}.png";
         };
         globals.services.${serviceName}.domain = serviceDomain;
     
    @@ -12610,7 +9940,7 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -12636,23 +9966,23 @@ in
     
    -
    3.3.2.32. Atuin
    +
    3.2.3.31. Atuin
    { lib, config, ... }:
     let
    -  serviceDomain = "shellhistory.swarsel.win";
       servicePort = 8888;
       serviceName = "atuin";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         topology.self.services.${serviceName}.info = "https://${serviceDomain}";
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services.atuin = {
    +    services.${serviceName} = {
           enable = true;
           host = "0.0.0.0";
           port = servicePort;
    @@ -12662,7 +9992,7 @@ in
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -12693,24 +10023,25 @@ in
     
    -
    3.3.2.33. Radicale
    +
    3.2.3.32. Radicale
    { self, lib, config, ... }:
     let
       inherit (config.repo.secrets.local.radicale) user1;
       sopsFile = self + /secrets/winters/secrets2.yaml;
    -  serviceDomain = "schedule.swarsel.win";
    +
       servicePort = 8000;
       serviceName = "radicale";
       serviceUser = "radicale";
       serviceGroup = serviceUser;
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     
    -  cfg = config.services."${serviceName}";
    +  cfg = config.services.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         sops = {
           secrets.radicale-user = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0440"; };
    @@ -12730,7 +10061,7 @@ in
         topology.self.services.${serviceName}.info = "https://${serviceDomain}";
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services.radicale = {
    +    services.${serviceName} = {
           enable = true;
           settings = {
             server = {
    @@ -12773,11 +10104,10 @@ in
         ];
     
         networking.firewall.allowedTCPPorts = [ servicePort ];
    -    networking.firewall.allowedUDPPorts = [ servicePort ];
     
         nodes.moonside.services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "192.168.1.2:${builtins.toString servicePort}" = { };
               };
    @@ -12809,12 +10139,11 @@ in
     
    -
    3.3.2.34. croc
    +
    3.2.3.33. croc
    { self, lib, config, pkgs, ... }:
     let
    -  serviceDomain = "send.swarsel.win";
       servicePorts = [
         9009
         9010
    @@ -12823,12 +10152,13 @@ let
         9013
       ];
       serviceName = "croc";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     
       cfg = config.services.croc;
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         sops = {
           secrets = {
    @@ -12848,12 +10178,12 @@ in
         topology.self.services.${serviceName} = {
           name = lib.swarselsystems.toCapitalized serviceName;
           info = "https://${serviceDomain}";
    -      icon = "${self}/topology/images/${serviceName}.png";
    +      icon = "${self}/files/topology-images/${serviceName}.png";
         };
     
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services.croc = {
    +    services.${serviceName} = {
           enable = true;
           ports = servicePorts;
           pass = config.sops.secrets.croc-password.path;
    @@ -12862,7 +10192,7 @@ in
     
     
         systemd.services = {
    -      "${serviceName}" = {
    +      ${serviceName} = {
             serviceConfig = {
               ExecStart = lib.mkForce "${pkgs.croc}/bin/croc ${lib.optionalString cfg.debug "--debug"} relay --ports ${
                 lib.concatMapStringsSep "," toString cfg.ports}";
    @@ -12883,27 +10213,27 @@ in
     
    -
    3.3.2.35. microbin
    +
    3.2.3.34. microbin
    { self, lib, config, ... }:
     let
    -  serviceDomain = "scratch.swarsel.win";
       servicePort = 8777;
       serviceName = "microbin";
       serviceUser = "microbin";
       serviceGroup = serviceUser;
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
     
    -  cfg = config.services."${serviceName}";
    +  cfg = config.services.${serviceName};
     in
     {
    -  options.swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  options.swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         users = {
    -      groups."${serviceGroup}" = { };
    +      groups.${serviceGroup} = { };
     
    -      users."${serviceUser}" = {
    +      users.${serviceUser} = {
             isSystemUser = true;
             group = serviceGroup;
           };
    @@ -12933,11 +10263,11 @@ in
         topology.self.services.${serviceName} = {
           name = lib.swarselsystems.toCapitalized serviceName;
           info = "https://${serviceDomain}";
    -      icon = "${self}/topology/images/${serviceName}.png";
    +      icon = "${self}/files/topology-images/${serviceName}.png";
         };
         globals.services.${serviceName}.domain = serviceDomain;
     
    -    services."${serviceName}" = {
    +    services.${serviceName} = {
           enable = true;
           passwordFile = config.sops.templates.microbin-env.path;
           dataDir = "/var/lib/microbin";
    @@ -12972,7 +10302,7 @@ in
         };
     
         systemd.services = {
    -      "${serviceName}" = {
    +      ${serviceName} = {
             serviceConfig = {
               DynamicUser = lib.mkForce false;
               User = serviceUser;
    @@ -12989,7 +10319,7 @@ in
     
         services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "localhost:${builtins.toString servicePort}" = { };
               };
    @@ -13020,25 +10350,26 @@ in
     
    -
    3.3.2.36. shlink
    +
    3.2.3.35. shlink
    { self, lib, config, ... }:
     let
    -  serviceDomain = "s.swarsel.win";
       servicePort = 8081;
       serviceName = "shlink";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
    +
       containerRev = "sha256:1a697baca56ab8821783e0ce53eb4fb22e51bb66749ec50581adc0cb6d031d7a";
     in
     {
       options = {
    -    swarselsystems.modules.server."${serviceName}" = lib.mkEnableOption "enable ${serviceName} on server";
    +    swarselsystems.modules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
       };
    -  config = lib.mkIf config.swarselsystems.modules.server."${serviceName}" {
    +  config = lib.mkIf config.swarselsystems.modules.server.${serviceName} {
     
         sops = {
           secrets = {
    -        shlink-api = {  };
    +        shlink-api = { };
           };
     
           templates = {
    @@ -13050,7 +10381,7 @@ in
           };
         };
     
    -    virtualisation.oci-containers.containers."shlink" = {
    +    virtualisation.oci-containers.containers.${serviceName} = {
           image = "shlinkio/shlink@${containerRev}";
           environment = {
             "DEFAULT_DOMAIN" = serviceDomain;
    @@ -13076,13 +10407,13 @@ in
         topology.self.services.${serviceName} = {
           name = lib.swarselsystems.toCapitalized serviceName;
           info = "https://${serviceDomain}";
    -      icon = "${self}/topology/images/${serviceName}.png";
    +      icon = "${self}/files/topology-images/${serviceName}.png";
         };
         globals.services.${serviceName}.domain = serviceDomain;
     
         services.nginx = {
           upstreams = {
    -        "${serviceName}" = {
    +        ${serviceName} = {
               servers = {
                 "localhost:${builtins.toString servicePort}" = { };
               };
    @@ -13109,30 +10440,42 @@ in
     
    -

    3.3.3. Darwin

    +

    3.2.4. Darwin

    -
    3.3.3.1. Imports
    +
    3.2.4.1. Imports

    This section sets up all the imports that are used in the home-manager section.

    -
    _:
    +
    { self, lib, config, outputs, globals, ... }:
    +let
    +  macUser = globals.user.work;
    +in
     {
    +  imports = [
    +  ];
     
    -  nix.settings.experimental-features = "nix-command flakes";
    -  nixpkgs = {
    -    hostPlatform = "x86_64-darwin";
    -    overlays = [ outputs.overlays.default ];
    -    config = {
    -      allowUnfree = true;
    +  options.swarselsystems.modules.darwin.general = lib.mkEnableOption "darwin config";
    +  config = lib.mkIf config.swarselsystems.modules.darwin.general {
    +    nix.settings.experimental-features = "nix-command flakes";
    +    nixpkgs = {
    +      hostPlatform = "x86_64-darwin";
    +      overlays = [ outputs.overlays.default ];
    +      config = {
    +        allowUnfree = true;
    +      };
         };
    -  };
     
    -  system.stateVersion = 4;
    +    home-manager.users."${macUser}".imports = [
    +      "${self}/modules/home/darwin"
    +    ];
    +
    +    system.stateVersion = 4;
    +  };
     }
     
    @@ -13140,7 +10483,7 @@ This section sets up all the imports that are used in the home-manager section.
    -

    3.3.4. Optional

    +

    3.2.5. Optional

    These sets of configuration do not need to be deployed on every host, for a multitude of reasons. @@ -13171,7 +10514,7 @@ in

    -
    3.3.4.1. gaming
    +
    3.2.5.1. gaming

    This opens a few gaming ports and installs the steam configuration suite for gaming. There are more options in Gaming (home-manager side). @@ -13225,7 +10568,7 @@ This opens a few gaming ports and installs the steam configuration suite for gam

    -
    3.3.4.2. VirtualBox
    +
    3.2.5.2. VirtualBox

    This sets the VirtualBox configuration. Guest should not be enabled if not direly needed, it will make rebuilds unbearably slow. I only use this privately to run an old editor that does not run well under wine, so I put it into it's own specialisation. @@ -13265,7 +10608,7 @@ This sets the VirtualBox configuration. Guest should not be enabled if not direl

    -
    3.3.4.3. VmWare
    +
    3.2.5.3. VmWare

    This sets the VirtualBox configuration. Guest should not be enabled if not direly needed, it will make rebuilds unbearably slow. @@ -13285,33 +10628,8 @@ This sets the VirtualBox configuration. Guest should not be enabled if not direl

    -
    -
    3.3.4.4. Auto-login
    -
    -

    -Auto login for the initial session. -

    - -
    -
    { lib, config, ... }:
    -let
    -  inherit (config.swarselsystems) mainUser;
    -in
    -{
    -  options.swarselsystems.modules.optional.autologin = lib.mkEnableOption "optional autologin settings";
    -  config = lib.mkIf config.swarselsystems.modules.optional.autologin {
    -    services = {
    -      getty.autologinUser = mainUser;
    -      greetd.settings.initial_session.user = mainUser;
    -    };
    -  };
    -}
    -
    -
    -
    -
    -
    3.3.4.5. nswitch-rcm
    +
    3.2.5.4. nswitch-rcm

    This smashes Atmosphere 1.3.2 on the switch, which is what I am currenty using. @@ -13336,15 +10654,18 @@ This smashes Atmosphere 1.3.2 on the switch, which is what I am currenty using.

    -
    3.3.4.6. Framework
    +
    3.2.5.5. Framework

    This holds configuration that is specific to framework laptops.

    -
    { lib, config, ... }:
    +
    { lib, config, inputs, ... }:
     {
    +  imports = [
    +    inputs.fw-fanctrl.nixosModules.default
    +  ];
       options.swarselsystems.modules.optional.framework = lib.mkEnableOption "optional framework machine settings";
       config = lib.mkIf config.swarselsystems.modules.optional.framework {
         services = {
    @@ -13375,7 +10696,7 @@ This holds configuration that is specific to framework laptops.
     
    -
    3.3.4.7. AMD CPU
    +
    3.2.5.6. AMD CPU
    { lib, config, ... }:
    @@ -13392,7 +10713,7 @@ This holds configuration that is specific to framework laptops.
     
    -
    3.3.4.8. AMD GPU
    +
    3.2.5.7. AMD GPU
    { lib, config, ... }:
    @@ -13415,7 +10736,7 @@ This holds configuration that is specific to framework laptops.
     
    -
    3.3.4.9. Hibernation
    +
    3.2.5.8. Hibernation
    { lib, config, ... }:
    @@ -13447,7 +10768,7 @@ This holds configuration that is specific to framework laptops.
     
    -
    3.3.4.10. BTRFS
    +
    3.2.5.9. BTRFS
    { lib, config, ... }:
    @@ -13464,7 +10785,7 @@ This holds configuration that is specific to framework laptops.
     
    -
    3.3.4.11. work
    +
    3.2.5.10. work

    Options that I need specifically at work. There are more options at Work (home-manager side). @@ -13474,6 +10795,7 @@ Options that I need specifically at work. There are more options at { self, lib, pkgs, config, ... }: let inherit (config.swarselsystems) mainUser homeDir xdgDir; + iwd = config.networking.networkmanager.wifi.backend == "iwd"; owner = mainUser; sopsFile = self + /secrets/work/secrets.yaml; swarselService = name: description: execStart: { @@ -13522,6 +10844,8 @@ in "govchost" "govcnetwork" "govcpool" + "baseuser" + "basepw" ]; in { @@ -13533,6 +10857,12 @@ in }) secretNames ); + templates = { + "network-manager-work.env".content = '' + BASEUSER=${config.sops.placeholder.baseuser} + BASEPASS=${config.sops.placeholder.basepw} + ''; + }; }; boot.initrd = { @@ -13570,7 +10900,48 @@ in networking = { inherit (config.swarselsystems) hostName fqdn; - networkmanager.wifi.scanRandMacAddress = false; + + networkmanager = { + wifi.scanRandMacAddress = false; + ensureProfiles = { + environmentFiles = [ + "${config.sops.templates."network-manager-work.env".path}" + ]; + profiles = { + VBC = { + "802-1x" = { + eap = if (!iwd) then "ttls;" else "peap;"; + identity = "$BASEUSER"; + password = "$BASEPASS"; + phase2-auth = "mschapv2"; + }; + connection = { + id = "VBC"; + type = "wifi"; + }; + ipv4 = { method = "auto"; }; + ipv6 = { + addr-gen-mode = "default"; + method = "auto"; + }; + proxy = { }; + wifi = { + cloned-mac-address = "permanent"; + mac-address = "E8:65:38:52:63:FF"; + mac-address-randomization = "1"; + mode = "infrastructure"; + ssid = "VBC"; + }; + wifi-security = { + auth-alg = "open"; + key-mgmt = "wpa-eap"; + }; + }; + }; + }; + }; + + firewall = { enable = lib.mkDefault true; trustedInterfaces = [ "virbr0" ]; @@ -13639,7 +11010,7 @@ in openssh = { enable = true; extraConfig = '' - ''; + ''; }; syncthing = { @@ -13685,86 +11056,6 @@ in # }; }; -} -

    -
    -
    -
    -
    -
    3.3.4.12. Minimal Install
    -
    -

    -These options are really only to be used on the iso image in order to run nixos-anywhere. -

    - -
    -
    { lib, pkgs, ... }:
    -{
    -
    -  nix.settings = {
    -    experimental-features = [ "nix-command" "flakes" ];
    -    warn-dirty = false;
    -  };
    -
    -  boot = {
    -    # initrd.systemd.enable = true;
    -    kernelPackages = pkgs.linuxPackages_latest;
    -    supportedFilesystems = lib.mkForce [ "brtfs" "vfat" ];
    -    loader = {
    -      efi.canTouchEfiVariables = true;
    -      systemd-boot = {
    -        enable = true;
    -        configurationLimit = lib.mkDefault 5;
    -        consoleMode = lib.mkDefault "max";
    -      };
    -    };
    -  };
    -
    -  services = {
    -    qemuGuest.enable = true;
    -    openssh = {
    -      enable = true;
    -      ports = lib.mkDefault [ 22 ];
    -      settings.PermitRootLogin = "yes";
    -      authorizedKeysFiles = lib.mkForce [
    -        "/etc/ssh/authorized_keys.d/%u"
    -      ];
    -    };
    -  };
    -
    -  security.sudo.extraConfig = ''
    -    Defaults    env_keep+=SSH_AUTH_SOCK
    -    Defaults lecture = never
    -  '';
    -
    -  security.pam = {
    -    sshAgentAuth.enable = true;
    -    services = {
    -      sudo.u2fAuth = true;
    -    };
    -  };
    -
    -  environment.systemPackages = with pkgs; [
    -    curl
    -    git
    -    gnupg
    -    rsync
    -    ssh-to-age
    -    sops
    -    vim
    -    just
    -    sbctl
    -  ];
    -
    -  programs = {
    -    git.enable = true;
    -  };
    -
    -  fileSystems."/boot".options = [ "umask=0077" ];
    -
    -  networking.networkmanager.enable = true;
    -
    -
     }
     
    @@ -13773,18 +11064,30 @@ These options are really only to be used on the iso image in order to run nixos-
    -

    3.4. Home-manager

    +

    3.3. Home-manager

    The general structure is the same as in the NixOS section.

    + +
    +
    { lib, ... }:
    +let
    +  importNames = lib.swarselsystems.readNix "modules/home";
    +in
    +{
    +  imports = lib.swarselsystems.mkImports importNames "modules/home";
    +}
    +
    +
    +
    -

    3.4.1. Common

    +

    3.3.1. Common

    -
    3.4.1.1. Imports
    +
    3.3.1.1. Imports

    This section sets up all the imports that are used in the home-manager section. @@ -13803,7 +11106,7 @@ in

    -
    3.4.1.2. Shared Configuration Options (holds firefox & stylix config parts)
    +
    3.3.1.2. Shared Configuration Options (holds firefox & stylix config parts)

    Provides settings related to nix-darwin systems. At the moment, I am only making use of a isDarwin flag. @@ -13854,7 +11157,7 @@ This is where the theme for the whole OS is defined. Originally, this noweb-ref }; wallpaper = lib.mkOption { type = lib.types.path; - default = "${self}/wallpaper/lenovowp.png"; + default = "${self}/files/wallpaper/lenovowp.png"; }; sharescreen = lib.mkOption { type = lib.types.str; @@ -13873,7 +11176,7 @@ This is where the theme for the whole OS is defined. Originally, this noweb-ref type = lib.types.attrs; default = { enable = true; - base16Scheme = "${self}/programs/stylix/swarsel.yaml"; + base16Scheme = "${self}/files/stylix/swarsel.yaml"; polarity = "dark"; opacity.popups = 0.5; cursor = { @@ -13928,7 +11231,7 @@ This is where the theme for the whole OS is defined. Originally, this noweb-ref firefox = lib.mkOption { type = lib.types.attrs; default = { - userChrome = builtins.readFile "${self}/programs/firefox/chrome/userChrome.css"; + userChrome = builtins.readFile "${self}/files/firefox/chrome/userChrome.css"; extensions = { packages = with pkgs.nur.repos.rycee.firefox-addons; [ tridactyl @@ -14099,7 +11402,7 @@ This is where the theme for the whole OS is defined. Originally, this noweb-ref

    -
    3.4.1.3. General home-manager-settings
    +
    3.3.1.3. General home-manager-settings

    Again, we adapt nix to our needs, enable the home-manager command for non-NixOS machines (NixOS machines are using it as a module) and setting user information that I always keep the same. @@ -14158,7 +11461,7 @@ in

    -
    3.4.1.4. nixGL
    +
    3.3.1.4. nixGL

    This integrates nixGL into home-manager. NixGL provies OpenGL and Vulkan APIs to nix installed utilities. This is needed for graphical applications on non-NixOS systems. @@ -14207,7 +11510,7 @@ It can be set to either:

    -
    3.4.1.5. Installed packages
    +
    3.3.1.5. Installed packages
    -
    3.4.1.5.2. Self-defined
    +
    3.3.1.5.2. Self-defined
    -
    3.4.1.7. Yubikey
    +
    3.3.1.7. Yubikey
    { lib, config, nixosConfig, ... }:
    @@ -14522,7 +11825,7 @@ in
       options.swarselsystems.modules.yubikey = lib.mkEnableOption "yubikey settings";
     
       config = lib.mkIf config.swarselsystems.modules.yubikey {
    -    pam.yubico.authorizedYubiKeys = {
    +    pam.yubico.authorizedYubiKeys = lib.mkIf (config.swarselsystems.isNixos && !config.swarselsystems.isPublic) {
           ids = [
             nixosConfig.repo.secrets.common.yubikeys.dev1
             nixosConfig.repo.secrets.common.yubikeys.dev2
    @@ -14535,7 +11838,7 @@ in
     
    -
    3.4.1.8. SSH Machines
    +
    3.3.1.8. SSH Machines

    It is very convenient to have SSH aliases in place for machines that I use. This is mainly used for some server machines and some university clusters. We also enable agent forwarding to have our Yubikey SSH key accessible on the remote host. @@ -14591,7 +11894,7 @@ It is very convenient to have SSH aliases in place for machines that I use. This

    -
    3.4.1.9. Theme (stylix)
    +
    3.3.1.9. Theme (stylix)

    These section allows home-manager to allow theme settings, and handles some other appearance-related settings like cursor styles. Interestingly, system icons (adwaita) still need to be setup on system-level, and will break if defined here. @@ -14623,7 +11926,7 @@ This section has been notably empty ever since switching to stylix. Only Emacs i

    -
    3.4.1.10. Desktop Entries, MIME types (xdg)
    +
    3.3.1.10. Desktop Entries, MIME types (xdg)

    Some programs lack a dmenu launcher - I define them myself here. @@ -14742,7 +12045,7 @@ TODO: Non-NixOS machines (=sp3) should not use these by default, but instead the

    -
    3.4.1.11. Linking dotfiles (Symlinks home.file)
    +
    3.3.1.11. Linking dotfiles (Symlinks home.file)

    This section should be used in order to symlink already existing configuration files using `home.file` and setting session variables using `home.sessionVariables`. @@ -14764,29 +12067,29 @@ Also in firefox `about:config > toolkit.legacyUserProfileCustomizations.style config = lib.mkIf config.swarselsystems.modules.symlink { home.file = { "init.el" = lib.mkDefault { - source = self + /programs/emacs/init.el; + source = self + /files/emacs/init.el; target = ".emacs.d/init.el"; }; "early-init.el" = { - source = self + /programs/emacs/early-init.el; + source = self + /files/emacs/early-init.el; target = ".emacs.d/early-init.el"; }; # on NixOS, Emacs does not find the aspell dicts easily. Write the configuration manually ".aspell.conf" = { - source = self + /programs/config/.aspell.conf; + source = self + /files/config/.aspell.conf; target = ".aspell.conf"; }; ".gitmessage" = { - source = self + /programs/git/.gitmessage; + source = self + /files/git/.gitmessage; target = ".gitmessage"; }; }; xdg.configFile = { - "tridactyl/tridactylrc".source = self + /programs/firefox/tridactyl/tridactylrc; - "tridactyl/themes/base16-codeschool.css".source = self + /programs/firefox/tridactyl/themes/base16-codeschool.css; - "tridactyl/themes/swarsel.css".source = self + /programs/firefox/tridactyl/themes/swarsel.css; - "swayidle/config".source = self + /programs/swayidle/config; + "tridactyl/tridactylrc".source = self + /files/firefox/tridactyl/tridactylrc; + "tridactyl/themes/base16-codeschool.css".source = self + /files/firefox/tridactyl/themes/base16-codeschool.css; + "tridactyl/themes/swarsel.css".source = self + /files/firefox/tridactyl/themes/swarsel.css; + "swayidle/config".source = self + /files/swayidle/config; }; }; } @@ -14795,17 +12098,18 @@ Also in firefox `about:config > toolkit.legacyUserProfileCustomizations.style

    -
    3.4.1.12. Sourcing environment variables
    +
    3.3.1.12. Sourcing environment variables

    Sets environment variables. Here I am only setting the EDITOR variable, most variables are set in the Sway section.

    -
    { lib, config, nixosConfig, ... }:
    +
    { lib, config, nixosConfig, globals, ... }:
     let
       inherit (nixosConfig.repo.secrets.common.mail) address1 address2 address3 address4 allMailAddresses;
       inherit (nixosConfig.repo.secrets.common) fullName;
    +  crocDomain = globals.services.croc.domain;
     in
     {
       options.swarselsystems.modules.env = lib.mkEnableOption "env settings";
    @@ -14813,11 +12117,11 @@ in
         home.sessionVariables = {
           EDITOR = "e -w";
           DISPLAY = ":0";
    -      CROC_RELAY = "send.swarsel.win";
    +      CROC_RELAY = crocDomain;
           SWARSEL_LO_RES = config.swarselsystems.lowResolution;
           SWARSEL_HI_RES = config.swarselsystems.highResolution;
         };
    -    systemd.user.sessionVariables = {
    +    systemd.user.sessionVariables = lib.mkIf (config.swarselsystems.isNixos && !config.swarselsystems.isPublic) {
           SWARSEL_MAIL1 = address1;
           SWARSEL_MAIL2 = address2;
           SWARSEL_MAIL3 = address3;
    @@ -14832,7 +12136,7 @@ in
     
    -
    3.4.1.13. General Programs: bottom, imv, sioyek, bat, carapace, wlogout, swayr, yt-dlp, mpv, jq, nix-index, ripgrep, pandoc, fzf, zoxide
    +
    3.3.1.13. General Programs: bottom, imv, sioyek, bat, carapace, wlogout, swayr, yt-dlp, mpv, jq, nix-index, ripgrep, pandoc, fzf, zoxide

    This section is for programs that require no further configuration. zsh Integration is enabled by default for these. @@ -14875,7 +12179,7 @@ This section is for programs that require no further configuration. zsh Integrat

    -
    3.4.1.14. nix-index
    +
    3.3.1.14. nix-index

    nix-index provides a way to find out which packages are provided by which derivations. By default it also comes with a replacement for command-not-found.sh, however, the implementation is based on a channel based setup. I like consistency, so I replace the command with one that provides a flakes-based output. @@ -14890,7 +12194,7 @@ nix-index provides a way to find out which packages are provided by which deriva let commandNotFound = pkgs.runCommandLocal "command-not-found.sh" { } '' mkdir -p $out/etc/profile.d - substitute ${self + /scripts/command-not-found.sh} \ + substitute ${self + /files/scripts/command-not-found.sh} \ $out/etc/profile.d/command-not-found.sh \ --replace-fail @nix-locate@ ${pkgs.nix-index}/bin/nix-locate \ --replace-fail @tput@ ${pkgs.ncurses}/bin/tput @@ -14911,7 +12215,7 @@ nix-index provides a way to find out which packages are provided by which deriva

    -
    3.4.1.15. password-store
    +
    3.3.1.15. password-store

    Enables password store with the pass-otp extension which allows me to store and generate one-time-passwords. @@ -14936,7 +12240,7 @@ Enables password store with the pass-otp extension which allows me

    -
    3.4.1.16. direnv
    +
    3.3.1.16. direnv

    Enables direnv, which I use for nearly all of my nix dev flakes. @@ -14959,7 +12263,7 @@ Enables direnv, which I use for nearly all of my nix dev flakes.

    -
    3.4.1.17. eza
    +
    3.3.1.17. eza

    Eza provides me with a better ls command and some other useful aliases. @@ -14986,10 +12290,13 @@ Eza provides me with a better ls command and some other useful alia

    -
    3.4.1.18. atuin
    +
    3.3.1.18. atuin
    -
    { lib, config, ... }:
    +
    { lib, config, globals, ... }:
    +let
    +  atuinDomain = globals.services.atuin.domain;
    +in
     {
       options.swarselsystems.modules.atuin = lib.mkEnableOption "atuin settings";
       config = lib.mkIf config.swarselsystems.modules.atuin {
    @@ -14999,7 +12306,7 @@ Eza provides me with a better ls command and some other useful alia
           settings = {
             auto_sync = true;
             sync_frequency = "5m";
    -        sync_address = "https://shellhistory.swarsel.win";
    +        sync_address = "https://${atuinDomain}";
           };
         };
       };
    @@ -15009,17 +12316,19 @@ Eza provides me with a better ls command and some other useful alia
     
    -
    3.4.1.19. git
    +
    3.3.1.19. git

    Here I set up my git config, automatic signing of commits, useful aliases for my ost used commands (for when I am not using Magit) as well as a git template defined in Linking dotfiles.

    -
    { lib, config, nixosConfig, ... }:
    +
    { lib, config, nixosConfig, globals, ... }:
     let
       inherit (nixosConfig.repo.secrets.common.mail) address1;
       inherit (nixosConfig.repo.secrets.common) fullName;
    +
    +  gitUser = globals.user.name;
     in
     {
       options.swarselsystems.modules.git = lib.mkEnableOption "git settings";
    @@ -15043,15 +12352,15 @@ in
             key = "0x76FD3810215AE097";
             signByDefault = true;
           };
    -      userEmail = lib.mkDefault address1;
    -      userName = fullName;
    +      userEmail = lib.mkIf (config.swarselsystems.isNixos && !config.swarselsystems.isPublic) (lib.mkDefault address1);
    +      userName = lib.mkIf (config.swarselsystems.isNixos && !config.swarselsystems.isPublic) fullName;
           difftastic.enable = true;
           lfs.enable = true;
           includes = [
             {
               contents = {
                 github = {
    -              user = "Swarsel";
    +              user = gitUser;
                 };
                 commit = {
                   template = "~/.gitmessage";
    @@ -15067,7 +12376,7 @@ in
     
    -
    3.4.1.20. Fuzzel
    +
    3.3.1.20. Fuzzel

    Here I only need to set basic layout options - the rest is being managed by stylix. @@ -15096,7 +12405,7 @@ Here I only need to set basic layout options - the rest is being managed by styl

    -
    3.4.1.21. Starship
    +
    3.3.1.21. Starship

    Starship makes my zsh look cooler! I have symbols for most programming languages and toolchains, also I build my own powerline. @@ -15232,7 +12541,7 @@ Starship makes my zsh look cooler! I have symbols for most programm

    -
    3.4.1.22. Kitty
    +
    3.3.1.22. Kitty

    Kitty is the terminal emulator of choice for me, it is nice to configure using nix, fast, and has a nice style. @@ -15263,7 +12572,7 @@ The theme is handled by stylix.

    -
    3.4.1.23. zsh
    +
    3.3.1.23. zsh

    zsh is the most convenient shell for me and it happens to be super neat to configure within home manager. @@ -15436,7 +12745,7 @@ in

    -
    3.4.1.24. zellij
    +
    3.3.1.24. zellij
    { self, lib, config, pkgs, ... }:
    @@ -15453,8 +12762,8 @@ in
         ];
     
         xdg.configFile = {
    -      "zellij/config.kdl".text = import "${self}/programs/zellij/config.kdl.nix" { inherit config; };
    -      "zellij/layouts/default.kdl".text = import "${self}/programs/zellij/layouts/default.kdl.nix" { inherit config pkgs; };
    +      "zellij/config.kdl".text = import "${self}/files/zellij/config.kdl.nix" { inherit config; };
    +      "zellij/layouts/default.kdl".text = import "${self}/files/zellij/layouts/default.kdl.nix" { inherit config pkgs; };
         };
       };
     
    @@ -15464,7 +12773,7 @@ in
     
    -
    3.4.1.25. tmux
    +
    3.3.1.25. tmux
    { lib, config, pkgs, ... }:
    @@ -15573,7 +12882,7 @@ in
     
    -
    3.4.1.26. Mail
    +
    3.3.1.26. Mail

    Normally I use 4 mail accounts - here I set them all up. Three of them are Google accounts (sadly), which are a chore to setup. The last is just a sender account that I setup SMTP for here. @@ -15606,7 +12915,7 @@ in # this is needed so that mbsync can use the passwords from sops systemd.user.services.mbsync.Unit.After = [ "sops-nix.service" ]; - accounts = lib.mkIf (!config.swarselsystems.isPublic) { + accounts = lib.mkIf (config.swarselsystems.isNixos && !config.swarselsystems.isPublic) { email = { maildirBasePath = "Mail"; accounts = { @@ -15729,7 +13038,7 @@ in

    -
    3.4.1.27. Home-manager: Emacs
    +
    3.3.1.27. Home-manager: Emacs

    By using the emacs-overlay NixOS module, I can install all Emacs packages that I want to use right through NixOS. This is done by passing my init.el file to the configuration which will then be parsed upon system rebuild, looking for use-package sections in the Elisp code. Also I define here the style of Emacs that I want to run - I am going with native Wayland Emacs here (emacs-pgtk). All of the nice options such as tree-sitter support are enabled by default, so I do not need to adjust the build process. @@ -15755,7 +13064,7 @@ in programs.emacs = { enable = true; package = pkgs.emacsWithPackagesFromUsePackage { - config = self + /programs/emacs/init.el; + config = self + /files/emacs/init.el; package = pkgs.emacs-git-pgtk; alwaysEnsure = true; alwaysTangle = true; @@ -15824,7 +13133,7 @@ in

    -
    3.4.1.28. Waybar
    +
    3.3.1.28. Waybar

    Again I am just using the first bar option here that I was able to find good understandable documentation for. Of note is that the `cpu` section's `format` is not defined here, but in section 1 (since not every machine has the same number of cores) @@ -15847,7 +13156,7 @@ The rest of the related configuration is found here:

    -
    { self, config, lib, ... }:
    +
    { self, config, lib, pkgs, ... }:
     let
       generateIcons = n: lib.concatStringsSep " " (builtins.map (x: "{icon" + toString x + "}") (lib.range 0 (n - 1)));
       modulesLeft = [
    @@ -15928,28 +13237,28 @@ in
     
               "custom/pseudobat" = lib.mkIf (!config.swarselsystems.isLaptop) {
                 format = "";
    -            on-click-right = "wlogout -p layer-shell";
    +            on-click-right = "${pkgs.wlogout}/bin/wlogout -p layer-shell";
               };
     
               "custom/configwarn" = {
    -            exec = "waybarupdate";
    +            exec = "${pkgs.waybarupdate}/bin/waybarupdate";
                 interval = 60;
               };
     
               "custom/scratchpad-indicator" = {
                 interval = 3;
    -            exec = "swaymsg -t get_tree | jq 'recurse(.nodes[]) | first(select(.name==\"__i3_scratch\")) | .floating_nodes | length | select(. >= 1)'";
    +            exec = "${pkgs.swayfx}/bin/swaymsg -t get_tree | ${pkgs.jq}/bin/jq 'recurse(.nodes[]) | first(select(.name==\"__i3_scratch\")) | .floating_nodes | length | select(. >= 1)'";
                 format = "{} ";
    -            on-click = "swaymsg 'scratchpad show'";
    -            on-click-right = "swaymsg 'move scratchpad'";
    +            on-click = "${pkgs.swayfx}/bin/swaymsg 'scratchpad show'";
    +            on-click-right = "${pkgs.swayfx}/bin/swaymsg 'move scratchpad'";
               };
     
               "custom/github" = {
                 format = "{}  ";
                 return-type = "json";
                 interval = 60;
    -            exec = "github-notifications";
    -            on-click = "xdg-open https://github.com/notifications";
    +            exec = "${pkgs.github-notifications}/bin/github-notifications";
    +            on-click = "${pkgs.xdg-utils}/bin/xdg-open https://github.com/notifications";
               };
     
               idle_inhibitor = {
    @@ -16084,8 +13393,8 @@ in
                   ];
                 };
                 scroll-step = 1;
    -            on-click = "pamixer -t";
    -            on-click-right = "pavucontrol";
    +            on-click = "${pkgs.pamixer}/bin/pamixer -t";
    +            on-click-right = "${pkgs.pavucontrol}/bin/pavucontrol";
               };
     
               memory = {
    @@ -16099,13 +13408,13 @@ in
                 interval = 5;
                 format-icons = [ "▁" "▂" "▃" "▄" "▅" "▆" "▇" "█" ];
                 # on-click-right= "com.github.stsdc.monitor";
    -            on-click-right = "kitty -o confirm_os_window_close=0 btm";
    +            on-click-right = "${pkgs.kitty}/bin/kitty -o confirm_os_window_close=0 btm";
     
               };
               "custom/vpn" = {
                 format = "()";
                 exec = "echo '{\"class\": \"connected\"}'";
    -            exec-if = "test -d /proc/sys/net/ipv4/conf/tun0";
    +            exec-if = "${pkgs.toybox}/bin/test -d /proc/sys/net/ipv4/conf/tun0";
                 return-type = "json";
                 interval = 5;
               };
    @@ -16153,7 +13462,7 @@ in
               };
             };
           };
    -      style = builtins.readFile (self + /programs/waybar/style.css);
    +      style = builtins.readFile (self + /files/waybar/style.css);
         };
       };
     }
    @@ -16162,7 +13471,7 @@ in
     
    -
    3.4.1.29. Firefox
    +
    3.3.1.29. Firefox

    Setting up firefox along with some policies that are important to me (mostly disabling telemetry related stuff as well as Pocket). I also enable some integrations that enable super useful packages, namely tridactyl and browserpass. @@ -16336,14 +13645,14 @@ I used to build the firefox addon bypass-paywalls-clean myself here

    -
    3.4.1.30. Services
    +
    3.3.1.30. Services

    Services that can be defined through home-manager should be defined here.

    -
    3.4.1.30.1. gnome-keyring
    +
    3.3.1.30.1. gnome-keyring

    Used for storing sessions in e.g. Nextcloud @@ -16364,7 +13673,7 @@ Used for storing sessions in e.g. Nextcloud

    -
    3.4.1.30.2. KDE Connect
    +
    3.3.1.30.2. KDE Connect

    This enables phone/computer communication, including sending clipboard, files etc. Sadly on Wayland many of the features are broken (like remote control). @@ -16387,7 +13696,7 @@ This enables phone/computer communication, including sending clipboard, files et

    -
    3.4.1.30.3. Mako
    +
    3.3.1.30.3. Mako

    Desktop notifications! @@ -16438,7 +13747,7 @@ The `extraConfig` section here CANNOT be reindented. This has something to do wi

    -
    3.4.1.30.4. SwayOSD
    +
    3.3.1.30.4. SwayOSD
    { lib, config, ... }:
    @@ -16456,7 +13765,7 @@ The `extraConfig` section here CANNOT be reindented. This has something to do wi
     
    -
    3.4.1.30.5. yubikey-touch-detector
    +
    3.3.1.30.5. yubikey-touch-detector
    { lib, config, pkgs, ... }:
    @@ -16497,7 +13806,7 @@ The `extraConfig` section here CANNOT be reindented. This has something to do wi
     
    -
    3.4.1.31. Sway
    +
    3.3.1.31. Sway

    I am currently using SwayFX, which adds some nice effects to sway, like rounded corners and hiding the separator between title and content of a window. @@ -16722,10 +14031,10 @@ Currently, I am too lazy to explain every option here, but most of it is very se # output = lib.mapAttrs' lib.swarselsystems.eachMonitor monitors; output = { "${config.swarselsystems.sharescreen}" = { - bg = "${self}/wallpaper/lenovowp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/lenovowp.png ${config.stylix.imageScalingMode}"; }; "Philips Consumer Electronics Company PHL BDM3270 AU11806002320" = { - bg = "${self}/wallpaper/standwp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/standwp.png ${config.stylix.imageScalingMode}"; }; }; input = config.swarselsystems.standardinputs; @@ -16918,7 +14227,7 @@ Currently, I am too lazy to explain every option here, but most of it is very se

    -
    3.4.1.32. Kanshi
    +
    3.3.1.32. Kanshi
    { lib, config, ... }:
    @@ -17014,7 +14323,7 @@ Currently, I am too lazy to explain every option here, but most of it is very se
     
    -
    3.4.1.33. gpg-agent
    +
    3.3.1.33. gpg-agent

    Settinfs that are needed for the gpg-agent. Also we are enabling emacs support for unlocking my Yubikey here. @@ -17068,7 +14377,7 @@ in

    -
    3.4.1.34. gammastep
    +
    3.3.1.34. gammastep

    This service changes the screen hue at night. I am not sure if that really does something, but I like the color anyways. @@ -17082,7 +14391,7 @@ in { options.swarselsystems.modules.gammastep = lib.mkEnableOption "gammastep settings"; config = lib.mkIf config.swarselsystems.modules.gammastep { - services.gammastep = { + services.gammastep = lib.mkIf (config.swarselsystems.isNixos && !config.swarselsystems.isPublic) { enable = true; provider = "manual"; inherit longitude latitude; @@ -17095,11 +14404,11 @@ in

    -

    3.4.2. Server

    +

    3.3.2. Server

    -
    3.4.2.1. Imports
    +
    3.3.2.1. Imports

    This section sets up all the imports that are used in the home-manager section. @@ -17122,7 +14431,7 @@ in

    -
    3.4.2.2. Symlinking dotfiles
    +
    3.3.2.2. Symlinking dotfiles

    This section should be used in order to symlink already existing configuration files using `home.file` and setting session variables using `home.sessionVariables`. @@ -17139,7 +14448,7 @@ As for the `home.sessionVariables`, it should be noted that environment variable config = lib.mkIf config.swarselsystems.modules.server.dotfiles { home.file = { "init.el" = lib.mkForce { - source = self + /programs/emacs/server.el; + source = self + /files/emacs/server.el; target = ".emacs.d/init.el"; }; }; @@ -17151,11 +14460,11 @@ As for the `home.sessionVariables`, it should be noted that environment variable

    -

    3.4.3. Darwin

    +

    3.3.3. Darwin

    -
    3.4.3.1. Imports
    +
    3.3.3.1. Imports

    This section sets up all the imports that are used in the home-manager section. @@ -17163,13 +14472,10 @@ This section sets up all the imports that are used in the home-manager section.

    { self, ... }:
    -let
    -  modulesPath = "${self}/modules";
    -in
     {
       imports = [
    -    "${modulesPath}/home/common/settings.nix"
    -    "${modulesPath}/home/common/sharedsetup.nix"
    +    "${self}/modules/home/common/settings.nix"
    +    "${self}/modules/home/common/sharedsetup.nix"
       ];
     }
     
    @@ -17178,7 +14484,7 @@ in
    -

    3.4.4. Optional

    +

    3.3.4. Optional

    Akin to the optional NixOS modules. @@ -17196,7 +14502,7 @@ in

    -
    3.4.4.1. Gaming
    +
    3.3.4.1. Gaming

    The rest of the settings is at gaming. @@ -17248,7 +14554,7 @@ The rest of the settings is at

    -
    3.4.4.2. Work
    +
    3.3.4.2. Work

    The rest of the settings is at work. Here, I am setting up the different firefox profiles that I need for the SSO sites that I need to access at work as well as a few ssh shorthands. @@ -17285,13 +14591,13 @@ in wayland.windowManager.sway.config = { output = { "Applied Creative Technology Transmitter QUATTRO201811" = { - bg = "${self}/wallpaper/navidrome.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/navidrome.png ${config.stylix.imageScalingMode}"; }; "Hewlett Packard HP Z24i CN44250RDT" = { - bg = "${self}/wallpaper/op6wp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/op6wp.png ${config.stylix.imageScalingMode}"; }; "HP Inc. HP 732pk CNC4080YL5" = { - bg = "${self}/wallpaper/botanicswp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/botanicswp.png ${config.stylix.imageScalingMode}"; }; }; }; @@ -17696,7 +15002,7 @@ in

    -
    3.4.4.3. Framework
    +
    3.3.4.3. Framework

    This holds configuration that is specific to framework laptops. @@ -17717,6 +15023,2616 @@ This holds configuration that is specific to framework laptops. }; }; } +

    +
    +
    +
    +
    +
    +
    +

    3.4. Packages

    +
    +

    +This is the central station for self-defined packages. These are all referenced in default.nix. Wherever possible, I am keeping the shell version of these scripts in this file as well and then read it using builtin.readFile in the NixOS configurations. This lets me keep full control in this one file but also keep the separate files uncluttered. +

    + +

    +Note: The structure of generating the packages was changed in commit 2cf03a3 refactor: package and module generation. That commit can be checked out in order to see a simpler version of achieving the same thing. +

    + +
    +
    { self, lib, pkgs, ... }:
    +let
    +  mkPackages = names: pkgs: builtins.listToAttrs (map
    +    (name: {
    +      inherit name;
    +      value = pkgs.callPackage "${self}/pkgs/${name}" { inherit self name; };
    +    })
    +    names);
    +  packageNames = lib.swarselsystems.readNix "pkgs";
    +in
    +mkPackages packageNames pkgs
    +
    +
    +
    +
    +
    +
    +

    3.4.1. pass-fuzzel

    +
    +

    +This app allows me, in conjunction with my Yubikey, to quickly enter passwords when the need arises. Normal and TOTP passwords are supported, and they can either be printed directly or copied to the clipboard. +

    + +
    +
    # Adapted from https://code.kulupu.party/thesuess/home-manager/src/branch/main/modules/river.nix
    +shopt -s nullglob globstar
    +
    +otp=0
    +typeit=0
    +while :; do
    +    case ${1:-} in
    +    -t | --type)
    +        typeit=1
    +        ;;
    +    -o | --otp)
    +        otp=1
    +        ;;
    +    *) break ;;
    +    esac
    +    shift
    +done
    +
    +export PASSWORD_STORE_DIR=~/.local/share/password-store
    +prefix=${PASSWORD_STORE_DIR-~/.local/share/password-store}
    +if [[ $otp -eq 0 ]]; then
    +    password_files=("$prefix"/**/*.gpg)
    +else
    +    password_files=("$prefix"/otp/**/*.gpg)
    +fi
    +password_files=("${password_files[@]#"$prefix"/}")
    +password_files=("${password_files[@]%.gpg}")
    +
    +password=$(printf '%s\n' "${password_files[@]}" | fuzzel --dmenu "$@")
    +
    +[[ -n $password ]] || exit
    +if [[ $otp -eq 0 ]]; then
    +    if [[ $typeit -eq 0 ]]; then
    +        pass show -c "$password" &> /tmp/pass-fuzzel
    +    else
    +        pass show "$password" | {
    +            IFS= read -r pass
    +            printf %s "$pass"
    +        } | wtype -
    +    fi
    +else
    +    if [[ $typeit -eq 0 ]]; then
    +        pass otp -c "$password" &> /tmp/pass-fuzzel
    +    else
    +        pass otp "$password" | {
    +            IFS= read -r pass
    +            printf %s "$pass"
    +        } | wtype -
    +    fi
    +fi
    +notify-send -u critical -a pass -t 1000 "Copied/Typed Password"
    +
    +
    + +
    +
    { self, name, writeShellApplication, libnotify, pass, fuzzel, wtype }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ libnotify (pass.withExtensions (exts: [ exts.pass-otp ])) fuzzel wtype ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.2. cura5

    +
    +

    +The version of cura used to be quite outdated in nixpkgs. I am fetching a newer AppImage here and use that instead. +

    + + +
    +
    # taken from https://github.com/NixOS/nixpkgs/issues/186570#issuecomment-1627797219
    +{ appimageTools, fetchurl, writeScriptBin, pkgs, ... }:
    +
    +
    +let
    +  cura5 = appimageTools.wrapType2 rec {
    +    pname = "cura5";
    +    version = "5.9.0";
    +    src = fetchurl {
    +      url = "https://github.com/Ultimaker/Cura/releases/download/${version}/UltiMaker-Cura-${version}-linux-X64.AppImage";
    +      hash = "sha256-STtVeM4Zs+PVSRO3cI0LxnjRDhOxSlttZF+2RIXnAp4=";
    +    };
    +    extraPkgs = pkgs: with pkgs; [ ];
    +  };
    +in
    +writeScriptBin "cura" ''
    +  #! ${pkgs.bash}/bin/bash
    +  # AppImage version of Cura loses current working directory and treats all paths relative to $HOME.
    +  # So we convert each of the files passed as argument to an absolute path.
    +  # This fixes use cases like `cd /path/to/my/files; cura mymodel.stl anothermodel.stl`.
    +  args=()
    +  for a in "$@"; do
    +      if [ -e "$a" ]; then
    +         a="$(realpath "$a")"
    +      fi
    +      args+=("$a")
    +  done
    +  exec "${cura5}/bin/cura5" "''${args[@]}"
    +''
    +
    +
    +
    +
    +
    +
    +

    3.4.3. hm-specialisation

    +
    +

    +This script allows for quick git home-manager specialisation switching. +

    + + +
    +
    { name, writeShellApplication, fzf, findutils, home-manager, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ fzf findutils home-manager ];
    +  text = ''
    +    genpath=$(home-manager generations | head -1 | awk '{print $7}')
    +    dirs=$(find "$genpath/specialisation" -type l 2>/dev/null; [ -d "$genpath" ] && echo "$genpath")
    +    "$(echo "$dirs" | fzf --prompt="Choose home-manager specialisation to activate")"/activate
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +
    +

    3.4.4. cdw

    +
    +

    +This script allows for quick git worktree switching. +

    + + +
    +
    { name, writeShellApplication, fzf, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ fzf ];
    +  text = ''
    +    cd "$(git worktree list | fzf | awk '{print $1}')"
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +
    +

    3.4.5. cdb

    +
    +

    +This script allows for quick git branch switching. +

    + +
    +
    { name, writeShellApplication, fzf, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ fzf ];
    +  text = ''
    +    git checkout "$(git branch --list | grep -v "^\*" | fzf | awk '{print $1}')"
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.6. bak

    +
    +

    +This script lets me quickly backup files by appending .bak to the filename. +

    + + +
    +
    { name, writeShellApplication, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  text = ''
    +    cp -r "$1"{,.bak}
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +
    +

    3.4.7. timer

    +
    +

    +This app starts a configuratble timer and uses TTS to say something once the timer runs out. +

    + + +
    +
    { name, writeShellApplication, speechd, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ speechd ];
    +  text = ''
    +    sleep "$1"; while true; do spd-say "$2"; sleep 0.5; done;
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.8. e

    +
    +

    +This is a shorthand for calling emacsclient mostly. Also, it hides the kittyterm scratchpad window that I sometimes use for calling a command quickly, in case it is on the screen. After emacs closes, the kittyterm window is then shown again if it was visible earlier. +

    + +
    +
    wait=0
    +while :; do
    +    case ${1:-} in
    +    -w | --wait)
    +        wait=1
    +        ;;
    +    *) break ;;
    +    esac
    +    shift
    +done
    +
    +STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep kittyterm || true)
    +if [ "$STR" == "" ]; then
    +    swaymsg '[title="kittyterm"]' scratchpad show
    +    emacsclient -c -a "" "$@"
    +    swaymsg '[title="kittyterm"]' scratchpad show
    +else
    +    if [[ $wait -eq 0 ]]; then
    +        emacsclient -n -c -a "" "$@"
    +    else
    +        emacsclient -c -a "" "$@"
    +    fi
    +fi
    +
    +
    + +
    +
    { self, name, writeShellApplication, emacs30-pgtk, sway, jq }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ emacs30-pgtk sway jq ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.9. command-not-found

    +
    +

    +The normal command-not-found.sh uses the outdated nix-shell commands as suggestions. This version supplies me with the more modern nixpkgs#<name> version. +

    + + +
    +
    # Adapted from https://github.com/bennofs/nix-index/blob/master/command-not-found.sh
    +command_not_found_handle() {
    +    if [ -n "${MC_SID-}" ] || ! [ -t 1 ]; then
    +        >&2 echo "$1: command not found"
    +        return 127
    +    fi
    +
    +    echo -n "searching nix-index..."
    +    ATTRS=$(@nix-locate@ --minimal --no-group --type x --type s --top-level --whole-name --at-root "/bin/$1")
    +
    +    case $(echo -n "$ATTRS" | grep -c "^") in
    +    0)
    +        >&2 echo -ne "$(@tput@ el1)\r"
    +        >&2 echo "$1: command not found"
    +        ;;
    +    *)
    +        >&2 echo -ne "$(@tput@ el1)\r"
    +        >&2 echo "The program ‘$(@tput@ setaf 4)$1$(@tput@ sgr0)’ is currently not installed."
    +        >&2 echo "It is provided by the following derivation(s):"
    +        while read -r ATTR; do
    +            ATTR=${ATTR%.out}
    +            >&2 echo "  $(@tput@ setaf 12)nixpkgs#$(@tput@ setaf 4)$ATTR$(@tput@ sgr0)"
    +        done <<< "$ATTRS"
    +        ;;
    +    esac
    +
    +    return 127
    +}
    +
    +command_not_found_handler() {
    +    command_not_found_handle "$@"
    +    return $?
    +}
    +
    +
    +
    +
    +
    +

    3.4.10. swarselcheck

    +
    +

    +This app checks for different apps that I keep around in the scratchpad for quick viewing and hiding (messengers and music players mostly) and then behaves like the kittyterm hider that I described in e. +

    + +
    +
    kitty=0
    +element=0
    +vesktop=0
    +spotifyplayer=0
    +while :; do
    +    case ${1:-} in
    +    -k | --kitty)
    +        kitty=1
    +        ;;
    +    -e | --element)
    +        element=1
    +        ;;
    +    -d | --vesktop)
    +        vesktop=1
    +        ;;
    +    -s | --spotifyplayer)
    +        spotifyplayer=1
    +        ;;
    +    *) break ;;
    +    esac
    +    shift
    +done
    +
    +if [[ $kitty -eq 1 ]]; then
    +    STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep kittyterm || true)
    +    CHECK=$(swaymsg -t get_tree | grep kittyterm || true)
    +    if [ "$CHECK" == "" ]; then
    +        exec kitty -T kittyterm -o confirm_os_window_close=0 zellij attach --create kittyterm &
    +        sleep 1
    +    fi
    +    if [ "$STR" == "" ]; then
    +        exec swaymsg '[title="kittyterm"]' scratchpad show
    +    else
    +        exec swaymsg '[title="kittyterm"]' scratchpad show
    +    fi
    +elif [[ $element -eq 1 ]]; then
    +    STR=$(swaymsg -t get_tree | grep Element || true)
    +    if [ "$STR" == "" ]; then
    +        exec element-desktop
    +    else
    +        exec swaymsg '[app_id=Element]' kill
    +    fi
    +elif [[ $vesktop -eq 1 ]]; then
    +    STR=$(swaymsg -t get_tree | grep vesktop || true)
    +    if [ "$STR" == "" ]; then
    +        exec vesktop
    +    else
    +        exec swaymsg '[app_id=vesktop]' kill
    +    fi
    +elif [[ $spotifyplayer -eq 1 ]]; then
    +    STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep spotifytui || true)
    +    CHECK=$(swaymsg -t get_tree | grep spotifytui || true)
    +    if [ "$CHECK" == "" ]; then
    +        exec kitty -T spotifytui -o confirm_os_window_close=0 spotify_player &
    +        sleep 1
    +    fi
    +    if [ "$STR" == "" ]; then
    +        exec swaymsg '[title="spotifytui"]' scratchpad show
    +    else
    +        exec swaymsg '[title="spotifytui"]' scratchpad show
    +    fi
    +fi
    +
    +
    + +
    +
    { self, name, writeShellApplication, kitty, element-desktop, vesktop, spotify-player, jq }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ kitty element-desktop vesktop spotify-player jq ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.11. swarselzellij

    +
    +
    +
    KITTIES=$(($(pgrep -P 1 kitty | wc -l) - 1))
    +
    +if ((KITTIES < 1)); then
    +    exec kitty -o confirm_os_window_close=0 zellij attach --create main
    +else
    +    exec kitty -o confirm_os_window_close=0 zellij attach --create "temp $KITTIES"
    +fi
    +
    +
    + +
    +
    { self, name, writeShellApplication, kitty }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ kitty ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.12. waybarupdate

    +
    +

    +This scripts checks if there are uncommited changes in either my dotfile repo, my university repo, or my passfile repo. In that case a warning will be shown in waybar. +

    + +
    +
    CFG=$(git --git-dir="$HOME"/.dotfiles/.git --work-tree="$HOME"/.dotfiles/ status -s | wc -l)
    +CSE=$(git --git-dir="$DOCUMENT_DIR_PRIV"/CSE_TUWIEN/.git --work-tree="$DOCUMENT_DIR_PRIV"/CSE_TUWIEN/ status -s | wc -l)
    +PASS=$(($(git --git-dir="$HOME"/.local/share/password-store/.git --work-tree="$HOME"/.local/share/password-store/ status -s | wc -l) + $(git --git-dir="$HOME"/.local/share/password-store/.git --work-tree="$HOME"/.local/share/password-store/ diff origin/main..HEAD | wc -l)))
    +
    +if [[ $CFG != 0 ]]; then
    +    CFG_STR='CONFIG'
    +else
    +    CFG_STR=''
    +fi
    +
    +if [[ $CSE != 0 ]]; then
    +    CSE_STR=' CSE'
    +else
    +    CSE_STR=''
    +fi
    +
    +if [[ $PASS != 0 ]]; then
    +    PASS_STR=' PASS'
    +else
    +    PASS_STR=''
    +fi
    +
    +OUT="$CFG_STR""$CSE_STR""$PASS_STR"
    +echo "$OUT"
    +
    +
    + +
    +
    { self, name, writeShellApplication, git }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ git ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.13. opacitytoggle

    +
    +

    +This app quickly toggles between 5% and 0% transparency. +

    + +
    +
    if swaymsg opacity plus 0.01 -q; then
    +    swaymsg opacity 1
    +else
    +    swaymsg opacity 0.95
    +fi
    +
    +
    + +
    +
    { self, name, writeShellApplication, sway }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ sway ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +

    3.4.14. fs-diff

    +
    +

    +This utility is used to compare the current state of the root directory with the blanket state that is stored in /root-blank (the snapshot that is restored on each reboot of an impermanence machine). Using this, I can find files that I will lose once I reboot - if there are important files in that list, I can then easily add them to the persist options. +

    + +
    +
    set -euo pipefail
    +
    +OLD_TRANSID=$(sudo btrfs subvolume find-new /mnt/root-blank 9999999)
    +OLD_TRANSID=${OLD_TRANSID#transid marker was }
    +
    +sudo btrfs subvolume find-new "/mnt/root" "$OLD_TRANSID" |
    +    sed '$d' |
    +    cut -f17- -d' ' |
    +    sort |
    +    uniq |
    +    while read -r path; do
    +        path="/$path"
    +        if [ -L "$path" ]; then
    +            : # The path is a symbolic link, so is probably handled by NixOS already
    +        elif [ -d "$path" ]; then
    +            : # The path is a directory, ignore
    +        else
    +            echo "$path"
    +        fi
    +    done
    +
    +
    + +
    +
    { self, name, writeShellApplication }:
    +writeShellApplication {
    +  inherit name;
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +

    3.4.15. github-notifications

    +
    +

    +This utility checks if there are updated packages in nixpkgs-unstable. It does so by fully building the most recent configuration, which I do not love, but it has its merits once I am willing to switch to the newer version. +

    + + +
    +
    { name, writeShellApplication, jq, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ jq ];
    +  text = ''
    +    count=$(curl -u Swarsel:"$(cat "$XDG_RUNTIME_DIR/secrets/github_notif")" https://api.github.com/notifications | jq '. | length')
    +
    +    if [[ "$count" != "0" ]]; then
    +        echo "{\"text\":\"$count\"}"
    +    fi
    +  '';
    +}
    +
    +
    +
    +
    +
    +

    3.4.16. fullscreen

    +
    +

    +This application moves the wl-mirror app to the T workspace and makes it fullscreen there. +

    + +
    +
    { name, writeShellApplication, sway, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ sway ];
    +  text = ''
    +    swaymsg '[app_id=at.yrlf.wl_mirror] move to workspace 14:T'
    +    swaymsg '[app_id=at.yrlf.wl_mirror] fullscreen'
    +  '';
    +}
    +
    +
    +
    +
    +
    +

    3.4.17. screenshare

    +
    +
    +
    +headless="false"
    +while [[ $# -gt 0 ]]; do
    +    case "$1" in
    +    -h)
    +        headless="true"
    +        ;;
    +    *)
    +        echo "Invalid option detected."
    +        ;;
    +    esac
    +    shift
    +done
    +
    +SHARESCREEN="$(nix eval --raw ~/.dotfiles#nixosConfigurations."$(hostname)".config.home-manager.users."$(whoami)".swarselsystems.sharescreen)"
    +
    +if [[ $headless == "true" ]]; then
    +    wl-mirror "$SHARESCREEN"
    +else
    +    wl-mirror "$SHARESCREEN" &
    +    sleep 0.1
    +    swaymsg '[app_id=at.yrlf.wl_mirror] move to workspace 14:T'
    +    swaymsg '[app_id=at.yrlf.wl_mirror] fullscreen'
    +fi
    +
    +
    + + +
    +
    { self, name, writeShellApplication, sway }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ sway ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +

    3.4.18. swarsel-bootstrap

    +
    +

    +This program sets up a new NixOS host remotely. It also takes care of secret management on the new host. +

    + +
    +
    # highly inspired by https://github.com/EmergentMind/nix-config/blob/dev/files/scripts/bootstrap-nixos.sh
    +set -eo pipefail
    +
    +target_hostname=""
    +target_destination=""
    +target_user="swarsel"
    +ssh_port="22"
    +persist_dir=""
    +disk_encryption=0
    +temp=$(mktemp -d)
    +
    +function help_and_exit() {
    +    echo
    +    echo "Remotely installs SwarselSystem on a target machine including secret deployment."
    +    echo
    +    echo "USAGE: $0 -n <target_hostname> -d <target_destination> [OPTIONS]"
    +    echo
    +    echo "ARGS:"
    +    echo "  -n <target_hostname>                    specify target_hostname of the target host to deploy the nixos config on."
    +    echo "  -d <target_destination>                 specify ip or url to the target host."
    +    echo "                                          target during install process."
    +    echo
    +    echo "OPTIONS:"
    +    echo "  -u <target_user>                        specify target_user with sudo access. nix-config will be cloned to their home."
    +    echo "                                          Default='${target_user}'."
    +    echo "  --port <ssh_port>                       specify the ssh port to use for remote access. Default=${ssh_port}."
    +    echo "  --debug                                 Enable debug mode."
    +    echo "  -h | --help                             Print this help."
    +    exit 0
    +}
    +
    +function cleanup() {
    +    rm -rf "$temp"
    +}
    +trap cleanup exit
    +
    +function red() {
    +    echo -e "\x1B[31m[!] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[31m[!] $($2) \x1B[0m"
    +    fi
    +}
    +function green() {
    +    echo -e "\x1B[32m[+] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[32m[+] $($2) \x1B[0m"
    +    fi
    +}
    +function yellow() {
    +    echo -e "\x1B[33m[*] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[33m[*] $($2) \x1B[0m"
    +    fi
    +}
    +
    +function yes_or_no() {
    +    echo -en "\x1B[32m[+] $* [y/n] (default: y): \x1B[0m"
    +    while true; do
    +        read -rp "" yn
    +        yn=${yn:-y}
    +        case $yn in
    +        [Yy]*) return 0 ;;
    +        [Nn]*) return 1 ;;
    +        esac
    +    done
    +}
    +
    +function update_sops_file() {
    +    key_name=$1
    +    key_type=$2
    +    key=$3
    +
    +    if [ ! "$key_type" == "hosts" ] && [ ! "$key_type" == "users" ]; then
    +        red "Invalid key type passed to update_sops_file. Must be either 'hosts' or 'users'."
    +        exit 1
    +    fi
    +    cd "${git_root}"
    +
    +    SOPS_FILE=".sops.yaml"
    +    sed -i "{
    +                                                # Remove any * and & entries for this host
    +                                                /[*&]$key_name/ d;
    +                                                # Inject a new age: entry
    +                                                # n matches the first line following age: and p prints it, then we transform it while reusing the spacing
    +                                                /age:/{n; p; s/\(.*- \*\).*/\1$key_name/};
    +                                                # Inject a new hosts or user: entry
    +                                                /&$key_type/{n; p; s/\(.*- &\).*/\1$key_name $key/}
    +                                                }" $SOPS_FILE
    +    green "Updating .sops.yaml"
    +    cd -
    +}
    +
    +while [[ $# -gt 0 ]]; do
    +    case "$1" in
    +    -n)
    +        shift
    +        target_hostname=$1
    +        ;;
    +    -d)
    +        shift
    +        target_destination=$1
    +        ;;
    +    -u)
    +        shift
    +        target_user=$1
    +        ;;
    +    --port)
    +        shift
    +        ssh_port=$1
    +        ;;
    +    --debug)
    +        set -x
    +        ;;
    +    -h | --help) help_and_exit ;;
    +    *)
    +        echo "Invalid option detected."
    +        help_and_exit
    +        ;;
    +    esac
    +    shift
    +done
    +
    +green "~SwarselSystems~ remote installer"
    +green "Reading system information for $target_hostname ..."
    +
    +DISK="$(nix eval --raw ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.rootDisk)"
    +green "Root Disk: $DISK"
    +
    +CRYPTED="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isCrypted)"
    +if [[ $CRYPTED == "true" ]]; then
    +    green "Encryption: ✓"
    +    disk_encryption=1
    +else
    +    red "Encryption: X"
    +    disk_encryption=0
    +fi
    +
    +IMPERMANENCE="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isImpermanence)"
    +if [[ $IMPERMANENCE == "true" ]]; then
    +    green "Impermanence: ✓"
    +    persist_dir="/persist"
    +else
    +    red "Impermanence: X"
    +    persist_dir=""
    +fi
    +
    +SWAP="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isSwap)"
    +if [[ $SWAP == "true" ]]; then
    +    green "Swap: ✓"
    +else
    +    red "Swap: X"
    +fi
    +
    +SECUREBOOT="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isSecureBoot)"
    +if [[ $SECUREBOOT == "true" ]]; then
    +    green "Secure Boot: ✓"
    +else
    +    red "Secure Boot: X"
    +fi
    +
    +ssh_cmd="ssh -oport=${ssh_port} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -t $target_user@$target_destination"
    +# ssh_root_cmd=$(echo "$ssh_cmd" | sed "s|${target_user}@|root@|") # uses @ in the sed switch to avoid it triggering on the $ssh_key value
    +ssh_root_cmd=${ssh_cmd/${target_user}@/root@}
    +scp_cmd="scp -oport=${ssh_port} -o StrictHostKeyChecking=no"
    +
    +if [[ -z ${FLAKE} ]]; then
    +    FLAKE=/home/"$target_user"/.dotfiles
    +fi
    +if [ ! -d "$FLAKE" ]; then
    +    cd /home/"$target_user"
    +    yellow "Flake directory not found - cloning repository from GitHub"
    +    git clone git@github.com:Swarsel/.dotfiles.git || (yellow "Could not clone repository via SSH - defaulting to HTTPS" && git clone https://github.com/Swarsel/.dotfiles.git)
    +    FLAKE=/home/"$target_user"/.dotfiles
    +fi
    +
    +cd "$FLAKE"
    +git_root=$(git rev-parse --show-toplevel)
    +# ------------------------
    +green "Wiping known_hosts of $target_destination"
    +sed -i "/$target_hostname/d; /$target_destination/d" ~/.ssh/known_hosts
    +# ------------------------
    +green "Preparing a new ssh_host_ed25519_key pair for $target_hostname."
    +# Create the directory where sshd expects to find the host keys
    +install -d -m755 "$temp/$persist_dir/etc/ssh"
    +# Generate host ssh key pair without a passphrase
    +ssh-keygen -t ed25519 -f "$temp/$persist_dir/etc/ssh/ssh_host_ed25519_key" -C root@"$target_hostname" -N ""
    +# Set the correct permissions so sshd will accept the key
    +chmod 600 "$temp/$persist_dir/etc/ssh/ssh_host_ed25519_key"
    +echo "Adding ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
    +# This will fail if we already know the host, but that's fine
    +ssh-keyscan -p "$ssh_port" "$target_destination" >> ~/.ssh/known_hosts || true
    +# ------------------------
    +# when using luks, disko expects a passphrase on /tmp/disko-password, so we set it for now and will update the passphrase later
    +# via the config
    +if [ "$disk_encryption" -eq 1 ]; then
    +    while true; do
    +        green "Set disk encryption passphrase:"
    +        read -rs luks_passphrase
    +        green "Please confirm passphrase:"
    +        read -rs luks_passphrase_confirm
    +        if [[ $luks_passphrase == "$luks_passphrase_confirm" ]]; then
    +            $ssh_root_cmd "/bin/sh -c 'echo $luks_passphrase > /tmp/disko-password'"
    +            break
    +        else
    +            red "Passwords do not match"
    +        fi
    +    done
    +fi
    +# ------------------------
    +green "Generating hardware-config.nix for $target_hostname and adding it to the nix-config."
    +$ssh_root_cmd "nixos-generate-config --force --no-filesystems --root /mnt"
    +
    +green "Injecting initialSetup"
    +$ssh_root_cmd "sed -i '/  boot.extraModulePackages /a \  swarselsystems.initialSetup = true;' /mnt/etc/nixos/hardware-configuration.nix"
    +
    +mkdir -p "$FLAKE"/hosts/nixos/"$target_hostname"
    +$scp_cmd root@"$target_destination":/mnt/etc/nixos/hardware-configuration.nix "${git_root}"/hosts/nixos/"$target_hostname"/hardware-configuration.nix
    +# ------------------------
    +
    +green "Deploying minimal NixOS installation on $target_destination"
    +SHELL=/bin/sh nix run github:nix-community/nixos-anywhere -- --ssh-port "$ssh_port" --extra-files "$temp" --flake .#"$target_hostname" root@"$target_destination"
    +
    +echo "Updating ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
    +ssh-keyscan -p "$ssh_port" "$target_destination" >> ~/.ssh/known_hosts || true
    +# ------------------------
    +
    +while true; do
    +    read -rp "Press Enter to continue once the remote host has finished booting."
    +    if nc -z "$target_destination" "${ssh_port}" 2> /dev/null; then
    +        green "$target_destination is booted. Continuing..."
    +        break
    +    else
    +        yellow "$target_destination is not yet ready."
    +    fi
    +done
    +
    +# ------------------------
    +
    +if [[ $SECUREBOOT == "true" ]]; then
    +    green "Setting up secure boot keys"
    +    $ssh_root_cmd "mkdir -p /var/lib/sbctl"
    +    read -ra scp_call <<< "${scp_cmd}"
    +    sudo "${scp_call[@]}" -r /var/lib/sbctl root@"$target_destination":/var/lib/
    +    $ssh_root_cmd "sbctl enroll-keys --ignore-immutable --microsoft || true"
    +fi
    +# ------------------------
    +green "Disabling initialSetup"
    +sed -i '/swarselsystems\.initialSetup = true;/d' "$git_root"/hosts/nixos/"$target_hostname"/hardware-configuration.nix
    +
    +if [ -n "$persist_dir" ]; then
    +    $ssh_root_cmd "cp /etc/machine-id $persist_dir/etc/machine-id || true"
    +    $ssh_root_cmd "cp -R /etc/ssh/ $persist_dir/etc/ssh/ || true"
    +fi
    +# ------------------------
    +green "Generating an age key based on the new ssh_host_ed25519_key."
    +target_key=$(
    +    ssh-keyscan -p "$ssh_port" -t ssh-ed25519 "$target_destination" 2>&1 |
    +        grep ssh-ed25519 |
    +        cut -f2- -d" " ||
    +        (
    +            red "Failed to get ssh key. Host down?"
    +            exit 1
    +        )
    +)
    +host_age_key=$(nix shell nixpkgs#ssh-to-age.out -c sh -c "echo $target_key | ssh-to-age")
    +
    +if grep -qv '^age1' <<< "$host_age_key"; then
    +    red "The result from generated age key does not match the expected format."
    +    yellow "Result: $host_age_key"
    +    yellow "Expected format: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    +    exit 1
    +else
    +    echo "$host_age_key"
    +fi
    +
    +green "Updating nix-secrets/.sops.yaml"
    +update_sops_file "$target_hostname" "hosts" "$host_age_key"
    +yellow ".sops.yaml has been updated. There may be superfluous entries, you might need to edit manually."
    +if yes_or_no "Do you want to manually edit .sops.yaml now?"; then
    +    vim "${git_root}"/.sops.yaml
    +fi
    +green "Updating all secrets files to reflect updates .sops.yaml"
    +sops updatekeys --yes --enable-local-keyservice "${git_root}"/secrets/*/secrets.yaml
    +# --------------------------
    +green "Making ssh_host_ed25519_key available to home-manager for user $target_user"
    +sed -i "/$target_hostname/d; /$target_destination/d" ~/.ssh/known_hosts
    +$scp_cmd root@"$target_destination":/etc/ssh/ssh_host_ed25519_key root@"$target_destination":/home/"$target_user"/.ssh/ssh_host_ed25519_key
    +$ssh_root_cmd "mkdir -p /home/$target_user/.ssh; chown $target_user:users /home/$target_user/.ssh/ssh_host_ed25519_key"
    +# __________________________
    +
    +if yes_or_no "Add ssh host fingerprints for git upstream repositories? (This is needed for building the full config)"; then
    +    green "Adding ssh host fingerprints for git{lab,hub}"
    +    $ssh_cmd "mkdir -p /home/$target_user/.ssh/; ssh-keyscan -t ssh-ed25519 gitlab.com github.com swagit.swarsel.win >> /home/$target_user/.ssh/known_hosts"
    +    $ssh_root_cmd "mkdir -p /root/.ssh/; ssh-keyscan -t ssh-ed25519 gitlab.com github.com swagit.swarsel.win >> /root/.ssh/known_hosts"
    +fi
    +# --------------------------
    +
    +if yes_or_no "Do you want to copy your full nix-config and nix-secrets to $target_hostname?"; then
    +    green "Adding ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
    +    ssh-keyscan -p "$ssh_port" "$target_destination" >> ~/.ssh/known_hosts || true
    +    green "Copying full nix-config to $target_hostname"
    +    cd "${git_root}"
    +    just sync "$target_user" "$target_destination"
    +
    +    if [ -n "$persist_dir" ]; then
    +        $ssh_root_cmd "cp -r /home/$target_user/.dotfiles $persist_dir/.dotfiles || true"
    +        $ssh_root_cmd "cp -r /home/$target_user/.ssh $persist_dir/.ssh || true"
    +    fi
    +
    +    if yes_or_no "Do you want to rebuild immediately?"; then
    +        green "Rebuilding nix-config on $target_hostname"
    +        yellow "Reminder: The password is 'setup'"
    +        $ssh_root_cmd "mkdir -p /root/.local/share/nix/; printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' > /root/.local/share/nix/trusted-settings.json"
    +        $ssh_cmd -oForwardAgent=yes "cd .dotfiles && sudo nixos-rebuild --show-trace --flake .#$target_hostname switch"
    +    fi
    +else
    +    echo
    +    green "NixOS was successfully installed!"
    +    echo "Post-install config build instructions:"
    +    echo "To copy nix-config from this machine to the $target_hostname, run the following command from ~/nix-config"
    +    echo "just sync $target_user $target_destination"
    +    echo "To rebuild, sign into $target_hostname and run the following command from ~/nix-config"
    +    echo "cd nix-config"
    +    # see above FIXME:(bootstrap)
    +    echo "sudo nixos-rebuild --show-trace --flake .#$target_hostname switch"
    +    # echo "just rebuild"
    +    echo
    +fi
    +
    +if yes_or_no "You can now commit and push the nix-config, which includes the hardware-configuration.nix for $target_hostname?"; then
    +    cd "${git_root}"
    +    deadnix hosts/nixos/"$target_hostname"/hardware-configuration.nix -qe
    +    nixpkgs-fmt hosts/nixos/"$target_hostname"/hardware-configuration.nix
    +    (pre-commit run --all-files 2> /dev/null || true) &&
    +        git add "$git_root/hosts/nixos/$target_hostname/hardware-configuration.nix" &&
    +        git add "$git_root/.sops.yaml" &&
    +        git add "$git_root/secrets" &&
    +        (git commit -m "feat: deployed $target_hostname" || true) && git push
    +fi
    +
    +
    + + +
    +
    { self, name, writeShellApplication, openssh }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ openssh ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +

    3.4.19. swarsel-rebuild

    +
    +
    +
    set -eo pipefail
    +
    +target_config="chaostheatre"
    +target_user="swarsel"
    +
    +function help_and_exit() {
    +    echo
    +    echo "Builds SwarselSystem configuration."
    +    echo
    +    echo "USAGE: $0 [OPTIONS]"
    +    echo
    +    echo "ARGS:"
    +    echo "  -n <target_config>                       specify nixos config to build."
    +    echo "                                          Default: chaostheatre"
    +    echo "  -u <target_user>                        specify user to deploy for."
    +    echo "                                          Default: swarsel"
    +    echo "  -h | --help                             Print this help."
    +    exit 0
    +}
    +
    +function red() {
    +    echo -e "\x1B[31m[!] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[31m[!] $($2) \x1B[0m"
    +    fi
    +}
    +function green() {
    +    echo -e "\x1B[32m[+] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[32m[+] $($2) \x1B[0m"
    +    fi
    +}
    +function yellow() {
    +    echo -e "\x1B[33m[*] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[33m[*] $($2) \x1B[0m"
    +    fi
    +}
    +
    +while [[ $# -gt 0 ]]; do
    +    case "$1" in
    +    -n)
    +        shift
    +        target_config=$1
    +        ;;
    +    -u)
    +        shift
    +        target_user=$1
    +        ;;
    +    -h | --help) help_and_exit ;;
    +    *)
    +        echo "Invalid option detected."
    +        help_and_exit
    +        ;;
    +    esac
    +    shift
    +done
    +
    +cd /home/"$target_user"
    +
    +if [ ! -d /home/"$target_user"/.dotfiles ]; then
    +    green "Cloning repository from GitHub"
    +    git clone https://github.com/Swarsel/.dotfiles.git
    +else
    +    red "A .dotfiles repository is in the way. Please (re-)move the repository and try again."
    +    exit 1
    +fi
    +
    +local_keys=$(ssh-add -L || true)
    +pub_key=$(cat /home/"$target_user"/.dotfiles/secrets/keys/ssh/yubikey.pub)
    +read -ra pub_arr <<< "$pub_key"
    +
    +cd .dotfiles
    +if [[ $local_keys != *"${pub_arr[1]}"* ]]; then
    +    yellow "The ssh key for this configuration is not available."
    +    green "Adjusting flake.nix so that the configuration is buildable"
    +    sed -i '/nix-secrets = {/,/^[[:space:]]*};/d' flake.nix
    +    sed -i '/vbc-nix = {/,/^[[:space:]]*};/d' flake.nix
    +    sed -i '/[[:space:]]*\/\/ (inputs.vbc-nix.overlays.default final prev)/d' overlays/default.nix
    +    rm modules/home/common/env.nix
    +    rm modules/home/common/gammastep.nix
    +    rm modules/home/common/git.nix
    +    rm modules/home/common/mail.nix
    +    rm modules/home/common/yubikey.nix
    +    rm modules/nixos/server/restic.nix
    +    rm hosts/nixos/sync/default.nix
    +    rm -rf modules/nixos/server
    +    rm -rf modules/home/server
    +    nix flake update vbc-nix
    +    git add .
    +else
    +    green "Valid SSH key found! Continuing with installation"
    +fi
    +sudo nixos-generate-config --dir /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/
    +git add /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/hardware-configuration.nix
    +
    +green "Installing flake $target_config"
    +sudo nixos-rebuild --show-trace --flake .#"$target_config" boot
    +yellow "Please keep in mind that this is only a demo of the configuration. Things might break unexpectedly."
    +
    +
    + + + +
    +
    { self, name, writeShellApplication, git }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ git ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +

    3.4.20. swarsel-install

    +
    +

    +Autoformatting always puts the EOF with indentation, which makes shfmt check fail. When editing this block, unindent them manually. +

    + +
    +
    set -eo pipefail
    +
    +target_config="chaostheatre"
    +target_hostname="chaostheatre"
    +target_user="swarsel"
    +persist_dir=""
    +target_disk="/dev/vda"
    +disk_encryption=0
    +
    +function help_and_exit() {
    +    echo
    +    echo "Locally installs SwarselSystem on this machine."
    +    echo
    +    echo "USAGE: $0 -n <target_config> -d <target_disk> [OPTIONS]"
    +    echo
    +    echo "ARGS:"
    +    echo "  -n <target_config>                      specify the nixos config to deploy."
    +    echo "                                          Default: chaostheatre"
    +    echo "  -d <target_disk>                        specify disk to install on."
    +    echo "                                          Default: /dev/vda"
    +    echo "  -u <target_user>                        specify user to deploy for."
    +    echo "                                          Default: swarsel"
    +    echo "  -h | --help                             Print this help."
    +    exit 0
    +}
    +
    +function red() {
    +    echo -e "\x1B[31m[!] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[31m[!] $($2) \x1B[0m"
    +    fi
    +}
    +function green() {
    +    echo -e "\x1B[32m[+] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[32m[+] $($2) \x1B[0m"
    +    fi
    +}
    +function yellow() {
    +    echo -e "\x1B[33m[*] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[33m[*] $($2) \x1B[0m"
    +    fi
    +}
    +
    +while [[ $# -gt 0 ]]; do
    +    case "$1" in
    +    -n)
    +        shift
    +        target_config=$1
    +        target_hostname=$1
    +        ;;
    +    -u)
    +        shift
    +        target_user=$1
    +        ;;
    +    -d)
    +        shift
    +        target_disk=$1
    +        ;;
    +    -h | --help) help_and_exit ;;
    +    *)
    +        echo "Invalid option detected."
    +        help_and_exit
    +        ;;
    +    esac
    +    shift
    +done
    +
    +function cleanup() {
    +    sudo rm -rf .cache/nix
    +    sudo rm -rf /root/.cache/nix
    +}
    +trap cleanup exit
    +
    +green "~SwarselSystems~ local installer"
    +
    +cd /home/"$target_user"
    +
    +sudo rm -rf /root/.cache/nix
    +sudo rm -rf .cache/nix
    +sudo rm -rf .dotfiles
    +
    +green "Cloning repository from GitHub"
    +git clone https://github.com/Swarsel/.dotfiles.git
    +
    +local_keys=$(ssh-add -L || true)
    +pub_key=$(cat /home/"$target_user"/.dotfiles/secrets/keys/ssh/yubikey.pub)
    +read -ra pub_arr <<< "$pub_key"
    +
    +cd .dotfiles
    +if [[ $local_keys != *"${pub_arr[1]}"* ]]; then
    +    yellow "The ssh key for this configuration is not available."
    +    green "Adjusting flake.nix so that the configuration is buildable ..."
    +    sed -i '/nix-secrets = {/,/^[[:space:]]*};/d' flake.nix
    +    sed -i '/vbc-nix = {/,/^[[:space:]]*};/d' flake.nix
    +    sed -i '/[[:space:]]*\/\/ (inputs.vbc-nix.overlays.default final prev)/d' overlays/default.nix
    +    rm modules/home/common/env.nix
    +    rm modules/home/common/gammastep.nix
    +    rm modules/home/common/git.nix
    +    rm modules/home/common/mail.nix
    +    rm modules/home/common/yubikey.nix
    +    rm modules/nixos/server/restic.nix
    +    rm hosts/nixos/sync/default.nix
    +    rm -rf modules/nixos/server
    +    rm -rf modules/home/server
    +    cat > hosts/nixos/chaostheatre/options-home.nix << EOF
    +        { self, lib, ... }:
    +        {
    +        options = {
    +          swarselsystems = {
    +            modules = {
    +              yubikey = lib.mkEnableOption "dummy option for chaostheatre";
    +              env = lib.mkEnableOption "dummy option for chaostheatre";
    +              git = lib.mkEnableOption "dummy option for chaostheatre";
    +              mail = lib.mkEnableOption "dummy option for chaostheatre";
    +              gammastep = lib.mkEnableOption "dummy option for chaostheatre";
    +            };
    +          };
    +        };
    +        }
    +EOF
    +    nix flake update vbc-nix
    +    git add .
    +else
    +    green "Valid SSH key found! Continuing with installation"
    +fi
    +
    +green "Reading system information for $target_config ..."
    +DISK="$(nix eval --raw ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.rootDisk)"
    +green "Root Disk in config: $DISK - Root Disk passed in cli: $target_disk"
    +
    +CRYPTED="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isCrypted)"
    +if [[ $CRYPTED == "true" ]]; then
    +    green "Encryption: ✓"
    +    disk_encryption=1
    +else
    +    red "Encryption: X"
    +    disk_encryption=0
    +fi
    +
    +IMPERMANENCE="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isImpermanence)"
    +if [[ $IMPERMANENCE == "true" ]]; then
    +    green "Impermanence: ✓"
    +    persist_dir="/persist"
    +else
    +    red "Impermanence: X"
    +    persist_dir=""
    +fi
    +
    +SWAP="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isSwap)"
    +if [[ $SWAP == "true" ]]; then
    +    green "Swap: ✓"
    +else
    +    red "Swap: X"
    +fi
    +
    +SECUREBOOT="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.swarselsystems.isSecureBoot)"
    +if [[ $SECUREBOOT == "true" ]]; then
    +    green "Secure Boot: ✓"
    +else
    +    red "Secure Boot: X"
    +fi
    +
    +if [ "$disk_encryption" -eq 1 ]; then
    +    while true; do
    +        green "Set disk encryption passphrase:"
    +        read -rs luks_passphrase
    +        green "Please confirm passphrase:"
    +        read -rs luks_passphrase_confirm
    +        if [[ $luks_passphrase == "$luks_passphrase_confirm" ]]; then
    +            echo "$luks_passphrase" > /tmp/disko-password
    +            break
    +        else
    +            red "Passwords do not match"
    +        fi
    +    done
    +fi
    +
    +green "Setting up disk ..."
    +if [[ $target_config == "chaostheatre" ]]; then
    +    sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/v1.10.0 -- --mode destroy,format,mount --flake .#"$target_config" --yes-wipe-all-disks --arg diskDevice "$target_disk"
    +else
    +    sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/latest -- --mode destroy,format,mount --flake .#"$target_config" --yes-wipe-all-disks
    +fi
    +sudo mkdir -p /mnt/"$persist_dir"/home/"$target_user"/
    +sudo cp -r /home/"$target_user"/.dotfiles /mnt/"$persist_dir"/home/"$target_user"/
    +sudo chown -R 1000:100 /mnt/"$persist_dir"/home/"$target_user"
    +
    +green "Generating hardware configuration ..."
    +sudo nixos-generate-config --root /mnt --no-filesystems --dir /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/
    +
    +green "Injecting initialSetup ..."
    +sudo sed -i '/  boot.extraModulePackages /a \  swarselsystems.initialSetup = true;' /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/hardware-configuration.nix
    +
    +git add /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/hardware-configuration.nix
    +sudo mkdir -p /root/.local/share/nix/
    +printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | sudo tee /root/.local/share/nix/trusted-settings.json > /dev/null
    +green "Installing flake $target_config"
    +sudo nixos-install --flake .#"$target_config"
    +green "Installation finished! Reboot to see changes"
    +
    +
    + + + +
    +
    { self, name, writeShellApplication, git }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ git ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +

    3.4.21. swarsel-postinstall

    +
    +
    +
    set -eo pipefail
    +
    +target_config="chaostheatre"
    +target_user="swarsel"
    +
    +function help_and_exit() {
    +    echo
    +    echo "Locally installs SwarselSystem on this machine."
    +    echo
    +    echo "USAGE: $0 -d <disk> [OPTIONS]"
    +    echo
    +    echo "ARGS:"
    +    echo "  -d <disk>                               specify disk to install on."
    +    echo "  -n <target_config>                      specify the nixos config to deploy."
    +    echo "                                          Default: chaostheatre"
    +    echo "                                          Default: chaostheatre"
    +    echo "  -u <target_user>                        specify user to deploy for."
    +    echo "                                          Default: swarsel"
    +    echo "  -h | --help                             Print this help."
    +    exit 0
    +}
    +
    +function green() {
    +    echo -e "\x1B[32m[+] $1 \x1B[0m"
    +    if [ -n "${2-}" ]; then
    +        echo -e "\x1B[32m[+] $($2) \x1B[0m"
    +    fi
    +}
    +
    +while [[ $# -gt 0 ]]; do
    +    case "$1" in
    +    -n)
    +        shift
    +        target_config=$1
    +        ;;
    +    -u)
    +        shift
    +        target_user=$1
    +        ;;
    +    -h | --help) help_and_exit ;;
    +    *)
    +        echo "Invalid option detected."
    +        help_and_exit
    +        ;;
    +    esac
    +    shift
    +done
    +
    +function cleanup() {
    +    sudo rm -rf .cache/nix
    +    sudo rm -rf /root/.cache/nix
    +}
    +trap cleanup exit
    +
    +sudo rm -rf .cache/nix
    +sudo rm -rf /root/.cache/nix
    +
    +green "~SwarselSystems~ remote post-installer"
    +
    +cd /home/"$target_user"/.dotfiles
    +
    +SECUREBOOT="$(nix eval ~/.dotfiles#nixosConfigurations."$target_config".config.swarselsystems.isSecureBoot)"
    +
    +if [[ $SECUREBOOT == "true" ]]; then
    +    green "Setting up secure boot keys"
    +    sudo mkdir -p /var/lib/sbctl
    +    sbctl create-keys || true
    +    sbctl enroll-keys --ignore-immutable --microsoft || true
    +fi
    +
    +green "Disabling initialSetup"
    +sed -i '/swarselsystems\.initialSetup = true;/d' /home/"$target_user"/.dotfiles/hosts/nixos/"$target_config"/hardware-configuration.nix
    +sudo nixos-rebuild --flake .#"$target_config" switch
    +green "Post-install finished!"
    +
    +
    + + + +
    +
    { self, name, writeShellApplication, git }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ git ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +

    3.4.22. t2ts

    +
    +
    +
    { name, writeShellApplication, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ ];
    +  text = ''
    +    date -d"$1" +%s
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.23. ts2t

    +
    +
    +
    { name, writeShellApplication, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ ];
    +  text = ''
    +    date -d @"$1" 2>/dev/null || date -r "$1"
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.24. vershell

    +
    +
    +
    { name, writeShellApplication, ... }:
    +
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ ];
    +  text = ''
    +    nix shell github:nixos/nixpkgs/"$1"#"$2";
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.25. eontimer

    +
    +
    +
    { lib
    +, python3
    +, fetchFromGitHub
    +, makeDesktopItem
    +, writeShellScript
    +, ...
    +}:
    +let
    +  wrapper = writeShellScript "eontimer-wrapper" ''
    +    export QT_QPA_PLATFORM=xcb
    +    exec @out@/bin/EonTimer
    +  '';
    +in
    +python3.pkgs.buildPythonApplication rec {
    +  pname = "eontimer";
    +  version = "3.0.0-rc.6";
    +  pyproject = true;
    +
    +  src = fetchFromGitHub {
    +    owner = "DasAmpharos";
    +    repo = "EonTimer";
    +    rev = version;
    +    hash = "sha256-+XN/VGGlEg2gVncRZrWDOZ2bfxt8xyIu22F2wHlG6YI=";
    +  };
    +
    +  build-system = [
    +    python3.pkgs.setuptools
    +    python3.pkgs.wheel
    +  ];
    +
    +  dependencies = with python3.pkgs; [
    +    altgraph
    +    certifi
    +    charset-normalizer
    +    idna
    +    libsass
    +    macholib
    +    packaging
    +    pillow
    +    pipdeptree
    +    platformdirs
    +    pyinstaller
    +    pyinstaller-hooks-contrib
    +    pyside6
    +    requests
    +    setuptools
    +    shiboken6
    +    urllib3
    +  ];
    +
    +  nativeBuildInputs = [
    +    python3.pkgs.pyinstaller
    +  ];
    +
    +  buildPhase = ''
    +    runHook preBuild
    +
    +    pyinstaller --clean --noconfirm EonTimer.spec
    +
    +    runHook postBuild
    +  '';
    +
    +  installPhase = ''
    +    runHook preInstall
    +
    +    mkdir -p $out/bin
    +    mkdir -p $out/share/applications
    +    cp dist/EonTimer $out/bin/
    +    install -Dm755 -T ${wrapper} $out/bin/eontimer
    +    substituteInPlace $out/bin/eontimer --subst-var out
    +
    +    runHook postInstall
    +  '';
    +
    +  postInstall = ''
    +    install -Dm755 -t $out/share/applications ${
    +         makeDesktopItem {
    +           name = "eontimer";
    +           desktopName = "EonTimer";
    +           comment = "Start EonTimer";
    +           exec = "eontimer";
    +         }
    +       }/share/applications/eontimer.desktop
    +  '';
    +
    +
    +
    +  meta = {
    +    description = "Pokémon RNG Timer";
    +    homepage = "https://github.com/DasAmpharos/EonTimer";
    +    license = lib.licenses.mit;
    +    maintainers = with lib.maintainers; [ ];
    +    mainProgram = "eon-timer";
    +  };
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.26. project

    +
    +
    +
    set -euo pipefail
    +
    +if [ ! -d "$(pwd)/.git" ]; then
    +    git init
    +fi
    +nix flake init --template "$FLAKE"#"$1"
    +direnv allow
    +
    +
    + +
    +
    { self, name, writeShellApplication }:
    +writeShellApplication {
    +  inherit name;
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +

    3.4.27. fhs

    +
    +
    +
    { name, pkgs, ... }:
    +let
    +  base = pkgs.appimageTools.defaultFhsEnvArgs;
    +in
    +pkgs.buildFHSEnv (base // {
    +  name = "fhs";
    +  targetPkgs = pkgs: (base.targetPkgs pkgs) ++ [ pkgs.pkg-config ];
    +  profile = "export FHS=1";
    +  runScript = "zsh";
    +  extraOutputsToInstall = [ "dev" ];
    +})
    +
    +
    +
    +
    +
    +

    3.4.28. swarsel-displaypower

    +
    +

    +A crude script to power on all displays that might be attached. Needed because sometimes displays do not awake from sleep. +

    + +
    +
    swaymsg "output * power on" > /dev/null 2>&1 || true
    +swaymsg "output * dpms on" > /dev/null 2>&1 || true
    +
    +
    + +
    +
    { self, name, writeShellApplication, sway }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ sway ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.29. swarsel-mgba

    +
    +

    +AppImage version of mgba in which the lua scripting works. +

    + + +
    +
    { appimageTools, fetchurl, ... }:
    +let
    +  pname = "mgba";
    +  version = "0.10.4";
    +  src = fetchurl {
    +    url = "https://github.com/mgba-emu/mgba/releases/download/${version}/mGBA-${version}-appimage-x64.appimage";
    +    hash = "sha256-rDihDfuA8DqxvCe6UeavCzpjeU+fSqUbFnyTNC2dc1I=";
    +  };
    +  appimageContents = appimageTools.extractType2 { inherit pname version src; };
    +in
    +appimageTools.wrapType2 {
    +  inherit pname version src;
    +  extraInstallCommands = ''
    +    install -Dm444 ${appimageContents}/io.mgba.mGBA.desktop -t $out/share/applications
    +    substituteInPlace $out/share/applications/io.mgba.mGBA.desktop \
    +      --replace-fail 'Exec=mgba-qt %f' 'Exec=mgba'
    +    cp -r ${appimageContents}/usr/share/icons $out/share
    +  '';
    +
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.30. swarsel-deploy

    +
    +
    +
    # heavily inspired from https://github.com/oddlama/nix-config/blob/d42cbde676001a7ad8a3cace156e050933a4dcc3/pkgs/deploy.nix
    +{ name, bc, nix-output-monitor, writeShellApplication, ... }:
    +writeShellApplication {
    +  runtimeInputs = [ bc nix-output-monitor ];
    +  inherit name;
    +  text = ''
    +    set -euo pipefail
    +    shopt -s lastpipe # allow cmd | readarray
    +
    +    function die() {
    +        echo "error: $*" >&2
    +        exit 1
    +    }
    +    function show_help() {
    +        echo 'Usage: deploy [OPTIONS] <host,...> [ACTION]'
    +        echo "Builds, pushes and activates nixosConfigurations on target systems."
    +        echo ""
    +        echo 'ACTION:'
    +        echo '  switch          [default] Switch immediately to the new configuration and make it the boot default'
    +        echo '  boot            Make the configuration the new boot default'
    +        echo "  test            Activate the configuration but don't make it the boot default"
    +        echo "  dry-activate    Don't activate, just show what would be done"
    +        echo ""
    +        echo 'OPTIONS: [passed to nix build]'
    +    }
    +
    +    function time_start() {
    +        T_START=$(date +%s.%N)
    +    }
    +
    +    function time_next() {
    +        T_END=$(date +%s.%N)
    +        T_LAST=$(${bc}/bin/bc <<< "scale=1; ($T_END - $T_START)/1")
    +        T_START="$T_END"
    +    }
    +
    +    USER_FLAKE_DIR=$(git rev-parse --show-toplevel 2> /dev/null || pwd) ||
    +        die "Could not determine current working directory. Something went very wrong."
    +    [[ -e "$USER_FLAKE_DIR/flake.nix" ]] ||
    +        die "Could not determine location of your project's flake.nix. Please run this at or below your main directory containing the flake.nix."
    +    cd "$USER_FLAKE_DIR"
    +
    +    [[ $# -gt 0 ]] || {
    +        show_help
    +        exit 1
    +    }
    +
    +    OPTIONS=()
    +    POSITIONAL_ARGS=()
    +    while [[ $# -gt 0 ]]; do
    +        case "$1" in
    +        "help" | "--help" | "-help" | "-h")
    +            show_help
    +            exit 1
    +            ;;
    +
    +        -*) OPTIONS+=("$1") ;;
    +        *) POSITIONAL_ARGS+=("$1") ;;
    +        esac
    +        shift
    +    done
    +
    +    [[ ''${#POSITIONAL_ARGS[@]} -ge 1 ]] ||
    +        die "Missing argument: <hosts...>"
    +    [[ ''${#POSITIONAL_ARGS[@]} -le 2 ]] ||
    +        die "Too many arguments given."
    +
    +    tr , '\n' <<< "''${POSITIONAL_ARGS[0]}" | sort -u | readarray -t HOSTS
    +    ACTION="''${POSITIONAL_ARGS[1]-switch}"
    +
    +    # Expand flake paths for hosts definitions
    +    declare -A TOPLEVEL_FLAKE_PATHS
    +    for host in "''${HOSTS[@]}"; do
    +        TOPLEVEL_FLAKE_PATHS["$host"]=".#nixosConfigurations.$host.config.system.build.toplevel"
    +    done
    +
    +    time_start
    +
    +    # Get outputs of all derivations (should be cached)
    +    declare -A TOPLEVEL_STORE_PATHS
    +    for host in "''${HOSTS[@]}"; do
    +        toplevel="''${TOPLEVEL_FLAKE_PATHS["$host"]}"
    +        # Make sudo call to get prompt out of the way
    +        sudo echo "    Building 📦 $host"
    +        nix build --no-link "''${OPTIONS[@]}" --show-trace --log-format internal-json -v "$toplevel" |& ${nix-output-monitor}/bin/nom --json ||
    +            die "Failed to get derivation path for $host from ''${TOPLEVEL_FLAKE_PATHS["$host"]}"
    +        TOPLEVEL_STORE_PATHS["$host"]=$(nix build --no-link --print-out-paths "''${OPTIONS[@]}" "$toplevel")
    +        time_next
    +        echo "       Built ✅ $host ''${TOPLEVEL_STORE_PATHS["$host"]} in ''${T_LAST}s"
    +    done
    +
    +    current_host=$(hostname)
    +
    +    for host in "''${HOSTS[@]}"; do
    +        store_path="''${TOPLEVEL_STORE_PATHS["$host"]}"
    +
    +        if [ "$host" = "$current_host" ]; then
    +            echo -e "\033[1;36m    Running locally for $host... \033[m"
    +            ssh_prefix="sudo"
    +        else
    +            echo -e "\033[1;36m     Copying \033[m➡️  \033[34m$host\033[m"
    +            nix copy --to "ssh://$host" "$store_path"
    +            time_next
    +            echo -e "\033[1;32m      Copied \033[m✅  \033[34m$host\033[m \033[90min ''${T_LAST}s\033[m"
    +            ssh_prefix="ssh $host --"
    +        fi
    +
    +        echo -e "\033[1;36m    Applying \033[m⚙️  \033[34m$host\033[m"
    +        prev_system=$($ssh_prefix readlink -e /nix/var/nix/profiles/system)
    +        $ssh_prefix /run/current-system/sw/bin/nix-env --profile /nix/var/nix/profiles/system --set "$store_path" ||
    +            die "Failed to set system profile"
    +        $ssh_prefix "$store_path"/bin/switch-to-configuration "$ACTION" ||
    +            echo "Error while activating new system" >&2
    +
    +        if [[ -n $prev_system ]]; then
    +            $ssh_prefix nvd --color always diff "$prev_system" "$store_path" || true
    +        fi
    +
    +        time_next
    +        echo -e "\033[1;32m     Applied \033[m✅  \033[34m$host\033[m \033[90min ''${T_LAST}s\033[m"
    +    done
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.31. swarsel-build

    +
    +
    +
    { name, nix-output-monitor, writeShellApplication, ... }:
    +writeShellApplication {
    +  runtimeInputs = [ nix-output-monitor ];
    +  inherit name;
    +  text = ''
    +    set -euo pipefail
    +    [[ "$#" -ge 1 ]] \
    +      || { echo "usage: build <HOST>..." >&2; exit 1; }
    +    HOSTS=()
    +    for h in "$@"; do
    +      HOSTS+=(".#nixosConfigurations.$h.config.system.build.toplevel")
    +    done
    +    nom build --no-link --print-out-paths --show-trace "''${HOSTS[@]}"
    +  '';
    +}
    +
    +
    +
    +
    +
    +
    +

    3.4.32. sshrm

    +
    +

    +This programs simply runs ssh-keygen on the last host that I tried to ssh into. I need this frequently when working with cloud-init usually. +

    + +
    +
    HISTFILE="$HOME"/.histfile
    +
    +last_ssh_cmd=$(grep -E "ssh " "$HISTFILE" | sed -E 's/^: [0-9]+:[0-9]+;//' | grep "^ssh " | tail -1)
    +host=$(echo "$last_ssh_cmd" | sed -E 's/.*ssh ([^@ ]+@)?([^ ]+).*/\2/')
    +
    +if [[ -n $host ]]; then
    +    echo "Removing SSH host key for: $host"
    +    ssh-keygen -R "$host"
    +else
    +    echo "No valid SSH command found in history."
    +fi
    +
    +
    + +
    +
    { self, name, writeShellApplication, openssh }:
    +writeShellApplication {
    +  inherit name;
    +  runtimeInputs = [ openssh ];
    +  text = builtins.readFile "${self}/files/scripts/${name}.sh";
    +}
    +
    +
    +
    +
    +
    +
    +

    3.5. Profiles

    +
    +

    +In this section I define custom modules under the swarsel attribute. These are mostly used to define settings specific to a host. I keep these settings confined to either home-manager or nixos to maintain compatibility with non-NixOS machines. +

    + +

    +Note: The structure of generating the packages was changed in commit 2cf03a3 refactor: package and module generation. That commit can be checked out in order to see a simpler version of achieving the same thing. +

    +
    +
    +

    3.5.1. NixOS

    +
    +

    +Modules that need to be loaded on the NixOS level. Note that these will not be available on systems that are not running NixOS. +

    + +
    +
    { lib, ... }:
    +let
    +  profileNames = lib.swarselsystems.readNix "profiles/nixos";
    +in
    +{
    +  imports = lib.swarselsystems.mkImports profileNames "profiles/nixos";
    +}
    +
    +
    +
    +
    +
    3.5.1.1. Personal
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.personal = lib.mkEnableOption "is this a personal host";
    +  config = lib.mkIf config.swarselsystems.profiles.personal {
    +    swarselsystems.modules = {
    +      packages = lib.mkDefault true;
    +      general = lib.mkDefault true;
    +      home-manager = lib.mkDefault true;
    +      xserver = lib.mkDefault true;
    +      users = lib.mkDefault true;
    +      env = lib.mkDefault true;
    +      security = lib.mkDefault true;
    +      systemdTimeout = lib.mkDefault true;
    +      hardware = lib.mkDefault true;
    +      pulseaudio = lib.mkDefault true;
    +      pipewire = lib.mkDefault true;
    +      network = lib.mkDefault true;
    +      time = lib.mkDefault true;
    +      sops = lib.mkDefault true;
    +      pii = lib.mkDefault true;
    +      stylix = lib.mkDefault true;
    +      programs = lib.mkDefault true;
    +      zsh = lib.mkDefault true;
    +      syncthing = lib.mkDefault true;
    +      blueman = lib.mkDefault true;
    +      networkDevices = lib.mkDefault true;
    +      gvfs = lib.mkDefault true;
    +      interceptionTools = lib.mkDefault true;
    +      swayosd = lib.mkDefault true;
    +      ppd = lib.mkDefault true;
    +      yubikey = lib.mkDefault true;
    +      ledger = lib.mkDefault true;
    +      keyboards = lib.mkDefault true;
    +      login = lib.mkDefault true;
    +      nix-ld = lib.mkDefault true;
    +      impermanence = lib.mkDefault true;
    +      nvd = lib.mkDefault true;
    +      gnome-keyring = lib.mkDefault true;
    +      sway = lib.mkDefault true;
    +      xdg-portal = lib.mkDefault true;
    +      distrobox = lib.mkDefault true;
    +      appimage = lib.mkDefault true;
    +      lid = lib.mkDefault true;
    +      lowBattery = lib.mkDefault true;
    +      lanzaboote = lib.mkDefault true;
    +      autologin = lib.mkDefault true;
    +
    +      optional = {
    +        gaming = lib.mkDefault true;
    +        virtualbox = lib.mkDefault true;
    +        nswitch-rcm = lib.mkDefault true;
    +      };
    +
    +      server = {
    +        ssh = lib.mkDefault true;
    +      };
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.2. Chaostheatre
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.chaostheatre = lib.mkEnableOption "is this a chaostheatre host";
    +  config = lib.mkIf config.swarselsystems.profiles.chaostheatre {
    +    swarselsystems.modules = {
    +      packages = lib.mkDefault true;
    +      general = lib.mkDefault true;
    +      home-manager = lib.mkDefault true;
    +      xserver = lib.mkDefault true;
    +      users = lib.mkDefault true;
    +      env = lib.mkDefault true;
    +      security = lib.mkDefault true;
    +      systemdTimeout = lib.mkDefault true;
    +      hardware = lib.mkDefault true;
    +      pulseaudio = lib.mkDefault true;
    +      pipewire = lib.mkDefault true;
    +      network = lib.mkDefault true;
    +      time = lib.mkDefault true;
    +      sops = lib.mkDefault false;
    +      stylix = lib.mkDefault true;
    +      programs = lib.mkDefault true;
    +      zsh = lib.mkDefault true;
    +      syncthing = lib.mkDefault true;
    +      blueman = lib.mkDefault true;
    +      networkDevices = lib.mkDefault true;
    +      gvfs = lib.mkDefault true;
    +      interceptionTools = lib.mkDefault true;
    +      swayosd = lib.mkDefault true;
    +      ppd = lib.mkDefault true;
    +      yubikey = lib.mkDefault true;
    +      ledger = lib.mkDefault true;
    +      keyboards = lib.mkDefault true;
    +      login = lib.mkDefault true;
    +      nix-ld = lib.mkDefault true;
    +      impermanence = lib.mkDefault true;
    +      nvd = lib.mkDefault true;
    +      gnome-keyring = lib.mkDefault true;
    +      sway = lib.mkDefault true;
    +      xdg-portal = lib.mkDefault true;
    +      distrobox = lib.mkDefault true;
    +      appimage = lib.mkDefault true;
    +      lid = lib.mkDefault true;
    +      lowBattery = lib.mkDefault true;
    +      lanzaboote = lib.mkDefault true;
    +      autologin = lib.mkDefault true;
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.3. toto
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.toto = lib.mkEnableOption "is this a toto (setup) host";
    +  config = lib.mkIf config.swarselsystems.profiles.toto {
    +    swarselsystems.modules = {
    +      general = lib.mkDefault true;
    +      home-manager = lib.mkDefault true;
    +      xserver = lib.mkDefault true;
    +      users = lib.mkDefault true;
    +      sops = lib.mkDefault true;
    +      impermanence = lib.mkDefault true;
    +      lanzaboote = lib.mkDefault true;
    +      autologin = lib.mkDefault true;
    +      server = {
    +        ssh = lib.mkDefault true;
    +      };
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.4. Work
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.work = lib.mkEnableOption "is this a work host";
    +  config = lib.mkIf config.swarselsystems.profiles.work {
    +    swarselsystems.modules = {
    +      optional = {
    +        work = lib.mkDefault true;
    +      };
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.5. Framework
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.framework = lib.mkEnableOption "is this a framework brand host";
    +  config = lib.mkIf config.swarselsystems.profiles.framework {
    +    swarselsystems.modules = {
    +      optional = {
    +        framework = lib.mkDefault true;
    +      };
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.6. AMD CPU
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.amdcpu = lib.mkEnableOption "is this a host with amd cpu";
    +  config = lib.mkIf config.swarselsystems.profiles.amdcpu {
    +    swarselsystems.modules = {
    +      optional = {
    +        amdcpu = lib.mkDefault true;
    +      };
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.7. AMD GPU
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.amdgpu = lib.mkEnableOption "is this a host with amd gpu";
    +  config = lib.mkIf config.swarselsystems.profiles.amdgpu {
    +    swarselsystems.modules = {
    +      optional = {
    +        amdgpu = lib.mkDefault true;
    +      };
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.8. Hibernation
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.hibernation = lib.mkEnableOption "is this a host using hibernation";
    +  config = lib.mkIf config.swarselsystems.profiles.hibernation {
    +    swarselsystems.modules = {
    +      optional = {
    +        hibernation = lib.mkDefault true;
    +      };
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.9. BTRFS
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.btrfs = lib.mkEnableOption "is this a host using btrfs";
    +  config = lib.mkIf config.swarselsystems.profiles.btrfs {
    +    swarselsystems.modules = {
    +      optional = {
    +        btrfs = lib.mkDefault true;
    +      };
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.10. Local Server
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.server.local = lib.mkEnableOption "is this a local server";
    +  config = lib.mkIf config.swarselsystems.profiles.server.local {
    +    swarselsystems = {
    +      modules = {
    +        general = lib.mkDefault true;
    +        pii = lib.mkDefault true;
    +        home-manager = lib.mkDefault true;
    +        xserver = lib.mkDefault true;
    +        time = lib.mkDefault true;
    +        users = lib.mkDefault true;
    +        sops = lib.mkDefault true;
    +        server = {
    +          general = lib.mkDefault true;
    +          packages = lib.mkDefault true;
    +          nfs = lib.mkDefault true;
    +          nginx = lib.mkDefault true;
    +          ssh = lib.mkDefault true;
    +          kavita = lib.mkDefault true;
    +          restic = lib.mkDefault true;
    +          jellyfin = lib.mkDefault true;
    +          navidrome = lib.mkDefault true;
    +          spotifyd = lib.mkDefault true;
    +          mpd = lib.mkDefault true;
    +          postgresql = lib.mkDefault true;
    +          matrix = lib.mkDefault true;
    +          nextcloud = lib.mkDefault true;
    +          immich = lib.mkDefault true;
    +          paperless = lib.mkDefault true;
    +          transmission = lib.mkDefault true;
    +          syncthing = lib.mkDefault true;
    +          grafana = lib.mkDefault true;
    +          emacs = lib.mkDefault true;
    +          freshrss = lib.mkDefault true;
    +          jenkins = lib.mkDefault false;
    +          kanidm = lib.mkDefault true;
    +          firefly-iii = lib.mkDefault true;
    +          koillection = lib.mkDefault true;
    +          radicale = lib.mkDefault true;
    +          atuin = lib.mkDefault true;
    +        };
    +      };
    +    };
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.11. OCI Sync Server
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.server.sync = lib.mkEnableOption "is this a oci sync server";
    +  config = lib.mkIf config.swarselsystems.profiles.server.sync {
    +    swarselsystems = {
    +      modules = {
    +        general = lib.mkDefault true;
    +        nix-ld = lib.mkDefault true;
    +        pii = lib.mkDefault true;
    +        home-manager = lib.mkDefault true;
    +        xserver = lib.mkDefault true;
    +        time = lib.mkDefault true;
    +        users = lib.mkDefault true;
    +        sops = lib.mkDefault true;
    +        server = {
    +          general = lib.mkDefault true;
    +          packages = lib.mkDefault true;
    +          nginx = lib.mkDefault true;
    +          ssh = lib.mkDefault true;
    +          forgejo = lib.mkDefault true;
    +          ankisync = lib.mkDefault true;
    +        };
    +      };
    +    };
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.1.12. Moonside
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.server.moonside = lib.mkEnableOption "is this a moonside server";
    +  config = lib.mkIf config.swarselsystems.profiles.server.moonside {
    +    swarselsystems = {
    +      modules = {
    +        general = lib.mkDefault true;
    +        pii = lib.mkDefault true;
    +        home-manager = lib.mkDefault true;
    +        xserver = lib.mkDefault true;
    +        time = lib.mkDefault true;
    +        users = lib.mkDefault true;
    +        impermanence = lib.mkDefault true;
    +        sops = lib.mkDefault true;
    +        server = {
    +          general = lib.mkDefault true;
    +          packages = lib.mkDefault true;
    +          nginx = lib.mkDefault true;
    +          ssh = lib.mkDefault true;
    +          oauth2-proxy = lib.mkDefault true;
    +          croc = lib.mkDefault true;
    +          microbin = lib.mkDefault true;
    +          shlink = lib.mkDefault true;
    +        };
    +      };
    +    };
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    +

    3.5.2. home-manager

    +
    +

    +This holds modules that are to be used on most hosts. These are also the most important options to configure, as these allow me easy access to monitor, keyboard, and other setups. +

    + +
    +
    { lib, ... }:
    +let
    +  profileNames = lib.swarselsystems.readNix "profiles/home";
    +in
    +{
    +  imports = lib.swarselsystems.mkImports profileNames "profiles/home";
    +}
    +
    +
    +
    +
    +
    3.5.2.1. Personal
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.personal = lib.mkEnableOption "is this a personal host";
    +  config = lib.mkIf config.swarselsystems.profiles.personal {
    +    swarselsystems.modules = {
    +      packages = lib.mkDefault true;
    +      ownpackages = lib.mkDefault true;
    +      general = lib.mkDefault true;
    +      nixgl = lib.mkDefault true;
    +      sops = lib.mkDefault true;
    +      yubikey = lib.mkDefault true;
    +      ssh = lib.mkDefault true;
    +      stylix = lib.mkDefault true;
    +      desktop = lib.mkDefault true;
    +      symlink = lib.mkDefault true;
    +      env = lib.mkDefault true;
    +      programs = lib.mkDefault true;
    +      nix-index = lib.mkDefault true;
    +      passwordstore = lib.mkDefault true;
    +      direnv = lib.mkDefault true;
    +      eza = lib.mkDefault true;
    +      atuin = lib.mkDefault true;
    +      git = lib.mkDefault true;
    +      fuzzel = lib.mkDefault true;
    +      starship = lib.mkDefault true;
    +      kitty = lib.mkDefault true;
    +      zsh = lib.mkDefault true;
    +      zellij = lib.mkDefault true;
    +      tmux = lib.mkDefault true;
    +      mail = lib.mkDefault true;
    +      emacs = lib.mkDefault true;
    +      waybar = lib.mkDefault true;
    +      firefox = lib.mkDefault true;
    +      gnome-keyring = lib.mkDefault true;
    +      kdeconnect = lib.mkDefault true;
    +      mako = lib.mkDefault true;
    +      swayosd = lib.mkDefault true;
    +      yubikeytouch = lib.mkDefault true;
    +      sway = lib.mkDefault true;
    +      kanshi = lib.mkDefault true;
    +      gpgagent = lib.mkDefault true;
    +      gammastep = lib.mkDefault true;
    +
    +      optional = {
    +        gaming = lib.mkDefault true;
    +      };
    +    };
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.2.2. Chaostheatre
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.chaostheatre = lib.mkEnableOption "is this a chaostheatre host";
    +  config = lib.mkIf config.swarselsystems.profiles.chaostheatre {
    +    swarselsystems.modules = {
    +      packages = lib.mkDefault true;
    +      ownpackages = lib.mkDefault true;
    +      general = lib.mkDefault true;
    +      nixgl = lib.mkDefault true;
    +      sops = lib.mkDefault true;
    +      yubikey = lib.mkDefault false;
    +      ssh = lib.mkDefault true;
    +      stylix = lib.mkDefault true;
    +      desktop = lib.mkDefault true;
    +      symlink = lib.mkDefault true;
    +      env = lib.mkDefault false;
    +      programs = lib.mkDefault true;
    +      nix-index = lib.mkDefault true;
    +      direnv = lib.mkDefault true;
    +      eza = lib.mkDefault true;
    +      git = lib.mkDefault false;
    +      fuzzel = lib.mkDefault true;
    +      starship = lib.mkDefault true;
    +      kitty = lib.mkDefault true;
    +      zsh = lib.mkDefault true;
    +      zellij = lib.mkDefault true;
    +      tmux = lib.mkDefault true;
    +      mail = lib.mkDefault false;
    +      emacs = lib.mkDefault true;
    +      waybar = lib.mkDefault true;
    +      firefox = lib.mkDefault true;
    +      gnome-keyring = lib.mkDefault true;
    +      kdeconnect = lib.mkDefault true;
    +      mako = lib.mkDefault true;
    +      swayosd = lib.mkDefault true;
    +      yubikeytouch = lib.mkDefault true;
    +      sway = lib.mkDefault true;
    +      kanshi = lib.mkDefault true;
    +      gpgagent = lib.mkDefault true;
    +      gammastep = lib.mkDefault false;
    +    };
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.2.3. toto
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.toto = lib.mkEnableOption "is this a toto (setup) host";
    +  config = lib.mkIf config.swarselsystems.profiles.toto {
    +    swarselsystems.modules = {
    +      general = lib.mkDefault true;
    +      sops = lib.mkDefault true;
    +      ssh = lib.mkDefault true;
    +    };
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.2.4. Work
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.work = lib.mkEnableOption "is this a work host";
    +  config = lib.mkIf config.swarselsystems.profiles.work {
    +    swarselsystems.modules = {
    +      optional = {
    +        work = lib.mkDefault true;
    +      };
    +    };
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.2.5. Framework
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.framework = lib.mkEnableOption "is this a framework brand host";
    +  config = lib.mkIf config.swarselsystems.profiles.framework {
    +    swarselsystems.modules = {
    +      optional = {
    +        framework = lib.mkDefault true;
    +      };
    +    };
    +
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.2.6. Darwin
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.darwin = lib.mkEnableOption "is this a darwin host";
    +  config = lib.mkIf config.swarselsystems.profiles.darwin {
    +    swarselsystems.modules = {
    +      general = lib.mkDefault true;
    +    };
    +  };
    +
    +}
    +
    +
    +
    +
    +
    +
    +
    3.5.2.7. Local Server
    +
    +
    +
    { lib, config, ... }:
    +{
    +  options.swarselsystems.profiles.server.local = lib.mkEnableOption "is this a local server";
    +  config = lib.mkIf config.swarselsystems.profiles.server.local {
    +    swarselsystems.modules = {
    +      general = lib.mkDefault true;
    +      server = {
    +        dotfiles = lib.mkDefault true;
    +      };
    +    };
    +  };
    +
    +}
    +
     
    @@ -21192,7 +21108,7 @@ This sets up the dashboard, which is really quite useless. But, it dashboard-set-footer nil dashboard-banner-logo-title "Welcome to SwarsEmacs!" dashboard-image-banner-max-height 300 - dashboard-startup-banner "~/.dotfiles/wallpaper/swarsel.png" + dashboard-startup-banner "~/.dotfiles/files/wallpaper/swarsel.png" dashboard-projects-backend 'projectile dashboard-projects-switch-function 'magit-status dashboard-set-navigator t @@ -22846,9 +22762,17 @@ base0F: "5EC4FF" # #5EC4FF passt

    6.13. .gitmessage

    +

    +The double source block is intended here to circumvent a org-babel convenience where the first n empty lines of each source block are not taken into the final file. For the .gitmessage I want an empty newline to type into, so this is what I use to achieve that. +

    +
    -#                         max. 50 chars is here: #
    +
    +
    + +
    +
    #                         max. 50 chars is here: #
     # <type>[optional scope]: <description>
     # types: feat, fix, build, chore, ci, docs, style, refactor, perf, test
     # ! indicates a breaking change.
    @@ -23688,8 +23612,8 @@ Otherwise, the files that are possibly of biggest interest are found here:
     
     - [SwarselSystems.org](../SwarselSystems.org)
     - [flake.nix](../flake.nix)
    -- [early-init.el](../programs/emacs/early-init.el)
    -- [init.el](../programs/emacs/init.el)
    +- [early-init.el](../files/emacs/early-init.el)
    +- [init.el](../files/emacs/init.el)
     
     
     ### Getting started
    @@ -23751,7 +23675,7 @@ Alternatively, to install this from any NixOS live ISO, run `nix run --experimen
     |🚪 **DM**      | [greetd](https://github.com/Swarsel/.dotfiles/tree/main/modules/nixos/common/login.nix)                         |
     |🪟 **WM**      | [SwayFX](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/sway.nix)                         |
     |⛩️ **Bar**     | [Waybar](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/waybar.nix)                         |
    -|✒️ **Editor**  | [Emacs](https://github.com/Swarsel/.dotfiles/tree/main/programs/emacs/init.el)                          |
    +|✒️ **Editor**  | [Emacs](https://github.com/Swarsel/.dotfiles/tree/main/files/emacs/init.el)                          |
     |🖥️ **Terminal**| [Kitty](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/kitty.nix)                          |
     |🚀 **Launcher**| [Fuzzel](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/fuzzel.nix)                         |
     |🚨 **Alerts**  | [Mako](https://github.com/Swarsel/.dotfiles/tree/main/modules/home/common/mako.nix)                           |
    @@ -23926,7 +23850,7 @@ If you feel that I forgot to pay you tribute for code that I used in this reposi
     

    Author: Leon Schwarzäugl

    -

    Created: 2025-07-02 Mi 01:23

    +

    Created: 2025-07-04 Fr 18:25

    Validate

    diff --git a/modules/home/common/emacs.nix b/modules/home/common/emacs.nix index f1e3ba5..865ace7 100644 --- a/modules/home/common/emacs.nix +++ b/modules/home/common/emacs.nix @@ -13,7 +13,7 @@ in programs.emacs = { enable = true; package = pkgs.emacsWithPackagesFromUsePackage { - config = self + /programs/emacs/init.el; + config = self + /files/emacs/init.el; package = pkgs.emacs-git-pgtk; alwaysEnsure = true; alwaysTangle = true; diff --git a/modules/home/common/nix-index.nix b/modules/home/common/nix-index.nix index 0ac40f2..b23b1c1 100644 --- a/modules/home/common/nix-index.nix +++ b/modules/home/common/nix-index.nix @@ -6,7 +6,7 @@ let commandNotFound = pkgs.runCommandLocal "command-not-found.sh" { } '' mkdir -p $out/etc/profile.d - substitute ${self + /scripts/command-not-found.sh} \ + substitute ${self + /files/scripts/command-not-found.sh} \ $out/etc/profile.d/command-not-found.sh \ --replace-fail @nix-locate@ ${pkgs.nix-index}/bin/nix-locate \ --replace-fail @tput@ ${pkgs.ncurses}/bin/tput diff --git a/modules/home/common/sharedsetup.nix b/modules/home/common/sharedsetup.nix index 2d15169..7fd614a 100644 --- a/modules/home/common/sharedsetup.nix +++ b/modules/home/common/sharedsetup.nix @@ -25,7 +25,7 @@ }; wallpaper = lib.mkOption { type = lib.types.path; - default = "${self}/wallpaper/lenovowp.png"; + default = "${self}/files/wallpaper/lenovowp.png"; }; sharescreen = lib.mkOption { type = lib.types.str; @@ -44,7 +44,7 @@ type = lib.types.attrs; default = { enable = true; - base16Scheme = "${self}/programs/stylix/swarsel.yaml"; + base16Scheme = "${self}/files/stylix/swarsel.yaml"; polarity = "dark"; opacity.popups = 0.5; cursor = { @@ -99,7 +99,7 @@ firefox = lib.mkOption { type = lib.types.attrs; default = { - userChrome = builtins.readFile "${self}/programs/firefox/chrome/userChrome.css"; + userChrome = builtins.readFile "${self}/files/firefox/chrome/userChrome.css"; extensions = { packages = with pkgs.nur.repos.rycee.firefox-addons; [ tridactyl diff --git a/modules/home/common/sway.nix b/modules/home/common/sway.nix index c48f398..29148fd 100644 --- a/modules/home/common/sway.nix +++ b/modules/home/common/sway.nix @@ -212,10 +212,10 @@ # output = lib.mapAttrs' lib.swarselsystems.eachMonitor monitors; output = { "${config.swarselsystems.sharescreen}" = { - bg = "${self}/wallpaper/lenovowp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/lenovowp.png ${config.stylix.imageScalingMode}"; }; "Philips Consumer Electronics Company PHL BDM3270 AU11806002320" = { - bg = "${self}/wallpaper/standwp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/standwp.png ${config.stylix.imageScalingMode}"; }; }; input = config.swarselsystems.standardinputs; diff --git a/modules/home/common/symlink.nix b/modules/home/common/symlink.nix index 15d8636..a0f1e89 100644 --- a/modules/home/common/symlink.nix +++ b/modules/home/common/symlink.nix @@ -4,29 +4,29 @@ config = lib.mkIf config.swarselsystems.modules.symlink { home.file = { "init.el" = lib.mkDefault { - source = self + /programs/emacs/init.el; + source = self + /files/emacs/init.el; target = ".emacs.d/init.el"; }; "early-init.el" = { - source = self + /programs/emacs/early-init.el; + source = self + /files/emacs/early-init.el; target = ".emacs.d/early-init.el"; }; # on NixOS, Emacs does not find the aspell dicts easily. Write the configuration manually ".aspell.conf" = { - source = self + /programs/config/.aspell.conf; + source = self + /files/config/.aspell.conf; target = ".aspell.conf"; }; ".gitmessage" = { - source = self + /programs/git/.gitmessage; + source = self + /files/git/.gitmessage; target = ".gitmessage"; }; }; xdg.configFile = { - "tridactyl/tridactylrc".source = self + /programs/firefox/tridactyl/tridactylrc; - "tridactyl/themes/base16-codeschool.css".source = self + /programs/firefox/tridactyl/themes/base16-codeschool.css; - "tridactyl/themes/swarsel.css".source = self + /programs/firefox/tridactyl/themes/swarsel.css; - "swayidle/config".source = self + /programs/swayidle/config; + "tridactyl/tridactylrc".source = self + /files/firefox/tridactyl/tridactylrc; + "tridactyl/themes/base16-codeschool.css".source = self + /files/firefox/tridactyl/themes/base16-codeschool.css; + "tridactyl/themes/swarsel.css".source = self + /files/firefox/tridactyl/themes/swarsel.css; + "swayidle/config".source = self + /files/swayidle/config; }; }; } diff --git a/modules/home/common/waybar.nix b/modules/home/common/waybar.nix index ec5cee8..af2204f 100644 --- a/modules/home/common/waybar.nix +++ b/modules/home/common/waybar.nix @@ -304,7 +304,7 @@ in }; }; }; - style = builtins.readFile (self + /programs/waybar/style.css); + style = builtins.readFile (self + /files/waybar/style.css); }; }; } diff --git a/modules/home/common/zellij.nix b/modules/home/common/zellij.nix index 19e9e7f..e2b80c0 100644 --- a/modules/home/common/zellij.nix +++ b/modules/home/common/zellij.nix @@ -12,8 +12,8 @@ ]; xdg.configFile = { - "zellij/config.kdl".text = import "${self}/programs/zellij/config.kdl.nix" { inherit config; }; - "zellij/layouts/default.kdl".text = import "${self}/programs/zellij/layouts/default.kdl.nix" { inherit config pkgs; }; + "zellij/config.kdl".text = import "${self}/files/zellij/config.kdl.nix" { inherit config; }; + "zellij/layouts/default.kdl".text = import "${self}/files/zellij/layouts/default.kdl.nix" { inherit config pkgs; }; }; }; diff --git a/modules/home/optional/work.nix b/modules/home/optional/work.nix index 069e979..32beefd 100644 --- a/modules/home/optional/work.nix +++ b/modules/home/optional/work.nix @@ -28,13 +28,13 @@ in wayland.windowManager.sway.config = { output = { "Applied Creative Technology Transmitter QUATTRO201811" = { - bg = "${self}/wallpaper/navidrome.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/navidrome.png ${config.stylix.imageScalingMode}"; }; "Hewlett Packard HP Z24i CN44250RDT" = { - bg = "${self}/wallpaper/op6wp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/op6wp.png ${config.stylix.imageScalingMode}"; }; "HP Inc. HP 732pk CNC4080YL5" = { - bg = "${self}/wallpaper/botanicswp.png ${config.stylix.imageScalingMode}"; + bg = "${self}/files/wallpaper/botanicswp.png ${config.stylix.imageScalingMode}"; }; }; }; diff --git a/modules/home/server/symlink.nix b/modules/home/server/symlink.nix index bbacf96..27c3bf6 100644 --- a/modules/home/server/symlink.nix +++ b/modules/home/server/symlink.nix @@ -4,7 +4,7 @@ config = lib.mkIf config.swarselsystems.modules.server.dotfiles { home.file = { "init.el" = lib.mkForce { - source = self + /programs/emacs/server.el; + source = self + /files/emacs/server.el; target = ".emacs.d/init.el"; }; }; diff --git a/modules/nixos/server/ankisync.nix b/modules/nixos/server/ankisync.nix index 881841b..d3db63a 100644 --- a/modules/nixos/server/ankisync.nix +++ b/modules/nixos/server/ankisync.nix @@ -16,7 +16,7 @@ in topology.self.services.${serviceName} = { name = lib.mkForce "Anki Sync Server"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; info = "https://${serviceDomain}"; }; diff --git a/modules/nixos/server/croc.nix b/modules/nixos/server/croc.nix index 8570169..86dbe89 100644 --- a/modules/nixos/server/croc.nix +++ b/modules/nixos/server/croc.nix @@ -34,7 +34,7 @@ in topology.self.services.${serviceName} = { name = lib.swarselsystems.toCapitalized serviceName; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; globals.services.${serviceName}.domain = serviceDomain; diff --git a/modules/nixos/server/firefly-iii.nix b/modules/nixos/server/firefly-iii.nix index 6c8b92b..2b5c313 100644 --- a/modules/nixos/server/firefly-iii.nix +++ b/modules/nixos/server/firefly-iii.nix @@ -32,7 +32,7 @@ in topology.self.services.${serviceName} = { name = "Firefly-III"; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; globals.services.${serviceName}.domain = serviceDomain; diff --git a/modules/nixos/server/freshrss.nix b/modules/nixos/server/freshrss.nix index 09c6502..6454fb7 100644 --- a/modules/nixos/server/freshrss.nix +++ b/modules/nixos/server/freshrss.nix @@ -50,7 +50,7 @@ in topology.self.services.${serviceName} = { name = "FreshRSS"; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; globals.services.${serviceName}.domain = serviceDomain; diff --git a/modules/nixos/server/kavita.nix b/modules/nixos/server/kavita.nix index 75cda1b..2fe9752 100644 --- a/modules/nixos/server/kavita.nix +++ b/modules/nixos/server/kavita.nix @@ -23,7 +23,7 @@ in topology.self.services.${serviceName} = { name = "Kavita"; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; globals.services.${serviceName}.domain = serviceDomain; diff --git a/modules/nixos/server/koillection.nix b/modules/nixos/server/koillection.nix index 3ab45f4..07b45b1 100644 --- a/modules/nixos/server/koillection.nix +++ b/modules/nixos/server/koillection.nix @@ -22,7 +22,7 @@ in topology.self.services.${serviceName} = { name = lib.swarselsystems.toCapitalized serviceName; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; globals.services.${serviceName}.domain = serviceDomain; diff --git a/modules/nixos/server/microbin.nix b/modules/nixos/server/microbin.nix index a089d54..99efa1a 100644 --- a/modules/nixos/server/microbin.nix +++ b/modules/nixos/server/microbin.nix @@ -45,7 +45,7 @@ in topology.self.services.${serviceName} = { name = lib.swarselsystems.toCapitalized serviceName; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; globals.services.${serviceName}.domain = serviceDomain; diff --git a/modules/nixos/server/mpd.nix b/modules/nixos/server/mpd.nix index 3965a5b..9212229 100644 --- a/modules/nixos/server/mpd.nix +++ b/modules/nixos/server/mpd.nix @@ -35,7 +35,7 @@ in topology.self.services.${serviceName} = { name = lib.toUpper serviceName; info = "http://localhost:${builtins.toString servicePort}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; services.${serviceName} = { diff --git a/modules/nixos/server/shlink.nix b/modules/nixos/server/shlink.nix index ace9e4d..d1615a9 100644 --- a/modules/nixos/server/shlink.nix +++ b/modules/nixos/server/shlink.nix @@ -52,7 +52,7 @@ in topology.self.services.${serviceName} = { name = lib.swarselsystems.toCapitalized serviceName; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/${serviceName}.png"; + icon = "${self}/files/topology-images/${serviceName}.png"; }; globals.services.${serviceName}.domain = serviceDomain; diff --git a/modules/nixos/server/transmission.nix b/modules/nixos/server/transmission.nix index c71bda0..9c3376d 100644 --- a/modules/nixos/server/transmission.nix +++ b/modules/nixos/server/transmission.nix @@ -80,7 +80,7 @@ in readarr = { name = "Readarr"; info = "https://${serviceDomain}/readarr"; - icon = "${self}/topology/images/readarr.png"; + icon = "${self}/files/topology-images/readarr.png"; }; sonarr.info = "https://${serviceDomain}/sonarr"; lidarr.info = "https://${serviceDomain}/lidarr"; diff --git a/nix/hosts.nix b/nix/hosts.nix index 336c46c..8f94eb4 100644 --- a/nix/hosts.nix +++ b/nix/hosts.nix @@ -84,7 +84,7 @@ homeConfigurations = mkHalfHostConfigs (lib.swarselsystems.readHosts "home") "home" lib.swarselsystems.pkgsFor.x86_64-linux; nixOnDroidConfigurations = mkHalfHostConfigs (lib.swarselsystems.readHosts "android") "android" lib.swarselsystems.pkgsFor.aarch64-linux; - diskoConfigurations.default = import "${self}/templates/hosts/nixos/disk-config.nix"; + diskoConfigurations.default = import "${self}/files/templates/hosts/nixos/disk-config.nix"; nodes = config.nixosConfigurations // config.darwinConfigurations; diff --git a/nix/installer-config.nix b/nix/installer-config.nix new file mode 100644 index 0000000..86b533d --- /dev/null +++ b/nix/installer-config.nix @@ -0,0 +1,111 @@ +{ pkgs, lib, ... }: +{ + + config = { + home-manager.users.root.home = { + stateVersion = "23.05"; + file = { + ".bash_history" = { + text = '' + swarsel-install -n chaostheatre + ''; + }; + }; + }; + + nix.settings = { + experimental-features = [ "nix-command" "flakes" ]; + }; + + boot = { + supportedFilesystems = lib.mkForce [ "brtfs" "vfat" ]; + loader.systemd-boot = { + enable = true; + }; + }; + + services = { + qemuGuest.enable = true; + openssh = { + enable = true; + settings.PermitRootLogin = "yes"; + authorizedKeysFiles = lib.mkForce [ + "/etc/ssh/authorized_keys.d/%u" + ]; + }; + }; + + environment.systemPackages = with pkgs; [ + curl + git + gnupg + rsync + ssh-to-age + sops + vim + just + sbctl + ]; + + programs = { + git.enable = true; + }; + + fileSystems."/boot".options = [ "umask=0077" ]; + + environment.etc."issue".text = '' + ~SwarselSystems~ + IP of primary interface: \4 + The Password for all users & root is 'setup'. + Install the system remotely by running 'bootstrap -n -d ' on a machine with deployed secrets. + Alternatively, run 'swarsel-install -n ' for a local install. For your convenience, an example call is in the bash history (press up on the keyboard to access). + ''; + + networking = { + hostName = "drugstore"; + wireless.enable = false; + dhcpcd.runHook = "${pkgs.utillinux}/bin/agetty --reload"; + networkmanager.enable = true; + }; + + services.getty.autologinUser = lib.mkForce "root"; + + users = { + allowNoPasswordLogin = true; + users = { + root = { + password = "setup"; # this is overwritten after install + initialHashedPassword = lib.mkForce null; + openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDd0XXoLfRE0AyasxscEBwMqOnLWPqwz+etGqzVNeSw/RcgnxOi903mlVjCH+jzWMSe2GVSgzgM20j/r9sfE2P1z+wq/RODFS04JM0ltUoFkkm/IDZXQ2piOk7AoVi5ajdx4EiBnXY87jvxh5cCgQltkj3ouPF7FVN/MaN21IgWYB8NgkaVGft//OplodlDQNot17c0sFMibY0HcquwmHhqKOtKM1gT98+jZl0rd1rCqXFOvkesW6FPC4nzirPai+Hizp5gncrkJOZmLLqrjVx6PfpQzqzIhoUn1YS5CpyfXnKZUgx2Oi8SENmWOZ9DxYvDklgEttob37E2bIXbUhOw/u4I3olGFgCsKL6jg0N+d5teEaCZFnzlOp0UMWiUo7lVqq7Bwl3rNka2pxEdZ9v/1+m9cJiP7h6pnKmccVGku57iGIDnsnoTrmo1qbAje+EsmPYbc+qMnTDvOdSHTOXnjsyTd+ADklvMHCUAuf6ku4ktQEhlZxU3PvYvKHa1cTCEXxLWjytIgHgTgab9M5IH29Q55LSRRQBzUdkwjOG6KhsqG+xEE6038EbXr0MGKTm01AFmeVZWewmkSLu2UdoOMiw8mTSQhQFfp2QruYHnh7oJCo7ttKT1sLoRX+TfgQm1ryn/orhReg2GFfmbiLGxaJGVNvjqCxqrIFQXx4ZDHw== cardno:22_412_399" ]; + }; + }; + }; + + programs.bash.shellAliases = { + "swarsel-install" = "nix run github:Swarsel/.dotfiles#swarsel-install --"; + }; + + system.activationScripts.cache = { + text = '' + mkdir -p -m=0777 /home/setup/.local/state/nix/profiles + mkdir -p -m=0777 /home/setup/.local/state/home-manager/gcroots + mkdir -p -m=0777 /home/setup/.local/share/nix/ + printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /home/setup/.local/share/nix/trusted-settings.json > /dev/null + mkdir -p /root/.local/share/nix/ + printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /root/.local/share/nix/trusted-settings.json > /dev/null + ''; + }; + systemd = { + services.sshd.wantedBy = lib.mkForce [ "multi-user.target" ]; + targets = { + sleep.enable = false; + suspend.enable = false; + hibernate.enable = false; + hybrid-sleep.enable = false; + }; + }; + + system.stateVersion = lib.mkForce "23.05"; + + }; +} diff --git a/nix/iso.nix b/nix/iso.nix index a0b4e95..b31f999 100644 --- a/nix/iso.nix +++ b/nix/iso.nix @@ -1,126 +1,19 @@ -{ self, pkgs, inputs, config, lib, modulesPath, ... }: -let - pubKeys = lib.filesystem.listFilesRecursive "${self}/secrets/keys/ssh"; -in +{ inputs, ... }: { - - imports = [ - "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" - "${modulesPath}/installer/cd-dvd/channel.nix" - - "${self}/modules/iso/minimal.nix" - "${self}/modules/nixos/common/sharedsetup.nix" - "${self}/modules/nixos/common/topology.nix" - "${self}/modules/home/common/sharedsetup.nix" - - "${self}/modules/nixos/common/globals.nix" - - - inputs.home-manager.nixosModules.home-manager + perSystem = { pkgs, system, ... }: { - home-manager.users."setup".imports = [ - "${self}/modules/home/common/settings.nix" - "${self}/modules/home/common/sharedsetup.nix" - ]; - } - ]; - - config = { - swarselsystems = { - info = "~SwarselSystems~ installer ISO"; - }; - home-manager.users."setup" = { - home = { - stateVersion = "23.05"; - file = { - ".bash_history" = { - source = self + /programs/bash/.bash_history; - }; - }; - }; - swarselsystems = { - modules.general = lib.mkForce true; + # nix build --print-out-paths --no-link .#images..live-iso + packages.live-iso = inputs.nixos-generators.nixosGenerate { + inherit pkgs; + modules = [ + inputs.home-manager.nixosModules.home-manager + ./installer-config.nix + ]; + format = + { + x86_64-linux = "install-iso"; + aarch64-linux = "sd-aarch64-installer"; + }.${system}; }; }; - home-manager.users.root.home = { - stateVersion = "23.05"; - file = { - ".bash_history" = { - source = self + /programs/bash/.bash_history; - }; - }; - }; - - # environment.etc."issue".text = "\x1B[32m~SwarselSystems~\x1B[0m\nIP of primary interface: \x1B[31m\\4\x1B[0m\nThe Password for all users & root is '\x1B[31msetup\x1B[0m'.\nInstall the system remotely by running '\x1B[33mbootstrap -n -d [--impermanence] [--encryption]\x1B[0m' on a machine with deployed secrets.\nAlternatively, run '\x1B[33mswarsel-install -d -f \x1B[0m' for a local install.\n"; - environment.etc."issue".source = "${self}/programs/etc/issue"; - networking.dhcpcd.runHook = "${pkgs.utillinux}/bin/agetty --reload"; - - isoImage = { - makeEfiBootable = true; - makeUsbBootable = true; - squashfsCompression = "zstd -Xcompression-level 3"; - }; - - nixpkgs = { - hostPlatform = lib.mkDefault "x86_64-linux"; - config.allowUnfree = true; - }; - - services.getty.autologinUser = lib.mkForce "setup"; - - users = { - allowNoPasswordLogin = true; - groups.swarsel = { }; - users = { - setup = { - name = "setup"; - group = "setup"; - isNormalUser = true; - password = "setup"; # this is overwritten after install - openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key); - extraGroups = [ "wheel" ]; - }; - root = { - # password = lib.mkForce config.users.users.swarsel.password; # this is overwritten after install - openssh.authorizedKeys.keys = config.users.users."setup".openssh.authorizedKeys.keys; - }; - }; - }; - - boot = { - loader.systemd-boot.enable = lib.mkForce true; - loader.efi.canTouchEfiVariables = true; - }; - - programs.bash.shellAliases = { - "swarsel-install" = "nix run github:Swarsel/.dotfiles#swarsel-install --"; - }; - - system.activationScripts.cache = { - text = '' - mkdir -p -m=0777 /home/setup/.local/state/nix/profiles - mkdir -p -m=0777 /home/setup/.local/state/home-manager/gcroots - mkdir -p -m=0777 /home/setup/.local/share/nix/ - printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /home/setup/.local/share/nix/trusted-settings.json > /dev/null - mkdir -p /root/.local/share/nix/ - printf '{\"extra-substituters\":{\"https://nix-community.cachix.org\":true,\"https://nix-community.cachix.org https://cache.ngi0.nixos.org/\":true},\"extra-trusted-public-keys\":{\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=\":true,\"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA=\":true}}' | tee /root/.local/share/nix/trusted-settings.json > /dev/null - ''; - }; - systemd = { - services.sshd.wantedBy = lib.mkForce [ "multi-user.target" ]; - targets = { - sleep.enable = false; - suspend.enable = false; - hibernate.enable = false; - hybrid-sleep.enable = false; - }; - }; - - system.stateVersion = lib.mkForce "23.05"; - - networking = { - hostName = "drugstore"; - wireless.enable = false; - }; - }; } diff --git a/nix/templates.nix b/nix/templates.nix index ded942a..3b811c7 100644 --- a/nix/templates.nix +++ b/nix/templates.nix @@ -7,7 +7,7 @@ (name: { inherit name; value = { - path = "${self}/templates/${name}"; + path = "${self}/files/templates/${name}"; description = "${name} project "; }; }) diff --git a/nix/topology.nix b/nix/topology.nix index 2fec00a..469e6ba 100644 --- a/nix/topology.nix +++ b/nix/topology.nix @@ -47,7 +47,7 @@ pfsense = mkRouter "pfSense" { info = "HUNSN RM02"; - image = "${self}/topology-images/hunsn.png"; + image = "${self}/files/topology-images/hunsn.png"; interfaceGroups = [ [ "eth2" @@ -96,7 +96,7 @@ wifi-ap = mkSwitch "Wi-Fi AP" { info = "Huawei"; - image = "${self}/topology-images/huawei.png"; + image = "${self}/files/topology-images/huawei.png"; interfaceGroups = [ [ "eth1" @@ -107,7 +107,7 @@ switch-livingroom = mkSwitch "Switch Livingroom" { info = "TL-SG108"; - image = "${self}/topology-images/TL-SG108.png"; + image = "${self}/files/topology-images/TL-SG108.png"; interfaceGroups = [ [ "eth1" @@ -129,13 +129,13 @@ nswitch = mkDevice "Nintendo Switch" { info = "Nintendo Switch"; - image = "${self}/topology-images/nintendo-switch.png"; + image = "${self}/files/topology-images/nintendo-switch.png"; interfaces.eth1 = { }; }; pc = mkDevice "Windows Gaming Server" { info = "i7-4790k, GTX970, 32GB RAM"; - image = "${self}/topology-images/pc.png"; + image = "${self}/files/topology-images/pc.png"; interfaces.eth1 = { }; }; @@ -143,7 +143,7 @@ switch-bedroom = mkSwitch "Switch Bedroom" { info = "TL-SG1005D"; - image = "${self}/topology-images/TL-SG1005D.png"; + image = "${self}/files/topology-images/TL-SG1005D.png"; interfaceGroups = [ [ "eth1" @@ -158,7 +158,7 @@ printer = mkDevice "Printer" { info = "DELL C2665dnf"; - image = "${self}/topology-images/DELL-C2665dnf.png"; + image = "${self}/files/topology-images/DELL-C2665dnf.png"; interfaces.eth1 = { }; }; diff --git a/pkgs/e/default.nix b/pkgs/e/default.nix index 94a201d..7043846 100644 --- a/pkgs/e/default.nix +++ b/pkgs/e/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ emacs30-pgtk sway jq ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/fs-diff/default.nix b/pkgs/fs-diff/default.nix index de6a2e6..978ac41 100644 --- a/pkgs/fs-diff/default.nix +++ b/pkgs/fs-diff/default.nix @@ -1,5 +1,5 @@ { self, name, writeShellApplication }: writeShellApplication { inherit name; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/opacitytoggle/default.nix b/pkgs/opacitytoggle/default.nix index 4c65c9f..d6c547b 100644 --- a/pkgs/opacitytoggle/default.nix +++ b/pkgs/opacitytoggle/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ sway ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/pass-fuzzel/default.nix b/pkgs/pass-fuzzel/default.nix index 48afb79..ae34790 100644 --- a/pkgs/pass-fuzzel/default.nix +++ b/pkgs/pass-fuzzel/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ libnotify (pass.withExtensions (exts: [ exts.pass-otp ])) fuzzel wtype ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/project/default.nix b/pkgs/project/default.nix index de6a2e6..978ac41 100644 --- a/pkgs/project/default.nix +++ b/pkgs/project/default.nix @@ -1,5 +1,5 @@ { self, name, writeShellApplication }: writeShellApplication { inherit name; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/screenshare/default.nix b/pkgs/screenshare/default.nix index 4c65c9f..d6c547b 100644 --- a/pkgs/screenshare/default.nix +++ b/pkgs/screenshare/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ sway ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/sshrm/default.nix b/pkgs/sshrm/default.nix index 6c3749b..31f6957 100644 --- a/pkgs/sshrm/default.nix +++ b/pkgs/sshrm/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ openssh ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/swarsel-bootstrap/default.nix b/pkgs/swarsel-bootstrap/default.nix index 6c3749b..31f6957 100644 --- a/pkgs/swarsel-bootstrap/default.nix +++ b/pkgs/swarsel-bootstrap/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ openssh ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/swarsel-displaypower/default.nix b/pkgs/swarsel-displaypower/default.nix index 4c65c9f..d6c547b 100644 --- a/pkgs/swarsel-displaypower/default.nix +++ b/pkgs/swarsel-displaypower/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ sway ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/swarsel-install/default.nix b/pkgs/swarsel-install/default.nix index 6799593..41cc1ea 100644 --- a/pkgs/swarsel-install/default.nix +++ b/pkgs/swarsel-install/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ git ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/swarsel-postinstall/default.nix b/pkgs/swarsel-postinstall/default.nix index 6799593..41cc1ea 100644 --- a/pkgs/swarsel-postinstall/default.nix +++ b/pkgs/swarsel-postinstall/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ git ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/swarsel-rebuild/default.nix b/pkgs/swarsel-rebuild/default.nix index 6799593..41cc1ea 100644 --- a/pkgs/swarsel-rebuild/default.nix +++ b/pkgs/swarsel-rebuild/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ git ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/swarselcheck/default.nix b/pkgs/swarselcheck/default.nix index 11d0aa5..7504de3 100644 --- a/pkgs/swarselcheck/default.nix +++ b/pkgs/swarselcheck/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ kitty element-desktop vesktop spotify-player jq ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/swarselzellij/default.nix b/pkgs/swarselzellij/default.nix index f2f8fb1..1615bef 100644 --- a/pkgs/swarselzellij/default.nix +++ b/pkgs/swarselzellij/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ kitty ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/pkgs/waybarupdate/default.nix b/pkgs/waybarupdate/default.nix index 6799593..41cc1ea 100644 --- a/pkgs/waybarupdate/default.nix +++ b/pkgs/waybarupdate/default.nix @@ -2,5 +2,5 @@ writeShellApplication { inherit name; runtimeInputs = [ git ]; - text = builtins.readFile "${self}/scripts/${name}.sh"; + text = builtins.readFile "${self}/files/scripts/${name}.sh"; } diff --git a/programs/bash/.bash_history b/programs/bash/.bash_history deleted file mode 100644 index 3e879d2..0000000 --- a/programs/bash/.bash_history +++ /dev/null @@ -1 +0,0 @@ -swarsel-install -n chaostheatre diff --git a/programs/emacs/custom.el b/programs/emacs/custom.el deleted file mode 100644 index cdcad2f..0000000 --- a/programs/emacs/custom.el +++ /dev/null @@ -1,36 +0,0 @@ -;; (custom-set-variables - ;; custom-set-variables was added by Custom. - ;; If you edit it by hand, you could mess it up, so be careful. - ;; Your init file should contain only one such instance. - ;; If there is more than one, they won't work right. - ;; '(custom-safe-themes - ;; '("7ec8fd456c0c117c99e3a3b16aaf09ed3fb91879f6601b1ea0eeaee9c6def5d9" - ;; "badd1a5e20bd0c29f4fe863f3b480992c65ef1fa63951f59aa5d6b129a3f9c4c" - ;; "2e05569868dc11a52b08926b4c1a27da77580daa9321773d92822f7a639956ce" - ;; default)) - ;; '(send-mail-function 'sendmail-send-it)) -;; (custom-set-faces -;; ;; custom-set-faces was added by Custom. -;; ;; If you edit it by hand, you could mess it up, so be careful. -;; ;; Your init file should contain only one such instance. -;; ;; If there is more than one, they won't work right. -;; '(evil-goggles-change-face ((t (:inherit diff-removed)))) -;; '(evil-goggles-delete-face ((t (:inherit diff-removed)))) -;; '(evil-goggles-paste-face ((t (:inherit diff-added)))) -;; '(evil-goggles-undo-redo-add-face ((t (:inherit diff-added)))) -;; '(evil-goggles-undo-redo-change-face ((t (:inherit diff-changed)))) -;; '(evil-goggles-undo-redo-remove-face ((t (:inherit diff-removed)))) -;; '(evil-goggles-yank-face ((t (:inherit diff-changed)))) -;; '(flycheck-posframe-border-face ((t (:foreground "darkgrey")))) -;; '(ivy-current-match ((t (:extend t :background "dark cyan" :foreground "black")))) -;; '(org-block ((t (:inherit fixed-pitch :extend t :background "#20282F")))) -;; '(org-block-begin-line ((t (:inherit org-block :extend t :background "#20282F" :foreground "DeepSkyBlue4" :weight bold))))) -;; (custom-set-faces - ;; custom-set-faces was added by Custom. - ;; If you edit it by hand, you could mess it up, so be careful. - ;; Your init file should contain only one such instance. - ;; If there is more than one, they won't work right. - ;; '(highlight-indent-guides-even-face ((t (:background "gray10")))) - ;; '(highlight-indent-guides-odd-face ((t (:background "gray20")))) - ;; '(highlight-indent-guides-stack-even-face ((t (:background "gray40")))) - ;; '(highlight-indent-guides-stack-odd-face ((t (:background "gray50"))))) diff --git a/programs/etc/issue b/programs/etc/issue deleted file mode 100644 index f05e80d..0000000 --- a/programs/etc/issue +++ /dev/null @@ -1,5 +0,0 @@ -~SwarselSystems~ - IP of primary interface: \4 - The Password for all users & root is 'setup'. - Install the system remotely by running 'bootstrap -n -d ' on a machine with deployed secrets. - Alternatively, run 'swarsel-install -n ' for a local install. For your convenience, an example call is in the bash history (press up on the keyboard to access). diff --git a/programs/firefox/tridactyl/themes/base16-codeschool.css b/programs/firefox/tridactyl/themes/base16-codeschool.css deleted file mode 100644 index b61c643..0000000 --- a/programs/firefox/tridactyl/themes/base16-codeschool.css +++ /dev/null @@ -1,153 +0,0 @@ -:root { /* Codeschool by Chris Kempson (http://chriskempson.com) */ - --base00: #232c31; - --base01: #1c3657; - --base02: #2a343a; - --base03: #3f4944; - --base04: #84898c; - --base05: #9ea7a6; - --base06: #a7cfa3; - --base07: #b5d8f6; - --base08: #2a5491; - --base09: #43820d; - --base0A: #a03b1e; - --base0B: #237986; - --base0C: #b02f30; - --base0D: #484d79; - --base0E: #c59820; - --base0F: #c98344; - - --tridactyl-fg: var(--base05); - --tridactyl-bg: var(--base00); - --tridactyl-url-fg: var(--base08); - --tridactyl-url-bg: var(--base00); - --tridactyl-highlight-box-bg: var(--base0B); - --tridactyl-highlight-box-fg: var(--base00); - - /* Hint character tags */ - --tridactyl-hintspan-fg: var(--base00) !important; - --tridactyl-hintspan-bg: var(--base0A) !important; - - /* Element Highlights */ - --tridactyl-hint-active-fg: none; - --tridactyl-hint-active-bg: none; - --tridactyl-hint-active-outline: none; - --tridactyl-hint-bg: none; - --tridactyl-hint-outline: none; -} - -#command-line-holder { order: 1; - border: 2px solid var(--base0B); - color: var(--tridactyl-bg); -} - -#tridactyl-input { padding: 1rem; - color: var(--tridactyl-fg); - width: 90%; - font-size: 1.5rem; - line-height: 1.5; - background: var(--tridactyl-bg); - padding-left: unset; - padding: 1rem; -} - -#completions table { font-size: 0.8rem; - font-weight: 200; - border-spacing: 0; - table-layout: fixed; - padding: 1rem; - padding-top: 1rem; - padding-bottom: 1rem; -} - -#completions > div { max-height: calc(70 * var(--option-height)); - min-height: calc(10 * var(--option-height)); -} - -/* COMPLETIONS */ - -#completions { --option-height: 1.4em; - color: var(--tridactyl-fg); - background: var(--tridactyl-bg); - display: inline-block; - font-size: unset; - font-weight: 200; - overflow: hidden; - width: 100%; - border-top: unset; - order: 2; -} - -/* Olie doesn't know how CSS inheritance works */ -#completions .HistoryCompletionSource { max-height: unset; - min-height: unset; -} - -#completions .HistoryCompletionSource table { width: 100%; - font-size: 9pt; - border-spacing: 0; - table-layout: fixed; -} - -/* redundancy 2: redundancy 2: more redundancy */ -#completions .BmarkCompletionSource { max-height: unset; - min-height: unset; -} - -#completions table tr td.prefix,#completions table tr td.privatewindow,#completions table tr td.container,#completions table tr td.icon { display: true; -} - -#completions .BufferCompletionSource table { width: unset; - font-size: unset; - border-spacing: unset; - table-layout: unset; -} - -#completions table tr .title { width: 50%; -} - -#completions table tr { white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -#completions .sectionHeader { background: unset; - font-weight: 200; - border-bottom: unset; - padding: 1rem !important; - padding-left: unset; - padding-bottom: 0.2rem; -} - -#cmdline_iframe { position: fixed !important; - bottom: unset; - top: 25% !important; - left: 10% !important; - z-index: 2147483647 !important; - width: 80% !important; - box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 20px !important; -} - -.TridactylStatusIndicator { position: fixed !important; - bottom: 0 !important; - background: var(--tridactyl-bg) !important; - border: unset !important; - border: 1px var(--base0B) solid !important; - font-size: 12pt !important; - /*font-weight: 200 !important;*/ - padding: 0.8ex !important; -} - -#completions .focused { background: var(--base0B); - color: var(--base00); -} - -#completions .focused .url { background: var(--base0B); - color: var(--base00); -} -/* #Ocean-normal { */ -/* border-color: green !important; */ -/* } */ - -/* #Ocean-insert { */ -/* border-color: yellow !important; */ -/* } */ diff --git a/programs/server/prometheus/web.config b/programs/server/prometheus/web.config deleted file mode 100644 index 19d9d31..0000000 --- a/programs/server/prometheus/web.config +++ /dev/null @@ -1,2 +0,0 @@ -basic_auth_users: - admin: $2a$12$UFCdK2B67OM.p51ON8eKLOxQ4Ek9jruJPtaLE4Owc4Ukf7jGx//LC