diff --git a/flake.nix b/flake.nix index 050ce81..6eb1986 100644 --- a/flake.nix +++ b/flake.nix @@ -48,8 +48,8 @@ invoiceplane-template.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = inputs@{ self, ... }: - inputs.flake-parts.lib.mkFlake { inherit inputs; } { + outputs = inputs @ {self, ...}: + inputs.flake-parts.lib.mkFlake {inherit inputs;} { systems = [ "x86_64-linux" "aarch64-linux" @@ -65,7 +65,13 @@ ./overlays ]; - perSystem = args@{ system, pkgs, lib, config, ... }: { + perSystem = args @ { + system, + pkgs, + lib, + config, + ... + }: { _module.args = { inherit inputs; pkgs = import inputs.nixpkgs { @@ -98,12 +104,11 @@ deploy-rs - terraform-ls + terraform-ls opentofu terraform-backend-git deno - denols ]; shellHook = '' diff --git a/hosts/biolimo/default.nix b/hosts/biolimo/default.nix index 8fa27a6..c5d727d 100644 --- a/hosts/biolimo/default.nix +++ b/hosts/biolimo/default.nix @@ -1,4 +1,4 @@ -{ ... }: { +{...}: { imports = [ ./configuration.nix ./hardware-configuration.nix diff --git a/hosts/chocolatebar/factorio/default.nix b/hosts/chocolatebar/factorio/default.nix index 0d16c6c..1018bf8 100644 --- a/hosts/chocolatebar/factorio/default.nix +++ b/hosts/chocolatebar/factorio/default.nix @@ -39,6 +39,6 @@ in { ]; }; - networking.firewall.allowedUDPPorts = [ 34197 ]; - networking.firewall.allowedTCPPorts = [ 34197 ]; + networking.firewall.allowedUDPPorts = [34197]; + networking.firewall.allowedTCPPorts = [34197]; } diff --git a/hosts/default.nix b/hosts/default.nix index 30bd27d..6e19e96 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -1,5 +1,9 @@ -{ withSystem, self, inputs, ...}: { + withSystem, + self, + inputs, + ... +}: { flake = { nixosConfigurations = { stroopwafel = self.nixos-flake.lib.mkLinuxSystem { @@ -137,7 +141,7 @@ self.nixosModules.graphical self.nixosModules.audio self.nixosModules.bluetooth - ({ ... }: { pub-solar.graphical.wayland.software-renderer.enable = true; }) + ({...}: {pub-solar.graphical.wayland.software-renderer.enable = true;}) ]; }; }; diff --git a/hosts/droppie/configuration.nix b/hosts/droppie/configuration.nix index 8a420cc..5d476ef 100644 --- a/hosts/droppie/configuration.nix +++ b/hosts/droppie/configuration.nix @@ -23,7 +23,7 @@ in { # Hack so that network is considered up by boot.initrd.network and postCommands gets executed. "ip=127.0.0.1:::::lo:none" ]; - boot.initrd.availableKernelModules = [ "tg3" ]; + boot.initrd.availableKernelModules = ["tg3"]; boot.initrd.network = { enable = true; ssh = { diff --git a/hosts/droppie/hardware-configuration.nix b/hosts/droppie/hardware-configuration.nix index 2283883..1ee4771 100644 --- a/hosts/droppie/hardware-configuration.nix +++ b/hosts/droppie/hardware-configuration.nix @@ -1,17 +1,21 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; + config, + lib, + pkgs, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "ehci_pci" "usbhid" "usb_storage" "uas" "sd_mod" ]; - boot.initrd.kernelModules = [ "dm-snapshot" "amdgpu" ]; - boot.kernelModules = [ "kvm-amd" ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "ehci_pci" "usbhid" "usb_storage" "uas" "sd_mod"]; + boot.initrd.kernelModules = ["dm-snapshot" "amdgpu"]; + boot.kernelModules = ["kvm-amd"]; + boot.extraModulePackages = []; boot.initrd.luks.devices = { "cryptroot" = { @@ -21,42 +25,42 @@ "cryptdata".device = "/dev/sda1"; }; - fileSystems."/" = - { device = "none"; - fsType = "tmpfs"; - }; + fileSystems."/" = { + device = "none"; + fsType = "tmpfs"; + }; - fileSystems."/nix" = - { device = "/dev/disk/by-uuid/837cc93f-6d9a-4bfd-b089-29ac6d68127c"; - fsType = "ext4"; - neededForBoot = true; - }; + fileSystems."/nix" = { + device = "/dev/disk/by-uuid/837cc93f-6d9a-4bfd-b089-29ac6d68127c"; + fsType = "ext4"; + neededForBoot = true; + }; - fileSystems."/persist" = - { device = "/dev/disk/by-uuid/a7711118-51b0-4d84-8f18-ef2e06084e05"; - fsType = "ext4"; - neededForBoot = true; - }; + fileSystems."/persist" = { + device = "/dev/disk/by-uuid/a7711118-51b0-4d84-8f18-ef2e06084e05"; + fsType = "ext4"; + neededForBoot = true; + }; - fileSystems."/home" = - { device = "/dev/disk/by-uuid/0965d496-ffad-4a8d-9de7-28af903baf16"; - fsType = "ext4"; - }; + fileSystems."/home" = { + device = "/dev/disk/by-uuid/0965d496-ffad-4a8d-9de7-28af903baf16"; + fsType = "ext4"; + }; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/991E-79C1"; - fsType = "vfat"; - neededForBoot = true; - }; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/991E-79C1"; + fsType = "vfat"; + neededForBoot = true; + }; - fileSystems."/data" = - { device = "/dev/disk/by-uuid/5fc34ef4-207b-45fb-b846-dbb01080d9fe"; - fsType = "ext4"; - }; + fileSystems."/data" = { + device = "/dev/disk/by-uuid/5fc34ef4-207b-45fb-b846-dbb01080d9fe"; + fsType = "ext4"; + }; - swapDevices = - [ { device = "/dev/disk/by-uuid/0ef8dbbd-2832-4fb2-8a52-86682822f769"; } - ]; + swapDevices = [ + {device = "/dev/disk/by-uuid/0ef8dbbd-2832-4fb2-8a52-86682822f769";} + ]; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; diff --git a/hosts/droppie/jellyfin.nix b/hosts/droppie/jellyfin.nix index 29390a5..018ea06 100644 --- a/hosts/droppie/jellyfin.nix +++ b/hosts/droppie/jellyfin.nix @@ -17,7 +17,7 @@ }; # from https://jellyfin.org/docs/general/networking/index.html - networking.firewall.allowedUDPPorts = [ 1900 7359 ]; + networking.firewall.allowedUDPPorts = [1900 7359]; security.acme.certs = { "media.b12f.io" = {}; diff --git a/hosts/droppie/networking.nix b/hosts/droppie/networking.nix index 56bece7..a82cdeb 100644 --- a/hosts/droppie/networking.nix +++ b/hosts/droppie/networking.nix @@ -10,7 +10,12 @@ networking.interfaces.enp2s0f1.useDHCP = true; networking.interfaces.enp2s0f0 = { - ipv6.addresses = [ { address = "2a02:908:5b1:e3c0:3::"; prefixLength = 64; } ]; + ipv6.addresses = [ + { + address = "2a02:908:5b1:e3c0:3::"; + prefixLength = 64; + } + ]; }; # Allow pub.solar restic backups diff --git a/hosts/frikandel/configuration.nix b/hosts/frikandel/configuration.nix index fed1bcb..480a6c1 100644 --- a/hosts/frikandel/configuration.nix +++ b/hosts/frikandel/configuration.nix @@ -9,7 +9,6 @@ with lib; let psCfg = config.pub-solar; xdg = config.home-manager.users."${psCfg.user.name}".xdg; in { - # Use the systemd-boot EFI boot loader. boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; @@ -20,13 +19,13 @@ in { "ip=127.0.0.1:::::lo:none" ]; - boot.initrd.availableKernelModules = [ "virtio_pci" "virtio_net" ]; + boot.initrd.availableKernelModules = ["virtio_pci" "virtio_net"]; boot.initrd.network = { enable = true; ssh = { enable = true; port = 2222; - hostKeys = [ /boot/initrd-ssh-key ]; + hostKeys = [/boot/initrd-ssh-key]; authorizedKeys = flake.self.publicKeys; shell = "/bin/cryptsetup-askpass"; }; @@ -44,7 +43,7 @@ in { ''; }; - boot.supportedFilesystems = [ "zfs" ]; + boot.supportedFilesystems = ["zfs"]; # Copy the NixOS configuration file and link it from the resulting system # (/run/current-system/configuration.nix). This is useful in case you diff --git a/hosts/frikandel/email.nix b/hosts/frikandel/email.nix index bb91aba..3b54d3f 100644 --- a/hosts/frikandel/email.nix +++ b/hosts/frikandel/email.nix @@ -5,15 +5,15 @@ lib, ... }: let - hzDomain = lib.concatStrings [ "hw" "dz" "z." "net" ]; + hzDomain = lib.concatStrings ["hw" "dz" "z." "net"]; dkimDNSb12fio = '' - default._domainkey IN TXT ( "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyla9hW3TvoXvZQxwzaJ4SZ9ict1HU3E6+FWlwNIgE6tIpTCyRJtiSIUDqB8TLTIBoxIs+QQBXZi+QUi3Agu6OSY2RiV0EwO8+oOOqOD9pERftc/aqe51cXuv4kPqwvpXEBwrXFWVM+VxivEubUJ7eKkFyXJpelv0LslXv/MmYbUyed6dF+reOGZCsvnbiRv74qdxbAL/25j62E8WrnxzJwhUtx/JhdBOjsHBvuw9hy6rZsVJL9eXayWyGRV6qmsLRzsRSBs+mDrgmKk4dugADd11+A03ics3i8hplRoWDkqnNKz1qy4f5TsV6v9283IANrAzRfHwX8EvNiFsBz+ZCQIDAQAB" ) ; + default._domainkey IN TXT ( "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyla9hW3TvoXvZQxwzaJ4SZ9ict1HU3E6+FWlwNIgE6tIpTCyRJtiSIUDqB8TLTIBoxIs+QQBXZi+QUi3Agu6OSY2RiV0EwO8+oOOqOD9pERftc/aqe51cXuv4kPqwvpXEBwrXFWVM+VxivEubUJ7eKkFyXJpelv0LslXv/MmYbUyed6dF+reOGZCsvnbiRv74qdxbAL/25j62E8WrnxzJwhUtx/JhdBOjsHBvuw9hy6rZsVJL9eXayWyGRV6qmsLRzsRSBs+mDrgmKk4dugADd11+A03ics3i8hplRoWDkqnNKz1qy4f5TsV6v9283IANrAzRfHwX8EvNiFsBz+ZCQIDAQAB" ) ; ''; dkimDNSmezzabiz = '' - default._domainkey IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDG8iuDq0eon2k7QlBJWGxwDiEv53iJQu2uqxOjr7Ul/nfQjuR6kVKs6oOVopnyFTGRpffrpSHHW1YUN5nF76p0fJphk4l+QmJP36/xweajsNU27PAkb88xG6yRKl28MCfPdMR96+Jobpei8S0UhqcskYs1aZybm7ci9ZuAMidziwIDAQAB" ) ; + default._domainkey IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDG8iuDq0eon2k7QlBJWGxwDiEv53iJQu2uqxOjr7Ul/nfQjuR6kVKs6oOVopnyFTGRpffrpSHHW1YUN5nF76p0fJphk4l+QmJP36/xweajsNU27PAkb88xG6yRKl28MCfPdMR96+Jobpei8S0UhqcskYs1aZybm7ci9ZuAMidziwIDAQAB" ) ; ''; dkimDNShzDomain = '' - default._domainkey IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvVA2XZno6g6qBdmxoLgX2Qmd883M6yV4YkE/VaNH6xcR0AcTo4hEYoAOPryfKn4FE/TYvyk/k2cyBKpMBn2qbVhwUavYQh/e9bweS2FKQvdzCUUoqXk04o2MqSXb2ZFwkUCtfrPcckBgpF754PDL4HMZGPnkMSdDX7bmYe37CWQIDAQAB") ; + default._domainkey IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvVA2XZno6g6qBdmxoLgX2Qmd883M6yV4YkE/VaNH6xcR0AcTo4hEYoAOPryfKn4FE/TYvyk/k2cyBKpMBn2qbVhwUavYQh/e9bweS2FKQvdzCUUoqXk04o2MqSXb2ZFwkUCtfrPcckBgpF754PDL4HMZGPnkMSdDX7bmYe37CWQIDAQAB") ; ''; in { age.secrets."b12f.io-dkim-private-rsa" = { @@ -55,21 +55,23 @@ in { owner = "maddy"; }; - users.users.maddy.extraGroups = [ "nginx" ]; + users.users.maddy.extraGroups = ["nginx"]; security.acme.certs = { - "mail.b12f.io".reloadServices = [ "maddy" ]; - "b12f.io".reloadServices = [ "maddy" ]; + "mail.b12f.io".reloadServices = ["maddy"]; + "b12f.io".reloadServices = ["maddy"]; "mta-sts.b12f.io" = {}; - "mail.mezza.biz".reloadServices = [ "maddy" ]; - "mezza.biz".reloadServices = [ "maddy" ]; + "mail.mezza.biz".reloadServices = ["maddy"]; + "mezza.biz".reloadServices = ["maddy"]; "mta-sts.mezza.biz" = {}; - "mail.${hzDomain}".reloadServices = [ "maddy" ]; - "${hzDomain}".reloadServices = [ "maddy" ]; + "mail.${hzDomain}".reloadServices = ["maddy"]; + "${hzDomain}".reloadServices = ["maddy"]; "mta-sts.${hzDomain}" = {}; }; - services.nginx.virtualHosts = builtins.foldl' (hosts: hostName: hosts // { + services.nginx.virtualHosts = builtins.foldl' (hosts: hostName: + hosts + // { "mta-sts.${hostName}" = { forceSSL = true; useACMEHost = "mta-sts.${hostName}"; @@ -86,13 +88,13 @@ in { tryFiles = "$uri $uri/ =404"; }; }; - }) {} [ "b12f.io" "mezza.biz" hzDomain ]; + }) {} ["b12f.io" "mezza.biz" hzDomain]; systemd.tmpfiles.rules = [ "d '/run/maddy' 0750 maddy maddy - -" ]; - system.activationScripts.makeMaddyDKIMDNS = lib.stringAfter [ "var" ] '' + system.activationScripts.makeMaddyDKIMDNS = lib.stringAfter ["var"] '' mkdir -p /var/lib/maddy/dkim_keys echo '${dkimDNSb12fio}' >> /var/lib/maddy/dkim_keys/b12f.io_default.dns @@ -101,8 +103,8 @@ in { chown -R maddy:maddy /var/lib/maddy ''; - networking.firewall.allowedTCPPorts = [ 25 ]; - networking.firewall.interfaces.wg-private.allowedTCPPorts = [ 465 587 993 ]; + networking.firewall.allowedTCPPorts = [25]; + networking.firewall.interfaces.wg-private.allowedTCPPorts = [465 587 993]; services.maddy = { enable = true; @@ -311,7 +313,7 @@ in { ''; }; - systemd.services.rspamd.serviceConfig.SupplementaryGroups = [ "maddy" ]; + systemd.services.rspamd.serviceConfig.SupplementaryGroups = ["maddy"]; age.secrets."rclone-pubsolar.conf" = { file = "${flake.self}/secrets/rclone-pubsolar.conf.age"; @@ -325,7 +327,7 @@ in { services.restic.backups = { maddy = { - paths = [ "/var/lib/maddy" ]; + paths = ["/var/lib/maddy"]; initialize = true; passwordFile = config.age.secrets."restic-password".path; # See https://www.hosting.de/blog/verschluesselte-backups-mit-rclone-und-restic-in-nextcloud/ diff --git a/hosts/frikandel/hardware-configuration.nix b/hosts/frikandel/hardware-configuration.nix index 6892076..d7d89d4 100644 --- a/hosts/frikandel/hardware-configuration.nix +++ b/hosts/frikandel/hardware-configuration.nix @@ -1,16 +1,21 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: { + config, + lib, + pkgs, + modulesPath, + ... +}: { imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; - boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = ["ahci" "xhci_pci" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod"]; + boot.initrd.kernelModules = []; + boot.kernelModules = []; + boot.extraModulePackages = []; boot.initrd.luks.devices = { cryptroot = { @@ -19,19 +24,19 @@ }; }; - fileSystems."/" = - { device = "zroot/root"; - fsType = "zfs"; - }; + fileSystems."/" = { + device = "zroot/root"; + fsType = "zfs"; + }; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/684A-5884"; - fsType = "vfat"; - }; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/684A-5884"; + fsType = "vfat"; + }; - swapDevices = - [ { device = "/dev/disk/by-uuid/a7d1cbb8-7c9e-4c3d-841a-add867f47389"; } - ]; + swapDevices = [ + {device = "/dev/disk/by-uuid/a7d1cbb8-7c9e-4c3d-841a-add867f47389";} + ]; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; } diff --git a/hosts/frikandel/networking.nix b/hosts/frikandel/networking.nix index e535c3d..a8efdc8 100644 --- a/hosts/frikandel/networking.nix +++ b/hosts/frikandel/networking.nix @@ -17,8 +17,18 @@ # Network configuration (Hetzner uses static IP assignments, and we don't use DHCP here) networking.useDHCP = false; networking.interfaces.enp1s0 = { - ipv4.addresses = [{ address = "128.140.109.213"; prefixLength = 32; }]; - ipv6.addresses = [{ address = "2a01:4f8:c2c:b60::"; prefixLength = 64; }]; + ipv4.addresses = [ + { + address = "128.140.109.213"; + prefixLength = 32; + } + ]; + ipv6.addresses = [ + { + address = "2a01:4f8:c2c:b60::"; + prefixLength = 64; + } + ]; }; networking.defaultGateway = { address = "172.31.1.1"; @@ -29,5 +39,5 @@ interface = "enp1s0"; }; - networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.firewall.allowedTCPPorts = [80 443]; } diff --git a/hosts/frikandel/unbound.nix b/hosts/frikandel/unbound.nix index 380e325..7cb2301 100644 --- a/hosts/frikandel/unbound.nix +++ b/hosts/frikandel/unbound.nix @@ -29,8 +29,8 @@ owner = "unbound"; }; - networking.firewall.interfaces.wg-private.allowedUDPPorts = [ 53 ]; - networking.firewall.interfaces.wg-private.allowedTCPPorts = [ 53 ]; + networking.firewall.interfaces.wg-private.allowedUDPPorts = [53]; + networking.firewall.interfaces.wg-private.allowedTCPPorts = [53]; services.resolved.enable = false; services.unbound = { @@ -102,10 +102,10 @@ "\"mail.mezza.biz. 10800 IN A 10.13.12.7\"" "\"mail.mezza.biz. 10800 IN AAAA fd00:b12f:acab:1312:acab:7::\"" - "\"h${"w"+"dz"+"z.n"}et. 10800 IN A 10.13.12.7\"" - "\"h${"w"+"dz"+"z.n"}et. 10800 IN AAAA fd00:b12f:acab:1312:acab:7::\"" - "\"mail.h${"w"+"dz"+"z.n"}et. 10800 IN A 10.13.12.7\"" - "\"mail.h${"w"+"dz"+"z.n"}et. 10800 IN AAAA fd00:b12f:acab:1312:acab:7::\"" + "\"h${"w" + "dz" + "z.n"}et. 10800 IN A 10.13.12.7\"" + "\"h${"w" + "dz" + "z.n"}et. 10800 IN AAAA fd00:b12f:acab:1312:acab:7::\"" + "\"mail.h${"w" + "dz" + "z.n"}et. 10800 IN A 10.13.12.7\"" + "\"mail.h${"w" + "dz" + "z.n"}et. 10800 IN AAAA fd00:b12f:acab:1312:acab:7::\"" ]; tls-cert-bundle = "/etc/ssl/certs/ca-certificates.crt"; @@ -133,5 +133,4 @@ }; }; }; - } diff --git a/hosts/frikandel/wireguard.nix b/hosts/frikandel/wireguard.nix index f186f61..36867c6 100644 --- a/hosts/frikandel/wireguard.nix +++ b/hosts/frikandel/wireguard.nix @@ -4,7 +4,8 @@ pkgs, lib, ... -}: with lib; { +}: +with lib; { boot.kernel.sysctl = { "net.ipv4.ip_forward" = 1; "net.ipv6.conf.wg-private.forwarding" = 1; @@ -16,10 +17,10 @@ enable = true; enableIPv6 = true; externalInterface = "enp1s0"; - internalInterfaces = [ "wg-private" ]; + internalInterfaces = ["wg-private"]; }; - networking.firewall.allowedUDPPorts = [ 51899 ]; + networking.firewall.allowedUDPPorts = [51899]; networking.firewall.extraForwardRules = [ "iifname { != wg-private } reject" @@ -57,7 +58,8 @@ ]; privateKeyFile = config.age.secrets.wg-private-key.path; peers = [ - { # pie + { + # pie publicKey = "hPTXEqQ2GYEywdPNdZBacwB9KKcoFZ/heClxnqmizyw="; allowedIPs = [ "10.13.12.2/32" @@ -66,7 +68,8 @@ persistentKeepalive = 30; dynamicEndpointRefreshSeconds = 30; } - { # droppie + { + # droppie publicKey = "qsnBMoj9Z16D8PJ5ummRtIfT5AiMpoF3SoOCo4sbyiw="; allowedIPs = [ "10.13.12.3/32" @@ -75,7 +78,8 @@ persistentKeepalive = 30; dynamicEndpointRefreshSeconds = 30; } - { # chocolatebar + { + # chocolatebar publicKey = "nk8EtGE/QsnSEm1lhLS3/w83nOBD2OGYhODIf92G91A="; allowedIPs = [ "10.13.12.5/32" @@ -84,7 +88,8 @@ persistentKeepalive = 30; dynamicEndpointRefreshSeconds = 30; } - { # biolimo + { + # biolimo publicKey = "4ymN7wwBuhF+h+5fFN0TqXmVyOe1AsWiTqRL0jJ3CDc="; allowedIPs = [ "10.13.12.6/32" @@ -93,7 +98,8 @@ persistentKeepalive = 30; dynamicEndpointRefreshSeconds = 30; } - { # stroopwafel + { + # stroopwafel publicKey = "5iNRg13utOJ30pX2Z8SjwPNUFwfH2zonlbeYW2mKFkU="; allowedIPs = [ "10.13.12.8/32" @@ -102,7 +108,8 @@ persistentKeepalive = 30; dynamicEndpointRefreshSeconds = 30; } - { # fp3 + { + # fp3 publicKey = "wQJXFibxhWkyUbRPrPt5y/YfDnH3gDQ5a/PWoyxDfDI="; allowedIPs = [ "10.13.12.9/32" diff --git a/hosts/iso/default.nix b/hosts/iso/default.nix index 89246d1..c76fdcb 100644 --- a/hosts/iso/default.nix +++ b/hosts/iso/default.nix @@ -4,7 +4,7 @@ ... }: { isoImage.squashfsCompression = "gzip -Xcompression-level 1"; - systemd.services.sshd.wantedBy = lib.mkForce [ "multi-user.target" ]; + systemd.services.sshd.wantedBy = lib.mkForce ["multi-user.target"]; networking.networkmanager.enable = false; services.openssh.openFirewall = lib.mkForce true; } diff --git a/hosts/maoam/default.nix b/hosts/maoam/default.nix index fb4f6af..2751636 100644 --- a/hosts/maoam/default.nix +++ b/hosts/maoam/default.nix @@ -1,8 +1,12 @@ -{ flake, pkgs, ... }: { +{ + flake, + pkgs, + ... +}: { imports = [ ./configuration.nix ./hardware-configuration.nix - ((import "${flake.inputs.mobile-nixos}/lib/configuration.nix") { device = "pine64-pinephone"; }) + ((import "${flake.inputs.mobile-nixos}/lib/configuration.nix") {device = "pine64-pinephone";}) "${flake.inputs.mobile-nixos}/examples/phosh/phosh.nix" ]; } diff --git a/hosts/maoam/hardware-configuration.nix b/hosts/maoam/hardware-configuration.nix index 61ee65a..9ff3ebe 100644 --- a/hosts/maoam/hardware-configuration.nix +++ b/hosts/maoam/hardware-configuration.nix @@ -1,6 +1,10 @@ # NOTE: this file was generated by the Mobile NixOS installer. -{ config, lib, pkgs, ... }: { + config, + lib, + pkgs, + ... +}: { fileSystems = { "/" = { device = "/dev/disk/by-uuid/51a668b8-fa2e-4d3e-ac3f-73ca002d0004"; diff --git a/hosts/pie/authelia.nix b/hosts/pie/authelia.nix index 8879572..cb17727 100644 --- a/hosts/pie/authelia.nix +++ b/hosts/pie/authelia.nix @@ -81,7 +81,7 @@ in { }; authentication_backend = { refresh_interval = "disable"; - password_reset = { disable = true; }; + password_reset = {disable = true;}; file = { path = config.age.secrets."authelia-users-file".path; watch = false; @@ -93,7 +93,10 @@ in { storage.local.path = "/var/lib/authelia-b12f/db.sqlite3"; access_control.default_policy = "two_factor"; session.cookies = [ - { domain = "b12f.io"; authelia_url = "https://auth.b12f.io"; } + { + domain = "b12f.io"; + authelia_url = "https://auth.b12f.io"; + } ]; notifier.smtp = { host = "mail.b12f.io"; @@ -110,7 +113,7 @@ in { services.restic.backups = { authelia = { - paths = [ "/var/lib/authelia-b12f" ]; + paths = ["/var/lib/authelia-b12f"]; initialize = true; passwordFile = config.age.secrets."restic-password".path; # See https://www.hosting.de/blog/verschluesselte-backups-mit-rclone-und-restic-in-nextcloud/ diff --git a/hosts/pie/configuration.nix b/hosts/pie/configuration.nix index 350cf02..806b899 100644 --- a/hosts/pie/configuration.nix +++ b/hosts/pie/configuration.nix @@ -20,7 +20,7 @@ in { boot.loader.systemd-boot.enable = false; boot.loader.generic-extlinux-compatible.enable = false; - boot.supportedFilesystems = [ "zfs" ]; + boot.supportedFilesystems = ["zfs"]; boot.kernelParams = [ "boot.shell_on_fail=1" @@ -28,7 +28,7 @@ in { "ip=127.0.0.1:::::lo:none" ]; # See https://discourse.nixos.org/t/ssh-and-network-in-initrd-on-raspberry-pi-4/6289/3 - boot.initrd.availableKernelModules = [ "genet" ]; + boot.initrd.availableKernelModules = ["genet"]; boot.initrd.network = { enable = true; ssh = { diff --git a/hosts/pie/dhcpd.nix b/hosts/pie/dhcpd.nix index 5d576fb..d6149f0 100644 --- a/hosts/pie/dhcpd.nix +++ b/hosts/pie/dhcpd.nix @@ -1,6 +1,9 @@ -{ pkgs, adblock-unbound, ... }: { - networking.firewall.allowedUDPPorts = [ 67 547 ]; + pkgs, + adblock-unbound, + ... +}: { + networking.firewall.allowedUDPPorts = [67 547]; networking.firewall.extraInputRules = '' ip6 daddr ff02::1:2/128 udp dport 547 accept comment "DHCPv6 server" ''; @@ -30,7 +33,7 @@ { subnet = "192.168.178.0/24"; pools = [ - { pool = "192.168.178.2 - 192.168.178.255"; } + {pool = "192.168.178.2 - 192.168.178.255";} ]; option-data = [ @@ -100,19 +103,19 @@ subnet = "2a02:908:5b1:e3c0::/64"; pools = [ - { pool = "2a02:908:5b1:e3c0::/72"; } + {pool = "2a02:908:5b1:e3c0::/72";} ]; ddns-qualifying-suffix = "local."; option-data = [ { - name = "dns-servers"; - data = "2a02:908:5b1:e3c0:2::"; + name = "dns-servers"; + data = "2a02:908:5b1:e3c0:2::"; } { - name = "domain-search"; - data = "local"; + name = "domain-search"; + data = "local"; } ]; diff --git a/hosts/pie/firefly.nix b/hosts/pie/firefly.nix index 0c65bf0..3fc3238 100644 --- a/hosts/pie/firefly.nix +++ b/hosts/pie/firefly.nix @@ -80,14 +80,14 @@ in { volumes = [ "/var/lib/firefly/upload:/var/www/html/storage/upload" ]; - extraOptions = [ "--network=firefly" ]; + extraOptions = ["--network=firefly"]; environmentFiles = [ ./.env.firefly config.age.secrets."firefly-secrets.env".path config.age.secrets."firefly-cron-secrets.env".path ]; - ports = [ "127.0.0.1:8080:8080" ]; - dependsOn = [ "firefly-db" ]; + ports = ["127.0.0.1:8080:8080"]; + dependsOn = ["firefly-db"]; }; containers."firefly-db" = { @@ -96,7 +96,7 @@ in { volumes = [ "/var/lib/firefly/db:/var/lib/postgresql/data" ]; - extraOptions = [ "--network=firefly" ]; + extraOptions = ["--network=firefly"]; environmentFiles = [ config.age.secrets."firefly-db-secrets.env".path ]; @@ -105,8 +105,8 @@ in { containers."firefly-importer" = { image = "fireflyiii/data-importer:latest"; autoStart = true; - extraOptions = [ "--network=firefly" ]; - ports = [ "127.0.0.1:8081:8080" ]; + extraOptions = ["--network=firefly"]; + ports = ["127.0.0.1:8081:8080"]; environment = { FIREFLY_III_URL = "https://firefly.b12f.io"; }; @@ -114,7 +114,7 @@ in { ./.env.firefly-importer config.age.secrets."firefly-importer-secrets.env".path ]; - dependsOn = [ "firefly" ]; + dependsOn = ["firefly"]; }; containers."firefly-cron" = { @@ -128,7 +128,7 @@ in { environmentFiles = [ config.age.secrets."firefly-cron-secrets.env".path ]; - extraOptions = [ "--network=firefly" ]; + extraOptions = ["--network=firefly"]; }; }; }; diff --git a/hosts/pie/hardware-configuration.nix b/hosts/pie/hardware-configuration.nix index 8c09beb..ca9cfec 100644 --- a/hosts/pie/hardware-configuration.nix +++ b/hosts/pie/hardware-configuration.nix @@ -1,18 +1,22 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - { + config, + lib, + pkgs, + modulesPath, + ... +}: { imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "usbhid" "uas" "usb_storage" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ ]; - boot.extraModulePackages = [ ]; - boot.supportedFilesystems = [ "zfs" ]; + boot.initrd.availableKernelModules = ["xhci_pci" "usbhid" "uas" "usb_storage"]; + boot.initrd.kernelModules = []; + boot.kernelModules = []; + boot.extraModulePackages = []; + boot.supportedFilesystems = ["zfs"]; boot.initrd.luks.devices = { cryptroot = { @@ -21,20 +25,19 @@ }; }; - fileSystems."/" = - { device = "zroot/root"; - fsType = "zfs"; - }; + fileSystems."/" = { + device = "zroot/root"; + fsType = "zfs"; + }; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/0D5D-B809"; - fsType = "vfat"; - }; - - swapDevices = - [ { device = "/dev/disk/by-uuid/af71e930-42ce-4174-a098-4ea5753b1ea9"; } - ]; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/0D5D-B809"; + fsType = "vfat"; + }; + swapDevices = [ + {device = "/dev/disk/by-uuid/af71e930-42ce-4174-a098-4ea5753b1ea9";} + ]; nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; diff --git a/hosts/pie/invoiceplane.nix b/hosts/pie/invoiceplane.nix index 0c5d4dd..96e5dd5 100644 --- a/hosts/pie/invoiceplane.nix +++ b/hosts/pie/invoiceplane.nix @@ -44,7 +44,7 @@ in { createLocally = false; }; - invoiceTemplates = [ pkgs.invoiceplane-template ]; + invoiceTemplates = [pkgs.invoiceplane-template]; extraConfig = '' SETUP_COMPLETED=true @@ -72,7 +72,7 @@ in { containers."invoiceplane-db" = { image = "mariadb:11"; autoStart = true; - ports = [ "127.0.0.1:3306:3306" ]; + ports = ["127.0.0.1:3306:3306"]; volumes = [ "/var/lib/invoiceplane/db:/var/lib/mysql" ]; diff --git a/hosts/pie/networking.nix b/hosts/pie/networking.nix index ff0e5bf..5866af8 100644 --- a/hosts/pie/networking.nix +++ b/hosts/pie/networking.nix @@ -15,16 +15,25 @@ networking.interfaces.enabcm6e4ei0 = { ipv4.addresses = [ - { address = "192.168.178.2"; prefixLength = 32; } + { + address = "192.168.178.2"; + prefixLength = 32; + } ]; ipv6.addresses = [ - { address = "2a02:908:5b1:e3c0:2::"; prefixLength = 128; } - { address = "fe80:b12f:acab:1312:acab:2::"; prefixLength = 128; } + { + address = "2a02:908:5b1:e3c0:2::"; + prefixLength = 128; + } + { + address = "fe80:b12f:acab:1312:acab:2::"; + prefixLength = 128; + } ]; }; networking.hosts = { - "192.168.178.3" = [ "droppie-initrd.b12f.io" ]; + "192.168.178.3" = ["droppie-initrd.b12f.io"]; }; services.openssh.allowSFTP = true; diff --git a/hosts/pie/paperless.nix b/hosts/pie/paperless.nix index 6979c7f..50518d9 100644 --- a/hosts/pie/paperless.nix +++ b/hosts/pie/paperless.nix @@ -13,33 +13,34 @@ with lib; let backupDir = "/var/lib/PaperlessBackup"; consumptionDir = "/var/lib/scandir"; - scan2paperless = with pkgs; writeShellScriptBin "scan2paperless" '' - DEVICE=$1 - NUM_PAGES=$2 - NAME=$3 + scan2paperless = with pkgs; + writeShellScriptBin "scan2paperless" '' + DEVICE=$1 + NUM_PAGES=$2 + NAME=$3 - if [ -z "''${DEVICE}" ] || [ -z "''${NUM_PAGES}" ] || [ -z "''${NAME}" ]; then - echo "Usage: scan2paperless " - exit 1 - fi + if [ -z "''${DEVICE}" ] || [ -z "''${NUM_PAGES}" ] || [ -z "''${NAME}" ]; then + echo "Usage: scan2paperless " + exit 1 + fi - tmpDir=$(${coreutils}/bin/mktemp -d) - files=() + tmpDir=$(${coreutils}/bin/mktemp -d) + files=() - for i in $(seq 1 $NUM_PAGES); do - fileName=$(${openssl}/bin/openssl rand -hex 12) - file="$tmpDir/$fileName.jpg" - echo "Start scanning page $i/$NUM_PAGES"; - ${sane-backends}/bin/scanimage -d $DEVICE --format=jpeg --resolution 300 --progress -o $file - echo "Finished scanning page $i"; - files+=($file) - done + for i in $(seq 1 $NUM_PAGES); do + fileName=$(${openssl}/bin/openssl rand -hex 12) + file="$tmpDir/$fileName.jpg" + echo "Start scanning page $i/$NUM_PAGES"; + ${sane-backends}/bin/scanimage -d $DEVICE --format=jpeg --resolution 300 --progress -o $file + echo "Finished scanning page $i"; + files+=($file) + done - pdf="${consumptionDir}/$NAME.pdf" - ${python3Packages.img2pdf}/bin/img2pdf --output $pdf ''${files[@]} + pdf="${consumptionDir}/$NAME.pdf" + ${python3Packages.img2pdf}/bin/img2pdf --output $pdf ''${files[@]} - echo "PDF written to $pdf" - ''; + echo "PDF written to $pdf" + ''; in { age.secrets."paperless.env" = { file = "${flake.self}/secrets/paperless.env.age"; @@ -82,7 +83,7 @@ in { }; }; - systemd.services.paperless-web.serviceConfig.EnvironmentFile = [ config.age.secrets."paperless.env".path ]; + systemd.services.paperless-web.serviceConfig.EnvironmentFile = [config.age.secrets."paperless.env".path]; ################################# # Scanning @@ -147,7 +148,7 @@ in { services.restic.backups = { paperless = { - paths = [ backupDir ]; + paths = [backupDir]; initialize = true; passwordFile = config.age.secrets."restic-password".path; # See https://www.hosting.de/blog/verschluesselte-backups-mit-rclone-und-restic-in-nextcloud/ diff --git a/hosts/pie/unbound.nix b/hosts/pie/unbound.nix index 797baa5..a769b7a 100644 --- a/hosts/pie/unbound.nix +++ b/hosts/pie/unbound.nix @@ -29,8 +29,8 @@ owner = "unbound"; }; - networking.firewall.allowedUDPPorts = [ 53 ]; - networking.firewall.allowedTCPPorts = [ 53 ]; + networking.firewall.allowedUDPPorts = [53]; + networking.firewall.allowedTCPPorts = [53]; services.resolved.enable = false; services.unbound = { @@ -94,5 +94,4 @@ }; }; }; - } diff --git a/hosts/pie/wake-droppie.nix b/hosts/pie/wake-droppie.nix index 992ac9b..ca14ad4 100644 --- a/hosts/pie/wake-droppie.nix +++ b/hosts/pie/wake-droppie.nix @@ -1,5 +1,4 @@ -{ pkgs, ... }: -{ +{pkgs, ...}: { services.cron = { enable = true; systemCronJobs = [ diff --git a/hosts/stroopwafel/configuration.nix b/hosts/stroopwafel/configuration.nix index b5f5835..314dfc2 100644 --- a/hosts/stroopwafel/configuration.nix +++ b/hosts/stroopwafel/configuration.nix @@ -17,9 +17,9 @@ in { boot.initrd.preLVMCommands = "udevadm trigger --settle"; boot.swraid.enable = true; boot.swraid.mdadmConf = '' -DEVICE /dev/nvme0n1p2 /dev/nvme1n1p2 -ARRAY /dev/md/nixos:root metadata=1.2 name=nixos:root UUID=67d1aa81:1b348887:c17a75e8:f2edf2bd -MAILADDR ${psCfg.user.email} + DEVICE /dev/nvme0n1p2 /dev/nvme1n1p2 + ARRAY /dev/md/nixos:root metadata=1.2 name=nixos:root UUID=67d1aa81:1b348887:c17a75e8:f2edf2bd + MAILADDR ${psCfg.user.email} ''; pub-solar.core.hibernation.enable = true; diff --git a/hosts/stroopwafel/default.nix b/hosts/stroopwafel/default.nix index b7f5e9c..ab6bf98 100644 --- a/hosts/stroopwafel/default.nix +++ b/hosts/stroopwafel/default.nix @@ -1,4 +1,4 @@ -{ ... }: { +{...}: { imports = [ ./configuration.nix ./hardware-configuration.nix diff --git a/hosts/stroopwafel/hardware-configuration.nix b/hosts/stroopwafel/hardware-configuration.nix index 7a09048..a621c30 100644 --- a/hosts/stroopwafel/hardware-configuration.nix +++ b/hosts/stroopwafel/hardware-configuration.nix @@ -1,55 +1,59 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; + config, + lib, + pkgs, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "usbhid" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ "dm-snapshot" ]; - boot.kernelModules = [ "kvm-amd" ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = ["nvme" "xhci_pci" "usbhid" "usb_storage" "sd_mod"]; + boot.initrd.kernelModules = ["dm-snapshot"]; + boot.kernelModules = ["kvm-amd"]; + boot.extraModulePackages = []; boot.initrd.luks.devices."cryptroot" = { device = "/dev/disk/by-id/md-name-nixos:root"; allowDiscards = true; }; - fileSystems."/" = - { device = "none"; - fsType = "tmpfs"; - }; + fileSystems."/" = { + device = "none"; + fsType = "tmpfs"; + }; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/EC82-67F4"; - fsType = "vfat"; - }; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/EC82-67F4"; + fsType = "vfat"; + }; - fileSystems."/home" = - { device = "/dev/disk/by-uuid/0cc568f0-402d-4535-980a-ed3a1dc697b9"; - fsType = "ext4"; - # https://github.com/ryantm/agenix/issues/45#issuecomment-957865406 - neededForBoot = true; - }; + fileSystems."/home" = { + device = "/dev/disk/by-uuid/0cc568f0-402d-4535-980a-ed3a1dc697b9"; + fsType = "ext4"; + # https://github.com/ryantm/agenix/issues/45#issuecomment-957865406 + neededForBoot = true; + }; - fileSystems."/nix" = - { device = "/dev/disk/by-uuid/e203d629-4d34-4147-bee6-919f0bfa25de"; - fsType = "ext4"; - }; + fileSystems."/nix" = { + device = "/dev/disk/by-uuid/e203d629-4d34-4147-bee6-919f0bfa25de"; + fsType = "ext4"; + }; - fileSystems."/persist" = - { device = "/dev/disk/by-uuid/a0855aaa-76bf-445e-b0d1-ab1552e5496f"; - fsType = "ext4"; - # https://github.com/ryantm/agenix/issues/45#issuecomment-957865406 - neededForBoot = true; - }; + fileSystems."/persist" = { + device = "/dev/disk/by-uuid/a0855aaa-76bf-445e-b0d1-ab1552e5496f"; + fsType = "ext4"; + # https://github.com/ryantm/agenix/issues/45#issuecomment-957865406 + neededForBoot = true; + }; - swapDevices = - [ { device = "/dev/disk/by-uuid/761507ab-479d-414b-ac3e-2149564ca470"; } - ]; + swapDevices = [ + {device = "/dev/disk/by-uuid/761507ab-479d-414b-ac3e-2149564ca470";} + ]; # Enables DHCP on each ethernet and wireless interface. In case of scripted networking # (the default) this is the recommended approach. When using systemd-networkd it's diff --git a/hosts/stroopwafel/networking.nix b/hosts/stroopwafel/networking.nix index d194d30..2874432 100644 --- a/hosts/stroopwafel/networking.nix +++ b/hosts/stroopwafel/networking.nix @@ -46,7 +46,7 @@ pub-solar.wireguard.ehex = { ownIPs = [ - "10.42.0.135/22" + "10.42.0.135/22" ]; privateKeyFile = config.age.secrets.wg-ehex-key.path; }; diff --git a/lib/add-local-hostname.nix b/lib/add-local-hostname.nix index 6940fa8..2e15ff5 100644 --- a/lib/add-local-hostname.nix +++ b/lib/add-local-hostname.nix @@ -1,5 +1,4 @@ -{ lib }: -hostnames: { +{lib}: hostnames: { "127.0.0.1" = hostnames; "::1" = hostnames; } diff --git a/lib/default.nix b/lib/default.nix index d9cf8cf..a1717fa 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,4 +1,8 @@ -{ lib, inputs, ... }: { +{ + lib, + inputs, + ... +}: { # Configuration common to all Linux systems flake = { lib = let @@ -10,7 +14,7 @@ #foo = callLibs ./foo.nix; ## In configs, they can be used under "lib.our" - deploy = import ./deploy.nix { inherit inputs lib; }; + deploy = import ./deploy.nix {inherit inputs lib;}; addLocalHostname = callLibs ./add-local-hostname.nix; recursiveMerge = callLibs ./recursive-merge.nix; mkEmailAddress = account: domain: account + "@" + domain; diff --git a/lib/deploy.nix b/lib/deploy.nix index ff01300..f73e37a 100644 --- a/lib/deploy.nix +++ b/lib/deploy.nix @@ -1,11 +1,13 @@ /* - * The contents of this file are adapted from digga - * https://github.com/divnix/digga - * - * Licensed under the MIT license - */ - -{ lib, inputs }: let +* The contents of this file are adapted from digga +* https://github.com/divnix/digga +* +* Licensed under the MIT license +*/ +{ + lib, + inputs, +}: let getFqdn = c: let net = c.config.networking; fqdn = @@ -17,48 +19,53 @@ in { mkDeployNodes = systemConfigurations: extraConfig: /* - * - Synopsis: mkNodes _systemConfigurations_ _extraConfig_ + * + Synopsis: mkNodes _systemConfigurations_ _extraConfig_ - Generate the `nodes` attribute expected by deploy-rs - where _systemConfigurations_ are `nodes`. + Generate the `nodes` attribute expected by deploy-rs + where _systemConfigurations_ are `nodes`. - _systemConfigurations_ should take the form of a flake's - _nixosConfigurations_. Note that deploy-rs does not currently support - deploying to darwin hosts. + _systemConfigurations_ should take the form of a flake's + _nixosConfigurations_. Note that deploy-rs does not currently support + deploying to darwin hosts. - _extraConfig_, if specified, will be merged into each of the - nodes' configurations. + _extraConfig_, if specified, will be merged into each of the + nodes' configurations. - Example _systemConfigurations_ input: + Example _systemConfigurations_ input: - ``` - { - hostname-1 = { - fastConnection = true; - sshOpts = [ "-p" "25" ]; - }; - hostname-2 = { - sshOpts = [ "-p" "19999" ]; - sshUser = "root"; - }; - } - ``` - * - */ + ``` + { + hostname-1 = { + fastConnection = true; + sshOpts = [ "-p" "25" ]; + }; + hostname-2 = { + sshOpts = [ "-p" "19999" ]; + sshUser = "root"; + }; + } + ``` + * + */ lib.recursiveUpdate (lib.mapAttrs ( _: c: let system = c.pkgs.stdenv.hostPlatform.system; # Unmodified nixpkgs - pkgs = import inputs.nixpkgs { inherit system; }; + pkgs = import inputs.nixpkgs {inherit system;}; # nixpkgs with deploy-rs overlay but force the nixpkgs package deployPkgs = import inputs.nixpkgs { inherit system; overlays = [ inputs.deploy-rs.overlay # or deploy-rs.overlays.default - (self: super: { deploy-rs = { inherit (pkgs) deploy-rs; lib = super.deploy-rs.lib; }; }) + (self: super: { + deploy-rs = { + inherit (pkgs) deploy-rs; + lib = super.deploy-rs.lib; + }; + }) ]; }; in { diff --git a/lib/recursive-merge.nix b/lib/recursive-merge.nix index 1b2c37e..f75201e 100644 --- a/lib/recursive-merge.nix +++ b/lib/recursive-merge.nix @@ -1,6 +1,4 @@ -{ lib }: -attrList: -let +{lib}: attrList: let f = attrPath: zipAttrsWith ( n: values: @@ -13,4 +11,4 @@ let else last values ); in - f [] attrList; + f [] attrList diff --git a/modules/core/networking.nix b/modules/core/networking.nix index 5880227..62d6b37 100644 --- a/modules/core/networking.nix +++ b/modules/core/networking.nix @@ -10,8 +10,8 @@ systemd.services.systemd-networkd-wait-online.enable = lib.mkDefault false; networking.hosts = { - "128.140.109.213" = [ "vpn.b12f.io" ]; - "2a01:4f8:c2c:b60::" = [ "vpn.b12f.io" ]; + "128.140.109.213" = ["vpn.b12f.io"]; + "2a01:4f8:c2c:b60::" = ["vpn.b12f.io"]; }; networking.networkmanager = { @@ -38,7 +38,7 @@ }; # Don't expose SSH via public interfaces - networking.firewall.interfaces.wg-private.allowedTCPPorts = [ 22 ]; + networking.firewall.interfaces.wg-private.allowedTCPPorts = [22]; # For rage encryption, all hosts need a ssh key pair services.openssh = { diff --git a/modules/graphical/alacritty.nix b/modules/graphical/alacritty.nix index a743574..b80acc5 100644 --- a/modules/graphical/alacritty.nix +++ b/modules/graphical/alacritty.nix @@ -159,8 +159,8 @@ # Base16 Burn 256 - alacritty color config # Benjamin Bädorf colors = { - # When true, bold text is drawn using the bright variant of colors. - draw_bold_text_with_bright_colors = true; + # When true, bold text is drawn using the bright variant of colors. + draw_bold_text_with_bright_colors = true; # Default colors primary = { diff --git a/modules/graphical/default.nix b/modules/graphical/default.nix index fcaf192..effb1f5 100644 --- a/modules/graphical/default.nix +++ b/modules/graphical/default.nix @@ -105,7 +105,7 @@ in { toggle-kbd-layout vlc wcwd - wl-mirror + wl-mirror ]; home-manager.users."${psCfg.user.name}" = { diff --git a/modules/graphical/sway/config/config.d/mode_system.conf.nix b/modules/graphical/sway/config/config.d/mode_system.conf.nix index 411213e..7539d3f 100644 --- a/modules/graphical/sway/config/config.d/mode_system.conf.nix +++ b/modules/graphical/sway/config/config.d/mode_system.conf.nix @@ -2,39 +2,40 @@ pkgs, psCfg, ... -}: with pkgs; -'' - # Set shut down, restart and locking features -'' -+ ( - if psCfg.core.hibernation.enable - then '' - set $mode_system (e)xit, (l)ock, (h)ibernate, (r)eboot, (Shift+s)hutdown +}: +with pkgs; '' - else '' - set $mode_system (e)xit, (l)ock, (r)eboot, (Shift+s)hutdown + # Set shut down, restart and locking features '' -) -+ '' - bindsym $mod+0 mode "$mode_system" + + ( + if psCfg.core.hibernation.enable + then '' + set $mode_system (e)xit, (l)ock, (h)ibernate, (r)eboot, (Shift+s)hutdown + '' + else '' + set $mode_system (e)xit, (l)ock, (r)eboot, (Shift+s)hutdown + '' + ) + + '' + bindsym $mod+0 mode "$mode_system" - mode "$mode_system" { - bindsym e exec ${sway}/bin/swaymsg exit, mode "default" - bindsym l exec ${swaylock-bg}/bin/swaylock-bg, mode "default" -'' -+ ( - if psCfg.core.hibernation.enable - then '' - bindsym h exec ${systemd}/bin/systemctl hibernate, mode "default" + mode "$mode_system" { + bindsym e exec ${sway}/bin/swaymsg exit, mode "default" + bindsym l exec ${swaylock-bg}/bin/swaylock-bg, mode "default" '' - else "" -) -+ '' - bindsym r exec ${systemd}/bin/systemctl reboot, mode "default" - bindsym Shift+s exec ${systemd}/bin/systemctl poweroff, mode "default" + + ( + if psCfg.core.hibernation.enable + then '' + bindsym h exec ${systemd}/bin/systemctl hibernate, mode "default" + '' + else "" + ) + + '' + bindsym r exec ${systemd}/bin/systemctl reboot, mode "default" + bindsym Shift+s exec ${systemd}/bin/systemctl poweroff, mode "default" - # exit system mode: "Enter" or "Escape" - bindsym Return mode "default" - bindsym Escape mode "default" -} -'' + # exit system mode: "Enter" or "Escape" + bindsym Return mode "default" + bindsym Escape mode "default" + } + '' diff --git a/modules/graphical/waybar.nix b/modules/graphical/waybar.nix index f99cd1e..99bb0ae 100644 --- a/modules/graphical/waybar.nix +++ b/modules/graphical/waybar.nix @@ -46,10 +46,10 @@ in { on-scroll = "-1"; on-click-right = "mode"; format = { - months = "{}"; - days = "{}"; - weekdays = "{}"; - today = "{}"; + months = "{}"; + days = "{}"; + weekdays = "{}"; + today = "{}"; }; }; }; diff --git a/modules/invoiceplane/default.nix b/modules/invoiceplane/default.nix index da1747f..1fa7a48 100644 --- a/modules/invoiceplane/default.nix +++ b/modules/invoiceplane/default.nix @@ -1,215 +1,221 @@ -{ config, pkgs, lib, ... }: - -with lib; - -let +{ + config, + pkgs, + lib, + ... +}: +with lib; let cfg = config.services.invoiceplane; eachSite = cfg.sites; user = "invoiceplane"; webserver = config.services.${cfg.webserver}; - invoiceplane-config = hostName: cfg: pkgs.writeText "ipconfig.php" '' - IP_URL=http://${hostName} - ENABLE_DEBUG=false - DISABLE_SETUP=false - REMOVE_INDEXPHP=false - DB_HOSTNAME=${cfg.database.host} - DB_USERNAME=${cfg.database.user} - # NOTE: file_get_contents adds newline at the end of returned string - DB_PASSWORD=${if cfg.database.passwordFile == null then "" else "trim(file_get_contents('${cfg.database.passwordFile}'),\"\\r\\n\")"} - DB_DATABASE=${cfg.database.name} - DB_PORT=${toString cfg.database.port} - SESS_EXPIRATION=864000 - ENABLE_INVOICE_DELETION=false - DISABLE_READ_ONLY=false - ENCRYPTION_KEY= - ENCRYPTION_CIPHER=AES-256 - SETUP_COMPLETED=false - REMOVE_INDEXPHP=true - ''; - - extraConfig = hostName: cfg: pkgs.writeText "extraConfig.php" '' - ${toString cfg.extraConfig} - ''; - - pkg = hostName: cfg: pkgs.stdenv.mkDerivation rec { - pname = "invoiceplane-${hostName}"; - version = src.version; - src = pkgs.invoiceplane; - - postPhase = '' - # Patch index.php file to load additional config file - substituteInPlace index.php \ - --replace "require('vendor/autoload.php');" "require('vendor/autoload.php'); \$dotenv = Dotenv\Dotenv::createImmutable(__DIR__, 'extraConfig.php'); \$dotenv->load();"; + invoiceplane-config = hostName: cfg: + pkgs.writeText "ipconfig.php" '' + IP_URL=http://${hostName} + ENABLE_DEBUG=false + DISABLE_SETUP=false + REMOVE_INDEXPHP=false + DB_HOSTNAME=${cfg.database.host} + DB_USERNAME=${cfg.database.user} + # NOTE: file_get_contents adds newline at the end of returned string + DB_PASSWORD=${ + if cfg.database.passwordFile == null + then "" + else "trim(file_get_contents('${cfg.database.passwordFile}'),\"\\r\\n\")" + } + DB_DATABASE=${cfg.database.name} + DB_PORT=${toString cfg.database.port} + SESS_EXPIRATION=864000 + ENABLE_INVOICE_DELETION=false + DISABLE_READ_ONLY=false + ENCRYPTION_KEY= + ENCRYPTION_CIPHER=AES-256 + SETUP_COMPLETED=false + REMOVE_INDEXPHP=true ''; - installPhase = '' - mkdir -p $out - cp -r * $out/ - - # symlink uploads and log directories - rm -r $out/uploads $out/application/logs $out/vendor/mpdf/mpdf/tmp - ln -sf ${cfg.stateDir}/uploads $out/ - ln -sf ${cfg.stateDir}/logs $out/application/ - ln -sf ${cfg.stateDir}/tmp $out/vendor/mpdf/mpdf/ - - # symlink the InvoicePlane config - ln -s ${cfg.stateDir}/ipconfig.php $out/ipconfig.php - - # symlink the extraConfig file - ln -s ${extraConfig hostName cfg} $out/extraConfig.php - - # symlink additional templates - ${concatMapStringsSep "\n" (template: "cp -r ${template}/. $out/application/views/invoice_templates/pdf/") cfg.invoiceTemplates} + extraConfig = hostName: cfg: + pkgs.writeText "extraConfig.php" '' + ${toString cfg.extraConfig} ''; - }; - siteOpts = { lib, name, ... }: - { - options = { + pkg = hostName: cfg: + pkgs.stdenv.mkDerivation rec { + pname = "invoiceplane-${hostName}"; + version = src.version; + src = pkgs.invoiceplane; - enable = mkEnableOption (lib.mdDoc "InvoicePlane web application"); + postPhase = '' + # Patch index.php file to load additional config file + substituteInPlace index.php \ + --replace "require('vendor/autoload.php');" "require('vendor/autoload.php'); \$dotenv = Dotenv\Dotenv::createImmutable(__DIR__, 'extraConfig.php'); \$dotenv->load();"; + ''; - stateDir = mkOption { - type = types.path; - default = "/var/lib/invoiceplane/${name}"; - description = lib.mdDoc '' - This directory is used for uploads of attachments and cache. - The directory passed here is automatically created and permissions - adjusted as required. - ''; - }; + installPhase = '' + mkdir -p $out + cp -r * $out/ - database = { - host = mkOption { - type = types.str; - default = "localhost"; - description = lib.mdDoc "Database host address."; - }; + # symlink uploads and log directories + rm -r $out/uploads $out/application/logs $out/vendor/mpdf/mpdf/tmp + ln -sf ${cfg.stateDir}/uploads $out/ + ln -sf ${cfg.stateDir}/logs $out/application/ + ln -sf ${cfg.stateDir}/tmp $out/vendor/mpdf/mpdf/ - port = mkOption { - type = types.port; - default = 3306; - description = lib.mdDoc "Database host port."; - }; + # symlink the InvoicePlane config + ln -s ${cfg.stateDir}/ipconfig.php $out/ipconfig.php - name = mkOption { - type = types.str; - default = "invoiceplane"; - description = lib.mdDoc "Database name."; - }; + # symlink the extraConfig file + ln -s ${extraConfig hostName cfg} $out/extraConfig.php - user = mkOption { - type = types.str; - default = "invoiceplane"; - description = lib.mdDoc "Database user."; - }; + # symlink additional templates + ${concatMapStringsSep "\n" (template: "cp -r ${template}/. $out/application/views/invoice_templates/pdf/") cfg.invoiceTemplates} + ''; + }; - passwordFile = mkOption { - type = types.nullOr types.path; - default = null; - example = "/run/keys/invoiceplane-dbpassword"; - description = lib.mdDoc '' - A file containing the password corresponding to - {option}`database.user`. - ''; - }; - - createLocally = mkOption { - type = types.bool; - default = true; - description = lib.mdDoc "Create the database and database user locally."; - }; - }; - - invoiceTemplates = mkOption { - type = types.listOf types.path; - default = []; - description = lib.mdDoc '' - List of path(s) to respective template(s) which are copied from the 'invoice_templates/pdf' directory. - - ::: {.note} - These templates need to be packaged before use, see example. - ::: - ''; - example = literalExpression '' - let - # Let's package an example template - template-vtdirektmarketing = pkgs.stdenv.mkDerivation { - name = "vtdirektmarketing"; - # Download the template from a public repository - src = pkgs.fetchgit { - url = "https://git.project-insanity.org/onny/invoiceplane-vtdirektmarketing.git"; - sha256 = "1hh0q7wzsh8v8x03i82p6qrgbxr4v5fb05xylyrpp975l8axyg2z"; - }; - sourceRoot = "."; - # Installing simply means copying template php file to the output directory - installPhase = "" - mkdir -p $out - cp invoiceplane-vtdirektmarketing/vtdirektmarketing.php $out/ - ""; - }; - # And then pass this package to the template list like this: - in [ template-vtdirektmarketing ] - ''; - }; - - poolConfig = mkOption { - type = with types; attrsOf (oneOf [ str int bool ]); - default = { - "pm" = "dynamic"; - "pm.max_children" = 32; - "pm.start_servers" = 2; - "pm.min_spare_servers" = 2; - "pm.max_spare_servers" = 4; - "pm.max_requests" = 500; - }; - description = lib.mdDoc '' - Options for the InvoicePlane PHP pool. See the documentation on `php-fpm.conf` - for details on configuration directives. - ''; - }; - - extraConfig = mkOption { - type = types.nullOr types.lines; - default = null; - example = '' - SETUP_COMPLETED=true - DISABLE_SETUP=true - IP_URL=https://invoice.example.com - ''; - description = lib.mdDoc '' - InvoicePlane configuration. Refer to - - for details on supported values. - ''; - }; - - cron = { - - enable = mkOption { - type = types.bool; - default = false; - description = lib.mdDoc '' - Enable cron service which periodically runs Invoiceplane tasks. - Requires key taken from the administration page. Refer to - - on how to configure it. - ''; - }; - - key = mkOption { - type = types.str; - description = lib.mdDoc "Cron key taken from the administration page."; - }; - - }; + siteOpts = { + lib, + name, + ... + }: { + options = { + enable = mkEnableOption (lib.mdDoc "InvoicePlane web application"); + stateDir = mkOption { + type = types.path; + default = "/var/lib/invoiceplane/${name}"; + description = lib.mdDoc '' + This directory is used for uploads of attachments and cache. + The directory passed here is automatically created and permissions + adjusted as required. + ''; }; + database = { + host = mkOption { + type = types.str; + default = "localhost"; + description = lib.mdDoc "Database host address."; + }; + + port = mkOption { + type = types.port; + default = 3306; + description = lib.mdDoc "Database host port."; + }; + + name = mkOption { + type = types.str; + default = "invoiceplane"; + description = lib.mdDoc "Database name."; + }; + + user = mkOption { + type = types.str; + default = "invoiceplane"; + description = lib.mdDoc "Database user."; + }; + + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/keys/invoiceplane-dbpassword"; + description = lib.mdDoc '' + A file containing the password corresponding to + {option}`database.user`. + ''; + }; + + createLocally = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc "Create the database and database user locally."; + }; + }; + + invoiceTemplates = mkOption { + type = types.listOf types.path; + default = []; + description = lib.mdDoc '' + List of path(s) to respective template(s) which are copied from the 'invoice_templates/pdf' directory. + + ::: {.note} + These templates need to be packaged before use, see example. + ::: + ''; + example = literalExpression '' + let + # Let's package an example template + template-vtdirektmarketing = pkgs.stdenv.mkDerivation { + name = "vtdirektmarketing"; + # Download the template from a public repository + src = pkgs.fetchgit { + url = "https://git.project-insanity.org/onny/invoiceplane-vtdirektmarketing.git"; + sha256 = "1hh0q7wzsh8v8x03i82p6qrgbxr4v5fb05xylyrpp975l8axyg2z"; + }; + sourceRoot = "."; + # Installing simply means copying template php file to the output directory + installPhase = "" + mkdir -p $out + cp invoiceplane-vtdirektmarketing/vtdirektmarketing.php $out/ + ""; + }; + # And then pass this package to the template list like this: + in [ template-vtdirektmarketing ] + ''; + }; + + poolConfig = mkOption { + type = with types; attrsOf (oneOf [str int bool]); + default = { + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 4; + "pm.max_requests" = 500; + }; + description = lib.mdDoc '' + Options for the InvoicePlane PHP pool. See the documentation on `php-fpm.conf` + for details on configuration directives. + ''; + }; + + extraConfig = mkOption { + type = types.nullOr types.lines; + default = null; + example = '' + SETUP_COMPLETED=true + DISABLE_SETUP=true + IP_URL=https://invoice.example.com + ''; + description = lib.mdDoc '' + InvoicePlane configuration. Refer to + + for details on supported values. + ''; + }; + + cron = { + enable = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Enable cron service which periodically runs Invoiceplane tasks. + Requires key taken from the administration page. Refer to + + on how to configure it. + ''; + }; + + key = mkOption { + type = types.str; + description = lib.mdDoc "Cron key taken from the administration page."; + }; + }; }; -in -{ + }; +in { disabledModules = [ "services/web-apps/invoiceplane.nix" ]; @@ -218,7 +224,6 @@ in options = { services.invoiceplane = mkOption { type = types.submodule { - options.sites = mkOption { type = types.attrsOf (types.submodule siteOpts); default = {}; @@ -226,7 +231,7 @@ in }; options.webserver = mkOption { - type = types.enum [ "caddy" "nginx" ]; + type = types.enum ["caddy" "nginx"]; default = "caddy"; description = lib.mdDoc '' Which webserver to use for virtual host management. Currently only @@ -237,160 +242,172 @@ in default = {}; description = lib.mdDoc "InvoicePlane configuration."; }; - }; # implementation - config = mkIf (eachSite != {}) (mkMerge [{ + config = mkIf (eachSite != {}) (mkMerge [ + { + assertions = flatten (mapAttrsToList (hostName: cfg: [ + { + assertion = cfg.database.createLocally -> cfg.database.user == user; + message = ''services.invoiceplane.sites."${hostName}".database.user must be ${user} if the database is to be automatically provisioned''; + } + { + assertion = cfg.database.createLocally -> cfg.database.passwordFile == null; + message = ''services.invoiceplane.sites."${hostName}".database.passwordFile cannot be specified if services.invoiceplane.sites."${hostName}".database.createLocally is set to true.''; + } + { + assertion = cfg.cron.enable -> cfg.cron.key != null; + message = ''services.invoiceplane.sites."${hostName}".cron.key must be set in order to use cron service.''; + } + ]) + eachSite); - assertions = flatten (mapAttrsToList (hostName: cfg: - [{ assertion = cfg.database.createLocally -> cfg.database.user == user; - message = ''services.invoiceplane.sites."${hostName}".database.user must be ${user} if the database is to be automatically provisioned''; - } - { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null; - message = ''services.invoiceplane.sites."${hostName}".database.passwordFile cannot be specified if services.invoiceplane.sites."${hostName}".database.createLocally is set to true.''; - } - { assertion = cfg.cron.enable -> cfg.cron.key != null; - message = ''services.invoiceplane.sites."${hostName}".cron.key must be set in order to use cron service.''; - } - ]) eachSite); - - services.mysql = mkIf (any (v: v.database.createLocally) (attrValues eachSite)) { - enable = true; - package = mkDefault pkgs.mariadb; - ensureDatabases = mapAttrsToList (hostName: cfg: cfg.database.name) eachSite; - ensureUsers = mapAttrsToList (hostName: cfg: - { name = cfg.database.user; - ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; }; - } - ) eachSite; - }; - - services.phpfpm = { - phpPackage = pkgs.php81; - pools = mapAttrs' (hostName: cfg: ( - nameValuePair "invoiceplane-${hostName}" { - inherit user; - group = webserver.group; - settings = { - "listen.owner" = webserver.user; - "listen.group" = webserver.group; - } // cfg.poolConfig; - } - )) eachSite; - }; - - } - - { - - systemd.tmpfiles.rules = flatten (mapAttrsToList (hostName: cfg: [ - "d ${cfg.stateDir} 0750 ${user} ${webserver.group} - -" - "f ${cfg.stateDir}/ipconfig.php 0750 ${user} ${webserver.group} - -" - "d ${cfg.stateDir}/logs 0750 ${user} ${webserver.group} - -" - "d ${cfg.stateDir}/uploads 0750 ${user} ${webserver.group} - -" - "d ${cfg.stateDir}/uploads/archive 0750 ${user} ${webserver.group} - -" - "d ${cfg.stateDir}/uploads/customer_files 0750 ${user} ${webserver.group} - -" - "d ${cfg.stateDir}/uploads/temp 0750 ${user} ${webserver.group} - -" - "d ${cfg.stateDir}/uploads/temp/mpdf 0750 ${user} ${webserver.group} - -" - "d ${cfg.stateDir}/tmp 0750 ${user} ${webserver.group} - -" - ]) eachSite); - - systemd.services.invoiceplane-config = { - serviceConfig.Type = "oneshot"; - script = concatStrings (mapAttrsToList (hostName: cfg: - '' - mkdir -p ${cfg.stateDir}/logs \ - ${cfg.stateDir}/uploads - if ! grep -q IP_URL "${cfg.stateDir}/ipconfig.php"; then - cp "${invoiceplane-config hostName cfg}" "${cfg.stateDir}/ipconfig.php" - fi - '') eachSite); - wantedBy = [ "multi-user.target" ]; - }; - - users.users.${user} = { - group = webserver.group; - isSystemUser = true; - }; - - } - { - - # Cron service implementation - - systemd.timers = mapAttrs' (hostName: cfg: ( - nameValuePair "invoiceplane-cron-${hostName}" (mkIf cfg.cron.enable { - wantedBy = [ "timers.target" ]; - timerConfig = { - OnBootSec = "5m"; - OnUnitActiveSec = "5m"; - Unit = "invoiceplane-cron-${hostName}.service"; - }; - }) - )) eachSite; - - systemd.services = - mapAttrs' (hostName: cfg: ( - nameValuePair "invoiceplane-cron-${hostName}" (mkIf cfg.cron.enable { - serviceConfig = { - Type = "oneshot"; - User = user; - ExecStart = "${pkgs.curl}/bin/curl --header 'Host: ${hostName}' http://localhost/invoices/cron/recur/${cfg.cron.key}"; - }; - }) - )) eachSite; - - } - - (mkIf (cfg.webserver == "caddy") { - services.caddy = { - enable = true; - virtualHosts = mapAttrs' (hostName: cfg: ( - nameValuePair "http://${hostName}" { - extraConfig = '' - root * ${pkg hostName cfg} - file_server - php_fastcgi unix/${config.services.phpfpm.pools."invoiceplane-${hostName}".socket} - ''; - } - )) eachSite; - }; - }) - - (mkIf (cfg.webserver == "nginx") { - services.nginx = { - enable = true; - virtualHosts = mapAttrs' (hostName: cfg: ( - nameValuePair "${hostName}" { - root = "${pkg hostName cfg}"; - extraConfig = '' - index index.php index.html index.htm; - - if (!-e $request_filename){ - rewrite ^(.*)$ /index.php break; + services.mysql = mkIf (any (v: v.database.createLocally) (attrValues eachSite)) { + enable = true; + package = mkDefault pkgs.mariadb; + ensureDatabases = mapAttrsToList (hostName: cfg: cfg.database.name) eachSite; + ensureUsers = + mapAttrsToList ( + hostName: cfg: { + name = cfg.database.user; + ensurePermissions = {"${cfg.database.name}.*" = "ALL PRIVILEGES";}; } - ''; + ) + eachSite; + }; - locations = { - "/setup".extraConfig = '' - rewrite ^(.*)$ http://${hostName}/ redirect; - ''; + services.phpfpm = { + phpPackage = pkgs.php81; + pools = + mapAttrs' (hostName: cfg: ( + nameValuePair "invoiceplane-${hostName}" { + inherit user; + group = webserver.group; + settings = + { + "listen.owner" = webserver.user; + "listen.group" = webserver.group; + } + // cfg.poolConfig; + } + )) + eachSite; + }; + } - "~ .php$" = { - extraConfig = '' - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_pass unix:${config.services.phpfpm.pools."invoiceplane-${hostName}".socket}; - include ${pkgs.nginx}/conf/fastcgi_params; - include ${pkgs.nginx}/conf/fastcgi.conf; - ''; + { + systemd.tmpfiles.rules = flatten (mapAttrsToList (hostName: cfg: [ + "d ${cfg.stateDir} 0750 ${user} ${webserver.group} - -" + "f ${cfg.stateDir}/ipconfig.php 0750 ${user} ${webserver.group} - -" + "d ${cfg.stateDir}/logs 0750 ${user} ${webserver.group} - -" + "d ${cfg.stateDir}/uploads 0750 ${user} ${webserver.group} - -" + "d ${cfg.stateDir}/uploads/archive 0750 ${user} ${webserver.group} - -" + "d ${cfg.stateDir}/uploads/customer_files 0750 ${user} ${webserver.group} - -" + "d ${cfg.stateDir}/uploads/temp 0750 ${user} ${webserver.group} - -" + "d ${cfg.stateDir}/uploads/temp/mpdf 0750 ${user} ${webserver.group} - -" + "d ${cfg.stateDir}/tmp 0750 ${user} ${webserver.group} - -" + ]) + eachSite); + + systemd.services.invoiceplane-config = { + serviceConfig.Type = "oneshot"; + script = concatStrings (mapAttrsToList (hostName: cfg: '' + mkdir -p ${cfg.stateDir}/logs \ + ${cfg.stateDir}/uploads + if ! grep -q IP_URL "${cfg.stateDir}/ipconfig.php"; then + cp "${invoiceplane-config hostName cfg}" "${cfg.stateDir}/ipconfig.php" + fi + '') + eachSite); + wantedBy = ["multi-user.target"]; + }; + + users.users.${user} = { + group = webserver.group; + isSystemUser = true; + }; + } + { + # Cron service implementation + + systemd.timers = + mapAttrs' (hostName: cfg: ( + nameValuePair "invoiceplane-cron-${hostName}" (mkIf cfg.cron.enable { + wantedBy = ["timers.target"]; + timerConfig = { + OnBootSec = "5m"; + OnUnitActiveSec = "5m"; + Unit = "invoiceplane-cron-${hostName}.service"; }; - }; - } - )) eachSite; - }; - }) + }) + )) + eachSite; + systemd.services = + mapAttrs' (hostName: cfg: ( + nameValuePair "invoiceplane-cron-${hostName}" (mkIf cfg.cron.enable { + serviceConfig = { + Type = "oneshot"; + User = user; + ExecStart = "${pkgs.curl}/bin/curl --header 'Host: ${hostName}' http://localhost/invoices/cron/recur/${cfg.cron.key}"; + }; + }) + )) + eachSite; + } + + (mkIf (cfg.webserver == "caddy") { + services.caddy = { + enable = true; + virtualHosts = + mapAttrs' (hostName: cfg: ( + nameValuePair "http://${hostName}" { + extraConfig = '' + root * ${pkg hostName cfg} + file_server + php_fastcgi unix/${config.services.phpfpm.pools."invoiceplane-${hostName}".socket} + ''; + } + )) + eachSite; + }; + }) + + (mkIf (cfg.webserver == "nginx") { + services.nginx = { + enable = true; + virtualHosts = + mapAttrs' (hostName: cfg: ( + nameValuePair "${hostName}" { + root = "${pkg hostName cfg}"; + extraConfig = '' + index index.php index.html index.htm; + + if (!-e $request_filename){ + rewrite ^(.*)$ /index.php break; + } + ''; + + locations = { + "/setup".extraConfig = '' + rewrite ^(.*)$ http://${hostName}/ redirect; + ''; + + "~ .php$" = { + extraConfig = '' + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_pass unix:${config.services.phpfpm.pools."invoiceplane-${hostName}".socket}; + include ${pkgs.nginx}/conf/fastcgi_params; + include ${pkgs.nginx}/conf/fastcgi.conf; + ''; + }; + }; + } + )) + eachSite; + }; + }) ]); } diff --git a/modules/nix/default.nix b/modules/nix/default.nix index fd3099b..bba8b79 100644 --- a/modules/nix/default.nix +++ b/modules/nix/default.nix @@ -5,15 +5,16 @@ flake, ... }: { - nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ - "steam" - "steam-original" - "steam-run" - "hplip" - "cups-brother-hl3140cw" - "uhk-agent" - "uhk-udev-rules" - ]; + nixpkgs.config.allowUnfreePredicate = pkg: + builtins.elem (lib.getName pkg) [ + "steam" + "steam-original" + "steam-run" + "hplip" + "cups-brother-hl3140cw" + "uhk-agent" + "uhk-udev-rules" + ]; nix = { # Use default version alias for nix package diff --git a/modules/persistence/default.nix b/modules/persistence/default.nix index 435e136..8544110 100644 --- a/modules/persistence/default.nix +++ b/modules/persistence/default.nix @@ -1,5 +1,8 @@ -{ lib, config, ... }: { + lib, + config, + ... +}: { environment.persistence."/persist" = { hideMounts = true; directories = [ @@ -17,7 +20,7 @@ fileSystems."/etc/nixos" = { device = "/home/${config.pub-solar.user.name}/Workspace/os"; - options = [ "bind" ]; + options = ["bind"]; }; systemd.tmpfiles.rules = [ diff --git a/modules/portable/default.nix b/modules/portable/default.nix index 5c7fb9d..cc63e0c 100644 --- a/modules/portable/default.nix +++ b/modules/portable/default.nix @@ -1,5 +1,4 @@ -{ pkgs, ... }: -{ +{pkgs, ...}: { services.cron = { enable = true; systemCronJobs = [ diff --git a/modules/printing/default.nix b/modules/printing/default.nix index 03caa88..fd0f112 100644 --- a/modules/printing/default.nix +++ b/modules/printing/default.nix @@ -16,11 +16,15 @@ services.printing.listenAddresses = ["localhost:631"]; services.printing.defaultShared = lib.mkDefault false; - services.printing.drivers = [ - pkgs.gutenprint - ] ++ (if (pkgs.system == "x86_64-linux") - then [ pkgs.cups-brother-hl3140cw ] - else []); + services.printing.drivers = + [ + pkgs.gutenprint + ] + ++ ( + if (pkgs.system == "x86_64-linux") + then [pkgs.cups-brother-hl3140cw] + else [] + ); # environment.persistence."/persist" = { # directories = [ diff --git a/modules/proxy/default.nix b/modules/proxy/default.nix index 6db5ee1..dcfc678 100644 --- a/modules/proxy/default.nix +++ b/modules/proxy/default.nix @@ -5,7 +5,7 @@ lib, ... }: { - networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.firewall.allowedTCPPorts = [80 443]; services.nginx = { enable = true; diff --git a/modules/terminal-life/.config/git/gitmessage.nix b/modules/terminal-life/.config/git/gitmessage.nix index 223bfc3..15f0eb7 100644 --- a/modules/terminal-life/.config/git/gitmessage.nix +++ b/modules/terminal-life/.config/git/gitmessage.nix @@ -6,27 +6,27 @@ user = config.pub-solar.user; xdg = config.home-manager.users."${user.name}".xdg; in '' -# What happened? -# -# fix feat build chore ci docs style refactor perf test -# -# type!(optional scope): --------------# -# + # What happened? + # + # fix feat build chore ci docs style refactor perf test + # + # type!(optional scope): --------------# + # -# ^\n -# What exactly was done and why? --------------------------------------# -# + # ^\n + # What exactly was done and why? --------------------------------------# + # -# ^\n -# -# Any issue numbers or links? -# -# Ref: #123 + # ^\n + # + # Any issue numbers or links? + # + # Ref: #123 -# ^\n -# -# Co-authored-by: Example Name + # ^\n + # + # Co-authored-by: Example Name '' diff --git a/modules/terminal-life/default.nix b/modules/terminal-life/default.nix index 949353d..fb4410d 100644 --- a/modules/terminal-life/default.nix +++ b/modules/terminal-life/default.nix @@ -21,34 +21,40 @@ in { config = { programs.command-not-found.enable = false; - users.users."${psCfg.user.name}".packages = with pkgs; [ - asciinema - bat - blesh - eza - fd - ripgrep - (nnn.overrideAttrs (o: { - patches = - (o.patches or []) - ++ [ - ./nnn/0001-feat-use-wasd-keybindings-for-jkli.patch - ]; - })) - p - powerline - screen - watson - jump - ] ++ (if cfg.full then [ - # Nix specific utilities - alejandra - manix - nix-index - nix-tree - nix-inspect - nvd - ] else []); + users.users."${psCfg.user.name}".packages = with pkgs; + [ + asciinema + bat + blesh + eza + fd + ripgrep + (nnn.overrideAttrs (o: { + patches = + (o.patches or []) + ++ [ + ./nnn/0001-feat-use-wasd-keybindings-for-jkli.patch + ]; + })) + p + powerline + screen + watson + jump + ] + ++ ( + if cfg.full + then [ + # Nix specific utilities + alejandra + manix + nix-index + nix-tree + nix-inspect + nvd + ] + else [] + ); home-manager.users."${psCfg.user.name}" = { xdg.dataFile."scripts/base16.sh".source = .local/share/scripts/base16.sh; diff --git a/modules/terminal-life/direnv/default.nix b/modules/terminal-life/direnv/default.nix index 0143c83..dbaa385 100644 --- a/modules/terminal-life/direnv/default.nix +++ b/modules/terminal-life/direnv/default.nix @@ -1,5 +1,4 @@ -{ ... }: -{ +{...}: { enable = true; nix-direnv = { enable = true; diff --git a/modules/terminal-life/git/default.nix b/modules/terminal-life/git/default.nix index 6533d04..13c8720 100644 --- a/modules/terminal-life/git/default.nix +++ b/modules/terminal-life/git/default.nix @@ -1,5 +1,4 @@ -{ ... }: -{ +{...}: { enable = true; extraConfig = { diff --git a/modules/terminal-life/nvim/default.nix b/modules/terminal-life/nvim/default.nix index 379975f..394ee69 100644 --- a/modules/terminal-life/nvim/default.nix +++ b/modules/terminal-life/nvim/default.nix @@ -19,119 +19,130 @@ in { withPython3 = true; extraPackages = with pkgs; [ - ripgrep - nixd - universal-ctags - # ansible-language-server - # clang-tools - # gopls - # nodePackages.bash-language-server - # nodePackages.svelte-language-server - # nodePackages.typescript - # nodePackages.typescript-language-server - # nodePackages.vue-language-server - # nodePackages.vscode-langservers-extracted - # nginx-language-server - # lua-language-server - # cmake-language-server - # vim-language-server - # yaml-language-server - # python3Packages.python-lsp-server - # nodePackages.dockerfile-language-server-nodejs - # docker-compose-language-service - # rust-analyzer - # cargo - # solargraph - # terraform-ls - # python3Full - ]; + ripgrep + nixd + universal-ctags + # ansible-language-server + # clang-tools + # gopls + # nodePackages.bash-language-server + # nodePackages.svelte-language-server + # nodePackages.typescript + # nodePackages.typescript-language-server + # nodePackages.vue-language-server + # nodePackages.vscode-langservers-extracted + # nginx-language-server + # lua-language-server + # cmake-language-server + # vim-language-server + # yaml-language-server + # python3Packages.python-lsp-server + # nodePackages.dockerfile-language-server-nodejs + # docker-compose-language-service + # rust-analyzer + # cargo + # solargraph + # terraform-ls + # python3Full + ]; - plugins = with pkgs.vimPlugins; [ - # The status bar in the bottom of the screen with the mode indication and file location - vim-airline + plugins = with pkgs.vimPlugins; + [ + # The status bar in the bottom of the screen with the mode indication and file location + vim-airline - # Automatically load editorconfig files in repos to configure nvim settings - editorconfig-vim + # Automatically load editorconfig files in repos to configure nvim settings + editorconfig-vim - # File browser. Use n to access - nnn-vim + # File browser. Use n to access + nnn-vim - # Highlight characters when using f, F, t, and T - quick-scope + # Highlight characters when using f, F, t, and T + quick-scope - # Undo history etc. per project - vim-workspace-nvfetcher + # Undo history etc. per project + vim-workspace-nvfetcher - # Neovim colorschemes / themes - sonokai - vim-hybrid-material - vim-airline-themes - vim-apprentice-nvfetcher + # Neovim colorschemes / themes + sonokai + vim-hybrid-material + vim-airline-themes + vim-apprentice-nvfetcher - # Git integrations - # A Git wrapper so awesome, it should be illegal - fugitive - # Shows git diff markers in the sign column - vim-gitgutter - # GitHub extension for fugitive - vim-rhubarb - # Ease your git workflow within Vim - vimagit-nvfetcher + # Git integrations + # A Git wrapper so awesome, it should be illegal + fugitive + # Shows git diff markers in the sign column + vim-gitgutter + # GitHub extension for fugitive + vim-rhubarb + # Ease your git workflow within Vim + vimagit-nvfetcher - # Telescope fuzzy finder - telescope-nvim - telescope-fzf-native-nvim + # Telescope fuzzy finder + telescope-nvim + telescope-fzf-native-nvim - # Make the yanked region apparent - vim-highlightedyank + # Make the yanked region apparent + vim-highlightedyank - # :Beautify Code beautifier - vim-beautify-nvfetcher + # :Beautify Code beautifier + vim-beautify-nvfetcher - # Unload, delete or wipe a buffer without closing the window - vim-bufkill + # Unload, delete or wipe a buffer without closing the window + vim-bufkill - # Defaults everyone can agree on - vim-sensible + # Defaults everyone can agree on + vim-sensible - # Work with tags files - vim-gutentags - ] ++ (if cfg.full then [ - nvim-treesitter.withAllGrammars + # Work with tags files + vim-gutentags + ] + ++ ( + if cfg.full + then [ + nvim-treesitter.withAllGrammars - # Dependencies for nvim-lspconfig - nvim-cmp - cmp-nvim-lsp - cmp_luasnip - luasnip + # Dependencies for nvim-lspconfig + nvim-cmp + cmp-nvim-lsp + cmp_luasnip + luasnip - # Quickstart configs for neovim LSP - lsp_extensions-nvim - nvim-lspconfig + # Quickstart configs for neovim LSP + lsp_extensions-nvim + nvim-lspconfig - # Collaborative editing in Neovim using built-in capabilities - instant-nvim-nvfetcher + # Collaborative editing in Neovim using built-in capabilities + instant-nvim-nvfetcher - # JSON schemas - SchemaStore-nvim - ] else []); + # JSON schemas + SchemaStore-nvim + ] + else [] + ); extraConfig = builtins.concatStringsSep "\n" ([ - '' - " Persistent undo - set undofile - set undodir=${xdg.cacheHome}/nvim/undo + '' + " Persistent undo + set undofile + set undodir=${xdg.cacheHome}/nvim/undo - set backupdir=${xdg.dataHome}/nvim/backup - set directory=${xdg.dataHome}/nvim/swap/ - '' - (builtins.readFile ./init.vim) - (builtins.readFile ./plugins.vim) - (builtins.readFile ./clipboard.vim) - (builtins.readFile ./ui.vim) - (builtins.readFile ./filetypes.vim) - ] ++ (if cfg.full then [ - (builtins.readFile ./lsp.vim) - (builtins.readFile ./cmp.vim) - ] else [])); + set backupdir=${xdg.dataHome}/nvim/backup + set directory=${xdg.dataHome}/nvim/swap/ + '' + (builtins.readFile ./init.vim) + (builtins.readFile ./plugins.vim) + (builtins.readFile ./clipboard.vim) + (builtins.readFile ./ui.vim) + (builtins.readFile ./filetypes.vim) + ] + ++ ( + if cfg.full + then [ + (builtins.readFile ./lsp.vim) + (builtins.readFile ./cmp.vim) + ] + else [] + )); } diff --git a/modules/user/default.nix b/modules/user/default.nix index 8dc7b65..5c92ab4 100644 --- a/modules/user/default.nix +++ b/modules/user/default.nix @@ -7,98 +7,100 @@ }: let psCfg = config.pub-solar; in -with lib; { - imports = [ - ./home.nix - ]; - - options.pub-solar = { - user = { - name = mkOption { - description = "User login name"; - type = types.nullOr types.str; - default = "nixos"; - }; - description = mkOption { - description = "User description"; - type = types.nullOr types.str; - default = "The main PubSolarOS user"; - }; - password = mkOption { - description = "User password"; - type = types.nullOr types.str; - default = null; - }; - passwordlessSudo = mkOption { - description = "Whether this user can use sudo without entering a password"; - type = types.bool; - default = false; - }; - publicKeys = mkOption { - description = "User SSH public keys"; - type = types.listOf types.str; - default = []; - }; - fullName = mkOption { - description = "User full name"; - type = types.nullOr types.str; - default = null; - }; - email = mkOption { - description = "User email address"; - type = types.nullOr types.str; - default = null; - }; - gpgKeyId = mkOption { - description = "GPG Key ID"; - type = types.nullOr types.str; - default = null; - }; - }; - }; - - config = { - users = { - mutableUsers = false; - - users."${psCfg.user.name}" = { - # Indicates whether this is an account for a “real” user. - # This automatically sets group to users, createHome to true, - # home to /home/username, useDefaultShell to true, and isSystemUser to false. - isNormalUser = true; - description = psCfg.user.description; - extraGroups = [ - "input" - "lp" - "networkmanager" - "scanner" - "video" - "dialout" - "wheel" - ]; - shell = pkgs.bash; - initialHashedPassword = - if psCfg.user.password != null - then psCfg.user.password - else ""; - openssh.authorizedKeys.keys = - flake.self.publicKeys ++ - (if psCfg.user.publicKeys != null - then psCfg.user.publicKeys - else []); - }; - }; - - security.sudo.extraRules = mkIf psCfg.user.passwordlessSudo [ - { - users = ["${psCfg.user.name}"]; - commands = [ - { - command = "ALL"; - options = ["NOPASSWD"]; - } - ]; - } + with lib; { + imports = [ + ./home.nix ]; - }; -} + + options.pub-solar = { + user = { + name = mkOption { + description = "User login name"; + type = types.nullOr types.str; + default = "nixos"; + }; + description = mkOption { + description = "User description"; + type = types.nullOr types.str; + default = "The main PubSolarOS user"; + }; + password = mkOption { + description = "User password"; + type = types.nullOr types.str; + default = null; + }; + passwordlessSudo = mkOption { + description = "Whether this user can use sudo without entering a password"; + type = types.bool; + default = false; + }; + publicKeys = mkOption { + description = "User SSH public keys"; + type = types.listOf types.str; + default = []; + }; + fullName = mkOption { + description = "User full name"; + type = types.nullOr types.str; + default = null; + }; + email = mkOption { + description = "User email address"; + type = types.nullOr types.str; + default = null; + }; + gpgKeyId = mkOption { + description = "GPG Key ID"; + type = types.nullOr types.str; + default = null; + }; + }; + }; + + config = { + users = { + mutableUsers = false; + + users."${psCfg.user.name}" = { + # Indicates whether this is an account for a “real” user. + # This automatically sets group to users, createHome to true, + # home to /home/username, useDefaultShell to true, and isSystemUser to false. + isNormalUser = true; + description = psCfg.user.description; + extraGroups = [ + "input" + "lp" + "networkmanager" + "scanner" + "video" + "dialout" + "wheel" + ]; + shell = pkgs.bash; + initialHashedPassword = + if psCfg.user.password != null + then psCfg.user.password + else ""; + openssh.authorizedKeys.keys = + flake.self.publicKeys + ++ ( + if psCfg.user.publicKeys != null + then psCfg.user.publicKeys + else [] + ); + }; + }; + + security.sudo.extraRules = mkIf psCfg.user.passwordlessSudo [ + { + users = ["${psCfg.user.name}"]; + commands = [ + { + command = "ALL"; + options = ["NOPASSWD"]; + } + ]; + } + ]; + }; + } diff --git a/modules/wireguard/default.nix b/modules/wireguard/default.nix index f4f4948..6d920b0 100644 --- a/modules/wireguard/default.nix +++ b/modules/wireguard/default.nix @@ -1,4 +1,4 @@ -{ ... }: { +{...}: { imports = [ ./private.nix ./tunnel.nix diff --git a/modules/wireguard/ehex.nix b/modules/wireguard/ehex.nix index 8119c92..b3e5ce6 100644 --- a/modules/wireguard/ehex.nix +++ b/modules/wireguard/ehex.nix @@ -2,8 +2,7 @@ lib, config, ... -}: -let +}: let cfg = config.pub-solar.wireguard.ehex; in { options.pub-solar.wireguard.ehex = { @@ -19,10 +18,10 @@ in { }; }; - config = lib.mkIf (lib.length cfg.ownIPs != 0){ + config = lib.mkIf (lib.length cfg.ownIPs != 0) { networking.firewall.allowedUDPPorts = [51822]; - systemd.network.wait-online.ignoredInterfaces = [ "wg-ehex" ]; + systemd.network.wait-online.ignoredInterfaces = ["wg-ehex"]; systemd.services.wireguard-wg-ehex = import ./service-override.nix lib; @@ -42,8 +41,8 @@ in { { endpoint = "vpn-gateway.ehex.de:4242"; publicKey = "Fsg4KEyDEvQEt/1cVWU9xa/k9x/3UhONDj61aXZ7tys="; - presharedKey = "tQy7B5R3wOgWwIKFDcEr4WZIqCrwG+9UgPRIQx/5xso="; - allowedIPs = [ "10.42.0.0/22" "10.0.66.0/24" ]; + presharedKey = "tQy7B5R3wOgWwIKFDcEr4WZIqCrwG+9UgPRIQx/5xso="; + allowedIPs = ["10.42.0.0/22" "10.0.66.0/24"]; persistentKeepalive = 15; dynamicEndpointRefreshSeconds = 30; } diff --git a/modules/wireguard/private.nix b/modules/wireguard/private.nix index 407b3dd..ce960ac 100644 --- a/modules/wireguard/private.nix +++ b/modules/wireguard/private.nix @@ -3,8 +3,7 @@ config, pkgs, ... -}: -let +}: let cfg = config.pub-solar.wireguard.private; in { options.pub-solar.wireguard.private = { @@ -43,7 +42,7 @@ in { config = lib.mkIf (builtins.length cfg.ownIPs != 0) { networking.firewall.allowedUDPPorts = [51899]; - systemd.network.wait-online.ignoredInterfaces = [ "wg-private" ]; + systemd.network.wait-online.ignoredInterfaces = ["wg-private"]; systemd.services.wireguard-wg-private = import ./service-override.nix lib; @@ -53,21 +52,30 @@ in { mtu = 1300; ips = cfg.ownIPs; privateKeyFile = cfg.privateKeyFile; - postSetup = "" - + (if cfg.useDNS then '' - printf "nameserver 10.13.12.7\nnameserver fd00:b12f:acab:1312:acab:7::" | resolvconf -a wg-private -m 0 -x - '' else "") - + (if cfg.fullTunnel then '' - defaultRoute=$(${pkgs.iproute2}/bin/ip r | ${pkgs.gnugrep}/bin/grep "default via" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $3 " " $4 " " $5 }') - ipv4=$(${pkgs.dnsutils}/bin/dig +short A vpn.b12f.io) - ${pkgs.iproute2}/bin/ip route add $ipv4 metric 256 via $defaultRoute - ipv6=$(${pkgs.dnsutils}/bin/dig +short AAAA vpn.b12f.io) - ${pkgs.iproute2}/bin/ip route add $ipv6 metric 256 via $defaultRoute - ip -4 route delete default dev wg-private || true - ip -4 route replace default dev wg-private metric 512 - ip -6 route delete default dev wg-private || true - ip -6 route replace default dev wg-private metric 512 - '' else ""); + postSetup = + "" + + ( + if cfg.useDNS + then '' + printf "nameserver 10.13.12.7\nnameserver fd00:b12f:acab:1312:acab:7::" | resolvconf -a wg-private -m 0 -x + '' + else "" + ) + + ( + if cfg.fullTunnel + then '' + defaultRoute=$(${pkgs.iproute2}/bin/ip r | ${pkgs.gnugrep}/bin/grep "default via" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $3 " " $4 " " $5 }') + ipv4=$(${pkgs.dnsutils}/bin/dig +short A vpn.b12f.io) + ${pkgs.iproute2}/bin/ip route add $ipv4 metric 256 via $defaultRoute + ipv6=$(${pkgs.dnsutils}/bin/dig +short AAAA vpn.b12f.io) + ${pkgs.iproute2}/bin/ip route add $ipv6 metric 256 via $defaultRoute + ip -4 route delete default dev wg-private || true + ip -4 route replace default dev wg-private metric 512 + ip -6 route delete default dev wg-private || true + ip -6 route replace default dev wg-private metric 512 + '' + else "" + ); postShutdown = lib.mkIf cfg.useDNS '' resolvconf -d wg-private -f ''; @@ -75,13 +83,19 @@ in { { # frikandel publicKey = "p6YKNYBlySKfhTN+wbSsKdoNjzko/XSAiTAlCJzP1jA="; - allowedIPs = [ - "10.13.12.0/24" - "fd00:b12f:acab:1312::/64" - ] ++ (if cfg.fullTunnel then [ - "0.0.0.0/0" - "::/0" - ] else []); + allowedIPs = + [ + "10.13.12.0/24" + "fd00:b12f:acab:1312::/64" + ] + ++ ( + if cfg.fullTunnel + then [ + "0.0.0.0/0" + "::/0" + ] + else [] + ); endpoint = "vpn.b12f.io:51899"; dynamicEndpointRefreshSeconds = 30; } diff --git a/modules/wireguard/pub.solar.nix b/modules/wireguard/pub.solar.nix index d28fb8d..ba1913a 100644 --- a/modules/wireguard/pub.solar.nix +++ b/modules/wireguard/pub.solar.nix @@ -2,8 +2,7 @@ lib, config, ... -}: -let +}: let cfg = config.pub-solar.wireguard.pub-solar; in { options.pub-solar.wireguard.pub-solar = { @@ -19,10 +18,10 @@ in { }; }; - config = lib.mkIf (lib.length cfg.ownIPs != 0){ + config = lib.mkIf (lib.length cfg.ownIPs != 0) { networking.firewall.allowedUDPPorts = [51821]; - systemd.network.wait-online.ignoredInterfaces = [ "wg-pub-solar" ]; + systemd.network.wait-online.ignoredInterfaces = ["wg-pub-solar"]; systemd.services.wireguard-wg-pub-solar = import ./service-override.nix lib; @@ -36,14 +35,14 @@ in { { endpoint = "flora-6.pub.solar:51820"; publicKey = "jtSR5G2P/nm9s8WrVc26Xc/SQLupRxyXE+5eIeqlsTU="; - allowedIPs = [ "10.7.6.2/32" "fd00:fae:fae:fae:fae:2::/96" ]; + allowedIPs = ["10.7.6.2/32" "fd00:fae:fae:fae:fae:2::/96"]; persistentKeepalive = 15; dynamicEndpointRefreshSeconds = 30; } { endpoint = "nachtigall.pub.solar:51820"; publicKey = "qzNywKY9RvqTnDO8eLik75/SHveaSk9OObilDzv+xkk="; - allowedIPs = [ "10.7.6.1/32" "fd00:fae:fae:fae:fae:1::/96" ]; + allowedIPs = ["10.7.6.1/32" "fd00:fae:fae:fae:fae:1::/96"]; persistentKeepalive = 15; dynamicEndpointRefreshSeconds = 30; } diff --git a/modules/wireguard/service-override.nix b/modules/wireguard/service-override.nix index a010b5a..593d9d6 100644 --- a/modules/wireguard/service-override.nix +++ b/modules/wireguard/service-override.nix @@ -1,17 +1,17 @@ lib: { - wantedBy = [ - "network.target" - "network-online.target" - "nss-lookup.target" - ]; + wantedBy = [ + "network.target" + "network-online.target" + "nss-lookup.target" + ]; - serviceConfig = { - Type = lib.mkForce "simple"; - Restart = "on-failure"; - RestartSec = "15"; - }; + serviceConfig = { + Type = lib.mkForce "simple"; + Restart = "on-failure"; + RestartSec = "15"; + }; - environment = { - WG_ENDPOINT_RESOLUTION_RETRIES = "infinity"; - }; + environment = { + WG_ENDPOINT_RESOLUTION_RETRIES = "infinity"; + }; } diff --git a/modules/wireguard/tunnel.nix b/modules/wireguard/tunnel.nix index 2bfe943..08f10be 100644 --- a/modules/wireguard/tunnel.nix +++ b/modules/wireguard/tunnel.nix @@ -3,8 +3,7 @@ config, pkgs, ... -}: -let +}: let cfg = config.pub-solar.wireguard.tunnel; in { options.pub-solar.wireguard.tunnel = { @@ -37,10 +36,10 @@ in { }; }; - config = lib.mkIf (lib.length cfg.ownIPs != 0){ + config = lib.mkIf (lib.length cfg.ownIPs != 0) { networking.firewall.allowedUDPPorts = [51820]; - systemd.network.wait-online.ignoredInterfaces = [ "wg-tunnel" ]; + systemd.network.wait-online.ignoredInterfaces = ["wg-tunnel"]; systemd.targets.wireguard-wg-tunnel = { wantedBy = lib.mkForce []; @@ -73,11 +72,22 @@ in { }; networking.wireguard.interfaces = let - splitEndpoint = (lib.strings.splitString ":" cfg.peer.endpoint); - joinIPV6 = p: ip: p + (if (lib.stringLength ip > 0) then ":" else "") + ip; + splitEndpoint = lib.strings.splitString ":" cfg.peer.endpoint; + joinIPV6 = p: ip: + p + + ( + if (lib.stringLength ip > 0) + then ":" + else "" + ) + + ip; isIPV4 = lib.length splitEndpoint < 3; - ipFlag = if isIPV4 then "-4" else "-6"; - endpointIP = (if isIPV4 + ipFlag = + if isIPV4 + then "-4" + else "-6"; + endpointIP = ( + if isIPV4 then lib.elemAt splitEndpoint 0 else lib.lists.fold joinIPV6 "" ((lib.lists.take ((lib.length splitEndpoint) - 1)) splitEndpoint) ); @@ -87,24 +97,36 @@ in { listenPort = 51820; ips = cfg.ownIPs; privateKeyFile = cfg.privateKeyFile; - postSetup = '' - defaultRoute=$(${pkgs.iproute2}/bin/ip ${ipFlag} r | ${pkgs.gnugrep}/bin/grep "default via" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $3 " " $4 " " $5 }') - ${pkgs.iproute2}/bin/ip ${ipFlag} route add "${endpointIPStripped}${if isIPV4 then "/32" else "/128"}" metric 256 via $defaultRoute - ip -4 route delete default dev wg-tunnel || true - ip -4 route add default dev wg-tunnel metric 512 - ip -6 route delete default dev wg-tunnel || true - ip -6 route add default dev wg-tunnel metric 512 - '' + (if cfg.useDNS - then ''printf "nameserver 10.64.0.1" | resolvconf -a wg-tunnel -m 0 -x'' - else ""); - postShutdown = '' - addedRoute=$(${pkgs.iproute2}/bin/ip ${ipFlag} r | ${pkgs.gnugrep}/bin/grep "${endpointIPStripped}" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $1 " " $2 " " $3 " " $4 " " $5 }') - if [ -n "$addedRoute" ]; then - ${pkgs.iproute2}/bin/ip ${ipFlag} route delete $addedRoute - fi - '' + (if cfg.useDNS - then ''resolvconf -d wg-tunnel -f'' - else ""); + postSetup = + '' + defaultRoute=$(${pkgs.iproute2}/bin/ip ${ipFlag} r | ${pkgs.gnugrep}/bin/grep "default via" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $3 " " $4 " " $5 }') + ${pkgs.iproute2}/bin/ip ${ipFlag} route add "${endpointIPStripped}${ + if isIPV4 + then "/32" + else "/128" + }" metric 256 via $defaultRoute + ip -4 route delete default dev wg-tunnel || true + ip -4 route add default dev wg-tunnel metric 512 + ip -6 route delete default dev wg-tunnel || true + ip -6 route add default dev wg-tunnel metric 512 + '' + + ( + if cfg.useDNS + then ''printf "nameserver 10.64.0.1" | resolvconf -a wg-tunnel -m 0 -x'' + else "" + ); + postShutdown = + '' + addedRoute=$(${pkgs.iproute2}/bin/ip ${ipFlag} r | ${pkgs.gnugrep}/bin/grep "${endpointIPStripped}" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $1 " " $2 " " $3 " " $4 " " $5 }') + if [ -n "$addedRoute" ]; then + ${pkgs.iproute2}/bin/ip ${ipFlag} route delete $addedRoute + fi + '' + + ( + if cfg.useDNS + then ''resolvconf -d wg-tunnel -f'' + else "" + ); peers = [ { publicKey = cfg.peer.publicKey; diff --git a/modules/wireshark/default.nix b/modules/wireshark/default.nix index e04b232..b0487a7 100644 --- a/modules/wireshark/default.nix +++ b/modules/wireshark/default.nix @@ -12,6 +12,6 @@ in { users.users."${psCfg.user.name}" = { extraGroups = ["wireshark"]; - packages = [ pkgs.wireshark ]; + packages = [pkgs.wireshark]; }; } diff --git a/overlays/default.nix b/overlays/default.nix index deb84f5..7a5baa1 100644 --- a/overlays/default.nix +++ b/overlays/default.nix @@ -5,16 +5,16 @@ }: { flake = { nixosModules = rec { - overlays = ({ ... }: { + overlays = {...}: { nixpkgs.overlays = [ inputs.deno2nix.overlays.default inputs.nixd.overlays.default inputs.invoiceplane-template.overlays.default (final: prev: let - unstable = import inputs.nixpkgs-unstable { system = prev.system; }; - master = import inputs.nixpkgs-master { system = prev.system; }; - authelia-438 = import inputs.authelia-438 { system = prev.system; }; + unstable = import inputs.nixpkgs-unstable {system = prev.system;}; + master = import inputs.nixpkgs-master {system = prev.system;}; + authelia-438 = import inputs.authelia-438 {system = prev.system;}; in { factorio-headless = master.factorio-headless; paperless-ngx = unstable.paperless-ngx; @@ -59,7 +59,7 @@ }; }) ]; - }); + }; }; }; } diff --git a/overlays/element-desktop.nix b/overlays/element-desktop.nix index c6c39c7..35dbc7d 100644 --- a/overlays/element-desktop.nix +++ b/overlays/element-desktop.nix @@ -1,3 +1,3 @@ final: prev: { - element-desktop = prev.element-desktop.override { electron = prev.electron_28; }; + element-desktop = prev.element-desktop.override {electron = prev.electron_28;}; } diff --git a/pkgs/_sources/generated.nix b/pkgs/_sources/generated.nix index 822c473..b8a311a 100644 --- a/pkgs/_sources/generated.nix +++ b/pkgs/_sources/generated.nix @@ -1,6 +1,10 @@ # This file was generated by nvfetcher, please do not modify it manually. -{ fetchgit, fetchurl, fetchFromGitHub, dockerTools }: { + fetchgit, + fetchurl, + fetchFromGitHub, + dockerTools, +}: { b12f-io-nvfetcher = { pname = "b12f-io-nvfetcher"; version = "38adb94ce69d8807ea2e36f57abe08091192b31c"; diff --git a/pkgs/check-battery.nix b/pkgs/check-battery.nix index 28f6e06..115eeb2 100644 --- a/pkgs/check-battery.nix +++ b/pkgs/check-battery.nix @@ -1,13 +1,13 @@ self: with self; '' -status=$(cat /sys/class/power_supply/BAT0/status) -if [ $status != "Discharging" ]; then - exit 0 -fi + status=$(cat /sys/class/power_supply/BAT0/status) + if [ $status != "Discharging" ]; then + exit 0 + fi -capacity=$(cat /sys/class/power_supply/BAT0/capacity) -if [ $capacity -lt 20 ]; then - export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus - ${libnotify}/bin/notify-send -u critical "Battery ''${capacity}%" -fi + capacity=$(cat /sys/class/power_supply/BAT0/capacity) + if [ $capacity -lt 20 ]; then + export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus + ${libnotify}/bin/notify-send -u critical "Battery ''${capacity}%" + fi '' diff --git a/pkgs/default.nix b/pkgs/default.nix index 24b7e37..6ef3b2a 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -5,8 +5,14 @@ with prev; { # then, call packages with `final.callPackage` check-battery = writeShellScriptBin "check-battery" (import ./check-battery.nix final); concourse = import ./concourse.nix final; - element-b12f = writeShellScriptBin "element-b12f" (import ./element-desktop.nix { inherit final; profile = "b12f"; }); - element-mezza = writeShellScriptBin "element-mezza" (import ./element-desktop.nix { inherit final; profile = "mezza"; }); + element-b12f = writeShellScriptBin "element-b12f" (import ./element-desktop.nix { + inherit final; + profile = "b12f"; + }); + element-mezza = writeShellScriptBin "element-mezza" (import ./element-desktop.nix { + inherit final; + profile = "mezza"; + }); fetch-hostingde-invoices = import ./fetch-hostingde-invoices final; import-gtk-settings = writeShellScriptBin "import-gtk-settings" (import ./import-gtk-settings.nix final); lgcl = writeShellScriptBin "lgcl" (import ./lgcl.nix final); diff --git a/pkgs/element-desktop.nix b/pkgs/element-desktop.nix index 2a04ab1..4286cbe 100644 --- a/pkgs/element-desktop.nix +++ b/pkgs/element-desktop.nix @@ -1,4 +1,7 @@ -{ final, profile }: +{ + final, + profile, +}: with final; '' -${element-desktop}/bin/element-desktop --profile=${profile} + ${element-desktop}/bin/element-desktop --profile=${profile} '' diff --git a/pkgs/fetch-hostingde-invoices/default.nix b/pkgs/fetch-hostingde-invoices/default.nix index cf710bd..97c86db 100644 --- a/pkgs/fetch-hostingde-invoices/default.nix +++ b/pkgs/fetch-hostingde-invoices/default.nix @@ -1,4 +1,5 @@ -self: self.deno2nix.mkExecutable { +self: +self.deno2nix.mkExecutable { pname = "fetch-hostingde-invoices"; version = "0.1.0"; diff --git a/public-keys.nix b/public-keys.nix index 74af8a1..0bc38cb 100644 --- a/public-keys.nix +++ b/public-keys.nix @@ -1,5 +1,4 @@ -{ lib, ... }: -{ +{lib, ...}: { flake = { publicKeys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCmXpOU6vzQiVSSYCoxHYv7wDxC63Qg3dxlAMR6AOzwIABCU5PFFNcO0NWYms/YR7MOViorl+19LCLRABar9JgHU1n+uqxKV6eGph3OPeMp5sN8LAh7C9N+TZj8iJzBxQ3ch+Z/LdmLRwYNJ7KSUI+gwGK6xRS3+z1022Y4P0G0sx7IeCBl4lealQEIIF10ZOfjUdBcLQar7XTc5AxyGKnHCerXHRtccCoadLQujk0AvPXbv3Ma4JwX9X++AnCWRWakqS5UInu2tGuZ/6Hrjd2a9AKWjTaBVDcbYqCvY4XVuMj2/A2bCceFBaoi41apybSk26FSFTU4qiEUNQ6lxeOwG4+1NCXyHe2bGI4VyoxinDYa8vLLzXIRfTRA0qoGfCweXNeWPf0jMqASkUKaSOH5Ot7O5ps34r0j9pWzavDid8QeKJPyhxKuF1a5G4iBEZ0O9vuti60dPSjJPci9oTxbune2/jb7Sa0yO06DtLFJ2ncr5f70s/BDxKk4XIwQLy+KsvzlQEGdY8yA6xv28bOGxL3sQ0HE2pDTsvIbAisVOKzdJeolStL9MM5W8Hg0r/KkGj2bg0TfoRp1xHV9hjKkvJrsQ6okaPvNFeZq0HXzPhWMOVQ+/46z80uaQ1ByRLr3FTwuWJ7F/73ndfxiq6bDE4z2Ji0vOjeWJm6HCxTdGw== id_bbcom" diff --git a/users/b12f/email.nix b/users/b12f/email.nix index 1c6cfdd..df376f3 100644 --- a/users/b12f/email.nix +++ b/users/b12f/email.nix @@ -12,59 +12,71 @@ with lib; let cacheHome = xdg.cacheHome; maildirBasePath = "/home/${psCfg.user.name}/Mail"; - generateMailAccount = args@{ address, ... }: rec { - inherit address; - realName = if (args ? "fullName") then args.fullName else psCfg.user.fullName; - signature = { - showSignature = "append"; - text = if (args ? "emptysignature") then "" else builtins.readFile (./.config/neomutt + "/${builtins.replaceStrings ["@"] ["_"] address}.signature"); - }; + generateMailAccount = args @ {address, ...}: + rec { + inherit address; + realName = + if (args ? "fullName") + then args.fullName + else psCfg.user.fullName; + signature = { + showSignature = "append"; + text = + if (args ? "emptysignature") + then "" + else builtins.readFile (./.config/neomutt + "/${builtins.replaceStrings ["@"] ["_"] address}.signature"); + }; - folders = { - inbox = "INBOX"; - drafts = "Drafts"; - sent = "Sent"; - trash = "Trash"; - }; + folders = { + inbox = "INBOX"; + drafts = "Drafts"; + sent = "Sent"; + trash = "Trash"; + }; - gpg.key = psCfg.user.gpgKeyId; + gpg.key = psCfg.user.gpgKeyId; - userName = address; - passwordCommand = "secret-tool lookup email ${address}"; - imap = { - host = mkIf (args ? "host") args.host; - port = 993; - }; - smtp = { - host = mkIf (args ? "host") args.host; - port = 587; - tls.useStartTls = true; - }; + userName = address; + passwordCommand = "secret-tool lookup email ${address}"; + imap = { + host = mkIf (args ? "host") args.host; + port = 993; + }; + smtp = { + host = mkIf (args ? "host") args.host; + port = 587; + tls.useStartTls = true; + }; - offlineimap.enable = true; - imapnotify = { - enable = true; - boxes = [ "INBOX" ]; - onNotify = "${pkgs.offlineimap}/bin/offlineimap -a ${address}"; - onNotifyPost = "${pkgs.libnotify}/bin/notify-send '${address} has new mail'"; - }; - msmtp.enable = true; - neomutt = { - enable = true; - sendMailCommand = "msmtp -a ${address}"; - extraConfig = '' - set pgp_default_key="${gpg.key}" + offlineimap.enable = true; + imapnotify = { + enable = true; + boxes = ["INBOX"]; + onNotify = "${pkgs.offlineimap}/bin/offlineimap -a ${address}"; + onNotifyPost = "${pkgs.libnotify}/bin/notify-send '${address} has new mail'"; + }; + msmtp.enable = true; + neomutt = { + enable = true; + sendMailCommand = "msmtp -a ${address}"; + extraConfig = '' + set pgp_default_key="${gpg.key}" - unmailboxes * + unmailboxes * - mailboxes +INBOX \ - +Drafts \ - +Sent \ - +Archive \ - +Trash - ''; - }; - } // (if args ? "config" then args.config else {}); + mailboxes +INBOX \ + +Drafts \ + +Sent \ + +Archive \ + +Trash + ''; + }; + } + // ( + if args ? "config" + then args.config + else {} + ); in { users.users."${psCfg.user.name}".packages = with pkgs; [ w3m @@ -86,65 +98,66 @@ in { accounts.email = { inherit maildirBasePath; - accounts = with flake.self.lib; lib.lists.foldr (item: set: (set // { "${item.address}" = generateMailAccount item; })) {} [ - { - address = mkEmailAddress "hello" "benjaminbaedorf.eu"; - host = "mail.hosting.de"; - config.primary = true; - } - { - address = mkEmailAddress "mail" "b12f.io"; - host = "mail.b12f.io"; - } - { - address = mkEmailAddress "benjamin.baedorf" "rwth-aachen.de"; - host = "mail.rwth-aachen.de"; - config.userName = mkEmailAddress "bb564306" "rwth-aachen.de"; - } - { - address = mkEmailAddress "byb" "miom.space"; - host = "mail.hosting.de"; - } - { - address = mkEmailAddress "contact" "miom.space"; - host = "mail.hosting.de"; - } - { - address = mkEmailAddress "admins" "pub.solar"; - host = "mail.pub.solar"; - } - { - address = mkEmailAddress "crew" "pub.solar"; - host = "mail.pub.solar"; - } - # { - # address = mkEmailAddress "benjamin.yule.baedorf" "verkstedt.com"; - # flavor = "gmail"; - # config = { - # smtp.host = "smtp.gmail.com"; - # imap.host = "imap.gmail.com"; - # }; - # } - { - address = mkEmailAddress "benjamin-yule.baedorf" "ext.ehealthexperts.de"; - config = { - smtp.host = "smtp.mailbox.org"; - imap.host = "imap.mailbox.org"; - }; - } - { - fullName = "mezza"; - address = mkEmailAddress "mail" "mezza.biz"; - host = "mail.mezza.biz"; - emptysignature = true; - } - { - fullname = "hwd"+ "zz"; - address = mkEmailAddress "mail" "h" + "w" + "dz" + "z.net"; - host = "mail.h" + "w" + "dz" + "z.net"; - emptysignature = true; - } - ]; + accounts = with flake.self.lib; + lib.lists.foldr (item: set: (set // {"${item.address}" = generateMailAccount item;})) {} [ + { + address = mkEmailAddress "hello" "benjaminbaedorf.eu"; + host = "mail.hosting.de"; + config.primary = true; + } + { + address = mkEmailAddress "mail" "b12f.io"; + host = "mail.b12f.io"; + } + { + address = mkEmailAddress "benjamin.baedorf" "rwth-aachen.de"; + host = "mail.rwth-aachen.de"; + config.userName = mkEmailAddress "bb564306" "rwth-aachen.de"; + } + { + address = mkEmailAddress "byb" "miom.space"; + host = "mail.hosting.de"; + } + { + address = mkEmailAddress "contact" "miom.space"; + host = "mail.hosting.de"; + } + { + address = mkEmailAddress "admins" "pub.solar"; + host = "mail.pub.solar"; + } + { + address = mkEmailAddress "crew" "pub.solar"; + host = "mail.pub.solar"; + } + # { + # address = mkEmailAddress "benjamin.yule.baedorf" "verkstedt.com"; + # flavor = "gmail"; + # config = { + # smtp.host = "smtp.gmail.com"; + # imap.host = "imap.gmail.com"; + # }; + # } + { + address = mkEmailAddress "benjamin-yule.baedorf" "ext.ehealthexperts.de"; + config = { + smtp.host = "smtp.mailbox.org"; + imap.host = "imap.mailbox.org"; + }; + } + { + fullName = "mezza"; + address = mkEmailAddress "mail" "mezza.biz"; + host = "mail.mezza.biz"; + emptysignature = true; + } + { + fullname = "hwd" + "zz"; + address = mkEmailAddress "mail" "h" + "w" + "dz" + "z.net"; + host = "mail.h" + "w" + "dz" + "z.net"; + emptysignature = true; + } + ]; }; services.imapnotify.enable = true; @@ -154,69 +167,167 @@ in { enable = true; binds = [ # Moving around - { map = ["generic"]; key = "g"; action = "noop"; } - { map = ["generic"]; key = "gg"; action = "first-entry"; } - { map = ["generic" "index"]; key = "G"; action = "last-entry"; } - { map = ["generic" "index"]; key = "i"; action = "previous-entry"; } - { map = ["generic" "index"]; key = "k"; action = "next-entry"; } - { map = ["pager" "index"]; key = "d"; action = "noop"; } - { map = ["pager" "index"]; key = "dd"; action = "delete-message"; } - { map = ["pager"]; key = "i"; action = "previous-line"; } - { map = ["pager"]; key = "k"; action = "next-line"; } - { map = ["pager"]; key = "I"; action = "previous-entry"; } - { map = ["pager"]; key = "K"; action = "next-entry"; } + { + map = ["generic"]; + key = "g"; + action = "noop"; + } + { + map = ["generic"]; + key = "gg"; + action = "first-entry"; + } + { + map = ["generic" "index"]; + key = "G"; + action = "last-entry"; + } + { + map = ["generic" "index"]; + key = "i"; + action = "previous-entry"; + } + { + map = ["generic" "index"]; + key = "k"; + action = "next-entry"; + } + { + map = ["pager" "index"]; + key = "d"; + action = "noop"; + } + { + map = ["pager" "index"]; + key = "dd"; + action = "delete-message"; + } + { + map = ["pager"]; + key = "i"; + action = "previous-line"; + } + { + map = ["pager"]; + key = "k"; + action = "next-line"; + } + { + map = ["pager"]; + key = "I"; + action = "previous-entry"; + } + { + map = ["pager"]; + key = "K"; + action = "next-entry"; + } - { map = ["pager"]; key = "r"; action = "noop"; } - { map = ["pager"]; key = "rr"; action = "reply"; } - { map = ["pager"]; key = "ra"; action = "group-reply"; } - { map = ["pager"]; key = "rn"; action = "group-chat-reply"; } - { map = ["pager"]; key = "rl"; action = "list-reply"; } + { + map = ["pager"]; + key = "r"; + action = "noop"; + } + { + map = ["pager"]; + key = "rr"; + action = "reply"; + } + { + map = ["pager"]; + key = "ra"; + action = "group-reply"; + } + { + map = ["pager"]; + key = "rn"; + action = "group-chat-reply"; + } + { + map = ["pager"]; + key = "rl"; + action = "list-reply"; + } # Threads - { map = ["browser" "pager" "index"]; key = "N"; action = "search-opposite"; } - { map = ["pager" "index"]; key = "dT"; action = "delete-thread"; } - { map = ["pager" "index"]; key = "dt"; action = "delete-subthread"; } - { map = ["pager" "index"]; key = "g"; action = "noop"; } - { map = ["pager" "index"]; key = "gt"; action = "next-thread"; } - { map = ["pager" "index"]; key = "gT"; action = "previous-thread"; } - { map = ["index"]; key = "za"; action = "collapse-thread"; } - { map = ["index"]; key = "zA"; action = "collapse-all"; } - ]; - - macros = [ - # Enable URL opening { - map = ["index" "pager"]; - key = "\\Cb"; - action = '' ${pkgs.urlscan}/bin/urlscan" "call urlscan to extract URLs out of a message''; + map = ["browser" "pager" "index"]; + key = "N"; + action = "search-opposite"; } { - map = ["attach" "compose"]; - key = "\\Cb"; - action = '' ${pkgs.urlscan}/bin/urlscan" "call urlscan to extract URLs out of a message''; + map = ["pager" "index"]; + key = "dT"; + action = "delete-thread"; } - # Translate markdown to html { - map = ["compose"]; - key = "\\Cm"; - action = ''F ${pkgs.pandoc}/bin/pandoc -s -f markdown -t html \ny^T^Utext/html; charset=utf-8\n" "Convert to HTML''; + map = ["pager" "index"]; + key = "dt"; + action = "delete-subthread"; } - # Save to ~/Downloads by default { - map = ["attach"]; - key = "S"; - action = ''~/Downloads/" "Save to Downloads''; + map = ["pager" "index"]; + key = "g"; + action = "noop"; + } + { + map = ["pager" "index"]; + key = "gt"; + action = "next-thread"; + } + { + map = ["pager" "index"]; + key = "gT"; + action = "previous-thread"; } { map = ["index"]; - key = "\\Ca"; - action = ''~NN." "Mark all as read''; + key = "za"; + action = "collapse-thread"; } - ] ++ lib.lists.imap1 (i: address: { - map = ["index" "pager"]; - key = ""; - action = ''source ${configHome}/neomutt/${address}!''; - }) (builtins.attrNames accounts.email.accounts); + { + map = ["index"]; + key = "zA"; + action = "collapse-all"; + } + ]; + + macros = + [ + # Enable URL opening + { + map = ["index" "pager"]; + key = "\\Cb"; + action = '' ${pkgs.urlscan}/bin/urlscan" "call urlscan to extract URLs out of a message''; + } + { + map = ["attach" "compose"]; + key = "\\Cb"; + action = '' ${pkgs.urlscan}/bin/urlscan" "call urlscan to extract URLs out of a message''; + } + # Translate markdown to html + { + map = ["compose"]; + key = "\\Cm"; + action = ''F ${pkgs.pandoc}/bin/pandoc -s -f markdown -t html \ny^T^Utext/html; charset=utf-8\n" "Convert to HTML''; + } + # Save to ~/Downloads by default + { + map = ["attach"]; + key = "S"; + action = ''~/Downloads/" "Save to Downloads''; + } + { + map = ["index"]; + key = "\\Ca"; + action = ''~NN." "Mark all as read''; + } + ] + ++ lib.lists.imap1 (i: address: { + map = ["index" "pager"]; + key = ""; + action = ''source ${configHome}/neomutt/${address}!''; + }) (builtins.attrNames accounts.email.accounts); # unmailboxes = true; extraConfig = '' @@ -234,7 +345,7 @@ in { imap_check_subscribed = "yes"; date_format = ''"!%d.%m.%Y %H:%M"''; index_format = ''"%4C %Z %D %4c %20.20L %s"''; - mailcap_path = "${configHome}/neomutt/mailcap"; + mailcap_path = "${configHome}/neomutt/mailcap"; }; }; }; @@ -251,7 +362,7 @@ in { services.restic.backups = { email = { - paths = [ maildirBasePath ]; + paths = [maildirBasePath]; initialize = true; passwordFile = config.age.secrets."restic-password".path; # See https://www.hosting.de/blog/verschluesselte-backups-mit-rclone-und-restic-in-nextcloud/ diff --git a/users/default.nix b/users/default.nix index 888811f..b1dccc0 100644 --- a/users/default.nix +++ b/users/default.nix @@ -1,5 +1,4 @@ -{ self, ... }: -{ +{self, ...}: { flake = { nixosModules = rec { root = import ./root; diff --git a/users/root/default.nix b/users/root/default.nix index fc783cb..465a813 100644 --- a/users/root/default.nix +++ b/users/root/default.nix @@ -1,4 +1,3 @@ -{...}: -{ +{...}: { users.users.root.hashedPassword = "$y$j9T$HihsChALx5fotahvDVhdC/$iQCGUr35quGDDEFg0SGjDBxWzU/kokgOVDX.weRvL80"; }