feat: globals

feat: more vlan config
This commit is contained in:
Patrick 2024-12-20 20:40:27 +01:00
parent 8332bc45ba
commit 053365c277
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
196 changed files with 1624 additions and 1448 deletions

View file

@ -2,13 +2,14 @@
config,
lib,
pkgs,
globals,
...
}:
{
boot = lib.mkIf (!config.boot.isContainer) {
initrd.systemd = {
enable = true;
emergencyAccess = config.secrets.secrets.global.users.root.passwordHash;
emergencyAccess = globals.users.root.hashedPassword;
extraBin.ip = "${pkgs.iproute2}/bin/ip";
extraBin.cryptsetup = "${pkgs.cryptsetup}/bin/cryptsetup";
users.root.shell = "${pkgs.bashInteractive}/bin/bash";

View file

@ -20,6 +20,7 @@
../../modules/deterministic-ids.nix
../../modules/distributed-config.nix
../../modules/globals.nix
../../modules/meta.nix
../../modules/iwd.nix
../../modules/secrets.nix

View file

@ -77,8 +77,5 @@
let
local = config.node.secretsDir + "/secrets.nix.age";
in
{
global = ../../secrets/secrets.nix.age;
}
// lib.optionalAttrs (config.node.name != null && lib.pathExists local) { inherit local; };
lib.optionalAttrs (config.node.name != null && lib.pathExists local) { inherit local; };
}

View file

@ -1,7 +1,7 @@
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
};
imports = [ ../actual.nix ];
services.actual = {

View file

@ -1,8 +1,8 @@
{ config, lib, ... }:
{ config, ... }:
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.adguardhome.port ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ config.services.adguardhome.port ];
};
services.adguardhome = {
enable = true;
@ -30,11 +30,11 @@
];
};
user_rules = [
"||adguardhome.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnetv4}"
"||nc.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnetv4}"
"||immich.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnetv4}"
"||smb.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth-samba config.secrets.secrets.global.net.privateSubnetv4}"
"||fritz.box^$dnsrewrite=${lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4}"
# "||adguardhome.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnetv4}"
# "||nc.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnetv4}"
# "||immich.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnetv4}"
# "||smb.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth-samba config.secrets.secrets.global.net.privateSubnetv4}"
# "||fritz.box^$dnsrewrite=${lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4}"
];
dhcp.enabled = false;
ratelimit = 60;

View file

@ -1,4 +1,10 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
globals,
...
}:
let
prestart = pkgs.writeShellScript "blog-pre" ''
if [ ! -d ./.ssh ]; then
@ -8,18 +14,20 @@ let
ssh-keygen -t ed25519 -N "" -f .ssh/id_ed25519
fi
if [ ! -d ./blog ]; then
${
lib.getExe pkgs.git
} clone --recurse-submodules ssh://git@forge.lel.lol:9922/patrick/blog.git ||\
${lib.getExe pkgs.git} clone --recurse-submodules ssh://git@forge.lel.lol:9922/patrick/blog.git ||\
echo "failed to clone the repository did you forget to add the ssh key?"
fi
'';
in {
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
in
{
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 80 ];
};
environment.systemPackages = [ pkgs.signal-cli pkgs.cargo ];
environment.systemPackages = [
pkgs.signal-cli
pkgs.cargo
];
services.nginx = {
enable = true;
user = "blog";
@ -31,12 +39,14 @@ in {
"[forge.lel.lol]:9922".publicKey =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWoGqHwkLVFXJwYcKs3CjQognvlZmROUIgkvvUgNalx";
};
environment.persistence."/persist".directories = [{
environment.persistence."/persist".directories = [
{
directory = "/var/lib/blog";
user = "blog";
group = "blog";
mode = "0700";
}];
}
];
systemd.timers.blog-update = {
wantedBy = [ "timers.target" ];
timerConfig = {
@ -60,14 +70,17 @@ in {
else
echo "Commiting newest changes"
git -c user.name="blog-bot" \
-c user.email="blog-bot@${config.secrets.secrets.global.domains.mail_public}" \
-c user.email="blog-bot@${globals.domains.mail_public}" \
commit -m "Automatic commit for blog on $(date -u -I)"
fi
git pull --rebase
git push
${lib.getExe pkgs.zola} -r public build
'';
path = [ pkgs.openssh pkgs.git ];
path = [
pkgs.openssh
pkgs.git
];
serviceConfig = {
Requires = "blog";
Type = "oneshot";

View file

@ -1,4 +1,4 @@
{ config, ... }:
{ config, globals, ... }:
{
age.secrets.cloudflare_token_dns = {
rekeyFile = config.node.secretsDir + "/cloudflare_api_token.age";
@ -8,12 +8,12 @@
networking.enableIPv6 = false;
services.ddclient = {
enable = true;
zone = config.secrets.secrets.global.domains.web;
zone = globals.domains.web;
protocol = "Cloudflare";
username = "token";
usev4 = "webv4, webv4='https://cloudflare.com/cdn-cgi/trace', webv4-skip='ip='";
usev6 = "";
passwordFile = config.age.secrets.cloudflare_token_dns.path;
domains = [ config.secrets.secrets.global.domains.web ];
domains = [ globals.domains.web ];
};
}

View file

@ -1,9 +1,14 @@
{ config, nodes, ... }:
{
config,
nodes,
globals,
...
}:
{
i18n.supportedLocales = [ "all" ];
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 80 ];
};
age.secrets.appKey = {
@ -16,12 +21,12 @@
services.firefly-iii = {
enable = true;
enableNginx = true;
virtualHost = "money.${config.secrets.secrets.global.domains.web}";
virtualHost = globals.services.firefly.domain;
settings = {
APP_URL = "https://money.${config.secrets.secrets.global.domains.web}";
APP_URL = "https://${globals.services.firefly.domain}";
TZ = "Europe/Berlin";
TRUSTED_PROXIES = nodes.elisabeth.config.wireguard.elisabeth.ipv4;
SITE_OWNER = "firefly-admin@${config.secrets.secrets.global.domains.mail_public}";
TRUSTED_PROXIES = nodes.nucnix-nginx.config.wireguard.services.ipv4;
SITE_OWNER = "firefly-admin@${globals.domains.mail_public}";
APP_KEY_FILE = config.age.secrets.appKey.path;
AUTHENTICATION_GUARD = "remote_user_guard";
AUTHENTICATION_GUARD_HEADER = "X-User";

View file

@ -1,13 +1,11 @@
{
config,
globals,
nodes,
pkgs,
lib,
...
}:
let
forgejoDomain = "forge.${config.secrets.secrets.global.domains.web}";
in
{
age.secrets.resticpasswd = {
generator.script = "alnum";
@ -27,8 +25,8 @@ in
passwordFile = config.age.secrets.resticpasswd.path;
hetznerStorageBox = {
enable = true;
inherit (config.secrets.secrets.global.hetzner) mainUser;
inherit (config.secrets.secrets.global.hetzner.users.forgejo) subUid path;
inherit (globals.hetzner) mainUser;
inherit (globals.hetzner.users.forgejo) subUid path;
sshAgeSecret = "forgejoHetznerSsh";
};
paths = [ config.services.forgejo.stateDir ];
@ -52,9 +50,9 @@ in
home = config.services.forgejo.stateDir;
};
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [
config.services.forgejo.settings.server.HTTP_PORT
];
};
@ -86,7 +84,7 @@ in
group = "stalwart-mail";
mode = "440";
};
services.idmail.provision.mailboxes."forge@${config.secrets.secrets.global.domains.mail_public}" = {
services.idmail.provision.mailboxes."forge@${globals.domains.mail_public}" = {
password_hash = "%{file:${nodes.mailnix.config.age.secrets.idmail-forgejo-passwd-hash.path}}%";
owner = "admin";
};
@ -116,9 +114,9 @@ in
# federation.ENABLED = true;
mailer = {
ENABLED = true;
SMTP_ADDR = "smtp.${config.secrets.secrets.global.domains.mail_public}";
FROM = "forge@${config.secrets.secrets.global.domains.mail_public}";
USER = "forge@${config.secrets.secrets.global.domains.mail_public}";
SMTP_ADDR = "smtp.${globals.domains.mail_public}";
FROM = "forge@${globals.domains.mail_public}";
USER = "forge@${globals.domains.mail_public}";
SEND_AS_PLAIN_TEXT = true;
};
oauth2_client = {
@ -137,8 +135,8 @@ in
server = {
HTTP_ADDR = "0.0.0.0";
HTTP_PORT = 3000;
DOMAIN = forgejoDomain;
ROOT_URL = "https://${forgejoDomain}/";
DOMAIN = globals.services.forgejo.domain;
ROOT_URL = "https://${globals.services.forgejo.domain}/";
LANDING_PAGE = "login";
SSH_PORT = 9922;
};
@ -176,7 +174,7 @@ in
"--key"
clientId
"--auto-discover-url"
"https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/${clientId}/.well-known/openid-configuration"
"https://auth.${globals.domains.web}/oauth2/openid/${clientId}/.well-known/openid-configuration"
"--scopes"
"email"
"--scopes"

View file

@ -1,7 +1,7 @@
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
};
services.homebox = {
enable = true;

View file

@ -1,12 +1,13 @@
{
inputs,
config,
globals,
...
}:
let
domain = config.secrets.secrets.global.domains.mail_public;
idmailDomain = "alias.${domain}";
priv_domain = config.secrets.secrets.global.domains.mail_private;
domain = globals.domains.mail_public;
idmailDomain = globals.services.idmail.domain;
priv_domain = globals.domains.mail_private;
mkRandomSecret = {
generator.script = "alnum";

View file

@ -3,11 +3,12 @@
pkgs,
nodes,
config,
globals,
...
}:
let
version = "v1.119.1";
immichDomain = "immich.${config.secrets.secrets.global.domains.web}";
immichDomain = "immich.${globals.domains.web}";
ipImmichMachineLearning = "10.89.0.10";
ipImmichPostgres = "10.89.0.12";
@ -57,10 +58,10 @@ let
};
notifications.smtp = {
enabled = true;
from = "immich@${config.secrets.secrets.global.domains.mail_public}";
from = "immich@${globals.domains.mail_public}";
transport = {
username = "immich@${config.secrets.secrets.global.domains.mail_public}";
host = "smtp.${config.secrets.secrets.global.domains.mail_public}";
username = "immich@${globals.domains.mail_public}";
host = "smtp.${globals.domains.mail_public}";
port = 465;
};
};
@ -91,7 +92,7 @@ let
clientId = "immich";
# clientSecret will be dynamically added in activation script
issuerUrl = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/${clientId}";
issuerUrl = "https://auth.${globals.domains.web}/oauth2/openid/${clientId}";
scope = "openid email profile";
storageLabelClaim = "preferred_username";
};
@ -163,7 +164,7 @@ in
group = "stalwart-mail";
mode = "440";
};
services.idmail.provision.mailboxes."immich@${config.secrets.secrets.global.domains.mail_public}" = {
services.idmail.provision.mailboxes."immich@${globals.domains.mail_public}" = {
password_hash = "%{file:${nodes.mailnix.config.age.secrets.idmail-immich-passwd-hash.path}}%";
owner = "admin";
};
@ -193,8 +194,8 @@ in
passwordFile = config.age.secrets.resticpasswd.path;
hetznerStorageBox = {
enable = true;
inherit (config.secrets.secrets.global.hetzner) mainUser;
inherit (config.secrets.secrets.global.hetzner.users.immich) subUid path;
inherit (globals.hetzner) mainUser;
inherit (globals.hetzner.users.immich) subUid path;
sshAgeSecret = "immichHetznerSsh";
};
backupPrepareCommand = ''
@ -242,15 +243,15 @@ in
vcpu = 12;
};
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
};
networking.nftables.chains.forward.into-immich-container = {
after = [ "conntrack" ];
rules = [
"iifname elisabeth ip saddr ${nodes.elisabeth.config.wireguard.elisabeth.ipv4} tcp dport 2283 accept"
"iifname elisabeth ip saddr ${nodes.nucnix-nginx.config.wireguard.services.ipv4} tcp dport 2283 accept"
"iifname podman1 oifname lan accept"
];
};

View file

@ -1,8 +1,8 @@
{ config, ... }:
{ globals, ... }:
{
services.invidious = {
enable = true;
domain = "yt.${config.secrets.secrets.global.domains.web}";
inherit (globals.services.invidious) domain;
sig-helper.enable = true;
settings = {
external_port = 443;
@ -33,8 +33,8 @@
}
];
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
};
}

View file

@ -1,11 +1,13 @@
{ config, pkgs, ... }:
let
kanidmdomain = "auth.${config.secrets.secrets.global.domains.web}";
in
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
globals,
config,
pkgs,
...
}:
{
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
};
environment.persistence."/persist".directories = [
{
@ -56,8 +58,8 @@ in
package = pkgs.kanidm.withSecretProvisioning;
enableServer = true;
serverSettings = {
domain = kanidmdomain;
origin = "https://${kanidmdomain}";
inherit (globals.services.kanidm) domain;
origin = "https://${globals.services.kanidm.domain}";
tls_chain = config.age.secrets.kanidm-cert.path;
tls_key = config.age.secrets.kanidm-key.path;
bindaddress = "0.0.0.0:3000";
@ -83,8 +85,8 @@ in
};
systems.oauth2.paperless = {
displayName = "paperless";
originUrl = "https://ppl.${config.secrets.secrets.global.domains.web}/accounts/oidc/kanidm/login/callback/";
originLanding = "https://ppl.${config.secrets.secrets.global.domains.web}/";
originUrl = "https://${globals.services.paperless.domain}/accounts/oidc/kanidm/login/callback/";
originLanding = "https://${globals.services.paperless.domain}/";
basicSecretFile = config.age.secrets.oauth2-paperless.path;
scopeMaps."paperless.access" = [
"openid"
@ -103,8 +105,8 @@ in
};
systems.oauth2.nextcloud = {
displayName = "nextcloud";
originUrl = "https://nc.${config.secrets.secrets.global.domains.web}/";
originLanding = "https://nc.${config.secrets.secrets.global.domains.web}/";
originUrl = "https://${globals.services.nextcloud.domain}/";
originLanding = "https://${globals.services.nextcloud.domain}/";
basicSecretFile = config.age.secrets.oauth2-nextcloud.path;
allowInsecureClientDisablePkce = true;
scopeMaps."nextcloud.access" = [
@ -125,10 +127,10 @@ in
systems.oauth2.immich = {
displayName = "Immich";
originUrl = [
"https://immich.${config.secrets.secrets.global.domains.web}/auth/login"
"https://immich.${config.secrets.secrets.global.domains.web}/api/oauth/mobile-redirect"
"https://${globals.services.immich.domain}/auth/login"
"https://${globals.services.immich.domain}/api/oauth/mobile-redirect"
];
originLanding = "https://immich.${config.secrets.secrets.global.domains.web}/";
originLanding = "https://${globals.services.immich.domain}/";
basicSecretFile = config.age.secrets.oauth2-immich.path;
allowInsecureClientDisablePkce = true;
enableLegacyCrypto = true;
@ -149,8 +151,8 @@ in
systems.oauth2.oauth2-proxy = {
displayName = "Oauth2-Proxy";
originUrl = "https://oauth2.${config.secrets.secrets.global.domains.web}/oauth2/callback";
originLanding = "https://oauth2.${config.secrets.secrets.global.domains.web}/";
originUrl = "https://${globals.services.oauth2-proxy.domain}/oauth2/callback";
originLanding = "https://${globals.services.oauth2-proxy.domain}/";
basicSecretFile = config.age.secrets.oauth2-proxy.path;
scopeMaps."adguardhome.access" = [
"openid"
@ -202,8 +204,8 @@ in
};
systems.oauth2.forgejo = {
displayName = "Forgejo";
originUrl = "https://forge.${config.secrets.secrets.global.domains.web}/user/oauth2/kanidm/callback";
originLanding = "https://forge.${config.secrets.secrets.global.domains.web}/";
originUrl = "https://${globals.services.forgejo.domain}/user/oauth2/kanidm/callback";
originLanding = "https://${globals.services.forgejo.domain}/";
basicSecretFile = config.age.secrets.oauth2-forgejo.path;
scopeMaps."forgejo.access" = [
"openid"
@ -223,10 +225,10 @@ in
public = true;
displayName = "Netbird";
originUrl = [
"https://netbird.${config.secrets.secrets.global.domains.web}/peers"
"https://netbird.${config.secrets.secrets.global.domains.web}/add-peers"
"https://${globals.services.netbird.domain}/peers"
"https://${globals.services.netbird.domain}/add-peers"
];
originLanding = "https://netbird.${config.secrets.secrets.global.domains.web}/";
originLanding = "https://${globals.services.netbird.domain}/";
preferShortUsername = true;
enableLocalhostRedirects = true;
enableLegacyCrypto = true;

View file

@ -4,11 +4,12 @@
config,
pkgs,
lib,
globals,
...
}:
let
priv_domain = config.secrets.secrets.global.domains.mail_private;
domain = config.secrets.secrets.global.domains.mail_public;
priv_domain = globals.domains.mail_private;
domain = globals.domains.mail_public;
mailDomains = [
priv_domain
domain
@ -41,8 +42,8 @@ in
passwordFile = config.age.secrets.resticpasswd.path;
hetznerStorageBox = {
enable = true;
inherit (config.secrets.secrets.global.hetzner) mainUser;
inherit (config.secrets.secrets.global.hetzner.users.maddy) subUid path;
inherit (globals.hetzner) mainUser;
inherit (globals.hetzner.users.maddy) subUid path;
sshAgeSecret = "maddyHetznerSsh";
};
paths = [

View file

@ -1,8 +1,13 @@
{ config, lib, ... }:
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [
config,
lib,
globals,
...
}:
{
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [
80 # dashboard
3000 # management
8012 # signal
@ -47,20 +52,20 @@
clients.main = {
port = 51820;
environment = {
NB_MANAGEMENT_URL = "https://netbird.${config.secrets.secrets.global.domains.web}";
NB_ADMIN_URL = "https://netbird.${config.secrets.secrets.global.domains.web}";
NB_MANAGEMENT_URL = "https://${globals.services.netbird.domain}";
NB_ADMIN_URL = "https://${globals.services.netbird.domain}";
NB_HOSTNAME = "home";
};
};
server = {
enable = true;
domain = "netbird.${config.secrets.secrets.global.domains.web}";
inherit (globals.services.netbird) domain;
dashboard = {
enableNginx = true;
settings = {
AUTH_AUTHORITY = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/netbird";
AUTH_AUTHORITY = "https://${globals.services.kanidm.domain}/oauth2/openid/netbird";
# Fix Kanidm not supporting fragmented URIs
AUTH_REDIRECT_URI = "/peers";
AUTH_SILENT_REDIRECT_URI = "/add-peers";
@ -69,7 +74,7 @@
relay = {
authSecretFile = config.age.secrets.relaySecret.path;
settings.NB_EXPOSED_ADDRESS = "rels://netbird.${config.secrets.secrets.global.domains.web}:443";
settings.NB_EXPOSED_ADDRESS = "rels://${globals.services.netbird.domain}:443";
};
coturn = {
@ -82,12 +87,12 @@
# DNS server should do the lookup this is not used
dnsDomain = "internal.invalid";
singleAccountModeDomain = "netbird.patrick";
oidcConfigEndpoint = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/netbird/.well-known/openid-configuration";
oidcConfigEndpoint = "https://${globals.services.kanidm.domain}/oauth2/openid/netbird/.well-known/openid-configuration";
settings = {
TURNConfig = {
Secret._secret = config.age.secrets.coturnSecret.path;
};
Signal.URI = "netbird.${config.secrets.secrets.global.domains.web}:443";
Signal.URI = "${globals.services.netbird.domain}:443";
HttpConfig = {
# This is not possible
# failed validating JWT token sent from peer y1ParZkbzVMQGeU/KMycYl75v90i2O6EwgO1YQZnSFs= with error rpc error: code = Internal desc = unable to fetch account with claims, err: user ID is empty

View file

@ -3,11 +3,9 @@
pkgs,
config,
nodes,
globals,
...
}:
let
hostName = "nc.${config.secrets.secrets.global.domains.web}";
in
{
age.secrets.mailnix-passwd = {
@ -28,7 +26,7 @@ in
group = "stalwart-mail";
mode = "440";
};
services.idmail.provision.mailboxes."nextcloud@${config.secrets.secrets.global.domains.mail_public}" = {
services.idmail.provision.mailboxes."nextcloud@${globals.domains.mail_public}" = {
password_hash = "%{file:${nodes.mailnix.config.age.secrets.idmail-nextcloud-passwd-hash.path}}%";
owner = "admin";
};
@ -57,7 +55,7 @@ in
services.postgresql.package = pkgs.postgresql_16;
services.nextcloud = {
inherit hostName;
hostName = globals.services.nextcloud.domain;
enable = true;
package = pkgs.nextcloud30;
configureRedis = true;
@ -79,7 +77,7 @@ in
phpOptions."opcache.interned_strings_buffer" = "32";
settings = {
default_phone_region = "DE";
trusted_proxies = [ nodes.elisabeth.config.wireguard.elisabeth.ipv4 ];
trusted_proxies = [ nodes.nucnix-nginx.config.wireguard.services.ipv4 ];
overwriteprotocol = "https";
maintenance_window_start = 2;
enabledPreviewProviders = [
@ -97,13 +95,13 @@ in
];
mail_smtpmode = "smtp";
mail_smtphost = "smtp.${config.secrets.secrets.global.domains.mail_public}";
mail_smtphost = "smtp.${globals.domains.mail_public}";
mail_smtpport = 465;
mail_from_address = "nextcloud";
mail_smtpsecure = "ssl";
mail_domain = config.secrets.secrets.global.domains.mail_public;
mail_domain = globals.domains.mail_public;
mail_smtpauth = true;
mail_smtpname = "nextcloud@${config.secrets.secrets.global.domains.mail_public}";
mail_smtpname = "nextcloud@${globals.domains.mail_public}";
loglevel = 2;
};
config = {
@ -123,9 +121,9 @@ in
"L+ ${config.services.nextcloud.datadir}/config/mailer.config.php - - - - ${mailer-passwd-conf}"
];
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 80 ];
};
networking = {
# Use systemd-resolved inside the container

186
config/services/nginx.nix Normal file
View file

@ -0,0 +1,186 @@
{
config,
nodes,
lib,
globals,
...
}:
let
ipOf = name: nodes.${globals.services.${name}.host}.config.wireguard.services.ipv4;
in
{
wireguard.services = {
client.via = "nucnix";
};
services.netbird.server.proxy =
let
cfg = nodes.elisabeth-netbird.config.services.netbird.server;
in
{
domain = "${globals.services.netbird.domain}";
enable = true;
enableNginx = true;
signalAddress = "${nodes.elisabeth-netbird.config.wireguard.services.ipv4}:${toString cfg.signal.port}";
relayAddress = "${nodes.elisabeth-netbird.config.wireguard.services.ipv4}:${toString cfg.relay.port}";
managementAddress = "${nodes.elisabeth-netbird.config.wireguard.services.ipv4}:${toString cfg.management.port}";
dashboardAddress = "${nodes.elisabeth-netbird.config.wireguard.services.ipv4}:80";
};
services.nginx =
let
blockOf =
hostName:
{
virtualHostExtraConfig ? "",
maxBodySize ? "500M",
port ? 3000,
upstream ? hostName,
protocol ? "http",
...
}:
{
upstreams.${hostName} = {
servers."${ipOf upstream}:${toString port}" = { };
extraConfig = ''
zone ${hostName} 64k ;
keepalive 5 ;
'';
};
virtualHosts.${globals.services.${hostName}.domain} = {
forceSSL = true;
useACMEHost = "web";
locations."/" = {
proxyPass = "${protocol}://${hostName}";
proxyWebsockets = true;
X-Frame-Options = "SAMEORIGIN";
};
extraConfig =
''
client_max_body_size ${maxBodySize} ;
''
+ virtualHostExtraConfig;
};
};
proxyProtect =
hostName:
{
allowedGroup ? true,
...
}@cfg:
lib.mkMerge [
(blockOf hostName cfg)
{
virtualHosts.${globals.services.${hostName}.domain} = {
locations."/".extraConfig = ''
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag
auth_request_set $user $upstream_http_x_auth_request_preferred_username;
# Set the email to our own domain in case user change their mail
auth_request_set $email "''${upstream_http_x_auth_request_preferred_username}@${globals.domains.web}";
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
'';
locations."/oauth2/" = {
proxyPass = "http://oauth2-proxy";
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
locations."= /oauth2/auth" = {
proxyPass =
"http://oauth2-proxy/oauth2/auth"
+ lib.optionalString allowedGroup "?allowed_groups=${hostName}_access";
extraConfig = ''
internal;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
'';
};
};
}
];
in
lib.mkMerge [
{
enable = true;
recommendedSetup = true;
virtualHosts."${globals.services.netbird.domain}".useACMEHost = "web";
}
(blockOf "vaultwarden" { maxBodySize = "1G"; })
(blockOf "forgejo" { maxBodySize = "1G"; })
(blockOf "immich" {
maxBodySize = "5G";
virtualHostExtraConfig = ''
proxy_buffering off;
proxy_request_buffering off;
'';
})
(proxyProtect "adguardhome" { })
(proxyProtect "oauth2-proxy" { allowedGroup = false; })
(blockOf "paperless" { maxBodySize = "5G"; })
(proxyProtect "ttrss" { port = 80; })
(proxyProtect "invidious" { })
(blockOf "yourspotify" { port = 80; })
(blockOf "blog" { port = 80; })
(blockOf "homebox" { })
(proxyProtect "ollama" { })
(proxyProtect "firefly" { port = 80; })
(blockOf "apispotify" {
port = 3000;
upstream = "yourspotify";
})
(blockOf "nextcloud" {
maxBodySize = "5G";
port = 80;
})
(blockOf "kanidm" {
protocol = "https";
virtualHostExtraConfig = ''
proxy_ssl_verify off ;
'';
})
];
age.secrets.cloudflare_token_acme = {
rekeyFile = config.node.secretsDir + "/cloudflare_api_token.age";
mode = "440";
group = "acme";
};
security.acme = {
acceptTerms = true;
defaults = {
email = globals.accounts.email."1".address;
dnsProvider = "cloudflare";
dnsPropagationCheck = true;
reloadServices = [ "nginx" ];
credentialFiles = {
"CF_DNS_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path;
"CF_ZONE_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path;
};
};
};
security.acme.certs.web = {
domain = globals.domains.web;
extraDomainNames = [ "*.${globals.domains.web}" ];
};
users.groups.acme.members = [ "nginx" ];
environment.persistence."/state".directories = [
{
directory = "/var/lib/acme";
user = "acme";
group = "acme";
mode = "0755";
}
];
}

View file

@ -1,8 +1,13 @@
{ config, nodes, ... }:
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
config,
nodes,
globals,
...
}:
{
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
};
age.secrets.oauth2-cookie-secret = {
@ -13,7 +18,7 @@
services.oauth2-proxy = {
enable = true;
cookie.domain = ".${config.secrets.secrets.global.domains.web}";
cookie.domain = ".${globals.domains.web}";
cookie.secure = true;
cookie.expire = "900m";
cookie.secret = null;
@ -22,26 +27,26 @@
reverseProxy = true;
httpAddress = "0.0.0.0:3000";
redirectURL = "https://oauth2.${config.secrets.secrets.global.domains.web}/oauth2/callback";
redirectURL = "https://oauth2.${globals.domains.web}/oauth2/callback";
setXauthrequest = true;
extraConfig = {
code-challenge-method = "S256";
whitelist-domain = ".${config.secrets.secrets.global.domains.web}";
whitelist-domain = ".${globals.domains.web}";
set-authorization-header = true;
pass-access-token = true;
skip-jwt-bearer-tokens = true;
upstream = "static://202";
oidc-issuer-url = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/oauth2-proxy";
oidc-issuer-url = "https://auth.${globals.domains.web}/oauth2/openid/oauth2-proxy";
provider-display-name = "Kanidm";
#client-secret-file = config.age.secrets.oauth2-client-secret.path;
};
provider = "oidc";
scope = "openid email";
loginURL = "https://auth.${config.secrets.secrets.global.domains.web}/ui/oauth2";
redeemURL = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/token";
validateURL = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/oauth2-proxy/userinfo";
loginURL = "https://auth.${globals.domains.web}/ui/oauth2";
redeemURL = "https://auth.${globals.domains.web}/oauth2/token";
validateURL = "https://auth.${globals.domains.web}/oauth2/openid/oauth2-proxy/userinfo";
clientID = "oauth2-proxy";
email.domains = [ "*" ];
};

View file

@ -3,9 +3,9 @@
disabledModules = [ "services/misc/octoprint.nix" ];
imports = [ "${inputs.nixpkgs-octoprint}/nixos/modules/services/misc/octoprint.nix" ];
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.octoprint.port ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ config.services.octoprint.port ];
};
environment.persistence."/persist".directories = [
{

View file

@ -1,8 +1,8 @@
{ config, ... }:
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.open-webui.port ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ config.services.open-webui.port ];
};
services.ollama = {
host = "localhost";

View file

@ -1,12 +1,12 @@
{
pkgs,
nodes,
globals,
config,
lib,
...
}:
let
paperlessdomain = "ppl.${config.secrets.secrets.global.domains.web}";
paperlessBackupDir = "/var/cache/backups/paperless";
in
{
@ -34,8 +34,8 @@ in
passwordFile = config.age.secrets.resticpasswd.path;
hetznerStorageBox = {
enable = true;
inherit (config.secrets.secrets.global.hetzner) mainUser;
inherit (config.secrets.secrets.global.hetzner.users.paperless) subUid path;
inherit (globals.hetzner) mainUser;
inherit (globals.hetzner.users.paperless) subUid path;
sshAgeSecret = "paperlessHetznerSsh";
};
paths = [ paperlessBackupDir ];
@ -64,9 +64,9 @@ in
before = [ "restic-backups-main.service" ];
};
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.paperless.port ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ config.services.paperless.port ];
};
age.secrets.paperless-admin-passwd = {
@ -83,10 +83,10 @@ in
consumptionDir = "/paperless/consume";
mediaDir = "/paperless/media";
settings = {
PAPERLESS_URL = "https://${paperlessdomain}";
PAPERLESS_ALLOWED_HOSTS = paperlessdomain;
PAPERLESS_CORS_ALLOWED_HOSTS = "https://${paperlessdomain}";
PAPERLESS_TRUSTED_PROXIES = nodes.elisabeth.config.wireguard.elisabeth.ipv4;
PAPERLESS_URL = "https://${globals.services.paperless.domain}";
PAPERLESS_ALLOWED_HOSTS = globals.services.paperless.domain;
PAPERLESS_CORS_ALLOWED_HOSTS = "https://${globals.services.paperless.domain}";
PAPERLESS_TRUSTED_PROXIES = nodes.nucnix-nginx.config.wireguard.services.ipv4;
PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect";
@ -98,7 +98,7 @@ in
provider_id = "kanidm";
name = "Kanidm";
client_id = "paperless";
settings.server_url = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/${client_id}/.well-known/openid-configuration";
settings.server_url = "https://${globals.services.kanidm.domain}/oauth2/openid/${client_id}/.well-known/openid-configuration";
}
];
};

View file

@ -1,143 +0,0 @@
{
config,
nodes,
lib,
pkgs,
...
}:
let
prestart = pkgs.writeShellScript "pr-tracker-pre" ''
if [ ! -d ./nixpkgs ]; then
${lib.getExe pkgs.git} clone https://github.com/NixOS/nixpkgs.git
fi
'';
in
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
};
networking.firewall.allowedTCPPorts = [ 3000 ];
environment.persistence."/persist".directories = [
{
directory = "/var/lib/pr-tracker";
user = "pr-tracker";
group = "pr-tracker";
mode = "0700";
}
];
age.secrets.maddyPasswd = {
generator.script = "alnum";
owner = "pr-tracker";
};
age.secrets.prTrackerEnv = {
rekeyFile = config.node.secretsDir + "/env.age";
owner = "pr-tracker";
};
age.secrets.prTrackerWhiteList = {
rekeyFile = config.node.secretsDir + "/white-list.age";
owner = "pr-tracker";
};
nodes.maddy = {
age.secrets.pr-trackerPasswd = {
inherit (config.age.secrets.maddyPasswd) rekeyFile;
inherit (nodes.maddy.config.services.maddy) group;
mode = "640";
};
services.maddy.ensureCredentials = {
"pr-tracker@${config.secrets.secrets.global.domains.mail_public}".passwordFile =
nodes.maddy.config.age.secrets.pr-trackerPasswd.path;
};
};
systemd.sockets.pr-tracker = {
listenStreams = [ "0.0.0.0:3000" ];
wantedBy = [ "sockets.target" ];
};
systemd.services.pr-tracker = {
path = [ pkgs.git ];
serviceConfig = {
User = "pr-tracker";
Group = "pr-tracker";
StateDirectory = "pr-tracker";
WorkingDirectory = "/var/lib/pr-tracker";
LimitNOFILE = "1048576";
PrivateTmp = true;
PrivateDevices = true;
StateDirectoryMode = "0700";
Restart = "always";
ExecStartPre = prestart;
ExecStart = ''
${lib.getExe pkgs.pr-tracker} --url "https://pr-tracker.${config.secrets.secrets.global.domains.web}"\
--user-agent "Patricks pr-tracker" \
--path nixpkgs --remote origin \
--email-white-list ${config.age.secrets.prTrackerWhiteList.path} \
--email-address pr-tracker@${config.secrets.secrets.global.domains.mail_public} \
--email-server smtp.${config.secrets.secrets.global.domains.mail_public} \
'';
EnvironmentFile = config.age.secrets.prTrackerEnv.path;
# Hardening
CapabilityBoundingSet = "";
LockPersonality = true;
MemoryDenyWriteExecute = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProcSubset = "pid";
ProtectSystem = "strict";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"@pkey"
];
UMask = "0077";
};
};
systemd.timers.pr-tracker-update = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "30m";
OnUnitActiveSec = "30m";
};
};
users.groups.pr-tracker = { };
users.users.pr-tracker = {
isSystemUser = true;
group = "pr-tracker";
home = "/var/lib/pr-tracker";
};
systemd.services.pr-tracker-update = {
script = ''
${lib.getExe pkgs.git} -C nixpkgs fetch
${lib.getExe pkgs.curl} http://localhost:3000/update
'';
serviceConfig = {
Requires = "pr-tracker";
Type = "oneshot";
User = "pr-tracker";
Group = "pr-tracker";
StateDirectory = "pr-tracker";
WorkingDirectory = "/var/lib/pr-tracker";
LimitNOFILE = "1048576";
PrivateTmp = true;
PrivateDevices = true;
StateDirectoryMode = "0700";
ExecStartPre = prestart;
EnvironmentFile = config.age.secrets.prTrackerEnv.path;
};
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, ... }:
{
config,
lib,
globals,
...
}:
let
shares = lib.removeAttrs config.services.samba.settings [ "global" ];
in
@ -26,8 +31,8 @@ in
passwordFile = config.age.secrets.resticpasswd.path;
hetznerStorageBox = {
enable = true;
inherit (config.secrets.secrets.global.hetzner) mainUser;
inherit (config.secrets.secrets.global.hetzner.users.smb) subUid path;
inherit (globals.hetzner) mainUser;
inherit (globals.hetzner.users.smb) subUid path;
sshAgeSecret = "resticHetznerSsh";
};
paths = [ "/bunker" ];

View file

@ -1,8 +1,8 @@
{ config, pkgs, ... }:
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 80 ];
};
services.freshrss = {
enable = true;

View file

@ -2,11 +2,9 @@
config,
lib,
nodes,
globals,
...
}:
let
vaultwardenDomain = "pw.${config.secrets.secrets.global.domains.web}";
in
{
age.secrets.vaultwarden-env = {
rekeyFile = config.node.secretsDir + "/vaultwarden-env.age";
@ -41,8 +39,8 @@ in
passwordFile = config.age.secrets.resticpasswd.path;
hetznerStorageBox = {
enable = true;
inherit (config.secrets.secrets.global.hetzner) mainUser;
inherit (config.secrets.secrets.global.hetzner.users.vaultwarden) subUid path;
inherit (globals.hetzner) mainUser;
inherit (globals.hetzner.users.vaultwarden) subUid path;
sshAgeSecret = "vaultwardenHetznerSsh";
};
paths = [ config.services.vaultwarden.backupDir ];
@ -70,7 +68,7 @@ in
group = "stalwart-mail";
mode = "440";
};
services.idmail.provision.mailboxes."vaultwarden@${config.secrets.secrets.global.domains.mail_public}" = {
services.idmail.provision.mailboxes."vaultwarden@${globals.domains.mail_public}" = {
password_hash = "%{file:${nodes.mailnix.config.age.secrets.idmail-vaultwarden-passwd-hash.path}}%";
owner = "admin";
};
@ -101,21 +99,23 @@ in
passwordIterations = 1000000;
invitationsAllowed = true;
invitationOrgName = "Vaultwarden";
domain = "https://${vaultwardenDomain}";
domain = "https://${globals.services.vaultwarden.domain}";
smtpHost = "smtp.${config.secrets.secrets.global.domains.mail_public}";
smtpFrom = "vaultwarden@${config.secrets.secrets.global.domains.mail_public}";
smtpHost = "smtp.${globals.domains.mail_public}";
smtpFrom = "vaultwarden@${globals.domains.mail_public}";
smtpPort = 465;
smtpSecurity = "force_tls";
smtpUsername = "vaultwarden@${config.secrets.secrets.global.domains.mail_public}";
smtpUsername = "vaultwarden@${globals.domains.mail_public}";
smtpEmbedImages = true;
};
environmentFile = config.age.secrets.vaultwarden-env.path;
};
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.vaultwarden.config.rocketPort ];
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [
config.services.vaultwarden.config.rocketPort
];
};
# Replace uses of old name

View file

@ -1,8 +1,8 @@
{ config, pkgs, ... }:
{
wireguard.elisabeth = {
client.via = "elisabeth";
firewallRuleForNode.elisabeth.allowedTCPPorts = [
wireguard.services = {
client.via = "nucnix";
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [
3000
80
];

View file

@ -1637,11 +1637,11 @@
"treefmt-nix": "treefmt-nix_3"
},
"locked": {
"lastModified": 1734374811,
"narHash": "sha256-+an6TysKwyWWeC7MeWGoHcULR9gc7TeXyszMAzvwRRo=",
"lastModified": 1734695484,
"narHash": "sha256-wmUjUxaXpItyGzafb96oVuJu/0qM6VEBKehIQ2cC1dg=",
"ref": "refs/heads/main",
"rev": "85a6a4df38b05ed2d70e530d43de9820b3231e4a",
"revCount": 25,
"rev": "99cbcc03d9ce737e53fbdab3213ce136fbca8bbe",
"revCount": 26,
"type": "git",
"url": "https://forge.lel.lol/patrick/nixp-meta.git"
},

View file

@ -116,6 +116,7 @@
imports = [
./nix/agenix-rekey.nix
./nix/devshell.nix
./nix/globals.nix
./nix/hosts.nix
./nix/pkgs.nix
./nix/patch.nix

123
globals.nix Normal file
View file

@ -0,0 +1,123 @@
{
config,
lib,
inputs,
...
}:
let
inherit (config) globals;
# Try to access the extra builtin we loaded via nix-plugins.
# Throw an error if that doesn't exist.
rageImportEncrypted =
assert lib.assertMsg (builtins ? extraBuiltins.rageImportEncrypted)
"The extra builtin 'rageImportEncrypted' is not available, so repo.secrets cannot be decrypted. Did you forget to add nix-plugins and point it to `./nix/extra-builtins.nix` ?";
builtins.extraBuiltins.rageImportEncrypted;
in
{
imports = [
(rageImportEncrypted inputs.self.secretsConfig.masterIdentities ./secrets/global.nix.age)
];
globals = {
net.vlans = {
home = rec {
id = 10;
cidrv4 = "10.99.${toString id}.0/24";
cidrv6 = "fd${toString id}::/64";
};
services = rec {
id = 20;
cidrv4 = "10.99.${toString id}.0/24";
cidrv6 = "fd${toString id}::/64";
};
devices = rec {
id = 30;
cidrv4 = "10.99.${toString id}.0/24";
cidrv6 = "fd${toString id}::/64";
};
iot = rec {
id = 40;
cidrv4 = "10.99.${toString id}.0/24";
cidrv6 = "fd${toString id}::/64";
};
guests = rec {
id = 50;
cidrv4 = "10.99.${toString id}.0/24";
cidrv6 = "fd${toString id}::/64";
};
};
services = {
adguardhome = {
domain = "adguardhome.${globals.domains.web}";
host = "nucnix-adguardhome";
};
forgejo = {
domain = "forge.${globals.domains.web}";
host = "elisabeth-forgejo";
};
immich = {
domain = "immich.${globals.domains.web}";
host = "elisabeth-immich";
};
nextcloud = {
domain = "nc.${globals.domains.web}";
host = "elisabeth-nextcloud";
};
ollama = {
domain = "ai.${globals.domains.web}";
host = "elisabeth-ollama";
};
paperless = {
domain = "ppl.${globals.domains.web}";
host = "elisabeth-paperless";
};
ttrss = {
domain = "rss.${globals.domains.web}";
host = "elisabeth-ttrss";
};
vaultwarden = {
domain = "pw.${globals.domains.web}";
host = "elisabeth-vaultwarden";
};
yourspotify = {
domain = "sptfy.${globals.domains.web}";
host = "elisabeth-yourspotify";
};
apispotify = {
domain = "apisptfy.${globals.domains.web}";
host = "elisabeth-apispotify";
};
kanidm = {
domain = "auth.${globals.domains.web}";
host = "elisabeth-kanidm";
};
oauth2-proxy = {
domain = "oauth2.${globals.domains.web}";
host = "elisabeth-oauth2-proxy";
};
actual = {
domain = "actual.${globals.domains.web}";
host = "elisabeth-actual";
};
firefly = {
domain = "money.${globals.domains.web}";
host = "elisabeth-firefly";
};
homebox = {
domain = "homebox.${globals.domains.web}";
host = "elisabeth-homebox";
};
invidious = {
domain = "yt.${globals.domains.web}";
host = "elisabeth-invidious";
};
blog = {
domain = "blog.${globals.domains.web}";
host = "elisabeth-blog";
};
netbird = {
domain = "netbird.${globals.domains.web}";
host = "elisabeth-netbird";
};
};
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, ... }:
{
config,
lib,
# globals,
...
}:
{
disko.devices = {
disk = {
@ -127,7 +132,8 @@
};
wireguard.scrtiny-patrick.server = {
host = config.secrets.secrets.global.domains.web;
#host = globals.domains.web;
host = "3.3.3.3";
port = 51831;
reservedAddresses = [
"10.44.0.0/16"

View file

@ -4,177 +4,9 @@
inputs,
lib,
minimal,
nodes,
...
}:
let
domainOf =
hostName:
let
domains = {
adguardhome = "adguardhome";
forgejo = "forge";
immich = "immich";
nextcloud = "nc";
ollama = "ai";
paperless = "ppl";
ttrss = "rss";
vaultwarden = "pw";
yourspotify = "sptfy";
apispotify = "apisptfy";
kanidm = "auth";
oauth2-proxy = "oauth2";
actual = "actual";
firefly = "money";
homebox = "homebox";
invidious = "yt";
blog = "blog";
};
in
"${domains.${hostName}}.${config.secrets.secrets.global.domains.web}";
# TODO hard coded elisabeth nicht so schön
ipOf = hostName: nodes."elisabeth-${hostName}".config.wireguard.elisabeth.ipv4;
in
{
services.netbird.server.proxy =
let
cfg = nodes.elisabeth-netbird.config.services.netbird.server;
in
{
domain = "netbird.${config.secrets.secrets.global.domains.web}";
enable = true;
enableNginx = true;
signalAddress = "${nodes.elisabeth-netbird.config.wireguard.elisabeth.ipv4}:${toString cfg.signal.port}";
relayAddress = "${nodes.elisabeth-netbird.config.wireguard.elisabeth.ipv4}:${toString cfg.relay.port}";
managementAddress = "${nodes.elisabeth-netbird.config.wireguard.elisabeth.ipv4}:${toString cfg.management.port}";
dashboardAddress = "${nodes.elisabeth-netbird.config.wireguard.elisabeth.ipv4}:80";
};
services.nginx =
let
blockOf =
hostName:
{
virtualHostExtraConfig ? "",
maxBodySize ? "500M",
port ? 3000,
upstream ? hostName,
protocol ? "http",
...
}:
{
upstreams.${hostName} = {
servers."${ipOf upstream}:${toString port}" = { };
extraConfig = ''
zone ${hostName} 64k ;
keepalive 5 ;
'';
};
virtualHosts.${domainOf hostName} = {
forceSSL = true;
useACMEHost = "web";
locations."/" = {
proxyPass = "${protocol}://${hostName}";
proxyWebsockets = true;
X-Frame-Options = "SAMEORIGIN";
};
extraConfig =
''
client_max_body_size ${maxBodySize} ;
''
+ virtualHostExtraConfig;
};
};
proxyProtect =
hostName:
{
allowedGroup ? true,
...
}@cfg:
lib.mkMerge [
(blockOf hostName cfg)
{
virtualHosts.${domainOf hostName} = {
locations."/".extraConfig = ''
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag
auth_request_set $user $upstream_http_x_auth_request_preferred_username;
# Set the email to our own domain in case user change their mail
auth_request_set $email "''${upstream_http_x_auth_request_preferred_username}@${config.secrets.secrets.global.domains.web}";
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
'';
locations."/oauth2/" = {
proxyPass = "http://oauth2-proxy";
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
locations."= /oauth2/auth" = {
proxyPass =
"http://oauth2-proxy/oauth2/auth"
+ lib.optionalString allowedGroup "?allowed_groups=${hostName}_access";
extraConfig = ''
internal;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
'';
};
};
}
];
in
lib.mkMerge [
{
enable = true;
recommendedSetup = true;
virtualHosts."netbird.${config.secrets.secrets.global.domains.web}".useACMEHost = "web";
}
(blockOf "vaultwarden" { maxBodySize = "1G"; })
(blockOf "forgejo" { maxBodySize = "1G"; })
(blockOf "immich" {
maxBodySize = "5G";
virtualHostExtraConfig = ''
proxy_buffering off;
proxy_request_buffering off;
'';
})
(proxyProtect "adguardhome" { })
(proxyProtect "oauth2-proxy" { allowedGroup = false; })
(blockOf "paperless" { maxBodySize = "5G"; })
(proxyProtect "ttrss" { port = 80; })
(proxyProtect "invidious" { })
(blockOf "yourspotify" { port = 80; })
(blockOf "blog" { port = 80; })
(blockOf "homebox" { })
(proxyProtect "ollama" { })
(proxyProtect "firefly" { port = 80; })
(blockOf "apispotify" {
port = 3000;
upstream = "yourspotify";
})
(blockOf "nextcloud" {
maxBodySize = "5G";
port = 80;
})
(blockOf "kanidm" {
protocol = "https";
virtualHostExtraConfig = ''
proxy_ssl_verify off ;
'';
})
];
guests =
let
@ -219,11 +51,9 @@ in
../../config/services/${guestName}.nix
{
node.secretsDir = config.node.secretsDir + "/${guestName}";
networking.nftables.firewall.zones.untrusted.interfaces =
if lib.length config.guests.${guestName}.networking.links < 2 then
config.guests.${guestName}.networking.links
else
[ ];
networking.nftables.firewall.zones.untrusted.interfaces = lib.mkIf (
lib.length config.guests.${guestName}.networking.links == 1
) config.guests.${guestName}.networking.links;
}
];
};
@ -233,11 +63,11 @@ in
backend = "microvm";
microvm = {
system = "x86_64-linux";
interfaces."lan" = { };
interfaces.lan = { };
baseMac = config.secrets.secrets.local.networking.interfaces.lan01.mac;
};
extraSpecialArgs = {
inherit (inputs.self) nodes;
inherit (inputs.self) nodes globals;
inherit (inputs.self.pkgs.x86_64-linux) lib;
inherit inputs minimal stateVersion;
};
@ -247,15 +77,11 @@ in
mkContainer = guestName: cfg: {
${guestName} = mkGuest guestName cfg // {
backend = "container";
container.macvlans = [ "lan" ];
container.macvlans = [ "lan-services" ];
extraSpecialArgs = {
inherit
lib
nodes
inputs
minimal
stateVersion
;
inherit (inputs.self) nodes globals;
inherit (inputs.self.pkgs.x86_64-linux) lib;
inherit inputs minimal stateVersion;
};
};
};

View file

@ -1,96 +1,151 @@
{ config, lib, ... }:
{
config,
lib,
globals,
...
}:
let
inherit (lib)
flip
mapAttrsToList
mkMerge
genAttrs
attrNames
;
in
{
networking = {
inherit (config.secrets.secrets.local.networking) hostId;
};
systemd.network.networks = {
"10-lan01" = {
address = [
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name}
config.secrets.secrets.global.net.privateSubnetv4
networking.nftables.firewall.zones = genAttrs (attrNames globals.net.vlans) (name: {
interfaces = [ "lan-${name}" ];
});
systemd.network.netdevs = mkMerge (
flip mapAttrsToList globals.net.vlans (
name:
{
id,
...
}:
{
"40-vlan-${name}" = {
netdevConfig = {
Name = "vlan-${name}";
Kind = "vlan";
};
vlanConfig.Id = id;
};
"50-macvlan-${name}" = {
netdevConfig = {
Name = "lan-${name}";
Kind = "macvlan";
};
extraConfig = ''
[MACVLAN]
Mode=bridge
'';
};
}
)
);
systemd.network.networks = mkMerge (
[
{
"40-vlans" = {
matchConfig.Name = "lan01";
networkConfig.LinkLocalAddressing = "no";
};
}
]
++ (flip mapAttrsToList globals.net.vlans (
name:
{
cidrv4,
cidrv6,
...
}:
{
"40-vlans".vlan = [ "vlan-${name}" ];
"10-vlan-${name}" = {
matchConfig.Name = "vlan-${name}";
# This interface should only be used from attached macvtaps.
# So don't acquire a link local address and only wait for
# this interface to gain a carrier.
networkConfig.LinkLocalAddressing = "no";
linkConfig.RequiredForOnline = "carrier";
extraConfig = ''
[Network]
MACVLAN=lan-${name}
'';
};
"20-lan-${name}" = {
address = [
(lib.net.cidr.hostCidr 1 cidrv4)
];
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
#matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
matchConfig.Name = "lan";
dhcpV6Config.UseDNS = false;
dhcpV4Config.UseDNS = false;
ipv6AcceptRAConfig.UseDNS = false;
matchConfig.Name = "lan-${name}";
networkConfig = {
MulticastDNS = true;
IPv6PrivacyExtensions = "yes";
IPv4Forwarding = "yes";
IPv6SendRA = true;
IPv6AcceptRA = false;
DHCPPrefixDelegation = true;
};
ipv6Prefixes = [
{ Prefix = cidrv6; }
];
};
}
))
);
networking.nftables.firewall = {
snippets.nnf-ssh.enable = lib.mkForce false;
rules = {
ssh = {
from = [
"home"
];
to = [ "local" ];
allowedTCPPorts = [ 22 ];
};
};
};
boot.initrd.systemd.network = {
boot.initrd = {
availableKernelModules = [
"8021q"
];
systemd.network = {
enable = true;
networks = {
# redo the network cause the livesystem has macvlans
"10-lan01" = {
"10-lanhome" = {
address = [
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name}
config.secrets.secrets.global.net.privateSubnetv4
)
# (lib.net.cidr.hostCidr 1 globals.net.vlans.home.cidrv4)
];
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
dhcpV6Config.UseDNS = false;
dhcpV4Config.UseDNS = false;
ipv6AcceptRAConfig.UseDNS = false;
matchConfig.Name = "vlan-home";
networkConfig = {
IPv6PrivacyExtensions = "yes";
MulticastDNS = true;
};
};
};
};
networking.nftables.firewall.zones.untrusted.interfaces = [ "lan" ];
wireguard.elisabeth.server = {
host =
lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name}
config.secrets.secrets.global.net.privateSubnetv4;
reservedAddresses = [
"10.42.0.0/20"
"fd00:1764::/112"
"40-vlans" = {
matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
vlan = [
"vlan-home"
];
openFirewall = true;
};
# To be able to ping containers from the host, it is necessary
# to create a macvlan on the host on the VLAN 1 network.
networking.macvlans.lan = {
interface = "lan01";
mode = "bridge";
};
netdevs = {
"10-vlan-home" = {
netdevConfig = {
Name = "vlan-home";
Kind = "vlan";
};
# vlanConfig.Id = globals.net.vlans.home.id;
};
};
};
};
age.secrets.cloudflare_token_acme = {
rekeyFile = ./secrets/cloudflare_api_token.age;
mode = "440";
group = "acme";
};
security.acme = {
acceptTerms = true;
defaults = {
email = config.secrets.secrets.global.devEmail;
dnsProvider = "cloudflare";
dnsPropagationCheck = true;
reloadServices = [ "nginx" ];
credentialFiles = {
"CF_DNS_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path;
"CF_ZONE_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path;
};
};
};
security.acme.certs.web = {
domain = config.secrets.secrets.global.domains.web;
extraDomainNames = [ "*.${config.secrets.secrets.global.domains.web}" ];
};
users.groups.acme.members = [ "nginx" ];
environment.persistence."/state".directories = [
{
directory = "/var/lib/acme";
user = "acme";
group = "acme";
mode = "0755";
}
];
}

View file

@ -1,20 +0,0 @@
age-encryption.org/v1
-> X25519 WretELIMVw/omsoHEMGR7PsFsfiUEfyUmlKMzmrw+wA
IW+zJKWSMfZiKs1LQwuAtej7ZDEvDt5oY+wfWpZoB1c
-> piv-p256 XTQkUA A5MNklHowU6rYbcJBT/+dW0v9Gex5IJ1sC5ksuRsfu1k
VPN/pCvMXi6Uc1uk6yuySK/e8bSjJ66zm4W62leQpBk
-> piv-p256 ZFgiIw Ah5jjfu6nrqXrW7YqfIEKWF3PrLOmEEM5LhRvi5EJVmE
MaVt5imJLBgM3NEw7tc18g9jMwPRl9c5RgCFzDIl8hk
-> piv-p256 5vmPtQ AqViuuU1xW/ngBTWFMjZax9SaQyZ/COo0fHNOwq/8Hkb
MDD3bD8PMS3AWPougqz/BXGGZGGnFPafZ0dc7Xqa0VM
-> piv-p256 ZFgiIw AuTg62739Zom64yEb4FZfA5lyeW9YP9h+3iDQJcQZSuM
TtwsPfCJi6bYH8tpPSdf9ZQlpXUC6t/AT1wM2aCXcNM
-> "-grease
n7GU3iZJjAz/ul8nNXzXYtrR
--- mvuAEeT2IOYZKF9u/htBSJSAxKuzLjx4hR65yyHzPK4
fœ<šJ{ïAzß(Ôz(Z|òxÏ0þhÍiaJd*T,o‡Ì«“A?¯ôò,ùÒ>²?»òe§.*Ð'Lû„ Æ7Õ®®B±÷ˆ®Â=<3D>ÈQ&<>c?*Wã¢#"ðÛù$Ee~?íû1‡í²Aý…ÿ±°aŸñÓ1Elƶx<C2B6>ÄñƼñ\<5C>Ëfµ'ê¼Xb"KÞñØÜf oÄhy|I¨5¦hÐÏÍÕî%?CKÒ <0C>R‰…È5÷ŽC! T7¯ÏÒððñ½'‰zÝIøSΰÖ&­AÖ&l´²®¤†ïþv$JYŸíR<C3AD> DVòO"üô­±Ùåў¥µ LSˆ|€¾øˆ\St,éÅŽÇ€w°Ïɬ<C389>,]>¼Qï8uLä~L&ûhÎ ÑÅ`špÙXÐ)Çål²
ã`ãÓ¸L/Rþ åÖ<ºZ3qW
î®\n]$çlÂÊ>Á<>Døj˜a5ÔÂ@=ñÒ5À|‰‰@Rõü- a½ÊÖµë<C2B5><C3AB>s•³^žŠÆ´—`ašì«b^ƒ0qræˆÙ™F¿%ÖCåë¼Ykª¯à&%<25><>ʪ7V™þUj2¯Ü.¥õ<C2A5>KÞ'«c!†ôÈ°+AÝ è[ ¸<>ö¥r©—¼&òjÉ[<06>†G<E280A0>t2D}ÿ»‚³-ÙHî Þàú€Å¾4ø0奣ýÊå&WÖ,“;}¢ØÀ5ðš¤÷
‰Zmìô^á[=çL Ëa(
4­=NŽ8ø¹=ð<>ƒ¢ü=åKQl“ð^ôm¶¢Aæ´?¸ì*°¾$í+<56>Ç—%UZ"á2²™Bá7ëÈbÅ>ÆMÛÊé(ø§û·ÿbÇAV^Ù¾a1bæg£ûA³ù,:±¢‚Å­íÖöRÙ.RöZ6M„ãšö! BÏ·þQ¶³El
”‰‰ïÓ¹~qö=ê³ üJ<C3BC>R{Œ#¾Ø×fªwQC>®cOºf<>°q¬ªÊä.eY@®Ú_붹»<cï.G˜â®ßÓù9E¬~´ë£¬xPÿ

View file

@ -4,114 +4,9 @@
inputs,
lib,
minimal,
nodes,
...
}:
let
domainOf =
hostName:
let
domains = {
};
in
"${domains.${hostName}}.${config.secrets.secrets.global.domains.web}";
# TODO hard coded elisabeth nicht so schön
ipOf = hostName: nodes."elisabeth-${hostName}".config.wireguard.elisabeth.ipv4;
in
{
services.nginx =
let
blockOf =
hostName:
{
virtualHostExtraConfig ? "",
maxBodySize ? "500M",
port ? 3000,
upstream ? hostName,
protocol ? "http",
...
}:
{
upstreams.${hostName} = {
servers."${ipOf upstream}:${toString port}" = { };
extraConfig = ''
zone ${hostName} 64k ;
keepalive 5 ;
'';
};
virtualHosts.${domainOf hostName} = {
forceSSL = true;
useACMEHost = "web";
locations."/" = {
proxyPass = "${protocol}://${hostName}";
proxyWebsockets = true;
X-Frame-Options = "SAMEORIGIN";
};
extraConfig =
''
client_max_body_size ${maxBodySize} ;
''
+ virtualHostExtraConfig;
};
};
proxyProtect =
hostName:
{
allowedGroup ? true,
...
}@cfg:
lib.mkMerge [
(blockOf hostName cfg)
{
virtualHosts.${domainOf hostName} = {
locations."/".extraConfig = ''
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag
auth_request_set $user $upstream_http_x_auth_request_preferred_username;
# Set the email to our own domain in case user change their mail
auth_request_set $email "''${upstream_http_x_auth_request_preferred_username}@${config.secrets.secrets.global.domains.web}";
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
'';
locations."/oauth2/" = {
proxyPass = "http://oauth2-proxy";
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
locations."= /oauth2/auth" = {
proxyPass =
"http://oauth2-proxy/oauth2/auth"
+ lib.optionalString allowedGroup "?allowed_groups=${hostName}_access";
extraConfig = ''
internal;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
'';
};
};
}
];
in
lib.mkMerge [
{
enable = false;
recommendedSetup = true;
}
];
guests =
let
mkGuest = guestName: _: {
@ -129,11 +24,9 @@ in
../../config/services/${guestName}.nix
{
node.secretsDir = config.node.secretsDir + "/${guestName}";
networking.nftables.firewall.zones.untrusted.interfaces =
if lib.length config.guests.${guestName}.networking.links < 2 then
config.guests.${guestName}.networking.links
else
[ ];
networking.nftables.firewall.zones.untrusted.interfaces = lib.mkIf (
lib.length config.guests.${guestName}.networking.links == 1
) config.guests.${guestName}.networking.links;
}
];
};
@ -143,11 +36,11 @@ in
backend = "microvm";
microvm = {
system = "x86_64-linux";
macvtap = "lan";
interfaces.lan = { };
baseMac = config.secrets.secrets.local.networking.interfaces.lan01.mac;
};
extraSpecialArgs = {
inherit (inputs.self) nodes;
inherit (inputs.self) nodes globals;
inherit (inputs.self.pkgs.x86_64-linux) lib;
inherit inputs minimal stateVersion;
};
@ -165,16 +58,14 @@ in
backend = "container";
container.macvlans = macvlans;
extraSpecialArgs = {
inherit
lib
nodes
inputs
minimal
stateVersion
;
inherit (inputs.self) nodes globals;
inherit (inputs.self.pkgs.x86_64-linux) lib;
inherit inputs minimal stateVersion;
};
};
};
in
{ } // mkContainer "adguardhome" { macvlans = [ "lan-services" ]; };
{ }
// mkContainer "adguardhome" { macvlans = [ "lan-services" ]; }
// mkContainer "nginx" { macvlans = [ "lan-services" ]; };
}

View file

@ -1,4 +1,4 @@
{ config, ... }:
{ globals, ... }:
{
@ -22,7 +22,7 @@
wifi6.enable = true;
wifi7.enable = true;
networks.wlan1 = {
inherit (config.secrets.secrets.global.hostapd) ssid;
inherit (globals.hostapd) ssid;
apIsolate = true;
authentication = {
saePasswords = [

View file

@ -1,26 +1,48 @@
{ config, lib, ... }:
{
config,
lib,
globals,
...
}:
let
vlans = {
home = 10;
services = 20;
devices = 30;
iot = 40;
guests = 50;
};
inherit (lib) flip mapAttrsToList;
inherit (lib)
flip
mapAttrsToList
mkMerge
genAttrs
attrNames
;
in
{
imports =
[
imports = [
./hostapd.nix
./kea.nix
];
networking.nftables.firewall.zones = mkMerge [
{ fritz.interfaces = [ "vlan-fritz" ]; }
(genAttrs (attrNames globals.net.vlans) (name: {
interfaces = [ "lan-${name}" ];
}))
];
systemd.network.netdevs = mkMerge (
[
{
"40-vlan-fritz" = {
netdevConfig = {
Name = "vlan-fritz";
Kind = "vlan";
};
vlanConfig.Id = 2;
};
}
]
++ (flip mapAttrsToList vlans (
name: id: {
networking.nftables.firewall.zones.${name}.interfaces = [ "lan-${name}" ];
systemd.network = {
netdevs = {
++ (flip mapAttrsToList globals.net.vlans (
name:
{
id,
...
}:
{
"40-vlan-${name}" = {
netdevConfig = {
Name = "vlan-${name}";
@ -28,7 +50,7 @@ in
};
vlanConfig.Id = id;
};
"50-mlan-${name}" = {
"50-macvlan-${name}" = {
netdevConfig = {
Name = "lan-${name}";
Kind = "macvlan";
@ -38,8 +60,39 @@ in
Mode=bridge
'';
};
}
))
);
systemd.network.networks = mkMerge (
[
{
"10-lan-fritz" = {
address = [
(lib.net.cidr.hostCidr 2 "10.99.2.0/24")
];
gateway = [ (lib.net.cidr.host 1 "10.99.2.0/24") ];
matchConfig.Name = "vlan-fritz";
networkConfig = {
IPv6PrivacyExtensions = "yes";
};
networks = {
};
"40-vlans" = {
matchConfig.Name = "lan01";
networkConfig.LinkLocalAddressing = "no";
vlan = [ "lan-fritz" ];
};
}
]
++ (flip mapAttrsToList globals.net.vlans (
name:
{
cidrv4,
cidrv6,
...
}:
{
"40-vlans".vlan = [ "vlan-${name}" ];
"10-vlan-${name}" = {
matchConfig.Name = "vlan-${name}";
# This interface should only be used from attached macvtaps.
@ -54,7 +107,7 @@ in
};
"20-lan-${name}" = {
address = [
(lib.net.cidr.hostCidr 1 "10.99.${toString id}.0/24")
(lib.net.cidr.hostCidr 1 cidrv4)
];
matchConfig.Name = "lan-${name}";
networkConfig = {
@ -66,13 +119,12 @@ in
DHCPPrefixDelegation = true;
};
ipv6Prefixes = [
{ Prefix = "fd${toString id}::/64"; }
{ Prefix = cidrv6; }
];
};
};
};
}
));
))
);
networking.nftables.firewall = {
snippets.nnf-ssh.enable = lib.mkForce false;
rules = {
@ -96,46 +148,24 @@ in
verdict = "accept";
masquerade = true;
};
wireguard = {
from = [ "services" ];
to = [ "local" ];
allowedUDPPorts = [ config.wireguard.services.server.port ];
};
};
networking.nftables.firewall.zones.fritz.interfaces = [ "vlan-fritz" ];
};
wireguard.services.server = {
host = lib.net.cidr.host 1 "10.99.20.0/24";
reservedAddresses = [
"10.42.0.0/20"
"fd00:1764::/112"
];
openFirewall = true;
};
networking = {
inherit (config.secrets.secrets.local.networking) hostId;
};
systemd.network = {
netdevs."40-vlan-fritz" = {
netdevConfig = {
Name = "vlan-fritz";
Kind = "vlan";
};
vlanConfig.Id = 2;
};
networks = {
"10-lan-fritz" = {
address = [
(lib.net.cidr.hostCidr 2 "10.99.2.0/24")
];
gateway = [ (lib.net.cidr.host 1 "10.99.2.0/24") ];
matchConfig.Name = "vlan-fritz";
networkConfig = {
IPv6PrivacyExtensions = "yes";
};
};
};
networks."40-vlans" = {
matchConfig.Name = "lan01";
networkConfig.LinkLocalAddressing = "no";
vlan = [
"vlan-fritz"
"vlan-home"
"vlan-services"
"vlan-devices"
"vlan-iot"
"vlan-guests"
];
};
};
boot.initrd = {
@ -148,7 +178,7 @@ in
# redo the network cause the livesystem has macvlans
"10-lanhome" = {
address = [
(lib.net.cidr.hostCidr 1 "10.99.10.0/24")
(lib.net.cidr.hostCidr 1 globals.net.vlans.home.cidrv4)
];
matchConfig.Name = "vlan-home";
networkConfig = {
@ -180,7 +210,7 @@ in
Name = "vlan-home";
Kind = "vlan";
};
vlanConfig.Id = 10;
vlanConfig.Id = globals.net.vlans.home.id;
};
"10-vlan-fritz" = {
netdevConfig = {

Binary file not shown.

150
modules/globals.nix Normal file
View file

@ -0,0 +1,150 @@
{
lib,
options,
...
}:
let
inherit (lib)
mkOption
types
;
in
{
options = {
globals = mkOption {
default = { };
type = types.submodule {
options = {
accounts.email = mkOption {
# Not really, should be the same type as the home-manager accounts.email option
# Just don't wann copy the whole definition
type = types.attrs;
default = { };
};
hostapd.ssid = mkOption {
type = types.nullOr types.str;
default = null;
description = "The ssid to use with hostapd";
};
domains = mkOption {
type = types.attrsOf types.str;
default = { };
};
hosts = mkOption {
type = types.attrsOf (
types.submodule {
options = {
ip = mkOption {
type = types.nullOr types.net.ipv4;
default = null;
description = "The public IP of this host";
};
};
}
);
};
users = mkOption {
type = types.attrsOf (
types.submodule {
options = {
hashedPassword = mkOption {
type = types.nullOr types.str;
default = null;
description = "The public IP of this host";
};
};
}
);
};
hetzner = mkOption {
default = { };
description = "Storage box configurations.";
type = types.submodule {
options = {
mainUser = mkOption {
type = types.str;
description = "Main username for the storagebox";
};
users = mkOption {
default = { };
description = "Subuser configurations.";
type = types.attrsOf (
types.submodule {
options = {
subUid = mkOption {
type = types.int;
description = "The subuser id";
};
path = mkOption {
type = types.str;
description = "The home path for this subuser (i.e. backup destination)";
};
};
}
);
};
};
};
};
net.vlans = mkOption {
default = { };
type = types.attrsOf (
types.submodule (vlanNetSubmod: {
options = {
id = mkOption {
type = types.ints.between 1 4094;
description = "The VLAN id";
};
cidrv4 = mkOption {
type = types.nullOr types.net.cidrv4;
default = null;
description = "The CIDRv4 of this vlan";
};
cidrv6 = mkOption {
type = types.nullOr types.net.cidrv6;
default = null;
description = "The CIDRv6 of this vlan";
};
name = mkOption {
description = "The name of this VLAN";
default = vlanNetSubmod.config._module.args.name;
type = types.str;
};
};
})
);
};
services = mkOption {
type = types.attrsOf (
types.submodule {
options = {
domain = mkOption {
type = types.str;
description = "The domain under which this service can be reached";
};
host = mkOption {
type = types.str;
description = "The node-name on which this service runs";
};
};
}
);
};
};
};
};
_globalsDefs = mkOption {
type = types.unspecified;
default = options.globals.definitions;
readOnly = true;
internal = true;
};
};
}

53
nix/globals.nix Normal file
View file

@ -0,0 +1,53 @@
{ inputs, ... }:
{
flake =
{
config,
lib,
...
}:
{
globals =
let
globalsSystem = lib.evalModules {
prefix = [ "globals" ];
specialArgs = {
inherit (inputs.self.pkgs.x86_64-linux) lib;
inherit inputs;
inherit (config) nodes;
};
modules = [
../modules/globals.nix
../globals.nix
(
{ lib, ... }:
{
globals = lib.mkMerge (
lib.concatLists (
lib.flip lib.mapAttrsToList config.nodes (
name: cfg:
builtins.addErrorContext "while aggregating globals from nixosConfigurations.${name} into flake-level globals:" cfg.config._globalsDefs
)
)
);
}
)
];
};
in
{
# Make sure the keys of this attrset are trivially evaluatable to avoid infinite recursion,
# therefore we inherit relevant attributes from the config.
inherit (globalsSystem.config.globals)
accounts
hosts
hostapd
domains
services
hetzner
net
users
;
};
};
}

View file

@ -25,7 +25,7 @@
specialArgs = {
# Use the correct instance lib that has our overlays
inherit (pkgs) lib;
inherit (config) nodes;
inherit (config) nodes globals;
inherit minimal stateVersion;
inputs = inputs // {
nixpkgs = self.nixpkgs-patched;
@ -87,7 +87,7 @@
nodes = config.nixosConfigurations // config.guestConfigurations;
wireguardEvalCache = config.pkgs.x86_64-linux.lib.wireguard.createEvalCache inputs [
"scrtiny-patrick"
"elisabeth"
"services"
];
};
}

BIN
secrets/global.nix.age Normal file

Binary file not shown.

Binary file not shown.

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 Mv11pZInyrNKXp9yT3maeq+nLpYWEKGSTog8bpa/KWw
ybH+dojanR8n4Ubq1H9D7CE5ipz9y3nqUnqw/6h9VNY
-> piv-p256 XTQkUA A3oYQXSUKuRPADT5kQEcZdgnkWuquWC2IMTYY7PHxU2g
dHajYp4/VOsBjdhQD1+UmX47F0v6q54zAFtJk82H1Os
-> piv-p256 ZFgiIw As8XHst+QSiFmM+jsDEPunagwwGsy9XG5ECAH3p4nUzp
qRxV2IOLGyMvsGIIKEj5wsjPzv8VB3s8UsXZ5tSJwxE
-> piv-p256 5vmPtQ At3pi/3ckCTfglnBNUOo3Iw182iBhm4/BdpEo6j51FZi
hJlqdt9g3g/BnvoXzjpjJgaRaNQlNgebF1SvGxLFTkw
-> piv-p256 ZFgiIw A3idLYAMWytoYJMcEl3wMbmWYxkFKMgQyBBp6KT/+OsY
29hfrgCAF+wRMQD4f+cItT63oOp0lx05FqpCKZTNyXs
-> 9O-grease < `3z5 sj+v
Qp3zpkMRcdwm62T+5GuIsMOd8dP1UetRc2x+z95NyQGM4lgNwjV2yoGPFNo8igPR
Hd7p4XkjjEcYtS9jv8m+pZbIi2KRdVCMLRC8f+Av7Y2ONQI
--- ViopD9rjKx8zdT8FHjYlB+N0MUsQT9imiTv8dlzF6RU
z”ëç<C3AB>¹“ Š~{†r¶Ë<C2B6>ƒ<03><>÷Ʀo<>Ã]¸-µñ¢<>¦!;$Ùûd“J<|IÀ<>óÎÁíás*Ó·ö×v¿ Å

View file

@ -1 +0,0 @@
n3HlzW2vkFj565rNTLcZHgJbBip9MXe4s1rctRWi1TQ=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 OJ8Lc0YjxJytlBJ14MMt6cuzyNeXkdOnh+mFymRz52U
sqSNr/vm5OZvaoiLTMxCcncIKtsGaZFfgHUXxFEfyiA
-> piv-p256 XTQkUA AhTYzUCOiOKq4EEU/bjl/eAkeDwo8o4YNVGKWw5Fuhux
ryBAAFjmFQM+4BLL66/Uvbb9Rtwb+neZS//aXYtHucY
-> piv-p256 ZFgiIw AtoEavPlKH74ztkeKOqRyPrzWQ7HLgE4yRrPxhGhRBX5
K1X0z4320HfFUDfNlYVJ73y6dp8ZtUXm31A86lud1cI
-> piv-p256 5vmPtQ AkNdVLt9VK/jBtew/8P70REU+qLxfsa8/4hsHaUD89cI
0odU8kcEA2hLHi5j8MW9twXX8zskKLudJPwyFT4/h0Q
-> piv-p256 ZFgiIw Axrpxh2W6qRG46jz+DLqIf74ZaSregbkUpKGlf/YFxcx
0pPiAtjPImcD+tnw4iKqiUPMW3q/edcX9z9/ZhEo67A
-> L1Uvx5wl-grease |&LSN XV(8oXE S*[P j6
JxdNfsiy1wJneYw90pf7Nlu7maEmuoC+KEXNpEB65P9TO16LfEobXUd5jwd+qjKG
GbvBchGQbYb5lFuVFbcgQDaI2Smadf4/IZZIfQ
--- UXIgkYtiD7ga9iZQAypc3agc0j8i1lbtdvNUphx2VZo
`~ÖpÓâKåb çFQ“S<E2809C>ò­"<22>¼ïêþYª2 ;r#UÀuÌÀOqx”{.ßäÃߣe[ØãÊvE™<E284A2>¨…E øLÕ­IMÑ"ÑmC

View file

@ -1 +0,0 @@
np/SufIR7ds1sqhdyEOf3bBXmvauVFnvcprB2osMAQE=

View file

@ -1,17 +0,0 @@
age-encryption.org/v1
-> X25519 eVtVzXtvsEgbNOdIy4VDn1FbpMAoSZ89cHEoFF+zDls
0naCdMLWG6MRREA/+OC+xbjxDnPXXfcwdvhGY9bmF3I
-> piv-p256 ZFgiIw A0b4W+z9JJLdoeLsceIWTgfq9AGhGCYzghM8A/xxi73q
9z6A/Xk39YcMlY6vflm/HEvMjjrfC8hcp9SVIZ601Xs
-> piv-p256 XTQkUA As6ZR0tijPVbIGJJQE7ebHDJVuMdvEF7uSecCAFZBr8q
f6KhqssOYi6Lm7xpNaQEtHKZ6qyd3/lRLDI7Id0+1I8
-> piv-p256 ZFgiIw AuJ8buC0fCg9gT9DpLSAfVFpYue6nKwq1Q4RLZU0eIfy
+UP/GGc/qW8wznHYVsW7xFuK4/pLgvesoODaafsZDhs
-> piv-p256 5vmPtQ AyrqpWUElWE9Ai+DeV1lUq+nHAqaZFZkMTPPIu0DiesF
S5T0MFAArqnNXtwrYGzAi5rK+BkWn/Gs8U6vtqijIwc
-> 0Skk=zN=-grease E: ]pN}4
zV/hyZHiaSckbVGuS+oNFItTxcLKTyL8G4G+Btzcym1Afm0CCrXL5fc/ss7tQ7Mx
ac7JEfvv9cCnAezvog
--- rvFVqJgSmwEk/Qy4x/LoIlAuJ6JtWxFvInGyO7lv96k
4ËñNÕࣅ
/ýLÒ©—C³I*³Ë¨¢2ã•‘¸.!Ûøšï.Ñ1þ »¡•Øèö 39ˆ)]t•mIý-&5t

View file

@ -1 +0,0 @@
DVpnYaoXKKk37IbTyG08bTWogBAD9N/s2PVodeHFaXo=

View file

@ -1 +0,0 @@
9xRD/oWYa5zpt7Om257Aj7U9IV6zKo4OqDBUxVzHo2A=

View file

@ -1,15 +0,0 @@
age-encryption.org/v1
-> X25519 eycLfsdMAUw2tJj5x33PGrfpUpivh/HTPa68TmTPmGQ
sTqEotydAfRHRRjI1JzO04OKBoHyVy0yk1wbdE4Psjc
-> piv-p256 XTQkUA AhCVTIgeo2WfoMZOvjZpf+YrQtruXlc5zt4u7giH6iOM
XYE/PHqHLWdTTYeBa12wIEMYp4dWa1uUkIRVB1SZ32U
-> piv-p256 ZFgiIw Akz/mZ2lQ/ZdzCX5R9rbM75WrMuJNGUYQ/jmsAzD8S25
a57G5Ceu7PcT0RK3gxbUmkqQoD6x3yjciqOU4JR69OM
-> piv-p256 5vmPtQ AzJjFtgTTuJxJRj2vJGJyOEnlYSa1teV4HPliIpffFHx
mLYOWr6SuCu5kgMUnTMDmXDpUZO6gnwm3V3qXRMxKDU
-> piv-p256 ZFgiIw A/OaBb5aN3DKxTAK4n2WtYvKGLZmRb4YCzlih9re4PcF
b45rIFE73gyGiRimMTREoMVSxWPbho8kwM0NzPGeNV4
-> TjQN9Fe6-grease 90VQ v=D
p4sbV1E
--- Wv+ihDw2UuzFYlPz6bQN/9kpXygD1+IWXzhM3g/q/ZQ
âW+Gd$<24>x”âzň5…÷”˕óaÁĺ5zĘüĽ´~řąú¨7jě!hóöťŠF€¦dPöą0MŇkž/p»ŇŕÝřĘ

View file

@ -1 +0,0 @@
7MnECQQR91RRR4S2M7iW0h8wDn4Ewhj7R2Z+y8AAg2A=

View file

@ -1 +0,0 @@
QZ8sx7wJ0pMAfxyA1hDgcemyI26/Vfaf7TICofiXPhM=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 QmW1YFkf2wn5zgzh1wLmb+dLk0+1/D6FWUEKg7mxciw
OR7j2nCl9FxcKBxMsJN0i3jrv5UQOxDGnwfmye7DYxo
-> piv-p256 XTQkUA AnTdNy1t0SAaeHIG91KQmlMVpAKqmalwfktAg91FL4aB
Z+jBzSM0JmJFzcqMe3N7r0HdFGeOnDVGh4ROYTYVP08
-> piv-p256 ZFgiIw Alks31//hpPgAS3ADktyVTQdT/Ab4Yu8FajsmWBijhqD
PzmjkWcHT8sEeKvIZLWNaUkFhR92YQ0Vs0SkG1c+lpQ
-> piv-p256 5vmPtQ A0t2/mWwCHc/UpwYvkObwJZ1gTqMYyjhljelgQCXNM+m
5q3i0ClG03ASXtlqBHMbhCFYSPem3d8y3lkFeEUW0eI
-> piv-p256 ZFgiIw AxL98VRYkHkM+uDSBWTI8bjdgvboJQ3o5l0M6ICq9IbF
N+Sb5dU3rksUVD4QFNu6U0jgs8Mo71CGWn4GiUb5CAU
-> e=H-grease T :(0"zbb` 7"
TkofyvqI9KJyWtPh3r4GLt0zpT5CJxo720xjJihdUjHeOLp4oVbhV1z2J2dsfJdG
vuZ3EBDXzhYYtLfVyQZltSKRSOw+5za9b7MEdKaulAMPeRo
--- qoqvdfP6fW3lXoN6DP2Qvl1NFXB4S3iipvV8gUiu/CY
³‰ ÚÇ<C39A>/h°K?8†ÓCC¼WíQš{Ù¹i<C2B9>{,ι³¡¡CEÃGö<47>£\G8jžP¶{<7B>‰6é·‡BüåLb«O÷®¹nR(å($°

View file

@ -1 +0,0 @@
V/8fGOARvXPqD+bZmn1n6E+/6R5bhP7kO15eKJctqTE=

View file

@ -1 +0,0 @@
34nMC0dvuS70Rn+685ExtKqQcEHdJvUzVvTcTZNwoVM=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 fFaEXRFuLeEW1V7DL243Zno37t1iA/ZoNatPCeh2LAc
bJ0y06//wH8ik5U1bfFifh+pmeOR0YpkZQoGscjMWSw
-> piv-p256 XTQkUA Aidtub6Z2JRPQDYO7Kz6bt+dQ2pmoNmbWxtViDt6F4GK
2sJMJfb4s/7KLjbjscvj7PktYrq+Y63GtAq8FQHiq9M
-> piv-p256 ZFgiIw Aw59iVn6zdxOepPlOge2b7As/G4+xWlVFYaVKkQOGwnw
m5PFMiGMV84Z6RY33ThrInsEKJTz92XFywunORtcw7c
-> piv-p256 5vmPtQ AuWWwbt+X8944l9dQdrop5cU7Yba4d6iNtgDcaOecfsH
l8/suY98Y0OLbYwhuLU6TYr7p9ZgTa5MvH/RvNwkWKQ
-> piv-p256 ZFgiIw A0QKpC1NyUusFefjUhHLQ+/0+nNWl928B1bZuXluWAQl
OcC8nBvW5KvozJSGX9gIyO8sh3DBxo9tOMQUhqjxKSk
-> v6t-grease
XjsK/Era/aby9lXJis4lXJrRGLUyyiwjo+jCOUwazvB5ZegR+2hXI8zjd78CgvXX
Iw
--- oYdppQraw32pbZ3RTXwoIv7A18Ul4wGCECPeZuxxvtI
È&'“©Ø¶ÃíãÜ.“[7~Ž‡rò™=‡sOu2u;¬hTzº·<C2BA>¬O}Œ¶ÔF,e+ÄzäT.ºþŒ·½·÷.+Œv<C592>ÔU¦¿áóDßå Ž

View file

@ -1 +0,0 @@
/89yv+rT1lqLAtDoIynHCEgHcrv6lwfoPTp7/4GP4ks=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 zghXrLqQhlVqAAbMi1k8gvG5IjG9boIJCyEx63DwwGo
/ae8dzj7mPxZdpciA+lLiR6H/WCrIvTkUfaXGP+RZiY
-> piv-p256 XTQkUA A4PgmdpN1WmH++JUTIdADZBqDrCQ2N8HP9FzQ7DtyJuU
CIzSKNP8YYYfMycueE564094XeKJ9mNEceAuUEnvFFI
-> piv-p256 ZFgiIw AgxtRiqyF4Fo6Us/l8vXhWl2tQakCQGwd1Dogf/Wqnyv
Gi9O1lFR2hhfkXoC7cmlpT+iHx0DxeDFmuU9i+Gc4Ms
-> piv-p256 5vmPtQ AsbmH20Pc58VF7tBnoE5iqzlrsahCDTHkvuyAQ4W5SPy
BcJr9QsIDanypSNZ0UWrt0VnJK99LM0FOmCQWc+2rPY
-> piv-p256 ZFgiIw A5CT86jvz263c1GoDrtGVBXZx9EZeQwCL2d/tCXGqay3
8kHhsuD77fPPLPe8JYTuHNcCtp0VJcdrTg220BVdyGc
-> v-"@h-grease sJN %C \ ?mh0`=L
FarOmtacPX3pzMNzucQdNxI8MpVZdumJghhEPiukRJxp5+3InvEp7lvBhtZv49i3
QPoKNFjUweN6aXA9Vs1cpSQ
--- k49nSQRFr22Pc4QtH0WlYQ2/yMpBXSJasmQ97ZcxLkU
^sÛø¬hÈÊ<C388>LÜvÕçøí©++'•å8¶{ZŠïÀÑCÆðŽ}ö¯ZúPQ0U$¸±²¨þ•:YÀ—õ”ïËÊ1­NO l'

View file

@ -1 +0,0 @@
yv8nqlqgBxDIf6oYrn01FRKoKnqZPfdenWIFHxfSLiA=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 iEBzJEtJTSmO3Sh0BMklgsGOBgVaiCYESkyvEjNRqg4
f8QwJYgLHLCrILE3QjeTiRL3B7o/YyzJry43O2m4v1w
-> piv-p256 XTQkUA A9pZLJ7fdKXK8/vAvk0dxotvScae5Y4nNXNDCwIPRm5M
AIsWjvaRKXLsKrPnncf70FmLBzZCoCApDutow7YBYNA
-> piv-p256 ZFgiIw AgeKhANA0G02k3DHnLD6m3fr6JKEDboK5mxScP8azmnT
lLW7QTJRhTlfg1rWl5tmHlkSL3jtU3Q6XcNlCW839Wg
-> piv-p256 5vmPtQ AkkCLbo5aWnOow68CsrVModJBDJmaberAIothw92Uj6W
iwVUFQkCOHg5e+EwuKZq21hkCk/8ZgyT2FrqD1vvMbs
-> piv-p256 ZFgiIw A5ldqhV8Y7KIzQ7iKleWUqirmt9/YC5kqmP7mR+b779K
I2OwnqfBAZOHQ8R3kiz20PUJA7PJlaUsh5Q9+W2XDyY
-> m*X-grease
tpDjVLTPOYTlDyBgstO+1xHdCTwc8iW0rOKpgqNF1iZH+e76Q7fUqt7OSSshyFqf
EZzGvqkemxXNLccD8VJXeeU5zLA4LqBEmNiK36zPzEMoJO8xEJ7SsmTtufY
--- RYsqETvw8iUKHCkw8z5mKPtEUds3e5WRn7o+llL33u0
ŒãwøypjÍl}سÖ/âÎúü×Ví±úÁ4óúù"m@þyZ‡xè­ýuý<75>ë,pn=Á¾ „,:­¤`É„¤/Á0¡Ó>3

View file

@ -1 +0,0 @@
qV+5b1yOMnHBE5hgKbJSDWnmvb15yt9XF37Le00C8wE=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 g1vqWzZctykJkoxT61vjFHJUqeNOKSg0bf3wCYB7MDc
D4JZnpctpgjZaIn5WK3/hpY9R5XhQHWnHFJ+Uh48ZIs
-> piv-p256 XTQkUA A64jIlHXaqPB+WBfZFOrOihV6EF7Y2yt5BxVtGydv/E/
JJ/yeiDQSl2NINj2sSN/TUzdNhgmrtI6NcPcp45tLSk
-> piv-p256 ZFgiIw AmP5WWw0UADOv+ilwqnbRYtq4sQUPPIAANFNjf33yqKr
B5FRnKIDqLPAlFzrpZXjoiH6BhE51GRocvGhRrGFEv0
-> piv-p256 5vmPtQ AoFOKSUyPwm3C/KmrC7z38CFMXr/Ct9mzvil7bHjg4jV
hFV3hQGKo8zPOybLDnRYlyeNTX5kFb8AOwBrgZ0JTb0
-> piv-p256 ZFgiIw A8SpfqzsNh/My9UQSiBNFKH8p29bLNs3NfbBkAQbbr+0
xeittOKnGG63GDguhqN2fYMg0LiLkqU3b7XStbDrrNY
-> y-grease x#'<Q
2zNxND7dipOrQT2lnYqzR3Nfl3ovQ7RJXiuUbsGuDp9tyPCxZ6I2DgclkMmt9VYu
qNm5aDYTLJpNfPhJniEtkBi+Yw
--- BA6/EyC1xL8JXy/dwpqrTyHT2SRbsyvlAHq32w8yIDE
û<EFBFBD>EëåD!¿dJUEŽÁ<C5BD>Zw5H#£i7<69>}­1»ÙãhÈ3÷«P1Õ<31>Q<EFBFBD>]gñ2à!YÈLmw×E¯ÒNò™Žd*Ì«È›

View file

@ -1 +0,0 @@
+OFa4ZrDnLty45PNocVJ7uhzU8JAaZiqZxCP9dENu1c=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 Fpotjtu7lksK7LzYZTkTP7OXF2etf6k/jAs3qT63pyg
Az3CTRHiYmqI9mVSvt61WgbQa1Sw7tTI/GwuwGNm2Rk
-> piv-p256 ZFgiIw AwwKW8KYhA3dsUgANUxvffEiFLOadwllahNrchfzQTfq
AO08XTSUINWT5eY1EgPqHHSY/y0gsgszz3psNnGSauA
-> piv-p256 XTQkUA AuxujxLf1wM1siHqnkbayQ6C4KZbsAzdUO/8dsiTRohe
1AUfKkOngKRI4jPG820VihSIP5ms9jH8MvHlEBiwVAE
-> piv-p256 ZFgiIw AqLEvSEzM5D4K/W67DVz7icte3mw5+FqFtBiv4Ba2xua
mbrEOcAnkiXq1Phh1SlnTjDuhLma+4hqv8FMceymOzQ
-> piv-p256 5vmPtQ AzENFlgqOyGbU/FXskgenHamZs/H+78mS9PWsYoXXqae
pyx2IlIw+p+7dAUg5Ohj1cKxW/9S51LjR2A47aNgH0c
-> AJ/nN^^b-grease P%To4qn; llf1 (\|f~06
ROV54+I9IMrCY2DvOXDRsY4otebllTMp6ddWYA
--- PGvDf7ZhjEQzcNDXVlDw4Qehrs/lg7hi22vu/2lo0N8
ˆ¤rëyÔ<79>±³{<7B>f#ßç`M}Ñ”<iö÷<C3B6>d=ÇÔp¾bÍnÿÂåEËé<C38B>-
¹$thòˆû:;.9ñ

View file

@ -1 +0,0 @@
wODUgMHl+qSCB8O1purynIY/AaPyIJ4kCFCEHmRedEk=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 m8FrH/TJL5v2er4GSGnDNLJGaTiRaiXYtxk7pGMMJnY
o6eINCtC6MdZUy3t5K7jWbWyp66YIILG8ndYxmRp974
-> piv-p256 XTQkUA Al8tF63UnANIwwup8gZEEcFb4DdF+6LDbe24InqpVfjb
dPAkYSsEe2vqmXx7k84bK0PYxiI8UKFHZzHswnSSQjs
-> piv-p256 ZFgiIw AqUv2b0Mg00xIF9QoCa2u6YBrMJAMJQ5q5TkJlT94pyL
q6LsNNkptP6KHorvFTeVfbhQVWeKRcgl7dnaY23hDGM
-> piv-p256 5vmPtQ AqIVMtD5c/hClFfSEjjEC/YEhuB1yk1Lgmse9yCkfdkA
V9/tCgauksldhaCRp8WZ9WfOSFPq4NOZptk+mp5dZI8
-> piv-p256 ZFgiIw A3LfSXJschjsAQHGwmkaHDeezim1DjR4T8n9hSpGj0I5
rHpCP8fa0VxPYV6qAKYQLg6Jreyq++HDV/nUQJzTVzw
-> ]-grease ?+jZ e jc:Xwo$
O92bCAaMkQpSsOKzFztoIy94sjgyZs4RfFoBz9Zcwb+P3IaHUpTGvW8wyYOGNcm8
2FLljf/kFZtHxtV8W7GtVnFDj0uwrMnClCnen329/46Ou6pHDcJ+/Q
--- swSl+llzwbh5ymR1l6iRQlTM0j+70PAw0v8xhZA/jlY
¸ÒÌ6WñÛÙ™ì†5BÔÙ IVSs$¯¥çC¿”ûl:Ʋ+»8+¶2‰µ<î³ÒT-R¶»¥âÀ®÷Iÿs>¬ZRˆÄ¥¾"㤽o

View file

@ -1 +0,0 @@
k0IBTHKntu0plDUIApo0ZOa3XlAh2Wea09nih4Ahij8=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 sJWb1AB1ani7iSARBKiza76F4BZ/1RT+nYo+h3SCvDM
G9r4LID6JVa+CbM+goWlorWNAutTfCWCRXkMKe68GnQ
-> piv-p256 ZFgiIw AimY8gt/sR16sX1pmQ7KsWjklSprUl5xQT51DJ2CBrmo
35Gchuo7PlxnVg7nCmPX2l+Hwpqkn11Deh/gINotDK4
-> piv-p256 XTQkUA A4Y83D0/vdl4f2gr8g09YO5xTM2en6/zdXTA4tlXTzse
pt0/k460n/rw0pGQVmbBvWkmscra5wL7Q4pUfC1aqJs
-> piv-p256 ZFgiIw A7kGeBnc71Bei30JFsrUPlhOYRfP/WwrtNYxyZ94blmd
tQcInK3OPdN5uYugFZc6JNMgMMrBHrNrfPLgK1GQuOU
-> piv-p256 5vmPtQ A2cBNFJA8IFoZcUGhwpTCrrh9v+ffe6UhbJkhYvfv310
zf161XjBEKWYDLwaWw+wGuCGJJFD6NatL3BgSQACB38
-> --grease \tv Z&IiJD *{Xl~2`' FOEGQ+s
hnw8ilMQCmjeH1dsP0p0Y6fY0X7l5goCmTR07RFMnXRH2Y7FQzSe5Ipg16+V9Rmj
1+RZABaebmFQFAJwtfFmeLXzsFVn0sMtflMR/wmunn+RuZ0XfzHzM0QOU2g
--- rdxJZDoceAdq9YF8GoDLcHz5UInJlcXCrOgr3/XxI/Q
è×Ч"ðV÷\ÆÒ¯<C392>œ/¤ßSÙñó×Üw¿qH(„¡€­HÐØö<C398>(=÷Åæ­ùŒœîaPiäÇ”ûØÜ_:K°·ˆSŸ1tØ¥Æ

View file

@ -1 +0,0 @@
HKftlC7tQXYToYo0VLHqvdnZxQfNtJ8u0QDN3mLgqiA=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 jCMM6Kfzndo9RElgyE/ufEMYrpwsowEpuYQ+U7NypCo
MBpF5pwy9moVqDHGudv0OxxG6UtdbKfvdphs89h3mi0
-> piv-p256 XTQkUA Asa11BAxSalte9zAy9P2TCw+OlzgPHHmVZJ0idqMUTOq
I7Uc1mXKZZCJ2sJ0vFvXzo0a173AwtO5IBQZ4LTfjuI
-> piv-p256 ZFgiIw AxkNUN4odgmfqbKIddw7LtY5SEDB0oxMOg+/vo3ooiMZ
rX4mq9JYyp6secsjIclReA4hDdSumaEeVava7TtO36M
-> piv-p256 5vmPtQ Au5aRQkGYLFwjjZGs/z/HDpVIwAMLK+O2FHK4tI+gxNw
HQYY3BJvG912yNOhne/e5Bosoa0N9i/d3Arsi1otmsQ
-> piv-p256 ZFgiIw AhGklGMPM/rAaye57Fz2PO1CIMBNjRPyP1sgsBsFhdUL
ITdXsq7gZ/13qqTsvfh+8FReiBmIpRwI+vDL+UBQKGY
-> ^}`pou-grease Wfm6eR *q.w\ ifZ #dT9
vd8IjtgnVmIKwldS7/Ii71SzniVtW9G6tCCiSmPM3tZE1EaYy0Z/6KuKPyz+tWst
Y+i4j7okriIH645tQXaI0oHcx4VZFn+JyRdX7mYNldwoNW3OKA
--- bAVe+xtXMtXfbGWz8TC+Wvbpmb8d5YVtUtdYqIG6Qfo
CÝöKvÛ3<EFBFBD>±mJÂÙÅÙ[l~0šr)+2Ì?éœÑ¦þ\U"“ôóMVÎQââ'BÎÄþ*Xï@¦­<10>Ä$DІ<C390>ìXy´dJ·fü<66>¶•9

View file

@ -1 +0,0 @@
9kyNM6XKz6HRLBECG/xRwplVZ7o6SEIxTPDuTvcPxw0=

View file

@ -1 +0,0 @@
SX7PZcM1u/eJZM/ghvBDS7am6HZzlsxhK537HWp62VQ=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 8Xu4B4tsiFMALzzDr8aIj1srctAEZ1QKYzT9wTs0DwU
0URbUZ1UlEdZpo8vT/LiJHW5RERO61S7RrJYviO6OYQ
-> piv-p256 XTQkUA A2ZwHHpSy6EzWxhfouDwh+PO//N1isE6TPUwAVPaAW2c
ljLdsmhEgsDRlz0y5Waea2FEm0k1L4W8igzYHz+/amk
-> piv-p256 ZFgiIw AohzN9q6Jo0LVuuYmxzhfizqlRPnuAlYIKx6dvMYvcq/
lSHu87hQJNVNHDTnMc9Se693+yELopkk6hFmUclLiuc
-> piv-p256 5vmPtQ AsBXiyuQmIaO2+Z2GTyT/rdhai2ahEkYkcO+dYsibZX4
DE5cSckHALqUdEYBe8Tpioo/DnD+DBpV/0pWZwvd2eI
-> piv-p256 ZFgiIw AgSNI31rf5CH8Gy+3ulIla3MgNkLfaHO/wKtfu4XTG/Y
n10QiolManskviiW3ogFtTpbzr1Mcs7/nFCxO6IQvdg
-> &\+nN-grease
xHRCwm5QRd8kTNpD9BNQflDjSoMEES64Y2yIHfbaEhJlLEp3MR+m2RzayFNxOfpr
zRjUwvQfjlhkS4bXLmYf5HHtBApMMX4
--- Ucy5PhVNSDJP+v6m5QDaZcomuvr5Z4XveQSTJwCAMsM
³çÜHaý<12> ÿ-´íÀý—5t¸õ†—Tv3‰¦DêÛ³Ø^?ݸ‰¬‚ãò\huýÊ9ù.`EÙ¬ªÓÂùè¦Áè cÒVBHÔG†Ìž©G

View file

@ -1 +0,0 @@
zipMs/ic3IPILamMOvnGWZU+PYdyA1i9UzC9UxRMXXc=

View file

@ -1 +0,0 @@
01wz/sO0PIlwtKTfR2z8pQKzFt4kO5CSq57f32y2F0Q=

View file

@ -1 +0,0 @@
F3tFnEGn58ahB2p4hI4xFRfwyK7SU3+Dx598DcLAQlA=

View file

@ -1 +0,0 @@
eIq8a4zS+xAcuilz8dw2znMm8xzMmYm3jg7wvAX5UV8=

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 kZNXioiEjSwPSSCQfLIUHJ/Po3Kjyzexkm9JOT02CUU
ZDtL78nQ9iM5br5keKL/HuuLO31giHa40m5YhoNkeN8
-> piv-p256 ZFgiIw AgNxOYUDaV1QTaV+IyMF09gouj/UtJA+y8H9h/MrgVM1
luS8js59wJ3cfsEloakGvoMmMWNkkq3Rc/AAvbxCA0I
-> piv-p256 XTQkUA A97+iI4FmLSEqnBpW7MJDFocMQBnv1yl5sNPLsZzapzP
CEmzOhcv6V6OGC3fpP8pUomlIRZxj05TQyYdDEtVwbI
-> piv-p256 ZFgiIw Az7qLW7ASn9x4PQt5yswl6BWULosp8j9D1sIlYe+E+XW
g80n2hOdx1m8pw8jeCFPHOH34bOApNVxapgiQj13USc
-> piv-p256 5vmPtQ Aj9Px4PctikcatMGBt7PTghHWLGtUXu0dbWUBROppbnX
5uYv5eEaZ6nfaId6JUaQSjbwTwZ+uyv7wSppAFZFnAM
-> )K-#NG;f-grease w] Do
Jlm3URc6Elpr7TIlK8e5K6Xu1Xy1f/mpG6XgdWgPRbNNOf0dXddDRuFT3g6lf6tK
FVmTXrLndZmPq33DD0WP6MwtBWmDCeh59/3DpjmvSxppM6Q
--- Pj8J65gm8i3w3GErpi1PXNdeQs/8cGkG2vetkgOifis
<06>ÿ·mBÑò¸¸F àºîG“…‰pRbúÎeƒ:8þiG8<47>Uyl +V`01ççà4<C3A0>ƒ´±ŒŽº¹Êèá+¢ñBâîó£&

View file

@ -1 +0,0 @@
2l6LxDMuuo+vr3aAraMbaVrCMHbWNNIujpwjDD/UPWA=

View file

@ -1 +0,0 @@
YFUko5BLbPFUxgMBOdRmuaP3W8MyKqcbKfGs+kJsaHQ=

View file

@ -1,15 +0,0 @@
age-encryption.org/v1
-> X25519 EYthUGeAWjYiRRcvPvVuWppnAnVEKvbBgkegeGFGzGQ
STGglgLwWiYP0Plr69RVxlIGVh0ZohPCaUy0Tl2rnbw
-> piv-p256 XTQkUA A1Tk7Xmx3KAxWakrxXyjLHzuAvwc0Y7p582tV/i45s/0
nhkvRnz7+lr0df84MMoHQJbpUoj+0UrdTw/XISq8taU
-> piv-p256 ZFgiIw A4rpsK3V2kcIQ2DRRL3Vj9nZUgANguzqvtHuLAVsCVlP
3V0M6j9CU/LWRkYaDI+3qvynu3s8UU91pjCaMEG8sTc
-> piv-p256 5vmPtQ AsD/VOJLQcHSoOVtJ8zdHxSnOv2JX/MsAGP0fB3SPvBq
yy4YY33Tzflj3rQg9xVAfJe47NNeX3GLBn4iZa0+aVM
-> piv-p256 ZFgiIw ApTVTCfJLHfVGA1Qbi44CisjSX4j/tJINa8xRDnEGYAN
4Z9/mK57H6JH7fsAlQTcEX/JjdzDiA+XgsA8tvcqM7U
-> Vffv6Z%t-grease Kc1"0ol xYS0
SOTywmAk8Z0fVaBEgVlPJMVWYNrN
--- GsqSM5RXgbGD3xulF6piH/NxH7AcVRVJT6rHQUqV/sY
xA€Żˇ,©Afí°ôáYíüU„R×!·$9ŻQăöUcNj¤<6A>Ţn%îHĺŇýnźÂĹáuéîČťÜVAŃéâtébJ

View file

@ -1,15 +0,0 @@
age-encryption.org/v1
-> X25519 8xUsd8+0vzcdMZ+9/Q7c4uHrINfL/YnGb2oi5TPPUwk
GrQDEqwQpunmU/Fwa0o2YV1VEMwb7F3uuUqPC2b9kNg
-> piv-p256 ZFgiIw AtzJHfEspGUDVtaXot1EE/u3Z5cTVL+PeBN2f5ZWbL6M
fOV0Hp6+cZB3NbypVXQtPULDonweA/62/G5gnunWVG4
-> piv-p256 XTQkUA AmPo/XlWsLPW+JYoTGCLTxWccJuh4EcKafN+D+URuGoF
3rHV1yeANXzWRpWb/0EA1IjCOitoTsLGN4dU1raTr0k
-> piv-p256 ZFgiIw AuduWmro6APJsPTCZrtRpkwECkOfsDL109rvrE9UxkkV
cnJb8UKLM1Oy9nZr+HQp3p6OhT/+9Htc3GoAqADa2nI
-> piv-p256 5vmPtQ A3ge8G2tligkbgdXvrngnObz6/kk3R5HN1Gl31Diz5hc
1d0ebykK0ccq7R4UegjAL+dl0EX6dves6Qsg4n7I0sA
-> :/-grease 4$+ P= _VV%:"P|
4Ny9m7mh1lEg
--- CsASon+mZ54A0BLZmBl9NaSa9n6M9mYbpY6igzdGF+U
“]lS"qùv¢½Öö˜P2­Õb¥“ç]•áÍÞ nóƒ7ÆÏ¥C@dD-y+å=ÊÇ<C38A>äY§ †Dë` v  ÆpñÙ~‹ìãþž

View file

@ -1,15 +0,0 @@
age-encryption.org/v1
-> X25519 xJo5HhKHIrFP7wbV//wpaFoboByUMZOXreZt5Xdd5BU
Ru6CBmrq1v/rbPhoPXYhCHq0yMGCCUiTgs6ZM5kVNKU
-> piv-p256 XTQkUA AivD+Matq7mjlIusMtx6+lHk5ryKZcg56EEwhGN71x2M
6qgJoPZWiuylup3zgJjYm1zLoG9YYL+as8UtGFhpnCg
-> piv-p256 ZFgiIw AqW0keuSK7y8oSO3JYe3/l+pAh+Wxqbu0XFNJ+qBH1Xc
vfCxAefSzfOo/1+ihhRS8Ilh7nsKwwyEf1LLRPfaKiQ
-> piv-p256 5vmPtQ Aqz7EelM5PCayYWA4IBPOjcPQp+qRU0TcTQIJM6cOBu9
t1bkON97ATB7CCcCFCOZVAr3PvZ0dFR9rnURWLD7dkk
-> piv-p256 ZFgiIw AvVb0aN4gHr586PdYixoAPBpF061efDQBshijna2MwQH
7TJos5wgP7QfSDLmjKvWEQCt1svv8/psA9os7FcG7Aw
-> mIBupI-grease jy yXj i/P I
M9tNIG4pdjXCQm9gWUWNr7bE0YBOzA
--- kKw6CxBObbcfeukkS/spDO+s4zcMkriNfDrfXoD04uw
 #¥sÏ®&ºJwÁ´Àüm~ÄÄS<C384>¼Ä&<04>X-Æ¥u—[WŒn¦tB[<01>죣ecÆHr×É)hÃg')Öð.M—Ыó U—Îkš

View file

@ -1,17 +0,0 @@
age-encryption.org/v1
-> X25519 qsgCpy8yqEIlPRdfE+Lxs5gOIYX9zIcllgXtOT0bQV8
GN/imU+Sf+2hT5zzOmYI9TgbLX4QgncJ1SHBjKaYlSA
-> piv-p256 XTQkUA AoLpzcqYmEDQTqFx+W3IBRGp03iJjaRrDRI8wfGbq/1X
QO08SCWFfwpSTUaQCnIKaGGWIgXh0i7w/p62X56ZMEc
-> piv-p256 ZFgiIw AlBi1aYyOCfnmlfVAdDVfvbN6NzEr/ypLeoH90cEwa5G
HZJ9bubfkFIEJbygeuvRm7UeTLppXG4knQFkKL678mM
-> piv-p256 5vmPtQ A3JtC4PRXJTHIuJzHoygX/5X4ok7cIfFF4wIQ2oghhpm
g4dV5vVrjbDt3ysLfBs74sy7yu1ol9PGPYF6uWnIu6k
-> piv-p256 ZFgiIw AuxXXZDLX6G9CTNow/ppXhTJ0GrNBO3RB7p9VC3BeY+0
QyfdagRgpUghg5U+mTYxxhVKrIIDEcAAzqwSSjwEbrk
-> 4-grease }E2
0IdsRluyK0F88hpuyJ8yVMFkcBJ6L9z5JBs8lovL26wWtxUg6knJD2vVopGiKCiD
Vol1dGBhU9085pt0C68av0GXXvPzxrsO+SDTz8c
--- m8uTaLg5F3GK5noq8WaqyfWN4bwotHUgnWvOMgzzAII
ñ­Ýûc„àFÉ%
ÍLD9QŽvÜ °W;!ÐÄê˵aÆ…aÀŠ o¨²Ì<C2B2>§±ÏE}Z/»s¦Û8š7º¿ÐD<C390>ã§<C3A3>±D<C2B1>7

View file

@ -1,17 +0,0 @@
age-encryption.org/v1
-> X25519 h2wNST4+qSw4uCVCUqSoprjByli3t11plBHp9y7dRGA
DCCsXoA+stUFmu0aNcNJSClOFTF9pNjgN6hsZjHkOrA
-> piv-p256 XTQkUA AvmTYpnMbBf4FiesxT0+RahR55nXJbmCsPh9jSXCk28K
AUOUpit2AsUMCh3KRqwMMSLJlSUlGBeoJZWyey3S41Q
-> piv-p256 ZFgiIw Ax8nhmzow+Pshj2paySHEdKc+V+BBP55FpwNa/HOumWu
1vnybx4PiWiep4LKISh9+DQzDcv46iTf0BytjwsVPqo
-> piv-p256 5vmPtQ A5l+gaNbTzurlEnGVdjdYBrXjF5R+xdxBANv3V9W74Tq
AmWUmtqPpGCG2G9xEswFwnCLNWS0iP9wdaS7UhMIA68
-> piv-p256 ZFgiIw Aq2tikCz8rv/r8PcY/3PKws74HTRdKC5WP1Ht/0ifeC+
kSiDUso530lPlYN2P0JIVG1LgEbL2TkRK9v8YQpUQ7A
-> =3mcTXky-grease |'ZI-R @E>y{ m){w =.h
yyiAGQon2cSKl+YqqZzrHRtsAnSVkg88UlO9Oj6nAdMc7/X+kNmoV0roz471Qcst
5WRDl9zm+ZUTS5bCqDdLThdKlxe2BFc4vp5WWd/QBVrlGuKPza8
--- JfX5HKp3fQCfBufji0c+DBERd4JPBp1v/HG5vXkRUzY
+{<7B>|Æ\X,<2C>50†¶tº+½KcÎ<>²ôàp¼àN²³d
ÇW:MÈ°Í•¼ÜJŽã”­*ìnË™a­9xþ-]

View file

@ -1,15 +0,0 @@
age-encryption.org/v1
-> X25519 DgYfF0fRhZ8YZ/OhLAkh2yTKJ8wJGn3NIWlZKPSouT8
t0ru+RkJaYwu1182O+7mXUPY//1MfMpWfAZHt8EB0Qg
-> piv-p256 XTQkUA AhsO8VrcSN3C0OvXnQZgknZmPQXkJ/AZLgoEJi8SEb02
45FaY0/8fSFDe7ICj26UaZU2b7FJ6LwYjA8PAG0te7k
-> piv-p256 ZFgiIw AyajmWcvtlbiql9fmKjAqOFrGXwxE+dKlO450qEzY6gj
ybg/Vq7X6iqFEvNAUeSwBL9MYEZk4PB1rj7m980JQZI
-> piv-p256 5vmPtQ ArpWoKRL+CQf70RgopH6D3atHb8F29h7wjuJcsTSgyQn
JuvfAbnXSwP3Jl1nX1y2pxsoIMuoh3vPr09vO42GgRs
-> piv-p256 ZFgiIw AwrP0evFqosflrXzbYJNx4fdJS9dF1107gPf3NEAoDJl
4TRZzpprOcjoXKMpWCXsgwMiKQHlKPmcFGxEQfq0fTM
-> HYEBa=-grease 5a{m+}I
vCELeWobKeGEIHMdXjqKDVyjrsgrKdp74Z8adOYuFF+01bSwou0bx5NE4PypoY8
--- Jp0EMbTh9Fm57m+RQGZZ1TQx2si06y00JrDP8a2quCo
% Pq~K<>!w`<60>/¦øÖI¬áMR$Zz·ô·©vNWDµç¦¶Å4`p1ª•S já*¤Ýxî`è¦<C3A8>"%*µk:

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 rqjulMMqQvFeDApkCZo4KQvgVbmZ/TLOpy3fe9CQCTc
j3JoyoBWSZtVDka4qqquips0HmZakBuToEjNe+ZEccQ
-> piv-p256 ZFgiIw A4e5w+3n+gkOMBeSI5VklW1kJ3846byVint8b7HGer4Z
jY/O+b0JwsNxpSvEtrWB1IaeVACDagAaqfLmoy9VGrw
-> piv-p256 XTQkUA A8WfkKXTvoJ4M4gX/t3xaK8wy2pZbLO9dBHrlUqKJHjr
I6WsWbqg+DIrOR7cJCk5cHz4gz0d44RhcNSqUU/9VSA
-> piv-p256 ZFgiIw Axn28eRfih6xjAKMw9ZFXHN4jKs013d2IhmLTAwl1Ixq
RldIXTSGdfjC5o4xzOttzyX89zAsuJGitSeoyts62mo
-> piv-p256 5vmPtQ A7sqh4eBJsdzALHPVdbk2WJ5YH0M8iSBX/wP8DtI7Mpm
tq6yVRXYXKwQD3qbvvBdF4AuFehgvgS7lq2DkI5hI6Y
-> s?-grease 38 Pego6HDg _|QaxRe
rexAgfgN8bC3JvURMFuCxfHxnIQ88B2hvka0BmvM7XJSWA8gAGLxjhOr0sw6iygG
6R+lshVeDfexCFxX4KWENEVzb9f4JWCqcGA
--- NtjNfHsaetHNRBHHwX0ncFGEb5hewYNhg8/WmJCLg80
<EFBFBD>ÎJÀZ¡»uó­Ö#ù|4|«/kd¥å óçêínÄÝ^@ß…3{—õ85Gtû‚å¼þò0mÐ.!Ç×¹ÿ€ÇXú½!¤ÃQ

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 OOfIE0asKIsd83l3FlOAUzVTZ2nyzgVVZ+3eFmVQTSM
Xp86tkjnZahB3SOb+/5/Q74MsCRwj0E5cWe3XyNnJlE
-> piv-p256 XTQkUA A+LfTwtC6M9B5IuzZx9zcSZ6/hblgphmAIwA6CRxk6AW
mYyS2Ot8h2eJbrJ/afIcfOX59aQCThE26KTibA71MQE
-> piv-p256 ZFgiIw A5I8g7TKBSDLsM0FpV6U/JVpabKuuCHHR9HdPqkuZqqa
CkvfGh6xS9GvSKhh/FNW4nKJgQMTUGbuqZtMbJvVyPg
-> piv-p256 5vmPtQ AlNBDeN5ihouDbb7mjNn7f4GDTRR0hf2M67LhCwMRR+x
vffnqgDMvm3OVlBKUvLR+aG5t9vBBJ8ygKTyk314G/Y
-> piv-p256 ZFgiIw ArEwrMQWaBWaOOYzUfB1zTCRQu/AjNiyN58UBSGaNhq/
ZwryYVzJR3RYGYMZPWmvWkvD5dyGwF1FIsDPSvCTmOg
-> .-grease
OozUcy+eh4uVbpuy/agtDWTCaZeccGlqym5s6L7KE+LqYmNhy61RwRC5NZqBPbsT
7H6EepsguVZzijQBhvPhJOK/a82g
--- 14GCAxnHT3eXYAvqtbaW6qHO2IAANgmVPl6Wlfox6wM
慾・刎^<5E><>eユ*PJBウ「ヨサ|ァヌ開碗ヒ<E7A297>」gヤa=゚十騨剽ヌC舟<43>C」du覡粟ネァj€ッ&U<>fル鑑?D`

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> X25519 bq+eQrKzKWG2cvp+7cKzpkN7KEbxf4H8aSOBxOBNeVE
uiZloroeAw+q0T9CTGbAg6cdHShGaa5YOVk0iE5FLMM
-> piv-p256 XTQkUA A5CqoI0rxRrOyHv6LksBqtzWPapfCLi6IdK3KAUATzJF
d3VMdZpw0TjU8kZ6WNLcbvenDD4WWxJp2rEogNnW43o
-> piv-p256 ZFgiIw Ah/2IZobkAFu0r0rSHvB9RyQhXh+wk1R9Vlky8J44xib
5GXXZuXybVXcrpU8G8bWYwMOjnzdw7X+YjQaQlA1F4E
-> piv-p256 5vmPtQ AjmJ3ZgFxcbSbGefvufWZNzo0nOc8vl+4jA7kb5kwSbI
2ks2FzxZ/YloeAVCRT/0NEo4hRWzUbknj+pnwtGuEZM
-> piv-p256 ZFgiIw ApvFPxETdpXGYLa9srv+pKFHNOGfa7ie8oyOInKDbOqC
8rIukUZzrkWdH11pnTYfPd259ql/UGg5/Z6SuNvslUA
-> X=N9-grease CPXXj9j! Mf6?oC AuDyAWo z5x1TGOh
CYoYan7n
--- 9xwTgosTBqh7i3YCpHUhvkYV6bormJ3hYP4WHTwwQk4
íIˆy»0Ö[Ûž$ÞŒ‹Ž- ¦¨:k@™ Ê}é9 Ÿåµ
2òîl'*Ô­[Sêr$ÿ*ÅWjüBì,-w£RÒ1ãBý&ø!€.ó@

Some files were not shown because too many files have changed in this diff Show more