forked from tangled.org/core
this repo has no description
1{ 2 description = "atproto github"; 3 4 inputs = { 5 nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; 6 indigo = { 7 url = "github:oppiliappan/indigo"; 8 flake = false; 9 }; 10 htmx-src = { 11 url = "https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js"; 12 flake = false; 13 }; 14 lucide-src = { 15 url = "https://github.com/lucide-icons/lucide/releases/download/0.483.0/lucide-icons-0.483.0.zip"; 16 flake = false; 17 }; 18 ia-fonts-src = { 19 url = "github:iaolo/iA-Fonts"; 20 flake = false; 21 }; 22 gitignore = { 23 url = "github:hercules-ci/gitignore.nix"; 24 inputs.nixpkgs.follows = "nixpkgs"; 25 }; 26 }; 27 28 outputs = { 29 self, 30 nixpkgs, 31 indigo, 32 htmx-src, 33 lucide-src, 34 gitignore, 35 ia-fonts-src, 36 }: let 37 supportedSystems = ["x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin"]; 38 forAllSystems = nixpkgs.lib.genAttrs supportedSystems; 39 nixpkgsFor = forAllSystems (system: 40 import nixpkgs { 41 inherit system; 42 overlays = [self.overlays.default]; 43 }); 44 inherit (gitignore.lib) gitignoreSource; 45 in { 46 overlays.default = final: prev: let 47 goModHash = "sha256-2vljseczrvsl2T0P9k69ro72yU59l5fp9r/sszmXYY4="; 48 buildCmdPackage = name: 49 final.buildGoModule { 50 pname = name; 51 version = "0.1.0"; 52 src = gitignoreSource ./.; 53 subPackages = ["cmd/${name}"]; 54 vendorHash = goModHash; 55 CGO_ENABLED = 0; 56 }; 57 in { 58 indigo-lexgen = final.buildGoModule { 59 pname = "indigo-lexgen"; 60 version = "0.1.0"; 61 src = indigo; 62 subPackages = ["cmd/lexgen"]; 63 vendorHash = "sha256-pGc29fgJFq8LP7n/pY1cv6ExZl88PAeFqIbFEhB3xXs="; 64 doCheck = false; 65 }; 66 67 appview = with final; 68 final.pkgsStatic.buildGoModule { 69 pname = "appview"; 70 version = "0.1.0"; 71 src = gitignoreSource ./.; 72 postUnpack = '' 73 pushd source 74 mkdir -p appview/pages/static/{fonts,icons} 75 cp -f ${htmx-src} appview/pages/static/htmx.min.js 76 cp -rf ${lucide-src}/*.svg appview/pages/static/icons/ 77 cp -f ${ia-fonts-src}/"iA Writer Quattro"/Static/*.ttf appview/pages/static/fonts/ 78 cp -f ${ia-fonts-src}/"iA Writer Mono"/Static/*.ttf appview/pages/static/fonts/ 79 ${pkgs.tailwindcss}/bin/tailwindcss -i input.css -o appview/pages/static/tw.css 80 popd 81 ''; 82 doCheck = false; 83 subPackages = ["cmd/appview"]; 84 vendorHash = goModHash; 85 CGO_ENABLED = 1; 86 stdenv = pkgsStatic.stdenv; 87 }; 88 89 knotserver = with final; 90 final.pkgsStatic.buildGoModule { 91 pname = "knotserver"; 92 version = "0.1.0"; 93 src = gitignoreSource ./.; 94 nativeBuildInputs = [final.makeWrapper]; 95 subPackages = ["cmd/knotserver"]; 96 vendorHash = goModHash; 97 installPhase = '' 98 runHook preInstall 99 100 mkdir -p $out/bin 101 cp $GOPATH/bin/knotserver $out/bin/knotserver 102 103 wrapProgram $out/bin/knotserver \ 104 --prefix PATH : ${pkgs.git}/bin 105 106 runHook postInstall 107 ''; 108 CGO_ENABLED = 1; 109 }; 110 knotserver-unwrapped = final.pkgsStatic.buildGoModule { 111 pname = "knotserver"; 112 version = "0.1.0"; 113 src = gitignoreSource ./.; 114 subPackages = ["cmd/knotserver"]; 115 vendorHash = goModHash; 116 CGO_ENABLED = 1; 117 }; 118 repoguard = buildCmdPackage "repoguard"; 119 keyfetch = buildCmdPackage "keyfetch"; 120 }; 121 packages = forAllSystems (system: { 122 inherit 123 (nixpkgsFor."${system}") 124 indigo-lexgen 125 appview 126 knotserver 127 knotserver-unwrapped 128 repoguard 129 keyfetch 130 ; 131 }); 132 defaultPackage = forAllSystems (system: nixpkgsFor.${system}.appview); 133 formatter = forAllSystems (system: nixpkgsFor."${system}".alejandra); 134 devShells = forAllSystems (system: let 135 pkgs = nixpkgsFor.${system}; 136 staticShell = pkgs.mkShell.override { 137 stdenv = pkgs.pkgsStatic.stdenv; 138 }; 139 in { 140 default = staticShell { 141 nativeBuildInputs = [ 142 pkgs.go 143 pkgs.air 144 pkgs.gopls 145 pkgs.httpie 146 pkgs.indigo-lexgen 147 pkgs.litecli 148 pkgs.websocat 149 pkgs.tailwindcss 150 pkgs.nixos-shell 151 ]; 152 shellHook = '' 153 mkdir -p appview/pages/static/{fonts,icons} 154 cp -f ${htmx-src} appview/pages/static/htmx.min.js 155 cp -rf ${lucide-src}/*.svg appview/pages/static/icons/ 156 cp -f ${ia-fonts-src}/"iA Writer Quattro"/Static/*.ttf appview/pages/static/fonts/ 157 cp -f ${ia-fonts-src}/"iA Writer Mono"/Static/*.ttf appview/pages/static/fonts/ 158 ''; 159 }; 160 }); 161 apps = forAllSystems (system: let 162 pkgs = nixpkgsFor."${system}"; 163 air-watcher = name: 164 pkgs.writeShellScriptBin "run" 165 '' 166 ${pkgs.air}/bin/air -c /dev/null \ 167 -build.cmd "${pkgs.tailwindcss}/bin/tailwindcss -i input.css -o ./appview/pages/static/tw.css && ${pkgs.go}/bin/go build -o ./out/${name}.out ./cmd/${name}/main.go" \ 168 -build.bin "./out/${name}.out" \ 169 -build.include_ext "go,html,css" 170 ''; 171 in { 172 watch-appview = { 173 type = "app"; 174 program = ''${air-watcher "appview"}/bin/run''; 175 }; 176 watch-knotserver = { 177 type = "app"; 178 program = ''${air-watcher "knotserver"}/bin/run''; 179 }; 180 }); 181 182 nixosModules.appview = { 183 config, 184 pkgs, 185 lib, 186 ... 187 }: 188 with lib; { 189 options = { 190 services.tangled-appview = { 191 enable = mkOption { 192 type = types.bool; 193 default = false; 194 description = "Enable tangled appview"; 195 }; 196 port = mkOption { 197 type = types.int; 198 default = 3000; 199 description = "Port to run the appview on"; 200 }; 201 cookie_secret = mkOption { 202 type = types.str; 203 default = "00000000000000000000000000000000"; 204 description = "Cookie secret"; 205 }; 206 }; 207 }; 208 209 config = mkIf config.services.tangled-appview.enable { 210 systemd.services.tangled-appview = { 211 description = "tangled appview service"; 212 wantedBy = ["multi-user.target"]; 213 214 serviceConfig = { 215 ListenStream = "0.0.0.0:${toString config.services.tangled-appview.port}"; 216 ExecStart = "${self.packages.${pkgs.system}.appview}/bin/appview"; 217 Restart = "always"; 218 }; 219 220 environment = { 221 TANGLED_DB_PATH = "appview.db"; 222 TANGLED_COOKIE_SECRET = config.services.tangled-appview.cookie_secret; 223 }; 224 }; 225 }; 226 }; 227 228 nixosModules.knotserver = { 229 config, 230 pkgs, 231 lib, 232 ... 233 }: 234 with lib; { 235 options = { 236 services.tangled-knotserver = { 237 enable = mkOption { 238 type = types.bool; 239 default = false; 240 description = "Enable a tangled knotserver"; 241 }; 242 243 appviewEndpoint = mkOption { 244 type = types.str; 245 default = "https://tangled.sh"; 246 description = "Appview endpoint"; 247 }; 248 249 gitUser = mkOption { 250 type = types.str; 251 default = "git"; 252 description = "User that hosts git repos and performs git operations"; 253 }; 254 255 repo = { 256 scanPath = mkOption { 257 type = types.path; 258 default = "/home/git"; 259 description = "Path where repositories are scanned from"; 260 }; 261 262 mainBranch = mkOption { 263 type = types.str; 264 default = "main"; 265 description = "Default branch name for repositories"; 266 }; 267 }; 268 269 server = { 270 listenAddr = mkOption { 271 type = types.str; 272 default = "0.0.0.0:5555"; 273 description = "Address to listen on"; 274 }; 275 276 internalListenAddr = mkOption { 277 type = types.str; 278 default = "127.0.0.1:5444"; 279 description = "Internal address for inter-service communication"; 280 }; 281 282 secretFile = mkOption { 283 type = lib.types.path; 284 example = "KNOT_SERVER_SECRET=<hash>"; 285 description = "File containing secret key provided by appview (required)"; 286 }; 287 288 dbPath = mkOption { 289 type = types.path; 290 default = "knotserver.db"; 291 description = "Path to the database file"; 292 }; 293 294 hostname = mkOption { 295 type = types.str; 296 example = "knot.tangled.sh"; 297 description = "Hostname for the server (required)"; 298 }; 299 300 dev = mkOption { 301 type = types.bool; 302 default = false; 303 description = "Enable development mode (disables signature verification)"; 304 }; 305 }; 306 }; 307 }; 308 309 config = mkIf config.services.tangled-knotserver.enable { 310 environment.systemPackages = with pkgs; [git]; 311 312 system.activationScripts.gitConfig = '' 313 mkdir -p /home/git/.config/git 314 cat > /home/git/.config/git/config << EOF 315 [user] 316 name = Git User 317 email = git@example.com 318 EOF 319 chown -R git:git /home/git/.config 320 ''; 321 322 users.users.git = { 323 isNormalUser = true; 324 home = "/home/git"; 325 createHome = true; 326 group = "git"; 327 }; 328 329 users.groups.git = {}; 330 331 services.openssh = { 332 enable = true; 333 extraConfig = '' 334 Match User git 335 AuthorizedKeysCommand /etc/ssh/keyfetch_wrapper 336 AuthorizedKeysCommandUser nobody 337 ''; 338 }; 339 340 environment.etc."ssh/keyfetch_wrapper" = { 341 mode = "0555"; 342 text = '' 343 #!${pkgs.stdenv.shell} 344 ${self.packages.${pkgs.system}.keyfetch}/bin/keyfetch \ 345 -repoguard-path ${self.packages.${pkgs.system}.repoguard}/bin/repoguard \ 346 -log-path /tmp/repoguard.log 347 ''; 348 }; 349 350 systemd.services.knotserver = { 351 description = "knotserver service"; 352 after = ["network.target" "sshd.service"]; 353 wantedBy = ["multi-user.target"]; 354 serviceConfig = { 355 User = "git"; 356 WorkingDirectory = "/home/git"; 357 Environment = [ 358 "KNOT_REPO_SCAN_PATH=${config.services.tangled-knotserver.repo.scanPath}" 359 "APPVIEW_ENDPOINT=${config.services.tangled-knotserver.appviewEndpoint}" 360 "KNOT_SERVER_INTERNAL_LISTEN_ADDR=${config.services.tangled-knotserver.server.internalListenAddr}" 361 "KNOT_SERVER_LISTEN_ADDR=${config.services.tangled-knotserver.server.listenAddr}" 362 "KNOT_SERVER_HOSTNAME=${config.services.tangled-knotserver.server.hostname}" 363 ]; 364 EnvironmentFile = config.services.tangled-knotserver.server.secretFile; 365 ExecStart = "${self.packages.${pkgs.system}.knotserver}/bin/knotserver"; 366 Restart = "always"; 367 }; 368 }; 369 370 networking.firewall.allowedTCPPorts = [22]; 371 }; 372 }; 373 374 nixosConfigurations.knotVM = nixpkgs.lib.nixosSystem { 375 system = "x86_64-linux"; 376 modules = [ 377 self.nixosModules.knotserver 378 ({ 379 config, 380 pkgs, 381 ... 382 }: { 383 virtualisation.memorySize = 2048; 384 virtualisation.cores = 2; 385 services.getty.autologinUser = "root"; 386 environment.systemPackages = with pkgs; [curl vim git]; 387 systemd.tmpfiles.rules = [ 388 "w /var/lib/knotserver/secret 0660 git git - KNOT_SERVER_SECRET=6995e040e80e2d593b5e5e9ca611a70140b9ef8044add0a28b48b1ee34aa3e85" 389 ]; 390 services.tangled-knotserver = { 391 enable = true; 392 server = { 393 secretFile = "/var/lib/knotserver/secret"; 394 hostname = "localhost:6000"; 395 listenAddr = "0.0.0.0:6000"; 396 }; 397 }; 398 }) 399 ]; 400 }; 401 }; 402}