Compare commits

..

35 commits

Author SHA1 Message Date
8479644fc4 dynamic dns updates 2026-05-28 22:36:32 +02:00
d41530b65f step 1 for dyn dns 2026-05-28 22:36:23 +02:00
975fb518ef paperless 2026-05-28 22:08:46 +02:00
1df84d34b6 cleanup 2026-05-28 15:21:24 +02:00
281e3bcb0a update 2026-05-28 15:16:54 +02:00
9dd5ae6698 minipc 2026-05-28 14:57:18 +02:00
131a282338 update 2026-05-10 16:57:35 +02:00
f3aed2bf45 update 2026-04-15 22:06:01 +02:00
eebb543d99 update to nixos 25.11 2026-02-14 20:37:31 +01:00
f2b1f2bc51 update and matrix 2026-02-14 17:40:02 +01:00
d392369473 update 2026-01-31 15:04:01 +01:00
c5ec691a7c hugo chat permissive cors 2026-01-31 14:36:40 +01:00
ac0860cd05 update does-it-build 2026-01-11 19:37:15 +01:00
ad469cf152 womangling 2026-01-10 20:37:45 +01:00
9015d6ebab update 2025-12-28 18:43:32 +01:00
413dfef394 update 2025-12-22 13:12:07 +01:00
f6fb60c03a update does-it-build
now needs a new rust version so let's pull in the rust from 25.11 lol
2025-11-29 00:14:47 +01:00
343ee03765 apply 2025-11-22 13:42:24 +01:00
306028604c update 2025-11-14 23:03:03 +01:00
4a0f3cc7a7 update 2025-11-14 21:50:41 +01:00
bd9d44526a update does-it-build 2025-11-10 21:16:29 +01:00
6cf0169b96 update 2025-11-01 15:35:15 +01:00
56272d89e3 snowflake-proxy 2025-10-24 23:31:42 +02:00
432fa7eb0e update 2025-10-05 12:06:06 +02:00
d3bb071aae gamer 2025-09-29 18:04:28 +02:00
4eb8087847 shorten proton ttl 2025-09-29 17:49:15 +02:00
f53dfd45bb update 2025-09-28 12:55:44 +02:00
925c0b7fe4 update 2025-09-12 20:55:17 +02:00
1353cdf0cd i'll chose to not question it 2025-09-12 20:55:05 +02:00
d5e2fdcdd3 remove unused dep 2025-08-23 21:07:42 +02:00
12e01508a5 magic 2025-08-20 20:39:35 +02:00
d21158e234 harden 2025-08-18 21:54:20 +02:00
6206de09bb update and better 2025-08-18 21:10:44 +02:00
9c688d469f Better caching for the blog 2025-08-17 22:19:56 +02:00
6b97a53344 move website to garage
dynamic updates at any time without a nixos rebuild!
2025-08-13 21:31:45 +02:00
68 changed files with 581 additions and 291 deletions

View file

@ -1,77 +0,0 @@
#!/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,11 +1,15 @@
{ pkgs, lib, my-projects-versions, ... }:
{ pkgs, lib, config, my-projects-versions, ... }:
let
does-it-build-base = (import (pkgs.fetchFromGitHub my-projects-versions.does-it-build.fetchFromGitHub)) { inherit pkgs; };
does-it-build-base = (import (pkgs.fetchFromGitHub my-projects-versions.does-it-build.fetchFromGitHub)) {
inherit pkgs;
};
does-it-build = does-it-build-base.overrideAttrs (finalAttrs: previousAttrs: {
DOES_IT_BUILD_OVERRIDE_VERSION = my-projects-versions.does-it-build.commit;
});
in
{
age.secrets.does_it_build_private_key.file = ../../secrets/does_it_build_private_key.age;
services.caddy.virtualHosts = {
"does-it-build.noratrieb.dev" = {
logFormat = "";
@ -35,7 +39,32 @@ in
User = "does-it-build";
Group = "does-it-build";
ExecStart = "${lib.getExe' (does-it-build) "does-it-build" }";
Environment = "DB_PATH=/var/lib/does-it-build/db.sqlite";
Environment = [
"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,6 +9,7 @@ let
url =
"https://github.com/C0RR1T/HugoChat/releases/download/2024-08-05/hugo-client.tar.xz";
sha256 = "sha256:121ai8q6bm7gp0pl1ajfk0k2nrfg05zid61i20z0j5gpb2qyhsib";
stripRoot = false;
};
in
{
@ -61,35 +62,27 @@ in
"api.hugo-chat.noratrieb.dev" =
let
cors = pkgs.writeText "cors" ''
# https://gist.github.com/ryanburnette/d13575c9ced201e73f8169d3a793c1a3
@cors_preflight{args[0]} method OPTIONS
@cors{args[0]} header Origin {args[0]}
handle @cors_preflight{args[0]} {
header {
Access-Control-Allow-Origin "{args[0]}"
Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS"
Access-Control-Allow-Credentials "false"
Access-Control-Allow-Headers "$${args[1]}"
Access-Control-Max-Age "86400"
defer
}
respond "" 204
@cors_preflight {
method OPTIONS
header Origin *
}
handle @cors{args[0]} {
handle @cors_preflight {
header {
Access-Control-Allow-Origin "{args[0]}"
Access-Control-Expose-Headers *
defer
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "*"
Access-Control-Allow-Headers "content-type"
}
respond 204
}
'';
in
{
logFormat = "";
extraConfig = ''
import ${cors} https://hugo-chat.noratrieb.dev "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type"
import ${cors}
encode zstd gzip
reverse_proxy * localhost:5001
'';

View file

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

View file

@ -4,10 +4,11 @@ let
src = pkgs.fetchFromGitHub my-projects-versions.widetom.fetchFromGitHub;
pname = "widetom";
version = "0.1.0";
cargoHash = "sha256-AWbdPcDc+QOW7U/FYbqlIsg+3MwfggKCTCw1z/ZbSEE=";
cargoHash = "sha256-riQA+GviHMqiSvoRKcJhM3MGVEIv6urgYyvBZZd4fCc=";
meta = {
mainProgram = "widertom";
};
RUSTFLAGS = "-Cforce-frame-pointers=true";
};
in
{
@ -31,6 +32,21 @@ in
serviceConfig = {
DynamicUser = true;
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,10 +23,9 @@ check_dig_answer A "nilstrieb.dev" "161.97.165.1"
check_dig_answer NS noratrieb.dev "noratrieb.dev..*3600.*IN.*NS.*ns1.noratrieb.dev."
# Mail stuff
check_dig_answer MX noratrieb.dev "mail.protonmail.ch."
check_dig_answer MX noratrieb.dev "mailsec.protonmail.ch."
check_dig_answer TXT noratrieb.dev "protonmail-verification=09106d260e40df267109be219d9c7b2759e808b5"
check_dig_answer TXT noratrieb.dev "v=spf1 include:_spf.protonmail.ch ~all"
check_dig_answer MX noratrieb.dev "mail.tutanota.de."
check_dig_answer TXT noratrieb.dev "t-verify=dae826f2ae9f73a71cc247183616b6c9"
check_dig_answer TXT noratrieb.dev "v=spf1 include:spf.tutanota.de -all"
# Check HTTP responses
http_hosts=(

View file

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

@ -0,0 +1,50 @@
{ 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,40 +1,11 @@
{ pkgs, config, lib, name, ... }:
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
];
};
{ pkgs, config, lib, name, ... }: {
imports = [ ../caddy-base ];
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
services.caddy = {
enable = true;
package = caddy;
logFormat = ''
output stdout
format json
'';
globalConfig = ''
email tls@noratrieb.dev
auto_https disable_redirects
@ -70,12 +41,6 @@ in
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" = {
logFormat = "";
extraConfig = ''

View file

@ -2,9 +2,12 @@
let
pretense = import (pkgs.fetchFromGitHub my-projects-versions.pretense.fetchFromGitHub);
quotdd = import (pkgs.fetchFromGitHub my-projects-versions.quotdd.fetchFromGitHub);
networkConfig = networkingConfig."${name}";
in
{
deployment.targetHost = "${name}.infra.noratrieb.dev";
deployment.targetHost =
if networkConfig.publicIPv4 == null
then name else "${name}.infra.noratrieb.dev";
# TODO: ensure that the rust programs have frame pointers
@ -20,6 +23,8 @@ in
nixPath = [ "nixpkgs=${nixpkgs-path}" ];
};
nixpkgs.config.allowUnfree = true;
environment.systemPackages = with pkgs; [
vim
wget
@ -27,10 +32,14 @@ in
traceroute
dnsutils
nftables
htop
];
networking.hostName = name;
# Swiss german console tty keyboard layout
console.keyMap = "sg";
time.timeZone = "Europe/Zurich";
users.users.root.openssh.authorizedKeys.keys = [ ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG0n1ikUG9rYqobh7WpAyXrqZqxQoQ2zNJrFPj12gTpP nilsh@PC-Nils'' ];
@ -60,6 +69,7 @@ in
settings = {
PasswordAuthentication = false;
AllowUsers = [ "root" ];
};
};
services.fail2ban = {
@ -79,6 +89,22 @@ in
"PRETENSE_PORTS=23,3306,5432,1521" # telnet,mysql,postgres,oracle
"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 = {
@ -90,6 +116,23 @@ in
ExecStart = "${lib.getExe (quotdd {inherit pkgs;})}";
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
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 = [
@ -188,6 +231,22 @@ in
};
systemd.services.alloy.serviceConfig = {
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 = ''
discovery.process "all" {

View file

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

View file

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

View file

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

View file

@ -0,0 +1,34 @@
{ 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

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

View file

@ -0,0 +1,42 @@
# 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

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

View file

@ -0,0 +1,24 @@
{ 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

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

View file

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

View file

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

View file

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

View file

@ -1,31 +1,4 @@
{
"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": {
"commit": "270b01fc1118dfd713c1c41530d1a7d98f04527d",
"fetchFromGitHub": {
@ -45,12 +18,12 @@
}
},
"does-it-build": {
"commit": "81790825173d87f89656f66f12a123bc99e2f6f1",
"commit": "5518c49d7c6348ba01f286ce031f5322bbd9f786",
"fetchFromGitHub": {
"owner": "Noratrieb",
"repo": "does-it-build",
"rev": "81790825173d87f89656f66f12a123bc99e2f6f1",
"hash": "sha256-MCgGDd7Sg+BiG8L20Bbz8bHMB/Xuc1ztOVwv/b37BnQ="
"rev": "5518c49d7c6348ba01f286ce031f5322bbd9f786",
"hash": "sha256-nOV0n2THZXG/fC3lgPW2gDeWn7bYIZydCTIkKJ+U898="
}
},
"upload.files.noratrieb.dev": {
@ -72,12 +45,12 @@
}
},
"widetom": {
"commit": "33d1738799618d72fe2b86896f766cbfea58dc76",
"commit": "387f6ff587b66186332cf5cfba90c966bba0695c",
"fetchFromGitHub": {
"owner": "Noratrieb",
"repo": "widetom",
"rev": "33d1738799618d72fe2b86896f766cbfea58dc76",
"hash": "sha256-lSjlDozwKRLF62jsDaWo+8+rcQdeEgurEnuw00hk3o8="
"rev": "387f6ff587b66186332cf5cfba90c966bba0695c",
"hash": "sha256-0PCal2czxBlgDh59TM7o94C9PG3a98YYUJ887/BYeEA="
}
}
}

View file

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

Binary file not shown.

Binary file not shown.

View file

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

Binary file not shown.

View file

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

Binary file not shown.

View file

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

Binary file not shown.

View file

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

Binary file not shown.

View file

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

Binary file not shown.

View file

@ -0,0 +1,5 @@
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,15 +1,14 @@
age-encryption.org/v1
-> ssh-ed25519 qM6TYg HodUMahq+fafwLXzUaC/Y2E2btbeC32/CwBPL7y5hlg
67R4TdZQNacpJLHCa+GdsycwWGekicCPhcOAQer7Uek
-> ssh-ed25519 91VHug ffJ4wwzD4G1wbS7XyQM4vQwjyv4llGHog9RxI5+JZXE
ybHjj+2DqadF21NjHHqB64zu+fWscbNFe/5zvgDIFP8
-> ssh-ed25519 XzACZQ i7RCIUKgmO7BtDysfZ5wsBLbXwu2x0a2qOnmm9AdBHw
+VRFX+3yf4WHMoagaQOEl3Z0W0VWN0v1PqUrunfQrZM
-> ssh-ed25519 51bcvA ywiVAHSTYuHmuM7f0lrRHDR89B30BPi/u0esMNloJQc
0wbsh2I2pzhahpm662E3ulw76/YyvtTXBtS0mtg1/pM
-> ssh-ed25519 vT7ExA 7iK8tSFGz3EvsQw4bUkDMQSQdKshxFQTRLFo6wmVp3M
dsoqzeXaH8Wf9/VwZd483vi6bbkfwKcaPJllHoDFNEE
--- JR+WkrSCQyDgBaW016W/jnoT7UdeLUYAztu+zZ4Jk5U
c&qc3Úö
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!£“?
-> ssh-ed25519 qM6TYg rRl7WcBUycyZnCXeuPgeCPUBRjl5fXbvErOtESs9Pjo
ra1UlArViFAgu3ldeOQ/I6/rsaSr0yGSMjQSl2V3JSc
-> ssh-ed25519 91VHug Q8+LWlf3zKenc9Nw0SrC5IgHcUr9SkK3Se/exTlUs1g
jf1PEQiL1p6zg/VEFriXef5Oj6tiUMgXd6fvrxRTfew
-> ssh-ed25519 XzACZQ L4Xe5fEXnXVCgoUmTnOoT+8SNx4Tcxuak6sKQBMU/V8
Jt/U6vVTY6dOa8p/CZAZ6mkSvYAvz4k61W2vMfQIWb4
-> ssh-ed25519 51bcvA UWQ3aY+PLAPfYXaV6lcmVb22cuq8Tjjlr/YQv0LvXnE
lgUQBRTZ0/1UFGsiA5JMUvW2KJ/+Gz/Q8y8qk3pGozU
-> ssh-ed25519 vT7ExA Xbbo3IR8gsXyQCuIzOwBWXqvEBAHm2L9oDPAgQoqkX0
+Txx4q4u7sQnAykGwvi2sEBQNKf1ODkgMk0E2fD5AFg
--- KVYftap0YUB0g3a9/IdYghEHZMD0C7kJY+cvmQDG1no
“î˪¬†µµÏÍ­ ®8gjš <C5A1>¶Y„H}D> £ùåa‡ñ¤<C3B1>݇í!‡ÅoÒ)ËŒÈÌv+M$Jï[áÝ+ 
Àv;?»l2a¦º RgÝÛ+%Ý!¡õÔŒ `ß±±=CuíE½`o%ÞXͼrªLa¾YlžX:F`_'ψ¥ç„§­šBâ¦<C3A2>Wí70o††ˆÐø þš

Binary file not shown.

View file

@ -6,6 +6,7 @@ let
vps3 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHvupo7d9YMZw56qhjB+tZPijxiG1dKChLpkOWZN0Y7C";
vps4 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMpoLgBTWj1BcNxXVdM26jDBZl+BCtUTj20Wv4sZdCHz";
vps5 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBWbIznvWQSqRF1E9Gv9y7JXMy3LZxMAWj6K0Nq91kyZ";
minipc = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINApZRrvK4RC1SU5m4OLbill7HZYPQtuvh/m/AB4q5dG";
in
{
"widetom_bot_token.age".publicKeys = [ vps1 ];
@ -28,6 +29,10 @@ in
"pyroscope_s3_secret.age".publicKeys = [ vps3 ];
"restic_backup.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_envvar.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ];
"wg_private_dns1.age".publicKeys = [ dns1 ];
@ -37,4 +42,5 @@ in
"wg_private_vps3.age".publicKeys = [ vps3 ];
"wg_private_vps4.age".publicKeys = [ vps4 ];
"wg_private_vps5.age".publicKeys = [ vps5 ];
"wg_private_minipc.age".publicKeys = [ minipc ];
}

Binary file not shown.

View file

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

Binary file not shown.

View file

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

Binary file not shown.

View file

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

View file

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

View file

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

Binary file not shown.

View file

@ -1,23 +1,22 @@
import fs from "node:fs/promises";
const path = `${import.meta.dirname}/nixpkgs.json`;
const nixpkgs = JSON.parse(await fs.readFile(path));
const channels = JSON.parse(await fs.readFile(path));
for (const [channel, nixpkgs] of Object.entries(channels)) {
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()}`
`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(nixpkgs, null, 2) + "\n");
}
}
await fs.writeFile(path, JSON.stringify(channels, null, 2) + "\n");

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.