feat: globals
feat: more vlan config
This commit is contained in:
parent
8332bc45ba
commit
053365c277
|
@ -2,13 +2,14 @@
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
|
globals,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
boot = lib.mkIf (!config.boot.isContainer) {
|
boot = lib.mkIf (!config.boot.isContainer) {
|
||||||
initrd.systemd = {
|
initrd.systemd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
emergencyAccess = config.secrets.secrets.global.users.root.passwordHash;
|
emergencyAccess = globals.users.root.hashedPassword;
|
||||||
extraBin.ip = "${pkgs.iproute2}/bin/ip";
|
extraBin.ip = "${pkgs.iproute2}/bin/ip";
|
||||||
extraBin.cryptsetup = "${pkgs.cryptsetup}/bin/cryptsetup";
|
extraBin.cryptsetup = "${pkgs.cryptsetup}/bin/cryptsetup";
|
||||||
users.root.shell = "${pkgs.bashInteractive}/bin/bash";
|
users.root.shell = "${pkgs.bashInteractive}/bin/bash";
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
../../modules/deterministic-ids.nix
|
../../modules/deterministic-ids.nix
|
||||||
../../modules/distributed-config.nix
|
../../modules/distributed-config.nix
|
||||||
|
../../modules/globals.nix
|
||||||
../../modules/meta.nix
|
../../modules/meta.nix
|
||||||
../../modules/iwd.nix
|
../../modules/iwd.nix
|
||||||
../../modules/secrets.nix
|
../../modules/secrets.nix
|
||||||
|
|
|
@ -77,8 +77,5 @@
|
||||||
let
|
let
|
||||||
local = config.node.secretsDir + "/secrets.nix.age";
|
local = config.node.secretsDir + "/secrets.nix.age";
|
||||||
in
|
in
|
||||||
{
|
lib.optionalAttrs (config.node.name != null && lib.pathExists local) { inherit local; };
|
||||||
global = ../../secrets/secrets.nix.age;
|
|
||||||
}
|
|
||||||
// lib.optionalAttrs (config.node.name != null && lib.pathExists local) { inherit local; };
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
|
||||||
};
|
};
|
||||||
imports = [ ../actual.nix ];
|
imports = [ ../actual.nix ];
|
||||||
services.actual = {
|
services.actual = {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, lib, ... }:
|
{ config, ... }:
|
||||||
{
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.adguardhome.port ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ config.services.adguardhome.port ];
|
||||||
};
|
};
|
||||||
services.adguardhome = {
|
services.adguardhome = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -30,11 +30,11 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
user_rules = [
|
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}"
|
# "||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}"
|
# "||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}"
|
# "||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}"
|
# "||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}"
|
# "||fritz.box^$dnsrewrite=${lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4}"
|
||||||
];
|
];
|
||||||
dhcp.enabled = false;
|
dhcp.enabled = false;
|
||||||
ratelimit = 60;
|
ratelimit = 60;
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
{ config, pkgs, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
globals,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
prestart = pkgs.writeShellScript "blog-pre" ''
|
prestart = pkgs.writeShellScript "blog-pre" ''
|
||||||
if [ ! -d ./.ssh ]; then
|
if [ ! -d ./.ssh ]; then
|
||||||
|
@ -8,18 +14,20 @@ let
|
||||||
ssh-keygen -t ed25519 -N "" -f .ssh/id_ed25519
|
ssh-keygen -t ed25519 -N "" -f .ssh/id_ed25519
|
||||||
fi
|
fi
|
||||||
if [ ! -d ./blog ]; then
|
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?"
|
echo "failed to clone the repository did you forget to add the ssh key?"
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
in {
|
in
|
||||||
wireguard.elisabeth = {
|
{
|
||||||
client.via = "elisabeth";
|
wireguard.services = {
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
|
client.via = "nucnix";
|
||||||
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 80 ];
|
||||||
};
|
};
|
||||||
environment.systemPackages = [ pkgs.signal-cli pkgs.cargo ];
|
environment.systemPackages = [
|
||||||
|
pkgs.signal-cli
|
||||||
|
pkgs.cargo
|
||||||
|
];
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
user = "blog";
|
user = "blog";
|
||||||
|
@ -31,12 +39,14 @@ in {
|
||||||
"[forge.lel.lol]:9922".publicKey =
|
"[forge.lel.lol]:9922".publicKey =
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWoGqHwkLVFXJwYcKs3CjQognvlZmROUIgkvvUgNalx";
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWoGqHwkLVFXJwYcKs3CjQognvlZmROUIgkvvUgNalx";
|
||||||
};
|
};
|
||||||
environment.persistence."/persist".directories = [{
|
environment.persistence."/persist".directories = [
|
||||||
directory = "/var/lib/blog";
|
{
|
||||||
user = "blog";
|
directory = "/var/lib/blog";
|
||||||
group = "blog";
|
user = "blog";
|
||||||
mode = "0700";
|
group = "blog";
|
||||||
}];
|
mode = "0700";
|
||||||
|
}
|
||||||
|
];
|
||||||
systemd.timers.blog-update = {
|
systemd.timers.blog-update = {
|
||||||
wantedBy = [ "timers.target" ];
|
wantedBy = [ "timers.target" ];
|
||||||
timerConfig = {
|
timerConfig = {
|
||||||
|
@ -60,14 +70,17 @@ in {
|
||||||
else
|
else
|
||||||
echo "Commiting newest changes"
|
echo "Commiting newest changes"
|
||||||
git -c user.name="blog-bot" \
|
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)"
|
commit -m "Automatic commit for blog on $(date -u -I)"
|
||||||
fi
|
fi
|
||||||
git pull --rebase
|
git pull --rebase
|
||||||
git push
|
git push
|
||||||
${lib.getExe pkgs.zola} -r public build
|
${lib.getExe pkgs.zola} -r public build
|
||||||
'';
|
'';
|
||||||
path = [ pkgs.openssh pkgs.git ];
|
path = [
|
||||||
|
pkgs.openssh
|
||||||
|
pkgs.git
|
||||||
|
];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Requires = "blog";
|
Requires = "blog";
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, ... }:
|
{ config, globals, ... }:
|
||||||
{
|
{
|
||||||
age.secrets.cloudflare_token_dns = {
|
age.secrets.cloudflare_token_dns = {
|
||||||
rekeyFile = config.node.secretsDir + "/cloudflare_api_token.age";
|
rekeyFile = config.node.secretsDir + "/cloudflare_api_token.age";
|
||||||
|
@ -8,12 +8,12 @@
|
||||||
networking.enableIPv6 = false;
|
networking.enableIPv6 = false;
|
||||||
services.ddclient = {
|
services.ddclient = {
|
||||||
enable = true;
|
enable = true;
|
||||||
zone = config.secrets.secrets.global.domains.web;
|
zone = globals.domains.web;
|
||||||
protocol = "Cloudflare";
|
protocol = "Cloudflare";
|
||||||
username = "token";
|
username = "token";
|
||||||
usev4 = "webv4, webv4='https://cloudflare.com/cdn-cgi/trace', webv4-skip='ip='";
|
usev4 = "webv4, webv4='https://cloudflare.com/cdn-cgi/trace', webv4-skip='ip='";
|
||||||
usev6 = "";
|
usev6 = "";
|
||||||
passwordFile = config.age.secrets.cloudflare_token_dns.path;
|
passwordFile = config.age.secrets.cloudflare_token_dns.path;
|
||||||
domains = [ config.secrets.secrets.global.domains.web ];
|
domains = [ globals.domains.web ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
{ config, nodes, ... }:
|
{
|
||||||
|
config,
|
||||||
|
nodes,
|
||||||
|
globals,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
i18n.supportedLocales = [ "all" ];
|
i18n.supportedLocales = [ "all" ];
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 80 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
age.secrets.appKey = {
|
age.secrets.appKey = {
|
||||||
|
@ -16,12 +21,12 @@
|
||||||
services.firefly-iii = {
|
services.firefly-iii = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableNginx = true;
|
enableNginx = true;
|
||||||
virtualHost = "money.${config.secrets.secrets.global.domains.web}";
|
virtualHost = globals.services.firefly.domain;
|
||||||
settings = {
|
settings = {
|
||||||
APP_URL = "https://money.${config.secrets.secrets.global.domains.web}";
|
APP_URL = "https://${globals.services.firefly.domain}";
|
||||||
TZ = "Europe/Berlin";
|
TZ = "Europe/Berlin";
|
||||||
TRUSTED_PROXIES = nodes.elisabeth.config.wireguard.elisabeth.ipv4;
|
TRUSTED_PROXIES = nodes.nucnix-nginx.config.wireguard.services.ipv4;
|
||||||
SITE_OWNER = "firefly-admin@${config.secrets.secrets.global.domains.mail_public}";
|
SITE_OWNER = "firefly-admin@${globals.domains.mail_public}";
|
||||||
APP_KEY_FILE = config.age.secrets.appKey.path;
|
APP_KEY_FILE = config.age.secrets.appKey.path;
|
||||||
AUTHENTICATION_GUARD = "remote_user_guard";
|
AUTHENTICATION_GUARD = "remote_user_guard";
|
||||||
AUTHENTICATION_GUARD_HEADER = "X-User";
|
AUTHENTICATION_GUARD_HEADER = "X-User";
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
|
globals,
|
||||||
nodes,
|
nodes,
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
|
||||||
forgejoDomain = "forge.${config.secrets.secrets.global.domains.web}";
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
age.secrets.resticpasswd = {
|
age.secrets.resticpasswd = {
|
||||||
generator.script = "alnum";
|
generator.script = "alnum";
|
||||||
|
@ -27,8 +25,8 @@ in
|
||||||
passwordFile = config.age.secrets.resticpasswd.path;
|
passwordFile = config.age.secrets.resticpasswd.path;
|
||||||
hetznerStorageBox = {
|
hetznerStorageBox = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (config.secrets.secrets.global.hetzner) mainUser;
|
inherit (globals.hetzner) mainUser;
|
||||||
inherit (config.secrets.secrets.global.hetzner.users.forgejo) subUid path;
|
inherit (globals.hetzner.users.forgejo) subUid path;
|
||||||
sshAgeSecret = "forgejoHetznerSsh";
|
sshAgeSecret = "forgejoHetznerSsh";
|
||||||
};
|
};
|
||||||
paths = [ config.services.forgejo.stateDir ];
|
paths = [ config.services.forgejo.stateDir ];
|
||||||
|
@ -52,9 +50,9 @@ in
|
||||||
home = config.services.forgejo.stateDir;
|
home = config.services.forgejo.stateDir;
|
||||||
};
|
};
|
||||||
|
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [
|
||||||
config.services.forgejo.settings.server.HTTP_PORT
|
config.services.forgejo.settings.server.HTTP_PORT
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
@ -86,7 +84,7 @@ in
|
||||||
group = "stalwart-mail";
|
group = "stalwart-mail";
|
||||||
mode = "440";
|
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}}%";
|
password_hash = "%{file:${nodes.mailnix.config.age.secrets.idmail-forgejo-passwd-hash.path}}%";
|
||||||
owner = "admin";
|
owner = "admin";
|
||||||
};
|
};
|
||||||
|
@ -116,9 +114,9 @@ in
|
||||||
# federation.ENABLED = true;
|
# federation.ENABLED = true;
|
||||||
mailer = {
|
mailer = {
|
||||||
ENABLED = true;
|
ENABLED = true;
|
||||||
SMTP_ADDR = "smtp.${config.secrets.secrets.global.domains.mail_public}";
|
SMTP_ADDR = "smtp.${globals.domains.mail_public}";
|
||||||
FROM = "forge@${config.secrets.secrets.global.domains.mail_public}";
|
FROM = "forge@${globals.domains.mail_public}";
|
||||||
USER = "forge@${config.secrets.secrets.global.domains.mail_public}";
|
USER = "forge@${globals.domains.mail_public}";
|
||||||
SEND_AS_PLAIN_TEXT = true;
|
SEND_AS_PLAIN_TEXT = true;
|
||||||
};
|
};
|
||||||
oauth2_client = {
|
oauth2_client = {
|
||||||
|
@ -137,8 +135,8 @@ in
|
||||||
server = {
|
server = {
|
||||||
HTTP_ADDR = "0.0.0.0";
|
HTTP_ADDR = "0.0.0.0";
|
||||||
HTTP_PORT = 3000;
|
HTTP_PORT = 3000;
|
||||||
DOMAIN = forgejoDomain;
|
DOMAIN = globals.services.forgejo.domain;
|
||||||
ROOT_URL = "https://${forgejoDomain}/";
|
ROOT_URL = "https://${globals.services.forgejo.domain}/";
|
||||||
LANDING_PAGE = "login";
|
LANDING_PAGE = "login";
|
||||||
SSH_PORT = 9922;
|
SSH_PORT = 9922;
|
||||||
};
|
};
|
||||||
|
@ -176,7 +174,7 @@ in
|
||||||
"--key"
|
"--key"
|
||||||
clientId
|
clientId
|
||||||
"--auto-discover-url"
|
"--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"
|
"--scopes"
|
||||||
"email"
|
"email"
|
||||||
"--scopes"
|
"--scopes"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
|
||||||
};
|
};
|
||||||
services.homebox = {
|
services.homebox = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
{
|
{
|
||||||
inputs,
|
inputs,
|
||||||
config,
|
config,
|
||||||
|
globals,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
domain = config.secrets.secrets.global.domains.mail_public;
|
domain = globals.domains.mail_public;
|
||||||
idmailDomain = "alias.${domain}";
|
idmailDomain = globals.services.idmail.domain;
|
||||||
priv_domain = config.secrets.secrets.global.domains.mail_private;
|
priv_domain = globals.domains.mail_private;
|
||||||
|
|
||||||
mkRandomSecret = {
|
mkRandomSecret = {
|
||||||
generator.script = "alnum";
|
generator.script = "alnum";
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
nodes,
|
nodes,
|
||||||
config,
|
config,
|
||||||
|
globals,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
version = "v1.119.1";
|
version = "v1.119.1";
|
||||||
immichDomain = "immich.${config.secrets.secrets.global.domains.web}";
|
immichDomain = "immich.${globals.domains.web}";
|
||||||
|
|
||||||
ipImmichMachineLearning = "10.89.0.10";
|
ipImmichMachineLearning = "10.89.0.10";
|
||||||
ipImmichPostgres = "10.89.0.12";
|
ipImmichPostgres = "10.89.0.12";
|
||||||
|
@ -57,10 +58,10 @@ let
|
||||||
};
|
};
|
||||||
notifications.smtp = {
|
notifications.smtp = {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
from = "immich@${config.secrets.secrets.global.domains.mail_public}";
|
from = "immich@${globals.domains.mail_public}";
|
||||||
transport = {
|
transport = {
|
||||||
username = "immich@${config.secrets.secrets.global.domains.mail_public}";
|
username = "immich@${globals.domains.mail_public}";
|
||||||
host = "smtp.${config.secrets.secrets.global.domains.mail_public}";
|
host = "smtp.${globals.domains.mail_public}";
|
||||||
port = 465;
|
port = 465;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -91,7 +92,7 @@ let
|
||||||
|
|
||||||
clientId = "immich";
|
clientId = "immich";
|
||||||
# clientSecret will be dynamically added in activation script
|
# 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";
|
scope = "openid email profile";
|
||||||
storageLabelClaim = "preferred_username";
|
storageLabelClaim = "preferred_username";
|
||||||
};
|
};
|
||||||
|
@ -163,7 +164,7 @@ in
|
||||||
group = "stalwart-mail";
|
group = "stalwart-mail";
|
||||||
mode = "440";
|
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}}%";
|
password_hash = "%{file:${nodes.mailnix.config.age.secrets.idmail-immich-passwd-hash.path}}%";
|
||||||
owner = "admin";
|
owner = "admin";
|
||||||
};
|
};
|
||||||
|
@ -193,8 +194,8 @@ in
|
||||||
passwordFile = config.age.secrets.resticpasswd.path;
|
passwordFile = config.age.secrets.resticpasswd.path;
|
||||||
hetznerStorageBox = {
|
hetznerStorageBox = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (config.secrets.secrets.global.hetzner) mainUser;
|
inherit (globals.hetzner) mainUser;
|
||||||
inherit (config.secrets.secrets.global.hetzner.users.immich) subUid path;
|
inherit (globals.hetzner.users.immich) subUid path;
|
||||||
sshAgeSecret = "immichHetznerSsh";
|
sshAgeSecret = "immichHetznerSsh";
|
||||||
};
|
};
|
||||||
backupPrepareCommand = ''
|
backupPrepareCommand = ''
|
||||||
|
@ -242,15 +243,15 @@ in
|
||||||
vcpu = 12;
|
vcpu = 12;
|
||||||
};
|
};
|
||||||
|
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.nftables.chains.forward.into-immich-container = {
|
networking.nftables.chains.forward.into-immich-container = {
|
||||||
after = [ "conntrack" ];
|
after = [ "conntrack" ];
|
||||||
rules = [
|
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"
|
"iifname podman1 oifname lan accept"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, ... }:
|
{ globals, ... }:
|
||||||
{
|
{
|
||||||
services.invidious = {
|
services.invidious = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain = "yt.${config.secrets.secrets.global.domains.web}";
|
inherit (globals.services.invidious) domain;
|
||||||
sig-helper.enable = true;
|
sig-helper.enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
external_port = 443;
|
external_port = 443;
|
||||||
|
@ -33,8 +33,8 @@
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
kanidmdomain = "auth.${config.secrets.secrets.global.domains.web}";
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
wireguard.elisabeth = {
|
globals,
|
||||||
client.via = "elisabeth";
|
config,
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
wireguard.services = {
|
||||||
|
client.via = "nucnix";
|
||||||
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
|
||||||
};
|
};
|
||||||
environment.persistence."/persist".directories = [
|
environment.persistence."/persist".directories = [
|
||||||
{
|
{
|
||||||
|
@ -56,8 +58,8 @@ in
|
||||||
package = pkgs.kanidm.withSecretProvisioning;
|
package = pkgs.kanidm.withSecretProvisioning;
|
||||||
enableServer = true;
|
enableServer = true;
|
||||||
serverSettings = {
|
serverSettings = {
|
||||||
domain = kanidmdomain;
|
inherit (globals.services.kanidm) domain;
|
||||||
origin = "https://${kanidmdomain}";
|
origin = "https://${globals.services.kanidm.domain}";
|
||||||
tls_chain = config.age.secrets.kanidm-cert.path;
|
tls_chain = config.age.secrets.kanidm-cert.path;
|
||||||
tls_key = config.age.secrets.kanidm-key.path;
|
tls_key = config.age.secrets.kanidm-key.path;
|
||||||
bindaddress = "0.0.0.0:3000";
|
bindaddress = "0.0.0.0:3000";
|
||||||
|
@ -83,8 +85,8 @@ in
|
||||||
};
|
};
|
||||||
systems.oauth2.paperless = {
|
systems.oauth2.paperless = {
|
||||||
displayName = "paperless";
|
displayName = "paperless";
|
||||||
originUrl = "https://ppl.${config.secrets.secrets.global.domains.web}/accounts/oidc/kanidm/login/callback/";
|
originUrl = "https://${globals.services.paperless.domain}/accounts/oidc/kanidm/login/callback/";
|
||||||
originLanding = "https://ppl.${config.secrets.secrets.global.domains.web}/";
|
originLanding = "https://${globals.services.paperless.domain}/";
|
||||||
basicSecretFile = config.age.secrets.oauth2-paperless.path;
|
basicSecretFile = config.age.secrets.oauth2-paperless.path;
|
||||||
scopeMaps."paperless.access" = [
|
scopeMaps."paperless.access" = [
|
||||||
"openid"
|
"openid"
|
||||||
|
@ -103,8 +105,8 @@ in
|
||||||
};
|
};
|
||||||
systems.oauth2.nextcloud = {
|
systems.oauth2.nextcloud = {
|
||||||
displayName = "nextcloud";
|
displayName = "nextcloud";
|
||||||
originUrl = "https://nc.${config.secrets.secrets.global.domains.web}/";
|
originUrl = "https://${globals.services.nextcloud.domain}/";
|
||||||
originLanding = "https://nc.${config.secrets.secrets.global.domains.web}/";
|
originLanding = "https://${globals.services.nextcloud.domain}/";
|
||||||
basicSecretFile = config.age.secrets.oauth2-nextcloud.path;
|
basicSecretFile = config.age.secrets.oauth2-nextcloud.path;
|
||||||
allowInsecureClientDisablePkce = true;
|
allowInsecureClientDisablePkce = true;
|
||||||
scopeMaps."nextcloud.access" = [
|
scopeMaps."nextcloud.access" = [
|
||||||
|
@ -125,10 +127,10 @@ in
|
||||||
systems.oauth2.immich = {
|
systems.oauth2.immich = {
|
||||||
displayName = "Immich";
|
displayName = "Immich";
|
||||||
originUrl = [
|
originUrl = [
|
||||||
"https://immich.${config.secrets.secrets.global.domains.web}/auth/login"
|
"https://${globals.services.immich.domain}/auth/login"
|
||||||
"https://immich.${config.secrets.secrets.global.domains.web}/api/oauth/mobile-redirect"
|
"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;
|
basicSecretFile = config.age.secrets.oauth2-immich.path;
|
||||||
allowInsecureClientDisablePkce = true;
|
allowInsecureClientDisablePkce = true;
|
||||||
enableLegacyCrypto = true;
|
enableLegacyCrypto = true;
|
||||||
|
@ -149,8 +151,8 @@ in
|
||||||
|
|
||||||
systems.oauth2.oauth2-proxy = {
|
systems.oauth2.oauth2-proxy = {
|
||||||
displayName = "Oauth2-Proxy";
|
displayName = "Oauth2-Proxy";
|
||||||
originUrl = "https://oauth2.${config.secrets.secrets.global.domains.web}/oauth2/callback";
|
originUrl = "https://${globals.services.oauth2-proxy.domain}/oauth2/callback";
|
||||||
originLanding = "https://oauth2.${config.secrets.secrets.global.domains.web}/";
|
originLanding = "https://${globals.services.oauth2-proxy.domain}/";
|
||||||
basicSecretFile = config.age.secrets.oauth2-proxy.path;
|
basicSecretFile = config.age.secrets.oauth2-proxy.path;
|
||||||
scopeMaps."adguardhome.access" = [
|
scopeMaps."adguardhome.access" = [
|
||||||
"openid"
|
"openid"
|
||||||
|
@ -202,8 +204,8 @@ in
|
||||||
};
|
};
|
||||||
systems.oauth2.forgejo = {
|
systems.oauth2.forgejo = {
|
||||||
displayName = "Forgejo";
|
displayName = "Forgejo";
|
||||||
originUrl = "https://forge.${config.secrets.secrets.global.domains.web}/user/oauth2/kanidm/callback";
|
originUrl = "https://${globals.services.forgejo.domain}/user/oauth2/kanidm/callback";
|
||||||
originLanding = "https://forge.${config.secrets.secrets.global.domains.web}/";
|
originLanding = "https://${globals.services.forgejo.domain}/";
|
||||||
basicSecretFile = config.age.secrets.oauth2-forgejo.path;
|
basicSecretFile = config.age.secrets.oauth2-forgejo.path;
|
||||||
scopeMaps."forgejo.access" = [
|
scopeMaps."forgejo.access" = [
|
||||||
"openid"
|
"openid"
|
||||||
|
@ -223,10 +225,10 @@ in
|
||||||
public = true;
|
public = true;
|
||||||
displayName = "Netbird";
|
displayName = "Netbird";
|
||||||
originUrl = [
|
originUrl = [
|
||||||
"https://netbird.${config.secrets.secrets.global.domains.web}/peers"
|
"https://${globals.services.netbird.domain}/peers"
|
||||||
"https://netbird.${config.secrets.secrets.global.domains.web}/add-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;
|
preferShortUsername = true;
|
||||||
enableLocalhostRedirects = true;
|
enableLocalhostRedirects = true;
|
||||||
enableLegacyCrypto = true;
|
enableLegacyCrypto = true;
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
config,
|
config,
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
|
globals,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
priv_domain = config.secrets.secrets.global.domains.mail_private;
|
priv_domain = globals.domains.mail_private;
|
||||||
domain = config.secrets.secrets.global.domains.mail_public;
|
domain = globals.domains.mail_public;
|
||||||
mailDomains = [
|
mailDomains = [
|
||||||
priv_domain
|
priv_domain
|
||||||
domain
|
domain
|
||||||
|
@ -41,8 +42,8 @@ in
|
||||||
passwordFile = config.age.secrets.resticpasswd.path;
|
passwordFile = config.age.secrets.resticpasswd.path;
|
||||||
hetznerStorageBox = {
|
hetznerStorageBox = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (config.secrets.secrets.global.hetzner) mainUser;
|
inherit (globals.hetzner) mainUser;
|
||||||
inherit (config.secrets.secrets.global.hetzner.users.maddy) subUid path;
|
inherit (globals.hetzner.users.maddy) subUid path;
|
||||||
sshAgeSecret = "maddyHetznerSsh";
|
sshAgeSecret = "maddyHetznerSsh";
|
||||||
};
|
};
|
||||||
paths = [
|
paths = [
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
{ config, lib, ... }:
|
|
||||||
{
|
{
|
||||||
wireguard.elisabeth = {
|
config,
|
||||||
client.via = "elisabeth";
|
lib,
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [
|
globals,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
wireguard.services = {
|
||||||
|
client.via = "nucnix";
|
||||||
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [
|
||||||
80 # dashboard
|
80 # dashboard
|
||||||
3000 # management
|
3000 # management
|
||||||
8012 # signal
|
8012 # signal
|
||||||
|
@ -47,20 +52,20 @@
|
||||||
clients.main = {
|
clients.main = {
|
||||||
port = 51820;
|
port = 51820;
|
||||||
environment = {
|
environment = {
|
||||||
NB_MANAGEMENT_URL = "https://netbird.${config.secrets.secrets.global.domains.web}";
|
NB_MANAGEMENT_URL = "https://${globals.services.netbird.domain}";
|
||||||
NB_ADMIN_URL = "https://netbird.${config.secrets.secrets.global.domains.web}";
|
NB_ADMIN_URL = "https://${globals.services.netbird.domain}";
|
||||||
NB_HOSTNAME = "home";
|
NB_HOSTNAME = "home";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
server = {
|
server = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain = "netbird.${config.secrets.secrets.global.domains.web}";
|
inherit (globals.services.netbird) domain;
|
||||||
|
|
||||||
dashboard = {
|
dashboard = {
|
||||||
enableNginx = true;
|
enableNginx = true;
|
||||||
settings = {
|
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
|
# Fix Kanidm not supporting fragmented URIs
|
||||||
AUTH_REDIRECT_URI = "/peers";
|
AUTH_REDIRECT_URI = "/peers";
|
||||||
AUTH_SILENT_REDIRECT_URI = "/add-peers";
|
AUTH_SILENT_REDIRECT_URI = "/add-peers";
|
||||||
|
@ -69,7 +74,7 @@
|
||||||
|
|
||||||
relay = {
|
relay = {
|
||||||
authSecretFile = config.age.secrets.relaySecret.path;
|
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 = {
|
coturn = {
|
||||||
|
@ -82,12 +87,12 @@
|
||||||
# DNS server should do the lookup this is not used
|
# DNS server should do the lookup this is not used
|
||||||
dnsDomain = "internal.invalid";
|
dnsDomain = "internal.invalid";
|
||||||
singleAccountModeDomain = "netbird.patrick";
|
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 = {
|
settings = {
|
||||||
TURNConfig = {
|
TURNConfig = {
|
||||||
Secret._secret = config.age.secrets.coturnSecret.path;
|
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 = {
|
HttpConfig = {
|
||||||
# This is not possible
|
# 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
|
# 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
|
||||||
|
|
|
@ -3,11 +3,9 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
config,
|
config,
|
||||||
nodes,
|
nodes,
|
||||||
|
globals,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
|
||||||
hostName = "nc.${config.secrets.secrets.global.domains.web}";
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
|
|
||||||
age.secrets.mailnix-passwd = {
|
age.secrets.mailnix-passwd = {
|
||||||
|
@ -28,7 +26,7 @@ in
|
||||||
group = "stalwart-mail";
|
group = "stalwart-mail";
|
||||||
mode = "440";
|
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}}%";
|
password_hash = "%{file:${nodes.mailnix.config.age.secrets.idmail-nextcloud-passwd-hash.path}}%";
|
||||||
owner = "admin";
|
owner = "admin";
|
||||||
};
|
};
|
||||||
|
@ -57,7 +55,7 @@ in
|
||||||
services.postgresql.package = pkgs.postgresql_16;
|
services.postgresql.package = pkgs.postgresql_16;
|
||||||
|
|
||||||
services.nextcloud = {
|
services.nextcloud = {
|
||||||
inherit hostName;
|
hostName = globals.services.nextcloud.domain;
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.nextcloud30;
|
package = pkgs.nextcloud30;
|
||||||
configureRedis = true;
|
configureRedis = true;
|
||||||
|
@ -79,7 +77,7 @@ in
|
||||||
phpOptions."opcache.interned_strings_buffer" = "32";
|
phpOptions."opcache.interned_strings_buffer" = "32";
|
||||||
settings = {
|
settings = {
|
||||||
default_phone_region = "DE";
|
default_phone_region = "DE";
|
||||||
trusted_proxies = [ nodes.elisabeth.config.wireguard.elisabeth.ipv4 ];
|
trusted_proxies = [ nodes.nucnix-nginx.config.wireguard.services.ipv4 ];
|
||||||
overwriteprotocol = "https";
|
overwriteprotocol = "https";
|
||||||
maintenance_window_start = 2;
|
maintenance_window_start = 2;
|
||||||
enabledPreviewProviders = [
|
enabledPreviewProviders = [
|
||||||
|
@ -97,13 +95,13 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
mail_smtpmode = "smtp";
|
mail_smtpmode = "smtp";
|
||||||
mail_smtphost = "smtp.${config.secrets.secrets.global.domains.mail_public}";
|
mail_smtphost = "smtp.${globals.domains.mail_public}";
|
||||||
mail_smtpport = 465;
|
mail_smtpport = 465;
|
||||||
mail_from_address = "nextcloud";
|
mail_from_address = "nextcloud";
|
||||||
mail_smtpsecure = "ssl";
|
mail_smtpsecure = "ssl";
|
||||||
mail_domain = config.secrets.secrets.global.domains.mail_public;
|
mail_domain = globals.domains.mail_public;
|
||||||
mail_smtpauth = true;
|
mail_smtpauth = true;
|
||||||
mail_smtpname = "nextcloud@${config.secrets.secrets.global.domains.mail_public}";
|
mail_smtpname = "nextcloud@${globals.domains.mail_public}";
|
||||||
loglevel = 2;
|
loglevel = 2;
|
||||||
};
|
};
|
||||||
config = {
|
config = {
|
||||||
|
@ -123,9 +121,9 @@ in
|
||||||
"L+ ${config.services.nextcloud.datadir}/config/mailer.config.php - - - - ${mailer-passwd-conf}"
|
"L+ ${config.services.nextcloud.datadir}/config/mailer.config.php - - - - ${mailer-passwd-conf}"
|
||||||
];
|
];
|
||||||
|
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 80 ];
|
||||||
};
|
};
|
||||||
networking = {
|
networking = {
|
||||||
# Use systemd-resolved inside the container
|
# Use systemd-resolved inside the container
|
||||||
|
|
186
config/services/nginx.nix
Normal file
186
config/services/nginx.nix
Normal 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";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
|
@ -1,8 +1,13 @@
|
||||||
{ config, nodes, ... }:
|
|
||||||
{
|
{
|
||||||
wireguard.elisabeth = {
|
config,
|
||||||
client.via = "elisabeth";
|
nodes,
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
globals,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
wireguard.services = {
|
||||||
|
client.via = "nucnix";
|
||||||
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 3000 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
age.secrets.oauth2-cookie-secret = {
|
age.secrets.oauth2-cookie-secret = {
|
||||||
|
@ -13,7 +18,7 @@
|
||||||
|
|
||||||
services.oauth2-proxy = {
|
services.oauth2-proxy = {
|
||||||
enable = true;
|
enable = true;
|
||||||
cookie.domain = ".${config.secrets.secrets.global.domains.web}";
|
cookie.domain = ".${globals.domains.web}";
|
||||||
cookie.secure = true;
|
cookie.secure = true;
|
||||||
cookie.expire = "900m";
|
cookie.expire = "900m";
|
||||||
cookie.secret = null;
|
cookie.secret = null;
|
||||||
|
@ -22,26 +27,26 @@
|
||||||
|
|
||||||
reverseProxy = true;
|
reverseProxy = true;
|
||||||
httpAddress = "0.0.0.0:3000";
|
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;
|
setXauthrequest = true;
|
||||||
extraConfig = {
|
extraConfig = {
|
||||||
code-challenge-method = "S256";
|
code-challenge-method = "S256";
|
||||||
whitelist-domain = ".${config.secrets.secrets.global.domains.web}";
|
whitelist-domain = ".${globals.domains.web}";
|
||||||
set-authorization-header = true;
|
set-authorization-header = true;
|
||||||
pass-access-token = true;
|
pass-access-token = true;
|
||||||
skip-jwt-bearer-tokens = true;
|
skip-jwt-bearer-tokens = true;
|
||||||
upstream = "static://202";
|
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";
|
provider-display-name = "Kanidm";
|
||||||
#client-secret-file = config.age.secrets.oauth2-client-secret.path;
|
#client-secret-file = config.age.secrets.oauth2-client-secret.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
provider = "oidc";
|
provider = "oidc";
|
||||||
scope = "openid email";
|
scope = "openid email";
|
||||||
loginURL = "https://auth.${config.secrets.secrets.global.domains.web}/ui/oauth2";
|
loginURL = "https://auth.${globals.domains.web}/ui/oauth2";
|
||||||
redeemURL = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/token";
|
redeemURL = "https://auth.${globals.domains.web}/oauth2/token";
|
||||||
validateURL = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/oauth2-proxy/userinfo";
|
validateURL = "https://auth.${globals.domains.web}/oauth2/openid/oauth2-proxy/userinfo";
|
||||||
clientID = "oauth2-proxy";
|
clientID = "oauth2-proxy";
|
||||||
email.domains = [ "*" ];
|
email.domains = [ "*" ];
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
disabledModules = [ "services/misc/octoprint.nix" ];
|
disabledModules = [ "services/misc/octoprint.nix" ];
|
||||||
imports = [ "${inputs.nixpkgs-octoprint}/nixos/modules/services/misc/octoprint.nix" ];
|
imports = [ "${inputs.nixpkgs-octoprint}/nixos/modules/services/misc/octoprint.nix" ];
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.octoprint.port ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ config.services.octoprint.port ];
|
||||||
};
|
};
|
||||||
environment.persistence."/persist".directories = [
|
environment.persistence."/persist".directories = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
{
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.open-webui.port ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ config.services.open-webui.port ];
|
||||||
};
|
};
|
||||||
services.ollama = {
|
services.ollama = {
|
||||||
host = "localhost";
|
host = "localhost";
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
pkgs,
|
pkgs,
|
||||||
nodes,
|
nodes,
|
||||||
|
globals,
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
paperlessdomain = "ppl.${config.secrets.secrets.global.domains.web}";
|
|
||||||
paperlessBackupDir = "/var/cache/backups/paperless";
|
paperlessBackupDir = "/var/cache/backups/paperless";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -34,8 +34,8 @@ in
|
||||||
passwordFile = config.age.secrets.resticpasswd.path;
|
passwordFile = config.age.secrets.resticpasswd.path;
|
||||||
hetznerStorageBox = {
|
hetznerStorageBox = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (config.secrets.secrets.global.hetzner) mainUser;
|
inherit (globals.hetzner) mainUser;
|
||||||
inherit (config.secrets.secrets.global.hetzner.users.paperless) subUid path;
|
inherit (globals.hetzner.users.paperless) subUid path;
|
||||||
sshAgeSecret = "paperlessHetznerSsh";
|
sshAgeSecret = "paperlessHetznerSsh";
|
||||||
};
|
};
|
||||||
paths = [ paperlessBackupDir ];
|
paths = [ paperlessBackupDir ];
|
||||||
|
@ -64,9 +64,9 @@ in
|
||||||
before = [ "restic-backups-main.service" ];
|
before = [ "restic-backups-main.service" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.paperless.port ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ config.services.paperless.port ];
|
||||||
};
|
};
|
||||||
|
|
||||||
age.secrets.paperless-admin-passwd = {
|
age.secrets.paperless-admin-passwd = {
|
||||||
|
@ -83,10 +83,10 @@ in
|
||||||
consumptionDir = "/paperless/consume";
|
consumptionDir = "/paperless/consume";
|
||||||
mediaDir = "/paperless/media";
|
mediaDir = "/paperless/media";
|
||||||
settings = {
|
settings = {
|
||||||
PAPERLESS_URL = "https://${paperlessdomain}";
|
PAPERLESS_URL = "https://${globals.services.paperless.domain}";
|
||||||
PAPERLESS_ALLOWED_HOSTS = paperlessdomain;
|
PAPERLESS_ALLOWED_HOSTS = globals.services.paperless.domain;
|
||||||
PAPERLESS_CORS_ALLOWED_HOSTS = "https://${paperlessdomain}";
|
PAPERLESS_CORS_ALLOWED_HOSTS = "https://${globals.services.paperless.domain}";
|
||||||
PAPERLESS_TRUSTED_PROXIES = nodes.elisabeth.config.wireguard.elisabeth.ipv4;
|
PAPERLESS_TRUSTED_PROXIES = nodes.nucnix-nginx.config.wireguard.services.ipv4;
|
||||||
|
|
||||||
PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect";
|
PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect";
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ in
|
||||||
provider_id = "kanidm";
|
provider_id = "kanidm";
|
||||||
name = "Kanidm";
|
name = "Kanidm";
|
||||||
client_id = "paperless";
|
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";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,4 +1,9 @@
|
||||||
{ config, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
globals,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
shares = lib.removeAttrs config.services.samba.settings [ "global" ];
|
shares = lib.removeAttrs config.services.samba.settings [ "global" ];
|
||||||
in
|
in
|
||||||
|
@ -26,8 +31,8 @@ in
|
||||||
passwordFile = config.age.secrets.resticpasswd.path;
|
passwordFile = config.age.secrets.resticpasswd.path;
|
||||||
hetznerStorageBox = {
|
hetznerStorageBox = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (config.secrets.secrets.global.hetzner) mainUser;
|
inherit (globals.hetzner) mainUser;
|
||||||
inherit (config.secrets.secrets.global.hetzner.users.smb) subUid path;
|
inherit (globals.hetzner.users.smb) subUid path;
|
||||||
sshAgeSecret = "resticHetznerSsh";
|
sshAgeSecret = "resticHetznerSsh";
|
||||||
};
|
};
|
||||||
paths = [ "/bunker" ];
|
paths = [ "/bunker" ];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
{
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [ 80 ];
|
||||||
};
|
};
|
||||||
services.freshrss = {
|
services.freshrss = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
nodes,
|
nodes,
|
||||||
|
globals,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
|
||||||
vaultwardenDomain = "pw.${config.secrets.secrets.global.domains.web}";
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
age.secrets.vaultwarden-env = {
|
age.secrets.vaultwarden-env = {
|
||||||
rekeyFile = config.node.secretsDir + "/vaultwarden-env.age";
|
rekeyFile = config.node.secretsDir + "/vaultwarden-env.age";
|
||||||
|
@ -41,8 +39,8 @@ in
|
||||||
passwordFile = config.age.secrets.resticpasswd.path;
|
passwordFile = config.age.secrets.resticpasswd.path;
|
||||||
hetznerStorageBox = {
|
hetznerStorageBox = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (config.secrets.secrets.global.hetzner) mainUser;
|
inherit (globals.hetzner) mainUser;
|
||||||
inherit (config.secrets.secrets.global.hetzner.users.vaultwarden) subUid path;
|
inherit (globals.hetzner.users.vaultwarden) subUid path;
|
||||||
sshAgeSecret = "vaultwardenHetznerSsh";
|
sshAgeSecret = "vaultwardenHetznerSsh";
|
||||||
};
|
};
|
||||||
paths = [ config.services.vaultwarden.backupDir ];
|
paths = [ config.services.vaultwarden.backupDir ];
|
||||||
|
@ -70,7 +68,7 @@ in
|
||||||
group = "stalwart-mail";
|
group = "stalwart-mail";
|
||||||
mode = "440";
|
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}}%";
|
password_hash = "%{file:${nodes.mailnix.config.age.secrets.idmail-vaultwarden-passwd-hash.path}}%";
|
||||||
owner = "admin";
|
owner = "admin";
|
||||||
};
|
};
|
||||||
|
@ -101,21 +99,23 @@ in
|
||||||
passwordIterations = 1000000;
|
passwordIterations = 1000000;
|
||||||
invitationsAllowed = true;
|
invitationsAllowed = true;
|
||||||
invitationOrgName = "Vaultwarden";
|
invitationOrgName = "Vaultwarden";
|
||||||
domain = "https://${vaultwardenDomain}";
|
domain = "https://${globals.services.vaultwarden.domain}";
|
||||||
|
|
||||||
smtpHost = "smtp.${config.secrets.secrets.global.domains.mail_public}";
|
smtpHost = "smtp.${globals.domains.mail_public}";
|
||||||
smtpFrom = "vaultwarden@${config.secrets.secrets.global.domains.mail_public}";
|
smtpFrom = "vaultwarden@${globals.domains.mail_public}";
|
||||||
smtpPort = 465;
|
smtpPort = 465;
|
||||||
smtpSecurity = "force_tls";
|
smtpSecurity = "force_tls";
|
||||||
smtpUsername = "vaultwarden@${config.secrets.secrets.global.domains.mail_public}";
|
smtpUsername = "vaultwarden@${globals.domains.mail_public}";
|
||||||
smtpEmbedImages = true;
|
smtpEmbedImages = true;
|
||||||
};
|
};
|
||||||
environmentFile = config.age.secrets.vaultwarden-env.path;
|
environmentFile = config.age.secrets.vaultwarden-env.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.vaultwarden.config.rocketPort ];
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [
|
||||||
|
config.services.vaultwarden.config.rocketPort
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# Replace uses of old name
|
# Replace uses of old name
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
{
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.services = {
|
||||||
client.via = "elisabeth";
|
client.via = "nucnix";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [
|
firewallRuleForNode.nucnix-nginx.allowedTCPPorts = [
|
||||||
3000
|
3000
|
||||||
80
|
80
|
||||||
];
|
];
|
||||||
|
|
|
@ -1637,11 +1637,11 @@
|
||||||
"treefmt-nix": "treefmt-nix_3"
|
"treefmt-nix": "treefmt-nix_3"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1734374811,
|
"lastModified": 1734695484,
|
||||||
"narHash": "sha256-+an6TysKwyWWeC7MeWGoHcULR9gc7TeXyszMAzvwRRo=",
|
"narHash": "sha256-wmUjUxaXpItyGzafb96oVuJu/0qM6VEBKehIQ2cC1dg=",
|
||||||
"ref": "refs/heads/main",
|
"ref": "refs/heads/main",
|
||||||
"rev": "85a6a4df38b05ed2d70e530d43de9820b3231e4a",
|
"rev": "99cbcc03d9ce737e53fbdab3213ce136fbca8bbe",
|
||||||
"revCount": 25,
|
"revCount": 26,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://forge.lel.lol/patrick/nixp-meta.git"
|
"url": "https://forge.lel.lol/patrick/nixp-meta.git"
|
||||||
},
|
},
|
||||||
|
|
|
@ -116,6 +116,7 @@
|
||||||
imports = [
|
imports = [
|
||||||
./nix/agenix-rekey.nix
|
./nix/agenix-rekey.nix
|
||||||
./nix/devshell.nix
|
./nix/devshell.nix
|
||||||
|
./nix/globals.nix
|
||||||
./nix/hosts.nix
|
./nix/hosts.nix
|
||||||
./nix/pkgs.nix
|
./nix/pkgs.nix
|
||||||
./nix/patch.nix
|
./nix/patch.nix
|
||||||
|
|
123
globals.nix
Normal file
123
globals.nix
Normal 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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,4 +1,9 @@
|
||||||
{ config, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
# globals,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
disko.devices = {
|
disko.devices = {
|
||||||
disk = {
|
disk = {
|
||||||
|
@ -127,7 +132,8 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
wireguard.scrtiny-patrick.server = {
|
wireguard.scrtiny-patrick.server = {
|
||||||
host = config.secrets.secrets.global.domains.web;
|
#host = globals.domains.web;
|
||||||
|
host = "3.3.3.3";
|
||||||
port = 51831;
|
port = 51831;
|
||||||
reservedAddresses = [
|
reservedAddresses = [
|
||||||
"10.44.0.0/16"
|
"10.44.0.0/16"
|
||||||
|
|
|
@ -4,177 +4,9 @@
|
||||||
inputs,
|
inputs,
|
||||||
lib,
|
lib,
|
||||||
minimal,
|
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 =
|
guests =
|
||||||
let
|
let
|
||||||
|
@ -219,11 +51,9 @@ in
|
||||||
../../config/services/${guestName}.nix
|
../../config/services/${guestName}.nix
|
||||||
{
|
{
|
||||||
node.secretsDir = config.node.secretsDir + "/${guestName}";
|
node.secretsDir = config.node.secretsDir + "/${guestName}";
|
||||||
networking.nftables.firewall.zones.untrusted.interfaces =
|
networking.nftables.firewall.zones.untrusted.interfaces = lib.mkIf (
|
||||||
if lib.length config.guests.${guestName}.networking.links < 2 then
|
lib.length config.guests.${guestName}.networking.links == 1
|
||||||
config.guests.${guestName}.networking.links
|
) config.guests.${guestName}.networking.links;
|
||||||
else
|
|
||||||
[ ];
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
@ -233,11 +63,11 @@ in
|
||||||
backend = "microvm";
|
backend = "microvm";
|
||||||
microvm = {
|
microvm = {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
interfaces."lan" = { };
|
interfaces.lan = { };
|
||||||
baseMac = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
baseMac = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
||||||
};
|
};
|
||||||
extraSpecialArgs = {
|
extraSpecialArgs = {
|
||||||
inherit (inputs.self) nodes;
|
inherit (inputs.self) nodes globals;
|
||||||
inherit (inputs.self.pkgs.x86_64-linux) lib;
|
inherit (inputs.self.pkgs.x86_64-linux) lib;
|
||||||
inherit inputs minimal stateVersion;
|
inherit inputs minimal stateVersion;
|
||||||
};
|
};
|
||||||
|
@ -247,15 +77,11 @@ in
|
||||||
mkContainer = guestName: cfg: {
|
mkContainer = guestName: cfg: {
|
||||||
${guestName} = mkGuest guestName cfg // {
|
${guestName} = mkGuest guestName cfg // {
|
||||||
backend = "container";
|
backend = "container";
|
||||||
container.macvlans = [ "lan" ];
|
container.macvlans = [ "lan-services" ];
|
||||||
extraSpecialArgs = {
|
extraSpecialArgs = {
|
||||||
inherit
|
inherit (inputs.self) nodes globals;
|
||||||
lib
|
inherit (inputs.self.pkgs.x86_64-linux) lib;
|
||||||
nodes
|
inherit inputs minimal stateVersion;
|
||||||
inputs
|
|
||||||
minimal
|
|
||||||
stateVersion
|
|
||||||
;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,96 +1,151 @@
|
||||||
{ config, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
globals,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib)
|
||||||
|
flip
|
||||||
|
mapAttrsToList
|
||||||
|
mkMerge
|
||||||
|
genAttrs
|
||||||
|
attrNames
|
||||||
|
;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
networking = {
|
networking = {
|
||||||
inherit (config.secrets.secrets.local.networking) hostId;
|
inherit (config.secrets.secrets.local.networking) hostId;
|
||||||
};
|
};
|
||||||
systemd.network.networks = {
|
networking.nftables.firewall.zones = genAttrs (attrNames globals.net.vlans) (name: {
|
||||||
"10-lan01" = {
|
interfaces = [ "lan-${name}" ];
|
||||||
address = [
|
});
|
||||||
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name}
|
systemd.network.netdevs = mkMerge (
|
||||||
config.secrets.secrets.global.net.privateSubnetv4
|
flip mapAttrsToList globals.net.vlans (
|
||||||
)
|
name:
|
||||||
];
|
{
|
||||||
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
|
id,
|
||||||
#matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
...
|
||||||
matchConfig.Name = "lan";
|
}:
|
||||||
dhcpV6Config.UseDNS = false;
|
{
|
||||||
dhcpV4Config.UseDNS = false;
|
"40-vlan-${name}" = {
|
||||||
ipv6AcceptRAConfig.UseDNS = false;
|
netdevConfig = {
|
||||||
networkConfig = {
|
Name = "vlan-${name}";
|
||||||
MulticastDNS = true;
|
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)
|
||||||
|
];
|
||||||
|
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 = {
|
|
||||||
enable = true;
|
boot.initrd = {
|
||||||
networks = {
|
|
||||||
# redo the network cause the livesystem has macvlans
|
availableKernelModules = [
|
||||||
"10-lan01" = {
|
"8021q"
|
||||||
address = [
|
];
|
||||||
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name}
|
systemd.network = {
|
||||||
config.secrets.secrets.global.net.privateSubnetv4
|
enable = true;
|
||||||
)
|
networks = {
|
||||||
];
|
# redo the network cause the livesystem has macvlans
|
||||||
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
|
"10-lanhome" = {
|
||||||
matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
address = [
|
||||||
dhcpV6Config.UseDNS = false;
|
# (lib.net.cidr.hostCidr 1 globals.net.vlans.home.cidrv4)
|
||||||
dhcpV4Config.UseDNS = false;
|
];
|
||||||
ipv6AcceptRAConfig.UseDNS = false;
|
matchConfig.Name = "vlan-home";
|
||||||
networkConfig = {
|
networkConfig = {
|
||||||
IPv6PrivacyExtensions = "yes";
|
IPv6PrivacyExtensions = "yes";
|
||||||
MulticastDNS = true;
|
};
|
||||||
|
};
|
||||||
|
"40-vlans" = {
|
||||||
|
matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
||||||
|
vlan = [
|
||||||
|
"vlan-home"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
netdevs = {
|
||||||
|
"10-vlan-home" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Name = "vlan-home";
|
||||||
|
Kind = "vlan";
|
||||||
|
};
|
||||||
|
# vlanConfig.Id = globals.net.vlans.home.id;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
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"
|
|
||||||
];
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>Lš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>Xà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æ´?¸ì*°¾$í+‚Vº<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ÿ
|
|
|
@ -4,114 +4,9 @@
|
||||||
inputs,
|
inputs,
|
||||||
lib,
|
lib,
|
||||||
minimal,
|
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 =
|
guests =
|
||||||
let
|
let
|
||||||
mkGuest = guestName: _: {
|
mkGuest = guestName: _: {
|
||||||
|
@ -129,11 +24,9 @@ in
|
||||||
../../config/services/${guestName}.nix
|
../../config/services/${guestName}.nix
|
||||||
{
|
{
|
||||||
node.secretsDir = config.node.secretsDir + "/${guestName}";
|
node.secretsDir = config.node.secretsDir + "/${guestName}";
|
||||||
networking.nftables.firewall.zones.untrusted.interfaces =
|
networking.nftables.firewall.zones.untrusted.interfaces = lib.mkIf (
|
||||||
if lib.length config.guests.${guestName}.networking.links < 2 then
|
lib.length config.guests.${guestName}.networking.links == 1
|
||||||
config.guests.${guestName}.networking.links
|
) config.guests.${guestName}.networking.links;
|
||||||
else
|
|
||||||
[ ];
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
@ -143,11 +36,11 @@ in
|
||||||
backend = "microvm";
|
backend = "microvm";
|
||||||
microvm = {
|
microvm = {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
macvtap = "lan";
|
interfaces.lan = { };
|
||||||
baseMac = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
baseMac = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
||||||
};
|
};
|
||||||
extraSpecialArgs = {
|
extraSpecialArgs = {
|
||||||
inherit (inputs.self) nodes;
|
inherit (inputs.self) nodes globals;
|
||||||
inherit (inputs.self.pkgs.x86_64-linux) lib;
|
inherit (inputs.self.pkgs.x86_64-linux) lib;
|
||||||
inherit inputs minimal stateVersion;
|
inherit inputs minimal stateVersion;
|
||||||
};
|
};
|
||||||
|
@ -165,16 +58,14 @@ in
|
||||||
backend = "container";
|
backend = "container";
|
||||||
container.macvlans = macvlans;
|
container.macvlans = macvlans;
|
||||||
extraSpecialArgs = {
|
extraSpecialArgs = {
|
||||||
inherit
|
inherit (inputs.self) nodes globals;
|
||||||
lib
|
inherit (inputs.self.pkgs.x86_64-linux) lib;
|
||||||
nodes
|
inherit inputs minimal stateVersion;
|
||||||
inputs
|
|
||||||
minimal
|
|
||||||
stateVersion
|
|
||||||
;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{ } // mkContainer "adguardhome" { macvlans = [ "lan-services" ]; };
|
{ }
|
||||||
|
// mkContainer "adguardhome" { macvlans = [ "lan-services" ]; }
|
||||||
|
// mkContainer "nginx" { macvlans = [ "lan-services" ]; };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, ... }:
|
{ globals, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
wifi6.enable = true;
|
wifi6.enable = true;
|
||||||
wifi7.enable = true;
|
wifi7.enable = true;
|
||||||
networks.wlan1 = {
|
networks.wlan1 = {
|
||||||
inherit (config.secrets.secrets.global.hostapd) ssid;
|
inherit (globals.hostapd) ssid;
|
||||||
apIsolate = true;
|
apIsolate = true;
|
||||||
authentication = {
|
authentication = {
|
||||||
saePasswords = [
|
saePasswords = [
|
||||||
|
|
|
@ -1,78 +1,130 @@
|
||||||
{ config, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
globals,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
vlans = {
|
inherit (lib)
|
||||||
home = 10;
|
flip
|
||||||
services = 20;
|
mapAttrsToList
|
||||||
devices = 30;
|
mkMerge
|
||||||
iot = 40;
|
genAttrs
|
||||||
guests = 50;
|
attrNames
|
||||||
};
|
;
|
||||||
inherit (lib) flip mapAttrsToList;
|
|
||||||
in
|
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 (
|
||||||
[
|
[
|
||||||
./hostapd.nix
|
{
|
||||||
./kea.nix
|
"40-vlan-fritz" = {
|
||||||
]
|
netdevConfig = {
|
||||||
++ (flip mapAttrsToList vlans (
|
Name = "vlan-fritz";
|
||||||
name: id: {
|
Kind = "vlan";
|
||||||
networking.nftables.firewall.zones.${name}.interfaces = [ "lan-${name}" ];
|
|
||||||
|
|
||||||
systemd.network = {
|
|
||||||
netdevs = {
|
|
||||||
"40-vlan-${name}" = {
|
|
||||||
netdevConfig = {
|
|
||||||
Name = "vlan-${name}";
|
|
||||||
Kind = "vlan";
|
|
||||||
};
|
|
||||||
vlanConfig.Id = id;
|
|
||||||
};
|
|
||||||
"50-mlan-${name}" = {
|
|
||||||
netdevConfig = {
|
|
||||||
Name = "lan-${name}";
|
|
||||||
Kind = "macvlan";
|
|
||||||
};
|
|
||||||
extraConfig = ''
|
|
||||||
[MACVLAN]
|
|
||||||
Mode=bridge
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
networks = {
|
|
||||||
"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 "10.99.${toString id}.0/24")
|
|
||||||
];
|
|
||||||
matchConfig.Name = "lan-${name}";
|
|
||||||
networkConfig = {
|
|
||||||
MulticastDNS = true;
|
|
||||||
IPv6PrivacyExtensions = "yes";
|
|
||||||
IPv4Forwarding = "yes";
|
|
||||||
IPv6SendRA = true;
|
|
||||||
IPv6AcceptRA = false;
|
|
||||||
DHCPPrefixDelegation = true;
|
|
||||||
};
|
|
||||||
ipv6Prefixes = [
|
|
||||||
{ Prefix = "fd${toString id}::/64"; }
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
vlanConfig.Id = 2;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
));
|
]
|
||||||
|
++ (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 (
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"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.
|
||||||
|
# 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)
|
||||||
|
];
|
||||||
|
matchConfig.Name = "lan-${name}";
|
||||||
|
networkConfig = {
|
||||||
|
MulticastDNS = true;
|
||||||
|
IPv6PrivacyExtensions = "yes";
|
||||||
|
IPv4Forwarding = "yes";
|
||||||
|
IPv6SendRA = true;
|
||||||
|
IPv6AcceptRA = false;
|
||||||
|
DHCPPrefixDelegation = true;
|
||||||
|
};
|
||||||
|
ipv6Prefixes = [
|
||||||
|
{ Prefix = cidrv6; }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
))
|
||||||
|
);
|
||||||
networking.nftables.firewall = {
|
networking.nftables.firewall = {
|
||||||
snippets.nnf-ssh.enable = lib.mkForce false;
|
snippets.nnf-ssh.enable = lib.mkForce false;
|
||||||
rules = {
|
rules = {
|
||||||
|
@ -96,46 +148,24 @@ in
|
||||||
verdict = "accept";
|
verdict = "accept";
|
||||||
masquerade = true;
|
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 = {
|
networking = {
|
||||||
inherit (config.secrets.secrets.local.networking) hostId;
|
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 = {
|
boot.initrd = {
|
||||||
|
|
||||||
|
@ -148,7 +178,7 @@ in
|
||||||
# redo the network cause the livesystem has macvlans
|
# redo the network cause the livesystem has macvlans
|
||||||
"10-lanhome" = {
|
"10-lanhome" = {
|
||||||
address = [
|
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";
|
matchConfig.Name = "vlan-home";
|
||||||
networkConfig = {
|
networkConfig = {
|
||||||
|
@ -180,7 +210,7 @@ in
|
||||||
Name = "vlan-home";
|
Name = "vlan-home";
|
||||||
Kind = "vlan";
|
Kind = "vlan";
|
||||||
};
|
};
|
||||||
vlanConfig.Id = 10;
|
vlanConfig.Id = globals.net.vlans.home.id;
|
||||||
};
|
};
|
||||||
"10-vlan-fritz" = {
|
"10-vlan-fritz" = {
|
||||||
netdevConfig = {
|
netdevConfig = {
|
||||||
|
|
BIN
hosts/nucnix/secrets/nginx/generated/dhparams.pem.age
Normal file
BIN
hosts/nucnix/secrets/nginx/generated/dhparams.pem.age
Normal file
Binary file not shown.
150
modules/globals.nix
Normal file
150
modules/globals.nix
Normal 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
53
nix/globals.nix
Normal 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
|
||||||
|
;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -25,7 +25,7 @@
|
||||||
specialArgs = {
|
specialArgs = {
|
||||||
# Use the correct instance lib that has our overlays
|
# Use the correct instance lib that has our overlays
|
||||||
inherit (pkgs) lib;
|
inherit (pkgs) lib;
|
||||||
inherit (config) nodes;
|
inherit (config) nodes globals;
|
||||||
inherit minimal stateVersion;
|
inherit minimal stateVersion;
|
||||||
inputs = inputs // {
|
inputs = inputs // {
|
||||||
nixpkgs = self.nixpkgs-patched;
|
nixpkgs = self.nixpkgs-patched;
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
nodes = config.nixosConfigurations // config.guestConfigurations;
|
nodes = config.nixosConfigurations // config.guestConfigurations;
|
||||||
wireguardEvalCache = config.pkgs.x86_64-linux.lib.wireguard.createEvalCache inputs [
|
wireguardEvalCache = config.pkgs.x86_64-linux.lib.wireguard.createEvalCache inputs [
|
||||||
"scrtiny-patrick"
|
"scrtiny-patrick"
|
||||||
"elisabeth"
|
"services"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
BIN
secrets/global.nix.age
Normal file
BIN
secrets/global.nix.age
Normal file
Binary file not shown.
Binary file not shown.
|
@ -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¿$öÅ
|
|
|
@ -1 +0,0 @@
|
||||||
n3HlzW2vkFj565rNTLcZHgJbBip9MXe4s1rctRWi1TQ=
|
|
|
@ -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
|
|
|
@ -1 +0,0 @@
|
||||||
np/SufIR7ds1sqhdyEOf3bBXmvauVFnvcprB2osMAQE=
|
|
|
@ -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þ »¡•Øèöa³@ý‚3‹Tô9ˆ‰)]t•mIý-&5t
|
|
|
@ -1 +0,0 @@
|
||||||
DVpnYaoXKKk37IbTyG08bTWogBAD9N/s2PVodeHFaXo=
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
9xRD/oWYa5zpt7Om257Aj7U9IV6zKo4OqDBUxVzHo2A=
|
|
|
@ -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ĘMź’üĽ´~řąú¨7jě!hóöťŠF€¦dPöą0MŇkž/p»ŇŕÝřĘ
|
|
|
@ -1 +0,0 @@
|
||||||
7MnECQQR91RRR4S2M7iW0h8wDn4Ewhj7R2Z+y8AAg2A=
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
QZ8sx7wJ0pMAfxyA1hDgcemyI26/Vfaf7TICofiXPhM=
|
|
|
@ -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(å($°
|
|
|
@ -1 +0,0 @@
|
||||||
V/8fGOARvXPqD+bZmn1n6E+/6R5bhP7kO15eKJctqTE=
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
34nMC0dvuS70Rn+685ExtKqQcEHdJvUzVvTcTZNwoVM=
|
|
|
@ -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ßå Ž
|
|
|
@ -1 +0,0 @@
|
||||||
/89yv+rT1lqLAtDoIynHCEgHcrv6lwfoPTp7/4GP4ks=
|
|
|
@ -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À—õ”ïËÊ1NO
l'
|
|
|
@ -1 +0,0 @@
|
||||||
yv8nqlqgBxDIf6oYrn01FRKoKnqZPfdenWIFHxfSLiA=
|
|
|
@ -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
|
|
|
@ -1 +0,0 @@
|
||||||
qV+5b1yOMnHBE5hgKbJSDWnmvb15yt9XF37Le00C8wE=
|
|
|
@ -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*Ì«È›
|
|
|
@ -1 +0,0 @@
|
||||||
+OFa4ZrDnLty45PNocVJ7uhzU8JAaZiqZxCP9dENu1c=
|
|
|
@ -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ñw¬
|
|
|
@ -1 +0,0 @@
|
||||||
wODUgMHl+qSCB8O1purynIY/AaPyIJ4kCFCEHmRedEk=
|
|
|
@ -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
|
|
|
@ -1 +0,0 @@
|
||||||
k0IBTHKntu0plDUIApo0ZOa3XlAh2Wea09nih4Ahij8=
|
|
|
@ -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Ø¥Æ
|
|
|
@ -1 +0,0 @@
|
||||||
HKftlC7tQXYToYo0VLHqvdnZxQfNtJ8u0QDN3mLgqiA=
|
|
|
@ -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
|
|
|
@ -1 +0,0 @@
|
||||||
9kyNM6XKz6HRLBECG/xRwplVZ7o6SEIxTPDuTvcPxw0=
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
SX7PZcM1u/eJZM/ghvBDS7am6HZzlsxhK537HWp62VQ=
|
|
|
@ -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
|
|
|
@ -1 +0,0 @@
|
||||||
zipMs/ic3IPILamMOvnGWZU+PYdyA1i9UzC9UxRMXXc=
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
01wz/sO0PIlwtKTfR2z8pQKzFt4kO5CSq57f32y2F0Q=
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
F3tFnEGn58ahB2p4hI4xFRfwyK7SU3+Dx598DcLAQlA=
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
eIq8a4zS+xAcuilz8dw2znMm8xzMmYm3jg7wvAX5UV8=
|
|
|
@ -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>ÿ·m›BÑò¸¸F
àºîG“…‰pRbúÎeƒ:8þiG8<47>Uyl
+V›`01ç‹çà4<C3A0>ƒ´±ŒŽº¹Êèá+¢ñB‘âîó£&
|
|
|
@ -1 +0,0 @@
|
||||||
2l6LxDMuuo+vr3aAraMbaVrCMHbWNNIujpwjDD/UPWA=
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
YFUko5BLbPFUxgMBOdRmuaP3W8MyKqcbKfGs+kJsaHQ=
|
|
|
@ -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 ^Ă
|
|
Binary file not shown.
|
@ -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ñÙ~‹ìãþž
|
|
|
@ -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š
|
|
|
@ -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
|
|
|
@ -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Ë™a9xþ-]
|
|
|
@ -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ª•SMœ’já*¤Ýxî`è¦<C3A8>"%*µk:
|
|
|
@ -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
|
|
||||||
Où<EFBFBD>ÎJÀZ¡»uóÖ#ù|4|«/kd¥å óçêínÄÝ^@ß…3{—õ85Gtû‚å¼þò0mÐ.!Ç×¹ÿ€ÇXú½!¤ÃQ
|
|
|
@ -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><>eFユ*PJBウ「ヨサ|ァヌ開碗ヒ<E7A297>」gヤa=゚十騨剽ヌC舟<43>C」du覡粟ネァjッ&U<>fル鑑?D`
|
|
|
@ -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
Loading…
Reference in a new issue