a more proper nixos module for the tangled knotserver

fix: compat with latest @tangled.sh/core

+10
changelog.md
··· 1 + # changelog 2 + 3 + ## 2025-06-23 4 + 5 + this update fixes usage with newer `@tangled.sh/core` revisions. 6 + 7 + - replaced wrapped packages with just a wrapped keyfetch binary 8 + - added `cfg.openFirewall` option to automatically open firewall ports (currently ssh only). 9 + - reject module usage with old `@tangled.sh/core` revisions. 10 + - (**tests**) also test-run the wrapped `keyfetch` binary
+66 -27
flake.lock
··· 33 33 "url": "https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js" 34 34 } 35 35 }, 36 - "ia-fonts-src": { 36 + "htmx-ws-src": { 37 37 "flake": false, 38 38 "locked": { 39 - "lastModified": 1686932517, 40 - "narHash": "sha256-2T165nFfCzO65/PIHauJA//S+zug5nUwPcg8NUEydfc=", 41 - "owner": "iaolo", 42 - "repo": "iA-Fonts", 43 - "rev": "f32c04c3058a75d7ce28919ce70fe8800817491b", 44 - "type": "github" 39 + "narHash": "sha256-XbUFiv94ZPB6VVULoTWOsje5Gq1I+IT72lMc4CpUYrY=", 40 + "type": "file", 41 + "url": "https://unpkg.com/htmx.org@2.0.4/dist/ext/ws.js" 42 + }, 43 + "original": { 44 + "type": "file", 45 + "url": "https://unpkg.com/htmx.org@2.0.4/dist/ext/ws.js" 46 + } 47 + }, 48 + "ibm-plex-mono-src": { 49 + "flake": false, 50 + "locked": { 51 + "lastModified": 1731402384, 52 + "narHash": "sha256-OwUmrPfEehLDz0fl2ChYLK8FQM2p0G1+EMrGsYEq+6g=", 53 + "type": "tarball", 54 + "url": "https://github.com/IBM/plex/releases/download/@ibm/plex-mono@1.1.0/ibm-plex-mono.zip" 45 55 }, 46 56 "original": { 47 - "owner": "iaolo", 48 - "repo": "iA-Fonts", 49 - "type": "github" 57 + "type": "tarball", 58 + "url": "https://github.com/IBM/plex/releases/download/@ibm/plex-mono@1.1.0/ibm-plex-mono.zip" 50 59 } 51 60 }, 52 61 "indigo": { 53 62 "flake": false, 54 63 "locked": { 55 - "lastModified": 1738491661, 56 - "narHash": "sha256-+njDigkvjH4XmXZMog5Mp0K4x9mamHX6gSGJCZB9mE4=", 64 + "lastModified": 1745333930, 65 + "narHash": "sha256-83fIHqDE+dfnZ88HaNuwfKFO+R0RKAM1WxMfNh/Matk=", 57 66 "owner": "oppiliappan", 58 67 "repo": "indigo", 59 - "rev": "feb802f02a462ac0a6392ffc3e40b0529f0cdf71", 68 + "rev": "e4e59280737b8676611fc077a228d47b3e8e9491", 60 69 "type": "github" 61 70 }, 62 71 "original": { ··· 65 74 "type": "github" 66 75 } 67 76 }, 77 + "inter-fonts-src": { 78 + "flake": false, 79 + "locked": { 80 + "lastModified": 1731687360, 81 + "narHash": "sha256-5vdKKvHAeZi6igrfpbOdhZlDX2/5+UvzlnCQV6DdqoQ=", 82 + "type": "tarball", 83 + "url": "https://github.com/rsms/inter/releases/download/v4.1/Inter-4.1.zip" 84 + }, 85 + "original": { 86 + "type": "tarball", 87 + "url": "https://github.com/rsms/inter/releases/download/v4.1/Inter-4.1.zip" 88 + } 89 + }, 68 90 "lucide-src": { 69 91 "flake": false, 70 92 "locked": { 71 - "narHash": "sha256-5ipNSxTlQ7627lGgsyZxk7vS1sr9RkrlR8/QMj2Zg6s=", 72 - "type": "file", 73 - "url": "https://unpkg.com/lucide@0.482.0" 93 + "lastModified": 1742302029, 94 + "narHash": "sha256-OyPVtpnC4/AAmPq84Wt1r1Gcs48d9KG+UBCtZK87e9k=", 95 + "type": "tarball", 96 + "url": "https://github.com/lucide-icons/lucide/releases/download/0.483.0/lucide-icons-0.483.0.zip" 74 97 }, 75 98 "original": { 76 - "type": "file", 77 - "url": "https://unpkg.com/lucide@0.482.0" 99 + "type": "tarball", 100 + "url": "https://github.com/lucide-icons/lucide/releases/download/0.483.0/lucide-icons-0.483.0.zip" 78 101 } 79 102 }, 80 103 "nixpkgs": { 81 104 "locked": { 82 - "lastModified": 1742069588, 83 - "narHash": "sha256-C7jVfohcGzdZRF6DO+ybyG/sqpo1h6bZi9T56sxLy+k=", 105 + "lastModified": 1750506804, 106 + "narHash": "sha256-VLFNc4egNjovYVxDGyBYTrvVCgDYgENp5bVi9fPTDYc=", 84 107 "owner": "NixOS", 85 108 "repo": "nixpkgs", 86 - "rev": "c80f6a7e10b39afcc1894e02ef785b1ad0b0d7e5", 109 + "rev": "4206c4cb56751df534751b058295ea61357bbbaa", 87 110 "type": "github" 88 111 }, 89 112 "original": { ··· 99 122 "tangledCore": "tangledCore" 100 123 } 101 124 }, 125 + "sqlite-lib-src": { 126 + "flake": false, 127 + "locked": { 128 + "lastModified": 1706631843, 129 + "narHash": "sha256-bJoMjirsBjm2Qk9KPiy3yV3+8b/POlYe76/FQbciHro=", 130 + "type": "tarball", 131 + "url": "https://sqlite.org/2024/sqlite-amalgamation-3450100.zip" 132 + }, 133 + "original": { 134 + "type": "tarball", 135 + "url": "https://sqlite.org/2024/sqlite-amalgamation-3450100.zip" 136 + } 137 + }, 102 138 "tangledCore": { 103 139 "inputs": { 104 140 "gitignore": "gitignore", 105 141 "htmx-src": "htmx-src", 106 - "ia-fonts-src": "ia-fonts-src", 142 + "htmx-ws-src": "htmx-ws-src", 143 + "ibm-plex-mono-src": "ibm-plex-mono-src", 107 144 "indigo": "indigo", 145 + "inter-fonts-src": "inter-fonts-src", 108 146 "lucide-src": "lucide-src", 109 147 "nixpkgs": [ 110 148 "nixpkgs" 111 - ] 149 + ], 150 + "sqlite-lib-src": "sqlite-lib-src" 112 151 }, 113 152 "locked": { 114 - "lastModified": 1742252247, 115 - "narHash": "sha256-4P2cyFbmfi4vO+cH5Rs8T0HjyIM9my7DDehMavPQ4ms=", 153 + "lastModified": 1750580269, 154 + "narHash": "sha256-Y8WCUQYknbPPBN2nKCnL2B7rqFpIJxZ9dGB8ahmPPnA=", 116 155 "ref": "refs/heads/master", 117 - "rev": "d27004cb9772260c5a2005fe1f53f1e44884f79e", 118 - "revCount": 336, 156 + "rev": "fa3beeb9d299bbcf86440e77899773506e654e29", 157 + "revCount": 861, 119 158 "type": "git", 120 159 "url": "https://tangled.sh/@tangled.sh/core" 121 160 },
+30 -15
module.nix
··· 9 9 let 10 10 inherit (lib) 11 11 mkOption 12 + mkEnableOption 12 13 types 13 14 mkIf 14 15 optional ··· 16 17 cfg = config.services.tangled-knotserver; 17 18 tangledPkgs = tangledFlake.packages.${pkgs.system}; 18 19 19 - wrapped-packages = 20 + keyfetch-wrapped = 20 21 pkgs.runCommandCC "tangled-packages-wrapped" { nativeBuildInputs = [ pkgs.makeBinaryWrapper ]; } 21 22 '' 22 23 mkdir -p $out/bin 23 24 24 - makeBinaryWrapper ${lib.getExe' tangledPkgs.repoguard "repoguard"} $out/bin/repoguard \ 25 - --add-flags -internal-api=http://${cfg.server.internalListenAddr} 26 - # other flags are set by keyfetch 27 - 28 - makeBinaryWrapper ${lib.getExe' tangledPkgs.keyfetch "keyfetch"} $out/bin/keyfetch \ 29 - --add-flags "-repoguard-path=$out/bin/repoguard" \ 30 - --add-flags "-internal-api=http://${cfg.server.internalListenAddr}" \ 31 - --add-flags "-git-dir=${cfg.repo.scanPath}" \ 32 - --add-flags "-log-path=/var/log/knotserver/repoguard.log" 25 + makeBinaryWrapper ${lib.getExe' tangledPkgs.knot "knot"} $out/bin/keyfetch \ 26 + --add-flags "keys" \ 27 + --append-flags "-output authorized-keys" \ 28 + --append-flags "-internal-api=http://${cfg.server.internalListenAddr}" \ 29 + --append-flags "-git-dir=${cfg.repo.scanPath}" \ 30 + --append-flags "-log-path=/var/log/knotserver/repoguard.log" 33 31 ''; 34 32 35 33 in ··· 40 38 41 39 options = { 42 40 services.tangled-knotserver = { 43 - enable = mkOption { 41 + enable = mkEnableOption "a tangled knot server"; 42 + 43 + openFirewall = mkOption { 44 44 type = types.bool; 45 45 default = false; 46 - description = "Enable a tangled knotserver"; 46 + description = "Whether to automatically configure the firewall to open necessary ports."; 47 47 }; 48 48 49 49 appviewEndpoint = mkOption { ··· 70 70 description = "Git email address for git operations that requires one."; 71 71 }; 72 72 }; 73 + 74 + # TODO: should a `stateDirectory` option be added? 73 75 74 76 repo = { 75 77 scanPath = mkOption { ··· 166 168 tangled-knotserver: development mode is enabled. This is not recommended in production as signature checks are disabled. 167 169 ''; 168 170 171 + assertions = [ 172 + { 173 + assertion = tangledPkgs ? knot; 174 + message = "tangled-knotserver: your version of tangled flake is not compatible with this version of the knotserver module. please consider updating the pinned @tangled.sh/core version."; 175 + } 176 + ]; 177 + 169 178 environment.systemPackages = with pkgs; [ git ]; 170 179 171 180 users.users.${cfg.user} = { 181 + createHome = true; 172 182 home = cfg.repo.scanPath; 173 183 group = cfg.user; 174 184 isSystemUser = true; ··· 198 208 serviceConfig = { 199 209 User = cfg.user; 200 210 WorkingDirectory = cfg.repo.scanPath; 201 - ExecStart = lib.getExe' tangledPkgs.knotserver "knotserver"; 211 + ExecStart = if (tangledPkgs ? knotserver) # compat 212 + then lib.getExe' tangledPkgs.knotserver "knotserver" 213 + else "${lib.getExe' tangledPkgs.knot "knot"} server"; 202 214 Restart = "always"; 203 215 204 216 StateDirectory = mkIf (lib.hasPrefix "/var/lib/tangled-knot" cfg.repo.scanPath) "tangled-knot"; ··· 222 234 }; 223 235 224 236 services.openssh = { 225 - enable = true; 237 + enable = true; # required for the module to actually function 226 238 extraConfig = '' 227 239 Match User ${cfg.user} 228 240 AuthorizedKeysCommand ${config.security.wrapperDir}/keyfetch ··· 236 248 owner = "root"; 237 249 group = config.users.groups.${cfg.user}.name; 238 250 permissions = "u+rx,go+x"; 239 - source = lib.getExe' wrapped-packages "keyfetch"; 251 + source = lib.getExe' keyfetch-wrapped "keyfetch"; 240 252 }; 253 + 254 + # open firewall ports if configured 255 + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [22]; 241 256 }; 242 257 }
+29
readme.md
··· 19 19 - logging to `/var/log/knotserver` prevents other users from messing around with repoguard, possibly a dos by just creating `/tmp/repoguard.log`. 20 20 - these changes should not affect usage at all, just implementation details. 21 21 22 + ## usage 23 + 24 + add this flake to your inputs, then import the module to your nixos config. 25 + 26 + whilst not required, it is recommended to add the core flake and let the module flake follow that input, since i don't have all day updating this repo. 27 + 28 + ```nix 29 + { 30 + inputs = { 31 + # ...other stuff like nixpkgs 32 + tangled.url = "git+https://tangled.sh/@tangled.sh/core"; 33 + knotserver-module = { 34 + url = "git+https://tangled.sh/@soopy.moe/knotserver-module"; 35 + inputs.tangledCore.follows = "tangled"; 36 + }; 37 + }; 38 + 39 + outputs = {nixpkgs, knotserver-module, ...}: { 40 + nixosConfigurations.saturday = nixpkgs.lib.nixosSystem { 41 + modules = [ 42 + knotserver-module.nixosModules.default 43 + ./configuration.nix 44 + ]; 45 + }; 46 + }; 47 + } 48 + ``` 49 + 50 + 22 51 ## stability 23 52 24 53 this module is stable to use.
+1
test.nix
··· 21 21 machine.wait_for_unit("knotserver.service") 22 22 machine.wait_for_open_port(5555) 23 23 machine.succeed('curl -f http://127.0.0.1:5555 | grep "This is a knot server"') 24 + machine.succeed('/run/wrappers/bin/keyfetch') 24 25 ''; 25 26 }