From 8609dece0cf44f09c67e254cdcdd0cb05385d8f2 Mon Sep 17 00:00:00 2001 From: Akshay Date: Mon, 28 Apr 2025 12:02:48 +0100 Subject: [PATCH] nix: configure air to stop on error --- flake.nix | 757 +++++++++++++++++++++++++++--------------------------- 1 file changed, 373 insertions(+), 384 deletions(-) diff --git a/flake.nix b/flake.nix index a1187832..c51e696b 100644 --- a/flake.nix +++ b/flake.nix @@ -29,430 +29,419 @@ }; }; - outputs = - { self - , nixpkgs - , indigo - , htmx-src - , lucide-src - , gitignore - , inter-fonts-src - , ibm-plex-mono-src - , + outputs = { + self, + nixpkgs, + indigo, + htmx-src, + lucide-src, + gitignore, + inter-fonts-src, + ibm-plex-mono-src, + }: let + supportedSystems = ["x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin"]; + forAllSystems = nixpkgs.lib.genAttrs supportedSystems; + nixpkgsFor = forAllSystems (system: + import nixpkgs { + inherit system; + overlays = [self.overlays.default]; + }); + inherit (gitignore.lib) gitignoreSource; + in { + overlays.default = final: prev: let + goModHash = "sha256-EilWxfqrcKDaSR5zA3ZuDSCq7V+/IfWpKPu8HWhpndA="; + buildCmdPackage = name: + final.buildGoModule { + pname = name; + version = "0.1.0"; + src = gitignoreSource ./.; + subPackages = ["cmd/${name}"]; + vendorHash = goModHash; + CGO_ENABLED = 0; + }; + in { + indigo-lexgen = final.buildGoModule { + pname = "indigo-lexgen"; + version = "0.1.0"; + src = indigo; + subPackages = ["cmd/lexgen"]; + vendorHash = "sha256-pGc29fgJFq8LP7n/pY1cv6ExZl88PAeFqIbFEhB3xXs="; + doCheck = false; + }; + + appview = with final; + final.pkgsStatic.buildGoModule { + pname = "appview"; + version = "0.1.0"; + src = gitignoreSource ./.; + postUnpack = '' + pushd source + mkdir -p appview/pages/static/{fonts,icons} + cp -f ${htmx-src} appview/pages/static/htmx.min.js + cp -rf ${lucide-src}/*.svg appview/pages/static/icons/ + cp -f ${inter-fonts-src}/web/InterVariable*.woff2 appview/pages/static/fonts/ + cp -f ${inter-fonts-src}/web/InterDisplay*.woff2 appview/pages/static/fonts/ + cp -f ${ibm-plex-mono-src}/fonts/complete/woff2/IBMPlexMono-Regular.woff2 appview/pages/static/fonts/ + ${pkgs.tailwindcss}/bin/tailwindcss -i input.css -o appview/pages/static/tw.css + popd + ''; + doCheck = false; + subPackages = ["cmd/appview"]; + vendorHash = goModHash; + CGO_ENABLED = 1; + stdenv = pkgsStatic.stdenv; + }; + + knotserver = with final; + final.pkgsStatic.buildGoModule { + pname = "knotserver"; + version = "0.1.0"; + src = gitignoreSource ./.; + nativeBuildInputs = [final.makeWrapper]; + subPackages = ["cmd/knotserver"]; + vendorHash = goModHash; + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + cp $GOPATH/bin/knotserver $out/bin/knotserver + + wrapProgram $out/bin/knotserver \ + --prefix PATH : ${pkgs.git}/bin + + runHook postInstall + ''; + CGO_ENABLED = 1; + }; + knotserver-unwrapped = final.pkgsStatic.buildGoModule { + pname = "knotserver"; + version = "0.1.0"; + src = gitignoreSource ./.; + subPackages = ["cmd/knotserver"]; + vendorHash = goModHash; + CGO_ENABLED = 1; + }; + repoguard = buildCmdPackage "repoguard"; + keyfetch = buildCmdPackage "keyfetch"; + }; + packages = forAllSystems (system: { + inherit + (nixpkgsFor."${system}") + indigo-lexgen + appview + knotserver + knotserver-unwrapped + repoguard + keyfetch + ; + }); + defaultPackage = forAllSystems (system: nixpkgsFor.${system}.appview); + formatter = forAllSystems (system: nixpkgsFor."${system}".alejandra); + devShells = forAllSystems (system: let + pkgs = nixpkgsFor.${system}; + staticShell = pkgs.mkShell.override { + stdenv = pkgs.pkgsStatic.stdenv; + }; + in { + default = staticShell { + nativeBuildInputs = [ + pkgs.go + pkgs.air + pkgs.gopls + pkgs.httpie + pkgs.indigo-lexgen + pkgs.litecli + pkgs.websocat + pkgs.tailwindcss + pkgs.nixos-shell + ]; + shellHook = '' + mkdir -p appview/pages/static/{fonts,icons} + cp -f ${htmx-src} appview/pages/static/htmx.min.js + cp -rf ${lucide-src}/*.svg appview/pages/static/icons/ + cp -f ${inter-fonts-src}/web/InterVariable*.woff2 appview/pages/static/fonts/ + cp -f ${inter-fonts-src}/web/InterDisplay*.woff2 appview/pages/static/fonts/ + cp -f ${ibm-plex-mono-src}/fonts/complete/woff2/IBMPlexMono-Regular.woff2 appview/pages/static/fonts/ + ''; + }; + }); + apps = forAllSystems (system: let + pkgs = nixpkgsFor."${system}"; + air-watcher = name: + pkgs.writeShellScriptBin "run" + '' + TANGLED_DEV=true ${pkgs.air}/bin/air -c /dev/null \ + -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" \ + -build.bin "./out/${name}.out" \ + -build.include_ext "go" + ''; + tailwind-watcher = + pkgs.writeShellScriptBin "run" + '' + ${pkgs.tailwindcss}/bin/tailwindcss -w -i input.css -o ./appview/pages/static/tw.css + ''; + in { + watch-appview = { + type = "app"; + program = ''${air-watcher "appview"}/bin/run''; + }; + watch-knotserver = { + type = "app"; + program = ''${air-watcher "knotserver"}/bin/run''; + }; + watch-tailwind = { + type = "app"; + program = ''${tailwind-watcher}/bin/run''; + }; + }); + + nixosModules.appview = { + config, + pkgs, + lib, + ... }: - let - supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; - forAllSystems = nixpkgs.lib.genAttrs supportedSystems; - nixpkgsFor = forAllSystems (system: - import nixpkgs { - inherit system; - overlays = [ self.overlays.default ]; - }); - inherit (gitignore.lib) gitignoreSource; - in - { - overlays.default = final: prev: - let - goModHash = "sha256-EilWxfqrcKDaSR5zA3ZuDSCq7V+/IfWpKPu8HWhpndA="; - buildCmdPackage = name: - final.buildGoModule { - pname = name; - version = "0.1.0"; - src = gitignoreSource ./.; - subPackages = [ "cmd/${name}" ]; - vendorHash = goModHash; - CGO_ENABLED = 0; + with lib; { + options = { + services.tangled-appview = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable tangled appview"; + }; + port = mkOption { + type = types.int; + default = 3000; + description = "Port to run the appview on"; + }; + cookie_secret = mkOption { + type = types.str; + default = "00000000000000000000000000000000"; + description = "Cookie secret"; }; - in - { - indigo-lexgen = final.buildGoModule { - pname = "indigo-lexgen"; - version = "0.1.0"; - src = indigo; - subPackages = [ "cmd/lexgen" ]; - vendorHash = "sha256-pGc29fgJFq8LP7n/pY1cv6ExZl88PAeFqIbFEhB3xXs="; - doCheck = false; }; + }; + + config = mkIf config.services.tangled-appview.enable { + systemd.services.tangled-appview = { + description = "tangled appview service"; + wantedBy = ["multi-user.target"]; - appview = with final; - final.pkgsStatic.buildGoModule { - pname = "appview"; - version = "0.1.0"; - src = gitignoreSource ./.; - postUnpack = '' - pushd source - mkdir -p appview/pages/static/{fonts,icons} - cp -f ${htmx-src} appview/pages/static/htmx.min.js - cp -rf ${lucide-src}/*.svg appview/pages/static/icons/ - cp -f ${inter-fonts-src}/web/InterVariable*.woff2 appview/pages/static/fonts/ - cp -f ${inter-fonts-src}/web/InterDisplay*.woff2 appview/pages/static/fonts/ - cp -f ${ibm-plex-mono-src}/fonts/complete/woff2/IBMPlexMono-Regular.woff2 appview/pages/static/fonts/ - ${pkgs.tailwindcss}/bin/tailwindcss -i input.css -o appview/pages/static/tw.css - popd - ''; - doCheck = false; - subPackages = [ "cmd/appview" ]; - vendorHash = goModHash; - CGO_ENABLED = 1; - stdenv = pkgsStatic.stdenv; + serviceConfig = { + ListenStream = "0.0.0.0:${toString config.services.tangled-appview.port}"; + ExecStart = "${self.packages.${pkgs.system}.appview}/bin/appview"; + Restart = "always"; }; - knotserver = with final; - final.pkgsStatic.buildGoModule { - pname = "knotserver"; - version = "0.1.0"; - src = gitignoreSource ./.; - nativeBuildInputs = [ final.makeWrapper ]; - subPackages = [ "cmd/knotserver" ]; - vendorHash = goModHash; - installPhase = '' - runHook preInstall - - mkdir -p $out/bin - cp $GOPATH/bin/knotserver $out/bin/knotserver - - wrapProgram $out/bin/knotserver \ - --prefix PATH : ${pkgs.git}/bin - - runHook postInstall - ''; - CGO_ENABLED = 1; + environment = { + TANGLED_DB_PATH = "appview.db"; + TANGLED_COOKIE_SECRET = config.services.tangled-appview.cookie_secret; }; - knotserver-unwrapped = final.pkgsStatic.buildGoModule { - pname = "knotserver"; - version = "0.1.0"; - src = gitignoreSource ./.; - subPackages = [ "cmd/knotserver" ]; - vendorHash = goModHash; - CGO_ENABLED = 1; }; - repoguard = buildCmdPackage "repoguard"; - keyfetch = buildCmdPackage "keyfetch"; }; - packages = forAllSystems (system: { - inherit - (nixpkgsFor."${system}") - indigo-lexgen - appview - knotserver - knotserver-unwrapped - repoguard - keyfetch - ; - }); - defaultPackage = forAllSystems (system: nixpkgsFor.${system}.appview); - formatter = forAllSystems (system: nixpkgsFor."${system}".alejandra); - devShells = forAllSystems (system: - let - pkgs = nixpkgsFor.${system}; - staticShell = pkgs.mkShell.override { - stdenv = pkgs.pkgsStatic.stdenv; - }; - in - { - default = staticShell { - nativeBuildInputs = [ - pkgs.go - pkgs.air - pkgs.gopls - pkgs.httpie - pkgs.indigo-lexgen - pkgs.litecli - pkgs.websocat - pkgs.tailwindcss - pkgs.nixos-shell - ]; - shellHook = '' - mkdir -p appview/pages/static/{fonts,icons} - cp -f ${htmx-src} appview/pages/static/htmx.min.js - cp -rf ${lucide-src}/*.svg appview/pages/static/icons/ - cp -f ${inter-fonts-src}/web/InterVariable*.woff2 appview/pages/static/fonts/ - cp -f ${inter-fonts-src}/web/InterDisplay*.woff2 appview/pages/static/fonts/ - cp -f ${ibm-plex-mono-src}/fonts/complete/woff2/IBMPlexMono-Regular.woff2 appview/pages/static/fonts/ - ''; - }; - }); - apps = forAllSystems (system: - let - pkgs = nixpkgsFor."${system}"; - air-watcher = name: - pkgs.writeShellScriptBin "run" - '' - TANGLED_DEV=true ${pkgs.air}/bin/air -c /dev/null \ - -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" \ - -build.bin "./out/${name}.out" \ - -build.include_ext "go" - ''; - tailwind-watcher = - pkgs.writeShellScriptBin "run" - '' - ${pkgs.tailwindcss}/bin/tailwindcss -w -i input.css -o ./appview/pages/static/tw.css - ''; - in - { - watch-appview = { - type = "app"; - program = ''${air-watcher "appview"}/bin/run''; - }; - watch-knotserver = { - type = "app"; - program = ''${air-watcher "knotserver"}/bin/run''; - }; - watch-tailwind = { - type = "app"; - program = ''${tailwind-watcher}/bin/run''; - }; - }); - - nixosModules.appview = - { config - , pkgs - , lib - , ... - }: - with lib; { - options = { - services.tangled-appview = { - enable = mkOption { - type = types.bool; - default = false; - description = "Enable tangled appview"; - }; - port = mkOption { - type = types.int; - default = 3000; - description = "Port to run the appview on"; - }; - cookie_secret = mkOption { - type = types.str; - default = "00000000000000000000000000000000"; - description = "Cookie secret"; - }; - }; + }; + + nixosModules.knotserver = { + config, + pkgs, + lib, + ... + }: let + cfg = config.services.tangled-knotserver; + in + with lib; { + options = { + services.tangled-knotserver = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable a tangled knotserver"; }; - config = mkIf config.services.tangled-appview.enable { - systemd.services.tangled-appview = { - description = "tangled appview service"; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - ListenStream = "0.0.0.0:${toString config.services.tangled-appview.port}"; - ExecStart = "${self.packages.${pkgs.system}.appview}/bin/appview"; - Restart = "always"; - }; - - environment = { - TANGLED_DB_PATH = "appview.db"; - TANGLED_COOKIE_SECRET = config.services.tangled-appview.cookie_secret; - }; - }; + appviewEndpoint = mkOption { + type = types.str; + default = "https://tangled.sh"; + description = "Appview endpoint"; }; - }; - nixosModules.knotserver = - { config - , pkgs - , lib - , ... - }: - let - cfg = config.services.tangled-knotserver; - in - with lib; { - options = { - services.tangled-knotserver = { - enable = mkOption { - type = types.bool; - default = false; - description = "Enable a tangled knotserver"; + gitUser = mkOption { + type = types.str; + default = "git"; + description = "User that hosts git repos and performs git operations"; + }; + + openFirewall = mkOption { + type = types.bool; + default = true; + description = "Open port 22 in the firewall for ssh"; + }; + + stateDir = mkOption { + type = types.path; + default = "/home/${cfg.gitUser}"; + description = "Tangled knot data directory"; + }; + + repo = { + scanPath = mkOption { + type = types.path; + default = cfg.stateDir; + description = "Path where repositories are scanned from"; }; - appviewEndpoint = mkOption { + mainBranch = mkOption { type = types.str; - default = "https://tangled.sh"; - description = "Appview endpoint"; + default = "main"; + description = "Default branch name for repositories"; }; + }; - gitUser = mkOption { + server = { + listenAddr = mkOption { type = types.str; - default = "git"; - description = "User that hosts git repos and performs git operations"; + default = "0.0.0.0:5555"; + description = "Address to listen on"; }; - openFirewall = mkOption { - type = types.bool; - default = true; - description = "Open port 22 in the firewall for ssh"; + internalListenAddr = mkOption { + type = types.str; + default = "127.0.0.1:5444"; + description = "Internal address for inter-service communication"; }; - stateDir = mkOption { + secretFile = mkOption { + type = lib.types.path; + example = "KNOT_SERVER_SECRET="; + description = "File containing secret key provided by appview (required)"; + }; + + dbPath = mkOption { type = types.path; - default = "/home/${cfg.gitUser}"; - description = "Tangled knot data directory"; + default = "${cfg.stateDir}/knotserver.db"; + description = "Path to the database file"; }; - repo = { - scanPath = mkOption { - type = types.path; - default = cfg.stateDir; - description = "Path where repositories are scanned from"; - }; - - mainBranch = mkOption { - type = types.str; - default = "main"; - description = "Default branch name for repositories"; - }; + hostname = mkOption { + type = types.str; + example = "knot.tangled.sh"; + description = "Hostname for the server (required)"; }; - server = { - listenAddr = mkOption { - type = types.str; - default = "0.0.0.0:5555"; - description = "Address to listen on"; - }; - - internalListenAddr = mkOption { - type = types.str; - default = "127.0.0.1:5444"; - description = "Internal address for inter-service communication"; - }; - - secretFile = mkOption { - type = lib.types.path; - example = "KNOT_SERVER_SECRET="; - description = "File containing secret key provided by appview (required)"; - }; - - dbPath = mkOption { - type = types.path; - default = "${cfg.stateDir}/knotserver.db"; - description = "Path to the database file"; - }; - - hostname = mkOption { - type = types.str; - example = "knot.tangled.sh"; - description = "Hostname for the server (required)"; - }; - - dev = mkOption { - type = types.bool; - default = false; - description = "Enable development mode (disables signature verification)"; - }; + dev = mkOption { + type = types.bool; + default = false; + description = "Enable development mode (disables signature verification)"; }; }; }; + }; - config = mkIf cfg.enable { - environment.systemPackages = with pkgs; [ git ]; - - system.activationScripts.gitConfig = '' - mkdir -p "${cfg.repo.scanPath}" - chown -R ${cfg.gitUser}:${cfg.gitUser} \ - "${cfg.repo.scanPath}" - - mkdir -p "${cfg.stateDir}/.config/git" - cat > "${cfg.stateDir}/.config/git/config" << EOF - [user] - name = Git User - email = git@example.com - EOF - chown -R ${cfg.gitUser}:${cfg.gitUser} \ - "${cfg.stateDir}" - ''; - - users.users.${cfg.gitUser} = { - isSystemUser = true; - useDefaultShell = true; - home = cfg.stateDir; - createHome = true; - group = cfg.gitUser; - }; + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [git]; + + system.activationScripts.gitConfig = '' + mkdir -p "${cfg.repo.scanPath}" + chown -R ${cfg.gitUser}:${cfg.gitUser} \ + "${cfg.repo.scanPath}" + + mkdir -p "${cfg.stateDir}/.config/git" + cat > "${cfg.stateDir}/.config/git/config" << EOF + [user] + name = Git User + email = git@example.com + EOF + chown -R ${cfg.gitUser}:${cfg.gitUser} \ + "${cfg.stateDir}" + ''; + + users.users.${cfg.gitUser} = { + isSystemUser = true; + useDefaultShell = true; + home = cfg.stateDir; + createHome = true; + group = cfg.gitUser; + }; - users.groups.${cfg.gitUser} = { }; + users.groups.${cfg.gitUser} = {}; - services.openssh = { - enable = true; - extraConfig = '' - Match User ${cfg.gitUser} - AuthorizedKeysCommand /etc/ssh/keyfetch_wrapper - AuthorizedKeysCommandUser nobody - ''; - }; + services.openssh = { + enable = true; + extraConfig = '' + Match User ${cfg.gitUser} + AuthorizedKeysCommand /etc/ssh/keyfetch_wrapper + AuthorizedKeysCommandUser nobody + ''; + }; - environment.etc."ssh/keyfetch_wrapper" = { - mode = "0555"; - text = '' - #!${pkgs.stdenv.shell} - ${self.packages.${pkgs.system}.keyfetch}/bin/keyfetch \ - -repoguard-path ${self.packages.${pkgs.system}.repoguard}/bin/repoguard \ - -internal-api "http://${cfg.server.internalListenAddr}" \ - -git-dir "${cfg.repo.scanPath}" \ - -log-path /tmp/repoguard.log - ''; - }; + environment.etc."ssh/keyfetch_wrapper" = { + mode = "0555"; + text = '' + #!${pkgs.stdenv.shell} + ${self.packages.${pkgs.system}.keyfetch}/bin/keyfetch \ + -repoguard-path ${self.packages.${pkgs.system}.repoguard}/bin/repoguard \ + -internal-api "http://${cfg.server.internalListenAddr}" \ + -git-dir "${cfg.repo.scanPath}" \ + -log-path /tmp/repoguard.log + ''; + }; - systemd.services.knotserver = { - description = "knotserver service"; - after = [ "network.target" "sshd.service" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - User = cfg.gitUser; - WorkingDirectory = cfg.stateDir; - Environment = [ - "KNOT_REPO_SCAN_PATH=${cfg.repo.scanPath}" - "KNOT_REPO_MAIN_BRANCH=${cfg.repo.mainBranch}" - "APPVIEW_ENDPOINT=${cfg.appviewEndpoint}" - "KNOT_SERVER_INTERNAL_LISTEN_ADDR=${cfg.server.internalListenAddr}" - "KNOT_SERVER_LISTEN_ADDR=${cfg.server.listenAddr}" - "KNOT_SERVER_DB_PATH=${cfg.server.dbPath}" - "KNOT_SERVER_HOSTNAME=${cfg.server.hostname}" - ]; - EnvironmentFile = cfg.server.secretFile; - ExecStart = "${self.packages.${pkgs.system}.knotserver}/bin/knotserver"; - Restart = "always"; - }; + systemd.services.knotserver = { + description = "knotserver service"; + after = ["network.target" "sshd.service"]; + wantedBy = ["multi-user.target"]; + serviceConfig = { + User = cfg.gitUser; + WorkingDirectory = cfg.stateDir; + Environment = [ + "KNOT_REPO_SCAN_PATH=${cfg.repo.scanPath}" + "KNOT_REPO_MAIN_BRANCH=${cfg.repo.mainBranch}" + "APPVIEW_ENDPOINT=${cfg.appviewEndpoint}" + "KNOT_SERVER_INTERNAL_LISTEN_ADDR=${cfg.server.internalListenAddr}" + "KNOT_SERVER_LISTEN_ADDR=${cfg.server.listenAddr}" + "KNOT_SERVER_DB_PATH=${cfg.server.dbPath}" + "KNOT_SERVER_HOSTNAME=${cfg.server.hostname}" + ]; + EnvironmentFile = cfg.server.secretFile; + ExecStart = "${self.packages.${pkgs.system}.knotserver}/bin/knotserver"; + Restart = "always"; }; - - networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ 22 ]; }; + + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [22]; }; + }; - nixosConfigurations.knotVM = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - self.nixosModules.knotserver - ({ config - , pkgs - , ... - }: { - virtualisation.memorySize = 2048; - virtualisation.diskSize = 10 * 1024; - virtualisation.cores = 2; - services.getty.autologinUser = "root"; - environment.systemPackages = with pkgs; [ curl vim git ]; - systemd.tmpfiles.rules = - let - u = config.services.tangled-knotserver.gitUser; - g = config.services.tangled-knotserver.gitUser; - in - [ - "d /var/lib/knotserver 0770 ${u} ${g} - -" # Create the directory first - "f+ /var/lib/knotserver/secret 0660 ${u} ${g} - KNOT_SERVER_SECRET=679f15000084699abc6a20d3ef449efa3656583f38e456a08f0638250688ff2e" - ]; - services.tangled-knotserver = { - enable = true; - server = { - secretFile = "/var/lib/knotserver/secret"; - hostname = "localhost:6000"; - listenAddr = "0.0.0.0:6000"; - }; + nixosConfigurations.knotVM = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + self.nixosModules.knotserver + ({ + config, + pkgs, + ... + }: { + virtualisation.memorySize = 2048; + virtualisation.diskSize = 10 * 1024; + virtualisation.cores = 2; + services.getty.autologinUser = "root"; + environment.systemPackages = with pkgs; [curl vim git]; + systemd.tmpfiles.rules = let + u = config.services.tangled-knotserver.gitUser; + g = config.services.tangled-knotserver.gitUser; + in [ + "d /var/lib/knotserver 0770 ${u} ${g} - -" # Create the directory first + "f+ /var/lib/knotserver/secret 0660 ${u} ${g} - KNOT_SERVER_SECRET=679f15000084699abc6a20d3ef449efa3656583f38e456a08f0638250688ff2e" + ]; + services.tangled-knotserver = { + enable = true; + server = { + secretFile = "/var/lib/knotserver/secret"; + hostname = "localhost:6000"; + listenAddr = "0.0.0.0:6000"; }; - }) - ]; - }; + }; + }) + ]; }; + }; } -- 2.51.2