diff --git a/config/basic/boot.nix b/config/basic/boot.nix index 3543b4f..1efda23 100644 --- a/config/basic/boot.nix +++ b/config/basic/boot.nix @@ -3,7 +3,8 @@ lib, pkgs, ... -}: { +}: +{ boot = lib.mkIf (!config.boot.isContainer) { initrd.systemd = { enable = true; @@ -11,12 +12,23 @@ extraBin.ip = "${pkgs.iproute}/bin/ip"; extraBin.cryptsetup = "${pkgs.cryptsetup}/bin/cryptsetup"; users.root.shell = "${pkgs.bashInteractive}/bin/bash"; - storePaths = ["${pkgs.bashInteractive}/bin/bash"]; + storePaths = [ "${pkgs.bashInteractive}/bin/bash" ]; }; - initrd.availableKernelModules = ["xhci_pci" "nvme" "r8169" "usb_storage" "usbhid" "sd_mod" "rtsx_pci_sdmmc" "ahci" "uas" "tpm_crb"]; - supportedFilesystems = ["ntfs"]; - kernelModules = ["kvm-intel"]; + initrd.availableKernelModules = [ + "xhci_pci" + "nvme" + "r8169" + "usb_storage" + "usbhid" + "sd_mod" + "rtsx_pci_sdmmc" + "ahci" + "uas" + "tpm_crb" + ]; + supportedFilesystems = [ "ntfs" ]; + kernelModules = [ "kvm-intel" ]; kernelParams = [ "rd.luks.options=timeout=0" "rootflags=x-systemd.device-timeout=0" diff --git a/config/basic/default.nix b/config/basic/default.nix index 21394bd..b56d230 100644 --- a/config/basic/default.nix +++ b/config/basic/default.nix @@ -1,8 +1,5 @@ +{ inputs, lib, ... }: { - inputs, - lib, - ... -}: { imports = [ ./boot.nix ./home-manager.nix @@ -37,6 +34,6 @@ inputs.nixos-nftables-firewall.nixosModules.default inputs.nixvim.nixosModules.nixvim ]; - age.identityPaths = ["/state/etc/ssh/ssh_host_ed25519_key"]; + age.identityPaths = [ "/state/etc/ssh/ssh_host_ed25519_key" ]; boot.mode = lib.mkDefault "efi"; } diff --git a/config/basic/home-manager.nix b/config/basic/home-manager.nix index 9569942..dfe9a2e 100644 --- a/config/basic/home-manager.nix +++ b/config/basic/home-manager.nix @@ -4,7 +4,8 @@ pkgs, nodes, ... -}: { +}: +{ imports = [ ../../modules-hm/impermanence.nix ../../modules-hm/images.nix @@ -18,9 +19,7 @@ spicePkgs = inputs.spicetify-nix.legacyPackages.${pkgs.system}; }; sharedModules = [ - { - home.stateVersion = stateVersion; - } + { home.stateVersion = stateVersion; } inputs.nix-index-database.hmModules.nix-index inputs.nixos-extra-modules.homeManagerModules.default inputs.nixvim.homeManagerModules.nixvim @@ -38,5 +37,5 @@ # But still link all completions from all packages so they # can be found by zsh - environment.pathsToLink = ["/share/zsh"]; + environment.pathsToLink = [ "/share/zsh" ]; } diff --git a/config/basic/impermanence.nix b/config/basic/impermanence.nix index 96634f2..c1c311a 100644 --- a/config/basic/impermanence.nix +++ b/config/basic/impermanence.nix @@ -3,35 +3,23 @@ lib, pkgs, ... -}: let - onlyHost = - lib.mkIf (!config.boot.isContainer); - prune = folder: - pkgs.writers.writePython3Bin "impermanence-prune" {} '' +}: +let + onlyHost = lib.mkIf (!config.boot.isContainer); + prune = + folder: + pkgs.writers.writePython3Bin "impermanence-prune" { } '' import os import sys mounts = [${ - lib.concatStringsSep ", " - ((map (x: - "\"" - + ( - if x.home != null - then x.home + "/" - else "" - ) - + x.directory - + "\"") - config.environment.persistence.${folder}.directories) - ++ (map (x: - "\"" - + ( - if x.home != null - then x.home + "/" - else "" - ) - + x.file - + "\"") - config.environment.persistence.${folder}.files)) + lib.concatStringsSep ", " ( + (map ( + x: "\"" + (if x.home != null then x.home + "/" else "") + x.directory + "\"" + ) config.environment.persistence.${folder}.directories) + ++ (map ( + x: "\"" + (if x.home != null then x.home + "/" else "") + x.file + "\"" + ) config.environment.persistence.${folder}.files) + ) }] # noqa: E501 mounts = [os.path.normpath(x) for x in mounts] mounts.sort() @@ -53,11 +41,10 @@ file=sys.stderr) print("\n".join(erg)) ''; -in { +in +{ # to allow all users to access hm managed persistent folders - lib.scripts.impermanence.pruneScripts = - lib.mapAttrs (k: _: prune k) - config.environment.persistence; + lib.scripts.impermanence.pruneScripts = lib.mapAttrs (k: _: prune k) config.environment.persistence; programs.fuse.userAllowOther = true; services.openssh.hostKeys = lib.mkForce [ { @@ -68,15 +55,10 @@ in { environment.persistence."/state" = { hideMounts = true; - files = - [ - "/etc/ssh/ssh_host_ed25519_key" - "/etc/ssh/ssh_host_ed25519_key.pub" - ] - ++ lib.lists.optionals (!config.boot.isContainer) - [ - "/etc/machine-id" - ]; + files = [ + "/etc/ssh/ssh_host_ed25519_key" + "/etc/ssh/ssh_host_ed25519_key.pub" + ] ++ lib.lists.optionals (!config.boot.isContainer) [ "/etc/machine-id" ]; directories = [ "/var/log" "/var/lib/systemd" @@ -93,22 +75,20 @@ in { }; environment.persistence."/persist" = { hideMounts = true; - directories = []; + directories = [ ]; }; fileSystems."/persist".neededForBoot = true; fileSystems."/state".neededForBoot = true; # After importing the rpool, rollback the root system to be empty. - boot.initrd.systemd.services.impermanence-root = - onlyHost - { - wantedBy = ["initrd.target"]; - after = ["zfs-import-rpool.service"]; - before = ["sysroot.mount"]; - unitConfig.DefaultDependencies = "no"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.zfs}/bin/zfs rollback -r rpool/local/root@blank"; - }; + boot.initrd.systemd.services.impermanence-root = onlyHost { + wantedBy = [ "initrd.target" ]; + after = [ "zfs-import-rpool.service" ]; + before = [ "sysroot.mount" ]; + unitConfig.DefaultDependencies = "no"; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.zfs}/bin/zfs rollback -r rpool/local/root@blank"; }; + }; } diff --git a/config/basic/net.nix b/config/basic/net.nix index a7e1485..a7712c4 100644 --- a/config/basic/net.nix +++ b/config/basic/net.nix @@ -1,17 +1,13 @@ +{ lib, config, ... }: { - lib, - config, - ... -}: { networking = { useNetworkd = true; dhcpcd.enable = false; useDHCP = false; # allow mdns port - firewall.allowedUDPPorts = [5353]; + firewall.allowedUDPPorts = [ 5353 ]; renameInterfacesByMac = lib.mkIf (!config.boot.isContainer) ( - lib.mapAttrs (_: v: v.mac) - (config.secrets.secrets.local.networking.interfaces or {}) + lib.mapAttrs (_: v: v.mac) (config.secrets.secrets.local.networking.interfaces or { }) ); }; systemd.network = { @@ -19,8 +15,8 @@ wait-online.anyInterface = true; }; system.nssDatabases.hosts = lib.mkMerge [ - (lib.mkBefore ["mdns_minimal [NOTFOUND=return]"]) - (lib.mkAfter ["mdns"]) + (lib.mkBefore [ "mdns_minimal [NOTFOUND=return]" ]) + (lib.mkAfter [ "mdns" ]) ]; services.resolved = { enable = true; diff --git a/config/basic/nftables.nix b/config/basic/nftables.nix index 0d0544e..768eba0 100644 --- a/config/basic/nftables.nix +++ b/config/basic/nftables.nix @@ -1,8 +1,5 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { networking.nftables = { stopRuleset = lib.mkDefault '' table inet filter { @@ -36,20 +33,31 @@ nnf-ssh.enable = true; nnf-icmp = { enable = true; - ipv6Types = ["echo-request" "destination-unreachable" "packet-too-big" "time-exceeded" "parameter-problem" "nd-router-advert" "nd-neighbor-solicit" "nd-neighbor-advert"]; - ipv4Types = ["echo-request" "destination-unreachable" "router-advertisement" "time-exceeded" "parameter-problem"]; + ipv6Types = [ + "echo-request" + "destination-unreachable" + "packet-too-big" + "time-exceeded" + "parameter-problem" + "nd-router-advert" + "nd-neighbor-solicit" + "nd-neighbor-advert" + ]; + ipv4Types = [ + "echo-request" + "destination-unreachable" + "router-advertisement" + "time-exceeded" + "parameter-problem" + ]; }; }; rules.untrusted-to-local = { - from = ["untrusted"]; - to = ["local"]; + from = [ "untrusted" ]; + to = [ "local" ]; - inherit - (config.networking.firewall) - allowedTCPPorts - allowedUDPPorts - ; + inherit (config.networking.firewall) allowedTCPPorts allowedUDPPorts; }; }; }; diff --git a/config/basic/nix.nix b/config/basic/nix.nix index 46e4efd..e4f8d55 100644 --- a/config/basic/nix.nix +++ b/config/basic/nix.nix @@ -1,14 +1,15 @@ +{ inputs, stateVersion, ... }: { - inputs, - stateVersion, - ... -}: { nix = { settings = { auto-optimise-store = true; - allowed-users = ["@wheel"]; - trusted-users = ["root"]; - system-features = ["recursive-nix" "repl-flake" "big-parallel"]; + allowed-users = [ "@wheel" ]; + trusted-users = [ "root" ]; + system-features = [ + "recursive-nix" + "repl-flake" + "big-parallel" + ]; substituters = [ "https://nix-community.cachix.org" "https://cache.nixos.org" @@ -24,7 +25,7 @@ cores = 0; max-jobs = "auto"; # make agenix rekey find the secrets even without trusted user - extra-sandbox-paths = ["/var/tmp/agenix-rekey?"]; + extra-sandbox-paths = [ "/var/tmp/agenix-rekey?" ]; }; daemonCPUSchedPolicy = "batch"; daemonIOSchedPriority = 5; @@ -34,7 +35,7 @@ experimental-features = nix-command flakes recursive-nix flake-registry = /etc/nix/registry.json ''; - nixPath = ["nixpkgs=/run/current-system/nixpkgs"]; + nixPath = [ "nixpkgs=/run/current-system/nixpkgs" ]; optimise.automatic = true; gc = { automatic = true; diff --git a/config/basic/ssh.nix b/config/basic/ssh.nix index 7704258..3358a14 100644 --- a/config/basic/ssh.nix +++ b/config/basic/ssh.nix @@ -1,4 +1,5 @@ -{lib, ...}: { +{ lib, ... }: +{ # Enable the OpenSSH daemon. services.openssh = { enable = true; diff --git a/config/basic/system.nix b/config/basic/system.nix index c36aae0..0098ffd 100644 --- a/config/basic/system.nix +++ b/config/basic/system.nix @@ -5,24 +5,24 @@ pkgs, config, ... -}: { +}: +{ system.stateVersion = stateVersion; age.rekey = { - inherit - (inputs.self.secretsConfig) - masterIdentities - extraEncryptionPubkeys - ; + inherit (inputs.self.secretsConfig) masterIdentities extraEncryptionPubkeys; storageMode = "derivation"; forceRekeyOnSystem = builtins.extraBuiltins.unsafeCurrentSystem; - hostPubkey = let - pubkeyPath = config.node.secretsDir + "/host.pub"; - in - lib.mkIf (lib.pathExists pubkeyPath || lib.trace "Missing pubkey for ${config.node.name}: ${toString pubkeyPath} not found, using dummy replacement key for now." false) - pubkeyPath; + hostPubkey = + let + pubkeyPath = config.node.secretsDir + "/host.pub"; + in + lib.mkIf ( + lib.pathExists pubkeyPath + || lib.trace "Missing pubkey for ${config.node.name}: ${toString pubkeyPath} not found, using dummy replacement key for now." false + ) pubkeyPath; generatedSecretsDir = config.node.secretsDir + "/generated/"; cacheDir = "/var/tmp/agenix-rekey/\"$UID\""; }; @@ -38,16 +38,16 @@ # to create a link called /run/agenix. Agenix should probably fail in this case, # but doesn't and instead puts the generation link into the existing directory. # TODO See https://github.com/ryantm/agenix/pull/187. - system.activationScripts = lib.mkIf (config.age.secrets != {}) { + system.activationScripts = lib.mkIf (config.age.secrets != { }) { removeAgenixLink.text = "[[ ! -L /run/agenix ]] && [[ -d /run/agenix ]] && rm -rf /run/agenix"; - agenixNewGeneration.deps = ["removeAgenixLink"]; + agenixNewGeneration.deps = [ "removeAgenixLink" ]; }; time.timeZone = lib.mkDefault "Europe/Berlin"; i18n.defaultLocale = "C.UTF-8"; console = { font = "${pkgs.terminus_font}/share/consolefonts/ter-v28n.psf.gz"; - packages = with pkgs; [terminus_font]; + packages = with pkgs; [ terminus_font ]; useXkbConfig = true; # use xkbOptions in tty. keyMap = lib.mkDefault "de-latin1-nodeadkeys"; }; @@ -71,11 +71,12 @@ powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; - secrets.secretFiles = let - local = config.node.secretsDir + "/secrets.nix.age"; - in + secrets.secretFiles = + let + local = config.node.secretsDir + "/secrets.nix.age"; + in { global = ../../secrets/secrets.nix.age; } - // lib.optionalAttrs (config.node.name != null && lib.pathExists local) {inherit local;}; + // lib.optionalAttrs (config.node.name != null && lib.pathExists local) { inherit local; }; } diff --git a/config/basic/users.nix b/config/basic/users.nix index e4dd4b4..87d1e94 100644 --- a/config/basic/users.nix +++ b/config/basic/users.nix @@ -1,49 +1,51 @@ { users.mutableUsers = false; - users.deterministicIds = let - uidGid = id: { - uid = id; - gid = id; + users.deterministicIds = + let + uidGid = id: { + uid = id; + gid = id; + }; + in + { + nscd = uidGid 201; + sshd = uidGid 202; + tss = uidGid 203; + rtkit = uidGid 204; + nixseparatedebuginfod = uidGid 205; + wireshark = uidGid 206; + polkituser = uidGid 207; + msr = uidGid 208; + avahi = uidGid 209; + fwupd-refresh = uidGid 210; + podman = uidGid 211; + acme = uidGid 212; + nextcloud = uidGid 213; + redis-nextcloud = uidGid 214; + radicale = uidGid 215; + git = uidGid 215; + vaultwarden = uidGid 215; + redis-paperless = uidGid 216; + microvm = uidGid 217; + maddy = uidGid 218; + tt_rss = uidGid 219; + freshrss = uidGid 220; + mongodb = uidGid 221; + authelia-main = uidGid 222; + kanidm = uidGid 223; + oauth2-proxy = uidGid 224; + influxdb2 = uidGid 225; + firefly-iii = uidGid 226; + paperless = uidGid 315; + systemd-oom = uidGid 300; + systemd-coredump = uidGid 301; + patrick = uidGid 1000; + smb = uidGid 2000; + david = uidGid 2004; + helen = uidGid 2001; + ggr = uidGid 2002; + family = uidGid 2003; + printer = uidGid 2005; + pr-tracker = uidGid 2006; }; - in { - nscd = uidGid 201; - sshd = uidGid 202; - tss = uidGid 203; - rtkit = uidGid 204; - nixseparatedebuginfod = uidGid 205; - wireshark = uidGid 206; - polkituser = uidGid 207; - msr = uidGid 208; - avahi = uidGid 209; - fwupd-refresh = uidGid 210; - podman = uidGid 211; - acme = uidGid 212; - nextcloud = uidGid 213; - redis-nextcloud = uidGid 214; - radicale = uidGid 215; - git = uidGid 215; - vaultwarden = uidGid 215; - redis-paperless = uidGid 216; - microvm = uidGid 217; - maddy = uidGid 218; - tt_rss = uidGid 219; - freshrss = uidGid 220; - mongodb = uidGid 221; - authelia-main = uidGid 222; - kanidm = uidGid 223; - oauth2-proxy = uidGid 224; - influxdb2 = uidGid 225; - firefly-iii = uidGid 226; - paperless = uidGid 315; - systemd-oom = uidGid 300; - systemd-coredump = uidGid 301; - patrick = uidGid 1000; - smb = uidGid 2000; - david = uidGid 2004; - helen = uidGid 2001; - ggr = uidGid 2002; - family = uidGid 2003; - printer = uidGid 2005; - pr-tracker = uidGid 2006; - }; } diff --git a/config/hardware/bluetooth.nix b/config/hardware/bluetooth.nix index 1a6e458..d55dab6 100644 --- a/config/hardware/bluetooth.nix +++ b/config/hardware/bluetooth.nix @@ -1,10 +1,11 @@ -{pkgs, ...}: { - environment.systemPackages = with pkgs; [bluetuith]; +{ pkgs, ... }: +{ + environment.systemPackages = with pkgs; [ bluetuith ]; hardware.bluetooth = { enable = true; powerOnBoot = false; - disabledPlugins = ["sap"]; + disabledPlugins = [ "sap" ]; settings = { General = { FastConnectable = "true"; @@ -16,15 +17,13 @@ }; hardware.pulseaudio = { - package = pkgs.pulseaudio.override {bluetoothSupport = true;}; + package = pkgs.pulseaudio.override { bluetoothSupport = true; }; extraConfig = '' load-module module-bluetooth-discover load-module module-bluetooth-policy load-module module-switch-on-connect ''; - extraModules = with pkgs; [pulseaudio-modules-bt]; + extraModules = with pkgs; [ pulseaudio-modules-bt ]; }; - environment.persistence."/state".directories = [ - "/var/lib/bluetooth" - ]; + environment.persistence."/state".directories = [ "/var/lib/bluetooth" ]; } diff --git a/config/hardware/nintendo.nix b/config/hardware/nintendo.nix index 44466ea..a7067fc 100644 --- a/config/hardware/nintendo.nix +++ b/config/hardware/nintendo.nix @@ -1,3 +1 @@ -{ - services.joycond.enable = true; -} +{ services.joycond.enable = true; } diff --git a/config/hardware/nvidia.nix b/config/hardware/nvidia.nix index 9191bdb..c3523d7 100644 --- a/config/hardware/nvidia.nix +++ b/config/hardware/nvidia.nix @@ -5,7 +5,7 @@ ... }: lib.optionalAttrs (!minimal) { - services.xserver.videoDrivers = lib.mkForce ["nvidia"]; + services.xserver.videoDrivers = lib.mkForce [ "nvidia" ]; hardware = { graphics = { diff --git a/config/hardware/physical.nix b/config/hardware/physical.nix index 5eb7123..29558d3 100644 --- a/config/hardware/physical.nix +++ b/config/hardware/physical.nix @@ -1,5 +1,6 @@ # Configuration for actual physical machines -{config, ...}: { +{ config, ... }: +{ hardware = { enableRedistributableFirmware = true; enableAllFirmware = true; @@ -8,6 +9,6 @@ services = { fwupd.enable = true; smartd.enable = true; - thermald.enable = builtins.elem config.nixpkgs.hostPlatform.system ["x86_64-linux"]; + thermald.enable = builtins.elem config.nixpkgs.hostPlatform.system [ "x86_64-linux" ]; }; } diff --git a/config/hardware/pipewire.nix b/config/hardware/pipewire.nix index 9117e8b..fc17069 100644 --- a/config/hardware/pipewire.nix +++ b/config/hardware/pipewire.nix @@ -13,7 +13,10 @@ lib.optionalAttrs (!minimal) { # packages = pkgs.linuxPackages_6_6_rt; # }; #}; - environment.systemPackages = with pkgs; [pulseaudio pulsemixer]; + environment.systemPackages = with pkgs; [ + pulseaudio + pulsemixer + ]; hardware.pulseaudio.enable = lib.mkForce false; security.rtkit.enable = true; diff --git a/config/hardware/yubikey.nix b/config/hardware/yubikey.nix index 8c11869..8e2fd4a 100644 --- a/config/hardware/yubikey.nix +++ b/config/hardware/yubikey.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ environment.systemPackages = with pkgs; [ yubikey-personalization yubikey-manager @@ -7,5 +8,8 @@ services.pcscd.enable = true; - services.udev.packages = with pkgs; [yubikey-personalization libu2f-host]; + services.udev.packages = with pkgs; [ + yubikey-personalization + libu2f-host + ]; } diff --git a/config/optional/graphical.nix b/config/optional/graphical.nix index 24d8661..0968b2b 100644 --- a/config/optional/graphical.nix +++ b/config/optional/graphical.nix @@ -4,13 +4,11 @@ pkgs, lib, ... -}: let - inherit - (lib) - mkOption - types - ; -in { +}: +let + inherit (lib) mkOption types; +in +{ options.hidpi = mkOption { default = false; type = types.bool; @@ -18,14 +16,10 @@ in { }; # stylix acceses stylix options on import meaning you can only import this module when you're actually setting stylix options - imports = [ - inputs.stylix.nixosModules.stylix - ]; + imports = [ inputs.stylix.nixosModules.stylix ]; config = { - environment.systemPackages = with pkgs; [ - xdg-utils - ]; + environment.systemPackages = with pkgs; [ xdg-utils ]; xdg.portal = { xdgOpenUsePortal = true; enable = true; @@ -38,13 +32,11 @@ in { "gtk" "hyprland" ]; - sway.default = [ - "wlr" - ]; + sway.default = [ "wlr" ]; }; }; # needed for gnome pinentry - services.dbus.packages = [pkgs.gcr]; + services.dbus.packages = [ pkgs.gcr ]; fonts = { enableGhostscriptFonts = false; fontDir.enable = false; @@ -75,7 +67,7 @@ in { ''; }; packages = with pkgs; [ - (nerdfonts.override {fonts = ["FiraCode"];}) + (nerdfonts.override { fonts = [ "FiraCode" ]; }) ibm-plex dejavu_fonts unifont @@ -160,71 +152,73 @@ in { }; home-manager.sharedModules = [ - ({ - pkgs, - config, - nixosConfig, - ... - }: { - stylix = { - cursor = { - package = pkgs.openzone-cursors; - name = "OpenZone_White_Slim"; - size = - if nixosConfig.hidpi - then 48 - else 18; - }; - inherit (nixosConfig.stylix) polarity; - targets = { - gtk.enable = true; - bat.enable = true; - dunst.enable = true; - zathura.enable = true; - xresources.enable = true; - }; - }; - - xresources.properties = { - "Xft.hinting" = true; - "Xft.antialias" = true; - "Xft.autohint" = false; - "Xft.lcdfilter" = "lcddefault"; - "Xft.hintstyle" = "hintfull"; - "Xft.rgba" = "rgb"; - }; - - gtk = let - gtk34extraConfig = { - gtk-application-prefer-dark-theme = 1; - gtk-cursor-theme-size = 18; - gtk-enable-animations = true; - gtk-xft-antialias = 1; - gtk-xft-dpi = 96; # XXX: delete for wayland? - gtk-xft-hinting = 1; - gtk-xft-hintstyle = "hintfull"; - gtk-xft-rgba = "rgb"; - }; - in { - enable = true; - iconTheme = { - name = "Vimix-Doder"; - package = pkgs.vimix-icon-theme; + ( + { + pkgs, + config, + nixosConfig, + ... + }: + { + stylix = { + cursor = { + package = pkgs.openzone-cursors; + name = "OpenZone_White_Slim"; + size = if nixosConfig.hidpi then 48 else 18; + }; + inherit (nixosConfig.stylix) polarity; + targets = { + gtk.enable = true; + bat.enable = true; + dunst.enable = true; + zathura.enable = true; + xresources.enable = true; + }; }; - gtk2.extraConfig = "gtk-application-prefer-dark-theme = true"; - gtk3.extraConfig = gtk34extraConfig; - gtk4.extraConfig = gtk34extraConfig; - }; + xresources.properties = { + "Xft.hinting" = true; + "Xft.antialias" = true; + "Xft.autohint" = false; + "Xft.lcdfilter" = "lcddefault"; + "Xft.hintstyle" = "hintfull"; + "Xft.rgba" = "rgb"; + }; - home.sessionVariables.GTK_THEME = config.gtk.theme.name; + gtk = + let + gtk34extraConfig = { + gtk-application-prefer-dark-theme = 1; + gtk-cursor-theme-size = 18; + gtk-enable-animations = true; + gtk-xft-antialias = 1; + gtk-xft-dpi = 96; # XXX: delete for wayland? + gtk-xft-hinting = 1; + gtk-xft-hintstyle = "hintfull"; + gtk-xft-rgba = "rgb"; + }; + in + { + enable = true; + iconTheme = { + name = "Vimix-Doder"; + package = pkgs.vimix-icon-theme; + }; - qt = { - enable = true; - platformTheme.name = "adwaita"; - style.name = "Adwaita-Dark"; - }; - }) + gtk2.extraConfig = "gtk-application-prefer-dark-theme = true"; + gtk3.extraConfig = gtk34extraConfig; + gtk4.extraConfig = gtk34extraConfig; + }; + + home.sessionVariables.GTK_THEME = config.gtk.theme.name; + + qt = { + enable = true; + platformTheme.name = "adwaita"; + style.name = "Adwaita-Dark"; + }; + } + ) ]; }; } diff --git a/config/optional/initrd-ssh.nix b/config/optional/initrd-ssh.nix index ae7bf26..a22e0bb 100644 --- a/config/optional/initrd-ssh.nix +++ b/config/optional/initrd-ssh.nix @@ -1,8 +1,5 @@ +{ config, pkgs, ... }: { - config, - pkgs, - ... -}: { age.secrets.initrd_host_ed25519_key.generator.script = "ssh-ed25519"; boot.initrd.network.enable = true; @@ -14,7 +11,7 @@ # need two activations to change as well as that to enable this # module you need to set hostKeys to a dummy value and generate # and invalid initrd once - hostKeys = [config.age.secrets.initrd_host_ed25519_key.path]; + hostKeys = [ config.age.secrets.initrd_host_ed25519_key.path ]; }; # Make sure that there is always a valid initrd hostkey available that can be installed into @@ -30,7 +27,10 @@ ${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f "${config.age.secrets.initrd_host_ed25519_key.path}" fi ''; - deps = ["agenixInstall" "users"]; + deps = [ + "agenixInstall" + "users" + ]; }; - system.activationScripts.agenixChown.deps = ["agenixEnsureInitrdHostkey"]; + system.activationScripts.agenixChown.deps = [ "agenixEnsureInitrdHostkey" ]; } diff --git a/config/optional/printing.nix b/config/optional/printing.nix index 17ee20f..8847e4e 100644 --- a/config/optional/printing.nix +++ b/config/optional/printing.nix @@ -1,7 +1,11 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ services.printing = { enable = true; - drivers = [pkgs.hplipWithPlugin pkgs.hplip]; + drivers = [ + pkgs.hplipWithPlugin + pkgs.hplip + ]; }; environment.persistence."/state".directories = [ { diff --git a/config/optional/secureboot.nix b/config/optional/secureboot.nix index 088eb1a..085aa7b 100644 --- a/config/optional/secureboot.nix +++ b/config/optional/secureboot.nix @@ -8,10 +8,7 @@ lib.optionalAttrs (!minimal) { environment.systemPackages = [ # For debugging and troubleshooting Secure Boot. - (pkgs.sbctl.override - { - databasePath = "/run/secureboot"; - }) + (pkgs.sbctl.override { databasePath = "/run/secureboot"; }) ]; age.secrets.secureboot.rekeyFile = ../../hosts/${config.node.name}/secrets/secureboot.tar.age; system.activationScripts.securebootuntar = { @@ -21,7 +18,7 @@ lib.optionalAttrs (!minimal) { chmod 700 /run/secureboot ${pkgs.gnutar}/bin/tar xf ${config.age.secrets.secureboot.path} -C /run/secureboot || true ''; - deps = ["agenix"]; + deps = [ "agenix" ]; }; # Lanzaboote currently replaces the systemd-boot module. diff --git a/config/optional/steam.nix b/config/optional/steam.nix index 02818f3..618fad2 100644 --- a/config/optional/steam.nix +++ b/config/optional/steam.nix @@ -8,8 +8,8 @@ lib.optionalAttrs (!minimal) { programs.steam = { enable = true; package = pkgs.steam.override { - extraPkgs = pkgs: - with pkgs; [ + extraPkgs = + pkgs: with pkgs; [ # vampir überlebende braucht diese pkgs libgdiplus cups diff --git a/config/optional/wayland.nix b/config/optional/wayland.nix index a5a4ff1..3514f33 100644 --- a/config/optional/wayland.nix +++ b/config/optional/wayland.nix @@ -14,10 +14,10 @@ lib.optionalAttrs (!minimal) { enable = true; xdgOpenUsePortal = true; config.common = { - "org.freedesktop.impl.portal.Secret" = ["gnome-keyring"]; - "org.freedesktop.impl.portal.ScreenCast" = ["hyprland"]; - "org.freedesktop.impl.portal.Screenshot" = ["hyprland"]; - "org.freedesktop.portal.FileChooser" = ["xdg-desktop-portal-gtk"]; + "org.freedesktop.impl.portal.Secret" = [ "gnome-keyring" ]; + "org.freedesktop.impl.portal.ScreenCast" = [ "hyprland" ]; + "org.freedesktop.impl.portal.Screenshot" = [ "hyprland" ]; + "org.freedesktop.portal.FileChooser" = [ "xdg-desktop-portal-gtk" ]; }; extraPortals = [ pkgs.xdg-desktop-portal-hyprland diff --git a/config/optional/xserver.nix b/config/optional/xserver.nix index b095b9e..cbacbbe 100644 --- a/config/optional/xserver.nix +++ b/config/optional/xserver.nix @@ -12,7 +12,7 @@ lib.optionalAttrs (!minimal) { displayManager.startx.enable = true; autoRepeatDelay = 235; autoRepeatInterval = 60; - videoDrivers = ["modesetting"]; + videoDrivers = [ "modesetting" ]; }; services.libinput = { enable = true; @@ -28,10 +28,9 @@ lib.optionalAttrs (!minimal) { disableWhileTyping = true; }; }; - services.udev.extraRules = let - exe = - pkgs.writeShellScript "set-key-repeat" - '' + services.udev.extraRules = + let + exe = pkgs.writeShellScript "set-key-repeat" '' if [ -d "/tmp/.X11-unix" ]; then for D in /tmp/.X11-unix/*; do file=$(${pkgs.coreutils}/bin/basename $D) @@ -43,7 +42,8 @@ lib.optionalAttrs (!minimal) { done fi ''; - in '' - ACTION=="add", SUBSYSTEM=="input", ATTRS{bInterfaceClass}=="03", RUN+="${exe}" - ''; + in + '' + ACTION=="add", SUBSYSTEM=="input", ATTRS{bInterfaceClass}=="03", RUN+="${exe}" + ''; } diff --git a/config/optional/zfs.nix b/config/optional/zfs.nix index 0f14120..7dc568c 100644 --- a/config/optional/zfs.nix +++ b/config/optional/zfs.nix @@ -3,15 +3,16 @@ config, lib, ... -}: { - boot.supportedFilesystems = ["zfs"]; +}: +{ + boot.supportedFilesystems = [ "zfs" ]; boot.kernelPackages = lib.mkDefault config.boot.zfs.package.latestCompatibleLinuxPackages; # The root pool should never be imported forcefully. # Failure to import is important to notice! boot.zfs.forceImportRoot = false; - environment.systemPackages = with pkgs; [zfs]; + environment.systemPackages = with pkgs; [ zfs ]; # Might help with hangs mainly atuin #boot.kernelPatches = [ @@ -40,5 +41,5 @@ }; }; # TODO remove once this is upstreamed - boot.initrd.systemd.services."zfs-import-rpool".after = ["cryptsetup.target"]; + boot.initrd.systemd.services."zfs-import-rpool".after = [ "cryptsetup.target" ]; } diff --git a/config/services/actual.nix b/config/services/actual.nix index 752269b..596e861 100644 --- a/config/services/actual.nix +++ b/config/services/actual.nix @@ -1,16 +1,12 @@ { wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [3000]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ]; }; - imports = [../actual.nix]; + imports = [ ../actual.nix ]; services.actual = { enable = true; settings.port = 3000; }; - environment.persistence."/persist".directories = [ - { - directory = "/var/lib/private/actual"; - } - ]; + environment.persistence."/persist".directories = [ { directory = "/var/lib/private/actual"; } ]; } diff --git a/config/services/adguardhome.nix b/config/services/adguardhome.nix index d2ff93b..93c56cf 100644 --- a/config/services/adguardhome.nix +++ b/config/services/adguardhome.nix @@ -1,11 +1,8 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [config.services.adguardhome.port]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.adguardhome.port ]; }; services.adguardhome = { enable = true; @@ -16,8 +13,12 @@ settings = { dns = { bind_hosts = [ - (lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv4) - (lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv6) + (lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} + config.secrets.secrets.global.net.privateSubnetv4 + ) + (lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} + config.secrets.secrets.global.net.privateSubnetv6 + ) ]; anonymize_client_ip = false; upstream_dns = [ @@ -61,8 +62,8 @@ }; }; networking.firewall = { - allowedTCPPorts = [53]; - allowedUDPPorts = [53]; + allowedTCPPorts = [ 53 ]; + allowedUDPPorts = [ 53 ]; }; environment.persistence."/persist".directories = [ { diff --git a/config/services/ddclient.nix b/config/services/ddclient.nix index ec60aa1..754e8e9 100644 --- a/config/services/ddclient.nix +++ b/config/services/ddclient.nix @@ -1,4 +1,5 @@ -{config, ...}: { +{ config, ... }: +{ age.secrets.cloudflare_token_dns = { rekeyFile = config.node.secretsDir + "/cloudflare_api_token.age"; mode = "440"; @@ -13,6 +14,6 @@ usev4 = "webv4, webv4='https://cloudflare.com/cdn-cgi/trace', webv4-skip='ip='"; usev6 = ""; passwordFile = config.age.secrets.cloudflare_token_dns.path; - domains = [config.secrets.secrets.global.domains.web]; + domains = [ config.secrets.secrets.global.domains.web ]; }; } diff --git a/config/services/firefly.nix b/config/services/firefly.nix index 9544c12..3a531d3 100644 --- a/config/services/firefly.nix +++ b/config/services/firefly.nix @@ -1,12 +1,9 @@ +{ config, nodes, ... }: { - config, - nodes, - ... -}: { - i18n.supportedLocales = ["all"]; + i18n.supportedLocales = [ "all" ]; wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [80]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ]; }; age.secrets.appKey = { diff --git a/config/services/forgejo.nix b/config/services/forgejo.nix index 12a6862..5c5bb3c 100644 --- a/config/services/forgejo.nix +++ b/config/services/forgejo.nix @@ -4,9 +4,11 @@ pkgs, lib, ... -}: let +}: +let forgejoDomain = "forge.${config.secrets.secrets.global.domains.web}"; -in { +in +{ age.secrets.resticpasswd = { generator.script = "alnum"; }; @@ -29,7 +31,7 @@ in { inherit (config.secrets.secrets.global.hetzner.users.forgejo) subUid path; sshAgeSecret = "forgejoHetznerSsh"; }; - paths = [config.services.forgejo.stateDir]; + paths = [ config.services.forgejo.stateDir ]; pruneOpts = [ "--keep-daily 10" "--keep-weekly 7" @@ -42,7 +44,7 @@ in { # Recommended by forgejo: https://forgejo.org/docs/latest/admin/recommendations/#git-over-ssh services.openssh.settings.AcceptEnv = "GIT_PROTOCOL"; - users.groups.git = {}; + users.groups.git = { }; users.users.git = { isSystemUser = true; useDefaultShell = true; @@ -52,9 +54,11 @@ in { wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [config.services.forgejo.settings.server.HTTP_PORT]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ + config.services.forgejo.settings.server.HTTP_PORT + ]; }; - networking.firewall.allowedTCPPorts = [config.services.forgejo.settings.server.SSH_PORT]; + networking.firewall.allowedTCPPorts = [ config.services.forgejo.settings.server.SSH_PORT ]; environment.persistence."/panzer".directories = [ { @@ -145,30 +149,31 @@ in { # see https://github.com/go-gitea/gitea/issues/21376. systemd.services.forgejo = { serviceConfig.RestartSec = "60"; # Retry every minute - preStart = let - exe = lib.getExe config.services.forgejo.package; - providerName = "kanidm"; - clientId = "forgejo"; - args = lib.escapeShellArgs [ - "--name" - providerName - "--provider" - "openidConnect" - "--key" - clientId - "--auto-discover-url" - "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/${clientId}/.well-known/openid-configuration" - "--scopes" - "email" - "--scopes" - "profile" - "--group-claim-name" - "groups" - "--admin-group" - "admin" - "--skip-local-2fa" - ]; - in + preStart = + let + exe = lib.getExe config.services.forgejo.package; + providerName = "kanidm"; + clientId = "forgejo"; + args = lib.escapeShellArgs [ + "--name" + providerName + "--provider" + "openidConnect" + "--key" + clientId + "--auto-discover-url" + "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/${clientId}/.well-known/openid-configuration" + "--scopes" + "email" + "--scopes" + "profile" + "--group-claim-name" + "groups" + "--admin-group" + "admin" + "--skip-local-2fa" + ]; + in lib.mkAfter '' provider_id=$(${exe} admin auth list | ${pkgs.gnugrep}/bin/grep -w '${providerName}' | cut -f1) SECRET="$(< ${config.age.secrets.openid-secret.path})" diff --git a/config/services/homebox.nix b/config/services/homebox.nix index ebde44b..bf1eb2d 100644 --- a/config/services/homebox.nix +++ b/config/services/homebox.nix @@ -1,8 +1,8 @@ { - imports = [../../modules/homebox.nix]; + imports = [ ../../modules/homebox.nix ]; wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [3000]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ]; }; services.homebox = { enable = true; diff --git a/config/services/immich.nix b/config/services/immich.nix index fefd138..f67c7a5 100644 --- a/config/services/immich.nix +++ b/config/services/immich.nix @@ -4,7 +4,8 @@ nodes, config, ... -}: let +}: +let version = "v1.106.4"; immichDomain = "immich.${config.secrets.secrets.global.domains.web}"; @@ -136,21 +137,14 @@ serviceConfig = { Restart = "always"; }; - after = [ - "podman-network-immich-default.service" - ]; - requires = [ - "podman-network-immich-default.service" - ]; - partOf = [ - "podman-compose-immich-root.target" - ]; - wantedBy = [ - "podman-compose-immich-root.target" - ]; + after = [ "podman-network-immich-default.service" ]; + requires = [ "podman-network-immich-default.service" ]; + partOf = [ "podman-compose-immich-root.target" ]; + wantedBy = [ "podman-compose-immich-root.target" ]; }; processedConfigFile = "/run/agenix/immich.config.json"; -in { +in +{ age.secrets.resticpasswd = { generator.script = "alnum"; }; @@ -206,7 +200,7 @@ in { system.activationScripts.agenixRooterDerivedSecrets = { # Run after agenix has generated secrets - deps = ["agenix"]; + deps = [ "agenix" ]; text = '' immichClientSecret=$(< ${config.age.secrets.immich-oauth2-client-secret.path}) ${pkgs.jq}/bin/jq --arg immichClientSecret "$immichClientSecret" '.oauth.clientSecret = $immichClientSecret' ${configFile} > ${processedConfigFile} @@ -221,11 +215,11 @@ in { wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [3000]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ]; }; networking.nftables.chains.forward.into-immich-container = { - after = ["conntrack"]; + after = [ "conntrack" ]; rules = [ "iifname elisabeth ip saddr ${nodes.elisabeth.config.wireguard.elisabeth.ipv4} tcp dport 3001 accept" "iifname podman1 oifname lan accept" @@ -313,9 +307,7 @@ in { "${upload_folder}:/usr/src/app/upload:rw" "${environment.DB_PASSWORD_FILE}:${environment.DB_PASSWORD_FILE}:ro" ]; - ports = [ - "3000:3001/tcp" - ]; + ports = [ "3000:3001/tcp" ]; dependsOn = [ "immich_postgres" "immich_redis" @@ -327,18 +319,16 @@ in { "--ip=${ipImmichServer}" ]; }; - systemd.services."podman-immich_server" = - serviceConfig - // { - unitConfig.UpheldBy = [ - "podman-immich_postgres.service" - "podman-immich_redis.service" - ]; - }; + systemd.services."podman-immich_server" = serviceConfig // { + unitConfig.UpheldBy = [ + "podman-immich_postgres.service" + "podman-immich_redis.service" + ]; + }; # Networks systemd.services."podman-network-immich-default" = { - path = [pkgs.podman]; + path = [ pkgs.podman ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; @@ -347,8 +337,8 @@ in { script = '' podman network inspect immich-default || podman network create immich-default --opt isolate=true --disable-dns --subnet=10.89.0.0/24 ''; - partOf = ["podman-compose-immich-root.target"]; - wantedBy = ["podman-compose-immich-root.target"]; + partOf = [ "podman-compose-immich-root.target" ]; + wantedBy = [ "podman-compose-immich-root.target" ]; }; # Root service @@ -358,6 +348,6 @@ in { unitConfig = { Description = "Root target generated by compose2nix."; }; - wantedBy = ["multi-user.target"]; + wantedBy = [ "multi-user.target" ]; }; } diff --git a/config/services/kanidm.nix b/config/services/kanidm.nix index 0ba0fa4..0b5f39b 100644 --- a/config/services/kanidm.nix +++ b/config/services/kanidm.nix @@ -1,12 +1,14 @@ -{config, ...}: let +{ config, ... }: +let kanidmdomain = "auth.${config.secrets.secrets.global.domains.web}"; -in { - imports = [../../modules/kanidm.nix]; +in +{ + imports = [ ../../modules/kanidm.nix ]; wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [3000]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ]; }; - disabledModules = ["services/security/kanidm.nix"]; + disabledModules = [ "services/security/kanidm.nix" ]; environment.persistence."/persist".directories = [ { directory = "/var/lib/kanidm"; @@ -74,42 +76,50 @@ in { inherit (config.secrets.secrets.local.kanidm) persons; groups."paperless.access" = { - members = ["paperless.admins"]; + members = [ "paperless.admins" ]; }; # currently not usable groups."paperless.admins" = { - members = ["administrator"]; + members = [ "administrator" ]; }; systems.oauth2.paperless = { displayName = "paperless"; originUrl = "https://ppl.${config.secrets.secrets.global.domains.web}/"; basicSecretFile = config.age.secrets.oauth2-paperless.path; - scopeMaps."paperless.access" = ["openid" "email" "profile"]; + scopeMaps."paperless.access" = [ + "openid" + "email" + "profile" + ]; preferShortUsername = true; }; groups."nextcloud.access" = { - members = ["nextcloud.admins"]; + members = [ "nextcloud.admins" ]; }; # currently not usable groups."nextcloud.admins" = { - members = ["administrator"]; + members = [ "administrator" ]; }; systems.oauth2.nextcloud = { displayName = "nextcloud"; originUrl = "https://nc.${config.secrets.secrets.global.domains.web}/"; basicSecretFile = config.age.secrets.oauth2-nextcloud.path; allowInsecureClientDisablePkce = true; - scopeMaps."nextcloud.access" = ["openid" "email" "profile"]; + scopeMaps."nextcloud.access" = [ + "openid" + "email" + "profile" + ]; preferShortUsername = true; }; groups."immich.access" = { - members = ["immich.admins"]; + members = [ "immich.admins" ]; }; # currently not usable groups."immich.admins" = { - members = ["administrator"]; + members = [ "administrator" ]; }; systems.oauth2.immich = { displayName = "Immich"; @@ -117,57 +127,84 @@ in { basicSecretFile = config.age.secrets.oauth2-immich.path; allowInsecureClientDisablePkce = true; enableLegacyCrypto = true; - scopeMaps."immich.access" = ["openid" "email" "profile"]; + scopeMaps."immich.access" = [ + "openid" + "email" + "profile" + ]; preferShortUsername = true; }; - groups."rss.access" = {}; - groups."firefly.access" = {}; - groups."ollama.access" = {}; - groups."adguardhome.access" = {}; - groups."octoprint.access" = {}; + groups."rss.access" = { }; + groups."firefly.access" = { }; + groups."ollama.access" = { }; + groups."adguardhome.access" = { }; + groups."octoprint.access" = { }; systems.oauth2.oauth2-proxy = { displayName = "Oauth2-Proxy"; originUrl = "https://oauth2.${config.secrets.secrets.global.domains.web}/"; basicSecretFile = config.age.secrets.oauth2-proxy.path; - scopeMaps."adguardhome.access" = ["openid" "email" "profile"]; - scopeMaps."rss.access" = ["openid" "email" "profile"]; - scopeMaps."firefly.access" = ["openid" "email" "profile"]; - scopeMaps."ollama.access" = ["openid" "email" "profile"]; - scopeMaps."octoprint.access" = ["openid" "email" "profile"]; + scopeMaps."adguardhome.access" = [ + "openid" + "email" + "profile" + ]; + scopeMaps."rss.access" = [ + "openid" + "email" + "profile" + ]; + scopeMaps."firefly.access" = [ + "openid" + "email" + "profile" + ]; + scopeMaps."ollama.access" = [ + "openid" + "email" + "profile" + ]; + scopeMaps."octoprint.access" = [ + "openid" + "email" + "profile" + ]; preferShortUsername = true; claimMaps.groups = { joinType = "array"; - valuesByGroup."adguardhome.access" = ["adguardhome_access"]; - valuesByGroup."rss.access" = ["ttrss_access"]; - valuesByGroup."firefly.access" = ["firefly_access"]; - valuesByGroup."ollama.access" = ["ollama_access"]; - valuesByGroup."octoprint.access" = ["octoprint_access"]; + valuesByGroup."adguardhome.access" = [ "adguardhome_access" ]; + valuesByGroup."rss.access" = [ "ttrss_access" ]; + valuesByGroup."firefly.access" = [ "firefly_access" ]; + valuesByGroup."ollama.access" = [ "ollama_access" ]; + valuesByGroup."octoprint.access" = [ "octoprint_access" ]; }; }; groups."forgejo.access" = { - members = ["forgejo.admins"]; + members = [ "forgejo.admins" ]; }; groups."forgejo.admins" = { - members = ["administrator"]; + members = [ "administrator" ]; }; systems.oauth2.forgejo = { displayName = "Forgejo"; originUrl = "https://forge.${config.secrets.secrets.global.domains.web}/"; basicSecretFile = config.age.secrets.oauth2-forgejo.path; - scopeMaps."forgejo.access" = ["openid" "email" "profile"]; + scopeMaps."forgejo.access" = [ + "openid" + "email" + "profile" + ]; allowInsecureClientDisablePkce = true; preferShortUsername = true; claimMaps.groups = { joinType = "array"; - valuesByGroup."forgejo.admins" = ["admin"]; + valuesByGroup."forgejo.admins" = [ "admin" ]; }; }; - groups."netbird.access" = { - }; + groups."netbird.access" = { }; systems.oauth2.netbird = { public = true; displayName = "Netbird"; @@ -175,7 +212,11 @@ in { preferShortUsername = true; enableLocalhostRedirects = true; enableLegacyCrypto = true; - scopeMaps."netbird.access" = ["openid" "email" "profile"]; + scopeMaps."netbird.access" = [ + "openid" + "email" + "profile" + ]; }; }; }; diff --git a/config/services/maddy.nix b/config/services/maddy.nix index fe93bd1..c73dc71 100644 --- a/config/services/maddy.nix +++ b/config/services/maddy.nix @@ -5,12 +5,17 @@ pkgs, lib, ... -}: let +}: +let priv_domain = config.secrets.secrets.global.domains.mail_private; domain = config.secrets.secrets.global.domains.mail_public; - mailDomains = [priv_domain domain]; + mailDomains = [ + priv_domain + domain + ]; maddyBackupDir = "/var/cache/backups/maddy"; -in { +in +{ systemd.tmpfiles.settings = { "10-maddy".${maddyBackupDir}.d = { inherit (config.services.maddy) user group; @@ -40,7 +45,10 @@ in { inherit (config.secrets.secrets.global.hetzner.users.maddy) subUid path; sshAgeSecret = "maddyHetznerSsh"; }; - paths = ["/var/lib/maddy/messages" maddyBackupDir]; + paths = [ + "/var/lib/maddy/messages" + maddyBackupDir + ]; pruneOpts = [ "--keep-daily 10" "--keep-weekly 7" @@ -49,22 +57,21 @@ in { ]; }; }; - systemd.services.maddy-backup = let - cfg = config.systemd.services.maddy; - in { - description = "Maddy db backup"; - serviceConfig = - lib.recursiveUpdate - cfg.serviceConfig - { + systemd.services.maddy-backup = + let + cfg = config.systemd.services.maddy; + in + { + description = "Maddy db backup"; + serviceConfig = lib.recursiveUpdate cfg.serviceConfig { ExecStart = "${pkgs.sqlite}/bin/sqlite3 /var/lib/maddy/imapsql.db \".backup '${maddyBackupDir}/imapsql.sqlite3'\""; Restart = "no"; Type = "oneshot"; }; - inherit (cfg) environment; - requiredBy = ["restic-backups-main.service"]; - before = ["restic-backups-main.service"]; - }; + inherit (cfg) environment; + requiredBy = [ "restic-backups-main.service" ]; + before = [ "restic-backups-main.service" ]; + }; age.secrets.patrickPasswd = { generator.script = "alnum"; @@ -73,7 +80,10 @@ in { }; # Opening ports for additional TLS listeners. This is not yet # implemented in the module. - networking.firewall.allowedTCPPorts = [993 465]; + networking.firewall.allowedTCPPorts = [ + 993 + 465 + ]; services.maddy = { enable = true; hostname = "mx1." + domain; @@ -91,9 +101,7 @@ in { ensureCredentials = { "patrick@${domain}".passwordFile = config.age.secrets.patrickPasswd.path; }; - ensureAccounts = [ - "patrick@${domain}" - ]; + ensureAccounts = [ "patrick@${domain}" ]; openFirewall = true; config = '' ## Maddy Mail Server - default configuration file (2022-06-18) @@ -288,33 +296,31 @@ in { useACMEWildcardHost = true; locations."=/mail/config-v1.1.xml".alias = pkgs.writeText "autoconfig.${domain}.xml" - /* - xml - */ - '' - - - - ${domain} - %EMAILADDRESS% - %EMAILLOCALPART% - - mail.${domain} - 993 - SSL - password-cleartext - %EMAILADDRESS% - - - mail.${domain} - 465 - SSL - password-cleartext - %EMAILADDRESS% - - - - ''; + # xml + '' + + + + ${domain} + %EMAILADDRESS% + %EMAILLOCALPART% + + mail.${domain} + 993 + SSL + password-cleartext + %EMAILADDRESS% + + + mail.${domain} + 465 + SSL + password-cleartext + %EMAILADDRESS% + + + + ''; })) ]; environment.persistence."/persist".directories = [ diff --git a/config/services/murmur.nix b/config/services/murmur.nix index d1d973c..009d794 100644 --- a/config/services/murmur.nix +++ b/config/services/murmur.nix @@ -1,5 +1,6 @@ -{config, ...}: { - networking.firewall.allowedUDPPorts = [config.services.teamspeak3.defaultVoicePort]; +{ config, ... }: +{ + networking.firewall.allowedUDPPorts = [ config.services.teamspeak3.defaultVoicePort ]; services.teamspeak3 = { enable = true; }; diff --git a/config/services/netbird.nix b/config/services/netbird.nix index 9433592..110d83a 100644 --- a/config/services/netbird.nix +++ b/config/services/netbird.nix @@ -1,11 +1,12 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [80 3000 3001]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ + 80 + 3000 + 3001 + ]; }; age.secrets.coturnPassword = { @@ -19,14 +20,20 @@ }; age.secrets.dataEnc = { - generator.script = {pkgs, ...}: '' - ${lib.getExe pkgs.openssl} rand -base64 32 - ''; + generator.script = + { pkgs, ... }: + '' + ${lib.getExe pkgs.openssl} rand -base64 32 + ''; group = "netbird"; }; - networking.firewall.allowedTCPPorts = [80 3000 3001]; - networking.firewall.allowedUDPPorts = [3478]; + networking.firewall.allowedTCPPorts = [ + 80 + 3000 + 3001 + ]; + networking.firewall.allowedUDPPorts = [ 3478 ]; services.netbird = { server = { enable = true; diff --git a/config/services/nextcloud.nix b/config/services/nextcloud.nix index 39e5fe9..e6dc92e 100644 --- a/config/services/nextcloud.nix +++ b/config/services/nextcloud.nix @@ -4,9 +4,11 @@ config, nodes, ... -}: let +}: +let hostName = "nc.${config.secrets.secrets.global.domains.web}"; -in { +in +{ age.secrets.maddyPasswd = { generator.script = "alnum"; mode = "440"; @@ -20,7 +22,8 @@ in { mode = "640"; }; services.maddy.ensureCredentials = { - "nextcloud@${config.secrets.secrets.global.domains.mail_public}".passwordFile = nodes.maddy.config.age.secrets.nextcloudPasswd.path; + "nextcloud@${config.secrets.secrets.global.domains.mail_public}".passwordFile = + nodes.maddy.config.age.secrets.nextcloudPasswd.path; }; }; environment.persistence."/persist".directories = [ @@ -54,7 +57,15 @@ in { config.adminpassFile = config.age.secrets.ncpasswd.path; # Kinda ok just remember to instanly change after first setup config.adminuser = "admin"; extraApps = with config.services.nextcloud.package.packages.apps; { - inherit contacts calendar tasks notes maps phonetrack user_oidc; + inherit + contacts + calendar + tasks + notes + maps + phonetrack + user_oidc + ; }; maxUploadSize = "4G"; extraAppsEnable = true; @@ -62,7 +73,7 @@ in { phpOptions."opcache.interned_strings_buffer" = "32"; settings = { default_phone_region = "DE"; - trusted_proxies = [nodes.elisabeth.config.wireguard.elisabeth.ipv4]; + trusted_proxies = [ nodes.elisabeth.config.wireguard.elisabeth.ipv4 ]; overwriteprotocol = "https"; maintenance_window_start = 2; enabledPreviewProviders = [ @@ -93,20 +104,22 @@ in { dbtype = "pgsql"; }; }; - systemd.tmpfiles.rules = let - mailer-passwd-conf = pkgs.writeText "nextcloud-config.php" '' - trim(file_get_contents('${config.age.secrets.maddyPasswd.path}')), - ]; - ''; - in [ - "L+ ${config.services.nextcloud.datadir}/config/mailer.config.php - - - - ${mailer-passwd-conf}" - ]; + systemd.tmpfiles.rules = + let + mailer-passwd-conf = pkgs.writeText "nextcloud-config.php" '' + trim(file_get_contents('${config.age.secrets.maddyPasswd.path}')), + ]; + ''; + in + [ + "L+ ${config.services.nextcloud.datadir}/config/mailer.config.php - - - - ${mailer-passwd-conf}" + ]; wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [80]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ]; }; networking = { # Use systemd-resolved inside the container diff --git a/config/services/oauth2-proxy.nix b/config/services/oauth2-proxy.nix index 2f900d5..52f4eed 100644 --- a/config/services/oauth2-proxy.nix +++ b/config/services/oauth2-proxy.nix @@ -1,11 +1,8 @@ +{ config, nodes, ... }: { - config, - nodes, - ... -}: { wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [3000]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ]; }; age.secrets.oauth2-cookie-secret = { @@ -46,7 +43,7 @@ redeemURL = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/token"; validateURL = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/oauth2-proxy/userinfo"; clientID = "oauth2-proxy"; - email.domains = ["*"]; + email.domains = [ "*" ]; }; systemd.services.oauth2-proxy.serviceConfig = { @@ -72,18 +69,18 @@ # it includes the newline terminating the file which # makes kanidm reject the secret age.secrets.oauth2-client-secret-env = { - generator.dependencies = [ - nodes.elisabeth-kanidm.config.age.secrets.oauth2-proxy - ]; - generator.script = { - lib, - decrypt, - deps, - ... - }: '' - echo -n "OAUTH2_PROXY_CLIENT_SECRET=" - ${decrypt} ${lib.escapeShellArg (lib.head deps).file} - ''; + generator.dependencies = [ nodes.elisabeth-kanidm.config.age.secrets.oauth2-proxy ]; + generator.script = + { + lib, + decrypt, + deps, + ... + }: + '' + echo -n "OAUTH2_PROXY_CLIENT_SECRET=" + ${decrypt} ${lib.escapeShellArg (lib.head deps).file} + ''; mode = "440"; group = "oauth2-proxy"; }; diff --git a/config/services/octoprint.nix b/config/services/octoprint.nix index 6c6ec69..20afa0f 100644 --- a/config/services/octoprint.nix +++ b/config/services/octoprint.nix @@ -1,12 +1,13 @@ -{config, ...}: { +{ config, ... }: +{ wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [config.services.octoprint.port]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.octoprint.port ]; }; services.octoprint = { port = 3000; enable = true; - plugins = ps: with ps; [ender3v2tempfix]; + plugins = ps: with ps; [ ender3v2tempfix ]; extraConfig = { accessControl = { addRemoteUser = true; diff --git a/config/services/ollama.nix b/config/services/ollama.nix index cc7f7c7..a8bbb4e 100644 --- a/config/services/ollama.nix +++ b/config/services/ollama.nix @@ -1,7 +1,8 @@ -{config, ...}: { +{ config, ... }: +{ wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [config.services.open-webui.port]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.open-webui.port ]; }; services.ollama = { host = "localhost"; diff --git a/config/services/paperless.nix b/config/services/paperless.nix index f0e972d..3755a21 100644 --- a/config/services/paperless.nix +++ b/config/services/paperless.nix @@ -4,10 +4,12 @@ config, lib, ... -}: let +}: +let paperlessdomain = "ppl.${config.secrets.secrets.global.domains.web}"; paperlessBackupDir = "/var/cache/backups/paperless"; -in { +in +{ systemd.tmpfiles.settings = { "10-paperless".${paperlessBackupDir}.d = { inherit (config.services.paperless) user; @@ -36,7 +38,7 @@ in { inherit (config.secrets.secrets.global.hetzner.users.paperless) subUid path; sshAgeSecret = "paperlessHetznerSsh"; }; - paths = [paperlessBackupDir]; + paths = [ paperlessBackupDir ]; pruneOpts = [ "--keep-daily 10" "--keep-weekly 7" @@ -45,27 +47,26 @@ in { ]; }; }; - systemd.services.paperless-backup = let - cfg = config.systemd.services.paperless-consumer; - in { - description = "Paperless document backup"; - serviceConfig = - lib.recursiveUpdate - cfg.serviceConfig - { + systemd.services.paperless-backup = + let + cfg = config.systemd.services.paperless-consumer; + in + { + description = "Paperless document backup"; + serviceConfig = lib.recursiveUpdate cfg.serviceConfig { ExecStart = "${config.services.paperless.package}/bin/paperless-ngx document_exporter -na -nt -f -d ${paperlessBackupDir}"; - ReadWritePaths = cfg.serviceConfig.ReadWritePaths ++ [paperlessBackupDir]; + ReadWritePaths = cfg.serviceConfig.ReadWritePaths ++ [ paperlessBackupDir ]; Restart = "no"; Type = "oneshot"; }; - inherit (cfg) environment; - requiredBy = ["restic-backups-main.service"]; - before = ["restic-backups-main.service"]; - }; + inherit (cfg) environment; + requiredBy = [ "restic-backups-main.service" ]; + before = [ "restic-backups-main.service" ]; + }; wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [config.services.paperless.port]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.paperless.port ]; }; age.secrets.paperless-admin-passwd = { diff --git a/config/services/pr-tracker.nix b/config/services/pr-tracker.nix index 40cc06a..2f6f5ba 100644 --- a/config/services/pr-tracker.nix +++ b/config/services/pr-tracker.nix @@ -4,18 +4,20 @@ lib, pkgs, ... -}: let +}: +let prestart = pkgs.writeShellScript "pr-tracker-pre" '' if [ ! -d ./nixpkgs ]; then ${lib.getExe pkgs.git} clone https://github.com/NixOS/nixpkgs.git fi ''; -in { +in +{ wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [3000]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ]; }; - networking.firewall.allowedTCPPorts = [3000]; + networking.firewall.allowedTCPPorts = [ 3000 ]; environment.persistence."/persist".directories = [ { directory = "/var/lib/pr-tracker"; @@ -43,15 +45,16 @@ in { mode = "640"; }; services.maddy.ensureCredentials = { - "pr-tracker@${config.secrets.secrets.global.domains.mail_public}".passwordFile = nodes.maddy.config.age.secrets.pr-trackerPasswd.path; + "pr-tracker@${config.secrets.secrets.global.domains.mail_public}".passwordFile = + nodes.maddy.config.age.secrets.pr-trackerPasswd.path; }; }; systemd.sockets.pr-tracker = { - listenStreams = ["0.0.0.0:3000"]; - wantedBy = ["sockets.target"]; + listenStreams = [ "0.0.0.0:3000" ]; + wantedBy = [ "sockets.target" ]; }; systemd.services.pr-tracker = { - path = [pkgs.git]; + path = [ pkgs.git ]; serviceConfig = { User = "pr-tracker"; Group = "pr-tracker"; @@ -104,13 +107,13 @@ in { }; }; systemd.timers.pr-tracker-update = { - wantedBy = ["timers.target"]; + wantedBy = [ "timers.target" ]; timerConfig = { OnBootSec = "30m"; OnUnitActiveSec = "30m"; }; }; - users.groups.pr-tracker = {}; + users.groups.pr-tracker = { }; users.users.pr-tracker = { isSystemUser = true; group = "pr-tracker"; diff --git a/config/services/radicale.nix b/config/services/radicale.nix index 9eb2d66..1d905b1 100644 --- a/config/services/radicale.nix +++ b/config/services/radicale.nix @@ -4,14 +4,20 @@ config, pkgs, # not unused needed for the usage of attrs later to contains pkgs ... -} @ attrs: let +}@attrs: +let hostName = "radicale.${config.secrets.secrets.global.domains.mail}"; -in { - imports = [./containers.nix ./ddclient.nix ./acme.nix]; +in +{ + imports = [ + ./containers.nix + ./ddclient.nix + ./acme.nix + ]; services.nginx = { enable = true; upstreams.radicale = { - servers."192.168.178.34:8000" = {}; + servers."192.168.178.34:8000" = { }; extraConfig = '' zone radicale 64k ; @@ -32,10 +38,10 @@ in { config = _: { systemd.network.networks = { "lan01" = { - address = ["192.168.178.34/24"]; - gateway = ["192.168.178.1"]; + address = [ "192.168.178.34/24" ]; + gateway = [ "192.168.178.1" ]; matchConfig.Name = "lan01*"; - dns = ["192.168.178.2"]; + dns = [ "192.168.178.2" ]; networkConfig = { IPv6PrivacyExtensions = "yes"; MulticastDNS = true; @@ -54,7 +60,10 @@ in { enable = true; setting = { server = { - hosts = ["0.0.0.0:8000" "[::]:8000"]; + hosts = [ + "0.0.0.0:8000" + "[::]:8000" + ]; auth = { type = "htpasswd"; htpasswd_filename = "/etc/radicale/users"; @@ -89,7 +98,7 @@ in { networking = { firewall = { enable = true; - allowedTCPPorts = [8000]; + allowedTCPPorts = [ 8000 ]; }; # Use systemd-resolved inside the container useHostResolvConf = lib.mkForce false; @@ -106,4 +115,3 @@ in { #kanidm #remote backups #immich - diff --git a/config/services/samba.nix b/config/services/samba.nix index c08080e..4fb56a2 100644 --- a/config/services/samba.nix +++ b/config/services/samba.nix @@ -1,16 +1,13 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { services.samba-wsdd = { enable = true; # make shares visible for windows 10 clients openFirewall = true; }; - disabledModules = ["services/networking/netbird.nix"]; + disabledModules = [ "services/networking/netbird.nix" ]; - imports = [../../modules/netbird-client.nix]; + imports = [ ../../modules/netbird-client.nix ]; services.netbird.tunnels = { netbird-samba = { environment = { @@ -43,7 +40,7 @@ inherit (config.secrets.secrets.global.hetzner.users.smb) subUid path; sshAgeSecret = "resticHetznerSsh"; }; - paths = ["/bunker"]; + paths = [ "/bunker" ]; pruneOpts = [ "--keep-daily 10" "--keep-weekly 7" @@ -55,11 +52,17 @@ wireguard.samba-patrick.server = { host = config.secrets.secrets.global.domains.web; port = 51830; - reservedAddresses = ["10.43.0.0/20" "fd00:1765::/112"]; + reservedAddresses = [ + "10.43.0.0/20" + "fd00:1765::/112" + ]; openFirewall = true; }; - networking.nftables.firewall.zones.untrusted.interfaces = ["samba-patrick" "netbird-samba"]; + networking.nftables.firewall.zones.untrusted.interfaces = [ + "samba-patrick" + "netbird-samba" + ]; services.samba = { enable = true; @@ -106,53 +109,49 @@ "disable spoolss = yes" "show add printer wizard = no" ]; - shares = let - mkShare = { - name, - user ? "smb", - group ? "smb", - hasBunker ? false, - hasPaperless ? false, - persistRoot ? "/panzer", - }: cfg: let - config = + shares = + let + mkShare = { - "#persistRoot" = persistRoot; - "#user" = user; - "#group" = group; - "read only" = "no"; - "guest ok" = "no"; - "create mask" = "0740"; - "directory mask" = "0750"; - "force user" = user; - "force group" = group; - "valid users" = "${user} @${group}"; - "force create mode" = "0660"; - "force directory mode" = "0770"; - # Might be necessary for windows user to be able to open thing in smb - "acl allow execute always" = "no"; + name, + user ? "smb", + group ? "smb", + hasBunker ? false, + hasPaperless ? false, + persistRoot ? "/panzer", + }: + cfg: + let + config = { + "#persistRoot" = persistRoot; + "#user" = user; + "#group" = group; + "read only" = "no"; + "guest ok" = "no"; + "create mask" = "0740"; + "directory mask" = "0750"; + "force user" = user; + "force group" = group; + "valid users" = "${user} @${group}"; + "force create mode" = "0660"; + "force directory mode" = "0770"; + # Might be necessary for windows user to be able to open thing in smb + "acl allow execute always" = "no"; + } // cfg; + in + { + "${name}" = config // { + "path" = "/media/smb/${name}"; + }; } - // cfg; - in - { - "${name}" = - config - // {"path" = "/media/smb/${name}";}; - } - // lib.optionalAttrs hasBunker - { - "${name}-important" = - config - // { + // lib.optionalAttrs hasBunker { + "${name}-important" = config // { "path" = "/media/smb/${name}-important"; "#persistRoot" = "/bunker"; }; - } - // lib.optionalAttrs hasPaperless - { - "${name}-paperless" = - config - // { + } + // lib.optionalAttrs hasPaperless { + "${name}-paperless" = config // { "path" = "/media/smb/${name}-paperless"; "#paperless" = true; "force user" = "paperless"; @@ -160,46 +159,47 @@ # Empty to prevent imperamence setting a persistence folder "#persistRoot" = ""; }; - }; - in + }; + in lib.mkMerge [ (mkShare { name = "ggr-data"; user = "ggr"; group = "ggr"; hasBunker = true; - } {}) + } { }) (mkShare { name = "patri"; user = "patrick"; group = "patrick"; hasBunker = true; hasPaperless = true; - } {}) + } { }) (mkShare { name = "helen-data"; user = "helen"; group = "helen"; hasBunker = true; - } {}) + } { }) (mkShare { name = "david"; user = "david"; group = "david"; hasBunker = true; hasPaperless = true; - } {}) + } { }) (mkShare { name = "printer"; user = "printer"; group = "printer"; - } {}) + } { }) (mkShare { name = "family-data"; user = "family"; group = "family"; - } {}) - (mkShare { + } { }) + (mkShare + { name = "media"; user = "family"; group = "family"; @@ -208,7 +208,8 @@ { "read only" = "yes"; "write list" = "@family"; - }) + } + ) ]; }; # to get this file start a smbd, add users using 'smbpasswd -a ' @@ -216,129 +217,162 @@ age.secrets.smbpassdb = { rekeyFile = config.node.secretsDir + "/smbpassdb.tdb.age"; }; - users = let - users = lib.unique (lib.mapAttrsToList (_: val: val."force user") config.services.samba.shares); - groups = lib.unique (users ++ (lib.mapAttrsToList (_: val: val."force group") config.services.samba.shares)); - in { - users = lib.mkMerge ((lib.flip map users (user: { - ${user} = { - isNormalUser = true; - home = "/var/empty"; - createHome = false; - useDefaultShell = false; - autoSubUidGidRange = false; - group = "${user}"; - }; - })) - ++ [ - {paperless.isNormalUser = lib.mkForce false;} - ]); - groups = lib.mkMerge ((lib.flip map groups (group: { - ${group} = { - }; - })) - ++ [ - { - family.members = ["patrick" "david" "helen" "ggr"]; - printer.members = ["patrick" "david" "helen" "ggr"]; - } - ]); - }; - - fileSystems = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: - lib.optionalAttrs ((v ? "#paperless") && v."#paperless") { - "${v.path}/consume" = { - fsType = "none"; - options = ["bind"]; - device = "/paperless/consume/${v."#user"}"; - }; - "${v.path}/media/archive" = { - fsType = "none "; - options = ["bind" "ro"]; - device = "/paperless/media/documents/archive/${v."#user"}"; - }; - "${v.path}/media/originals" = { - fsType = "none "; - options = ["bind" "ro"]; - device = "/paperless/media/documents/originals/${v."#user"}"; - }; - })); - - systemd.tmpfiles.settings = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: - lib.optionalAttrs ((v ? "#paperless") && v."#paperless") { - "10-smb-paperless"."/paperless/consume/".d = { - user = "paperless"; - group = "paperless"; - mode = "0770"; - }; - "10-smb-paperless"."/paperless/consume/${v."#user"}".d = { - user = "paperless"; - group = "paperless"; - mode = "0770"; - }; - "10-smb-paperless"."/paperless/media/".d = { - user = "paperless"; - group = "paperless"; - mode = "0770"; - }; - "10-smb-paperless"."/paperless/media/documents/".d = { - user = "paperless"; - group = "paperless"; - mode = "0770"; - }; - - "10-smb-paperless"."/paperless/media/documents/archive/".d = { - user = "paperless"; - group = "paperless"; - mode = "0770"; - }; - "10-smb-paperless"."/paperless/media/documents/archive/${v."#user"}".d = { - user = "paperless"; - group = "paperless"; - mode = "0770"; - }; - "10-smb-paperless"."/paperless/media/documents/archive/${v."#user"}/.keep".f = { - user = "paperless"; - group = "paperless"; - mode = "0660"; - }; - "10-smb-paperless"."/paperless/media/documents/originals/".d = { - user = "paperless"; - group = "paperless"; - mode = "0770"; - }; - "10-smb-paperless"."/paperless/media/documents/originals/${v."#user"}".d = { - user = "paperless"; - group = "paperless"; - mode = "0770"; - }; - "10-smb-paperless"."/paperless/media/documents/originals/${v."#user"}/.keep".f = { - user = "paperless"; - group = "paperless"; - mode = "0660"; - }; - })); - environment.persistence = lib.mkMerge (lib.flatten [ - (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: - lib.optionalAttrs ((v ? "#persistRoot") && (v."#persistRoot" != "")) { - ${v."#persistRoot"}.directories = [ + users = + let + users = lib.unique (lib.mapAttrsToList (_: val: val."force user") config.services.samba.shares); + groups = lib.unique ( + users ++ (lib.mapAttrsToList (_: val: val."force group") config.services.samba.shares) + ); + in + { + users = lib.mkMerge ( + (lib.flip map users (user: { + ${user} = { + isNormalUser = true; + home = "/var/empty"; + createHome = false; + useDefaultShell = false; + autoSubUidGidRange = false; + group = "${user}"; + }; + })) + ++ [ { paperless.isNormalUser = lib.mkForce false; } ] + ); + groups = lib.mkMerge ( + (lib.flip map groups (group: { + ${group} = { }; + })) + ++ [ { - directory = "${v.path}"; - user = "${v."force user"}"; - group = "${v."force group"}"; - mode = "0770"; + family.members = [ + "patrick" + "david" + "helen" + "ggr" + ]; + printer.members = [ + "patrick" + "david" + "helen" + "ggr" + ]; } - ]; - })) - (lib.flip lib.mapAttrsToList config.services.netbird.tunnels ( - _: v: { - "/state".directories = [ - { - directory = "/var/lib/${v.stateDir}"; - mode = "0770"; - } - ]; + ] + ); + }; + + fileSystems = lib.mkMerge ( + lib.flip lib.mapAttrsToList config.services.samba.shares ( + _: v: + lib.optionalAttrs ((v ? "#paperless") && v."#paperless") { + "${v.path}/consume" = { + fsType = "none"; + options = [ "bind" ]; + device = "/paperless/consume/${v."#user"}"; + }; + "${v.path}/media/archive" = { + fsType = "none "; + options = [ + "bind" + "ro" + ]; + device = "/paperless/media/documents/archive/${v."#user"}"; + }; + "${v.path}/media/originals" = { + fsType = "none "; + options = [ + "bind" + "ro" + ]; + device = "/paperless/media/documents/originals/${v."#user"}"; + }; } - )) - ]); + ) + ); + + systemd.tmpfiles.settings = lib.mkMerge ( + lib.flip lib.mapAttrsToList config.services.samba.shares ( + _: v: + lib.optionalAttrs ((v ? "#paperless") && v."#paperless") { + "10-smb-paperless"."/paperless/consume/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + "10-smb-paperless"."/paperless/consume/${v."#user"}".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + "10-smb-paperless"."/paperless/media/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + "10-smb-paperless"."/paperless/media/documents/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + + "10-smb-paperless"."/paperless/media/documents/archive/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + "10-smb-paperless"."/paperless/media/documents/archive/${v."#user"}".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + "10-smb-paperless"."/paperless/media/documents/archive/${v."#user"}/.keep".f = { + user = "paperless"; + group = "paperless"; + mode = "0660"; + }; + "10-smb-paperless"."/paperless/media/documents/originals/".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + "10-smb-paperless"."/paperless/media/documents/originals/${v."#user"}".d = { + user = "paperless"; + group = "paperless"; + mode = "0770"; + }; + "10-smb-paperless"."/paperless/media/documents/originals/${v."#user"}/.keep".f = { + user = "paperless"; + group = "paperless"; + mode = "0660"; + }; + } + ) + ); + environment.persistence = lib.mkMerge ( + lib.flatten [ + (lib.flip lib.mapAttrsToList config.services.samba.shares ( + _: v: + lib.optionalAttrs ((v ? "#persistRoot") && (v."#persistRoot" != "")) { + ${v."#persistRoot"}.directories = [ + { + directory = "${v.path}"; + user = "${v."force user"}"; + group = "${v."force group"}"; + mode = "0770"; + } + ]; + } + )) + (lib.flip lib.mapAttrsToList config.services.netbird.tunnels ( + _: v: { + "/state".directories = [ + { + directory = "/var/lib/${v.stateDir}"; + mode = "0770"; + } + ]; + } + )) + ] + ); } diff --git a/config/services/ttrss.nix b/config/services/ttrss.nix index e68a7bb..742b119 100644 --- a/config/services/ttrss.nix +++ b/config/services/ttrss.nix @@ -1,7 +1,8 @@ -{config, ...}: { +{ config, ... }: +{ wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [80]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ]; }; services.freshrss = { enable = true; diff --git a/config/services/vaultwarden.nix b/config/services/vaultwarden.nix index d0af019..13565e5 100644 --- a/config/services/vaultwarden.nix +++ b/config/services/vaultwarden.nix @@ -3,9 +3,11 @@ lib, nodes, ... -}: let +}: +let vaultwardenDomain = "pw.${config.secrets.secrets.global.domains.web}"; -in { +in +{ age.secrets.vaultwarden-env = { rekeyFile = config.node.secretsDir + "/vaultwarden-env.age"; mode = "440"; @@ -43,7 +45,7 @@ in { inherit (config.secrets.secrets.global.hetzner.users.vaultwarden) subUid path; sshAgeSecret = "vaultwardenHetznerSsh"; }; - paths = [config.services.vaultwarden.backupDir]; + paths = [ config.services.vaultwarden.backupDir ]; pruneOpts = [ "--keep-daily 10" "--keep-weekly 7" @@ -64,17 +66,18 @@ in { mode = "640"; }; services.maddy.ensureCredentials = { - "vaultwarden@${config.secrets.secrets.global.domains.mail_public}".passwordFile = nodes.maddy.config.age.secrets.vaultwardenPasswd.path; + "vaultwarden@${config.secrets.secrets.global.domains.mail_public}".passwordFile = + nodes.maddy.config.age.secrets.vaultwardenPasswd.path; }; }; system.activationScripts.systemd_env_smtp_passwd = { text = '' echo "SMTP_PASSWORD=$(< ${lib.escapeShellArg config.age.secrets.maddyPasswd.path})" > /run/vaultwarden_smtp_passwd ''; - deps = ["agenix"]; + deps = [ "agenix" ]; }; - systemd.services.vaultwarden.serviceConfig.EnvironmentFile = ["/run/vaultwarden_smtp_passwd"]; + systemd.services.vaultwarden.serviceConfig.EnvironmentFile = [ "/run/vaultwarden_smtp_passwd" ]; services.vaultwarden = { enable = true; @@ -107,7 +110,7 @@ in { wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [config.services.vaultwarden.config.rocketPort]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.vaultwarden.config.rocketPort ]; }; # Replace uses of old name diff --git a/config/services/yourspotify.nix b/config/services/yourspotify.nix index 6550f02..cdf7b62 100644 --- a/config/services/yourspotify.nix +++ b/config/services/yourspotify.nix @@ -1,11 +1,11 @@ +{ config, pkgs, ... }: { - config, - pkgs, - ... -}: { wireguard.elisabeth = { client.via = "elisabeth"; - firewallRuleForNode.elisabeth.allowedTCPPorts = [3000 80]; + firewallRuleForNode.elisabeth.allowedTCPPorts = [ + 3000 + 80 + ]; }; age.secrets.spotifySecret = { owner = "root"; diff --git a/flake.nix b/flake.nix index c62d541..a334276 100644 --- a/flake.nix +++ b/flake.nix @@ -101,27 +101,29 @@ }; }; - outputs = { - self, - nixpkgs, - flake-utils, - agenix-rekey, - nixos-generators, - pre-commit-hooks, - devshell, - nixvim, - nixos-extra-modules, - nix-topology, - ... - } @ inputs: let - inherit (nixpkgs) lib; - stateVersion = "23.05"; - in + outputs = + { + self, + nixpkgs, + flake-utils, + agenix-rekey, + nixos-generators, + pre-commit-hooks, + devshell, + nixvim, + nixos-extra-modules, + nix-topology, + ... + }@inputs: + let + inherit (nixpkgs) lib; + stateVersion = "23.05"; + in { secretsConfig = { # This should be a link to one of the age public keys is './keys' - masterIdentities = [./keys/PatC.pub]; - extraEncryptionPubkeys = [./secrets/recipients.txt]; + masterIdentities = [ ./keys/PatC.pub ]; + extraEncryptionPubkeys = [ ./secrets/recipients.txt ]; }; agenix-rekey = agenix-rekey.configure { userFlake = self; @@ -129,8 +131,7 @@ }; inherit stateVersion; - inherit - (import ./nix/hosts.nix inputs) + inherit (import ./nix/hosts.nix inputs) hosts nixosConfigurations minimalConfigurations @@ -139,19 +140,20 @@ nodes = self.nixosConfigurations // self.guestConfigurations; inherit - (lib.foldl' lib.recursiveUpdate {} - (lib.mapAttrsToList - (import ./nix/generate-installer-package.nix inputs) - self.minimalConfigurations)) + (lib.foldl' lib.recursiveUpdate { } ( + lib.mapAttrsToList (import ./nix/generate-installer-package.nix inputs) self.minimalConfigurations + )) packages ; } // flake-utils.lib.eachDefaultSystem (system: rec { - apps.setupHetznerStorageBoxes = import (nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix") { - inherit pkgs; - nixosConfigurations = self.nodes; - decryptIdentity = builtins.head self.secretsConfig.masterIdentities; - }; + apps.setupHetznerStorageBoxes = + import (nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix") + { + inherit pkgs; + nixosConfigurations = self.nodes; + decryptIdentity = builtins.head self.secretsConfig.masterIdentities; + }; pkgs = import nixpkgs { overlays = import ./lib inputs @@ -172,7 +174,7 @@ topology = import nix-topology { inherit pkgs; modules = [ - {inherit (self) nixosConfigurations;} + { inherit (self) nixosConfigurations; } ./nix/topology.nix ]; }; @@ -191,19 +193,17 @@ .${system}; }; - checks.pre-commit-check = - pre-commit-hooks.lib.${system}.run - { - src = lib.cleanSource ./.; - hooks = { - nixfmt = { - enable = true; - package = pkgs.nixfmt-rfc-style; - }; - deadnix.enable = true; - statix.enable = true; + checks.pre-commit-check = pre-commit-hooks.lib.${system}.run { + src = lib.cleanSource ./.; + hooks = { + nixfmt = { + enable = true; + package = pkgs.nixfmt-rfc-style; }; + deadnix.enable = true; + statix.enable = true; }; + }; devShell = import ./nix/devshell.nix inputs system; formatter = pkgs.nixfmt-rfc-style; }); diff --git a/hosts/desktopnix/default.nix b/hosts/desktopnix/default.nix index ff642d1..b4b442a 100644 --- a/hosts/desktopnix/default.nix +++ b/hosts/desktopnix/default.nix @@ -1,8 +1,5 @@ +{ inputs, lib, ... }: { - inputs, - lib, - ... -}: { imports = [ inputs.nixos-hardware.nixosModules.common-gpu-nvidia-nonprime inputs.nixos-hardware.nixosModules.common-cpu-intel-cpu-only @@ -51,9 +48,23 @@ device = "/dev/input/event15"; }; - boot.binfmt.emulatedSystems = ["aarch64-linux" "riscv64-linux"]; - nix.settings.system-features = ["kvm" "nixos-test"]; - boot.kernelParams = lib.mkForce ["rd.luks.options=timeout=0" "rootflags=x-systemd.device-timeout=0" "nohibernate" "root=fstab" "loglevel=4" "nvidia-drm.modeset=1" "nvidia.NVreg_PreserveVideoMemoryAllocations=1"]; + boot.binfmt.emulatedSystems = [ + "aarch64-linux" + "riscv64-linux" + ]; + nix.settings.system-features = [ + "kvm" + "nixos-test" + ]; + boot.kernelParams = lib.mkForce [ + "rd.luks.options=timeout=0" + "rootflags=x-systemd.device-timeout=0" + "nohibernate" + "root=fstab" + "loglevel=4" + "nvidia-drm.modeset=1" + "nvidia.NVreg_PreserveVideoMemoryAllocations=1" + ]; services.netbird.enable = true; # Do not cleanup nix store to prevent having to rebuild packages onca a month diff --git a/hosts/desktopnix/fs.nix b/hosts/desktopnix/fs.nix index 3127a61..375bd7a 100644 --- a/hosts/desktopnix/fs.nix +++ b/hosts/desktopnix/fs.nix @@ -3,7 +3,8 @@ nodes, lib, ... -}: { +}: +{ disko.devices = { disk = { m2-ssd = rec { @@ -12,9 +13,15 @@ content = with lib.disko.gpt; { type = "gpt"; partitions = { - boot = (partEfi "2GiB") // {device = "${device}-part1";}; - swap = (partSwap "16G") // {device = "${device}-part2";}; - rpool = (partLuksZfs "m2-ssd" "rpool" "100%") // {device = "${device}-part3";}; + boot = (partEfi "2GiB") // { + device = "${device}-part1"; + }; + swap = (partSwap "16G") // { + device = "${device}-part2"; + }; + rpool = (partLuksZfs "m2-ssd" "rpool" "100%") // { + device = "${device}-part3"; + }; }; }; }; @@ -24,13 +31,15 @@ content = with lib.disko.gpt; { type = "gpt"; partitions = { - panzer = (partLuksZfs "sata-hdd" "panzer" "100%") // {device = "${device}-part1";}; + panzer = (partLuksZfs "sata-hdd" "panzer" "100%") // { + device = "${device}-part1"; + }; }; }; }; }; zpool = with lib.disko.zfs; { - rpool = mkZpool {datasets = impermanenceZfsDatasets;}; + rpool = mkZpool { datasets = impermanenceZfsDatasets; }; panzer = mkZpool { datasets = { "local" = unmountable; @@ -42,8 +51,8 @@ fileSystems."/state".neededForBoot = true; fileSystems."/persist".neededForBoot = true; fileSystems."/panzer/state".neededForBoot = true; - boot.initrd.systemd.services."zfs-import-panzer".after = ["cryptsetup.target"]; - boot.initrd.systemd.services."zfs-import-rpool".after = ["cryptsetup.target"]; + boot.initrd.systemd.services."zfs-import-panzer".after = [ "cryptsetup.target" ]; + boot.initrd.systemd.services."zfs-import-rpool".after = [ "cryptsetup.target" ]; wireguard.scrtiny-patrick.client.via = "elisabeth"; diff --git a/hosts/desktopnix/net.nix b/hosts/desktopnix/net.nix index b0d5d91..edca0e6 100644 --- a/hosts/desktopnix/net.nix +++ b/hosts/desktopnix/net.nix @@ -1,4 +1,5 @@ -{config, ...}: { +{ config, ... }: +{ networking = { inherit (config.secrets.secrets.local.networking) hostId; }; @@ -20,6 +21,6 @@ }; }; }; - networking.nftables.firewall.zones.untrusted.interfaces = ["lan01"]; + networking.nftables.firewall.zones.untrusted.interfaces = [ "lan01" ]; wireguard.samba-patrick.client.via = "elisabeth-samba"; } diff --git a/hosts/elisabeth/default.nix b/hosts/elisabeth/default.nix index 8a738fc..ceca0d2 100644 --- a/hosts/elisabeth/default.nix +++ b/hosts/elisabeth/default.nix @@ -3,29 +3,26 @@ minimal, lib, ... -}: { - imports = - [ - inputs.nixos-hardware.nixosModules.common-pc - inputs.nixos-hardware.nixosModules.common-pc-ssd - inputs.nixos-hardware.nixosModules.common-cpu-amd - inputs.nixos-hardware.nixosModules.common-cpu-amd-pstate +}: +{ + imports = [ + inputs.nixos-hardware.nixosModules.common-pc + inputs.nixos-hardware.nixosModules.common-pc-ssd + inputs.nixos-hardware.nixosModules.common-cpu-amd + inputs.nixos-hardware.nixosModules.common-cpu-amd-pstate - ../../config/basic + ../../config/basic - ../../config/optional/initrd-ssh.nix - ../../config/optional/secureboot.nix - ../../config/optional/zfs.nix + ../../config/optional/initrd-ssh.nix + ../../config/optional/secureboot.nix + ../../config/optional/zfs.nix - ../../config/hardware/physical.nix + ../../config/hardware/physical.nix - ./blog.nix - ./net.nix - ./fs.nix - ] - ++ lib.lists.optionals (!minimal) [ - ./guests.nix - ]; + ./blog.nix + ./net.nix + ./fs.nix + ] ++ lib.lists.optionals (!minimal) [ ./guests.nix ]; services.xserver = { xkb = { layout = "de"; diff --git a/hosts/elisabeth/fs.nix b/hosts/elisabeth/fs.nix index f41123d..771905f 100644 --- a/hosts/elisabeth/fs.nix +++ b/hosts/elisabeth/fs.nix @@ -1,8 +1,5 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { disko.devices = { disk = { internal-ssd = rec { @@ -11,8 +8,12 @@ content = with lib.disko.gpt; { type = "gpt"; partitions = { - boot = (partEfi "1GiB") // {device = "${device}-part1";}; - rpool = (partLuksZfs "ssd" "rpool" "100%") // {device = "${device}-part2";}; + boot = (partEfi "1GiB") // { + device = "${device}-part1"; + }; + rpool = (partLuksZfs "ssd" "rpool" "100%") // { + device = "${device}-part2"; + }; }; }; }; @@ -49,7 +50,7 @@ }; zpool = with lib.disko.zfs; { - rpool = mkZpool {datasets = impermanenceZfsDatasets;}; + rpool = mkZpool { datasets = impermanenceZfsDatasets; }; panzer = mkZpool { datasets = { "safe/guests" = unmountable; @@ -128,10 +129,13 @@ wireguard.scrtiny-patrick.server = { host = config.secrets.secrets.global.domains.web; port = 51831; - reservedAddresses = ["10.44.0.0/16" "fd00:1766::/112"]; + reservedAddresses = [ + "10.44.0.0/16" + "fd00:1766::/112" + ]; openFirewall = true; }; - networking.nftables.firewall.zones.untrusted.interfaces = ["scrtiny-patrick"]; + networking.nftables.firewall.zones.untrusted.interfaces = [ "scrtiny-patrick" ]; services.scrutiny = { enable = true; openFirewall = true; @@ -156,6 +160,6 @@ fileSystems."/state".neededForBoot = true; fileSystems."/persist".neededForBoot = true; - boot.initrd.systemd.services."zfs-import-panzer".after = ["cryptsetup.target"]; - boot.initrd.systemd.services."zfs-import-renaultft".after = ["cryptsetup.target"]; + boot.initrd.systemd.services."zfs-import-panzer".after = [ "cryptsetup.target" ]; + boot.initrd.systemd.services."zfs-import-renaultft".after = [ "cryptsetup.target" ]; } diff --git a/hosts/elisabeth/guests.nix b/hosts/elisabeth/guests.nix index 2c9e08e..48b851a 100644 --- a/hosts/elisabeth/guests.nix +++ b/hosts/elisabeth/guests.nix @@ -6,122 +6,136 @@ minimal, nodes, ... -}: let - domainOf = hostName: let - domains = { - adguardhome = "adguardhome"; - forgejo = "forge"; - immich = "immich"; - nextcloud = "nc"; - ollama = "ai"; - paperless = "ppl"; - ttrss = "rss"; - vaultwarden = "pw"; - yourspotify = "sptfy"; - apispotify = "apisptfy"; - kanidm = "auth"; - oauth2-proxy = "oauth2"; - netbird = "netbird"; - actual = "actual"; - firefly = "money"; - homebox = "homebox"; - octoprint = "print"; - pr-tracker = "tracker"; - }; - in "${domains.${hostName}}.${config.secrets.secrets.global.domains.web}"; +}: +let + domainOf = + hostName: + let + domains = { + adguardhome = "adguardhome"; + forgejo = "forge"; + immich = "immich"; + nextcloud = "nc"; + ollama = "ai"; + paperless = "ppl"; + ttrss = "rss"; + vaultwarden = "pw"; + yourspotify = "sptfy"; + apispotify = "apisptfy"; + kanidm = "auth"; + oauth2-proxy = "oauth2"; + netbird = "netbird"; + actual = "actual"; + firefly = "money"; + homebox = "homebox"; + octoprint = "print"; + pr-tracker = "tracker"; + }; + in + "${domains.${hostName}}.${config.secrets.secrets.global.domains.web}"; # TODO hard coded elisabeth nicht so schön - ipOf = hostName: - if nodes ? ${hostName} - then nodes.${hostName}.config.wireguard.elisabeth.ipv4 - else nodes."elisabeth-${hostName}".config.wireguard.elisabeth.ipv4; -in { - services.nginx = let - blockOf = hostName: { - virtualHostExtraConfig ? "", - maxBodySize ? "500M", - port ? 3000, - upstream ? hostName, - protocol ? "http", - }: { - upstreams.${hostName} = { - servers."${ipOf upstream}:${toString port}" = {}; - extraConfig = '' - zone ${hostName} 64k ; - keepalive 5 ; - ''; - }; - virtualHosts.${domainOf hostName} = { - forceSSL = true; - useACMEHost = "web"; - locations."/" = { - proxyPass = "${protocol}://${hostName}"; - proxyWebsockets = true; - X-Frame-Options = "SAMEORIGIN"; - }; - extraConfig = - '' - client_max_body_size ${maxBodySize} ; - '' - + virtualHostExtraConfig; - }; - }; - proxyProtect = hostName: cfg: allowedGroup: - lib.mkMerge [ - (blockOf hostName cfg) + ipOf = + hostName: + if nodes ? ${hostName} then + nodes.${hostName}.config.wireguard.elisabeth.ipv4 + else + nodes."elisabeth-${hostName}".config.wireguard.elisabeth.ipv4; +in +{ + services.nginx = + let + blockOf = + hostName: { - virtualHosts.${domainOf hostName} = { - locations."/".extraConfig = '' - auth_request /oauth2/auth; - error_page 401 = /oauth2/sign_in; - - # pass information via X-User and X-Email headers to backend, - # requires running with --set-xauthrequest flag - auth_request_set $user $upstream_http_x_auth_request_preferred_username; - # Set the email to our own domain in case user change their mail - auth_request_set $email "''${upstream_http_x_auth_request_preferred_username}@${config.secrets.secrets.global.domains.web}"; - proxy_set_header X-User $user; - proxy_set_header X-Email $email; - - # if you enabled --cookie-refresh, this is needed for it to work with auth_request - auth_request_set $auth_cookie $upstream_http_set_cookie; - add_header Set-Cookie $auth_cookie; + virtualHostExtraConfig ? "", + maxBodySize ? "500M", + port ? 3000, + upstream ? hostName, + protocol ? "http", + }: + { + upstreams.${hostName} = { + servers."${ipOf upstream}:${toString port}" = { }; + extraConfig = '' + zone ${hostName} 64k ; + keepalive 5 ; ''; - locations."/oauth2/" = { - proxyPass = "http://oauth2-proxy"; - extraConfig = '' - proxy_set_header X-Scheme $scheme; - proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; - ''; - }; - - locations."= /oauth2/auth" = { - proxyPass = "http://oauth2-proxy/oauth2/auth" + lib.optionalString allowedGroup "?allowed_groups=${hostName}_access"; - extraConfig = '' - internal; - - proxy_set_header X-Scheme $scheme; - # nginx auth_request includes headers but not body - proxy_set_header Content-Length ""; - proxy_pass_request_body off; - ''; - }; }; - } - ]; - in + virtualHosts.${domainOf hostName} = { + forceSSL = true; + useACMEHost = "web"; + locations."/" = { + proxyPass = "${protocol}://${hostName}"; + proxyWebsockets = true; + X-Frame-Options = "SAMEORIGIN"; + }; + extraConfig = + '' + client_max_body_size ${maxBodySize} ; + '' + + virtualHostExtraConfig; + }; + }; + proxyProtect = + hostName: cfg: allowedGroup: + lib.mkMerge [ + (blockOf hostName cfg) + { + virtualHosts.${domainOf hostName} = { + locations."/".extraConfig = '' + auth_request /oauth2/auth; + error_page 401 = /oauth2/sign_in; + + # pass information via X-User and X-Email headers to backend, + # requires running with --set-xauthrequest flag + auth_request_set $user $upstream_http_x_auth_request_preferred_username; + # Set the email to our own domain in case user change their mail + auth_request_set $email "''${upstream_http_x_auth_request_preferred_username}@${config.secrets.secrets.global.domains.web}"; + proxy_set_header X-User $user; + proxy_set_header X-Email $email; + + # if you enabled --cookie-refresh, this is needed for it to work with auth_request + auth_request_set $auth_cookie $upstream_http_set_cookie; + add_header Set-Cookie $auth_cookie; + ''; + locations."/oauth2/" = { + proxyPass = "http://oauth2-proxy"; + extraConfig = '' + proxy_set_header X-Scheme $scheme; + proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; + ''; + }; + + locations."= /oauth2/auth" = { + proxyPass = + "http://oauth2-proxy/oauth2/auth" + + lib.optionalString allowedGroup "?allowed_groups=${hostName}_access"; + extraConfig = '' + internal; + + proxy_set_header X-Scheme $scheme; + # nginx auth_request includes headers but not body + proxy_set_header Content-Length ""; + proxy_pass_request_body off; + ''; + }; + }; + } + ]; + in lib.mkMerge [ { enable = true; recommendedSetup = true; upstreams.netbird = { - servers."${ipOf "netbird"}:80" = {}; + servers."${ipOf "netbird"}:80" = { }; extraConfig = '' zone netbird 64k ; keepalive 5 ; ''; }; upstreams.netbird-mgmt = { - servers."${ipOf "netbird"}:3000" = {}; + servers."${ipOf "netbird"}:3000" = { }; extraConfig = '' zone netbird 64k ; keepalive 5 ; @@ -159,16 +173,16 @@ in { ''; }; } - (blockOf "vaultwarden" {maxBodySize = "1G";}) - (blockOf "forgejo" {maxBodySize = "1G";}) - (blockOf "immich" {maxBodySize = "5G";}) - (proxyProtect "adguardhome" {} true) - (proxyProtect "oauth2-proxy" {} false) - (blockOf "paperless" {maxBodySize = "5G";}) - (proxyProtect "ttrss" {port = 80;} true) - (blockOf "yourspotify" {port = 80;}) + (blockOf "vaultwarden" { maxBodySize = "1G"; }) + (blockOf "forgejo" { maxBodySize = "1G"; }) + (blockOf "immich" { maxBodySize = "5G"; }) + (proxyProtect "adguardhome" { } true) + (proxyProtect "oauth2-proxy" { } false) + (blockOf "paperless" { maxBodySize = "5G"; }) + (proxyProtect "ttrss" { port = 80; } true) + (blockOf "yourspotify" { port = 80; }) #(blockOf "homebox" {}) - (blockOf "pr-tracker" {}) + (blockOf "pr-tracker" { }) { virtualHosts.${domainOf "pr-tracker"} = { locations."/update" = { @@ -176,9 +190,9 @@ in { }; }; } - (proxyProtect "ollama" {} true) - (proxyProtect "octoprint" {} true) - (proxyProtect "firefly" {port = 80;} true) + (proxyProtect "ollama" { } true) + (proxyProtect "octoprint" { } true) + (proxyProtect "firefly" { port = 80; } true) (blockOf "apispotify" { port = 3000; upstream = "yourspotify"; @@ -187,71 +201,76 @@ in { maxBodySize = "5G"; port = 80; }) - (blockOf "kanidm" - { - protocol = "https"; - virtualHostExtraConfig = '' - proxy_ssl_verify off ; - ''; - }) + (blockOf "kanidm" { + protocol = "https"; + virtualHostExtraConfig = '' + proxy_ssl_verify off ; + ''; + }) ]; - guests = let - mkGuest = guestName: { - enablePanzer ? false, - enableRenaultFT ? false, - enableBunker ? false, - enableSharedPaperless ? false, - ... - }: { - autostart = true; - zfs."/state" = { - pool = "rpool"; - dataset = "local/guests/${guestName}"; - }; - zfs."/persist" = { - pool = "rpool"; - dataset = "safe/guests/${guestName}"; - }; - zfs."/panzer" = lib.mkIf enablePanzer { - pool = "panzer"; - dataset = "safe/guests/${guestName}"; - }; - zfs."/renaultft" = lib.mkIf enableRenaultFT { - pool = "renaultft"; - dataset = "safe/guests/${guestName}"; - }; - # kinda not necesarry should be removed on next reimaging - zfs."/bunker" = lib.mkIf enableBunker { - pool = "panzer"; - dataset = "bunker/guests/${guestName}"; - }; - zfs."/paperless" = lib.mkIf enableSharedPaperless { - pool = "panzer"; - dataset = "bunker/shared/paperless"; - }; - modules = [ - ../../config/basic - ../../config/services/${guestName}.nix + guests = + let + mkGuest = + guestName: { - node.secretsDir = config.node.secretsDir + "/${guestName}"; - networking.nftables.firewall.zones.untrusted.interfaces = [config.guests.${guestName}.networking.mainLinkName]; - systemd.network.networks."10-${config.guests.${guestName}.networking.mainLinkName}" = { - DHCP = lib.mkForce "no"; - address = [ - (lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips."${config.guests.${guestName}.nodeName}" config.secrets.secrets.global.net.privateSubnetv4) - (lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips."${config.guests.${guestName}.nodeName}" config.secrets.secrets.global.net.privateSubnetv6) - ]; - gateway = [(lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4)]; + enablePanzer ? false, + enableRenaultFT ? false, + enableBunker ? false, + enableSharedPaperless ? false, + ... + }: + { + autostart = true; + zfs."/state" = { + pool = "rpool"; + dataset = "local/guests/${guestName}"; }; - } - ]; - }; + zfs."/persist" = { + pool = "rpool"; + dataset = "safe/guests/${guestName}"; + }; + zfs."/panzer" = lib.mkIf enablePanzer { + pool = "panzer"; + dataset = "safe/guests/${guestName}"; + }; + zfs."/renaultft" = lib.mkIf enableRenaultFT { + pool = "renaultft"; + dataset = "safe/guests/${guestName}"; + }; + # kinda not necesarry should be removed on next reimaging + zfs."/bunker" = lib.mkIf enableBunker { + pool = "panzer"; + dataset = "bunker/guests/${guestName}"; + }; + zfs."/paperless" = lib.mkIf enableSharedPaperless { + pool = "panzer"; + dataset = "bunker/shared/paperless"; + }; + modules = [ + ../../config/basic + ../../config/services/${guestName}.nix + { + node.secretsDir = config.node.secretsDir + "/${guestName}"; + networking.nftables.firewall.zones.untrusted.interfaces = [ + config.guests.${guestName}.networking.mainLinkName + ]; + systemd.network.networks."10-${config.guests.${guestName}.networking.mainLinkName}" = { + DHCP = lib.mkForce "no"; + address = [ + (lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips."${config.guests.${guestName}.nodeName + }" config.secrets.secrets.global.net.privateSubnetv4) + (lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips."${config.guests.${guestName}.nodeName + }" config.secrets.secrets.global.net.privateSubnetv6) + ]; + gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ]; + }; + } + ]; + }; - mkMicrovm = guestName: cfg: { - ${guestName} = - mkGuest guestName cfg - // { + mkMicrovm = guestName: cfg: { + ${guestName} = mkGuest guestName cfg // { backend = "microvm"; microvm = { system = "x86_64-linux"; @@ -264,46 +283,42 @@ in { inherit inputs minimal stateVersion; }; }; - }; + }; - mkContainer = guestName: cfg: { - ${guestName} = - mkGuest guestName cfg - // { + mkContainer = guestName: cfg: { + ${guestName} = mkGuest guestName cfg // { backend = "container"; container.macvlan = "lan"; extraSpecialArgs = { - inherit lib nodes inputs minimal stateVersion; + inherit + lib + nodes + inputs + minimal + stateVersion + ; }; }; - }; - in - {} - // mkContainer "adguardhome" {} - // mkContainer "oauth2-proxy" {} - // mkContainer "vaultwarden" {} - // mkContainer "ddclient" {} - // mkContainer "ollama" {} - // mkContainer "murmur" {} + }; + in + { } + // mkContainer "adguardhome" { } + // mkContainer "oauth2-proxy" { } + // mkContainer "vaultwarden" { } + // mkContainer "ddclient" { } + // mkContainer "ollama" { } + // mkContainer "murmur" { } #// mkContainer "homebox" {} - // mkContainer "pr-tracker" {} - // mkContainer "ttrss" {} - // mkContainer "firefly" {} - // mkContainer "yourspotify" {} - // mkContainer "netbird" {} - // mkContainer "kanidm" {} - // mkContainer "nextcloud" { - enablePanzer = true; - } - // mkContainer "paperless" { - enableSharedPaperless = true; - } - // mkContainer "forgejo" { - enablePanzer = true; - } - // mkMicrovm "immich" { - enablePanzer = true; - } + // mkContainer "pr-tracker" { } + // mkContainer "ttrss" { } + // mkContainer "firefly" { } + // mkContainer "yourspotify" { } + // mkContainer "netbird" { } + // mkContainer "kanidm" { } + // mkContainer "nextcloud" { enablePanzer = true; } + // mkContainer "paperless" { enableSharedPaperless = true; } + // mkContainer "forgejo" { enablePanzer = true; } + // mkMicrovm "immich" { enablePanzer = true; } // mkContainer "samba" { enablePanzer = true; enableRenaultFT = true; diff --git a/hosts/elisabeth/net.nix b/hosts/elisabeth/net.nix index ee27741..0197c49 100644 --- a/hosts/elisabeth/net.nix +++ b/hosts/elisabeth/net.nix @@ -1,15 +1,16 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { networking = { inherit (config.secrets.secrets.local.networking) hostId; }; systemd.network.networks = { "10-lan01" = { - address = [(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv4)]; - gateway = [(lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4)]; + address = [ + (lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name} + config.secrets.secrets.global.net.privateSubnetv4 + ) + ]; + gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ]; #matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac; matchConfig.Name = "lan"; dhcpV6Config.UseDNS = false; @@ -33,8 +34,12 @@ networks = { # redo the network cause the livesystem has macvlans "10-lan01" = { - address = [(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv4)]; - gateway = [(lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4)]; + address = [ + (lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name} + config.secrets.secrets.global.net.privateSubnetv4 + ) + ]; + gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ]; matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac; dhcpV6Config.UseDNS = false; dhcpV4Config.UseDNS = false; @@ -46,11 +51,16 @@ }; }; }; - networking.nftables.firewall.zones.untrusted.interfaces = ["lan"]; + networking.nftables.firewall.zones.untrusted.interfaces = [ "lan" ]; wireguard.elisabeth.server = { - host = lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv4; - reservedAddresses = ["10.42.0.0/20" "fd00:1764::/112"]; + host = + lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} + config.secrets.secrets.global.net.privateSubnetv4; + reservedAddresses = [ + "10.42.0.0/20" + "fd00:1764::/112" + ]; openFirewall = true; }; # To be able to ping containers from the host, it is necessary @@ -71,7 +81,7 @@ email = config.secrets.secrets.global.devEmail; dnsProvider = "cloudflare"; dnsPropagationCheck = true; - reloadServices = ["nginx"]; + reloadServices = [ "nginx" ]; credentialFiles = { "CF_DNS_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path; "CF_ZONE_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path; @@ -80,9 +90,9 @@ }; security.acme.certs.web = { domain = config.secrets.secrets.global.domains.web; - extraDomainNames = ["*.${config.secrets.secrets.global.domains.web}"]; + extraDomainNames = [ "*.${config.secrets.secrets.global.domains.web}" ]; }; - users.groups.acme.members = ["nginx"]; + users.groups.acme.members = [ "nginx" ]; environment.persistence."/state".directories = [ { directory = "/var/lib/acme"; diff --git a/hosts/maddy/default.nix b/hosts/maddy/default.nix index 17ee751..a345ced 100644 --- a/hosts/maddy/default.nix +++ b/hosts/maddy/default.nix @@ -9,6 +9,11 @@ ./fs.nix ]; boot.mode = "bios"; - boot.initrd.availableKernelModules = ["virtio_pci" "virtio_net" "virtio_scsi" "virtio_blk"]; + boot.initrd.availableKernelModules = [ + "virtio_pci" + "virtio_net" + "virtio_scsi" + "virtio_blk" + ]; nixpkgs.hostPlatform = "x86_64-linux"; } diff --git a/hosts/maddy/fs.nix b/hosts/maddy/fs.nix index 0caa2d7..c4a72bb 100644 --- a/hosts/maddy/fs.nix +++ b/hosts/maddy/fs.nix @@ -1,8 +1,5 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { disko.devices = { disk = { drive = rec { @@ -11,9 +8,15 @@ content = with lib.disko.gpt; { type = "gpt"; partitions = { - grub = partGrub // {device = "${device}-part1";}; - bios = (partEfi "512MiB") // {device = "${device}-part2";}; - rpool = (partLuksZfs "rpool" "rpool" "100%") // {device = "${device}-part3";}; + grub = partGrub // { + device = "${device}-part1"; + }; + bios = (partEfi "512MiB") // { + device = "${device}-part2"; + }; + rpool = (partLuksZfs "rpool" "rpool" "100%") // { + device = "${device}-part3"; + }; #(lib.attrsets.recursiveUpdate (partLuksZfs "rpool" "rpool" "17GiB" "100%") {content.extraFormatArgs = ["--pbkdf pbkdf2"];}) }; }; @@ -21,13 +24,11 @@ }; zpool = with lib.disko.zfs; { - rpool = mkZpool {datasets = impermanenceZfsDatasets;}; + rpool = mkZpool { datasets = impermanenceZfsDatasets; }; }; }; fileSystems."/state".neededForBoot = true; fileSystems."/persist".neededForBoot = true; - boot.loader.grub.devices = [ - "/dev/disk/by-id/${config.secrets.secrets.local.disko.drive}" - ]; + boot.loader.grub.devices = [ "/dev/disk/by-id/${config.secrets.secrets.local.disko.drive}" ]; } diff --git a/hosts/maddy/net.nix b/hosts/maddy/net.nix index a733a9c..79b2975 100644 --- a/hosts/maddy/net.nix +++ b/hosts/maddy/net.nix @@ -1,36 +1,37 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { networking.hostId = config.secrets.secrets.local.networking.hostId; networking.domain = config.secrets.secrets.global.domains.mail_public; boot.initrd.systemd.network = { enable = true; - networks = {inherit (config.systemd.network.networks) "lan01";}; + networks = { + inherit (config.systemd.network.networks) "lan01"; + }; }; systemd.network.networks = { - "lan01" = let - icfg = config.secrets.secrets.local.networking.interfaces.lan01; - in { - address = [ - icfg.hostCidrv4 - (lib.net.cidr.hostCidr 1 icfg.hostCidrv6) - ]; - gateway = ["fe80::1"]; - routes = [ - {Destination = "172.31.1.1";} - { - Gateway = "172.31.1.1"; - GatewayOnLink = true; - } - ]; - matchConfig.MACAddress = icfg.mac; - networkConfig.IPv6PrivacyExtensions = "yes"; - linkConfig.RequiredForOnline = "routable"; - }; + "lan01" = + let + icfg = config.secrets.secrets.local.networking.interfaces.lan01; + in + { + address = [ + icfg.hostCidrv4 + (lib.net.cidr.hostCidr 1 icfg.hostCidrv6) + ]; + gateway = [ "fe80::1" ]; + routes = [ + { Destination = "172.31.1.1"; } + { + Gateway = "172.31.1.1"; + GatewayOnLink = true; + } + ]; + matchConfig.MACAddress = icfg.mac; + networkConfig.IPv6PrivacyExtensions = "yes"; + linkConfig.RequiredForOnline = "routable"; + }; }; age.secrets.cloudflare_token_acme = { rekeyFile = ./secrets/cloudflare_api_token.age; @@ -43,25 +44,25 @@ email = config.secrets.secrets.global.devEmail; dnsProvider = "cloudflare"; dnsPropagationCheck = true; - reloadServices = ["nginx"]; + reloadServices = [ "nginx" ]; credentialFiles = { "CF_DNS_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path; "CF_ZONE_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path; }; }; }; - networking.nftables.firewall.zones.untrusted.interfaces = ["lan01"]; + networking.nftables.firewall.zones.untrusted.interfaces = [ "lan01" ]; security.acme.certs = { mail_public = { domain = config.secrets.secrets.global.domains.mail_public; - extraDomainNames = ["*.${config.secrets.secrets.global.domains.mail_public}"]; + extraDomainNames = [ "*.${config.secrets.secrets.global.domains.mail_public}" ]; }; mail_private = { domain = config.secrets.secrets.global.domains.mail_private; - extraDomainNames = ["*.${config.secrets.secrets.global.domains.mail_private}"]; + extraDomainNames = [ "*.${config.secrets.secrets.global.domains.mail_private}" ]; }; }; - users.groups.acme.members = ["maddy"]; + users.groups.acme.members = [ "maddy" ]; environment.persistence."/state".directories = [ { directory = "/var/lib/acme"; diff --git a/hosts/octoprint/default.nix b/hosts/octoprint/default.nix index 1241577..4f7477e 100644 --- a/hosts/octoprint/default.nix +++ b/hosts/octoprint/default.nix @@ -1,8 +1,5 @@ +{ inputs, lib, ... }: { - inputs, - lib, - ... -}: { imports = [ ../../config/basic ../../config/services/octoprint.nix diff --git a/hosts/octoprint/fs.nix b/hosts/octoprint/fs.nix index ad6f92c..2b8a58e 100644 --- a/hosts/octoprint/fs.nix +++ b/hosts/octoprint/fs.nix @@ -1,9 +1,10 @@ -{lib, ...}: { +{ lib, ... }: +{ fileSystems = lib.mkForce { "/" = { device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888"; fsType = "ext4"; }; }; - environment.persistence = lib.mkForce {}; + environment.persistence = lib.mkForce { }; } diff --git a/hosts/octoprint/net.nix b/hosts/octoprint/net.nix index 93c7ce7..5a77ad4 100644 --- a/hosts/octoprint/net.nix +++ b/hosts/octoprint/net.nix @@ -1,4 +1,5 @@ -{config, ...}: { +{ config, ... }: +{ networking = { inherit (config.secrets.secrets.local.networking) hostId; wireless.iwd = { diff --git a/hosts/patricknix/default.nix b/hosts/patricknix/default.nix index 8525fa6..0aea02d 100644 --- a/hosts/patricknix/default.nix +++ b/hosts/patricknix/default.nix @@ -1,8 +1,5 @@ +{ inputs, lib, ... }: { - inputs, - lib, - ... -}: { imports = [ inputs.nixos-hardware.nixosModules.common-cpu-intel # for some reasons the cpu-intel includes the gpu as well @@ -45,11 +42,12 @@ layout = "de"; }; libinput = { - touchpad = lib.mkForce { - accelSpeed = "0.5"; - }; + touchpad = lib.mkForce { accelSpeed = "0.5"; }; }; }; nixpkgs.hostPlatform = "x86_64-linux"; - nix.settings.system-features = ["kvm" "nixos-test"]; + nix.settings.system-features = [ + "kvm" + "nixos-test" + ]; } diff --git a/hosts/patricknix/fs.nix b/hosts/patricknix/fs.nix index 1422909..3a255e9 100644 --- a/hosts/patricknix/fs.nix +++ b/hosts/patricknix/fs.nix @@ -1,8 +1,5 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { disko.devices = { disk = { m2-ssd = rec { @@ -11,15 +8,21 @@ content = with lib.disko.gpt; { type = "gpt"; partitions = { - boot = (partEfi "1GiB") // {device = "${device}-part1";}; - swap = (partSwap "16GiB") // {device = "${device}-part2";}; - rpool = (partLuksZfs "rpool" "rpool" "100%") // {device = "${device}-part3";}; + boot = (partEfi "1GiB") // { + device = "${device}-part1"; + }; + swap = (partSwap "16GiB") // { + device = "${device}-part2"; + }; + rpool = (partLuksZfs "rpool" "rpool" "100%") // { + device = "${device}-part3"; + }; }; }; }; }; zpool = with lib.disko.zfs; { - rpool = mkZpool {datasets = impermanenceZfsDatasets;}; + rpool = mkZpool { datasets = impermanenceZfsDatasets; }; }; }; fileSystems."/state".neededForBoot = true; diff --git a/hosts/patricknix/net.nix b/hosts/patricknix/net.nix index ef25c8a..acbacf8 100644 --- a/hosts/patricknix/net.nix +++ b/hosts/patricknix/net.nix @@ -1,4 +1,5 @@ -{config, ...}: { +{ config, ... }: +{ age.secrets.eduroam = { rekeyFile = ./secrets/iwd/eduroam.8021x.age; path = "/var/lib/iwd/eduroam.8021x"; @@ -10,7 +11,11 @@ devoloog-sae20.rekeyFile = ./secrets/iwd/devoloog-sae20.age; }; wireguard.samba-patrick.client.via = "elisabeth-samba"; - networking.nftables.firewall.zones.untrusted.interfaces = ["lan01" "lan02" "wlan01"]; + networking.nftables.firewall.zones.untrusted.interfaces = [ + "lan01" + "lan02" + "wlan01" + ]; networking = { inherit (config.secrets.secrets.local.networking) hostId; wireless.iwd = { @@ -36,7 +41,7 @@ IPv6PrivacyExtensions = "yes"; MulticastDNS = true; }; - dns = ["1.1.1.1"]; + dns = [ "1.1.1.1" ]; dhcpV4Config.RouteMetric = 10; dhcpV6Config.RouteMetric = 10; }; @@ -47,7 +52,7 @@ IPv6PrivacyExtensions = "yes"; MulticastDNS = true; }; - dns = ["1.1.1.1"]; + dns = [ "1.1.1.1" ]; dhcpV4Config.RouteMetric = 10; dhcpV6Config.RouteMetric = 10; }; @@ -58,7 +63,7 @@ IPv6PrivacyExtensions = "yes"; MulticastDNS = true; }; - dns = ["1.1.1.1"]; + dns = [ "1.1.1.1" ]; dhcpV4Config.RouteMetric = 40; dhcpV6Config.RouteMetric = 40; }; diff --git a/lib/default.nix b/lib/default.nix index e5ad4a1..ac518f2 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,3 +1 @@ -inputs: [ - (import ./misc.nix inputs) -] +inputs: [ (import ./misc.nix inputs) ] diff --git a/lib/misc.nix b/lib/misc.nix index 7b262be..44a8994 100644 --- a/lib/misc.nix +++ b/lib/misc.nix @@ -1,11 +1,9 @@ -_inputs: _self: super: let +_inputs: _self: super: +let writeText = text: (super.writeText (builtins.hashString "sha256" "${text}") "${text}"); -in { - lib = - super.lib - // { - inherit - writeText - ; - }; +in +{ + lib = super.lib // { + inherit writeText; + }; } diff --git a/modules-hm/images.nix b/modules-hm/images.nix index a8d2f01..065214d 100644 --- a/modules-hm/images.nix +++ b/modules-hm/images.nix @@ -1,10 +1,6 @@ -{ - lib, - config, - ... -}: let - inherit - (lib) +{ lib, config, ... }: +let + inherit (lib) mkEnableOption mkMerge attrNames @@ -18,7 +14,8 @@ mapAttrs' listToAttrs ; -in { +in +{ home-manager.sharedModules = [ { options.images = { @@ -39,26 +36,25 @@ in { imports = [ ( - {config, ...}: { + { config, ... }: + { age.secrets = mkMerge ( - flip map - (attrNames config.home-manager.users) - ( + flip map (attrNames config.home-manager.users) ( user: - mkIf config.home-manager.users.${user}.images.enable ( - listToAttrs (flip map (attrNames (filterAttrs (_: type: type == "regular") (builtins.readDir ../secrets/img))) - ( - file: { - name = "images-${user}-${file}"; - value = { - name = removeSuffix ".age" file; - rekeyFile = ../secrets/img/${file}; - owner = user; - group = user; - }; - } - )) + mkIf config.home-manager.users.${user}.images.enable ( + listToAttrs ( + flip map (attrNames (filterAttrs (_: type: type == "regular") (builtins.readDir ../secrets/img))) + (file: { + name = "images-${user}-${file}"; + value = { + name = removeSuffix ".age" file; + rekeyFile = ../secrets/img/${file}; + owner = user; + group = user; + }; + }) ) + ) ) ); } diff --git a/modules-hm/impermanence.nix b/modules-hm/impermanence.nix index cfff0cc..c361065 100644 --- a/modules-hm/impermanence.nix +++ b/modules-hm/impermanence.nix @@ -1,10 +1,6 @@ -{ - config, - lib, - ... -}: let - inherit - (lib) +{ config, lib, ... }: +let + inherit (lib) flip mapAttrs attrNames @@ -13,7 +9,8 @@ mkMerge isAttrs ; -in { +in +{ # Expose a home manager module for each user that allows extending # environment.persistence.${sourceDir}.users.${userName} simply by # specifying home.persistence.${sourceDir} in home manager. @@ -21,74 +18,63 @@ in { { options.home.persistence = mkOption { description = "Additional persistence config for the given source path"; - default = {}; - type = types.attrsOf (types.submodule { - options = { - files = mkOption { - description = "Additional files to persist via NixOS impermanence."; - type = types.listOf (types.either types.attrs types.str); - default = []; - }; + default = { }; + type = types.attrsOf ( + types.submodule { + options = { + files = mkOption { + description = "Additional files to persist via NixOS impermanence."; + type = types.listOf (types.either types.attrs types.str); + default = [ ]; + }; - directories = mkOption { - description = "Additional directories to persist via NixOS impermanence."; - type = types.listOf (types.either types.attrs types.str); - default = []; + directories = mkOption { + description = "Additional directories to persist via NixOS impermanence."; + type = types.listOf (types.either types.attrs types.str); + default = [ ]; + }; }; - }; - }); + } + ); }; } ]; # For each user that has a home-manager config, merge the locally defined # persistence options that we defined above. - imports = let - mkUserFiles = map (x: - {parentDirectory.mode = "700";} - // ( - if isAttrs x - then x - else {file = x;} - )); - mkUserDirs = map (x: - {mode = "700";} - // ( - if isAttrs x - then x - else {directory = x;} - )); - in [ - { - environment.persistence = mkMerge ( - flip map - (attrNames config.home-manager.users) - ( - user: let - hmUserCfg = config.home-manager.users.${user}; - in - flip mapAttrs hmUserCfg.home.persistence - (_: sourceCfg: { - users.${user} = { - # This needs to be set for allo users with non - # standart home (not /home/ - # due to nixpkgs it - # can't be deduced from homeDirectory - # as there will be infinite recursion - # If this setting is forgotten there - # are assertions in place warning you - home = - { - root = "/root"; - } - .${user} - or "/home/${user}"; - files = mkUserFiles sourceCfg.files; - directories = mkUserDirs sourceCfg.directories; - }; - }) - ) + imports = + let + mkUserFiles = map ( + x: { parentDirectory.mode = "700"; } // (if isAttrs x then x else { file = x; }) ); - } - ]; + mkUserDirs = map (x: { mode = "700"; } // (if isAttrs x then x else { directory = x; })); + in + [ + { + environment.persistence = mkMerge ( + flip map (attrNames config.home-manager.users) ( + user: + let + hmUserCfg = config.home-manager.users.${user}; + in + flip mapAttrs hmUserCfg.home.persistence ( + _: sourceCfg: { + users.${user} = { + # This needs to be set for allo users with non + # standart home (not /home/ + # due to nixpkgs it + # can't be deduced from homeDirectory + # as there will be infinite recursion + # If this setting is forgotten there + # are assertions in place warning you + home = { root = "/root"; }.${user} or "/home/${user}"; + files = mkUserFiles sourceCfg.files; + directories = mkUserDirs sourceCfg.directories; + }; + } + ) + ) + ); + } + ]; } diff --git a/modules-hm/streamdeck.nix b/modules-hm/streamdeck.nix index 221a412..3f0264a 100644 --- a/modules-hm/streamdeck.nix +++ b/modules-hm/streamdeck.nix @@ -1,58 +1,59 @@ -{ - lib, - pkgs, - ... -}: let - inherit - (lib) +{ lib, pkgs, ... }: +let + inherit (lib) types mkEnableOption mkPackageOption mkOption mkIf ; - settingsFormat = pkgs.formats.json {}; -in { + settingsFormat = pkgs.formats.json { }; +in +{ home-manager.sharedModules = [ - ({config, ...}: let - cfg = settingsFormat.generate "config.json" { - streamdeck_ui_version = 2; - state = config.programs.streamdeck-ui.settings; - }; - preStart = pkgs.writeShellScript "streamdeck-setup-config" '' - ${pkgs.coreutils}/bin/cp "${cfg}" "$XDG_RUNTIME_DIR/streamdeck/config.json" - ''; - in { - options.programs.streamdeck-ui = { - enable = mkEnableOption "streamdeck-ui"; - package = mkPackageOption pkgs "streamdeck-ui" {}; - settings = mkOption { - default = {}; - type = types.submodule {freeformType = settingsFormat.type;}; - description = "Configuration per streamdeck"; + ( + { config, ... }: + let + cfg = settingsFormat.generate "config.json" { + streamdeck_ui_version = 2; + state = config.programs.streamdeck-ui.settings; }; - }; - config = mkIf config.programs.streamdeck-ui.enable { - systemd.user = { - services = { - streamdeck = { - Unit = { - Description = "start streamdeck-ui"; - # For some reason this depends on X or wayland running - ConditionEnvironment = ["DISPLAY"]; + preStart = pkgs.writeShellScript "streamdeck-setup-config" '' + ${pkgs.coreutils}/bin/cp "${cfg}" "$XDG_RUNTIME_DIR/streamdeck/config.json" + ''; + in + { + options.programs.streamdeck-ui = { + enable = mkEnableOption "streamdeck-ui"; + package = mkPackageOption pkgs "streamdeck-ui" { }; + settings = mkOption { + default = { }; + type = types.submodule { freeformType = settingsFormat.type; }; + description = "Configuration per streamdeck"; + }; + }; + config = mkIf config.programs.streamdeck-ui.enable { + systemd.user = { + services = { + streamdeck = { + Unit = { + Description = "start streamdeck-ui"; + # For some reason this depends on X or wayland running + ConditionEnvironment = [ "DISPLAY" ]; + }; + Service = { + Type = "exec"; + ExecStart = "${pkgs.streamdeck-ui}/bin/streamdeck --no-ui"; + ExecStartPre = preStart; + Environment = ''STREAMDECK_UI_CONFIG=%t/streamdeck/config.json''; + RuntimeDirectory = "streamdeck"; + }; + Install.WantedBy = [ "graphical-session.target" ]; }; - Service = { - Type = "exec"; - ExecStart = "${pkgs.streamdeck-ui}/bin/streamdeck --no-ui"; - ExecStartPre = preStart; - Environment = ''STREAMDECK_UI_CONFIG=%t/streamdeck/config.json''; - RuntimeDirectory = "streamdeck"; - }; - Install.WantedBy = ["graphical-session.target"]; }; }; }; - }; - }) + } + ) ]; } diff --git a/modules/actual.nix b/modules/actual.nix index 1041ec8..a805513 100644 --- a/modules/actual.nix +++ b/modules/actual.nix @@ -3,9 +3,9 @@ pkgs, config, ... -}: let - inherit - (lib) +}: +let + inherit (lib) types mkEnableOption mkPackageOption @@ -15,13 +15,14 @@ cfg = config.services.actual; configFile = formatType.generate "config.json" cfg.settings; - formatType = pkgs.formats.json {}; -in { + formatType = pkgs.formats.json { }; +in +{ options.services.actual = { enable = mkEnableOption "actual, a privacy focused app for managing your finances"; - package = mkPackageOption pkgs "actual" {}; + package = mkPackageOption pkgs "actual" { }; settings = mkOption { - default = {}; + default = { }; type = types.submodule { freeformType = formatType.type; config = { @@ -33,7 +34,7 @@ in { }; }; config.systemd.services.actual = { - after = ["network.target"]; + after = [ "network.target" ]; environment.ACTUAL_CONFIG_PATH = configFile; serviceConfig = { ExecStartPre = "${pkgs.coreutils}/bin/ln -sf ${cfg.package}/migrations /var/lib/actual/"; @@ -78,6 +79,6 @@ in { ]; UMask = "0077"; }; - wantedBy = ["multi-user.target"]; + wantedBy = [ "multi-user.target" ]; }; } diff --git a/modules/deterministic-ids.nix b/modules/deterministic-ids.nix index 65d931c..bd7422d 100644 --- a/modules/deterministic-ids.nix +++ b/modules/deterministic-ids.nix @@ -1,10 +1,6 @@ -{ - lib, - config, - ... -}: let - inherit - (lib) +{ lib, config, ... }: +let + inherit (lib) concatLists flip mapAttrsToList @@ -16,65 +12,86 @@ ; cfg = config.users.deterministicIds; -in { +in +{ options = { users.deterministicIds = mkOption { - default = {}; + default = { }; description = mdDoc '' Maps a user or group name to its expected uid/gid values. If a user/group is used on the system without specifying a uid/gid, this module will assign the corresponding ids defined here, or show an error if the definition is missing. ''; - type = types.attrsOf (types.submodule { - options = { - uid = mkOption { - type = types.nullOr types.int; - default = null; - description = mdDoc "The uid to assign if it is missing in `users.users.`."; + type = types.attrsOf ( + types.submodule { + options = { + uid = mkOption { + type = types.nullOr types.int; + default = null; + description = mdDoc "The uid to assign if it is missing in `users.users.`."; + }; + gid = mkOption { + type = types.nullOr types.int; + default = null; + description = mdDoc "The gid to assign if it is missing in `users.groups.`."; + }; }; - gid = mkOption { - type = types.nullOr types.int; - default = null; - description = mdDoc "The gid to assign if it is missing in `users.groups.`."; - }; - }; - }); + } + ); }; users.users = mkOption { - type = types.attrsOf (types.submodule ({name, ...}: { - config.uid = let - deterministicUid = cfg.${name}.uid or null; - in - mkIf (deterministicUid != null) (mkDefault deterministicUid); - })); + type = types.attrsOf ( + types.submodule ( + { name, ... }: + { + config.uid = + let + deterministicUid = cfg.${name}.uid or null; + in + mkIf (deterministicUid != null) (mkDefault deterministicUid); + } + ) + ); }; users.groups = mkOption { - type = types.attrsOf (types.submodule ({name, ...}: { - config.gid = let - deterministicGid = cfg.${name}.gid or null; - in - mkIf (deterministicGid != null) (mkDefault deterministicGid); - })); + type = types.attrsOf ( + types.submodule ( + { name, ... }: + { + config.gid = + let + deterministicGid = cfg.${name}.gid or null; + in + mkIf (deterministicGid != null) (mkDefault deterministicGid); + } + ) + ); }; }; config = { assertions = - concatLists (flip mapAttrsToList config.users.users (name: user: [ - { - assertion = user.uid != null; - message = "non-deterministic uid detected for '${name}', please assign one via `users.deterministicIds`"; + concatLists ( + flip mapAttrsToList config.users.users ( + name: user: [ + { + assertion = user.uid != null; + message = "non-deterministic uid detected for '${name}', please assign one via `users.deterministicIds`"; + } + { + assertion = !user.autoSubUidGidRange; + message = "non-deterministic subUids/subGids detected for: ${name}"; + } + ] + ) + ) + ++ flip mapAttrsToList config.users.groups ( + name: group: { + assertion = group.gid != null; + message = "non-deterministic gid detected for '${name}', please assign one via `users.deterministicIds`"; } - { - assertion = !user.autoSubUidGidRange; - message = "non-deterministic subUids/subGids detected for: ${name}"; - } - ])) - ++ flip mapAttrsToList config.users.groups (name: group: { - assertion = group.gid != null; - message = "non-deterministic gid detected for '${name}', please assign one via `users.deterministicIds`"; - }); + ); }; } diff --git a/modules/distributed-config.nix b/modules/distributed-config.nix index c1f8d2a..6e98b6b 100644 --- a/modules/distributed-config.nix +++ b/modules/distributed-config.nix @@ -3,9 +3,9 @@ lib, nodes, ... -}: let - inherit - (lib) +}: +let + inherit (lib) attrNames concatMap concatStringsSep @@ -21,16 +21,20 @@ ; nodeName = config.node.name; - mkForwardedOption = path: + mkForwardedOption = + path: mkOption { type = mkOptionType { name = "Same type that the receiving option `${concatStringsSep "." path}` normally accepts."; - merge = _loc: defs: - builtins.filter - (x: builtins.isAttrs x -> ((x._type or "") != "__distributed_config_empty")) - (map (x: x.value) defs); + merge = + _loc: defs: + builtins.filter (x: builtins.isAttrs x -> ((x._type or "") != "__distributed_config_empty")) ( + map (x: x.value) defs + ); + }; + default = { + _type = "__distributed_config_empty"; }; - default = {_type = "__distributed_config_empty";}; description = '' Anything specified here will be forwarded to `${concatStringsSep "." path}` on the given node. Forwarding happens as-is to the raw values, @@ -39,28 +43,39 @@ }; forwardedOptions = [ - ["age" "secrets"] - ["services" "maddy" "ensureCredentials"] + [ + "age" + "secrets" + ] + [ + "services" + "maddy" + "ensureCredentials" + ] ]; - attrsForEachOption = f: (foldl' (acc: path: recursiveUpdate acc (setAttrByPath path (f path))) {} forwardedOptions); -in { + attrsForEachOption = + f: (foldl' (acc: path: recursiveUpdate acc (setAttrByPath path (f path))) { } forwardedOptions); +in +{ options.nodes = mkOption { description = "Options forwareded to the given node."; - default = {}; - type = types.attrsOf (types.submodule { - options = attrsForEachOption mkForwardedOption; - }); + default = { }; + type = types.attrsOf (types.submodule { options = attrsForEachOption mkForwardedOption; }); }; - config = let - mergeConfigFromOthers = let - getConfig = path: otherNode: let - cfg = nodes.${otherNode}.config.nodes.${nodeName} or null; - in - optionals (cfg != null) (getAttrFromPath path cfg); + config = + let + mergeConfigFromOthers = + let + getConfig = + path: otherNode: + let + cfg = nodes.${otherNode}.config.nodes.${nodeName} or null; + in + optionals (cfg != null) (getAttrFromPath path cfg); + in + path: mkMerge (concatMap (getConfig path) (attrNames nodes)); in - path: mkMerge (concatMap (getConfig path) (attrNames nodes)); - in attrsForEachOption mergeConfigFromOthers; } diff --git a/modules/homebox.nix b/modules/homebox.nix index 4c5bbb9..ec2804e 100644 --- a/modules/homebox.nix +++ b/modules/homebox.nix @@ -3,20 +3,21 @@ config, pkgs, ... -}: let +}: +let cfg = config.services.homebox; - inherit - (lib) + inherit (lib) mkEnableOption mkPackageOption mkDefault types mkIf ; -in { +in +{ options.services.homebox = { enable = mkEnableOption "homebox"; - package = mkPackageOption pkgs "homebox" {}; + package = mkPackageOption pkgs "homebox" { }; settings = lib.mkOption { type = types.attrsOf types.str; defaultText = '' @@ -39,7 +40,7 @@ in { HBOX_MODE = mkDefault "production"; }; systemd.services.homebox = { - after = ["network.target"]; + after = [ "network.target" ]; environment = cfg.settings; serviceConfig = { User = "homebox"; @@ -86,8 +87,8 @@ in { # System Call Filtering UMask = "0077"; }; - wantedBy = ["multi-user.target"]; + wantedBy = [ "multi-user.target" ]; }; }; - meta.maintainers = with lib.maintainers; [patrickdag]; + meta.maintainers = with lib.maintainers; [ patrickdag ]; } diff --git a/modules/iwd.nix b/modules/iwd.nix index 30ec23d..373da62 100644 --- a/modules/iwd.nix +++ b/modules/iwd.nix @@ -3,103 +3,141 @@ pkgs, config, ... -}: { - options.networking.wireless.iwd = let - inherit - (lib) - mkOption - literalExample - types - hasAttrByPath - ; - in { - networks = mkOption { - default = {}; - example = literalExample '' - { "karlsruhe.freifunk.net" = {}; - }; - ''; - - description = '' - Declarative configuration of wifi networks for - iwd8. - - All networks will be stored in - /var/lib/iwd/<name>.<type>. - - Since each network is stored in its own file, declarative networks can be used in an - environment with imperatively added networks via - iwctl1. - ''; - - type = types.attrsOf (types.submodule ({config, ...}: { - config.kind = - if (hasAttrByPath ["Security" "Passphrase"] config.settings) - then "psk" - else if !(hasAttrByPath ["Security"] config.settings) - then "open" - else "8021x"; - - options = { - kind = mkOption { - type = types.enum ["open" "psk" "8021x"]; - description = "The type of network. This will determine the file ending. The module will try to determine this automatically so this should only be set when the heuristics fail."; +}: +{ + options.networking.wireless.iwd = + let + inherit (lib) + mkOption + literalExample + types + hasAttrByPath + ; + in + { + networks = mkOption { + default = { }; + example = literalExample '' + { "karlsruhe.freifunk.net" = {}; }; - settings = mkOption { - type = with types; (attrsOf (attrsOf (oneOf [str path]))); - description = '' - Contents of the iwd config file for this network - The lowest level values should be files, that will be read into the config files - ''; - default = {}; - }; - }; - })); - }; - }; - - config = let - inherit - (lib) - mkIf - flip - mapAttrsToList - concatStringsSep - ; - cfg = config.networking.wireless.iwd; - - encoder = pkgs.writeScriptBin "encoder" '' - #! ${pkgs.runtimeShell} -e - - # Extract file-ext from network names - ext="$(sed -re 's/.*\.(8021x|open|psk)$/\1/' <<< "$*")" - to_enc="$(sed -re "s/(.*)\.$ext/\1/g" <<< "$*")" - - # Encode ssid (excluding file-extensio) as base64 if needed - [[ "$to_enc" =~ ^[[:alnum:]]+$ ]] && { echo "$to_enc.$ext"; exit 0; } - echo "=$(printf "$to_enc" | ${pkgs.unixtools.xxd}/bin/xxd -pu).$ext" - ''; - in - mkIf cfg.enable { - systemd.services.iwd = mkIf (cfg.networks != {}) { - path = [encoder]; - preStart = let - dataDir = "/var/lib/iwd"; - in '' - # Create config files for declaratively defined networks in the NixOS config. - ${concatStringsSep "\n" (flip mapAttrsToList cfg.networks (network: config: '' - filename=${dataDir}/"$(encoder '${network}.${config.kind}')" - touch "$filename" - cat >$filename <iwd8. + + All networks will be stored in + /var/lib/iwd/<name>.<type>. + + Since each network is stored in its own file, declarative networks can be used in an + environment with imperatively added networks via + iwctl1. + ''; + + type = types.attrsOf ( + types.submodule ( + { config, ... }: + { + config.kind = + if + (hasAttrByPath [ + "Security" + "Passphrase" + ] config.settings) + then + "psk" + else if !(hasAttrByPath [ "Security" ] config.settings) then + "open" + else + "8021x"; + + options = { + kind = mkOption { + type = types.enum [ + "open" + "psk" + "8021x" + ]; + description = "The type of network. This will determine the file ending. The module will try to determine this automatically so this should only be set when the heuristics fail."; + }; + settings = mkOption { + type = + with types; + (attrsOf ( + attrsOf (oneOf [ + str + path + ]) + )); + description = '' + Contents of the iwd config file for this network + The lowest level values should be files, that will be read into the config files + ''; + default = { }; + }; + }; + } + ) + ); + }; + }; + + config = + let + inherit (lib) + mkIf + flip + mapAttrsToList + concatStringsSep + ; + cfg = config.networking.wireless.iwd; + + encoder = pkgs.writeScriptBin "encoder" '' + #! ${pkgs.runtimeShell} -e + + # Extract file-ext from network names + ext="$(sed -re 's/.*\.(8021x|open|psk)$/\1/' <<< "$*")" + to_enc="$(sed -re "s/(.*)\.$ext/\1/g" <<< "$*")" + + # Encode ssid (excluding file-extensio) as base64 if needed + [[ "$to_enc" =~ ^[[:alnum:]]+$ ]] && { echo "$to_enc.$ext"; exit 0; } + echo "=$(printf "$to_enc" | ${pkgs.unixtools.xxd}/bin/xxd -pu).$ext" + ''; + in + mkIf cfg.enable { + systemd.services.iwd = mkIf (cfg.networks != { }) { + path = [ encoder ]; + preStart = + let + dataDir = "/var/lib/iwd"; + in + '' + # Create config files for declaratively defined networks in the NixOS config. + ${concatStringsSep "\n" ( + flip mapAttrsToList cfg.networks ( + network: config: '' + filename=${dataDir}/"$(encoder '${network}.${config.kind}')" + touch "$filename" + cat >$filename </dev/null; then - echo "Failed to recover idm_admin account" >&2 - exit 1 - fi - '' - else '' - # Recover idm_admin account - if ! recover_out=$(${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin -o json); then - echo "$recover_out" >&2 - echo "kanidm provision: Failed to recover admin account" >&2 - exit 1 - fi - if ! KANIDM_IDM_ADMIN_PASSWORD=$(grep '{"password' <<< "$recover_out" | ${getExe pkgs.jq} -r .password); then - echo "$recover_out" >&2 - echo "kanidm provision: Failed to parse password for idm_admin account" >&2 - exit 1 - fi - ''; + if cfg.provision.idmAdminPasswordFile != null then + '' + KANIDM_IDM_ADMIN_PASSWORD=$(< ${cfg.provision.idmAdminPasswordFile}) + # We always reset the idm_admin account password if a desired password was specified. + if ! KANIDM_RECOVER_ACCOUNT_PASSWORD=$KANIDM_IDM_ADMIN_PASSWORD ${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin --from-environment >/dev/null; then + echo "Failed to recover idm_admin account" >&2 + exit 1 + fi + '' + else + '' + # Recover idm_admin account + if ! recover_out=$(${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin -o json); then + echo "$recover_out" >&2 + echo "kanidm provision: Failed to recover admin account" >&2 + exit 1 + fi + if ! KANIDM_IDM_ADMIN_PASSWORD=$(grep '{"password' <<< "$recover_out" | ${getExe pkgs.jq} -r .password); then + echo "$recover_out" >&2 + echo "kanidm provision: Failed to parse password for idm_admin account" >&2 + exit 1 + fi + ''; postStartScript = pkgs.writeShellScript "post-start" '' set -euo pipefail @@ -191,13 +204,14 @@ KANIDM_PROVISION_IDM_ADMIN_TOKEN=$KANIDM_IDM_ADMIN_PASSWORD \ ${getExe pkgs.kanidm-provision} --url "${cfg.provision.instanceUrl}" --state ${provisionStateJson} ${optionalString cfg.provision.acceptInvalidCerts "--accept-invalid-certs"} ''; -in { +in +{ options.services.kanidm = { enableClient = mkEnableOption (mdDoc "the Kanidm client"); enableServer = mkEnableOption (mdDoc "the Kanidm server"); enablePam = mkEnableOption (mdDoc "the Kanidm PAM and NSS integration"); - package = mkPackageOption pkgs "kanidm" {}; + package = mkPackageOption pkgs "kanidm" { }; serverSettings = mkOption { type = types.submodule { @@ -253,12 +267,20 @@ in { log_level = mkOption { description = mdDoc "Log level of the server."; default = "info"; - type = types.enum ["info" "debug" "trace"]; + type = types.enum [ + "info" + "debug" + "trace" + ]; }; role = mkOption { description = mdDoc "The role of this server. This affects the replication relationship and thereby available features."; default = "WriteReplica"; - type = types.enum ["WriteReplica" "WriteReplicaNoUI" "ReadOnlyReplica"]; + type = types.enum [ + "WriteReplica" + "WriteReplicaNoUI" + "ReadOnlyReplica" + ]; }; online_backup = { path = mkOption { @@ -284,7 +306,7 @@ in { }; }; }; - default = {}; + default = { }; description = mdDoc '' Settings for Kanidm, see [the documentation](https://kanidm.github.io/kanidm/stable/server_configuration.html) @@ -387,227 +409,245 @@ in { groups = mkOption { description = "Provisioning of kanidm groups"; - default = {}; - type = types.attrsOf (types.submodule (groupSubmod: { - options = { - present = mkPresentOption "group"; + default = { }; + type = types.attrsOf ( + types.submodule (groupSubmod: { + options = { + present = mkPresentOption "group"; - members = mkOption { - description = "List of kanidm entities (persons, groups, ...) which are part of this group."; - type = types.listOf types.str; - apply = unique; - default = []; + members = mkOption { + description = "List of kanidm entities (persons, groups, ...) which are part of this group."; + type = types.listOf types.str; + apply = unique; + default = [ ]; + }; }; - }; - config.members = concatLists (flip mapAttrsToList cfg.provision.persons ( - person: personCfg: - optional (personCfg.present && builtins.elem groupSubmod.config._module.args.name personCfg.groups) person - )); - })); + config.members = concatLists ( + flip mapAttrsToList cfg.provision.persons ( + person: personCfg: + optional ( + personCfg.present && builtins.elem groupSubmod.config._module.args.name personCfg.groups + ) person + ) + ); + }) + ); }; persons = mkOption { description = "Provisioning of kanidm persons"; - default = {}; - type = types.attrsOf (types.submodule { - options = { - present = mkPresentOption "person"; + default = { }; + type = types.attrsOf ( + types.submodule { + options = { + present = mkPresentOption "person"; - displayName = mkOption { - description = "Display name"; - type = types.str; - example = "My User"; - }; + displayName = mkOption { + description = "Display name"; + type = types.str; + example = "My User"; + }; - legalName = mkOption { - description = "Full legal name"; - type = types.nullOr types.str; - example = "Jane Doe"; - default = null; - }; + legalName = mkOption { + description = "Full legal name"; + type = types.nullOr types.str; + example = "Jane Doe"; + default = null; + }; - mailAddresses = mkOption { - description = "Mail addresses. First given address is considered the primary address."; - type = types.listOf types.str; - example = ["jane.doe@example.com"]; - default = []; - }; + mailAddresses = mkOption { + description = "Mail addresses. First given address is considered the primary address."; + type = types.listOf types.str; + example = [ "jane.doe@example.com" ]; + default = [ ]; + }; - groups = mkOption { - description = "List of groups this person should belong to."; - type = types.listOf types.str; - apply = unique; - default = []; + groups = mkOption { + description = "List of groups this person should belong to."; + type = types.listOf types.str; + apply = unique; + default = [ ]; + }; }; - }; - }); + } + ); }; systems.oauth2 = mkOption { description = "Provisioning of oauth2 resource servers"; - default = {}; - type = types.attrsOf (types.submodule { - options = { - present = mkPresentOption "oauth2 resource server"; + default = { }; + type = types.attrsOf ( + types.submodule { + options = { + present = mkPresentOption "oauth2 resource server"; - public = mkOption { - description = "Whether this is a public client (enforces PKCE, doesn't use a basic secret)"; - type = types.bool; - default = false; + public = mkOption { + description = "Whether this is a public client (enforces PKCE, doesn't use a basic secret)"; + type = types.bool; + default = false; + }; + + displayName = mkOption { + description = "Display name"; + type = types.str; + example = "Some Service"; + }; + + originUrl = mkOption { + description = "The origin URL of the service. OAuth2 redirects will only be allowed to sites under this origin. Must end with a slash."; + type = types.strMatching ".*://.*/$"; + example = "https://someservice.example.com/"; + }; + + originLanding = mkOption { + description = "When redirecting from the Kanidm Apps Listing page, some linked applications may need to land on a specific page to trigger oauth2/oidc interactions."; + type = types.nullOr types.str; + default = null; + example = "https://someservice.example.com/home"; + }; + + basicSecretFile = mkOption { + description = '' + The basic secret to use for this service. If null, the random secret generated + by kanidm will not be touched. Do NOT use a path from the nix store here! + ''; + type = types.nullOr types.path; + example = "/run/secrets/some-oauth2-basic-secret"; + default = null; + }; + + enableLocalhostRedirects = mkOption { + description = "Allow localhost redirects. Only for public clients."; + type = types.bool; + default = false; + }; + + enableLegacyCrypto = mkOption { + description = "Enable legacy crypto on this client. Allows JWT signing algorthms like RS256."; + type = types.bool; + default = false; + }; + + allowInsecureClientDisablePkce = mkOption { + description = '' + Disable PKCE on this oauth2 resource server to work around insecure clients + that may not support it. You should request the client to enable PKCE! + Only for non-public clients. + ''; + type = types.bool; + default = false; + }; + + preferShortUsername = mkOption { + description = "Use 'name' instead of 'spn' in the preferred_username claim"; + type = types.bool; + default = false; + }; + + scopeMaps = mkOption { + description = '' + Maps kanidm groups to returned oauth scopes. + See [Scope Relations](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html#scope-relationships) for more information. + ''; + type = types.attrsOf (types.listOf types.str); + default = { }; + }; + + supplementaryScopeMaps = mkOption { + description = '' + Maps kanidm groups to additionally returned oauth scopes. + See [Scope Relations](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html#scope-relationships) for more information. + ''; + type = types.attrsOf (types.listOf types.str); + default = { }; + }; + + removeOrphanedClaimMaps = mkOption { + description = "Whether claim maps not specified here but present in kanidm should be removed from kanidm."; + type = types.bool; + default = true; + }; + + claimMaps = mkOption { + description = '' + Adds additional claims (and values) based on which kanidm groups an authenticating party belongs to. + See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information. + ''; + default = { }; + type = types.attrsOf ( + types.submodule { + options = { + joinType = mkOption { + description = '' + Determines how multiple values are joined to create the claim value. + See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information. + ''; + type = types.enum [ + "array" + "csv" + "ssv" + ]; + default = "array"; + }; + + valuesByGroup = mkOption { + description = "Maps kanidm groups to values for the claim."; + default = { }; + type = types.attrsOf (types.listOf types.str); + }; + }; + } + ); + }; }; - - displayName = mkOption { - description = "Display name"; - type = types.str; - example = "Some Service"; - }; - - originUrl = mkOption { - description = "The origin URL of the service. OAuth2 redirects will only be allowed to sites under this origin. Must end with a slash."; - type = types.strMatching ".*://.*/$"; - example = "https://someservice.example.com/"; - }; - - originLanding = mkOption { - description = "When redirecting from the Kanidm Apps Listing page, some linked applications may need to land on a specific page to trigger oauth2/oidc interactions."; - type = types.nullOr types.str; - default = null; - example = "https://someservice.example.com/home"; - }; - - basicSecretFile = mkOption { - description = '' - The basic secret to use for this service. If null, the random secret generated - by kanidm will not be touched. Do NOT use a path from the nix store here! - ''; - type = types.nullOr types.path; - example = "/run/secrets/some-oauth2-basic-secret"; - default = null; - }; - - enableLocalhostRedirects = mkOption { - description = "Allow localhost redirects. Only for public clients."; - type = types.bool; - default = false; - }; - - enableLegacyCrypto = mkOption { - description = "Enable legacy crypto on this client. Allows JWT signing algorthms like RS256."; - type = types.bool; - default = false; - }; - - allowInsecureClientDisablePkce = mkOption { - description = '' - Disable PKCE on this oauth2 resource server to work around insecure clients - that may not support it. You should request the client to enable PKCE! - Only for non-public clients. - ''; - type = types.bool; - default = false; - }; - - preferShortUsername = mkOption { - description = "Use 'name' instead of 'spn' in the preferred_username claim"; - type = types.bool; - default = false; - }; - - scopeMaps = mkOption { - description = '' - Maps kanidm groups to returned oauth scopes. - See [Scope Relations](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html#scope-relationships) for more information. - ''; - type = types.attrsOf (types.listOf types.str); - default = {}; - }; - - supplementaryScopeMaps = mkOption { - description = '' - Maps kanidm groups to additionally returned oauth scopes. - See [Scope Relations](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html#scope-relationships) for more information. - ''; - type = types.attrsOf (types.listOf types.str); - default = {}; - }; - - removeOrphanedClaimMaps = mkOption { - description = "Whether claim maps not specified here but present in kanidm should be removed from kanidm."; - type = types.bool; - default = true; - }; - - claimMaps = mkOption { - description = '' - Adds additional claims (and values) based on which kanidm groups an authenticating party belongs to. - See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information. - ''; - default = {}; - type = types.attrsOf (types.submodule { - options = { - joinType = mkOption { - description = '' - Determines how multiple values are joined to create the claim value. - See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information. - ''; - type = types.enum ["array" "csv" "ssv"]; - default = "array"; - }; - - valuesByGroup = mkOption { - description = "Maps kanidm groups to values for the claim."; - default = {}; - type = types.attrsOf (types.listOf types.str); - }; - }; - }); - }; - }; - }); + } + ); }; }; }; config = mkIf (cfg.enableClient || cfg.enableServer || cfg.enablePam) { - assertions = let - entityList = type: attrs: flip mapAttrsToList (filterPresent attrs) (name: _: {inherit type name;}); - entities = - entityList "group" cfg.provision.groups - ++ entityList "person" cfg.provision.persons - ++ entityList "oauth2" cfg.provision.systems.oauth2; + assertions = + let + entityList = + type: attrs: flip mapAttrsToList (filterPresent attrs) (name: _: { inherit type name; }); + entities = + entityList "group" cfg.provision.groups + ++ entityList "person" cfg.provision.persons + ++ entityList "oauth2" cfg.provision.systems.oauth2; - # Accumulate entities by name. Track corresponding entity types for later duplicate check. - entitiesByName = - foldl' ( - acc: { - type, - name, - }: - acc - // { - ${name} = (acc.${name} or []) ++ [type]; - } - ) {} - entities; + # Accumulate entities by name. Track corresponding entity types for later duplicate check. + entitiesByName = foldl' ( + acc: { type, name }: acc // { ${name} = (acc.${name} or [ ]) ++ [ type ]; } + ) { } entities; - assertGroupsKnown = opt: groups: let - knownGroups = attrNames (filterPresent cfg.provision.groups); - unknownGroups = subtractLists knownGroups groups; - in { - assertion = (cfg.enableServer && cfg.provision.enable) -> unknownGroups == []; - message = "${opt} refers to unknown groups: ${toString unknownGroups}"; - }; + assertGroupsKnown = + opt: groups: + let + knownGroups = attrNames (filterPresent cfg.provision.groups); + unknownGroups = subtractLists knownGroups groups; + in + { + assertion = (cfg.enableServer && cfg.provision.enable) -> unknownGroups == [ ]; + message = "${opt} refers to unknown groups: ${toString unknownGroups}"; + }; - assertEntitiesKnown = opt: entities: let - unknownEntities = subtractLists (attrNames entitiesByName) entities; - in { - assertion = (cfg.enableServer && cfg.provision.enable) -> unknownEntities == []; - message = "${opt} refers to unknown entities: ${toString unknownEntities}"; - }; - in + assertEntitiesKnown = + opt: entities: + let + unknownEntities = subtractLists (attrNames entitiesByName) entities; + in + { + assertion = (cfg.enableServer && cfg.provision.enable) -> unknownEntities == [ ]; + message = "${opt} refers to unknown entities: ${toString unknownEntities}"; + }; + in [ { - assertion = !cfg.enableServer || ((cfg.serverSettings.tls_chain or null) == null) || (!isStorePath cfg.serverSettings.tls_chain); + assertion = + !cfg.enableServer + || ((cfg.serverSettings.tls_chain or null) == null) + || (!isStorePath cfg.serverSettings.tls_chain); message = '' points to a file in the Nix store. You should use a quoted absolute path to @@ -615,7 +655,10 @@ in { ''; } { - assertion = !cfg.enableServer || ((cfg.serverSettings.tls_key or null) == null) || (!isStorePath cfg.serverSettings.tls_key); + assertion = + !cfg.enableServer + || ((cfg.serverSettings.tls_key or null) == null) + || (!isStorePath cfg.serverSettings.tls_key); message = '' points to a file in the Nix store. You should use a quoted absolute path to @@ -639,9 +682,10 @@ in { { assertion = !cfg.enableServer - || (cfg.serverSettings.domain - == null - -> cfg.serverSettings.role == "WriteReplica" || cfg.serverSettings.role == "WriteReplicaNoUI"); + || ( + cfg.serverSettings.domain == null + -> cfg.serverSettings.role == "WriteReplica" || cfg.serverSettings.role == "WriteReplicaNoUI" + ); message = '' can only be set if this instance is not a ReadOnlyReplica. Otherwise the db would inherit it from @@ -655,13 +699,14 @@ in { # If any secret is provisioned, the kanidm package must have some required patches applied to it { assertion = - (cfg.provision.enable + ( + cfg.provision.enable && ( - cfg.provision.adminPasswordFile - != null + cfg.provision.adminPasswordFile != null || cfg.provision.idmAdminPasswordFile != null || any (x: x.basicSecretFile != null) (attrValues (filterPresent cfg.provision.systems.oauth2)) - )) + ) + ) -> cfg.package.enableSecretProvisioning; message = '' Specifying an admin account password or oauth2 basicSecretFile requires kanidm to be built with the secret provisioning patches. @@ -669,56 +714,80 @@ in { ''; } # Entity names must be globally unique: - (let - # Filter all names that occurred in more than one entity type. - duplicateNames = filterAttrs (_: v: builtins.length v > 1) entitiesByName; - in { - assertion = cfg.provision.enable -> duplicateNames == {}; - message = '' - services.kanidm.provision requires all entity names (group, person, oauth2, ...) to be unique! - ${concatLines (mapAttrsToList (name: xs: " - '${name}' used as: ${toString xs}") duplicateNames)}''; - }) + ( + let + # Filter all names that occurred in more than one entity type. + duplicateNames = filterAttrs (_: v: builtins.length v > 1) entitiesByName; + in + { + assertion = cfg.provision.enable -> duplicateNames == { }; + message = '' + services.kanidm.provision requires all entity names (group, person, oauth2, ...) to be unique! + ${concatLines ( + mapAttrsToList (name: xs: " - '${name}' used as: ${toString xs}") duplicateNames + )}''; + } + ) ] ++ flip mapAttrsToList (filterPresent cfg.provision.persons) ( person: personCfg: - assertGroupsKnown "services.kanidm.provision.persons.${person}.groups" personCfg.groups + assertGroupsKnown "services.kanidm.provision.persons.${person}.groups" personCfg.groups ) ++ flip mapAttrsToList (filterPresent cfg.provision.groups) ( group: groupCfg: - assertEntitiesKnown "services.kanidm.provision.groups.${group}.members" groupCfg.members + assertEntitiesKnown "services.kanidm.provision.groups.${group}.members" groupCfg.members ) - ++ concatLists (flip mapAttrsToList (filterPresent cfg.provision.systems.oauth2) ( - oauth2: oauth2Cfg: + ++ concatLists ( + flip mapAttrsToList (filterPresent cfg.provision.systems.oauth2) ( + oauth2: oauth2Cfg: [ - (assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.scopeMaps" (attrNames oauth2Cfg.scopeMaps)) - (assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.supplementaryScopeMaps" (attrNames oauth2Cfg.supplementaryScopeMaps)) + (assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.scopeMaps" ( + attrNames oauth2Cfg.scopeMaps + )) + (assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.supplementaryScopeMaps" ( + attrNames oauth2Cfg.supplementaryScopeMaps + )) ] - ++ concatLists (flip mapAttrsToList oauth2Cfg.claimMaps (claim: claimCfg: [ - (assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim}.valuesByGroup" (attrNames claimCfg.valuesByGroup)) - # At least one group must map to a value in each claim map - { - assertion = (cfg.provision.enable && cfg.enableServer) -> any (xs: xs != []) (attrValues claimCfg.valuesByGroup); - message = "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim} does not specify any values for any group"; - } - # Public clients cannot define a basic secret - { - assertion = (cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) -> oauth2Cfg.basicSecretFile == null; - message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot specify a basic secret"; - } - # Public clients cannot disable PKCE - { - assertion = (cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) -> !oauth2Cfg.allowInsecureClientDisablePkce; - message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot disable PKCE"; - } - # Non-public clients cannot enable localhost redirects - { - assertion = (cfg.provision.enable && cfg.enableServer && !oauth2Cfg.public) -> !oauth2Cfg.enableLocalhostRedirects; - message = "services.kanidm.provision.systems.oauth2.${oauth2} is a non-public client and thus cannot enable localhost redirects"; - } - ])) - )); + ++ concatLists ( + flip mapAttrsToList oauth2Cfg.claimMaps ( + claim: claimCfg: [ + (assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim}.valuesByGroup" ( + attrNames claimCfg.valuesByGroup + )) + # At least one group must map to a value in each claim map + { + assertion = + (cfg.provision.enable && cfg.enableServer) + -> any (xs: xs != [ ]) (attrValues claimCfg.valuesByGroup); + message = "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim} does not specify any values for any group"; + } + # Public clients cannot define a basic secret + { + assertion = + (cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) -> oauth2Cfg.basicSecretFile == null; + message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot specify a basic secret"; + } + # Public clients cannot disable PKCE + { + assertion = + (cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) + -> !oauth2Cfg.allowInsecureClientDisablePkce; + message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot disable PKCE"; + } + # Non-public clients cannot enable localhost redirects + { + assertion = + (cfg.provision.enable && cfg.enableServer && !oauth2Cfg.public) + -> !oauth2Cfg.enableLocalhostRedirects; + message = "services.kanidm.provision.systems.oauth2.${oauth2} is a non-public client and thus cannot enable localhost redirects"; + } + ] + ) + ) + ) + ); - environment.systemPackages = mkIf cfg.enableClient [cfg.package]; + environment.systemPackages = mkIf cfg.enableClient [ cfg.package ]; systemd.tmpfiles.settings."10-kanidm" = { ${cfg.serverSettings.online_backup.path}.d = { @@ -730,14 +799,16 @@ in { systemd.services.kanidm = mkIf cfg.enableServer { description = "kanidm identity management daemon"; - wantedBy = ["multi-user.target"]; - after = ["network.target"]; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; serviceConfig = mkMerge [ # Merge paths and ignore existing prefixes needs to sidestep mkMerge - (defaultServiceConfig + ( + defaultServiceConfig // { BindReadOnlyPaths = mergePaths (defaultServiceConfig.BindReadOnlyPaths ++ certPaths); - }) + } + ) { StateDirectory = "kanidm"; StateDirectoryMode = "0700"; @@ -754,13 +825,17 @@ in { cfg.serverSettings.online_backup.path ]; - AmbientCapabilities = ["CAP_NET_BIND_SERVICE"]; - CapabilityBoundingSet = ["CAP_NET_BIND_SERVICE"]; + AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; # This would otherwise override the CAP_NET_BIND_SERVICE capability. PrivateUsers = mkForce false; # Port needs to be exposed to the host network PrivateNetwork = mkForce false; - RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"]; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; TemporaryFileSystem = "/:ro"; } ]; @@ -769,9 +844,12 @@ in { systemd.services.kanidm-unixd = mkIf cfg.enablePam { description = "Kanidm PAM daemon"; - wantedBy = ["multi-user.target"]; - after = ["network.target"]; - restartTriggers = [unixConfigFile clientConfigFile]; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + restartTriggers = [ + unixConfigFile + clientConfigFile + ]; serviceConfig = mkMerge [ defaultServiceConfig { @@ -796,7 +874,11 @@ in { ]; # Needs to connect to kanidmd PrivateNetwork = mkForce false; - RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"]; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; TemporaryFileSystem = "/:ro"; } ]; @@ -805,10 +887,16 @@ in { systemd.services.kanidm-unixd-tasks = mkIf cfg.enablePam { description = "Kanidm PAM home management daemon"; - wantedBy = ["multi-user.target"]; - after = ["network.target" "kanidm-unixd.service"]; - partOf = ["kanidm-unixd.service"]; - restartTriggers = [unixConfigFile clientConfigFile]; + wantedBy = [ "multi-user.target" ]; + after = [ + "network.target" + "kanidm-unixd.service" + ]; + partOf = [ "kanidm-unixd.service" ]; + restartTriggers = [ + unixConfigFile + clientConfigFile + ]; serviceConfig = { ExecStart = "${cfg.package}/bin/kanidm_unixd_tasks"; @@ -828,13 +916,18 @@ in { "/run/kanidm-unixd:/var/run/kanidm-unixd" ]; # CAP_DAC_OVERRIDE is needed to ignore ownership of unixd socket - CapabilityBoundingSet = ["CAP_CHOWN" "CAP_FOWNER" "CAP_DAC_OVERRIDE" "CAP_DAC_READ_SEARCH"]; + CapabilityBoundingSet = [ + "CAP_CHOWN" + "CAP_FOWNER" + "CAP_DAC_OVERRIDE" + "CAP_DAC_READ_SEARCH" + ]; IPAddressDeny = "any"; # Need access to users PrivateUsers = false; # Need access to home directories ProtectHome = false; - RestrictAddressFamilies = ["AF_UNIX"]; + RestrictAddressFamilies = [ "AF_UNIX" ]; TemporaryFileSystem = "/:ro"; Restart = "on-failure"; }; @@ -843,29 +936,21 @@ in { # These paths are hardcoded environment.etc = mkMerge [ - (mkIf cfg.enableServer { - "kanidm/server.toml".source = serverConfigFile; - }) + (mkIf cfg.enableServer { "kanidm/server.toml".source = serverConfigFile; }) (mkIf options.services.kanidm.clientSettings.isDefined { "kanidm/config".source = clientConfigFile; }) - (mkIf cfg.enablePam { - "kanidm/unixd".source = unixConfigFile; - }) + (mkIf cfg.enablePam { "kanidm/unixd".source = unixConfigFile; }) ]; - system.nssModules = mkIf cfg.enablePam [cfg.package]; + system.nssModules = mkIf cfg.enablePam [ cfg.package ]; system.nssDatabases.group = optional cfg.enablePam "kanidm"; system.nssDatabases.passwd = optional cfg.enablePam "kanidm"; users.groups = mkMerge [ - (mkIf cfg.enableServer { - kanidm = {}; - }) - (mkIf cfg.enablePam { - kanidm-unixd = {}; - }) + (mkIf cfg.enableServer { kanidm = { }; }) + (mkIf cfg.enablePam { kanidm-unixd = { }; }) ]; users.users = mkMerge [ (mkIf cfg.enableServer { @@ -873,7 +958,7 @@ in { description = "Kanidm server"; isSystemUser = true; group = "kanidm"; - packages = [cfg.package]; + packages = [ cfg.package ]; }; }) (mkIf cfg.enablePam { @@ -886,6 +971,10 @@ in { ]; }; - meta.maintainers = with lib.maintainers; [erictapen Flakebi oddlama]; + meta.maintainers = with lib.maintainers; [ + erictapen + Flakebi + oddlama + ]; meta.buildDocsInSandbox = false; } diff --git a/modules/meta.nix b/modules/meta.nix index 97613e6..4aaa4a0 100644 --- a/modules/meta.nix +++ b/modules/meta.nix @@ -1,10 +1,8 @@ -{lib, ...}: let - inherit - (lib) - mkOption - types - ; -in { +{ lib, ... }: +let + inherit (lib) mkOption types; +in +{ options.node = { secretsDir = mkOption { description = "Path to the secrets directory for this node."; diff --git a/modules/netbird-client.nix b/modules/netbird-client.nix index 297ca57..af573d9 100644 --- a/modules/netbird-client.nix +++ b/modules/netbird-client.nix @@ -3,9 +3,9 @@ lib, pkgs, ... -}: let - inherit - (lib) +}: +let + inherit (lib) attrNames getExe literalExpression @@ -22,8 +22,7 @@ versionOlder ; - inherit - (lib.types) + inherit (lib.types) attrsOf port str @@ -36,7 +35,8 @@ kernel = config.boot.kernelPackages; cfg = config.services.netbird; -in { +in +{ meta.maintainers = with maintainers; [ misuzu thubrecht @@ -46,16 +46,13 @@ in { options.services.netbird = { enable = mkEnableOption (lib.mdDoc "Netbird daemon"); - package = mkPackageOption pkgs "netbird" {}; + package = mkPackageOption pkgs "netbird" { }; tunnels = mkOption { type = attrsOf ( submodule ( + { name, config, ... }: { - name, - config, - ... - }: { options = { port = mkOption { type = port; @@ -111,7 +108,7 @@ in { } ) ); - default = {}; + default = { }; description = '' Attribute set of Netbird tunnels, each one will spawn a daemon listening on ... ''; @@ -124,106 +121,99 @@ in { services.netbird.tunnels.wt0.stateDir = "netbird"; }) - (mkIf (cfg.tunnels != {}) { + (mkIf (cfg.tunnels != { }) { boot.extraModulePackages = optional (versionOlder kernel.kernel.version "5.6") kernel.wireguard; - environment.systemPackages = [cfg.package]; + environment.systemPackages = [ cfg.package ]; networking.dhcpcd.denyInterfaces = attrNames cfg.tunnels; systemd.network.networks = mkIf config.networking.useNetworkd ( - mapAttrs' - ( + mapAttrs' ( name: _: - nameValuePair "50-netbird-${name}" { - matchConfig = { - Name = name; - }; - linkConfig = { - Unmanaged = true; - ActivationPolicy = "manual"; - }; - } - ) - cfg.tunnels + nameValuePair "50-netbird-${name}" { + matchConfig = { + Name = name; + }; + linkConfig = { + Unmanaged = true; + ActivationPolicy = "manual"; + }; + } + ) cfg.tunnels ); - systemd.services = - mapAttrs' - ( - name: { - environment, - stateDir, - environmentFile, - userAccess, - ... - }: - nameValuePair "netbird-${name}" { - description = "A WireGuard-based mesh network that connects your devices into a single private network"; + systemd.services = mapAttrs' ( + name: + { + environment, + stateDir, + environmentFile, + userAccess, + ... + }: + nameValuePair "netbird-${name}" { + description = "A WireGuard-based mesh network that connects your devices into a single private network"; - documentation = ["https://netbird.io/docs/"]; + documentation = [ "https://netbird.io/docs/" ]; - after = ["network.target"]; - wantedBy = ["multi-user.target"]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; - path = with pkgs; [openresolv]; + path = with pkgs; [ openresolv ]; - inherit environment; + inherit environment; - serviceConfig = { - EnvironmentFile = mkIf (environmentFile != null) environmentFile; - ExecStart = "${getExe cfg.package} service run"; - Restart = "always"; - RuntimeDirectory = stateDir; - StateDirectory = stateDir; - StateDirectoryMode = "0700"; - WorkingDirectory = "/var/lib/${stateDir}"; - RuntimeDirectoryMode = - if userAccess - then "0755" - else "0750"; + serviceConfig = { + EnvironmentFile = mkIf (environmentFile != null) environmentFile; + ExecStart = "${getExe cfg.package} service run"; + Restart = "always"; + RuntimeDirectory = stateDir; + StateDirectory = stateDir; + StateDirectoryMode = "0700"; + WorkingDirectory = "/var/lib/${stateDir}"; + RuntimeDirectoryMode = if userAccess then "0755" else "0750"; - # hardening - LockPersonality = true; - MemoryDenyWriteExecute = true; - NoNewPrivileges = true; - PrivateMounts = true; - PrivateTmp = true; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = false; # needed to load wg module for kernel-mode WireGuard - ProtectKernelTunables = false; - ProtectSystem = true; - RemoveIPC = true; - RestrictNamespaces = true; - RestrictRealtime = true; - RestrictSUIDSGID = true; + # hardening + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateMounts = true; + PrivateTmp = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = false; # needed to load wg module for kernel-mode WireGuard + ProtectKernelTunables = false; + ProtectSystem = true; + RemoveIPC = true; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; - # Hardening - #CapabilityBoundingSet = ""; - #PrivateUsers = true; - #ProtectProc = "invisible"; - #ProcSubset = "pid"; - #RestrictAddressFamilies = [ - # "AF_INET" - # "AF_INET6" - # "AF_NETLINK" - #]; - #SystemCallArchitectures = "native"; - #SystemCallFilter = [ - # "@system-service" - # "@pkey" - #]; - UMask = "0077"; - }; + # Hardening + #CapabilityBoundingSet = ""; + #PrivateUsers = true; + #ProtectProc = "invisible"; + #ProcSubset = "pid"; + #RestrictAddressFamilies = [ + # "AF_INET" + # "AF_INET6" + # "AF_NETLINK" + #]; + #SystemCallArchitectures = "native"; + #SystemCallFilter = [ + # "@system-service" + # "@pkey" + #]; + UMask = "0077"; + }; - stopIfChanged = false; - } - ) - cfg.tunnels; + stopIfChanged = false; + } + ) cfg.tunnels; }) ]; } diff --git a/modules/secrets.nix b/modules/secrets.nix index d4bf864..93db425 100644 --- a/modules/secrets.nix +++ b/modules/secrets.nix @@ -3,9 +3,9 @@ inputs, config, ... -}: let - inherit - (lib) +}: +let + inherit (lib) mapAttrs assertMsg types @@ -16,22 +16,25 @@ # If the given expression is a bare set, it will be wrapped in a function, # so that the imported file can always be applied to the inputs, similar to # how modules can be functions or sets. - constSet = x: - if builtins.isAttrs x - then (_: x) - else x; + constSet = x: if builtins.isAttrs x then (_: x) else x; - rageImportEncrypted = assert assertMsg (builtins ? extraBuiltins.rageImportEncrypted) "The rageImportEncrypted extra plugin is not loaded"; + rageImportEncrypted = + assert assertMsg ( + builtins ? extraBuiltins.rageImportEncrypted + ) "The rageImportEncrypted extra plugin is not loaded"; builtins.extraBuiltins.rageImportEncrypted; # This "imports" an encrypted .nix.age file - importEncrypted = path: + importEncrypted = + path: constSet ( - if builtins.pathExists path - then rageImportEncrypted inputs.self.secretsConfig.masterIdentities path - else {} + if builtins.pathExists path then + rageImportEncrypted inputs.self.secretsConfig.masterIdentities path + else + { } ); cfg = config.secrets; -in { +in +{ options.secrets = { defineRageBuiltins = mkOption { default = true; @@ -43,7 +46,7 @@ in { }; secretFiles = mkOption { - default = {}; + default = { }; type = types.attrsOf types.path; example = literalExpression "{ local = ./secrets.nix.age; }"; description = mdDoc '' @@ -56,28 +59,30 @@ in { secrets = mkOption { readOnly = true; - default = - mapAttrs (_: x: importEncrypted x inputs) cfg.secretFiles; + default = mapAttrs (_: x: importEncrypted x inputs) cfg.secretFiles; description = mdDoc '' the secrets decrypted from the secretFiles ''; }; }; config.home-manager.sharedModules = [ - ({config, ...}: { - options = { - userSecretsFile = mkOption { - default = ../users/${config._module.args.name}/secrets.nix.age; - type = types.path; - description = "The global secrets attribute that should be exposed to the user"; + ( + { config, ... }: + { + options = { + userSecretsFile = mkOption { + default = ../users/${config._module.args.name}/secrets.nix.age; + type = types.path; + description = "The global secrets attribute that should be exposed to the user"; + }; + userSecrets = mkOption { + readOnly = true; + default = importEncrypted config.userSecretsFile inputs; + type = types.unspecified; + description = "User secrets"; + }; }; - userSecrets = mkOption { - readOnly = true; - default = importEncrypted config.userSecretsFile inputs; - type = types.unspecified; - description = "User secrets"; - }; - }; - }) + } + ) ]; } diff --git a/modules/smb-mounts.nix b/modules/smb-mounts.nix index d2957f3..4a87f13 100644 --- a/modules/smb-mounts.nix +++ b/modules/smb-mounts.nix @@ -3,9 +3,9 @@ config, lib, ... -}: let - inherit - (lib) +}: +let + inherit (lib) mkOption types flip @@ -19,83 +19,85 @@ "x-systemd.device-timeout=5s" "x-systemd.mount-timeout=5s" ]; -in { +in +{ # Give users the ability to add their own smb shares home-manager.sharedModules = [ { options.home.smb = mkOption { description = "Samba shares to be mountable under $HOME/smb"; - default = []; - type = types.listOf (types.submodule ({config, ...}: { - options = { - localPath = mkOption { - description = "The path under which the share will be mounted. Defaults to the remotePath"; - type = types.str; - default = config.remotePath; - }; - address = mkOption { - description = "The remote share address"; - type = types.str; - example = "10.1.2.5"; - }; - remotePath = mkOption { - description = "The remote share path"; - type = types.str; - example = "data-10"; - }; - credentials = mkOption { - description = "A smb credential file to access the remote share"; - type = types.path; - }; - automatic = mkOption { - description = "Whether this share should be automatically mounted on boot"; - default = false; - type = types.bool; - }; - }; - })); + default = [ ]; + type = types.listOf ( + types.submodule ( + { config, ... }: + { + options = { + localPath = mkOption { + description = "The path under which the share will be mounted. Defaults to the remotePath"; + type = types.str; + default = config.remotePath; + }; + address = mkOption { + description = "The remote share address"; + type = types.str; + example = "10.1.2.5"; + }; + remotePath = mkOption { + description = "The remote share path"; + type = types.str; + example = "data-10"; + }; + credentials = mkOption { + description = "A smb credential file to access the remote share"; + type = types.path; + }; + automatic = mkOption { + description = "Whether this share should be automatically mounted on boot"; + default = false; + type = types.bool; + }; + }; + } + ) + ); }; } ]; imports = [ { - environment.systemPackages = [pkgs.cifs-utils]; - fileSystems = - mkMerge - ( - flip - concatMap - (attrNames config.home-manager.users) - ( - user: let - parentPath = "/home/${user}/smb"; - cfg = config.home-manager.users.${user}.home.smb; - inherit (config.users.users.${user}) uid; - inherit (config.users.groups.${user}) gid; - in - flip map cfg ( - cfg: { - "${parentPath}/${cfg.localPath}" = let - options = - baseOptions - ++ [ - "uid=${toString uid}" - "gid=${toString gid}" - "file_mode=0600" - "dir_mode=0700" - "credentials=${cfg.credentials}" - ] - ++ (optional (!cfg.automatic) "noauto"); - in { - inherit options; - device = "//${cfg.address}/${cfg.remotePath}"; - fsType = "cifs"; - }; - } - ) - ) - ); + environment.systemPackages = [ pkgs.cifs-utils ]; + fileSystems = mkMerge ( + flip concatMap (attrNames config.home-manager.users) ( + user: + let + parentPath = "/home/${user}/smb"; + cfg = config.home-manager.users.${user}.home.smb; + inherit (config.users.users.${user}) uid; + inherit (config.users.groups.${user}) gid; + in + flip map cfg (cfg: { + "${parentPath}/${cfg.localPath}" = + let + options = + baseOptions + ++ [ + "uid=${toString uid}" + "gid=${toString gid}" + "file_mode=0600" + "dir_mode=0700" + "credentials=${cfg.credentials}" + ] + ++ (optional (!cfg.automatic) "noauto"); + in + { + inherit options; + device = "//${cfg.address}/${cfg.remotePath}"; + fsType = "cifs"; + }; + }) + ) + ); } ]; } diff --git a/nix/devshell.nix b/nix/devshell.nix index 3973b53..ad0223b 100644 --- a/nix/devshell.nix +++ b/nix/devshell.nix @@ -1,70 +1,69 @@ -{ - self, - ... -}: system: let +{ self, ... }: +system: +let pkgs = self.pkgs.${system}; in - pkgs.devshell.mkShell { - name = "nix-config"; - packages = with pkgs; [ - # Nix - nil +pkgs.devshell.mkShell { + name = "nix-config"; + packages = with pkgs; [ + # Nix + nil - # Misc - shellcheck - pre-commit - rage - nix - nix-diff - nix-update - ]; - commands = [ - { - package = pkgs.deploy; - help = "build and deploy nix configurations"; - } - { - package = pkgs.agenix-rekey; - help = "Edit and rekey repository secrets"; - } - { - package = pkgs.nixfmt-rfc-style; - help = "Format nix code"; - } - { - package = pkgs.statix; - help = "Linter for nix"; - } - { - package = pkgs.deadnix; - help = "Remove dead nix code"; - } - { - package = pkgs.nix-tree; - help = "Show nix closure tree"; - } - { - package = pkgs.update-nix-fetchgit; - help = "Update fetcher inside nix files"; - } - { - package = pkgs.nvd; - help = "List package differences between systems"; - } - { - package = pkgs.vulnix; - help = "List vulnerabilities found in your system"; - } - ]; - env = [ - { - name = "NIX_CONFIG"; - value = '' - plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins - extra-builtins-file = ${../nix}/extra-builtins.nix - ''; - } - ]; + # Misc + shellcheck + pre-commit + rage + nix + nix-diff + nix-update + ]; + commands = [ + { + package = pkgs.deploy; + help = "build and deploy nix configurations"; + } + { + package = pkgs.agenix-rekey; + help = "Edit and rekey repository secrets"; + } + { + package = pkgs.nixfmt-rfc-style; + help = "Format nix code"; + } + { + package = pkgs.statix; + help = "Linter for nix"; + } + { + package = pkgs.deadnix; + help = "Remove dead nix code"; + } + { + package = pkgs.nix-tree; + help = "Show nix closure tree"; + } + { + package = pkgs.update-nix-fetchgit; + help = "Update fetcher inside nix files"; + } + { + package = pkgs.nvd; + help = "List package differences between systems"; + } + { + package = pkgs.vulnix; + help = "List vulnerabilities found in your system"; + } + ]; + env = [ + { + name = "NIX_CONFIG"; + value = '' + plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins + extra-builtins-file = ${../nix}/extra-builtins.nix + ''; + } + ]; - devshell.startup.pre-commit.text = self.checks.${system}.pre-commit-check.shellHook; - } + devshell.startup.pre-commit.text = self.checks.${system}.pre-commit-check.shellHook; +} diff --git a/nix/extra-builtins.nix b/nix/extra-builtins.nix index b13d451..334fa52 100644 --- a/nix/extra-builtins.nix +++ b/nix/extra-builtins.nix @@ -14,21 +14,40 @@ # ''; # } # ``` -{exec, ...}: let +{ exec, ... }: +let assertMsg = pred: msg: pred || builtins.throw msg; - hasSuffix = suffix: content: let - lenContent = builtins.stringLength content; - lenSuffix = builtins.stringLength suffix; - in + hasSuffix = + suffix: content: + let + lenContent = builtins.stringLength content; + lenSuffix = builtins.stringLength suffix; + in lenContent >= lenSuffix && builtins.substring (lenContent - lenSuffix) lenContent content == suffix; -in { +in +{ # Instead of calling rage 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. - rageImportEncrypted = identities: nixFile: - assert assertMsg (builtins.isPath nixFile) "The file to decrypt must be given as a path to prevent impurity."; - assert assertMsg (hasSuffix ".nix.age" nixFile) "The content of the decrypted file must be a nix expression and should therefore end in .nix.age"; - exec ([./rage-decrypt-and-cache.sh nixFile] ++ identities); + rageImportEncrypted = + identities: nixFile: + assert assertMsg (builtins.isPath nixFile) + "The file to decrypt must be given as a path to prevent impurity."; + assert assertMsg (hasSuffix ".nix.age" nixFile) + "The content of the decrypted file must be a nix expression and should therefore end in .nix.age"; + exec ( + [ + ./rage-decrypt-and-cache.sh + nixFile + ] + ++ identities + ); # currentSystem - unsafeCurrentSystem = exec ["nix" "eval" "--impure" "--expr" "builtins.currentSystem"]; + unsafeCurrentSystem = exec [ + "nix" + "eval" + "--impure" + "--expr" + "builtins.currentSystem" + ]; } diff --git a/nix/generate-installer-package.nix b/nix/generate-installer-package.nix index f200e1e..9075786 100644 --- a/nix/generate-installer-package.nix +++ b/nix/generate-installer-package.nix @@ -1,11 +1,15 @@ -{self, ...}: nodeName: nodeAttrs: let +{ self, ... }: +nodeName: nodeAttrs: +let #FIXME inherit nodeAttrs. system; system = "x86_64-linux"; pkgs = self.pkgs.${system}; - disko-script = pkgs.writeShellScriptBin "disko-script" "${nodeAttrs.config.system.build.diskoScript}"; + disko-script = pkgs.writeShellScriptBin "disko-script" "${nodeAttrs.config.system.build.diskoScript + }"; disko-mount = pkgs.writeShellScriptBin "disko-mount" "${nodeAttrs.config.system.build.mountScript}"; - disko-format = pkgs.writeShellScriptBin "disko-format" "${nodeAttrs.config.system.build.formatScript}"; + disko-format = pkgs.writeShellScriptBin "disko-format" "${nodeAttrs.config.system.build.formatScript + }"; install-system = pkgs.writeShellScriptBin "install-system" '' set -euo pipefail @@ -28,7 +32,8 @@ install-system ]; }; -in { +in +{ # Everything required for the installer as a single package, # so it can be used from an existing live system by copying the derivation. packages.${system}.installer-package.${nodeName} = installer-package; diff --git a/nix/hosts.nix b/nix/hosts.nix index e603557..9ef8806 100644 --- a/nix/hosts.nix +++ b/nix/hosts.nix @@ -1,7 +1,7 @@ -inputs: let +inputs: +let inherit (inputs) self; - inherit - (inputs.nixpkgs.lib) + inherit (inputs.nixpkgs.lib) concatMapAttrs filterAttrs flip @@ -12,9 +12,12 @@ inputs: let ; # Creates a new nixosSystem with the correct specialArgs, pkgs and name definition - mkHost = {minimal}: name: let - pkgs = self.pkgs.x86_64-linux; - in + mkHost = + { minimal }: + name: + let + pkgs = self.pkgs.x86_64-linux; + in nixosSystem { specialArgs = { # Use the correct instance lib that has our overlays @@ -42,22 +45,30 @@ inputs: let # to instanciate hosts correctly. hosts = builtins.attrNames (filterAttrs (_: type: type == "directory") (builtins.readDir ../hosts)); # Process each nixosHosts declaration and generatea nixosSystem definitions - nixosConfigurations = genAttrs hosts (mkHost {minimal = false;}); - minimalConfigurations = genAttrs hosts (mkHost {minimal = true;}); + nixosConfigurations = genAttrs hosts (mkHost { + minimal = false; + }); + minimalConfigurations = genAttrs hosts (mkHost { + minimal = true; + }); # True NixOS nodes can define additional guest nodes that are built # together with it. We collect all defined guests from each node here # to allow accessing any node via the unified attribute `nodes`. - guestConfigurations = flip concatMapAttrs self.nixosConfigurations (_: node: - flip mapAttrs' (node.config.guests or {}) ( + guestConfigurations = flip concatMapAttrs self.nixosConfigurations ( + _: node: + flip mapAttrs' (node.config.guests or { }) ( guestName: guestDef: - nameValuePair guestDef.nodeName ( - if guestDef.backend == "microvm" - then node.config.microvm.vms.${guestName}.config - else node.config.containers.${guestName}.nixosConfiguration - ) - )); -in { + nameValuePair guestDef.nodeName ( + if guestDef.backend == "microvm" then + node.config.microvm.vms.${guestName}.config + else + node.config.containers.${guestName}.nixosConfiguration + ) + ) + ); +in +{ inherit hosts nixosConfigurations diff --git a/nix/installer-configuration.nix b/nix/installer-configuration.nix index 568fa4f..4203c47 100644 --- a/nix/installer-configuration.nix +++ b/nix/installer-configuration.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ nix.extraOptions = '' experimental-features = nix-command flakes recursive-nix ''; diff --git a/nix/topology.nix b/nix/topology.nix index 0967ef4..ffcd441 100644 --- a/nix/topology.nix +++ b/nix/topology.nix @@ -1 +1 @@ -{} +{ } diff --git a/pkgs/actual.nix b/pkgs/actual.nix index 2b172ad..ec551b8 100644 --- a/pkgs/actual.nix +++ b/pkgs/actual.nix @@ -71,7 +71,7 @@ stdenv.mkDerivation rec { homepage = "https://actualbudget.com/"; license = licenses.mit; mainProgram = "actual-server"; - maintainers = with maintainers; [patrickdag]; - platforms = ["x86_64-linux"]; + maintainers = with maintainers; [ patrickdag ]; + platforms = [ "x86_64-linux" ]; }; } diff --git a/pkgs/awakened-poe-trade.nix b/pkgs/awakened-poe-trade.nix index 692c28c..85b1094 100644 --- a/pkgs/awakened-poe-trade.nix +++ b/pkgs/awakened-poe-trade.nix @@ -1,7 +1,5 @@ -{ - pkgs, - fetchurl, -}: let +{ pkgs, fetchurl }: +let name = "awakened-poe-trade"; version = "3.22.10003"; description = "Path of Exile trading app for price checking"; @@ -23,17 +21,17 @@ sha256 = "sha256-fZ3PU+yE1n/RytkPFAXQhU85KNQStYcSrdgw+OYfJRg="; }; in - pkgs.appimageTools.wrapType2 { - name = "awakened-poe-trade"; - src = fetchurl { - url = "https://github.com/SnosMe/awakened-poe-trade/releases/download/v${version}/${file}"; - hash = "sha256-b+cDOmU0s0MqP5ZgCacmAon8UqDejG4HcOqi+Uf2dEM="; - }; +pkgs.appimageTools.wrapType2 { + name = "awakened-poe-trade"; + src = fetchurl { + url = "https://github.com/SnosMe/awakened-poe-trade/releases/download/v${version}/${file}"; + hash = "sha256-b+cDOmU0s0MqP5ZgCacmAon8UqDejG4HcOqi+Uf2dEM="; + }; - extraInstallCommands = '' - mkdir -p $out/share/applications - cp ${icon} $out/share/applications/awakened-poe-trade.png - cp ${desktopEntry} $out/share/applications/${name}.desktop - substituteInPlace $out/share/applications/awakened-poe-trade.desktop --replace /share/ $out/share/ - ''; - } + extraInstallCommands = '' + mkdir -p $out/share/applications + cp ${icon} $out/share/applications/awakened-poe-trade.png + cp ${desktopEntry} $out/share/applications/${name}.desktop + substituteInPlace $out/share/applications/awakened-poe-trade.desktop --replace /share/ $out/share/ + ''; +} diff --git a/pkgs/default.nix b/pkgs/default.nix index e6d2588..e9e54a9 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,39 +1,43 @@ [ (import ./scripts) (_self: super: { - zsh-histdb-skim = super.callPackage ./zsh-histdb-skim.nix {}; - zsh-histdb = super.callPackage ./zsh-histdb.nix {}; - actual = super.callPackage ./actual.nix {}; - pr-tracker = super.callPackage ./pr-tracker.nix {}; - homebox = super.callPackage ./homebox.nix {}; - deploy = super.callPackage ./deploy.nix {}; - mongodb-bin = super.callPackage ./mongodb-bin.nix {}; - awakened-poe-trade = super.callPackage ./awakened-poe-trade.nix {}; - neovim-clean = super.neovim-unwrapped.overrideAttrs (_neovimFinal: neovimPrev: { - nativeBuildInputs = (neovimPrev.nativeBuildInputs or []) ++ [super.makeWrapper]; - postInstall = - (neovimPrev.postInstall or "") - + '' - wrapProgram $out/bin/nvim --add-flags "--clean" - ''; - }); - kanidm = super.kanidm.overrideAttrs (old: let - provisionSrc = super.fetchFromGitHub { - owner = "oddlama"; - repo = "kanidm-provision"; - rev = "v1.1.0"; - hash = "sha256-pFOFFKh3la/sZGXj+pAM8x4SMeffvvbOvTjPeHS1XPU="; - }; - in { - patches = - old.patches - ++ [ + zsh-histdb-skim = super.callPackage ./zsh-histdb-skim.nix { }; + zsh-histdb = super.callPackage ./zsh-histdb.nix { }; + actual = super.callPackage ./actual.nix { }; + pr-tracker = super.callPackage ./pr-tracker.nix { }; + homebox = super.callPackage ./homebox.nix { }; + deploy = super.callPackage ./deploy.nix { }; + mongodb-bin = super.callPackage ./mongodb-bin.nix { }; + awakened-poe-trade = super.callPackage ./awakened-poe-trade.nix { }; + neovim-clean = super.neovim-unwrapped.overrideAttrs ( + _neovimFinal: neovimPrev: { + nativeBuildInputs = (neovimPrev.nativeBuildInputs or [ ]) ++ [ super.makeWrapper ]; + postInstall = + (neovimPrev.postInstall or "") + + '' + wrapProgram $out/bin/nvim --add-flags "--clean" + ''; + } + ); + kanidm = super.kanidm.overrideAttrs ( + old: + let + provisionSrc = super.fetchFromGitHub { + owner = "oddlama"; + repo = "kanidm-provision"; + rev = "v1.1.0"; + hash = "sha256-pFOFFKh3la/sZGXj+pAM8x4SMeffvvbOvTjPeHS1XPU="; + }; + in + { + patches = old.patches ++ [ "${provisionSrc}/patches/1.2.0-oauth2-basic-secret-modify.patch" "${provisionSrc}/patches/1.2.0-recover-account.patch" ]; - passthru.enableSecretProvisioning = true; - doCheck = false; - }); - kanidm-provision = super.callPackage ./kanidm-provision.nix {}; + passthru.enableSecretProvisioning = true; + doCheck = false; + } + ); + kanidm-provision = super.callPackage ./kanidm-provision.nix { }; }) ] diff --git a/pkgs/deploy.nix b/pkgs/deploy.nix index 6c287ea..5ad27f1 100644 --- a/pkgs/deploy.nix +++ b/pkgs/deploy.nix @@ -3,7 +3,8 @@ writeShellApplication, nvd, nix-output-monitor, -}: let +}: +let deploy = writeShellApplication { name = "deploy"; text = '' @@ -166,7 +167,10 @@ ''; }; in - symlinkJoin { - name = "deploy and build"; - paths = [deploy build]; - } +symlinkJoin { + name = "deploy and build"; + paths = [ + deploy + build + ]; +} diff --git a/pkgs/homebox.nix b/pkgs/homebox.nix index 6c5efa7..5c7e06b 100644 --- a/pkgs/homebox.nix +++ b/pkgs/homebox.nix @@ -7,7 +7,8 @@ lib, buildGoModule, fetchFromGitHub, -}: let +}: +let pname = "homebox"; version = "0.10.3"; src = "${fetchFromGitHub { @@ -101,38 +102,38 @@ outputHash = "sha256-BVZSdc8e6v+paMzMYazEdnKSNw+OnCpjSzGSEKxVl24="; }; in - buildGoModule { - inherit pname version; - src = "${src}/backend"; +buildGoModule { + inherit pname version; + src = "${src}/backend"; - vendorHash = "sha256-TtFz+dDpoMs3PAQjiYQm1+Q6prn4Hiaf7xqWt41oY7w="; + vendorHash = "sha256-TtFz+dDpoMs3PAQjiYQm1+Q6prn4Hiaf7xqWt41oY7w="; - CGO_ENABLED = 0; - GOOS = "linux"; - doCheck = false; + CGO_ENABLED = 0; + GOOS = "linux"; + doCheck = false; - # options used by upstream: - # https://github.com/simulot/immich-go/blob/0.13.2/.goreleaser.yaml - ldflags = [ - "-s" - "-w" - "-extldflags=-static" - "-X main.version=${version}" - ]; + # options used by upstream: + # https://github.com/simulot/immich-go/blob/0.13.2/.goreleaser.yaml + ldflags = [ + "-s" + "-w" + "-extldflags=-static" + "-X main.version=${version}" + ]; - preBuild = '' - ldflags+=" -X main.commit=$(cat COMMIT)" - ldflags+=" -X main.date=$(cat SOURCE_DATE)" - mkdir -p ./app/api/static/public - cp -r ${frontend}/* ./app/api/static/public - ''; + preBuild = '' + ldflags+=" -X main.commit=$(cat COMMIT)" + ldflags+=" -X main.date=$(cat SOURCE_DATE)" + mkdir -p ./app/api/static/public + cp -r ${frontend}/* ./app/api/static/public + ''; - meta = with lib; { - mainProgram = "api"; - homepage = "https://hay-kot.github.io/homebox/"; - maintainers = with maintainers; [patrickdag]; - license = licenses.agpl3Only; - description = "A inventory and organization system built for the Home User"; - platforms = platforms.all; - }; - } + meta = with lib; { + mainProgram = "api"; + homepage = "https://hay-kot.github.io/homebox/"; + maintainers = with maintainers; [ patrickdag ]; + license = licenses.agpl3Only; + description = "A inventory and organization system built for the Home User"; + platforms = platforms.all; + }; +} diff --git a/pkgs/kanidm-provision.nix b/pkgs/kanidm-provision.nix index b076dbb..af5b07d 100644 --- a/pkgs/kanidm-provision.nix +++ b/pkgs/kanidm-provision.nix @@ -19,8 +19,11 @@ rustPlatform.buildRustPackage rec { meta = with lib; { description = "A small utility to help with kanidm provisioning"; homepage = "https://github.com/oddlama/kanidm-provision"; - license = with licenses; [asl20 mit]; - maintainers = with maintainers; [oddlama]; + license = with licenses; [ + asl20 + mit + ]; + maintainers = with maintainers; [ oddlama ]; mainProgram = "kanidm-provision"; }; } diff --git a/pkgs/mongodb-bin.nix b/pkgs/mongodb-bin.nix index 6c8a797..8eded0f 100644 --- a/pkgs/mongodb-bin.nix +++ b/pkgs/mongodb-bin.nix @@ -11,27 +11,26 @@ stdenv.mkDerivation { pname = "mongodb-bin"; version = "1.0.0"; srcs = [ - ( - fetchurl { - url = "https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-6.0.14.tgz"; - hash = "sha256-1MW3pVIffdxq63gY64ozM1erWM2ou2L8T+MTfG+ZPLg="; - } - ) - ( - fetchurl { - url = "https://downloads.mongodb.com/compass/mongosh-2.1.5-linux-x64.tgz"; - hash = "sha256-R1GGB0ZGqmpJtMUNF2+EJK6iNiChHuoHyOf2vKDcOKA="; - } - ) + (fetchurl { + url = "https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-6.0.14.tgz"; + hash = "sha256-1MW3pVIffdxq63gY64ozM1erWM2ou2L8T+MTfG+ZPLg="; + }) + (fetchurl { + url = "https://downloads.mongodb.com/compass/mongosh-2.1.5-linux-x64.tgz"; + hash = "sha256-R1GGB0ZGqmpJtMUNF2+EJK6iNiChHuoHyOf2vKDcOKA="; + }) ]; sourceRoot = "."; - nativeBuildInputs = [ - autoPatchelfHook - ]; + nativeBuildInputs = [ autoPatchelfHook ]; buildPhase = '' mkdir -p $out/bin cp mongosh-2.1.5-linux-x64/bin/mongosh $out/bin/mongo cp mongodb-linux-x86_64-ubuntu2204-6.0.14/bin/mongod $out/bin/mongod ''; - buildInputs = [openssl curl xz libgcc]; + buildInputs = [ + openssl + curl + xz + libgcc + ]; } diff --git a/pkgs/ollama-webui.nix b/pkgs/ollama-webui.nix index 5330959..1e188c9 100644 --- a/pkgs/ollama-webui.nix +++ b/pkgs/ollama-webui.nix @@ -56,7 +56,7 @@ buildNpmPackage rec { homepage = "https://github.com/ollama-webui/ollama-webui"; license = licenses.mit; mainProgram = pname; - maintainers = with maintainers; [malteneuss]; + maintainers = with maintainers; [ malteneuss ]; platforms = platforms.all; }; } diff --git a/pkgs/pr-tracker.nix b/pkgs/pr-tracker.nix index 1639909..5c45e96 100644 --- a/pkgs/pr-tracker.nix +++ b/pkgs/pr-tracker.nix @@ -18,8 +18,11 @@ rustPlatform.buildRustPackage { cargoHash = "sha256-9bhKtg2g5H4zGn7yVCjTazeXfeoKjtAKAlzkLkCraiw="; - nativeBuildInputs = [pkg-config]; - buildInputs = [openssl systemd]; + nativeBuildInputs = [ pkg-config ]; + buildInputs = [ + openssl + systemd + ]; meta = with lib; { description = "Nixpkgs pull request channel tracker"; @@ -29,7 +32,7 @@ rustPlatform.buildRustPackage { ''; platforms = platforms.linux; license = licenses.agpl3Plus; - maintainers = with maintainers; [patrickdag]; + maintainers = with maintainers; [ patrickdag ]; mainProgram = "pr-tracker"; }; } diff --git a/pkgs/scripts/clone-term.nix b/pkgs/scripts/clone-term.nix index ff79e9d..4c9b431 100644 --- a/pkgs/scripts/clone-term.nix +++ b/pkgs/scripts/clone-term.nix @@ -7,7 +7,12 @@ }: writeShellApplication { name = "clone-term"; - runtimeInputs = [ps procps xdotool jq]; + runtimeInputs = [ + ps + procps + xdotool + jq + ]; text = '' if [[ ''${XDG_CURRENT_DESKTOP-} == sway ]]; then diff --git a/pkgs/scripts/default.nix b/pkgs/scripts/default.nix index 98efb96..e123533 100644 --- a/pkgs/scripts/default.nix +++ b/pkgs/scripts/default.nix @@ -1,7 +1,7 @@ _final: prev: { scripts = { - usbguardw = prev.callPackage ./usbguardw.nix {}; - clone-term = prev.callPackage ./clone-term.nix {}; - impermanence-o = prev.callPackage ./impermanence-orphan.nix {}; + usbguardw = prev.callPackage ./usbguardw.nix { }; + clone-term = prev.callPackage ./clone-term.nix { }; + impermanence-o = prev.callPackage ./impermanence-orphan.nix { }; }; } diff --git a/pkgs/scripts/impermanence-orphan.nix b/pkgs/scripts/impermanence-orphan.nix index e9d031b..1a3a808 100644 --- a/pkgs/scripts/impermanence-orphan.nix +++ b/pkgs/scripts/impermanence-orphan.nix @@ -1,5 +1,5 @@ -{writers}: -writers.writePython3Bin "find-orphaned" {} '' +{ writers }: +writers.writePython3Bin "find-orphaned" { } '' import sys import os if len(sys.argv) != 2: diff --git a/pkgs/scripts/usbguardw.nix b/pkgs/scripts/usbguardw.nix index 0b95b06..9453aac 100644 --- a/pkgs/scripts/usbguardw.nix +++ b/pkgs/scripts/usbguardw.nix @@ -1,4 +1,4 @@ -{writeShellApplication}: +{ writeShellApplication }: writeShellApplication { name = "usguardw"; text = '' diff --git a/pkgs/zsh-histdb-skim.nix b/pkgs/zsh-histdb-skim.nix index 7bbacee..fc37cc9 100644 --- a/pkgs/zsh-histdb-skim.nix +++ b/pkgs/zsh-histdb-skim.nix @@ -6,7 +6,7 @@ rustPlatform.buildRustPackage rec { pname = "zsh-histd-skim"; version = "0.8.6"; - buildInputs = [sqlite]; + buildInputs = [ sqlite ]; src = fetchFromGitHub { owner = "m42e"; repo = "zsh-histdb-skim"; diff --git a/users/common/graphical/Xorg/default.nix b/users/common/graphical/Xorg/default.nix index 46d14df..caf46fb 100644 --- a/users/common/graphical/Xorg/default.nix +++ b/users/common/graphical/Xorg/default.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ home.packages = [ pkgs.xclip pkgs.xdragon diff --git a/users/common/graphical/Xorg/herbst-keys.nix b/users/common/graphical/Xorg/herbst-keys.nix index ca145cd..2c78251 100644 --- a/users/common/graphical/Xorg/herbst-keys.nix +++ b/users/common/graphical/Xorg/herbst-keys.nix @@ -79,13 +79,15 @@ MOD: TAGS: pkgs: "${MOD}-m " = "spawn ${pkgs.thunderbird}/bin/thunderbird"; "Menu" = "spawn rofi -show drun"; } -// builtins.listToAttrs (map (x: { +// builtins.listToAttrs ( + map (x: { name = "${MOD}-${x}"; value = "use_index ${x}"; - }) - TAGS) -// builtins.listToAttrs (map (x: { + }) TAGS +) +// builtins.listToAttrs ( + map (x: { name = "${MOD}-Shift-${x}"; value = "move_index ${x}"; - }) - TAGS) + }) TAGS +) diff --git a/users/common/graphical/Xorg/herbstluft.nix b/users/common/graphical/Xorg/herbstluft.nix index 12aac06..ba3430f 100644 --- a/users/common/graphical/Xorg/herbstluft.nix +++ b/users/common/graphical/Xorg/herbstluft.nix @@ -1,18 +1,14 @@ -{ - pkgs, - lib, - ... -}: let +{ pkgs, lib, ... }: +let # set the modifier key to WIN MOD = "Super"; #set the default resize step for herbstluft TAGS = map toString (lib.lists.range 1 9); -in { +in +{ xsession.windowManager.herbstluftwm = { enable = true; - package = pkgs.herbstluftwm.overrideAttrs (_finalAttrs: _previousAttrs: { - doCheck = false; - }); + package = pkgs.herbstluftwm.overrideAttrs (_finalAttrs: _previousAttrs: { doCheck = false; }); extraConfig = '' herbstclient set auto_detect_monitors 1 killall polybar diff --git a/users/common/graphical/Xorg/i3.nix b/users/common/graphical/Xorg/i3.nix index d4dcc39..34dfec0 100644 --- a/users/common/graphical/Xorg/i3.nix +++ b/users/common/graphical/Xorg/i3.nix @@ -3,11 +3,12 @@ pkgs, lib, ... -}: { +}: +{ # import shared sway config - imports = [../sway3.nix]; + imports = [ ../sway3.nix ]; systemd.user.services = { - flameshot.Install.WantedBy = lib.mkForce ["i3-session.target"]; + flameshot.Install.WantedBy = lib.mkForce [ "i3-session.target" ]; }; stylix.targets.i3.enable = true; @@ -16,82 +17,87 @@ enableSystemdTarget = true; config = { startup = [ - {command = "${pkgs.xorg.xrandr}/bin/xrandr --output DVI-D-0 --mode 1920x1080 --pos 0x0 --rate 60.00 --output DP-4 --mode 2560x1440 --pos 1920x720 --primary --rate 144 --output HDMI-0 --pos 0x1080 --rate 60.00";} + { + command = "${pkgs.xorg.xrandr}/bin/xrandr --output DVI-D-0 --mode 1920x1080 --pos 0x0 --rate 60.00 --output DP-4 --mode 2560x1440 --pos 1920x720 --primary --rate 144 --output HDMI-0 --pos 0x1080 --rate 60.00"; + } ]; menu = "rofi -show drun"; - keybindings = let - cfg = config.xsession.windowManager.i3.config; - maim = "${pkgs.maim}/bin/maim -qs -b 1 --hidecursor"; - in { - "Menu" = "exec ${cfg.menu}"; - "Ctrl+F9" = "exec ${config.xsession.wallpapers.script}"; - "${cfg.modifier}+F12" = - "exec " - + toString ( - pkgs.writeShellScript "clipboard-screenshot" '' - ${maim} | ${pkgs.xclip}/bin/xclip -selection clipboard -t image/png - '' - ); - "${cfg.modifier}+F11" = - "exec " - + toString ( - pkgs.writeShellScript "clipboard-screenshot" '' - out="screenshot-$(date +"%Y-%m-%dT%H:%M:%S%:z")" - ${maim} | ${pkgs.xclip}/bin/xclip -selection clipboard -t image/png - '' - ); - "${cfg.modifier}+F10" = let - nsend = '' - ${pkgs.libnotify}/bin/notify-send \ - -h string:category:Screenshot\ - ''; + keybindings = + let + cfg = config.xsession.windowManager.i3.config; + maim = "${pkgs.maim}/bin/maim -qs -b 1 --hidecursor"; in - "exec " - + toString ( - pkgs.writeShellScript "clipboard-qr-screenshot" '' - set -euo pipefail - if qr=$(${maim} | ${pkgs.zbar}/bin/zbarimg -q --raw -); then - return=$? - else - return=$? - fi - case "$return" in - "0") - ${nsend} "Copied qr to clipboard" - ${pkgs.xclip}/bin/xclip -selection clipboard -f <<< ''${qr%"''${qr##*[![:space:]]}"} - exit 0 - ;; - "4") - ${nsend} "No qr found" - ;; - *) - ${nsend} "Failure scanning qr" - ;; - esac - '' - ); - "${cfg.modifier}+F9" = - "exec " - + toString ( - pkgs.writeShellScript "clipboard-ocr-screenshot" '' - set -euo pipefail - qr=$(${maim} | ${pkgs.zbar}/bin/zbarimg -q --raw -) || true - case "$?" in - 0) - ${pkgs.libnotify}/bin/notify-send -h string:category:"Screenshot" "Copied qr to clipboard" - ${pkgs.xclip}/bin/xclip -selection clipboard -f <<< ''${qr%"''${qr##*[![:space:]]}"} - exit 0 - ;; - 4) - ${pkgs.libnotify}/bin/notify-send -h string:category:"Screenshot" "No qr found" - ;; - *) - ${pkgs.libnotify}/bin/notify-send -h string:category:"Screenshot" "Failure scanning qr" - ;; - esac - '' - ); - }; + { + "Menu" = "exec ${cfg.menu}"; + "Ctrl+F9" = "exec ${config.xsession.wallpapers.script}"; + "${cfg.modifier}+F12" = + "exec " + + toString ( + pkgs.writeShellScript "clipboard-screenshot" '' + ${maim} | ${pkgs.xclip}/bin/xclip -selection clipboard -t image/png + '' + ); + "${cfg.modifier}+F11" = + "exec " + + toString ( + pkgs.writeShellScript "clipboard-screenshot" '' + out="screenshot-$(date +"%Y-%m-%dT%H:%M:%S%:z")" + ${maim} | ${pkgs.xclip}/bin/xclip -selection clipboard -t image/png + '' + ); + "${cfg.modifier}+F10" = + let + nsend = '' + ${pkgs.libnotify}/bin/notify-send \ + -h string:category:Screenshot\ + ''; + in + "exec " + + toString ( + pkgs.writeShellScript "clipboard-qr-screenshot" '' + set -euo pipefail + if qr=$(${maim} | ${pkgs.zbar}/bin/zbarimg -q --raw -); then + return=$? + else + return=$? + fi + case "$return" in + "0") + ${nsend} "Copied qr to clipboard" + ${pkgs.xclip}/bin/xclip -selection clipboard -f <<< ''${qr%"''${qr##*[![:space:]]}"} + exit 0 + ;; + "4") + ${nsend} "No qr found" + ;; + *) + ${nsend} "Failure scanning qr" + ;; + esac + '' + ); + "${cfg.modifier}+F9" = + "exec " + + toString ( + pkgs.writeShellScript "clipboard-ocr-screenshot" '' + set -euo pipefail + qr=$(${maim} | ${pkgs.zbar}/bin/zbarimg -q --raw -) || true + case "$?" in + 0) + ${pkgs.libnotify}/bin/notify-send -h string:category:"Screenshot" "Copied qr to clipboard" + ${pkgs.xclip}/bin/xclip -selection clipboard -f <<< ''${qr%"''${qr##*[![:space:]]}"} + exit 0 + ;; + 4) + ${pkgs.libnotify}/bin/notify-send -h string:category:"Screenshot" "No qr found" + ;; + *) + ${pkgs.libnotify}/bin/notify-send -h string:category:"Screenshot" "Failure scanning qr" + ;; + esac + '' + ); + }; }; }; } diff --git a/users/common/graphical/Xorg/polybar.nix b/users/common/graphical/Xorg/polybar.nix index a526458..53f9c6c 100644 --- a/users/common/graphical/Xorg/polybar.nix +++ b/users/common/graphical/Xorg/polybar.nix @@ -13,7 +13,8 @@ pkgs, nixosConfig, ... -}: let +}: +let color = { shade1 = "#311B92"; shade2 = "#4527A0"; @@ -58,7 +59,8 @@ }; fontsize = "9"; -in { +in +{ services.polybar = { enable = true; @@ -89,9 +91,24 @@ in { }; modules = with lib; { - left = concatStringsSep " " ["left1" "title" "left2"]; - center = concatStringsSep " " ["workspaces"]; - right = concatStringsSep " " ["right5" "alsa" "right4" "battery" "right3" "network" "right2" "date" "right1" "keyboardswitcher"]; + left = concatStringsSep " " [ + "left1" + "title" + "left2" + ]; + center = concatStringsSep " " [ "workspaces" ]; + right = concatStringsSep " " [ + "right5" + "alsa" + "right4" + "battery" + "right3" + "network" + "right2" + "date" + "right1" + "keyboardswitcher" + ]; }; tray = { @@ -108,9 +125,22 @@ in { dpi = 96; height = 22; modules = with lib; { - left = concatStringsSep " " ["left1" "title" "left2"]; - center = concatStringsSep " " ["workspaces"]; - right = concatStringsSep " " ["right5" "alsa" "right3" "network" "right2" "date" "right1" "keyboardswitcher"]; + left = concatStringsSep " " [ + "left1" + "title" + "left2" + ]; + center = concatStringsSep " " [ "workspaces" ]; + right = concatStringsSep " " [ + "right5" + "alsa" + "right3" + "network" + "right2" + "date" + "right1" + "keyboardswitcher" + ]; }; }; patricknix = { @@ -120,14 +150,28 @@ in { dpi = 144; height = 33; modules = with lib; { - left = concatStringsSep " " ["left1" "title" "left2"]; - center = concatStringsSep " " ["workspaces"]; - right = concatStringsSep " " ["right5" "alsa" "right4" "battery" "right3" "network" "right2" "date" "right1" "keyboardswitcher"]; + left = concatStringsSep " " [ + "left1" + "title" + "left2" + ]; + center = concatStringsSep " " [ "workspaces" ]; + right = concatStringsSep " " [ + "right5" + "alsa" + "right4" + "battery" + "right3" + "network" + "right2" + "date" + "right1" + "keyboardswitcher" + ]; }; }; } - .${nixosConfig.node.name} - or {}; + .${nixosConfig.node.name} or { }; # Functional MODULES @@ -296,8 +340,7 @@ in { interface = "wlan0"; }; } - .${nixosConfig.node.name} - or {}; + .${nixosConfig.node.name} or { }; "module/keyboardswitcher" = { type = "custom/menu"; diff --git a/users/common/graphical/default.nix b/users/common/graphical/default.nix index ffdc0b3..f5e2be7 100644 --- a/users/common/graphical/default.nix +++ b/users/common/graphical/default.nix @@ -1,8 +1,5 @@ +{ pkgs, config, ... }: { - pkgs, - config, - ... -}: { home = { packages = with pkgs; [ zathura diff --git a/users/common/graphical/sway3.nix b/users/common/graphical/sway3.nix index ebbaeff..d3cfd10 100644 --- a/users/common/graphical/sway3.nix +++ b/users/common/graphical/sway3.nix @@ -32,63 +32,108 @@ let trayOutput = "primary"; } ]; - floating.criteria = [ - {class = "Pavucontrol";} - ]; + floating.criteria = [ { class = "Pavucontrol"; } ]; assigns = { - "2:d" = [ - {class = "^firefox$";} - ]; - "2:2" = [ - {class = "^spotify$";} - ]; - "3:u" = [ - {class = "^thunderbird$";} - ]; + "2:d" = [ { class = "^firefox$"; } ]; + "2:2" = [ { class = "^spotify$"; } ]; + "3:u" = [ { class = "^thunderbird$"; } ]; "4:a" = [ - {class = "^bottles$";} - {class = "^steam$";} - {class = "^prismlauncher$";} - ]; - "1:F1" = [ - {class = "^discord$";} + { class = "^bottles$"; } + { class = "^steam$"; } + { class = "^prismlauncher$"; } ]; + "1:F1" = [ { class = "^discord$"; } ]; "2:F2" = [ - {class = "^Signal$";} - {class = "^TelegramDesktop$";} + { class = "^Signal$"; } + { class = "^TelegramDesktop$"; } ]; }; - workspaceOutputAssign = let - output = out: - lib.lists.imap1 (i: x: { - workspace = "${toString i}:${x}"; - output = out; - }); - in + workspaceOutputAssign = + let + output = + out: + lib.lists.imap1 ( + i: x: { + workspace = "${toString i}:${x}"; + output = out; + } + ); + in { "desktopnix" = - output "HDMI-0" ["1" "2" "3" "4" "5" "6" "7" "8" "9"] - ++ output "DP-4" ["j" "d" "u" "a" "x" "p"] - ++ output "DVI-D-0" ["F1" "F2" "F3" "F4"]; + output "HDMI-0" [ + "1" + "2" + "3" + "4" + "5" + "6" + "7" + "8" + "9" + ] + ++ output "DP-4" [ + "j" + "d" + "u" + "a" + "x" + "p" + ] + ++ output "DVI-D-0" [ + "F1" + "F2" + "F3" + "F4" + ]; "patricknix" = - output "eDP-1" ["1" "2" "3" "4" "5" "6" "7" "8" "9"] - ++ output "DP-1" ["j" "d" "u" "a" "x" "p"]; - "gojo" = - output "eDP-1" ["1" "2" "3" "4" "5" "6"]; + output "eDP-1" [ + "1" + "2" + "3" + "4" + "5" + "6" + "7" + "8" + "9" + ] + ++ output "DP-1" [ + "j" + "d" + "u" + "a" + "x" + "p" + ]; + "gojo" = output "eDP-1" [ + "1" + "2" + "3" + "4" + "5" + "6" + ]; } - .${nixosConfig.node.name} - or []; + .${nixosConfig.node.name} or [ ]; keybindings = - (lib.attrsets.mergeAttrsList (map (x: (let - key = lib.elemAt (lib.strings.splitString ":" x.workspace) 1; - in { - "${modifier}+${key}" = "workspace ${x.workspace}"; - "${modifier}+Shift+${key}" = "move container to workspace ${x.workspace}"; - })) - cfg.workspaceOutputAssign)) + (lib.attrsets.mergeAttrsList ( + map ( + x: + ( + let + key = lib.elemAt (lib.strings.splitString ":" x.workspace) 1; + in + { + "${modifier}+${key}" = "workspace ${x.workspace}"; + "${modifier}+Shift+${key}" = "move container to workspace ${x.workspace}"; + } + ) + ) cfg.workspaceOutputAssign + )) // { "${modifier}+t" = "exec ${terminal}"; "${modifier}+b" = "exec firefox"; @@ -137,7 +182,8 @@ let "${modifier}+period" = "workspace next_on_output"; }; }; -in { +in +{ wayland.windowManager.sway.config = cfg; xsession.windowManager.i3.config = cfg; @@ -146,9 +192,7 @@ in { bars.main = { blocks = [ - { - block = "net"; - } + { block = "net"; } { block = "cpu"; format = " $icon $utilization "; @@ -158,7 +202,10 @@ in { format = " $icon $utilization $memory $temperature "; } ] - ++ {"patricknix" = [{block = "battery";}];}.${nixosConfig.node.name} or [] + ++ { + "patricknix" = [ { block = "battery"; } ]; + } + .${nixosConfig.node.name} or [ ] ++ [ { block = "sound"; diff --git a/users/common/graphical/wayland/default.nix b/users/common/graphical/wayland/default.nix index 9ee931b..5918afc 100644 --- a/users/common/graphical/wayland/default.nix +++ b/users/common/graphical/wayland/default.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ imports = [ ../. ./fuzzel.nix diff --git a/users/common/graphical/wayland/fuzzel.nix b/users/common/graphical/wayland/fuzzel.nix index 914b6de..a16039c 100644 --- a/users/common/graphical/wayland/fuzzel.nix +++ b/users/common/graphical/wayland/fuzzel.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ stylix.targets.fuzzel.enable = true; home.packages = with pkgs; [ (writeShellScriptBin "fuzzel" '' diff --git a/users/common/graphical/wayland/hyprland.nix b/users/common/graphical/wayland/hyprland.nix index 1e9a50a..e51f5d0 100644 --- a/users/common/graphical/wayland/hyprland.nix +++ b/users/common/graphical/wayland/hyprland.nix @@ -3,9 +3,9 @@ lib, nixosConfig, ... -}: let - inherit - (lib) +}: +let + inherit (lib) mkMerge optionals elem @@ -46,7 +46,8 @@ # Listen to the Hyprland socket for events and process each line with the handle function ${pkgs.socat}/bin/socat -U - UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock | while read -r line; do handle "$line"; done ''; -in { +in +{ wayland.windowManager.hyprland = { enable = true; settings = mkMerge [ @@ -82,19 +83,20 @@ in { focus_preferred_method = 1; workspace_center_on = 1; }; - bind = let - monitor_binds = { - "1" = "j"; - "2" = "d"; - "3" = "u"; - "4" = "a"; - "5" = "x"; - "6" = "F1"; - "7" = "F2"; - "8" = "F3"; - "9" = "F4"; - }; - in + bind = + let + monitor_binds = { + "1" = "j"; + "2" = "d"; + "3" = "u"; + "4" = "a"; + "5" = "x"; + "6" = "F1"; + "7" = "F2"; + "8" = "F3"; + "9" = "F4"; + }; + in [ "SUPER,q,killactive," "SUPER,return,fullscreen," @@ -146,12 +148,10 @@ in { "SUPER + SHIFT,q,exit" ] - ++ flip concatMap (map toString (lib.lists.range 1 9)) ( - x: [ - "SUPER,${monitor_binds."${x}"},workspace,${x}" - "SUPER + SHIFT,${monitor_binds."${x}"},movetoworkspacesilent,${x}" - ] - ); + ++ flip concatMap (map toString (lib.lists.range 1 9)) (x: [ + "SUPER,${monitor_binds."${x}"},workspace,${x}" + "SUPER + SHIFT,${monitor_binds."${x}"},movetoworkspacesilent,${x}" + ]); cursor.no_warps = true; debug.disable_logs = false; @@ -163,7 +163,7 @@ in { "QT_QPA_PLATFORM,wayland" "SDL_VIDEODRIVER,'wayland,x11,windows'" "GDK_BACKEND,wayland" - "WLR_DRM_NO_ATOMIC,1" #retest on newest nvidia driver + "WLR_DRM_NO_ATOMIC,1" # retest on newest nvidia driver ]; bindm = [ # mouse movements diff --git a/users/common/graphical/wayland/sway.nix b/users/common/graphical/wayland/sway.nix index 0fc5f84..ea9d165 100644 --- a/users/common/graphical/wayland/sway.nix +++ b/users/common/graphical/wayland/sway.nix @@ -1,10 +1,7 @@ +{ config, nixosConfig, ... }: { - config, - nixosConfig, - ... -}: { # import shared i3 config - imports = [../sway3.nix]; + imports = [ ../sway3.nix ]; stylix.targets.sway.enable = true; wayland.windowManager.sway = { enable = true; @@ -42,11 +39,13 @@ map_to_output = "eDP-1"; }; }; - keybindings = let - cfg = config.wayland.windowManager.sway.config; - in { - "Menu" = "exec ${cfg.menu}"; - }; + keybindings = + let + cfg = config.wayland.windowManager.sway.config; + in + { + "Menu" = "exec ${cfg.menu}"; + }; } // { desktopnix = { @@ -80,15 +79,16 @@ }; }; } - .${nixosConfig.node.name} - or {}; - extraConfig = let - cfg = config.wayland.windowManager.sway.config; - in '' - bindgesture swipe:3:left workpace next - bindgesture swipe:3:right workpace prev - bindgesture pinch:4:outward exec ${cfg.menu} - ''; + .${nixosConfig.node.name} or { }; + extraConfig = + let + cfg = config.wayland.windowManager.sway.config; + in + '' + bindgesture swipe:3:left workpace next + bindgesture swipe:3:right workpace prev + bindgesture pinch:4:outward exec ${cfg.menu} + ''; }; # Cursor invisible home.sessionVariables = { diff --git a/users/common/graphical/wayland/swaync/default.nix b/users/common/graphical/wayland/swaync/default.nix index defc692..7fea219 100644 --- a/users/common/graphical/wayland/swaync/default.nix +++ b/users/common/graphical/wayland/swaync/default.nix @@ -1,8 +1,5 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { services.swaync = { enable = true; settings = { @@ -88,5 +85,5 @@ }; # Started via hyprland to ensure it restarts properly with hyprland - systemd.user.services.swaync.Install.WantedBy = lib.mkForce []; + systemd.user.services.swaync.Install.WantedBy = lib.mkForce [ ]; } diff --git a/users/common/graphical/wayland/swww.nix b/users/common/graphical/wayland/swww.nix index 3a89cdc..4488e61 100644 --- a/users/common/graphical/wayland/swww.nix +++ b/users/common/graphical/wayland/swww.nix @@ -1,13 +1,8 @@ -{ - lib, - pkgs, - ... -}: let +{ lib, pkgs, ... }: +let swww-update-wallpaper = pkgs.writeShellApplication { name = "swww-update-wallpaper"; - runtimeInputs = [ - pkgs.swww - ]; + runtimeInputs = [ pkgs.swww ]; text = '' FILES=("$HOME/.local/share/wallpapers/"*) TYPES=("wipe" "any") @@ -20,14 +15,15 @@ --transition-duration 1.5 ''; }; -in { +in +{ systemd.user = { services = { swww = { - Install.WantedBy = ["graphical-session.target"]; + Install.WantedBy = [ "graphical-session.target" ]; Unit = { Description = "Wayland wallpaper daemon"; - PartOf = ["graphical-session.target"]; + PartOf = [ "graphical-session.target" ]; }; Service = { ExecStart = "${pkgs.swww}/bin/swww-daemon"; @@ -35,7 +31,7 @@ in { }; }; swww-update-wallpaper = { - Install.WantedBy = ["default.target"]; + Install.WantedBy = [ "default.target" ]; Unit.Description = "Update the wallpaper"; Service = { Type = "oneshot"; @@ -46,7 +42,7 @@ in { }; }; timers.swww-update-wallpaper = { - Install.WantedBy = ["timers.target"]; + Install.WantedBy = [ "timers.target" ]; Unit.Description = "Periodically switch to a new wallpaper"; Timer.OnCalendar = "*:0/3"; # Every 5 minutes }; diff --git a/users/common/graphical/wayland/waybar/default.nix b/users/common/graphical/wayland/waybar/default.nix index 9ec6410..2711603 100644 --- a/users/common/graphical/wayland/waybar/default.nix +++ b/users/common/graphical/wayland/waybar/default.nix @@ -3,12 +3,14 @@ lib, nixosConfig, ... -}: { +}: +{ programs.waybar = { enable = true; systemd.enable = false; style = - ({ + ( + { desktopnix = '' * { /* `otf-font-awesome` is required to be installed for icons */ @@ -26,14 +28,18 @@ } ''; } - .${nixosConfig.node.name} - or "") + .${nixosConfig.node.name} or "" + ) + builtins.readFile ./waybar.css; settings.main = { layer = "top"; position = "bottom"; - modules-left = ["privacy" "hyprland/submap" "hyprland/window"]; - modules-center = ["hyprland/workspaces"]; + modules-left = [ + "privacy" + "hyprland/submap" + "hyprland/window" + ]; + modules-center = [ "hyprland/workspaces" ]; modules-right = { desktopnix = [ @@ -58,13 +64,22 @@ "tray" ]; } - .${nixosConfig.node.name} - or []; + .${nixosConfig.node.name} or [ ]; battery = { interval = 1; format = "{icon} {capacity}%"; - format-icons = ["" "" "" "" "" "" "" "" ""]; + format-icons = [ + "" + "" + "" + "" + "" + "" + "" + "" + "" + ]; states = { critical = 10; warning = 20; @@ -74,7 +89,18 @@ backlight = { device = "intel_backlight"; format = "{icon} {percent}%"; - format-icons = ["󱩎" "󱩏" "󱩐" "󱩑" "󱩒" "󱩓" "󱩔" "󱩕" "󱩖" "󰛨"]; + format-icons = [ + "󱩎" + "󱩏" + "󱩐" + "󱩑" + "󱩒" + "󱩓" + "󱩔" + "󱩕" + "󱩖" + "󰛨" + ]; on-scroll-up = "${pkgs.acpilight}/bin/xbacklight +5"; on-scroll-down = "${pkgs.acpilight}/bin/xbacklight -5"; }; @@ -114,7 +140,11 @@ on-scroll-up = "${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+"; on-scroll-down = "${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%-"; format-muted = "󰖁"; - format-icons = ["󰕿" "󰖀" "󰕾"]; + format-icons = [ + "󰕿" + "󰖀" + "󰕾" + ]; }; "hyprland/workspaces" = { @@ -123,9 +153,21 @@ all-outputs = false; sort-by = "id"; persistent-workspaces = { - "DP-3" = [1 2 3 4 5]; - "DVI-D-1" = [6 7]; - "HDMI-A-1" = [8 9]; + "DP-3" = [ + 1 + 2 + 3 + 4 + 5 + ]; + "DVI-D-1" = [ + 6 + 7 + ]; + "HDMI-A-1" = [ + 8 + 9 + ]; }; }; diff --git a/users/common/impermanence.nix b/users/common/impermanence.nix index 7fd1ef2..614b906 100644 --- a/users/common/impermanence.nix +++ b/users/common/impermanence.nix @@ -3,24 +3,21 @@ lib, nixosConfig, ... -}: { +}: +{ home.persistence."/state" = { - files = with lib.lists; + files = + with lib.lists; [ ".ssh/known_hosts" ".cache/fuzzel" ] - ++ optionals config.programs.rofi.enable [ - ".cache/rofi3.druncache" - ]; - directories = with lib.lists; - [".config/dconf"] - ++ optionals config.programs.direnv.enable [ - ".local/share/direnv" - ] - ++ optionals config.programs.nushell.enable [ - ".config/nushell" - ] + ++ optionals config.programs.rofi.enable [ ".cache/rofi3.druncache" ]; + directories = + with lib.lists; + [ ".config/dconf" ] + ++ optionals config.programs.direnv.enable [ ".local/share/direnv" ] + ++ optionals config.programs.nushell.enable [ ".config/nushell" ] ++ optionals nixosConfig.services.pipewire.enable [ # persist sound config ".local/state/wireplumber" diff --git a/users/common/programs/bottles.nix b/users/common/programs/bottles.nix index ce61a48..72c2f35 100644 --- a/users/common/programs/bottles.nix +++ b/users/common/programs/bottles.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ home.packages = with pkgs; [ bottles winetricks diff --git a/users/common/programs/firefox.nix b/users/common/programs/firefox.nix index 9d53c04..0630fe6 100644 --- a/users/common/programs/firefox.nix +++ b/users/common/programs/firefox.nix @@ -17,9 +17,9 @@ ]; xdg.mimeApps.enable = true; xdg.mimeApps.defaultApplications = { - "text/html" = ["firefox.desktop"]; - "text/xml" = ["firefox.desktop"]; - "x-scheme-handler/http" = ["firefox.desktop"]; - "x-scheme-handler/https" = ["firefox.desktop"]; + "text/html" = [ "firefox.desktop" ]; + "text/xml" = [ "firefox.desktop" ]; + "x-scheme-handler/http" = [ "firefox.desktop" ]; + "x-scheme-handler/https" = [ "firefox.desktop" ]; }; } diff --git a/users/common/programs/gdb.nix b/users/common/programs/gdb.nix index 5c14861..98142de 100644 --- a/users/common/programs/gdb.nix +++ b/users/common/programs/gdb.nix @@ -1,19 +1,19 @@ -{pkgs, ...}: let +{ pkgs, ... }: +let pwndbgWithDebuginfod = - (pkgs.pwndbg.override { - gdb = pkgs.gdb.override { - enableDebuginfod = true; - }; - }) - .overrideAttrs (_finalAttrs: previousAttrs: { - installPhase = - previousAttrs.installPhase - + '' - ln -s $out/bin/pwndbg $out/bin/gdb - ''; - }); -in { - home.packages = [pwndbgWithDebuginfod]; + (pkgs.pwndbg.override { gdb = pkgs.gdb.override { enableDebuginfod = true; }; }).overrideAttrs + ( + _finalAttrs: previousAttrs: { + installPhase = + previousAttrs.installPhase + + '' + ln -s $out/bin/pwndbg $out/bin/gdb + ''; + } + ); +in +{ + home.packages = [ pwndbgWithDebuginfod ]; home.enableDebugInfo = true; xdg.configFile.gdbinit = { target = "gdb/gbdinit"; @@ -29,7 +29,5 @@ in { ''; }; - home.persistence."/state".directories = [ - ".local/share/gdb" - ]; + home.persistence."/state".directories = [ ".local/share/gdb" ]; } diff --git a/users/common/programs/git.nix b/users/common/programs/git.nix index d6d05f4..7ae46e8 100644 --- a/users/common/programs/git.nix +++ b/users/common/programs/git.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ programs.git = { enable = true; difftastic.enable = true; diff --git a/users/common/programs/gpg.nix b/users/common/programs/gpg.nix index 32981e7..62fc697 100644 --- a/users/common/programs/gpg.nix +++ b/users/common/programs/gpg.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ services.gpg-agent = { enable = true; enableSshSupport = true; diff --git a/users/common/programs/htop.nix b/users/common/programs/htop.nix index 70eca97..9bab773 100644 --- a/users/common/programs/htop.nix +++ b/users/common/programs/htop.nix @@ -1,4 +1,5 @@ -{config, ...}: { +{ config, ... }: +{ programs.htop = { enable = true; settings = @@ -12,21 +13,25 @@ hide_userland_threads = 1; sort_key = 46; # Sort by %CPU if not in tree mode } - // (with config.lib.htop; + // ( + with config.lib.htop; leftMeters [ (bar "LeftCPUs2") (bar "Memory") (bar "Swap") (bar "ZFSARC") (text "NetworkIO") - ]) - // (with config.lib.htop; + ] + ) + // ( + with config.lib.htop; rightMeters [ (bar "RightCPUs2") (text "LoadAverage") (text "Tasks") (text "Uptime") (text "Systemd") - ]); + ] + ); }; } diff --git a/users/common/programs/kitty.nix b/users/common/programs/kitty.nix index 08fe540..da096d9 100644 --- a/users/common/programs/kitty.nix +++ b/users/common/programs/kitty.nix @@ -1,14 +1,9 @@ +{ pkgs, lib, ... }: { - pkgs, - lib, - ... -}: { stylix.targets.kitty.enable = true; programs.kitty = { enable = true; - package = pkgs.kitty.overrideAttrs (_finalAttrs: _prevAttrs: { - doCheck = false; - }); + package = pkgs.kitty.overrideAttrs (_finalAttrs: _prevAttrs: { doCheck = false; }); settings = { # Use xterm-256color because copying terminfo-kitty is painful. term = "xterm-256color"; diff --git a/users/common/programs/minecraft.nix b/users/common/programs/minecraft.nix index c77fd56..1029fd6 100644 --- a/users/common/programs/minecraft.nix +++ b/users/common/programs/minecraft.nix @@ -1,8 +1,5 @@ -{pkgs, ...}: { - home.persistence."/persist".directories = [ - ".local/share/PrismLauncher" - ]; - home.packages = [ - pkgs.prismlauncher - ]; +{ pkgs, ... }: +{ + home.persistence."/persist".directories = [ ".local/share/PrismLauncher" ]; + home.packages = [ pkgs.prismlauncher ]; } diff --git a/users/common/programs/nvim/default.nix b/users/common/programs/nvim/default.nix index 4defcc5..5ff4b49 100644 --- a/users/common/programs/nvim/default.nix +++ b/users/common/programs/nvim/default.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ imports = [ ./nixvim/keybinds.nix ./nixvim/options.nix @@ -26,9 +27,7 @@ require("onedark").load() ''; extraConfigLuaPost = - /* - lua - */ + # lua '' vim.notify = require("notify") require("window-picker").setup { diff --git a/users/common/programs/nvim/nixvim/keybinds.nix b/users/common/programs/nvim/nixvim/keybinds.nix index 49bfa4c..589d04c 100644 --- a/users/common/programs/nvim/nixvim/keybinds.nix +++ b/users/common/programs/nvim/nixvim/keybinds.nix @@ -3,56 +3,89 @@ let noremap = true; silent = true; }; -in { +in +{ programs.nixvim.keymaps = [ { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } # scroll with cursor lock @@ -60,13 +93,21 @@ in { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = ""; action = ""; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = ""; @@ -84,13 +125,21 @@ in { key = "u"; action = "UndotreeToggle"; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } { key = "t"; action = "Neotree toggle"; inherit options; - mode = ["n" "v" "s"]; + mode = [ + "n" + "v" + "s" + ]; } ]; } diff --git a/users/common/programs/nvim/nixvim/options.nix b/users/common/programs/nvim/nixvim/options.nix index b771c6a..6c8674a 100644 --- a/users/common/programs/nvim/nixvim/options.nix +++ b/users/common/programs/nvim/nixvim/options.nix @@ -12,7 +12,10 @@ wildignore = "*.o,*~"; # Only complete the longest common prefix and list all results. # You can use the cursor keys to select an item in this list - wildmode = ["list" "full"]; + wildmode = [ + "list" + "full" + ]; # set case handling ignorecase = true; diff --git a/users/common/programs/nvim/nixvim/plugins.nix b/users/common/programs/nvim/nixvim/plugins.nix index daa7a7c..037e2bb 100644 --- a/users/common/programs/nvim/nixvim/plugins.nix +++ b/users/common/programs/nvim/nixvim/plugins.nix @@ -8,26 +8,44 @@ programs.nixvim.plugins = { lualine = { enable = true; - extensions = ["fzf" "nvim-dap-ui" "symbols-outline" "trouble" "neo-tree" "quickfix" "fugitive"]; + extensions = [ + "fzf" + "nvim-dap-ui" + "symbols-outline" + "trouble" + "neo-tree" + "quickfix" + "fugitive" + ]; componentSeparators.left = ""; componentSeparators.right = ""; sectionSeparators.left = ""; sectionSeparators.right = ""; sections = { - lualine_a = ["mode"]; - lualine_b = ["branch" "filename"]; - lualine_c = ["diff" "diagnostics"]; - lualine_x = ["encoding" "fileformat" "filetype"]; - lualine_y = ["progress"]; - lualine_z = ["location"]; + lualine_a = [ "mode" ]; + lualine_b = [ + "branch" + "filename" + ]; + lualine_c = [ + "diff" + "diagnostics" + ]; + lualine_x = [ + "encoding" + "fileformat" + "filetype" + ]; + lualine_y = [ "progress" ]; + lualine_z = [ "location" ]; }; inactiveSections = { - lualine_a = ["filename"]; - lualine_b = []; - lualine_c = ["diagnostics"]; - lualine_x = []; - lualine_y = []; - lualine_z = ["location"]; + lualine_a = [ "filename" ]; + lualine_b = [ ]; + lualine_c = [ "diagnostics" ]; + lualine_x = [ ]; + lualine_y = [ ]; + lualine_z = [ "location" ]; }; }; fugitive.enable = true; @@ -36,13 +54,20 @@ rainbow-delimiters.enable = true; rustaceanvim = { enable = true; - settings.server.settings.files.excludeDirs = [".direnv"]; + settings.server.settings.files.excludeDirs = [ ".direnv" ]; }; indent-blankline = { enable = true; settings = { - exclude.buftypes = ["help" "terminal" "nofile"]; - exclude.filetypes = ["terminal" "lsp-info"]; + exclude.buftypes = [ + "help" + "terminal" + "nofile" + ]; + exclude.filetypes = [ + "terminal" + "lsp-info" + ]; }; }; gitsigns = { @@ -64,7 +89,7 @@ fzf-native.enable = true; frecency.enable = true; }; - enabledExtensions = ["notify"]; + enabledExtensions = [ "notify" ]; keymaps = { "gf" = { action = "git_files"; diff --git a/users/common/programs/nvim/nixvim/plugins/alpha.nix b/users/common/programs/nvim/nixvim/plugins/alpha.nix index fdcbf4a..aff2877 100644 --- a/users/common/programs/nvim/nixvim/plugins/alpha.nix +++ b/users/common/programs/nvim/nixvim/plugins/alpha.nix @@ -1,90 +1,92 @@ { programs.nixvim.plugins.alpha = { enable = true; - layout = let - padding = val: { - type = "padding"; - inherit val; - }; - in [ - (padding 2) - { - type = "text"; - val = [ - "⠄⠰⠛⠋⢉⣡⣤⣄⡉⠓⢦⣀⠙⠉⠡⠔⠒⠛⠛⠛⠶⢶⣄⠘⢿⣷⣤⡈⠻⣧" - "⢀⡔⠄⠄⠄⠙⣿⣿⣿⣷⣤⠉⠁⡀⠐⠒⢿⣿⣿⣿⣶⣄⡈⠳⢄⣹⣿⣿⣾⣿" - "⣼⠁⢠⡄⠄⠄⣿⣿⣿⣿⡟⠄⡐⠁⡀⠄⠈⣿⣿⣿⣿⣿⣷⣤⡈⠻⣿⣿⣿⣿" - "⢻⡀⠈⠄⠄⣀⣿⣿⣿⡿⠃⠄⡇⠈⠛⠄⠄⣿⣿⣿⣿⣿⣿⠟⠋⣠⣶⣿⣿⣿" - "⠄⢉⡓⠚⠛⠛⠋⣉⣩⣤⣤⣀⠑⠤⣤⣤⣾⣿⣿⣿⡿⠛⢁⣤⣾⣿⣿⣿⣿⣿" - "⠄⠈⠙⠛⠋⣭⣭⣶⣾⣿⣿⣿⣷⣦⢠⡍⠉⠉⢠⣤⣴⠚⢩⣴⣿⣿⣿⣿⣿⣿" - "⠄⢴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⣭⣭⣭⣥⣴⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿" - "⠄⣴⣶⡶⠶⠶⠶⠶⠶⠶⠶⠶⣮⣭⣝⣛⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿" - "⠄⠙⣿⡄⠄⠄⢀⡤⠬⢭⣝⣒⢂⠭⣉⠻⠿⣷⣶⣦⣭⡛⣿⣿⣿⣿⣿⣿⣿⣿" - "⠄⠄⠸⣿⡇⠄⠸⣎⣁⣾⠿⠉⢀⠇⣸⣿⣿⢆⡉⠹⣿⣿⢸⣿⣿⣿⣿⣿⣿⣿" - "⠄⠄⠄⣿⡇⠄⢀⡶⠶⠶⠾⠿⠮⠭⠭⢭⣥⣿⣿⣷⢸⣿⢸⣿⣿⣿⣿⣿⣿⣿" - "⠄⠄⠄⣿⡇⠄⠈⣷⠄⠄⠄⣭⣙⣹⢙⣰⡎⣿⢏⣡⣾⢏⣾⣿⣿⣿⣿⣿⣿⣿" - "⠄⠄⢰⣿⡇⠄⠄⢿⠄⠄⠈⣿⠉⠉⣻⣿⡷⣰⣿⡿⣡⣿⣿⣿⣿⣿⣿⣿⣿⣿" - "⠄⠄⢸⣿⡇⠄⠄⠘⠿⠤⠤⠿⠿⠿⢤⣤⣤⡿⣃⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿" - "⠄⠄⠘⢿⣷⣤⣄⣀⣀⣀⣀⣀⣠⣴⣾⡿⢋⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋" - ]; - opts = { - position = "center"; - hl = "Type"; + layout = + let + padding = val: { + type = "padding"; + inherit val; }; - } - (padding 2) - { - type = "group"; - opts.spacing = 1; - val = [ - { - type = "button"; - val = " New file"; - on_press.__raw = "function() vim.cmd[[enew]] end"; - opts = { - keymap = [ - "n" - "e" - ":enew" - { - noremap = true; - silent = true; - nowait = true; - } - ]; - shortcut = "e"; - position = "center"; - cursor = 3; - width = 50; - align_shortcut = "right"; - hl_shortcut = "Keyword"; - }; - } - { - type = "button"; - val = "󰅙 Quit Neovim"; - on_press.__raw = "function() vim.cmd[[qa]] end"; - opts = { - keymap = [ - "n" - "q" - ":qa" - { - noremap = true; - silent = true; - nowait = true; - } - ]; - shortcut = "q"; - position = "center"; - cursor = 3; - width = 50; - align_shortcut = "right"; - hl_shortcut = "Keyword"; - }; - } - ]; - } - ]; + in + [ + (padding 2) + { + type = "text"; + val = [ + "⠄⠰⠛⠋⢉⣡⣤⣄⡉⠓⢦⣀⠙⠉⠡⠔⠒⠛⠛⠛⠶⢶⣄⠘⢿⣷⣤⡈⠻⣧" + "⢀⡔⠄⠄⠄⠙⣿⣿⣿⣷⣤⠉⠁⡀⠐⠒⢿⣿⣿⣿⣶⣄⡈⠳⢄⣹⣿⣿⣾⣿" + "⣼⠁⢠⡄⠄⠄⣿⣿⣿⣿⡟⠄⡐⠁⡀⠄⠈⣿⣿⣿⣿⣿⣷⣤⡈⠻⣿⣿⣿⣿" + "⢻⡀⠈⠄⠄⣀⣿⣿⣿⡿⠃⠄⡇⠈⠛⠄⠄⣿⣿⣿⣿⣿⣿⠟⠋⣠⣶⣿⣿⣿" + "⠄⢉⡓⠚⠛⠛⠋⣉⣩⣤⣤⣀⠑⠤⣤⣤⣾⣿⣿⣿⡿⠛⢁⣤⣾⣿⣿⣿⣿⣿" + "⠄⠈⠙⠛⠋⣭⣭⣶⣾⣿⣿⣿⣷⣦⢠⡍⠉⠉⢠⣤⣴⠚⢩⣴⣿⣿⣿⣿⣿⣿" + "⠄⢴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⣭⣭⣭⣥⣴⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿" + "⠄⣴⣶⡶⠶⠶⠶⠶⠶⠶⠶⠶⣮⣭⣝⣛⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿" + "⠄⠙⣿⡄⠄⠄⢀⡤⠬⢭⣝⣒⢂⠭⣉⠻⠿⣷⣶⣦⣭⡛⣿⣿⣿⣿⣿⣿⣿⣿" + "⠄⠄⠸⣿⡇⠄⠸⣎⣁⣾⠿⠉⢀⠇⣸⣿⣿⢆⡉⠹⣿⣿⢸⣿⣿⣿⣿⣿⣿⣿" + "⠄⠄⠄⣿⡇⠄⢀⡶⠶⠶⠾⠿⠮⠭⠭⢭⣥⣿⣿⣷⢸⣿⢸⣿⣿⣿⣿⣿⣿⣿" + "⠄⠄⠄⣿⡇⠄⠈⣷⠄⠄⠄⣭⣙⣹⢙⣰⡎⣿⢏⣡⣾⢏⣾⣿⣿⣿⣿⣿⣿⣿" + "⠄⠄⢰⣿⡇⠄⠄⢿⠄⠄⠈⣿⠉⠉⣻⣿⡷⣰⣿⡿⣡⣿⣿⣿⣿⣿⣿⣿⣿⣿" + "⠄⠄⢸⣿⡇⠄⠄⠘⠿⠤⠤⠿⠿⠿⢤⣤⣤⡿⣃⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿" + "⠄⠄⠘⢿⣷⣤⣄⣀⣀⣀⣀⣀⣠⣴⣾⡿⢋⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋" + ]; + opts = { + position = "center"; + hl = "Type"; + }; + } + (padding 2) + { + type = "group"; + opts.spacing = 1; + val = [ + { + type = "button"; + val = " New file"; + on_press.__raw = "function() vim.cmd[[enew]] end"; + opts = { + keymap = [ + "n" + "e" + ":enew" + { + noremap = true; + silent = true; + nowait = true; + } + ]; + shortcut = "e"; + position = "center"; + cursor = 3; + width = 50; + align_shortcut = "right"; + hl_shortcut = "Keyword"; + }; + } + { + type = "button"; + val = "󰅙 Quit Neovim"; + on_press.__raw = "function() vim.cmd[[qa]] end"; + opts = { + keymap = [ + "n" + "q" + ":qa" + { + noremap = true; + silent = true; + nowait = true; + } + ]; + shortcut = "q"; + position = "center"; + cursor = 3; + width = 50; + align_shortcut = "right"; + hl_shortcut = "Keyword"; + }; + } + ]; + } + ]; }; } diff --git a/users/common/programs/nvim/nixvim/plugins/cmp.nix b/users/common/programs/nvim/nixvim/plugins/cmp.nix index 29da3c3..315d497 100644 --- a/users/common/programs/nvim/nixvim/plugins/cmp.nix +++ b/users/common/programs/nvim/nixvim/plugins/cmp.nix @@ -24,28 +24,28 @@ settings = { sources = [ #{name = "luasnip";} - {name = "nvim_lsp_signature_help";} - {name = "nvim_lsp";} - {name = "nvim_lsp_document_symbol";} - {name = "treesitter";} - {name = "path";} - {name = "calc";} - {name = "emoji";} + { name = "nvim_lsp_signature_help"; } + { name = "nvim_lsp"; } + { name = "nvim_lsp_document_symbol"; } + { name = "treesitter"; } + { name = "path"; } + { name = "calc"; } + { name = "emoji"; } ]; snippet.expand = - /* - lua - */ + # lua '' function(args) require('luasnip').lsp_expand(args.body) end ''; - formatting.fields = ["abbr" "kind" "menu"]; + formatting.fields = [ + "abbr" + "kind" + "menu" + ]; formatting.format = - /* - lua - */ + # lua '' function(_, vim_item) local icons = { @@ -98,9 +98,7 @@ "" = "cmp.mapping.confirm({ select = false })"; "" = "cmp.mapping(cmp.mapping.complete(), { \"i\", \"c\" })"; "" = - /* - lua - */ + # lua '' function(fallback) if cmp.visible() then @@ -116,9 +114,7 @@ end ''; "" = - /* - lua - */ + # lua '' function(fallback) if cmp.visible() then diff --git a/users/common/programs/nvim/nixvim/plugins/lsp.nix b/users/common/programs/nvim/nixvim/plugins/lsp.nix index b720ef7..6311a8c 100644 --- a/users/common/programs/nvim/nixvim/plugins/lsp.nix +++ b/users/common/programs/nvim/nixvim/plugins/lsp.nix @@ -1,8 +1,5 @@ +{ lib, pkgs, ... }: { - lib, - pkgs, - ... -}: { programs.nixvim.plugins = { none-ls = { enable = true; @@ -57,7 +54,10 @@ nil-ls = { enable = true; settings = { - formatting.command = [(lib.getExe pkgs.nixfmt-rfc-style) "--quiet"]; + formatting.command = [ + (lib.getExe pkgs.nixfmt-rfc-style) + "--quiet" + ]; }; }; nixd.enable = true; diff --git a/users/common/programs/nvim/nixvim/plugins/neo-tree.nix b/users/common/programs/nvim/nixvim/plugins/neo-tree.nix index 12721ab..86e6a95 100644 --- a/users/common/programs/nvim/nixvim/plugins/neo-tree.nix +++ b/users/common/programs/nvim/nixvim/plugins/neo-tree.nix @@ -48,7 +48,7 @@ useLibuvFileWatcher = true; filteredItems = { hideDotfiles = false; - hideByName = [".git"]; + hideByName = [ ".git" ]; }; }; }; diff --git a/users/common/programs/obs.nix b/users/common/programs/obs.nix index 9bb3175..1a2b8b4 100644 --- a/users/common/programs/obs.nix +++ b/users/common/programs/obs.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ programs.obs-studio = { enable = true; plugins = with pkgs.obs-studio-plugins; [ diff --git a/users/common/programs/poe.nix b/users/common/programs/poe.nix index 59c5d03..a4a1522 100644 --- a/users/common/programs/poe.nix +++ b/users/common/programs/poe.nix @@ -1,11 +1,8 @@ -{pkgs, ...}: { - home.persistence."/state".directories = [ - ".config/awakened-poe-trade" - ]; +{ pkgs, ... }: +{ + home.persistence."/state".directories = [ ".config/awakened-poe-trade" ]; - home.persistence."/persist".directories = [ - ".local/share/pobfrontend" - ]; + home.persistence."/persist".directories = [ ".local/share/pobfrontend" ]; home.packages = [ #pkgs.awakened-poe-trade diff --git a/users/common/programs/spicetify.nix b/users/common/programs/spicetify.nix index a4b5bdb..8f0ac00 100644 --- a/users/common/programs/spicetify.nix +++ b/users/common/programs/spicetify.nix @@ -1,4 +1,5 @@ -{spicePkgs, ...}: { +{ spicePkgs, ... }: +{ programs.spicetify = { enable = true; theme = spicePkgs.themes.retroBlur; diff --git a/users/common/programs/thunderbird.nix b/users/common/programs/thunderbird.nix index f10c091..21b6a81 100644 --- a/users/common/programs/thunderbird.nix +++ b/users/common/programs/thunderbird.nix @@ -1,14 +1,13 @@ +{ config, lib, ... }: { - config, - lib, - ... -}: { accounts.email.accounts = lib.flip lib.mapAttrs' config.userSecrets.accounts.email ( _: v: - lib.nameValuePair v.address (lib.recursiveUpdate v { + lib.nameValuePair v.address ( + lib.recursiveUpdate v { thunderbird.enable = true; - thunderbird.profiles = ["personal"]; - }) + thunderbird.profiles = [ "personal" ]; + } + ) ); programs.thunderbird = { enable = true; @@ -69,11 +68,14 @@ }; }; - home.persistence."/state".directories = [".cache/thunderbird" ".thunderbird"]; + home.persistence."/state".directories = [ + ".cache/thunderbird" + ".thunderbird" + ]; xdg.mimeApps.enable = true; xdg.mimeApps.defaultApplications = { - "x-scheme-handler/mailto" = ["thunderbird.desktop"]; - "x-scheme-handler/mid" = ["thunderbird.desktop"]; - "message/rfc822" = ["thunderbird.desktop"]; + "x-scheme-handler/mailto" = [ "thunderbird.desktop" ]; + "x-scheme-handler/mid" = [ "thunderbird.desktop" ]; + "message/rfc822" = [ "thunderbird.desktop" ]; }; } diff --git a/users/common/shells/pager.nix b/users/common/shells/pager.nix index d01b645..59a61d9 100644 --- a/users/common/shells/pager.nix +++ b/users/common/shells/pager.nix @@ -1,70 +1,70 @@ +{ pkgs, lib, ... }: +let + exe = lib.getExe ( + pkgs.nixvim.makeNixvim { + package = pkgs.neovim-clean; + + opts = { + buftype = "nowrite"; + backup = false; + modeline = false; + shelltemp = false; + swapfile = false; + undofile = false; + writebackup = false; + virtualedit = "all"; + splitkeep = "screen"; + termguicolors = false; + # set case handling + ignorecase = true; + smartcase = true; + }; + + extraConfigLua = '' + vim.opt.shadafile = vim.fn.stdpath "state" .. "/shada/man.shada"; + ''; + + keymaps = [ + { + action = ""; + key = ""; + mode = [ "n" ]; + options = { + silent = true; + desc = "Jump to tag under cursor"; + }; + } + { + action = ":pop"; + key = ""; + mode = [ "n" ]; + options = { + silent = true; + desc = "Jump to previous tag in stack"; + }; + } + { + action = ":pop"; + key = ""; + mode = [ "n" ]; + options = { + silent = true; + desc = "Jump to previous tag in stack"; + }; + } + { + action = ":tag"; + key = ""; + mode = [ "n" ]; + options = { + silent = true; + desc = "Jump to next tag in stack"; + }; + } + ]; + } + ); +in { - pkgs, - lib, - ... -}: let - exe = lib.getExe (pkgs.nixvim.makeNixvim { - package = pkgs.neovim-clean; - - opts = { - buftype = "nowrite"; - backup = false; - modeline = false; - shelltemp = false; - swapfile = false; - undofile = false; - writebackup = false; - virtualedit = "all"; - splitkeep = "screen"; - termguicolors = false; - # set case handling - ignorecase = true; - smartcase = true; - }; - - extraConfigLua = '' - vim.opt.shadafile = vim.fn.stdpath "state" .. "/shada/man.shada"; - ''; - - keymaps = [ - { - action = ""; - key = ""; - mode = ["n"]; - options = { - silent = true; - desc = "Jump to tag under cursor"; - }; - } - { - action = ":pop"; - key = ""; - mode = ["n"]; - options = { - silent = true; - desc = "Jump to previous tag in stack"; - }; - } - { - action = ":pop"; - key = ""; - mode = ["n"]; - options = { - silent = true; - desc = "Jump to previous tag in stack"; - }; - } - { - action = ":tag"; - key = ""; - mode = ["n"]; - options = { - silent = true; - desc = "Jump to next tag in stack"; - }; - } - ]; - }); -in { home.sessionVariables.MANPAGER = "${exe} '+Man!'"; } diff --git a/users/common/shells/starfish.nix b/users/common/shells/starfish.nix index 29f6ae2..a5610cf 100644 --- a/users/common/shells/starfish.nix +++ b/users/common/shells/starfish.nix @@ -1,4 +1,5 @@ -{lib, ...}: { +{ lib, ... }: +{ programs.starship = { enable = true; settings = { diff --git a/users/common/shells/zsh/default.nix b/users/common/shells/zsh/default.nix index a5e01f3..613c7ac 100644 --- a/users/common/shells/zsh/default.nix +++ b/users/common/shells/zsh/default.nix @@ -1,11 +1,6 @@ +{ pkgs, config, ... }: { - pkgs, - config, - ... -}: { - imports = [ - ../starfish.nix - ]; + imports = [ ../starfish.nix ]; # save history in xdg data home home.sessionVariables.HISTDB_FILE = "${config.xdg.dataHome}/zsh/history.db"; diff --git a/users/patrick/default.nix b/users/patrick/default.nix index 00c93d0..52c767c 100644 --- a/users/patrick/default.nix +++ b/users/patrick/default.nix @@ -34,7 +34,7 @@ lib.optionalAttrs (!minimal) { } ]; }; - users.groups.patrick = {}; + users.groups.patrick = { }; environment.systemPackages = with pkgs; [ # xournalpp needs this or else it will crash @@ -87,11 +87,8 @@ lib.optionalAttrs (!minimal) { ../common/graphical/wayland ./smb.nix ]; - "patricknix" = [ - ../common/graphical/wayland - ]; + "patricknix" = [ ../common/graphical/wayland ]; } - .${config.node.name} - or []; + .${config.node.name} or [ ]; }; } diff --git a/users/patrick/firefox.nix b/users/patrick/firefox.nix index 5932b30..4f33fb1 100644 --- a/users/patrick/firefox.nix +++ b/users/patrick/firefox.nix @@ -1,117 +1,120 @@ -{pkgs, ...}: { - programs.firefox = let - betterfox = pkgs.fetchFromGitHub { - owner = "yokoffing"; - repo = "Betterfox"; - rev = "116.1"; - hash = "sha256-Ai8Szbrk/4FhGhS4r5gA2DqjALFRfQKo2a/TwWCIA6g="; - }; - in { - profiles.patrick = { - userChrome = '' - #TabsToolbar { - visibility: collapse; - } - - #titlebar { - margin-bottom: !important; - } - - #titlebar-buttonbox { - height: 32px !important; - } - ''; - extraConfig = builtins.concatStringsSep "\n" [ - (builtins.readFile "${betterfox}/Securefox.js") - (builtins.readFile "${betterfox}/Fastfox.js") - (builtins.readFile "${betterfox}/Peskyfox.js") - ]; - settings = { - # user chrome soll funzen - "toolkit.legacyUserProfileCustomizations.stylesheets" = true; - # nvidia hardware video decode - # https:#github.com/elFarto/nvidia-vaapi-driver - "media.ffmpeg.vaapi.enabled" = true; - "media.rdd-ffmpeg.enabled" = true; - "gfx.x11-egl.force-enabled" = true; - # enable if grapics card support av1 - "media.av1.enabled" = false; - "widget.dmabuf.force-enabled" = true; - # General - "browser.toolbars.bookmarks.visibility" = "never"; # Never show the bookmark toolbar - "intl.accept_languages" = "en-US,en"; - "browser.startup.page" = 3; # always resume session on restart - "privacy.clearOnShutdown.history" = false; # persist history pls - "devtools.chrome.enabled" = true; # enable js in the dev console - "browser.tabs.crashReporting.sendReport" = false; # don't send crash reports - "accessibility.typeaheadfind.enablesound" = false; # No sound in search windows pls - "general.autoScroll" = true; - "browser.translations.automaticallyPopup" = false; - "browser.translations.neverTranslateLanguages" = "de"; - - # Privacy - "privacy.donottrackheader.enabled" = true; - "privacy.trackingprotection.enabled" = true; - "privacy.trackingprotection.socialtracking.enabled" = true; - "privacy.userContext.enabled" = true; - "privacy.userContext.ui.enabled" = true; - # Firefox shall not test option changes on me pls - "app.normandy.enabled" = false; - "app.shield.optoutstudies.enabled" = false; - - "beacon.enabled" = false; - "device.sensors.enabled" = false; - "geo.enabled" = false; - # enable ech - "network.dns.echconfig.enabled" = true; - #disable all telemetry - "toolkit.telemetry.archive.enabled" = false; - "toolkit.telemetry.enabled" = false; # enforced by nixos - "toolkit.telemetry.server" = ""; - "toolkit.telemetry.unified" = false; - "extensions.webcompat-reporter.enabled" = false; # don't report compability problems to mozilla - "datareporting.policy.dataSubmissionEnabled" = false; - "datareporting.healthreport.uploadEnabled" = false; - "browser.ping-centre.telemetry" = false; - "browser.urlbar.eventTelemetry.enabled" = false; # (default) - # no firefox passwd manager - "browser.contentblocking.report.lockwise.enabled" = false; - "browser.uitour.enabled" = false; - "browser.newtabpage.activity-stream.showSponsored" = false; - "browser.newtabpage.activity-stream.showSponsoredTopSites" = false; - # no encrypted media extension pls - "media.eme.enabled" = false; - "browser.eme.ui.enabled" = false; - "browser.urlbar.speculativeConnect.enabled" = false; - "dom.battery.enabled" = false; # no battery for you - "dom.private-attribution.submission.enabled" = false; # No PPA for me pls +{ pkgs, ... }: +{ + programs.firefox = + let + betterfox = pkgs.fetchFromGitHub { + owner = "yokoffing"; + repo = "Betterfox"; + rev = "116.1"; + hash = "sha256-Ai8Szbrk/4FhGhS4r5gA2DqjALFRfQKo2a/TwWCIA6g="; }; - search = { - force = true; - default = "kagi"; + in + { + profiles.patrick = { + userChrome = '' + #TabsToolbar { + visibility: collapse; + } - engines = { - "Bing".metaData.hidden = true; - "Amazon.com".metaData.hidden = true; - "Google".metaData.hidden = true; + #titlebar { + margin-bottom: !important; + } - "kagi" = { - iconUpdateURL = "https://kagi.com/favicon.ico"; - updateInterval = 24 * 60 * 60 * 1000; # update every day - urls = [ - { - template = "https://kagi.com/search"; - params = [ - { - name = "q"; - value = "{searchTerms}"; - } - ]; - } - ]; + #titlebar-buttonbox { + height: 32px !important; + } + ''; + extraConfig = builtins.concatStringsSep "\n" [ + (builtins.readFile "${betterfox}/Securefox.js") + (builtins.readFile "${betterfox}/Fastfox.js") + (builtins.readFile "${betterfox}/Peskyfox.js") + ]; + settings = { + # user chrome soll funzen + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; + # nvidia hardware video decode + # https:#github.com/elFarto/nvidia-vaapi-driver + "media.ffmpeg.vaapi.enabled" = true; + "media.rdd-ffmpeg.enabled" = true; + "gfx.x11-egl.force-enabled" = true; + # enable if grapics card support av1 + "media.av1.enabled" = false; + "widget.dmabuf.force-enabled" = true; + # General + "browser.toolbars.bookmarks.visibility" = "never"; # Never show the bookmark toolbar + "intl.accept_languages" = "en-US,en"; + "browser.startup.page" = 3; # always resume session on restart + "privacy.clearOnShutdown.history" = false; # persist history pls + "devtools.chrome.enabled" = true; # enable js in the dev console + "browser.tabs.crashReporting.sendReport" = false; # don't send crash reports + "accessibility.typeaheadfind.enablesound" = false; # No sound in search windows pls + "general.autoScroll" = true; + "browser.translations.automaticallyPopup" = false; + "browser.translations.neverTranslateLanguages" = "de"; + + # Privacy + "privacy.donottrackheader.enabled" = true; + "privacy.trackingprotection.enabled" = true; + "privacy.trackingprotection.socialtracking.enabled" = true; + "privacy.userContext.enabled" = true; + "privacy.userContext.ui.enabled" = true; + # Firefox shall not test option changes on me pls + "app.normandy.enabled" = false; + "app.shield.optoutstudies.enabled" = false; + + "beacon.enabled" = false; + "device.sensors.enabled" = false; + "geo.enabled" = false; + # enable ech + "network.dns.echconfig.enabled" = true; + #disable all telemetry + "toolkit.telemetry.archive.enabled" = false; + "toolkit.telemetry.enabled" = false; # enforced by nixos + "toolkit.telemetry.server" = ""; + "toolkit.telemetry.unified" = false; + "extensions.webcompat-reporter.enabled" = false; # don't report compability problems to mozilla + "datareporting.policy.dataSubmissionEnabled" = false; + "datareporting.healthreport.uploadEnabled" = false; + "browser.ping-centre.telemetry" = false; + "browser.urlbar.eventTelemetry.enabled" = false; # (default) + # no firefox passwd manager + "browser.contentblocking.report.lockwise.enabled" = false; + "browser.uitour.enabled" = false; + "browser.newtabpage.activity-stream.showSponsored" = false; + "browser.newtabpage.activity-stream.showSponsoredTopSites" = false; + # no encrypted media extension pls + "media.eme.enabled" = false; + "browser.eme.ui.enabled" = false; + "browser.urlbar.speculativeConnect.enabled" = false; + "dom.battery.enabled" = false; # no battery for you + "dom.private-attribution.submission.enabled" = false; # No PPA for me pls + }; + search = { + force = true; + default = "kagi"; + + engines = { + "Bing".metaData.hidden = true; + "Amazon.com".metaData.hidden = true; + "Google".metaData.hidden = true; + + "kagi" = { + iconUpdateURL = "https://kagi.com/favicon.ico"; + updateInterval = 24 * 60 * 60 * 1000; # update every day + urls = [ + { + template = "https://kagi.com/search"; + params = [ + { + name = "q"; + value = "{searchTerms}"; + } + ]; + } + ]; + }; }; }; }; }; - }; } diff --git a/users/patrick/impermanence.nix b/users/patrick/impermanence.nix index d104c0f..c534e71 100644 --- a/users/patrick/impermanence.nix +++ b/users/patrick/impermanence.nix @@ -1,8 +1,5 @@ +{ nixosConfig, lib, ... }: { - nixosConfig, - lib, - ... -}: { home.persistence = { "/state" = { directories = [ @@ -47,10 +44,8 @@ #".local/share/wallpapers" ]; }; - "/panzer/state".directories = - lib.lists.optionals (nixosConfig.disko.devices.zpool ? "panzer") - [ - ".local/share/SteamPanzer" - ]; + "/panzer/state".directories = lib.lists.optionals (nixosConfig.disko.devices.zpool ? "panzer") [ + ".local/share/SteamPanzer" + ]; }; } diff --git a/users/patrick/patrick.nix b/users/patrick/patrick.nix index 4892012..3d99d8a 100644 --- a/users/patrick/patrick.nix +++ b/users/patrick/patrick.nix @@ -3,7 +3,8 @@ lib, nixosConfig, ... -}: { +}: +{ images.enable = true; home = { packages = with pkgs; [ @@ -41,8 +42,10 @@ }; # Make sure the keygrips exist, otherwise we'd need to run `gpg --card-status` # before being able to use the yubikey. - home.activation.installKeygrips = lib.hm.dag.entryAfter ["writeBoundary"] '' + home.activation.installKeygrips = lib.hm.dag.entryAfter [ "writeBoundary" ] '' run mkdir -p "$HOME/.gnupg/private-keys-v1.d" - run ${lib.getExe pkgs.gnutar} xvf ${lib.escapeShellArg nixosConfig.age.secrets."my-gpg-yubikey-keygrip.tar".path} -C "$HOME/.gnupg/private-keys-v1.d/" + run ${lib.getExe pkgs.gnutar} xvf ${ + lib.escapeShellArg nixosConfig.age.secrets."my-gpg-yubikey-keygrip.tar".path + } -C "$HOME/.gnupg/private-keys-v1.d/" ''; } diff --git a/users/patrick/smb.nix b/users/patrick/smb.nix index 9699bba..4ba362d 100644 --- a/users/patrick/smb.nix +++ b/users/patrick/smb.nix @@ -1,41 +1,40 @@ +{ nixosConfig, nodes, ... }: { - nixosConfig, - nodes, - ... -}: { - home.smb = let - address = nodes.elisabeth-samba.config.wireguard.samba-patrick.ipv4; - credentials = nixosConfig.age.secrets.smb-creds.path; - in [ - { - inherit address credentials; - remotePath = "patri"; - automatic = true; - } - { - inherit address credentials; - remotePath = "patri-important"; - automatic = true; - } - { - inherit address credentials; - remotePath = "patri-paperless"; - automatic = true; - } - { - inherit address credentials; - remotePath = "family-data"; - automatic = true; - } - { - inherit address credentials; - remotePath = "printer"; - automatic = true; - } - { - inherit address credentials; - remotePath = "media"; - automatic = true; - } - ]; + home.smb = + let + address = nodes.elisabeth-samba.config.wireguard.samba-patrick.ipv4; + credentials = nixosConfig.age.secrets.smb-creds.path; + in + [ + { + inherit address credentials; + remotePath = "patri"; + automatic = true; + } + { + inherit address credentials; + remotePath = "patri-important"; + automatic = true; + } + { + inherit address credentials; + remotePath = "patri-paperless"; + automatic = true; + } + { + inherit address credentials; + remotePath = "family-data"; + automatic = true; + } + { + inherit address credentials; + remotePath = "printer"; + automatic = true; + } + { + inherit address credentials; + remotePath = "media"; + automatic = true; + } + ]; } diff --git a/users/patrick/ssh.nix b/users/patrick/ssh.nix index 9200c06..aec31d6 100644 --- a/users/patrick/ssh.nix +++ b/users/patrick/ssh.nix @@ -1,4 +1,5 @@ -{config, ...}: { +{ config, ... }: +{ # yubikey public key parts home.file.".ssh/1.pub".text = '' ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDZixkix0KfKuq7Q19whS5FQQg51/AJGB5BiNF/7h/LM cardno:15 489 049 @@ -10,33 +11,38 @@ enable = true; controlMaster = "auto"; controlPersist = "5s"; - matchBlocks = let - identityFile = ["~/.ssh/1.pub" "~/.ssh/2.pub"]; - in { - "elisabeth" = { - hostname = "lel.lol"; - user = "root"; - }; + matchBlocks = + let + identityFile = [ + "~/.ssh/1.pub" + "~/.ssh/2.pub" + ]; + in + { + "elisabeth" = { + hostname = "lel.lol"; + user = "root"; + }; - "patricknix" = { - hostname = "patricknix.local"; - user = "root"; - }; + "patricknix" = { + hostname = "patricknix.local"; + user = "root"; + }; - "maddy" = { - hostname = config.userSecrets.hetzner_ip; - user = "root"; - }; + "maddy" = { + hostname = config.userSecrets.hetzner_ip; + user = "root"; + }; - "desktopnix" = { - hostname = "desktopnix.local"; - user = "root"; + "desktopnix" = { + hostname = "desktopnix.local"; + user = "root"; + }; + "*" = { + user = "root"; + identitiesOnly = true; + inherit identityFile; + }; }; - "*" = { - user = "root"; - identitiesOnly = true; - inherit identityFile; - }; - }; }; } diff --git a/users/patrick/streamdeck.nix b/users/patrick/streamdeck.nix index 4286c29..4da9a45 100644 --- a/users/patrick/streamdeck.nix +++ b/users/patrick/streamdeck.nix @@ -1,4 +1,5 @@ -{config, ...}: { +{ config, ... }: +{ programs.streamdeck-ui = { enable = true; settings = { diff --git a/users/root/default.nix b/users/root/default.nix index 66e3602..79a7213 100644 --- a/users/root/default.nix +++ b/users/root/default.nix @@ -4,7 +4,8 @@ lib, minimal, ... -}: { +}: +{ users.users.root = { shell = pkgs.zsh; openssh.authorizedKeys.keys = [ @@ -16,7 +17,5 @@ ]; hashedPassword = config.secrets.secrets.global.users.root.passwordHash; }; - home-manager.users.root.imports = lib.lists.optionals (!minimal) [ - ../common - ]; + home-manager.users.root.imports = lib.lists.optionals (!minimal) [ ../common ]; }