Compare commits

..

1 commit

Author SHA1 Message Date
3c1ec0f287 dynamic dns updates 2025-08-13 20:36:27 +02:00
68 changed files with 291 additions and 581 deletions

77
ci/build.sh Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env bash
set -euo pipefail
APP="$1"
if [ "$APP" = "hugo-chat" ]; then
REPO="https://github.com/C0RR1T/HugoChat.git"
elif [ "$APP" = "cors" ]; then
REPO="https://github.com/noratrieb-lehre/davinci-cors.git"
else
REPO="https://github.com/Noratrieb/$APP.git"
fi
echo "Checking out $REPO"
git clone "$REPO" ../app
cd ../app
CURRENT_COMMIT=$(git rev-parse HEAD | cut -c1-8)
echo "Latest commit of $APP is $CURRENT_COMMIT"
echo "**Commit: \`$CURRENT_COMMIT\`**" >> "$GITHUB_STEP_SUMMARY"
if [ "$APP" = "hugo-chat" ]; then
IMAGE_PREFIX="docker.noratrieb.dev/hugo-chat"
SERVER_FULL_NAME="$IMAGE_PREFIX-server:$CURRENT_COMMIT"
CLIENT_FULL_NAME="$IMAGE_PREFIX-client:$CURRENT_COMMIT"
pushd ./HugoServer
echo "Building server"
docker build . -t "$SERVER_FULL_NAME"
docker push "$SERVER_FULL_NAME"
popd
pushd ./hugo-client
echo "Building client"
docker build . -t "$CLIENT_FULL_NAME"
docker push "$CLIENT_FULL_NAME"
popd
exit 0
fi
if [ "$APP" = "cors" ]; then
IMAGE_PREFIX="docker.noratrieb.dev/cors-school"
SERVER_FULL_NAME="$IMAGE_PREFIX-server:$CURRENT_COMMIT"
CLIENT_FULL_NAME="$IMAGE_PREFIX-client:$CURRENT_COMMIT"
BOT_FULL_NAME="$IMAGE_PREFIX-bot:$CURRENT_COMMIT"
pushd ./react-frontend
echo "Building frontend"
docker build -t "$CLIENT_FULL_NAME" .
docker push "$CLIENT_FULL_NAME"
popd
pushd ./rust
echo "Building server"
docker build -t "$SERVER_FULL_NAME" -f Dockerfile.server .
docker push "$SERVER_FULL_NAME"
echo "Building bot"
docker build -t "$BOT_FULL_NAME" -f Dockerfile.bot .
docker push "$BOT_FULL_NAME"
popd
exit 0
fi
if [ "$APP" = "dockerolat" ]; then
APP="openolat"
fi
IMAGE_PREFIX="docker.noratrieb.dev/$APP"
IMAGE_FULL_NAME="$IMAGE_PREFIX:$CURRENT_COMMIT"
docker build . -t "$IMAGE_FULL_NAME"
docker push "$IMAGE_FULL_NAME"

View file

@ -1,15 +1,11 @@
{ pkgs, lib, config, my-projects-versions, ... }: { pkgs, lib, my-projects-versions, ... }:
let let
does-it-build-base = (import (pkgs.fetchFromGitHub my-projects-versions.does-it-build.fetchFromGitHub)) { does-it-build-base = (import (pkgs.fetchFromGitHub my-projects-versions.does-it-build.fetchFromGitHub)) { inherit pkgs; };
inherit pkgs;
};
does-it-build = does-it-build-base.overrideAttrs (finalAttrs: previousAttrs: { does-it-build = does-it-build-base.overrideAttrs (finalAttrs: previousAttrs: {
DOES_IT_BUILD_OVERRIDE_VERSION = my-projects-versions.does-it-build.commit; DOES_IT_BUILD_OVERRIDE_VERSION = my-projects-versions.does-it-build.commit;
}); });
in in
{ {
age.secrets.does_it_build_private_key.file = ../../secrets/does_it_build_private_key.age;
services.caddy.virtualHosts = { services.caddy.virtualHosts = {
"does-it-build.noratrieb.dev" = { "does-it-build.noratrieb.dev" = {
logFormat = ""; logFormat = "";
@ -39,32 +35,7 @@ in
User = "does-it-build"; User = "does-it-build";
Group = "does-it-build"; Group = "does-it-build";
ExecStart = "${lib.getExe' (does-it-build) "does-it-build" }"; ExecStart = "${lib.getExe' (does-it-build) "does-it-build" }";
Environment = [ Environment = "DB_PATH=/var/lib/does-it-build/db.sqlite";
"DB_PATH=/var/lib/does-it-build/db.sqlite"
"GITHUB_SEND_PINGS=1"
"GITHUB_OWNER=Noratrieb"
"GITHUB_REPO=does-it-build-notifications"
"GITHUB_APP_ID=2263995" # https://github.com/settings/apps/does-it-build
];
# GITHUB_APP_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----...
EnvironmentFile = [ config.age.secrets.does_it_build_private_key.path ];
ProtectHome = true;
StateDirectory = "does-it-build";
ProtectSystem = "strict";
PrivateTmp = true;
RemoveIPC = true;
NoNewPrivileges = true;
PrivateDevices = true;
ProtectClock = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
ProtectKernelModules = true;
PrivateMounts = true;
RestrictNamespaces = "";
RestrictSUIDSGID = true;
ProtectHostname = true;
}; };
}; };

View file

@ -9,7 +9,6 @@ let
url = url =
"https://github.com/C0RR1T/HugoChat/releases/download/2024-08-05/hugo-client.tar.xz"; "https://github.com/C0RR1T/HugoChat/releases/download/2024-08-05/hugo-client.tar.xz";
sha256 = "sha256:121ai8q6bm7gp0pl1ajfk0k2nrfg05zid61i20z0j5gpb2qyhsib"; sha256 = "sha256:121ai8q6bm7gp0pl1ajfk0k2nrfg05zid61i20z0j5gpb2qyhsib";
stripRoot = false;
}; };
in in
{ {
@ -62,27 +61,35 @@ in
"api.hugo-chat.noratrieb.dev" = "api.hugo-chat.noratrieb.dev" =
let let
cors = pkgs.writeText "cors" '' cors = pkgs.writeText "cors" ''
@cors_preflight { # https://gist.github.com/ryanburnette/d13575c9ced201e73f8169d3a793c1a3
method OPTIONS @cors_preflight{args[0]} method OPTIONS
header Origin * @cors{args[0]} header Origin {args[0]}
}
handle @cors_preflight { handle @cors_preflight{args[0]} {
header { header {
Access-Control-Allow-Origin "*" Access-Control-Allow-Origin "{args[0]}"
Access-Control-Allow-Methods "*" Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS"
Access-Control-Allow-Headers "content-type" Access-Control-Allow-Credentials "false"
Access-Control-Allow-Headers "$${args[1]}"
Access-Control-Max-Age "86400"
defer
} }
respond 204 respond "" 204
} }
handle @cors{args[0]} {
header {
Access-Control-Allow-Origin "{args[0]}"
Access-Control-Expose-Headers *
defer
}
}
''; '';
in in
{ {
logFormat = ""; logFormat = "";
extraConfig = '' extraConfig = ''
import ${cors} import ${cors} https://hugo-chat.noratrieb.dev "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type"
encode zstd gzip encode zstd gzip
reverse_proxy * localhost:5001 reverse_proxy * localhost:5001
''; '';

View file

@ -1,36 +0,0 @@
{ pkgs, ... }: {
services.matrix-continuwuity = {
enable = true;
settings = {
global = {
server_name = "noratrieb.dev";
allow_registration = false;
allow_encryption = true;
allow_federation = true;
trusted_servers = [ "matrix.org" ];
well_known = {
server = "matrix.noratrieb.dev:443";
client = "https://matrix.noratrieb.dev";
support_page = "https://noratrieb.dev";
};
};
};
};
environment.systemPackages = [ pkgs.matrix-continuwuity ];
services.caddy.virtualHosts."matrix.noratrieb.dev" = {
extraConfig = ''
encode zstd gzip
reverse_proxy * http://localhost:6167
'';
};
services.caddy.virtualHosts."matrix.noratrieb.dev:8448" = {
extraConfig = ''
encode zstd gzip
reverse_proxy * http://localhost:6167
'';
};
networking.firewall.allowedTCPPorts = [ 8448 ];
networking.firewall.interfaces.wg0.allowedTCPPorts = [ 6167 ];
}

View file

@ -1,39 +1,25 @@
{ ... }: { { pkgs, lib, my-projects-versions, ... }:
services.caddy.globalConfig = '' let
filesystem garage s3 { website = import (pkgs.fetchFromGitHub my-projects-versions.website.fetchFromGitHub);
bucket noratrieb.dev blog = pkgs.fetchFromGitHub my-projects-versions.blog.fetchFromGitHub;
region garage slides = pkgs.fetchFromGitHub my-projects-versions.slides.fetchFromGitHub;
endpoint http://localhost:3900 website-build = website { inherit pkgs slides blog; };
use_path_style in
} {
'';
services.caddy.virtualHosts = { services.caddy.virtualHosts = {
"noratrieb.dev" = { "noratrieb.dev" = {
logFormat = ""; logFormat = "";
extraConfig = '' extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy /.well-known/matrix/* https://matrix.noratrieb.dev {
header_up Host matrix.noratrieb.dev
}
header -Last-Modified header -Last-Modified
root * ${import ../../packages/caddy-static-prepare {
header /blog/css/* Cache-Control "max-age=31540000, immutable" name = "website";
header /blog/fonts/* Cache-Control "max-age=31540000, immutable" src = website-build;
inherit pkgs lib;
@txt { }}
path /
not header Accept *text/html*
}
rewrite @txt /index.txt
file_server { file_server {
fs garage etag_file_extensions .sha256
# TODO: run precompress script precompressed zstd gzip br
# etag_file_extensions .sha256
# precompressed zstd gzip br
} }
''; '';
}; };
@ -44,12 +30,5 @@
reverse_proxy * localhost:3902 reverse_proxy * localhost:3902
''; '';
}; };
"womangling.noratrieb.dev" = {
logFormat = "";
extraConfig = ''
encode zstd gzip
reverse_proxy * localhost:3902
'';
};
}; };
} }

View file

@ -4,11 +4,10 @@ let
src = pkgs.fetchFromGitHub my-projects-versions.widetom.fetchFromGitHub; src = pkgs.fetchFromGitHub my-projects-versions.widetom.fetchFromGitHub;
pname = "widetom"; pname = "widetom";
version = "0.1.0"; version = "0.1.0";
cargoHash = "sha256-riQA+GviHMqiSvoRKcJhM3MGVEIv6urgYyvBZZd4fCc="; cargoHash = "sha256-AWbdPcDc+QOW7U/FYbqlIsg+3MwfggKCTCw1z/ZbSEE=";
meta = { meta = {
mainProgram = "widertom"; mainProgram = "widertom";
}; };
RUSTFLAGS = "-Cforce-frame-pointers=true";
}; };
in in
{ {
@ -32,21 +31,6 @@ in
serviceConfig = { serviceConfig = {
DynamicUser = true; DynamicUser = true;
ExecStart = lib.getExe widetom; ExecStart = lib.getExe widetom;
PrivateDevices = true;
ProtectHome = true;
ProtectClock = true;
ProtectKernelLogs = true;
ProtectHostname = true;
ProtectKernelTunables = true;
CapabilityBoundingSet = "";
ProtectProc = "noaccess";
RestrictNamespaces = true;
MemoryDenyWriteExecute = true;
ProtectControlGroups = true;
ProtectKernelModules = true;
SystemCallArchitectures = "";
SystemCallFilter = "@system-service";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
}; };
}; };

View file

@ -23,9 +23,10 @@ check_dig_answer A "nilstrieb.dev" "161.97.165.1"
check_dig_answer NS noratrieb.dev "noratrieb.dev..*3600.*IN.*NS.*ns1.noratrieb.dev." check_dig_answer NS noratrieb.dev "noratrieb.dev..*3600.*IN.*NS.*ns1.noratrieb.dev."
# Mail stuff # Mail stuff
check_dig_answer MX noratrieb.dev "mail.tutanota.de." check_dig_answer MX noratrieb.dev "mail.protonmail.ch."
check_dig_answer TXT noratrieb.dev "t-verify=dae826f2ae9f73a71cc247183616b6c9" check_dig_answer MX noratrieb.dev "mailsec.protonmail.ch."
check_dig_answer TXT noratrieb.dev "v=spf1 include:spf.tutanota.de -all" check_dig_answer TXT noratrieb.dev "protonmail-verification=09106d260e40df267109be219d9c7b2759e808b5"
check_dig_answer TXT noratrieb.dev "v=spf1 include:_spf.protonmail.ch ~all"
# Check HTTP responses # Check HTTP responses
http_hosts=( http_hosts=(

View file

@ -2,7 +2,7 @@
meta = meta =
let let
nixpkgs-version = builtins.fromJSON (builtins.readFile ./nixpkgs.json); nixpkgs-version = builtins.fromJSON (builtins.readFile ./nixpkgs.json);
nixpkgs-path = (fetchTarball "https://github.com/NixOS/nixpkgs/archive/${nixpkgs-version."nixos-25.11".commit}.tar.gz"); nixpkgs-path = (fetchTarball "https://github.com/NixOS/nixpkgs/archive/${nixpkgs-version.commit}.tar.gz");
in in
{ {
# Override to pin the Nixpkgs version (recommended). This option # Override to pin the Nixpkgs version (recommended). This option
@ -66,7 +66,7 @@
wg = { wg = {
privateIP = "10.0.0.3"; privateIP = "10.0.0.3";
publicKey = "pdUxG1vhmYraKzIIEFxTRAMhGwGztBL/Ly5icJUV3g0="; publicKey = "pdUxG1vhmYraKzIIEFxTRAMhGwGztBL/Ly5icJUV3g0=";
peers = [ "vps1" "vps2" "vps4" "vps5" "dns1" "dns2" "minipc" ]; peers = [ "vps1" "vps2" "vps4" "vps5" "dns1" "dns2" ];
}; };
tags = [ "apps" ]; tags = [ "apps" ];
}; };
@ -92,17 +92,6 @@
}; };
tags = [ "apps" ]; tags = [ "apps" ];
}; };
minipc = {
publicIPv4 = null;
publicIPv6 = null;
wg = {
privateIP = "10.0.2.1";
publicKey = "ecYfTot7RrJyNebSZTQ1wciOhvrpNSSbkR15twpSSl4=";
peers = [ "vps3" ];
noEndpoint = true;
};
tags = [ "home" ];
};
}; };
}; };
@ -190,7 +179,6 @@
./modules/registry ./modules/registry
./modules/backup ./modules/backup
./modules/restic ./modules/restic
./modules/snowflake-proxy
# apps # apps
./apps/website ./apps/website
@ -213,10 +201,6 @@
./modules/wg-mesh ./modules/wg-mesh
./modules/caddy ./modules/caddy
./modules/garage ./modules/garage
./modules/snowflake-proxy
# apps
./apps/matrix
]; ];
system.stateVersion = "23.11"; system.stateVersion = "23.11";
@ -230,7 +214,6 @@
./modules/caddy ./modules/caddy
./modules/garage ./modules/garage
./modules/prometheus ./modules/prometheus
./modules/snowflake-proxy
./apps/website ./apps/website
]; ];
@ -246,7 +229,6 @@
./modules/garage ./modules/garage
./modules/backup ./modules/backup
./modules/restic ./modules/restic
./modules/snowflake-proxy
# apps # apps
./apps/website ./apps/website
@ -302,7 +284,6 @@
./modules/caddy ./modules/caddy
./modules/wg-mesh ./modules/wg-mesh
./modules/garage ./modules/garage
./modules/snowflake-proxy
./apps/fakessh ./apps/fakessh
]; ];
@ -311,18 +292,4 @@
system.stateVersion = "23.11"; system.stateVersion = "23.11";
}; };
minipc = { name, nodes, modulesPath, config, pkgs, lib, ... }: {
imports = [
./modules/minipc
./modules/wg-mesh
./modules/nas-mount
./modules/postgres
./modules/immich
./modules/tailscale
./modules/paperless
./modules/caddy-base
];
system.stateVersion = "25.05";
};
} }

View file

@ -1,50 +0,0 @@
{ pkgs, ... }:
let
caddy = pkgs.caddy.withPlugins {
plugins = [
"github.com/noratrieb-mirrors/certmagic-s3@v1.1.3"
"github.com/sagikazarmark/caddy-fs-s3@v0.10.0"
"github.com/caddy-dns/rfc2136@v1.0.0"
];
hash = "sha256-m5RHlrheqzoGqKQxixq+xTd2hlnCTets9zCT7aFka8g=";
};
in
{
environment.systemPackages = [ pkgs.caddy ];
networking.firewall.interfaces.wg0.allowedTCPPorts = [ 9010 ]; # metrics
networking.firewall = {
allowedTCPPorts = [
80 # HTTP
443 # HTTPS
];
allowedUDPPorts = [
443 # HTTP/3 via QUIC
];
};
services.caddy = {
enable = true;
package = caddy;
logFormat = ''
output stdout
format json
'';
globalConfig = ''
auto_https disable_redirects
servers {
metrics
}
'';
virtualHosts = {
":9010" = {
logFormat = "output discard";
extraConfig = ''
metrics /metrics
'';
};
};
};
}

View file

@ -1,11 +1,40 @@
{ pkgs, config, lib, name, ... }: { { pkgs, config, lib, name, ... }:
imports = [ ../caddy-base ];
let
caddy = pkgs.caddy.withPlugins {
plugins = [
"github.com/noratrieb-mirrors/certmagic-s3@v1.1.3"
"github.com/caddy-dns/rfc2136@v1.0.0"
];
hash = "sha256-HdCXbqrrGPZSdHv7bZvGz9T6loVbrfKydTbjTyt5Wt0=";
};
in
{
environment.systemPackages = [ caddy ];
networking.firewall.interfaces.wg0.allowedTCPPorts = [ 9010 ]; # metrics
networking.firewall = {
allowedTCPPorts = [
80 # HTTP
443 # HTTPS
];
allowedUDPPorts = [
443 # HTTP/3 via QUIC
];
};
age.secrets.caddy_s3_key_secret.file = ../../secrets/caddy_s3_key_secret.age; age.secrets.caddy_s3_key_secret.file = ../../secrets/caddy_s3_key_secret.age;
systemd.services.caddy.serviceConfig.EnvironmentFile = [ config.age.secrets.caddy_s3_key_secret.path ]; systemd.services.caddy.serviceConfig.EnvironmentFile = config.age.secrets.caddy_s3_key_secret.path;
systemd.services.caddy.after = [ "garage.service" ]; # the cert store depends on garage systemd.services.caddy.after = [ "garage.service" ]; # the cert store depends on garage
services.caddy = { services.caddy = {
enable = true;
package = caddy;
logFormat = ''
output stdout
format json
'';
globalConfig = '' globalConfig = ''
email tls@noratrieb.dev email tls@noratrieb.dev
auto_https disable_redirects auto_https disable_redirects
@ -41,6 +70,12 @@
respond "This is an HTTPS-only server, silly you. Go to https:// instead." 418 respond "This is an HTTPS-only server, silly you. Go to https:// instead." 418
''; '';
}; };
":9010" = {
logFormat = "output discard";
extraConfig = ''
metrics /metrics
'';
};
"${name}.infra.noratrieb.dev" = { "${name}.infra.noratrieb.dev" = {
logFormat = ""; logFormat = "";
extraConfig = '' extraConfig = ''

View file

@ -2,12 +2,9 @@
let let
pretense = import (pkgs.fetchFromGitHub my-projects-versions.pretense.fetchFromGitHub); pretense = import (pkgs.fetchFromGitHub my-projects-versions.pretense.fetchFromGitHub);
quotdd = import (pkgs.fetchFromGitHub my-projects-versions.quotdd.fetchFromGitHub); quotdd = import (pkgs.fetchFromGitHub my-projects-versions.quotdd.fetchFromGitHub);
networkConfig = networkingConfig."${name}";
in in
{ {
deployment.targetHost = deployment.targetHost = "${name}.infra.noratrieb.dev";
if networkConfig.publicIPv4 == null
then name else "${name}.infra.noratrieb.dev";
# TODO: ensure that the rust programs have frame pointers # TODO: ensure that the rust programs have frame pointers
@ -23,8 +20,6 @@ in
nixPath = [ "nixpkgs=${nixpkgs-path}" ]; nixPath = [ "nixpkgs=${nixpkgs-path}" ];
}; };
nixpkgs.config.allowUnfree = true;
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
vim vim
wget wget
@ -32,14 +27,10 @@ in
traceroute traceroute
dnsutils dnsutils
nftables nftables
htop
]; ];
networking.hostName = name; networking.hostName = name;
# Swiss german console tty keyboard layout
console.keyMap = "sg";
time.timeZone = "Europe/Zurich"; time.timeZone = "Europe/Zurich";
users.users.root.openssh.authorizedKeys.keys = [ ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG0n1ikUG9rYqobh7WpAyXrqZqxQoQ2zNJrFPj12gTpP nilsh@PC-Nils'' ]; users.users.root.openssh.authorizedKeys.keys = [ ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG0n1ikUG9rYqobh7WpAyXrqZqxQoQ2zNJrFPj12gTpP nilsh@PC-Nils'' ];
@ -69,7 +60,6 @@ in
settings = { settings = {
PasswordAuthentication = false; PasswordAuthentication = false;
AllowUsers = [ "root" ];
}; };
}; };
services.fail2ban = { services.fail2ban = {
@ -89,22 +79,6 @@ in
"PRETENSE_PORTS=23,3306,5432,1521" # telnet,mysql,postgres,oracle "PRETENSE_PORTS=23,3306,5432,1521" # telnet,mysql,postgres,oracle
"PRETENSE_METRICS_PORT=9150" "PRETENSE_METRICS_PORT=9150"
]; ];
PrivateDevices = true;
ProtectHome = true;
ProtectClock = true;
ProtectKernelLogs = true;
ProtectHostname = true;
ProtectKernelTunables = true;
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
ProtectProc = "ptraceable";
RestrictNamespaces = true;
MemoryDenyWriteExecute = true;
ProtectControlGroups = true;
ProtectKernelModules = true;
SystemCallArchitectures = "";
SystemCallFilter = "@system-service";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
ProtectSystem = "strict";
}; };
}; };
systemd.services.quotdd = { systemd.services.quotdd = {
@ -116,23 +90,6 @@ in
ExecStart = "${lib.getExe (quotdd {inherit pkgs;})}"; ExecStart = "${lib.getExe (quotdd {inherit pkgs;})}";
AmbientCapabilities = "CAP_NET_BIND_SERVICE"; AmbientCapabilities = "CAP_NET_BIND_SERVICE";
Environment = [ ]; Environment = [ ];
PrivateDevices = true;
ProtectHome = true;
ProtectClock = true;
ProtectKernelLogs = true;
ProtectHostname = true;
ProtectKernelTunables = true;
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
ProtectProc = "ptraceable";
RestrictNamespaces = true;
MemoryDenyWriteExecute = true;
ProtectControlGroups = true;
ProtectKernelModules = true;
SystemCallArchitectures = "";
SystemCallFilter = "@system-service";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
ProtectSystem = "strict";
}; };
}; };
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [
@ -231,22 +188,6 @@ in
}; };
systemd.services.alloy.serviceConfig = { systemd.services.alloy.serviceConfig = {
DynamicUser = lib.mkForce false; DynamicUser = lib.mkForce false;
PrivateDevices = true;
ProtectClock = true;
ProtectKernelLogs = true;
PrivateMounts = true;
ProtectControlGroups = true;
ProtectHostname = true;
LockPersonality = true;
ProtectKernelTunables = true;
ProtectSystem = true;
ProtectHome = true;
PrivateTmp = true;
NoNewPrivileges = true;
RestrictNamespaces = "";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
# TODO: find what's required for /proc/kallsyms (it should be CAP_SYSLOG!)
# CapabilityBoundingSet = "CAP_SYS_PTRACE CAP_BPF CAP_SYSLOG";
}; };
environment.etc."alloy/config.alloy".text = '' environment.etc."alloy/config.alloy".text = ''
discovery.process "all" { discovery.process "all" {

View file

@ -18,7 +18,7 @@ let
vps1 // { vps1 // {
TTL = hour1; TTL = hour1;
SOA = { SOA = {
nameServer = "ns.nilstrieb.dev."; nameServer = "ns1.nilstrieb.dev.";
adminEmail = "void@nilstrieb.dev"; adminEmail = "void@nilstrieb.dev";
serial = 2024072601; serial = 2024072601;
}; };
@ -34,7 +34,6 @@ let
]; ];
subdomains = { subdomains = {
ns = dns1;
ns1 = dns1; ns1 = dns1;
ns2 = dns2; ns2 = dns2;

View file

@ -14,10 +14,6 @@ let
A = lib.lists.flatten (map (host: if builtins.hasAttr "A" host then host.A else [ ]) hosts); A = lib.lists.flatten (map (host: if builtins.hasAttr "A" host then host.A else [ ]) hosts);
AAAA = lib.lists.flatten (map (host: if builtins.hasAttr "AAAA" host then host.AAAA else [ ]) hosts); AAAA = lib.lists.flatten (map (host: if builtins.hasAttr "AAAA" host then host.AAAA else [ ]) hosts);
}; };
minipc = {
A = [ (a "100.100.2.1") ]; # tailscale IP
};
in in
with hostsToDns; with hostsToDns;
# vps{1,3,4} contains root noratrieb.dev # vps{1,3,4} contains root noratrieb.dev
@ -41,12 +37,13 @@ let
TXT = [ TXT = [
"protonmail-verification=09106d260e40df267109be219d9c7b2759e808b5" "protonmail-verification=09106d260e40df267109be219d9c7b2759e808b5"
"t-verify=dae826f2ae9f73a71cc247183616b6c9" # tuta verification "v=spf1 include:_spf.protonmail.ch ~all"
"v=spf1 include:spf.tutanota.de -all"
]; ];
MX = [ MX = [
(ttl 60 (mx.mx 10 "mail.tutanota.de.")) (mx.mx 10 "mail.protonmail.ch.")
(mx.mx 20 "mailsec.protonmail.ch.")
]; ];
subdomains = { subdomains = {
@ -66,12 +63,6 @@ let
}; };
}; };
womangling = combine [ vps1 vps3 vps4 ];
garage = combine [ vps1 vps2 vps3 vps4 ];
matrix = vps2;
# --- apps # --- apps
docker = vps1; docker = vps1;
hugo-chat = vps1 // { hugo-chat = vps1 // {
@ -96,26 +87,18 @@ let
grafana = vps3; grafana = vps3;
infra.subdomains = hostsToDns; infra.subdomains = hostsToDns;
# --- internal stuff
internal.subdomains = {
immich = minipc;
paperless = minipc;
};
# --- other verification # --- other verification
_discord.TXT = [ "dh=e0f7e99c70c4ce17f7afcce3be8bfda9cd363843" ]; _discord.TXT = [ "dh=e0f7e99c70c4ce17f7afcce3be8bfda9cd363843" ];
_atproto.TXT = [ "did=did:plc:pqyzoyxk7gfcbxk65mjyncyl" ]; _atproto.TXT = [ "did=did:plc:pqyzoyxk7gfcbxk65mjyncyl" ];
# --- email # --- email
_mta-sts.CNAME = [ (cname "mta-sts.tutanota.de.") ];
mta-sts.CNAME = [ (cname "mta-sts.tutanota.de.") ];
_domainkey.subdomains = { _domainkey.subdomains = {
s1.CNAME = [ (cname "s1.domainkey.tutanota.de.") ]; protonmail.CNAME = [ (cname "protonmail.domainkey.deenxxi4ieo32na6brazky2h7bt5ezko6vexdbvbzzbtj6oj43kca.domains.proton.ch.") ];
s2.CNAME = [ (cname "s2.domainkey.tutanota.de.") ]; protonmail2.CNAME = [ (cname "protonmail2.domainkey.deenxxi4ieo32na6brazky2h7bt5ezko6vexdbvbzzbtj6oj43kca.domains.proton.ch.") ];
protonmail3.CNAME = [ (cname "protonmail3.domainkey.deenxxi4ieo32na6brazky2h7bt5ezko6vexdbvbzzbtj6oj43kca.domains.proton.ch.") ];
}; };
_dmarc.TXT = [ _dmarc.TXT = [
"v=DMARC1; p=quarantine; adkim=s" "v=DMARC1; p=quarantine"
]; ];
# retired # retired

View file

@ -20,7 +20,7 @@ in
}; };
services.garage = { services.garage = {
enable = true; enable = true;
package = pkgs.garage_2; package = pkgs.garage_2_0_0;
settings = { settings = {
metadata_dir = "/var/lib/garage/meta"; metadata_dir = "/var/lib/garage/meta";
data_dir = "/var/lib/garage/data"; data_dir = "/var/lib/garage/data";
@ -53,12 +53,5 @@ in
}; };
environmentFile = config.age.secrets.garage_secrets.path; environmentFile = config.age.secrets.garage_secrets.path;
}; };
services.caddy.virtualHosts."garage.noratrieb.dev" = {
logFormat = "";
extraConfig = ''
encode zstd gzip
reverse_proxy * localhost:3900
'';
};
} }

View file

@ -1,34 +0,0 @@
{ config, pkgs, ... }: {
age.secrets.immich_secrets.file = ../../secrets/immich_secrets.age;
services.immich = {
enable = true;
mediaLocation = "/mnt/nas/HEY/_Nora/immich";
secretsFile = config.age.secrets.immich_secrets.path;
host = "0.0.0.0";
database = {
enableVectors = false;
enableVectorChord = true;
};
environment = {
IMMICH_TELEMETRY_INCLUDE = "all";
};
openFirewall = true;
};
services.postgresql = {
ensureDatabases = [ "immich" ];
ensureUsers = [
{
name = "immich";
ensureDBOwnership = true;
}
];
authentication = pkgs.lib.mkForce ''
#type database DBuser auth-method
local all all peer
'';
};
networking.firewall.interfaces.wg0.allowedTCPPorts = [ 8081 8082 ];
}

View file

@ -1,8 +0,0 @@
{ ... }: {
imports = [ ./hardware-configuration.nix ];
networking.networkmanager.enable = true;
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
}

View file

@ -1,42 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{
device = "/dev/disk/by-uuid/9327fdbf-f6d2-41ae-b69f-6dbb97ab388a";
fsType = "ext4";
};
fileSystems."/boot" =
{
device = "/dev/disk/by-uuid/2A59-D3C9";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices =
[{ device = "/dev/disk/by-uuid/db30dd66-fa2a-46a4-b81a-b0fc935db5ac"; }];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp2s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,6 +0,0 @@
{ ... }: {
fileSystems."/mnt/nas" = {
device = "nas:/volume1/homes";
fsType = "nfs";
};
}

View file

@ -1,24 +0,0 @@
{ config, ... }:
let nasDir = "/mnt/nas/HEY/_Nora/paperless"; in {
age.secrets.paperless_env.file = ../../secrets/paperless_env.age;
services.paperless = {
enable = true;
consumptionDir = "${nasDir}/consume";
address = "0.0.0.0";
port = 8010;
environmentFile = config.age.secrets.paperless_env.path;
settings = {
PAPERLESS_TIME_ZONE = "Europe/Zurich";
PAPERLESS_ADMIN_USER = "nora";
PAPERLESS_OCR_LANGUAGE = "deu+eng";
};
exporter = {
enable = true;
directory = "${nasDir}/export_minipc";
onCalendar = "02:25:00";
};
};
networking.firewall.allowedTCPPorts = [ 8010 ];
}

View file

@ -1,6 +0,0 @@
{ pkgs, ... }: {
config.services.postgresql = {
enable = true;
package = pkgs.postgresql_18;
};
}

View file

@ -85,13 +85,6 @@
scrape_interval = "1h"; scrape_interval = "1h";
static_configs = [{ targets = [ "localhost:7846" ]; }]; static_configs = [{ targets = [ "localhost:7846" ]; }];
} }
{
job_name = "immich";
static_configs = [
{ targets = [ "minipc.local:8081" ]; labels = { server = "minipc"; }; }
{ targets = [ "minipc.local:8082" ]; labels = { server = "minipc"; }; }
];
}
]; ];
}; };
@ -226,7 +219,6 @@
pyroscope = pkgs.fetchzip { pyroscope = pkgs.fetchzip {
url = "https://github.com/grafana/pyroscope/releases/download/v1.14.0/pyroscope_1.14.0_linux_amd64.tar.gz"; url = "https://github.com/grafana/pyroscope/releases/download/v1.14.0/pyroscope_1.14.0_linux_amd64.tar.gz";
sha256 = "sha256:005539bp2a2kac8ff6vz77g0niav81rggha1bsfx454fw4dyli4y"; sha256 = "sha256:005539bp2a2kac8ff6vz77g0niav81rggha1bsfx454fw4dyli4y";
stripRoot = false;
}; };
pyroscopeConfig = { pyroscopeConfig = {
analytics.reporting_enabled = false; analytics.reporting_enabled = false;

View file

@ -1,3 +0,0 @@
{ ... }: {
services.snowflake-proxy.enable = true;
}

View file

@ -1,13 +0,0 @@
{ ... }: {
networking.nftables.enable = true;
services.tailscale = {
enable = true;
extraUpFlags = [ "--advertise-exit-node" ];
useRoutingFeatures = "server";
};
systemd.services.tailscaled.serviceConfig.Environment = [
"TS_DEBUG_FIREWALL_MODE=nftables"
];
}

View file

@ -35,9 +35,7 @@ in
let peerConfig = (builtins.getAttr peer networkingConfig).wg; let peerConfig = (builtins.getAttr peer networkingConfig).wg;
in { in {
inherit (peerConfig) publicKey; inherit (peerConfig) publicKey;
endpoint = endpoint = "${peer}.infra.noratrieb.dev:${toString listenPort}";
if !(builtins.hasAttr "noEndpoint" peerConfig) || !peerConfig.noEndpoint
then "${peer}.infra.noratrieb.dev:${toString listenPort}" else null;
allowedIPs = [ "${peerConfig.privateIP}/32" ]; allowedIPs = [ "${peerConfig.privateIP}/32" ];
# sometimes there's some weirdness....?? # sometimes there's some weirdness....??
persistentKeepalive = 25; persistentKeepalive = 25;

View file

@ -1,4 +1,31 @@
{ {
"website": {
"commit": "57c4a239da5d17eafde4ade165f3c6706639a9b4",
"fetchFromGitHub": {
"owner": "Noratrieb",
"repo": "website",
"rev": "57c4a239da5d17eafde4ade165f3c6706639a9b4",
"hash": "sha256-or6mCQjbc7tWAzzAKQpznZv+2vWJMhyzqxBPwRE2HKw="
}
},
"blog": {
"commit": "ea2758dd10f29e8d66ca3f54d7303f2ac20005d2",
"fetchFromGitHub": {
"owner": "Noratrieb",
"repo": "blog",
"rev": "ea2758dd10f29e8d66ca3f54d7303f2ac20005d2",
"hash": "sha256-LvQ41eJzOvI7mLYDTvlFwGZ2TKrZO26rasydqnEZ/t4="
}
},
"slides": {
"commit": "0401f35c22b124b69447655f0c537badae9e223c",
"fetchFromGitHub": {
"owner": "Noratrieb",
"repo": "slides",
"rev": "0401f35c22b124b69447655f0c537badae9e223c",
"hash": "sha256-K1Me4wf/GSfoc1PGWVJygPyTVV8SXienxUrzXkdCrjQ="
}
},
"pretense": { "pretense": {
"commit": "270b01fc1118dfd713c1c41530d1a7d98f04527d", "commit": "270b01fc1118dfd713c1c41530d1a7d98f04527d",
"fetchFromGitHub": { "fetchFromGitHub": {
@ -18,12 +45,12 @@
} }
}, },
"does-it-build": { "does-it-build": {
"commit": "5518c49d7c6348ba01f286ce031f5322bbd9f786", "commit": "81790825173d87f89656f66f12a123bc99e2f6f1",
"fetchFromGitHub": { "fetchFromGitHub": {
"owner": "Noratrieb", "owner": "Noratrieb",
"repo": "does-it-build", "repo": "does-it-build",
"rev": "5518c49d7c6348ba01f286ce031f5322bbd9f786", "rev": "81790825173d87f89656f66f12a123bc99e2f6f1",
"hash": "sha256-nOV0n2THZXG/fC3lgPW2gDeWn7bYIZydCTIkKJ+U898=" "hash": "sha256-MCgGDd7Sg+BiG8L20Bbz8bHMB/Xuc1ztOVwv/b37BnQ="
} }
}, },
"upload.files.noratrieb.dev": { "upload.files.noratrieb.dev": {
@ -45,12 +72,12 @@
} }
}, },
"widetom": { "widetom": {
"commit": "387f6ff587b66186332cf5cfba90c966bba0695c", "commit": "33d1738799618d72fe2b86896f766cbfea58dc76",
"fetchFromGitHub": { "fetchFromGitHub": {
"owner": "Noratrieb", "owner": "Noratrieb",
"repo": "widetom", "repo": "widetom",
"rev": "387f6ff587b66186332cf5cfba90c966bba0695c", "rev": "33d1738799618d72fe2b86896f766cbfea58dc76",
"hash": "sha256-0PCal2czxBlgDh59TM7o94C9PG3a98YYUJ887/BYeEA=" "hash": "sha256-lSjlDozwKRLF62jsDaWo+8+rcQdeEgurEnuw00hk3o8="
} }
} }
} }

View file

@ -1,6 +1,5 @@
{ {
"nixos-25.11": { "channel": "nixos-25.05",
"lastUpdated": "2026-05-28T12:57:27.843Z", "lastUpdated": "2025-08-03T11:42:11.747Z",
"commit": "b77b3de8775677f84492abe84635f87b0e153f0f" "commit": "59e69648d345d6e8fef86158c555730fa12af9de"
}
} }

Binary file not shown.

Binary file not shown.

View file

@ -1,5 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg N7lS400e/5mSV3BlhnzThydz/c3DIIOHLNQodTErR08 -> ssh-ed25519 qM6TYg py66rUtQIWm6K163vaJaoAseekNA70yQKMDH1FkWYVc
vMqHXmSloSrWCxeD4QCH30GSqg1AI+6Dy16atFLNxjs rP7T1akj7LmzIcJeoK+mq+GfOjWpnWFnSpUhIA9Vihc
--- aJ6lQv9jnJHyocy+Kz4jPCtpiIewxoooR0Zsm7CS/pY --- UjRtQl6/Gz3QPiLhSyksrsRvFoCjiCKi4D0HdBb1dJY
éj9ò†ÇKy€È°0*ÜbÉÉ¿Y£0ûÅÅþ<C385>I3v +¶D"*/go™#Š³âØµñ ¦àq™ƒ(¯mÑzÁºÚhžØÒàk½šÔHÚ9:¾ãM>c=”ά֦äÀMŠ” â³L1

View file

@ -1,5 +1,6 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg Ln9ZxoEmhHUMbU4PufH8OYVzEnvFEm+b/SlBfitqEhw -> ssh-ed25519 qM6TYg DlJpvGP2I1iGodnEufzr0qCAmmU6XiKbnNCRJmjPsHs
M0n0qe7L9peTLylt0uoTR4gQBcCxfSIm7FAR0mPeG5E upNAkX1DPfs7AJi+/hUKKcehn7tTcR0knW8W+kP1u/k
--- BzrHhLTDQ49g2GTkJdmLpdhRBp1rfdekcW+A26jzKys --- ZEI6vM0+n33fVLPssJyEWYW/xNgoa0/2BIZeG3NzBrk
G6à?ÑU'réy¸†ÃÉ@b <0B>$ÏMçZŸ`ñ÷@äÂëkv£]Ÿ6Þ_°ÛŸNÜæÙø $ò!ám“ìVk€<6B>gA‰]ÿyW°,¾ë´ød'ª ;Ȧ핒 ÅÜŽˆ ¯¾-r `
ÈgR/n´|òS“\h}•LR£áèE‡Ú@ø„¦ðš‡˜OüåjF"Vж¨ëív-ƒqË“<C38B>ðxjf´Ì ŒÂ­f=×ÁaI¤8òÖѦãlÃàž C

Binary file not shown.

View file

@ -1,13 +1,13 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg Kmd5m9hb9QXzbbrLWC3SLcUfy/B8bEWdJMQ1iMe5MQ8 -> ssh-ed25519 qM6TYg SrZQBYLsUcrDu6ds1fJAyjM+mHPpAW04U6yRqA/TjH8
A4ZoS84dtX+DMOzPXOMBb402q3o6LBExOda+Rm4hbO0 LZUTPquz+YNmlRWrXwY2fvXsVwOEM/uhzWcaf7WsY5o
-> ssh-ed25519 91VHug rXXXRgZI91mIlLAclodKDk3V14pDyRCv5kg1RCB7AH8 -> ssh-ed25519 91VHug sVXnaD5sruvFKnPwldWzlH8KUIeZ/toWqYe/F2tfBX0
CzC46ry6tCYkDX4jTW08j7Itqjb0raz2nlmU5/7zLCc CapfF55c1MvBDcDywNpnS4blYwD0HrPyrcncMRbl5lo
-> ssh-ed25519 XzACZQ KbzLsMTNqcjJ2I+Bx5moRC74Z/QKHrbFVovC5hhm8DY -> ssh-ed25519 XzACZQ WqU7ebK4SnCyxP4zxIdmMDAaH7mk2HpgvUwbFWhoNWs
aAGFH0KBdM+nm4HyZ0X7MPc3+fBbcQrQAcvrK0F7LNM wm0ZtnIQCKZW+WJIDtAIdOQkvp5LLyvTQ2vNFC7C26U
-> ssh-ed25519 51bcvA qv9cje7I7Sxje9xV0DghaxSxyovB37O3B1Bt6sHp/Bk -> ssh-ed25519 51bcvA xtMa2mIZ7GHOFJEcpZjr13vOovJsyo9fMWAnm66pxEg
2zEnhhy6dIOWMdbQE54xtQKfZjR2vTH+Z4son1/gYr8 DqNSop7GSDMvsDzu9NK5ubf2xWMLX1fFLSiZUA42RUU
-> ssh-ed25519 vT7ExA voN3ZvXhhqv4V9FpVTd2ViydPgxvjpQpeUcH6jljen4 -> ssh-ed25519 vT7ExA 24tU87648MvZgbvt9PNWBUQsQBDyeBd2QV0jiKGMwWs
sLjK4aWqGSlxxeMKPrIZCjw4tsz95C1R498bFZgBMVk mSuA/G6ZjRYhG3TMGt8SQ8aqK8s9s81YBslBwQLr4Fg
--- Kfk+aieCFtZiKPE8toWEZwZw06sELpx1FiJCVDyLGcc --- sr5nQObjSdkQ+eILGm+p/nnD1XxrcCXwVY70INFlZMU
éÈuøÜMú?Cš¬†ìÒóô0Z©&Œß ‡ÊrSÓÖgµ™W«áp´8ã¦{*6§ÿÀy•¤§q“¯õð%‡øÎ ÚÊ›.ê)¶½uT}nw?”ñ‡]4^žjk„ž…*y"©#Oû÷N*6}ÿÏyIÙ<01>.7ÄT˜¥ïSéº- ©R©

Binary file not shown.

View file

@ -1,6 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 yMKb8Q lRux6HhczttLaNglBB4xdx7B4GUhs50ucnyYYYlNLzo
nxSaMiEcscZ62uEA3N4ssHN0Vc/fw0wRsGzUXHk5vyA
--- FpSXOah6uQRaHLOxdGNFF9Pud9NsjYDLhiXzqg5/Sao
ëóxÞ l×l w¦¹Ž\v¦S-Ñ!V”ý]å·õÛðõýé}gëÉ΃[>e®;¢n0n!‘œ;L
·+

View file

@ -1,5 +1,6 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg w8lK7Dhc3CzenrzJTI32uTNgXVyBUKJf7F1xGG6AV2Q -> ssh-ed25519 qM6TYg 5HRKvL31uap1+SLnv05qGlV2nAq8Oduk3GNPoQAUyWo
wBlK8pbH1M0NBeAFjwLyyuOKT2jk+o1BwjkQPNc9pvY RYng6wk2+XalYE/2N71L7dUpajuNycKs6naYSL9RZt0
--- 5hl/tchAPOurJ+fDLDB5/l/MuqrSTjV2Pnhc1Dy7Uhk --- 2SyDL6m1ZyW7Lam875/RBW3sWP17/8Ceop7cB4ewx/o
a.þAæ »òÈhUŠwq<77><.ädÖz<C396>œ¼XÁМ&;ⶸÇò9ÛÂۻͮc:zÃ<òòb>`¾ËÖùDøÖ ÕXìLøòʳöhý\Y ÃÁ•Ç<E280A2>•»'çø°ôU^ø—š+^¡ø3k5Õt4 %ÎăÓxŃDŔ·~†Ą
áě˙´ŤÜ% E˘ އą<4E>#7đ<37>×䌪E2ň@ÚŰ·"«ç[¸JšX*Ća0ýpöR(FC7OLđęڤϠ=ŻŘű{oŃ <>a÷[5<>C¨]Ž­¶Ëűđ:Z>´™r÷m

Binary file not shown.

View file

@ -1,8 +1,7 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg sx4kKW1m2RrcVkyxDMdDgh5jcwfrRDAFYa0EJBZKFnI -> ssh-ed25519 qM6TYg t4OIcjhlaEBxFFK/VibGcE0D5zb4LrMv0zS1vxMKxHA
WPbchNFC7tTqC4DrIw7hUZSNNxE64kkXZdXB6/VFhj4 /OIYeC0s9Jd5R6MaLQPHlgscrSkNwpdK1doADIZwmHE
-> ssh-ed25519 XzACZQ GXDgzIGU4X6/oOr5hcI7SoorcowGPJHx/0X2+gj+Sk0 -> ssh-ed25519 XzACZQ 7ieKRLiY3EzGlRcAzxnhzDQkUMmpNutUViBeMrSkWkM
NATuZ7IZ0QwM9/GtaYdLXjBs6X0enhpVgWvGVpyqOO0 qxeyBVm6aHDH7oQXDShuEqUGY9W8bp2vHfWvJEssfLg
--- xMESjwLO7fJhwd0HnYzypoh3s6YRx86vSdXovvSBoHg --- RuCRpuvvN5pIBe4zMaF0X0J5oW2z9ytkSfwKdkQlqo4
9Iü{¶Ö<C2B6>µÊ¼Ø<C2BC>Zòd©«„{æYr©X­öB= t9͆“¤ľ™żáî/ˇý‹”/d3Žĺů˝ÚńfůÁŁY.h Ýdg"°Á,<ÉZc„1ú“EŃĽ š•(ČÖ}ôĂâĎĄÄEÖ ®}tMŇü`H¸]w¸ŃWÁ?ú~(T]~'
ˆé]£ê ÓHÜ´ÕÍð¸`lâñRäΙRw8Q—íúi4ô*tê³#ÍÆšmÈŸ+6h¡S&æVŽá¼™';J™0]É ¿=¡

Binary file not shown.

View file

@ -1,5 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 yMKb8Q IornZ92EjvlpeFh0JuSElL/iH1pEblFxfXp9QrTuelA
Js60AJA93bYHGsTEX8S94B7h37kh7vkWktcvbNJlg5Q
--- OiyTon34BUPU3DCFrMdc9FdDeLB2AquG97fgMQpDbRk
A¼/nnÂ8)æ<>Ì0yì?êà ÐðC¾ DV5ôØ_C©‹øªŽ~Z˜Ëã¤&RmªùÏÍÉ8*à;*º~"[ÄZÜÙŒb2VI4JŒ!àÇðÑ,(ó§ÄZÛÝ^Wé%zV£ßÔ6î²-7¢Ž£ú6ÚAu£“<06>Á2M8S¸5ãL<C3A3>D[‰ß±¯µÖÿ&˜C"ZF[â¥

Binary file not shown.

Binary file not shown.

View file

@ -1,14 +1,15 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg rRl7WcBUycyZnCXeuPgeCPUBRjl5fXbvErOtESs9Pjo -> ssh-ed25519 qM6TYg HodUMahq+fafwLXzUaC/Y2E2btbeC32/CwBPL7y5hlg
ra1UlArViFAgu3ldeOQ/I6/rsaSr0yGSMjQSl2V3JSc 67R4TdZQNacpJLHCa+GdsycwWGekicCPhcOAQer7Uek
-> ssh-ed25519 91VHug Q8+LWlf3zKenc9Nw0SrC5IgHcUr9SkK3Se/exTlUs1g -> ssh-ed25519 91VHug ffJ4wwzD4G1wbS7XyQM4vQwjyv4llGHog9RxI5+JZXE
jf1PEQiL1p6zg/VEFriXef5Oj6tiUMgXd6fvrxRTfew ybHjj+2DqadF21NjHHqB64zu+fWscbNFe/5zvgDIFP8
-> ssh-ed25519 XzACZQ L4Xe5fEXnXVCgoUmTnOoT+8SNx4Tcxuak6sKQBMU/V8 -> ssh-ed25519 XzACZQ i7RCIUKgmO7BtDysfZ5wsBLbXwu2x0a2qOnmm9AdBHw
Jt/U6vVTY6dOa8p/CZAZ6mkSvYAvz4k61W2vMfQIWb4 +VRFX+3yf4WHMoagaQOEl3Z0W0VWN0v1PqUrunfQrZM
-> ssh-ed25519 51bcvA UWQ3aY+PLAPfYXaV6lcmVb22cuq8Tjjlr/YQv0LvXnE -> ssh-ed25519 51bcvA ywiVAHSTYuHmuM7f0lrRHDR89B30BPi/u0esMNloJQc
lgUQBRTZ0/1UFGsiA5JMUvW2KJ/+Gz/Q8y8qk3pGozU 0wbsh2I2pzhahpm662E3ulw76/YyvtTXBtS0mtg1/pM
-> ssh-ed25519 vT7ExA Xbbo3IR8gsXyQCuIzOwBWXqvEBAHm2L9oDPAgQoqkX0 -> ssh-ed25519 vT7ExA 7iK8tSFGz3EvsQw4bUkDMQSQdKshxFQTRLFo6wmVp3M
+Txx4q4u7sQnAykGwvi2sEBQNKf1ODkgMk0E2fD5AFg dsoqzeXaH8Wf9/VwZd483vi6bbkfwKcaPJllHoDFNEE
--- KVYftap0YUB0g3a9/IdYghEHZMD0C7kJY+cvmQDG1no --- JR+WkrSCQyDgBaW016W/jnoT7UdeLUYAztu+zZ4Jk5U
“î˪¬†µµÏÍ­ ®8gjš <C5A1>¶Y„H}D> £ùåa‡ñ¤<C3B1>݇í!‡ÅoÒ)ËŒÈÌv+M$Jï[áÝ+  c&qc3Úö
Àv;?»l2a¦º RgÝÛ+%Ý!¡õÔŒ `ß±±=CuíE½`o%ÞXͼrªLa¾YlžX:F`_'ψ¥ç„§­šBâ¦<C3A2>Wí70o††ˆÐø þš k“öº`œ„¸<E2809A>Ãlo-;<3B>ö_{˜cý9¡k™¥Ä*`ô`¡"U][àÆ¿LþOH$†?T߸¸ƒêø$±k˜ÏNÑrä"–Ê £~XRB}ë5cqK=oõý™ÿH"âu
¡Ñs a7ÅÌeA¹z#Þó<C39E>ƒ¶IÚ©´Òèf~ÄM~AœYž2ä¢ÓãB!£“?

Binary file not shown.

View file

@ -6,7 +6,6 @@ let
vps3 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHvupo7d9YMZw56qhjB+tZPijxiG1dKChLpkOWZN0Y7C"; vps3 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHvupo7d9YMZw56qhjB+tZPijxiG1dKChLpkOWZN0Y7C";
vps4 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMpoLgBTWj1BcNxXVdM26jDBZl+BCtUTj20Wv4sZdCHz"; vps4 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMpoLgBTWj1BcNxXVdM26jDBZl+BCtUTj20Wv4sZdCHz";
vps5 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBWbIznvWQSqRF1E9Gv9y7JXMy3LZxMAWj6K0Nq91kyZ"; vps5 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBWbIznvWQSqRF1E9Gv9y7JXMy3LZxMAWj6K0Nq91kyZ";
minipc = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINApZRrvK4RC1SU5m4OLbill7HZYPQtuvh/m/AB4q5dG";
in in
{ {
"widetom_bot_token.age".publicKeys = [ vps1 ]; "widetom_bot_token.age".publicKeys = [ vps1 ];
@ -29,10 +28,6 @@ in
"pyroscope_s3_secret.age".publicKeys = [ vps3 ]; "pyroscope_s3_secret.age".publicKeys = [ vps3 ];
"restic_backup.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ]; "restic_backup.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ];
"generic_backup_password.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ]; "generic_backup_password.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ];
"website_s3_key_write.age".publicKeys = [ vps1 ]; # only used by Noratrieb/website GHA
"does_it_build_private_key.age".publicKeys = [ vps4 ];
"immich_secrets.age".publicKeys = [ minipc ];
"paperless_env.age".publicKeys = [ minipc ];
"knot_dns_rfc2136_key_config.age".publicKeys = [ dns1 dns2 ]; "knot_dns_rfc2136_key_config.age".publicKeys = [ dns1 dns2 ];
"knot_dns_rfc2136_key_envvar.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ]; "knot_dns_rfc2136_key_envvar.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ];
"wg_private_dns1.age".publicKeys = [ dns1 ]; "wg_private_dns1.age".publicKeys = [ dns1 ];
@ -42,5 +37,4 @@ in
"wg_private_vps3.age".publicKeys = [ vps3 ]; "wg_private_vps3.age".publicKeys = [ vps3 ];
"wg_private_vps4.age".publicKeys = [ vps4 ]; "wg_private_vps4.age".publicKeys = [ vps4 ];
"wg_private_vps5.age".publicKeys = [ vps5 ]; "wg_private_vps5.age".publicKeys = [ vps5 ];
"wg_private_minipc.age".publicKeys = [ minipc ];
} }

Binary file not shown.

View file

@ -1,6 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 LZU5Eg YCaoZYLxmyrcSVXaTqDeC25n7lwuGlTDfWPNxg9etn0 -> ssh-ed25519 LZU5Eg 2I80UG4n18vxvqUJXwKeAPqelD83nX/n8XHi/XVq208
xSVH1o+ITY39M7X8FNpj5liEW/20HTq0ZRxsoo3U8JQ mDoUzJu9KfUFyzJPoLPU+xhSbGesECEQZSSrc38HA54
--- i8MfM8cVg0SJnNqUYeTQ+dY2FZ6yEhIGkiHgxBzTDYE --- J9+vPA8z+/8jcO/V9iVZ3tWJF4TUe+nD6fmjH6f5dmc
ŠsÄt´÷ v¶@<(xÃÞ÷Eh»µ]8eÔý-$<24>K00”T!Å“ÀŽŸÄ<¬"5 SCÔ#ÆFÐà ¼¾é©wabèû
Fã0e<EFBFBD>Ò<EFBFBD>ŠYØ-{sóh]ƬfAp»ùûûB^ú£1ûäÄeð0!ä¾3šþÍÜs™§ÄÙ"·új@æþ=²rµ¯Rsí(+˜"

Binary file not shown.

View file

@ -1,7 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 yMKb8Q QdFcYSyIYFlrx1vOfnWaFzULi8AxYIpH1HXLRZzs+iE
3JG+l7U6AXmWe/H9J1B3dFjD+GCNRM4wsNWR0CHU0PM
--- UXqL/EG0JYwnV4Owi0Gy4BnpW7QkgiF4z2P9Qskfq4w
@
£þqû¯ÈÐÍ,YL³Ñ3ü)×eq¶¹ÙaK@]¯ÿe»à‰x¡CÏ
tþòÎv-G!Í}Šš±çJÒÁ i˜È$=*‚ª

Binary file not shown.

View file

@ -1,5 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 91VHug MzqFl7ZTH4laSYXRYPbIiXadl/bqVXPHRM7wD5aLhy8 -> ssh-ed25519 91VHug YHHrtch+bKHxenRqMPSvqqby7odUGontauTfAfTAhlw
Ng19G3jaJJr1s33i0kCHxIUQeTmoISTN+VQQD3rB33I VDY1jPyeClwpg7Tq604rU+Po+nue7cBRqhIEdc8iiAk
--- JkYGUYo6Ys48HI9UpXGardgf+k+DC71dxLiXqxMmFEQ --- mUabX/gruf9Erp4OeRmCEwd7KR2aTApviipXyCL1P+g
C<15>æqÎC<11>!<21>nÐ ý½Æˆ,ýbæA«8"ºMeNÑŒnÀÍM[(üÖ¡¶Xͤ×X+•á~ãØ“„ýS¾nßKXõÄià8¿†> “š¨ ˇťŚ‹ɤR<C2A4>-ĎGuÔÄű™:7€+"SŇ5ěÔSSÇ3\ÁRpMď?s0±Ś<C2B1>$ć’@ţ°±ń…řűÎČô€Ň$§…) ýí

Binary file not shown.

View file

@ -1,5 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 51bcvA soCOaoBhsAvjaw29hw6Q9JkrLGbfQEwgszOIl38+CB8 -> ssh-ed25519 51bcvA kyLCrT3jFu1BszuLMnyP0ej1kL5OvnAu/R6vR+PtYWU
uj17MiT/crUT+LXF9TEylo131FV1cKQbNXQNWCI1djw n70Krz1NA1BHhMrJQprm+LBBhY8AeQwI1PvHbF628OE
--- MAVo3X1mO0iUC0mEo4wbbDbK19hKxB/zEcfqfR4Bxsw --- VbdM9HH1CM+4f6z/5oSId9DW6Gi1+q3IuCE6qPKg1mM
2ü}[üI,sW/ä8®˜ªöKDŸÎkŠjzH¬,(ny¦ß”8uóÚq.^PrͪßCý—ð¤MÔ`)ì fœyô,XüOÒ¡ Ą@T˝YÔ(ÇčQŁLYŹŮGHGnk†¤ ,®]&§ď%UfÇĺMő±W“´qx”őźJkÚ_k¨ëh(y Śk|<04>»*=ŇIk Ź

View file

@ -1,5 +1,7 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 vT7ExA Z8248Zxd0dGjx/YtU3cVKwuKMDRaHQpo6d21bwSOWz0 -> ssh-ed25519 vT7ExA 2giKg2lnsURC0VqDT8Ibfn9jvkIJUOwIZkRN0Px8OSo
/7PxJCz7yfuGuBWioDQMizW9+tL7Ku7JEB2h6aG4vmE g3ZQzVSDVUl/BX3tAktgkFk5lVKgplZa+vtLYSd+RW8
--- xEBearw/OGRugS23zBrNGj5zKY/bNsot+UQOcCEATWA --- 9ZTtNf9EG2B6oDyWYST8QiNGQHdYgQ5PoHzEHwW2eY8
ƒœ!«pÕ%~¢)6- Hy*îeÀŸ¡Ÿ» º âgã ¨‡pÒXÑ·Ók÷Ý Ùˆ¿èmé4bÖùn”ŸÀÙÁª¬êx6díe ÝМ?Ÿ<>Mâ-<2D>À€b÷>[Á;°^]·v|¤.
<EFBFBD>IüòyˆlþM<>¹s|ÂN5úUÑój
ƒä:¬á€ìʦý¤ò<E280BA>ET½

View file

@ -1,6 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg XJWJcqVabkHFOrbsNTS6+jc/pQ1a4D8lZkObT8BZwiE -> ssh-ed25519 qM6TYg Xds9FlVzv4E6ZFFTH6zZwG8ewomPq5R3S3/8jDN7zw0
DgFVt1+01MNlPm898/qnC0wGbs6eEsLcHpyANA5tpsA l1EWvQR0RK865mVQVuCFuo+02HTzrHHlsY9r+E2/Nfc
--- VhhquCcml82lpKjXLecBoCz/2CHNl2S9htU2iIWfvyY --- n9KSdsLECG7uH0yD5GsWC/1mTDMXi/JLDJ++oUycTEs
~<>'t/!Fb†[k"õýy¦føiª¢Ü¨ŸL½ÑGêêg!ËFqZ¡aA<61>3 ÉL«wÐÜð-§b—}ó¶T6ÁúkíÀX Ò¢óF3¾q4Ÿèy·¬hzÒ?hSÖ8<C396>Ïb=ƒ1)ÑP*{˜ËºS>Ø(æ<>+<2B>1yð#*ÂiêBS
úiý¡E`vÕ8Õ÷<Í1Fýmpx~õ¦)gc¹«7R¾³×ð¿µ&%U'XäDD

Binary file not shown.

View file

@ -1,22 +1,23 @@
import fs from "node:fs/promises"; import fs from "node:fs/promises";
const path = `${import.meta.dirname}/nixpkgs.json`; const path = `${import.meta.dirname}/nixpkgs.json`;
const channels = JSON.parse(await fs.readFile(path)); const nixpkgs = JSON.parse(await fs.readFile(path));
for (const [channel, nixpkgs] of Object.entries(channels)) { const res = await fetch(
const res = await fetch( `https://api.github.com/repos/NixOS/nixpkgs/commits/${nixpkgs.channel}`
`https://api.github.com/repos/NixOS/nixpkgs/commits/${channel}` );
if (!res.ok) {
throw new Error(
`get commit for ${name}: ${res.status} - ${await res.text()}`
); );
if (!res.ok) {
throw new Error(
`get commit for ${channel}: ${res.status} - ${await res.text()}`
);
}
const body = await res.json();
if (body.sha !== nixpkgs.commit) {
nixpkgs.commit = body.sha;
nixpkgs.lastUpdated = new Date().toISOString();
}
} }
await fs.writeFile(path, JSON.stringify(channels, null, 2) + "\n"); const body = await res.json();
if (body.sha !== nixpkgs.commit) {
nixpkgs.commit = body.sha;
nixpkgs.lastUpdated = new Date().toISOString();
await fs.writeFile(path, JSON.stringify(nixpkgs, null, 2) + "\n");
}

Binary file not shown.

Binary file not shown.

Binary file not shown.