This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

1# modified from https://tangled.sh/@tangled.sh/core/blob/master/flake.nix 2tangledFlake: 3{ 4 config, 5 pkgs, 6 lib, 7 ... 8}: 9let 10 inherit (lib) 11 mkOption 12 types 13 mkIf 14 optional 15 ; 16 cfg = config.services.tangled-knotserver; 17 tangledPkgs = tangledFlake.packages.${pkgs.system}; 18 19 wrapped-packages = 20 pkgs.runCommandCC "tangled-packages-wrapped" { nativeBuildInputs = [ pkgs.makeBinaryWrapper ]; } 21 '' 22 mkdir -p $out/bin 23 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" 33 ''; 34 35in 36{ 37 imports = [ 38 (lib.mkRenamedOptionModule ["services" "tangled-knotserver" "gitUser"] ["services" "tangled-knotserver" "user"]) 39 ]; 40 41 options = { 42 services.tangled-knotserver = { 43 enable = mkOption { 44 type = types.bool; 45 default = false; 46 description = "Enable a tangled knotserver"; 47 }; 48 49 appviewEndpoint = mkOption { 50 type = types.str; 51 default = "https://tangled.sh"; 52 description = "Appview endpoint"; 53 }; 54 55 user = mkOption { 56 type = types.str; 57 default = "git"; 58 description = "User that runs the server, hosts git repos and performs git operations"; 59 }; 60 61 git = { 62 name = mkOption { 63 type = types.str; 64 default = "Tangled Knot daemon"; 65 description = "Git username for git operations that requires one."; 66 }; 67 email = mkOption { 68 type = types.str; 69 default = "knot@example.invalid"; 70 description = "Git email address for git operations that requires one."; 71 }; 72 }; 73 74 repo = { 75 scanPath = mkOption { 76 type = types.path; 77 default = "/var/lib/tangled-knot"; 78 description = "Path where repositories are stored"; 79 }; 80 81 mainBranch = mkOption { 82 type = types.str; 83 default = "main"; 84 description = "Default branch name for repositories"; 85 }; 86 }; 87 88 server = { 89 listenAddr = mkOption { 90 type = types.str; 91 default = "0.0.0.0:5555"; 92 description = "Address to listen on"; 93 }; 94 95 internalListenAddr = mkOption { 96 type = types.str; 97 default = "127.0.0.1:5444"; 98 description = "Internal address for inter-service communication"; 99 }; 100 101 dbPath = mkOption { 102 type = types.path; 103 default = "knotserver.db"; 104 description = "Path to the database file"; 105 }; 106 107 hostname = mkOption { 108 type = types.str; 109 example = "knot.tangled.sh"; 110 description = "Hostname for the server (required)"; 111 }; 112 113 dev = mkOption { 114 type = types.bool; 115 default = false; 116 description = "Enable development mode (disables signature verification)"; 117 internal = true; 118 }; 119 }; 120 121 extraConfig = mkOption { 122 type = types.attrsOf types.str; 123 default = { }; 124 example = lib.literalExpression '' 125 { 126 # this is only an example, do NOT do this! your secret will end up readable by *everyone*! 127 KNOT_SERVER_SECRET = "verysecuresecret"; 128 } 129 ''; 130 description = '' 131 Additional environment variables. Use `environmentFile` for secrets. 132 133 `KNOT_SERVER_SECRET` must be set for the knotserver to work, and can be obtained from 134 [this page](https://tangled.sh/knots). Please set this with environmentFile instead of setting it here 135 directly. 136 ''; 137 }; 138 139 extraSshdConfig = mkOption { 140 type = types.lines; 141 default = ""; 142 example = '' 143 Banner none 144 PasswordAuthentication no 145 KbdInteractiveAuthentication no 146 ''; 147 description = "Additional sshd_config options to set for the git user."; 148 }; 149 150 environmentFile = mkOption { 151 type = types.nullOr types.path; 152 default = null; 153 example = "/etc/tangled/knotserver.env"; 154 description = '' 155 Environment file to set additional configuration and secrets for the knotserver. 156 157 `KNOT_SERVER_SECRET` must be set for the knotserver to work, and can be obtained from 158 [this page](https://tangled.sh/knots). 159 ''; 160 }; 161 }; 162 }; 163 164 config = mkIf cfg.enable { 165 warnings = optional cfg.server.dev '' 166 tangled-knotserver: development mode is enabled. This is not recommended in production as signature checks are disabled. 167 ''; 168 169 environment.systemPackages = with pkgs; [ git ]; 170 171 users.users.${cfg.user} = { 172 home = cfg.repo.scanPath; 173 group = cfg.user; 174 isSystemUser = true; 175 useDefaultShell = true; 176 }; 177 178 users.groups.${cfg.user} = { }; 179 180 systemd.services.knotserver = { 181 description = "knotserver service"; 182 path = [pkgs.git]; 183 after = [ 184 "network-online.target" 185 "sshd.service" 186 ]; 187 wants = [ 188 "network-online.target" 189 "sshd.service" 190 ]; 191 wantedBy = [ "multi-user.target" ]; 192 193 preStart = '' 194 git config --global user.name "${cfg.git.name}" 195 git config --global user.email "${cfg.git.email}" 196 ''; 197 198 serviceConfig = { 199 User = cfg.user; 200 WorkingDirectory = cfg.repo.scanPath; 201 ExecStart = lib.getExe' tangledPkgs.knotserver "knotserver"; 202 Restart = "always"; 203 204 StateDirectory = mkIf (lib.hasPrefix "/var/lib/tangled-knot" cfg.repo.scanPath) "tangled-knot"; 205 EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; 206 # TODO: hardening 207 }; 208 209 environment = { 210 APPVIEW_ENDPOINT = cfg.appviewEndpoint; 211 KNOT_REPO_SCAN_PATH = cfg.repo.scanPath; 212 KNOT_SERVER_INTERNAL_LISTEN_ADDR = cfg.server.internalListenAddr; 213 KNOT_SERVER_LISTEN_ADDR = cfg.server.listenAddr; 214 KNOT_SERVER_HOSTNAME = cfg.server.hostname; 215 } // cfg.extraConfig; 216 }; 217 218 systemd.tmpfiles.settings."knotserver-settings"."/var/log/knotserver"."d" = { 219 mode = "0750"; 220 user = config.users.users.${cfg.user}.name; 221 group = config.users.groups.${cfg.user}.name; 222 }; 223 224 services.openssh = { 225 enable = true; 226 extraConfig = '' 227 Match User ${cfg.user} 228 AuthorizedKeysCommand ${config.security.wrapperDir}/keyfetch 229 AuthorizedKeysCommandUser nobody 230 ${cfg.extraSshdConfig} 231 ''; 232 }; 233 234 # get around openssh restrictions 235 security.wrappers.keyfetch = { 236 owner = "root"; 237 group = config.users.groups.${cfg.user}.name; 238 permissions = "u+rx,go+x"; 239 source = lib.getExe' wrapped-packages "keyfetch"; 240 }; 241 }; 242}