From f1f2043fbaf8ef6c3990ea81ca4a80f2c2541050 Mon Sep 17 00:00:00 2001 From: Nettika Date: Wed, 15 Oct 2025 14:26:28 -0700 Subject: [PATCH 1/6] WIP --- hosts/astral/default.nix | 6 ++ hosts/astral/links.nix | 18 ++-- hosts/astral/radicale.nix | 100 ++++++++++++++++++ hosts/astral/secrets/radicale-htpasswd | 7 ++ .../astral/secrets/radicale-sync-secrets.fish | 7 ++ secrets.nix | 3 + 6 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 hosts/astral/radicale.nix create mode 100644 hosts/astral/secrets/radicale-htpasswd create mode 100644 hosts/astral/secrets/radicale-sync-secrets.fish diff --git a/hosts/astral/default.nix b/hosts/astral/default.nix index cc03584..c600557 100644 --- a/hosts/astral/default.nix +++ b/hosts/astral/default.nix @@ -7,6 +7,7 @@ agenix.nixosModules.default ./forgejo.nix ./links.nix + ./radicale.nix ./vaultwarden.nix ]; @@ -35,6 +36,11 @@ services.caddy = { enable = true; + package = pkgs.caddy.withPlugins { + plugins = + [ "github.com/abiosoft/caddy-exec@v0.0.0-20240914124740-521d8736cb4d" ]; + hash = "sha256-ef6/x7wjKk0axjX6MfAzTTwPM2FTOTSSyI9zLLrczV0="; + }; virtualHosts = { "astral.leaf.ninja".extraConfig = '' respond "astral is online" diff --git a/hosts/astral/links.nix b/hosts/astral/links.nix index eb70571..bbf7a7e 100644 --- a/hosts/astral/links.nix +++ b/hosts/astral/links.nix @@ -22,15 +22,15 @@ let httpd.serve_forever() ''; in { - systemd.services.links-webhook = { - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - serviceConfig = { - Type = "simple"; - ExecStart = "${pkgs.python3}/bin/python3 ${webhookHandler}"; - Restart = "always"; - }; - }; + # systemd.services.links-webhook = { + # wantedBy = [ "multi-user.target" ]; + # after = [ "network.target" ]; + # serviceConfig = { + # Type = "simple"; + # ExecStart = "${pkgs.python3}/bin/python3 ${webhookHandler}"; + # Restart = "always"; + # }; + # }; services.caddy.virtualHosts.${domain}.extraConfig = '' root * ${root} diff --git a/hosts/astral/radicale.nix b/hosts/astral/radicale.nix new file mode 100644 index 0000000..79527b7 --- /dev/null +++ b/hosts/astral/radicale.nix @@ -0,0 +1,100 @@ +{ pkgs, config, lib, ... }: +let domain = "radicale.leaf.ninja"; +in { + users.users.radicale-sync = { + isSystemUser = true; + group = "radicale-sync"; + }; + + users.groups.radicale-sync = { }; + + age.secrets = { + radicale-htpasswd = { + file = ./secrets/radicale-htpasswd; + mode = "400"; + owner = "radicale"; + }; + radicale-sync-secrets = { + file = ./secrets/radicale-sync-secrets.fish; + mode = "400"; + owner = "radicale-sync"; + }; + }; + + services.radicale = { + enable = true; + settings = { + server.hosts = [ "localhost:5232" ]; + auth = { + type = "htpasswd"; + htpasswd_filename = config.age.secrets.radicale-htpasswd.path; + htpasswd_encryption = "plain"; + }; + }; + rights = { + root = { + user = ".+"; + collection = ""; + permissions = "R"; + }; + principal = { + user = ".+"; + collection = "{user}"; + permissions = "RW"; + }; + calendars = { + user = ".+"; + collection = "{user}/[^/]+"; + permissions = "rw"; + }; + remote = { + user = ".+"; + collection = "remote/.+"; + permissions = "r"; + }; + }; + }; + + services.caddy.virtualHosts.${domain}.extraConfig = '' + reverse_proxy localhost:5232 + ''; + + systemd.timers.radicale-sync = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnBootSec = "5min"; + OnCalendar = "*-*-* *:0/4:00"; + }; + }; + + systemd.services.radicale-sync = let + radicaleUrl = "http://localhost:5232"; + remoteCollections = [{ + collection = "devhack"; + url = "https://devhack.net/calendar.ics"; + }]; + remoteCollectionsFile = pkgs.writers.writeText "remote-collections" + (lib.concatMapStringsSep "\n" + ({ collection, url }: "${collection} ${url}") remoteCollections); + syncScript = pkgs.writers.writeFish "sync.fish" '' + alias curl ${lib.getExe pkgs.curl} + source ${config.age.secrets.radicale-sync-secrets.path} + while read -l name url + set tempfile (mktemp) + curl -sf $url -o $tempfile + curl -sf -u "remote:$password" \ + -X PUT "${radicaleUrl}/remote/$name" \ + -H 'Content-Type: text/calendar; charset=utf-8' \ + --data-binary @$tempfile + echo "Uploaded $name" + end < ${remoteCollectionsFile} + ''; + in { + serviceConfig = { + Type = "oneshot"; + User = "radicale-sync"; + Group = "radicale-sync"; + ExecStart = syncScript; + }; + }; +} diff --git a/hosts/astral/secrets/radicale-htpasswd b/hosts/astral/secrets/radicale-htpasswd new file mode 100644 index 0000000..c2a396c --- /dev/null +++ b/hosts/astral/secrets/radicale-htpasswd @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 f+PJrQ iGtaCi4amFijPCydakWm6qo6eYPiRHp5Rrr7TpnRLxo +MiFAmPkU9gDBYdNqGA9CdYike2n780nQ7o8nAZ0GGtE +-> ssh-ed25519 nz/vnw FiTGU3HNakVR1VNVyUPdiu+WhEMf9t/ONBgoQRILExA +TjDSkxA6z1ovqu2mA0G1UY1k29f35HFHDZQWA90XSzM +--- WK1KjkiLaqH1jN3zIgetSHEe5xEddBYjlt3Qu5Z/Bcg +Ϲ%slma@Oԧ> K<(Co6hӖLɠ(_hR2Ȋ"znp/MW}LNe%C̺7?#j3ҋG?ÁX{V%Ym lf \ No newline at end of file diff --git a/hosts/astral/secrets/radicale-sync-secrets.fish b/hosts/astral/secrets/radicale-sync-secrets.fish new file mode 100644 index 0000000..3cc4d6d --- /dev/null +++ b/hosts/astral/secrets/radicale-sync-secrets.fish @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 f+PJrQ f+4sexgdKNmdc7DQe3h6v8CveCiHN+dLFX0vdMzBOBQ +/nSP3nPNdxKjOUIn0xzH/ht4QC68aMxCLplP8kIeKr4 +-> ssh-ed25519 nz/vnw ejIzeXNfCDxPhho7426oR6WQWlJxDprp1j90lgCGnmM +yaq9bU726x5xtHhK7ZQc1Onlg681cSQsSxSCRU/GBAU +--- UT7B9uDmsNJwTLroGj+JQdKbsOHhgSnnlhMru4tY7/M +uK Ti,M`S4~6ϒjҫ9$H0d?pXV%IJؘ "ҾdWO \ No newline at end of file diff --git a/secrets.nix b/secrets.nix index 58ceb27..7956f39 100644 --- a/secrets.nix +++ b/secrets.nix @@ -13,4 +13,7 @@ in { "hosts/astral/secrets/vaultwarden-env.age".publicKeys = [ marauder astral ]; "hosts/astral/secrets/forgejo-mailer-password.age".publicKeys = [ marauder astral ]; + "hosts/astral/secrets/radicale-htpasswd".publicKeys = [ marauder astral ]; + "hosts/astral/secrets/radicale-sync-secrets.fish".publicKeys = + [ marauder astral ]; } From 01015c19b9a12099173504e8bc7aa7a1dd553d28 Mon Sep 17 00:00:00 2001 From: Nettika Date: Wed, 15 Oct 2025 14:29:17 -0700 Subject: [PATCH 2/6] Setup radicale on astral --- hosts/astral/default.nix | 1 + hosts/astral/radicale.nix | 25 +++++++++++++++++++++++++ hosts/astral/secrets/radicale-htpasswd | 9 +++++++++ secrets.nix | 1 + 4 files changed, 36 insertions(+) create mode 100644 hosts/astral/radicale.nix create mode 100644 hosts/astral/secrets/radicale-htpasswd diff --git a/hosts/astral/default.nix b/hosts/astral/default.nix index cc03584..3ad498a 100644 --- a/hosts/astral/default.nix +++ b/hosts/astral/default.nix @@ -7,6 +7,7 @@ agenix.nixosModules.default ./forgejo.nix ./links.nix + ./radicale.nix ./vaultwarden.nix ]; diff --git a/hosts/astral/radicale.nix b/hosts/astral/radicale.nix new file mode 100644 index 0000000..68d3c08 --- /dev/null +++ b/hosts/astral/radicale.nix @@ -0,0 +1,25 @@ +{ config, ... }: +let domain = "radicale.leaf.ninja"; +in { + age.secrets.radicale-htpasswd = { + file = ./secrets/radicale-htpasswd; + mode = "400"; + owner = "radicale"; + }; + + services.radicale = { + enable = true; + settings = { + server.hosts = [ "localhost:5232" ]; + auth = { + type = "htpasswd"; + htpasswd_filename = config.age.secrets.radicale-htpasswd.path; + htpasswd_encryption = "plain"; + }; + }; + }; + + services.caddy.virtualHosts.${domain}.extraConfig = '' + reverse_proxy localhost:5232 + ''; +} diff --git a/hosts/astral/secrets/radicale-htpasswd b/hosts/astral/secrets/radicale-htpasswd new file mode 100644 index 0000000..36c140f --- /dev/null +++ b/hosts/astral/secrets/radicale-htpasswd @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 f+PJrQ pKqLrqz0R7kAzNQZ3ChRsoWa63JEN2H2KHtGguF5nSc +6Mk1qDWKx26jPdEzaVMh0vgUeVWjAGcmIPpvSU8BFNE +-> ssh-ed25519 nz/vnw 0PuVNQ97Qa6iCk4pPf34lgS1aPb4CeDB4Qclk5F24T4 +OwJOYMTlTY9+Pj/BwG09z4q2/QViii710Kh3xPU5FRA +--- mSdutlC3gFq8lDjeOGqi361i+DUI1Yg6Bpl7hCfznJA +tQ/rNeKeѥ~ן{_o +y_ܭ}ûP*W5F.ECZ#; +liԧ*]yT \ No newline at end of file diff --git a/secrets.nix b/secrets.nix index 58ceb27..33a040c 100644 --- a/secrets.nix +++ b/secrets.nix @@ -13,4 +13,5 @@ in { "hosts/astral/secrets/vaultwarden-env.age".publicKeys = [ marauder astral ]; "hosts/astral/secrets/forgejo-mailer-password.age".publicKeys = [ marauder astral ]; + "hosts/astral/secrets/radicale-htpasswd".publicKeys = [ marauder astral ]; } From 39f73ef2f21e4d2b578da80524ac95b49b294aba Mon Sep 17 00:00:00 2001 From: Nettika Date: Wed, 15 Oct 2025 17:43:36 -0700 Subject: [PATCH 3/6] Use caddy-exec to handling Forgejo webhooks on astral --- hosts/astral/default.nix | 5 +++++ hosts/astral/links.nix | 48 +++++++++++++--------------------------- 2 files changed, 20 insertions(+), 33 deletions(-) diff --git a/hosts/astral/default.nix b/hosts/astral/default.nix index 3ad498a..c600557 100644 --- a/hosts/astral/default.nix +++ b/hosts/astral/default.nix @@ -36,6 +36,11 @@ services.caddy = { enable = true; + package = pkgs.caddy.withPlugins { + plugins = + [ "github.com/abiosoft/caddy-exec@v0.0.0-20240914124740-521d8736cb4d" ]; + hash = "sha256-ef6/x7wjKk0axjX6MfAzTTwPM2FTOTSSyI9zLLrczV0="; + }; virtualHosts = { "astral.leaf.ninja".extraConfig = '' respond "astral is online" diff --git a/hosts/astral/links.nix b/hosts/astral/links.nix index eb70571..fe836be 100644 --- a/hosts/astral/links.nix +++ b/hosts/astral/links.nix @@ -1,39 +1,21 @@ -{ pkgs, ... }: +{ pkgs, lib, ... }: let domain = "nettika.leaf.ninja"; root = "/srv/links"; - webhookHandler = pkgs.writeScript "webhook-handler.py" '' - #!${pkgs.python3}/bin/python3 - - import http.server - import socketserver - import subprocess - import os - - class WebhookHandler(http.server.SimpleHTTPRequestHandler): - def do_POST(self): - os.chdir('${root}') - subprocess.run(['${pkgs.git}/bin/git', 'pull'], check=True) - self.send_response(200) - self.end_headers() - self.wfile.write(b'OK') - - with socketserver.TCPServer(("127.0.0.1", 8081), WebhookHandler) as httpd: - httpd.serve_forever() - ''; in { - systemd.services.links-webhook = { - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - serviceConfig = { - Type = "simple"; - ExecStart = "${pkgs.python3}/bin/python3 ${webhookHandler}"; - Restart = "always"; - }; + services.caddy.virtualHosts = { + ${domain}.extraConfig = '' + root * ${root} + file_server + ''; + "http://localhost:8081".extraConfig = let git = lib.getExe pkgs.git; + in '' + route { + exec { + command ${git} pull --rebase + directory ${root} + } + } + ''; }; - - services.caddy.virtualHosts.${domain}.extraConfig = '' - root * ${root} - file_server - ''; } From d6ef606632cbdf45a49a665b3232b9112a42afb9 Mon Sep 17 00:00:00 2001 From: Nettika Date: Wed, 15 Oct 2025 22:05:17 -0700 Subject: [PATCH 4/6] Remove winboat from marauder --- flake.lock | 37 +------------------------------------ flake.nix | 1 - hosts/default.nix | 4 ++-- hosts/marauder/default.nix | 3 +-- 4 files changed, 4 insertions(+), 41 deletions(-) diff --git a/flake.lock b/flake.lock index c14689d..dc58554 100755 --- a/flake.lock +++ b/flake.lock @@ -98,22 +98,6 @@ "type": "github" } }, - "nixpkgs_2": { - "locked": { - "lastModified": 1758690382, - "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "e643668fd71b949c53f8626614b21ff71a07379d", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "phps": { "inputs": { "flake-compat": "flake-compat", @@ -140,8 +124,7 @@ "inputs": { "agenix": "agenix", "nixpkgs": "nixpkgs", - "phps": "phps", - "winboat": "winboat" + "phps": "phps" } }, "systems": { @@ -191,24 +174,6 @@ "repo": "flake-utils", "type": "github" } - }, - "winboat": { - "inputs": { - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1760183562, - "narHash": "sha256-lauscAI61WXjLTuGiRDMUAEeTqvOTSWhRoHDaor5sfE=", - "owner": "TibixDev", - "repo": "winboat", - "rev": "ae60de6c2cba7a2001fef1027d5c2e06614e6904", - "type": "github" - }, - "original": { - "owner": "TibixDev", - "repo": "winboat", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 19932c2..f8c151e 100755 --- a/flake.nix +++ b/flake.nix @@ -11,7 +11,6 @@ url = "github:ryantm/agenix"; inputs.nixpkgs.follows = "nixpkgs"; }; - winboat.url = "github:TibixDev/winboat"; }; outputs = inputs: { diff --git a/hosts/default.nix b/hosts/default.nix index 02b0866..1b52d15 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -1,4 +1,4 @@ -{ self, nixpkgs, phps, agenix, winboat }: +{ self, nixpkgs, phps, agenix }: let baseSpecialArgs = { inherit (self) nixosModules; @@ -11,7 +11,7 @@ in { marauder = nixosSystem { system = "x86_64-linux"; modules = [ ./marauder ]; - specialArgs = { inherit phps winboat; }; + specialArgs = { inherit phps; }; }; astral = nixosSystem { system = "x86_64-linux"; diff --git a/hosts/marauder/default.nix b/hosts/marauder/default.nix index cf47dd2..630416e 100755 --- a/hosts/marauder/default.nix +++ b/hosts/marauder/default.nix @@ -1,4 +1,4 @@ -{ pkgs, nixosModules, phps, agenix, winboat, ... }: +{ pkgs, nixosModules, phps, agenix, ... }: let fortune = pkgs.writeShellScript "cgi" '' echo "Content-type: text/html" @@ -164,7 +164,6 @@ in { pkg-config prismlauncher system-config-printer - winboat.packages.x86_64-linux.winboat ]; programs.git = { From 5e6167ece8f96295a74da5a047eec8686563cc36 Mon Sep 17 00:00:00 2001 From: Nettika Date: Wed, 15 Oct 2025 22:07:26 -0700 Subject: [PATCH 5/6] Add various apps to marauder --- hosts/marauder/default.nix | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/hosts/marauder/default.nix b/hosts/marauder/default.nix index 630416e..e6639d7 100755 --- a/hosts/marauder/default.nix +++ b/hosts/marauder/default.nix @@ -102,7 +102,7 @@ in { environment.systemPackages = with pkgs; [ # Chat clients discord - element-desktop + cinny-desktop signal-desktop slack telegram-desktop @@ -119,6 +119,7 @@ in { krita openscad-unstable orca-slicer + plasticity # Multimedia ffcheck @@ -132,6 +133,8 @@ in { # Dev Tools fossil + just + kondo nixd nixfmt-classic nixpkgs-fmt @@ -149,7 +152,6 @@ in { dig htop jq - just unzip zip @@ -157,13 +159,17 @@ in { mullvad-vpn qbittorrent + # Utility Apps + baobab + gparted + system-config-printer + # Misc gcc intiface-central openssl pkg-config prismlauncher - system-config-printer ]; programs.git = { From 55a68c21dab9722f3f70f169c5b5f549787e5268 Mon Sep 17 00:00:00 2001 From: Nettika Date: Thu, 16 Oct 2025 07:21:05 -0700 Subject: [PATCH 6/6] Enable arch64 emulation on marauder --- hosts/marauder/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/hosts/marauder/default.nix b/hosts/marauder/default.nix index e6639d7..ab09178 100755 --- a/hosts/marauder/default.nix +++ b/hosts/marauder/default.nix @@ -76,6 +76,7 @@ in { }; kernelModules = [ "kvm-amd" ]; kernelParams = [ "amd_pstate=active" ]; + binfmt.emulatedSystems = [ "aarch64-linux" ]; }; hardware = {