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
71 changed files with 635 additions and 298 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 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 = 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 = "";
@ -35,7 +39,32 @@ 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 = "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 = 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
{ {
@ -61,35 +62,27 @@ in
"api.hugo-chat.noratrieb.dev" = "api.hugo-chat.noratrieb.dev" =
let let
cors = pkgs.writeText "cors" '' cors = pkgs.writeText "cors" ''
# https://gist.github.com/ryanburnette/d13575c9ced201e73f8169d3a793c1a3 @cors_preflight {
@cors_preflight{args[0]} method OPTIONS method OPTIONS
@cors{args[0]} header Origin {args[0]} header Origin *
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
} }
handle @cors{args[0]} { handle @cors_preflight {
header { header {
Access-Control-Allow-Origin "{args[0]}" Access-Control-Allow-Origin "*"
Access-Control-Expose-Headers * Access-Control-Allow-Methods "*"
defer Access-Control-Allow-Headers "content-type"
} }
respond 204
} }
''; '';
in in
{ {
logFormat = ""; logFormat = "";
extraConfig = '' 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 encode zstd gzip
reverse_proxy * localhost:5001 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 services.caddy.globalConfig = ''
website = import (pkgs.fetchFromGitHub my-projects-versions.website.fetchFromGitHub); filesystem garage s3 {
blog = pkgs.fetchFromGitHub my-projects-versions.blog.fetchFromGitHub; bucket noratrieb.dev
slides = pkgs.fetchFromGitHub my-projects-versions.slides.fetchFromGitHub; region garage
website-build = website { inherit pkgs slides blog; }; endpoint http://localhost:3900
in use_path_style
{ }
'';
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 {
name = "website"; header /blog/css/* Cache-Control "max-age=31540000, immutable"
src = website-build; header /blog/fonts/* Cache-Control "max-age=31540000, immutable"
inherit pkgs lib;
}} @txt {
path /
not header Accept *text/html*
}
rewrite @txt /index.txt
file_server { file_server {
etag_file_extensions .sha256 fs garage
precompressed zstd gzip br # TODO: run precompress script
# etag_file_extensions .sha256
# precompressed zstd gzip br
} }
''; '';
}; };
@ -30,5 +44,12 @@ in
reverse_proxy * localhost:3902 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; src = pkgs.fetchFromGitHub my-projects-versions.widetom.fetchFromGitHub;
pname = "widetom"; pname = "widetom";
version = "0.1.0"; version = "0.1.0";
cargoHash = "sha256-AWbdPcDc+QOW7U/FYbqlIsg+3MwfggKCTCw1z/ZbSEE="; cargoHash = "sha256-riQA+GviHMqiSvoRKcJhM3MGVEIv6urgYyvBZZd4fCc=";
meta = { meta = {
mainProgram = "widertom"; mainProgram = "widertom";
}; };
RUSTFLAGS = "-Cforce-frame-pointers=true";
}; };
in in
{ {
@ -31,6 +32,21 @@ 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,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." 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.protonmail.ch." check_dig_answer MX noratrieb.dev "mail.tutanota.de."
check_dig_answer MX noratrieb.dev "mailsec.protonmail.ch." check_dig_answer TXT noratrieb.dev "t-verify=dae826f2ae9f73a71cc247183616b6c9"
check_dig_answer TXT noratrieb.dev "protonmail-verification=09106d260e40df267109be219d9c7b2759e808b5" check_dig_answer TXT noratrieb.dev "v=spf1 include:spf.tutanota.de -all"
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.commit}.tar.gz"); nixpkgs-path = (fetchTarball "https://github.com/NixOS/nixpkgs/archive/${nixpkgs-version."nixos-25.11".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" ]; peers = [ "vps1" "vps2" "vps4" "vps5" "dns1" "dns2" "minipc" ];
}; };
tags = [ "apps" ]; tags = [ "apps" ];
}; };
@ -92,6 +92,17 @@
}; };
tags = [ "apps" ]; 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/registry
./modules/backup ./modules/backup
./modules/restic ./modules/restic
./modules/snowflake-proxy
# apps # apps
./apps/website ./apps/website
@ -201,6 +213,10 @@
./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";
@ -214,6 +230,7 @@
./modules/caddy ./modules/caddy
./modules/garage ./modules/garage
./modules/prometheus ./modules/prometheus
./modules/snowflake-proxy
./apps/website ./apps/website
]; ];
@ -229,6 +246,7 @@
./modules/garage ./modules/garage
./modules/backup ./modules/backup
./modules/restic ./modules/restic
./modules/snowflake-proxy
# apps # apps
./apps/website ./apps/website
@ -284,6 +302,7 @@
./modules/caddy ./modules/caddy
./modules/wg-mesh ./modules/wg-mesh
./modules/garage ./modules/garage
./modules/snowflake-proxy
./apps/fakessh ./apps/fakessh
]; ];
@ -292,4 +311,18 @@
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

@ -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,39 +1,11 @@
{ 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"
];
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
@ -47,6 +19,17 @@ in
insecure true insecure true
} }
acme_dns rfc2136 {
key_name "test"
key_alg "hmac-sha256"
key ""
server "dns1.local:53"
}
tls {
dns_challenge_override_domain "nilstrieb.dev"
}
servers { servers {
metrics metrics
} }
@ -58,12 +41,6 @@ in
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,9 +2,12 @@
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 = "${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 # TODO: ensure that the rust programs have frame pointers
@ -20,6 +23,8 @@ 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
@ -27,10 +32,14 @@ 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'' ];
@ -60,6 +69,7 @@ in
settings = { settings = {
PasswordAuthentication = false; PasswordAuthentication = false;
AllowUsers = [ "root" ];
}; };
}; };
services.fail2ban = { services.fail2ban = {
@ -79,6 +89,22 @@ 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 = {
@ -90,6 +116,23 @@ 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 = [
@ -188,6 +231,22 @@ 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

@ -1,6 +1,12 @@
{ pkgs, lib, networkingConfig, ... }: { pkgs, lib, networkingConfig, config, ... }:
let metricsPort = 9433; in let metricsPort = 9433; in
{ {
age.secrets.knot_dns_rfc2136_key_config = {
file =
../../secrets/knot_dns_rfc2136_key_config.age;
owner = "knot";
};
# get the package for the debugging tools # get the package for the debugging tools
environment.systemPackages = with pkgs; [ knot-dns ]; environment.systemPackages = with pkgs; [ knot-dns ];
@ -21,6 +27,7 @@ let metricsPort = 9433; in
services.knot = { services.knot = {
enable = true; enable = true;
keyFiles = [ config.age.secrets.knot_dns_rfc2136_key_config.path ];
settingsFile = pkgs.writeTextFile { settingsFile = pkgs.writeTextFile {
name = "knot.conf"; name = "knot.conf";
text = '' text = ''
@ -28,6 +35,18 @@ let metricsPort = 9433; in
listen: 0.0.0.0@53 listen: 0.0.0.0@53
listen: ::@53 listen: ::@53
key:
- id: rfc2136-update
algorithm: hmac-sha256
secret: QRpeYCJLokRWyzT/tWrxaly5Seb5yTkE6/Ub66edWds=
acl:
- id: update_acl
address: 10.0.0.0/24
key: rfc2136-update
action: update
update-type: [TXT]
zone: zone:
- domain: noratrieb.dev - domain: noratrieb.dev
storage: /var/lib/knot/zones/ storage: /var/lib/knot/zones/
@ -35,6 +54,7 @@ let metricsPort = 9433; in
- domain: nilstrieb.dev - domain: nilstrieb.dev
storage: /var/lib/knot/zones/ storage: /var/lib/knot/zones/
file: ${import ./nilstrieb.dev.nix { inherit pkgs lib networkingConfig; }} file: ${import ./nilstrieb.dev.nix { inherit pkgs lib networkingConfig; }}
acl: update_acl
log: log:
- target: syslog - target: syslog
any: info any: info

View file

@ -18,7 +18,7 @@ let
vps1 // { vps1 // {
TTL = hour1; TTL = hour1;
SOA = { SOA = {
nameServer = "ns1.nilstrieb.dev."; nameServer = "ns.nilstrieb.dev.";
adminEmail = "void@nilstrieb.dev"; adminEmail = "void@nilstrieb.dev";
serial = 2024072601; serial = 2024072601;
}; };
@ -34,6 +34,7 @@ let
]; ];
subdomains = { subdomains = {
ns = dns1;
ns1 = dns1; ns1 = dns1;
ns2 = dns2; 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); 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
@ -37,13 +41,12 @@ let
TXT = [ TXT = [
"protonmail-verification=09106d260e40df267109be219d9c7b2759e808b5" "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.mx 10 "mail.protonmail.ch.") (ttl 60 (mx.mx 10 "mail.tutanota.de."))
(mx.mx 20 "mailsec.protonmail.ch.")
]; ];
subdomains = { subdomains = {
@ -51,6 +54,9 @@ let
ns1 = dns1; ns1 = dns1;
ns2 = dns2; ns2 = dns2;
# --- ACME setup for caddy
_acme-challenge.CNAME = [ (cname "_acme-challenge.nilstrieb.dev.") ];
# --- website stuff # --- website stuff
blog = vps1; blog = vps1;
www = vps1; www = vps1;
@ -60,6 +66,12 @@ 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 // {
@ -84,18 +96,26 @@ 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 = {
protonmail.CNAME = [ (cname "protonmail.domainkey.deenxxi4ieo32na6brazky2h7bt5ezko6vexdbvbzzbtj6oj43kca.domains.proton.ch.") ]; s1.CNAME = [ (cname "s1.domainkey.tutanota.de.") ];
protonmail2.CNAME = [ (cname "protonmail2.domainkey.deenxxi4ieo32na6brazky2h7bt5ezko6vexdbvbzzbtj6oj43kca.domains.proton.ch.") ]; s2.CNAME = [ (cname "s2.domainkey.tutanota.de.") ];
protonmail3.CNAME = [ (cname "protonmail3.domainkey.deenxxi4ieo32na6brazky2h7bt5ezko6vexdbvbzzbtj6oj43kca.domains.proton.ch.") ];
}; };
_dmarc.TXT = [ _dmarc.TXT = [
"v=DMARC1; p=quarantine" "v=DMARC1; p=quarantine; adkim=s"
]; ];
# retired # retired

View file

@ -20,7 +20,7 @@ in
}; };
services.garage = { services.garage = {
enable = true; enable = true;
package = pkgs.garage_2_0_0; package = pkgs.garage_2;
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,5 +53,12 @@ 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

@ -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"; 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"; }; }
];
}
]; ];
}; };
@ -219,6 +226,7 @@
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

@ -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; let peerConfig = (builtins.getAttr peer networkingConfig).wg;
in { in {
inherit (peerConfig) publicKey; 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" ]; allowedIPs = [ "${peerConfig.privateIP}/32" ];
# sometimes there's some weirdness....?? # sometimes there's some weirdness....??
persistentKeepalive = 25; 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": { "pretense": {
"commit": "270b01fc1118dfd713c1c41530d1a7d98f04527d", "commit": "270b01fc1118dfd713c1c41530d1a7d98f04527d",
"fetchFromGitHub": { "fetchFromGitHub": {
@ -45,12 +18,12 @@
} }
}, },
"does-it-build": { "does-it-build": {
"commit": "81790825173d87f89656f66f12a123bc99e2f6f1", "commit": "5518c49d7c6348ba01f286ce031f5322bbd9f786",
"fetchFromGitHub": { "fetchFromGitHub": {
"owner": "Noratrieb", "owner": "Noratrieb",
"repo": "does-it-build", "repo": "does-it-build",
"rev": "81790825173d87f89656f66f12a123bc99e2f6f1", "rev": "5518c49d7c6348ba01f286ce031f5322bbd9f786",
"hash": "sha256-MCgGDd7Sg+BiG8L20Bbz8bHMB/Xuc1ztOVwv/b37BnQ=" "hash": "sha256-nOV0n2THZXG/fC3lgPW2gDeWn7bYIZydCTIkKJ+U898="
} }
}, },
"upload.files.noratrieb.dev": { "upload.files.noratrieb.dev": {
@ -72,12 +45,12 @@
} }
}, },
"widetom": { "widetom": {
"commit": "33d1738799618d72fe2b86896f766cbfea58dc76", "commit": "387f6ff587b66186332cf5cfba90c966bba0695c",
"fetchFromGitHub": { "fetchFromGitHub": {
"owner": "Noratrieb", "owner": "Noratrieb",
"repo": "widetom", "repo": "widetom",
"rev": "33d1738799618d72fe2b86896f766cbfea58dc76", "rev": "387f6ff587b66186332cf5cfba90c966bba0695c",
"hash": "sha256-lSjlDozwKRLF62jsDaWo+8+rcQdeEgurEnuw00hk3o8=" "hash": "sha256-0PCal2czxBlgDh59TM7o94C9PG3a98YYUJ887/BYeEA="
} }
} }
} }

View file

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

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 kxQujT+O6ZGlzTONdS/18DUVoxNapwtxitQo8GKr2hc -> ssh-ed25519 qM6TYg N7lS400e/5mSV3BlhnzThydz/c3DIIOHLNQodTErR08
b7KjCjuvhmWcqNB6BvNruL17Ww6yWkVKjjm/MGd+jlE vMqHXmSloSrWCxeD4QCH30GSqg1AI+6Dy16atFLNxjs
--- q3EzroLr8b0T2gKQ4xUR67YOLSwFP1V8UxAnKY0PP24 --- aJ6lQv9jnJHyocy+Kz4jPCtpiIewxoooR0Zsm7CS/pY
゚l貊0嬌1スCXq<58>謎{T姻tg傅リ゚ュヘ<EFBDAD>ロ捕詑<E68D95><EFBFBD>s5<13>hxk- éj9ò†ÇKy€È°0*ÜbÉÉ¿Y£0ûÅÅþ<C385>I3v +¶D"*/go™#Š³âØµñ

Binary file not shown.

View file

@ -1,5 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg yxVVZ7LOgN9NiKsl1+dN7Rp6Rsf0zlqb25Y6w43styk -> ssh-ed25519 qM6TYg Ln9ZxoEmhHUMbU4PufH8OYVzEnvFEm+b/SlBfitqEhw
gQ5g7TL8+lyGp0SxdcoRg0nTpu1w6WbZZK0ERyqRpkc M0n0qe7L9peTLylt0uoTR4gQBcCxfSIm7FAR0mPeG5E
--- 5uKpMbkW4zZ035mNXCuty+64IZ360gly/ezxnwtRX/0 --- BzrHhLTDQ49g2GTkJdmLpdhRBp1rfdekcW+A26jzKys
šË<EFBFBD>ô±ëSϸ>q!ŁźěOß·żźŤ”ÉTCż¸ŁŇşž<C59F>Ď[ń*󅬟«’\wźÝtcÇ×Őíg? |B±ŘĹë;’»"*îd<C3AE><57>ţÔvŔ/vĚnqe G6à?ÑU'réy¸†ÃÉ@b <0B>$ÏMçZŸ`ñ÷@äÂëkv£]Ÿ6Þ_°ÛŸNÜæÙø $ò!ám“ìVk€<6B>gA‰]ÿyW°,¾ë´ød'ª ;Ȧ핒 ÅÜŽˆ

View file

@ -1,14 +1,14 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg L6XQVJyw/T2kwH2iOa3dAxwxlAInVTKXek5QHUKsU3g -> ssh-ed25519 qM6TYg Nl4yCNn9+FiX2uBliOH052tOjnTj4DcFzaIDjD2MVTY
Mm8VXH3CITbrJTqBcjdMHGm1k7Kztd4irHqWnF0yKWM aU848NDVI6MN5JPm9FRha+HJySIEyRRcNaiiBRnxJLY
-> ssh-ed25519 91VHug 2PoHH6c5lVj6hfTH6+2NLzJcpXh20LgYgUHYrpY9Wg4 -> ssh-ed25519 91VHug HfzLsV+15VwIFXz9mYc3dNdlFnb2MdqOMIV3DkxnJmQ
iSaKgUoh0eSjeoiZ7mggn7LWV9C9xsM2foZrpJZY/ok Fr2LDl/Z5Tn9FspwZynbCvK9Let8VWGAr00lf3Uhj14
-> ssh-ed25519 XzACZQ xyYG90gHM9XHAxIv2cFU/WvZsdLo6prAPQgRKADP0UY -> ssh-ed25519 XzACZQ GWXW5myuKkabbJwdW3OsHl08KBo0wu3dJXXo13xYjR4
XdiJz1Zmh3S+IvaOCZBqrF8DSWBrrqePjy+ZiEwuaSA SYu+6yj0om9BHFoJH8wsDPEbQCQy/oAp1jRW9wX6Ys0
-> ssh-ed25519 51bcvA IYyt435x3NPiTKDKCVb8dIK5naOSyU/Wh7dOLQ6SRAM -> ssh-ed25519 51bcvA nenOCUH5VZ2j/u1fv7mD/2hZufU6KWY46UZwzINXSSo
M0s39vyjDY24Mlb16UHy9lFEseaJxzZhtCvszKxwVSA GbQOiKQ6ko7RpuYvmtUnf5wzNrKpR/FHkrYHhRzURDw
-> ssh-ed25519 vT7ExA ZBvUjCU8vYFddKgNfnuROuiDnDXhitG6eR6ek4+1R1E -> ssh-ed25519 vT7ExA 8/Cn92m/Qtoo78VSNEYNrC4HqoIKxLyvT7A0R0CpE0U
fiyuqamkakZ4t1MosIUqZaR0WEh7XVAwJiwH8lz3bsc rehfI6pEM0nAv9AQAFa3g/PTd4uvc8zwWLAVAgoq3NA
--- zvHNHd6bOMd0f3eIrl1qzyRh6zUe7G8mdrraYGtrnXU --- fHz+V2yXufeCvWNZ4Eu+vAdPYBoDYyuUlXcrTo8O/88
¿Ÿ%iFr Ñ™Ù`|)Ñ+é¢ÏŽúÜ<C3BA>ÿšS—”®ŽGÎNP²ß>ƒ?E{Ö¦<C396>mda‡dä<64>j`Ôˆ¾îþVÙü uÅn¢§­ÅZ¥Ö»X±ÂïUæ—½}ú¾>Ðj_´Dü_; 5ŠOpaò; rº¾À´u^+Ä=ú$!1
Ÿ¾Þ~4bðwZ'7¬µ0æ^Œ2Žã+w­Z0j;<3B>4ÕyTdp·•1'9Ù ²7Zësbøó¿ß. *(§¦y”Wö _‡P¡g`S^Gäàrƒ ¡rFç-Nà™ïöHræ³+ü°2äz>äFÔiw`ˬó öÖ0ðëÎ2íŒ4(3 ÿÑÍÕ«HÌ÷³=¹ay$tÔV†ÂßÉ‚É|H×å  ØIÕ “ådæ2´_`åä‹ <19>dÜðr?P³M‹Îý æ…bØ´Ä%qhùoÇë"áß—™lzs;r{…XÿuEã n)'!äýò»V °·°ÓZÖ˜ÓêÜŒ—™¡uÓ

View file

@ -1,14 +1,13 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg IBVFRlOVLHcuS6xa7UVGA1z9NTBtNwGbt94c/yTB8wE -> ssh-ed25519 qM6TYg Kmd5m9hb9QXzbbrLWC3SLcUfy/B8bEWdJMQ1iMe5MQ8
T+VtsTngND9kAd6DAtksXN4xYs+E8JZSxDeOm+G23tc A4ZoS84dtX+DMOzPXOMBb402q3o6LBExOda+Rm4hbO0
-> ssh-ed25519 91VHug nUkRwHgpn2i56NNY0VAuG+r3CX1rjt1M0ZVKj+ijwGo -> ssh-ed25519 91VHug rXXXRgZI91mIlLAclodKDk3V14pDyRCv5kg1RCB7AH8
ea8Ry6JIJlPOObY+v2Q5MkdcZqCeDLAOxC583WY38Hg CzC46ry6tCYkDX4jTW08j7Itqjb0raz2nlmU5/7zLCc
-> ssh-ed25519 XzACZQ 7f+8YcecMvwnOgwxjRMUUUm9Sp4cyKpIZWWMDrrCtzg -> ssh-ed25519 XzACZQ KbzLsMTNqcjJ2I+Bx5moRC74Z/QKHrbFVovC5hhm8DY
Bqhd2kpuTg3Xchme5wHfg4zkuikeM4H9GdOZVUv+HZk aAGFH0KBdM+nm4HyZ0X7MPc3+fBbcQrQAcvrK0F7LNM
-> ssh-ed25519 51bcvA DUk4CsGXhdj4uIqzYpoGmtHs5dnjIBUb0c9zj1DEum4 -> ssh-ed25519 51bcvA qv9cje7I7Sxje9xV0DghaxSxyovB37O3B1Bt6sHp/Bk
hGe3j5Ycn/WVV5wgg+vZuh2KhnamHACkHrDWcVgkSjo 2zEnhhy6dIOWMdbQE54xtQKfZjR2vTH+Z4son1/gYr8
-> ssh-ed25519 vT7ExA Zf67OkbMvOpgABZDuXw3U94KqX32VG8nnjo3Xmkbih0 -> ssh-ed25519 vT7ExA voN3ZvXhhqv4V9FpVTd2ViydPgxvjpQpeUcH6jljen4
5K5fnBxkQDaYwuMPhyNU5ZrZLjkgknG7dzMzyuANMuU sLjK4aWqGSlxxeMKPrIZCjw4tsz95C1R498bFZgBMVk
--- Jon4j4/xeZqS/6KsWszsVOoVOgJgsPEKxmtC7PcocCA --- Kfk+aieCFtZiKPE8toWEZwZw06sELpx1FiJCVDyLGcc
Ú솳—µ’~Š… éÈuøÜMú?Cš¬†ìÒóô0Z©&Œß ‡ÊrSÓÖgµ™W«áp´8ã¦{*6§ÿÀy•¤§q“¯õð%‡øÎ
¢íNŒ+jKþ߬Ÿ/á]Ó !ä‚¶Œ¢.7„k~<÷ñfÃCÖT.ªOŸêÅ¥*aÁ •Û

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
·+

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,13 @@
age-encryption.org/v1
-> ssh-ed25519 qM6TYg QQMDIquZuxMKwx2hl2ST9BMXa61DBdC/cMUutcRIRHw
l7oENezyJwfJHrgNUtFMfOF08BhAYWQOjW8v7VPN/aE
-> ssh-ed25519 91VHug wQBzeFG2xixYU5L8/d81n5FkZMqO3uCSF60Xi80mvnU
nPAgKpJj7WDJ4tbKGnlWAhvAUOyLIyOY3aPofKM0LfY
-> ssh-ed25519 XzACZQ HYj1Omcc8WYq6s9l5hVrjjibg1LFHnkYkXiPolGewws
uhrQ6nmP5fMApIJzUzwXcnlILdPvmlG4QhG1laW6alk
-> ssh-ed25519 51bcvA e2Xng7rC2SkYiDn5BRTIDBxn7vN/F95hI+okWL9TymI
7TJrZQlJsnGMu5jaFQllI1E/+ZGHZjGmaUpuNZSAPDI
-> ssh-ed25519 vT7ExA PSM21ZGF9T9g6rxnsCv3rAio1f5KckTHgivfclDjFFs
rq3M2R/LHYki4nQ68iFoLXH8VVmWyBDD6yv6y4tt5qQ
--- KqTQhyl3ef04vDQ8eu1IvTsEaSMYtQxxBAcIO+WYPr4
Â$Jk¾#_“¼ø¼Frë"çàB}~¾åœP«@ì.÷ëŸeÜ…¢ŸYSL;ÎÐPŠz &0ÑDiKÿJ´^ÿ:à¨Oc'’—+âá

View file

@ -1,5 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 XzACZQ SXWsCSPW+iEQiaoW4lLmQCAtw47p2ccK2FIrOePUFEo -> ssh-ed25519 XzACZQ aRbZOixkF1CtYIoCxgHX1Cw25ozmtV4HWsFIY0sfHAw
d+bSrgW1uewdh+/LOD+6zK4voc89O3ZPMXQ36kl6rfw y9PvJ4rdceua7Q4GVqz09KZsensKhA8pLMjGyub06xY
--- Te2X1EuZEwoerdfBLxPtcuzWGOzF6dC1biFAebpX5kY --- gCH1ZBj/XvuwrtJcjVXr99OT89N7JOIlHd5xofjwH9o
š<EFBFBD>0‰´1<EFBFBD>¥,ýÔkò÷FÁ¬/©ÉÀÎQ<C38E>½ÙoËbZ£z rG¬ª*«~}LF2Pôz!"7жð-¤…7^yù¹™?bz7Ú.ú¨N{æž:<3A>!)º%æèY®á1ß+†P_æ¶<w¹ í2ÿž<18>eɪ¬"<øâºJ¥$"£’œΞ3‰<33>7Ùc7ƒ Pcwe§žOKD-¡ÑõPý¶8¼æDub3àóØ@HÞÊ}ÿ„!<21>ºE¿í<7F>½¥lÛH^k<>lMro\…ë%ƒ’#Ó¸¨˦Na¼µœ,þ=FkŠu:‰œ![” ˆÂ=¸ø&º÷0XÝ<·OMÌÜ¥Ð<0E>Ù©•!·ñ2À³-¯…JZ‰§|1îÔ

View file

@ -1,8 +1,8 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg k3jtd2qoiQCsKZYJliH9ySFuO7CVQQ5Sv2ikFYcaD2c -> ssh-ed25519 qM6TYg sx4kKW1m2RrcVkyxDMdDgh5jcwfrRDAFYa0EJBZKFnI
TSIg6y4C2WaLQJUyNT3HQOj09VmKSkQxlsVlaDc+1tY WPbchNFC7tTqC4DrIw7hUZSNNxE64kkXZdXB6/VFhj4
-> ssh-ed25519 XzACZQ NZhP9TD5nYxBMgO1O3vDOITeh7qxq4vhjG7AppQmRlM -> ssh-ed25519 XzACZQ GXDgzIGU4X6/oOr5hcI7SoorcowGPJHx/0X2+gj+Sk0
I1JiT8ISWLVUgoCphHSbhYvfssfP55NuBI2jclG3DVQ NATuZ7IZ0QwM9/GtaYdLXjBs6X0enhpVgWvGVpyqOO0
--- 6UR3wbSTB/f0s8hP/YHaY9HFDpnLAts0yksKCv7p9BA --- xMESjwLO7fJhwd0HnYzypoh3s6YRx86vSdXovvSBoHg
¤<EFBFBD>­iÓÆg50ß2LQÑî°káL† 9Iü{¶Ö<C2B6>µÊ¼Ø<C2BC>Zòd©«„{æYr©X­öB=
»B×$5Ñ˵m ²¾#„{_8ÕêÏÞj&+<2B><>Ñ;Zûç-'ƒÐWHSòÑaÄæ·f?óÎ56[t8¿¥&Zë¸_/î3BÀ”Ó_4½n ˆé]£ê Ó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.

View file

@ -1,6 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg amvNJk2G0JJHgGOwAWCtYIJgylqBAYDSXTKNYKwb4mo -> ssh-ed25519 qM6TYg vZTE3zklC5ACYvOuHSNPMDJshQPcxmbfen0TygKKW2s
aBXr7jN0/VUDTxCGvn+obz3JIU0boKcm4BbwFAidm1o 2TMCnx49MiF0AqCFMTmuXC/xKzos66rskkDfdnIdQTU
--- B6s8naj3JiQdjBDdwzY+PqW01QZFgKMpKSOVXHDfbHw --- 8JTyQvwrmMPdNLPK4cGGenl5DN2UpoCqUQzdbEvezpQ
˛Tą1ôÄQđ˛qÎýŇ”Ś?)W“Ĺ<E2809C>‰ť€˙ŘÚ<C598><C39A>‡4ę¬zŃc"CĎ+ĹŚHÓmQ)ö·ËÔ‹ˇ#Ś1HăßýÂnc«¬^ĆaÜűGş±.™µ' Þ!|GöqÇÖ^D;-Bžé2¸œ>ç"åÖ2¢ˆÆ<1E>A°)Ædõs\  Ó²îi¯¾îE!Ìg66û,}¸ PÃcÃQxðÂ0´<30>v<11>DV4Î:¬¸Ò¯÷;£mïåÉ(xs
$ bc´Ě

Binary file not shown.

Binary file not shown.

View file

@ -6,6 +6,7 @@ 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 ];
@ -28,6 +29,12 @@ 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_envvar.age".publicKeys = [ vps1 vps2 vps3 vps4 vps5 ];
"wg_private_dns1.age".publicKeys = [ dns1 ]; "wg_private_dns1.age".publicKeys = [ dns1 ];
"wg_private_dns2.age".publicKeys = [ dns2 ]; "wg_private_dns2.age".publicKeys = [ dns2 ];
"wg_private_vps1.age".publicKeys = [ vps1 ]; "wg_private_vps1.age".publicKeys = [ vps1 ];
@ -35,4 +42,5 @@ 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,5 +1,6 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 LZU5Eg o+MPatbYPM3sZq0MCqvvxlvKMQwlbajHURPQ+0g0qm8 -> ssh-ed25519 LZU5Eg YCaoZYLxmyrcSVXaTqDeC25n7lwuGlTDfWPNxg9etn0
UUurAYkPWXCaow746EV4dAQ+qTJnHIehcorUmanBc+o xSVH1o+ITY39M7X8FNpj5liEW/20HTq0ZRxsoo3U8JQ
--- BV+bxd0OIc3J4uT39al2odyn8ScDpq58SiwnW5pvRj4 --- i8MfM8cVg0SJnNqUYeTQ+dY2FZ6yEhIGkiHgxBzTDYE
òçT7W í|õfJÞÜ%"cõôäqÁ{TãP~f<>v,;Ñ:å…<C3A5>¾êŒ-ÓÏšÛ4þ€a† æ-¯uÌ\Lƒ_-¼VHâøûš³½%
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,8 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 91VHug cjq3el2rlJCWS3VwM5Dt22Ot/PoCdU5wJWTMosYQ6VE -> ssh-ed25519 91VHug MzqFl7ZTH4laSYXRYPbIiXadl/bqVXPHRM7wD5aLhy8
w/IyVNNAObRJxpV162CojPRE8yYbXJj1kaCBoPo3rNk Ng19G3jaJJr1s33i0kCHxIUQeTmoISTN+VQQD3rB33I
--- EDM/kgV9ewXhMvrQfHDtPLl7W46VCbZL5ciBO/B+Iu8 --- JkYGUYo6Ys48HI9UpXGardgf+k+DC71dxLiXqxMmFEQ
cL>¡‡È&ð°Â²=°^³$Úüm TüãÃ4õ& C<15>æqÎC<11>!<21>nÐ ý½Æˆ,ýbæA«8"ºMeNÑŒnÀÍM[(üÖ¡¶Xͤ×X+•á~ãØ“„ýS¾nßKXõÄià8¿†>
ƧÀÀI¢Ç)
c
¶LQiеá6ÓRÞÐòS•Üøÿ +T@ó0=ÉÉðö

Binary file not shown.

View file

@ -1,7 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 51bcvA mVJPirZJQxHgpX6CkMckYTpJk6HYN7CZYlUPPF1mYDM -> ssh-ed25519 51bcvA soCOaoBhsAvjaw29hw6Q9JkrLGbfQEwgszOIl38+CB8
XVZqovyalftEtV//FQM11Za+YAEMAuBTypcPQz1+G3E uj17MiT/crUT+LXF9TEylo131FV1cKQbNXQNWCI1djw
--- 7QAtADWyWr8SY3jLLzKxPsedOLyasfLs4lK3nmhkOi0 --- MAVo3X1mO0iUC0mEo4wbbDbK19hKxB/zEcfqfR4Bxsw
]J„éÄÑäXtE¬šŽæ)<29>þÿhS<01>ö¾º»ÈF· 2ü}[üI,sW/ä8®˜ªöKDŸÎkŠjzH¬,(ny¦ß”8uóÚq.^PrͪßCý—ð¤MÔ`)ì fœyô,XüOÒ¡
ïÈÓ×þ¤$Ò2"ðTö¾aû`’†Ä®ùÒ{ŸŽ<>:=


View file

@ -1,5 +1,5 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 vT7ExA G9mqOZiAvq+ot4OUevoxvNPIkgWgS8KqMY76uGsxeGs -> ssh-ed25519 vT7ExA Z8248Zxd0dGjx/YtU3cVKwuKMDRaHQpo6d21bwSOWz0
AMEwoZoFc+axirDc5q+FM3e76IedkxblC3vVqUjmPL8 /7PxJCz7yfuGuBWioDQMizW9+tL7Ku7JEB2h6aG4vmE
--- oXGSsFKfJRPvcU1X3zHN7M6vd0IxBpNowyh4sPesq3A --- xEBearw/OGRugS23zBrNGj5zKY/bNsot+UQOcCEATWA
¢¡i3<><18>¥Ÿûôc—ÿòØMÄTN0—‰}r"Зs˜Œ§ö<>OrP˜®ÃîFP`Q•˜¯<º%å:7ø3ç ƒœ!«pÕ%~¢)6- Hy*îeÀŸ¡Ÿ» º âgã ¨‡pÒXÑ·Ók÷Ý Ùˆ¿èmé4bÖùn”ŸÀÙÁª¬êx6díe

View file

@ -1,5 +1,6 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 qM6TYg oaTrhtYhEl2Za2fhNt0BgnjXPCkzo1Or9jsLLCnJhzA -> ssh-ed25519 qM6TYg XJWJcqVabkHFOrbsNTS6+jc/pQ1a4D8lZkObT8BZwiE
Wk99OfMEXXG+cV1LEvC9wf0GeVgT1Z2GA0AtLYCRKD4 DgFVt1+01MNlPm898/qnC0wGbs6eEsLcHpyANA5tpsA
--- 4U4dwN+tJ2LFpIjxEaoZ6HHV5QQU4kr0r0pDXKKcTgE --- VhhquCcml82lpKjXLecBoCz/2CHNl2S9htU2iIWfvyY
NäÖ]èn<C3A8>Ý?óã€àð‚ý¹!ý|!ƒ³:Öú»ÐÁMlØ*Èý Ü'÷×?E ØùôM@Ér_iÎvo:Niõlk<13>¾8S(ÿ:øÖŠÇR/0^xiÛ[x ~<>'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"; import fs from "node:fs/promises";
const path = `${import.meta.dirname}/nixpkgs.json`; const path = `${import.meta.dirname}/nixpkgs.json`;
const nixpkgs = JSON.parse(await fs.readFile(path)); const channels = JSON.parse(await fs.readFile(path));
const res = await fetch( for (const [channel, nixpkgs] of Object.entries(channels)) {
`https://api.github.com/repos/NixOS/nixpkgs/commits/${nixpkgs.channel}` const res = await fetch(
); `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(
const body = await res.json(); `get commit for ${channel}: ${res.status} - ${await res.text()}`
);
if (body.sha !== nixpkgs.commit) { }
const body = await res.json();
if (body.sha !== nixpkgs.commit) {
nixpkgs.commit = body.sha; nixpkgs.commit = body.sha;
nixpkgs.lastUpdated = new Date().toISOString(); 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.

Binary file not shown.

Binary file not shown.