This repository has no description
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 keyfetchWrapper = pkgs.writeShellScriptBin {
20 name = "keyfetch-wrapper";
21 runtimeInputs = [ tangledPkgs.keyfetch ];
22 text = ''
23 keyfetch -repoguard-path ${lib.getExe tangledPkgs.repoguard} -log-path /tmp/repoguard.log
24 '';
25 };
26in
27{
28 options = {
29 services.tangled-knotserver = {
30 enable = mkOption {
31 type = types.bool;
32 default = false;
33 description = "Enable a tangled knotserver";
34 };
35
36 appviewEndpoint = mkOption {
37 type = types.str;
38 default = "https://tangled.sh";
39 description = "Appview endpoint";
40 };
41
42 gitUser = mkOption {
43 type = types.str;
44 default = "git";
45 description = "User that hosts git repos and performs git operations";
46 };
47
48 repo = {
49 scanPath = mkOption {
50 type = types.path;
51 default = "/var/lib/tangled-knot";
52 description = "Path where repositories are scanned from";
53 };
54
55 mainBranch = mkOption {
56 type = types.str;
57 default = "main";
58 description = "Default branch name for repositories";
59 };
60 };
61
62 server = {
63 listenAddr = mkOption {
64 type = types.str;
65 default = "0.0.0.0:5555";
66 description = "Address to listen on";
67 };
68
69 internalListenAddr = mkOption {
70 type = types.str;
71 default = "127.0.0.1:5444";
72 description = "Internal address for inter-service communication";
73 };
74
75 dbPath = mkOption {
76 type = types.path;
77 default = "knotserver.db";
78 description = "Path to the database file";
79 };
80
81 hostname = mkOption {
82 type = types.str;
83 example = "knot.tangled.sh";
84 description = "Hostname for the server (required)";
85 };
86
87 dev = mkOption {
88 type = types.bool;
89 default = false;
90 description = "Enable development mode (disables signature verification)";
91 internal = true;
92 };
93 };
94
95 extraConfig = mkOption {
96 type = types.attrsOf types.str;
97 default = { };
98 example = lib.literalExpression ''
99 {
100 # this is only an example, do NOT do this! your secret will end up readable by *everyone*!
101 KNOT_SERVER_SECRET = "verysecuresecret";
102 }
103 '';
104 description = "Additional environment variables. Use `environmentFile` for secrets.";
105 };
106
107 environmentFile = mkOption {
108 type = types.nullOr types.path;
109 default = null;
110 example = "/etc/tangled/knotserver.env";
111 description = ''
112 Environment file to set additional configuration and secrets for the knotserver.
113
114 `KNOT_SERVER_SECRET` must be set for the knotserver to work, and can be obtained from
115 [this page](https://tangled.sh/knots).
116 '';
117 };
118 };
119 };
120
121 config = mkIf config.enable {
122 warnings = optional cfg.server.dev ''
123 tangled-knotserver: development mode is enabled. This is not recommended in production as signature checks are disabled.
124 '';
125
126 environment.systemPackages = with pkgs; [ git ];
127
128 users.users.${cfg.gitUser} = {
129 home = cfg.repo.scanPath;
130 group = cfg.gitUser;
131 isSystemUser = true;
132 useDefaultShell = true;
133 };
134
135 users.groups.${cfg.gitUser} = { };
136
137 services.openssh = {
138 enable = true;
139 extraConfig = ''
140 Match User ${cfg.gitUser}
141 AuthorizedKeysCommand ${keyfetchWrapper}
142 AuthorizedKeysCommandUser nobody
143 '';
144 };
145
146 systemd.services.knotserver = {
147 description = "knotserver service";
148 after = [
149 "network-online.target"
150 "sshd.service"
151 ];
152 wants = [
153 "network-online.target"
154 "sshd.service"
155 ];
156 wantedBy = [ "multi-user.target" ];
157 serviceConfig = {
158 User = cfg.gitUser;
159 WorkingDirectory = cfg.repo.scanPath;
160 ExecStart = lib.getExe tangledPkgs.knotserver;
161 Restart = "always";
162 EnvironmentFile = cfg.environmentFile;
163 };
164
165 environment = {
166 KNOT_REPO_SCANPATH = cfg.repo.scanPath;
167 APPVIEW_ENDPOINT = cfg.appviewEndpoint;
168 KNOT_SERVER_INTERNAL_LISTEN_ADDR = cfg.server.internalListenAddr;
169 KNOT_SERVER_LISTEN_ADDR = cfg.server.listenAddr;
170 KNOT_SERVER_HOSTNAME = cfg.server.hostname;
171 } // cfg.extraConfig;
172 };
173 };
174}