feat[server]: add home proxy

This commit is contained in:
Leon Schwarzäugl 2026-01-04 17:45:53 +01:00 committed by Leon Schwarzäugl
parent 75891c3103
commit c1c7431891
84 changed files with 2961 additions and 1601 deletions

5
.github/README.md vendored
View file

@ -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 |

View file

@ -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:

File diff suppressed because it is too large Load diff

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

40
flake.lock generated
View file

@ -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": {

View file

@ -61,7 +61,7 @@
postgresql = true;
attic = true;
garage = true;
hydra = false;
hydra = true;
};
}

View file

@ -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 = {

View file

@ -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 = {

View file

@ -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"
];
};
};

View file

@ -17,8 +17,8 @@ in
];
topology.self.interfaces = {
"eth1" = { };
"wifi" = { };
eth1.network = lib.mkForce "home";
wifi = { };
};
swarselsystems = {

View file

@ -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"
);
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;
};
};
}

View file

@ -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

View file

@ -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

View file

@ -23,9 +23,9 @@ in
topology.self = {
interfaces = {
"eth1" = { };
"wifi" = { };
"fritz-wg" = { };
eth1.network = lib.mkForce "home";
wifi = { };
fritz-wg.network = "fritz-wg";
};
};

View file

@ -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",

View file

@ -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";

View file

@ -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" ]

View file

@ -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;
}
];
};
};
}

View file

@ -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)
);
};
}

View file

@ -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 ];
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";
};
};
};
}

View file

@ -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;

View file

@ -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;
};
};
}

View file

@ -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 {

View file

@ -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}" ];
};
};
}

View file

@ -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

View file

@ -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; };

View file

@ -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 = {

View file

@ -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 {

View file

@ -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" ];
};
};
};

View file

@ -62,7 +62,6 @@ in
virtualHosts = {
"${serviceDomain}" = {
useACMEHost = globals.domains.main;
forceSSL = true;
acmeRoot = null;
locations = {

View file

@ -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 [
# "services"
# "home"
# "devices"
# "guests"
# ])
# {
# name = "domain-name-servers";
# data = globals.networks.home-lan.vlans.services.hosts.hintbooth-adguardhome.ipv4;
# };
++
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}";
};
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;

View file

@ -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;

View file

@ -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; };

View file

@ -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;

View file

@ -16,6 +16,8 @@ in
mpv
];
topology.self.services.${serviceName}.info = "https://${serviceDomain}";
users = {
groups = {
${serviceGroup} = {

View file

@ -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 = {

View file

@ -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;

View file

@ -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 = {

View file

@ -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;

View file

@ -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,11 +205,13 @@ in
};
};
nodes.${webProxy}.services.nginx = {
nodes =
let
genNginx = toAddress: extraConfig: {
upstreams = {
${serviceName} = {
servers = {
"${serviceAddress}:${builtins.toString servicePort}" = { };
"${toAddress}:${builtins.toString servicePort}" = { };
};
};
};
@ -230,9 +229,17 @@ in
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
'' + lib.optionalString (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 globals.hosts.${oauthServer}.wanAddress4 nginxAccessRules;
};
};
}

View file

@ -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;

View file

@ -13,6 +13,8 @@
sops
tmux
busybox
ndisc6
tcpdump
swarsel-deploy
] ++ lib.optionals withHomeManager [
swarsel-gens

View file

@ -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";
};
};
};
};
}

View file

@ -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";
};
}

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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
];

View file

@ -1,7 +1,7 @@
{ self, config, lib, globals, inputs, outputs, minimal, nixosConfig ? null, ... }:
{
_module.args = {
confLib = rec {
let
domainDefault = service: config.repo.secrets.common.services.domains.${service};
proxyDefault = config.swarselsystems.proxyHost;
addressDefault =
if
@ -15,13 +15,13 @@
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;
in
{
_module.args = {
confLib = rec {
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};
};
};

View file

@ -4,10 +4,15 @@
inputs.nix-topology.flakeModule
];
perSystem.topology.modules = [
perSystem = { system, ... }:
let
inherit (self.outputs) lib;
in
{
topology.modules = [
({ config, ... }:
let
inherit (self.outputs) globals;
globals = self.outputs.globals.${system};
inherit (config.lib.topology)
mkInternet
mkDevice
@ -20,17 +25,37 @@
renderer = "elk";
networks = {
home-lan = {
name = "Home LAN";
inherit (globals.networks.home-lan) cidrv4;
fritz-lan = {
name = "Fritz!Box LAN";
inherit (globals.networks.home-lan) cidrv4 cidrv6;
};
services = {
name = "VLAN: Services";
inherit (globals.networks.home-lan.vlans.services) cidrv4 cidrv6;
};
home = {
name = "VLAN: Home";
inherit (globals.networks.home-lan.vlans.home) cidrv4 cidrv6;
};
devices = {
name = "VLAN: Devices";
inherit (globals.networks.home-lan.vlans.devices) cidrv4 cidrv6;
};
guests = {
name = "VLAN: Guests";
inherit (globals.networks.home-lan.vlans.guests) cidrv4 cidrv6;
};
fritz-wg = {
name = "Wireguard Tunnel for Fritzbox net access";
inherit (globals.networks.twothreetunnel-wg) cidrv4;
name = "WireGuard: Fritz!Box tunnel";
inherit (globals.networks.fritz-wg) cidrv4 cidrv6;
};
wg = {
name = "Wireguard Tunnel for proxy access";
inherit (globals.networks.twothreetunnel-wg) cidrv4;
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;
};
};
@ -38,13 +63,9 @@
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 "liliputsteps" "lan")
(mkConnection "treehouse" "eth1")
(mkConnection "toto" "bootstrapper")
(mkConnection "hotel" "demo host")
];
@ -53,7 +74,7 @@
fritzbox = mkRouter "FRITZ!Box" {
info = "FRITZ!Box 7682";
image = "${self}/files/topology-images/hunsn.png";
image = "${self}/files/topology-images/Fritz!Box_7682.png";
interfaceGroups = [
[
"eth1"
@ -67,83 +88,90 @@
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";
eth-wan = mkConnection "hintbooth" "lan";
};
interfaces = {
eth1 = {
addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ];
network = "home-lan";
};
eth2 = {
addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ];
network = "home-lan";
};
eth3 = {
addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ];
network = "home-lan";
network = "fritz-lan";
};
eth2 = { };
eth3 = { };
eth-wan = {
addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ];
network = "home-lan";
network = "fritz-lan";
};
wifi = {
addresses = [ globals.networks.home-lan.hosts.fritzbox.ipv4 ];
virtual = true;
network = "home-lan";
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 = "wg";
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-SG108";
image = "${self}/files/topology-images/TL-SG108.png";
info = "TL-SG108E";
image = "${self}/files/topology-images/TL-SG108E.png";
interfaceGroups = [
[
"eth1"
"eth2"
"eth3"
"eth4"
"eth5"
"eth6"
"eth7"
"eth8"
]
# 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 = mkSwitch "Switch Bedroom" {
info = "TL-SG1005D";
image = "${self}/files/topology-images/TL-SG1005D.png";
switch-bedroom = mkDevice "Switch Bedroom" {
info = "Cisco SG 200-08";
image = "${self}/files/topology-images/Cisco_SG_200-08.png";
interfaceGroups = [
[
"eth1"
"eth2"
"eth3"
"eth4"
"eth5"
]
# trunk
[ "eth1" ]
# devices
[ "eth2" ]
# guests
[ "eth3" "eth4" "eth5" "eth6" "eth7" "eth8" ]
];
connections.eth2 = mkConnection "printer" "eth1";
connections.eth3 = mkConnection "machpizza" "eth1";
interfaces = {
eth2 = { network = lib.mkForce "devices"; };
eth3 = { network = lib.mkForce "guests"; };
};
connections = {
eth2 = mkConnection "printer" "eth1";
eth3 = mkConnection "machpizza" "eth1";
};
};
nswitch = mkDevice "Nintendo Switch" {
@ -158,23 +186,55 @@
image = "${self}/files/topology-images/zflip6.png";
interfaces = {
wifi = { };
fritz-wg = { };
fritz-wg.network = "fritz-wg";
};
};
machpizza = mkDevice "machpizza" {
info = "MacBook Pro 2016";
icon = "${self}/files/topology-images/mac.png";
icon = "devices.laptop";
deviceIcon = "${self}/files/topology-images/mac.png";
interfaces = {
eth1 = { };
eth1.network = "guests";
wifi = { };
};
};
pc = mkDevice "Windows Gaming Server" {
info = "i7-4790k, GTX970, 32GB RAM";
image = "${self}/files/topology-images/pc.png";
interfaces.eth1 = { };
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" {
@ -189,4 +249,5 @@
];
};
}

View file

@ -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;
};
};
};

View file

@ -0,0 +1 @@
emVomIbxGS95tDiwPpUbsRTAur/TZ+BRy7+4737Sv1Q=

View file

@ -0,0 +1 @@
G4NXSwhwU5a2K1q3oAwmnOtBlCj15J2aqh6zIJJtggE=

View file

@ -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

View file

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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