From 3d58f32cbe20a863b8928aa6f817b8537db10a44 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Wed, 4 Jun 2025 20:49:05 +0100 Subject: [PATCH] nix: break out knot module into separate file Change-Id: ylynlqwtkoqtkurmqmxtrsrstpyvlnqp Signed-off-by: oppiliappan --- flake.nix | 171 +----------------------------------------- nix/modules/knot.nix | 172 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 170 deletions(-) create mode 100644 nix/modules/knot.nix diff --git a/flake.nix b/flake.nix index ee525ef..8249c8c 100644 --- a/flake.nix +++ b/flake.nix @@ -200,176 +200,6 @@ }; }); - nixosModules.knot = { - config, - pkgs, - lib, - ... - }: let - cfg = config.services.tangled-knot; - in - with lib; { - options = { - services.tangled-knot = { - enable = mkOption { - type = types.bool; - default = false; - description = "Enable a tangled knot"; - }; - - appviewEndpoint = mkOption { - type = types.str; - default = "https://tangled.sh"; - description = "Appview endpoint"; - }; - - 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"; - }; - - mainBranch = mkOption { - type = types.str; - default = "main"; - description = "Default branch name for repositories"; - }; - }; - - 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)"; - }; - }; - }; - }; - - 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} = {}; - - 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}.knot}/bin/knot keys \ - -output authorized-keys \ - -internal-api "http://${cfg.server.internalListenAddr}" \ - -git-dir "${cfg.repo.scanPath}" \ - -log-path /tmp/knotguard.log - ''; - }; - - systemd.services.knot = { - description = "knot 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}.knot}/bin/knot server"; - Restart = "always"; - }; - }; - - networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [22]; - }; - }; - nixosConfigurations.knotVM = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ @@ -403,5 +233,6 @@ ]; }; nixosModules.appview = import ./nix/modules/appview.nix {inherit self;}; + nixosModules.knot = import ./nix/modules/knot.nix {inherit self;}; }; } diff --git a/nix/modules/knot.nix b/nix/modules/knot.nix new file mode 100644 index 0000000..7fa5c40 --- /dev/null +++ b/nix/modules/knot.nix @@ -0,0 +1,172 @@ +{self}: { + config, + pkgs, + lib, + ... +}: let + cfg = config.services.tangled-knot; +in + with lib; { + options = { + services.tangled-knot = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable a tangled knot"; + }; + + appviewEndpoint = mkOption { + type = types.str; + default = "https://tangled.sh"; + description = "Appview endpoint"; + }; + + 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"; + }; + + mainBranch = mkOption { + type = types.str; + default = "main"; + description = "Default branch name for repositories"; + }; + }; + + 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)"; + }; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + git + self.packages."${pkgs.system}".knot + ]; + + 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} = {}; + + 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}.knot}/bin/knot keys \ + -output authorized-keys \ + -internal-api "http://${cfg.server.internalListenAddr}" \ + -git-dir "${cfg.repo.scanPath}" \ + -log-path /tmp/knotguard.log + ''; + }; + + systemd.services.knot = { + description = "knot 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}.knot}/bin/knot server"; + Restart = "always"; + }; + }; + + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [22]; + }; + } -- 2.43.0