1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8
9 cfg = config.services.gitDaemon;
10
11in
12{
13
14 ###### interface
15
16 options = {
17 services.gitDaemon = {
18
19 enable = lib.mkOption {
20 type = lib.types.bool;
21 default = false;
22 description = ''
23 Enable Git daemon, which allows public hosting of git repositories
24 without any access controls. This is mostly intended for read-only access.
25
26 You can allow write access by setting daemon.receivepack configuration
27 item of the repository to true. This is solely meant for a closed LAN setting
28 where everybody is friendly.
29
30 If you need any access controls, use something else.
31 '';
32 };
33
34 package = lib.mkPackageOption pkgs "git" { };
35
36 basePath = lib.mkOption {
37 type = lib.types.str;
38 default = "";
39 example = "/srv/git/";
40 description = ''
41 Remap all the path requests as relative to the given path. For example,
42 if you set base-path to /srv/git, then if you later try to pull
43 git://example.com/hello.git, Git daemon will interpret the path as /srv/git/hello.git.
44 '';
45 };
46
47 exportAll = lib.mkOption {
48 type = lib.types.bool;
49 default = false;
50 description = ''
51 Publish all directories that look like Git repositories (have the objects
52 and refs subdirectories), even if they do not have the git-daemon-export-ok file.
53
54 If disabled, you need to touch .git/git-daemon-export-ok in each repository
55 you want the daemon to publish.
56
57 Warning: enabling this without a repository whitelist or basePath
58 publishes every git repository you have.
59 '';
60 };
61
62 repositories = lib.mkOption {
63 type = lib.types.listOf lib.types.str;
64 default = [ ];
65 example = [
66 "/srv/git"
67 "/home/user/git/repo2"
68 ];
69 description = ''
70 A whitelist of paths of git repositories, or directories containing repositories
71 all of which would be published. Paths must not end in "/".
72
73 Warning: leaving this empty and enabling exportAll publishes all
74 repositories in your filesystem or basePath if specified.
75 '';
76 };
77
78 listenAddress = lib.mkOption {
79 type = lib.types.str;
80 default = "";
81 example = "example.com";
82 description = "Listen on a specific IP address or hostname.";
83 };
84
85 port = lib.mkOption {
86 type = lib.types.port;
87 default = 9418;
88 description = "Port to listen on.";
89 };
90
91 options = lib.mkOption {
92 type = lib.types.str;
93 default = "";
94 description = "Extra configuration options to be passed to Git daemon.";
95 };
96
97 user = lib.mkOption {
98 type = lib.types.str;
99 default = "git";
100 description = "User under which Git daemon would be running.";
101 };
102
103 group = lib.mkOption {
104 type = lib.types.str;
105 default = "git";
106 description = "Group under which Git daemon would be running.";
107 };
108
109 };
110 };
111
112 ###### implementation
113
114 config = lib.mkIf cfg.enable {
115
116 users.users = lib.optionalAttrs (cfg.user == "git") {
117 git = {
118 uid = config.ids.uids.git;
119 group = "git";
120 description = "Git daemon user";
121 };
122 };
123
124 users.groups = lib.optionalAttrs (cfg.group == "git") {
125 git.gid = config.ids.gids.git;
126 };
127
128 systemd.services.git-daemon = {
129 after = [ "network.target" ];
130 wantedBy = [ "multi-user.target" ];
131 script =
132 "${lib.getExe cfg.package} daemon --reuseaddr "
133 + (lib.optionalString (cfg.basePath != "") "--base-path=${cfg.basePath} ")
134 + (lib.optionalString (cfg.listenAddress != "") "--listen=${cfg.listenAddress} ")
135 + "--port=${toString cfg.port} --user=${cfg.user} --group=${cfg.group} ${cfg.options} "
136 + "--verbose "
137 + (lib.optionalString cfg.exportAll "--export-all ")
138 + lib.concatStringsSep " " cfg.repositories;
139 };
140
141 };
142
143}