]> Git — Sourcephile - sourcephile-nix.git/blob - nixos/modules/services/misc/sourcehut/git.nix
sourcehut: use StateDirectory
[sourcephile-nix.git] / nixos / modules / services / misc / sourcehut / git.nix
1 { config, lib, pkgs, ... }:
2
3 with lib;
4 let
5 cfg = config.services.sourcehut;
6 scfg = cfg.git;
7 iniKey = "git.sr.ht";
8 statePath = "/var/lib/sourcehut/gitsrht";
9
10 rcfg = config.services.redis;
11 drv = pkgs.sourcehut.gitsrht;
12 in
13 {
14 options.services.sourcehut.git = {
15 user = mkOption {
16 type = types.str;
17 visible = false;
18 internal = true;
19 readOnly = true;
20 default = "git";
21 description = ''
22 User for git.sr.ht.
23 '';
24 };
25
26 port = mkOption {
27 type = types.port;
28 default = 5001;
29 description = ''
30 Port on which the "git" module should listen.
31 '';
32 };
33
34 database = mkOption {
35 type = types.str;
36 default = "git.sr.ht";
37 description = ''
38 PostgreSQL database name for git.sr.ht.
39 '';
40 };
41
42 package = mkOption {
43 type = types.package;
44 default = pkgs.git;
45 example = literalExample "pkgs.gitFull";
46 description = ''
47 Git package for git.sr.ht. This can help silence collisions.
48 '';
49 };
50 };
51
52 config = with scfg; lib.mkIf (cfg.enable && elem "git" cfg.services) {
53 # sshd refuses to run with `Unsafe AuthorizedKeysCommand ... bad ownership or modes for directory /nix/store`
54 environment.etc."ssh/gitsrht-dispatch" = {
55 mode = "0755";
56 text = ''
57 #! ${pkgs.stdenv.shell}
58 ${cfg.python}/bin/gitsrht-dispatch "$@"
59 '';
60 };
61
62 # Needs this in the $PATH when sshing into the server
63 environment.systemPackages = [ cfg.git.package ];
64
65 users = {
66 users = {
67 "${user}" = {
68 isSystemUser = true;
69 group = user;
70 # https://stackoverflow.com/questions/22314298/git-push-results-in-fatal-protocol-error-bad-line-length-character-this
71 # Probably could use gitsrht-shell if output is restricted to just parameters...
72 shell = pkgs.bash;
73 description = "git.sr.ht user";
74 };
75 };
76
77 groups = {
78 "${user}" = { };
79 };
80 };
81
82 services = {
83 cron.systemCronJobs = [ "*/20 * * * * ${cfg.python}/bin/gitsrht-periodic" ];
84 fcgiwrap.enable = true;
85
86 openssh.authorizedKeysCommand = ''/etc/ssh/gitsrht-dispatch "%u" "%h" "%t" "%k"'';
87 openssh.authorizedKeysCommandUser = "root";
88 openssh.extraConfig = ''
89 PermitUserEnvironment SRHT_*
90 '';
91
92 postgresql = {
93 authentication = ''
94 local ${database} ${user} trust
95 '';
96 ensureDatabases = [ database ];
97 ensureUsers = [
98 {
99 name = user;
100 ensurePermissions = { "DATABASE \"${database}\"" = "ALL PRIVILEGES"; };
101 }
102 ];
103 };
104 };
105
106 systemd = {
107 tmpfiles.rules = [
108 # /var/log is owned by root
109 "f /var/log/git-srht-shell 0644 ${user} ${user} -"
110
111 "d ${cfg.settings."${iniKey}".repos} 2755 ${user} ${user} -"
112 ];
113
114 services = {
115 gitsrht = import ./service.nix { inherit config pkgs lib; } scfg drv iniKey {
116 after = [ "redis.service" "postgresql.service" "network.target" ];
117 requires = [ "redis.service" "postgresql.service" ];
118 wantedBy = [ "multi-user.target" ];
119
120 # Needs internally to create repos at the very least
121 path = [ pkgs.git ];
122 description = "git.sr.ht website service";
123
124 serviceConfig.ExecStart = "${cfg.python}/bin/gunicorn ${drv.pname}.app:app -b ${cfg.address}:${toString port}";
125 };
126
127 gitsrht-webhooks = {
128 after = [ "postgresql.service" "network.target" ];
129 requires = [ "postgresql.service" ];
130 wantedBy = [ "multi-user.target" ];
131
132 description = "git.sr.ht webhooks service";
133 serviceConfig = {
134 Type = "simple";
135 User = user;
136 Restart = "always";
137 };
138
139 serviceConfig.ExecStart = "${cfg.python}/bin/celery -A ${drv.pname}.webhooks worker --loglevel INFO --pool eventlet";
140 };
141 };
142 };
143
144 services.sourcehut.settings = {
145 # The authorized keys hook uses this to dispatch to various handlers
146 # The format is a program to exec into as the key, and the user to match as the
147 # value. When someone tries to log in as this user, this program is executed
148 # and is expected to omit an AuthorizedKeys file.
149 #
150 # Discard of the string context is in order to allow derivation-derived strings.
151 # This is safe if the relevant package is installed which will be the case if the setting is utilized.
152 "git.sr.ht::dispatch".${builtins.unsafeDiscardStringContext "${pkgs.sourcehut.gitsrht}/bin/gitsrht-keys"} = mkDefault "${user}:${user}";
153 };
154
155 services.nginx.virtualHosts."git.${cfg.originBase}" = {
156 forceSSL = true;
157 locations."/".proxyPass = "http://${cfg.address}:${toString port}";
158 locations."/query".proxyPass = "http://${cfg.address}:${toString (port + 100)}";
159 locations."/static".root = "${pkgs.sourcehut.gitsrht}/${pkgs.sourcehut.python.sitePackages}/gitsrht";
160 extraConfig = ''
161 location = /authorize {
162 proxy_pass http://${cfg.address}:${toString port};
163 proxy_pass_request_body off;
164 proxy_set_header Content-Length "";
165 proxy_set_header X-Original-URI $request_uri;
166 }
167 location ~ ^/([^/]+)/([^/]+)/(HEAD|info/refs|objects/info/.*|git-upload-pack).*$ {
168 auth_request /authorize;
169 root /var/lib/git;
170 fastcgi_pass unix:/run/fcgiwrap.sock;
171 fastcgi_param SCRIPT_FILENAME ${pkgs.git}/bin/git-http-backend;
172 fastcgi_param PATH_INFO $uri;
173 fastcgi_param GIT_PROJECT_ROOT $document_root;
174 fastcgi_read_timeout 500s;
175 include ${pkgs.nginx}/conf/fastcgi_params;
176 gzip off;
177 }
178 '';
179
180 };
181 };
182 }