diff --git a/.github/README.md b/.github/README.md index f59542a..99247e8 100644 --- a/.github/README.md +++ b/.github/README.md @@ -171,13 +171,14 @@ |๐Ÿ  **treehouse** | NVIDIA DGX Spark | AI Workstation, remote builder, hm-only-reference | |๐Ÿ–ฅ๏ธ **summers** | ASUS Z10PA-D8, 2* Intel Xeon E5-2650 v4, 128GB RAM | Homeserver (microvms), remote builder, data storage | |๐Ÿ–ฅ๏ธ **winters** | ASRock J4105-ITX, 32GB RAM | Homeserver (IoT server in spe) | - |๐Ÿ–ฅ๏ธ **hintbooth** | HUNSN RM02, 8GB RAM | Router | + |๐Ÿ–ฅ๏ธ **hintbooth** | HUNSN RM02, 8GB RAM | Router, DNS Resolver, home NGINX endpoint | |โ˜๏ธ **stoicclub** | Cloud Server: 1 vCPUs, 8GB RAM | Authoritative DNS server | |โ˜๏ธ **liliputsteps** | Cloud Server: 1 vCPUs, 8GB RAM | SSH bastion | |โ˜๏ธ **twothreetunnel**| Cloud Server: 2 vCPUs, 8GB RAM | Service proxy | |โ˜๏ธ **eagleland** | Cloud Server: 2 vCPUs, 8GB RAM | Mailserver | - |โ˜๏ธ **moonside** | Cloud Server: 4 vCPUs, 24GB RAM | Gaming server, syncthing + lightweight services | + |โ˜๏ธ **moonside** | Cloud Server: 4 vCPUs, 24GB RAM | Game servers, syncthing + other lightweight services | |โ˜๏ธ **belchsfactory** | Cloud Server: 4 vCPUs, 24GB RAM | Hydra builder and nix binary cache | + |๐ŸชŸ **chaostheater** | Asus Z97-A, i7-4790k, GTX970, 32GB RAM | Home Game Streaming Server (Windows/AtlasOS, not nix-managed) | |๐Ÿ“ฑ **magicant** | Samsung Galaxy Z Flip 6 | Phone | |๐Ÿ’ฟ **drugstore** | - | NixOS-installer ISO for bootstrapping new hosts | |๐Ÿ’ฟ **brickroad** | - | Kexec tarball for bootstrapping low-memory machines | diff --git a/.sops.yaml b/.sops.yaml index e69d45d..46194ef 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -19,6 +19,8 @@ keys: - &twothreetunnel age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d - &winters age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza - &dgx age1ax5hqk6e2ekgfx5u7pl8ayc3vvhrehyvtvf07llaxhs5azpnny0qpltrns + - &hintbooth-adguardhome age1c2enwel9un28dcs4wg0vcyamx9a4a6g3walkhu8w5lqhmd804paq9d24as + - &hintbooth-nginx age1c2enwel9un28dcs4wg0vcyamx9a4a6g3walkhu8w5lqhmd804paq9d24as creation_rules: - path_regex: secrets/repo/[^/]+\.(yaml|json|env|ini|enc)$ key_groups: @@ -38,6 +40,8 @@ creation_rules: - *pyramid - *moonside - *dgx + - *hintbooth-adguardhome + - *hintbooth-nginx - path_regex: secrets/work/[^/]+\.(yaml|json|env|ini)$ key_groups: @@ -53,6 +57,7 @@ creation_rules: age: - *twothreetunnel - *eagleland + - *hintbooth-nginx - path_regex: hosts/nixos/x86_64-linux/pyramid/secrets/[^/]+\.(yaml|json|env|ini|enc)$ key_groups: @@ -131,6 +136,22 @@ creation_rules: age: - *hintbooth + - path_regex: hosts/nixos/x86_64-linux/hintbooth/secrets/adguardhome/[^/]+\.(yaml|json|env|ini|enc)$ + key_groups: + - pgp: + - *swarsel + age: + - *hintbooth + - *hintbooth-adguardhome + + - path_regex: hosts/nixos/x86_64-linux/hintbooth/secrets/nginx/[^/]+\.(yaml|json|env|ini|enc)$ + key_groups: + - pgp: + - *swarsel + age: + - *hintbooth + - *hintbooth-nginx + - path_regex: hosts/darwin/x86_64-darwin/nbm-imba-166/secrets/[^/]+\.(yaml|json|env|ini|enc)$ key_groups: - pgp: diff --git a/SwarselSystems.org b/SwarselSystems.org index b7c2b09..4942346 100644 --- a/SwarselSystems.org +++ b/SwarselSystems.org @@ -884,13 +884,14 @@ Here I give a brief overview over the host machines that I am using. This is hel |๐Ÿ  **treehouse** | NVIDIA DGX Spark | AI Workstation, remote builder, hm-only-reference | |๐Ÿ–ฅ๏ธ **summers** | ASUS Z10PA-D8, 2* Intel Xeon E5-2650 v4, 128GB RAM | Homeserver (microvms), remote builder, data storage | |๐Ÿ–ฅ๏ธ **winters** | ASRock J4105-ITX, 32GB RAM | Homeserver (IoT server in spe) | - |๐Ÿ–ฅ๏ธ **hintbooth** | HUNSN RM02, 8GB RAM | Router | + |๐Ÿ–ฅ๏ธ **hintbooth** | HUNSN RM02, 8GB RAM | Router, DNS Resolver, home NGINX endpoint | |โ˜๏ธ **stoicclub** | Cloud Server: 1 vCPUs, 8GB RAM | Authoritative DNS server | |โ˜๏ธ **liliputsteps** | Cloud Server: 1 vCPUs, 8GB RAM | SSH bastion | |โ˜๏ธ **twothreetunnel**| Cloud Server: 2 vCPUs, 8GB RAM | Service proxy | |โ˜๏ธ **eagleland** | Cloud Server: 2 vCPUs, 8GB RAM | Mailserver | - |โ˜๏ธ **moonside** | Cloud Server: 4 vCPUs, 24GB RAM | Gaming server, syncthing + lightweight services | + |โ˜๏ธ **moonside** | Cloud Server: 4 vCPUs, 24GB RAM | Game servers, syncthing + other lightweight services | |โ˜๏ธ **belchsfactory** | Cloud Server: 4 vCPUs, 24GB RAM | Hydra builder and nix binary cache | + |๐ŸชŸ **chaostheater** | Asus Z97-A, i7-4790k, GTX970, 32GB RAM | Home Game Streaming Server (Windows/AtlasOS, not nix-managed) | |๐Ÿ“ฑ **magicant** | Samsung Galaxy Z Flip 6 | Phone | |๐Ÿ’ฟ **drugstore** | - | NixOS-installer ISO for bootstrapping new hosts | |๐Ÿ’ฟ **brickroad** | - | Kexec tarball for bootstrapping low-memory machines | @@ -1934,191 +1935,252 @@ Another note concerning [[https://flake.parts/][flake-parts]]: inputs.nix-topology.flakeModule ]; - perSystem.topology.modules = [ - ({ config, ... }: - let - inherit (self.outputs) globals; - inherit (config.lib.topology) - mkInternet - mkDevice - mkSwitch - mkRouter - mkConnection - ; - in - { - renderer = "elk"; + perSystem = { system, ... }: + let + inherit (self.outputs) lib; + in + { + topology.modules = [ + ({ config, ... }: + let + globals = self.outputs.globals.${system}; + inherit (config.lib.topology) + mkInternet + mkDevice + mkSwitch + mkRouter + mkConnection + ; + in + { + renderer = "elk"; - networks = { - home-lan = { - name = "Home LAN"; - inherit (globals.networks.home-lan) cidrv4; - }; - fritz-wg = { - name = "Wireguard Tunnel for Fritzbox net access"; - inherit (globals.networks.twothreetunnel-wg) cidrv4; - }; - wg = { - name = "Wireguard Tunnel for proxy access"; - inherit (globals.networks.twothreetunnel-wg) cidrv4; - }; - }; - - nodes = { - internet = mkInternet { - connections = [ - (mkConnection "fritzbox" "dsl") - (mkConnection "moonside" "wan") - (mkConnection "belchsfactory" "wan") - (mkConnection "twothreetunnel" "wan") - (mkConnection "stoicclub" "wan") - (mkConnection "liliputsteps" "wan") - (mkConnection "eagleland" "wan") - (mkConnection "magicant" "wifi") - (mkConnection "toto" "bootstrapper") - (mkConnection "hotel" "demo host") - ]; - }; - - - fritzbox = mkRouter "FRITZ!Box" { - info = "FRITZ!Box 7682"; - image = "${self}/files/topology-images/hunsn.png"; - interfaceGroups = [ - [ - "eth1" - "eth2" - "eth3" - "eth-wan" - "wifi" - ] - [ "dsl" ] - ]; - - connections = { - eth1 = mkConnection "winters" "eth1"; - eth2 = mkConnection "switch-bedroom" "eth1"; - eth3 = mkConnection "switch-livingroom" "eth1"; - eth-wan = mkConnection "hintbooth" "eth6"; - wgPyramid = mkConnection "pyramid" "fritz-wg"; - wgMagicant = mkConnection "magicant" "fritz-wg"; - wifiPyramid = mkConnection "pyramid" "wifi"; - wifiMagicant = mkConnection "magicant" "wifi"; - wifiBakery = mkConnection "bakery" "wifi"; - wifiMachpizza = mkConnection "machpizza" "wifi"; - }; - interfaces = { - eth1 = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - network = "home-lan"; + networks = { + fritz-lan = { + name = "Fritz!Box LAN"; + inherit (globals.networks.home-lan) cidrv4 cidrv6; }; - eth2 = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - network = "home-lan"; + services = { + name = "VLAN: Services"; + inherit (globals.networks.home-lan.vlans.services) cidrv4 cidrv6; }; - eth3 = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - network = "home-lan"; + home = { + name = "VLAN: Home"; + inherit (globals.networks.home-lan.vlans.home) cidrv4 cidrv6; }; - eth-wan = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - network = "home-lan"; + devices = { + name = "VLAN: Devices"; + inherit (globals.networks.home-lan.vlans.devices) cidrv4 cidrv6; }; - wifi = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - virtual = true; - network = "home-lan"; + guests = { + name = "VLAN: Guests"; + inherit (globals.networks.home-lan.vlans.guests) cidrv4 cidrv6; }; fritz-wg = { - addresses = [ globals.networks.fritz-wg.hosts.fritzbox.ipv4 ]; - network = "wg"; - virtual = true; - type = "wireguard"; + name = "WireGuard: Fritz!Box tunnel"; + inherit (globals.networks.fritz-wg) cidrv4 cidrv6; + }; + wgProxy = { + name = "WireGuard: Web proxy tunnel"; + inherit (globals.networks.twothreetunnel-wgProxy) cidrv4 cidrv6; + }; + wgHome = { + name = "WireGuard: Home proxy tunnel"; + inherit (globals.networks.home-wgHome) cidrv4 cidrv6; }; }; - }; - switch-livingroom = mkSwitch "Switch Livingroom" { - info = "TL-SG108"; - image = "${self}/files/topology-images/TL-SG108.png"; - interfaceGroups = [ - [ - "eth1" - "eth2" - "eth3" - "eth4" - "eth5" - "eth6" - "eth7" - "eth8" - ] - ]; - connections = { - eth2 = mkConnection "nswitch" "eth1"; - eth7 = mkConnection "pc" "eth1"; - eth8 = mkConnection "pyramid" "eth1"; + nodes = { + internet = mkInternet { + connections = [ + (mkConnection "fritzbox" "dsl") + (mkConnection "magicant" "wifi") + (mkConnection "liliputsteps" "lan") + (mkConnection "treehouse" "eth1") + (mkConnection "toto" "bootstrapper") + (mkConnection "hotel" "demo host") + ]; + }; + + + fritzbox = mkRouter "FRITZ!Box" { + info = "FRITZ!Box 7682"; + image = "${self}/files/topology-images/Fritz!Box_7682.png"; + interfaceGroups = [ + [ + "eth1" + "eth2" + "eth3" + "eth-wan" + "wifi" + ] + [ "dsl" ] + ]; + + connections = { + eth1 = mkConnection "winters" "eth1"; + eth-wan = mkConnection "hintbooth" "lan"; + }; + interfaces = { + eth1 = { + addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; + network = "fritz-lan"; + }; + eth2 = { }; + eth3 = { }; + eth-wan = { + addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; + network = "fritz-lan"; + }; + wifi = { + addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; + virtual = true; + renderer.hidePhysicalConnections = true; + network = "fritz-lan"; + physicalConnections = [ + (mkConnection "pyramid" "wifi") + (mkConnection "bakery" "wifi") + (mkConnection "machpizza" "wifi") + ]; + }; + fritz-wg = { + addresses = [ globals.networks.fritz-wg.hosts.fritzbox.ipv4 ]; + network = "fritz-wg"; + virtual = true; + renderer.hidePhysicalConnections = true; + type = "wireguard"; + physicalConnections = [ + (mkConnection "pyramid" "fritz-wg") + (mkConnection "magicant" "fritz-wg") + ]; + }; + }; + }; + + switch-livingroom = mkSwitch "Switch Livingroom" { + info = "TL-SG108E"; + image = "${self}/files/topology-images/TL-SG108E.png"; + interfaceGroups = [ + # trunk + [ "eth1" ] + # devices + [ "eth2" ] + # home + [ "eth3" "eth8" ] + # guests + [ "eth4" "eth5" "eth6" "eth7" ] + ]; + interfaces = { + eth2 = { network = lib.mkForce "devices"; }; + eth3 = { network = lib.mkForce "home"; }; + eth7 = { network = lib.mkForce "guests"; }; + eth8 = { network = lib.mkForce "home"; }; + }; + connections = { + eth2 = mkConnection "nswitch" "eth1"; + eth3 = mkConnection "bakery" "eth1"; + eth7 = mkConnection "pc" "eth1"; + eth8 = mkConnection "pyramid" "eth1"; + }; + }; + + switch-bedroom = mkDevice "Switch Bedroom" { + info = "Cisco SG 200-08"; + image = "${self}/files/topology-images/Cisco_SG_200-08.png"; + interfaceGroups = [ + # trunk + [ "eth1" ] + # devices + [ "eth2" ] + # guests + [ "eth3" "eth4" "eth5" "eth6" "eth7" "eth8" ] + ]; + interfaces = { + eth2 = { network = lib.mkForce "devices"; }; + eth3 = { network = lib.mkForce "guests"; }; + }; + connections = { + eth2 = mkConnection "printer" "eth1"; + eth3 = mkConnection "machpizza" "eth1"; + }; + }; + + nswitch = mkDevice "Nintendo Switch" { + info = "Nintendo Switch"; + image = "${self}/files/topology-images/nintendo-switch.png"; + interfaces.eth1 = { }; + }; + + magicant = mkDevice "magicant" { + icon = "${self}/files/topology-images/phone.png"; + info = "Samsung Z Flip 6"; + image = "${self}/files/topology-images/zflip6.png"; + interfaces = { + wifi = { }; + fritz-wg.network = "fritz-wg"; + }; + }; + + machpizza = mkDevice "machpizza" { + info = "MacBook Pro 2016"; + icon = "devices.laptop"; + deviceIcon = "${self}/files/topology-images/mac.png"; + interfaces = { + eth1.network = "guests"; + wifi = { }; + }; + }; + + treehouse = mkDevice "treehouse" { + info = "NVIDIA DGX Spark"; + icon = "${self}/files/topology-images/home-manager.png"; + deviceIcon = "${self}/files/topology-images/dgxos.png"; + interfaces = { + eth1 = { }; + wifi = { }; + }; + services = { + ollama = { + name = "Ollama"; + icon = "${self}/files/topology-images/ollama.png"; + }; + openwebui = { + name = "Open WebUI"; + icon = "${self}/files/topology-images/openwebui.png"; + }; + comfyui = { + name = "Comfy UI"; + icon = "${self}/files/topology-images/comfyui.png"; + }; + }; + }; + + pc = mkDevice "Chaostheater" { + info = "ASUS Z97-A, i7-4790k, GTX970, 32GB RAM"; + icon = "${self}/files/topology-images/windows.png"; + deviceIcon = "${self}/files/topology-images/atlasos.png"; + services = { + sunshine = { + name = "Sunshine"; + icon = "${self}/files/topology-images/sunshine.png"; + }; + }; + interfaces.eth1.network = "guests"; + }; + + printer = mkDevice "Printer" { + info = "DELL C2665dnf"; + image = "${self}/files/topology-images/DELL-C2665dnf.png"; + interfaces.eth1 = { }; + }; + }; - }; - switch-bedroom = mkSwitch "Switch Bedroom" { - info = "TL-SG1005D"; - image = "${self}/files/topology-images/TL-SG1005D.png"; - interfaceGroups = [ - [ - "eth1" - "eth2" - "eth3" - "eth4" - "eth5" - ] - ]; - connections.eth2 = mkConnection "printer" "eth1"; - connections.eth3 = mkConnection "machpizza" "eth1"; - }; - - nswitch = mkDevice "Nintendo Switch" { - info = "Nintendo Switch"; - image = "${self}/files/topology-images/nintendo-switch.png"; - interfaces.eth1 = { }; - }; - - magicant = mkDevice "magicant" { - icon = "${self}/files/topology-images/phone.png"; - info = "Samsung Z Flip 6"; - image = "${self}/files/topology-images/zflip6.png"; - interfaces = { - wifi = { }; - fritz-wg = { }; - }; - }; - - machpizza = mkDevice "machpizza" { - info = "MacBook Pro 2016"; - icon = "${self}/files/topology-images/mac.png"; - interfaces = { - eth1 = { }; - wifi = { }; - }; - }; - - pc = mkDevice "Windows Gaming Server" { - info = "i7-4790k, GTX970, 32GB RAM"; - image = "${self}/files/topology-images/pc.png"; - interfaces.eth1 = { }; - }; - - printer = mkDevice "Printer" { - info = "DELL C2665dnf"; - image = "${self}/files/topology-images/DELL-C2665dnf.png"; - interfaces.eth1 = { }; - }; - - }; - - }) + }) - ]; + ]; + }; } #+end_src @@ -2953,9 +3015,9 @@ My work machine. Built for more security, this is the gold standard of my config topology.self = { interfaces = { - "eth1" = { }; - "wifi" = { }; - "fritz-wg" = { }; + eth1.network = lib.mkForce "home"; + wifi = { }; + fritz-wg.network = "fritz-wg"; }; }; @@ -3216,8 +3278,8 @@ My personal laptop. Closely follows the =pyramid= config, but leaves out some se ]; topology.self.interfaces = { - "eth1" = { }; - "wifi" = { }; + eth1.network = lib.mkForce "home"; + wifi = { }; }; swarselsystems = { @@ -3899,16 +3961,15 @@ This is my main server that I run at home. It handles most tasks that require bi ./disk-config.nix "${self}/modules/nixos/optional/systemd-networkd-server-home.nix" + "${self}/modules/nixos/optional/microvm-host.nix" ]; topology.self = { interfaces = { - "eth1" = { }; - "eth2" = { }; - "eth3" = { }; - "eth4" = { }; - "eth5" = { }; - "eth6" = { }; + lan2.physicalConnections = [ { node = "summers"; interface = "eth1";} ]; + lan3.physicalConnections = [ { node = "summers"; interface = "eth2";} ]; + lan4.physicalConnections = [ { node = "switch-bedroom"; interface = "eth1";} ]; + lan5.physicalConnections = [ { node = "switch-livingroom"; interface = "eth1";} ]; }; }; @@ -3938,6 +3999,8 @@ This is my main server that I run at home. It handles most tasks that require bi isServer = true; peers = [ "winters" + "hintbooth-adguardhome" + "hintbooth-nginx" ]; }; }; @@ -3960,6 +4023,7 @@ This is my main server that I run at home. It handles most tasks that require bi guests = lib.mkIf (!minimal && config.swarselsystems.withMicroVMs) ( { } // confLib.mkMicrovm "adguardhome" + // confLib.mkMicrovm "nginx" ); } @@ -4130,8 +4194,8 @@ This is my main server that I run at home. It handles most tasks that require bi :CUSTOM_ID: h:f479a908-8071-4d69-97ea-c03bfd7b88bf :END: -#+begin_src nix-ts :tangle hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome.nix - { self, lib, minimal, ... }: +#+begin_src nix-ts :tangle hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome/default.nix + { self, config, lib, minimal, ... }: { imports = [ "${self}/profiles/nixos/microvm" @@ -4140,8 +4204,24 @@ This is my main server that I run at home. It handles most tasks that require bi swarselsystems = { isMicroVM = true; + isImpermanence = true; + proxyHost = "twothreetunnel"; + server = { + wireguard.interfaces = { + wgHome = { + isClient = true; + serverName = "hintbooth"; + }; + wgProxy = { + isClient = true; + serverName = "twothreetunnel"; + }; + }; + }; }; + globals.general.homeDnsServer = config.node.name; + } // lib.optionalAttrs (!minimal) { microvm = { @@ -4153,6 +4233,79 @@ This is my main server that I run at home. It handles most tasks that require bi microvm = true; }; + swarselmodules.server = { + adguardhome = true; + }; + + } + +#+end_src + +****** Nginx +:PROPERTIES: +:CUSTOM_ID: h:90dc7f71-f9da-49ef-b273-edfab7daaa05 +:END: + +#+begin_src nix-ts :tangle hosts/nixos/x86_64-linux/hintbooth/guests/nginx/default.nix + { self, config, lib, minimal, globals, confLib, ... }: + let + inherit (confLib.static) nginxAccessRules; + in + { + imports = [ + "${self}/profiles/nixos/microvm" + "${self}/modules/nixos" + ]; + + swarselsystems = { + isMicroVM = true; + isImpermanence = true; + proxyHost = config.node.name; + server = { + wireguard.interfaces = { + wgHome = { + isClient = true; + serverName = "hintbooth"; + }; + }; + }; + }; + + globals.general.homeWebProxy = config.node.name; + + } // lib.optionalAttrs (!minimal) { + + microvm = { + mem = 3072 * 1; + vcpu = 1; + }; + + swarselprofiles = { + microvm = true; + }; + + swarselmodules.server = { + nginx = true; + }; + + services.nginx = { + upstreams.fritzbox = { + servers.${globals.networks.home-lan.hosts.fritzbox.ipv4} = { }; + }; + virtualHosts.${globals.services.fritzbox.domain} = { + useACMEHost = globals.domains.main; + forceSSL = true; + acmeRoot = null; + locations."/" = { + proxyPass = "http://fritzbox"; + proxyWebsockets = true; + }; + extraConfig = '' + proxy_ssl_verify off; + '' + nginxAccessRules; + }; + }; + } #+end_src @@ -4658,7 +4811,7 @@ This machine mainly acts as my proxy server to stand before my local machines. postgresql = true; attic = true; garage = true; - hydra = false; + hydra = true; }; } @@ -4833,6 +4986,7 @@ This machine mainly acts as my proxy server to stand before my local machines. ./disk-config.nix "${self}/modules/nixos/optional/systemd-networkd-server.nix" + "${self}/modules/nixos/optional/nix-topology-self.nix" ]; topology.self = { @@ -5030,7 +5184,7 @@ This machine mainly acts as my proxy server to stand before my local machines. :END: #+begin_src nix-ts :tangle hosts/nixos/aarch64-linux/liliputsteps/default.nix - { self, lib, minimal, ... }: + { self, config, lib, minimal, ... }: { imports = [ ./hardware-configuration.nix @@ -5042,6 +5196,16 @@ This machine mainly acts as my proxy server to stand before my local machines. topology.self = { icon = "devices.cloud-server"; + interfaces.ProxyJump = { + virtual = true; + physicalConnections = [ + (config.lib.topology.mkConnection "moonside" "lan") + (config.lib.topology.mkConnection "twothreetunnel" "lan") + (config.lib.topology.mkConnection "belchsfactory" "lan") + (config.lib.topology.mkConnection "stoicclub" "lan") + (config.lib.topology.mkConnection "eagleland" "wan") + ]; + }; }; swarselsystems = { @@ -5249,7 +5413,10 @@ This machine mainly acts as my proxy server to stand before my local machines. icon = "devices.cloud-server"; }; - globals.general.webProxy = config.node.name; + globals.general = { + webProxy = config.node.name; + oauthServer = config.node.name; + }; swarselsystems = { flakePath = "/root/.dotfiles"; @@ -5272,6 +5439,7 @@ This machine mainly acts as my proxy server to stand before my local machines. "winters" "belchsfactory" "eagleland" + "hintbooth-adguardhome" ]; }; }; @@ -6486,6 +6654,7 @@ in (splitPath "services.kanidm.provision.systems.oauth2") (splitPath "sops.secrets") (splitPath "swarselsystems.server.dns") + (splitPath "topology.self.services") ] ++ expandOptions (splitPath "networking.nftables.firewall") [ "zones" "rules" ] ++ expandOptions (splitPath "services.firezone.gateway") [ "enable" "name" "apiUrl" "tokenFile" "package" "logLevel" ] @@ -7388,7 +7557,7 @@ Normally, doing that also resets the lecture that happens on the first use of =s { config, lib, ... }: let mapperTarget = lib.swarselsystems.mkIfElse config.swarselsystems.isCrypted "/dev/mapper/cryptroot" "/dev/disk/by-label/nixos"; - inherit (config.swarselsystems) isImpermanence isCrypted; + inherit (config.swarselsystems) isImpermanence isCrypted isBtrfs; in { options.swarselmodules.impermanence = lib.mkEnableOption "impermanence config"; @@ -7404,7 +7573,7 @@ Normally, doing that also resets the lecture that happens on the first use of =s # So if it doesn't run, the btrfs system effectively acts like a normal system # Taken from https://github.com/NotAShelf/nyx/blob/2a8273ed3f11a4b4ca027a68405d9eb35eba567b/modules/core/common/system/impermanence/default.nix boot.tmp.useTmpfs = lib.mkIf (!isImpermanence) true; - boot.initrd.systemd = lib.mkIf isImpermanence { + boot.initrd.systemd = lib.mkIf (isImpermanence && isBtrfs) { enable = true; services.rollback = { description = "Rollback BTRFS root subvolume to a pristine state"; @@ -9291,6 +9460,8 @@ This is a collection of packages that are useful for server-type hosts that do n sops tmux busybox + ndisc6 + tcpdump swarsel-deploy ] ++ lib.optionals withHomeManager [ swarsel-gens @@ -9491,7 +9662,7 @@ This is a collection of packages that are useful for server-type hosts that do n }; }; config = { - extraConfig = lib.mkIf topmod.config.defaultStapling (lib.mkAfter '' + extraConfig = lib.mkIf topmod.config.defaultStapling (lib.mkBefore '' ssl_stapling on; ssl_stapling_verify on; resolver 1.1.1.1 8.8.8.8 valid=300s; @@ -10047,102 +10218,110 @@ In order to define a new wireguard interface, I have to: inherit (cfg) interfaces; ifaceList = builtins.attrValues interfaces; in - { - options = { - swarselmodules.server.${serviceName} = - lib.mkEnableOption "enable ${serviceName} settings"; + { + options = { + swarselmodules.server.${serviceName} = + lib.mkEnableOption "enable ${serviceName} settings"; - swarselsystems.server.wireguard = { - interfaces = let - topConfig = config; - in lib.mkOption { - type = lib.types.attrsOf (lib.types.submodule ({ config, name, ... }: { - options = { - isServer = lib.mkEnableOption "set this interface as a wireguard server"; - isClient = lib.mkEnableOption "set this interface as a wireguard client"; + swarselsystems.server.wireguard = { + interfaces = let + topConfig = config; + in lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({ config, name, ... }: { + options = { + isServer = lib.mkEnableOption "set this interface as a wireguard server"; + isClient = lib.mkEnableOption "set this interface as a wireguard client"; - serverName = lib.mkOption { - type = lib.types.str; - default = if config.isServer then topConfig.node.name else ""; - description = "Hostname of the WireGuard server this interface connects to (when isClient = true)."; + serverName = lib.mkOption { + type = lib.types.str; + default = if config.isServer then topConfig.node.name else ""; + description = "Hostname of the WireGuard server this interface connects to (when isClient = true)."; + }; + + serverNetConfigPrefix = lib.mkOption { + type = lib.types.str; + default = + let + serverCfg = nodes.${config.serverName}.config; + in + if serverCfg.swarselsystems.isCloud + then serverCfg.node.name + else "home"; + readOnly = true; + description = "Prefix used to look up the server network in globals.networks.\"-wg\"."; + }; + + ifName = lib.mkOption { + type = lib.types.str; + default = name; + description = "Name of the WireGuard interface."; + }; + + port = lib.mkOption { + type = lib.types.int; + default = servicePort; + description = "Port of the WireGuard interface."; + }; + + peers = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = lib.attrNames (lib.filterAttrs (name: _: name != topConfig.node.name) globals.networks."${config.serverNetConfigPrefix}-${config.ifName}".hosts); + description = "WireGuard peer config names of this wireguardinterface."; + }; }; - - serverNetConfigPrefix = lib.mkOption { - type = lib.types.str; - default = - let - serverCfg = nodes.${config.serverName}.config; - in - if serverCfg.swarselsystems.isCloud - then serverCfg.node.name - else "home"; - readOnly = true; - description = "Prefix used to look up the server network in globals.networks.\"-wg\"."; - }; - - ifName = lib.mkOption { - type = lib.types.str; - default = name; - description = "Name of the WireGuard interface."; - }; - - port = lib.mkOption { - type = lib.types.int; - default = servicePort; - description = "Port of the WireGuard interface."; - }; - - peers = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = lib.attrNames (lib.filterAttrs (name: _: name != topConfig.node.name) globals.networks."${config.serverNetConfigPrefix}-${config.ifName}".hosts); - description = "WireGuard peer config names of this wireguardinterface."; - }; - }; - })); - default = { }; - description = "WireGuard interfaces defined on this host."; + })); + default = { }; + description = "WireGuard interfaces defined on this host."; + }; }; }; - }; - config = lib.mkIf config.swarselmodules.server.${serviceName} { + config = lib.mkIf config.swarselmodules.server.${serviceName} { - assertions = lib.concatLists ( - lib.flip lib.mapAttrsToList interfaces ( - ifName: ifCfg: + assertions = lib.concatLists ( + lib.flip lib.mapAttrsToList interfaces ( + ifName: ifCfg: let assertionPrefix = "While evaluating the wireguard network ${ifName}:"; in + [ + { + assertion = ifCfg.isServer || (ifCfg.isClient && ifCfg.serverName != ""); + message = "${assertionPrefix}: This node must either be a server for the wireguard network or a client with serverName set."; + } + { + assertion = lib.stringLength ifName < 16; + message = "${assertionPrefix}: The specified linkName '${ifName}' is too long (must be max 15 characters)."; + } + ] + ) + ); + + topology.self.interfaces = lib.mapAttrs' + (wgName: _: + lib.nameValuePair "${wgName}" { + network = wgName; + } + ) + config.swarselsystems.server.wireguard.interfaces; + + environment.systemPackages = with pkgs; [ + wireguard-tools + ]; + + sops.secrets = + lib.mkMerge ( [ { - assertion = ifCfg.isServer || (ifCfg.isClient && ifCfg.serverName != ""); - message = "${assertionPrefix}: This node must either be a server for the wireguard network or a client with serverName set."; + wireguard-private-key = { + inherit sopsFile; + owner = serviceUser; + group = serviceGroup; + mode = "0600"; + }; } - { - assertion = lib.stringLength ifName < 16; - message = "${assertionPrefix}: The specified linkName '${ifName}' is too long (must be max 15 characters)."; - } - ] - ) - ); - - environment.systemPackages = with pkgs; [ - wireguard-tools - ]; - - sops.secrets = - lib.mkMerge ( - [ - { - wireguard-private-key = { - inherit sopsFile; - owner = serviceUser; - group = serviceGroup; - mode = "0600"; - }; - } - ] ++ (map - (i: + ] ++ (map + (i: let clientSecrets = lib.optionalAttrs i.isClient { @@ -10167,26 +10346,26 @@ In order to define a new wireguard interface, I have to: }) i.peers)); in - clientSecrets // serverSecrets - ) - ifaceList) - ); + clientSecrets // serverSecrets + ) + ifaceList) + ); - networking.firewall = { - checkReversePath = lib.mkIf (lib.any (i: i.isClient) ifaceList) "loose"; - allowedUDPPorts = lib.mkMerge ( - lib.flip lib.mapAttrsToList interfaces ( - _: ifCfg: - lib.optional ifCfg.isServer ifCfg.port - ) - ); - }; - - networking.nftables.firewall = { - zones = lib.mkMerge - ( + networking.firewall = { + checkReversePath = lib.mkIf (lib.any (i: i.isClient) ifaceList) "loose"; + allowedUDPPorts = lib.mkMerge ( lib.flip lib.mapAttrsToList interfaces ( - ifName: ifCfg: + _: ifCfg: + lib.optional ifCfg.isServer ifCfg.port + ) + ); + }; + + networking.nftables.firewall = { + zones = lib.mkMerge + ( + lib.flip lib.mapAttrsToList interfaces ( + ifName: ifCfg: { ${ifName}.interfaces = [ ifName ]; } @@ -10195,30 +10374,30 @@ In order to define a new wireguard interface, I have to: let peerNet = globals.networks."${ifCfg.serverNetConfigPrefix}-${ifName}".hosts.${peer}; in - lib.nameValuePair "${ifName}-node-${peer}" { - parent = ifName; - ipv4Addresses = lib.optional (peerNet.ipv4 != null) peerNet.ipv4; - ipv6Addresses = lib.optional (peerNet.ipv6 != null) peerNet.ipv6; - } + lib.nameValuePair "${ifName}-node-${peer}" { + parent = ifName; + ipv4Addresses = lib.optional (peerNet.ipv4 != null) peerNet.ipv4; + ipv6Addresses = lib.optional (peerNet.ipv6 != null) peerNet.ipv6; + } ) ifCfg.peers) - ) - ); - rules = lib.mkMerge ( - lib.flip lib.mapAttrsToList interfaces ( - ifName: ifCfg: + ) + ); + rules = lib.mkMerge ( + lib.flip lib.mapAttrsToList interfaces ( + ifName: ifCfg: let inherit (config.networking.nftables.firewall) localZoneName; netCfg = globals.networks."${ifCfg.serverNetConfigPrefix}-${ifName}"; in - { - "${ifName}-to-${localZoneName}" = { - inherit (netCfg.firewallRuleForAll) allowedTCPPorts allowedUDPPorts allowedTCPPortRanges allowedUDPPortRanges; - from = [ ifName ]; - to = [ localZoneName ]; - ignoreEmptyRule = true; - }; - } + { + "${ifName}-to-${localZoneName}" = { + inherit (netCfg.firewallRuleForAll) allowedTCPPorts allowedUDPPorts allowedTCPPortRanges allowedUDPPortRanges; + from = [ ifName ]; + to = [ localZoneName ]; + ignoreEmptyRule = true; + }; + } // lib.listToAttrs (map (peer: lib.nameValuePair "${ifName}-node-${peer}-to-${localZoneName}" ( @@ -10231,75 +10410,75 @@ In order to define a new wireguard interface, I have to: ) ) ifCfg.peers) - ) - ); - }; + ) + ); + }; - systemd.network = { - enable = true; + systemd.network = { + enable = true; - networks = lib.mkMerge (map - (i: + networks = lib.mkMerge (map + (i: let inherit (i) ifName; in - { - "50-${ifName}" = { - matchConfig.Name = ifName; - linkConfig = { - MTUBytes = 1408; # TODO: figure out where we lose those 12 bits (8 from pppoe maybe + ???) + { + "50-${ifName}" = { + matchConfig.Name = ifName; + linkConfig = { + MTUBytes = 1408; # TODO: figure out where we lose those 12 bits (8 from pppoe maybe + ???) + }; + + address = [ + globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv4 + globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv6 + ]; }; + }) + ifaceList); - address = [ - globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv4 - globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv6 - ]; - }; - }) - ifaceList); - - netdevs = lib.mkMerge (map - (i: + netdevs = lib.mkMerge (map + (i: let inherit (i) ifName; in - { - "50-${ifName}" = { - netdevConfig = { - Kind = "wireguard"; - Name = ifName; - }; + { + "50-${ifName}" = { + netdevConfig = { + Kind = "wireguard"; + Name = ifName; + }; - wireguardConfig = { - ListenPort = lib.mkIf i.isServer servicePort; + wireguardConfig = { + ListenPort = lib.mkIf i.isServer servicePort; - PrivateKeyFile = config.sops.secrets.wireguard-private-key.path; + PrivateKeyFile = config.sops.secrets.wireguard-private-key.path; - RouteTable = lib.mkIf i.isClient "main"; - }; + RouteTable = lib.mkIf i.isClient "main"; + }; - wireguardPeers = - lib.optionals i.isClient [ - { - PublicKey = - builtins.readFile "${self}/secrets/public/wg/${i.serverName}.pub"; + wireguardPeers = + lib.optionals i.isClient [ + { + PublicKey = + builtins.readFile "${self}/secrets/public/wg/${i.serverName}.pub"; - PresharedKeyFile = - config.sops.secrets."wireguard-${i.serverName}-${config.node.name}-${i.ifName}-presharedKey".path; + PresharedKeyFile = + config.sops.secrets."wireguard-${i.serverName}-${config.node.name}-${i.ifName}-presharedKey".path; - Endpoint = - "server.${i.serverName}.${globals.domains.main}:${toString servicePort}"; + Endpoint = + "server.${i.serverName}.${globals.domains.main}:${toString servicePort}"; - PersistentKeepalive = 25; + PersistentKeepalive = 25; - AllowedIPs = - let - wgNetwork = globals.networks."${i.serverNetConfigPrefix}-${i.ifName}"; - in - (lib.optional (wgNetwork.cidrv4 != null) wgNetwork.cidrv4) + AllowedIPs = + let + wgNetwork = globals.networks."${i.serverNetConfigPrefix}-${i.ifName}"; + in + (lib.optional (wgNetwork.cidrv4 != null) wgNetwork.cidrv4) ++ (lib.optional (wgNetwork.cidrv6 != null) wgNetwork.cidrv6); - } - ] + } + ] ++ lib.optionals i.isServer (map (clientName: { PublicKey = @@ -10313,18 +10492,18 @@ In order to define a new wireguard interface, I have to: clientInWgNetwork = globals.networks."${i.serverNetConfigPrefix}-${i.ifName}".hosts.${clientName}; in - (lib.optional (clientInWgNetwork.ipv4 != null) - (lib.net.cidr.make 32 clientInWgNetwork.ipv4)) + (lib.optional (clientInWgNetwork.ipv4 != null) + (lib.net.cidr.make 32 clientInWgNetwork.ipv4)) ++ (lib.optional (clientInWgNetwork.ipv6 != null) (lib.net.cidr.make 128 clientInWgNetwork.ipv6)); }) i.peers); - }; - }) - ifaceList); + }; + }) + ifaceList); + }; }; - }; - } + } #+end_src **** BTRFS @@ -10375,7 +10554,7 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin - global IPv4/IPv6 forwarding is enabled via boot.kernel.sysctl so this host acts as the main router between all VLANs, the WireGuard network, and the WAN (untrusted) #+begin_src nix-ts :tangle modules/nixos/server/router.nix - { lib, config, globals, ... }: + { lib, config, globals, confLib, ... }: let serviceName = "router"; bridgeVLANs = lib.mapAttrsToList @@ -10386,6 +10565,7 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin selectVLANs = vlans: map (vlan: { VLAN = globals.networks.home-lan.vlans.${vlan}.id; }) vlans; lan5VLANs = selectVLANs [ "home" "devices" "guests" ]; lan4VLANs = selectVLANs [ "home" "services" ]; + inherit (confLib.gen { }) homeDnsServer; in { options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; @@ -10393,13 +10573,27 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin { services.avahi.reflector = true; + topology.self.interfaces = (lib.mapAttrs' + (vlanName: _: + lib.nameValuePair "vlan-${vlanName}" { + network = lib.mkForce vlanName; + } + ) + globals.networks.home-lan.vlans) // (lib.mapAttrs' + (vlanName: _: + lib.nameValuePair "me-${vlanName}" { + network = lib.mkForce vlanName; + } + ) + globals.networks.home-lan.vlans); + networking.nftables = { firewall = { zones = { untrusted.interfaces = [ "lan" ]; wgHome.interfaces = [ "wgHome" ]; - adguardhome.ipv4Addresses = [ globals.networks.home-lan.vlans.services.hosts.hintbooth-adguardhome.ipv4 ]; - adguardhome.ipv6Addresses = [ globals.networks.home-lan.vlans.services.hosts.hintbooth-adguardhome.ipv6 ]; + adguardhome.ipv4Addresses = [ globals.networks.home-lan.vlans.services.hosts.${homeDnsServer}.ipv4 ]; + adguardhome.ipv6Addresses = [ globals.networks.home-lan.vlans.services.hosts.${homeDnsServer}.ipv6 ]; } // lib.flip lib.concatMapAttrs globals.networks.home-lan.vlans ( vlanName: _: { @@ -10409,7 +10603,7 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin rules = { masquerade-internet = { - from = map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans); + from = map (name: "vlan-${name}") (globals.general.internetVLANs); to = [ "untrusted" ]; # masquerade = true; NOTE: custom rule below for ip4 + ip6 late = true; # Only accept after any rejects have been processed @@ -10418,7 +10612,7 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin # Allow access to the AdGuardHome DNS server from any VLAN that has internet access access-adguardhome-dns = { - from = map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans); + from = map (name: "vlan-${name}") (globals.general.internetVLANs); to = [ "adguardhome" ]; verdict = "accept"; }; @@ -10438,7 +10632,7 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin services-to-local = { from = [ "vlan-services" ]; to = [ "local" ]; - allowedUDPPorts = [ 52829 ]; + allowedUDPPorts = [ 52829 547 ]; }; # Forward traffic between wireguard participants @@ -10456,7 +10650,7 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin late = true; rules = lib.forEach - (map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans)) + (map (name: "vlan-${name}") (globals.general.internetVLANs)) ( zone: lib.concatStringsSep " " [ @@ -10604,8 +10798,14 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin IPv6AcceptRA = false; }; ipv6Prefixes = [ - { Prefix = vlanCfg.cidrv6; } + { + Prefix = vlanCfg.cidrv6; + } ]; + ipv6SendRAConfig = { + Managed = true; # set RA M flag -> DHCPv6 for addresses + OtherInformation = true; # optional, for โ€œother infoโ€ via DHCPv6 + }; linkConfig.RequiredForOnline = "routable"; }; } @@ -10687,7 +10887,6 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin virtualHosts = { "${serviceDomain}" = { useACMEHost = globals.domains.main; - forceSSL = true; acmeRoot = null; locations = { @@ -10818,6 +11017,8 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin mpv ]; + topology.self.services.${serviceName}.info = "https://${serviceDomain}"; + users = { groups = { ${serviceGroup} = { @@ -11159,6 +11360,50 @@ This is the configuration to make [[#h:58c7563e-6954-42e6-a622-9d06523e8e24][Hin } #+end_src +**** podman + +#+begin_src nix-ts :tangle modules/nixos/server/podman.nix + { config, lib, ... }: + let + serviceName = "podman"; + in + { + options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; + config = lib.mkIf config.swarselmodules.server.${serviceName} { + + virtualisation = { + podman.enable = true; + oci-containers.backend = "podman"; + }; + + networking.nftables.firewall = lib.mkIf config.networking.nftables.enable { + + zones.podman = { + interfaces = [ "podman0" ]; + }; + + rules = { + podman-to-postgres = lib.mkIf config.services.postgresql.enable { + from = [ "podman" ]; + to = [ "local" ]; + before = [ "drop" ]; + allowedTCPPorts = [ config.services.postgresql.settings.port ]; + }; + + local-to-podman = { + from = [ "local" "wgProxy" "wgHme"]; + to = [ "podman" ]; + before = [ "drop" ]; + verdict = "accept"; + }; + }; + }; + + }; + } +#+end_src + + **** matrix :PROPERTIES: :CUSTOM_ID: h:1e68d84a-8f99-422f-89ac-78f664ac0013 @@ -13312,6 +13557,7 @@ kanidm person credential create-reset-token "radicale.access" = { }; "slink.access" = { }; "opkssh.access" = { }; + "adguardhome.access" = { }; }; inherit (config.repo.secrets.local) persons; @@ -13454,6 +13700,11 @@ kanidm person credential create-reset-token "email" "profile" ]; + "adguardhome.access" = [ + "openid" + "email" + "profile" + ]; }; preferShortUsername = true; claimMaps.groups = { @@ -13464,6 +13715,7 @@ kanidm person credential create-reset-token "firefly.access" = [ "firefly_access" ]; "radicale.access" = [ "radicale_access" ]; "slink.access" = [ "slink_access" ]; + "adguardhome.access" = [ "adguardhome_access" ]; }; }; }; @@ -13515,7 +13767,8 @@ kanidm person credential create-reset-token #+begin_src nix-ts :tangle modules/nixos/server/oauth2-proxy.nix { lib, config, globals, dns, confLib, ... }: let - inherit (confLib.gen { name = "oauth2-proxy"; port = 3004; }) servicePort serviceName serviceUser serviceGroup serviceDomain serviceAddress proxyAddress4 proxyAddress6 isHome isProxied homeProxy webProxy dnsServer homeProxyIf webProxyIf; + inherit (confLib.gen { name = "oauth2-proxy"; port = 3004; }) servicePort serviceName serviceUser serviceGroup serviceDomain serviceAddress proxyAddress4 proxyAddress6; + inherit (confLib.static) isHome isProxied homeProxy webProxy dnsServer homeProxyIf webProxyIf homeWebProxy oauthServer nginxAccessRules; kanidmDomain = globals.services.kanidm.domain; mainDomain = globals.domains.main; @@ -13634,10 +13887,6 @@ kanidm person credential create-reset-token }; config = lib.mkIf config.swarselmodules.server.${serviceName} { - nodes.${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { - "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; - }; - sops = { secrets = { "oauth2-cookie-secret" = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0440"; }; @@ -13669,8 +13918,8 @@ kanidm person credential create-reset-token }; }; services.${serviceName} = { - domain = serviceDomain; - inherit proxyAddress4 proxyAddress6 isHome; + domain = serviceDomain; + inherit proxyAddress4 proxyAddress6 isHome; }; }; @@ -13723,32 +13972,42 @@ kanidm person credential create-reset-token }; }; - nodes.${webProxy}.services.nginx = { - upstreams = { - ${serviceName} = { - servers = { - "${serviceAddress}:${builtins.toString servicePort}" = { }; - }; - }; - }; - virtualHosts = { - "${serviceDomain}" = { - useACMEHost = globals.domains.main; - - forceSSL = true; - acmeRoot = null; - locations = { - "/" = { - proxyPass = "http://${serviceName}"; + nodes = + let + genNginx = toAddress: extraConfig: { + upstreams = { + ${serviceName} = { + servers = { + "${toAddress}:${builtins.toString servicePort}" = { }; + }; + }; + }; + virtualHosts = { + "${serviceDomain}" = { + useACMEHost = globals.domains.main; + + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://${serviceName}"; + }; + }; + extraConfig = '' + proxy_set_header X-Scheme $scheme; + proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; + '' + lib.optionalString (extraConfig != "") extraConfig; }; }; - extraConfig = '' - proxy_set_header X-Scheme $scheme; - proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; - ''; }; + in + { + ${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { + "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; + }; + ${webProxy}.services.nginx = genNginx serviceAddress ""; + ${homeWebProxy}.services.nginx = genNginx globals.hosts.${oauthServer}.wanAddress4 nginxAccessRules; }; - }; }; } #+end_src @@ -13898,6 +14157,10 @@ kanidm person credential create-reset-token options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; config = lib.mkIf config.swarselmodules.server.${serviceName} { + swarselmodules.server = { + podman = true; + postgresql = true; + }; nodes.${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; @@ -14505,6 +14768,10 @@ kanidm person credential create-reset-token }; config = lib.mkIf config.swarselmodules.server.${serviceName} { + swarselmodules.server = { + podman = true; + }; + nodes.${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; }; @@ -14626,113 +14893,117 @@ Deployment notes: - finally, disable new user registration in web ui #+begin_src nix-ts :tangle modules/nixos/server/slink.nix -{ self, lib, config, dns, globals, confLib, ... }: -let - inherit (confLib.gen { name = "slink"; port = 3000; dir = "/var/lib/slink"; }) servicePort serviceName serviceDomain serviceDir serviceAddress proxyAddress4 proxyAddress6 isHome isProxied homeProxy webProxy dnsServer homeProxyIf webProxyIf; + { self, lib, config, dns, globals, confLib, ... }: + let + inherit (confLib.gen { name = "slink"; port = 3000; dir = "/var/lib/slink"; }) servicePort serviceName serviceDomain serviceDir serviceAddress proxyAddress4 proxyAddress6 isHome isProxied homeProxy webProxy dnsServer homeProxyIf webProxyIf; - containerRev = "sha256:98b9442696f0a8cbc92f0447f54fa4bad227af5dcfd6680545fedab2ed28ddd9"; -in -{ - options = { - swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; - }; - config = lib.mkIf config.swarselmodules.server.${serviceName} { - - nodes.${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { - "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; + containerRev = "sha256:98b9442696f0a8cbc92f0447f54fa4bad227af5dcfd6680545fedab2ed28ddd9"; + in + { + options = { + swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; }; + config = lib.mkIf config.swarselmodules.server.${serviceName} { - virtualisation.oci-containers.containers.${serviceName} = { - image = "anirdev/slink@${containerRev}"; - environment = { - "ORIGIN" = "https://${serviceDomain}"; - "TZ" = config.repo.secrets.common.location.timezone; - "STORAGE_PROVIDER" = "local"; - "IMAGE_MAX_SIZE" = "50M"; - "USER_APPROVAL_REQUIRED" = "true"; + swarselmodules.server = { + podman = true; }; - ports = [ "${builtins.toString servicePort}:${builtins.toString servicePort}" ]; - volumes = [ - "${serviceDir}/var/data:/app/var/data" - "${serviceDir}/images:/app/slink/images" + + nodes.${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { + "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; + }; + + virtualisation.oci-containers.containers.${serviceName} = { + image = "anirdev/slink@${containerRev}"; + environment = { + "ORIGIN" = "https://${serviceDomain}"; + "TZ" = config.repo.secrets.common.location.timezone; + "STORAGE_PROVIDER" = "local"; + "IMAGE_MAX_SIZE" = "50M"; + "USER_APPROVAL_REQUIRED" = "true"; + }; + ports = [ "${builtins.toString servicePort}:${builtins.toString servicePort}" ]; + volumes = [ + "${serviceDir}/var/data:/app/var/data" + "${serviceDir}/images:/app/slink/images" + ]; + }; + + systemd.tmpfiles.settings."12-slink" = builtins.listToAttrs ( + map + (path: { + name = "${serviceDir}/${path}"; + value = { + d = { + group = "root"; + user = "root"; + mode = "0750"; + }; + }; + }) [ + "var/data" + "images" + ] + ); + + # networking.firewall.allowedTCPPorts = [ servicePort ]; + + environment.persistence."/persist".directories = lib.mkIf config.swarselsystems.isImpermanence [ + { directory = serviceDir; } ]; - }; - systemd.tmpfiles.settings."12-slink" = builtins.listToAttrs ( - map - (path: { - name = "${serviceDir}/${path}"; - value = { - d = { - group = "root"; - user = "root"; - mode = "0750"; - }; + topology.self.services.${serviceName} = { + name = lib.swarselsystems.toCapitalized serviceName; + info = "https://${serviceDomain}"; + icon = "${self}/files/topology-images/shlink.png"; + }; + + globals = { + networks = { + ${webProxyIf}.hosts = lib.mkIf isProxied { + ${config.node.name}.firewallRuleForNode.${webProxy}.allowedTCPPorts = [ servicePort ]; }; - }) [ - "var/data" - "images" - ] - ); - - # networking.firewall.allowedTCPPorts = [ servicePort ]; - - environment.persistence."/persist".directories = lib.mkIf config.swarselsystems.isImpermanence [ - { directory = serviceDir; } - ]; - - topology.self.services.${serviceName} = { - name = lib.swarselsystems.toCapitalized serviceName; - info = "https://${serviceDomain}"; - icon = "${self}/files/topology-images/shlink.png"; - }; - - globals = { - networks = { - ${webProxyIf}.hosts = lib.mkIf isProxied { - ${config.node.name}.firewallRuleForNode.${webProxy}.allowedTCPPorts = [ servicePort ]; - }; - ${homeProxyIf}.hosts = lib.mkIf isHome { - ${config.node.name}.firewallRuleForNode.${homeProxy}.allowedTCPPorts = [ servicePort ]; - }; - }; - services.${serviceName} = { - domain = serviceDomain; - inherit proxyAddress4 proxyAddress6 isHome; - }; - }; - - nodes.${webProxy}.services.nginx = { - upstreams = { - ${serviceName} = { - servers = { - "${serviceAddress}:${builtins.toString servicePort}" = { }; + ${homeProxyIf}.hosts = lib.mkIf isHome { + ${config.node.name}.firewallRuleForNode.${homeProxy}.allowedTCPPorts = [ servicePort ]; }; }; + services.${serviceName} = { + domain = serviceDomain; + inherit proxyAddress4 proxyAddress6 isHome; + }; }; - virtualHosts = { - "${serviceDomain}" = { - useACMEHost = globals.domains.main; - forceSSL = true; - acmeRoot = null; - oauth2.enable = true; - oauth2.allowedGroups = [ "slink_access" ]; - locations = { - "/" = { - proxyPass = "http://${serviceName}"; + nodes.${webProxy}.services.nginx = { + upstreams = { + ${serviceName} = { + servers = { + "${serviceAddress}:${builtins.toString servicePort}" = { }; }; - "/image" = { - proxyPass = "http://${serviceName}"; - setOauth2Headers = false; - bypassAuth = true; + }; + }; + virtualHosts = { + "${serviceDomain}" = { + useACMEHost = globals.domains.main; + + forceSSL = true; + acmeRoot = null; + oauth2.enable = true; + oauth2.allowedGroups = [ "slink_access" ]; + locations = { + "/" = { + proxyPass = "http://${serviceName}"; + }; + "/image" = { + proxyPass = "http://${serviceName}"; + setOauth2Headers = false; + bypassAuth = true; + }; }; }; }; }; }; - }; -} + } #+end_src **** Snipe-IT (currently unused) @@ -14823,7 +15094,7 @@ in :END: #+begin_src nix-ts :tangle modules/nixos/server/homebox.nix - { lib, pkgs, config, globals, dns, confLib, ... }: + { self, lib, pkgs, config, globals, dns, confLib, ... }: let inherit (confLib.gen { name = "homebox"; port = 7745; }) servicePort serviceName serviceDomain serviceAddress proxyAddress4 proxyAddress6 isHome isProxied homeProxy webProxy dnsServer homeProxyIf webProxyIf; in @@ -14835,7 +15106,11 @@ in "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; }; - topology.self.services.${serviceName}.info = "https://${serviceDomain}"; + topology.self.services.${serviceName} = { + name = "Homebox"; + info = "https://${serviceDomain}"; + icon = "${self}/files/topology-images/${serviceName}.png"; + }; globals = { networks = { @@ -14913,6 +15188,7 @@ in options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; config = lib.mkIf config.swarselmodules.server.${serviceName} { + services.${serviceName} = { enable = true; user = serviceUser; @@ -14957,7 +15233,7 @@ or 2) use classic path addressing =aws s3 cp s3:/// s3:/// s3:/// s3:/// s3:/// s3:/// s3:/// s3:///=64 bytes. + # head -c 64 /dev/urandom | base64 -w 0 > secrets/${secret} + # chmod 600 secrets/${secret} + # fi + # '') + # ); + # loadSecretEnvironment = + # component: + # let + # relevantSecrets = lib.subtractLists (builtins.attrNames cfg.${component}.settings) ( + # builtins.attrNames cfg.settingsSecret + # ); + # in + # lib.concatLines ( + # lib.forEach relevantSecrets ( + # secret: + # ''export ${secret}=$(< ${ + # if cfg.settingsSecret.${secret} == null then + # "secrets/${secret}" + # else + # "\"$CREDENTIALS_DIRECTORY/${secret}\"" + # })'' + # ) + # ); + # in + # { + # script = lib.mkForce '' + # mkdir -p "$TZDATA_DIR" - environment.persistence."/persist".directories = lib.mkIf config.swarselsystems.isImpermanence [ - { directory = serviceDir; mode = "0700"; } - ]; + # # Generate and load secrets + # ${generateSecrets} + # ${loadSecretEnvironment "domain"} - services.firezone = { - server = { - enable = true; - enableLocalDB = true; - - smtp = { - inherit (config.repo.secrets.local.firezone.mail) from username; - host = globals.services.mailserver.domain; - port = 465; - implicitTls = true; - passwordFile = config.sops.secrets.firezone-smtp-password.path; - }; - - provision = { - enable = true; - accounts.main = { - name = "Home"; - relayGroups.relays.name = "Relays"; - gatewayGroups.home.name = "Home"; - actors.admin = { - type = "account_admin_user"; - name = "Admin"; - email = "admin@${globals.domains.main}"; - }; - groups.anyone = { - name = "anyone"; - members = [ - "admin" - ]; - }; - - auth.oidc = - let - client_id = "firezone"; - in - { - name = "Kanidm"; - adapter = "openid_connect"; - adapter_config = { - scope = "openid email profile"; - response_type = "code"; - inherit client_id; - discovery_document_uri = "https://${globals.services.kanidm.domain}/oauth2/openid/${client_id}/.well-known/openid-configuration"; - clientSecretFile = config.sops.secrets.kanidm-firezone-client.path; - }; - }; - - resources = - lib.genAttrs homeDomains - (domain: { - type = "dns"; - name = domain; - address = domain; - gatewayGroups = [ "home" ]; - filters = [ - { protocol = "icmp"; } - { - protocol = "tcp"; - ports = [ - 443 - 80 - ]; - } - { - protocol = "udp"; - ports = [ 443 ]; - } - ]; - }) - // { - "home.vlan-services.v4" = { - type = "cidr"; - name = "home.vlan-services.v4"; - address = globals.networks.home-lan.vlans.services.cidrv4; - gatewayGroups = [ "home" ]; - }; - "home.vlan-services.v6" = { - type = "cidr"; - name = "home.vlan-services.v6"; - address = globals.networks.home-lan.vlans.services.cidrv6; - gatewayGroups = [ "home" ]; - }; - }; - - policies = - { } - // allow "everyone" "home.vlan-services.v4" - // allow "anyone" "home.vlan-services.v4" - // allow "everyone" "home.vlan-services.v6" - // allow "anyone" "home.vlan-services.v6" - // lib.mergeAttrsList (map (domain: allow "everyone" domain) homeDomains) - // lib.mergeAttrsList (map (domain: allow "anyone" domain) homeDomains); - }; - }; - - domain = { - settings.ERLANG_DISTRIBUTION_PORT = domainPort; - package = pkgs.dev.firezone-server-domain; - }; - api = { - externalUrl = "https://${serviceDomain}/api/"; - address = "0.0.0.0"; - port = apiPort; - package = pkgs.dev.firezone-server-api; - }; - web = { - externalUrl = "https://${serviceDomain}/"; - address = "0.0.0.0"; - port = webPort; - package = pkgs.dev.firezone-server-web; - }; - }; - - relay = { - enable = true; - port = relayPort; - inherit (config.node) name; - apiUrl = "wss://${serviceDomain}/api/"; - tokenFile = config.sops.secrets.firezone-relay-token.path; - publicIpv4 = proxyAddress4; - publicIpv6 = proxyAddress6; - openFirewall = lib.mkIf (!isProxied) true; - package = pkgs.dev.firezone-relay; - }; - }; - # systemd.services.firezone-initialize = - # let - # generateSecrets = - # let - # requiredSecrets = lib.filterAttrs (_: v: v == null) cfg.settingsSecret; - # in - # '' - # mkdir -p secrets - # chmod 700 secrets - # '' - # + lib.concatLines ( - # lib.forEach (builtins.attrNames requiredSecrets) (secret: '' - # if [[ ! -e secrets/${secret} ]]; then - # echo "Generating ${secret}" - # # Some secrets like TOKENS_KEY_BASE require a value >=64 bytes. - # head -c 64 /dev/urandom | base64 -w 0 > secrets/${secret} - # chmod 600 secrets/${secret} - # fi - # '') - # ); - # loadSecretEnvironment = - # component: - # let - # relevantSecrets = lib.subtractLists (builtins.attrNames cfg.${component}.settings) ( - # builtins.attrNames cfg.settingsSecret - # ); - # in - # lib.concatLines ( - # lib.forEach relevantSecrets ( - # secret: - # ''export ${secret}=$(< ${ - # if cfg.settingsSecret.${secret} == null then - # "secrets/${secret}" - # else - # "\"$CREDENTIALS_DIRECTORY/${secret}\"" - # })'' - # ) - # ); - # in - # { - # script = lib.mkForce '' - # mkdir -p "$TZDATA_DIR" - - # # Generate and load secrets - # ${generateSecrets} - # ${loadSecretEnvironment "domain"} - - # echo "Running migrations" - # ${lib.getExe cfg.domain.package} eval "Domain.Release.migrate(manual: true)" - # ''; - # }; + # echo "Running migrations" + # ${lib.getExe cfg.domain.package} eval "Domain.Release.migrate(manual: true)" + # ''; + # }; - nodes = { - ${homeProxy} = - let - nodeCfg = nodes.${homeProxy}.config; - nodePkgs = nodes.${homeProxy}.pkgs; - in - { - sops.secrets.firezone-gateway-token = { inherit (nodeCfg.swarselsystems) sopsFile; mode = "0400"; }; - networking.nftables = { - firewall = { - zones.firezone.interfaces = [ "tun-firezone" ]; - rules = { - # masquerade firezone traffic - masquerade-firezone = { - from = [ "firezone" ]; - to = [ "vlan-services" ]; - # masquerade = true; NOTE: custom rule below for ip4 + ip6 - late = true; # Only accept after any rejects have been processed - verdict = "accept"; - }; - # forward firezone traffic - forward-incoming-firezone-traffic = { - from = [ "firezone" ]; - to = [ "vlan-services" ]; - verdict = "accept"; - }; - - # FIXME: is this needed? conntrack should take care of it and we want to masquerade anyway - forward-outgoing-firezone-traffic = { - from = [ "vlan-services" ]; - to = [ "firezone" ]; - verdict = "accept"; - }; - }; - }; - chains.postrouting = { + nodes = { + ${homeProxy} = + let + nodeCfg = nodes.${homeProxy}.config; + nodePkgs = nodes.${homeProxy}.pkgs; + in + { + sops.secrets.firezone-gateway-token = { inherit (nodeCfg.swarselsystems) sopsFile; mode = "0400"; }; + networking.nftables = { + firewall = { + zones.firezone.interfaces = [ "tun-firezone" ]; + rules = { + # masquerade firezone traffic masquerade-firezone = { - after = [ "hook" ]; - late = true; - rules = - lib.forEach - [ - "firezone" + from = [ "firezone" ]; + to = [ "vlan-services" ]; + # masquerade = true; NOTE: custom rule below for ip4 + ip6 + late = true; # Only accept after any rejects have been processed + verdict = "accept"; + }; + # forward firezone traffic + forward-incoming-firezone-traffic = { + from = [ "firezone" ]; + to = [ "vlan-services" ]; + verdict = "accept"; + }; + + # FIXME: is this needed? conntrack should take care of it and we want to masquerade anyway + forward-outgoing-firezone-traffic = { + from = [ "vlan-services" ]; + to = [ "firezone" ]; + verdict = "accept"; + }; + }; + }; + chains.postrouting = { + masquerade-firezone = { + after = [ "hook" ]; + late = true; + rules = + lib.forEach + [ + "firezone" + ] + ( + zone: + lib.concatStringsSep " " [ + "meta protocol { ip, ip6 }" + (lib.head nodeCfg.networking.nftables.firewall.zones.${zone}.ingressExpression) + (lib.head nodeCfg.networking.nftables.firewall.zones.vlan-services.egressExpression) + "masquerade random" ] - ( - zone: - lib.concatStringsSep " " [ - "meta protocol { ip, ip6 }" - (lib.head nodeCfg.networking.nftables.firewall.zones.${zone}.ingressExpression) - (lib.head nodeCfg.networking.nftables.firewall.zones.vlan-services.egressExpression) - "masquerade random" - ] - ); - }; + ); }; }; - - boot.kernel.sysctl = { - "net.core.wmem_max" = 16777216; - "net.core.rmem_max" = 134217728; - }; - services.firezone.gateway = { - enable = true; - logLevel = "trace"; - inherit (nodeCfg.node) name; - apiUrl = "wss://${globals.services.firezone.domain}/api/"; - tokenFile = nodeCfg.sops.secrets.firezone-gateway-token.path; - package = nodePkgs.stable25_05.firezone-gateway; # newer versions of firezone-gateway are not compatible with server package - }; }; - ${idmServer} = - let - nodeCfg = nodes.${idmServer}.config; - accountId = "6b3c6ba7-5240-4684-95ce-f40fdae45096"; - externalId = "08d714e9-1ab9-4133-a39d-00e843a960cc"; - in - { - sops.secrets.kanidm-firezone = { inherit (nodeCfg.swarselsystems) sopsFile; owner = "kanidm"; group = "kanidm"; mode = "0440"; }; - services.kanidm.provision = { - groups."firezone.access" = { }; - systems.oauth2.firezone = { - displayName = "Firezone VPN"; - # NOTE: state: both uuids are runtime values - originUrl = [ - "https://${globals.services.firezone.domain}/${accountId}/sign_in/providers/${externalId}/handle_callback" - "https://${globals.services.firezone.domain}/${accountId}/settings/identity_providers/openid_connect/${externalId}/handle_callback" - ]; - originLanding = "https://${globals.services.firezone.domain}/"; - basicSecretFile = nodeCfg.sops.secrets.kanidm-firezone.path; - preferShortUsername = true; - scopeMaps."firezone.access" = [ - "openid" - "email" - "profile" - ]; - }; + boot.kernel.sysctl = { + "net.core.wmem_max" = 16777216; + "net.core.rmem_max" = 134217728; + }; + services.firezone.gateway = { + enable = true; + # logLevel = "trace"; + inherit (nodeCfg.node) name; + apiUrl = "wss://${globals.services.firezone.domain}/api/"; + tokenFile = nodeCfg.sops.secrets.firezone-gateway-token.path; + package = nodePkgs.stable25_05.firezone-gateway; # newer versions of firezone-gateway are not compatible with server package + }; + + topology.self.services."${serviceName}-gateway" = { + name = lib.swarselsystems.toCapitalized "${serviceName} Gateway"; + icon = "${self}/files/topology-images/${serviceName}.png"; + }; + }; + ${idmServer} = + let + nodeCfg = nodes.${idmServer}.config; + accountId = "6b3c6ba7-5240-4684-95ce-f40fdae45096"; + externalId = "08d714e9-1ab9-4133-a39d-00e843a960cc"; + in + { + sops.secrets.kanidm-firezone = { inherit (nodeCfg.swarselsystems) sopsFile; owner = "kanidm"; group = "kanidm"; mode = "0440"; }; + services.kanidm.provision = { + groups."firezone.access" = { }; + systems.oauth2.firezone = { + displayName = "Firezone VPN"; + # NOTE: state: both uuids are runtime values + originUrl = [ + "https://${globals.services.firezone.domain}/${accountId}/sign_in/providers/${externalId}/handle_callback" + "https://${globals.services.firezone.domain}/${accountId}/settings/identity_providers/openid_connect/${externalId}/handle_callback" + ]; + originLanding = "https://${globals.services.firezone.domain}/"; + basicSecretFile = nodeCfg.sops.secrets.kanidm-firezone.path; + preferShortUsername = true; + scopeMaps."firezone.access" = [ + "openid" + "email" + "profile" + ]; + }; + + }; + }; + ${webProxy} = { + services.nginx = { + upstreams = { + ${serviceName} = { + servers."${serviceAddress}:${builtins.toString webPort}" = { }; + }; + "${serviceName}-api" = { + servers."${serviceAddress}:${builtins.toString apiPort}" = { }; }; }; - ${webProxy} = { - services.nginx = { - upstreams = { - ${serviceName} = { - servers."${serviceAddress}:${builtins.toString webPort}" = { }; + virtualHosts = { + ${serviceDomain} = { + useACMEHost = globals.domains.main; + forceSSL = true; + acmeRoot = null; + locations."/" = { + # The trailing slash is important to strip the location prefix from the request + proxyPass = "http://${serviceName}/"; + proxyWebsockets = true; }; - "${serviceName}-api" = { - servers."${serviceAddress}:${builtins.toString apiPort}" = { }; - }; - }; - virtualHosts = { - ${serviceDomain} = { - useACMEHost = globals.domains.main; - forceSSL = true; - acmeRoot = null; - locations."/" = { - # The trailing slash is important to strip the location prefix from the request - proxyPass = "http://${serviceName}/"; - proxyWebsockets = true; - }; - locations."/api/" = { - # The trailing slash is important to strip the location prefix from the request - proxyPass = "http://${serviceName}-api/"; - proxyWebsockets = true; - }; + locations."/api/" = { + # The trailing slash is important to strip the location prefix from the request + proxyPass = "http://${serviceName}-api/"; + proxyWebsockets = true; }; }; }; }; }; - }; - } + + }; + } +#+end_src +**** Adguardhome +:PROPERTIES: +:CUSTOM_ID: h:ecb66cb8-12b5-44e8-ad6b-7848711e1ffe +:END: + + +#+begin_src nix-ts :tangle modules/nixos/server/adguardhome.nix + { self, inputs, lib, config, globals, dns, confLib, ... }: + let + inherit (confLib.gen { name = "adguardhome"; port = 3000; }) serviceName servicePort serviceAddress serviceDomain proxyAddress4 proxyAddress6; + inherit (confLib.static) isHome isProxied homeProxy homeProxyIf webProxy webProxyIf homeWebProxy dnsServer homeDnsServer homeServiceAddress nginxAccessRules; + + homeServices = lib.attrNames (lib.filterAttrs (_: serviceCfg: serviceCfg.isHome) globals.services); + homeDomains = map (name: globals.services.${name}.domain) homeServices; + in + { + options = { + swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; + }; + config = lib.mkIf config.swarselmodules.server.${serviceName} { + + + globals = { + networks = { + ${webProxyIf}.hosts = lib.mkIf isProxied { + ${config.node.name}.firewallRuleForNode.${webProxy}.allowedTCPPorts = [ servicePort ]; + }; + ${homeProxyIf}.hosts = lib.mkIf isHome { + ${config.node.name}.firewallRuleForNode.${homeProxy}.allowedTCPPorts = [ servicePort ]; + }; + }; + services.${serviceName} = { + domain = serviceDomain; + inherit proxyAddress4 proxyAddress6 isHome; + }; + }; + + networking.firewall = { + allowedTCPPorts = [ 53 ]; + allowedUDPPorts = [ 53 ]; + }; + + services.adguardhome = { + enable = true; + mutableSettings = false; + host = "0.0.0.0"; + port = servicePort; + settings = { + dns = { + bind_hosts = [ + globals.networks.home-lan.vlans.services.hosts.${homeDnsServer}.ipv4 + globals.networks.home-lan.vlans.services.hosts.${homeDnsServer}.ipv6 + ]; + ratelimit = 300; + upstream_dns = [ + "https://dns.cloudflare.com/dns-query" + "https://dns.google/dns-query" + "https://doh.mullvad.net/dns-query" + ]; + bootstrap_dns = [ + "1.1.1.1" + "2606:4700:4700::1111" + "8.8.8.8" + "2001:4860:4860::8844" + ]; + dhcp.enabled = false; + }; + filtering.rewrites = [ + ] + # Use the local mirror-proxy for some services (not necessary, just for speed) + ++ + map + (domain: { + inherit domain; + # FIXME: change to homeWebProxy once that is setup + answer = globals.networks.home-lan.vlans.services.hosts.${homeWebProxy}.ipv4; + # answer = globals.hosts.${webProxy}.wanAddress4; + }) + homeDomains; + filters = [ + { + name = "AdGuard DNS filter"; + url = "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt"; + enabled = true; + } + { + name = "AdAway Default Blocklist"; + url = "https://adaway.org/hosts.txt"; + enabled = true; + } + { + name = "OISD (Big)"; + url = "https://big.oisd.nl"; + enabled = true; + } + ]; + }; + }; + + environment.persistence."/persist".directories = lib.mkIf config.swarselsystems.isImpermanence [ + { + directory = "/var/lib/private/AdGuardHome"; + mode = "0700"; + } + ]; + + nodes = + let + genNginx = toAddress: extraConfig: { + upstreams = { + ${serviceName} = { + servers = { + "${toAddress}:${builtins.toString servicePort}" = { }; + }; + }; + }; + virtualHosts = { + "${serviceDomain}" = { + useACMEHost = globals.domains.main; + forceSSL = true; + acmeRoot = null; + oauth2 = { + enable = true; + allowedGroups = [ "adguardhome_access" ]; + }; + locations = { + "/" = { + proxyPass = "http://${serviceName}"; + proxyWebsockets = true; + }; + }; + extraConfig = lib.mkIf (extraConfig != "") extraConfig; + }; + }; + }; + in + { + ${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { + "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; + }; + ${webProxy}.services.nginx = genNginx serviceAddress ""; + ${homeWebProxy}.services.nginx = genNginx homeServiceAddress nginxAccessRules; + }; + }; + } #+end_src *** Darwin :PROPERTIES: @@ -17405,15 +17912,22 @@ Some standard options that should be set for every microvm host. #+begin_src nix-ts :tangle modules/nixos/optional/microvm-host.nix { config, lib, ... }: { - # imports = [ - # inputs.microvm.nixosModules.host - # ]; - config = lib.mkIf (config.guests != { }) { - microvm = { - hypervisor = lib.mkDefault "qemu"; - }; + systemd.tmpfiles.settings."15-microvms" = builtins.listToAttrs ( + map + (path: { + name = "${lib.optionalString config.swarselsystems.isImpermanence "/persist"}/microvms/${path}"; + value = { + d = { + group = "kvm"; + user = "microvm"; + mode = "0750"; + }; + }; + }) (builtins.attrNames config.guests) + ); + }; } #+end_src @@ -17423,37 +17937,81 @@ Some standard options that should be set for every microvm host. :CUSTOM_ID: h:46419b40-c40b-4b55-ac6f-a30169322bd6 :END: -Some standard options that should be set vor every microvm guest. We set the default +Some standard options that should be set for every microvm guest. We set the default #+begin_src nix-ts :tangle modules/nixos/optional/microvm-guest.nix - { self, inputs, ... }: - { - imports = [ - inputs.disko.nixosModules.disko - inputs.home-manager.nixosModules.home-manager - inputs.impermanence.nixosModules.impermanence - inputs.lanzaboote.nixosModules.lanzaboote - inputs.microvm.nixosModules.host - inputs.microvm.nixosModules.microvm - inputs.nix-index-database.nixosModules.nix-index - inputs.nix-minecraft.nixosModules.minecraft-servers - inputs.nix-topology.nixosModules.default - inputs.nswitch-rcm-nix.nixosModules.nswitch-rcm - inputs.simple-nixos-mailserver.nixosModules.default - inputs.sops.nixosModules.sops - inputs.stylix.nixosModules.stylix - inputs.swarsel-nix.nixosModules.default - inputs.nixos-nftables-firewall.nixosModules.default + { self, lib, config, inputs, microVMParent, nodes, ... }: + { + imports = [ + inputs.disko.nixosModules.disko + inputs.home-manager.nixosModules.home-manager + inputs.impermanence.nixosModules.impermanence + inputs.lanzaboote.nixosModules.lanzaboote + inputs.microvm.nixosModules.microvm + inputs.nix-index-database.nixosModules.nix-index + inputs.nix-minecraft.nixosModules.minecraft-servers + inputs.nix-topology.nixosModules.default + inputs.nswitch-rcm-nix.nixosModules.nswitch-rcm + inputs.simple-nixos-mailserver.nixosModules.default + inputs.sops.nixosModules.sops + inputs.stylix.nixosModules.stylix + inputs.swarsel-nix.nixosModules.default + inputs.nixos-nftables-firewall.nixosModules.default - (inputs.nixos-extra-modules + "/modules/interface-naming.nix") + (inputs.nixos-extra-modules + "/modules/interface-naming.nix") - "${self}/modules/shared/meta.nix" - ]; + "${self}/modules/shared/meta.nix" + ]; - config = { - system.stateVersion = "23.05"; - }; - } + config = { + _module.args.dns = inputs.dns; + + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; + systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug"; + # NOTE: this is needed, we dont import sevrer network module for microvms + globals.hosts.${config.node.name}.isHome = true; + + fileSystems."/persist".neededForBoot = lib.mkForce true; + + systemd.network.networks."10-vlan-services" = { + dhcpV6Config = { + WithoutRA = "solicit"; + # duid-en is nice in principle, but I already have MAC info anyways for reservations + DUIDType = "link-layer"; + }; + # networkConfig = { + # IPv6PrivacyExtensions = "no"; + # IPv6AcceptRA = false; + # }; + ipv6AcceptRAConfig = { + DHCPv6Client = "always"; + }; + }; + + microvm = { + shares = [ + { + tag = "persist"; + source = "${lib.optionalString nodes.${microVMParent}.config.swarselsystems.isImpermanence "/persist"}/microvms/${config.networking.hostName}"; + mountPoint = "/persist"; + proto = "virtiofs"; + } + ]; + # mount the writeable overlay so that we can use nix shells inside the microvm + volumes = [ + { + image = "/tmp/nix-store-overlay-${config.networking.hostName}.img"; + autoCreate = true; + mountPoint = config.microvm.writableStoreOverlay; + size = 1024; + } + ]; + }; + }; + } #+end_src @@ -17472,10 +18030,10 @@ This set of options enables the network of the system to be managed by =systemd- networking = { useDHCP = lib.mkForce false; useNetworkd = true; - dhcpcd.enable = false; - renameInterfacesByMac = lib.mapAttrs (_: v: if (v ? mac) then v.mac else "") ( + dhcpcd.enable = lib.mkIf (!config.swarselsystems.isMicroVM) false; + renameInterfacesByMac = lib.mkIf (!config.swarselsystems.isMicroVM) (lib.mapAttrs (_: v: if (v ? mac) then v.mac else "") ( config.repo.secrets.local.networking.networks or { } - ); + )); }; systemd.network.enable = true; @@ -17709,16 +18267,28 @@ A VLAN can also be used as the initrd network - this is however disabled for the Hold standard options for nix-topology per config #+begin_src nix-ts :tangle modules/nixos/optional/nix-topology-self.nix - { lib, config, globals, ... }: + { lib, config, globals, confLib, ... }: + let + inherit (confLib.static) webProxy; + in { topology.self = { icon = lib.mkIf config.swarselsystems.isCloud "devices.cloud-server"; - interfaces.wan = lib.mkIf config.swarselsystems.isCloud { }; - interfaces.wg = lib.mkIf (config.swarselsystems.server.wireguard.isClient || config.swarselsystems.server.wireguard.isServer) { - addresses = [ globals.networks.twothreetunnel-wg.hosts.${config.node.name}.ipv4 ]; - renderer.hidePhysicalConnections = true; - virtual = true; - type = "wireguard"; + interfaces = { + wan = lib.mkIf (config.swarselsystems.isCloud && config.swarselsystems.server.localNetwork == "wan") { }; + lan = lib.mkIf (config.swarselsystems.isCloud && config.swarselsystems.server.localNetwork == "lan") { }; + wgProxy = lib.mkIf (config.swarselsystems.server.wireguard ? wgHome) { + addresses = [ globals.networks."${webProxy}-wg.hosts".${config.node.name}.ipv4 ]; + renderer.hidePhysicalConnections = true; + virtual = true; + type = "wireguard"; + }; + wgHome = lib.mkIf (config.swarselsystems.server.wireguard ? wgHome) { + addresses = [ globals.networks.home-wgHome.hosts.${config.node.name}.ipv4 ]; + renderer.hidePhysicalConnections = true; + virtual = true; + type = "wireguard"; + }; }; }; } @@ -24895,29 +25465,29 @@ In short, the options defined here are passed to the modules systems using =_mod :END: #+begin_src nix-ts :noweb yes :tangle modules/shared/config-lib.nix { self, config, lib, globals, inputs, outputs, minimal, nixosConfig ? null, ... }: + let + domainDefault = service: config.repo.secrets.common.services.domains.${service}; + proxyDefault = config.swarselsystems.proxyHost; + + addressDefault = + if + config.swarselsystems.proxyHost != config.node.name + then + if + config.swarselsystems.server.wireguard.interfaces.wgProxy.isClient + then + globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgProxy.serverNetConfigPrefix}-wgProxy".hosts.${config.node.name}.ipv4 + else + globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4 + else + "localhost"; + in { _module.args = { confLib = rec { - - addressDefault = - if - config.swarselsystems.proxyHost != config.node.name - then - if - config.swarselsystems.server.wireguard.interfaces.wgProxy.isClient - then - globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgProxy.serverNetConfigPrefix}-wgProxy".hosts.${config.node.name}.ipv4 - else - globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4 - else - "localhost"; - - domainDefault = service: config.repo.secrets.common.services.domains.${service}; - proxyDefault = config.swarselsystems.proxyHost; - getConfig = if nixosConfig == null then config else nixosConfig; - gen = { name, user ? name, group ? name, dir ? null, port ? null, domain ? (domainDefault name), address ? addressDefault, proxy ? proxyDefault }: rec { + gen = { name ? "n/a", user ? name, group ? name, dir ? null, port ? null, domain ? (domainDefault name), address ? addressDefault, proxy ? proxyDefault }: rec { servicePort = port; serviceName = name; specificServiceName = "${name}-${config.node.name}"; @@ -24932,44 +25502,66 @@ In short, the options defined here are passed to the modules systems using =_mod proxyAddress4 = globals.hosts.${proxy}.wanAddress4 or null; proxyAddress6 = globals.hosts.${proxy}.wanAddress6 or null; inherit (globals.hosts.${config.node.name}) isHome; - inherit (globals.general) homeProxy webProxy dnsServer idmServer; + inherit (globals.general) homeProxy webProxy dnsServer homeDnsServer homeWebProxy idmServer; webProxyIf = "${webProxy}-wgProxy"; homeProxyIf = "home-wgHome"; isProxied = config.node.name != webProxy; }; - mkMicrovm = if config.swarselsystems.withMicroVMs then (guestName: { - ${guestName} = { - backend = "microvm"; - autostart = true; - modules = [ - (config.node.configDir + /guests/${guestName}.nix) - { - node.secretsDir = config.node.configDir + /secrets/${guestName}; - node.configDir = config.node.configDir + /guests/${guestName}; - networking.nftables.firewall = { - zones.untrusted.interfaces = lib.mkIf ( - lib.length config.guests.${guestName}.networking.links == 1 - ) config.guests.${guestName}.networking.links; + static = rec { + inherit (globals.hosts.${config.node.name}) isHome; + inherit (globals.general) homeProxy webProxy dnsServer homeDnsServer homeWebProxy idmServer oauthServer; + webProxyIf = "${webProxy}-wgProxy"; + homeProxyIf = "home-wgHome"; + isProxied = config.node.name != webProxy; + nginxAccessRules = '' + allow ${globals.networks.home-lan.vlans.home.cidrv4}; + allow ${globals.networks.home-lan.vlans.home.cidrv6}; + allow ${globals.networks.home-lan.vlans.services.hosts.${homeProxy}.ipv4}; + allow ${globals.networks.home-lan.vlans.services.hosts.${homeProxy}.ipv6}; + deny all; + ''; + homeServiceAddress = lib.optionalString (config.swarselsystems.server.wireguard.interfaces ? wgHome) globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgHome.serverNetConfigPrefix}-wgHome".hosts.${config.node.name}.ipv4; + }; + + mkMicrovm = + if config.swarselsystems.withMicroVMs then + (guestName: { + ${guestName} = { + backend = "microvm"; + autostart = true; + modules = [ + (config.node.configDir + /guests/${guestName}/default.nix) + { + node.secretsDir = config.node.configDir + /secrets/${guestName}; + node.configDir = config.node.configDir + /guests/${guestName}; + networking.nftables.firewall = { + zones.untrusted.interfaces = lib.mkIf + ( + lib.length config.guests.${guestName}.networking.links == 1 + ) + config.guests.${guestName}.networking.links; + }; + } + "${self}/modules/nixos/optional/microvm-guest.nix" + "${self}/modules/nixos/optional/systemd-networkd-base.nix" + ]; + microvm = { + system = config.node.arch; + baseMac = config.repo.secrets.local.networking.networks.lan.mac; + interfaces.vlan-services = { }; }; - } - "${self}/modules/nixos/optional/microvm-guest.nix" - ]; - microvm = { - system = config.node.arch; - baseMac = config.repo.secrets.local.networking.networks.lan.mac; - interfaces.vlan-services = { }; - }; - extraSpecialArgs = { - inherit (outputs) nodes; - inherit (inputs.self.pkgs.${config.node.arch}) lib; - inherit inputs outputs minimal; - inherit (inputs) self; - withHomeManager = false; - globals = outputs.globals.${config.node.arch}; - }; - }; - }) else (_: {_ = {};}); + extraSpecialArgs = { + inherit (outputs) nodes; + inherit (inputs.self.pkgs.${config.node.arch}) lib; + inherit inputs outputs minimal; + inherit (inputs) self; + withHomeManager = false; + microVMParent = config.node.name; + globals = outputs.globals.${config.node.arch}; + }; + }; + }) else (_: { _ = { }; }); }; }; @@ -27432,6 +28024,8 @@ Modules that need to be loaded on the NixOS level. Note that these will not be a general = lib.mkDefault true; packages = lib.mkDefault true; ssh = lib.mkDefault true; + wireguard = lib.mkDefault true; + dns-home = lib.mkDefault true; }; }; }; @@ -29851,7 +30445,7 @@ It supports all functions that I normally need. Note that getting completions fo (use-package nix-ts-mode :after lsp-mode - :mode "\\.nix\\'" + :mode ("\\.nix\\'" . "\\.nix\\.enc\\'") :ensure t :hook (nix-ts-mode . lsp-deferred) ;; So that envrc mode will work diff --git a/files/emacs/init.el b/files/emacs/init.el index 26d3439..52ffc4e 100644 --- a/files/emacs/init.el +++ b/files/emacs/init.el @@ -1117,7 +1117,7 @@ create a new one." (use-package nix-ts-mode :after lsp-mode - :mode "\\.nix\\'" + :mode ("\\.nix\\'" . "\\.nix\\.enc\\'") :ensure t :hook (nix-ts-mode . lsp-deferred) ;; So that envrc mode will work diff --git a/files/topology-images/Cisco_SG_200-08.png b/files/topology-images/Cisco_SG_200-08.png new file mode 100644 index 0000000..216fbfc Binary files /dev/null and b/files/topology-images/Cisco_SG_200-08.png differ diff --git a/files/topology-images/Fritz!Box_7682.png b/files/topology-images/Fritz!Box_7682.png new file mode 100644 index 0000000..84ed885 Binary files /dev/null and b/files/topology-images/Fritz!Box_7682.png differ diff --git a/files/topology-images/TL-SG108E.png b/files/topology-images/TL-SG108E.png new file mode 100644 index 0000000..6d3d57d Binary files /dev/null and b/files/topology-images/TL-SG108E.png differ diff --git a/files/topology-images/atlasos.png b/files/topology-images/atlasos.png new file mode 100644 index 0000000..c7c28a4 Binary files /dev/null and b/files/topology-images/atlasos.png differ diff --git a/files/topology-images/clamav.png b/files/topology-images/clamav.png new file mode 100644 index 0000000..8832dc8 Binary files /dev/null and b/files/topology-images/clamav.png differ diff --git a/files/topology-images/comfyui.png b/files/topology-images/comfyui.png new file mode 100644 index 0000000..88f1191 Binary files /dev/null and b/files/topology-images/comfyui.png differ diff --git a/files/topology-images/dgxos.png b/files/topology-images/dgxos.png new file mode 100644 index 0000000..d593fc3 Binary files /dev/null and b/files/topology-images/dgxos.png differ diff --git a/files/topology-images/dovecot.png b/files/topology-images/dovecot.png new file mode 100644 index 0000000..16e35fa Binary files /dev/null and b/files/topology-images/dovecot.png differ diff --git a/files/topology-images/firezone.png b/files/topology-images/firezone.png new file mode 100644 index 0000000..fbbbf67 Binary files /dev/null and b/files/topology-images/firezone.png differ diff --git a/files/topology-images/garage.png b/files/topology-images/garage.png new file mode 100644 index 0000000..50306cf Binary files /dev/null and b/files/topology-images/garage.png differ diff --git a/files/topology-images/home-manager.png b/files/topology-images/home-manager.png new file mode 100644 index 0000000..8ff9258 Binary files /dev/null and b/files/topology-images/home-manager.png differ diff --git a/files/topology-images/homebox.png b/files/topology-images/homebox.png new file mode 100644 index 0000000..c4728f9 Binary files /dev/null and b/files/topology-images/homebox.png differ diff --git a/files/topology-images/kea.png b/files/topology-images/kea.png new file mode 100644 index 0000000..9e68bcd Binary files /dev/null and b/files/topology-images/kea.png differ diff --git a/files/topology-images/minecraft.png b/files/topology-images/minecraft.png new file mode 100644 index 0000000..a9690b9 Binary files /dev/null and b/files/topology-images/minecraft.png differ diff --git a/files/topology-images/nintendo-switch.png b/files/topology-images/nintendo-switch.png index 21f8de3..b42d542 100644 Binary files a/files/topology-images/nintendo-switch.png and b/files/topology-images/nintendo-switch.png differ diff --git a/files/topology-images/nsd.png b/files/topology-images/nsd.png new file mode 100644 index 0000000..4a76c8f Binary files /dev/null and b/files/topology-images/nsd.png differ diff --git a/files/topology-images/ollama.png b/files/topology-images/ollama.png new file mode 100644 index 0000000..8c2d452 Binary files /dev/null and b/files/topology-images/ollama.png differ diff --git a/files/topology-images/openwebui.png b/files/topology-images/openwebui.png new file mode 100644 index 0000000..a158087 Binary files /dev/null and b/files/topology-images/openwebui.png differ diff --git a/files/topology-images/postfix.png b/files/topology-images/postfix.png new file mode 100644 index 0000000..c809b0f Binary files /dev/null and b/files/topology-images/postfix.png differ diff --git a/files/topology-images/roundcube.png b/files/topology-images/roundcube.png new file mode 100644 index 0000000..014dc92 Binary files /dev/null and b/files/topology-images/roundcube.png differ diff --git a/files/topology-images/rspamd.png b/files/topology-images/rspamd.png new file mode 100644 index 0000000..8bf4c12 Binary files /dev/null and b/files/topology-images/rspamd.png differ diff --git a/files/topology-images/sunshine.png b/files/topology-images/sunshine.png new file mode 100644 index 0000000..14c9b79 Binary files /dev/null and b/files/topology-images/sunshine.png differ diff --git a/files/topology-images/tp_link_tl-sg108e.jpg b/files/topology-images/tp_link_tl-sg108e.jpg new file mode 100644 index 0000000..ea8826c Binary files /dev/null and b/files/topology-images/tp_link_tl-sg108e.jpg differ diff --git a/files/topology-images/windows.png b/files/topology-images/windows.png new file mode 100644 index 0000000..c16d05f Binary files /dev/null and b/files/topology-images/windows.png differ diff --git a/flake.lock b/flake.lock index 44acb12..5731952 100644 --- a/flake.lock +++ b/flake.lock @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1728330715, - "narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=", + "lastModified": 1764011051, + "narHash": "sha256-M7SZyPZiqZUR/EiiBJnmyUbOi5oE/03tCeFrTiUZchI=", "owner": "numtide", "repo": "devshell", - "rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef", + "rev": "17ed8d9744ebe70424659b0ef74ad6d41fc87071", "type": "github" }, "original": { @@ -426,11 +426,11 @@ "flake-compat_3": { "flake": false, "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1761588595, + "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", "type": "github" }, "original": { @@ -688,11 +688,11 @@ "systems": "systems_3" }, "locked": { - "lastModified": 1726560853, - "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -1369,11 +1369,11 @@ "pre-commit-hooks": "pre-commit-hooks" }, "locked": { - "lastModified": 1762088663, - "narHash": "sha256-rpCvFan9Dji1Vw4HfVqYdfWesz5sKZE3uSgYR9gRreA=", + "lastModified": 1767198021, + "narHash": "sha256-O/7ZAy0OczYEy7zl+EegeekvRqb3JPh0btyBKtRvbVw=", "owner": "oddlama", "repo": "nix-topology", - "rev": "c15f569794a0f1a437850d0ac81675bcf23ca6cb", + "rev": "0c052d902678b592b957eac2c250e4030fe70ebc", "type": "github" }, "original": { @@ -1862,11 +1862,11 @@ }, "nixpkgs_12": { "locked": { - "lastModified": 1730531603, - "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", + "lastModified": 1766651565, + "narHash": "sha256-QEhk0eXgyIqTpJ/ehZKg9IKS7EtlWxF3N7DXy42zPfU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", + "rev": "3e2499d5539c16d0d173ba53552a4ff8547f4539", "type": "github" }, "original": { @@ -2574,18 +2574,14 @@ "nixpkgs": [ "nix-topology", "nixpkgs" - ], - "nixpkgs-stable": [ - "nix-topology", - "nixpkgs" ] }, "locked": { - "lastModified": 1730797577, - "narHash": "sha256-SrID5yVpyUfknUTGWgYkTyvdr9J1LxUym4om3SVGPkg=", + "lastModified": 1765911976, + "narHash": "sha256-t3T/xm8zstHRLx+pIHxVpQTiySbKqcQbK+r+01XVKc0=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "1864030ed24a2b8b4e4d386a5eeaf0c5369e50a9", + "rev": "b68b780b69702a090c8bb1b973bab13756cc7a27", "type": "github" }, "original": { diff --git a/hosts/nixos/aarch64-linux/belchsfactory/default.nix b/hosts/nixos/aarch64-linux/belchsfactory/default.nix index f024b3b..f44891b 100644 --- a/hosts/nixos/aarch64-linux/belchsfactory/default.nix +++ b/hosts/nixos/aarch64-linux/belchsfactory/default.nix @@ -61,7 +61,7 @@ postgresql = true; attic = true; garage = true; - hydra = false; + hydra = true; }; } diff --git a/hosts/nixos/aarch64-linux/liliputsteps/default.nix b/hosts/nixos/aarch64-linux/liliputsteps/default.nix index 4a4ead2..28083e9 100644 --- a/hosts/nixos/aarch64-linux/liliputsteps/default.nix +++ b/hosts/nixos/aarch64-linux/liliputsteps/default.nix @@ -1,4 +1,4 @@ -{ self, lib, minimal, ... }: +{ self, config, lib, minimal, ... }: { imports = [ ./hardware-configuration.nix @@ -10,6 +10,16 @@ topology.self = { icon = "devices.cloud-server"; + interfaces.ProxyJump = { + virtual = true; + physicalConnections = [ + (config.lib.topology.mkConnection "moonside" "lan") + (config.lib.topology.mkConnection "twothreetunnel" "lan") + (config.lib.topology.mkConnection "belchsfactory" "lan") + (config.lib.topology.mkConnection "stoicclub" "lan") + (config.lib.topology.mkConnection "eagleland" "wan") + ]; + }; }; swarselsystems = { diff --git a/hosts/nixos/aarch64-linux/stoicclub/default.nix b/hosts/nixos/aarch64-linux/stoicclub/default.nix index 01b40d4..38128a9 100644 --- a/hosts/nixos/aarch64-linux/stoicclub/default.nix +++ b/hosts/nixos/aarch64-linux/stoicclub/default.nix @@ -5,6 +5,7 @@ ./disk-config.nix "${self}/modules/nixos/optional/systemd-networkd-server.nix" + "${self}/modules/nixos/optional/nix-topology-self.nix" ]; topology.self = { diff --git a/hosts/nixos/aarch64-linux/twothreetunnel/default.nix b/hosts/nixos/aarch64-linux/twothreetunnel/default.nix index 0b33db2..2b16886 100644 --- a/hosts/nixos/aarch64-linux/twothreetunnel/default.nix +++ b/hosts/nixos/aarch64-linux/twothreetunnel/default.nix @@ -12,7 +12,10 @@ icon = "devices.cloud-server"; }; - globals.general.webProxy = config.node.name; + globals.general = { + webProxy = config.node.name; + oauthServer = config.node.name; + }; swarselsystems = { flakePath = "/root/.dotfiles"; @@ -35,6 +38,7 @@ "winters" "belchsfactory" "eagleland" + "hintbooth-adguardhome" ]; }; }; diff --git a/hosts/nixos/x86_64-linux/bakery/default.nix b/hosts/nixos/x86_64-linux/bakery/default.nix index fb971d6..f11512a 100644 --- a/hosts/nixos/x86_64-linux/bakery/default.nix +++ b/hosts/nixos/x86_64-linux/bakery/default.nix @@ -17,8 +17,8 @@ in ]; topology.self.interfaces = { - "eth1" = { }; - "wifi" = { }; + eth1.network = lib.mkForce "home"; + wifi = { }; }; swarselsystems = { diff --git a/hosts/nixos/x86_64-linux/hintbooth/default.nix b/hosts/nixos/x86_64-linux/hintbooth/default.nix index 20a6d6c..648be45 100644 --- a/hosts/nixos/x86_64-linux/hintbooth/default.nix +++ b/hosts/nixos/x86_64-linux/hintbooth/default.nix @@ -6,16 +6,15 @@ ./disk-config.nix "${self}/modules/nixos/optional/systemd-networkd-server-home.nix" + "${self}/modules/nixos/optional/microvm-host.nix" ]; topology.self = { interfaces = { - "eth1" = { }; - "eth2" = { }; - "eth3" = { }; - "eth4" = { }; - "eth5" = { }; - "eth6" = { }; + lan2.physicalConnections = [{ node = "summers"; interface = "eth1"; }]; + lan3.physicalConnections = [{ node = "summers"; interface = "eth2"; }]; + lan4.physicalConnections = [{ node = "switch-bedroom"; interface = "eth1"; }]; + lan5.physicalConnections = [{ node = "switch-livingroom"; interface = "eth1"; }]; }; }; @@ -45,6 +44,8 @@ isServer = true; peers = [ "winters" + "hintbooth-adguardhome" + "hintbooth-nginx" ]; }; }; @@ -67,6 +68,7 @@ guests = lib.mkIf (!minimal && config.swarselsystems.withMicroVMs) ( { } // confLib.mkMicrovm "adguardhome" + // confLib.mkMicrovm "nginx" ); } diff --git a/hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome.nix b/hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome.nix deleted file mode 100644 index 2a0d511..0000000 --- a/hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ self, lib, minimal, ... }: -{ - imports = [ - "${self}/profiles/nixos/microvm" - "${self}/modules/nixos" - ]; - - swarselsystems = { - isMicroVM = true; - }; - -} // lib.optionalAttrs (!minimal) { - - microvm = { - mem = 1024 * 1; - vcpu = 1; - }; - - swarselprofiles = { - microvm = true; - }; - -} diff --git a/hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome/default.nix b/hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome/default.nix new file mode 100644 index 0000000..b10f730 --- /dev/null +++ b/hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome/default.nix @@ -0,0 +1,43 @@ +{ self, config, lib, minimal, ... }: +{ + imports = [ + "${self}/profiles/nixos/microvm" + "${self}/modules/nixos" + ]; + + swarselsystems = { + isMicroVM = true; + isImpermanence = true; + proxyHost = "twothreetunnel"; + server = { + wireguard.interfaces = { + wgHome = { + isClient = true; + serverName = "hintbooth"; + }; + wgProxy = { + isClient = true; + serverName = "twothreetunnel"; + }; + }; + }; + }; + + globals.general.homeDnsServer = config.node.name; + +} // lib.optionalAttrs (!minimal) { + + microvm = { + mem = 1024 * 1; + vcpu = 1; + }; + + swarselprofiles = { + microvm = true; + }; + + swarselmodules.server = { + adguardhome = true; + }; + +} diff --git a/hosts/nixos/x86_64-linux/hintbooth/guests/nginx/default.nix b/hosts/nixos/x86_64-linux/hintbooth/guests/nginx/default.nix new file mode 100644 index 0000000..39656a1 --- /dev/null +++ b/hosts/nixos/x86_64-linux/hintbooth/guests/nginx/default.nix @@ -0,0 +1,60 @@ +{ self, config, lib, minimal, globals, confLib, ... }: +let + inherit (confLib.static) nginxAccessRules; +in +{ + imports = [ + "${self}/profiles/nixos/microvm" + "${self}/modules/nixos" + ]; + + swarselsystems = { + isMicroVM = true; + isImpermanence = true; + proxyHost = config.node.name; + server = { + wireguard.interfaces = { + wgHome = { + isClient = true; + serverName = "hintbooth"; + }; + }; + }; + }; + + globals.general.homeWebProxy = config.node.name; + +} // lib.optionalAttrs (!minimal) { + + microvm = { + mem = 3072 * 1; + vcpu = 1; + }; + + swarselprofiles = { + microvm = true; + }; + + swarselmodules.server = { + nginx = true; + }; + + services.nginx = { + upstreams.fritzbox = { + servers.${globals.networks.home-lan.hosts.fritzbox.ipv4} = { }; + }; + virtualHosts.${globals.services.fritzbox.domain} = { + useACMEHost = globals.domains.main; + forceSSL = true; + acmeRoot = null; + locations."/" = { + proxyPass = "http://fritzbox"; + proxyWebsockets = true; + }; + extraConfig = '' + proxy_ssl_verify off; + '' + nginxAccessRules; + }; + }; + +} diff --git a/hosts/nixos/x86_64-linux/hintbooth/secrets/adguardhome/secrets.yaml b/hosts/nixos/x86_64-linux/hintbooth/secrets/adguardhome/secrets.yaml new file mode 100644 index 0000000..ff54541 --- /dev/null +++ b/hosts/nixos/x86_64-linux/hintbooth/secrets/adguardhome/secrets.yaml @@ -0,0 +1,57 @@ +wireguard-private-key: ENC[AES256_GCM,data:5RdR6CvGBwaklSgiP0kmz/ShroIa1By7ZqgxKrnSGjHRyrzaeWGTuJmqKJM=,iv:D5UmcQkbRs8WVQUA8XpFCwLy8+O4+RoJLWOkHj0H7ss=,tag:feSuK9jW+wLeygqhKHycDw==,type:str] +sops: + age: + - recipient: age1wmx8y2hs83j2u5srdnfxljrzxm8jtxl6fr0mq7xf2ldxyglpzf2qq89rpx + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBMEM4alliWlBCT3VsbVA5 + OGt5bmQvZW1TaUNkbWtFdzVGNDNpY0hBOVhzCm84TldYNHBrU01HMlBkbGNwZFAw + WVk0T3FycVRHUUNtM1pTYkQ4Qmw3RTgKLS0tIE9LUlNEVjJHOGVIK1RSMmRXUDF6 + QlRKY1hRVzNTVXhESUd3OElXL2pBZXcKDWYoOzi2b4qeIbCVCfTj0lTW+OfbnsXB + 8MugCHu7+b+ju0v/lUP66jDW9/2AH4PzHtCNHjsafyzr2qnW8HlOzA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1c2enwel9un28dcs4wg0vcyamx9a4a6g3walkhu8w5lqhmd804paq9d24as + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJRWJXR2tYdEd4cTZsSi9l + Tm1pSC9pek5BakpEMlkwVTcrMlBuVzlXWUVrCmlnV0xJc25nL0twK3VCZ3FRK2x2 + RW52Q1NxWUhTUGY0NnQ0WEhLMWxIcFUKLS0tIG83eVM0KzdLQ004aDRKNTYvdmVZ + d3ZOSStBMFpSU2ZjNWhFRkREQWlUdmcKggVvLy1mLYGf8084RQtlipS4+z4dfPsN + HZfid0srwYnezlQ5qOY8/HrDLWHEyuZ4xFZVi4n0k49qBpNwJdmvyQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-01-02T04:14:03Z" + mac: ENC[AES256_GCM,data:aA+oIq31QBla9hOpApaMeP7MFl/hI0kDjC1QyPkmexXuMB2pQJ6bBEmazreX2m2TPtHv1rtVUak7F6TbA+97IFb9EQFuAREi1Ca0xjz2eGVFQKu94qkS/FNemXTAkEZxC9LQ1TRqNXXNITehKUeIN65epuNbWqo+iOW0OHEXm/w=,iv:1NKL2PZBUDyHEIiB2ZpvTdCh9ZO+r8bPyJo+EO1PBmQ=,tag:5W9owm1Z+7O1CGVmH1afUw==,type:str] + pgp: + - created_at: "2026-01-02T21:12:51Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAwDh3VI7VctTARAAmvkQ9V14f0BT/bNdFVZtTlY4yVon37CX32SZPUcHV7o8 + Dya0sZd9tuVATSv79TnybscuNx95fkoZJwujBfAadexn2zY8zl1oEWEHx7p+8/mE + W8JbQAjbcbX9sNQYXc8kYJylBThmgNN/HXK7CGtgDFr9xnGzDBnDm/M31P1HwYBm + IdIQgFGErEt1K3xvw28Lk3tPuZLK3Y+H2Yna7RRF6K1blGJUvEnL6yFdA10/eFW7 + 8066mO26F2l5xFuktK0nNeniLHKa5VVYp8iM+JMhX38l0wiIi8pGyxo3uAjNpa0w + IfpCneEBe/yyaUPcWMjXmUG5LJe3kWUup8cSzvu01Z3W159/QsflxIMkIsklqhim + B2zuPdAlYsjjS/05DIHInN2IIB/rjADkQvXji1XYLhWJj4jxDeck/UIc6Q22TED+ + autlbl8d/5sqyO5ghPpShF/s0vMTqUfpXZrDrbuyDFqCfwi0ahP03bUsv20ZEz6u + zG3K5HuXHh7ATSppwuMbcv7vcjF1tkbo6XhWZDv0rY0DFWqiYhnxWwlFlGLxf4zX + g6r7Ca/E/YXG/eOET6M9DxwHjj0D7u/ryAkCktqPL9w8oNGarZQ/xMx0+ocI3byc + Zvzlmd63BtgaGNSxH3stK29KN3ED8cDkG/JzAxCATWiUBBkqW/ga4sGZqtLlSO+F + AgwDC9FRLmchgYQBD/9JbFZie25PO2CyELlUWm5SmJcugT9SK/mIA2fe1PlA+Gnf + 5z9iXraMSQchz4R1IoiixDhubwKeKp/auqhlOPvo58Lsi6iDR/WaLWabD+hcyAb1 + ck/f/PUzTLhlLcfu18VPfXVzfnky3dX8P5aS0WMLAQblj2RaaiHxnPqf49kXSn3q + VSJ0pr0nEsPuWtoCkHUAwAJ8X5GPXN2OD4YbHsNaA9h2vrJAxNd5+HNsvg8JtI88 + X/uMM7cWcaXcmNZOz166HUIPcJ5cabJ48Sv8sDfMPOcTiJkMiESBnRYTwdUcp08m + nGipSrUeW3pVOC1bGyukZb6sF84pTtCpqS+kOSfKFlxFFdAEcpzFIPuOMeo2dbKj + GSGPDemZFC2yFq883yk9/mZbgjOUsqrj0ZP3rCD5ZHpfUM5IxGQ+mKaOucTXYmif + lrTPMYnAc7pHxKZ87BgiKBYrfRAZvorLYKv8zG8YagAUw8iCtc68YUUdvLW9haQf + rwWCU1z+sszYSac7I57gfqICQhMUbs1n9S2Cn0C0xo4q2Lu36ysip4rEVGg6TmUu + znXYu+3orodw2TwC0tGxXHYKwmlr7EGnBCbdVKpDoCbV6cYkDYoPUFg0alqIPd5r + KCkee9MaCLLX7IdBrbLf1lkHGwSAs81GfZRMLBauM7/hn+hMUeIJnMbtJnVIB9Je + AdT2nSH06+POnjvxa2t0dUasnG/6ISBRSk6FgBBZ+pdVlrvaB4javgWGpiAWCUu6 + b2CMZF3HullmLj+wwAKlsZsIOXGICN5GeQxLHYF8Kx7Doj68Owu/zGM5MS+7XQ== + =wYdb + -----END PGP MESSAGE----- + fp: 4BE7925262289B476DBBC17B76FD3810215AE097 + unencrypted_suffix: _unencrypted + version: 3.11.0 diff --git a/hosts/nixos/x86_64-linux/hintbooth/secrets/nginx/secrets.yaml b/hosts/nixos/x86_64-linux/hintbooth/secrets/nginx/secrets.yaml new file mode 100644 index 0000000..cc13dad --- /dev/null +++ b/hosts/nixos/x86_64-linux/hintbooth/secrets/nginx/secrets.yaml @@ -0,0 +1,57 @@ +wireguard-private-key: ENC[AES256_GCM,data:3T0ZoPAs/OIkhdZlH171d9d2Ycxtp4WfI92pTBI3vRw7BVvEgQZKu5DCvbA=,iv:gsczaGwcI3JocOazMIEsgHFruEKDPxOTUQzx+rdCaio=,tag:/Sw7QsZ4fV+BMWdfcUevBA==,type:str] +sops: + age: + - recipient: age1wmx8y2hs83j2u5srdnfxljrzxm8jtxl6fr0mq7xf2ldxyglpzf2qq89rpx + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBMEM4alliWlBCT3VsbVA5 + OGt5bmQvZW1TaUNkbWtFdzVGNDNpY0hBOVhzCm84TldYNHBrU01HMlBkbGNwZFAw + WVk0T3FycVRHUUNtM1pTYkQ4Qmw3RTgKLS0tIE9LUlNEVjJHOGVIK1RSMmRXUDF6 + QlRKY1hRVzNTVXhESUd3OElXL2pBZXcKDWYoOzi2b4qeIbCVCfTj0lTW+OfbnsXB + 8MugCHu7+b+ju0v/lUP66jDW9/2AH4PzHtCNHjsafyzr2qnW8HlOzA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1c2enwel9un28dcs4wg0vcyamx9a4a6g3walkhu8w5lqhmd804paq9d24as + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJRWJXR2tYdEd4cTZsSi9l + Tm1pSC9pek5BakpEMlkwVTcrMlBuVzlXWUVrCmlnV0xJc25nL0twK3VCZ3FRK2x2 + RW52Q1NxWUhTUGY0NnQ0WEhLMWxIcFUKLS0tIG83eVM0KzdLQ004aDRKNTYvdmVZ + d3ZOSStBMFpSU2ZjNWhFRkREQWlUdmcKggVvLy1mLYGf8084RQtlipS4+z4dfPsN + HZfid0srwYnezlQ5qOY8/HrDLWHEyuZ4xFZVi4n0k49qBpNwJdmvyQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-01-03T05:23:18Z" + mac: ENC[AES256_GCM,data:u9N7GzLPDW7cHT4mkUAC9Diq1RdV5iSwcz/fqzXQKRmic09eVydAgyk2g6NbJ+4tBbAjIfeUch8Bhf5eG0sGzeDkb1qWAMEnP8EPmQ64OdRyN2SxJgxkc8KFGxkrGz9slS2ozWth6q/tKBSsOYbo8WDlCqXhmYp+zBxvYFR30Mg=,iv:HC1e2i0E7dV9/au+A0kHd+UXDhw3xf7RbTpwJI+hjpY=,tag:dPCDh9qalNtbHIhs//cBpg==,type:str] + pgp: + - created_at: "2026-01-02T21:12:51Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAwDh3VI7VctTARAAmvkQ9V14f0BT/bNdFVZtTlY4yVon37CX32SZPUcHV7o8 + Dya0sZd9tuVATSv79TnybscuNx95fkoZJwujBfAadexn2zY8zl1oEWEHx7p+8/mE + W8JbQAjbcbX9sNQYXc8kYJylBThmgNN/HXK7CGtgDFr9xnGzDBnDm/M31P1HwYBm + IdIQgFGErEt1K3xvw28Lk3tPuZLK3Y+H2Yna7RRF6K1blGJUvEnL6yFdA10/eFW7 + 8066mO26F2l5xFuktK0nNeniLHKa5VVYp8iM+JMhX38l0wiIi8pGyxo3uAjNpa0w + IfpCneEBe/yyaUPcWMjXmUG5LJe3kWUup8cSzvu01Z3W159/QsflxIMkIsklqhim + B2zuPdAlYsjjS/05DIHInN2IIB/rjADkQvXji1XYLhWJj4jxDeck/UIc6Q22TED+ + autlbl8d/5sqyO5ghPpShF/s0vMTqUfpXZrDrbuyDFqCfwi0ahP03bUsv20ZEz6u + zG3K5HuXHh7ATSppwuMbcv7vcjF1tkbo6XhWZDv0rY0DFWqiYhnxWwlFlGLxf4zX + g6r7Ca/E/YXG/eOET6M9DxwHjj0D7u/ryAkCktqPL9w8oNGarZQ/xMx0+ocI3byc + Zvzlmd63BtgaGNSxH3stK29KN3ED8cDkG/JzAxCATWiUBBkqW/ga4sGZqtLlSO+F + AgwDC9FRLmchgYQBD/9JbFZie25PO2CyELlUWm5SmJcugT9SK/mIA2fe1PlA+Gnf + 5z9iXraMSQchz4R1IoiixDhubwKeKp/auqhlOPvo58Lsi6iDR/WaLWabD+hcyAb1 + ck/f/PUzTLhlLcfu18VPfXVzfnky3dX8P5aS0WMLAQblj2RaaiHxnPqf49kXSn3q + VSJ0pr0nEsPuWtoCkHUAwAJ8X5GPXN2OD4YbHsNaA9h2vrJAxNd5+HNsvg8JtI88 + X/uMM7cWcaXcmNZOz166HUIPcJ5cabJ48Sv8sDfMPOcTiJkMiESBnRYTwdUcp08m + nGipSrUeW3pVOC1bGyukZb6sF84pTtCpqS+kOSfKFlxFFdAEcpzFIPuOMeo2dbKj + GSGPDemZFC2yFq883yk9/mZbgjOUsqrj0ZP3rCD5ZHpfUM5IxGQ+mKaOucTXYmif + lrTPMYnAc7pHxKZ87BgiKBYrfRAZvorLYKv8zG8YagAUw8iCtc68YUUdvLW9haQf + rwWCU1z+sszYSac7I57gfqICQhMUbs1n9S2Cn0C0xo4q2Lu36ysip4rEVGg6TmUu + znXYu+3orodw2TwC0tGxXHYKwmlr7EGnBCbdVKpDoCbV6cYkDYoPUFg0alqIPd5r + KCkee9MaCLLX7IdBrbLf1lkHGwSAs81GfZRMLBauM7/hn+hMUeIJnMbtJnVIB9Je + AdT2nSH06+POnjvxa2t0dUasnG/6ISBRSk6FgBBZ+pdVlrvaB4javgWGpiAWCUu6 + b2CMZF3HullmLj+wwAKlsZsIOXGICN5GeQxLHYF8Kx7Doj68Owu/zGM5MS+7XQ== + =wYdb + -----END PGP MESSAGE----- + fp: 4BE7925262289B476DBBC17B76FD3810215AE097 + unencrypted_suffix: _unencrypted + version: 3.11.0 diff --git a/hosts/nixos/x86_64-linux/pyramid/default.nix b/hosts/nixos/x86_64-linux/pyramid/default.nix index 2884de5..54b80c5 100644 --- a/hosts/nixos/x86_64-linux/pyramid/default.nix +++ b/hosts/nixos/x86_64-linux/pyramid/default.nix @@ -23,9 +23,9 @@ in topology.self = { interfaces = { - "eth1" = { }; - "wifi" = { }; - "fritz-wg" = { }; + eth1.network = lib.mkForce "home"; + wifi = { }; + fritz-wg.network = "fritz-wg"; }; }; diff --git a/hosts/nixos/x86_64-linux/winters/secrets/pii.nix.enc b/hosts/nixos/x86_64-linux/winters/secrets/pii.nix.enc index 8256be6..dc6fd8a 100644 --- a/hosts/nixos/x86_64-linux/winters/secrets/pii.nix.enc +++ b/hosts/nixos/x86_64-linux/winters/secrets/pii.nix.enc @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data: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,iv:Wc2rOI9aWgchjFGCl5R8d6E6GmYEKCIkIAZlUIlbE/4=,tag:3p301gA9WrBjwcpXs68ayg==,type:str]", + "data": "ENC[AES256_GCM,data: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,iv:kkH/Hy/0PNzkVdTfYTgKBAN6nYslP0OFIndsmORZVEg=,tag:j/fMiT9DCog0CHnM74MNMw==,type:str]", "sops": { "age": [ { @@ -7,8 +7,8 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3UFZTaXFNdjF2UmRFd3VL\nY2pZZ3ZaRkhZSjdVUjIraHV5ZlNaNGtwM3k0CkZ4OVRFcmR3MFBDcmdsbWFId3Iy\nVzQyUGI1eG44d3JFL2NvZEg4NnduT2cKLS0tIEdhOEZETk9nRTlVbmJ5UW9GalVx\nS00yaUpJZVFVNThFei8yRzJYejRkYk0Kf6Z8WnG8phRtFIUWIPys3PW0OImhAcF+\nUFLuL4Qr7zWaeItCRieYCs1yBn7KbUJHZNkJcvnkYW50NYvlEa8wBw==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2025-12-31T12:22:14Z", - "mac": "ENC[AES256_GCM,data:H17OWQwkZaugzTuMM8kBPZLYZs/poaLJt8osoY/gzC2CMpWXUtWpwgJ83CO7GkiPrPN2SZtEiaADP3PvZZqVcV5rDJNhdELmdvZfB14RQDUD9rYfnIX5uuzMMII+kguTkk+Zd1IRWv+MN9y4cdhys0lYJ7Nw1RyEMP9Bxd1zvcA=,iv:01Yode7T/2pUP1dFLyIUoDIfeWRWKf1Qq7pHvUDKQJQ=,tag:Ldxq5cRB2iexLhIrBfqGVQ==,type:str]", + "lastmodified": "2026-01-02T22:52:45Z", + "mac": "ENC[AES256_GCM,data:p/m76sd+5HhD+tz7oSnoSzVRCnB1czTUTF90LSyLQuL6aVyTpVZp+p6/CnYc/fG+L/8wBUsLrwwajl22S2+MZAqvQFoYQwY/AiFb10wZNK2fzPEURW3P+QYzaf62nb4G3GlckjAcGxGyeGcU4TnL1qZEDgp/KcdZpsUwvVQvV/U=,iv:k7m4dOr13gczZTGlz7uHIQB/uFPEQJX19uHuLB1fupg=,tag:mzpbLMV5aun7IOvPIJv0ng==,type:str]", "pgp": [ { "created_at": "2025-12-02T14:59:33Z", diff --git a/modules/nixos/common/impermanence.nix b/modules/nixos/common/impermanence.nix index e111c86..2e9b437 100644 --- a/modules/nixos/common/impermanence.nix +++ b/modules/nixos/common/impermanence.nix @@ -1,7 +1,7 @@ { config, lib, ... }: let mapperTarget = lib.swarselsystems.mkIfElse config.swarselsystems.isCrypted "/dev/mapper/cryptroot" "/dev/disk/by-label/nixos"; - inherit (config.swarselsystems) isImpermanence isCrypted; + inherit (config.swarselsystems) isImpermanence isCrypted isBtrfs; in { options.swarselmodules.impermanence = lib.mkEnableOption "impermanence config"; @@ -17,7 +17,7 @@ in # So if it doesn't run, the btrfs system effectively acts like a normal system # Taken from https://github.com/NotAShelf/nyx/blob/2a8273ed3f11a4b4ca027a68405d9eb35eba567b/modules/core/common/system/impermanence/default.nix boot.tmp.useTmpfs = lib.mkIf (!isImpermanence) true; - boot.initrd.systemd = lib.mkIf isImpermanence { + boot.initrd.systemd = lib.mkIf (isImpermanence && isBtrfs) { enable = true; services.rollback = { description = "Rollback BTRFS root subvolume to a pristine state"; diff --git a/modules/nixos/common/nodes.nix b/modules/nixos/common/nodes.nix index 236354d..daa270c 100644 --- a/modules/nixos/common/nodes.nix +++ b/modules/nixos/common/nodes.nix @@ -33,6 +33,7 @@ let (splitPath "services.kanidm.provision.systems.oauth2") (splitPath "sops.secrets") (splitPath "swarselsystems.server.dns") + (splitPath "topology.self.services") ] ++ expandOptions (splitPath "networking.nftables.firewall") [ "zones" "rules" ] ++ expandOptions (splitPath "services.firezone.gateway") [ "enable" "name" "apiUrl" "tokenFile" "package" "logLevel" ] diff --git a/modules/nixos/optional/microvm-guest.nix b/modules/nixos/optional/microvm-guest.nix index adf069f..21c29ce 100644 --- a/modules/nixos/optional/microvm-guest.nix +++ b/modules/nixos/optional/microvm-guest.nix @@ -1,11 +1,10 @@ -{ self, inputs, ... }: +{ self, lib, config, inputs, microVMParent, nodes, ... }: { imports = [ inputs.disko.nixosModules.disko inputs.home-manager.nixosModules.home-manager inputs.impermanence.nixosModules.impermanence inputs.lanzaboote.nixosModules.lanzaboote - inputs.microvm.nixosModules.host inputs.microvm.nixosModules.microvm inputs.nix-index-database.nixosModules.nix-index inputs.nix-minecraft.nixosModules.minecraft-servers @@ -23,6 +22,51 @@ ]; config = { - system.stateVersion = "23.05"; + _module.args.dns = inputs.dns; + + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; + systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug"; + # NOTE: this is needed, we dont import sevrer network module for microvms + globals.hosts.${config.node.name}.isHome = true; + + fileSystems."/persist".neededForBoot = lib.mkForce true; + + systemd.network.networks."10-vlan-services" = { + dhcpV6Config = { + WithoutRA = "solicit"; + # duid-en is nice in principle, but I already have MAC info anyways for reservations + DUIDType = "link-layer"; + }; + # networkConfig = { + # IPv6PrivacyExtensions = "no"; + # IPv6AcceptRA = false; + # }; + ipv6AcceptRAConfig = { + DHCPv6Client = "always"; + }; + }; + + microvm = { + shares = [ + { + tag = "persist"; + source = "${lib.optionalString nodes.${microVMParent}.config.swarselsystems.isImpermanence "/persist"}/microvms/${config.networking.hostName}"; + mountPoint = "/persist"; + proto = "virtiofs"; + } + ]; + # mount the writeable overlay so that we can use nix shells inside the microvm + volumes = [ + { + image = "/tmp/nix-store-overlay-${config.networking.hostName}.img"; + autoCreate = true; + mountPoint = config.microvm.writableStoreOverlay; + size = 1024; + } + ]; + }; }; } diff --git a/modules/nixos/optional/microvm-host.nix b/modules/nixos/optional/microvm-host.nix index 2948824..073353c 100644 --- a/modules/nixos/optional/microvm-host.nix +++ b/modules/nixos/optional/microvm-host.nix @@ -1,13 +1,21 @@ { config, lib, ... }: { - # imports = [ - # inputs.microvm.nixosModules.host - # ]; - config = lib.mkIf (config.guests != { }) { - microvm = { - hypervisor = lib.mkDefault "qemu"; - }; + systemd.tmpfiles.settings."15-microvms" = builtins.listToAttrs ( + map + (path: { + name = "${lib.optionalString config.swarselsystems.isImpermanence "/persist"}/microvms/${path}"; + value = { + d = { + group = "kvm"; + user = "microvm"; + mode = "0750"; + }; + }; + }) + (builtins.attrNames config.guests) + ); + }; } diff --git a/modules/nixos/optional/nix-topology-self.nix b/modules/nixos/optional/nix-topology-self.nix index 66299f0..e713893 100644 --- a/modules/nixos/optional/nix-topology-self.nix +++ b/modules/nixos/optional/nix-topology-self.nix @@ -1,13 +1,25 @@ -{ lib, config, globals, ... }: +{ lib, config, globals, confLib, ... }: +let + inherit (confLib.static) webProxy; +in { topology.self = { icon = lib.mkIf config.swarselsystems.isCloud "devices.cloud-server"; - interfaces.wan = lib.mkIf config.swarselsystems.isCloud { }; - interfaces.wg = lib.mkIf (config.swarselsystems.server.wireguard.isClient || config.swarselsystems.server.wireguard.isServer) { - addresses = [ globals.networks.twothreetunnel-wg.hosts.${config.node.name}.ipv4 ]; - renderer.hidePhysicalConnections = true; - virtual = true; - type = "wireguard"; + interfaces = { + wan = lib.mkIf (config.swarselsystems.isCloud && config.swarselsystems.server.localNetwork == "wan") { }; + lan = lib.mkIf (config.swarselsystems.isCloud && config.swarselsystems.server.localNetwork == "lan") { }; + wgProxy = lib.mkIf (config.swarselsystems.server.wireguard ? wgHome) { + addresses = [ globals.networks."${webProxy}-wg.hosts".${config.node.name}.ipv4 ]; + renderer.hidePhysicalConnections = true; + virtual = true; + type = "wireguard"; + }; + wgHome = lib.mkIf (config.swarselsystems.server.wireguard ? wgHome) { + addresses = [ globals.networks.home-wgHome.hosts.${config.node.name}.ipv4 ]; + renderer.hidePhysicalConnections = true; + virtual = true; + type = "wireguard"; + }; }; }; } diff --git a/modules/nixos/optional/systemd-networkd-base.nix b/modules/nixos/optional/systemd-networkd-base.nix index 5081e69..238a1ff 100644 --- a/modules/nixos/optional/systemd-networkd-base.nix +++ b/modules/nixos/optional/systemd-networkd-base.nix @@ -3,10 +3,10 @@ networking = { useDHCP = lib.mkForce false; useNetworkd = true; - dhcpcd.enable = false; - renameInterfacesByMac = lib.mapAttrs (_: v: if (v ? mac) then v.mac else "") ( + dhcpcd.enable = lib.mkIf (!config.swarselsystems.isMicroVM) false; + renameInterfacesByMac = lib.mkIf (!config.swarselsystems.isMicroVM) (lib.mapAttrs (_: v: if (v ? mac) then v.mac else "") ( config.repo.secrets.local.networking.networks or { } - ); + )); }; systemd.network.enable = true; diff --git a/modules/nixos/server/adguardhome.nix b/modules/nixos/server/adguardhome.nix new file mode 100644 index 0000000..f5b6262 --- /dev/null +++ b/modules/nixos/server/adguardhome.nix @@ -0,0 +1,138 @@ +{ self, inputs, lib, config, globals, dns, confLib, ... }: +let + inherit (confLib.gen { name = "adguardhome"; port = 3000; }) serviceName servicePort serviceAddress serviceDomain proxyAddress4 proxyAddress6; + inherit (confLib.static) isHome isProxied homeProxy homeProxyIf webProxy webProxyIf homeWebProxy dnsServer homeDnsServer homeServiceAddress nginxAccessRules; + + homeServices = lib.attrNames (lib.filterAttrs (_: serviceCfg: serviceCfg.isHome) globals.services); + homeDomains = map (name: globals.services.${name}.domain) homeServices; +in +{ + options = { + swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; + }; + config = lib.mkIf config.swarselmodules.server.${serviceName} { + + + globals = { + networks = { + ${webProxyIf}.hosts = lib.mkIf isProxied { + ${config.node.name}.firewallRuleForNode.${webProxy}.allowedTCPPorts = [ servicePort ]; + }; + ${homeProxyIf}.hosts = lib.mkIf isHome { + ${config.node.name}.firewallRuleForNode.${homeProxy}.allowedTCPPorts = [ servicePort ]; + }; + }; + services.${serviceName} = { + domain = serviceDomain; + inherit proxyAddress4 proxyAddress6 isHome; + }; + }; + + networking.firewall = { + allowedTCPPorts = [ 53 ]; + allowedUDPPorts = [ 53 ]; + }; + + services.adguardhome = { + enable = true; + mutableSettings = false; + host = "0.0.0.0"; + port = servicePort; + settings = { + dns = { + bind_hosts = [ + globals.networks.home-lan.vlans.services.hosts.${homeDnsServer}.ipv4 + globals.networks.home-lan.vlans.services.hosts.${homeDnsServer}.ipv6 + ]; + ratelimit = 300; + upstream_dns = [ + "https://dns.cloudflare.com/dns-query" + "https://dns.google/dns-query" + "https://doh.mullvad.net/dns-query" + ]; + bootstrap_dns = [ + "1.1.1.1" + "2606:4700:4700::1111" + "8.8.8.8" + "2001:4860:4860::8844" + ]; + dhcp.enabled = false; + }; + filtering.rewrites = [ + ] + # Use the local mirror-proxy for some services (not necessary, just for speed) + ++ + map + (domain: { + inherit domain; + # FIXME: change to homeWebProxy once that is setup + answer = globals.networks.home-lan.vlans.services.hosts.${homeWebProxy}.ipv4; + # answer = globals.hosts.${webProxy}.wanAddress4; + }) + homeDomains; + filters = [ + { + name = "AdGuard DNS filter"; + url = "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt"; + enabled = true; + } + { + name = "AdAway Default Blocklist"; + url = "https://adaway.org/hosts.txt"; + enabled = true; + } + { + name = "OISD (Big)"; + url = "https://big.oisd.nl"; + enabled = true; + } + ]; + }; + }; + + environment.persistence."/persist".directories = lib.mkIf config.swarselsystems.isImpermanence [ + { + directory = "/var/lib/private/AdGuardHome"; + mode = "0700"; + } + ]; + + nodes = + let + genNginx = toAddress: extraConfig: { + upstreams = { + ${serviceName} = { + servers = { + "${toAddress}:${builtins.toString servicePort}" = { }; + }; + }; + }; + virtualHosts = { + "${serviceDomain}" = { + useACMEHost = globals.domains.main; + forceSSL = true; + acmeRoot = null; + oauth2 = { + enable = true; + allowedGroups = [ "adguardhome_access" ]; + }; + locations = { + "/" = { + proxyPass = "http://${serviceName}"; + proxyWebsockets = true; + }; + }; + extraConfig = lib.mkIf (extraConfig != "") extraConfig; + }; + }; + }; + in + { + ${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { + "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; + }; + ${webProxy}.services.nginx = genNginx serviceAddress ""; + ${homeWebProxy}.services.nginx = genNginx homeServiceAddress nginxAccessRules; + }; + }; +} diff --git a/modules/nixos/server/attic.nix b/modules/nixos/server/attic.nix index e278ed6..3aeb11e 100644 --- a/modules/nixos/server/attic.nix +++ b/modules/nixos/server/attic.nix @@ -14,6 +14,12 @@ in "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; }; + topology.self.services.${serviceName} = { + name = lib.swarselsystems.toCapitalized serviceName; + info = "https://${serviceDomain}"; + # attic does not have a logo + }; + globals = { networks = { ${webProxyIf}.hosts = lib.mkIf isProxied { diff --git a/modules/nixos/server/dns-home.nix b/modules/nixos/server/dns-home.nix new file mode 100644 index 0000000..abb3f5a --- /dev/null +++ b/modules/nixos/server/dns-home.nix @@ -0,0 +1,16 @@ +{ lib, config, globals, confLib, ... }: +let + inherit (confLib.gen { name = "dns-home"; }) serviceName homeProxy; +in +{ + options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; + config = lib.mkIf (config.swarselmodules.server.${serviceName}) { + + networking.hosts = { + ${globals.networks.home-lan.vlans.services.hosts.${homeProxy}.ipv4} = [ "server.${homeProxy}.${globals.domains.main}" ]; + ${globals.networks.home-lan.vlans.services.hosts.${homeProxy}.ipv6} = [ "server.${homeProxy}.${globals.domains.main}" ]; + }; + + }; + +} diff --git a/modules/nixos/server/firezone.nix b/modules/nixos/server/firezone.nix index eb0f546..26addfc 100644 --- a/modules/nixos/server/firezone.nix +++ b/modules/nixos/server/firezone.nix @@ -1,4 +1,4 @@ -{ lib, pkgs, config, globals, confLib, dns, nodes, ... }: +{ self, lib, pkgs, config, globals, confLib, dns, nodes, ... }: let inherit (confLib.gen { name = "firezone"; dir = "/var/lib/private/firezone"; }) serviceName serviceDir serviceAddress serviceDomain proxyAddress4 proxyAddress6 isHome isProxied homeProxy webProxy homeProxyIf webProxyIf idmServer dnsServer; inherit (config.swarselsystems) sopsFile; @@ -60,6 +60,12 @@ in }; }; + topology.self.services.${serviceName} = { + name = lib.swarselsystems.toCapitalized serviceName; + info = "https://${serviceDomain}"; + icon = "${self}/files/topology-images/${serviceName}.png"; + }; + sops = { secrets = { kanidm-firezone-client = { inherit sopsFile; mode = "0400"; }; @@ -314,12 +320,17 @@ in }; services.firezone.gateway = { enable = true; - logLevel = "trace"; + # logLevel = "trace"; inherit (nodeCfg.node) name; apiUrl = "wss://${globals.services.firezone.domain}/api/"; tokenFile = nodeCfg.sops.secrets.firezone-gateway-token.path; package = nodePkgs.stable25_05.firezone-gateway; # newer versions of firezone-gateway are not compatible with server package }; + + topology.self.services."${serviceName}-gateway" = { + name = lib.swarselsystems.toCapitalized "${serviceName} Gateway"; + icon = "${self}/files/topology-images/${serviceName}.png"; + }; }; ${idmServer} = let diff --git a/modules/nixos/server/garage.nix b/modules/nixos/server/garage.nix index d180487..de46446 100644 --- a/modules/nixos/server/garage.nix +++ b/modules/nixos/server/garage.nix @@ -1,5 +1,5 @@ # inspired by https://github.com/atropos112/nixos/blob/7fef652006a1c939f4caf9c8a0cb0892d9cdfe21/modules/garage.nix -{ lib, pkgs, config, globals, dns, confLib, ... }: +{ self, lib, pkgs, config, globals, dns, confLib, ... }: let inherit (confLib.gen { name = "garage"; @@ -81,6 +81,12 @@ in "*.${subDomain}-web" = dns.lib.combinators.host proxyAddress4 proxyAddress6; }; + topology.self.services.${serviceName} = { + name = lib.swarselsystems.toCapitalized serviceName; + info = "https://${serviceDomain}"; + icon = "${self}/files/topology-images/${serviceName}.png"; + }; + sops = { secrets.garage-admin-token = { inherit sopsFile; }; secrets.garage-rpc-secret = { inherit sopsFile; }; diff --git a/modules/nixos/server/homebox.nix b/modules/nixos/server/homebox.nix index 5dba937..05fd201 100644 --- a/modules/nixos/server/homebox.nix +++ b/modules/nixos/server/homebox.nix @@ -1,4 +1,4 @@ -{ lib, pkgs, config, globals, dns, confLib, ... }: +{ self, lib, pkgs, config, globals, dns, confLib, ... }: let inherit (confLib.gen { name = "homebox"; port = 7745; }) servicePort serviceName serviceDomain serviceAddress proxyAddress4 proxyAddress6 isHome isProxied homeProxy webProxy dnsServer homeProxyIf webProxyIf; in @@ -10,7 +10,11 @@ in "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; }; - topology.self.services.${serviceName}.info = "https://${serviceDomain}"; + topology.self.services.${serviceName} = { + name = "Homebox"; + info = "https://${serviceDomain}"; + icon = "${self}/files/topology-images/${serviceName}.png"; + }; globals = { networks = { diff --git a/modules/nixos/server/hydra.nix b/modules/nixos/server/hydra.nix index 9227117..9798ff8 100644 --- a/modules/nixos/server/hydra.nix +++ b/modules/nixos/server/hydra.nix @@ -13,6 +13,8 @@ in "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; }; + topology.self.services.${serviceName}.info = "https://${serviceDomain}"; + globals = { networks = { ${webProxyIf}.hosts = lib.mkIf isProxied { diff --git a/modules/nixos/server/kanidm.nix b/modules/nixos/server/kanidm.nix index 339da48..da583f7 100644 --- a/modules/nixos/server/kanidm.nix +++ b/modules/nixos/server/kanidm.nix @@ -228,6 +228,7 @@ in "radicale.access" = { }; "slink.access" = { }; "opkssh.access" = { }; + "adguardhome.access" = { }; }; inherit (config.repo.secrets.local) persons; @@ -370,6 +371,11 @@ in "email" "profile" ]; + "adguardhome.access" = [ + "openid" + "email" + "profile" + ]; }; preferShortUsername = true; claimMaps.groups = { @@ -380,6 +386,7 @@ in "firefly.access" = [ "firefly_access" ]; "radicale.access" = [ "radicale_access" ]; "slink.access" = [ "slink_access" ]; + "adguardhome.access" = [ "adguardhome_access" ]; }; }; }; diff --git a/modules/nixos/server/kavita.nix b/modules/nixos/server/kavita.nix index 717266d..8a44cdc 100644 --- a/modules/nixos/server/kavita.nix +++ b/modules/nixos/server/kavita.nix @@ -62,7 +62,6 @@ in virtualHosts = { "${serviceDomain}" = { useACMEHost = globals.domains.main; - forceSSL = true; acmeRoot = null; locations = { diff --git a/modules/nixos/server/kea.nix b/modules/nixos/server/kea.nix index 4fc3dfa..b9686f6 100644 --- a/modules/nixos/server/kea.nix +++ b/modules/nixos/server/kea.nix @@ -1,6 +1,6 @@ -{ lib, config, globals, confLib, ... }: +{ self, lib, config, globals, confLib, ... }: let - inherit (confLib.gen { name = "kea"; dir = "/var/lib/private/kea"; }) serviceName serviceDir; + inherit (confLib.gen { name = "kea"; dir = "/var/lib/private/kea"; }) serviceName serviceDir homeDnsServer; dhcpX = intX: let x = builtins.toString intX; @@ -8,6 +8,7 @@ let { enable = true; settings = { + reservations-out-of-pool = true; lease-database = { name = "/var/lib/kea/dhcp${x}.leases"; persist = true; @@ -24,37 +25,44 @@ let inherit (vlanCfg) id; interface = "me-${vlanName}"; subnet = vlanCfg."cidrv${x}"; + rapid-commit = lib.mkIf (intX == 6) true; pools = [ { pool = "${lib.net.cidr.host 20 vlanCfg."cidrv${x}"} - ${lib.net.cidr.host (-6) vlanCfg."cidrv${x}"}"; } ]; + pd-pools = lib.mkIf (intX == 6) [ + { + prefix = builtins.replaceStrings [ "::" ] [ ":0:0:100::" ] (lib.head (lib.splitString "/" vlanCfg.cidrv6)); + prefix-len = 56; + delegated-len = 64; + } + ]; option-data = lib.optional (intX == 4) { name = "routers"; - data = vlanCfg.hosts.hintbooth."ipv${x}"; # FIXME: how to advertise v6 address also? + data = vlanCfg.hosts.hintbooth."ipv${x}"; + } + # Advertise DNS server for VLANS that have internet access + ++ + lib.optional + (lib.elem vlanName globals.general.internetVLANs) + { + name = if (intX == 4) then "domain-name-servers" else "dns-servers"; + data = globals.networks.home-lan.vlans.services.hosts.${homeDnsServer}."ipv${x}"; }; - # Advertise DNS server for VLANS that have internet access - # ++ - # lib.optional - # (lib.elem vlanName [ - # "services" - # "home" - # "devices" - # "guests" - # ]) - # { - # name = "domain-name-servers"; - # data = globals.networks.home-lan.vlans.services.hosts.hintbooth-adguardhome.ipv4; - # }; reservations = lib.concatLists ( lib.forEach (builtins.attrValues vlanCfg.hosts) ( hostCfg: lib.optional (hostCfg.mac != null) { - hw-address = hostCfg.mac; + hw-address = lib.mkIf (intX == 4) hostCfg.mac; + duid = lib.mkIf (intX == 6) "00:03:00:01:${hostCfg.mac}"; # 00:03 = duid type 3; 00:01 = ethernet ip-address = lib.mkIf (intX == 4) hostCfg."ipv${x}"; ip-addresses = lib.mkIf (intX == 6) [ hostCfg."ipv${x}" ]; + prefixes = lib.mkIf (intX == 6) [ + "${builtins.replaceStrings ["::"] [":0:0:${builtins.toString (256 + hostCfg.id)}::"] (lib.head (lib.splitString "/" vlanCfg.cidrv6))}/64" + ]; } ) ); @@ -73,6 +81,14 @@ in { directory = serviceDir; mode = "0700"; } ]; + topology = { + extractors.kea.enable = false; + self.services.${serviceName} = { + name = lib.swarselsystems.toCapitalized serviceName; + icon = "${self}/files/topology-images/${serviceName}.png"; + }; + }; + services.kea = { dhcp4 = dhcpX 4; dhcp6 = dhcpX 6; diff --git a/modules/nixos/server/koillection.nix b/modules/nixos/server/koillection.nix index 951812e..0cef41b 100644 --- a/modules/nixos/server/koillection.nix +++ b/modules/nixos/server/koillection.nix @@ -13,6 +13,10 @@ in options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; config = lib.mkIf config.swarselmodules.server.${serviceName} { + swarselmodules.server = { + podman = true; + postgresql = true; + }; nodes.${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; diff --git a/modules/nixos/server/mailserver.nix b/modules/nixos/server/mailserver.nix index 8d08b9f..24df0c8 100644 --- a/modules/nixos/server/mailserver.nix +++ b/modules/nixos/server/mailserver.nix @@ -1,4 +1,4 @@ -{ lib, config, globals, dns, confLib, ... }: +{ self, lib, config, globals, dns, confLib, ... }: let inherit (config.swarselsystems) sopsFile; inherit (confLib.gen { name = "mailserver"; dir = "/var/lib/dovecot"; user = "virtualMail"; group = "virtualMail"; port = 443; }) serviceName serviceDir servicePort serviceUser serviceGroup serviceAddress serviceDomain proxyAddress4 proxyAddress6 isHome webProxy dnsServer; @@ -32,6 +32,16 @@ in }; }; + topology.self.services = lib.listToAttrs (map + (service: + lib.nameValuePair "${service}" { + name = lib.swarselsystems.toCapitalized service; + info = lib.mkIf (service == "postfix" || service == "roundcube") (if service == "postfix" then "https://${serviceDomain}" else "https://${roundcubeDomain}"); + icon = "${self}/files/topology-images/${service}.png"; + } + ) + [ "postfix" "dovecot" "rspamd" "clamav" "roundcube" ]); + sops.secrets = { user1-hashed-pw = { inherit sopsFile; owner = serviceUser; }; user2-hashed-pw = { inherit sopsFile; owner = serviceUser; }; diff --git a/modules/nixos/server/minecraft/default.nix b/modules/nixos/server/minecraft/default.nix index d333d0a..d54e031 100644 --- a/modules/nixos/server/minecraft/default.nix +++ b/modules/nixos/server/minecraft/default.nix @@ -1,4 +1,4 @@ -{ lib, config, pkgs, globals, dns, confLib, ... }: +{ self, lib, config, pkgs, globals, dns, confLib, ... }: let inherit (confLib.gen { name = "minecraft"; port = 25565; dir = "/opt/minecraft"; proxy = config.node.name; }) serviceName servicePort serviceDir serviceDomain proxyAddress4 proxyAddress6 isHome dnsServer; inherit (config.swarselsystems) mainUser; @@ -12,7 +12,11 @@ in "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; }; - topology.self.services.${serviceName}.info = "https://${serviceDomain}"; + topology.self.services.${serviceName} = { + name = "Minecraft"; + info = "https://${serviceDomain}"; + icon = "${self}/files/topology-images/${serviceName}.png"; + }; globals.services.${serviceName} = { domain = serviceDomain; diff --git a/modules/nixos/server/navidrome.nix b/modules/nixos/server/navidrome.nix index 9bf5fc8..d825653 100644 --- a/modules/nixos/server/navidrome.nix +++ b/modules/nixos/server/navidrome.nix @@ -16,6 +16,8 @@ in mpv ]; + topology.self.services.${serviceName}.info = "https://${serviceDomain}"; + users = { groups = { ${serviceGroup} = { diff --git a/modules/nixos/server/nftables.nix b/modules/nixos/server/nftables.nix index b31407f..6ded12c 100644 --- a/modules/nixos/server/nftables.nix +++ b/modules/nixos/server/nftables.nix @@ -40,6 +40,7 @@ in nnf-drop.enable = true; nnf-loopback.enable = true; nnf-ssh.enable = true; + nnf-dhcpv6.enable = true; }; rules.untrusted-to-local = { diff --git a/modules/nixos/server/nginx.nix b/modules/nixos/server/nginx.nix index 604f509..4f57d92 100644 --- a/modules/nixos/server/nginx.nix +++ b/modules/nixos/server/nginx.nix @@ -67,7 +67,7 @@ in }; }; config = { - extraConfig = lib.mkIf topmod.config.defaultStapling (lib.mkAfter '' + extraConfig = lib.mkIf topmod.config.defaultStapling (lib.mkBefore '' ssl_stapling on; ssl_stapling_verify on; resolver 1.1.1.1 8.8.8.8 valid=300s; diff --git a/modules/nixos/server/nsd/default.nix b/modules/nixos/server/nsd/default.nix index 6e79fad..84efeca 100644 --- a/modules/nixos/server/nsd/default.nix +++ b/modules/nixos/server/nsd/default.nix @@ -1,4 +1,4 @@ -{ lib, config, globals, dns, confLib, ... }: +{ self, lib, config, globals, dns, confLib, ... }: let inherit (confLib.gen { name = "nsd"; port = 53; }) serviceName servicePort proxyAddress4 proxyAddress6; inherit (config.swarselsystems) sopsFile; @@ -34,6 +34,11 @@ in }; }; + topology.self.services.${serviceName} = { + name = lib.toUpper serviceName; + icon = "${self}/files/topology-images/${serviceName}.png"; + }; + services.nsd = { enable = true; keys = { diff --git a/modules/nixos/server/nsd/site1.nix b/modules/nixos/server/nsd/site1.nix index 901774c..8c155c7 100644 --- a/modules/nixos/server/nsd/site1.nix +++ b/modules/nixos/server/nsd/site1.nix @@ -3,7 +3,7 @@ with dns.lib.combinators; { SOA = { nameServer = "soa"; adminEmail = "admin@${globals.domains.main}"; # this option is not parsed as domain (we cannot just write "admin") - serial = 2025122401; # update this on changes for secondary dns + serial = 2026010201; # update this on changes for secondary dns }; useOrigin = false; diff --git a/modules/nixos/server/oauth2-proxy.nix b/modules/nixos/server/oauth2-proxy.nix index 2d85ba0..83e06b3 100644 --- a/modules/nixos/server/oauth2-proxy.nix +++ b/modules/nixos/server/oauth2-proxy.nix @@ -1,6 +1,7 @@ { lib, config, globals, dns, confLib, ... }: let - inherit (confLib.gen { name = "oauth2-proxy"; port = 3004; }) servicePort serviceName serviceUser serviceGroup serviceDomain serviceAddress proxyAddress4 proxyAddress6 isHome isProxied homeProxy webProxy dnsServer homeProxyIf webProxyIf; + inherit (confLib.gen { name = "oauth2-proxy"; port = 3004; }) servicePort serviceName serviceUser serviceGroup serviceDomain serviceAddress proxyAddress4 proxyAddress6; + inherit (confLib.static) isHome isProxied homeProxy webProxy dnsServer homeProxyIf webProxyIf homeWebProxy oauthServer nginxAccessRules; kanidmDomain = globals.services.kanidm.domain; mainDomain = globals.domains.main; @@ -119,10 +120,6 @@ in }; config = lib.mkIf config.swarselmodules.server.${serviceName} { - nodes.${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { - "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; - }; - sops = { secrets = { "oauth2-cookie-secret" = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0440"; }; @@ -208,31 +205,41 @@ in }; }; - nodes.${webProxy}.services.nginx = { - upstreams = { - ${serviceName} = { - servers = { - "${serviceAddress}:${builtins.toString servicePort}" = { }; - }; - }; - }; - virtualHosts = { - "${serviceDomain}" = { - useACMEHost = globals.domains.main; - - forceSSL = true; - acmeRoot = null; - locations = { - "/" = { - proxyPass = "http://${serviceName}"; + nodes = + let + genNginx = toAddress: extraConfig: { + upstreams = { + ${serviceName} = { + servers = { + "${toAddress}:${builtins.toString servicePort}" = { }; + }; + }; + }; + virtualHosts = { + "${serviceDomain}" = { + useACMEHost = globals.domains.main; + + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://${serviceName}"; + }; + }; + extraConfig = '' + proxy_set_header X-Scheme $scheme; + proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; + '' + lib.optionalString (extraConfig != "") extraConfig; }; }; - extraConfig = '' - proxy_set_header X-Scheme $scheme; - proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; - ''; }; + in + { + ${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { + "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; + }; + ${webProxy}.services.nginx = genNginx serviceAddress ""; + ${homeWebProxy}.services.nginx = genNginx globals.hosts.${oauthServer}.wanAddress4 nginxAccessRules; }; - }; }; } diff --git a/modules/nixos/server/opkssh.nix b/modules/nixos/server/opkssh.nix index 1cc01bc..178e3d7 100644 --- a/modules/nixos/server/opkssh.nix +++ b/modules/nixos/server/opkssh.nix @@ -11,6 +11,7 @@ in options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; config = lib.mkIf config.swarselmodules.server.${serviceName} { + services.${serviceName} = { enable = true; user = serviceUser; diff --git a/modules/nixos/server/packages.nix b/modules/nixos/server/packages.nix index af6702a..6b954eb 100644 --- a/modules/nixos/server/packages.nix +++ b/modules/nixos/server/packages.nix @@ -13,6 +13,8 @@ sops tmux busybox + ndisc6 + tcpdump swarsel-deploy ] ++ lib.optionals withHomeManager [ swarsel-gens diff --git a/modules/nixos/server/podman.nix b/modules/nixos/server/podman.nix new file mode 100644 index 0000000..80bdc22 --- /dev/null +++ b/modules/nixos/server/podman.nix @@ -0,0 +1,38 @@ +{ config, lib, ... }: +let + serviceName = "podman"; +in +{ + options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; + config = lib.mkIf config.swarselmodules.server.${serviceName} { + + virtualisation = { + podman.enable = true; + oci-containers.backend = "podman"; + }; + + networking.nftables.firewall = lib.mkIf config.networking.nftables.enable { + + zones.podman = { + interfaces = [ "podman0" ]; + }; + + rules = { + podman-to-postgres = lib.mkIf config.services.postgresql.enable { + from = [ "podman" ]; + to = [ "local" ]; + before = [ "drop" ]; + allowedTCPPorts = [ config.services.postgresql.settings.port ]; + }; + + local-to-podman = { + from = [ "local" "wgProxy" "wgHme" ]; + to = [ "podman" ]; + before = [ "drop" ]; + verdict = "accept"; + }; + }; + }; + + }; +} diff --git a/modules/nixos/server/router.nix b/modules/nixos/server/router.nix index 9f71f71..6dc482f 100644 --- a/modules/nixos/server/router.nix +++ b/modules/nixos/server/router.nix @@ -1,4 +1,4 @@ -{ lib, config, globals, ... }: +{ lib, config, globals, confLib, ... }: let serviceName = "router"; bridgeVLANs = lib.mapAttrsToList @@ -9,6 +9,7 @@ let selectVLANs = vlans: map (vlan: { VLAN = globals.networks.home-lan.vlans.${vlan}.id; }) vlans; lan5VLANs = selectVLANs [ "home" "devices" "guests" ]; lan4VLANs = selectVLANs [ "home" "services" ]; + inherit (confLib.gen { }) homeDnsServer; in { options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; @@ -16,13 +17,27 @@ in { services.avahi.reflector = true; + topology.self.interfaces = (lib.mapAttrs' + (vlanName: _: + lib.nameValuePair "vlan-${vlanName}" { + network = lib.mkForce vlanName; + } + ) + globals.networks.home-lan.vlans) // (lib.mapAttrs' + (vlanName: _: + lib.nameValuePair "me-${vlanName}" { + network = lib.mkForce vlanName; + } + ) + globals.networks.home-lan.vlans); + networking.nftables = { firewall = { zones = { untrusted.interfaces = [ "lan" ]; wgHome.interfaces = [ "wgHome" ]; - adguardhome.ipv4Addresses = [ globals.networks.home-lan.vlans.services.hosts.hintbooth-adguardhome.ipv4 ]; - adguardhome.ipv6Addresses = [ globals.networks.home-lan.vlans.services.hosts.hintbooth-adguardhome.ipv6 ]; + adguardhome.ipv4Addresses = [ globals.networks.home-lan.vlans.services.hosts.${homeDnsServer}.ipv4 ]; + adguardhome.ipv6Addresses = [ globals.networks.home-lan.vlans.services.hosts.${homeDnsServer}.ipv6 ]; } // lib.flip lib.concatMapAttrs globals.networks.home-lan.vlans ( vlanName: _: { @@ -32,7 +47,7 @@ in rules = { masquerade-internet = { - from = map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans); + from = map (name: "vlan-${name}") (globals.general.internetVLANs); to = [ "untrusted" ]; # masquerade = true; NOTE: custom rule below for ip4 + ip6 late = true; # Only accept after any rejects have been processed @@ -41,7 +56,7 @@ in # Allow access to the AdGuardHome DNS server from any VLAN that has internet access access-adguardhome-dns = { - from = map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans); + from = map (name: "vlan-${name}") (globals.general.internetVLANs); to = [ "adguardhome" ]; verdict = "accept"; }; @@ -61,7 +76,7 @@ in services-to-local = { from = [ "vlan-services" ]; to = [ "local" ]; - allowedUDPPorts = [ 52829 ]; + allowedUDPPorts = [ 52829 547 ]; }; # Forward traffic between wireguard participants @@ -79,7 +94,7 @@ in late = true; rules = lib.forEach - (map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans)) + (map (name: "vlan-${name}") (globals.general.internetVLANs)) ( zone: lib.concatStringsSep " " [ @@ -227,8 +242,14 @@ in IPv6AcceptRA = false; }; ipv6Prefixes = [ - { Prefix = vlanCfg.cidrv6; } + { + Prefix = vlanCfg.cidrv6; + } ]; + ipv6SendRAConfig = { + Managed = true; # set RA M flag -> DHCPv6 for addresses + OtherInformation = true; # optional, for โ€œother infoโ€ via DHCPv6 + }; linkConfig.RequiredForOnline = "routable"; }; } diff --git a/modules/nixos/server/shlink.nix b/modules/nixos/server/shlink.nix index 023b831..00853db 100644 --- a/modules/nixos/server/shlink.nix +++ b/modules/nixos/server/shlink.nix @@ -12,6 +12,10 @@ in }; config = lib.mkIf config.swarselmodules.server.${serviceName} { + swarselmodules.server = { + podman = true; + }; + nodes.${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; }; diff --git a/modules/nixos/server/slink.nix b/modules/nixos/server/slink.nix index 8e71aae..8ca9509 100644 --- a/modules/nixos/server/slink.nix +++ b/modules/nixos/server/slink.nix @@ -10,6 +10,10 @@ in }; config = lib.mkIf config.swarselmodules.server.${serviceName} { + swarselmodules.server = { + podman = true; + }; + nodes.${dnsServer}.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = { "${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6; }; diff --git a/modules/nixos/server/wireguard.nix b/modules/nixos/server/wireguard.nix index 98d9fdf..dcfa71d 100644 --- a/modules/nixos/server/wireguard.nix +++ b/modules/nixos/server/wireguard.nix @@ -95,6 +95,14 @@ in ) ); + topology.self.interfaces = lib.mapAttrs' + (wgName: _: + lib.nameValuePair "${wgName}" { + network = wgName; + } + ) + config.swarselsystems.server.wireguard.interfaces; + environment.systemPackages = with pkgs; [ wireguard-tools ]; diff --git a/modules/shared/config-lib.nix b/modules/shared/config-lib.nix index 1bc7e2a..eac2370 100644 --- a/modules/shared/config-lib.nix +++ b/modules/shared/config-lib.nix @@ -1,27 +1,27 @@ { self, config, lib, globals, inputs, outputs, minimal, nixosConfig ? null, ... }: +let + domainDefault = service: config.repo.secrets.common.services.domains.${service}; + proxyDefault = config.swarselsystems.proxyHost; + + addressDefault = + if + config.swarselsystems.proxyHost != config.node.name + then + if + config.swarselsystems.server.wireguard.interfaces.wgProxy.isClient + then + globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgProxy.serverNetConfigPrefix}-wgProxy".hosts.${config.node.name}.ipv4 + else + globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4 + else + "localhost"; +in { _module.args = { confLib = rec { - - addressDefault = - if - config.swarselsystems.proxyHost != config.node.name - then - if - config.swarselsystems.server.wireguard.interfaces.wgProxy.isClient - then - globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgProxy.serverNetConfigPrefix}-wgProxy".hosts.${config.node.name}.ipv4 - else - globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4 - else - "localhost"; - - domainDefault = service: config.repo.secrets.common.services.domains.${service}; - proxyDefault = config.swarselsystems.proxyHost; - getConfig = if nixosConfig == null then config else nixosConfig; - gen = { name, user ? name, group ? name, dir ? null, port ? null, domain ? (domainDefault name), address ? addressDefault, proxy ? proxyDefault }: rec { + gen = { name ? "n/a", user ? name, group ? name, dir ? null, port ? null, domain ? (domainDefault name), address ? addressDefault, proxy ? proxyDefault }: rec { servicePort = port; serviceName = name; specificServiceName = "${name}-${config.node.name}"; @@ -36,12 +36,28 @@ proxyAddress4 = globals.hosts.${proxy}.wanAddress4 or null; proxyAddress6 = globals.hosts.${proxy}.wanAddress6 or null; inherit (globals.hosts.${config.node.name}) isHome; - inherit (globals.general) homeProxy webProxy dnsServer idmServer; + inherit (globals.general) homeProxy webProxy dnsServer homeDnsServer homeWebProxy idmServer; webProxyIf = "${webProxy}-wgProxy"; homeProxyIf = "home-wgHome"; isProxied = config.node.name != webProxy; }; + static = rec { + inherit (globals.hosts.${config.node.name}) isHome; + inherit (globals.general) homeProxy webProxy dnsServer homeDnsServer homeWebProxy idmServer oauthServer; + webProxyIf = "${webProxy}-wgProxy"; + homeProxyIf = "home-wgHome"; + isProxied = config.node.name != webProxy; + nginxAccessRules = '' + allow ${globals.networks.home-lan.vlans.home.cidrv4}; + allow ${globals.networks.home-lan.vlans.home.cidrv6}; + allow ${globals.networks.home-lan.vlans.services.hosts.${homeProxy}.ipv4}; + allow ${globals.networks.home-lan.vlans.services.hosts.${homeProxy}.ipv6}; + deny all; + ''; + homeServiceAddress = lib.optionalString (config.swarselsystems.server.wireguard.interfaces ? wgHome) globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgHome.serverNetConfigPrefix}-wgHome".hosts.${config.node.name}.ipv4; + }; + mkMicrovm = if config.swarselsystems.withMicroVMs then (guestName: { @@ -49,7 +65,7 @@ backend = "microvm"; autostart = true; modules = [ - (config.node.configDir + /guests/${guestName}.nix) + (config.node.configDir + /guests/${guestName}/default.nix) { node.secretsDir = config.node.configDir + /secrets/${guestName}; node.configDir = config.node.configDir + /guests/${guestName}; @@ -62,6 +78,7 @@ }; } "${self}/modules/nixos/optional/microvm-guest.nix" + "${self}/modules/nixos/optional/systemd-networkd-base.nix" ]; microvm = { system = config.node.arch; @@ -74,6 +91,7 @@ inherit inputs outputs minimal; inherit (inputs) self; withHomeManager = false; + microVMParent = config.node.name; globals = outputs.globals.${config.node.arch}; }; }; diff --git a/nix/topology.nix b/nix/topology.nix index 72f92e8..dc22d6f 100644 --- a/nix/topology.nix +++ b/nix/topology.nix @@ -4,189 +4,250 @@ inputs.nix-topology.flakeModule ]; - perSystem.topology.modules = [ - ({ config, ... }: - let - inherit (self.outputs) globals; - inherit (config.lib.topology) - mkInternet - mkDevice - mkSwitch - mkRouter - mkConnection - ; - in - { - renderer = "elk"; + perSystem = { system, ... }: + let + inherit (self.outputs) lib; + in + { + topology.modules = [ + ({ config, ... }: + let + globals = self.outputs.globals.${system}; + inherit (config.lib.topology) + mkInternet + mkDevice + mkSwitch + mkRouter + mkConnection + ; + in + { + renderer = "elk"; - networks = { - home-lan = { - name = "Home LAN"; - inherit (globals.networks.home-lan) cidrv4; - }; - fritz-wg = { - name = "Wireguard Tunnel for Fritzbox net access"; - inherit (globals.networks.twothreetunnel-wg) cidrv4; - }; - wg = { - name = "Wireguard Tunnel for proxy access"; - inherit (globals.networks.twothreetunnel-wg) cidrv4; - }; - }; - - nodes = { - internet = mkInternet { - connections = [ - (mkConnection "fritzbox" "dsl") - (mkConnection "moonside" "wan") - (mkConnection "belchsfactory" "wan") - (mkConnection "twothreetunnel" "wan") - (mkConnection "stoicclub" "wan") - (mkConnection "liliputsteps" "wan") - (mkConnection "eagleland" "wan") - (mkConnection "magicant" "wifi") - (mkConnection "toto" "bootstrapper") - (mkConnection "hotel" "demo host") - ]; - }; - - - fritzbox = mkRouter "FRITZ!Box" { - info = "FRITZ!Box 7682"; - image = "${self}/files/topology-images/hunsn.png"; - interfaceGroups = [ - [ - "eth1" - "eth2" - "eth3" - "eth-wan" - "wifi" - ] - [ "dsl" ] - ]; - - connections = { - eth1 = mkConnection "winters" "eth1"; - eth2 = mkConnection "switch-bedroom" "eth1"; - eth3 = mkConnection "switch-livingroom" "eth1"; - eth-wan = mkConnection "hintbooth" "eth6"; - wgPyramid = mkConnection "pyramid" "fritz-wg"; - wgMagicant = mkConnection "magicant" "fritz-wg"; - wifiPyramid = mkConnection "pyramid" "wifi"; - wifiMagicant = mkConnection "magicant" "wifi"; - wifiBakery = mkConnection "bakery" "wifi"; - wifiMachpizza = mkConnection "machpizza" "wifi"; - }; - interfaces = { - eth1 = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - network = "home-lan"; + networks = { + fritz-lan = { + name = "Fritz!Box LAN"; + inherit (globals.networks.home-lan) cidrv4 cidrv6; }; - eth2 = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - network = "home-lan"; + services = { + name = "VLAN: Services"; + inherit (globals.networks.home-lan.vlans.services) cidrv4 cidrv6; }; - eth3 = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - network = "home-lan"; + home = { + name = "VLAN: Home"; + inherit (globals.networks.home-lan.vlans.home) cidrv4 cidrv6; }; - eth-wan = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - network = "home-lan"; + devices = { + name = "VLAN: Devices"; + inherit (globals.networks.home-lan.vlans.devices) cidrv4 cidrv6; }; - wifi = { - addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; - virtual = true; - network = "home-lan"; + guests = { + name = "VLAN: Guests"; + inherit (globals.networks.home-lan.vlans.guests) cidrv4 cidrv6; }; fritz-wg = { - addresses = [ globals.networks.fritz-wg.hosts.fritzbox.ipv4 ]; - network = "wg"; - virtual = true; - type = "wireguard"; + name = "WireGuard: Fritz!Box tunnel"; + inherit (globals.networks.fritz-wg) cidrv4 cidrv6; + }; + wgProxy = { + name = "WireGuard: Web proxy tunnel"; + inherit (globals.networks.twothreetunnel-wgProxy) cidrv4 cidrv6; + }; + wgHome = { + name = "WireGuard: Home proxy tunnel"; + inherit (globals.networks.home-wgHome) cidrv4 cidrv6; }; }; - }; - switch-livingroom = mkSwitch "Switch Livingroom" { - info = "TL-SG108"; - image = "${self}/files/topology-images/TL-SG108.png"; - interfaceGroups = [ - [ - "eth1" - "eth2" - "eth3" - "eth4" - "eth5" - "eth6" - "eth7" - "eth8" - ] - ]; - connections = { - eth2 = mkConnection "nswitch" "eth1"; - eth7 = mkConnection "pc" "eth1"; - eth8 = mkConnection "pyramid" "eth1"; + nodes = { + internet = mkInternet { + connections = [ + (mkConnection "fritzbox" "dsl") + (mkConnection "magicant" "wifi") + (mkConnection "liliputsteps" "lan") + (mkConnection "treehouse" "eth1") + (mkConnection "toto" "bootstrapper") + (mkConnection "hotel" "demo host") + ]; + }; + + + fritzbox = mkRouter "FRITZ!Box" { + info = "FRITZ!Box 7682"; + image = "${self}/files/topology-images/Fritz!Box_7682.png"; + interfaceGroups = [ + [ + "eth1" + "eth2" + "eth3" + "eth-wan" + "wifi" + ] + [ "dsl" ] + ]; + + connections = { + eth1 = mkConnection "winters" "eth1"; + eth-wan = mkConnection "hintbooth" "lan"; + }; + interfaces = { + eth1 = { + addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; + network = "fritz-lan"; + }; + eth2 = { }; + eth3 = { }; + eth-wan = { + addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; + network = "fritz-lan"; + }; + wifi = { + addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ]; + virtual = true; + renderer.hidePhysicalConnections = true; + network = "fritz-lan"; + physicalConnections = [ + (mkConnection "pyramid" "wifi") + (mkConnection "bakery" "wifi") + (mkConnection "machpizza" "wifi") + ]; + }; + fritz-wg = { + addresses = [ globals.networks.fritz-wg.hosts.fritzbox.ipv4 ]; + network = "fritz-wg"; + virtual = true; + renderer.hidePhysicalConnections = true; + type = "wireguard"; + physicalConnections = [ + (mkConnection "pyramid" "fritz-wg") + (mkConnection "magicant" "fritz-wg") + ]; + }; + }; + }; + + switch-livingroom = mkSwitch "Switch Livingroom" { + info = "TL-SG108E"; + image = "${self}/files/topology-images/TL-SG108E.png"; + interfaceGroups = [ + # trunk + [ "eth1" ] + # devices + [ "eth2" ] + # home + [ "eth3" "eth8" ] + # guests + [ "eth4" "eth5" "eth6" "eth7" ] + ]; + interfaces = { + eth2 = { network = lib.mkForce "devices"; }; + eth3 = { network = lib.mkForce "home"; }; + eth7 = { network = lib.mkForce "guests"; }; + eth8 = { network = lib.mkForce "home"; }; + }; + connections = { + eth2 = mkConnection "nswitch" "eth1"; + eth3 = mkConnection "bakery" "eth1"; + eth7 = mkConnection "pc" "eth1"; + eth8 = mkConnection "pyramid" "eth1"; + }; + }; + + switch-bedroom = mkDevice "Switch Bedroom" { + info = "Cisco SG 200-08"; + image = "${self}/files/topology-images/Cisco_SG_200-08.png"; + interfaceGroups = [ + # trunk + [ "eth1" ] + # devices + [ "eth2" ] + # guests + [ "eth3" "eth4" "eth5" "eth6" "eth7" "eth8" ] + ]; + interfaces = { + eth2 = { network = lib.mkForce "devices"; }; + eth3 = { network = lib.mkForce "guests"; }; + }; + connections = { + eth2 = mkConnection "printer" "eth1"; + eth3 = mkConnection "machpizza" "eth1"; + }; + }; + + nswitch = mkDevice "Nintendo Switch" { + info = "Nintendo Switch"; + image = "${self}/files/topology-images/nintendo-switch.png"; + interfaces.eth1 = { }; + }; + + magicant = mkDevice "magicant" { + icon = "${self}/files/topology-images/phone.png"; + info = "Samsung Z Flip 6"; + image = "${self}/files/topology-images/zflip6.png"; + interfaces = { + wifi = { }; + fritz-wg.network = "fritz-wg"; + }; + }; + + machpizza = mkDevice "machpizza" { + info = "MacBook Pro 2016"; + icon = "devices.laptop"; + deviceIcon = "${self}/files/topology-images/mac.png"; + interfaces = { + eth1.network = "guests"; + wifi = { }; + }; + }; + + treehouse = mkDevice "treehouse" { + info = "NVIDIA DGX Spark"; + icon = "${self}/files/topology-images/home-manager.png"; + deviceIcon = "${self}/files/topology-images/dgxos.png"; + interfaces = { + eth1 = { }; + wifi = { }; + }; + services = { + ollama = { + name = "Ollama"; + icon = "${self}/files/topology-images/ollama.png"; + }; + openwebui = { + name = "Open WebUI"; + icon = "${self}/files/topology-images/openwebui.png"; + }; + comfyui = { + name = "Comfy UI"; + icon = "${self}/files/topology-images/comfyui.png"; + }; + }; + }; + + pc = mkDevice "Chaostheater" { + info = "ASUS Z97-A, i7-4790k, GTX970, 32GB RAM"; + icon = "${self}/files/topology-images/windows.png"; + deviceIcon = "${self}/files/topology-images/atlasos.png"; + services = { + sunshine = { + name = "Sunshine"; + icon = "${self}/files/topology-images/sunshine.png"; + }; + }; + interfaces.eth1.network = "guests"; + }; + + printer = mkDevice "Printer" { + info = "DELL C2665dnf"; + image = "${self}/files/topology-images/DELL-C2665dnf.png"; + interfaces.eth1 = { }; + }; + }; - }; - switch-bedroom = mkSwitch "Switch Bedroom" { - info = "TL-SG1005D"; - image = "${self}/files/topology-images/TL-SG1005D.png"; - interfaceGroups = [ - [ - "eth1" - "eth2" - "eth3" - "eth4" - "eth5" - ] - ]; - connections.eth2 = mkConnection "printer" "eth1"; - connections.eth3 = mkConnection "machpizza" "eth1"; - }; - - nswitch = mkDevice "Nintendo Switch" { - info = "Nintendo Switch"; - image = "${self}/files/topology-images/nintendo-switch.png"; - interfaces.eth1 = { }; - }; - - magicant = mkDevice "magicant" { - icon = "${self}/files/topology-images/phone.png"; - info = "Samsung Z Flip 6"; - image = "${self}/files/topology-images/zflip6.png"; - interfaces = { - wifi = { }; - fritz-wg = { }; - }; - }; - - machpizza = mkDevice "machpizza" { - info = "MacBook Pro 2016"; - icon = "${self}/files/topology-images/mac.png"; - interfaces = { - eth1 = { }; - wifi = { }; - }; - }; - - pc = mkDevice "Windows Gaming Server" { - info = "i7-4790k, GTX970, 32GB RAM"; - image = "${self}/files/topology-images/pc.png"; - interfaces.eth1 = { }; - }; - - printer = mkDevice "Printer" { - info = "DELL C2665dnf"; - image = "${self}/files/topology-images/DELL-C2665dnf.png"; - interfaces.eth1 = { }; - }; - - }; - - }) + }) - ]; + ]; + }; } diff --git a/profiles/nixos/microvm/default.nix b/profiles/nixos/microvm/default.nix index b00d5a1..689bbbf 100644 --- a/profiles/nixos/microvm/default.nix +++ b/profiles/nixos/microvm/default.nix @@ -20,6 +20,8 @@ general = lib.mkDefault true; packages = lib.mkDefault true; ssh = lib.mkDefault true; + wireguard = lib.mkDefault true; + dns-home = lib.mkDefault true; }; }; }; diff --git a/secrets/public/wg/hintbooth-adguardhome.pub b/secrets/public/wg/hintbooth-adguardhome.pub new file mode 100644 index 0000000..f917a4a --- /dev/null +++ b/secrets/public/wg/hintbooth-adguardhome.pub @@ -0,0 +1 @@ +emVomIbxGS95tDiwPpUbsRTAur/TZ+BRy7+4737Sv1Q= diff --git a/secrets/public/wg/hintbooth-nginx.pub b/secrets/public/wg/hintbooth-nginx.pub new file mode 100644 index 0000000..4f23f14 --- /dev/null +++ b/secrets/public/wg/hintbooth-nginx.pub @@ -0,0 +1 @@ +G4NXSwhwU5a2K1q3oAwmnOtBlCj15J2aqh6zIJJtggE= diff --git a/secrets/repo/certs.yaml b/secrets/repo/certs.yaml index 50999c1..cec5da9 100644 --- a/secrets/repo/certs.yaml +++ b/secrets/repo/certs.yaml @@ -8,143 +8,161 @@ sops: - recipient: age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpZW1LTVFtaGVraTFDRVI2 - dkNRV0tpdUg1YmdiL2hMVUlodzFJM1hHUkJBClRHaGRMTDNlbVpDS1A5dzBpc2Yv - ancxU3lSRTJNMFBjeFNoSEF1Rys0YVUKLS0tIHVpb2g4bnN4NHJTdHJrSDdKVFZY - aGNOMDgvakoxcWJ3bEVyeFZOQU94UXcK/mjqz9Ys7ZEm2+9Y+mLrQVqoC5g5ag85 - Xp9Fo7gmsgc9lZwgxRPLzIBeWcaN17NIaMRDMxTz5cdDCRi5JP9FiQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFdDZiY1BsaHhLYy93L2Ju + TkJHRUdTU0VFKy9jd1p2ZmJrU092Z09yMTNvCnpzbXFIZ1VMVk1QVzN6YXFmckQ0 + U0hFam53Z3V5U2xYNjkwU1UxNmI4ZncKLS0tIGk1MC9EV2hnMFN6aFRtekt0enQy + RWxXVmhJU3NVbHdlS1Rsd05sSkZiY1UKaK5bSDPhQlVTryAYr/9mIgmXDzVp2KWF + M4FQURHk6kvSIVjHNfRyMX0IVtCFZMSmVpuPUP46J/5kzdN59Jn2Bw== + -----END AGE ENCRYPTED FILE----- + - recipient: age18cgqlely56hgmhscllkmafwpjdk6dwep6ej3vkk97dzemp8jtuksqrrjjl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLRElrSnhrM0ZVQ043K1Nk + VTNlWDVDNW5veDNPM0RuOWZTZ3IwQ2pBdmpFCktEZFNvUTRrVVRBdFU5alhJSTE0 + RVlqRkl5MUEzZjhUVWwrWTFWMk8yWG8KLS0tIHJKZXJrNXZiRjNiZEh6VEhHWnZT + dlI3RTl2MW43YVdJMVlDaUoxSDV3YTAKBCjLqctIpPeTYsRxhj0/7DzR0q1cGe2d + w0B8DmH56XP7vq+nLh6+imWFLsbEOS0lRPHRRBEiimEkYljO5ZkoZg== -----END AGE ENCRYPTED FILE----- - recipient: age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXMXRHK1Nud0VEMUh5OFRZ - Z1ljcmZyRG9yRFFwdWtTcEVXc3NEOVVId2xjCnVIb3cvSG9oODJvd0NGd1BIb3A4 - TmJ4SGdmd1FDWCs2c0YvZXkxWWFidG8KLS0tIHIzUlloTUhxY29pQ081akFGSmRO - Y25iUkw4bU1sUzZlUHEyWDB3d3hlZDAK4auJRQylMD3vf/PeMdImqRrx86sT2vdM - lbmSBNqry2CueSgvFp2z4q+NOE4F5z/rlc0GZnUvdzBTLZ83C1BYoQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3TEREZ0lVR2Q5aEN1S2sv + dVhURlhhWTJBdEdhbHlXZGVQa2ZwZkhFd2lnClM1QUJrMW1GU3FuVTFwUkZxR0xD + YS9kVFVRdGZKMVVRTk5sNm9nRVV1YkkKLS0tIExyKzlJUHhUdEVhSGJEUUs1YlQz + Yk5WMERLb1MyVTRvM3hkVVFNU3ZtajAKqH9sLSNTacfRj4c/FeeOyCITdz9zwgqm + e52OOUzI9nmq3zbhzd7b2nWHlJ2d/vmFN0u4oEpLodQPqBy/cvuoLQ== -----END AGE ENCRYPTED FILE----- - recipient: age1ly2endyt0y9xyddj6yuj4nw6fa3ltvzlvew4cr4lzs6dv8dkavpqadmyxx enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyZFpCaWNlSGdWTG9EanBC - MlVKZ1FCMHpzMkNJUTA3QzZ3aUtCbmFIemxjCktVZ0V3L25NNGxLaWRVbTZCWjBV - NXJKSzczYUd1ajJ6U0VsTmRpQW5SalEKLS0tIER1Y3VCTzJ5TjZ5dHMxSG8yaHM3 - OGFWc240c0lSYXEzWlp6eGtIcHpnUlkK+7wia8nrB982IdbW8zXg0p4Zf/3XE+Rn - u0Nsa7cbeOpB+stTV/i/2ayY86+zkN8UQXJnlv+AVf3Oe/3xaKsZ1A== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEbmRtN1FXaFYwUTBsbEhr + T0tGcVkvdmhjOWZMLzZ3UUpoQ0V6Y2luRlNrCnU0RThMcXlabWQraHB0ZjNldFRW + bUtRNGgwNDZhNjF6MzlQM2V5RmVRRnMKLS0tIDB0ZUpPZzJFMndSZXJNQWEzbjZQ + YVJxb3NLNEJkNXlzR0Q2MUNhZ0NGeTQKC204L2g3b/ER0RtnTaGtuZSukTawgiC0 + 94UolrcApg2tAUDJR9AqJ0iAAu8KSkcy77mQIs1t1d5lwejwsOBUMQ== -----END AGE ENCRYPTED FILE----- - recipient: age15klj4t7gpfp69472mne4ue62pp6m4e04dmjyw7yf30qtqd3vl3uqjmcyxm enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzUzNPMUE0M3Uzc2JqTUhk - ejVmS2FpSHN2YitaRHNMNm9abHdTSUF3QVdRCnlQcW9aMFh5MHRHNjNrWXFrRTlF - TXNBN3FEY3dPMHhNbEQ0eGdacGNvbkUKLS0tIEtoWlFqblROSndGOEZwdEN2cXcr - c0IzdGY3T3E4Vmk1SzkydEVLbng3MG8K2pF8UY+89cI0dh7xgdrvl7fn8f05jSpM - MFcVBU9ySITPb3lcGtOKVcyyh8OaTusdZWmzbnl/dKr7kWjg/M8l/g== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjbmZRNDYwVjhacnZzTm1J + MG5FWVd5TytPNWhDVTR6Z2dxdEYwbEU5VVFNCkVpdmMxTmR2dHBKNnZNTmF4c3hs + eUozU2VkKzlKMjhWaDJXQUx3ZXdHV1UKLS0tIEtNb25NU204dFovM2xvMEpDYUJX + QWZLNDQvZjZjaDZiN3JLcWswMkhtcnMK0kkTPKMgKNiOOgen2BQANozKY0npxINI + ZhKkf/eQsPD5kUbD1gLshfeOS+GOcDJSjrYigneJo11yEhNVF7juDQ== -----END AGE ENCRYPTED FILE----- - recipient: age1k73gy5em3js9zklnnkzp5hme9k04lny32fgahmzddknjw5c295asdyr4x6 enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQZmdsMEpVanFKdEhaNUlp - Tk5KYllvRWRhQXNBN2VzMGxHSVA2aVhhclZFCkdGWWhLakN4dkVVMnhMYkk2ZmdF - TDhtOGlpWlF3QlBKWVJkejhwUERZczQKLS0tIGMvdWpXV3pJaytsY2kvbXlsY3Rl - Wm56NTVKcmdESG43NGhhWk0xbHZFeU0KUwZW24hBFmC3PR5iP4e5eMt94I4xHgo6 - qB2ceOd4c86h16+XiJvhiYbPQdvuKcHoMSdmt2ZbHstzeuOn1ZdClA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0VVBQaVluOExJSnBxaWtn + N2RXb0UzaFgvTmpXcENKaTkzb05Vb3hMeHpnCjRVSmhTZ01sVy9ZRnZrK1FTa0Ey + TnJmYlVaNGFLRmZUcnFXYkswQnQ5emMKLS0tIGNuMlBmYnNzNXczYTljbUY3bUtk + TkFMSlZzTjVjMkVUaVcyVXI3cXc0K28KUDg9+qZqrbUk+D8TEG2p5tu6v8HgGfHK + MGkbN/+3wmitC2T1HEdA18ULGrmd1SFN6qGIfYOkR6dkhETIs+w/jQ== -----END AGE ENCRYPTED FILE----- - recipient: age1cmzh82q8k59yzceuuy2epmqu22g7m84gqvq056mhgehwpmvjadfsc3glc8 enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEZjEvNlMzQXYvZG9QaXdY - SDFqSDUzVE1xNE1sM0l5RXNJZllEL3c2Y3dzCjFMTEp0eFNRTndWWExYS1phSjlu - MGluSVZPOExnd3ErN2VZVTJIb2l4WjQKLS0tIHd2SEwwaXIvRXhEVFd5OC9vQ3ph - azdrTklmaWNYR3RuaitKbHk5WVhsb0UKgpHMKCR0/LzLWUgH3aasF9tETrapgsoB - oNXyxH7ry8jE+WYw4p+oOgSpNVuq9ae2Hot36u3hTjgXuub9kF2IhA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHSjhleGt2Y0JTU3ZRWnda + US9ScWpPYTk2Qlhjdlh6RS9JR0lzTVc1djMwCm8zZnJ2a1prOW9Vc3h4RjJXNE5G + d0IwYSttaC9iVGZaejBmK1J6SXc0aTgKLS0tIGZvbnJTZ29xcDJGbzkraytKb2tY + OUIxMHJmbTlhei9nSEpQeUtIWjJLSGsKwLTnTxIqkumhWoVbt7eKTU03upmZYvF1 + S3a4mS/FZAU/9PgtHeY7LF4a0wwnHBAOxTwKcj8lYPWQzfPNSBFEBQ== -----END AGE ENCRYPTED FILE----- - recipient: age1wmx8y2hs83j2u5srdnfxljrzxm8jtxl6fr0mq7xf2ldxyglpzf2qq89rpx enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyNFFWendCOFptUU15a1kz - TTNmSTUySkFrN2ZNUmZzNDVTWG96SDdwNENNCmx0TmdnTnVRYWo5ZHJQK093bG1X - TWk3Sm41RVFUY2FPVUN4TldjaEs1RUEKLS0tIFF3Vm9sY1BIeUxteFgwd0xaVXRt - SkJ6WmlobXF6Y01semFHUnJUK0wzZWcKMwhhIBUZxXRsaemaaJ7zFXJ8CH3Gw6N8 - nNZUTPb7eg7yvHIiST7EqO57qhpHuxqK/OCFBOIPYs/wjdO806ubAA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjMmF1VkdhUHIzYW5sdlo0 + UnpRUjNieVREc09ONWtqQTdWQU82R2g2S1RzClowWVpMZTEwM1czdW0zWmdiMGd3 + V1djaDBpRFZHU1BZbmRhUDk2RndmaGMKLS0tIG9oQmlKMW5TVE1lQ2ZEMnU1c0pI + dlRVNFR5ZDhJcitoaXdmdFBHenM2NEkKHrWek+5xtVdwVaLF7FuhdJJCdZxvg3ib + JKIN6/IKg6v8wWbts+oJZmH0+ibv3dPPCNll0U0toYGBkbJVUUiMbw== -----END AGE ENCRYPTED FILE----- - recipient: age1mjgw3nxlnqdj04mgjz3wn7fj2nl2nxla4p2r2fn4nkvayfgp09pqllxzyh enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSByUXA3T0Z6eVpGQVZheWFF - N2NOV2NjZFdlTUwySE16NlBuU2pPRlRFV25NCnlxOENwa3lKMlZHcXhhMkd1dHFH - bXAyQXErVlFvSnNvekxkWFpsNW1rc3cKLS0tIDRSS0lVT3BYNXZUcWk5dTNMc2Qw - ZjBKOW5XVTJiMFhpdm5qeUY0VjBqT2MK83ZdreVtLQdV5zPPjRpcDVKPtU2heVME - yhXwR5VmKKpSHnu9uYSzIjyWoLQA7uLD6GcFkUEcUuRifd0tYMJTuA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXQ0FYTnBILzF1TENDVFcx + Wi9pZUg1eGNiTCtGdUFrRERBVGxxR05jQWkwClBLK0FBd201ZzlRVC9aQUIwUzlz + Yy9Sc2dpQ2l3Ty9ST3JrdU54VFN2UlEKLS0tIG5ldXY1R1k0dGlsRXhPYlpLS2Yv + dFBoM0RGQXVLdnhxVnJ0V1FpWmFkTUUKCHv8KQYB2QdcTdCB3Wig7YTRKt1ZiqkA + MT5A0z0rizax0YZLGJ7QJlWkT/EmX0EsV62cvjzXeUkE2FKpYffiNQ== -----END AGE ENCRYPTED FILE----- - recipient: age16vzhcvz8tyxj8e0f47fy0z4p3dsg0ak4vl52ut3l07a0tz465cxslmhevl enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTZWl1dGFGajFZNzhJZkUr - Nm5hc0d2WG9QRDkraWYySVpiT2twakpqa2pVCjhDUk94LzFZalkyaUdIVE5YMDJL - V3NLRHUvaWcwbEpXcFNOVTlhMkg2UVEKLS0tIGxrYk9wVWFFd2V5ZDNycVA5VXUx - Y2wzNGFGMTJXUUpPbGxuMU5nWlFvU28KTmP0byJFneTPHUJ6e+ScSiKypMrz7TNV - FHZ78vmNIzcstLKgXwK23hyEIYTtgrLOP37B768fAM8aHiqGQORs+Q== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1VVlxd3RrRDFnN0Q5SGgx + OGlDV3lyYmRQTjBsZ1kydlI4UFNVMUNZYmdRCmh0dzdEUmFDWmU0VjZHZHhhN2ZX + MW04LzB1ZHc4K1dCbGVBK1NMRDJJbDAKLS0tIDEzclhsWWhIRlUrU1ZjV2Q2dExF + cW42NFdBa1JKZTRpb2Z3aVpNVDJaWFkKynL65X4AjGw7PDrFZw+J34KajCl/TfZ7 + fA1c8fyngnt42FuKVoSHiIrEUCfFEsf37NbV5WQFF61V0bO83EX5qQ== -----END AGE ENCRYPTED FILE----- - recipient: age15cx90pnp54xp5gxlt02yn9j2pz968wp3l5ukdkx55xuecp34e5pszjku4m enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSakpNTmczZGNWUmlxODlS - eURFTUcxLzZtSU5RT1J0cE56TXdPb3NsRlJnCm1pZVBGNFJrd0w4cFhFMkxzRmYw - Q2thUU1DVlhBc1Z2d1EvVEJvKzVQOG8KLS0tIDk4MUJ1Q1dIM1lkdC9KbjgrNG1n - YjF2TzltV2NsTVNRM3pRZVByS001R0EK6d+Hwl4dQB79n5Baq8kQKUqYaifbp7PH - YUZmR8xwiJP87oFmD2lETgJQyWDvGBk+nM5glAjIqO6PEhJBvviVHw== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1U2d3WXpqbkNQUnhvNmxT + NE1hUDFSZXBTOFlQMFYxT0F2VkdzK1MvRmlnCmkvc21GMTJjNmlXNWFxS0JsQzBL + MUVoWkdMR1hOd09MZUF4bUpubi9CM00KLS0tIDdCVkxXenIwN3F0YW1COEJxMTFn + a3VvbEZUUHNJcEhUMllud2tYQU1RQUkKDG5dUpTAKHdGrnD1U2JWWv2Ue/LShVwt + XRgdjTwmXtvf2s9sIetX2rLiJxcLkpRz8z+AjK5c3GWxF6ZVPuuGvA== -----END AGE ENCRYPTED FILE----- - recipient: age18quey88vge7xytclg2nuq4ncme86dg04lxwczqxczmdchnjg3p0saehsnh enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRVVYweEtGQSt2Qk9Ic2pJ - QnJlQ21wVzJTZGNrby82dU41bDRkWTFvandnCmtYSUpFRkNSZ2FBNFhpSURQVXFt - ekhBaHRlc2tSS0lXdFdRdXR5SEd2MzQKLS0tIEZTeFhqZjgzZDVwN2NxVVluMVlE - ZkhzSFkrS2NMK1diL2RwbnNzTzNQaWMK7/Q16epHfSDQ4q29DN0WpLKCWh2rnLJC - cKR+gQKXUNzt/7Osh6eWuCVWMfc9p03ruvlxrJ416Am4k66kbAmrQA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjQThNQVJyR1BVOElNNldl + ZmphdkE4ZVpaaHE2N2tPdGpxMFFaVHUzZkg4CmlsSmtRdnVMSDhTK1p3S05Kamhi + THRVMUE2d1NDc3FIdUpXQXoxa00xRk0KLS0tIEhhUnBIQnJQUnZKU21vTHk5WFVt + cUhkVFRNMHFkdVFMQTdWWUwyVGZxZU0K4Dn0V7ulWdSOnsFSaFTBdfOz6RD0R3Ba + MOM2I0afFAcbQI2rzdySbGzy7yJeuA1puBbrHDMOkVCK2soYm3Gerg== -----END AGE ENCRYPTED FILE----- - recipient: age1ax5hqk6e2ekgfx5u7pl8ayc3vvhrehyvtvf07llaxhs5azpnny0qpltrns enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5OXhuNk1VcFhpWWJYMHBN - U2pjWXJNbFpUZUdBbWFxOHRZY3N5bmxwdUJvClpTc3ZiTmpyZW8vS2UyNGh6N0l6 - UHBnTk9lSTEyOGFvSnRKUE5rN0lrRDgKLS0tIHRsOXJiR3RwVlRXSzlVRG1PRWxu - Zk5EVlJUekwxYWpuVkgxQ2oxcGI3K0UKmA+Ae0Ja6CfkGL3yhpGsmHVdZLPz2/Sc - TYeUhIwKRJql7Rg4Yu0aG//2gK0HKLnSOq/nJtSIJ+8P87OKTYg8iQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjOVpRQVJBVWFnaFR6SnBo + UXdrTk4yMW95QStMOGFqV0paSHp2Ly9Ga3pNCk1PSnFOWFUramM5OUxLU3BibG1C + blJtc3dNTWlBek5POXRMbUZDbG1WelkKLS0tIGZkVEErZ0twTFV6dWhVanUrdlpY + VkJDQ2Vmc3FPTEJKbWcrQkRwYnN2TG8KO245mM0A94pLL4/EHi6/eeh4rak02IuR + n8rBcJ/U4qOD+1QNW+mHbGiNNSHLtGHuVrM5uKaruRJDmxzNWQjmXA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1c2enwel9un28dcs4wg0vcyamx9a4a6g3walkhu8w5lqhmd804paq9d24as + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkUXdnZ1FLenQ3SjNwN3c1 + aTREVTBhNEIrN1NWWUJ3SlRrQmppSnVTc1JJCnFydzZoNEdxUVdDUEQ4UkUyUTYv + aXAvZmxXT1ZkSmpCWUpWeWJZYXFGcmMKLS0tIDdySzROS3dxSk1id2FKbHZ4UERG + ZzZzYjVjVCtMdVpoM0tzY2w4Mm9aSXcKr88HZkBxwuRzDtb/I8D7uopzjglZQsKD + oEd1uz/uYhDvy58MIKz9nnTMKyPUOE+uICZbjZ25ZsdkcDdCWNhyig== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-19T14:09:27Z" mac: ENC[AES256_GCM,data:tZ6QzVPivueZiC9Qfb3KNZAv02QatgHRNnlM+Y0iV4BZkYoBjxeDojutizvAMwUarnubUdk5I6m2OZK1mvVDZKXyI6zALX4JMeT2xYQWRHYzHpOygLhhGwTFVhV+0C4jN+eJFF2cNf9lu7NuZI9ylZSOY8I3YKUl+l0l3CkXUl4=,iv:JSGOUq+j9T/NXspn70dfu0J4ISV6vVFZUe/Z1CirrJk=,tag:Hm9N55f9qMc056nSTR1piw==,type:str] pgp: - - created_at: "2025-12-15T21:53:33Z" + - created_at: "2026-01-02T21:17:29Z" enc: |- -----BEGIN PGP MESSAGE----- - hQIMAwDh3VI7VctTAQ//T3Ld00/QPCKpVc4bonVGR1XRF8POkqr1eGc9locjDs+x - MZFYAUApLXsM2A7W6hPa+sgffHTPmyjg85xC3XC+Z9aWCnHAh0tFjU0OdBaMOaK1 - ha3nX3FmmC4QEuUs4elA0/CwfRG/16/bRTV+ys1jESM8AnQt9RhsBtDqJ42wNLFW - zlM96X+7j3DGyQAkgFV4qW4uL2tpPgnTgpvhjotW4Fl0xsBzf8E09IvmDGAV7sbt - JQcSAUxZilKjVlwutz2AnAOl3fLaaBuNIYySr0r6pc4uv9W9g9z3NdxkKLrdAN4w - UJglMIRai7Pv4DA9QdC6khJUswngfrk5GWuRTkqNSMkVOi5pl9y+Tdw9qKuSVFoE - GGmMzdmbFd7XOAYwIawAZqWAqlZ3mJaxAwSwut1Gls0u6BBQh4wjYJW6yknS8qJg - Gb92+Ly4r3/Kt+iOxpL9Uz6JUWtk4DFRCAdiwGdie6tnoB6VI01SVzkw2aDj7deN - kG7AFx1kofX+kUvi6gKK6kN0cZuwCOlyUE7OUSWSKWCmVzqUiDMy2WUdw+x5arqc - zjstPzBWW/hLr5aY8vHpPONoM32KWc6ewKnxeVt8kjCh64IHOJQ4c6ilgghqECUd - DN8AnpCXWeP09LkOu5rNX9miuLAEIGEYXZoP4bfVHKxP6jsx9jQdEBD0G21RaFOF - AgwDC9FRLmchgYQBD/9lPhj+gc929oxlP7cEanqOpcb3lHpS6d6wOF1PXoFn48P/ - JMchtMpNfQZ1kDW5CcdoG31zeTzhjpUlYVuZHhvhBuT+pEshjZOsw7vY0NAdScFE - /45MrKsRKeHEkhKcke6w2BNW+o+202ZIjSZv+1QvAQYt0wGfI9EzYclE9CV9zcrm - 3M5exSXVOYgt6REwEVKb0OaoAAgNrlRpJRj8CjrJ5g1vN21wG+anqhaxYoWFdsXm - LMKY9eyAAiFm01RU7cSHfl1Qy1op3KzpbQyabQ6zIbq7BS/ouo4jGyMyHt3DPT1e - EY7dkNFcZh5sIIZEmKWjFbjIXT/urVWdKJPfkdC/QLsCvm37V5sDs8JB9JFivumA - LcNgFVmoCdmM8K2f98q3R6K38VsNH+AgcJA87RKGnHMw3NVnHthR6x4T6+cknK09 - e0iV6wdazNN5/1Bmu1Y/JrnaGyIAuyoom0Nrv+OTVgjjenftw+J4GsWIpicSYHHc - mN8TcFqqrZ9QjHQS9BMXFNLC+m1HGpP4Mi8J7haEh6cIURFVkmZRDl+SUwnqX+BN - XtHs2q0Ht6jDY1K93StrXTFqNTasG31MUEcs8og/KkUhT4LGRIrAJoR70jPojV8c - TQsT/bLFgYVvKaKPRoI6SbJyhQeoJMnEoDFAZdlB78KBMcRSAHZt16j6f6bke9Jc - AYQEzirwmSjViuIEnu57k96w1UHJB+rjjgP62C88A0ENr97UbCacIC8EemFN0xPP - UDubuNbq7O9XAfoXbKy8jqeciZVo40AF8YN3HZuRnrppgik5zzs4o3yBv5k= - =1hR6 + hQIMAwDh3VI7VctTAQ//cFd10y5cI5pCudkNrwJjjCvaJmP33pteHYJrzH951JFt + FmO5NVPxFkyZIApN2LJ+neqDhfOHWoAqb+2GWeAnKQwqWWD3mAMzTFbZ/GnfNTpJ + tdGh/PtTawnjl5olwv/TSDj4DJSH9B/r5KJG+2oKvDNYHQ06K6qVoZTtlI9wA8nR + TLZlqlHlLNrYBBKNH8hUcdwCbd9wlBZGY/dhprTUlKb+W7i5LszQJuKdmxUj4njq + QVjxMG9AHKn+SU4awAOyEI0uzTdKApem1REaJE/d+quaR7KLCjZIpQ3n4SsbBUfJ + yAsBv57JAlxbaG5xuMZ/kjWQaGiufUK0J9IBfEKAyHZM//iFl+CAPNzPrQDPI4wy + 6HRL2r9EvUwZb6vJYskd8Od57nT4/0+zV8bSzh18JkEc9UKvMn7d4bx7AnKU+rsP + cDeIC5JTJjygaiodIdYAYS81FZZGj+t04hrAzkiPZcM/+3JdHNkuxV4jKbD6ljzr + xdCaJUXSmGrK4uznLFoIBz4A35UHSwSsa8s3RUL1Knem59cGSMVqfz6nJPQ/0sOT + tI+8VI5HCdJ0vlNw669opzgGGiaIKcBKWfrXsxYkww9ekWxbjWaBcFLKm3g7p/mh + KzFRmQwcOXG6nQ2ROUnL18Jh1u+iiXvzc17yK/6xuh3lLi+wvfRXMb3/ePG4j86F + AgwDC9FRLmchgYQBD/918RvwuPqcGLYgUJLJr/ycnAG5EzoSA7qqBvItgoJfzbah + oCnnVRwAyvvvYYyqWrpIxc9X5w8vD5CeLDWEX4slm6AXUbBFK9i+tesmXC6D7du/ + Sb/DHYH1Fa168nZ/oK2YieVQto6VS0WK37WqT6thybyEpYZu898tE9mY9riKlE+B + JHKjGailLl4KeaWbZQgLNP9KKi1wwOC/Ae43SS3XqFWu0zx/l4RHn/KvNNVcYyc5 + UuuBHhFem12f14xVy2bwjELTkQfImlBFmPmbN2sqOIG8maFzdwUVfVMcAR2Ceq9Z + pTOL2q7NCZ/JlwZ25ficJ1Og4Wnk3oTQwZswoN+nApIF7Td1QxmDLnGB8xmrnLpn + 7A1PCo9IR3MdOatqN2xvotV1WotYTz3lcqpHfsYpscEBuyozxVw++1c2+QpZtmBQ + C3MQoqUDXBwvku5BfVG97XFy1QDCCTelUPdNCvIkXoJg9AUugPYRokCcI2bTybFY + unL0sirc8+/mgEQTwZgJXDhtvYTpps0pj5PFwdDHRDgrW/CzSkLz05HIKl+NKDmc + +aIxFLAQiFBiqgJneb5q3GK7uZq0YVIb86MD5sqSNT2Utz1KMzhL56sTjPEtn73E + zfwMX/EpCkpshsfbG1hLZeKPsYZBAo14Jbv/IfWHX0OXp6EVWrLM4FT8sEEwWtJc + AeNU3uXSpOW5xlKv6bpNSl0A9C8XYK28FU8JaENq85Q5VZGLf4JP2auFXQ2PWbpo + 9MmhPhMNk4a5aDh+AqaB7yXCFvqzsGEJu8Xqe3gAN8Jn9ThMvUW+nwm56A0= + =arGb -----END PGP MESSAGE----- fp: 4BE7925262289B476DBBC17B76FD3810215AE097 unencrypted_suffix: _unencrypted diff --git a/secrets/repo/common.yaml b/secrets/repo/common.yaml index c32b307..3f054ac 100644 --- a/secrets/repo/common.yaml +++ b/secrets/repo/common.yaml @@ -41,143 +41,161 @@ sops: - recipient: age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1UEUyZDNVQ3U0NklpU1Bs - VndoTnRBMW5ESUlDWi83TUdGdXpMeDdRam1rClh2SU4zRmFscWtSWFMvYnlySXAw - S0hjcVZZN1MwTm1kZ2xUcVhxQ0wwdHMKLS0tIGE5djdQZkl6NFdJMUJPVWh2ZEJW - Y1BMbDgwaDliN2tLdjBYOU5TaG9uaDAK0bHyEDpXoM1hZlhw9uJVOpCG8FnfONyh - cZKAl0ykQ5dZ6pQo8K/4jtOf08GesZIRenyCxIE/lNZBvFg6OgJBJw== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvcTNvUVVSZ2R1N1FKWWw5 + dGJHc2swRXN6SmdvZ09zTGhYa1VqWnp3L0VzClZvYmhYTjdnVytBZFI3c2JqdlhI + M3NiNVFQTXkzZ09ESkUzamRleU02WFEKLS0tIElxaENIb0V6RElZeVZFZWRIRzlH + UE1mM0VEOExFNm9OaUV1NFh4cEc1alUKX6niNF5QxQ9ub+grPkUqeLw+gjBcwV2A + Y7zeR9eYAABCkDh789luQd37LXP2QdD90hiaDGMQChVMpmcIjdP34w== + -----END AGE ENCRYPTED FILE----- + - recipient: age18cgqlely56hgmhscllkmafwpjdk6dwep6ej3vkk97dzemp8jtuksqrrjjl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOS3g4dEhVYlBGMXNzcGN6 + ZldoUVRtY3FsNVNpcXI2cTk4T3RzNUQ2cW5NCmFmUXRXb3REaXZTVk5MemhOaUNk + bjYyYThFSm1ZZ2JRcDF4WnFxSndxL0kKLS0tIGJXZEsxRS9LcVRrd01xYzM5QVQx + MW9TYkhMRUdXZVVBeVkvRUFQWElhMW8KIhz1sFGRNkhVyLRZjA3IyYInRbNhN/Qq + 5OWHJj/iS05xunkPNoWfxphRtHRudljgDXpt2UwYgWoTm1cAnoIj5w== -----END AGE ENCRYPTED FILE----- - recipient: age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpcXFsVzNBRFlsQUxiREZI - dG1UVEE2c0NzSjk3bEM1UWlXMU5wakFZTFRJCm5VQUs4alk0TlYwNmRaOUNFOHdW - dC9CTVRuODFnMmpxRGY4L2l5azU3MTQKLS0tIE00Rm1BSDh3NnZRZ1BJbzVLL0t3 - TzM0TExsbUVXRUhKMDVMS3B1VzYwZGsKDD5JXe6ySfCrgiVXN8NjI75z2nr6HuhD - cTx0S3m3KD+uyw9bVVdUkRTCFaLwD05080PN46uB532HsZAMLLSFQQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXbkc3aGtMcXRiTm82Nllp + aHRJdFVvcXp6ZEorNmVmUmIySzdRWW8ydWlnCm9oYWZhTStJQmNSL21hVFFyOFpL + aUFmQk0wbzVwTWRtSEtkQ3RFc3hOUFkKLS0tIHo4YzU0aHhFVmZCTGZWclNpakdn + eVVDYUNXUk5BM2M4MFJjVlY5NzJKd0EKt/vaHVeTowmbc8MfQwHqxnbolf0t5Th/ + wBQHe+MUBg9lCr+TqDi7+TaRYa93V0oiBVQ1uDLweV5olpOi2ttc3g== -----END AGE ENCRYPTED FILE----- - recipient: age1ly2endyt0y9xyddj6yuj4nw6fa3ltvzlvew4cr4lzs6dv8dkavpqadmyxx enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJTFYzakJ4cVJoMnhTUDFx - SG82QWFMWW9La2lOcmdPNlpaWjNpNk11M0hZCmp6TXI5Q2NLa1ZieVdlbllhRUtB - cU1EVkZxa053NFJkZUs0bE00MnpsZGsKLS0tIC85UzhzQnNKUlMrdDB1SDJQZDUx - d2h1MEJHcjdxTXEySTlLNFlnSDJoSXcK2kWhF7v9mm3EIQoJ4aQIT8I/INKB3lSf - xEscNVOqeOGnfdrOIYHBWhWIsBNRsgfJMIxFY8TVxmDNGj6r4GqvHA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDUVQwYXNiVTE3dENRV2N1 + Z3AwcDk0YkRFZkRjZW9KZHFlYVNaWHljMUNjCnJmN2pzaXV6RFk4NmVFdSthYVcx + TVpTclp3NnlBakNaYUQwMmg3VVM1SDQKLS0tIFF2enEwWXAwYVVTeWxNY0kwRWdC + bVJuaEdsOERBKyszcHRYUFpUcm5zeDgKISCkCqLSCUwSM7XqrY+JMW9OE9q5sfbB + EXVLqqjqBICQ50vtnGywG70qu3WXzpuVy0NK+zA/3sgVpXuU6/Cplw== -----END AGE ENCRYPTED FILE----- - recipient: age15klj4t7gpfp69472mne4ue62pp6m4e04dmjyw7yf30qtqd3vl3uqjmcyxm enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSVWU3YlNtby9ZVWNWZ0R1 - NWV1VUo2V2hJSmJYVlJmVkloMzVxbVFobVdnCmxJV3ZvUzBrYmFLYW5NNWVWdDl0 - TDkzZmY0a0FHQTVmOUwwajhtaWRqNjQKLS0tIEJFUE9Oc0IwTXpJUFFjUWxXTFBW - NmpVbzRDbzVGOW5iVFBQYU9FdFJtUU0K1NAuCYjrYUZVLajR3h7Le1p7ZDcfGYpr - kctaY2S80mPxN2Dv1Y81S0G84ptmi7NXTCghDrPhkdrnzFd+egeWvA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArYnQzTm5nMHUrTForWTlq + akhabVhFRlVxQmZFS3RId1RBU3FTYVl0NUJNCmRGUlp3QzR2RFVNU2Q4aGlud1BN + bWlzWnNUQnJlelVsS3dhWTdyTGgxUWsKLS0tIG9sRE00QVozUzJ5eEJtekRQWmVr + YlM2WXdQTFJRMTlZQ2xlTzMzbXFFd0UKZBiT6x4zfpKQctOCUFmBQHzWZ2rFIIKh + Lx2oteWtHrGABf+wc45ypz6CBEJjw7moBf7ZCupOOL+jIJpe3UriqA== -----END AGE ENCRYPTED FILE----- - recipient: age1k73gy5em3js9zklnnkzp5hme9k04lny32fgahmzddknjw5c295asdyr4x6 enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkdHJCREhwRWdqVXVYa1o0 - dEdRNjhxd1VxWWI5b3dQQUVacXdmNUxWSFZrCjFFdEJHNmFGeVhyZVdSeW5BQXNO - L1I5VkdBK1FEZFQyblVtOWJOYzl5U1UKLS0tIE54NENJRUt5bzNvN0NIVVhlNEQ5 - YXFPeDBQZUJsL0IyNFVpVFB4NUdtZ28K4LIamLUU4zn9MY7NphIjfCMSWlwLkF1c - 8zqOyNS5tpjCsdZ47IInoPSxtlKEq/97PV/nUzw1BTH10Rxx3ENCGg== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFcHZqNFJWNGFOUUNkZTlN + L0IzcU9qR09BcGQ5ZGxGMmcxaWx4SHZDakdvCnZpc0N4QzNzTU1XWWhZYk10QjVN + dHEwMS9xOGRBSlFKQi82eE84aGMwbTgKLS0tIHNjNUFCaFdEM3lmTlhNUDJHQXlM + ZVhBQUNoYlMwQ056V1ZCRUdrdG5ESWsKO8a6+mhNR2jzTHuKROp0QbFFLJD0TN/e + 5zKySP6bHrlcK9fguXWnOqshWuxPdECNmE32L0pm9maL7G2T4FhvzA== -----END AGE ENCRYPTED FILE----- - recipient: age1cmzh82q8k59yzceuuy2epmqu22g7m84gqvq056mhgehwpmvjadfsc3glc8 enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1djk4SEFBUXF2U1FOQjZ2 - eTEvaWdMcTFzY0ZBTk1XUGE0UGUzNVMyYmlZClUwRU9KeGc0cVZGSTdDaERQSWhL - bHhwa3RtUWZXSWFxYmF5UWtLK0JabDAKLS0tIFR1eHFPVGNtRDJFMnNoaVJnUHlJ - d2k4TjF0a0tkbFRvVGR3ZS9XcndpcXMKpqZXI/APjHSqR+j4/k4UcQfdL7toFGHJ - 9vRdsWWYGae3JABNpFGC8xCpvEtdPyMwEQw0JpjkRz3n0KKSa0XL3Q== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGWDdyVm51cFZ1SjNVQU5L + UUFqbEhkV2puWEJxVmJkb1prOGNnZ1pRZG44CkZpOEZ5dUdjN0NYWXZSK1lLMERG + M3Rwb3FLa0crQmx1YkFZTnZlVGF6Z2MKLS0tIHpmd2RyZC9ZR2lIQUszZlNQbUJu + bVNkMTI3ZXpDY01KamRFb0FmY1B2dWcK1RRtVtIwzgckwxX5YEQWdL+BHUdEAD57 + 9Y/lLGzhGHwRA9lYaN8q+cpMDjhuIDiDqSZV7N16EZcOjZ0MIjZonw== -----END AGE ENCRYPTED FILE----- - recipient: age1wmx8y2hs83j2u5srdnfxljrzxm8jtxl6fr0mq7xf2ldxyglpzf2qq89rpx enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvSVR1SzFxSFphazlaM3Jv - a3V5Um5hMS9SU3FHTXJmQW1ncWh1VTdXNEhVClI5NmowcDdzSWVsTzRWSzN6L2JC - R3A1NElHdmFFU0psejNlWkNidTlWVUUKLS0tIEZWMjM0b25YSXRCS3U5aXdTN05W - eFUyYzZydWdvTjBTV2JnK3dQam5Ya1kKBhrX+2CX9ZJdymOY5yC2thfUY3/N2TB2 - LqUctgXpqxk67bupTN/wkfSkYV+//FdSdVtLiopnXHC5k0QIVizCSQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzaXZTNU4vNTArazNxZnBz + ZGNrWXJ6Y0JSaGY1UzhjdzhIdVVsNjlQUERZCm5RV0Ftams3US9WVzA0eHdOTkpX + RVYwS3MvUXZNOFFUMG9VKzh3aWk5YjQKLS0tIHZhb2ZSYndLcGJIK0xURTRBR2NQ + OVN2ZURGSWxCNkViK3NFSVRqdUo3aWMK4tjIx7paJg7bTgTwjnXjbpHE+Vvf3YbF + C9Ekp1Kw0k+THfTgnjwyNWuaLv+8VoLqt2k10H+oALjLHxQKpPSmCw== -----END AGE ENCRYPTED FILE----- - recipient: age1mjgw3nxlnqdj04mgjz3wn7fj2nl2nxla4p2r2fn4nkvayfgp09pqllxzyh enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2bW5hblpKNGlYRkwvVXpz - ZDlNdkNjS1ZPSGZUbXdnZHgrTE1XaWw4Z0FnCkNEZ1JFRDA5eVJEWTVGdVdwdXNI - Z1JXUnhXOXdTV0RoZnNYNnAxREZvV1kKLS0tIDB0dlM5ZVNzRlVzRDU5QjZDcllU - VFVjc3pZdHphT1dwYnV6NTFtTmViSTgK7a6/HWAV8Bxf3d062LFXB1QyTqvfLFPB - ZrTV01HMKzleFY3Fv9HLjJNGt/l54ZVdq+Ea3sp9UUfw+BKMpoqrrA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1ZmV3WUc3SGR3OU8wb1RX + aGVLUnJWdU5BTE1uSy9YSUhVUHIrMEhDVVVrCmhNYW9yd0I4RnBaSlJRRzR0R2NS + R2JkSENzQ2N4ZW5Xdmh2cW9iZHVvNW8KLS0tIDA4cTI2YitUMFlVL3ZlVFJlT1du + eXh3ZkJyRk1oOUlmM1dwdGUraXZsU1EKCVvFlj0X0Q79116nQ+8Ybsjk1HBE55vh + /j5g7ggeLdCcoU7qEevHvBukbGa84xmiwJxa13mumI7Yi4383P8Twg== -----END AGE ENCRYPTED FILE----- - recipient: age16vzhcvz8tyxj8e0f47fy0z4p3dsg0ak4vl52ut3l07a0tz465cxslmhevl enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0M2dYWVBZWVFNQ3JnWXVn - YVNnYWFzdGxXeVhLQ0tBdzdaYzhaN0p6cDIwClRXNUNtYTRiNXFCZnZ6WGQ5WUtJ - VzBRV211YzZ2VzNkTTJtblNFZ1hiUVUKLS0tIFVhVEpCRHZOTzVsUmlxT1VXZWZx - bi9pWnhsY0V4TjIzN1hqeVhkb3FsNTAKcngM/MK1uLuw2i9AOxPnscD+OLopKIuv - B9U7mSE5zRyYFgXK8Y+s8r3CBq9NUFlKFv8Rl9wmD7EMa1DfZ5GF7g== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMZkptNVRuYWZMWmZkdXMz + VDR2OEpOM2E2S2tZOTNPaXQ3c0taYVBZVm5rCnNqWnNHNEt2SlphdmhZZ2hGS0JE + RXlDQ281cEtjblNZeVBvWkVUaW5lc00KLS0tIGRLKytBRWNvUmlJZ2RzZHZWdFRy + K0VWbzdiOTRvbllSb1dIemVLNnZiWjQK9StbdLSPG2h98Dao5ZG3qvhvD6iSg3XK + MhgksJ/YfuWo0aaLMZ++1jjGD3O5DE3QbGrBA5R2RcInvUi7jHWBtQ== -----END AGE ENCRYPTED FILE----- - recipient: age15cx90pnp54xp5gxlt02yn9j2pz968wp3l5ukdkx55xuecp34e5pszjku4m enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1Q1lSdld6Q2kxMjJ1WTlB - M1I5MTRpMkNiRjJJOUVKRnlJcnZsd0UwbzBjCmlsMlFvMnp6UitRcjR3NCtDZ2Jz - TjgxSmwwRHFMQjlrTUFTSVBpNU93cXcKLS0tIGxxMXU4aURVbjFpSGlLS2JYNVdF - MnhxTURKWWdzWCtaMS9lTjM3YUdNSDQKhNFCq2mRvWMAsCUXrpiW69ti5LfBilp+ - 8B+mk86cFxhpaZtQLOthSBhhzTTdScCKDTywEVV6K51x1DGHqrYfbA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyMjZLa3J2dUlDNnJmcUtq + VndpSWxGREhCY21xRlpNb0F6dVhvZXV5YkNNCmJaVFFRdGY4NEdUcTZ4ckhmZldM + TmU5TDRwTG5QMGVHN3BwOWZuTFpQWlUKLS0tIEg5TjVjOUpaa1dabTlzM3REMmtz + ZUVWRGFsbDNWRTBaVUpnZlZLYW1GT2sKInrMXDj0MLNb4r2hwZEsw9HxpVE/eThv + TYyiPbaNkzr0EqDcOQQ/3MEw0Q2XPaMDdCG18u7kYlGGwdYNcWRgmw== -----END AGE ENCRYPTED FILE----- - recipient: age18quey88vge7xytclg2nuq4ncme86dg04lxwczqxczmdchnjg3p0saehsnh enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtR2NWOW45T0VSeWdPSHBM - OHJWRUUyaW5qbWx4ZytGOHJuQk5rRjlIRjBVClFJSm1kSWdGZ2xwMFE2TVRkSG9W - Z0FRS281UU5oSDkzMHkxOXhIMnpzcUkKLS0tIDNNTUhMR2Z1UVcrOFhRWWRYdUFF - T2d4dnJxTnBueW1LWHl3VnJMTm5abEEKUpUtH/deey97QuKWMFxabVSrpzzfaoSw - pR7nianRBaD8b8HsC8V7x98CenFBK0jVQAkx9VGMgqIGDsTaHiHPhQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0UVBvdXMzRVRuc0N4NktF + MzdnVExNWDNGanc3cGc0NkNoajJROFR2MUM0ClIvQnk1RmJCWXJZcjk4aHRYUTkv + cUN4NHJaSWxHckw0NTV4WWxKWHZHelEKLS0tIEs1em8xamQ4YnVpTzRZMDg0UkIz + b2N2RDRYemVDSzZESVhUOVR6MUEydG8KVLj9kVMaZeKDIQiVQF9lu80wA0m8CuMD + IBCwg5sHoz7fAK8vHpUPKh2XooD2BL9q0pPZCc3sCUjQvLgW1ZK1YQ== -----END AGE ENCRYPTED FILE----- - recipient: age1ax5hqk6e2ekgfx5u7pl8ayc3vvhrehyvtvf07llaxhs5azpnny0qpltrns enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2Zk9wN2hRTzJYVnZ6RUwx - WFVtdzF2NUM1QUxFRjdYNHVOWFErK0dOM0NZClZpc0JQZzBNc0lFd2IyZDAremZQ - aWxmK1ZtOEVZRFF5ajZ2QkFmK1J1bWcKLS0tIElpNHh4eDZZaFNWczl4MG9ZdjJ5 - L0gzWDFia2Jha0lDaGZaSWEwOWFmb1EKJqqjxODIgVeiMKtV6361sjYQa559pKCG - 1pKczlzXxL1FliBQoZZGq55NR4azWYEl/yV5tee1dtUohJW0pAyScA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2YWtZNlJBMUVna2tmODdo + TC82U0ZtMFV5L3Q4NktxZ1N5cklyR0ZUZ1R3ClNzSEhEVmg5WEpROTZIQzQ1dm92 + UGpxcHNzUytVYUM5dFJDcVVzVzNuWU0KLS0tIGtYaVNBTHNYNVZQTnZUN3BZSEh5 + eFQvUWx2Y3JPa2VCem55TkR3M3U2M00K5TSdJyIS1yCV8GIYZgWlSC/y2r5+hquL + RLougeJFaSXiZ9AOzsnC9jGzzBVvlsf5RNH+fYsK9oHuTH3Kv/s8Jg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1c2enwel9un28dcs4wg0vcyamx9a4a6g3walkhu8w5lqhmd804paq9d24as + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwWWRpTkFsWVZGbkY4dmli + VzRQaWt0UFM0L1BkV3dTSjMxbm4xMFhCT3hVCjNXbllqNDl4cXhZaDJVd1gxQ2No + d2tLL2VSY3N1T3E2WldHdDlwNXBycE0KLS0tIGd0YzUrZzF5cjlxVDBwWCtiZHNp + RVFnZWs5T1pxN3VHRWdnbjR4UFFIcGsKUnEeBhX9K2tUNd48XOvpb0n2OoeUPyq2 + N+LBxwPYoSxoiZAW0vDg4mNcJwALYDXA5ew0fSZj1nP2LvaROV84Jw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-23T01:11:36Z" mac: ENC[AES256_GCM,data:e0WoFBQSR5q3GOQ+GMJGBd4lNBAMqlnVjtUq3snxrdvcytb9YvKnoYQH+GjbdGIiqrND8pOVnZt34AjkR8YfpWe+VrkP3Vj/3l+1GjF1XIHbzBNKOQHdYPSVsH2NZwftcAdphbStf3GTlb+b+cpTn4a9Y4pTNGVoOaOA1tBr8bM=,iv:sPXktitTNMkBhHr6E/QRZCVKrgyED9/o9hiivbObACI=,tag:tTNr4UEf92UrtI0Jvi5o3g==,type:str] pgp: - - created_at: "2025-12-15T21:53:36Z" + - created_at: "2026-01-02T21:17:35Z" enc: |- -----BEGIN PGP MESSAGE----- - hQIMAwDh3VI7VctTAQ/+J73641lle7VHi7015hM2tzDaDhtLfoPl7R7jz2dOSmFx - FXfzu0kHK6Mg44WC5pcWvIHWJA9D0bKlMO5pxPO9vrG6tNU6C24WuibaLYbYWQDV - 7Gxbgi1SPEhLZY4BOU4nObRqR7GfDyHMVASKzzO5Rp15t4vxKko5VyPYPkX96XrG - OHcxeHe6BYBKCE6beee2KPtVfWtWxuKmK57inzeSnCGNVAXI/6RX7GMcCa1Y865C - QWvSmO8h6rEvCtj6heNdj39p1Iz1MckqAepsaTw6hpU9yiLkkiGzimZaeOJjU2V7 - hOfqmawpPWwGic7pcKE1kcbv9e7ogtcIOd1up1fWNn9jZ3wErwUiFYfT2oKfqlFB - rkO5IrDy6zvfF8diKmHM7/NiXwUa6h32uHxnLv0AcK8nOKaCW4ZcWOwmbu7gcZIb - 3Kl9teuaJ5FEV/7giz3lf8Fd5ljyGOUE3t1TWjJxzI0ovBjFMy8l5DEWhoNejfqI - cB2AbQqXuuOvdMTC+qaftpE+XXiIHniwQ3IzkUzhUE5p//xF2pk8SZkQ2iDn7Bb0 - 10p8TD8aLM7AuHd0fpkZPxpAyHCrN++i4wjsv8qdq8obmZ/BzsY4eUJnvcLlfaER - zMUuoT2JhbSLaFRgxgGrm/ez022X4pFmF5ONbbTrAEMxwcmvp9xGwy/krV43qX2F - AgwDC9FRLmchgYQBD/9PgG+2n2k5sUCLh266s4cHKbpVZdOnJ2uSiImyCtW95H2T - Uy0EpafcYyxEs/Hzz73UKaGDz9TwP2cAEVjQ4YumvrKq38SthyFXUAsiI8skXkic - LSEgEWzD0hmvW167mg1PptQyiPsgfAOBw6X6QdOFWJ3nadf8+2AV55JvHuQ9SxC4 - ejOsrVCQL7rMhNTXP2TSfm+ZFM9U6Qbv/xSXKPRBiqEsN/DZXD8BXTUY7KBpazOI - Ttjapr7DcI1ptMK/AIG1eJQAOpgRSsy6z+INpGsvbUIaAJDn8XFEt7kSMXGmQxDJ - oGtwHH1oDXK+ws/F3bn1FPZZlBVbq7fpSoEBBqnAd2jrGibEWEZ2zRBDSROalqCS - fA72h/1ZRUfx8iFBRd6Mu2PJAQ/oecZV+dcIlTD7B3v30HyAZTtVC2Mtdmxqi03U - TFTfhaeCNlficx1R1VtgAABlAMBeGerb6AuBVf9vziRkXiWcP/9RdYuTEJskHjZb - VXCQbEKck0YQHOds6QTu/+QlLZUoZF1LXVKF1iy+khc16oKYhRBUL58eJTOpYbtE - PUrayC6PXE0tKg1Ghe/yVsW9rLWmu7FMdAvM44/PjyI66zAwzKEu6STVahIrpxje - qKd1jugtsmR5kNK5CsORvval1iA6/UhU9fGdV9Zz1t6eyrMNatWk9yOO6uIq3NJe - AVqzW1bH3U8Ys+C7M/FHBskdSPnwgvANKb5hswadBkkRGep01HIJK5QdUj0W9CQ8 - obHQ1j0Rlzs70r6cxpruM9ddmGqP0/yRGncXHowrnf0ZnTzZr+Dhs+whA0V3Zg== - =jCXG + hQIMAwDh3VI7VctTARAAzjG3sJ25PaNOD6VowSNYaaK4DCY6PU2LGCCpJWzDXnwo + irJZUtGOiqeZeu/8BdWmQSwBiI9k/JuCt131rwXCrtj0+Yj0MRKTK/xc8NoDnW5t + R0CpQnWJ8yc1RRAMhx9l26HXH44786rhVt5/4ZCvq2mje6Ha0yK0vmjO6P+WR8kA + AUCuVUtQCtN5UP0yecdRHl6MvZe1qPd8tv3kLittJ2c48LD02CL3g0ZeATtCgiGN + 5h9cBfDQnFcBh5EuMxn3AoGQjIJollCS5fRNNi1VUTp4uyAqYnyRjnORNI6vRk2k + hju5W5ThidbYQlJlwO6hZM7e/sW/XM8RWi6x4TO1VN8MuXavKnIbzlOKmJZlLbb/ + yp0ueIzKuJpEz0nQZh0DFCD/D8yoTAfgtXgzzZKuUgErhkCQEXe/xKPDFvSKkWqA + AnVl6RwyTl5110Ea3535K3vycYR0EAxapEqzEZ0Ez/o28wR/1hgMrTWE9f++6HwT + wZ7EiPTs45yzZYJ0ONE4s9u9HNIvUY4UX3ncIhvTIWMyASfS2dbDu5fqxg5e+Szk + 9QcDL0bzLnGCmR4w6fKUl2mkupTMsi6sfRFMzGlabK6FizUnpwNQHd2LAxL7rNF6 + JiD6LxVQfY/TfKqQdKa93Ctf2k/tkdW2aw8JKZh02V9PqXUax0N4uR/TxOjKa/GF + AgwDC9FRLmchgYQBEADJTfHgtKmwdG4s+Mbml+VD3f0tDJnbOXBfISFp4+s/6Wf+ + kILyeL7V4yllzJWqUZ97IH4BScUBSbvcg45IvuzgfTrBTx6ZSa3OQYo+2KS76Wsv + uQkItpGdsVSrLYDseH4cOWev9D5zscU+pEdT6VKXP47UHbJPdxQ2IU0oncrMatgm + rBh+PfB+XeJRX9mKzsL9qVWuc5k9SVcsXLKSCM2IJszfRy/vsSJcAphReHxXHSuO + XYGVkSYLGgzA1by0wjZ4Gi3y8MVaUEm8rXYVnbaVRnx5bntEfj1pTjmqStH0EE07 + vkOooLLDFaP6o4c58jvRTwXBWKlBbgWqoSBgm08OPKQpFFpM+14GrLqGv5ECti6W + 299pjfyWU99ILNG6RdQiS5MLA01z4wWYXRlxyNVXOHlspVaacX8cE3/uGOslURwH + ZbDgmpyAr3Ss5nj7s8plnxpYIRdXNCgPJ8qZtEVSuQkHbkHMKUJ8gycQNRcB8wZI + H4EtOkeG6mLt7WJlWa4T2VF1AEfQXZoewkaWCK7JekY+DPyyK+b3JT6qArAMvGMl + apVaDegSptYYUteO67yHwP83GNAGwDY+o1/ECZhG4ucGkXYpS6MCBkyCeV++gy3B + qotF5Hr5xSOK8jzFm7k4UUiBiQmv8IDh6UUOOXAzejxn61ZYPdA+aEIBiSoueNJe + AffTd0ldG9HGm016X1uYrN63xNCRA6kVUWP+2c86CTGX2GKHb4YgtULBrVRW8hUR + KoofPhcaEVIUvrnMrPDIrp25Uh4DRakUMQUwsOjfliLmm03/07IJziTMWTZkYQ== + =qR6M -----END PGP MESSAGE----- fp: 4BE7925262289B476DBBC17B76FD3810215AE097 unencrypted_suffix: _unencrypted diff --git a/secrets/repo/globals.nix.enc b/secrets/repo/globals.nix.enc index 22b6467..c95426f 100644 --- a/secrets/repo/globals.nix.enc +++ b/secrets/repo/globals.nix.enc @@ -1,62 +1,70 @@ { - "data": "ENC[AES256_GCM,data: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,iv:LMwQRM3y2kJYM+9h7G9Cr2iwiQZx1KNmIn0zIa3MHRk=,tag:BKXIvu8hwZktmHqJ8kpeiw==,type:str]", + "data": "ENC[AES256_GCM,data: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,iv:O0b7UxLyCOGRu8N3dXjDtHuD/O6vHO3FWnsFT6LyjFU=,tag:qysiXpaiHGvhtjYwS8gjQA==,type:str]", "sops": { "age": [ { "recipient": "age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBaUxQZ2ExRmVJSWFnZFEv\nQ1A5VXNXZjZ6SHlLcnJtMWtSbTJyWm1CdFJFCnRBS3I5YUZkL2NyT2ZjL2M1ZmxT\nbWpoRHVCbVRwS2NqcHdOdkRQNkhzcXMKLS0tIFlzbERHVGJLL1hYczRBbllZaDc1\nVTF3dzM2TjlsY3pmV3ZDS3lGM2tsbE0KYOKd7D1jm5fgrdC/GFlZtxhnfsN5m0AB\n5gOWisPQYezayKs12Ver0t2reLV0vr63BY+mdi1qmTa4lMCzC1cqLw==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1YWl2aUhsVUZXVGZHUnhm\nK1hSUVl3ZW1MeGZGWDR3cGNrS2E1WnBCY3drCkNKcWcrZHk1UVZuWkdDRGoxRnhP\nVE8vYzRSSUpOSmRsYUZRaXFDbWVXT28KLS0tIFVLSFRPd3hKTEdtMmkwRFBWdVZ5\nd0hyYXVmYmFubjdHN255b0d6c0F1RlUKHlNhWypoeqRe9wuF5jGh2omhGTvnTtt6\nWRWnEw1i3wa1HFJn8S81oppvGrjmnGYPgaXcHjb4OHxt+9RKQYro6A==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age18cgqlely56hgmhscllkmafwpjdk6dwep6ej3vkk97dzemp8jtuksqrrjjl", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2WE9XZDZJV2tMeGhBanNH\nL2hLUVIwVk54OGFJSE1DMW5BMGk4aGYvTVZJCldKb000N1dFQVVxSFVoblpHSm5C\nM0dpUTREdlAvbkxaS2pLUXdtNjdYOEkKLS0tIHR6djdTMld6dTJSS3ZiRmpVZWtI\nWU1rT3hHWG5rdHU3eXJRTzlWcnV3RnMKI9jX76xcdENMjh4Be4gIzc0qedHUQtk+\nB7ORW+d2Wf9PdlTt3LZazjzw3xu8A+02IBsqwzJJjBIedDnRd/oUqA==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2WEMzWTMxSTdsUUVNYmNH\nRUkyQVpRWnQ3N3ZFN2dleVJNRmp3VENWaHpFClAxSGtqRi9GUUdwMWgrbzJLVkxW\nM3loNU1rNTFiUm1tMkpWQVV2b0RZZG8KLS0tIHNuRGtZMEdqaTh6VDMyZU5udm1G\nQUphdzNjU3NQTXBvQVpVeWczcFNtczgKjDN9tdNkTD1PES0CdB3aclsuQr58EGZC\n2dOpw8XOOZ6pCoPeaoLdZKv/prtSCdfwW4NKcKKWc9NRd79qg63WGw==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBESU5DcG1XV3hwb3VmZHdk\nblg3cHYyVVJBWGcrb1lJVEdnNGFzWWtPWUY0CklOZHU2ZWNoYm9ESHhJakl3THQw\nMk1XS0N5K1d1MGdwaEZ2Y1gvZDJqNEUKLS0tIHFvUXVNWHNPZGpTUVBnWWhTampG\nc0tSTC8zUVBuQjN0VjlNRkswZVFJaGsKSZ99ix3CP3IQ0m0GYVML7fa3R0gD5N7z\na1xwlW7e1bSEwMAUyPy5+E0alvVdC1nP95LtDyyPMkSXuiNJLbV07A==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1ly2endyt0y9xyddj6yuj4nw6fa3ltvzlvew4cr4lzs6dv8dkavpqadmyxx", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFcGg1L0w2czJCVit4bE9I\nRWs1UXBKREYwaGVNS2gxYUZTUnc4M1lXSVZZCjg0OGw2dk5BUjl0cFBBWjJwUkRU\nMmxYZWtqRWZKQnhVWHArTTJaVlpLV2MKLS0tIDZpWFRYSWF3TThSSEY4MEM0ZHg2\nNVVpSEpSS3d3YlloVHZYTHhhQkwva28KHcZko+q7mRJk+eDTSVyk3wYG8VLfnUJs\nH8uOoFaIwH5sf3K+1/LvUEGp7rEgbqHCTgRXrylNB2jQKq5bYkYlsw==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBVlA4WUszaWQ3OUc5RXBM\nU0VQWVVKeThtcU9SVTcvdi9VVGtGRDdqWTNzCkRZTXd1a045ZXZWUnFUaXUyNGFM\nU3lodFRtQjVudlFHVS9WMXFVbGo2bk0KLS0tIGVKZVZEQ0x1ZnI4cHhOK2k0elYz\ncFkwMWRHejQ1eURORnpaekNReUg5U1kKKghYvqmOysmJ12ZXjeUomoqc0O334Hcv\nnulvcj1NSwhVLKUZ4JalNrSNo/4xFcdyi7hn2d9DlkkU9KJ9OcWBOQ==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age15klj4t7gpfp69472mne4ue62pp6m4e04dmjyw7yf30qtqd3vl3uqjmcyxm", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFOHRxVzI5RllzUzI4MnNC\nN1IrOFRGdTQ1VExBYUozNDNXUTNpa3dPUTJzCjFvaTRON3hJd09zOVprZjExLzMr\nYTNCWklKR1Q2UVUvNndNc1RyS0ZPazAKLS0tIFVuZ0dYOWxaMjFYajAwRSs2UzBv\nUDJGcHUxSmZCem1Sc3BmNFV5WXVWTUUKkiqZwgj6iCmAGW9VGRVU+wuRuauDaUjF\nVorMFhPjU/Ukb5PjaGzTH2LxsfW3Z3vH1S3iQM3xSRgRagW2ut3VHA==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaRmc4YlduNzlaK3VXQVFt\nRXdHckU2TlRLUHltSTRxV0Y0UnBJTkFwdm1BCktBWWIyMnZYZnFvWEFRaFd2d1Vs\nc2VVbkY3WlZhRXN4c1FJTnl5dFBTR2MKLS0tIGFKbmdPL200Y01mMzZObEFqZElq\nTkpVb3AvVWswdkNEUWR2V3dXMHpMZDAKFUAb6ZxAycB4PbjUgePEWmUpbWRomU+A\ntpFpU30ZeWSicsRQRbzm340ZmtAhVk0Ud1M2N3J0TcIpre3CghZ9lQ==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1k73gy5em3js9zklnnkzp5hme9k04lny32fgahmzddknjw5c295asdyr4x6", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtdUlnZDlvaHVkN2ZDYVBq\nVWVSNXhHNVV5OGNUUm9RV0VsQ1pHNld5VUhZCkloaVBWc09jTnhLc0pqbzdmRW8z\nbnM4QXRnSXBoNDdvVGs2cVFYcWZ6cU0KLS0tIFZLUlIxVjBKdVBJaDBGMGVJT1ND\nVktFRHQzNnlZSE1BRW1wVFkzWlZ4NTQKo2CcfWKQ7wdiqfmaSokCCpf4CZnaeTBX\n/jb0saoV6Hp0n92mi/60eZIX95wWwGe4NAAisFFD+UQGWSCukm18Mw==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5ZU1vVUMyOHBXTm5iNUZz\ndWI2TVZpQnhkdVc4aUlIWmpwbUtwRXlDTkFJCmY3bVZ2ZmlWVEJjVy9oeEN1b01k\nR3pTUUlFTG54c0dyWUlQQzN5TlJFL0kKLS0tIDZGTGlHL1FoWC96dUdJS1I0UkpX\nVWowM1dmVnhYcEJXaEQxTitPQmsrbkUK7R+HqB6ohYcS1rQDfIJ5lHHcqeYcpRTT\nT23fTqjGlDmVUzDUdUISZeaVtTsaAwtq14YWdi1UEzwbGBdUQGmb/g==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1cmzh82q8k59yzceuuy2epmqu22g7m84gqvq056mhgehwpmvjadfsc3glc8", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBja0dhd1VzMVBBcFBTd3dw\nYlN4QUlvREhtcnpLTjFQVGNQV244T2JnVlNzCnlwZXI2cWZhVUZpTzVveERaZ2R2\nR0Y3RVNrUnNMNDM4WlB0YWF2bWxzQUkKLS0tIGFEemp6emloejlneE42UEY4Qitm\nK3ZBdFlVM0dIM2wxWk5JZCtqTUhWVG8K/q+YNSZT+HsqYTdxyB2FrrVCpSywDhkf\n796xAJjeXRX4E2ETN2QvHQ6EGG2tZFkQzVcWGX1ozugi8ZZe1mJP1Q==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxL2pFNG1JTzNQUzN3bDJI\nTi8wU0grcWhQcmp3SzZUYzdqZmc0TGsrNDNnCktwZTBYZEg1dnZsYXhPU3NtL05I\nWHZtQ1Q4YUdYay91RzJaQXVRWW51bTAKLS0tIHNDZ0UxWkRVQlE0L3JjaTZmZzJP\nQStKaGFISEJEVTdQSVdIOVMzNjdhWVUKbMH8jkFLlkvbl1e9mndT9civieCuH/z2\nweqBunzI9ANMqQvBH0HxWymUz6kc4Rg9HpChcLx5be2M1URl1VUTiw==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1wmx8y2hs83j2u5srdnfxljrzxm8jtxl6fr0mq7xf2ldxyglpzf2qq89rpx", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUMzdIVHRFbUFrLzlISVQw\nbG02Ukp5R1dlNVJaZmFpZmRSNVVpd1pDb0Q0CnVpL2JrMHRyOGF2bmVqRjNCc3cw\ncXZyNmxsZ2tFOHBjdGcvYnplcDVKKzgKLS0tIGoyNHI1bVdOcTR2MXhWZGhSTzI0\nSE1SdGVFRDVac3pLSE1TQ09BaE94aHMKMN9YNj4wbAdlR4VGoCPYVrEtQeFcFZh+\nWfhl5ra2R1yB+JNkxgf0jDKJUlEjlW/DKl/FOJ57g7lpNhPfUrMGkg==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJd21EYyszUU4xdnkxZVRT\neU5FMXVQcEFtM1VWcVBHK2lVOUdkaHk3aG5zCldkWWx5SHVzVWtKRE1LUUR6ZDRF\nc3Z6K0QyYWRiekh0R1pvSTR5UGpLR3cKLS0tIHhGWFppR3cwTEVTUUUwc2dsWUZz\nRVdETzJ2V25LUTU2a3AzWFFZUC9GTEUKrF9QLJEVxxMG0iJULun2QKmd1ATQUGlu\n8nnEWHOpuI+tZS4VM7bjs43fFsN/D1dwA4LFlVfYBNfH0EpVs/CjQw==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1mjgw3nxlnqdj04mgjz3wn7fj2nl2nxla4p2r2fn4nkvayfgp09pqllxzyh", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZM1A1VVBKTE5IOXlqRk5T\nQ3RJOXkzdFpkUmIyRXdRL1ZsSjhiSGxldWpNClNJRC9sbGJ6SVlFVUdWcXI0WVhV\ncWJTckxteGhkRFFqZDNSL2lIMXJONXcKLS0tIHBkajc3dEFQZUNEQ0ErTXlTZUFr\nRUJ4SGNuTWJIQWNNMFlpc055Z1NxVk0KPt1CoTXsvKs+XytsIgkjqxM2fQLJmC10\nTS5PQ3NgZhy5rT7ejnQUQeb2KDS/uN6dCNrWHK6R/OLR3wKzzASuGw==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5anZvRXRFRDRoTFFlL2Rz\nYU1UMWlmZVgrMGpqNC9oK1VhQ3lDbUNRVW1rClJhNVp4NlczWEdWWUdDa3dqSUhn\nLzQ5TTJyZjFrOUtXTTdUSytBb1pCcVkKLS0tIHp5NCs3cCtlNnlFUHN0ZkdNaWVs\nM1hpVlI3ZTVFSUFsdFBVQnM1MlJOUzQKLjYXNFjBkCo/+Sy+/3gzWPXRhAxtvae7\nJGGNUk9AoTPM/VSiKEJL3F+X+z3QvoiMjq/+uLU2hKMlYOH570X1Rw==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age16vzhcvz8tyxj8e0f47fy0z4p3dsg0ak4vl52ut3l07a0tz465cxslmhevl", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3WnhRTjU4R1R1MFJPRTNi\nN09LM3dMdlJlQkN2WnBmQWJPQVg4OHl1M0dRCnhhZVkrNTF3NUVvYUFGN2tmSHRT\neC9yc2dOUzFkTEV2NkJubElhNm55MlUKLS0tIHJZRnBxRWdBbWVUOUdJVWdwY00y\nOCtqMk4ySjlTZ2UyeTZMRHJwcktPemMKdOZleZmklSOQTo4fnCzjm4fC/KReWTzn\nJaS6FzbAWc/SwNIs+c/UHfCAWTQkX5xma9uzLOdr0/3cuu00+k73dw==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvcXVLanhqYVMxaTJ1NGx2\nNEFvdHRFWmxiS2dMUCs2S2N1OVV6N2IzRHhrCnB4TWZUQ1BqWHVTMVBFeDlSL0tU\nYmd4L29UV3ZVUGk3Snp3V3ZpYmlSdlEKLS0tIFVnYnY1WWJ2dHlWT2o3ZVV1aDlB\neXN5THRUNi9QR2pVUC9IclFBa2gwV1kKghCqpelZh84rvtwH7BjPWma4h+0axaUR\nntG9Bpoya3JzVFgyuae/ljmXf4WQvB+OBhh88GiHwXqX4SpH6udvrA==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age15cx90pnp54xp5gxlt02yn9j2pz968wp3l5ukdkx55xuecp34e5pszjku4m", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEWWNOdjJPNzQvRFdRc2xL\nT1FHM2tpV0tDSUFJdVJyTXk3cXZKWm5Cd1NFCi94dEVOT1NyRDhlSHZGRVpmMkZS\naWJLdzJMaGkzTnFicG8yRmJCdzltR3cKLS0tIEg2ZGU0SWFTQkR6aUdzc01VOEtS\nckhkM09FWnBqdkNVZng0ekVvWHdFNW8K+dutcLgF/Oq35B33/vxAiePxCLlcvC6H\nH/doZRDyor+93hWpC0nXJxJiPu3Pc0oYznDK/gRWYTnynBu2GP0adw==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3NW1lRFFYZjFOUTFkQTF3\nTWpqdGx1Y0lncjFxemNJNmpqN240VjJtWFN3CkhGdnNOVGF4aGdlL3k0RThOaWN3\nU1gvdUQxY2k2YXg3VTFwVTlFdWRSYUEKLS0tIHQyOVJOcjZselNtM2ZRWjZpQlJm\nZ3ozRjdmeWtHNWpESXpCZ3VtK1Nrc28KM0Hjz2wjsefnqAXqcqhE/kCJVXR5r4CD\n4VnG1bl4MV5dcaWooG9RBTgU1eSnoa1CQeH1SBS18ueA6/kRF+RuYg==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age18quey88vge7xytclg2nuq4ncme86dg04lxwczqxczmdchnjg3p0saehsnh", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzdGp0dkxpNDJpSHcvRURV\nMmQxcHJiWHhhNWlkd01lMVpCZ0greUZoeUQ4Cm9iQ1NUSHVIN012Vy9lWmpRdzJ5\nNmFwT0lxYWJyNHFDRlhEbEJDOGFYZTgKLS0tIEJGUXM4dlMwRGhoNW5JRGpSZElC\nK1kyb0V4MHBaNFRGZGg1dk12MFNrNGsKKMAWhhYHwWe+wXweyZNOldNKZbN93n4A\ntgNSFIpgCXYHLEryxby1nOZfyUVFNrCFdgN3DQQNy9KzUrCBuVb/tQ==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLNHJtSGhZTkR3ZG4wY2NE\nRHozK2cxR3pkZUl5TXREVFRma2ZJN3kzdmo0ClVLb0xXZ1pLVGJ6eGlsWmI1QzNo\nWnRNMTd5N2NYY29wQlZNOUtvMHRVNEUKLS0tIGU4QU9Fd2Y3aEJYT2JvMFdhRFpj\nRmRqRno4RVMzQ1ZzRDRMVDdFQXpiMEEK2QJ0gKd3QOKIVWYfFMbDCwmhPyBuFXG0\niqyCcJIyut/XzoqMTIuyyNWk+74ABdwj+vFPuq0nxnJUwiwnDrT+lw==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1ax5hqk6e2ekgfx5u7pl8ayc3vvhrehyvtvf07llaxhs5azpnny0qpltrns", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvbTFqR3RScWxnTFR3dlhv\nNUNEVGRkUDB4L3J6ckJIMWZCWk44RjdpVmxRCkhzZTBuSGduanBmQWsvNW5XMWQv\nYVZmNS9FVzN3a05kUVBheDljYUUrcHcKLS0tIGxPN1dWVkg4NUpnZGJ6VWFJWFVZ\nYnNvRG94MmFxYnlDQ0JyeDNFQldzdlkKsp+nYSR6Lxq8b3/dpMO7uTbNnO0Bva7w\nb9s908PLaZEN1jywEoba3yq743vuEHCKQWFIfDtsRcbNR6Yr4d2eGw==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBSTVmQUJ4THA1Ui8yMGxM\nN1dlbUJYSGxycy9WUTE2eSttSVYvR0RIL1VRCmpKbHBFcVBld2lKb1lqdFE0TkJ6\nS1ZCM1BYS0RLNUwzcEcwM01aOVV5V1UKLS0tIE9BNitEelVidDdzZE9QbE1Qb2hk\nWVY2emx0Q3BLbkNhdWJEYys0a2ZyZnMKqGe5ckj9cK1LnbtrOfPJPdhJCIBm2lOt\naq8nl+REJ0xFR2Pl4SMhIbqDgo5oV349OYQfRUBMhVE9XUUa5TsEAg==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1c2enwel9un28dcs4wg0vcyamx9a4a6g3walkhu8w5lqhmd804paq9d24as", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwS2paRXpLVk5yQzV3Zjly\nYkd5Q3NTU2xCaUlvZFpPQVVxUm5BZldpWXlNCmd2QzVFR0NuZjgxb0R5VDFmNHhN\nQnFhRWs3NVhBY2dlOUhmMmZYVytaOGsKLS0tIDUyTi9BK3l3RGhLWWxJbVZNZUV5\nWS9pTUdsUTJ6YklRNWhWbG9KVllZSTQKUsrU53r2xbnheBj9aEc2V2ZwKICFsU+5\nVXxUdwwmb6WTE53kK/yV0zsrWTDocb2/4e7qBUqnMb9Wgk2VHvhe4g==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2026-01-02T00:59:46Z", - "mac": "ENC[AES256_GCM,data:NJk6fM55PTbWRIfOyTGaHVHCiQeDQcp/V5QxGkf0E7/+u4aUIyWhrkHCORmv4dLmI+bfPBiGOyWWvQz7NqN8Cx40M4e+F7nkvAuDGGnIY8gTw+Qt+FYwSbxcFJBmTQ1wyw99xhvpKzl10uJsP8w3wqXEntC4bLQR9MDC7LlVeTY=,iv:p9MZvnheBxGT+EoZjboDLWaxlSWaMHTTADgPX+uDU5k=,tag:wsiEkpQrE88x/WZM7DhsFg==,type:str]", + "lastmodified": "2026-01-03T23:44:12Z", + "mac": "ENC[AES256_GCM,data:7+fRKPv0JkwHiWZOvPsp+gYHaDN2Dfdrm9cWLY378cA9xqcLpim1TvxeG3UaQQuFV6KSBiU7jBlZSOUUToXSG9mBL/pcLsErBsnqg1Wph7mK0JLzKUxPXJQIlRzZh0KmG1GCSHGQBqVQjVgyw4qUfmUdq4QZ5k5tWcQK3yCpuQA=,iv:1Sb3CkP9ad26vQjCpRLv1wXFtEHZL01EObPzstwY4C4=,tag:k1EC+zR/j/HZ1sejHFXv9A==,type:str]", "pgp": [ { - "created_at": "2025-12-15T21:53:38Z", - "enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ/8CWW8rCTmkuQS8SdFyDVBOu1xj4lQZn8hUVDVBfExU7EB\n3c+cO8DmvVBMCzwiwD4dgkektoQ6UqInEL/beYKc4MPUUZaXLHDXysbL5Z1iAHBZ\nFPsxgE7BmPManamCewqrcBYFeHTGVzSeU6FqZDkpNkzAkjyktq4Lj16U6JTzJhjV\nw+IiU7Lg+MBym7POPYqqq8EVGtNKWNPA3T9i+bYXirwPjyNbRjxghe76I8O4zWsQ\n5vnQZhkkwCaavBusNdg0Dffl7UkFDhFCjXB/Jgfwsb2JpTxjvWgBwsfb2qT7EnPA\nOvdi+wM3nyhvQM1yMhAoAXTjlJRr/coEw48LhvcX+u+TUr1nyrTktEzcuEFVW3z8\nq+TCLT9c87GonIJOIoGaE3oUHiyVtsYeMGBpIVAW2H9eA61LtOIj0/NtO8YDGdAr\nnO2G+LxEIr1ZEstNmKaiJKkrfmgYG2fl3zu0bZS4Sm9xuwOsLvGxc6e5Bd6Q9Aw8\nOllbWoeF23j5NLwi2JXDJ8zUxby+u/Q5AmxoyuFsCgMzKQG6F7VCkDoVx5gyetMl\nQNfrjElPOv0e0wVtHzf7wqkey1ulI25P6FD4ZoCaLYLU31eTA6d1vRCX0GxWs0Tf\nDiXZIVRvONk/2naH5rN6Qz7fT+Ub5g1ZhRB0Z9NK60GXnYZhQ6FnuRyWpv5eeRyF\nAgwDC9FRLmchgYQBD/wIIRbPDxsE1uJh1/PXlRPGu9G6WBl3FuiuqbimzHFKDApZ\nzw4qVwiZeVYmxOC3ZokA23Oe+hIDSgjIeVt94XvuentxmblOwEL+Mr6qpwQEPYvE\nh9nBgGWpwJzVfZcrtwVIoJcv9NmkYPMspKj3cgCCYZmbr3PbwNaaAmfn0h/FjGcS\n0pjEGlJAr6wODsxZBJ7mim8LOzXj2Ep+5ivqT2GwuIAeR6ahabClanMzoq/ayHKk\nAtUKBja+UZwRKFh0GSir9jmICDNrrQIqTE0d0MFQicSnjrHus+mHF1hMJkm6Zw35\nypm9zEbnSnVx0DFifSTth/69h63i7H3+CW7EqkfZ/zWpmPa2D6wg+SmhLnsWpclz\nJPDQOwiiBgFloJ+4BDM3vscI8KHhWcrRTuwD8RwUB/5BLw1WWfQ+6yOK9lWDtvaL\ntibk/iYz+fM6y8VQEHwF1S1EcdHW8VlcE/xPTS4xOukShbJmMSW+0Srhm5swRa9q\nty+txwUcU3w+IiLpxp34GoaxK3qz3OWpF5yAG6dMqZ5q/6u9PcuDuMVkMW26gj31\nxryWCoemlrp6DW3Gfmp6EeyVUNVbiJdXmU4jnCjWViQei3AtQ062yES8b/HDUyFg\nVmPfcTN0hpWPBxQGWGDTvDC/LzK9DeHLVUGhCoUlvBwS/zDbgAoo7xmUe7IqkdJe\nAT0zalGWoZdsebqWwp0txgrsgn17VzILFHgvmgU7NgjN8cTwiQ5odqAEfkzZQ/nx\niEfVFYe8fmzQVrCcDsCcxGBOavPTFQG5HbY5ssDSur3QfqKW7PgkPztPl2IkDA==\n=r685\n-----END PGP MESSAGE-----", + "created_at": "2026-01-02T21:17:44Z", + "enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ/9H7LfgDWyE3F7SrLQaGdx8rNwWy8olBcJC2O7C8usiBUH\nCqKNUUAfXaOqsNoZahWES2KNyTZgARGW/7lsQU3ISrYD/gxn45Pf8HyVXag2qbKQ\nSmYii8HXvrST+XHU7aErAZb293ByBSBvlg9JfQK8lNTKccvIKLLHTI8Xo/EkjUtl\nvfRocIPzesBnOBxTwvuWvnI+nvcuvael3UoKK9V9HaFBrS3i9U/z2EROaBOY+LI8\nCNgSaUNEGqeYh7/g3hSMzLWicM+3YS5MnlVDJIaERz08XvjgAfnqlmZPINZGCKpg\nUY2fBJKkG2lUsx4dfs2XcoIayygA9IIN4kPztI8jDL+KTh2he2iyfDEzTGqZ+Yfr\nbWzoUNxtCT5FluVYLsAUYBJB2TZhQJeNHpV+dOLzs0zTRbzh0f6dQQEs6u1W4ZVe\nRN8UwO+e35Bcn5sJ48y6143BCaJGsNwKg8wqmhOejUV6F8di9nHWasXgaxZKPbnz\nxIyt8E+PvWIYYQHadUQ0SIL5TMWU4csyoDvRbpQxYPVMl/Fi6v1khW7Dw3thhOPD\nXAygAQ3SDr2bzB4ZlWAozx9D4b2jgPk1qMHMHmypf4vdTqxKVs9UhzLRLK4IYDKB\n91drnFsAPhOzgx24CPEZANZEln/IlRmIFPReVCT+8sAvqDU+1CROSvR+OLqwfPyF\nAgwDC9FRLmchgYQBD/0dgT3VStJ6BJH29XYsfQsQcHSGgYan3Ecy6g02d3h4Md1r\npJN4s2THrlHe4LVLIyZ5xdetrxSvU6uz5TM2jAXL6cYLEFyr7FqrHNWHDXcbEiE4\nRgtVxV0P0c69skkVnBSObvc9drD/m7jbAy/9dsTs/1Xij1eAgvHlcItadAQVKCYO\nd7E5jFJfVmtQQ0VWqC6Y1i4tb1J/UKRGUG0T2oP9RkXPdCctVMr8J5DwNIw87p2Y\n2GF87yDM/D7mo6Gk00aeOYFPej9qTQHNo0e1xCw30cGOqlGQpcr+3Fc6hdt+ww8e\nPHVbR7ZA/OifnbBk+Wi1qqIlO4+FdxTHpOK8lZP1A/B2XtJsrmWGLPTHHw2iiIR4\nahPpsBtxOyGZXB9Qr/kTX+uNUQOtFXVbxi0AgnQ3W+UkJlpSd5BhxeeN/IqC0Xsd\nvzhv8A8evy6dEwa4eoDPdECBfHfcXQX7Cin4WFef1Vr/6r/mL4OvY+yeMRmZ0J+O\naEPeP5zX3u9YBZyjay3daLCTS2Jqoh55Vp1e94Hzi2CpZexj+tvph92CHAf0yJz/\nIbJfO1VXSMBnpRDzzM+lSGEv3RNk5OXre09j3kThuscGqXKH4+48qbhYBLr9TkCB\nVwxwYijDEAst0XOky+RXZxtR1muAi/hA07H1jZK0lMJYv26T3SL3pDSheMrxGtJe\nATYtKOMookgjDuzsQAthoIL+bV3Lx5yFJjF+phwL5vqTLWa0xj2IBUSnmXnUgCa7\niRLsMPrLG7qvX34Mr7HrOFRXWQjy8SdmU7PHgUyBAyK8I0JFl+mzF8x+fbRYow==\n=gdhs\n-----END PGP MESSAGE-----", "fp": "4BE7925262289B476DBBC17B76FD3810215AE097" } ], diff --git a/secrets/repo/pii.nix.enc b/secrets/repo/pii.nix.enc index 4cd6a2a..c54f933 100644 --- a/secrets/repo/pii.nix.enc +++ b/secrets/repo/pii.nix.enc @@ -1,62 +1,70 @@ { - "data": "ENC[AES256_GCM,data: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,iv:4ZbxVxZHzxn2eSqP8h8eV53IV9J0avHBg1R6/TgAmtY=,tag:SqndgxyiwbD89LSrZBMnuQ==,type:str]", + "data": "ENC[AES256_GCM,data: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,iv:CHxvIxUy9RNlieC17BWfSKFqz7wHvC9epHnBnaHZFyI=,tag:TSxK0lMVpDTo768ZWbJy9g==,type:str]", "sops": { "age": [ { "recipient": "age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzTXhjVDNLUW5sT2ZsbXhx\nRENRREhqeVp0KzBIVUE0RGo4eW5HZ3dRV2pNClY2N01ac2VscjRiOUdtNVBnSFg4\neFdSekl2UlZZekVFMXdVRVBnbXI4TGcKLS0tIG84RXQ3bXVxTmxXQm54akhxNG9I\nSzZxejlwMjVVRkFVOEFKYWJ4RFNOQVkKwUtbMRKa0CJYCa4TzHwMisw/mBCGroZn\nGnK489S1W833OkLtLApjsFowpoHpaizPMcrASTTkc7h+OtQ3yJlMig==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOU3VqNFJpVEFBN2lwWlNS\naExNbUpMMWQ2Zm5kWklxR0dMOUZUVWNhYWxrClFBRkVFUkhaSVlTamxhRTc5d09H\nWW9wVzdxTkZjME5pbVVmUnBXakpaK0EKLS0tIHFIY2JwTDB2REdqWHRSQkFoaGE2\nN3FWbCtpUm1SSFg0b3BEN1ZwUEhINzAKFjA6KD3PK7BZRYkHLSs58ffMHrCwhvy/\nrF0zA2UKhIBN1LvYlyDdO2yZSOCK+0iwEuvz++VhDm1UnR0hDNu8Tw==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age18cgqlely56hgmhscllkmafwpjdk6dwep6ej3vkk97dzemp8jtuksqrrjjl", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoa2F5ejliVW80blE4NUwy\nTUdCamtkZ1hPMk9hQ1I0d3hYV2o2R0p5NVNBCmQ5WGZLS0ZnYzRUTk5rc0JKbEQ2\nTEM4V1hNdEhzWFFJbWNuSUpVN3ZTT0UKLS0tIEU0TGlNYVJZV1dCQkRHM0phYmRH\nUVg1bi9IQllUQWpkYTA1bGRyMWVIRVEKPiZdGYR0bxk2ldQ/4Ce1RcXyZACcCjD3\n6oDBe1DT7mPHN1jPertICLYW8Q5/LBRX63AJxZIi+epZMGszI4m48Q==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzcGFhUWMzdlpQZnpxejBK\nUzFKcXFsRHIwdUJQdmEraDVJNGJuQ3RqUFZrCkZNVDNIZE9XSkxXV2UvaFB0cmQz\nUSsvUi9VRm5VSVN0NklqOHZhdkZySjgKLS0tIGFYREFxOXJrOFBCa1pua3oyVE9r\nS0l5QThvZXkwZ1Q5dytjNG4yaklpbHMKLVslGe5lj+ED2496KEcb8ccWW5YqF1qG\nSJGwZf6xRl8cLsbCE8qfC9zlZ9DDc63U1bgLGgqkEvYnmZ76BX6GXQ==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1T29EeXY5cDA1em1oWjhn\nYXRuci83ekU2d21ZMFc1R2tPT3c5RHNXazFNCmFYVWNwYXk2Q1pTQW1pVWpPNkV3\nb0UwSk9BVUJMMTFKV0xxQUgrNVNmYUkKLS0tIDNpcW55MTF6a29nd1d4WHEwNTZh\nWDBNcHF4S1hwVzFTaTVycHUyMnNFaHMKCJDevUKtn46qMNpNjTIctBVMCLs5lH5Z\nfU2rzvwIBxwn16NCOAInRxQEOASYITYo7FKuMD7W+3eQf0vAj22LRQ==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1ly2endyt0y9xyddj6yuj4nw6fa3ltvzlvew4cr4lzs6dv8dkavpqadmyxx", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnWE81MW9LQllDQTZ0OGh5\nRDdCK0RNMERJTFQ0RlpWYjV4RkU4ci9waWhzCkx2MEh5UmkrdUVWUmxGN3J6c0RQ\nYWpUdGE3T2dWNmMzV2x4MENYYmgwZkkKLS0tIGlra0RtYlhydHJCeUxFekZLdTcv\nbk1wOGszc2xQcVhUM2ZzNDBqQ1NzQ0UKftq1Kcxi+GHGf5SNswuprffd2SA6kKKl\nH+I/btSl+Sl9GTmTu3HTkAg4+Bux6uJtBAGqWyTOfRWV79Z5bQBNwg==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlZUhxUDdETlZCRnNJbldO\nU0NiV0hRVmtNYW5TWjdvOThyS1RSaExaWmdzCjJ3S1lXVmlFMjIyUEdad2xDWmlM\neFJOSnJSc2ZIMEJuK2NLVmdXSzRvcG8KLS0tIHlmZTNra0pzVVA5QThhN1ZaY0lO\naTN2S0VSTVgwSzBVZEN0em53STE3Q2sKlaQp9T/T7ZRY8FLB7yksMOwIfRWs/s7G\nPk3JnpuptFehhI/FeYAh+0fznBuTCKjqXF9X96a6RIFIC44/nKlfxQ==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age15klj4t7gpfp69472mne4ue62pp6m4e04dmjyw7yf30qtqd3vl3uqjmcyxm", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0alBqQjFTa1FHOEU3VkZu\nMjc1R2diZzJyNHNLTi9MU1czdy9EVHpGR1F3CmdUanRteFRPL0R6Rk83U0diQk1F\nTVJXWHBMbWE4R3pob1pMdGtoV3NMWDgKLS0tIEZYZ3cwRFRJdERUeHYrQit4WGl6\nSTd2cmNHNkFHSy9DVjF5bWp2SVBTd1UKwx/D3B8UWQHcifsOxCDkpFsi4KVG82t+\n+8Yw1X4ls8h76Xvgvx9F0QbmCw7DXX4cP1xYlqIQBf0N+vMo9shBtg==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzdVo5cUswRm1yS1BWU20v\nN1RlMkRXR1dhcFQwdXZhUVNWbkVrb2RrVmxFClZVVDJ1ektCT3NmYlk1WTBXVGUy\nWllkOTdlZ24wMHdKSmUzdmFMd0F6SEkKLS0tIGd3WGdueEpWTkNxQnZrbXdXTzhB\ncXVrNk43NlA2OWE1cnpqWmJKVktsNFkKwyaRDz53nk8nljSnqN+CXY7J1f2LmJls\nXfbOZfFH7Ayoelv0OCoWCm1ZfD5QLnTBoCZGCUw21r8YuXzu5+maoA==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1k73gy5em3js9zklnnkzp5hme9k04lny32fgahmzddknjw5c295asdyr4x6", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvT0d6Z2dtbm9vN0RweHVS\ncWhDb3VMWEFmQ3pGbVJzYU1hM1dJK3d5V0Q0ClBrVG43ZHhWQTZPVHY1MVRDb3F2\naE9lMzdWM28yT0ZLZWZielduM3pzZE0KLS0tIG84eWpZNktCTExSL2tNclVJMmhi\nVDV1MHp2VWpUNmZDbDEzaXhkVUQ5TzgK7Tdlsyya9kRwIc6oG3FBywJ9SWAvvKy0\nfYkW/m8pE9y9mPj62rqnAt4yS/GrSvKk1za8PkB1P5ehOWtxHeo79A==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0dkI2RXR4aDlSaGhxQS9j\naXlXdjdscjJqQVQzblNQdkJxaWpSZG5DaGdFCmcwK0JKVHJZaDNzU1FlR21FUkd0\neW5nWHFhTDZNTnJzZFI1SEdTOExwN1UKLS0tIEhaclEvbXllRG5EWFBYQVoxMXBZ\nSXltdFM1a3Y5bFREVzhBRm1YS0orMHcKUrHg6YkMF20G+GdLI0J1pj1zLe06Xn3Q\nWwxgB6ctI8D1qs+0GMoXB7sOsfczgYtVt1hC6EvYpmiHW+g54GGRHA==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1cmzh82q8k59yzceuuy2epmqu22g7m84gqvq056mhgehwpmvjadfsc3glc8", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNM3R6VUxMczBwTGY3UUl0\nR21taWdlc1dpUnhOY1o0OFF5ZFp5TjNMQzNzCkNsbkN3SSt1TVFsMVgvS1FGaVZF\nMzlkdjkzbGVhR25HZmZZSThSUktUVVEKLS0tIGR4bzZRR1B6WVM2dHpkbTBNaEsw\nZkdYV2dnbmptb1pZeWJuVXRROXhzbjQKzranKLFffOHVcIhPq7oHn/KWGIIH+P8n\nBJAx54HVYVxWUH4XifkgDmYNsGrENOAO3RR3NZ5NlUG0FcTD5zP4Kg==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlU1NCRFRYUVkwZ1VMTVlx\nVStFYlBaY3NGTThpS1NYMnVSdzVCU29NV0NVCmdKU0dPM2lySStVOENZajVRU21C\ndmJHVkhqNWFpbEpqOXdxd1kydjNFTXcKLS0tIFI1QWdmSVRHaG8zV29MSFJhRWU5\nREt1THJJR0RrK2ZzWlAzQ3dobjVOM1EK9sczJcZo9sW/rlKczTo3PYRmgm+mJ/ek\nyRniR+IaC+cdiSIuDS6nz6XwGqIrTpBjizpq3a5uWTzwzscU+uMuig==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1wmx8y2hs83j2u5srdnfxljrzxm8jtxl6fr0mq7xf2ldxyglpzf2qq89rpx", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArMkI4VmRqc1paVG9lTFVF\nQ2t1UnhmUElkSy9rdUxUMFpDaHVQQWxFWUNZCm5Rcm53MDFNcnRTaFRxZW15STJ1\nZnErWTN5b1Q5ZzRGdGRBYS8wbWt0OUEKLS0tIHZ5TFo1RUhLU2V6Tk9tTEJSZFhY\nUTVxbGNWVmpQQVIzU1l3REh3WHpGR00KgJibUNT/pdv+Zf5EJaGEuiJTBYq8lyLz\nsjOLWTw9iNXA2bIPhk3PDGyttjcW2RrbPSU4cuN/O7w+ZMw//HWhYQ==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4L0VvQXk5bWNVc2FUTk83\ndGp2KzdrclF3bW4yQlV4emdCQkIvTmV3WER3CitTOVZVWmp6Um5NVEs0aGg2TFhF\nRWtueVluSUMySVBjYVFmaHlYM1ZhalkKLS0tIDl5ZlZ6bEpIZW0wQ0phbnAwbThV\nVHZ6R1lCZE52alJGS1ZVMDljQzZ0TTAKptXEII9sr9zkdAXJLLCKVd3E3pOsgnIB\nLNqoJfg336E2aquo6LCjtBA0nSBxHkAnw0FFz81Kph7zK+Z1+tFB7A==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1mjgw3nxlnqdj04mgjz3wn7fj2nl2nxla4p2r2fn4nkvayfgp09pqllxzyh", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4WndZWUVMdEU0NGlBTk4x\nOVB3MjFvRjJqekgrM1BTN1NIL0tYWlRlOUZFCkZ4emtCZ2R2Njc5K1RseTF2TUxY\nL2FQK2VPN1Z3UXZiM2Zxb2lBOU1CSVEKLS0tIGtET282RDhYNVlOQXZ1SStrMWNJ\nS2E3ZlRPcEJQL3l0Ry8vMDIzUFFiYU0KqjPaREHI1rP25hH0Gd6rTMgMjy1NId/m\nCC12d6R28kVq1rGNO0mJw+FJ+Eu972Q87Nte/zz6ndcQmfAmXbfxsA==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBcEZVc1RpbC9vck5zYmh5\neWxObTlpMjlpUFZYWExCUDhQU1BHS3EvL1IwCk5xelVyRisyZUVLK3ZueUdRTmxI\nWlhZSlJQT1RSZXNZNWlxRFJpenhvb2MKLS0tIGlxeWl4VnFXQ1VVMXNmM2x2WXI4\nejd6djF5d1k1cm1Kd1JuNVBiWnI5TEEKnjIih/AMCQOakcmiEpG4Fqa+yYDafML/\nSepnQsojq99JF6oxtGAa1P6ibmAIglRtyo5ypRRTVMm6LWt8Nul1yA==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age16vzhcvz8tyxj8e0f47fy0z4p3dsg0ak4vl52ut3l07a0tz465cxslmhevl", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNRU5Nc2E5ZWhZZlU3OW5N\nMU91TGttdXp5RERlNlNmcHkyejdsb3JXMTA0ClJKTll3RjhrcGJyLy81c0pkYzhV\nYUhnTEY1dm9wTUlzTkE5cGF2alFrTFUKLS0tIDJtbDROS3V4Wm4wZXNzRnkrWk51\ncW5MbVNFSEROTlpOUFJFTE9BUXlJYWsKZiGBXaFa0mtbFoIG8pTjVgSSms22C5R+\n8EQ4k0fffsX2Ua4RL1DLiUxyNc9ck07E8hbp3L2lHRYBr/3sqtcSUQ==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1ZXpKOHRwWVByVXpUdHBS\nTEJ6dUJJSUQrSzc3MHZ0WHV6ZnM0dzlwTURFCjlxLzVDTDZhbGVpL3pQay9Md2lh\nTStxem5adyt0TVBjRnhsNmR0NnhLek0KLS0tIFhlWkQrKzFHall6Z0JXWEVMY0tT\nR040ZnhzTWFVbnlXdktVWnNuY00yU3cKmNYw+zRsH+KvxPW5o+fSKPKAVbxiVIoJ\nLZNXdAr6NGYMgKmvhq68M0C0mbLmmo505qb/oBntbfoGZJtSULAUnQ==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age15cx90pnp54xp5gxlt02yn9j2pz968wp3l5ukdkx55xuecp34e5pszjku4m", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRRkV1eVNGdGozRTNpWEpP\nTit5Zko3bEZWUStxc0lESWhTSGgvRGRtbUh3Ck9ra1ZoUHd2dEs1NGtiU2l1Wm9r\nMHprYkpQd3NLMk1ESmROemFyUjk2azAKLS0tIFlLeGZBUms2ZDQwK3dlWFh1N244\nVHR3TDNVcVhidWxPOVNNTUZiNHdUYjQKpNrP38lrlmazwR4MELuJphY5Ci7ZIqx6\nqefmDlF1yVyxIwoALq+Rl5yOrwYWr0CFXZxYeqfvgdQ22E5+AyzDoA==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJeUVRU2hGM1RxS0d0Ykw2\nazc1MWd1ZEZweU9PRFRPRG1BblZTakx3WUdjCmlyZitaZGVwZHRZWnRrOGdSazMw\na25McWhRZ053Y2lRNmdMc04rNGkyTWMKLS0tIGtXRkZWVHdmRTNYcG9xZThZY1VY\nZ0gwQlptSHRzOUVCS3QrNkQ3aG9YelEKt+43DmQ0Zn1x7NIWl57eGxG3gsALxhMv\nImpMryrccmEV3Ddc2LPpxIaRYnFBJhTKDNOyuSOSD+I471PJlOu9yg==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age18quey88vge7xytclg2nuq4ncme86dg04lxwczqxczmdchnjg3p0saehsnh", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4ME5PVjJCZ2FWUWtHUm9p\ndUc2UXg5RmhZNGo3YUR6WjQ4WjNaVnZHVlZrClZVb2NZYzVEOUpjdENIV1VDSUVs\nU1JvRzN4dTRXenh4RkNQY1VObGpHZWMKLS0tIG9hUHlaWjVUajVmMzFUQWFnUVpP\nVmxaNFRHWHJyYjFmSG16ZnJIdkNkb2sKlpc81NiI9AolycNrGaiLDYUvRrCbsMUe\nlUxLdCKo70CEnXTdLr2emhcxNwcSMljDPekMiPWcIFt9ScA639pFsQ==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3emtuVmF1c1hnZFNtcFkz\neVlnbW4xKzJIVE10Y0NtWWZLMXRQNkI2L1JNCjhpb0dmQU5pa0VOZnNaejZSa01I\nRldSSUxOKy8zekpCQVZtUTFMOGptZ2MKLS0tIDJIWDk0OWc0TThTTDJvdkF4RnFn\nZFowbEppZFdBc21SNWlFQVo1bE44ejQK2YVQILlu2yxCkTdwAP7J25NOgSHeNgJj\nOCrH1TU7mjp6dlB/hxeUWDRCbmqHs9ko054ZdXrxY+9BeodA02B1bg==\n-----END AGE ENCRYPTED FILE-----\n" }, { "recipient": "age1ax5hqk6e2ekgfx5u7pl8ayc3vvhrehyvtvf07llaxhs5azpnny0qpltrns", - "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGNi96SEpTVU1wa29DeDdw\nYm1weGNFVU1kdEdZMmRZTEJCeWliTm5mVGhrCkZhbmZzTGZoVHRmVTE0ZFcvMno2\nUkhVNFU5RGdOS1dEN3pZeGtBbHlhTW8KLS0tIEcwQk1LN1dydEpjSjlna3BwYlBZ\nZjNwdU5leHhJWTZqRElGZERVbFg0SkkKR5LI86bCwuWnzzF/+sYgnsEdHSCMYwr7\nhEaK43fFnD1zUKve/D8NmscJO0VAZIt7duzdeMLv7h+a2ebSXAJ7fA==\n-----END AGE ENCRYPTED FILE-----\n" + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1NXlqMHAzUUZtbDl4Nnc5\nNmxISjVNUFJsNHlSUDl3U2RpWUV1b2phb0RVCkowVitwa2ViaEpFZUVIMG1LK0ZL\nVG1FU2tUdUFhNzRTeGI4bnNoc3ZuQ1UKLS0tIHZ3amttT0VkbkVuTG9yWkFQcEJN\nc0VqQ2RKb3k1Q0pkV0RjZEg4YTM5dG8KkUaAqAlF5hPuENwYWjVXFETePjtW7w25\nUUHOYmr+3j77FuT44TKYlmN4PJNAabbkDAcXDhBvtN4Ja41SGucy4A==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1c2enwel9un28dcs4wg0vcyamx9a4a6g3walkhu8w5lqhmd804paq9d24as", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3dGRuaW5XTFdPYlZMNkN4\najZRc1BNWUs1TExCdTAzTCs0RGpDM1lPMXhBCkxac2NmY1lpZmsvbzA4cEF4ekt0\nb3IvQTNrbk03ZWFKREhPZnp3OW5pNDAKLS0tIDdYYWR6NEIrOUtoYWxZdEJDWmdm\nT25XdkYvL2tXOEtFR1U1WlE4RjVGcHMKZ5MM7iTvGFi34ZoTNg65FHrJKa8SONcT\nCjdgJIcU/7wFbgTm295vvjfrXw54+pKUT3u9NqmPGVkA0o1rsBbZoQ==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2025-12-24T13:04:51Z", - "mac": "ENC[AES256_GCM,data:ktWaSwQTDR1bu9ztdt/KzvItcPxxCzhjAUqBKipe0SUZjxqmjGpQDBD1+p6dH6vSQEdcHDk9vaSMUZOMbOQYrQiEEqL+DLhAtRnc7zf8Mcd03uWjXm/4/J1CETKXlAIY/qsh6aHJoCpaSPOBnR0/AnP8xw7ae6c5j5wVYRQMmVY=,iv:Db56gtwzmAZuSFMAeyMTJLT3LMOTvDtc0CCCtCJzuRM=,tag:RtnhRlavbUxaSDMKp44VgA==,type:str]", + "lastmodified": "2026-01-02T22:08:10Z", + "mac": "ENC[AES256_GCM,data:dwn1YbVF8pXOItkLrdPHIXN3ZoXsCuoCcCuv9Cz9UQBKaIISS7xDpwVLbpf2DMxPmpzjq7cbJHTe714Zi7uN9t80wN91Kt1YKIsr14kOAuJkoCZPh35Sanqo0tL347C24E3PrpvB26RWGPqA6CrKp13swDPpljMrdhz9GO5bzo8=,iv:NiEV6uQXthBauTe6otoPxaoPNsaEKQ0JlzZNYna8eg4=,tag:mUc+AUMoDADysZCSin5XQA==,type:str]", "pgp": [ { - "created_at": "2025-12-15T21:53:39Z", - "enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ/+NHWvBUy/8BbZsCHEEXhTI3FC372TPFUSj6Scr1Nfv/s+\nYozQw+up05n2t3f4WXro1zpfrxZeXmRv/wrWMb56OvNjCh27ZTyx/wooo0aljFkZ\nYPK5+nk/BvGBVXopiwF9Kj9IY964IdIi0rahYyGgZOigE40e9sPVAtFWQLefMpFl\nWG0iOrMez/4IUeqWhTZaNHfm0uo4y/69hEGtv4GA332IgdOPIslyzs5KvrvZci8R\nmqn88SUGNsyONFtwvrY5NVN4hr9UzklhecBD7NPGjCU0xW2PoZEjYD2SHP2eAp4Z\nVwq/lMux6oV62t/nTced43wIyGni5luwToPwrgWquSF73WaO3PiMFHH/4MXJxGOa\n+EKVehatyxK8tGo/H6fLhbK19vFlZFLKOmHZjQAikFVOfIxQSptnVIU+5j2wajkC\ncaMYYoUwlQGLxuG1X9RMdbEMQZRwKw5GfxSd0LlSFOOnBeWgm9W/0UawIjS/TIs2\ndZJ8TbInPyCjUWSUO1HK8qV534LfbuFCB4vzv1fBBrt3wwZ0M+QT4hBg6PeOrxox\nxToqsD3KBmmcnInMx0LJ3e5rh9X9CtzJ1DKgZweDpcawpSNg/BphruILlAKx8OEF\nOEPBou9XJTcDiPuExqPo4WDwfELHrjEDu2xJGgpSWS0e00KPHmFqTs38l0XB0++F\nAgwDC9FRLmchgYQBEACOCDUxvZ9S0fzxRc29eA8JdVtGslGtneZlHjoHAyRjpYGv\nfKFGR/HcFNcdPCahQoYyv9BdKJf1g9/jOhmX5TdE63fIcZEOrdeKAWFBaLdcOjOF\nUxT4wpiYGuOVslPkhGXIuQurjZipePVnt1/VFixrrENyEWm4DqGmq1Nr9FdJtwhJ\ndUL2zlBd9/jBKHV6+AKfmI2ZcSXu9gNelhUU0keU85TRBSa8tAWSBgxEOsMAxP+G\ndb1dp1EVtlwgce99GH5dyodsMyX3sMfjhmf3y7EELW3mg9h4gY88F4bRmbQUaHom\nGypHWWjqz5gXSKMh5sx0Mz3TNiQnxu4AGZUtuFffx5RjYyEw0J7xxtTfiHhPQ3C4\nL0iJ30f3SgNJZWQX1Cg90BFKc3yOEzK3ePzVoTX4BCnAGMKDRnU7GCSM4z1X0DdF\ncEstNxeWSWZ7UzlmQXl0WjT8i/fac4WL6rC9DiWnMDzu5ckyJi+LTZvbmftaHQhh\n1kB8jZ6n6pRSQFFZENNK+v1gBaNuBrmLzeGw865L7CEp8WjIkTdgXrD0Y4LUJnf+\nIQy8caHmcn0RyHsnYYiuKGvbknKR8ehm2N491I0khtKmxN7mupPaN9zdNjuSrpdh\nUw8ZK2A0OuiQuuDljbsa1HuhknR2QhPLoTrdFxV51T7pgEFSCiKiimw8LGD2ndJc\nAbVCL+b3lArUcgevMl02e7GUn9AjXJhaqRFtI8T20Zq4fM2ndBCeJU9ipvAF6q17\n4qCtUCx0M5xsS+2sWwTwaUH867c/JrvP2DQao/AUb58acvGZ4jRrZRoWZgE=\n=GidG\n-----END PGP MESSAGE-----", + "created_at": "2026-01-02T21:17:51Z", + "enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ/8DSXgLzTxvatqeyCClZwBZ1fczXzy1eCVMRCtd49ci9Fy\nZ28xzCeWf78i5QAEr7UtrkfcDYXojsaiTROQ1VbWm+Xx5SP00sOTsmlMlz4qAVpQ\n2uhIEX+v14jkTh4xluqVmqMnq2cFQCNSoCEJfeUzYiH+IR0JOpltGAsewGc8BVPF\nKCl+/PnybTFeNXNvJV+k6jdw9pboAid6ehJVFW0K7iJ5Ine4fCsnlTSs1xTbofhB\nfzxUDZqLc5VpwCvlM/aN/pFGwGhxezXwYo5arFlcW5ZTpakVWlpBQ9+qF4gSTfTU\nfOaLnKexJnbEIpfK3IfmftZnoSEucs+DG5Fyxf0TNXnovVBk1Q24f3r3b25lL6Pw\nLCkTVc1WB3EVPDkLho1KGx58A2BTLvl8beKXoBDpk+rIFnABVYjqjJcxRSmqgkV0\nSgYxAghk+6UZs9iREvn9ruWRaYMJz3Zyda1cfdbyeqRDi7cT/C2jVaq7LLDSuUQW\nwyKjrAXaHtuNa5goUwPnT4hDgImekXC8N1qR5fzI47/ZoYymeCxGt9z8geE3hEg7\nw4jYcIV+oHFenu7RB3b3NOZwchUEeBFPGlA274oM3nHrtKpL3fclnV1hvHmNEB0u\nirclqP9EYh3DLfvtcXXTpE8Pm5/8QPVbFTIqcc3RMA7b+SE8ZvE0xgMC1PxJN6uF\nAgwDC9FRLmchgYQBD/47FReVLf9fl8aqqiDUnWz3/3Rcz+KUp7UisUgDrdi3L2wv\ne8mYl32v8qOPVPkKyEPIdjLfLhdcv1TxP3U6UT8C9TeP3Edile2s7MbuO6u1V1yj\nSuCez5naXww4KiJozwl6FtAZZZ9aKRLLkxsPcfItkCPKlxcKc2DvEDWKOdHBWB0L\nKYBf0u8bF2SUHR8ykeKybc5imMg3/jI8Vbu0gt8TfihU2btqwR7Pd291421S6irT\nK4/8VCsB4uPz9JxF91XfW5m86NPCTODcTB2C9VIWmdkxnk4jpQmv6qwkQqVKdApN\njJO8P4vgu2iB12zq+dsmx9W+TfSizocrCbuUBieq64EOx80QtZEgGc8ORf7MWq+1\nrO6iC0QjlUnAW4oRNV/Qv3l7NSm0pCA9XQL9x7PMh0f3rTYLajOrYDI7cZticAA9\nC7ZuVjUiMB8ykj8nfflOsXUJyHVYT8njeMqVEixEWehj6aq9eMx1VStphS6C/cbr\nXQT96ISnIG0fa6fNqEqzXBES1HYvd6Wo/jjH70wzNCWezvJ5IDANPkEhvThc+MmW\nxgPSK1+1UEzJGQ7uDo4Aadwn/Fym3P558icaEdjt8Ykay+gZsIi7ANVhJa0SI5tk\nNKAXvcSA6Dq9tnILre+oLewf6A/AfFdUesiantEaKjUgWQtad2P3iDqyJHtsz9Jc\nAXI8hZQSfOmDjpgjG27pTajjhmwNQ7XD2ttm1iHp5ho16zYtS8bDtX7bEB35YyM+\nFBuxrwcUNDD/mfi9uAtcjQm3x/IdLU4e+NL07GvSEWRU5H8pUBPcaOeUqLI=\n=pnj0\n-----END PGP MESSAGE-----", "fp": "4BE7925262289B476DBBC17B76FD3810215AE097" } ], diff --git a/secrets/repo/wg.yaml b/secrets/repo/wg.yaml index fe2e361..f7ad2a3 100644 --- a/secrets/repo/wg.yaml +++ b/secrets/repo/wg.yaml @@ -2,149 +2,170 @@ wireguard-twothreetunnel-winters-wgProxy-presharedKey: ENC[AES256_GCM,data:FZWAR wireguard-twothreetunnel-moonside-wgProxy-presharedKey: ENC[AES256_GCM,data:Y/EwbaVbGljiz9XZmr7+/udBfeaY+CLMfnKzekXP50Hu8ek8aA1/SKs2qd0=,iv:BijEDkfpRWox8CPwCoZLA42WihYIqHJJgSgOfsOGcG4=,tag:8+qEnqTsqyNdD4oVPiuQuQ==,type:str] wireguard-twothreetunnel-eagleland-wgProxy-presharedKey: ENC[AES256_GCM,data:dF8VPApd6iYKIZjBXB2rjIXIxyy2+U76TdyFuyUW0zSbtjzqn1ZKrhX4w/M=,iv:GqOHsS97di9sHqjndlq0EdWLcJ1EMLmDOnFJlBgTvYU=,tag:PdxEYlg3lPShUJYlANLjhg==,type:str] wireguard-twothreetunnel-belchsfactory-wgProxy-presharedKey: ENC[AES256_GCM,data:NAbVE7ysGDD6TT0RxdL6bTNloac4RBU1JWeTFqYo9PO6ZU2f/yq6aboi2AA=,iv:Ky4UvgRDEG1UgDmi+m5mHWHO+yUGzphQPYIuyAXDkhw=,tag:WP+/8q8jfitNC/rXN5Mp2A==,type:str] +wireguard-twothreetunnel-hintbooth-adguardhome-wgProxy-presharedKey: ENC[AES256_GCM,data:Gr9tP9SkizZOR4brFO3+7PqDC9pG5RojWa+xDDtqfZT4Xo6ZAN2002WGUXQ=,iv:Zj7oy/d/o5sNYTsyPaUQ9Th/xDuG7o82NpnP6TZzqeE=,tag:OI/DCxjJNpZC1C7foO4xsw==,type:str] wireguard-hintbooth-winters-wgHome-presharedKey: ENC[AES256_GCM,data:57KGUxn1BibZ+9H9mXg9EYmcy1JBX+M79ACL3Qt0XEMl0dFlk9Wq6cr3JTg=,iv:9QHdykNlUU1H0uco21zA8leQH73PAeL+xTVi6V9zx7U=,tag:6mfSCddnVGMBEAqCHDIIrw==,type:str] +wireguard-hintbooth-hintbooth-adguardhome-wgHome-presharedKey: ENC[AES256_GCM,data:zBfV5HMy3h6q7yEF6Cu7sCTONa8nJRmMDHgVFvHVinKmyj0qpf/WGfnyb3g=,iv:3JlNgsJHkE1EawLWIJaZsiZlu7pN9ymFQ5ZqdM7W+AU=,tag:pGfsh34HnL8mUhKyFkLniA==,type:str] +wireguard-hintbooth-hintbooth-nginx-wgHome-presharedKey: ENC[AES256_GCM,data:BGdVjcCyhrSgIIZtdoBUscCitNjBat56YjZOFx9Vao3vBMjoHFGY1WFV7zk=,iv:wxVClKJE6R178vCp/RE3PgBYYLIvOdSV97AfJagWZ8o=,tag:zbuMwlJYIKtV7ylwvgLutw==,type:str] sops: age: - recipient: age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaQ1VJOVQra2htZXhTQ1Jj - Q2xxYzBtQlJBcHp3OWdvK0phYmprNnY3S1Y0CnZ2c3lRWThEVnNmeGs2aGZXNlZZ - cEZaUnRrUFFZZGFRd25nTnBrVjhuc1kKLS0tIHg0WXBQVGh2eVl2TEl0RkFsNElP - dXk5NmlTRHVENHRjbVVRd00vYkpoTGcKn4+hUSvHLU6xJA4UJSPWadFwPtyfKMii - 4wFBv1pRwUmxehIpS8C2HDnyBVnT0X/Sv00n27I2K4Z4/WzYTXPTdg== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOcGpVNWtxdTJLYWwxakNk + dW5vRTNEOCtBNzlPbEpGR2g5MDhIYU5pWmlzCmo2YnRGU3FCZXBXUXNTdm5qNzBD + dWNHYy9kZTJwaWxHeFFmZFh2ZTBtbjgKLS0tIEliVHZIbWFFYUdOUDljNVNwUTNS + N0c2ZStaaU8wVFRKeTAwRmtDV25wc2sKjFO0FeMx3v5Zn4Ipm2549/boRorripM/ + q11ro/tNhsSt+GJ4FTQA2hnmRj+fG7BQuTw/ewXC0posKS5optxAbw== + -----END AGE ENCRYPTED FILE----- + - recipient: age18cgqlely56hgmhscllkmafwpjdk6dwep6ej3vkk97dzemp8jtuksqrrjjl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsTUVIQTFYanlUQWswRUg4 + bSs4ZWZYcnFMVUlUUFdyVnE0T21IVkdWbTFnCkd4dndFcWR1RXRLeCtXWlYvTUFn + Uk81dHZXdTBSekJkaEZxUWZnZnUwR1kKLS0tIHc1a2tpSmNOc0s4akRCVzVjcVQv + cVNDL1JGd3dGNnIxSHhNckFLcTFJUWMKzqsDS/S3wHigjHBSgztEmg2na/2fR9As + JxUe/ZSdEaMKDj2ZJ3EM8u5aY6Sp79aNypHsPcOXjhX0VoAwPtRqFg== -----END AGE ENCRYPTED FILE----- - recipient: age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOM1VWRG5yRUx3MGNMK293 - RWJTQmgrUVRocHVuYkYwU0UwZXFrRm43cUZzCkFmMU9WT0M0cS9JQXJIMU1VZ1pu - TVZhc1lFNklRNCtzTmp0eldVaWhqUU0KLS0tIHJNbXV0U2VoejRCNWlFMG1RK2Nu - UWNoak1BS3RIY0NGRTlxcDIyYVlHM3MKHaA3riInA4NMkWQDg69uxGdR5f5l6rm5 - vywj80Mg/6Cy+mFtGc1y9RqqsFx3IpBW/ECeGrwtCLXvBKOnZ0gaZw== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrMjVXZVFnTEczbEg1ZXBG + RmQ0c0RoZS9pWXdhT0ZVSURLVGxTWFBWM0FjCjV4cjVER05YZnFaclJnVEllSURy + YmtzUzdOK0pldjJiaFVKVDcwY3VzQncKLS0tIC9xMUd2OVlsZ3lmRDYyYlZpYjUv + anFDWE1CNGljY3ltN1lpdk9ZK1JySXMK58PNBo74DHptQTfT1ozV3Ikgf5BccRIH + Bw26F4GF8hjJL1Gp8szouJ9iN/mSNR47NdQN0nWy0GfOs5fClFfWvA== -----END AGE ENCRYPTED FILE----- - recipient: age1ly2endyt0y9xyddj6yuj4nw6fa3ltvzlvew4cr4lzs6dv8dkavpqadmyxx enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUZDNzVFdlU0NYVTFsUkVB - OVhzbStSQTlEblhZdXh5cmZGTXVXNWIyQUhNCjc3ZlBHWDB5czlZcmVWU0dWUEVN - OHp3YmFRaTl3Q0FxSGxheU9RSUl1R1UKLS0tIDhNUmpkbkFlNzRlbWQ2dXdGcXVn - dlJVaFEwNVN4RGNVNVN3djM5c244SmsKO/jb+qiWJUu7BE3VoVQDquSxAQWDcSj2 - g+vLyNsrc1WsxyegfRYExGAx+DJHOCg9GyACXxifCP7xTVwfvH+yfg== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4T014MWhrRjdpRGkvallr + cDIwME0yUzZseXZVUlBra2d5aXgvOFh1SXdzClM4QS9zanRhWU0xZVFSdktDaWc2 + TnFWL0N2M3VmUFVMWFN1OGxqSk05QWsKLS0tIG14L1BiVnJ0NFJCYUZnWXl6TU9v + VTU1ajNOTWxWTG5OUWRFMStLRXJlTEkKR8JA3U5MLBwMnFDZtlbrkJxmY9nENsza + JCmxPW1BTH+VadbefjGPAEwVj8XqgTCw5f8awNNZFUUe0SIud80pmQ== -----END AGE ENCRYPTED FILE----- - recipient: age15klj4t7gpfp69472mne4ue62pp6m4e04dmjyw7yf30qtqd3vl3uqjmcyxm enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzRVBMTXcyV29kVVcyRTlY - SExraURsT2ZkamlGRGphRUpYYUJUb3hzV1JjClVTTzRHU0MvVkMvRnNid1ZYdkpP - ZTlUYnVhTHlKREtIK1N3MnRnZTNHWTQKLS0tIDdaTHRvV0s1dEJseXVSdTFXUjlY - bndzMzRNSHVScDhCZkV3MDQwYnllcGcKOHUp8Q2Qmgt0CcOZZL6obGKDT8fTJ5eZ - hOeJzPoS0MY8BEICcxekOl0MICOhlIySXKx6m4MpRjgnMVX1Y5OMIQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFWmpBbXY4YVZmVkVzQ3FW + eGl1SWZqZWFSa3lmNFBNRUh4UG9qREhQR2ljCk00bElJcHk3dTFNaG5FT1NiOU81 + aENlNHpkckFoRUVpakpmb3lIYU4zOEUKLS0tIFBpQjFEa2xiMmNHM3NhKzMrMFl3 + Vm91bU15TFJwSUd5WXI3VER5WnFEZlUK89Iu2PeG/7mXaTaCUClCVL44VFLJEZpM + 1s6QFAemy/B5UYeZBQsWiN1v9yAktvA+B7BeS0lyZohpV6SypLgjGQ== -----END AGE ENCRYPTED FILE----- - recipient: age1k73gy5em3js9zklnnkzp5hme9k04lny32fgahmzddknjw5c295asdyr4x6 enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOZnR5YlZXN3N1WnFUcm1o - clJ4cVFoNng3WFNKWEd5K3l2TTUzWW54dUdjCnc1L2l6WkJBVHQ4RXNrV25kSW5s - dE0rdnJqUmllUS9VVE93OG5idUdzUk0KLS0tIDNFaGQ4R2lwRUI3L1NxL0UyYVdM - VjJJdzBuNGsvazVEdzNKRW5OdTFFQlUK5Rz0X+FopwNYu8AuC7eJPxPAr/yiZSg7 - s0Di5Wy1kfKXdwRbgSgXFZifg7bC4wsetEGi3SPVOa5yIduoMyYmaw== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5RW9MOXMxcmZQRkhKcSt4 + cXJRYnVPVytOVDY1dlAveFg1eWlMZmxqcTNZCmVhaVZyZU9VcmNVczFLemNuYTJJ + SG5WWnNJNExBanVJb1VlT0VIWUtmYzAKLS0tIFBtSDN5aEJRVC90ek4weENZSmhQ + QUMrY0dlMStHZXY3VzBkZ3NZMFVnYzAK9C1GRRqXNWesrK3JYwol3hDkmjaBBUNW + 3CroUXgWDEQ5U8M3aFKSdhXND3WkPdDAKpt9cn34lEtlUOoy4MF/AQ== -----END AGE ENCRYPTED FILE----- - recipient: age1cmzh82q8k59yzceuuy2epmqu22g7m84gqvq056mhgehwpmvjadfsc3glc8 enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoUkErTEtHSzJubXZXOEZa - Ymx3aTBjb01KbEtHUGROSllpMXV0UlpwVmgwCkRFcWs4RWJlUXIzeEtDVnJrQVpa - R09Ra0VOMHpGUUpUYWJyeks3TzRRRTgKLS0tIFA1cmJ4SmJEWXdaVGdwZjZZN01y - aTF1ZnZvOHYvZDhxSG5JSDR4Zm41NlkKijbFP2InlSCYZNR/kPWiedeRCFpLDx0M - susZTvBARIzPqR+nRNFQ/W7CvwPFPtWIBHR4lOhDmrFYjkCh085Ffg== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2TTV6QTNBNzV1T1BVQUlq + OEVGUFpvNDlUT1lWanlQZ0E0cDhaY29vRUJVCkVVbzR2d2gwWGNESUZNSGJianBC + ZDk5anJ2V0hwQUVEMUg1dmZFLzFLODAKLS0tIFlGR0xGamFKY3lwUkhaRFMzK1ds + U2dyTlNkdFVTYXJKQ0pBRnE2S295czQKy0E1Iajqkzg8cyTYNXoqf9bas8BaBP4+ + x7kjIbKIgBbWpT3niLA6Zl+SN0tLva67ddau4undz7YA7OZ4VzZ2Sw== -----END AGE ENCRYPTED FILE----- - recipient: age1wmx8y2hs83j2u5srdnfxljrzxm8jtxl6fr0mq7xf2ldxyglpzf2qq89rpx enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJWEF2Vk5ZaWRFK29MTGht - SGFPSmRndDA2L0E0Qlhxd2RVeVV1UDhMMTI4ClhORmRrb1c4RnZDTmdQZ0ROYkE2 - eHhNbE95RkE1ZHYzYXluN3prUFRmSTAKLS0tIGVTcndEOWdvV0krOTRjd0dyZHow - NG9PZlBEaURzbDF0cGo2d2VvQnFocWsKmZk7kBvKqJMDBl8rIaLw3NrUbVxzrRMN - 1xSb0iK/JDsCBDZiz+dmb4Kha/LGV2DM+AyXD0p/qSQ23yJM8WMukw== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnajNaMk9JcE1xSHpyOHV5 + L05FL2lPd0ZBNVBEQ2thRDZEdHFYL3Nnd2hJCjltSnJ3MUVvSGNyclppNTA5TGsw + OVozcGJ6c3RCMXkxTnN0M25RcFhyVDQKLS0tIGljdHZUaTNhVEZKZE1FbXNaOGVu + T2k5RlNWWGt6a3NSSE9CQjFvK01mMncKuUQ8PeSkfj0RJgDRWbFXBFAuWAOvKAox + LxBKr1TZ4oHIYJjtgP9mnKpNL5ikda+EkdEAt7V7exy2m3SvV59frg== -----END AGE ENCRYPTED FILE----- - recipient: age1mjgw3nxlnqdj04mgjz3wn7fj2nl2nxla4p2r2fn4nkvayfgp09pqllxzyh enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4OS9Ib1ZITjVyTC9VS1JP - dkJRdGhEVlJab25zWmc1S0J0Tk9PL0lZdVFFClo1S2Rabk5qZ1R0NzZIT211N0Nw - M21scUlmZ1hVL2lSdGk4dEoyZW80UGsKLS0tIDIyMTdyWlNrMkxnSmlLamJJdksr - QWpZejBTSHp2T0F1YWtwQmdjRmtKVXcKM4Hr5Y2eDOfwadbTSAJu62KGisljfOfI - BiIqArmfyjo1upw676EyV5JeV3vbi2jTT1rn8QyodsSdnI9ms9Z4KQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3TFR0dG5YVjRYZUs0bk5W + SE5aK0lRWGhMVFhNNmNKbCtLa2tibXhJL0JzCldGN1hNdldXVWJ0b3VwaVRFMzk5 + OTdjTGpMS1NUTU50RjFRaVAxSHcrY1kKLS0tIHNvaEdING1kc2RMalhZL1FqL09K + d29KMENYVEVyNzUwNEVvbitXSHVjUncKokOmKLepXUcsYf/5QUBlsd0G8ZyCsV6T + z9otd0AdEPeRTSbh5pJ05WYEIR929aEPlaLLGhIdEI3XCOHey6GpvQ== -----END AGE ENCRYPTED FILE----- - recipient: age16vzhcvz8tyxj8e0f47fy0z4p3dsg0ak4vl52ut3l07a0tz465cxslmhevl enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhSjlMNU5KNHEwdUZLejZq - SlIvVUlvTyt5QktHeGs1QWYvcjN5Y2RrMkM4Ckkwcmx1MTUxWmoza0gxMW9pcVd4 - Q0IyL3hSNFAzQVliOHZjelpjQXZJZk0KLS0tIFJzRys5czdmNUwxeUJtVFk2Z0VU - cTZHRFRMczNvbjdLNGsvZEtTNHQySWcKgiQ+amm1xrvTrU0lZKIKg6VMaxiSkd1O - +ib0vqwWUXDjxxTYaLitRCB92fwem3lsUJgmhN1kcRS3v1COKimbtA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4ZFRFcDc1cWRLeHhmZ0dB + RFNOVGVpMENydmRMRkxuWXpCaHdxUWVwa1IwCmRUMmUzampKS3BidFVLYjJEOU1F + eEFqVXRCakpTclpGOEpMbUdVbkZORkUKLS0tIGdjUkg5UmRuV1M2Rmc2Uk5VeS9t + Z0ZtWWFRdkl5NDQwVjcvYmxKVG1wNFEKrP04VYIFR2V48RqpAMXgp1sDbr1NH0+0 + kvWoYuJcaKB1Tw3xBaLmrCjKt5Xd54linwpgidX4dOAqHjHWyNIHjQ== -----END AGE ENCRYPTED FILE----- - recipient: age15cx90pnp54xp5gxlt02yn9j2pz968wp3l5ukdkx55xuecp34e5pszjku4m enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxUGRlWGplcGtDb25Ua3pV - d3lIZWdmbno4bTJVMEtZVERUdkR2UlB1ekc4CjlnLzhMamxnYVd5OVQ0VzZuVjdy - NVQxOU5UcXk3M0Y5M1hLWU1WM0o3S2MKLS0tIG9xQWRRZS9SQW9sTS9FOUtjQThE - ZDI1Um1RWm9jeFllY2dmTUdEZTJqU1kKh2Vm61sylFJwsLOjdFVRUXtabg0YzHvL - jHfr0ihHqMWQLQnMVFDrkTH84cnHDZm/yTijXXRF/yAkxlVUF7Tv/w== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIeFFhbTRvQWNtaUNZWm5l + bnlBbVBlb28zd3hMRTFxRnlacUU5dng3SENVCnFDT0J0VWJmZXhueFFmTGs2TUlP + a1I4TkVnY2JPSkJlUmU2U3R0cFUzNmMKLS0tIGNLb2JVNnBZWDM0QngraUFkSXB4 + ZHR1N1Ivejc2VzFVdUlKL0lvdXJja0UKENB2JzmrXT/sFVpVzxR64OpoGwq65Q3H + KamGdqdsD1+MYsbnklUdHSJqqAbfTH+BYpjKtF+ZsPqaXcKB9VjKyQ== -----END AGE ENCRYPTED FILE----- - recipient: age18quey88vge7xytclg2nuq4ncme86dg04lxwczqxczmdchnjg3p0saehsnh enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIR3MyS3NxWWNwRktuUGFy - THJ6SkhuZEhRWWNXNzhIYW0yekV6bG9MNkZVCnVNZU5ITDRJUlVWLy9hUUZrNFps - bGtsTWxIT2NrRFR2ZlhDZndubUlUOTQKLS0tIFl4Z093dHlGRXk5MytLMk40ekRy - Q2ZNT3NKZTRvdEZKWGhnQmhqVGp6a2cKbgjp8N1EOVRt1mcLBhWOl5vkNeeomu3L - ur5Orku3qMdm52Ff0msNzlPnrUmmblBcHSrsDvkWb3YI/Pe/zrRlJg== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoWXJ0NUlEbXZNdHlzcmlC + N3VoaEFKVXdMTjJSYXV3Vlp3dmtFVCtNang4Cm93RDFVVXgrQnM4K2lraWNSVjBo + emR1MUlEdWJxY2h6RlhTdEx1SnpmZm8KLS0tIFlLenQ5WC8vZnpGVEZmVG1MbFZU + NkRQb3c0YjV1RnhzUm9CRVRtc3Z2MUEKbwFjrd9OxDUmw7SSMGYXjlzsMVL12iNv + 31E4a7ZCPw0zucoJpB3kFkQ/0vveOHZU3bjj0htm89H1BIaW0AZkzw== -----END AGE ENCRYPTED FILE----- - recipient: age1ax5hqk6e2ekgfx5u7pl8ayc3vvhrehyvtvf07llaxhs5azpnny0qpltrns enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaY3ZqNHJSeVJlMlhnTXgy - QW92SXV2dlFsbjVTSlltWXJ6ajEvaEl6S1FVCk1oTkViQ2EvK0NiYlBZWGszRzVk - T0U1UzNqTXE5aW5xL3JwU3kwMnlacDAKLS0tIElBVGhncUpvNE1BS1UvZ0VSZUww - THZaSXhMNldUbHpBMVZQWXYwaVVQYWsKpUbG+lC37W6bzOuu9MaUmEZ5T1b5EC9k - VIY9XUoA7h0Z6G5Jrx/lrf6qsghMqd59gPA1qh8KlCJBAUJPHzQKVg== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCdDZ1QThYRGJ0Ni9QNk9D + eE41Y3BsMmJWVkRkV05FWjhlcXF6ZlhsOEFzClBzZGxpU1Y1TmJVOHN0czNNcjZn + UGVQSm5RRWhwZjVDMDV6Qzk5RmljMjQKLS0tIGp5dUljSEExUGNxUnRZcHVTMFdj + ZW5MY1NJMmRJUmcyRTJnVDMzUzB3cHcK54+0I7202n4P1kZGaCI5kM5BRAnNh/ts + 7ygeuksGvi+7gs2UFn3LCUdsaL7RsBuX3NBiVyBvE02gfKecT7W/XQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-12-22T09:11:50Z" - mac: ENC[AES256_GCM,data:D6qKXhSuYGPm9K7Al/la3O++DmOTQN5++96k44IIvgSR5Q3kTkMYxPsf3PWNyjMm09+9aRauuHPHj098+W1rXaq43Iqr24JAuaZNwLyxtqkaibv/Zhx1RgEWGXyOHDtlfIPoULNKVZ0ls2mtk40oQHsfhnRyS42m+HMQnL+tCF4=,iv:uzKbpZu9P05KbaXnBUxN4rA9nYOXpeK+E/scWoFxpcs=,tag:PuMdBx3JOT1EfFkOPV0G2g==,type:str] + - recipient: age1c2enwel9un28dcs4wg0vcyamx9a4a6g3walkhu8w5lqhmd804paq9d24as + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKQ04yNzR6MXU3aEdFNU1J + c29qdk5pbjA0Q1FGcUZTaytrWFNyM3RXRVNVCmVyU2czclVjYmpmQmNuTmhHdUlv + MkpES2FmK1JLc0tmN1BBRW95YXl6SWcKLS0tIHhCendLQ0ZmbThYb2phTG1CWk53 + TTErRmhuaDlkenNSdkxiWEVTSGFEazgKZj2nEn4bgT8+oVUG38UDGmNrq9wAk7sq + 9PzYw3cjGwRUFwT4lV3vK8ZNU6DAepga7ebwxfPNjP35h9eMtRVQIg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-01-03T05:23:41Z" + mac: ENC[AES256_GCM,data:D1iqvJh7qLoC6GlwFItacyb15X7LrnXZfSQQVhFRQRnVbFc/ECqM6P9OP4PlCfAH5Up0c/iv84MsE/UFubGKGR0i19lCQ78nLPNkFfvJ+NXg0sr03FiFmW0Q8hwzauzdMUiQr9/36D/ax+BVBTQyWgZEneiCY7KoDaQKJWzOGT4=,iv:+AZ+1u+TZNqrLMaDcHU0fgPsvx5HFprlKQExH5pIjyM=,tag:ytnj7FQQ6YivKncyZUHigg==,type:str] pgp: - - created_at: "2025-12-15T21:53:40Z" + - created_at: "2026-01-02T21:17:55Z" enc: |- -----BEGIN PGP MESSAGE----- - hQIMAwDh3VI7VctTARAAq7Q/kBF7Xgf1sPEfLLNnue7G+uErtVHLwyGwqDRAE9aw - NQ9lg2xJIro3sJhaVz0EkKyuydkWw3vjAwltnRd6FVtfKnBeDirFJdoM2zOLNdQe - OYbpGp0/C2szgYkBqVU5hDh0Gzgho0UzO0rhwf/c+uVNTKPfUJBym72p2OKJSUcm - NWhf1On/aaHsLQ46y8TJxzoxI2PsziBXqMQGbKofAgnNPSyYRvzRWR5+1lShgt4e - KYLgzGKbLp+ENptPOmqLbKuuVhFX8WXULyRvS3hRTKjezncPuRqxG/GE+4BzS7ih - 6WZ+WBCeG4sNQaeTXDjtL18DyyzT9y+UihE8O+icIPvNpGkJgY5OiKfJU3W/Wqih - wxl3Pqgb9BDvz/jHMUt2GN07JuX1at/Plx/kG3xMmgrSJfDi5ZA6oiBi5B4AqOl5 - okn635mBXFnfGuz65hrP05P7p58BXLXvMZMsrk8kNknQu7mCeXUpDvXCFRo9xZnz - OeTc7LUP9Dp5rlSJSzkBibrZ4BxebFL4ujPQ+8cibIu2XAoSQPQUCmscq1D6K5aY - 37GS/HWwNzz3PimT/D2FlKpbE9Krn9z+H9a19DIpfdWhxD06pu9pLO9cPBmYyeHs - jAnd0RRg20mF2MBy2f24nu8+ziCARJQC0H9heR386zEDCKMCo2XkC0DqbN5CL16F - AgwDC9FRLmchgYQBEAC+cfiPynGPEFfdnt+Hta9/FMI5WMXMbV4XFqD0XW6VVRLe - 1o/kANe3TM2hFzf2qVfQ4oLPxOlQtJNylxYUl2Z9EJB+YLtuHgJ9ffx1Bkc2a6md - dxb2Qv6DaKv53EiD8quAIPhaC3XzVsfrAhwSL4pga11wFYEge1wXpGGFp2LNbghH - IW273sFPv6fBIqjM0dF4QtLFsphc6dRZdW6qzuFEkU++RvfZmoKdnrzMFTaYhiX1 - lwuHuiIWP3wX7YNGgTuKcecvlUo3kI67D6SGHBXVkeyejYH+wfzrApUGdHJ4NxY7 - l3xGkrWIwqWgqh5aNErgKAA8sUS/Gcn50UHlsmO5RY3qJQPmPK1p7nlH9IKktG+A - 6AvzdgWqHnqaA/Cb90bGJZP4m447XQHIv9UrwB+6rffRA7Dvw7oFsNnh8I3Nl/W3 - WNlJ1vuXmZXQhlBS/95DvWDOzOpqIh8XSYAR44506n9u9ZRh00dB/SQ5yTA7AjSX - +Jz4SAo+8I43CiBEUbGCoxRgwHa7h6UWK7LsXCGHkqHHS7VRWZ3MiZkrVdbwv8+D - fkcwHmxJQGxjhU5F/cdmMX2KYWXu93I2Ohk+vZ7IpDbP2H/G5epgn+pUHbEbBYrl - J874Pj2gKA8vJS7bm7tbMVyCebsRwzt2eh8qwAfJL9HAup7a+hIQaIVqxrvnz9Je - AcPIsNoAqTsZeGvL0LoLQJ5myKPsb9hs/pOYjRjjM6Fdyy1GwNCdTdcLFjTthVLI - 7JuiudM3Ce/c+mW7+57oKFAqGPB3HtAfye0A9bJ3R9co4LAvWSMk52ia+LanvQ== - =Iisf + hQIMAwDh3VI7VctTARAA001QiHU3uO1goHUTsx+QnhCrfIBDjVAHhZtj8CEx1tqk + YaxNUNDra1uyGQqwdH1Ly8h6cSzeUfEtPfkjsvegYo58PSkz5F6mrpROkB1mzzfG + /H3MpCHTzroXPmrT3lNxXZyYqxGzcfLBLU05etEiFV+sV2mjoV1nYY2gTnH8XtV9 + HVayfxR4cYZOS7ox8SkGoTvZHsbNT5+jaJn7GqRjrcjmjd7S3gvq83ROe82YHNA0 + 1O04PSGwnaGC88E9Y/7segZC8Tl1e25Z0c8yMd8JHsn/RL8beHwUHTn6nuyo65Bj + Xmic9M5C16ur5yQtVr/+xU/FCbmkecsOL4u5YgECFt5w7zJZzfGUHa2Z5dIQ9T5o + 2oY/h+GsN9xTM/6ZVcgCbZrcHnIvP+5VmIEmXkdTtb4cvTFJMkDWxx7NrS8dI/Rh + 76hoCStleuLpw8+zwIYC4QdJfFWBaQyw8w0nON/qp4E+kyU8E3syMsjqFOqclSeU + vFDTvgl4/Z0nPxTl+IBzG0cBPMjUXgmvGZj4NAhZhE5nNwkA34GvmMcfjVhy8ROX + WWwgiFBP20Po7p3aHz57KA4UTkgIZfhK4BRbb4BhQoaYEcXL8Sata/SJOR3RT2vQ + 8uB8H8orPpugdafS4wLv/qcwYn6pa2ubEQG59WfihIomDWh4jl+i+kfnM5fYwX+F + AgwDC9FRLmchgYQBEAC4bp8seECcmzLFnRZsABQI/TJg7jKDEZuudEiEGmKUhhOf + Mz1pQEEHyh5aTFSJDVq2bNgPKt4NJ/bQL1QOq1lnsprpAAL6+HoyezA6ygfh6YmW + 8kJOwJrVXlgo+H3XD4XeoA7VFVdcHkszFYgq4KCd8KX+haSkt0Wbj0s7sQkKQo/j + PUUQN34pxfyJ0IiqlKuLgpu7ggMJkDqZGoYnXH91Qt9TYi/liMMx4wo82YOQFH0d + xJUewsVvUpjwmFotOBKdhk+zZlOoNNr7QnyZ2SRyXNUFI66fsw5QsbwDSXJ4Hy8C + 3RVRZ7baxw2p5wMyZQBtMyqu9quS/XED0cZA+sxvKOTrC24YbD+nb1ktc/9ZJghH + TZjhQLLhmrbHPNnrHIrnEJ6XrxbgNHWTFE+yX/e2lRIRGwz0cfgbY2pLFJ+6uhSu + PkodKyq/PCerYZPnUMjnLxogNtgZhf6jK4AzG2xuFZne37NBEaXY3q1ktwafpRia + 1UrO4PC2cwJpNuIpMfHbA8xieppwRZbqBSSAM80V12963cFakUxLmZdMG0ApFTDU + 5NoAxwBaRooHjTgYwdfgtjikwsPOf/VFWrB2IkBqF/QhxdV2sxasmJCM04e1gidi + 0prCX7KoMNtBnHpubfwV7sTNdhN15IKmyHNLw9hXfZZmN9UAh6LxUS/KHMZSv9Je + AR+Ty00mCszxvBco6ee6Tv7gEhBU2ZBhu4yyWZC5Kd0pNvr4ZtCGNNY5wIjv00jd + nNnMW7MrEF4Tz/So+1TJHiLLFuap2RpXifCHRiXDMHqOUuFUgGFSNNlhYXycXQ== + =lDR9 -----END PGP MESSAGE----- fp: 4BE7925262289B476DBBC17B76FD3810215AE097 unencrypted_suffix: _unencrypted