From 685d438d5cee9ed3580292903d4701daa39a5050 Mon Sep 17 00:00:00 2001 From: Kieran Klukas Date: Mon, 10 Aug 2026 22:06:50 -0400 Subject: [PATCH] chore: format --- machines/prattle/default.nix | 4 +- machines/terebithia/default.nix | 5 +- modules/nixos/services/lard.nix | 36 +++-- modules/nixos/services/tangled.nix | 252 +++++++++++++++-------------- 4 files changed, 155 insertions(+), 142 deletions(-) diff --git a/machines/prattle/default.nix b/machines/prattle/default.nix index e2b3306..bfc93a8 100644 --- a/machines/prattle/default.nix +++ b/machines/prattle/default.nix @@ -355,7 +355,9 @@ systemd.tmpfiles.rules = [ # spindle microVM image (spindle resolves /spec.json under imageDir) "d /var/lib/spindle/images 0755 root root -" - "L+ /var/lib/spindle/images/nixos - - - - ${inputs.tangled.packages.${pkgs.system}.spindle-nixos-image}" + "L+ /var/lib/spindle/images/nixos - - - - ${ + inputs.tangled.packages.${pkgs.system}.spindle-nixos-image + }" "d /storage/media/movies 2775 root media -" "d /storage/media/tv 2775 root media -" "d /storage/torrents 2775 root media -" diff --git a/machines/terebithia/default.nix b/machines/terebithia/default.nix index 3ba8c13..8a8e3a0 100644 --- a/machines/terebithia/default.nix +++ b/machines/terebithia/default.nix @@ -542,7 +542,10 @@ domain = "lard.dunkirk.sh"; secretsFile = config.age.secrets.lard.path; healthUrl = "https://lard.dunkirk.sh/healthz"; - allowedClientIds = [ "ikc_NEil8GK01UX2O9AvbcDrv" "ikc_cskXitSS6XFSDzvyq3NBA"]; # lard, kloe + allowedClientIds = [ + "ikc_NEil8GK01UX2O9AvbcDrv" + "ikc_cskXitSS6XFSDzvyq3NBA" + ]; # lard, kloe allowedUsers = [ "https://dunkirk.sh/" ]; collectorClientId = "ikc_NEil8GK01UX2O9AvbcDrv"; }; diff --git a/modules/nixos/services/lard.nix b/modules/nixos/services/lard.nix index ed02938..290b70f 100644 --- a/modules/nixos/services/lard.nix +++ b/modules/nixos/services/lard.nix @@ -96,20 +96,22 @@ let ); in { - atelier.services.lard.environment = storage // { - LARD_ADDR = ":${toString cfg.port}"; - LARD_AUTH = cfg.authMode; - LARD_AUTH_SERVER = cfg.authServer; - LARD_PUBLIC_URL = "https://${cfg.domain}"; - LARD_OAUTH_CLIENT_IDS = lib.concatStringsSep "," cfg.allowedClientIds; - LARD_OAUTH_USERS = lib.concatStringsSep "," cfg.allowedUsers; - } - // lib.optionalAttrs (cfg.collectorClientId != "") { - LARD_COLLECTOR_CLIENT_ID = cfg.collectorClientId; - } - // lib.optionalAttrs (cfg.primaryUser != "") { - LARD_PRIMARY_USER = cfg.primaryUser; - }; + atelier.services.lard.environment = + storage + // { + LARD_ADDR = ":${toString cfg.port}"; + LARD_AUTH = cfg.authMode; + LARD_AUTH_SERVER = cfg.authServer; + LARD_PUBLIC_URL = "https://${cfg.domain}"; + LARD_OAUTH_CLIENT_IDS = lib.concatStringsSep "," cfg.allowedClientIds; + LARD_OAUTH_USERS = lib.concatStringsSep "," cfg.allowedUsers; + } + // lib.optionalAttrs (cfg.collectorClientId != "") { + LARD_COLLECTOR_CLIENT_ID = cfg.collectorClientId; + } + // lib.optionalAttrs (cfg.primaryUser != "") { + LARD_PRIMARY_USER = cfg.primaryUser; + }; assertions = [ { @@ -122,7 +124,11 @@ let ''; } { - assertion = !cfg.multiUser || cfg.primaryUser == "" || lib.elem cfg.primaryUser cfg.allowedUsers || cfg.allowedUsers == [ ]; + assertion = + !cfg.multiUser + || cfg.primaryUser == "" + || lib.elem cfg.primaryUser cfg.allowedUsers + || cfg.allowedUsers == [ ]; message = '' atelier.services.lard: primaryUser "${cfg.primaryUser}" is not in allowedUsers, so the tenant that inherits the pre-multi-user diff --git a/modules/nixos/services/tangled.nix b/modules/nixos/services/tangled.nix index 631eba1..6167e48 100644 --- a/modules/nixos/services/tangled.nix +++ b/modules/nixos/services/tangled.nix @@ -100,141 +100,143 @@ in # knot and spindle are gated independently so a machine can run just one # (e.g. spindle on a KVM host, knot elsewhere). - config = lib.mkIf cfg.enable (lib.mkMerge [ - (lib.mkIf cfg.spindle.enable { - services.tangled.spindle = { - enable = true; - server = { - owner = cfg.owner; - hostname = cfg.spindle.hostname; - listenAddr = "${cfg.spindle.bindAddr}:${toString cfg.spindle.port}"; - maxJobCount = cfg.spindle.maxJobCount; - }; - - pipelines = { - # No S3 log archival: only the bucket name can be set here (creds, - # region, endpoint would come from AWS_* env we don't provide), so - # uploads just error out. Logs are written to /var/log/spindle and - # the UI streams them from there, so an empty bucket disables the - # broken S3 path cleanly (NewS3 short-circuits on ""). - logBucket = ""; - - # Aggregate ceilings so a workflow requesting a larger-than-default VM - # (or a burst) can't exceed the job-count budget. Mirror the nixos - # image spec: 4 GiB / 2 vCPU per microVM. - microvm.limits.total = { - memoryMiB = cfg.spindle.maxJobCount * 4096; - vcpus = cfg.spindle.maxJobCount * 2; + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + (lib.mkIf cfg.spindle.enable { + services.tangled.spindle = { + enable = true; + server = { + owner = cfg.owner; + hostname = cfg.spindle.hostname; + listenAddr = "${cfg.spindle.bindAddr}:${toString cfg.spindle.port}"; + maxJobCount = cfg.spindle.maxJobCount; }; - # Keep nixery workflow concurrency in line with the job budget too - # (6 GiB per container; the default of 8 could otherwise over-commit). - nixery.maxConcurrentWorkflows = cfg.spindle.maxJobCount; + pipelines = { + # No S3 log archival: only the bucket name can be set here (creds, + # region, endpoint would come from AWS_* env we don't provide), so + # uploads just error out. Logs are written to /var/log/spindle and + # the UI streams them from there, so an empty bucket disables the + # broken S3 path cleanly (NewS3 short-circuits on ""). + logBucket = ""; + + # Aggregate ceilings so a workflow requesting a larger-than-default VM + # (or a burst) can't exceed the job-count budget. Mirror the nixos + # image spec: 4 GiB / 2 vCPU per microVM. + microvm.limits.total = { + memoryMiB = cfg.spindle.maxJobCount * 4096; + vcpus = cfg.spindle.maxJobCount * 2; + }; + + # Keep nixery workflow concurrency in line with the job budget too + # (6 GiB per container; the default of 8 could otherwise over-commit). + nixery.maxConcurrentWorkflows = cfg.spindle.maxJobCount; + }; }; - }; - atelier.backup.services.spindle = { - paths = [ "/var/lib/spindle" ]; - exclude = [ - "*.log" - "cache/*" - ]; - # Uses SQLite, stop before backup - preBackup = "systemctl stop spindle"; - postBackup = "systemctl start spindle"; - }; + atelier.backup.services.spindle = { + paths = [ "/var/lib/spindle" ]; + exclude = [ + "*.log" + "cache/*" + ]; + # Uses SQLite, stop before backup + preBackup = "systemctl stop spindle"; + postBackup = "systemctl start spindle"; + }; - # The public endpoint (hostname over HTTPS) is served by whichever host - # fronts the internet, reverse-proxying to this spindle over Tailscale. - # That host is often not the spindle host (e.g. a NAT'd KVM box), so the - # caddy vhost lives there, not here. - }) - - (lib.mkIf cfg.knot.enable { - services.tangled.knot = { - enable = true; - server = { - owner = cfg.owner; - hostname = cfg.knot.hostname; - listenAddr = "127.0.0.1:${toString cfg.knot.port}"; - internalListenAddr = "127.0.0.1:${toString cfg.knot.internalListenAddr}"; + # The public endpoint (hostname over HTTPS) is served by whichever host + # fronts the internet, reverse-proxying to this spindle over Tailscale. + # That host is often not the spindle host (e.g. a NAT'd KVM box), so the + # caddy vhost lives there, not here. + }) + + (lib.mkIf cfg.knot.enable { + services.tangled.knot = { + enable = true; + server = { + owner = cfg.owner; + hostname = cfg.knot.hostname; + listenAddr = "127.0.0.1:${toString cfg.knot.port}"; + internalListenAddr = "127.0.0.1:${toString cfg.knot.internalListenAddr}"; + }; + motd = cfg.knot.motd; }; - motd = cfg.knot.motd; - }; - # Backup configuration for the knot's git repositories - atelier.backup.services.knot = { - paths = [ "/home/git" ]; # Git repositories managed by knot - exclude = [ "*.log" ]; - # Uses SQLite, stop before backup - preBackup = "systemctl stop knot"; - postBackup = "systemctl start knot"; - }; + # Backup configuration for the knot's git repositories + atelier.backup.services.knot = { + paths = [ "/home/git" ]; # Git repositories managed by knot + exclude = [ "*.log" ]; + # Uses SQLite, stop before backup + preBackup = "systemctl stop knot"; + postBackup = "systemctl start knot"; + }; - # Prevent knot's memory leak from triggering system-wide OOM - # MemoryMax: hard kill at 4G (process is unresponsive well before 8G) - # MemoryHigh: throttle at 3G to slow growth - # MemorySwapMax: prevent swap thrashing entirely - systemd.services.knot.serviceConfig = { - MemoryMax = "8G"; - MemoryHigh = "6G"; - MemorySwapMax = "0"; - }; + # Prevent knot's memory leak from triggering system-wide OOM + # MemoryMax: hard kill at 4G (process is unresponsive well before 8G) + # MemoryHigh: throttle at 3G to slow growth + # MemorySwapMax: prevent swap thrashing entirely + systemd.services.knot.serviceConfig = { + MemoryMax = "8G"; + MemoryHigh = "6G"; + MemorySwapMax = "0"; + }; - # Proactively restart knot every 4 hours to prevent memory bloat - # from accumulating. The RepoCompare endpoint leaks ~1.5GB/hour under - # normal traffic, so 4h keeps it well under the 4G hard limit. - systemd.timers.knot-restart = { - wantedBy = [ "timers.target" ]; - timerConfig = { - OnCalendar = "*-*-* 00/4:00:00"; - Persistent = true; + # Proactively restart knot every 4 hours to prevent memory bloat + # from accumulating. The RepoCompare endpoint leaks ~1.5GB/hour under + # normal traffic, so 4h keeps it well under the 4G hard limit. + systemd.timers.knot-restart = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = "*-*-* 00/4:00:00"; + Persistent = true; + }; + }; + systemd.services.knot-restart = { + serviceConfig.Type = "oneshot"; + script = "${config.systemd.package}/bin/systemctl restart knot"; }; - }; - systemd.services.knot-restart = { - serviceConfig.Type = "oneshot"; - script = "${config.systemd.package}/bin/systemctl restart knot"; - }; - # Fix race condition: chown -R fails if SQLite WAL temp files (-wal, -shm) - # vanish during the pre-start script, causing the service to fail to start - systemd.services.knot.preStart = lib.mkForce '' - mkdir -p "/home/git" - chown -R git:git "/home/git" || true - - mkdir -p "/home/git/.config/git" - cat > "/home/git/.config/git/config" << EOF - [user] - name = Tangled - email = noreply@tangled.org - [receive] - advertisePushOptions = true - [uploadpack] - allowFilter = true - allowReachableSHA1InWant = true - EOF - printf "🧶 welcome to kieran's knot!\n" > /home/git/motd - chown -R git:git "/home/git" || true - ''; - - atelier.services.knot-sync = { - enable = true; - ownerDid = cfg.owner; - secretsFile = cfg.knot.syncSecretsFile; - }; + # Fix race condition: chown -R fails if SQLite WAL temp files (-wal, -shm) + # vanish during the pre-start script, causing the service to fail to start + systemd.services.knot.preStart = lib.mkForce '' + mkdir -p "/home/git" + chown -R git:git "/home/git" || true + + mkdir -p "/home/git/.config/git" + cat > "/home/git/.config/git/config" << EOF + [user] + name = Tangled + email = noreply@tangled.org + [receive] + advertisePushOptions = true + [uploadpack] + allowFilter = true + allowReachableSHA1InWant = true + EOF + printf "🧶 welcome to kieran's knot!\n" > /home/git/motd + chown -R git:git "/home/git" || true + ''; - services.caddy.virtualHosts."${cfg.knot.hostname}".extraConfig = '' - tls { - dns cloudflare {env.CLOUDFLARE_API_TOKEN} - } - header { - Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" - } - reverse_proxy localhost:${toString cfg.knot.port} { - header_up X-Forwarded-Proto {scheme} - header_up X-Forwarded-For {remote} - } - ''; - }) - ]); + atelier.services.knot-sync = { + enable = true; + ownerDid = cfg.owner; + secretsFile = cfg.knot.syncSecretsFile; + }; + + services.caddy.virtualHosts."${cfg.knot.hostname}".extraConfig = '' + tls { + dns cloudflare {env.CLOUDFLARE_API_TOKEN} + } + header { + Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + } + reverse_proxy localhost:${toString cfg.knot.port} { + header_up X-Forwarded-Proto {scheme} + header_up X-Forwarded-For {remote} + } + ''; + }) + ] + ); } -- 2.51.2