diff --git a/SwarselSystems.org b/SwarselSystems.org index 8364d02..54fa9b0 100644 --- a/SwarselSystems.org +++ b/SwarselSystems.org @@ -2,6 +2,7 @@ #+PROPERTY: header-args:emacs-lisp :tangle programs/emacs/init.el :mkdirp yes #+PROPERTY: header-args:nix :mkdirp yes #+PROPERTY: header-args:nix-ts :mkdirp yes +#+PROPERTY: header-args:shell :mkdirp yes #+EXPORT_FILE_NAME: index.html #+OPTIONS: toc:6 #+macro: revision-date (eval (format-time-string "%F %T %z")) @@ -1550,6 +1551,12 @@ This machine mainly acts as an external sync helper. It manages the following th All of these are processes that use little cpu but can take a lot of storage. For this I use a free Ampere instance from OCI with 50G of space. In case my account gets terminated, all of this data is easily replaceable or backed up regularly anyways. + +***** Main configuration +:PROPERTIES: +:CUSTOM_ID: h:922105c3-a604-47d9-918b-db1803784c75 +:END: + #+begin_src nix-ts :tangle hosts/nixos/sync/default.nix { lib, config, primaryUser, ... }: let @@ -1559,6 +1566,7 @@ This machine mainly acts as an external sync helper. It manages the following th }; 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 = [ @@ -1603,11 +1611,12 @@ This machine mainly acts as an external sync helper. It manages the following th 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; @@ -1663,7 +1672,7 @@ This machine mainly acts as an external sync helper. It manages the following th type = "receiveonly"; versioning = { type = "simple"; - params.keep = "5"; + params.keep = "5"; }; devices = [ "winters" "magicant" "${workHostName}" ]; id = "yjvni-9eaa7"; @@ -1726,6 +1735,51 @@ This machine mainly acts as an external sync helper. It manages the following th } #+end_src +***** hardware-configuration +:PROPERTIES: +:CUSTOM_ID: h:64dddedd-9b13-4b74-baf0-1d54d5a89d3b +:END: + +#+begin_src nix-ts :tangle hosts/nixos/sync/hardware-configuration.nix + { config, lib, modulesPath, ... }: { + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + ]; + + boot = { + initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" ]; + initrd.kernelModules = [ ]; + kernelModules = [ "kvm-amd" ]; + extraModulePackages = [ ]; + }; + + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/4b47378a-02eb-4548-bab8-59cbf379252a"; + fsType = "xfs"; + }; + + "/boot" = { + device = "/dev/disk/by-uuid/2B75-2AD5"; + fsType = "vfat"; + }; + }; + + swapDevices = [ + { device = "/dev/disk/by-uuid/f0126a93-753e-4769-ada8-7499a1efb3a9"; } + ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.ens3.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + } +#+end_src **** Moonside (OCI) :PROPERTIES: :CUSTOM_ID: h:f547ed16-5e6e-4744-9e33-af090e0a175b @@ -1740,6 +1794,8 @@ This machine mainly acts as an external sync helper. It manages the following th let 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; @@ -1778,7 +1834,7 @@ This machine mainly acts as an external sync helper. It manages the following th }; topology.self.interfaces.wg = { - addresses = ["192.168.3.4"]; + addresses = [ "192.168.3.4" ]; renderer.hidePhysicalConnections = true; virtual = true; type = "wireguard"; @@ -1821,10 +1877,12 @@ This machine mainly acts as an external sync helper. It manages the following th 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; @@ -1970,11 +2028,6 @@ This machine mainly acts as an external sync helper. It manages the following th :CUSTOM_ID: h:f99c05ab-f047-4350-b80a-4c1ff55b91bf :END: - loader.grub = { - efiSupport = true; - efiInstallAsRemovable = true; - device = "nodev"; - }; #+begin_src nix-ts :tangle hosts/nixos/moonside/hardware-configuration.nix { lib, modulesPath, ... }: { @@ -1983,7 +2036,7 @@ This machine mainly acts as an external sync helper. It manages the following th boot = { initrd = { availableKernelModules = [ "xhci_pci" "virtio_pci" "virtio_scsi" "usbhid" ]; - kernelModules = [ ]; + kernelModules = [ ]; }; kernelModules = [ ]; extraModulePackages = [ ]; @@ -2373,7 +2426,7 @@ This is a live environment ISO that I use to bootstrap new systems. It only load 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 +#+begin_src bash :tangle programs/etc/issue :mkdirp yes ~SwarselSystems~ IP of primary interface: \4 The Password for all users & root is 'setup'. @@ -2670,6 +2723,142 @@ I also set the =WLR_RENDERER_ALLOW_SOFTWARE=1= to allow this configuration to ru #+end_src +***** disko +:PROPERTIES: +:CUSTOM_ID: h:849e4233-ba40-4fec-acfe-0d76e1e4371b +: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" + ]; + }; + "/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" + ]; + }; + 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; + + environment.systemPackages = [ + pkgs.yubikey-manager + ]; +} +#+end_src + ***** NixOS dummy options configuration :PROPERTIES: :CUSTOM_ID: h:6f9c1a3b-452e-4944-86e8-cb17603cc3f9 @@ -2738,7 +2927,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 +#+begin_src shell :tangle 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 @@ -4612,7 +4801,7 @@ When adding a new entry here, do not forget to add it in the default output of t }; }; - nixpkgs-kernel = final: _: { + nixpkgs-kernel = final: _: { kernel = import inputs.nixpkgs-kernel { inherit (final) system; config.allowUnfree = true; @@ -4736,6 +4925,7 @@ Modules that need to be loaded on the NixOS level. Note that these will not be a lid = lib.mkDefault true; lowBattery = lib.mkDefault true; lanzaboote = lib.mkDefault true; + tmp = lib.mkDefault true; optional = { gaming = lib.mkDefault true; @@ -5022,12 +5212,12 @@ Modules that need to be loaded on the NixOS level. Note that these will not be a paperless = lib.mkDefault true; transmission = lib.mkDefault true; syncthing = lib.mkDefault true; - monitoring = lib.mkDefault true; + grafana = lib.mkDefault true; emacs = lib.mkDefault true; freshrss = lib.mkDefault true; jenkins = lib.mkDefault false; kanidm = lib.mkDefault true; - firefly = lib.mkDefault true; + firefly-iii = lib.mkDefault true; koillection = lib.mkDefault true; radicale = lib.mkDefault true; atuin = lib.mkDefault true; @@ -5101,7 +5291,7 @@ Modules that need to be loaded on the NixOS level. Note that these will not be a sops = lib.mkDefault true; nginx = lib.mkDefault true; ssh = lib.mkDefault true; - oauth2Proxy = lib.mkDefault true; + oauth2-proxy = lib.mkDefault true; croc = lib.mkDefault true; microbin = lib.mkDefault true; shlink = lib.mkDefault true; @@ -5402,7 +5592,7 @@ TODO upper = lib.toUpper first; lower = lib.toLower rest; in - upper + lower; + upper + lower; # mkUser = name: { @@ -5499,33 +5689,33 @@ TODO :END: #+begin_src nix-ts :tangle nix/extra-builtins.nix -# 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 - ]; -} + # 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 + ]; + } #+end_src **** sops-decrypt-and-cache @@ -5533,8 +5723,7 @@ in :CUSTOM_ID: h:315e6ef6-27d5-4cd8-85ff-053eabe60ddb :END: -#+begin_src shell :tangle nix/sops-decrypt-and-cache.sh - #!/usr/bin/env bash +#+begin_src shell :tangle nix/sops-decrypt-and-cache.sh :shebang #!/usr/bin/env bash # adapted from https://github.com/oddlama/nix-config/blob/main/nix/rage-decrypt-and-cache.sh set -euo pipefail @@ -5636,7 +5825,7 @@ in ] [ "wan" ] ]; - interfaces.wg0 = { + interfaces.wg = { addresses = [ "192.168.3.1" ]; network = "wg"; virtual = true; @@ -5751,14 +5940,10 @@ in :END: #+begin_src nix-ts :tangle nix/globals.nix + # taken from https://github.com/oddlama/nix-config/blob/main/nix/globals.nix { inputs, ... }: { - flake = - { - config, - lib, - ... - }: + flake = { config, lib, ... }: { globals = let @@ -5771,6 +5956,7 @@ in }; modules = [ ../modules/nixos/common/globals.nix + ./globals-general.nix ( { lib, ... }: { @@ -5778,7 +5964,7 @@ in 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 + builtins.addErrorContext "while aggregating globals from nixosConfigurations.${name} into flake-level globals:" cfg.config._globalsDefs ) ) ); @@ -5793,14 +5979,35 @@ in inherit (globalsSystem.config.globals) domains services - macs - myuser - root + user ; }; }; } +#+end_src +**** Set general global options + +This file is only loaded in the =lib.evalModules= call in [[#h:af83893d-c0f9-4b45-b816-4849110d41b3][Globals]] to load globals that do not belong to one host in particular; the structure of =globals.nix.enc= requires a toplevel =globals=. + +#+begin_src nix-ts :tangle nix/globals-general.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) + ]; + + } + #+end_src ** NixOS :PROPERTIES: @@ -5969,6 +6176,11 @@ A breakdown of the flags being set: }; services.dbus.implementation = "broker"; + + systemd.services.nix-daemon = { + environment.TMPDIR = "/var/tmp"; + }; + system.stateVersion = lib.mkDefault "23.05"; }; } @@ -6052,81 +6264,55 @@ A breakdown of the flags being set: :END: #+begin_src nix-ts :tangle modules/nixos/common/globals.nix -{ lib, options, ... }: -let - inherit (lib) - mkOption - types - ; - -in -{ - options = { - globals = mkOption { - default = { }; - type = types.submodule { - options = { - root = { - hashedPassword = mkOption { - type = types.str; - description = "My root user's password hash."; + { lib, options, ... }: + let + inherit (lib) + mkOption + types + ; + in + { + options = { + globals = mkOption { + default = { }; + type = types.submodule { + options = { + user = { + name = mkOption { + type = types.str; + }; }; - }; - - 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"; + services = mkOption { + type = types.attrsOf ( + types.submodule { + options = { + domain = mkOption { + type = types.str; + }; }; - }; - } - ); - }; - - domains = { - me = mkOption { - type = types.str; - description = "My main domain."; + } + ); }; - personal = mkOption { - type = types.str; - description = "My personal domain."; + domains = { + main = mkOption { + type = types.str; + }; }; }; - - macs = mkOption { - default = { }; - type = types.attrsOf types.str; - description = "Known MAC addresses for external devices."; - }; }; }; - }; - _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 **** System Packages @@ -6231,7 +6417,7 @@ Mostly used to install some compilers and lsp's that I want to have available wh 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). #+begin_src nix-ts :tangle modules/nixos/common/home-manager.nix - { inputs, config, lib, ... }: + { inputs, config, lib, outputs, globals, nodes, ... }: { options.swarselsystems.modules.home-manager = lib.mkEnableOption "home-manager"; @@ -6243,11 +6429,11 @@ We enable the use of =home-manager= as a NixoS module. A nice trick here is the sharedModules = [ inputs.nix-index-database.hmModules.nix-index inputs.sops-nix.homeManagerModules.sops - { - home.stateVersion = lib.mkDefault config.system.stateVersion; - } + { + home.stateVersion = lib.mkDefault config.system.stateVersion; + } ]; - extraSpecialArgs = { inherit (inputs) self; }; + extraSpecialArgs = { inherit (inputs) self; inherit inputs outputs globals nodes; }; }; }; } @@ -6551,6 +6737,7 @@ Here I only enable =networkmanager= and a few default networks. The rest of the networkmanager = { enable = true; + wifi.backend = "iwd"; ensureProfiles = lib.mkIf (!config.swarselsystems.isPublic) { environmentFiles = [ "${config.sops.templates."network-manager.env".path}" @@ -6936,7 +7123,7 @@ I use sops-nix to handle secrets that I want to have available on my machines at :CUSTOM_ID: h:82b8ede2-02d8-4c43-8952-7200ebd4dc23 :END: -#+begin_src nix-ts :tangle modules/nixos/common/pii.nix +#+begin_src nix-ts :tangle modules/nixos/common/pii.nix # largely based on https://github.com/oddlama/nix-config/blob/main/modules/secrets.nix { config, inputs, lib, ... }: let @@ -7659,6 +7846,7 @@ Normally, doing that also resets the lecture that happens on the first use of =s "/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"; @@ -7677,6 +7865,18 @@ Normally, doing that also resets the lecture that happens on the first use of =s } #+end_src +**** Mount /tmp inside tmpfs + +#+begin_src nix-ts :tangle modules/nixos/common/tmp.nix + { config, lib, ... }: + { + options.swarselsystems.modules.tmp = lib.mkEnableOption "tmp dir config"; + config = lib.mkIf config.swarselsystems.modules.tmp { + boot.tmp.useTmpfs = !config.swarselsystems.modules.impermanence true; + }; + } +#+end_src + **** Summary of nixos-rebuild diff :PROPERTIES: :CUSTOM_ID: h:b751d77d-246c-4bd6-b689-3467d82bf9c3 @@ -7917,7 +8117,7 @@ Since I hide the waybar completely during normal operation, I run the risk of no } #+end_src -**** Lanzaboote +**** Lanzaboote (secure boot) :PROPERTIES: :CUSTOM_ID: h:d9a89071-b3ba-44d1-b5e0-e9ca6270d377 :END: @@ -8078,7 +8278,10 @@ Here we just define some aliases for rebuilding the system, and we allow some in :END: #+begin_src nix-ts :tangle modules/nixos/server/nfs.nix - { 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 { @@ -8109,7 +8312,7 @@ Here we just define some aliases for rebuilding the system, and we allow some in path = "/Vault/Eternor"; writable = "true"; comment = "Eternor"; - "valid users" = "Swarsel"; + "valid users" = nfsUser; }; }; @@ -8138,6 +8341,10 @@ Here we just define some aliases for rebuilding the system, and we allow some in #+begin_src nix-ts :tangle modules/nixos/server/nginx.nix { 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 { @@ -8157,8 +8364,8 @@ Here we just define some aliases for rebuilding the system, and we allow some in acceptTerms = true; preliminarySelfsigned = false; defaults = { - email = "mrswarsel@gmail.com"; - dnsProvider = "cloudflare"; + inherit dnsProvider; + email = address3; environmentFile = "${config.sops.templates."certs.secret".path}"; }; }; @@ -8226,44 +8433,44 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t #+begin_src nix-ts :tangle modules/nixos/server/kavita.nix { 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}/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}" = { }; }; @@ -8297,15 +8504,15 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t #+begin_src nix-ts :tangle modules/nixos/server/jellyfin.nix { 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: { @@ -8324,7 +8531,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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 @@ -8332,7 +8539,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; @@ -8367,15 +8574,15 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t #+begin_src nix-ts :tangle modules/nixos/server/navidrome.nix { 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 @@ -8384,13 +8591,13 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t users = { groups = { - "${serviceGroup}" = { + ${serviceGroup} = { gid = 61593; }; }; users = { - "${serviceUser}" = { + ${serviceUser} = { isSystemUser = true; uid = 61593; group = serviceGroup; @@ -8403,11 +8610,11 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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 = { @@ -8449,7 +8656,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; @@ -8475,19 +8682,19 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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; @@ -8517,13 +8724,13 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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; @@ -8559,25 +8766,31 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t #+begin_src nix-ts :tangle modules/nixos/server/mpd.nix { 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; [ @@ -8586,19 +8799,19 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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}/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 = [ @@ -8658,13 +8871,13 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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}"; }; }; }; @@ -8679,17 +8892,18 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t #+begin_src nix-ts :tangle modules/nixos/server/matrix.nix { 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 *; @@ -8697,8 +8911,8 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t ''; 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 @@ -8707,24 +8921,24 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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} @@ -8735,7 +8949,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t }; }; - networking.firewall.allowedTCPPorts = [ 8008 8448 ]; + networking.firewall.allowedTCPPorts = [ servicePort federationPort ]; systemd = { timers."restart-bridges" = { @@ -8766,7 +8980,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t }; }; - globals.services.${serviceName}.domain = matrixDomain; + globals.services.${serviceName}.domain = serviceDomain; services = { postgresql = { @@ -8799,20 +9013,21 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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" @@ -8840,8 +9055,8 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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}"; @@ -8866,7 +9081,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t telegram_link_preview = true; permissions = { "*" = "relaybot"; - "@swarsel:${matrixDomain}" = "admin"; + "@swarsel:${serviceDomain}" = "admin"; }; animated_sticker = { target = "gif"; @@ -8886,8 +9101,8 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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}"; @@ -8912,7 +9127,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t }; }; login_shared_secret_map = { - matrixDomain = "as_token:doublepuppet"; + ${serviceDomain} = "as_token:doublepuppet"; }; sync_manual_marked_unread = true; send_presence_on_typing = true; @@ -8922,7 +9137,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t extev_polls = true; permissions = { "*" = "relay"; - "@swarsel:${matrixDomain}" = "admin"; + "@swarsel:${serviceDomain}" = "admin"; }; }; }; @@ -8933,8 +9148,8 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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}"; @@ -8948,12 +9163,12 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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"; }; }; }; @@ -8966,14 +9181,14 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t 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; @@ -9030,14 +9245,17 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t #+begin_src nix-ts :tangle modules/nixos/server/nextcloud.nix { 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 = { @@ -9056,7 +9274,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t globals.services.${serviceName}.domain = serviceDomain; services = { - nextcloud = { + ${serviceName} = { enable = true; settings = { trusted_proxies = [ "0.0.0.0" ]; @@ -9064,8 +9282,8 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t }; 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"; @@ -9074,7 +9292,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t }; extraAppsEnable = true; config = { - adminuser = "admin"; + inherit adminuser; adminpassFile = config.sops.secrets.nextcloudadminpass.path; dbtype = "sqlite"; }; @@ -9083,9 +9301,9 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { - "192.168.1.2:80" = { }; + "192.168.1.2:${builtins.toString servicePort}" = { }; }; }; }; @@ -9114,23 +9332,23 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t #+begin_src nix-ts :tangle modules/nixos/server/immich.nix { 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; @@ -9145,7 +9363,7 @@ Here I am forcing =startWhenNeeded= to false so that the value will not be set t nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; @@ -9192,19 +9410,23 @@ This is my personal document management system. It automatically pulls documents Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml='s. This is needed for e.g. online services that only send their invoices through email body text. #+begin_src nix-ts :tangle modules/nixos/server/paperless.nix - { 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" ]; }; @@ -9222,25 +9444,25 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= 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 = { @@ -9252,7 +9474,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= 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"; } ]; }; @@ -9262,7 +9484,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= tika = { enable = true; - port = 9998; + port = tikaPort; openFirewall = false; listenAddress = "127.0.0.1"; enableOcr = true; @@ -9271,7 +9493,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= gotenberg = { enable = true; package = pkgs.stable.gotenberg; - port = 3002; + port = gotenbergPort; bindIP = "127.0.0.1"; timeout = "600s"; chromium.package = pkgs.stable.chromium; @@ -9291,7 +9513,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; @@ -9330,7 +9552,9 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= #+begin_src nix-ts :tangle modules/nixos/server/transmission.nix { 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; @@ -9348,8 +9572,8 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= 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 = { @@ -9518,34 +9742,37 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= { 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; @@ -9567,14 +9794,14 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= }; 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"; @@ -9584,7 +9811,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= id = "yjvni-9eaa7"; }; "Org" = { - path = "/Vault/data/syncthing/Org"; + path = "${cfg.dataDir}/Org"; type = "receiveonly"; versioning = { type = "simple"; @@ -9594,7 +9821,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= id = "a7xnl-zjj3d"; }; "Vpn" = { - path = "/Vault/data/syncthing/Vpn"; + path = "${cfg.dataDir}/Vpn"; type = "receiveonly"; versioning = { type = "simple"; @@ -9604,7 +9831,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= id = "hgp9s-fyq3p"; }; # "Documents" = { - # path = "/Vault/data/syncthing/Documents"; + # path = "${cfg.dataDir}/Documents"; # type = "receiveonly"; # versioning = { # type = "simple"; @@ -9619,7 +9846,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of =.eml= nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; @@ -9709,7 +9936,7 @@ This manages backups for my pictures and obsidian files. } #+end_src -**** monitoring (Grafana) +**** monitoring (Grafana, Prometheus) :PROPERTIES: :CUSTOM_ID: h:a31c7192-e11d-4a26-915d-1bbc38e373d3 :END: @@ -9717,26 +9944,47 @@ This manages backups for my pictures and obsidian files. 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. #+begin_src nix-ts :tangle modules/nixos/server/monitoring.nix - { self, lib, config, ... }: + { self, lib, config, globals, ... }: let - serviceDomain = "status.swarsel.win"; + servicePort = 3000; serviceUser = "grafana"; serviceGroup = serviceUser; - moduleName = "monitoring"; + serviceName = "grafana"; + serviceDomain = config.repo.secrets.common.services.domains.${serviceName}; + + prometheusPort = 9090; + prometheusUser = "prometheus"; + prometheusGroup = prometheusUser; + 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"; }; + 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 = { sopsFile = self + /secrets/winters/secrets2.yaml; owner = prometheusUser; group = prometheusGroup; mode = "0440"; }; + + }; + templates = { + "web-config" = { + content = '' + basic_auth_users: + admin: ${config.sops.placeholder.prometheus-admin-hash} + ''; + owner = prometheusUser; + group = prometheusGroup; + mode = "0440"; + }; + }; }; users = { @@ -9745,7 +9993,7 @@ This section exposes several metrics that I use to check the health of my server extraGroups = [ "nextcloud" ]; }; - "${serviceUser}" = { + ${serviceUser} = { extraGroups = [ "users" ]; }; }; @@ -9754,12 +10002,12 @@ This section exposes several metrics that I use to check the health of my server 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 = { @@ -9816,9 +10064,9 @@ This section exposes several metrics that I use to check the health of my server 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 @@ -9830,13 +10078,13 @@ This section exposes several metrics that I use to check the health of my server prometheus = { enable = true; - webExternalUrl = "https://status.swarsel.win/${prometheusWebRoot}"; + webExternalUrl = "https://${serviceDomain}/${prometheusWebRoot}"; port = prometheusPort; listenAddress = "0.0.0.0"; globalConfig = { scrape_interval = "10s"; }; - webConfigFile = self + /programs/server/prometheus/web.config; + webConfigFile = config.sops.templates.web-config.path; scrapeConfigs = [ { job_name = "node"; @@ -9890,8 +10138,8 @@ This section exposes several metrics that I use to check the health of my server 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; }; }; @@ -9949,26 +10197,26 @@ This is a WIP Jenkins instance. It is used to automatically build a new system w #+begin_src nix-ts :tangle modules/nixos/server/jenkins.nix { 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}" = { }; }; @@ -10004,13 +10252,17 @@ This was an approach of hosting an RSS server from within emacs. That would have #+begin_src nix-ts :tangle modules/nixos/server/emacs.nix { 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; @@ -10028,31 +10280,34 @@ This was an approach of hosting an RSS server from within emacs. That would have 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 FreshRSS claims to support HTTP header auth, but at least it does not work with my oauth2-proxy setup. Until this is fixed, I resorted to the "form" login, since I mostly do not use the web version anyways. #+begin_src nix-ts :tangle modules/nixos/server/freshrss.nix { 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 = { @@ -10066,7 +10321,7 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with # 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} @@ -10084,18 +10339,18 @@ 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/freshrss.png"; + icon = "${self}/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; }; @@ -10105,9 +10360,9 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { - "192.168.1.2:80" = { }; + "192.168.1.2:${builtins.toString servicePort}" = { }; }; }; }; @@ -10141,26 +10396,28 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with :END: #+begin_src nix-ts :tangle modules/nixos/server/forgejo.nix - { 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"; }; @@ -10168,7 +10425,7 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with globals.services.${serviceName}.domain = serviceDomain; - services.forgejo = { + services.${serviceName} = { enable = true; user = serviceUser; group = serviceGroup; @@ -10210,13 +10467,13 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with }; }; - 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 [ [ @@ -10233,7 +10490,7 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with ] [ "--auto-discover-url" - "https://sso.swarsel.win/oauth2/openid/${clientId}/.well-known/openid-configuration" + "https://${kanidmDomain}/oauth2/openid/${clientId}/.well-known/openid-configuration" ] [ "--scopes" @@ -10268,7 +10525,7 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; @@ -10301,15 +10558,17 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with :END: #+begin_src nix-ts :tangle modules/nixos/server/ankisync.nix - { 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 ]; @@ -10317,6 +10576,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"; info = "https://${serviceDomain}"; }; @@ -10329,7 +10589,7 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with openFirewall = true; users = [ { - username = "Swarsel"; + username = ankiUser; passwordFile = config.sops.secrets.swarsel.path; } ]; @@ -10337,7 +10597,7 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; @@ -10374,29 +10634,36 @@ The forgejo configuration is a little broken and will show a 500 error when sign A stupid (but simple) way to get the =originUrl= is to simply set any URL there and try to auth using kanidm. Then check the logs (=journalctl -eu kanidm=) and check for the line that says something along the lines of `🚧 [warn]: Invalid OAuth2 redirect_uri (must be an exact match to a redirect-url) - got ` -To get other URLs (token, etc.), use https:///oauth2/openid//.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:///oauth2/openid//.well-known/oauth-authorization-server, e.g. https:///oauth2/openid/nextcloud/.well-known/oauth-authorization-server, with clienID being the client name as specified in kanidm. #+begin_src nix-ts :tangle modules/nixos/server/kanidm.nix { 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 = { @@ -10419,7 +10686,7 @@ To get other URLs (token, etc.), use https:///oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid//oauth2/openid/ toolkit.legacyUserProfileCustomizations.styleshe Sets environment variables. Here I am only setting the EDITOR variable, most variables are set in the [[#h:02df9dfc-d1af-4a37-a7a0-d8da0af96a20][Sway]] section. #+begin_src nix-ts :tangle modules/home/common/env.nix - { 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"; @@ -13173,11 +13471,11 @@ Sets environment variables. Here I am only setting the EDITOR variable, most var 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; @@ -13339,7 +13637,10 @@ Eza provides me with a better =ls= command and some other useful aliases. :END: #+begin_src nix-ts :tangle modules/home/common/atuin.nix - { 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 { @@ -13349,7 +13650,7 @@ Eza provides me with a better =ls= command and some other useful aliases. settings = { auto_sync = true; sync_frequency = "5m"; - sync_address = "https://shellhistory.swarsel.win"; + sync_address = "https://${atuinDomain}"; }; }; }; @@ -13364,10 +13665,12 @@ Eza provides me with a better =ls= command and some other useful aliases. Here I set up my git config, automatic signing of commits, useful aliases for my ost used commands (for when I am not using [[#h:d2c7323d-f8c6-4f23-b70a-930e3e4ecce5][Magit]]) as well as a git template defined in [[#h:5ef03803-e150-41bc-b603-e80d60d96efc][Linking dotfiles]]. #+begin_src nix-ts :tangle modules/home/common/git.nix - { 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"; @@ -13391,15 +13694,15 @@ Here I set up my git config, automatic signing of commits, useful aliases for my 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"; @@ -13925,7 +14228,7 @@ Normally I use 4 mail accounts - here I set them all up. Three of them are Googl # 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 = { @@ -14152,7 +14455,7 @@ The rest of the related configuration is found here: - [[#h:f93f66f9-6b8b-478e-b139-b2f382c1f25e][waybarupdate]] #+begin_src nix-ts :tangle modules/home/common/waybar.nix - { self, config, lib, ... }: + { self, config, lib, pkgs, ... }: let generateIcons = n: lib.concatStringsSep " " (builtins.map (x: "{icon" + toString x + "}") (lib.range 0 (n - 1))); modulesLeft = [ @@ -14233,28 +14536,28 @@ The rest of the related configuration is found here: "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 = { @@ -14389,8 +14692,8 @@ The rest of the related configuration is found here: ]; }; 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 = { @@ -14404,13 +14707,13 @@ The rest of the related configuration is found here: 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; }; @@ -15363,7 +15666,7 @@ This service changes the screen hue at night. I am not sure if that really does { 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; @@ -15454,6 +15757,16 @@ This section sets up all the imports that are used in the home-manager section. Akin to the optional NixOS modules. +#+begin_src nix-ts :tangle modules/home/optional/default.nix + { lib, ... }: + let + importNames = lib.swarselsystems.readNix "modules/home/optional"; + in + { + imports = lib.swarselsystems.mkImports importNames "modules/home/optional"; + } +#+end_src + **** Gaming :PROPERTIES: :CUSTOM_ID: h:84fd7029-ecb6-4131-9333-289982f24ffa @@ -18701,6 +19014,9 @@ company is now disabled since it seems that corfu runs just fine with lsp-mode a #+end_src *** lsp-mode in org-src blocks +:PROPERTIES: +:CUSTOM_ID: h:cd552ba1-4db1-4605-8ead-4fcb6a466826 +:END: #+begin_src emacs-lisp ;; thanks to https://tecosaur.github.io/emacs-config/config.html#lsp-support-src @@ -19876,6 +20192,1591 @@ This file defines a few workflows that I often need to run when working on my co rsync -av --filter=':- .gitignore' -e "ssh -l {{USER}}" . {{USER}}@{{HOST}}:.dotfiles/ #+end_src +** aspell.conf +:PROPERTIES: +:CUSTOM_ID: h:038feb42-6e1e-4b65-abe9-e26746b72b78 +:END: + +#+begin_src shell :tangle programs/config/.aspell.conf +dict-dir /run/current-system/sw/lib/aspell +#+end_src +** nix-plugins.patch +:PROPERTIES: +:CUSTOM_ID: h:931ff2fd-61f0-4f8f-b221-d879780f38d7 +:END: + +#+begin_src diff :tangle nix/nix-plugins.patch +diff --git a/extra-builtins.cc b/extra-builtins.cc +index 3a0f90e..bb10f8b 100644 +--- a/extra-builtins.cc ++++ b/extra-builtins.cc +@@ -1,9 +1,9 @@ +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + + #include "nix-plugins-config.h" +#+end_src +** Zellij layout default.kdl.nix +:PROPERTIES: +:CUSTOM_ID: h:bed316c9-47ed-494f-8375-998ef1315d7b +:END: + +#+begin_src shell :tangle programs/zellij/layouts/default.kdl.nix +{ config, pkgs }: +let + inherit (config.lib.stylix) colors; +in +'' + layout { + swap_tiled_layout name="vertical" { + tab max_panes=5 { + pane split_direction="vertical" { + pane + pane { children; } + } + } + tab max_panes=8 { + pane split_direction="vertical" { + pane { children; } + pane { pane; pane; pane; pane; } + } + } + tab max_panes=12 { + pane split_direction="vertical" { + pane { children; } + pane { pane; pane; pane; pane; } + pane { pane; pane; pane; pane; } + } + } + } + + swap_tiled_layout name="horizontal" { + tab max_panes=5 { + pane + pane + } + tab max_panes=8 { + pane { + pane split_direction="vertical" { children; } + pane split_direction="vertical" { pane; pane; pane; pane; } + } + } + tab max_panes=12 { + pane { + pane split_direction="vertical" { children; } + pane split_direction="vertical" { pane; pane; pane; pane; } + pane split_direction="vertical" { pane; pane; pane; pane; } + } + } + } + + swap_tiled_layout name="stacked" { + tab min_panes=5 { + pane split_direction="vertical" { + pane + pane stacked=true { children; } + } + } + } + + swap_floating_layout name="staggered" { + floating_panes + } + + swap_floating_layout name="enlarged" { + floating_panes max_panes=10 { + pane { x "5%"; y 1; width "90%"; height "90%"; } + pane { x "5%"; y 2; width "90%"; height "90%"; } + pane { x "5%"; y 3; width "90%"; height "90%"; } + pane { x "5%"; y 4; width "90%"; height "90%"; } + pane { x "5%"; y 5; width "90%"; height "90%"; } + pane { x "5%"; y 6; width "90%"; height "90%"; } + pane { x "5%"; y 7; width "90%"; height "90%"; } + pane { x "5%"; y 8; width "90%"; height "90%"; } + pane { x "5%"; y 9; width "90%"; height "90%"; } + pane focus=true { x 10; y 10; width "90%"; height "90%"; } + } + } + + swap_floating_layout name="spread" { + floating_panes max_panes=1 { + pane {y "50%"; x "50%"; } + } + floating_panes max_panes=2 { + pane { x "1%"; y "25%"; width "45%"; } + pane { x "50%"; y "25%"; width "45%"; } + } + floating_panes max_panes=3 { + pane focus=true { y "55%"; width "45%"; height "45%"; } + pane { x "1%"; y "1%"; width "45%"; } + pane { x "50%"; y "1%"; width "45%"; } + } + floating_panes max_panes=4 { + pane { x "1%"; y "55%"; width "45%"; height "45%"; } + pane focus=true { x "50%"; y "55%"; width "45%"; height "45%"; } + pane { x "1%"; y "1%"; width "45%"; height "45%"; } + pane { x "50%"; y "1%"; width "45%"; height "45%"; } + } + } + + default_tab_template { + children + pane size=1 borderless=true { + plugin location="file://${pkgs.zjstatus}/bin/zjstatus.wasm" { + format_left "{mode}#[bg=#${colors.base00}] {tabs}" + format_center "" + format_right "#[bg=#${colors.base00},fg=#${colors.base02}]#[bg=#${colors.base02},fg=#${colors.base01},bold] #[bg=#${colors.base02},fg=#${colors.base01},bold] {session} #[bg=#${colors.base02},fg=#${colors.base01},bold]" + format_space "" + format_hide_on_overlength "false" + format_precedence "lcr" + + border_enabled "false" + border_char "─" + border_format "#[fg=#6C7086]{char}" + border_position "top" + + mode_normal "#[bg=#${colors.base0B},fg=#${colors.base01},bold] NORMAL#[bg=#${colors.base01},fg=#${colors.base0B}]█" + mode_locked "#[bg=#${colors.base04},fg=#${colors.base01},bold] LOCKED #[bg=#${colors.base01},fg=#${colors.base04}]█" + mode_resize "#[bg=#${colors.base08},fg=#${colors.base01},bold] RESIZE#[bg=#${colors.base01},fg=#${colors.base08}]█" + mode_pane "#[bg=#${colors.base0D},fg=#${colors.base01},bold] PANE#[bg=#${colors.base01},fg=#${colors.base0D}]█" + mode_tab "#[bg=#${colors.base07},fg=#${colors.base01},bold] TAB#[bg=#${colors.base01},fg=#${colors.base07}]█" + mode_scroll "#[bg=#${colors.base0A},fg=#${colors.base01},bold] SCROLL#[bg=#${colors.base01},fg=#${colors.base0A}]█" + mode_enter_search "#[bg=#${colors.base0D},fg=#${colors.base01},bold] ENT-SEARCH#[bg=#${colors.base01},fg=#${colors.base0D}]█" + mode_search "#[bg=#${colors.base0D},fg=#${colors.base01},bold] SEARCHARCH#[bg=#${colors.base01},fg=#${colors.base0D}]█" + mode_rename_tab "#[bg=#${colors.base07},fg=#${colors.base01},bold] RENAME-TAB#[bg=#${colors.base01},fg=#${colors.base07}]█" + mode_rename_pane "#[bg=#${colors.base0D},fg=#${colors.base01},bold] RENAME-PANE#[bg=#${colors.base01},fg=#${colors.base0D}]█" + mode_session "#[bg=#${colors.base0E},fg=#${colors.base01},bold] SESSION#[bg=#${colors.base01},fg=#${colors.base0E}]█" + mode_move "#[bg=#${colors.base0F},fg=#${colors.base01},bold] MOVE#[bg=#${colors.base01},fg=#${colors.base0F}]█" + mode_prompt "#[bg=#${colors.base0D},fg=#${colors.base01},bold] PROMPT#[bg=#${colors.base01},fg=#${colors.base0D}]█" + mode_tmux "#[bg=#${colors.base09},fg=#${colors.base01},bold] TMUX#[bg=#${colors.base01},fg=#${colors.base09}]█" + + // formatting for inactive tabs + tab_normal "#[bg=#${colors.base01},fg=#${colors.base0C}]█#[bg=#${colors.base0C},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base0C},bold] {name}{floating_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█" + tab_normal_fullscreen "#[bg=#${colors.base01},fg=#${colors.base0C}]█#[bg=#${colors.base0C},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base0C},bold] {name}{fullscreen_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█" + tab_normal_sync "#[bg=#${colors.base01},fg=#${colors.base0C}]█#[bg=#${colors.base0C},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base0C},bold] {name}{sync_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█" + + // formatting for the current active tab + tab_active "#[bg=#${colors.base01},fg=#${colors.base09}]█#[bg=#${colors.base09},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base09},bold] {name}{floating_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█" + tab_active_fullscreen "#[bg=#${colors.base01},fg=#${colors.base09}]█#[bg=#${colors.base09},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base09},bold] {name}{fullscreen_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█" + tab_active_sync "#[bg=#${colors.base01},fg=#${colors.base09}]█#[bg=#${colors.base09},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base09},bold] {name}{sync_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█" + + // separator between the tabs + tab_separator "#[bg=#${colors.base00}] " + + // indicators + tab_sync_indicator " " + tab_fullscreen_indicator " 󰊓" + tab_floating_indicator " 󰹙" + + command_git_branch_command "git rev-parse --abbrev-ref HEAD" + command_git_branch_format "#[fg=blue] {stdout} " + command_git_branch_interval "10" + command_git_branch_rendermode "static" + + datetime "#[fg=#6C7086,bold] {format} " + datetime_format "%A, %d %b %Y %H:%M" + datetime_timezone "Europe/Vienna" + } + } + } + } +'' + +#+end_src +** Zellij config.kdl.nix +:PROPERTIES: +:CUSTOM_ID: h:ae07e867-fc17-4dd7-bd21-5886265308ee +:END: + +#+begin_src nix-ts :tangle programs/zellij/config.kdl.nix +{ config }: +'' + pane_frames false + simplified_ui false + default_shell "zsh" + copy_on_select true + on_force_close "detach" + + default_layout "default" + layout_dir "${config.home.homeDirectory}/.config/zellij/layouts" + theme_dir "${config.home.homeDirectory}/.config/zellij/themes" + + keybinds clear-defaults=true { + locked { + bind "Ctrl g" { SwitchToMode "normal"; } + } + pane { + bind "left" { MoveFocus "left"; } + bind "down" { MoveFocus "down"; } + bind "up" { MoveFocus "up"; } + bind "right" { MoveFocus "right"; } + bind "c" { SwitchToMode "renamepane"; PaneNameInput 0; } + bind "d" { NewPane "down"; SwitchToMode "normal"; } + bind "e" { TogglePaneEmbedOrFloating; SwitchToMode "normal"; } + bind "f" { ToggleFocusFullscreen; SwitchToMode "normal"; } + bind "h" { MoveFocus "left"; } + bind "j" { MoveFocus "down"; } + bind "k" { MoveFocus "up"; } + bind "l" { MoveFocus "right"; } + bind "n" { NewPane; SwitchToMode "normal"; } + bind "p" { SwitchFocus; } + bind "Ctrl p" { SwitchToMode "normal"; } + bind "r" { NewPane "right"; SwitchToMode "normal"; } + bind "w" { ToggleFloatingPanes; SwitchToMode "normal"; } + bind "z" { TogglePaneFrames; SwitchToMode "normal"; } + } + tab { + bind "left" { GoToPreviousTab; } + bind "down" { GoToNextTab; } + bind "up" { GoToPreviousTab; } + bind "right" { GoToNextTab; } + bind "1" { GoToTab 1; SwitchToMode "normal"; } + bind "2" { GoToTab 2; SwitchToMode "normal"; } + bind "3" { GoToTab 3; SwitchToMode "normal"; } + bind "4" { GoToTab 4; SwitchToMode "normal"; } + bind "5" { GoToTab 5; SwitchToMode "normal"; } + bind "6" { GoToTab 6; SwitchToMode "normal"; } + bind "7" { GoToTab 7; SwitchToMode "normal"; } + bind "8" { GoToTab 8; SwitchToMode "normal"; } + bind "9" { GoToTab 9; SwitchToMode "normal"; } + bind "[" { BreakPaneLeft; SwitchToMode "normal"; } + bind "]" { BreakPaneRight; SwitchToMode "normal"; } + bind "b" { BreakPane; SwitchToMode "normal"; } + bind "h" { GoToPreviousTab; } + bind "j" { GoToNextTab; } + bind "k" { GoToPreviousTab; } + bind "l" { GoToNextTab; } + bind "n" { NewTab; SwitchToMode "normal"; } + bind "r" { SwitchToMode "renametab"; TabNameInput 0; } + bind "s" { ToggleActiveSyncTab; SwitchToMode "normal"; } + bind "Ctrl t" { SwitchToMode "normal"; } + bind "x" { CloseTab; SwitchToMode "normal"; } + bind "tab" { ToggleTab; } + } + resize { + bind "left" { Resize "Increase left"; } + bind "down" { Resize "Increase down"; } + bind "up" { Resize "Increase up"; } + bind "right" { Resize "Increase right"; } + bind "+" { Resize "Increase"; } + bind "-" { Resize "Decrease"; } + bind "=" { Resize "Increase"; } + bind "H" { Resize "Decrease left"; } + bind "J" { Resize "Decrease down"; } + bind "K" { Resize "Decrease up"; } + bind "L" { Resize "Decrease right"; } + bind "h" { Resize "Increase left"; } + bind "j" { Resize "Increase down"; } + bind "k" { Resize "Increase up"; } + bind "l" { Resize "Increase right"; } + bind "Ctrl n" { SwitchToMode "normal"; } + } + move { + bind "left" { MovePane "left"; } + bind "down" { MovePane "down"; } + bind "up" { MovePane "up"; } + bind "right" { MovePane "right"; } + bind "h" { MovePane "left"; } + bind "Ctrl h" { SwitchToMode "normal"; } + bind "j" { MovePane "down"; } + bind "k" { MovePane "up"; } + bind "l" { MovePane "right"; } + bind "n" { MovePane; } + bind "p" { MovePaneBackwards; } + bind "tab" { MovePane; } + } + scroll { + bind "e" { EditScrollback; SwitchToMode "normal"; } + bind "s" { SwitchToMode "entersearch"; SearchInput 0; } + } + search { + bind "c" { SearchToggleOption "CaseSensitivity"; } + bind "n" { Search "down"; } + bind "o" { SearchToggleOption "WholeWord"; } + bind "p" { Search "up"; } + bind "w" { SearchToggleOption "Wrap"; } + } + session { + bind "c" { + LaunchOrFocusPlugin "configuration" { + floating true + move_to_focused_tab true + } + SwitchToMode "normal" + } + bind "Ctrl o" { SwitchToMode "normal"; } + bind "p" { + LaunchOrFocusPlugin "plugin-manager" { + floating true + move_to_focused_tab true + } + SwitchToMode "normal" + } + bind "w" { + LaunchOrFocusPlugin "session-manager" { + floating true + move_to_focused_tab true + } + SwitchToMode "normal" + } + } + shared_except "locked" { + bind "Alt left" { MoveFocusOrTab "left"; } + bind "Alt down" { MoveFocus "down"; } + bind "Alt up" { MoveFocus "up"; } + bind "Alt right" { MoveFocusOrTab "right"; } + bind "Alt +" { Resize "Increase"; } + bind "Alt -" { Resize "Decrease"; } + bind "Alt =" { Resize "Increase"; } + bind "Alt [" { PreviousSwapLayout; } + bind "Alt ]" { NextSwapLayout; } + bind "Alt f" { ToggleFloatingPanes; } + bind "Ctrl g" { SwitchToMode "locked"; } + bind "Alt h" { MoveFocusOrTab "left"; } + bind "Alt i" { MoveTab "left"; } + bind "Alt j" { MoveFocus "down"; } + bind "Alt k" { MoveFocus "up"; } + bind "Alt l" { MoveFocusOrTab "right"; } + bind "Alt n" { NewPane; } + bind "Alt o" { MoveTab "right"; } + bind "Ctrl q" { Quit; } + } + shared_except "locked" "move" { + bind "Ctrl h" { SwitchToMode "move"; } + } + shared_except "locked" "session" { + bind "Ctrl o" { SwitchToMode "session"; } + } + shared_except "locked" "scroll" "search" "tmux" { + bind "Ctrl b" { SwitchToMode "tmux"; } + } + shared_except "locked" "scroll" "search" { + bind "Ctrl s" { SwitchToMode "scroll"; } + } + shared_except "locked" "tab" { + bind "Ctrl t" { SwitchToMode "tab"; } + } + shared_except "locked" "pane" { + bind "Ctrl p" { SwitchToMode "pane"; } + } + shared_except "locked" "resize" { + bind "Ctrl n" { SwitchToMode "resize"; } + } + shared_except "normal" "locked" "entersearch" { + bind "enter" { SwitchToMode "normal"; } + } + shared_except "normal" "locked" "entersearch" "renametab" "renamepane" { + bind "esc" { SwitchToMode "normal"; } + } + shared_among "pane" "tmux" { + bind "x" { CloseFocus; SwitchToMode "normal"; } + } + shared_among "scroll" "search" { + bind "PageDown" { PageScrollDown; } + bind "PageUp" { PageScrollUp; } + bind "left" { PageScrollUp; } + bind "down" { ScrollDown; } + bind "up" { ScrollUp; } + bind "right" { PageScrollDown; } + bind "Ctrl b" { PageScrollUp; } + bind "Ctrl c" { ScrollToBottom; SwitchToMode "normal"; } + bind "d" { HalfPageScrollDown; } + bind "Ctrl f" { PageScrollDown; } + bind "h" { PageScrollUp; } + bind "j" { ScrollDown; } + bind "k" { ScrollUp; } + bind "l" { PageScrollDown; } + bind "Ctrl s" { SwitchToMode "normal"; } + bind "u" { HalfPageScrollUp; } + } + entersearch { + bind "Ctrl c" { SwitchToMode "scroll"; } + bind "esc" { SwitchToMode "scroll"; } + bind "enter" { SwitchToMode "search"; } + } + renametab { + bind "esc" { UndoRenameTab; SwitchToMode "tab"; } + } + shared_among "renametab" "renamepane" { + bind "Ctrl c" { SwitchToMode "normal"; } + } + renamepane { + bind "esc" { UndoRenamePane; SwitchToMode "pane"; } + } + shared_among "session" "tmux" { + bind "d" { Detach; } + } + tmux { + bind "left" { MoveFocus "left"; SwitchToMode "normal"; } + bind "down" { MoveFocus "down"; SwitchToMode "normal"; } + bind "up" { MoveFocus "up"; SwitchToMode "normal"; } + bind "right" { MoveFocus "right"; SwitchToMode "normal"; } + bind "space" { NextSwapLayout; } + bind "\"" { NewPane "down"; SwitchToMode "normal"; } + bind "%" { NewPane "right"; SwitchToMode "normal"; } + bind "," { SwitchToMode "renametab"; } + bind "[" { SwitchToMode "scroll"; } + bind "Ctrl b" { Write 2; SwitchToMode "normal"; } + bind "c" { NewTab; SwitchToMode "normal"; } + bind "h" { MoveFocus "left"; SwitchToMode "normal"; } + bind "j" { MoveFocus "down"; SwitchToMode "normal"; } + bind "k" { MoveFocus "up"; SwitchToMode "normal"; } + bind "l" { MoveFocus "right"; SwitchToMode "normal"; } + bind "n" { GoToNextTab; SwitchToMode "normal"; } + bind "o" { FocusNextPane; } + bind "p" { GoToPreviousTab; SwitchToMode "normal"; } + bind "z" { ToggleFocusFullscreen; SwitchToMode "normal"; } + } + } + + // Plugin aliases - can be used to change the implementation of Zellij + // changing these requires a restart to take effect + plugins { + compact-bar location="zellij:compact-bar" + configuration location="zellij:configuration" + filepicker location="zellij:strider" { + cwd "/" + } + plugin-manager location="zellij:plugin-manager" + session-manager location="zellij:session-manager" + status-bar location="zellij:status-bar" + strider location="zellij:strider" + tab-bar location="zellij:tab-bar" + welcome-screen location="zellij:session-manager" { + welcome_screen true + } + } + + // Plugins to load in the background when a new session starts + // eg. "file:/path/to/my-plugin.wasm" + // eg. "https://example.com/my-plugin.wasm" + load_plugins { + } + + // Provide a command to execute when copying text. The text will be piped to + // the stdin of the program to perform the copy. This can be used with + // terminal emulators which do not support the OSC 52 ANSI control sequence + // that will be used by default if this option is not set. + // Examples: + // + // copy_command "xclip -selection clipboard" // x11 + // copy_command "wl-copy" // wayland + // copy_command "pbcopy" // osx + // + // copy_command "pbcopy" + + // Choose the destination for copied text + // Allows using the primary selection buffer (on x11/wayland) instead of the system clipboard. + // Does not apply when using copy_command. + // Options: + // - system (default) + // - primary + // + // copy_clipboard "primary" + + // Path to the default editor to use to edit pane scrollbuffer + // Default: $EDITOR or $VISUAL + // scrollback_editor "/usr/bin/vim" + + // Toggle between having Zellij lay out panes according to a predefined set of layouts whenever possible + // Options: + // - true (default) + // - false + // + // auto_layout false + + // Whether sessions should be serialized to the cache folder (including their tabs/panes, cwds and running commands) so that they can later be resurrected + // Options: + // - true (default) + // - false + // + // session_serialization false + + // Whether pane viewports are serialized along with the session, default is false + // Options: + // - true + // - false (default) + // + // serialize_pane_viewport false + + // Scrollback lines to serialize along with the pane viewport when serializing sessions, 0 + // defaults to the scrollback size. If this number is higher than the scrollback size, it will + // also default to the scrollback size. This does nothing if `serialize_pane_viewport` is not true. + // + // scrollback_lines_to_serialize 10000 + + // Enable or disable the rendering of styled and colored underlines (undercurl). + // May need to be disabled for certain unsupported terminals + // (Requires restart) + // Default: true + // + // styled_underlines false + + // How often in seconds sessions are serialized + // + // serialization_interval 10000 + + // Enable or disable writing of session metadata to disk (if disabled, other sessions might not know + // metadata info on this session) + // (Requires restart) + // Default: false + // + // disable_session_metadata false + + // Enable or disable support for the enhanced Kitty Keyboard Protocol (the host terminal must also support it) + // (Requires restart) + // Default: true (if the host terminal supports it) + // + // support_kitty_keyboard_protocol false +'' + +#+end_src +** Vieb config +:PROPERTIES: +:CUSTOM_ID: h:0124a4eb-4ea3-455c-939d-ba4584c703af +:END: + +#+begin_src shell :tangle programs/vieb/viebrc +" Options +set adblocker=update +set adblockernotifications=all +set cache=clearonquit +set noclearcookiesonquit +set nocleardownloadsoncompleted +set nocleardownloadsonquit +set clearhistoryinterval=none +set noclearlocalstorageonquit +set noclosablepinnedtabs +set commandhist=persistuseronly +set containerkeeponreopen +set containernewtab=s:usecurrent +set containershowname=automatic +set containersplitpage=s:usecurrent +set containerstartuppage=main +set countlimit=100 +" set nodarkreader +set darkreaderbg=#181a1b +set darkreaderbrightness=100 +set darkreadercontrast=100 +set darkreaderfg=#e8e6e3 +set darkreadergrayscale=0 +set darkreadermode=dark +set darkreadersepia=0 +set darkreadertextstroke=0 +set devtoolsposition=split +set dialogalert=notifyblock +set dialogconfirm=notifyallow +set dialogprompt=notifyblock +set downloadmethod=automatic +set downloadpath= +set encodeurlcopy=nospaces +set encodeurlext=nospaces +set explorehist=persist +set externalcommand= +set favicons=session +set followchars=numbers +set followfallbackaction=filter +set followlabelposition=outsiderighttop +set follownewtabswitch +set guifontsize=14 +set guifullscreennavbar=oninput +set guifullscreentabbar=onupdate +set guihidetimeout=5000 +set guinavbar=oninput +set guiscrollbar=onscroll +set guitabbar=onupdate +set historyperpage=100 +set ignorecase +set incsearch +set inputfocusalignment=rememberend +set keeprecentlyclosed +set lang=en +set loadingindicator=line +set mapsuggest=9000000000000000 +set mapsuggestposition=topright +set markposition=newtab +set markpositionshifted=default +set maxmapdepth=10 +set menupage=elementasneeded +set menusuggest=both +set menuvieb=both +set mintabwidth=28 +set mouse=all +set mousedisabledbehavior=nothing +set nomousefocus +set mousenewtabswitch +set mousevisualmode=onswitch +set nativenotification=never +set nativetheme=dark +set newtaburl= +set notificationduration=6000 +set notificationforpermissions=silent +set notificationforsystemcommands=errors +set notificationlimitsmall=3 +set notificationposition=bottomright +set pdfbehavior=download +set permissioncamera=ask +set permissioncertificateerror=allow +set permissionclipboardread=allow +set permissionclipboardwrite=allow +set permissionclosepage=allow +set permissiondisplaycapture=ask +set permissionfullscreen=allow +set permissiongeolocation=block +set permissionhid=block +set permissionidledetection=block +set permissionmediadevices=allowfull +set permissionmicrophone=ask +set permissionmidi=ask +set permissionmidisysex=ask +set permissionnotifications=ask +set permissionopenexternal=ask +set permissionpersistentstorage=ask +set permissionpointerlock=block +set permissionscreenwakelock=block +set permissionsensors=block +set permissionserial=block +set permissionunknown=ask +set permissionusb=allow +set permissionwindowmanagement=ask +set pointerposlocalid=domain +set pointerpostype=casing +set noquitonlasttabclose +set redirecttohttp +set noreloadtaboncrash +set replacespecial=special +set replacestartup=never +set requesttimeout=20000 +set restoretabs=all +set scrollposlocalid=domain +set scrollpostype=casing +set searchemptyscope=global +set searchpointeralignment=left +set searchscope=global +set shell= +set showcmd +set smartcase +set spell +set nosplitbelow +set nosplitright +set nosponsorblock +set suggestbouncedelay=100 +set suggestcommands=9000000000000000 +set suggesttopsites=10 +set suspendbackgroundtab +set suspendonrestore=regular +set suspendtimeout=0 +set tabclosefocus=left +set tabcycle +set tabnewposition=right +set tabopenmuted=never +set taboverflow=scroll +set tabreopenmuted=remember +set tabreopenposition=right +set timeout +set timeoutlen=2000 +set translateapi=auto +set translatekey= +set translatelang=en-us +set translateurl=https://api-free.deepl.com/v2/ +" set nouserscript +" set nouserstyle +set useragent=%firefox +set vimcommand=gvim +set windowfullscreen=restore +set windowmaximize=restore +set windowposition=restore +set windowsize=restore +set windowtitle="%app - %title" + +" Commands +colorscheme default + + +" Mappings +nmap o +nmap t <:tabnew> +nmap b buffer +nmap g0 <:buffer 0> +nmap g^ <:buffer 0> +nmap g$ <:buffer -1> +nmap <:buffer #> +nmap J +nmap K +nmap >> +nmap +nmap O +nmap gx0 <:lclose> +nmap gx$ <:rclose> +nmap x +nunmap [ +nunmap ] +nmap [[ +nmap ]] +nmap [c +nmap ]c +nmap zz +nmap zi +nmap zo +nmap zm 5 +nmap zr 5 +nmap zM 5 +nmap zR 5 +nmap zI 7 +nmap zO 7 + +" Search +set searchengine=https://kagi.com/search?q=%s +set searchwords+=no~https://search.nixos.org/options?query=%s +set searchwords+=np~https://search.nixos.org/packages?query=%s +set searchwords+=hm~https://home-manager-options.extranix.com/?query=%s + +" Viebrc generated by Vieb +" vim: ft=vim + +#+end_src +** swayidle +:PROPERTIES: +:CUSTOM_ID: h:69ea5818-4ebb-436a-a31a-6a2348cf215c +:END: + +#+begin_src shell :tangle programs/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' +#+end_src +** stylix color scheme +:PROPERTIES: +:CUSTOM_ID: h:2e9b84d7-cb18-4e74-83f8-65ada11a8911 +:END: + +#+begin_src css :tangle programs/stylix/swarsel.yaml :mkdirp yes +# scheme: "better-contrast" +author: "Swarsel" +base00: "1D252C" # #1d252c passt +base01: "171D23" # #171d23 +base02: "5EC4FF" # #5EC4FF +base03: "566C7D" # #566C7D passt +base04: "5EC4FF" # #5EC4FF passt +base05: "A0B3C5" # #A0B3C5 passt +base06: "C06ECE" # #C06ECE passt +base07: "A0B3C5" # #A0B3C5 passt +base08: "D95468" # #D95468 passt +base09: "FFA880" # #ffA880 passt +base0A: "5EC4FF" # #5EC4FF +base0B: "8BD49C" # #8BD49C +base0C: "008B94" # #008B94 passt +base0D: "5EC4FF" # #5EC4FF passt +base0E: "C06ECE" # #C06ECE passt +base0F: "5EC4FF" # #5EC4FF passt + +# base00 - Default Background +# base01 - Lighter Background (Used for status bars) +# base02 - Selection Background +# base03 - Comments, Invisibles, Line Highlighting +# base04 - Dark Foreground (Used for status bars) +# base05 - Default Foreground, Caret, Delimiters, Operators +# base06 - Light Foreground (Not often used) +# base07 - Light Background (Not often used) +# base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted +# base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url +# base0A - Classes, Markup Bold, Search Text Background +# base0B - Strings, Inherited Class, Markup Code, Diff Inserted +# base0C - Support, Regular Expressions, Escape Characters, Markup Quotes +# base0D - Functions, Methods, Attribute IDs, Headings +# base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed +# base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. +#+end_src +** .gitmessage +:PROPERTIES: +:CUSTOM_ID: h:8bfaf6d3-a0ab-4199-a07b-8bd9991bc128 +:END: + +#+begin_src shell :tangle programs/git/.gitmessage + +# max. 50 chars is here: # +# [optional scope]: +# types: feat, fix, build, chore, ci, docs, style, refactor, perf, test +# ! indicates a breaking change. + + +# Body: wrap at 72 chars is here: # +# Include at least one empty line before co-authored. Format: +# Co-authored-by: name +#+end_src +** userChrome.css +:PROPERTIES: +:CUSTOM_ID: h:a2990def-9a2a-491b-9fee-3057dc324c3c +:END: + +#+begin_src css :tangle programs/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. */ + +/* Hide the whole toolbar area unless urlbar is focused or cursor is over the toolbar + * Dimensions on non-Win10 OS probably needs to be adjusted. + */ + +:root{ + --uc-autohide-toolbox-delay: 0ms; /* Wait 0.1s before hiding toolbars */ + --uc-toolbox-rotation: 107deg; /* This may need to be lower on mac - like 75 or so */ + + --base00: #1D252C; + --base01: #171D23; + --base02: #5EC4FF; + --base03: #566C7D; + --base04: #5EC4FF; + --base05: #A0B3C5; + --base06: #C06ECE; + --base07: #A0B3C5; + --base08: #D95468; + --base09: #FFA880; + --base0A: #5EC4FF; + --base0B: #8BD49C; + --base0C: #008B94; + --base0D: #5EC4FF; + --base0E: #C06ECE; + --base0F: #5EC4FF; + +} + +:root[sizemode="maximized"]{ + --uc-toolbox-rotation: 88.5deg; +} + +@media (-moz-platform: windows){ + :root:not([lwtheme]) #navigator-toolbox{ background-color: -moz-dialog !important; } +} + +:root[sizemode="fullscreen"], +:root[sizemode="fullscreen"] #navigator-toolbox{ margin-top: 0 !important; } + +#navigator-toolbox{ + --browser-area-z-index-toolbox: 3; + position: fixed !important; + background-color: var(--lwt-accent-color,black) !important; + transition: transform 0ms linear, opacity 0ms linear !important; + transition-delay: var(--uc-autohide-toolbox-delay) !important; + transform-origin: top; + transform: rotateX(var(--uc-toolbox-rotation)); + opacity: 0; + line-height: 0; + z-index: 1; + pointer-events: none; +} +:root[sessionrestored] #urlbar[popover]{ + pointer-events: none; + opacity: 0; + transition: transform 0ms linear var(--uc-autohide-toolbox-delay), opacity 0ms calc(var(--uc-autohide-toolbox-delay) + 0ms); + transform-origin: 0px calc(0px - var(--tab-min-height) - var(--tab-block-margin) * 2); + transform: rotateX(89.9deg); +} +#mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts)) ~ toolbox #urlbar[popover], +#navigator-toolbox:is(:hover,:focus-within) #urlbar[popover], +#urlbar-container > #urlbar[popover]:is([focused],[open]){ + pointer-events: auto; + opacity: 1; + transition-delay: 0ms; + transform: rotateX(0deg); +} +#mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts)) ~ toolbox, +#navigator-toolbox:has(#urlbar:is([open],[focus-within])), +#navigator-toolbox:hover, +#navigator-toolbox:focus-within{ + transition-delay: 0ms !important; + transform: rotateX(0); + opacity: 1; +} +/* This makes things like OS menubar/taskbar show the toolbox when hovered in maximized windows. + * Unfortunately it also means that other OS native surfaces (such as context menu on macos) + * and other always-on-top applications will trigger toolbox to show up. */ +@media (-moz-bool-pref: "userchrome.autohide-toolbox.unhide-by-native-ui.enabled"){ + :root[sizemode="maximized"]:not(:hover){ + #navigator-toolbox:not(:-moz-window-inactive), + #urlbar[popover]:not(:-moz-window-inactive){ + transition-delay: 0ms !important; + transform: rotateX(0); + opacity: 1; + } + } +} + +#navigator-toolbox > *{ line-height: normal; pointer-events: auto } + +#navigator-toolbox, +#navigator-toolbox > *{ + width: 100vw; + -moz-appearance: none !important; +} + +/* These two exist for oneliner compatibility */ +#nav-bar{ width: var(--uc-navigationbar-width,100vw) } +#TabsToolbar +{ + visibility: collapse; +} +/* Don't apply transform before window has been fully created */ +:root:not([sessionrestored]) #navigator-toolbox{ transform:none !important } + +:root[customizing] #navigator-toolbox{ + position: relative !important; + transform: none !important; + opacity: 1 !important; +} + +#navigator-toolbox[inFullscreen] > #PersonalToolbar, +#PersonalToolbar[collapsed="true"]{ display: none } + +/* Uncomment this if tabs toolbar is hidden with hide_tabs_toolbar.css */ + /*#titlebar{ margin-bottom: -9px }*/ + +/* Uncomment the following for compatibility with tabs_on_bottom.css - this isn't well tested though */ +/* +#navigator-toolbox{ flex-direction: column; display: flex; } +#titlebar{ order: 2 } +*/ +#sidebar-header { + display: none; +} +#sidebar-header { + /* display: none; */ + visibility: collapse !important; +} +/* Source file https://github.com/MrOtherGuy/firefox-csshacks/tree/master/chrome/autohide_sidebar.css made available under Mozilla Public License v. 2.0 +See the above repository for updates as well as full license text. */ + +/* Show sidebar only when the cursor is over it */ +/* The border controlling sidebar width will be removed so you'll need to modify these values to change width */ + +#sidebar-box{ + --uc-sidebar-width: 30px; + --uc-sidebar-hover-width: 210px; + --uc-autohide-sidebar-delay: 0ms; /* Wait 0.6s before hiding sidebar */ + --uc-autohide-transition-duration: 0ms; + --uc-autohide-transition-type: linear; + --browser-area-z-index-sidebar: 3; + position: relative; + min-width: var(--uc-sidebar-width) !important; + width: var(--uc-sidebar-width) !important; + max-width: var(--uc-sidebar-width) !important; + z-index: var(--browser-area-z-index-sidebar,3); +} +#sidebar-box[positionend]{ direction: rtl } +#sidebar-box[positionend] > *{ direction: ltr } + +#sidebar-box[positionend]:-moz-locale-dir(rtl){ direction: ltr } +#sidebar-box[positionend]:-moz-locale-dir(rtl) > *{ direction: rtl } + +#main-window[sizemode="fullscreen"] #sidebar-box{ --uc-sidebar-width: 1px; } + +#sidebar-splitter{ display: none } + +#sidebar-header{ + overflow: hidden; + color: var(--chrome-color, inherit) !important; + padding-inline: 0 !important; +} + +#sidebar-header::before, +#sidebar-header::after{ + content: ""; + display: flex; + padding-left: 8px; +} + +#sidebar-header, +#sidebar{ + transition: min-width var(--uc-autohide-transition-duration) var(--uc-autohide-transition-type) var(--uc-autohide-sidebar-delay) !important; + min-width: var(--uc-sidebar-width) !important; + will-change: min-width; +} +#sidebar-box:hover > #sidebar-header, +#sidebar-box:hover > #sidebar{ + min-width: var(--uc-sidebar-hover-width) !important; + transition-delay: 0ms !important; +} + +.sidebar-panel{ + background-color: transparent !important; + color: var(--newtab-text-primary-color) !important; +} + +.sidebar-panel #search-box{ + -moz-appearance: none !important; + background-color: rgba(249,249,250,0.1) !important; + color: inherit !important; +} + +/* Add sidebar divider and give it background */ + +#sidebar, +#sidebar-header{ + background-color: inherit !important; + border-inline: 1px solid rgb(80,80,80); + border-inline-width: 0px 1px; +} + +#sidebar-box:not([positionend]) > :-moz-locale-dir(rtl), +#sidebar-box[positionend] > *{ + border-inline-width: 1px 0px; +} + +/* Move statuspanel to the other side when sidebar is hovered so it doesn't get covered by sidebar */ + +#sidebar-box:not([positionend]):hover ~ #appcontent #statuspanel{ + inset-inline: auto 0px !important; +} +#sidebar-box:not([positionend]):hover ~ #appcontent #statuspanel-label{ + margin-inline: 0px !important; + border-left-style: solid !important; +} + +#+end_src +** Default Flake Template +:PROPERTIES: +:CUSTOM_ID: h:fefc38d9-b3fb-42c5-8a73-ca363e898bb9 +:END: + +#+begin_src nix-ts :tangle templates/default/flake.nix +{ + description = "General purpose Flake"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + systems.url = "github:nix-systems/default"; + }; + + outputs = + { nixpkgs + , systems + , ... + }: + let + forEachSystem = nixpkgs.lib.genAttrs (import systems); + pkgsFor = forEachSystem (system: import nixpkgs { inherit system; }); + in + { + formatter = forEachSystem (system: pkgsFor.${system}.nixpkgs-fmt); + + devShells = forEachSystem (system: { + default = pkgsFor.${system}.mkShell { + packages = with pkgsFor.${system}; [ + + ]; + }; + }); + + }; +} +#+end_src +** C++ Flake Template +:PROPERTIES: +:CUSTOM_ID: h:c54fc65b-91ef-4f8f-b0d5-cc0c3cb92b53 +:END: + +#+begin_src nix-ts :tangle templates/cpp/flake.nix + # heavily inspired by https://github.com/nulladmin1/nix-flake-templates/blob/main/cpp-cmake/flake.nix + { + description = "C++ Flake"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + systems.url = "github:nix-systems/default"; + }; + + outputs = + { self + , nixpkgs + , systems + , ... + }: + let + forEachSystem = nixpkgs.lib.genAttrs (import systems); + pkgsFor = forEachSystem (system: import nixpkgs { inherit system; }); + + pname = "name"; + in + { + formatter = forEachSystem (system: pkgsFor.${system}.nixpgks-fmt); + + devShells = forEachSystem (system: { + default = pkgsFor.${system}.mkShell { + packages = with pkgsFor.${system}; [ + libllvm + cmake + gtest + cppcheck + valgrind + doxygen + clang-tools + # cudatoolkit + ]; + }; + }); + + packages = forEachSystem (system: { + default = pkgsFor.${system}.stdenv.mkDerivation { + inherit pname; + version = "0.1.0"; + src = ./.; + + nativeBuildInputs = with pkgsFor.${system}; [ + cmake + ]; + buildInputs = with pkgsFor.${system}; [ + gtest + ]; + }; + }); + + apps = forEachSystem (system: { + default = { + type = "app"; + program = "${self.packages.${system}.default}/bin/${pname}"; + }; + }); + }; + } +#+end_src +** Go Flake Template +:PROPERTIES: +:CUSTOM_ID: h:def2d654-e8da-4d8a-8958-b59a60d019f5 +:END: + +#+begin_src nix-ts :tangle templates/go/flake.nix + # heavily inspired by https://github.com/nulladmin1/nix-flake-templates/blob/main/go-nix/flake.nix + { + description = "Go Flake"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + systems.url = "github:nix-systems/default"; + }; + + outputs = + { self + , nixpkgs + , systems + , ... + }: + let + forEachSystem = nixpkgs.lib.genAttrs (import systems); + pkgsFor = forEachSystem (system: import nixpkgs { inherit system; }); + + pname = "name"; + in + { + formatter = forEachSystem (system: pkgsFor.${system}.nixpkgs-fmt); + + devShells = forEachSystem (system: { + default = pkgsFor.${system}.mkShell { + packages = with pkgsFor.${system}; [ + go + gopls + go-tools + gotools + ]; + }; + }); + + packages = forEachSystem (system: { + default = pkgsFor.${system}.buildGoModule { + inherit pname; + version = "0.1.0"; + src = ./.; + vendorHash = null; + }; + }); + + apps = forEachSystem (system: { + default = { + type = "app"; + program = "${self.packages.${system}.default}/bin/${pname}"; + }; + }); + }; + } +#+end_src +** LaTeX Flake Template +:PROPERTIES: +:CUSTOM_ID: h:adccea10-6c72-46aa-8c67-5e06b7606c71 +:END: + +#+begin_src nix-ts :tangle templates/latex/flake.nix + # This template is based on https://github.com/Leixb/latex-template/tree/master + { + description = "LaTeX Flake"; + + inputs.flake-utils.url = "github:numtide/flake-utils"; + + outputs = { self, nixpkgs, flake-utils }: + { + + lib.latexmk = import ./build-document.nix; + + } // flake-utils.lib.eachDefaultSystem (system: + let + pname = "document"; + + pkgs = import nixpkgs { inherit system; }; + + latex-packages = with pkgs; [ + (texlive.combine { + inherit (texlive) + scheme-medium + framed + titlesec + cleveref + multirow + wrapfig + tabu + threeparttable + threeparttablex + makecell + environ + biblatex + biber + fvextra + upquote + catchfile + xstring + csquotes + minted + dejavu + comment + footmisc + xltabular + ltablex + ; + }) + which + python39Packages.pygments + ]; + + dev-packages = with pkgs; [ + texlab + zathura + wmctrl + ]; + in + rec { + devShell = pkgs.mkShell { + buildInputs = [ latex-packages dev-packages ]; + }; + + formatter = pkgs.nixpkgs-fmt; + + packages = flake-utils.lib.flattenTree { + default = import ./build-document.nix { + inherit pkgs; + name = pname; + texlive = latex-packages; + shellEscape = true; + minted = true; + SOURCE_DATE_EPOCH = toString self.lastModified; + }; + }; + + apps.default = flake-utils.lib.mkApp { drv = "${pkgs.texlivePackages.latexmk}"; exePath = "/bin/latexmk"; }; + } + ); + } +#+end_src +** Python Flake Template +:PROPERTIES: +:CUSTOM_ID: h:1a918c8d-08b4-4474-8d34-3da502081a16 +:END: + +#+begin_src nix-ts :tangle templates/python/flake.nix + # based on https://github.com/pyproject-nix/uv2nix/tree/master/templates/hello-world + { + description = "Python flake using uv2nix"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + pyproject-nix = { + url = "github:pyproject-nix/pyproject.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + uv2nix = { + url = "github:pyproject-nix/uv2nix"; + inputs = { + pyproject-nix.follows = "pyproject-nix"; + nixpkgs.follows = "nixpkgs"; + }; + }; + + pyproject-build-systems = { + url = "github:pyproject-nix/build-system-pkgs"; + inputs = { + pyproject-nix.follows = "pyproject-nix"; + uv2nix.follows = "uv2nix"; + nixpkgs.follows = "nixpkgs"; + }; + }; + }; + + outputs = + { nixpkgs + , uv2nix + , pyproject-nix + , pyproject-build-systems + , ... + }: + let + inherit (nixpkgs) lib; + pname = "name"; + forAllSystems = lib.genAttrs lib.systems.flakeExposed; + + # Load a uv workspace from a workspace root. + # Uv2nix treats all uv projects as workspace projects. + workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; }; + + overlay = workspace.mkPyprojectOverlay { + # Prefer prebuilt binary wheels as a package source. + # Sdists are less likely to "just work" because of the metadata missing from uv.lock. + # Binary wheels are more likely to, but may still require overrides for library dependencies. + sourcePreference = "wheel"; # or sourcePreference = "sdist"; + # Optionally customise PEP 508 environment + # environ = { + # platform_release = "5.10.65"; + # }; + }; + + + pythonSets = forAllSystems + (system: + let + inherit (pkgs) stdenv; + pkgs = nixpkgs.legacyPackages.${system}; + pyprojectOverrides = final: prev: { + # Implement build fixups here. + ${pname} = prev.${pname}.overrideAttrs (old: { + + passthru = old.passthru // { + # Put all tests in the passthru.tests attribute set. + # Nixpkgs also uses the passthru.tests mechanism for ofborg test discovery. + # + # For usage with Flakes we will refer to the passthru.tests attributes to construct the flake checks attribute set. + tests = + let + + virtualenv = final.mkVirtualEnv "${pname}-pytest-env" { + ${pname} = [ "test" ]; + }; + + in + (old.tests or { }) + // { + pytest = stdenv.mkDerivation { + name = "${final.${pname}.name}-pytest"; + inherit (final.${pname}) src; + nativeBuildInputs = [ + virtualenv + ]; + dontConfigure = true; + + # Because this package is running tests, and not actually building the main package + # the build phase is running the tests. + # + # We also output a HTML coverage report, which is used as the build output. + buildPhase = '' + runHook preBuild + pytest --cov tests --cov-report html + runHook postBuild + ''; + + # Install the HTML coverage report into the build output. + # + # If you wanted to install multiple test output formats such as TAP outputs + # you could make this derivation a multiple-output derivation. + # + # See https://nixos.org/manual/nixpkgs/stable/#chap-multiple-output for more information on multiple outputs. + installPhase = '' + runHook preInstall + mv htmlcov $out + runHook postInstall + ''; + }; + + }; + }; + }); + }; + + baseSet = pkgs.callPackage pyproject-nix.build.packages { + python = pkgs.python312; + }; + in + baseSet.overrideScope + ( + lib.composeManyExtensions [ + pyproject-build-systems.overlays.default + overlay + pyprojectOverrides + ] + )); + + in + { + packages = forAllSystems (system: + let + pythonSet = pythonSets.${system}; + in + { default = pythonSet.mkVirtualEnv "${pname}-env" workspace.deps.default; }); + + devShells = forAllSystems + (system: + let + pythonSet = pythonSets.${system}; + pkgs = nixpkgs.legacyPackages.${system}; + in + { + default = + let + # Create an overlay enabling editable mode for all local dependencies. + editableOverlay = workspace.mkEditablePyprojectOverlay { + # Use environment variable + root = "$REPO_ROOT"; + # Optional: Only enable editable for these packages + # members = [ "hello-world" ]; + }; + + # Override previous set with our overrideable overlay. + editablePythonSet = pythonSet.overrideScope editableOverlay; + + virtualenv = editablePythonSet.mkVirtualEnv "${pname}-dev-env" { + ${pname} = [ "dev" ]; + }; + + in + pkgs.mkShell { + packages = [ + virtualenv + pkgs.uv + ]; + shellHook = '' + # Undo dependency propagation by nixpkgs. + unset PYTHONPATH + + # Don't create venv using uv + export UV_NO_SYNC=1 + + # Prevent uv from downloading managed Python's + export UV_PYTHON_DOWNLOADS=never + + # Get repository root using git. This is expanded at runtime by the editable `.pth` machinery. + export REPO_ROOT=$(git rev-parse --show-toplevel) + ''; + }; + }); + + checks = forAllSystems ( + system: + let + pythonSet = pythonSets.${system}; + in + { + inherit (pythonSet.${pname}.passthru.tests) pytest; + } + ); + + formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.nixpkgs-fmt); + + }; + } +#+end_src +** Rust Flake Template +:PROPERTIES: +:CUSTOM_ID: h:c03663fd-f7bd-4054-9075-5dacaf2abf76 +:END: + +#+begin_src nix-ts :tangle 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"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + systems.url = "github:nix-systems/default"; + naersk.url = "github:nix-community/naersk"; + fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = + { self + , nixpkgs + , naersk + , fenix + , systems + , ... + }: + let + forEachSystem = nixpkgs.lib.genAttrs (import systems); + pkgsFor = forEachSystem (system: + + import nixpkgs { + inherit system; + overlays = [ + fenix.overlays.default + ]; + }); + rust-toolchain = forEachSystem (system: pkgsFor.${system}.fenix.stable); + in + { + formatter = forEachSystem (system: pkgsFor.${system}.nixpkgs-fmt); + + devShells = forEachSystem (system: { + default = pkgsFor.${system}.mkShell { + packages = with rust-toolchain.${system}; [ + cargo + rustc + clippy + rustfmt + rust-analyzer + ]; + env = { + RUST_BACKTRACE = "full"; + }; + RUST_SRC_PATH = "${rust-toolchain.${system}.rust-src}/lib/rustlib/src/rust/library"; + }; + }); + + packages = forEachSystem (system: { + default = + (pkgsFor.${system}.callPackage naersk { + inherit (rust-toolchain.${system}) cargo rustc; + }).buildPackage { + src = ./.; + }; + }); + + apps = forEachSystem (system: { + default = { + type = "app"; + program = "${self.packages.${system}.default}/bin/rust"; + }; + }); + }; + } +#+end_src ** GitHub Readme :PROPERTIES: :CUSTOM_ID: h:bf3e6fc0-a95a-46d0-9305-0d1068b2f1ec diff --git a/hosts/nixos/moonside/default.nix b/hosts/nixos/moonside/default.nix index dd7a28f..3086862 100644 --- a/hosts/nixos/moonside/default.nix +++ b/hosts/nixos/moonside/default.nix @@ -2,6 +2,8 @@ let 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; @@ -83,10 +85,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; diff --git a/hosts/nixos/sync/default.nix b/hosts/nixos/sync/default.nix index 56253cb..ed9c017 100644 --- a/hosts/nixos/sync/default.nix +++ b/hosts/nixos/sync/default.nix @@ -6,6 +6,7 @@ let }; 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 = [ @@ -50,11 +51,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; diff --git a/hosts/nixos/sync/hardware-configuration.nix b/hosts/nixos/sync/hardware-configuration.nix index 7421b3a..38606e5 100644 --- a/hosts/nixos/sync/hardware-configuration.nix +++ b/hosts/nixos/sync/hardware-configuration.nix @@ -1,8 +1,4 @@ -{ config -, lib -, modulesPath -, ... -}: { +{ config, lib, modulesPath, ... }: { imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; diff --git a/hosts/nixos/winters/secrets/pii.nix.enc b/hosts/nixos/winters/secrets/pii.nix.enc index e1f2457..0a46cc3 100644 --- a/hosts/nixos/winters/secrets/pii.nix.enc +++ b/hosts/nixos/winters/secrets/pii.nix.enc @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data:Bb45EoiwDMRxYR/YAmYcwn7HT3mF0kT1DHmBclmCxj0xK81qqQzFZyF+2WKFwyMYAC0gfOpeoi9B+a2nNfIaY7hujqQ1luLOaHAL687hKFM1w62U1w5XNs9Rs0OnO99ag8IZTAjY0lqC4djTrTlklx+x6qzISW2z191SMho4zD89mKA2qCk3iYd37+N/uOZ4LSPSBtX625d2lXZPpWhBDd/UrlZqwQqGa+cxdeM3QcRr+Xnv4hYVg+UC2kGXwBWCkMY9S12iQp0CQTMAcqhgfs5J7tdxycYcXYJZjUGfJBTrG6t5xVzzibKFpAjpl9aqiUGLNHf1EtwBP4+PtEs7XQCHltsz8PA4PtH291RVzT4FYUbkCTw1gQBgB1tQzwa4Gc7MBtvAR4DCXrTfda5eYGUzwBsCC9AVNI1jEaDncaiPPjK8rzyjcZGK9i5hMDf5L0XqLKG350RPRWMPFCnCml67n+tnEp4JsOfadpIJ7iCrBTXpgWHVXBcOKuEjIjAInBtzOUrV1AbH6f45R6N1jOoe315t4FlWPL4M0oUemi6Uw8NYiX80X2VD558j80jLZVfybz87IlvTI/GiI1GykkRoanH2LURtrzLUAGtpvK8ueCeKStYDLt89s4m8HFO/p8hhQ1id6vD8VAyvp7n6lZ4SUOjyWy1DTsR9YMz/t7oilwfsfp7bSiFzqk3cOgbZsdbyZZVNlGdN4XeWUHIztpiy1239N70xeE7HeJODkgrVs6HI8GME1LDtYZcBzyh1zHIInT5gv4fNBDTCG4a3yhpuDIPnCXwC3L93wX058u2t0ETcaeMRjeWZU0H0PFfM9DhjO6wmWRxQ0yqT69b1gsCoUWdsixfUtJQ9dKstM5pdJCNiEvehMC5SPXP20PPeZEIlmVnXGQqAs6Bcpo+TmdrNaI7llHPmRVE9MeumqC7V22eHVpwawP4NHwLXtL/SjZuMWDc7F2DnCm3lHxxqVfWS6XFFB+WcBkmQFh2cqCuRsGhXFUPevxpDp0thL8rBnUzro/Xlh1KvBSstC75m1c4dx/EL7yBLWllWOVCEQU7R2QEw77G/viCx3/KCuJrkTWXOyiREqXdUDin2N4jZAhH3QKONrBYYBubVPIpaWZEindKyjNdItFxTbSDb5MwOtBsCNhLTqT45vefXh4LYYOf/+YvUmEw9nkgQn5Nw8vJ8H2mpLyLGgKupSYdlErmcu59QWwjW3drentzx8DhMWBiICkAWRe8PHXZHcC8kD0+sEXtBtvtfgkQ3aYv2aF0Dy3DHcHhf2auDCuJr6IBwwM2RKO4EhS2Ec9YKVyDXC7/bZqsymTyCawKCQZYCK9ZPcI97gTM=,iv:peWndkV5HrPgsJTgMvDM+uLO6jqfpIBiiQzL80dqCFM=,tag:gPkHLiO6/yPUIZ6q/X4Thg==,type:str]", + "data": "ENC[AES256_GCM,data:XEzKhJ1+iwQZ24wnf7FdThWMwOKEwaYr3ecGjjLpTqx4+kq3W9FWFDSKkHAwo6077tsVTu7NCGZfat/gAylg1xgqAZAHA8/PMQejowAgIPCG7eCQvQfTMepcuWjgc9BAyFYcBjPFmLnvX69LE80Fw0Io1QeKIa6CVJKp4P6eC8OIKeG1fTc3/sWxr+3ZKTzGPKiGCnSMo7qM0/2HlV0bhp8yWFni+2nZ8UlPJluEnmx0bBR0uZ6bdqzLX/fFrmgTd6m30+Zq8pjKVhiHpEQd9m5aU2inCWv4OeNE3EQsLYcnhcVdrcySZ6R4AZ1nlZZedDhf+Ee4AwcIPVsA8HHqlUEY1CayHF5wLpkxralOpt+RFZYJkvupmozP/uYRymoAA6YgJGesr2Oki0wT041nioB9AvpU9xFvfCqbqXXsBvwtvhxpwhEJJOogZENKnjvvoDoLGZlFVPzkfqDANuv5SAJQiWuFLWEdcmQncRlsjwSPOGOnI+r+puHszPOaDsZigF/yuL4rd5a0RkS6dCOfYtCvQBBAMfEAWX13AiKF0Dtz5/ijEEK7iojoMF/B6rnoENs2l0cSljq7TGV0DVRDjFUTiMNbfRxUJUkMuqJFnNzMwz4METmAwgqHn217uvUk2V8UJ5v9k4sapRmogPTfCwhvxGDV1e9AJvL6WXJ2m0ldhKOcQXFiO/+ZtNB1FHJ22ZFcxcSSOSRmEQsB5Yw3zPEjQ7sU93sKRLEPrTEqSSNG75iZ+vZm9iEI2trFhtEOlU98Ury/USC9sjPN/sxGGR5hcRZajY2HUxVTucMheIWJ7mxhxLHg7rz/qWLSqC6TqKwnyv+NdBnrVaLWaRnZGRCgtvN+oJKRjyxCsiDHVoY52cP5SmdXGn3yrVxDuYGrkLf/JOj76Hs/TCSsYptMvKqH4R4vT8SlDnplpcIfd5KTr4sM1n4q4sai1wRc1wlN0EkwK7+otTYcStxtvgUUtW/4jkk+73TdvvR9IkV0PqghKuB6FdAM6qRX1M8AebcXNyZYW9k7sHRVWGk+eMrMe/qX2IAY1WUgdt7hs2Ci9XoJqWKCG17rcKZ/ORu0utrJt+l0H9fZihO8+aYHabsHueiyJTKJvZx9+12r5a6deXShtdpsdQVnMlczWKGKUIdQ7TB12HILGPAvvZkJh0aDq043UU/4dUwyUezi70QnH/Z/GRip68kXH6njBmZRlmmNAFSCHkGxMKxpgssHyXXNEvET/TIVEJeR1vYjqFoGIBrFQV1Bqu2yk3A2pZLBEEbsCQrOuE2CPpfrn5kCUnw2sJOWpnVqyQ+SA4xZ7W1vw7i8aL2ThZlKE3zsriECpOfEaDWv8ME2HsiL42VUmgv+6zm/2hiVK+OayQucBUbY8IC6Yjl2kXB7EPvUsc60V2xOJl40KIAJxa0GNgaRMWkYoFtnVrYbY4yT37UjIAu2fJD725qgkXOJwbFPlX7na86PVVB0MQ==,iv:JSG8DynJg8t7HEDoW7IwYt189P22h4BPMFYsJmo3mcU=,tag:cHoNQBL2DCpntJyhqay54Q==,type:str]", "sops": { "age": [ { @@ -7,8 +7,8 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyK0w2RjJ5R1l2ay94QXRj\nekJwSlowcFVLc1cvWVFjNEVFUnFocEJHYlNnCnBnUEYvNWdNWE9BTjB5ODRuTlAw\nMUh4QmlTeVVYNHM0S1FwWG5qUG42VDgKLS0tIHh5VlU2dVZmUlRIMDRlVEJmNU55\ncFlXR1BzMkVnMkFWN3BBZWhHalltMlEKibdARxBcFqaXUhYp3KkrrvO9YgaBDacl\n8BEv4ph0f2baDN0dsymJjmdHStwKTjOwDspRtCTs5u75hR35a2xyFQ==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2025-06-28T22:52:43Z", - "mac": "ENC[AES256_GCM,data:iv7/BhKzDCsx3I7lmwaBr9BHvTausvWDky2drGZD0YXJqh3KNAp9e2MZnPs8RzsavsEd23JG6Xi1u9cnlcJtmkebBTqrUPZOSJz6RTw/YAlCSR+d1Az5B10jY1wVeweGDVUn0ncVx2zzEjbguMQz4T1kcZU5XT7MX8XITDE6J9M=,iv:xPNHn6E4oTQ7F5f9Df8M+G07uxhhW7mXh2BWUX5cD9M=,tag:cU2OFctCdqdgQnTKns0yOQ==,type:str]", + "lastmodified": "2025-07-02T10:26:33Z", + "mac": "ENC[AES256_GCM,data:/rmQKH7up3IcAdyYpdpx6H6gdyiNsnPS6TaozSU0EXxoaods50xC5sf2/quqLaeSRJE/NjKvh+3BWchbFJMQZM4PvSML3XAO8w9t/GqmOwwLJrvnMyulqS5y7BVDJZysmDe9TFNz05UJfZdbvLrH8kyhTHF7ciA8HgJq5JzFiBc=,iv:ORyza5fzjptuq5WD3NA9/OTFbACtzHp5e6kNKT/EaTE=,tag:wsp3Z/ySHVmDC9uRCn30Uw==,type:str]", "pgp": [ { "created_at": "2025-06-11T11:42:23Z", diff --git a/index.html b/index.html index b511e56..d9c88f3 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 @@ -256,7 +256,12 @@
  • 3.1.3. Virtual hosts
  • @@ -743,14 +750,29 @@
  • 6.3. tridactyl theme
  • 6.4. Waybar style.css
  • 6.5. justfile
  • -
  • 6.6. GitHub Readme
  • +
  • 6.6. aspell.conf
  • +
  • 6.7. nix-plugins.patch
  • +
  • 6.8. Zellij layout default.kdl.nix
  • +
  • 6.9. Zellij config.kdl.nix
  • +
  • 6.10. Vieb config
  • +
  • 6.11. swayidle
  • +
  • 6.12. stylix color scheme
  • +
  • 6.13. .gitmessage
  • +
  • 6.14. userChrome.css
  • +
  • 6.15. Default Flake Template
  • +
  • 6.16. C++ Flake Template
  • +
  • 6.17. Go Flake Template
  • +
  • 6.18. LaTeX Flake Template
  • +
  • 6.19. Python Flake Template
  • +
  • 6.20. Rust Flake Template
  • +
  • 6.21. GitHub Readme
  • -This file has 76328 words spanning 20028 lines and was last revised on 2025-07-01 00:53:42 +0200. +This file has 83537 words spanning 21934 lines and was last revised on 2025-07-02 01:23:11 +0200.

    @@ -803,7 +825,7 @@ This section defines my Emacs configuration. For a while, I considered to use ry

    -My emacs is built using the emacs-overlay nix flake, which builds a bleeding edge emacs on wayland (pgtk) with utilities like treesitter support. By executing the below source block, the current build setting can be updated at any time, and you can see my most up-to-date build options (last updated: 2025-07-01 00:53:42 +0200) +My emacs is built using the emacs-overlay nix flake, which builds a bleeding edge emacs on wayland (pgtk) with utilities like treesitter support. By executing the below source block, the current build setting can be updated at any time, and you can see my most up-to-date build options (last updated: 2025-07-02 01:23:11 +0200)

    @@ -908,7 +930,7 @@ For archival reasons, here is shown how to use a noweb-ref block, in case I ever
    -
    enable = true;
    +
    enable = true;
     
    @@ -917,7 +939,7 @@ which can then be used in a block like:

    -
    enable = true;
    +
    enable = true;
     
    @@ -962,7 +984,7 @@ Holds the aforementioned filesystem configuration and is applied using -
    {
    +
    {
       my_value = 2;
       my_attrSet = {
         enable = true;
    @@ -1156,7 +1178,7 @@ In outputs = inputs@ [...], the inputs@ makes it so th
         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-linux";
    +    systems.url = "github:nix-systems/default";
         home-manager = {
           url = "github:nix-community/home-manager";
           inputs.nixpkgs.follows = "nixpkgs";
    @@ -1338,7 +1360,7 @@ In outputs = inputs@ [...], the inputs@ makes it so th
     
                   # nixosModules = import ./modules/nixos { inherit lib; };
                   # homeModules = import ./modules/home { inherit lib; };
    -              packages = lib.swarselsystems.forEachSystem (pkgs: import ./pkgs { inherit lib pkgs; });
    +              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; };
     
    @@ -1422,6 +1444,8 @@ In outputs = inputs@ [...], the inputs@ makes it so th
             systems = [
               "x86_64-linux"
               "aarch64-linux"
    +          "x86_64-darwin"
    +          "aarch64-darwin"
             ];
           };
     }
    @@ -1501,13 +1525,13 @@ 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-linux";
    +systems.url = "github:nix-systems/default";
     home-manager = {
       url = "github:nix-community/home-manager";
       inputs.nixpkgs.follows = "nixpkgs";
    @@ -1589,7 +1613,7 @@ Here I define a few variables that I need for my system specifications. There us
     
     
     
    @@ -1821,7 +1845,7 @@ In contrast, this defines home-manager systems, which I only have one of, that s
     

    -
    +
     # "swarsel@home-manager" = inputs.home-manager.lib.homeManagerConfiguration {
     #  pkgs = lib.swarselsystems.pkgsFor.x86_64-linux;
     #  extraSpecialArgs = { inherit inputs outputs; };
    @@ -1842,7 +1866,7 @@ 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 = [
    @@ -1859,7 +1883,7 @@ Nix on Android also demands an own flake output, which is provided here.
     

    2.11. topologyConfigurations

    -
    +
     
     
    @@ -1892,7 +1916,7 @@ 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, primaryUser, ... }:
     let
       modulesPath = "${self}/modules";
       sharedOptions = {
    @@ -1964,7 +1988,7 @@ Acceptance of arbitraty argumments is here needed because disko pas
     

    -
    { lib, pkgs, config, rootDisk, ... }:
    +
    { lib, pkgs, config, rootDisk, ... }:
     let
       type = "btrfs";
       extraArgs = [ "-L" "nixos" "-f" ]; # force overwrite
    @@ -2109,7 +2133,7 @@ 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, primaryUser, ... }:
     let
       sharedOptions = {
         isBtrfs = true;
    @@ -2196,7 +2220,7 @@ in
     
    3.1.2.1.2. hardware-configuration
    -
    { config, lib, pkgs, modulesPath, ... }:
    +
    { config, lib, pkgs, modulesPath, ... }:
     {
       imports =
         [
    @@ -2274,7 +2298,7 @@ in
     
    3.1.2.1.3. disko
    -
    {
    +
    {
       disko.devices = {
         disk = {
           nvme0n1 = {
    @@ -2368,7 +2392,7 @@ 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, primaryUser, ... }:
     let
       sharedOptions = {
         isBtrfs = false;
    @@ -2424,7 +2448,7 @@ in
     
    3.1.2.2.2. hardware-configuration
    -
    { config, lib, modulesPath, ... }:
    +
    { config, lib, modulesPath, ... }:
     
     {
       imports =
    @@ -2482,7 +2506,7 @@ A Mac notebook that I have received from work. I use this machine for getting ac
     

    -
    { lib, ... }:
    +
    { lib, ... }:
     let
       inherit (config.repo.secrets.local) workUser;
     in
    @@ -2517,7 +2541,7 @@ My phone. I use only a minimal config for remote debugging here.
     

    -
    +
     { pkgs, ... }: {
       environment = {
         packages = with pkgs; [
    @@ -2598,9 +2622,12 @@ Syncthing backup of replaceable data
     All of these are processes that use little cpu but can take a lot of storage. For this I use a free Ampere instance from OCI with 50G of space. In case my account gets terminated, all of this data is easily replaceable or backed up regularly anyways.
     

    - +
    +
    +
    3.1.3.1.1. Main configuration
    +
    -
    { lib, config, primaryUser, ... }:
    +
    { lib, config, primaryUser, ... }:
     let
       sharedOptions = {
         isBtrfs = false;
    @@ -2778,6 +2805,53 @@ in
     
    +
    +
    3.1.3.1.2. hardware-configuration
    +
    +
    +
    { config, lib, modulesPath, ... }: {
    +  imports = [
    +    (modulesPath + "/profiles/qemu-guest.nix")
    +  ];
    +
    +  boot = {
    +    initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" ];
    +    initrd.kernelModules = [ ];
    +    kernelModules = [ "kvm-amd" ];
    +    extraModulePackages = [ ];
    +  };
    +
    +  fileSystems = {
    +    "/" = {
    +      device = "/dev/disk/by-uuid/4b47378a-02eb-4548-bab8-59cbf379252a";
    +      fsType = "xfs";
    +    };
    +
    +    "/boot" = {
    +      device = "/dev/disk/by-uuid/2B75-2AD5";
    +      fsType = "vfat";
    +    };
    +  };
    +
    +  swapDevices = [
    +    { device = "/dev/disk/by-uuid/f0126a93-753e-4769-ada8-7499a1efb3a9"; }
    +  ];
    +
    +  # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
    +  # (the default) this is the recommended approach. When using systemd-networkd it's
    +  # still possible to use this option, but it's recommended to use it in conjunction
    +  # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
    +  networking.useDHCP = lib.mkDefault true;
    +  # networking.interfaces.ens3.useDHCP = lib.mkDefault true;
    +
    +  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
    +  hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
    +}
    +
    +
    +
    +
    +
    3.1.3.2. Moonside (OCI)
    @@ -2786,7 +2860,7 @@ in
    3.1.3.2.1. Main Configuration
    -
    { lib, config, primaryUser, ... }:
    +
    { lib, config, primaryUser, ... }:
     let
       inherit (config.repo.secrets.common) workHostName;
       inherit (config.repo.secrets.local.syncthing) dev1 dev2 dev3 loc1;
    @@ -3021,15 +3095,8 @@ in
     
    3.1.3.2.2. hardware-configuration
    -

    -loader.grub = { - efiSupport = true; - efiInstallAsRemovable = true; - device = "nodev"; -}; -

    -
    { lib, modulesPath, ... }:
    +
    { lib, modulesPath, ... }:
     {
       imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
     
    @@ -3052,7 +3119,7 @@ loader.grub = {
     
    3.1.3.2.3. disko
    -
    # NOTE: ... is needed because dikso passes diskoFile
    +
    # NOTE: ... is needed because dikso passes diskoFile
     { lib
     , config
     , rootDisk
    @@ -3199,7 +3266,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, primaryUser, ... }:
     let
       modulesPath = "${self}/modules";
       sharedOptions = {
    @@ -3291,7 +3358,7 @@ in
     
    3.1.4.1.2. disko
    -
    # NOTE: ... is needed because dikso passes diskoFile
    +
    # NOTE: ... is needed because dikso passes diskoFile
     { lib
     , pkgs
     , config
    @@ -3458,7 +3525,7 @@ Also, an initial bash history is provided to allow for a very quick local deploy
     
     
     
    -
    { self, pkgs, inputs, config, lib, modulesPath, primaryUser ? "swarsel", ... }:
    +
    { self, pkgs, inputs, config, lib, modulesPath, primaryUser ? "swarsel", ... }:
     let
       pubKeys = lib.filesystem.listFilesRecursive "${self}/secrets/keys/ssh";
     in
    @@ -3610,7 +3677,7 @@ This is the "reference implementation" of a setup that runs without NixOS, only
     

    -
    { self, outputs, config, ... }:
    +
    { self, outputs, config, ... }:
     {
     
       imports = [
    @@ -3669,7 +3736,7 @@ 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, primaryUser, ... }:
     let
       sharedOptions = {
         isBtrfs = false;
    @@ -3741,15 +3808,151 @@ in
     }
     
     
    +
    +
    +
    +
    +
    +
    3.1.4.4.2. disko
    +
    +
    +
    # 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;
    +    };
    +  };
    +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"
    +                  ];
    +                };
    +                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;
    +
    +  environment.systemPackages = [
    +    pkgs.yubikey-manager
    +  ];
    +}
     
    -
    3.1.4.4.2. NixOS dummy options configuration
    +
    3.1.4.4.3. NixOS dummy options configuration
    -
    _:
    +
    _:
     { }
     
     
    @@ -3757,10 +3960,10 @@ in
    -
    3.1.4.4.3. home-manager dummy options configuration
    +
    3.1.4.4.4. home-manager dummy options configuration
    -
    _:
    +
    _:
     { }
     
     
    @@ -3810,7 +4013,7 @@ Note: The structure of generating the packages was changed in commit 2cf03

    -
    { lib, pkgs, ... }:
    +
    { lib, pkgs, ... }:
     let
       packageNames = lib.swarselsystems.readNix "pkgs";
     in
    @@ -3883,7 +4086,7 @@ notify-send -u critical -a pass -t 1000 "Copied/Typed Password"
     
    -
    { self, name, writeShellApplication, libnotify, pass, fuzzel, wtype }:
    +
    { self, name, writeShellApplication, libnotify, pass, fuzzel, wtype }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ libnotify (pass.withExtensions (exts: [ exts.pass-otp ])) fuzzel wtype ];
    @@ -3903,7 +4106,7 @@ The version of cura used to be quite outdated in nixpkgs. I am fetc
     
     
     
    -
    # taken from https://github.com/NixOS/nixpkgs/issues/186570#issuecomment-1627797219
    +
    # taken from https://github.com/NixOS/nixpkgs/issues/186570#issuecomment-1627797219
     { appimageTools, fetchurl, writeScriptBin, pkgs, ... }:
     
     
    @@ -3946,7 +4149,7 @@ This script allows for quick git home-manager specialisation switching.
     
     
     
    -
    { name, writeShellApplication, fzf, findutils, home-manager, ... }:
    +
    { name, writeShellApplication, fzf, findutils, home-manager, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -3972,7 +4175,7 @@ This script allows for quick git worktree switching.
     
     
     
    -
    { name, writeShellApplication, fzf, ... }:
    +
    { name, writeShellApplication, fzf, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -3995,7 +4198,7 @@ This script allows for quick git branch switching.
     

    -
    { name, writeShellApplication, fzf, ... }:
    +
    { name, writeShellApplication, fzf, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -4018,7 +4221,7 @@ This script lets me quickly backup files by appending .bak to the f
     
     
     
    -
    { name, writeShellApplication, ... }:
    +
    { name, writeShellApplication, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -4041,7 +4244,7 @@ This app starts a configuratble timer and uses TTS to say something once the tim
     
     
     
    -
    { name, writeShellApplication, speechd, ... }:
    +
    { name, writeShellApplication, speechd, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -4090,7 +4293,7 @@ fi
     
    -
    { self, name, writeShellApplication, emacs30-pgtk, sway, jq }:
    +
    { self, name, writeShellApplication, emacs30-pgtk, sway, jq }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ emacs30-pgtk sway jq ];
    @@ -4221,7 +4424,7 @@ fi
     
    -
    { self, name, writeShellApplication, kitty, element-desktop, vesktop, spotify-player, jq }:
    +
    { self, name, writeShellApplication, kitty, element-desktop, vesktop, spotify-player, jq }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ kitty element-desktop vesktop spotify-player jq ];
    @@ -4247,7 +4450,7 @@ fi
     
    -
    { self, name, writeShellApplication, kitty }:
    +
    { self, name, writeShellApplication, kitty }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ kitty ];
    @@ -4294,7 +4497,7 @@ echo "$OUT"
     
    -
    { self, name, writeShellApplication, git }:
    +
    { self, name, writeShellApplication, git }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ git ];
    @@ -4322,7 +4525,7 @@ fi
     
    -
    { self, name, writeShellApplication, sway }:
    +
    { self, name, writeShellApplication, sway }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ sway ];
    @@ -4364,7 +4567,7 @@ sudo btrfs subvolume find-new "/mnt/root" "$OLD_TRANSID" |
     
    -
    { self, name, writeShellApplication }:
    +
    { self, name, writeShellApplication }:
     writeShellApplication {
       inherit name;
       text = builtins.readFile "${self}/scripts/${name}.sh";
    @@ -4382,7 +4585,7 @@ This utility checks if there are updated packages in nixpkgs-unstable. It does s
     
     
     
    -
    { name, writeShellApplication, jq, ... }:
    +
    { name, writeShellApplication, jq, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -4407,7 +4610,7 @@ This application moves the wl-mirror app to the T workspace and makes it fullscr
     

    -
    { name, writeShellApplication, sway, ... }:
    +
    { name, writeShellApplication, sway, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -4454,7 +4657,7 @@ fi
     
     
     
    -
    { self, name, writeShellApplication, sway }:
    +
    { self, name, writeShellApplication, sway }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ sway ];
    @@ -4816,7 +5019,7 @@ fi
     
     
     
    -
    { self, name, writeShellApplication, openssh }:
    +
    { self, name, writeShellApplication, openssh }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ openssh ];
    @@ -4936,7 +5139,7 @@ yellow "Please keep in mind that this is only a demo of the configuration. Thing
     
     
     
    -
    { self, name, writeShellApplication, git }:
    +
    { self, name, writeShellApplication, git }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ git ];
    @@ -5174,7 +5377,7 @@ green "Installation finished! Reboot to see changes"
     
     
     
    -
    { self, name, writeShellApplication, git }:
    +
    { self, name, writeShellApplication, git }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ git ];
    @@ -5268,7 +5471,7 @@ green "Post-install finished!"
     
     
     
    -
    { self, name, writeShellApplication, git }:
    +
    { self, name, writeShellApplication, git }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ git ];
    @@ -5282,7 +5485,7 @@ writeShellApplication {
     
    3.2.1.22. t2ts
    -
    { name, writeShellApplication, ... }:
    +
    { name, writeShellApplication, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -5300,7 +5503,7 @@ writeShellApplication {
     
    3.2.1.23. ts2t
    -
    { name, writeShellApplication, ... }:
    +
    { name, writeShellApplication, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -5318,7 +5521,7 @@ writeShellApplication {
     
    3.2.1.24. vershell
    -
    { name, writeShellApplication, ... }:
    +
    { name, writeShellApplication, ... }:
     
     writeShellApplication {
       inherit name;
    @@ -5336,7 +5539,7 @@ writeShellApplication {
     
    3.2.1.25. eontimer
    -
    { lib
    +
    { lib
     , python3
     , fetchFromGitHub
     , makeDesktopItem
    @@ -5451,7 +5654,7 @@ direnv allow
     
    -
    { self, name, writeShellApplication }:
    +
    { self, name, writeShellApplication }:
     writeShellApplication {
       inherit name;
       text = builtins.readFile "${self}/scripts/${name}.sh";
    @@ -5464,7 +5667,7 @@ writeShellApplication {
     
    3.2.1.27. fhs
    -
    { name, pkgs, ... }:
    +
    { name, pkgs, ... }:
     let
       base = pkgs.appimageTools.defaultFhsEnvArgs;
     in
    @@ -5493,7 +5696,7 @@ swaymsg "output * dpms on" > /dev/null 2>&1 || true
     
    -
    { self, name, writeShellApplication, sway }:
    +
    { self, name, writeShellApplication, sway }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ sway ];
    @@ -5513,7 +5716,7 @@ AppImage version of mgba in which the lua scripting works.
     
     
     
    -
    { appimageTools, fetchurl, ... }:
    +
    { appimageTools, fetchurl, ... }:
     let
       pname = "mgba";
       version = "0.10.4";
    @@ -5542,7 +5745,7 @@ appimageTools.wrapType2 {
     
    3.2.1.30. swarsel-deploy
    -
    # heavily inspired from https://github.com/oddlama/nix-config/blob/d42cbde676001a7ad8a3cace156e050933a4dcc3/pkgs/deploy.nix
    +
    # 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 ];
    @@ -5693,7 +5896,7 @@ fi
     
    -
    { self, name, writeShellApplication, openssh }:
    +
    { self, name, writeShellApplication, openssh }:
     writeShellApplication {
       inherit name;
       runtimeInputs = [ openssh ];
    @@ -5716,7 +5919,7 @@ When adding a new entry here, do not forget to add it in the default output of t
     

    -
    { self, inputs, lib, ... }:
    +
    { self, inputs, lib, ... }:
     
     let
       additions = final: _: import "${self}/pkgs" { pkgs = final; inherit lib; };
    @@ -5826,7 +6029,7 @@ Modules that need to be loaded on the NixOS level. Note that these will not be a
     

    -
    { lib, ... }:
    +
    { lib, ... }:
     let
       profileNames = lib.swarselsystems.readNix "profiles/nixos";
     in
    @@ -5840,7 +6043,7 @@ in
     
    3.2.3.1.1. Personal
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.personal = lib.mkEnableOption "is this a personal host";
       config = lib.mkIf config.swarselsystems.profiles.personal {
    @@ -5911,7 +6114,7 @@ in
     
    3.2.3.1.2. Chaostheatre
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.chaostheatre = lib.mkEnableOption "is this a chaostheatre host";
       config = lib.mkIf config.swarselsystems.profiles.chaostheatre {
    @@ -5974,7 +6177,7 @@ in
     
    3.2.3.1.3. toto
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.toto = lib.mkEnableOption "is this a toto (setup) host";
       config = lib.mkIf config.swarselsystems.profiles.toto {
    @@ -6007,7 +6210,7 @@ in
     
    3.2.3.1.4. Work
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.work = lib.mkEnableOption "is this a work host";
       config = lib.mkIf config.swarselsystems.profiles.work {
    @@ -6029,7 +6232,7 @@ in
     
    3.2.3.1.5. Framework
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.framework = lib.mkEnableOption "is this a framework brand host";
       config = lib.mkIf config.swarselsystems.profiles.framework {
    @@ -6051,7 +6254,7 @@ in
     
    3.2.3.1.6. AMD CPU
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.amdcpu = lib.mkEnableOption "is this a host with amd cpu";
       config = lib.mkIf config.swarselsystems.profiles.amdcpu {
    @@ -6073,7 +6276,7 @@ in
     
    3.2.3.1.7. AMD GPU
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.amdgpu = lib.mkEnableOption "is this a host with amd gpu";
       config = lib.mkIf config.swarselsystems.profiles.amdgpu {
    @@ -6095,7 +6298,7 @@ in
     
    3.2.3.1.8. Hibernation
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.hibernation = lib.mkEnableOption "is this a host using hibernation";
       config = lib.mkIf config.swarselsystems.profiles.hibernation {
    @@ -6117,7 +6320,7 @@ in
     
    3.2.3.1.9. BTRFS
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.btrfs = lib.mkEnableOption "is this a host using btrfs";
       config = lib.mkIf config.swarselsystems.profiles.btrfs {
    @@ -6139,7 +6342,7 @@ in
     
    3.2.3.1.10. Local Server
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.server.local = lib.mkEnableOption "is this a local server";
       config = lib.mkIf config.swarselsystems.profiles.server.local {
    @@ -6196,7 +6399,7 @@ in
     
    3.2.3.1.11. OCI Sync Server
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.server.sync = lib.mkEnableOption "is this a oci sync server";
       config = lib.mkIf config.swarselsystems.profiles.server.sync {
    @@ -6233,7 +6436,7 @@ in
     
    3.2.3.1.12. Moonside
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.server.moonside = lib.mkEnableOption "is this a moonside server";
       config = lib.mkIf config.swarselsystems.profiles.server.moonside {
    @@ -6277,7 +6480,7 @@ This holds modules that are to be used on most hosts. These are also the most im
     

    -
    { lib, ... }:
    +
    { lib, ... }:
     let
       profileNames = lib.swarselsystems.readNix "profiles/home";
     in
    @@ -6291,7 +6494,7 @@ in
     
    3.2.3.2.1. Personal
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.personal = lib.mkEnableOption "is this a personal host";
       config = lib.mkIf config.swarselsystems.profiles.personal {
    @@ -6350,7 +6553,7 @@ in
     
    3.2.3.2.2. Chaostheatre
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.chaostheatre = lib.mkEnableOption "is this a chaostheatre host";
       config = lib.mkIf config.swarselsystems.profiles.chaostheatre {
    @@ -6403,7 +6606,7 @@ in
     
    3.2.3.2.3. toto
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.toto = lib.mkEnableOption "is this a toto (setup) host";
       config = lib.mkIf config.swarselsystems.profiles.toto {
    @@ -6424,7 +6627,7 @@ in
     
    3.2.3.2.4. Work
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.work = lib.mkEnableOption "is this a work host";
       config = lib.mkIf config.swarselsystems.profiles.work {
    @@ -6445,7 +6648,7 @@ in
     
    3.2.3.2.5. Framework
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.framework = lib.mkEnableOption "is this a framework brand host";
       config = lib.mkIf config.swarselsystems.profiles.framework {
    @@ -6467,7 +6670,7 @@ in
     
    3.2.3.2.6. Darwin
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.darwin = lib.mkEnableOption "is this a darwin host";
       config = lib.mkIf config.swarselsystems.profiles.darwin {
    @@ -6486,7 +6689,7 @@ in
     
    3.2.3.2.7. Local Server
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.profiles.server.local = lib.mkEnableOption "is this a local server";
       config = lib.mkIf config.swarselsystems.profiles.server.local {
    @@ -6534,7 +6737,7 @@ TODO
     

    -
    { self, lib, systems, inputs, ... }:
    +
    { self, lib, systems, inputs, ... }:
     {
     
       mkIfElseList = p: yes: no: lib.mkMerge [
    @@ -6559,6 +6762,19 @@ TODO
         }
       );
     
    +  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;
    @@ -6578,6 +6794,7 @@ TODO
       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}"));
    @@ -6652,7 +6869,7 @@ TODO
     
    3.2.5.1. extra-builtins
    -
    # adapted from https://github.com/oddlama/nix-config/blob/main/nix/extra-builtins.nix
    +
    # adapted from https://github.com/oddlama/nix-config/blob/main/nix/extra-builtins.nix
     { exec, ... }:
     let
       assertMsg = pred: msg: pred || builtins.throw msg;
    @@ -6688,8 +6905,7 @@ in
     
    3.2.5.2. sops-decrypt-and-cache
    -
    #!/usr/bin/env bash
    -# adapted from https://github.com/oddlama/nix-config/blob/main/nix/rage-decrypt-and-cache.sh
    +
    # adapted from https://github.com/oddlama/nix-config/blob/main/nix/rage-decrypt-and-cache.sh
     set -euo pipefail
     
     print_out_path=false
    @@ -6736,7 +6952,7 @@ fi
     
    3.2.5.3. nix-topology
    -
    { config, ... }:
    +
    { config, ... }:
     let
       inherit (config.lib.topology)
         mkInternet
    @@ -6766,9 +6982,15 @@ in
             (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 = { };
     
    @@ -6888,7 +7110,9 @@ in
           image = ../topology/images/DELL-C2665dnf.png;
           interfaces.eth1 = { };
         };
    +
       };
    +
     }
     
     
    @@ -6899,7 +7123,7 @@ in
    3.2.5.4. Globals
    -
    { inputs, ... }:
    +
    { inputs, ... }:
     {
       flake =
         {
    @@ -6977,7 +7201,7 @@ This section is for setting things that should be used on hosts that are using t
     

    -
    { self, lib, ... }:
    +
    { self, lib, ... }:
     let
       importNames = lib.swarselsystems.readNix "modules/nixos/common";
       modulesPath = "${self}/modules";
    @@ -7002,7 +7226,7 @@ I usually use mutableUsers = false in my NixOS configuration. Howev
     

    -
    { lib, ... }:
    +
    { lib, ... }:
     {
       options = {
         swarselsystems = {
    @@ -7076,7 +7300,7 @@ A breakdown of the flags being set:
     
     
     
    -
    { lib, pkgs, config, outputs, inputs, ... }:
    +
    { lib, pkgs, config, outputs, inputs, ... }:
     {
       options.swarselsystems.modules.general = lib.mkEnableOption "general nix settings";
       config = lib.mkIf config.swarselsystems.modules.general {
    @@ -7147,7 +7371,7 @@ A breakdown of the flags being set:
     
    3.3.1.4. Share configuration between nodes
    -
    # adapted from https://github.com/oddlama/nix-config/blob/main/modules/distributed-config.nix
    +
    # adapted from https://github.com/oddlama/nix-config/blob/main/modules/distributed-config.nix
     { config, lib, outputs, ... }:
     let
       nodeName = config.node.name;
    @@ -7219,7 +7443,7 @@ in
     
    3.3.1.5. Global options
    -
    { lib, options, ... }:
    +
    { lib, options, ... }:
     let
       inherit (lib)
         mkOption
    @@ -7306,7 +7530,7 @@ Mostly used to install some compilers and lsp's that I want to have available wh
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.packages = lib.mkEnableOption "install packages";
       config = lib.mkIf config.swarselsystems.modules.packages {
    @@ -7402,7 +7626,7 @@ We enable the use of home-manager as a NixoS module. A nice trick h
     

    -
    { inputs, config, lib, ... }:
    +
    { inputs, config, lib, ... }:
     {
     
       options.swarselsystems.modules.home-manager = lib.mkEnableOption "home-manager";
    @@ -7434,7 +7658,7 @@ This sets up the nix-secrets extraSpeciaArgs. This should not be pr
     

    -
    { inputs, config, lib, ... }:
    +
    { inputs, config, lib, ... }:
     {
       options.swarselsystems.modules.home-managerExtra = lib.mkEnableOption "home-manager extras for non-chaostheatre";
       config = lib.mkIf config.swarselsystems.modules.home-managerExtra {
    @@ -7455,7 +7679,7 @@ Next, we setup the keymap in case we are not in a graphical session. At this poi
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.xserver = lib.mkEnableOption "xserver keymap";
       config = lib.mkIf config.swarselsystems.modules.packages {
    @@ -7484,7 +7708,7 @@ For that reason, make sure that sops-nix is properly working before
     

    -
    { self, pkgs, config, lib, ... }:
    +
    { self, pkgs, config, lib, ... }:
     let
       sopsFile = self + /secrets/general/secrets.yaml;
     in
    @@ -7518,7 +7742,7 @@ Next, we will setup some environment variables that need to be set on the system
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.env = lib.mkEnableOption "environment config";
       config = lib.mkIf config.swarselsystems.modules.env {
    @@ -7549,7 +7773,7 @@ Needed for control over system-wide privileges etc. Also I make sure that the ro
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.security = lib.mkEnableOption "security config";
       config = lib.mkIf config.swarselsystems.modules.security {
    @@ -7583,7 +7807,7 @@ There is a persistent bug over Linux kernels that makes the user wait 1m30s on s
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.systemdTimeout = lib.mkEnableOption "systemd timeout config";
       config = lib.mkIf config.swarselsystems.modules.systemdTimeout {
    @@ -7606,7 +7830,7 @@ Enable OpenGL, Sound, Bluetooth and various drivers.
     

    -
    { pkgs, config, lib, ... }:
    +
    { pkgs, config, lib, ... }:
     {
     
       options.swarselsystems = {
    @@ -7667,7 +7891,7 @@ This is only used on systems not running Pipewire.
     
     
     
    -
    { config, pkgs, lib, ... }: {
    +
    { config, pkgs, lib, ... }: {
     
       options.swarselsystems.modules.pulseaudio = lib.mkEnableOption "pulseaudio config";
       config = lib.mkIf config.swarselsystems.modules.pulseaudio {
    @@ -7690,7 +7914,7 @@ Pipewire handles communication on Wayland. This enables several sound tools as w
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.pipewire = lib.mkEnableOption "pipewire config";
       config = lib.mkIf config.swarselsystems.modules.pipewire {
    @@ -7722,7 +7946,7 @@ Here I only enable networkmanager and a few default networks. The r
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems = {
         modules.network = lib.mkEnableOption "network config";
    @@ -7985,7 +8209,7 @@ Setup timezone and locale. I want to use the US layout, but have the rest adapte
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.time = lib.mkEnableOption "time config";
       config = lib.mkIf config.swarselsystems.modules.time {
    @@ -8018,7 +8242,7 @@ Setup timezone and locale. I want to use the US layout, but have the rest adapte
     
    3.3.1.19. Meta options
    -
    { lib, ... }:
    +
    { lib, ... }:
     {
       options = {
         node = {
    @@ -8042,7 +8266,7 @@ Setup timezone and locale. I want to use the US layout, but have the rest adapte
     
    3.3.1.20. Topology
    -
    { self, lib, config, ... }:
    +
    { self, lib, config, ... }:
     {
       options.swarselsystems.info = lib.mkOption {
         type = lib.types.str;
    @@ -8075,7 +8299,7 @@ I use sops-nix to handle secrets that I want to have available on my machines at
     
     
     
    -
    { self, config, lib, ... }:
    +
    { self, config, lib, ... }:
     let
       certsSopsFile = self + /secrets/certs/secrets.yaml;
       inherit (config.swarselsystems) mainUser homeDir;
    @@ -8083,14 +8307,14 @@ in
     {
       options.swarselsystems.modules.commonSops = lib.mkEnableOption "sops config";
       config = lib.mkIf config.swarselsystems.modules.commonSops {
    -    sops = lib.mkIf (!config.swarselsystems.isPublic) {
    +    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";
     
           validateSopsFiles = false;
     
    -      secrets = {
    +      secrets = lib.mkIf (!config.swarselsystems.isPublic) {
             ernest = { };
             frauns = { };
             hotspot = { };
    @@ -8111,7 +8335,7 @@ in
             "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 = {
    +      templates = lib.mkIf (!config.swarselsystems.isPublic) {
             "network-manager.env".content = ''
               ERNEST=${config.sops.placeholder.ernest}
               FRAUNS=${config.sops.placeholder.frauns}
    @@ -8137,7 +8361,7 @@ in
     
    3.3.1.22. PII management
    -
    # largely based on https://github.com/oddlama/nix-config/blob/main/modules/secrets.nix
    +
    # largely based on https://github.com/oddlama/nix-config/blob/main/modules/secrets.nix
     { config, inputs, lib, ... }:
     let
     
    @@ -8224,7 +8448,7 @@ By default, stylix wants to style
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.stylix = lib.mkEnableOption "stylix config";
       config = lib.mkIf config.swarselsystems.modules.stylix {
    @@ -8253,7 +8477,7 @@ Some programs profit from being installed through dedicated NixOS settings on sy
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.programs = lib.mkEnableOption "small program modules config";
       config = lib.mkIf config.swarselsystems.modules.programs {
    @@ -8275,7 +8499,7 @@ Here I disable global completion to prevent redundant compinit calls and cache i
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.zsh = lib.mkEnableOption "zsh base config";
       config = lib.mkIf config.swarselsystems.modules.zsh {
    @@ -8296,7 +8520,7 @@ Here I disable global completion to prevent redundant compinit calls and cache i
     
    3.3.1.24.2. syncthing
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     let
       inherit (config.swarselsystems) mainUser homeDir;
     in
    @@ -8376,7 +8600,7 @@ Enables the blueman service including the nice system tray icon.
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.blueman = lib.mkEnableOption "blueman config";
       config = lib.mkIf config.swarselsystems.modules.blueman {
    @@ -8402,7 +8626,7 @@ Avahi is the service used for the network discovery.
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.networkDevices = lib.mkEnableOption "network device config";
       config = lib.mkIf config.swarselsystems.modules.networkDevices {
    @@ -8447,7 +8671,7 @@ This is being set to allow myself to use all functions of nautilus in NixOS
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.gvfs = lib.mkEnableOption "gvfs config for nautilus";
       config = lib.mkIf config.swarselsystems.modules.gvfs {
    @@ -8466,7 +8690,7 @@ This is a super-convenient package that lets my remap my CAPS key t
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.interceptionTools = lib.mkEnableOption "interception tools config";
       config = lib.mkIf config.swarselsystems.modules.interceptionTools {
    @@ -8520,7 +8744,7 @@ Most of the time I am using power-saver, however, it is good to be
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.ppd = lib.mkEnableOption "power profiles daemon config";
       config = lib.mkIf config.swarselsystems.modules.ppd {
    @@ -8535,7 +8759,7 @@ Most of the time I am using power-saver, however, it is good to be
     
    3.3.1.25.6. SwayOSD
    -
    { lib, pkgs, config, ... }:
    +
    { lib, pkgs, config, ... }:
     {
       options.swarselsystems.modules.swayosd = lib.mkEnableOption "swayosd settings";
       config = lib.mkIf config.swarselsystems.modules.swayosd {
    @@ -8586,7 +8810,7 @@ Also, since I use a GPG key in sops, it seems that scdaemon creates an instance
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.yubikey = lib.mkEnableOption "yubikey config";
       config = lib.mkIf config.swarselsystems.modules.yubikey {
    @@ -8614,7 +8838,7 @@ This performs the necessary configuration to support this hardware.
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.ledger = lib.mkEnableOption "ledger config";
       config = lib.mkIf config.swarselsystems.modules.ledger {
    @@ -8638,7 +8862,7 @@ This loads some udev rules that I need for my split keyboards.
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.keyboards = lib.mkEnableOption "keyboards config";
       config = lib.mkIf config.swarselsystems.modules.keyboards {
    @@ -8662,7 +8886,7 @@ This section houses the greetd related settings. I do not really want to use a d
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.login = lib.mkEnableOption "login config";
       config = lib.mkIf config.swarselsystems.modules.login {
    @@ -8705,7 +8929,7 @@ When a program does not work, start with nix-ldd <program>. T
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.nix-ld = lib.mkEnableOption "nix-ld config";
       config = lib.mkIf config.swarselsystems.modules.nix-ld {
    @@ -8834,7 +9058,7 @@ Normally, doing that also resets the lecture that happens on the first use of 
     
     
    -
    { config, lib, ... }:
    +
    { config, lib, ... }:
     let
       mapperTarget = lib.swarselsystems.mkIfElse config.swarselsystems.isCrypted "/dev/mapper/cryptroot" "/dev/disk/by-label/nixos";
       inherit (config.swarselsystems) isImpermanence isCrypted;
    @@ -8937,7 +9161,7 @@ This snipped is added to the activation script that is run after every rebuild a
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.nvd = lib.mkEnableOption "nvd config";
       config = lib.mkIf config.swarselsystems.modules.nvd {
    @@ -8962,7 +9186,7 @@ Used for storing sessions in e.g. Nextcloud. Using this on a system level keeps
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.gnome-keyring = lib.mkEnableOption "gnome-keyring config";
       config = lib.mkIf config.swarselsystems.modules.gnome-keyring {
    @@ -8985,7 +9209,7 @@ This is used to better integrate Sway into the system on NixOS hosts. On the hom
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.sway = lib.mkEnableOption "sway config";
       config = lib.mkIf config.swarselsystems.modules.sway {
    @@ -9021,7 +9245,7 @@ This allows me to use screen sharing on Wayland. The implementation is a bit cru
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.xdg-portal = lib.mkEnableOption "xdg portal config";
       config = lib.mkIf config.swarselsystems.modules.xdg-portal {
    @@ -9053,7 +9277,7 @@ I am using distrobox to quickly circumvent isses that I cannot immediately solve
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.distrobox = lib.mkEnableOption "distrobox config";
       config = lib.mkIf config.swarselsystems.modules.distrobox {
    @@ -9081,7 +9305,7 @@ Adds the necessary tools to allow .appimage programs easily.
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.appimage = lib.mkEnableOption "appimage config";
       config = lib.mkIf config.swarselsystems.modules.appimage {
    @@ -9104,7 +9328,7 @@ This turns off the display when the lid is closed.
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.lid = lib.mkEnableOption "lid config";
       config = lib.mkIf config.swarselsystems.modules.lid {
    @@ -9153,7 +9377,7 @@ Since I hide the waybar completely during normal operation, I run the risk of no
     

    -
    { pkgs, lib, config, ... }:
    +
    { pkgs, lib, config, ... }:
     {
       options.swarselsystems.modules.lowBattery = lib.mkEnableOption "low battery notification config";
       config = lib.mkIf config.swarselsystems.modules.lowBattery {
    @@ -9194,7 +9418,7 @@ This dynamically uses systemd boot or Lanzaboote depending on `config.swarselsys
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.lanzaboote = lib.mkEnableOption "lanzaboote config";
       config = lib.mkIf config.swarselsystems.modules.lanzaboote {
    @@ -9236,7 +9460,7 @@ Also, the system state version is set here. No need to touch it.
     

    -
    { self, lib, ... }:
    +
    { self, lib, ... }:
     let
       importNames = lib.swarselsystems.readNix "modules/nixos/server";
       modulesPath = "${self}/modules";
    @@ -9266,7 +9490,7 @@ Here we just define some aliases for rebuilding the system, and we allow some in
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     let
       inherit (config.swarselsystems) flakePath;
     in
    @@ -9311,7 +9535,7 @@ in
     
    3.3.2.3. System Packages
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.server.packages = lib.mkEnableOption "enable packages on server";
       config = lib.mkIf config.swarselsystems.modules.server.packages {
    @@ -9337,7 +9561,7 @@ in
     
    3.3.2.4. sops
    -
    { config, lib, ... }:
    +
    { config, lib, ... }:
     {
       options.swarselsystems.modules.server.sops = lib.mkEnableOption "enable sops on server";
       config = lib.mkIf config.swarselsystems.modules.server.sops {
    @@ -9356,7 +9580,7 @@ in
     
    3.3.2.5. nfs/samba (smb)
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.server.nfs = lib.mkEnableOption "enable nfs on server";
       config = lib.mkIf config.swarselsystems.modules.server.nfs {
    @@ -9391,7 +9615,6 @@ in
             };
           };
     
    -
           avahi = {
             publish.enable = true;
             publish.userServices = true; # Needed to allow samba to automatically register mDNS records without the need for an `extraServiceFile`
    @@ -9416,7 +9639,7 @@ in
     
    3.3.2.6. NGINX
    -
    { pkgs, lib, config, ... }:
    +
    { pkgs, lib, config, ... }:
     {
       options.swarselsystems.modules.server.nginx = lib.mkEnableOption "enable nginx on server";
       config = lib.mkIf config.swarselsystems.modules.server.nginx {
    @@ -9465,7 +9688,7 @@ Here I am forcing startWhenNeeded to false so that the value will n
     

    -
    { self, lib, config, ... }:
    +
    { self, lib, config, ... }:
     {
       options.swarselsystems.modules.server.ssh = lib.mkEnableOption "enable ssh on server";
       config = lib.mkIf config.swarselsystems.modules.server.ssh {
    @@ -9505,11 +9728,11 @@ Here I am forcing startWhenNeeded to false so that the value will n
     
    3.3.2.8. kavita
    -
    { self, lib, config, pkgs, ... }:
    +
    { self, lib, config, pkgs, ... }:
     let
       serviceName = "kavita";
       serviceUser = "kavita";
    -  serviceDomain = "scroll.swarsel.win";
    +  serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
       servicePort = 8080;
     in
     {
    @@ -9576,7 +9799,7 @@ in
     
    3.3.2.9. jellyfin
    -
    { pkgs, lib, config, ... }:
    +
    { pkgs, lib, config, ... }:
     let
       serviceDomain = "screen.swarsel.win";
       servicePort = 8096;
    @@ -9646,7 +9869,7 @@ in
     
    3.3.2.10. navidrome
    -
    { pkgs, config, lib, ... }:
    +
    { pkgs, config, lib, ... }:
     let
       serviceDomain = "sound.swarsel.win";
       servicePort = 4040;
    @@ -9790,7 +10013,7 @@ in
     
    3.3.2.11. spotifyd
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     let
       servicePort = 1025;
       serviceName = "spotifyd";
    @@ -9839,7 +10062,7 @@ in
     
    3.3.2.12. mpd
    -
    { self, lib, config, pkgs, ... }:
    +
    { self, lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.server.mpd = lib.mkEnableOption "enable mpd on server";
       config = lib.mkIf config.swarselsystems.modules.server.mpd {
    @@ -9905,7 +10128,7 @@ in
     
    3.3.2.13. pipewire
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       config = lib.mkIf (config?swarselsystems.modules.server.mpd || config?swarselsystems.modules.server.navidrome) {
     
    @@ -9933,7 +10156,7 @@ in
     
    3.3.2.14. postgresql
    -
    { config, lib, pkgs, ... }:
    +
    { config, lib, pkgs, ... }:
     let
       serviceName = "postgresql";
       postgresVersion = 14;
    @@ -9958,7 +10181,7 @@ in
     
    3.3.2.15. matrix
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     let
       matrixDomain = "swatrix.swarsel.win";
       serviceName = "matrix";
    @@ -10309,7 +10532,7 @@ in
     
    3.3.2.16. nextcloud
    -
    { pkgs, lib, config, ... }:
    +
    { pkgs, lib, config, ... }:
     let
       serviceDomain = "stash.swarsel.win";
       serviceUser = "nextcloud";
    @@ -10393,7 +10616,7 @@ in
     
    3.3.2.17. immich
    -
    { lib, config, globals, ... }:
    +
    { lib, config, globals, ... }:
     let
       serviceDomain = "shots.swarsel.win";
       servicePort = 3001;
    @@ -10477,7 +10700,7 @@ Also I install Tika and Gotenberg, which are needed to create PDFs out of 
     

    -
    { lib, pkgs, config, ... }:
    +
    { lib, pkgs, config, ... }:
     let
       serviceDomain = "scan.swarsel.win";
       servicePort = 28981;
    @@ -10613,7 +10836,7 @@ in
     
    3.3.2.19. transmission
    -
    { self, pkgs, lib, config, ... }:
    +
    { self, pkgs, lib, config, ... }:
     let
       serviceDomain = "store.swarsel.win";
       lidarrUser = "lidarr";
    @@ -10800,7 +11023,7 @@ in
     
    3.3.2.20. syncthing
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     let
       inherit (config.repo.secrets.common) workHostName;
       serviceDomain = "storync.swarsel.win";
    @@ -10940,7 +11163,7 @@ This manages backups for my pictures and obsidian files.
     

    -
    { lib, pkgs, config, ... }:
    +
    { lib, pkgs, config, ... }:
     let
       inherit (config.repo.secrets.local) resticRepo;
     in
    @@ -11006,12 +11229,14 @@ This section exposes several metrics that I use to check the health of my server
     

    -
    { self, lib, config, ... }:
    +
    { self, lib, config, ... }:
     let
       serviceDomain = "status.swarsel.win";
       servicePort = 3000;
       serviceUser = "grafana";
    +  prometheusUser = "prometheus";
       serviceGroup = serviceUser;
    +  prometheusGroup = prometheusUser;
       moduleName = "monitoring";
       grafanaUpstream = "grafana";
       prometheusUpstream = "prometheus";
    @@ -11022,10 +11247,24 @@ in
       options.swarselsystems.modules.server."${moduleName}" = lib.mkEnableOption "enable ${moduleName} on server";
       config = lib.mkIf config.swarselsystems.modules.server."${moduleName}" {
     
    -    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"; };
    +    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"; };
    +      };
    +      templates = {
    +        "web-config" = {
    +          content = ''
    +            basic_auth_users:
    +              admin: ${config.sops.placeholder.prometheus-admin-hash}
    +          '';
    +          owner = prometheusUser;
    +          group = prometheusGroup;
    +          mode = "0440";
    +        };
    +      };
         };
     
         users = {
    @@ -11125,7 +11364,7 @@ in
             globalConfig = {
               scrape_interval = "10s";
             };
    -        webConfigFile = self + /programs/server/prometheus/web.config;
    +        webConfigFile = config.sops.templates.web-config.path;
             scrapeConfigs = [
               {
                 job_name = "node";
    @@ -11238,7 +11477,7 @@ This is a WIP Jenkins instance. It is used to automatically build a new system w
     

    -
    { pkgs, lib, config, ... }:
    +
    { pkgs, lib, config, ... }:
     let
       serviceDomain = "servant.swarsel.win";
       servicePort = 8088;
    @@ -11296,7 +11535,7 @@ This was an approach of hosting an RSS server from within emacs. That would have
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.server.emacs = lib.mkEnableOption "enable emacs server on server";
       config = lib.mkIf config.swarselsystems.modules.server.emacs {
    @@ -11336,7 +11575,7 @@ FreshRSS claims to support HTTP header auth, but at least it does not work with
     

    -
    { self, lib, config, ... }:
    +
    { self, lib, config, ... }:
     let
       serviceName = "freshrss";
       serviceDomain = "signpost.swarsel.win";
    @@ -11442,7 +11681,7 @@ in
     
    3.3.2.26. forgejo (git server)
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     let
       serviceDomain = "swagit.swarsel.win";
       servicePort = 3000;
    @@ -11602,7 +11841,7 @@ in
     
    3.3.2.27. Anki Sync Server
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     let
       serviceDomain = "synki.swarsel.win";
       servicePort = 27701;
    @@ -11684,7 +11923,7 @@ To get other URLs (token, etc.), use 
    -
    { self, lib, pkgs, config, globals, ... }:
    +
    { self, lib, pkgs, config, globals, ... }:
     let
       certsSopsFile = self + /secrets/certs/secrets.yaml;
       serviceDomain = "sso.swarsel.win";
    @@ -11938,7 +12177,7 @@ in
     
    3.3.2.29. oauth2-proxy
    -
    { lib, config, globals, ... }:
    +
    { lib, config, globals, ... }:
     let
       kanidmDomain = globals.services.kanidm.domain;
       oauth2ProxyDomain = "soauth.swarsel.win";
    @@ -12163,7 +12402,7 @@ in
     
    3.3.2.30. Firefly-III
    -
    { self, lib, config, ... }:
    +
    { self, lib, config, ... }:
     let
       cfg = config.services.firefly-iii;
       serviceDomain = "stonks.swarsel.win";
    @@ -12272,7 +12511,7 @@ in
     
    3.3.2.31. Koillection
    -
    { self, lib, config, ... }:
    +
    { self, lib, config, ... }:
     let
       serviceDomain = "swag.swarsel.win";
       serviceUser = "koillection";
    @@ -12292,10 +12531,10 @@ in
           koillection-env-file = { };
         };
     
    -    topology.self.services.koillection = {
    -      name = "Koillection";
    +    topology.self.services.${serviceName} = {
    +      name = lib.swarselsystems.toCapitalized serviceName;
           info = "https://${serviceDomain}";
    -      icon = "${self}/topology/images/koillection.png";
    +      icon = "${self}/topology/images/${serviceName}.png";
         };
         globals.services.${serviceName}.domain = serviceDomain;
     
    @@ -12400,7 +12639,7 @@ in
     
    3.3.2.32. Atuin
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     let
       serviceDomain = "shellhistory.swarsel.win";
       servicePort = 8888;
    @@ -12457,7 +12696,7 @@ in
     
    3.3.2.33. Radicale
    -
    { self, lib, config, ... }:
    +
    { self, lib, config, ... }:
     let
       inherit (config.repo.secrets.local.radicale) user1;
       sopsFile = self + /secrets/winters/secrets2.yaml;
    @@ -12573,7 +12812,7 @@ in
     
    3.3.2.34. croc
    -
    { lib, config, pkgs, ... }:
    +
    { self, lib, config, pkgs, ... }:
     let
       serviceDomain = "send.swarsel.win";
       servicePorts = [
    @@ -12605,7 +12844,13 @@ in
           };
         };
     
    -    topology.self.services.${serviceName}.info = "https://${serviceDomain}";
    +
    +    topology.self.services.${serviceName} = {
    +      name = lib.swarselsystems.toCapitalized serviceName;
    +      info = "https://${serviceDomain}";
    +      icon = "${self}/topology/images/${serviceName}.png";
    +    };
    +
         globals.services.${serviceName}.domain = serviceDomain;
     
         services.croc = {
    @@ -12641,7 +12886,7 @@ in
     
    3.3.2.35. microbin
    -
    { lib, config, ... }:
    +
    { self, lib, config, ... }:
     let
       serviceDomain = "scratch.swarsel.win";
       servicePort = 8777;
    @@ -12685,7 +12930,11 @@ in
           };
         };
     
    -    topology.self.services.${serviceName}.info = "https://${serviceDomain}";
    +    topology.self.services.${serviceName} = {
    +      name = lib.swarselsystems.toCapitalized serviceName;
    +      info = "https://${serviceDomain}";
    +      icon = "${self}/topology/images/${serviceName}.png";
    +    };
         globals.services.${serviceName}.domain = serviceDomain;
     
         services."${serviceName}" = {
    @@ -12774,7 +13023,7 @@ in
     
    3.3.2.36. shlink
    -
    { lib, config, ... }:
    +
    { self, lib, config, ... }:
     let
       serviceDomain = "s.swarsel.win";
       servicePort = 8081;
    @@ -12824,7 +13073,11 @@ in
           { directory = "/var/lib/containers"; }
         ];
     
    -    topology.self.services.${serviceName}.info = "https://${serviceDomain}";
    +    topology.self.services.${serviceName} = {
    +      name = lib.swarselsystems.toCapitalized serviceName;
    +      info = "https://${serviceDomain}";
    +      icon = "${self}/topology/images/${serviceName}.png";
    +    };
         globals.services.${serviceName}.domain = serviceDomain;
     
         services.nginx = {
    @@ -12867,7 +13120,7 @@ This section sets up all the imports that are used in the home-manager section.
     

    -
    _:
    +
    _:
     {
     
       nix.settings.experimental-features = "nix-command flakes";
    @@ -12898,7 +13151,23 @@ These sets of configuration do not need to be deployed on every host, for a mult
     
  • The VirtualBox package takes forever to build, and I do not need virtual machines on every host.
  • There are some hosts that I do not want to autologin to.
  • nswitch-rcm is a tool I wrote for easy payload flashing of a Nintendo Switch in RCM mode. However, that is not needed on every machine.
  • -
  • The work profile is only used on my work laptop.
  • +
  • +The work profile is only used on my work laptop. +

    + +
    +
    { self, lib, ... }:
    +let
    +  importNames = lib.swarselsystems.readNix "modules/nixos/optional";
    +  modulesPath = "${self}/modules";
    +in
    +{
    +  imports = lib.swarselsystems.mkImports importNames "modules/nixos/optional" ++ [
    +    "${modulesPath}/home/common/sharedsetup.nix"
    +  ];
    +}
    +
    +
  • @@ -12909,7 +13178,7 @@ This opens a few gaming ports and installs the steam configuration suite for gam

    -
    { pkgs, lib, config, ... }:
    +
    { pkgs, lib, config, ... }:
     {
       options.swarselsystems.modules.optional.gaming = lib.mkEnableOption "optional gaming settings";
       config = lib.mkIf config.swarselsystems.modules.optional.gaming {
    @@ -12963,7 +13232,7 @@ This sets the VirtualBox configuration. Guest should not be enabled if not direl
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.optional.virtualbox = lib.mkEnableOption "optional VBox settings";
       config = lib.mkIf config.swarselsystems.modules.optional.virtualbox {
    @@ -13003,7 +13272,7 @@ This sets the VirtualBox configuration. Guest should not be enabled if not direl
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
     
       options.swarselsystems.modules.optional.vmware = lib.mkEnableOption "optional vmware settings";
    @@ -13024,7 +13293,7 @@ Auto login for the initial session.
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     let
       inherit (config.swarselsystems) mainUser;
     in
    @@ -13049,7 +13318,7 @@ This smashes Atmosphere 1.3.2 on the switch, which is what I am currenty using.
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.optional.nswitch-rcm = lib.mkEnableOption "optional nswitch-rcm settings";
       config = lib.mkIf config.swarselsystems.modules.optional.nswitch-rcm {
    @@ -13074,7 +13343,7 @@ This holds configuration that is specific to framework laptops.
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.optional.framework = lib.mkEnableOption "optional framework machine settings";
       config = lib.mkIf config.swarselsystems.modules.optional.framework {
    @@ -13109,7 +13378,7 @@ This holds configuration that is specific to framework laptops.
     
    3.3.4.7. AMD CPU
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.optional.amdcpu = lib.mkEnableOption "optional amd cpu settings";
       config = lib.mkIf config.swarselsystems.modules.optional.amdcpu {
    @@ -13126,7 +13395,7 @@ This holds configuration that is specific to framework laptops.
     
    3.3.4.8. AMD GPU
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.optional.amdgpu = lib.mkEnableOption "optional amd gpu settings";
       config = lib.mkIf config.swarselsystems.modules.optional.amdgpu {
    @@ -13149,7 +13418,7 @@ This holds configuration that is specific to framework laptops.
     
    3.3.4.9. Hibernation
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems = {
         modules.optional.hibernation = lib.mkEnableOption "optional amd gpu settings";
    @@ -13181,7 +13450,7 @@ This holds configuration that is specific to framework laptops.
     
    3.3.4.10. BTRFS
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.optional.btrfs = lib.mkEnableOption "optional btrfs settings";
       config = lib.mkIf config.swarselsystems.modules.optional.btrfs {
    @@ -13202,7 +13471,7 @@ Options that I need specifically at work. There are more options at 
    -
    { self, lib, pkgs, config, ... }:
    +
    { self, lib, pkgs, config, ... }:
     let
       inherit (config.swarselsystems) mainUser homeDir xdgDir;
       owner = mainUser;
    @@ -13429,7 +13698,7 @@ These options are really only to be used on the iso image in order to run nixos-
     

    -
    { lib, pkgs, ... }:
    +
    { lib, pkgs, ... }:
     {
     
       nix.settings = {
    @@ -13522,7 +13791,7 @@ This section sets up all the imports that are used in the home-manager section.
     

    -
    { lib, ... }:
    +
    { lib, ... }:
     let
       importNames = lib.swarselsystems.readNix "modules/home/common";
     in
    @@ -13558,7 +13827,7 @@ This is where the theme for the whole OS is defined. Originally, this noweb-ref
     

    -
    { self, lib, pkgs, ... }:
    +
    { self, lib, pkgs, ... }:
     {
       options.swarselsystems = {
         isLaptop = lib.mkEnableOption "laptop host";
    @@ -13837,7 +14106,7 @@ Again, we adapt nix to our needs, enable the home-manager command f
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     let
       inherit (config.swarselsystems) mainUser;
     in
    @@ -13906,7 +14175,7 @@ It can be set to either:
     
     
     
    -
    { lib, config, nixgl, ... }:
    +
    { lib, config, nixgl, ... }:
     {
       options.swarselsystems = {
         modules.nixgl = lib.mkEnableOption "nixgl settings";
    @@ -13960,7 +14229,7 @@ This holds packages that I can use as provided, or with small modifications (as
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     
     {
       options.swarselsystems.modules.packages = lib.mkEnableOption "packages settings";
    @@ -13976,7 +14245,7 @@ This holds packages that I can use as provided, or with small modifications (as
           picard-tools
           audacity
           sox
    -      stable.feishin
    +      # stable.feishin # does not work with oauth2-proxy
           calibre
     
           # printing
    @@ -14157,7 +14426,7 @@ This is just a separate container for derivations defined in 
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     
     {
       options.swarselsystems.modules.ownpackages = lib.mkEnableOption "own packages settings";
    @@ -14217,19 +14486,19 @@ Since we are using the home-manager implementation here, we need to specify the
     
     
     
    -
    { config, lib, ... }:
    +
    { config, lib, ... }:
     let
       inherit (config.swarselsystems) homeDir xdgDir;
     in
     {
       options.swarselsystems.modules.sops = lib.mkEnableOption "sops settings";
       config = lib.mkIf config.swarselsystems.modules.sops {
    -    sops = lib.mkIf (!config.swarselsystems.isPublic) {
    +    sops =  {
           age.sshKeyPaths = [ "${homeDir}/.ssh/sops" "${homeDir}/.ssh/ssh_host_ed25519_key" ];
           defaultSopsFile = lib.swarselsystems.mkIfElseList config.swarselsystems.isBtrfs "/persist/.dotfiles/secrets/general/secrets.yaml" "${homeDir}/.dotfiles/secrets/general/secrets.yaml";
     
           validateSopsFiles = false;
    -      secrets = {
    +      secrets = lib.mkIf (!config.swarselsystems.isPublic) {
             mrswarsel = { path = "${xdgDir}/secrets/mrswarsel"; };
             nautilus = { path = "${xdgDir}/secrets/nautilus"; };
             leon = { path = "${xdgDir}/secrets/leon"; };
    @@ -14248,7 +14517,7 @@ in
     
    3.4.1.7. Yubikey
    -
    { lib, config, nixosConfig, ... }:
    +
    { lib, config, nixosConfig, ... }:
     {
       options.swarselsystems.modules.yubikey = lib.mkEnableOption "yubikey settings";
     
    @@ -14273,7 +14542,7 @@ It is very convenient to have SSH aliases in place for machines that I use. This
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.ssh = lib.mkEnableOption "ssh settings";
       config = lib.mkIf config.swarselsystems.modules.ssh {
    @@ -14337,7 +14606,7 @@ This section has been notably empty ever since switching to stylix. Only Emacs i
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.stylix = lib.mkEnableOption "stylix settings";
       config = lib.mkIf config.swarselsystems.modules.stylix {
    @@ -14365,7 +14634,7 @@ TODO: Non-NixOS machines (=sp3) should not use these by default, but instead the
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.desktop = lib.mkEnableOption "desktop settings";
       config = lib.mkIf config.swarselsystems.modules.desktop {
    @@ -14489,7 +14758,7 @@ Also in firefox `about:config > toolkit.legacyUserProfileCustomizations.style
     

    -
    { self, lib, config, ... }:
    +
    { self, lib, config, ... }:
     {
       options.swarselsystems.modules.symlink = lib.mkEnableOption "symlink settings";
       config = lib.mkIf config.swarselsystems.modules.symlink {
    @@ -14533,7 +14802,7 @@ Sets environment variables. Here I am only setting the EDITOR variable, most var
     

    -
    { lib, config, nixosConfig, ... }:
    +
    { lib, config, nixosConfig, ... }:
     let
       inherit (nixosConfig.repo.secrets.common.mail) address1 address2 address3 address4 allMailAddresses;
       inherit (nixosConfig.repo.secrets.common) fullName;
    @@ -14570,7 +14839,7 @@ This section is for programs that require no further configuration. zsh Integrat
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.programs = lib.mkEnableOption "programs settings";
       config = lib.mkIf config.swarselsystems.modules.programs {
    @@ -14613,7 +14882,7 @@ nix-index provides a way to find out which packages are provided by which deriva
     

    -
    { self, lib, config, pkgs, ... }:
    +
    { self, lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.nix-index = lib.mkEnableOption "nix-index settings";
       config = lib.mkIf config.swarselsystems.modules.nix-index {
    @@ -14649,7 +14918,7 @@ Enables password store with the pass-otp extension which allows me
     

    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.passwordstore = lib.mkEnableOption "passwordstore settings";
       config = lib.mkIf config.swarselsystems.modules.passwordstore {
    @@ -14674,7 +14943,7 @@ Enables direnv, which I use for nearly all of my nix dev flakes.
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.direnv = lib.mkEnableOption "direnv settings";
       config = lib.mkIf config.swarselsystems.modules.direnv {
    @@ -14697,7 +14966,7 @@ Eza provides me with a better ls command and some other useful alia
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.eza = lib.mkEnableOption "eza settings";
       config = lib.mkIf config.swarselsystems.modules.eza {
    @@ -14720,7 +14989,7 @@ Eza provides me with a better ls command and some other useful alia
     
    3.4.1.18. atuin
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.atuin = lib.mkEnableOption "atuin settings";
       config = lib.mkIf config.swarselsystems.modules.atuin {
    @@ -14747,7 +15016,7 @@ Here I set up my git config, automatic signing of commits, useful aliases for my
     

    -
    { lib, config, nixosConfig, ... }:
    +
    { lib, config, nixosConfig, ... }:
     let
       inherit (nixosConfig.repo.secrets.common.mail) address1;
       inherit (nixosConfig.repo.secrets.common) fullName;
    @@ -14805,7 +15074,7 @@ Here I only need to set basic layout options - the rest is being managed by styl
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.fuzzel = lib.mkEnableOption "fuzzel settings";
       config = lib.mkIf config.swarselsystems.modules.fuzzel {
    @@ -14834,7 +15103,7 @@ Starship makes my zsh look cooler! I have symbols for most programm
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.starship = lib.mkEnableOption "starship settings";
       config = lib.mkIf config.swarselsystems.modules.starship {
    @@ -14974,7 +15243,7 @@ The theme is handled by stylix.
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.kitty = lib.mkEnableOption "kitty settings";
       config = lib.mkIf config.swarselsystems.modules.kitty {
    @@ -15038,7 +15307,7 @@ Currently I only use it as before with initExtra though.
     

    -
    { config, lib, ... }:
    +
    { config, lib, ... }:
     let
       inherit (config.swarselsystems) flakePath;
     in
    @@ -15117,7 +15386,7 @@ in
             #   src = pkgs.zsh-fzf-tab;
             # }
           ];
    -      initContent = ''
    +      initContent = lib.mkIf (!config.swarselsystems.isPublic) ''
             my-forward-word() {
               local WORDCHARS=$WORDCHARS
               WORDCHARS="''${WORDCHARS//:}"
    @@ -15170,7 +15439,7 @@ in
     
    3.4.1.24. zellij
    -
    { self, lib, config, pkgs, ... }:
    +
    { self, lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.zellij = lib.mkEnableOption "zellij settings";
       config = lib.mkIf config.swarselsystems.modules.zellij {
    @@ -15198,7 +15467,7 @@ in
     
    3.4.1.25. tmux
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     let
       tmux-super-fingers = pkgs.tmuxPlugins.mkTmuxPlugin
         {
    @@ -15311,7 +15580,7 @@ Normally I use 4 mail accounts - here I set them all up. Three of them are Googl
     

    -
    { lib, config, nixosConfig, ... }:
    +
    { lib, config, nixosConfig, ... }:
     let
       inherit (nixosConfig.repo.secrets.common.mail) address1 address2 add2Name address3 add3Name address4;
       inherit (nixosConfig.repo.secrets.common) fullName;
    @@ -15471,7 +15740,7 @@ Lastly, I am defining some more packages here that the parser has problems findi
     

    -
    { self, lib, config, pkgs, ... }:
    +
    { self, lib, config, pkgs, ... }:
     let
       inherit (config.swarselsystems) homeDir isPublic;
     in
    @@ -15578,7 +15847,7 @@ The rest of the related configuration is found here:
     
     
     
    -
    { self, config, lib, ... }:
    +
    { self, config, lib, ... }:
     let
       generateIcons = n: lib.concatStringsSep " " (builtins.map (x: "{icon" + toString x + "}") (lib.range 0 (n - 1)));
       modulesLeft = [
    @@ -15912,7 +16181,7 @@ I used to build the firefox addon bypass-paywalls-clean myself here
     

    -
    { config, pkgs, lib, ... }:
    +
    { config, pkgs, lib, ... }:
     {
       options.swarselsystems.modules.firefox = lib.mkEnableOption "firefox settings";
       config = lib.mkIf config.swarselsystems.modules.firefox {
    @@ -16081,7 +16350,7 @@ Used for storing sessions in e.g. Nextcloud
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.gnome-keyring = lib.mkEnableOption "gnome keyring settings";
       config = lib.mkIf config.swarselsystems.modules.gnome-keyring {
    @@ -16102,7 +16371,7 @@ This enables phone/computer communication, including sending clipboard, files et
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.kdeconnect = lib.mkEnableOption "kdeconnect settings";
       config = lib.mkIf config.swarselsystems.modules.kdeconnect {
    @@ -16129,7 +16398,7 @@ The `extraConfig` section here CANNOT be reindented. This has something to do wi
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.mako = lib.mkEnableOption "mako settings";
       config = lib.mkIf config.swarselsystems.modules.mako {
    @@ -16172,7 +16441,7 @@ The `extraConfig` section here CANNOT be reindented. This has something to do wi
     
    3.4.1.30.4. SwayOSD
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.swayosd = lib.mkEnableOption "swayosd settings";
       config = lib.mkIf config.swarselsystems.modules.swayosd {
    @@ -16190,7 +16459,7 @@ The `extraConfig` section here CANNOT be reindented. This has something to do wi
     
    3.4.1.30.5. yubikey-touch-detector
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.yubikeytouch = lib.mkEnableOption "yubikey touch detector service settings";
       config = lib.mkIf config.swarselsystems.modules.yubikeytouch {
    @@ -16239,7 +16508,7 @@ Currently, I am too lazy to explain every option here, but most of it is very se
     

    -
    { self, config, lib, ... }:
    +
    { self, config, lib, ... }:
     {
       options.swarselsystems = {
         modules.sway = lib.mkEnableOption "sway settings";
    @@ -16259,13 +16528,13 @@ Currently, I am too lazy to explain every option here, but most of it is very se
         startup = lib.mkOption {
           type = lib.types.listOf (lib.types.attrsOf lib.types.str);
           default = [
    -        { command = "nextcloud --background"; }
    +        # { command = "nextcloud --background"; }
             { command = "vesktop --start-minimized --enable-speech-dispatcher --ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime"; }
             { command = "element-desktop --hidden  --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu-driver-bug-workarounds"; }
             { command = "ANKI_WAYLAND=1 anki"; }
             { command = "OBSIDIAN_USE_WAYLAND=1 obsidian"; }
             { command = "nm-applet"; }
    -        { command = "feishin"; }
    +        # { command = "feishin"; }
           ];
         };
         kyria = lib.mkOption {
    @@ -16652,7 +16921,7 @@ Currently, I am too lazy to explain every option here, but most of it is very se
     
    3.4.1.32. Kanshi
    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.kanshi = lib.mkEnableOption "kanshi settings";
       config = lib.mkIf config.swarselsystems.modules.kanshi {
    @@ -16752,7 +17021,7 @@ Settinfs that are needed for the gpg-agent. Also we are enabling emacs support f
     

    -
    { self, lib, config, pkgs, ... }:
    +
    { self, lib, config, pkgs, ... }:
     let
       inherit (config.swarselsystems) mainUser homeDir;
     in
    @@ -16806,7 +17075,7 @@ This service changes the screen hue at night. I am not sure if that really does
     

    -
    { lib, config, nixosConfig, ... }:
    +
    { lib, config, nixosConfig, ... }:
     let
       inherit (nixosConfig.repo.secrets.common.location) latitude longitude;
     in
    @@ -16837,7 +17106,7 @@ This section sets up all the imports that are used in the home-manager section.
     

    -
    { self, lib, ... }:
    +
    { self, lib, ... }:
     let
       importNames = lib.swarselsystems.readNix "modules/home/server";
       modulesPath = "${self}/modules";
    @@ -16864,7 +17133,7 @@ As for the `home.sessionVariables`, it should be noted that environment variable
     

    -
    { self, lib, config, ... }:
    +
    { self, lib, config, ... }:
     {
       options.swarselsystems.modules.server.dotfiles = lib.mkEnableOption "server dotfiles settings";
       config = lib.mkIf config.swarselsystems.modules.server.dotfiles {
    @@ -16893,7 +17162,7 @@ This section sets up all the imports that are used in the home-manager section.
     

    -
    { self, ... }:
    +
    { self, ... }:
     let
       modulesPath = "${self}/modules";
     in
    @@ -16914,6 +17183,17 @@ in
     

    Akin to the optional NixOS modules.

    + +
    +
    { lib, ... }:
    +let
    +  importNames = lib.swarselsystems.readNix "modules/home/optional";
    +in
    +{
    +  imports = lib.swarselsystems.mkImports importNames "modules/home/optional";
    +}
    +
    +
    3.4.4.1. Gaming
    @@ -16923,7 +17203,7 @@ The rest of the settings is at
    -
    { lib, config, pkgs, ... }:
    +
    { lib, config, pkgs, ... }:
     {
       options.swarselsystems.modules.optional.gaming = lib.mkEnableOption "optional gaming settings";
       config = lib.mkIf config.swarselsystems.modules.optional.gaming {
    @@ -16975,7 +17255,7 @@ The rest of the settings is at 
     
     
    -
    { self, config, pkgs, lib, nixosConfig, ... }:
    +
    { self, config, pkgs, lib, nixosConfig, ... }:
     let
       inherit (config.swarselsystems) homeDir;
       inherit (nixosConfig.repo.secrets.local.work) user1 user1Long user2 user2Long user3 user3Long user4 path1 loc1 loc2 site1 site2 site3 site4 site5 site6 site7 lifecycle1 lifecycle2 domain1 domain2 gitMail;
    @@ -17304,13 +17584,13 @@ in
         };
         swarselsystems = {
           startup = [
    -        { command = "nextcloud --background"; }
    +        # { command = "nextcloud --background"; }
             { command = "vesktop --start-minimized --enable-speech-dispatcher --ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime"; }
             { command = "element-desktop --hidden  --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu-driver-bug-workarounds"; }
             { command = "ANKI_WAYLAND=1 anki"; }
             { command = "OBSIDIAN_USE_WAYLAND=1 obsidian"; }
             { command = "nm-applet"; }
    -        { command = "feishin"; }
    +        # { command = "feishin"; }
             { command = "teams-for-linux --disableGpu=true --minimized=true --trayIconEnabled=true"; }
             { command = "1password"; }
           ];
    @@ -17423,7 +17703,7 @@ This holds configuration that is specific to framework laptops.
     

    -
    { lib, config, ... }:
    +
    { lib, config, ... }:
     {
       options.swarselsystems.modules.optional.framework = lib.mkEnableOption "optional framework machine settings";
       config = lib.mkIf config.swarselsystems.modules.optional.framework {
    @@ -19412,7 +19692,7 @@ It also offers a very useful utility of exporting org-mode buffers to different
     
    -
    4.4.1.5.2. old easy structure templates
    +
    4.4.1.5.2. old easy structure templates (org-tempo)
    • @@ -19429,7 +19709,7 @@ Usage: Type <, followed by one of the below keywords and press < (add-to-list 'org-structure-template-alist '("sh" . "src shell")) (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) (add-to-list 'org-structure-template-alist '("py" . "src python :results output")) -(add-to-list 'org-structure-template-alist '("nix" . "src nix :tangle")) +(add-to-list 'org-structure-template-alist '("nix" . "src nix-ts :tangle"))

    @@ -19641,10 +19921,44 @@ This adds a rudimentary nix-mode to Emacs. I have not really tried this out, as
    -(use-package nix-mode)
    +(use-package nix-mode
    +  :after lsp-mode
    +  :ensure t
    +  :hook
    +  (nix-mode . lsp-deferred) ;; So that envrc mode will work
    +  :custom
    +  (lsp-disabled-clients '((nix-mode . nix-nil))) ;; Disable nil so that nixd will be used as lsp-server
    +  :config
    +  (setq lsp-nix-nixd-server-path "nixd"
    +        lsp-nix-nixd-formatting-command [ "nixpkgs-fmt" ]
    +        lsp-nix-nixd-nixpkgs-expr "import (builtins.getFlake \"/home/swarsel/.dotfiles\").inputs.nixpkgs { }"
    +        lsp-nix-nixd-nixos-options-expr "(builtins.getFlake \"/home/swarsel/.dotfiles\").nixosConfigurations.nbl-imba-2.options"
    +        lsp-nix-nixd-home-manager-options-expr "(builtins.getFlake \"/home/swarsel/.dotfiles\").nixosConfigurations.nbl-imba-2.options.home-manager.users.type.getSubOptions []"
    +        ))
     
     (use-package nix-ts-mode
    -  :mode "\\.nix\\'")
    +  :after lsp-mode
    +  :mode "\\.nix\\'"
    +  :ensure t
    +  :hook
    +  (nix-ts-mode . lsp-deferred) ;; So that envrc mode will work
    +  :custom
    +  (lsp-disabled-clients '((nix-ts-mode . nix-nil))) ;; Disable nil so that nixd will be used as lsp-server
    +  :config
    +  (setq lsp-nix-nixd-server-path "nixd"
    +        lsp-nix-nixd-formatting-command [ "nixpkgs-fmt" ]
    +        lsp-nix-nixd-nixpkgs-expr "import (builtins.getFlake \"/home/swarsel/.dotfiles\").inputs.nixpkgs { }"
    +        lsp-nix-nixd-nixos-options-expr "(builtins.getFlake \"/home/swarsel/.dotfiles\").nixosConfigurations.nbl-imba-2.options"
    +        lsp-nix-nixd-home-manager-options-expr "(builtins.getFlake \"/home/swarsel/.dotfiles\").nixosConfigurations.nbl-imba-2.options.home-manager.users.type.getSubOptions []"
    +        ))
    +
    +
    +(with-eval-after-load 'lsp-mode
    +  (lsp-register-client
    +   (make-lsp-client :new-connection (lsp-stdio-connection "nixd")
    +                    :major-modes '(nix-mode nix-ts-mode)
    +                    :priority 0
    +                    :server-id 'nixd)))
     
    @@ -20460,45 +20774,76 @@ A blocking issue can still occur while entering a direnv that has a longer evalu

    4.4.31. lsp-mode & company

    +

    +company is now disabled since it seems that corfu runs just fine with lsp-mode and I prefer it. Also I set the auto-guess-root option to true in order to stop excessive nag when editing within org-src blocks. +

    +
    -(use-package lsp-bridge
    -  :ensure nil)
    -
     (use-package lsp-mode
       :init
       ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
       (setq lsp-keymap-prefix "C-c l")
    +  (setq lsp-auto-guess-root "t")
       :commands lsp)
     
    -(use-package company)
    +;; (use-package company)
    +
    +
    +
    +
    +
    +
    +

    4.4.32. lsp-mode in org-src blocks

    +
    +
    +
    ;; thanks to https://tecosaur.github.io/emacs-config/config.html#lsp-support-src
    +(cl-defmacro lsp-org-babel-enable (lang)
    +  "Support LANG in org source code block."
    +  (setq centaur-lsp 'lsp-mode)
    +  (cl-check-type lang string)
    +  (let* ((edit-pre (intern (format "org-babel-edit-prep:%s" lang)))
    +         (intern-pre (intern (format "lsp--%s" (symbol-name edit-pre)))))
    +    `(progn
    +       (defun ,intern-pre (info)
    +         (let ((file-name (->> info caddr (alist-get :file))))
    +           (unless file-name
    +             (setq file-name (make-temp-file "babel-lsp-")))
    +           (setq buffer-file-name file-name)
    +           (lsp-deferred)))
    +       (put ',intern-pre 'function-documentation
    +            (format "Enable lsp-mode in the buffer of org source block (%s)."
    +                    (upcase ,lang)))
    +       (if (fboundp ',edit-pre)
    +           (advice-add ',edit-pre :after ',intern-pre)
    +         (progn
    +           (defun ,edit-pre (info)
    +             (,intern-pre info))
    +           (put ',edit-pre 'function-documentation
    +                (format "Prepare local buffer environment for org source block (%s)."
    +                        (upcase ,lang))))))))
    +(defvar org-babel-lang-list
    +  '( "nix" "nix-ts" "go" "python" "ipython" "bash" "sh" ))
    +(dolist (lang org-babel-lang-list)
    +  (eval `(lsp-org-babel-enable ,lang)))
     
     
    -

    4.4.32. lsp-bridge

    +

    4.4.33. lsp-bridge

     (use-package lsp-bridge
       :ensure nil)
    -
    -(use-package lsp-mode
    -  :init
    -  ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
    -  (setq lsp-keymap-prefix "C-c l")
    -  :commands lsp)
    -
    -(use-package company)
    -
     
    -

    4.4.33. sideline-flymake

    +

    4.4.34. sideline-flymake

    This brings back warnings and errors on the sideline for eglot; a feature that I have been missing from lsp-mode for a while. @@ -20518,7 +20863,7 @@ This brings back warnings and errors on the sideline for eglot; a feature that I

    -

    4.4.34. Prevent breaking of hardlinks

    +

    4.4.35. Prevent breaking of hardlinks

    This setting ensures that hard links are preserved during the backup process, which is useful for maintaining the integrity of files that are linked in multiple locations. @@ -20533,7 +20878,7 @@ This setting ensures that hard links are preserved during the backup process, wh

    -

    4.4.35. Dirvish

    +

    4.4.36. Dirvish

    Dirvish is an improvement upon the dired-framework and has more features like file preview etc. Sadly it has an incompatibility with openwith which is why I have disabled that package. @@ -20597,7 +20942,7 @@ Dirvish is an improvement upon the dired-framework and has more features like fi

    -

    4.4.36. undo-tree

    +

    4.4.37. undo-tree

    Base emacs undo logic is very useful, but not easy to understand for me. I prefer undo-tree, which makes switching between branches easier and also allows quickly switching back to a much older state using the visualizer. @@ -20632,7 +20977,7 @@ While we are at it, we are also setting up a persistent undo-file for every file

    -

    4.4.37. Hydra

    +

    4.4.38. Hydra

    Hydra allows for the writing of macro-style functions. I have not yet looked into this all too much, but it seems to be a potent feature. @@ -20646,7 +20991,7 @@ Hydra allows for the writing of macro-style functions. I have not yet looked int

    -
    4.4.37.1. Text scaling
    +
    4.4.38.1. Text scaling

    I only wrote this in order to try out hydra; rarely do I really need this. However, it can be useful for Presentations. It simply scales the text size. @@ -20668,11 +21013,11 @@ I only wrote this in order to try out hydra; rarely do I really need this. Howev

    -

    4.4.38. Email

    +

    4.4.39. Email

    -
    4.4.38.1. mu4e
    +
    4.4.39.1. mu4e

    In this section we are setting up mu4e, a mail client for emacs using mu with mbsync as backend. The mail accounts themselves are setup in the NixOS configuration, so we only need to add Emacs specific settings here. @@ -20736,7 +21081,7 @@ The hook functions are defined here: -

    4.4.38.2. mu4e-alert
    +
    4.4.39.2. mu4e-alert

    This adds the simple utility of sending desktop notifications whenever a new mail is received. I am using libnotify because I want to use this with notify-send. @@ -20757,7 +21102,7 @@ This adds the simple utility of sending desktop notifications whenever a new mai

    -

    4.4.39. Calendar

    +

    4.4.40. Calendar

    This provides a beautiful calender to emacs. @@ -20825,7 +21170,7 @@ Yes, I am aware that I am exposing my university-calendar to the public here. I

    -

    4.4.40. Dashboard: emacs startup screen

    +

    4.4.41. Dashboard: emacs startup screen

    This sets up the dashboard, which is really quite useless. But, it looks cool and makes me happy whenever I start an emacsclient without a file name as argument :) @@ -20898,7 +21243,7 @@ This sets up the dashboard, which is really quite useless. But, it

    -

    4.4.41. vterm

    +

    4.4.42. vterm

    @@ -20910,7 +21255,7 @@ This sets up the dashboard, which is really quite useless. But, it
     
    -

    4.4.42. multiple cursors

    +

    4.4.43. multiple cursors

    @@ -20921,7 +21266,7 @@ This sets up the dashboard, which is really quite useless. But, it
     
    -

    4.4.43. Less logging

    +

    4.4.44. Less logging

    @@ -21680,12 +22025,1612 @@ dd DRIVE ISO:
     sync USER HOST:
       rsync -av --filter=':- .gitignore' -e "ssh -l {{USER}}" . {{USER}}@{{HOST}}:.dotfiles/
     
    +
    +
    +
    +
    +
    +

    6.6. aspell.conf

    +
    +
    +
    dict-dir /run/current-system/sw/lib/aspell
    +
    +
    +
    +
    +
    +

    6.7. nix-plugins.patch

    +
    +
    +
    diff --git a/extra-builtins.cc b/extra-builtins.cc
    +index 3a0f90e..bb10f8b 100644
    +--- a/extra-builtins.cc
    ++++ b/extra-builtins.cc
    +@@ -1,9 +1,9 @@
    +-#include <config.h>
    +-#include <primops.hh>
    +-#include <globals.hh>
    +-#include <config-global.hh>
    +-#include <eval-settings.hh>
    +-#include <common-eval-args.hh>
    +-#include <filtering-source-accessor.hh>
    ++#include <nix/cmd/common-eval-args.hh>
    ++#include <nix/expr/eval-settings.hh>
    ++#include <nix/expr/primops.hh>
    ++#include <nix/fetchers/filtering-source-accessor.hh>
    ++#include <nix/store/globals.hh>
    ++#include <nix/util/configuration.hh>
    ++#include <nix/util/config-global.hh>
    +
    + #include "nix-plugins-config.h"
    +
    +
    +
    +
    +
    +

    6.8. Zellij layout default.kdl.nix

    +
    +
    +
    { config, pkgs }:
    +let
    +  inherit (config.lib.stylix) colors;
    +in
    +''
    +  layout {
    +         swap_tiled_layout name="vertical" {
    +             tab max_panes=5 {
    +                 pane split_direction="vertical" {
    +                     pane
    +                     pane { children; }
    +                 }
    +             }
    +             tab max_panes=8 {
    +                 pane split_direction="vertical" {
    +                     pane { children; }
    +                     pane { pane; pane; pane; pane; }
    +                 }
    +             }
    +             tab max_panes=12 {
    +                 pane split_direction="vertical" {
    +                     pane { children; }
    +                     pane { pane; pane; pane; pane; }
    +                     pane { pane; pane; pane; pane; }
    +                 }
    +             }
    +         }
    +
    +         swap_tiled_layout name="horizontal" {
    +             tab max_panes=5 {
    +                 pane
    +                 pane
    +             }
    +             tab max_panes=8 {
    +                 pane {
    +                     pane split_direction="vertical" { children; }
    +                     pane split_direction="vertical" { pane; pane; pane; pane; }
    +                 }
    +             }
    +             tab max_panes=12 {
    +                 pane {
    +                     pane split_direction="vertical" { children; }
    +                     pane split_direction="vertical" { pane; pane; pane; pane; }
    +                     pane split_direction="vertical" { pane; pane; pane; pane; }
    +                 }
    +             }
    +         }
    +
    +         swap_tiled_layout name="stacked" {
    +             tab min_panes=5 {
    +                 pane split_direction="vertical" {
    +                     pane
    +                     pane stacked=true { children; }
    +                 }
    +             }
    +         }
    +
    +         swap_floating_layout name="staggered" {
    +             floating_panes
    +         }
    +
    +         swap_floating_layout name="enlarged" {
    +             floating_panes max_panes=10 {
    +                 pane { x "5%"; y 1; width "90%"; height "90%"; }
    +                 pane { x "5%"; y 2; width "90%"; height "90%"; }
    +                 pane { x "5%"; y 3; width "90%"; height "90%"; }
    +                 pane { x "5%"; y 4; width "90%"; height "90%"; }
    +                 pane { x "5%"; y 5; width "90%"; height "90%"; }
    +                 pane { x "5%"; y 6; width "90%"; height "90%"; }
    +                 pane { x "5%"; y 7; width "90%"; height "90%"; }
    +                 pane { x "5%"; y 8; width "90%"; height "90%"; }
    +                 pane { x "5%"; y 9; width "90%"; height "90%"; }
    +                 pane focus=true { x 10; y 10; width "90%"; height "90%"; }
    +             }
    +         }
    +
    +         swap_floating_layout name="spread" {
    +             floating_panes max_panes=1 {
    +                 pane {y "50%"; x "50%"; }
    +             }
    +             floating_panes max_panes=2 {
    +                 pane { x "1%"; y "25%"; width "45%"; }
    +                 pane { x "50%"; y "25%"; width "45%"; }
    +             }
    +             floating_panes max_panes=3 {
    +                 pane focus=true { y "55%"; width "45%"; height "45%"; }
    +                 pane { x "1%"; y "1%"; width "45%"; }
    +                 pane { x "50%"; y "1%"; width "45%"; }
    +             }
    +             floating_panes max_panes=4 {
    +                 pane { x "1%"; y "55%"; width "45%"; height "45%"; }
    +                 pane focus=true { x "50%"; y "55%"; width "45%"; height "45%"; }
    +                 pane { x "1%"; y "1%"; width "45%"; height "45%"; }
    +                 pane { x "50%"; y "1%"; width "45%"; height "45%"; }
    +             }
    +         }
    +
    +         default_tab_template {
    +             children
    +             pane size=1 borderless=true {
    +                 plugin location="file://${pkgs.zjstatus}/bin/zjstatus.wasm" {
    +                     format_left   "{mode}#[bg=#${colors.base00}] {tabs}"
    +                     format_center ""
    +                     format_right  "#[bg=#${colors.base00},fg=#${colors.base02}]#[bg=#${colors.base02},fg=#${colors.base01},bold] #[bg=#${colors.base02},fg=#${colors.base01},bold] {session} #[bg=#${colors.base02},fg=#${colors.base01},bold]"
    +                     format_space  ""
    +                     format_hide_on_overlength "false"
    +                     format_precedence "lcr"
    +
    +                     border_enabled  "false"
    +                     border_char     "─"
    +                     border_format   "#[fg=#6C7086]{char}"
    +                     border_position "top"
    +
    +                     mode_normal        "#[bg=#${colors.base0B},fg=#${colors.base01},bold] NORMAL#[bg=#${colors.base01},fg=#${colors.base0B}]█"
    +                     mode_locked        "#[bg=#${colors.base04},fg=#${colors.base01},bold] LOCKED #[bg=#${colors.base01},fg=#${colors.base04}]█"
    +                     mode_resize        "#[bg=#${colors.base08},fg=#${colors.base01},bold] RESIZE#[bg=#${colors.base01},fg=#${colors.base08}]█"
    +                     mode_pane          "#[bg=#${colors.base0D},fg=#${colors.base01},bold] PANE#[bg=#${colors.base01},fg=#${colors.base0D}]█"
    +                     mode_tab           "#[bg=#${colors.base07},fg=#${colors.base01},bold] TAB#[bg=#${colors.base01},fg=#${colors.base07}]█"
    +                     mode_scroll        "#[bg=#${colors.base0A},fg=#${colors.base01},bold] SCROLL#[bg=#${colors.base01},fg=#${colors.base0A}]█"
    +                     mode_enter_search  "#[bg=#${colors.base0D},fg=#${colors.base01},bold] ENT-SEARCH#[bg=#${colors.base01},fg=#${colors.base0D}]█"
    +                     mode_search        "#[bg=#${colors.base0D},fg=#${colors.base01},bold] SEARCHARCH#[bg=#${colors.base01},fg=#${colors.base0D}]█"
    +                     mode_rename_tab    "#[bg=#${colors.base07},fg=#${colors.base01},bold] RENAME-TAB#[bg=#${colors.base01},fg=#${colors.base07}]█"
    +                     mode_rename_pane   "#[bg=#${colors.base0D},fg=#${colors.base01},bold] RENAME-PANE#[bg=#${colors.base01},fg=#${colors.base0D}]█"
    +                     mode_session       "#[bg=#${colors.base0E},fg=#${colors.base01},bold] SESSION#[bg=#${colors.base01},fg=#${colors.base0E}]█"
    +                     mode_move          "#[bg=#${colors.base0F},fg=#${colors.base01},bold] MOVE#[bg=#${colors.base01},fg=#${colors.base0F}]█"
    +                     mode_prompt        "#[bg=#${colors.base0D},fg=#${colors.base01},bold] PROMPT#[bg=#${colors.base01},fg=#${colors.base0D}]█"
    +                     mode_tmux          "#[bg=#${colors.base09},fg=#${colors.base01},bold] TMUX#[bg=#${colors.base01},fg=#${colors.base09}]█"
    +
    +                     // formatting for inactive tabs
    +                     tab_normal              "#[bg=#${colors.base01},fg=#${colors.base0C}]█#[bg=#${colors.base0C},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base0C},bold] {name}{floating_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█"
    +                     tab_normal_fullscreen   "#[bg=#${colors.base01},fg=#${colors.base0C}]█#[bg=#${colors.base0C},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base0C},bold] {name}{fullscreen_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█"
    +                     tab_normal_sync         "#[bg=#${colors.base01},fg=#${colors.base0C}]█#[bg=#${colors.base0C},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base0C},bold] {name}{sync_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█"
    +
    +                     // formatting for the current active tab
    +                     tab_active              "#[bg=#${colors.base01},fg=#${colors.base09}]█#[bg=#${colors.base09},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base09},bold] {name}{floating_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█"
    +                     tab_active_fullscreen   "#[bg=#${colors.base01},fg=#${colors.base09}]█#[bg=#${colors.base09},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base09},bold] {name}{fullscreen_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█"
    +                     tab_active_sync         "#[bg=#${colors.base01},fg=#${colors.base09}]█#[bg=#${colors.base09},fg=#${colors.base01},bold]{index} #[bg=#${colors.base01},fg=#${colors.base09},bold] {name}{sync_indicator}#[bg=#${colors.base01},fg=#${colors.base01},bold]█"
    +
    +                     // separator between the tabs
    +                     tab_separator           "#[bg=#${colors.base00}] "
    +
    +                     // indicators
    +                     tab_sync_indicator       " "
    +                     tab_fullscreen_indicator " 󰊓"
    +                     tab_floating_indicator   " 󰹙"
    +
    +                     command_git_branch_command     "git rev-parse --abbrev-ref HEAD"
    +                     command_git_branch_format      "#[fg=blue] {stdout} "
    +                     command_git_branch_interval    "10"
    +                     command_git_branch_rendermode  "static"
    +
    +                     datetime        "#[fg=#6C7086,bold] {format} "
    +                     datetime_format "%A, %d %b %Y %H:%M"
    +                     datetime_timezone "Europe/Vienna"
    +                 }
    +             }
    +         }
    +     }
    +''
    +
    +
    +
    +
    +
    +
    +

    6.9. Zellij config.kdl.nix

    +
    +
    +
    { config }:
    +''
    +  pane_frames false
    +  simplified_ui false
    +  default_shell "zsh"
    +  copy_on_select true
    +  on_force_close "detach"
    +
    +  default_layout "default"
    +  layout_dir "${config.home.homeDirectory}/.config/zellij/layouts"
    +  theme_dir "${config.home.homeDirectory}/.config/zellij/themes"
    +
    +  keybinds clear-defaults=true {
    +      locked {
    +          bind "Ctrl g" { SwitchToMode "normal"; }
    +      }
    +      pane {
    +          bind "left" { MoveFocus "left"; }
    +          bind "down" { MoveFocus "down"; }
    +          bind "up" { MoveFocus "up"; }
    +          bind "right" { MoveFocus "right"; }
    +          bind "c" { SwitchToMode "renamepane"; PaneNameInput 0; }
    +          bind "d" { NewPane "down"; SwitchToMode "normal"; }
    +          bind "e" { TogglePaneEmbedOrFloating; SwitchToMode "normal"; }
    +          bind "f" { ToggleFocusFullscreen; SwitchToMode "normal"; }
    +          bind "h" { MoveFocus "left"; }
    +          bind "j" { MoveFocus "down"; }
    +          bind "k" { MoveFocus "up"; }
    +          bind "l" { MoveFocus "right"; }
    +          bind "n" { NewPane; SwitchToMode "normal"; }
    +          bind "p" { SwitchFocus; }
    +          bind "Ctrl p" { SwitchToMode "normal"; }
    +          bind "r" { NewPane "right"; SwitchToMode "normal"; }
    +          bind "w" { ToggleFloatingPanes; SwitchToMode "normal"; }
    +          bind "z" { TogglePaneFrames; SwitchToMode "normal"; }
    +      }
    +      tab {
    +          bind "left" { GoToPreviousTab; }
    +          bind "down" { GoToNextTab; }
    +          bind "up" { GoToPreviousTab; }
    +          bind "right" { GoToNextTab; }
    +          bind "1" { GoToTab 1; SwitchToMode "normal"; }
    +          bind "2" { GoToTab 2; SwitchToMode "normal"; }
    +          bind "3" { GoToTab 3; SwitchToMode "normal"; }
    +          bind "4" { GoToTab 4; SwitchToMode "normal"; }
    +          bind "5" { GoToTab 5; SwitchToMode "normal"; }
    +          bind "6" { GoToTab 6; SwitchToMode "normal"; }
    +          bind "7" { GoToTab 7; SwitchToMode "normal"; }
    +          bind "8" { GoToTab 8; SwitchToMode "normal"; }
    +          bind "9" { GoToTab 9; SwitchToMode "normal"; }
    +          bind "[" { BreakPaneLeft; SwitchToMode "normal"; }
    +          bind "]" { BreakPaneRight; SwitchToMode "normal"; }
    +          bind "b" { BreakPane; SwitchToMode "normal"; }
    +          bind "h" { GoToPreviousTab; }
    +          bind "j" { GoToNextTab; }
    +          bind "k" { GoToPreviousTab; }
    +          bind "l" { GoToNextTab; }
    +          bind "n" { NewTab; SwitchToMode "normal"; }
    +          bind "r" { SwitchToMode "renametab"; TabNameInput 0; }
    +          bind "s" { ToggleActiveSyncTab; SwitchToMode "normal"; }
    +          bind "Ctrl t" { SwitchToMode "normal"; }
    +          bind "x" { CloseTab; SwitchToMode "normal"; }
    +          bind "tab" { ToggleTab; }
    +      }
    +      resize {
    +          bind "left" { Resize "Increase left"; }
    +          bind "down" { Resize "Increase down"; }
    +          bind "up" { Resize "Increase up"; }
    +          bind "right" { Resize "Increase right"; }
    +          bind "+" { Resize "Increase"; }
    +          bind "-" { Resize "Decrease"; }
    +          bind "=" { Resize "Increase"; }
    +          bind "H" { Resize "Decrease left"; }
    +          bind "J" { Resize "Decrease down"; }
    +          bind "K" { Resize "Decrease up"; }
    +          bind "L" { Resize "Decrease right"; }
    +          bind "h" { Resize "Increase left"; }
    +          bind "j" { Resize "Increase down"; }
    +          bind "k" { Resize "Increase up"; }
    +          bind "l" { Resize "Increase right"; }
    +          bind "Ctrl n" { SwitchToMode "normal"; }
    +      }
    +      move {
    +          bind "left" { MovePane "left"; }
    +          bind "down" { MovePane "down"; }
    +          bind "up" { MovePane "up"; }
    +          bind "right" { MovePane "right"; }
    +          bind "h" { MovePane "left"; }
    +          bind "Ctrl h" { SwitchToMode "normal"; }
    +          bind "j" { MovePane "down"; }
    +          bind "k" { MovePane "up"; }
    +          bind "l" { MovePane "right"; }
    +          bind "n" { MovePane; }
    +          bind "p" { MovePaneBackwards; }
    +          bind "tab" { MovePane; }
    +      }
    +      scroll {
    +          bind "e" { EditScrollback; SwitchToMode "normal"; }
    +          bind "s" { SwitchToMode "entersearch"; SearchInput 0; }
    +      }
    +      search {
    +          bind "c" { SearchToggleOption "CaseSensitivity"; }
    +          bind "n" { Search "down"; }
    +          bind "o" { SearchToggleOption "WholeWord"; }
    +          bind "p" { Search "up"; }
    +          bind "w" { SearchToggleOption "Wrap"; }
    +      }
    +      session {
    +          bind "c" {
    +              LaunchOrFocusPlugin "configuration" {
    +                  floating true
    +                  move_to_focused_tab true
    +              }
    +              SwitchToMode "normal"
    +          }
    +          bind "Ctrl o" { SwitchToMode "normal"; }
    +          bind "p" {
    +              LaunchOrFocusPlugin "plugin-manager" {
    +                  floating true
    +                  move_to_focused_tab true
    +              }
    +              SwitchToMode "normal"
    +          }
    +          bind "w" {
    +              LaunchOrFocusPlugin "session-manager" {
    +                  floating true
    +                  move_to_focused_tab true
    +              }
    +              SwitchToMode "normal"
    +          }
    +      }
    +      shared_except "locked" {
    +          bind "Alt left" { MoveFocusOrTab "left"; }
    +          bind "Alt down" { MoveFocus "down"; }
    +          bind "Alt up" { MoveFocus "up"; }
    +          bind "Alt right" { MoveFocusOrTab "right"; }
    +          bind "Alt +" { Resize "Increase"; }
    +          bind "Alt -" { Resize "Decrease"; }
    +          bind "Alt =" { Resize "Increase"; }
    +          bind "Alt [" { PreviousSwapLayout; }
    +          bind "Alt ]" { NextSwapLayout; }
    +          bind "Alt f" { ToggleFloatingPanes; }
    +          bind "Ctrl g" { SwitchToMode "locked"; }
    +          bind "Alt h" { MoveFocusOrTab "left"; }
    +          bind "Alt i" { MoveTab "left"; }
    +          bind "Alt j" { MoveFocus "down"; }
    +          bind "Alt k" { MoveFocus "up"; }
    +          bind "Alt l" { MoveFocusOrTab "right"; }
    +          bind "Alt n" { NewPane; }
    +          bind "Alt o" { MoveTab "right"; }
    +          bind "Ctrl q" { Quit; }
    +      }
    +      shared_except "locked" "move" {
    +          bind "Ctrl h" { SwitchToMode "move"; }
    +      }
    +      shared_except "locked" "session" {
    +          bind "Ctrl o" { SwitchToMode "session"; }
    +      }
    +      shared_except "locked" "scroll" "search" "tmux" {
    +          bind "Ctrl b" { SwitchToMode "tmux"; }
    +      }
    +      shared_except "locked" "scroll" "search" {
    +          bind "Ctrl s" { SwitchToMode "scroll"; }
    +      }
    +      shared_except "locked" "tab" {
    +          bind "Ctrl t" { SwitchToMode "tab"; }
    +      }
    +      shared_except "locked" "pane" {
    +          bind "Ctrl p" { SwitchToMode "pane"; }
    +      }
    +      shared_except "locked" "resize" {
    +          bind "Ctrl n" { SwitchToMode "resize"; }
    +      }
    +      shared_except "normal" "locked" "entersearch" {
    +          bind "enter" { SwitchToMode "normal"; }
    +      }
    +      shared_except "normal" "locked" "entersearch" "renametab" "renamepane" {
    +          bind "esc" { SwitchToMode "normal"; }
    +      }
    +      shared_among "pane" "tmux" {
    +          bind "x" { CloseFocus; SwitchToMode "normal"; }
    +      }
    +      shared_among "scroll" "search" {
    +          bind "PageDown" { PageScrollDown; }
    +          bind "PageUp" { PageScrollUp; }
    +          bind "left" { PageScrollUp; }
    +          bind "down" { ScrollDown; }
    +          bind "up" { ScrollUp; }
    +          bind "right" { PageScrollDown; }
    +          bind "Ctrl b" { PageScrollUp; }
    +          bind "Ctrl c" { ScrollToBottom; SwitchToMode "normal"; }
    +          bind "d" { HalfPageScrollDown; }
    +          bind "Ctrl f" { PageScrollDown; }
    +          bind "h" { PageScrollUp; }
    +          bind "j" { ScrollDown; }
    +          bind "k" { ScrollUp; }
    +          bind "l" { PageScrollDown; }
    +          bind "Ctrl s" { SwitchToMode "normal"; }
    +          bind "u" { HalfPageScrollUp; }
    +      }
    +      entersearch {
    +          bind "Ctrl c" { SwitchToMode "scroll"; }
    +          bind "esc" { SwitchToMode "scroll"; }
    +          bind "enter" { SwitchToMode "search"; }
    +      }
    +      renametab {
    +          bind "esc" { UndoRenameTab; SwitchToMode "tab"; }
    +      }
    +      shared_among "renametab" "renamepane" {
    +          bind "Ctrl c" { SwitchToMode "normal"; }
    +      }
    +      renamepane {
    +          bind "esc" { UndoRenamePane; SwitchToMode "pane"; }
    +      }
    +      shared_among "session" "tmux" {
    +          bind "d" { Detach; }
    +      }
    +      tmux {
    +          bind "left" { MoveFocus "left"; SwitchToMode "normal"; }
    +          bind "down" { MoveFocus "down"; SwitchToMode "normal"; }
    +          bind "up" { MoveFocus "up"; SwitchToMode "normal"; }
    +          bind "right" { MoveFocus "right"; SwitchToMode "normal"; }
    +          bind "space" { NextSwapLayout; }
    +          bind "\"" { NewPane "down"; SwitchToMode "normal"; }
    +          bind "%" { NewPane "right"; SwitchToMode "normal"; }
    +          bind "," { SwitchToMode "renametab"; }
    +          bind "[" { SwitchToMode "scroll"; }
    +          bind "Ctrl b" { Write 2; SwitchToMode "normal"; }
    +          bind "c" { NewTab; SwitchToMode "normal"; }
    +          bind "h" { MoveFocus "left"; SwitchToMode "normal"; }
    +          bind "j" { MoveFocus "down"; SwitchToMode "normal"; }
    +          bind "k" { MoveFocus "up"; SwitchToMode "normal"; }
    +          bind "l" { MoveFocus "right"; SwitchToMode "normal"; }
    +          bind "n" { GoToNextTab; SwitchToMode "normal"; }
    +          bind "o" { FocusNextPane; }
    +          bind "p" { GoToPreviousTab; SwitchToMode "normal"; }
    +          bind "z" { ToggleFocusFullscreen; SwitchToMode "normal"; }
    +      }
    +  }
    +
    +  // Plugin aliases - can be used to change the implementation of Zellij
    +  // changing these requires a restart to take effect
    +  plugins {
    +      compact-bar location="zellij:compact-bar"
    +      configuration location="zellij:configuration"
    +      filepicker location="zellij:strider" {
    +          cwd "/"
    +      }
    +      plugin-manager location="zellij:plugin-manager"
    +      session-manager location="zellij:session-manager"
    +      status-bar location="zellij:status-bar"
    +      strider location="zellij:strider"
    +      tab-bar location="zellij:tab-bar"
    +      welcome-screen location="zellij:session-manager" {
    +          welcome_screen true
    +      }
    +  }
    +
    +  // Plugins to load in the background when a new session starts
    +  // eg. "file:/path/to/my-plugin.wasm"
    +  // eg. "https://example.com/my-plugin.wasm"
    +  load_plugins {
    +  }
    +
    +  // Provide a command to execute when copying text. The text will be piped to
    +  // the stdin of the program to perform the copy. This can be used with
    +  // terminal emulators which do not support the OSC 52 ANSI control sequence
    +  // that will be used by default if this option is not set.
    +  // Examples:
    +  //
    +  // copy_command "xclip -selection clipboard" // x11
    +  // copy_command "wl-copy"                    // wayland
    +  // copy_command "pbcopy"                     // osx
    +  //
    +  // copy_command "pbcopy"
    +
    +  // Choose the destination for copied text
    +  // Allows using the primary selection buffer (on x11/wayland) instead of the system clipboard.
    +  // Does not apply when using copy_command.
    +  // Options:
    +  //   - system (default)
    +  //   - primary
    +  //
    +  // copy_clipboard "primary"
    +
    +  // Path to the default editor to use to edit pane scrollbuffer
    +  // Default: $EDITOR or $VISUAL
    +  // scrollback_editor "/usr/bin/vim"
    +
    +  // Toggle between having Zellij lay out panes according to a predefined set of layouts whenever possible
    +  // Options:
    +  //   - true (default)
    +  //   - false
    +  //
    +  // auto_layout false
    +
    +  // Whether sessions should be serialized to the cache folder (including their tabs/panes, cwds and running commands) so that they can later be resurrected
    +  // Options:
    +  //   - true (default)
    +  //   - false
    +  //
    +  // session_serialization false
    +
    +  // Whether pane viewports are serialized along with the session, default is false
    +  // Options:
    +  //   - true
    +  //   - false (default)
    +  //
    +  // serialize_pane_viewport false
    +
    +  // Scrollback lines to serialize along with the pane viewport when serializing sessions, 0
    +  // defaults to the scrollback size. If this number is higher than the scrollback size, it will
    +  // also default to the scrollback size. This does nothing if `serialize_pane_viewport` is not true.
    +  //
    +  // scrollback_lines_to_serialize 10000
    +
    +  // Enable or disable the rendering of styled and colored underlines (undercurl).
    +  // May need to be disabled for certain unsupported terminals
    +  // (Requires restart)
    +  // Default: true
    +  //
    +  // styled_underlines false
    +
    +  // How often in seconds sessions are serialized
    +  //
    +  // serialization_interval 10000
    +
    +  // Enable or disable writing of session metadata to disk (if disabled, other sessions might not know
    +  // metadata info on this session)
    +  // (Requires restart)
    +  // Default: false
    +  //
    +  // disable_session_metadata false
    +
    +  // Enable or disable support for the enhanced Kitty Keyboard Protocol (the host terminal must also support it)
    +  // (Requires restart)
    +  // Default: true (if the host terminal supports it)
    +  //
    +  // support_kitty_keyboard_protocol false
    +''
    +
    +
    +
    +
    +
    +
    +

    6.10. Vieb config

    +
    +
    +
    " Options
    +set adblocker=update
    +set adblockernotifications=all
    +set cache=clearonquit
    +set noclearcookiesonquit
    +set nocleardownloadsoncompleted
    +set nocleardownloadsonquit
    +set clearhistoryinterval=none
    +set noclearlocalstorageonquit
    +set noclosablepinnedtabs
    +set commandhist=persistuseronly
    +set containerkeeponreopen
    +set containernewtab=s:usecurrent
    +set containershowname=automatic
    +set containersplitpage=s:usecurrent
    +set containerstartuppage=main
    +set countlimit=100
    +" set nodarkreader
    +set darkreaderbg=#181a1b
    +set darkreaderbrightness=100
    +set darkreadercontrast=100
    +set darkreaderfg=#e8e6e3
    +set darkreadergrayscale=0
    +set darkreadermode=dark
    +set darkreadersepia=0
    +set darkreadertextstroke=0
    +set devtoolsposition=split
    +set dialogalert=notifyblock
    +set dialogconfirm=notifyallow
    +set dialogprompt=notifyblock
    +set downloadmethod=automatic
    +set downloadpath=
    +set encodeurlcopy=nospaces
    +set encodeurlext=nospaces
    +set explorehist=persist
    +set externalcommand=
    +set favicons=session
    +set followchars=numbers
    +set followfallbackaction=filter
    +set followlabelposition=outsiderighttop
    +set follownewtabswitch
    +set guifontsize=14
    +set guifullscreennavbar=oninput
    +set guifullscreentabbar=onupdate
    +set guihidetimeout=5000
    +set guinavbar=oninput
    +set guiscrollbar=onscroll
    +set guitabbar=onupdate
    +set historyperpage=100
    +set ignorecase
    +set incsearch
    +set inputfocusalignment=rememberend
    +set keeprecentlyclosed
    +set lang=en
    +set loadingindicator=line
    +set mapsuggest=9000000000000000
    +set mapsuggestposition=topright
    +set markposition=newtab
    +set markpositionshifted=default
    +set maxmapdepth=10
    +set menupage=elementasneeded
    +set menusuggest=both
    +set menuvieb=both
    +set mintabwidth=28
    +set mouse=all
    +set mousedisabledbehavior=nothing
    +set nomousefocus
    +set mousenewtabswitch
    +set mousevisualmode=onswitch
    +set nativenotification=never
    +set nativetheme=dark
    +set newtaburl=
    +set notificationduration=6000
    +set notificationforpermissions=silent
    +set notificationforsystemcommands=errors
    +set notificationlimitsmall=3
    +set notificationposition=bottomright
    +set pdfbehavior=download
    +set permissioncamera=ask
    +set permissioncertificateerror=allow
    +set permissionclipboardread=allow
    +set permissionclipboardwrite=allow
    +set permissionclosepage=allow
    +set permissiondisplaycapture=ask
    +set permissionfullscreen=allow
    +set permissiongeolocation=block
    +set permissionhid=block
    +set permissionidledetection=block
    +set permissionmediadevices=allowfull
    +set permissionmicrophone=ask
    +set permissionmidi=ask
    +set permissionmidisysex=ask
    +set permissionnotifications=ask
    +set permissionopenexternal=ask
    +set permissionpersistentstorage=ask
    +set permissionpointerlock=block
    +set permissionscreenwakelock=block
    +set permissionsensors=block
    +set permissionserial=block
    +set permissionunknown=ask
    +set permissionusb=allow
    +set permissionwindowmanagement=ask
    +set pointerposlocalid=domain
    +set pointerpostype=casing
    +set noquitonlasttabclose
    +set redirecttohttp
    +set noreloadtaboncrash
    +set replacespecial=special
    +set replacestartup=never
    +set requesttimeout=20000
    +set restoretabs=all
    +set scrollposlocalid=domain
    +set scrollpostype=casing
    +set searchemptyscope=global
    +set searchpointeralignment=left
    +set searchscope=global
    +set shell=
    +set showcmd
    +set smartcase
    +set spell
    +set nosplitbelow
    +set nosplitright
    +set nosponsorblock
    +set suggestbouncedelay=100
    +set suggestcommands=9000000000000000
    +set suggesttopsites=10
    +set suspendbackgroundtab
    +set suspendonrestore=regular
    +set suspendtimeout=0
    +set tabclosefocus=left
    +set tabcycle
    +set tabnewposition=right
    +set tabopenmuted=never
    +set taboverflow=scroll
    +set tabreopenmuted=remember
    +set tabreopenposition=right
    +set timeout
    +set timeoutlen=2000
    +set translateapi=auto
    +set translatekey=
    +set translatelang=en-us
    +set translateurl=https://api-free.deepl.com/v2/
    +" set nouserscript
    +" set nouserstyle
    +set useragent=%firefox
    +set vimcommand=gvim
    +set windowfullscreen=restore
    +set windowmaximize=restore
    +set windowposition=restore
    +set windowsize=restore
    +set windowtitle="%app - %title"
    +
    +" Commands
    +colorscheme default
    +
    +
    +" Mappings
    +nmap o <toExploreMode>
    +nmap t <:tabnew><toExploreMode>
    +nmap b <toCommandMode>buffer<Space>
    +nmap g0 <:buffer 0>
    +nmap g^ <:buffer 0>
    +nmap g$ <:buffer -1>
    +nmap <C-m> <:buffer #>
    +nmap J <previousTab>
    +nmap K <nextTab>
    +nmap >> <moveTabForward>
    +nmap <lt><lt> <moveTabBackward>
    +nmap O <toExploreMode><End>
    +nmap gx0 <:lclose>
    +nmap gx$ <:rclose>
    +nmap x <stopLoadingPage>
    +nunmap [
    +nunmap ]
    +nmap [[ <previousPage>
    +nmap ]] <nextPage>
    +nmap [c <decreasePageNumber>
    +nmap ]c <increasePageNumber>
    +nmap zz <zoomReset>
    +nmap zi <zoomIn>
    +nmap zo <zoomOut>
    +nmap zm 5<zoomIn>
    +nmap zr 5<zoomOut>
    +nmap zM 5<zoomIn>
    +nmap zR 5<zoomOut>
    +nmap zI 7<zoomIn>
    +nmap zO 7<zoomOut>
    +
    +" Search
    +set searchengine=https://kagi.com/search?q=%s
    +set searchwords+=no~https://search.nixos.org/options?query=%s
    +set searchwords+=np~https://search.nixos.org/packages?query=%s
    +set searchwords+=hm~https://home-manager-options.extranix.com/?query=%s
    +
    +" Viebrc generated by Vieb
    +" vim: ft=vim
    +
    +
    +
    +
    +
    +
    +

    6.11. swayidle

    +
    +
    +
    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'
    +
    +
    +
    +
    +
    +

    6.12. stylix color scheme

    +
    +
    +
    # scheme: "better-contrast"
    +author: "Swarsel"
    +base00: "1D252C" # #1d252c passt
    +base01: "171D23" # #171d23
    +base02: "5EC4FF" # #5EC4FF
    +base03: "566C7D" # #566C7D passt
    +base04: "5EC4FF" # #5EC4FF passt
    +base05: "A0B3C5" # #A0B3C5 passt
    +base06: "C06ECE" # #C06ECE passt
    +base07: "A0B3C5" # #A0B3C5 passt
    +base08: "D95468" # #D95468 passt
    +base09: "FFA880" # #ffA880 passt
    +base0A: "5EC4FF" # #5EC4FF
    +base0B: "8BD49C" # #8BD49C
    +base0C: "008B94" # #008B94 passt
    +base0D: "5EC4FF" # #5EC4FF passt
    +base0E: "C06ECE" # #C06ECE passt
    +base0F: "5EC4FF" # #5EC4FF passt
    +
    +# base00 - Default Background
    +# base01 - Lighter Background (Used for status bars)
    +# base02 - Selection Background
    +# base03 - Comments, Invisibles, Line Highlighting
    +# base04 - Dark Foreground (Used for status bars)
    +# base05 - Default Foreground, Caret, Delimiters, Operators
    +# base06 - Light Foreground (Not often used)
    +# base07 - Light Background (Not often used)
    +# base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted
    +# base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url
    +# base0A - Classes, Markup Bold, Search Text Background
    +# base0B - Strings, Inherited Class, Markup Code, Diff Inserted
    +# base0C - Support, Regular Expressions, Escape Characters, Markup Quotes
    +# base0D - Functions, Methods, Attribute IDs, Headings
    +# base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed
    +# base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. <?php ?>
    +
    +
    +
    +
    +
    +

    6.13. .gitmessage

    +
    +
    +
    +#                         max. 50 chars is here: #
    +# <type>[optional scope]: <description>
    +# types: feat, fix, build, chore, ci, docs, style, refactor, perf, test
    +# ! indicates a breaking change.
    +
    +
    +# Body:                                      wrap at 72 chars is here: #
    +# Include at least one empty line before co-authored. Format:
    +# Co-authored-by: name <user@users.noreply.github.com>
    +
    +
    +
    +
    +
    +

    6.14. userChrome.css

    +
    +
    +
      /* 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. */
    +
    +/* Hide the whole toolbar area unless urlbar is focused or cursor is over the toolbar
    + * Dimensions on non-Win10 OS probably needs to be adjusted.
    + */
    +
    +:root{
    +    --uc-autohide-toolbox-delay: 0ms; /* Wait 0.1s before hiding toolbars */
    +    --uc-toolbox-rotation: 107deg;  /* This may need to be lower on mac - like 75 or so */
    +
    +    --base00: #1D252C;
    +    --base01: #171D23;
    +    --base02: #5EC4FF;
    +    --base03: #566C7D;
    +    --base04: #5EC4FF;
    +    --base05: #A0B3C5;
    +    --base06: #C06ECE;
    +    --base07: #A0B3C5;
    +    --base08: #D95468;
    +    --base09: #FFA880;
    +    --base0A: #5EC4FF;
    +    --base0B: #8BD49C;
    +    --base0C: #008B94;
    +    --base0D: #5EC4FF;
    +    --base0E: #C06ECE;
    +    --base0F: #5EC4FF;
    +
    +}
    +
    +:root[sizemode="maximized"]{
    +    --uc-toolbox-rotation: 88.5deg;
    +}
    +
    +@media  (-moz-platform: windows){
    +    :root:not([lwtheme]) #navigator-toolbox{ background-color: -moz-dialog !important; }
    +}
    +
    +:root[sizemode="fullscreen"],
    +:root[sizemode="fullscreen"] #navigator-toolbox{ margin-top: 0 !important; }
    +
    +#navigator-toolbox{
    +    --browser-area-z-index-toolbox: 3;
    +    position: fixed !important;
    +    background-color: var(--lwt-accent-color,black) !important;
    +    transition: transform 0ms linear, opacity 0ms linear !important;
    +    transition-delay: var(--uc-autohide-toolbox-delay) !important;
    +    transform-origin: top;
    +    transform: rotateX(var(--uc-toolbox-rotation));
    +    opacity: 0;
    +    line-height: 0;
    +    z-index: 1;
    +    pointer-events: none;
    +}
    +:root[sessionrestored] #urlbar[popover]{
    +    pointer-events: none;
    +    opacity: 0;
    +    transition: transform 0ms linear var(--uc-autohide-toolbox-delay), opacity 0ms calc(var(--uc-autohide-toolbox-delay) + 0ms);
    +    transform-origin: 0px calc(0px - var(--tab-min-height) - var(--tab-block-margin) * 2);
    +    transform: rotateX(89.9deg);
    +}
    +#mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts)) ~ toolbox #urlbar[popover],
    +#navigator-toolbox:is(:hover,:focus-within) #urlbar[popover],
    +#urlbar-container > #urlbar[popover]:is([focused],[open]){
    +    pointer-events: auto;
    +    opacity: 1;
    +    transition-delay: 0ms;
    +    transform: rotateX(0deg);
    +}
    +#mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts)) ~ toolbox,
    +#navigator-toolbox:has(#urlbar:is([open],[focus-within])),
    +#navigator-toolbox:hover,
    +#navigator-toolbox:focus-within{
    +    transition-delay: 0ms !important;
    +    transform: rotateX(0);
    +    opacity: 1;
    +}
    +/* This makes things like OS menubar/taskbar show the toolbox when hovered in maximized windows.
    + * Unfortunately it also means that other OS native surfaces (such as context menu on macos)
    + * and other always-on-top applications will trigger toolbox to show up. */
    +@media (-moz-bool-pref: "userchrome.autohide-toolbox.unhide-by-native-ui.enabled"){
    +    :root[sizemode="maximized"]:not(:hover){
    +        #navigator-toolbox:not(:-moz-window-inactive),
    +    #urlbar[popover]:not(:-moz-window-inactive){
    +        transition-delay: 0ms !important;
    +        transform: rotateX(0);
    +        opacity: 1;
    +    }
    +    }
    +}
    +
    +#navigator-toolbox > *{ line-height: normal; pointer-events: auto }
    +
    +#navigator-toolbox,
    +#navigator-toolbox > *{
    +    width: 100vw;
    +    -moz-appearance: none !important;
    +}
    +
    +/* These two exist for oneliner compatibility */
    +#nav-bar{ width: var(--uc-navigationbar-width,100vw) }
    +#TabsToolbar
    +{
    +    visibility: collapse;
    +}
    +/* Don't apply transform before window has been fully created */
    +:root:not([sessionrestored]) #navigator-toolbox{ transform:none !important }
    +
    +:root[customizing] #navigator-toolbox{
    +    position: relative !important;
    +    transform: none !important;
    +    opacity: 1 !important;
    +}
    +
    +#navigator-toolbox[inFullscreen] > #PersonalToolbar,
    +#PersonalToolbar[collapsed="true"]{ display: none }
    +
    +/* Uncomment this if tabs toolbar is hidden with hide_tabs_toolbar.css */
    + /*#titlebar{ margin-bottom: -9px }*/
    +
    +/* Uncomment the following for compatibility with tabs_on_bottom.css - this isn't well tested though */
    +/*
    +#navigator-toolbox{ flex-direction: column; display: flex; }
    +#titlebar{ order: 2 }
    +*/
    +#sidebar-header {
    +    display: none;
    +}
    +#sidebar-header {
    +    /* display: none; */
    +    visibility: collapse !important;
    +}
    +/* Source file https://github.com/MrOtherGuy/firefox-csshacks/tree/master/chrome/autohide_sidebar.css made available under Mozilla Public License v. 2.0
    +See the above repository for updates as well as full license text. */
    +
    +/* Show sidebar only when the cursor is over it  */
    +/* The border controlling sidebar width will be removed so you'll need to modify these values to change width */
    +
    +#sidebar-box{
    +    --uc-sidebar-width: 30px;
    +    --uc-sidebar-hover-width: 210px;
    +    --uc-autohide-sidebar-delay: 0ms; /* Wait 0.6s before hiding sidebar */
    +    --uc-autohide-transition-duration: 0ms;
    +    --uc-autohide-transition-type: linear;
    +    --browser-area-z-index-sidebar: 3;
    +    position: relative;
    +    min-width: var(--uc-sidebar-width) !important;
    +    width: var(--uc-sidebar-width) !important;
    +    max-width: var(--uc-sidebar-width) !important;
    +    z-index: var(--browser-area-z-index-sidebar,3);
    +}
    +#sidebar-box[positionend]{ direction: rtl }
    +#sidebar-box[positionend] > *{ direction: ltr }
    +
    +#sidebar-box[positionend]:-moz-locale-dir(rtl){ direction: ltr }
    +#sidebar-box[positionend]:-moz-locale-dir(rtl) > *{ direction: rtl }
    +
    +#main-window[sizemode="fullscreen"] #sidebar-box{ --uc-sidebar-width: 1px; }
    +
    +#sidebar-splitter{ display: none }
    +
    +#sidebar-header{
    +    overflow: hidden;
    +    color: var(--chrome-color, inherit) !important;
    +    padding-inline: 0 !important;
    +}
    +
    +#sidebar-header::before,
    +#sidebar-header::after{
    +    content: "";
    +    display: flex;
    +    padding-left: 8px;
    +}
    +
    +#sidebar-header,
    +#sidebar{
    +    transition: min-width var(--uc-autohide-transition-duration) var(--uc-autohide-transition-type) var(--uc-autohide-sidebar-delay) !important;
    +    min-width: var(--uc-sidebar-width) !important;
    +    will-change: min-width;
    +}
    +#sidebar-box:hover > #sidebar-header,
    +#sidebar-box:hover > #sidebar{
    +    min-width: var(--uc-sidebar-hover-width) !important;
    +    transition-delay: 0ms !important;
    +}
    +
    +.sidebar-panel{
    +    background-color: transparent !important;
    +    color: var(--newtab-text-primary-color) !important;
    +}
    +
    +.sidebar-panel #search-box{
    +    -moz-appearance: none !important;
    +    background-color: rgba(249,249,250,0.1) !important;
    +    color: inherit !important;
    +}
    +
    +/* Add sidebar divider and give it background */
    +
    +#sidebar,
    +#sidebar-header{
    +    background-color: inherit !important;
    +    border-inline: 1px solid rgb(80,80,80);
    +    border-inline-width: 0px 1px;
    +}
    +
    +#sidebar-box:not([positionend]) > :-moz-locale-dir(rtl),
    +#sidebar-box[positionend] > *{
    +    border-inline-width: 1px 0px;
    +}
    +
    +/* Move statuspanel to the other side when sidebar is hovered so it doesn't get covered by sidebar */
    +
    +#sidebar-box:not([positionend]):hover ~ #appcontent #statuspanel{
    +    inset-inline: auto 0px !important;
    +}
    +#sidebar-box:not([positionend]):hover ~ #appcontent #statuspanel-label{
    +    margin-inline: 0px !important;
    +    border-left-style: solid !important;
    +}
    +
    +
    +
    +
    +
    +
    +

    6.15. Default Flake Template

    +
    +
    +
    {
    +  description = "General purpose Flake";
    +
    +  inputs = {
    +    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
    +    systems.url = "github:nix-systems/default";
    +  };
    +
    +  outputs =
    +    { nixpkgs
    +    , systems
    +    , ...
    +    }:
    +    let
    +      forEachSystem = nixpkgs.lib.genAttrs (import systems);
    +      pkgsFor = forEachSystem (system: import nixpkgs { inherit system; });
    +    in
    +    {
    +      formatter = forEachSystem (system: pkgsFor.${system}.nixpkgs-fmt);
    +
    +      devShells = forEachSystem (system: {
    +        default = pkgsFor.${system}.mkShell {
    +          packages = with pkgsFor.${system}; [
    +
    +          ];
    +        };
    +      });
    +
    +    };
    +}
    +
    +
    +
    +
    +
    +

    6.16. C++ Flake Template

    +
    +
    +
    # heavily inspired by https://github.com/nulladmin1/nix-flake-templates/blob/main/cpp-cmake/flake.nix
    +{
    +  description = "C++ Flake";
    +
    +  inputs = {
    +    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
    +    systems.url = "github:nix-systems/default";
    +  };
    +
    +  outputs =
    +    { self
    +    , nixpkgs
    +    , systems
    +    , ...
    +    }:
    +    let
    +      forEachSystem = nixpkgs.lib.genAttrs (import systems);
    +      pkgsFor = forEachSystem (system: import nixpkgs { inherit system; });
    +
    +      pname = "name";
    +    in
    +    {
    +      formatter = forEachSystem (system: pkgsFor.${system}.nixpgks-fmt);
    +
    +      devShells = forEachSystem (system: {
    +        default = pkgsFor.${system}.mkShell {
    +          packages = with pkgsFor.${system}; [
    +            libllvm
    +            cmake
    +            gtest
    +            cppcheck
    +            valgrind
    +            doxygen
    +            clang-tools
    +            # cudatoolkit
    +          ];
    +        };
    +      });
    +
    +      packages = forEachSystem (system: {
    +        default = pkgsFor.${system}.stdenv.mkDerivation {
    +          inherit pname;
    +          version = "0.1.0";
    +          src = ./.;
    +
    +          nativeBuildInputs = with pkgsFor.${system}; [
    +            cmake
    +          ];
    +          buildInputs = with pkgsFor.${system}; [
    +            gtest
    +          ];
    +        };
    +      });
    +
    +      apps = forEachSystem (system: {
    +        default = {
    +          type = "app";
    +          program = "${self.packages.${system}.default}/bin/${pname}";
    +        };
    +      });
    +    };
    +}
    +
    +
    +
    +
    +
    +

    6.17. Go Flake Template

    +
    +
    +
    # heavily inspired by https://github.com/nulladmin1/nix-flake-templates/blob/main/go-nix/flake.nix
    +{
    +  description = "Go Flake";
    +
    +  inputs = {
    +    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
    +    systems.url = "github:nix-systems/default";
    +  };
    +
    +  outputs =
    +    { self
    +    , nixpkgs
    +    , systems
    +    , ...
    +    }:
    +    let
    +      forEachSystem = nixpkgs.lib.genAttrs (import systems);
    +      pkgsFor = forEachSystem (system: import nixpkgs { inherit system; });
    +
    +      pname = "name";
    +    in
    +    {
    +      formatter = forEachSystem (system: pkgsFor.${system}.nixpkgs-fmt);
    +
    +      devShells = forEachSystem (system: {
    +        default = pkgsFor.${system}.mkShell {
    +          packages = with pkgsFor.${system}; [
    +            go
    +            gopls
    +            go-tools
    +            gotools
    +          ];
    +        };
    +      });
    +
    +      packages = forEachSystem (system: {
    +        default = pkgsFor.${system}.buildGoModule {
    +          inherit pname;
    +          version = "0.1.0";
    +          src = ./.;
    +          vendorHash = null;
    +        };
    +      });
    +
    +      apps = forEachSystem (system: {
    +        default = {
    +          type = "app";
    +          program = "${self.packages.${system}.default}/bin/${pname}";
    +        };
    +      });
    +    };
    +}
    +
    +
    +
    +
    +
    +

    6.18. LaTeX Flake Template

    +
    +
    +
    # This template is based on https://github.com/Leixb/latex-template/tree/master
    +{
    +  description = "LaTeX Flake";
    +
    +  inputs.flake-utils.url = "github:numtide/flake-utils";
    +
    +  outputs = { self, nixpkgs, flake-utils }:
    +    {
    +
    +      lib.latexmk = import ./build-document.nix;
    +
    +    } // flake-utils.lib.eachDefaultSystem (system:
    +      let
    +        pname = "document";
    +
    +        pkgs = import nixpkgs { inherit system; };
    +
    +        latex-packages = with pkgs; [
    +          (texlive.combine {
    +            inherit (texlive)
    +              scheme-medium
    +              framed
    +              titlesec
    +              cleveref
    +              multirow
    +              wrapfig
    +              tabu
    +              threeparttable
    +              threeparttablex
    +              makecell
    +              environ
    +              biblatex
    +              biber
    +              fvextra
    +              upquote
    +              catchfile
    +              xstring
    +              csquotes
    +              minted
    +              dejavu
    +              comment
    +              footmisc
    +              xltabular
    +              ltablex
    +              ;
    +          })
    +          which
    +          python39Packages.pygments
    +        ];
    +
    +        dev-packages = with pkgs; [
    +          texlab
    +          zathura
    +          wmctrl
    +        ];
    +      in
    +      rec {
    +        devShell = pkgs.mkShell {
    +          buildInputs = [ latex-packages dev-packages ];
    +        };
    +
    +        formatter = pkgs.nixpkgs-fmt;
    +
    +        packages = flake-utils.lib.flattenTree {
    +          default = import ./build-document.nix {
    +            inherit pkgs;
    +            name = pname;
    +            texlive = latex-packages;
    +            shellEscape = true;
    +            minted = true;
    +            SOURCE_DATE_EPOCH = toString self.lastModified;
    +          };
    +        };
    +
    +        apps.default = flake-utils.lib.mkApp { drv = "${pkgs.texlivePackages.latexmk}"; exePath = "/bin/latexmk"; };
    +      }
    +    );
    +}
    +
    +
    +
    +
    +
    +

    6.19. Python Flake Template

    +
    +
    +
    # based on https://github.com/pyproject-nix/uv2nix/tree/master/templates/hello-world
    +{
    +  description = "Python flake using uv2nix";
    +
    +  inputs = {
    +    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    +
    +    pyproject-nix = {
    +      url = "github:pyproject-nix/pyproject.nix";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +
    +    uv2nix = {
    +      url = "github:pyproject-nix/uv2nix";
    +      inputs = {
    +        pyproject-nix.follows = "pyproject-nix";
    +        nixpkgs.follows = "nixpkgs";
    +      };
    +    };
    +
    +    pyproject-build-systems = {
    +      url = "github:pyproject-nix/build-system-pkgs";
    +      inputs = {
    +        pyproject-nix.follows = "pyproject-nix";
    +        uv2nix.follows = "uv2nix";
    +        nixpkgs.follows = "nixpkgs";
    +      };
    +    };
    +  };
    +
    +  outputs =
    +    { nixpkgs
    +    , uv2nix
    +    , pyproject-nix
    +    , pyproject-build-systems
    +    , ...
    +    }:
    +    let
    +      inherit (nixpkgs) lib;
    +      pname = "name";
    +      forAllSystems = lib.genAttrs lib.systems.flakeExposed;
    +
    +      # Load a uv workspace from a workspace root.
    +      # Uv2nix treats all uv projects as workspace projects.
    +      workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; };
    +
    +      overlay = workspace.mkPyprojectOverlay {
    +        # Prefer prebuilt binary wheels as a package source.
    +        # Sdists are less likely to "just work" because of the metadata missing from uv.lock.
    +        # Binary wheels are more likely to, but may still require overrides for library dependencies.
    +        sourcePreference = "wheel"; # or sourcePreference = "sdist";
    +        # Optionally customise PEP 508 environment
    +        # environ = {
    +        #   platform_release = "5.10.65";
    +        # };
    +      };
    +
    +
    +      pythonSets = forAllSystems
    +        (system:
    +          let
    +            inherit (pkgs) stdenv;
    +            pkgs = nixpkgs.legacyPackages.${system};
    +            pyprojectOverrides = final: prev: {
    +              # Implement build fixups here.
    +              ${pname} = prev.${pname}.overrideAttrs (old: {
    +
    +                passthru = old.passthru // {
    +                  # Put all tests in the passthru.tests attribute set.
    +                  # Nixpkgs also uses the passthru.tests mechanism for ofborg test discovery.
    +                  #
    +                  # For usage with Flakes we will refer to the passthru.tests attributes to construct the flake checks attribute set.
    +                  tests =
    +                    let
    +
    +                      virtualenv = final.mkVirtualEnv "${pname}-pytest-env" {
    +                        ${pname} = [ "test" ];
    +                      };
    +
    +                    in
    +                    (old.tests or { })
    +                      // {
    +                      pytest = stdenv.mkDerivation {
    +                        name = "${final.${pname}.name}-pytest";
    +                        inherit (final.${pname}) src;
    +                        nativeBuildInputs = [
    +                          virtualenv
    +                        ];
    +                        dontConfigure = true;
    +
    +                        # Because this package is running tests, and not actually building the main package
    +                        # the build phase is running the tests.
    +                        #
    +                        # We also output a HTML coverage report, which is used as the build output.
    +                        buildPhase = ''
    +                          runHook preBuild
    +                          pytest --cov tests --cov-report html
    +                          runHook postBuild
    +                        '';
    +
    +                        # Install the HTML coverage report into the build output.
    +                        #
    +                        # If you wanted to install multiple test output formats such as TAP outputs
    +                        # you could make this derivation a multiple-output derivation.
    +                        #
    +                        # See https://nixos.org/manual/nixpkgs/stable/#chap-multiple-output for more information on multiple outputs.
    +                        installPhase = ''
    +                          runHook preInstall
    +                          mv htmlcov $out
    +                          runHook postInstall
    +                        '';
    +                      };
    +
    +                    };
    +                };
    +              });
    +            };
    +
    +            baseSet = pkgs.callPackage pyproject-nix.build.packages {
    +              python = pkgs.python312;
    +            };
    +          in
    +          baseSet.overrideScope
    +            (
    +              lib.composeManyExtensions [
    +                pyproject-build-systems.overlays.default
    +                overlay
    +                pyprojectOverrides
    +              ]
    +            ));
    +
    +    in
    +    {
    +      packages = forAllSystems (system:
    +        let
    +          pythonSet = pythonSets.${system};
    +        in
    +        { default = pythonSet.mkVirtualEnv "${pname}-env" workspace.deps.default; });
    +
    +      devShells = forAllSystems
    +        (system:
    +          let
    +            pythonSet = pythonSets.${system};
    +            pkgs = nixpkgs.legacyPackages.${system};
    +          in
    +          {
    +            default =
    +              let
    +                # Create an overlay enabling editable mode for all local dependencies.
    +                editableOverlay = workspace.mkEditablePyprojectOverlay {
    +                  # Use environment variable
    +                  root = "$REPO_ROOT";
    +                  # Optional: Only enable editable for these packages
    +                  # members = [ "hello-world" ];
    +                };
    +
    +                # Override previous set with our overrideable overlay.
    +                editablePythonSet = pythonSet.overrideScope editableOverlay;
    +
    +                virtualenv = editablePythonSet.mkVirtualEnv "${pname}-dev-env" {
    +                  ${pname} = [ "dev" ];
    +                };
    +
    +              in
    +              pkgs.mkShell {
    +                packages = [
    +                  virtualenv
    +                  pkgs.uv
    +                ];
    +                shellHook = ''
    +                  # Undo dependency propagation by nixpkgs.
    +                  unset PYTHONPATH
    +
    +                  # Don't create venv using uv
    +                  export UV_NO_SYNC=1
    +
    +                  # Prevent uv from downloading managed Python's
    +                  export UV_PYTHON_DOWNLOADS=never
    +
    +                  # Get repository root using git. This is expanded at runtime by the editable `.pth` machinery.
    +                  export REPO_ROOT=$(git rev-parse --show-toplevel)
    +                '';
    +              };
    +          });
    +
    +      checks = forAllSystems (
    +        system:
    +        let
    +          pythonSet = pythonSets.${system};
    +        in
    +        {
    +          inherit (pythonSet.${pname}.passthru.tests) pytest;
    +        }
    +      );
    +
    +      formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.nixpkgs-fmt);
    +
    +    };
    +}
    +
    +
    +
    +
    +
    +

    6.20. Rust Flake Template

    +
    +
    +
    # heavily inspired by https://github.com/nulladmin1/nix-flake-templates/blob/main/rust-fenix-naersk/flake.nix
    +{
    +  description = "Rust Flake using Fenix and Naersk";
    +
    +  inputs = {
    +    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
    +    systems.url = "github:nix-systems/default";
    +    naersk.url = "github:nix-community/naersk";
    +    fenix = {
    +      url = "github:nix-community/fenix";
    +      inputs.nixpkgs.follows = "nixpkgs";
    +    };
    +  };
    +
    +  outputs =
    +    { self
    +    , nixpkgs
    +    , naersk
    +    , fenix
    +    , systems
    +    , ...
    +    }:
    +    let
    +      forEachSystem = nixpkgs.lib.genAttrs (import systems);
    +      pkgsFor = forEachSystem (system:
    +
    +        import nixpkgs {
    +          inherit system;
    +          overlays = [
    +            fenix.overlays.default
    +          ];
    +        });
    +      rust-toolchain = forEachSystem (system: pkgsFor.${system}.fenix.stable);
    +    in
    +    {
    +      formatter = forEachSystem (system: pkgsFor.${system}.nixpkgs-fmt);
    +
    +      devShells = forEachSystem (system: {
    +        default = pkgsFor.${system}.mkShell {
    +          packages = with rust-toolchain.${system}; [
    +            cargo
    +            rustc
    +            clippy
    +            rustfmt
    +            rust-analyzer
    +          ];
    +          env = {
    +            RUST_BACKTRACE = "full";
    +          };
    +          RUST_SRC_PATH = "${rust-toolchain.${system}.rust-src}/lib/rustlib/src/rust/library";
    +        };
    +      });
    +
    +      packages = forEachSystem (system: {
    +        default =
    +          (pkgsFor.${system}.callPackage naersk {
    +            inherit (rust-toolchain.${system}) cargo rustc;
    +          }).buildPackage {
    +            src = ./.;
    +          };
    +      });
    +
    +      apps = forEachSystem (system: {
    +        default = {
    +          type = "app";
    +          program = "${self.packages.${system}.default}/bin/rust";
    +        };
    +      });
    +    };
    +}
     
    -

    6.6. GitHub Readme

    +

    6.21. GitHub Readme

    Here lies defined the readme for GitHub and Forgejo: @@ -21981,7 +23926,7 @@ If you feel that I forgot to pay you tribute for code that I used in this reposi

    diff --git a/modules/home/common/atuin.nix b/modules/home/common/atuin.nix index fb279ae..f0623e1 100644 --- a/modules/home/common/atuin.nix +++ b/modules/home/common/atuin.nix @@ -1,4 +1,7 @@ -{ 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 { @@ -8,7 +11,7 @@ settings = { auto_sync = true; sync_frequency = "5m"; - sync_address = "https://shellhistory.swarsel.win"; + sync_address = "https://${atuinDomain}"; }; }; }; diff --git a/modules/home/common/env.nix b/modules/home/common/env.nix index 976efa3..97edfda 100644 --- a/modules/home/common/env.nix +++ b/modules/home/common/env.nix @@ -1,7 +1,8 @@ -{ 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"; @@ -9,11 +10,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; diff --git a/modules/home/common/gammastep.nix b/modules/home/common/gammastep.nix index e97f770..e6d9e73 100644 --- a/modules/home/common/gammastep.nix +++ b/modules/home/common/gammastep.nix @@ -5,7 +5,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; diff --git a/modules/home/common/git.nix b/modules/home/common/git.nix index f593392..c716049 100644 --- a/modules/home/common/git.nix +++ b/modules/home/common/git.nix @@ -1,7 +1,9 @@ -{ 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"; @@ -25,15 +27,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"; diff --git a/modules/home/common/mail.nix b/modules/home/common/mail.nix index fbc10ae..0e804ad 100644 --- a/modules/home/common/mail.nix +++ b/modules/home/common/mail.nix @@ -24,7 +24,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 = { diff --git a/modules/home/common/packages.nix b/modules/home/common/packages.nix index 122089e..6caf23e 100644 --- a/modules/home/common/packages.nix +++ b/modules/home/common/packages.nix @@ -79,7 +79,7 @@ obsidian spotify vesktop # discord client - nextcloud-client + # nextcloud-client # enables a systemd service that I do not want spotify-player element-desktop nicotine-plus diff --git a/modules/home/common/waybar.nix b/modules/home/common/waybar.nix index 064b403..ec5cee8 100644 --- a/modules/home/common/waybar.nix +++ b/modules/home/common/waybar.nix @@ -1,4 +1,4 @@ -{ self, config, lib, ... }: +{ self, config, lib, pkgs, ... }: let generateIcons = n: lib.concatStringsSep " " (builtins.map (x: "{icon" + toString x + "}") (lib.range 0 (n - 1))); modulesLeft = [ @@ -79,28 +79,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 = { @@ -235,8 +235,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 = { @@ -250,13 +250,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; }; diff --git a/modules/home/common/yubikey.nix b/modules/home/common/yubikey.nix index 1837479..515e46a 100644 --- a/modules/home/common/yubikey.nix +++ b/modules/home/common/yubikey.nix @@ -3,7 +3,7 @@ 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 diff --git a/modules/nixos/common/globals.nix b/modules/nixos/common/globals.nix index 96830f0..a275927 100644 --- a/modules/nixos/common/globals.nix +++ b/modules/nixos/common/globals.nix @@ -4,7 +4,6 @@ let mkOption types ; - in { options = { @@ -12,21 +11,9 @@ in default = { }; type = types.submodule { options = { - root = { - hashedPassword = mkOption { - type = types.str; - description = "My root user's password hash."; - }; - }; - - myuser = { + user = { name = mkOption { type = types.str; - description = "My unix username."; - }; - hashedPassword = mkOption { - type = types.str; - description = "My unix password hash."; }; }; @@ -37,7 +24,6 @@ in options = { domain = mkOption { type = types.str; - description = "The domain under which this service can be reached"; }; }; } @@ -45,21 +31,9 @@ in }; domains = { - me = mkOption { + main = 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."; }; }; }; diff --git a/modules/nixos/common/home-manager.nix b/modules/nixos/common/home-manager.nix index c6645d8..57efbcc 100644 --- a/modules/nixos/common/home-manager.nix +++ b/modules/nixos/common/home-manager.nix @@ -1,4 +1,4 @@ -{ inputs, config, lib, ... }: +{ inputs, config, lib, outputs, globals, nodes, ... }: { options.swarselsystems.modules.home-manager = lib.mkEnableOption "home-manager"; @@ -14,7 +14,7 @@ home.stateVersion = lib.mkDefault config.system.stateVersion; } ]; - extraSpecialArgs = { inherit (inputs) self; }; + extraSpecialArgs = { inherit (inputs) self; inherit inputs outputs globals nodes; }; }; }; } diff --git a/modules/nixos/common/impermanence.nix b/modules/nixos/common/impermanence.nix index 854a2a8..c2cee7a 100644 --- a/modules/nixos/common/impermanence.nix +++ b/modules/nixos/common/impermanence.nix @@ -73,6 +73,7 @@ in "/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"; diff --git a/modules/nixos/common/network.nix b/modules/nixos/common/network.nix index ae1a8ad..dfffdee 100644 --- a/modules/nixos/common/network.nix +++ b/modules/nixos/common/network.nix @@ -22,6 +22,7 @@ networkmanager = { enable = true; + wifi.backend = "iwd"; ensureProfiles = lib.mkIf (!config.swarselsystems.isPublic) { environmentFiles = [ "${config.sops.templates."network-manager.env".path}" diff --git a/modules/nixos/common/settings.nix b/modules/nixos/common/settings.nix index e613993..9d000e8 100644 --- a/modules/nixos/common/settings.nix +++ b/modules/nixos/common/settings.nix @@ -58,6 +58,11 @@ }; services.dbus.implementation = "broker"; + + systemd.services.nix-daemon = { + environment.TMPDIR = "/var/tmp"; + }; + system.stateVersion = lib.mkDefault "23.05"; }; } diff --git a/modules/nixos/common/tmp.nix b/modules/nixos/common/tmp.nix new file mode 100644 index 0000000..27a533c --- /dev/null +++ b/modules/nixos/common/tmp.nix @@ -0,0 +1,7 @@ +{ config, lib, ... }: +{ + options.swarselsystems.modules.tmp = lib.mkEnableOption "tmp dir config"; + config = lib.mkIf config.swarselsystems.modules.tmp { + boot.tmp.useTmpfs = !config.swarselsystems.modules.impermanence true; + }; +} diff --git a/modules/nixos/optional/default.nix b/modules/nixos/optional/default.nix index a6237f7..9499b56 100644 --- a/modules/nixos/optional/default.nix +++ b/modules/nixos/optional/default.nix @@ -7,6 +7,4 @@ in imports = lib.swarselsystems.mkImports importNames "modules/nixos/optional" ++ [ "${modulesPath}/home/common/sharedsetup.nix" ]; - - } diff --git a/modules/nixos/server/ankisync.nix b/modules/nixos/server/ankisync.nix index 0fcd368..881841b 100644 --- a/modules/nixos/server/ankisync.nix +++ b/modules/nixos/server/ankisync.nix @@ -1,12 +1,14 @@ -{ 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 ]; @@ -14,6 +16,7 @@ in topology.self.services.${serviceName} = { name = lib.mkForce "Anki Sync Server"; + icon = "${self}/topology/images/${serviceName}.png"; info = "https://${serviceDomain}"; }; @@ -26,7 +29,7 @@ in openFirewall = true; users = [ { - username = "Swarsel"; + username = ankiUser; passwordFile = config.sops.secrets.swarsel.path; } ]; @@ -34,7 +37,7 @@ in services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/atuin.nix b/modules/nixos/server/atuin.nix index 658251f..790a900 100644 --- a/modules/nixos/server/atuin.nix +++ b/modules/nixos/server/atuin.nix @@ -1,17 +1,17 @@ { 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; @@ -21,7 +21,7 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/croc.nix b/modules/nixos/server/croc.nix index 2882b58..8570169 100644 --- a/modules/nixos/server/croc.nix +++ b/modules/nixos/server/croc.nix @@ -1,6 +1,5 @@ { self, lib, config, pkgs, ... }: let - serviceDomain = "send.swarsel.win"; servicePorts = [ 9009 9010 @@ -9,12 +8,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 = { @@ -39,7 +39,7 @@ in globals.services.${serviceName}.domain = serviceDomain; - services.croc = { + services.${serviceName} = { enable = true; ports = servicePorts; pass = config.sops.secrets.croc-password.path; @@ -48,7 +48,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}"; diff --git a/modules/nixos/server/emacs.nix b/modules/nixos/server/emacs.nix index 0313ca1..598ee6b 100644 --- a/modules/nixos/server/emacs.nix +++ b/modules/nixos/server/emacs.nix @@ -1,11 +1,15 @@ { 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; diff --git a/modules/nixos/server/firefly-iii.nix b/modules/nixos/server/firefly-iii.nix index 54cc0e5..6c8b92b 100644 --- a/modules/nixos/server/firefly-iii.nix +++ b/modules/nixos/server/firefly-iii.nix @@ -1,38 +1,47 @@ { 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}/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}"; @@ -69,9 +78,9 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { - "192.168.1.2:80" = { }; + "192.168.1.2:${builtins.toString servicePort}" = { }; }; }; }; diff --git a/modules/nixos/server/forgejo.nix b/modules/nixos/server/forgejo.nix index 5645837..0745438 100644 --- a/modules/nixos/server/forgejo.nix +++ b/modules/nixos/server/forgejo.nix @@ -1,23 +1,25 @@ -{ 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"; }; @@ -25,7 +27,7 @@ in globals.services.${serviceName}.domain = serviceDomain; - services.forgejo = { + services.${serviceName} = { enable = true; user = serviceUser; group = serviceGroup; @@ -67,13 +69,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 [ [ @@ -90,7 +92,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" @@ -125,7 +127,7 @@ in services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/freshrss.nix b/modules/nixos/server/freshrss.nix index 560d008..09c6502 100644 --- a/modules/nixos/server/freshrss.nix +++ b/modules/nixos/server/freshrss.nix @@ -1,21 +1,24 @@ { 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 = { @@ -29,7 +32,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} @@ -47,18 +50,18 @@ in topology.self.services.${serviceName} = { name = "FreshRSS"; info = "https://${serviceDomain}"; - icon = "${self}/topology/images/freshrss.png"; + icon = "${self}/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; }; @@ -68,9 +71,9 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { - "192.168.1.2:80" = { }; + "192.168.1.2:${builtins.toString servicePort}" = { }; }; }; }; diff --git a/modules/nixos/server/immich.nix b/modules/nixos/server/immich.nix index 2d6ab1a..f0d7bf1 100644 --- a/modules/nixos/server/immich.nix +++ b/modules/nixos/server/immich.nix @@ -1,22 +1,22 @@ { 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; @@ -31,7 +31,7 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/jellyfin.nix b/modules/nixos/server/jellyfin.nix index 4e15fd0..9762b79 100644 --- a/modules/nixos/server/jellyfin.nix +++ b/modules/nixos/server/jellyfin.nix @@ -1,14 +1,14 @@ { 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: { @@ -27,7 +27,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 @@ -35,7 +35,7 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/jenkins.nix b/modules/nixos/server/jenkins.nix index f9ba3f5..c2bdaec 100644 --- a/modules/nixos/server/jenkins.nix +++ b/modules/nixos/server/jenkins.nix @@ -1,25 +1,25 @@ { 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}" = { }; }; diff --git a/modules/nixos/server/kanidm.nix b/modules/nixos/server/kanidm.nix index 38109b2..90eed84 100644 --- a/modules/nixos/server/kanidm.nix +++ b/modules/nixos/server/kanidm.nix @@ -1,23 +1,30 @@ { 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 = { @@ -40,7 +47,7 @@ in globals.services.${serviceName}.domain = serviceDomain; services = { - kanidm = { + ${serviceName} = { package = pkgs.kanidmWithSecretProvisioning; enableServer = true; serverSettings = { @@ -85,12 +92,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 @@ -102,8 +109,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" = [ @@ -114,8 +121,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" @@ -133,8 +140,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" = [ @@ -153,8 +160,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" = [ @@ -215,12 +222,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}" = { }; }; diff --git a/modules/nixos/server/kavita.nix b/modules/nixos/server/kavita.nix index 544d042..75cda1b 100644 --- a/modules/nixos/server/kavita.nix +++ b/modules/nixos/server/kavita.nix @@ -1,43 +1,43 @@ { 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}/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}" = { }; }; diff --git a/modules/nixos/server/koillection.nix b/modules/nixos/server/koillection.nix index 9001951..3ab45f4 100644 --- a/modules/nixos/server/koillection.nix +++ b/modules/nixos/server/koillection.nix @@ -1,17 +1,18 @@ { 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"; }; @@ -97,7 +98,7 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/matrix.nix b/modules/nixos/server/matrix.nix index 5cb5fd1..06a73c5 100644 --- a/modules/nixos/server/matrix.nix +++ b/modules/nixos/server/matrix.nix @@ -1,16 +1,17 @@ { 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 *; @@ -18,8 +19,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 @@ -28,24 +29,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} @@ -56,7 +57,7 @@ in }; }; - networking.firewall.allowedTCPPorts = [ 8008 8448 ]; + networking.firewall.allowedTCPPorts = [ servicePort federationPort ]; systemd = { timers."restart-bridges" = { @@ -87,7 +88,7 @@ in }; }; - globals.services.${serviceName}.domain = matrixDomain; + globals.services.${serviceName}.domain = serviceDomain; services = { postgresql = { @@ -130,11 +131,11 @@ in "${dataDir}/signal-registration.yaml" "${dataDir}/doublepuppet.yaml" ]; - server_name = matrixDomain; - public_baseurl = "https://${matrixDomain}"; + server_name = serviceDomain; + public_baseurl = "https://${serviceDomain}"; listeners = [ { - port = synapsePort; + port = servicePort; bind_addresses = [ "0.0.0.0" # "::1" @@ -162,8 +163,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}"; @@ -188,7 +189,7 @@ in telegram_link_preview = true; permissions = { "*" = "relaybot"; - "@swarsel:${matrixDomain}" = "admin"; + "@swarsel:${serviceDomain}" = "admin"; }; animated_sticker = { target = "gif"; @@ -208,8 +209,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}"; @@ -234,7 +235,7 @@ in }; }; login_shared_secret_map = { - matrixDomain = "as_token:doublepuppet"; + ${serviceDomain} = "as_token:doublepuppet"; }; sync_manual_marked_unread = true; send_presence_on_typing = true; @@ -244,7 +245,7 @@ in extev_polls = true; permissions = { "*" = "relay"; - "@swarsel:${matrixDomain}" = "admin"; + "@swarsel:${serviceDomain}" = "admin"; }; }; }; @@ -255,8 +256,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}"; @@ -270,12 +271,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"; }; }; }; @@ -288,14 +289,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; diff --git a/modules/nixos/server/microbin.nix b/modules/nixos/server/microbin.nix index 7b2da0b..a089d54 100644 --- a/modules/nixos/server/microbin.nix +++ b/modules/nixos/server/microbin.nix @@ -1,21 +1,21 @@ { 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; }; @@ -49,7 +49,7 @@ in }; globals.services.${serviceName}.domain = serviceDomain; - services."${serviceName}" = { + services.${serviceName} = { enable = true; passwordFile = config.sops.templates.microbin-env.path; dataDir = "/var/lib/microbin"; @@ -84,7 +84,7 @@ in }; systemd.services = { - "${serviceName}" = { + ${serviceName} = { serviceConfig = { DynamicUser = lib.mkForce false; User = serviceUser; @@ -101,7 +101,7 @@ in services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "localhost:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/monitoring.nix b/modules/nixos/server/monitoring.nix index 4d1313a..8fe35f0 100644 --- a/modules/nixos/server/monitoring.nix +++ b/modules/nixos/server/monitoring.nix @@ -1,23 +1,44 @@ -{ self, lib, config, ... }: +{ self, lib, config, globals, ... }: let - serviceDomain = "status.swarsel.win"; + servicePort = 3000; serviceUser = "grafana"; serviceGroup = serviceUser; - moduleName = "monitoring"; + serviceName = "grafana"; + serviceDomain = config.repo.secrets.common.services.domains.${serviceName}; + + prometheusPort = 9090; + prometheusUser = "prometheus"; + prometheusGroup = prometheusUser; + 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"; }; + 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 = { sopsFile = self + /secrets/winters/secrets2.yaml; owner = prometheusUser; group = prometheusGroup; mode = "0440"; }; + + }; + templates = { + "web-config" = { + content = '' + basic_auth_users: + admin: ${config.sops.placeholder.prometheus-admin-hash} + ''; + owner = prometheusUser; + group = prometheusGroup; + mode = "0440"; + }; + }; }; users = { @@ -26,7 +47,7 @@ in extraGroups = [ "nextcloud" ]; }; - "${serviceUser}" = { + ${serviceUser} = { extraGroups = [ "users" ]; }; }; @@ -35,12 +56,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 = { @@ -97,9 +118,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 @@ -111,13 +132,13 @@ in prometheus = { enable = true; - webExternalUrl = "https://status.swarsel.win/${prometheusWebRoot}"; + webExternalUrl = "https://${serviceDomain}/${prometheusWebRoot}"; port = prometheusPort; listenAddress = "0.0.0.0"; globalConfig = { scrape_interval = "10s"; }; - webConfigFile = self + /programs/server/prometheus/web.config; + webConfigFile = config.sops.templates.web-config.path; scrapeConfigs = [ { job_name = "node"; @@ -171,8 +192,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; }; }; diff --git a/modules/nixos/server/mpd.nix b/modules/nixos/server/mpd.nix index e8e3b18..3965a5b 100644 --- a/modules/nixos/server/mpd.nix +++ b/modules/nixos/server/mpd.nix @@ -1,23 +1,29 @@ { 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; [ @@ -26,19 +32,19 @@ 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}/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 = [ diff --git a/modules/nixos/server/navidrome.nix b/modules/nixos/server/navidrome.nix index 52aa2ce..eed687f 100644 --- a/modules/nixos/server/navidrome.nix +++ b/modules/nixos/server/navidrome.nix @@ -1,14 +1,14 @@ { 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 @@ -17,13 +17,13 @@ in users = { groups = { - "${serviceGroup}" = { + ${serviceGroup} = { gid = 61593; }; }; users = { - "${serviceUser}" = { + ${serviceUser} = { isSystemUser = true; uid = 61593; group = serviceGroup; @@ -36,11 +36,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 = { @@ -82,7 +82,7 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; @@ -108,19 +108,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; diff --git a/modules/nixos/server/nextcloud.nix b/modules/nixos/server/nextcloud.nix index 736a95a..f18274b 100644 --- a/modules/nixos/server/nextcloud.nix +++ b/modules/nixos/server/nextcloud.nix @@ -1,13 +1,16 @@ { 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 = { @@ -26,7 +29,7 @@ in globals.services.${serviceName}.domain = serviceDomain; services = { - nextcloud = { + ${serviceName} = { enable = true; settings = { trusted_proxies = [ "0.0.0.0" ]; @@ -34,8 +37,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"; @@ -44,7 +47,7 @@ in }; extraAppsEnable = true; config = { - adminuser = "admin"; + inherit adminuser; adminpassFile = config.sops.secrets.nextcloudadminpass.path; dbtype = "sqlite"; }; @@ -53,9 +56,9 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { - "192.168.1.2:80" = { }; + "192.168.1.2:${builtins.toString servicePort}" = { }; }; }; }; diff --git a/modules/nixos/server/nfs.nix b/modules/nixos/server/nfs.nix index c96e7d2..93f21b7 100644 --- a/modules/nixos/server/nfs.nix +++ b/modules/nixos/server/nfs.nix @@ -1,4 +1,7 @@ -{ 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 { @@ -29,7 +32,7 @@ path = "/Vault/Eternor"; writable = "true"; comment = "Eternor"; - "valid users" = "Swarsel"; + "valid users" = nfsUser; }; }; diff --git a/modules/nixos/server/nginx.nix b/modules/nixos/server/nginx.nix index 88bdee3..adc741b 100644 --- a/modules/nixos/server/nginx.nix +++ b/modules/nixos/server/nginx.nix @@ -1,4 +1,8 @@ { 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 { @@ -18,8 +22,8 @@ acceptTerms = true; preliminarySelfsigned = false; defaults = { - email = "mrswarsel@gmail.com"; - dnsProvider = "cloudflare"; + inherit dnsProvider; + email = address3; environmentFile = "${config.sops.templates."certs.secret".path}"; }; }; diff --git a/modules/nixos/server/oauth2-proxy.nix b/modules/nixos/server/oauth2-proxy.nix index cad50e1..69cb302 100644 --- a/modules/nixos/server/oauth2-proxy.nix +++ b/modules/nixos/server/oauth2-proxy.nix @@ -1,12 +1,17 @@ { 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 ( @@ -114,12 +119,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 = { @@ -128,34 +133,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; @@ -168,16 +173,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 @@ -190,20 +195,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 = '' diff --git a/modules/nixos/server/paperless.nix b/modules/nixos/server/paperless.nix index 8c2334f..2749099 100644 --- a/modules/nixos/server/paperless.nix +++ b/modules/nixos/server/paperless.nix @@ -1,16 +1,20 @@ -{ 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" ]; }; @@ -28,25 +32,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 = { @@ -58,7 +62,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"; } ]; }; @@ -68,7 +72,7 @@ in tika = { enable = true; - port = 9998; + port = tikaPort; openFirewall = false; listenAddress = "127.0.0.1"; enableOcr = true; @@ -77,7 +81,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; @@ -97,7 +101,7 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/postgresql.nix b/modules/nixos/server/postgresql.nix index 52335d7..b2bc7e1 100644 --- a/modules/nixos/server/postgresql.nix +++ b/modules/nixos/server/postgresql.nix @@ -4,13 +4,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}"; }; }; }; diff --git a/modules/nixos/server/radicale.nix b/modules/nixos/server/radicale.nix index 35a36f7..046dffe 100644 --- a/modules/nixos/server/radicale.nix +++ b/modules/nixos/server/radicale.nix @@ -2,17 +2,18 @@ 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"; }; @@ -32,7 +33,7 @@ in topology.self.services.${serviceName}.info = "https://${serviceDomain}"; globals.services.${serviceName}.domain = serviceDomain; - services.radicale = { + services.${serviceName} = { enable = true; settings = { server = { @@ -75,11 +76,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}" = { }; }; diff --git a/modules/nixos/server/shlink.nix b/modules/nixos/server/shlink.nix index 254b073..ace9e4d 100644 --- a/modules/nixos/server/shlink.nix +++ b/modules/nixos/server/shlink.nix @@ -1,15 +1,16 @@ { 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 = { @@ -25,7 +26,7 @@ in }; }; - virtualisation.oci-containers.containers."shlink" = { + virtualisation.oci-containers.containers.${serviceName} = { image = "shlinkio/shlink@${containerRev}"; environment = { "DEFAULT_DOMAIN" = serviceDomain; @@ -57,7 +58,7 @@ in services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "localhost:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/spotifyd.nix b/modules/nixos/server/spotifyd.nix index 44732f5..1de618a 100644 --- a/modules/nixos/server/spotifyd.nix +++ b/modules/nixos/server/spotifyd.nix @@ -6,13 +6,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; diff --git a/modules/nixos/server/syncthing.nix b/modules/nixos/server/syncthing.nix index 354ebd4..3da42e5 100644 --- a/modules/nixos/server/syncthing.nix +++ b/modules/nixos/server/syncthing.nix @@ -1,34 +1,37 @@ { 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; @@ -50,14 +53,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"; @@ -67,7 +70,7 @@ in id = "yjvni-9eaa7"; }; "Org" = { - path = "/Vault/data/syncthing/Org"; + path = "${cfg.dataDir}/Org"; type = "receiveonly"; versioning = { type = "simple"; @@ -77,7 +80,7 @@ in id = "a7xnl-zjj3d"; }; "Vpn" = { - path = "/Vault/data/syncthing/Vpn"; + path = "${cfg.dataDir}/Vpn"; type = "receiveonly"; versioning = { type = "simple"; @@ -87,7 +90,7 @@ in id = "hgp9s-fyq3p"; }; # "Documents" = { - # path = "/Vault/data/syncthing/Documents"; + # path = "${cfg.dataDir}/Documents"; # type = "receiveonly"; # versioning = { # type = "simple"; @@ -102,7 +105,7 @@ in nodes.moonside.services.nginx = { upstreams = { - "${serviceName}" = { + ${serviceName} = { servers = { "192.168.1.2:${builtins.toString servicePort}" = { }; }; diff --git a/modules/nixos/server/transmission.nix b/modules/nixos/server/transmission.nix index 1c1c508..c71bda0 100644 --- a/modules/nixos/server/transmission.nix +++ b/modules/nixos/server/transmission.nix @@ -1,6 +1,8 @@ { 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; @@ -18,8 +20,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 = { diff --git a/nix/globals-general.nix b/nix/globals-general.nix new file mode 100644 index 0000000..cf202bd --- /dev/null +++ b/nix/globals-general.nix @@ -0,0 +1,16 @@ +{ 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) + ]; + +} diff --git a/nix/globals.nix b/nix/globals.nix index fd64ea4..1ea68fd 100644 --- a/nix/globals.nix +++ b/nix/globals.nix @@ -1,10 +1,7 @@ +# taken from https://github.com/oddlama/nix-config/blob/main/nix/globals.nix { inputs, ... }: { - flake = - { config - , lib - , ... - }: + flake = { config, lib, ... }: { globals = let @@ -17,6 +14,7 @@ }; modules = [ ../modules/nixos/common/globals.nix + ./globals-general.nix ( { lib, ... }: { @@ -39,9 +37,7 @@ inherit (globalsSystem.config.globals) domains services - macs - myuser - root + user ; }; }; diff --git a/profiles/nixos/localserver/default.nix b/profiles/nixos/localserver/default.nix index 9357196..591d8f5 100644 --- a/profiles/nixos/localserver/default.nix +++ b/profiles/nixos/localserver/default.nix @@ -31,12 +31,12 @@ paperless = lib.mkDefault true; transmission = lib.mkDefault true; syncthing = lib.mkDefault true; - monitoring = lib.mkDefault true; + grafana = lib.mkDefault true; emacs = lib.mkDefault true; freshrss = lib.mkDefault true; jenkins = lib.mkDefault false; kanidm = lib.mkDefault true; - firefly = lib.mkDefault true; + firefly-iii = lib.mkDefault true; koillection = lib.mkDefault true; radicale = lib.mkDefault true; atuin = lib.mkDefault true; diff --git a/profiles/nixos/moonside/default.nix b/profiles/nixos/moonside/default.nix index 0ea9d47..b05c5c2 100644 --- a/profiles/nixos/moonside/default.nix +++ b/profiles/nixos/moonside/default.nix @@ -18,7 +18,7 @@ sops = lib.mkDefault true; nginx = lib.mkDefault true; ssh = lib.mkDefault true; - oauth2Proxy = lib.mkDefault true; + oauth2-proxy = lib.mkDefault true; croc = lib.mkDefault true; microbin = lib.mkDefault true; shlink = lib.mkDefault true; diff --git a/profiles/nixos/personal/default.nix b/profiles/nixos/personal/default.nix index 1ba7146..eb9cadb 100644 --- a/profiles/nixos/personal/default.nix +++ b/profiles/nixos/personal/default.nix @@ -44,6 +44,7 @@ lid = lib.mkDefault true; lowBattery = lib.mkDefault true; lanzaboote = lib.mkDefault true; + tmp = lib.mkDefault true; optional = { gaming = lib.mkDefault true; diff --git a/programs/git/.gitmessage b/programs/git/.gitmessage index 5043ffe..3980609 100644 --- a/programs/git/.gitmessage +++ b/programs/git/.gitmessage @@ -1,4 +1,3 @@ - # max. 50 chars is here: # # [optional scope]: # types: feat, fix, build, chore, ci, docs, style, refactor, perf, test diff --git a/secrets/repo/globals.nix.enc b/secrets/repo/globals.nix.enc new file mode 100644 index 0000000..3830a00 --- /dev/null +++ b/secrets/repo/globals.nix.enc @@ -0,0 +1,42 @@ +{ + "data": "ENC[AES256_GCM,data:1h+/I2SLfNqHrqWDAYmkkxFMwbN23zhUVTfWYcG9hmwiZ5KZoGErt1pvR6p2BIyBb3XrfqQoV8TWJrE7IrDKRkdX4MoaviT+W6wXJ46nTJAkJ2lbuNIfQR1paAqiIfeRIzx2GgOf,iv:GIHpghRgq1SBIs8KHzNLTvFJ7aruPd6e4zDe5GjuNo0=,tag:TvXf4qYWoSOqvlqnVsKxsw==,type:str]", + "sops": { + "age": [ + { + "recipient": "age1h72072slm2pthn9m2qwjsyy2dsazc6hz97kpzh4gksvv0r2jqecqul8w63", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBudFBlTlVWMUk4QzByRlN2\nTUcrS0VhV2xEUTc2ZkJjY3dZaTg1ZTBmNVNvCnNhY2FpQkJkQ1VZRDhTN1dUaE5M\nSTJ4WUt0SDA2Y2FSK1JENU5kVkcwNlEKLS0tIFRvV3haejQxNUJUSGd6bkJMa3hM\nVFJQUWNhaGlVenRLSDhHd0VJSDcwKzAKt+JZAK2QVUdB4Nh/xqKS1acqQy7iNMka\n/YrjK6J9CSTGUAjfMZTPXXwstVYaZCZYUnZ0xeIlRZPQw741hx4kWQ==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age16vzhcvz8tyxj8e0f47fy0z4p3dsg0ak4vl52ut3l07a0tz465cxslmhevl", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2RUM0TVJFam5lTERkSzRZ\nVmF1SmJYU3VlN0psUXlYKzVkV0VNS21UWFNzCjU2b2p3cEZod21rYVNxWDQvS0lB\neHhDTTIySzZ3TnNYTkVQU1g4ejUzOEkKLS0tIDNxaWpMV2RJQzl5T1gyOW1aT0xH\nMFU0S1FyOFZnczhETTBvZkNmQUtvcEEKO32cV09CY6x9ievHyaKNLFR2Jt1y8Pbg\nCXnpvFmXMXROoxRaDN2N4+0SRyjhzuAabyAKszOksW+iJ7fwAmuR/Q==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1zlnxraee6tddr07xn59mx5rdexw8qxryd53eqlsajasfhfy78fkq705dfg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxRFZFcWhDYkpENkhmVzhr\naGVueEFRdUxHZ2l3K24zL1pWR1VtSzUxWWx3CkVReU5FSnI2TDkwV05KaVl6cERY\ndzR2Yk8way9aNlhIZEEwNmUyOTdYYncKLS0tIFNqVHpNczhZREkweCtYWmpPcjdK\nRWdRQ1ZGa256cTJrdEloRmpGTXFDMGsKF9A40XY/cRGd4ZQXnxnlHVxAWks77j+z\nt18W7/lECC0Dt/jLMfEup9dnPyXS60C4Mz35kRNFCPXgvlIiozzyYw==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age16lnmuuxfuxxtty3atnhut8wseppwnhp7rdhmxqd5tdvs9qnjffjq42sqyy", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYdGswSkh5bmZHait6Uisw\nTzRqZDUvOThVWjhHeWFUUGJzUUpWbWU4UkFJCk1pNjZjMUV6UWtHbUc2anpRcmZZ\nYTlOOTJFS2YyS1daRzJMUFZacHJiWjAKLS0tIEcveS9RckRLQ1N4dlRiaGliYW9E\ncmhXeVVnQ3RYSmJKcUs4NTVQLzMvN3cKPxFN6MiGXyXVX0ePLTioLGTxCyEUY+X2\nHJeiFKuFkDIpfdSxrPgwrWY6r8bVeLqMsepdruqUE4o0UGHVEOn7VA==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1glge4e97vgqzh332mqs5990vteezu2m8k4wq3z35jk0q8czw3gks2d7a3h", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5S2FWYzNseEkxUndRa2F6\ncW5kYzhvengrZ1pycnphQ2FFR1dYUXh4VlZFCjBPS3FhbXBvanZRNWwyYWZCSmRl\nTEs4V0NaajBkQzRxV2lJalBIVnI2bmMKLS0tIElpV0ZOU0RWWkswZ0Y4UUFiMlN6\neFRGdDIzNHA2b0lGSFFzaFZBcXNsWUkKvpYIHTeGlQ+Bqz/EcjlQ7R6I3yuwNc9l\njQQ99P3tq7bFgj4UIUDdRWaZG7PDGesEJZ6fjJEieA5o5IO3Kq0GAg==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age18quey88vge7xytclg2nuq4ncme86dg04lxwczqxczmdchnjg3p0saehsnh", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBibGlMSU4vUEF5UlNVZzlr\nMTMyOFY2Zi8rZFdZT1JrelZEUUZkZHFvOFdzCjVPbVovaU9nZklJQWNZeDJZNm0r\nMXBIK2hsZEY0NElxTVVMWmN6WU1Ld28KLS0tIENaallkK05SMllia3prV25hZDR2\nZDBNU0dYYnJESG1JZGpvSGp1WW9UMVEKJgfdLp7BRXvyAekecNJiaBXmxSj1qNxx\nZeHceqEkfWV/PzX+RP4LHjXTQCLEOJijbKxDmxSsYq49hC9xjZASuw==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-07-02T12:24:56Z", + "mac": "ENC[AES256_GCM,data:MTBfNpPWlBI6HbTrcUhydq4NH/4m+kQWPuIjHo2eJmGbdoXk1qN1fHoKTB5U29YZWQuybBiSCRtLLWZdKhs5Vv9UsXOPDsKLflCW+sr0DEKd37ONzhlHhWsHGLF9kFOXZtruJe0p0Sh7oGy3T6ee4ABog3LwQ59ZcRmAxr7haFI=,iv:mDCvJrZXPOeuD01sqoLNGEHcexHZkZ3ankBk/lCMbUs=,tag:fqqJ8O8lI30SIqcCxAXVPA==,type:str]", + "pgp": [ + { + "created_at": "2025-07-02T12:10:18Z", + "enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ//YG1H7a2MZEWjFupRqe1jgxJMsDXq0zWdK8Wy9mHCLmEk\njFJL8xjuJGYx1tKlQKq5tLPob1NmnIr9KXwtarFrIdWY34BwqmkYSO8Vmcp7iq5U\nL0xTRX4ZWTyOpTMwsIhIrEGWd1be4HlS/QedJxOn7/D5Y+XBHf+0t+4ScE+4n4ek\nlRhSxR9OlFrmmxAjD/PHsrekgi7wX02lHhy+yKmDQ4YYL3ve6AONY3dltOFr1wk3\nQ3ffjIGegkXTiafNbAvo6joekDDIGm44lRCoaxuS/0ZbDC0IZN9EUpw7KmJvRpaW\nkYWKLLZn07CpsG5cNvZvcSMTyVi+La7WJ4Nf8x+6XzRboVcVfQ/ZnCFqUKJTIGcS\ni+UBMgNxX7PCVmbQ2pIKzn5eSk0OTwgUv4LOJzivFDc60Mk/iq2c8ptOOuzBxhR2\n/M1fs4D8QfseU3b+/2e1ysVZGpba/QxYkdgeAa3FtZz8YpgFlSHdenuljrJke28I\nqkwWEdR80jBXwZ785Ur7Uqw3Pjv0xW9hwa0s3yJ1HyL4Was0ONp2aJIW1NSRbbFv\njTVJVQOJVz+bxMla9t9cB6JmV/JxSe4Q7dkiHFxdmxug2qL9aqpXFRy0M+R6HClp\n8FjvClOhyRAOFYwjm4Ry/jY1mM33hh+KiJ9fYxAZ6ZQBonl3BdOq6/LbAwKDdC6F\nAgwDC9FRLmchgYQBD/9YHAFQvEDfzbTbJrQT4BjqRyKjgA27tA3D8MwS9Gvub91V\nJfaYbn0bc9oJBqkTEmiKw2zOTTbEC0zw18aB3rHrAc0EjYZCP9XMYQvctJo1XAKo\nZFJcCCmdKzLX6XO7rLOyjEp4J5QfdgR2NAt4NXbBH9SjqNJ29bQhR14JyYUtd+Wo\nHcypltxgX4Hd69ZHBrhY/1YVfhLOoO/vhiyCLZPFrV5HYGo7Dzrtw1aZg+RYAH5R\nixZ+ADpdVj1Tc0EwBEIzjsmJ28g8liYOeRI8g4X8/RmgJRtPerBRMxXqXxHHU0Bq\ngZpm4Aafy2NGLWPQjjjbWO3emQSkQWPtldyiYf2pSdixm8gahMK4/As3Ziu1MvIw\nMlu6TsOca2762DJfw3eWJ7DeVAVH0gDOeibPMlRVOIlqRbKOg58ZDsVMwyQaiTxC\nWa/2Do6jOIEfWGhM8MbzVuhqEvkxlUHDJjP2v50SPCBVhdI3p+im5mr9cgalwlp/\nanSR7KMC1diRz2cpePb3bHgtJGoSHRoId85Xo/mhgPQS3wJGujEUafQQRR089YF7\nLHWgahHAYX1RP0tYA9sJQxBZkc4ryCMk3R6k6HdiZsoGB5D5rJa4ufdACrgsCuML\noF/hCCulldltYNN9ZekgB1Xii5SEYku0NP4NZnA6dsoXDE7hlcy95bm09iA7StJe\nASuM1tJbFJI7eRKdg2OafM5+aVGRsJqHmYue9sD+LY7LoOK0nR6tPrL97AybKqq1\nsHwXmxhaJglwBpConTHTIIKQw0ZGUuzowFHjrTs69lLkdIOq3BP8/3cBYJAeLw==\n=P5FL\n-----END PGP MESSAGE-----", + "fp": "4BE7925262289B476DBBC17B76FD3810215AE097" + } + ], + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/secrets/repo/pii.nix.enc b/secrets/repo/pii.nix.enc index 4185311..32b1498 100644 --- a/secrets/repo/pii.nix.enc +++ b/secrets/repo/pii.nix.enc @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data:K6Exxoz4dyUuVSvS0BQOyjCQ7iuicPUJbDYhWtX350/9tOhu9XorVNmI1ezfFEmY8iAdxVy/E3QEEQcO+XjJVEVGKoX8NtAWSMUkRJT/S2MLG0nNt3kcsIhoya3S5SDiblMIA+S/yFJOmsyykgLUynYgR9QL5URdGj2utoSi9+WYvUsbxrlmcxIqk443huoq4AeZp5X+HVSIhq0rby0/Uc62ox6jz4S9CwSNTOc41xI6UNRz96xppqcAhru7NjZxomtbI9LaDBMVVRe+k5GrKCTyjqp7JCaeN19Sba/k7Uh+4VOVokNEEL0cYNIZXh8eBBxT3ogQhAfOZXfp+lWKf1bAZvVFBrXI4cSGjNUDcbYCIa1gv+rdaVMju29ZNBp+Hx9p4WjJz6zFAbC+tjmH6wBjGNz8Zeqn5Mmm755yPgdvsVAW4ZZfB49T6qOjkDnNSltoHw0n49qTVS7AmQRSQvzPERyAte3IyftQ0bIGALE27h5oB6ls7X9EXUPyNqaT1G0trnrq5D8L4C3xqYJB3KriHA7PNfpKyOVM50ryACyuF2QRHeWfBnFu78hQbMg4lWYXnVggZQdeFDaHZUeYpJCmeyehmSl88+v8f6hjV0aDPlYh8Yv7lfJokGyffMNq0ShmT2/FBPu+9iAvk/apcE8KFdlct5qtkRaOeXp2iwnHWr2bYg/JQ4D4/xePvqBfV22Qd2MarA1qW7ggVJNCbKcOSJzwbEjPGjBjkH6crfO4LD/SYmVMgSoSGojdyLc7hsAFoUtdhzfknV6vVF7h0TTIIEVIEYt0HJGIfMk3PQ4Z+4O7PSwZXxctT8d7GvuWA45QMO+Ok3pRxqNmWUxEHrJF75l+lZMnSrtjdR1r+vNPnwJxHOgn/2h0sYYvqGVVZdHapxdi+V6za0f/,iv:xXAjuNpqXRuReAH6dlunrbPgspj2/+VtCV3p+xjtOi0=,tag:m//iBHvmYmWw4vtgojbpFw==,type:str]", + "data": "ENC[AES256_GCM,data:7dWpQIRuyPRNk/fZH9nI3KgDPK8LcydFUrk8bpgK3454O1VkNGUkGnRuVfPRuBdXydMXphjB4BE8XLZGmrxS5GbvUUcxYmSGmgNqlYSLZBhcHoxnOlnAubckvst2Twf5ORBienNEo4x+9JjpGKhYXfYvULww8gM5N5mJN0qwqWOCrSgk7fYDGHUtJ187RqBlO6zQFSxT69fMUGSyzqpLahvZeqb0VaZ/aG0XpzgIeFkOFj7FkfSoA1JkY5ls+QIamvpBTib2yHh8kmDV2WIrQCEgLtbPCJxV8/9CZbhR/COUL1QjoQs5012XdyPzw5/3xOytEGmQc5Qhjd35JnnfKDyecYkb/nO2t2xpmklh1uNgy3CywzxnBj+K2aD8iRum6gVMH5xTwX/qs+ctz6bHnTy1fJp75kWMBDV4WErOz/5N3dzpRd3mZU4juQXbZC0ND1N/sx5U+IIusnASs5unkV5/FY0H6FLRwiV7kY6UCo72XAzQxr8FCrPrV+ElKaT+EGdeMi8voyssp8iYh+UYsd/6M5vH0prCGhHZ+6H/IPf1brehf2MLbK1GdmVcIGb+i0wzCqa3bOMkDKyPX0WXJYGcJZn6O+WeFbiv5XhaWxHm2ML13HDxWo1RHpIlYVw+n0vGgZcWPxE3YLjKzurKVoJ+ELQD8I3HTDSRC4Yr8xa/61LIv+Cr4LSs9YVAfuNdaH6ZgFPXFw4F3zG7M0vzi2jl2jFz/AGbXaOQQIn0GygPJ48F7R6CsyoK9sc2l5stZXEVf9Hj9mZV/K6xpLYIckkFLnXGBz4c6F7WwN71wrz6r2mMexCUrPscu1qiSrVURMIv5v3e6UgR/p/Kzt3LphP6pEckI1jxK4Ed/iynXVMrxWrcG+5iS+hgI7F7D+7I6SAU6vI5NnBC4DpOpSSxIehClbgpFVEyeWJIezAMCpMPfF6EkDm83fQ8NMtc3qL0rfp3ESyFZtC0kK4HjIizAPcSVthfF9qIggTxVgOCPRE+GcM8agjzI20JuJaWQ42K9Cg+2u5uNZE1ZCNoXEV0lCory5h1iD4NjT9POSb6ds7k9x/rFB4n1CB8CpnzEeKwHW1jaknGFvekrQPcUsVIDvIdxbdixqolFb5nbPZ/NBX0X3zJmoRAAO8Q6B9ywXTVYDIrAQuYoHuWQr+UM75DYaK/e/bG9K6zelaq0drg7RYA+HncvFemm/4aPGehYHn1GnCZ6Par8oGsXBzk2ux4w8jwl0P7XEQZ3n9ej0rSG07v+cci3yY7mjAyYbcmHW4CDFdryibrMNIk9z9YJwrsaT4aMWHIXXiLqBcDwTJxTbT9mCjm5OSZ4KqDQYXLR2p0sjtXrKndjxOVzlqZ3BzE3zAQQfP80BygKlwZORz/cvR35vYyMe5C45MUl31B2fGpsX33LeLk3WrkWQv72BY23og6hKoNAPSCJupmAbWkmsDNwihsDwqx3ABbVH7rWYsii+VaTLC7drG6FtW1TJELBLtsRLCmPyivVrWbrK6ENj9N8h7UOcSZpd2TWCG/SeAeetvtc5mi79Ok1jRhVtDNF+lsI6FKzT5F0Nqjcr1QRoKyQYXoBIFgDrYJuw0pef2Fxpn2OprJd43PaeUzwBdKrTRMl6xg9T2YdNDVK+Y0IjDWh5vN590ti7K855tqgoYo2/3rwgsp6a3AvyITrYortG6iCmNkMRIc1szrViYTvC890+cdUUNw5VqrefF5zrbF9tyzV8yTKW8tWuchLMr2GQ4ZNzHT5Y2vE5U3bakZrDVf6LpQYI1W5HZ5zxOHhQzQpvSjaHHY5ViDtzvH3vE7dfgeWBm5GO8P7xIzK7eN11jHcVhtDXBnsDIkclO+vPIiY18kE0+F3HLJKLLRXTPUqvgqMf19gA4zqiaJI11PpoxtdH3AHyzN7Kj0jBXGDG4F5cl3myJ1QrXv3d5YK0TpEse4Tlg+LnKxZGU8ePJru91T2tmgRb7Y6dy+VTKi+r1lMHkV2v199Oz6nfFUyc7GzcHhvM8024slpcHNi22ZpelyTWtEzWWHE/Tj1pqZDOOt/b3mbYTlfcLDY2s/agWsY2Pv00ZoV8+pYEv7r83Yv3uixibxT+CHM8M1NzIGgAXdOCrIRSJapQeGqppUJj42QS/WBQ==,iv:y6HKnzcG5fd+muvJ06NAF6IRR6MHzEP0Nfuk5SiLung=,tag:26txIqAHo5p8XEswWtJP3w==,type:str]", "sops": { "age": [ { @@ -27,8 +27,8 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtU240VjVRZmJ5TGsrclJF\nRXRLbTRCZURtR0Z3d2E2eDNNeGRDODlXVEY4CllTeVFYbDJQWlRSS1RFLzAxSnlM\nZi9NU1c3cWo3YWRLcUJ2U2ZFWFBBVEEKLS0tIGtmZU9qSWdBT3RDeStaaFFDSWtk\ndkUzZXJwZUl4LzVxYXdidmxXRnNnclUKyAMZqCKSY/RQvTR4bbjLaPnGKwdBcHXc\nvtiVSrLdIdzMa6id/J07TJH5UesUmcp0wjU41MDa4aMBLy+cXhuBHA==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2025-07-01T10:27:51Z", - "mac": "ENC[AES256_GCM,data:RyksomYlwuQTcCfmZqmxMMoanvIzu4FcJ+xlUjbBu9Kb/OU5cp8PJXdA78jY/58GOu9s3fkSD1wFewFrPTwtO8xry4Fvw8smr2wttvDS4c6nJ/9lg3Vab147JCEszqHLxghGV48tChvB2zfhpVy1LoF4y+vixMPIrlTFAw+ICzg=,iv:0LzxSmi8kCweETwQw9+UDpudZvJiTaT9UMLfmi990gQ=,tag:vl2y2f3G+Xn1fWwgkE7NfQ==,type:str]", + "lastmodified": "2025-07-02T12:38:20Z", + "mac": "ENC[AES256_GCM,data:BWXYSlrqB28us/6YghcLBkbC+HVCS9KTmnkutff4fhenldjqJkUXTDgHIyHmibeTE8bbuuypCi1xWlEykbQ0msYoz9X6MAe9MsE1HjcWUudLNNrZ8ae1Cs/vRLZfIgigwmLDkas9VL+5sTFnEpdiPbQ4Ov5GOtRUPm6HKTj9l9U=,iv:Z5dIjU0tz+efSjES7L/gIiwKHy53Xtb9K8huBmBwOag=,tag:IhVCdtC/3EdO+FRjCJKboQ==,type:str]", "pgp": [ { "created_at": "2025-06-13T20:13:06Z", diff --git a/secrets/winters/secrets.yaml b/secrets/winters/secrets.yaml index f59f8b7..b35d486 100644 --- a/secrets/winters/secrets.yaml +++ b/secrets/winters/secrets.yaml @@ -79,8 +79,8 @@ sops: MEZ1UWw3alF1WnJZMFZvMFBpbDFJZlUKGRnoEEgjgJ9SSblmldtY6d8MdAy01yxl qkvEIoXbL+ky2ira7EgjD0legThzCnmlXUlcSn3SpwbkAGgcfd2kWA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-06-28T23:22:53Z" - mac: ENC[AES256_GCM,data:qzxBlSs1thae4TAtkyLkR5l+vMZT/gB6q/NbrdRpv3jPKpn7JL/LLDXX4DjPuZJjDt3T95s9ZBzpasuGHwVNNesdtfj4wjepzwppsgxecSILmiqTUjZC6p1GnMp4TugeLoFBv5qjPYpmu67kwAO8R+gKn/hDhXeIWI4MjgVqsGg=,iv:Gk4vaDOM/lORN5ug96WncFQx972r+LHWTZeLE8Qh6wA=,tag:pSH6xAXJIAtr1bvBMsQ7QA==,type:str] + lastmodified: "2025-07-01T23:25:43Z" + mac: ENC[AES256_GCM,data:TS1UWyZGQ1zgzHGVlcWhWgWgo56zaSbhcB3KryS6Ya5clgyFt4vY0R4dC+uYnjmY1QCXAFPVLQU24ufKFDz94fEm0sQCPEWF2d1n156IpMce4wtCUqc0sXJOqTI3OA8ty91EWSUXTaapXEG2Pd9MSKr6XXpAVVbhzXKU1rFd1zc=,iv:xeOThqJ0tWUu55O8JAQMi0D6YzkrrHe7AshSATgpQ2U=,tag:VvtzsK1/06BD39bfQUr7Mg==,type:str] pgp: - created_at: "2024-12-17T16:24:32Z" enc: |- diff --git a/secrets/winters/secrets2.yaml b/secrets/winters/secrets2.yaml index c2d6037..92456e7 100644 --- a/secrets/winters/secrets2.yaml +++ b/secrets/winters/secrets2.yaml @@ -1,5 +1,7 @@ #ENC[AES256_GCM,data:K3S1LFrPmaS5,iv:dxFzPLhN2otgy02VWzrLURmomtYdoIBHvEJ1LJ7Lj9k=,tag:stKgkBnRDZkCPlvFk+btRg==,type:comment] radicale-user: ENC[AES256_GCM,data:2G+WXxw6jrnPXsI=,iv:bUEhBDrdTt+O/4TXMkhmqnzfkSiws4n7L54Z0zZnSOI=,tag:JGQPit5uGqITUyyCpU3OIg==,type:str] +#ENC[AES256_GCM,data:+7JEI2P/6/5yiWQ=,iv:hV4TyNFsyugrfFM0emxGDDDq54XWy7fVCf/kwD0mtCM=,tag:iZz9mPsLG02rlgV1vP8aBQ==,type:comment] +prometheus-admin-hash: ENC[AES256_GCM,data:dUmTW6W419TzF8dLGcgRLlbLBg9puzgznNCrrAuNOIuhXCBrqaJdtyIVFCsnrDSEh1ZdMfGki4UERZcf,iv:XIlb65V6yhrKSU7AbRs6k1ISljZjWnAm1dPTCONwDJI=,tag:UkdDTywivitSxYR902uM5A==,type:str] sops: age: - recipient: age1h72072slm2pthn9m2qwjsyy2dsazc6hz97kpzh4gksvv0r2jqecqul8w63 @@ -11,8 +13,8 @@ sops: ZWxwbGs1bTNzdXVNSzhpNWVESGJlUzQKzZr3cYBF6s5ihgW/6CreOKWvQpqITrFX pW6gwbRbxaxDPRRdfn8qswcezxq5AwOk9drbOH+qgcwL2owRGxEhcQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-06-28T23:22:45Z" - mac: ENC[AES256_GCM,data:gfvgF71vpP2NWy8GEYDffy6ZEI4xq2Pb+ydlmhAxuVtkVveVc3xOzJH+/IJ4IOh8s2ik/b5KMP1u2OdU7gZzDbAQvMn6t+1NN6wun2TLTMCf/z1KuJYEddYS1KHtKmyj+CS7cEZtaW5EKDrATZ9WJOlLY0IADIPicO6kwIqGQew=,iv:1Cg7Mp6GXL6Ade4KfZoHETYNNKojheQHNOlJh2+BCGg=,tag:CvLNFSAkiJDrLMYUldn36Q==,type:str] + lastmodified: "2025-07-01T23:26:55Z" + mac: ENC[AES256_GCM,data:YQtQicQAfEeB404BTZCZg7SSzVEw4ezlHw0ISoOHeOEBmlhS5441Mv6HrTWr47K+/aKvzcSdyl4dKclUzlgPoggWdJy7QHvFl4sm+iMuLP+3tAjLVJIudai/BAPNC4uFWEEXVUdlryPE/lX/I5ddCUoI2YfQV2gY2PlKXd2+cjs=,iv:PT3ZYJV/Kqet38FGrmG3jPNTkTYw2SJv0gwJGU4xP1A=,tag:gHdn6yojkAkusTumGMydlg==,type:str] pgp: - created_at: "2025-06-28T23:22:37Z" enc: |- diff --git a/templates/python/flake.nix b/templates/python/flake.nix index c7b3d74..6a2bd12 100644 --- a/templates/python/flake.nix +++ b/templates/python/flake.nix @@ -1,5 +1,4 @@ # based on https://github.com/pyproject-nix/uv2nix/tree/master/templates/hello-world - { description = "Python flake using uv2nix"; diff --git a/topology/default.nix b/topology/default.nix index a017167..5751ff6 100644 --- a/topology/default.nix +++ b/topology/default.nix @@ -53,7 +53,7 @@ in ] [ "wan" ] ]; - interfaces.wg0 = { + interfaces.wg = { addresses = [ "192.168.3.1" ]; network = "wg"; virtual = true; diff --git a/topology/images/ankisync.png b/topology/images/ankisync.png new file mode 100644 index 0000000..3a4432c Binary files /dev/null and b/topology/images/ankisync.png differ