|
1
|
{ |
|
2
|
description = "a git server that your cow will love"; |
|
3
|
inputs = { |
|
4
|
nixpkgs.url = "github:NixOS/nixpkgs"; |
|
5
|
flake-utils.url = "github:numtide/flake-utils"; |
|
6
|
}; |
|
7
|
outputs = |
|
8
|
{ |
|
9
|
self, |
|
10
|
nixpkgs, |
|
11
|
flake-utils, |
|
12
|
}: |
|
13
|
flake-utils.lib.eachDefaultSystem ( |
|
14
|
system: |
|
15
|
let |
|
16
|
pkgs = nixpkgs.legacyPackages.${system}; |
|
17
|
version = self.rev or "dev"; |
|
18
|
in |
|
19
|
{ |
|
20
|
packages = { |
|
21
|
default = self.packages.${system}.mugit; |
|
22
|
mugit = pkgs.buildGoModule { |
|
23
|
pname = "mugit"; |
|
24
|
version = version; |
|
25
|
src = ./.; |
|
26
|
vendorHash = "sha256-VcNnosr9Co+MFEA36s4BIDmg/bx+/mTIHdgOaGJKhbc="; |
|
27
|
ldflags = [ |
|
28
|
"-s" |
|
29
|
"-w" |
|
30
|
"-X main.version=${version}" |
|
31
|
]; |
|
32
|
meta = with pkgs.lib; { |
|
33
|
homepage = "https://github.com/olexsmir/mugit"; |
|
34
|
license = licenses.mit; |
|
35
|
}; |
|
36
|
}; |
|
37
|
}; |
|
38
|
} |
|
39
|
) |
|
40
|
// { |
|
41
|
nixosModules.default = |
|
42
|
{ |
|
43
|
config, |
|
44
|
lib, |
|
45
|
pkgs, |
|
46
|
... |
|
47
|
}: |
|
48
|
with lib; |
|
49
|
let |
|
50
|
cfg = config.services.mugit; |
|
51
|
format = pkgs.formats.yaml { }; |
|
52
|
configFile = |
|
53
|
if cfg.configFile != null then cfg.configFile else format.generate "config.yaml" cfg.config; |
|
54
|
|
|
55
|
mugitWrapper = pkgs.symlinkJoin { |
|
56
|
name = "mugit"; |
|
57
|
paths = [ cfg.package ]; |
|
58
|
buildInputs = [ pkgs.makeWrapper ]; |
|
59
|
postBuild = '' |
|
60
|
wrapProgram $out/bin/mugit \ |
|
61
|
--add-flags "--config ${configFile}" |
|
62
|
''; |
|
63
|
}; |
|
64
|
|
|
65
|
mugitWithCompletions = pkgs.stdenv.mkDerivation { |
|
66
|
pname = "mugit"; |
|
67
|
version = cfg.package.version; |
|
68
|
src = mugitWrapper; |
|
69
|
nativeBuildInputs = [ pkgs.installShellFiles ]; |
|
70
|
installPhase = '' |
|
71
|
mkdir -p $out/bin |
|
72
|
cp -r $src/bin/* $out/bin/ |
|
73
|
|
|
74
|
installShellCompletion --cmd mugit \ |
|
75
|
--bash <($out/bin/mugit completion bash) \ |
|
76
|
--zsh <($out/bin/mugit completion zsh) \ |
|
77
|
--fish <($out/bin/mugit completion fish) |
|
78
|
''; |
|
79
|
}; |
|
80
|
in |
|
81
|
{ |
|
82
|
options.services.mugit = { |
|
83
|
enable = mkEnableOption "mugit service"; |
|
84
|
|
|
85
|
package = mkOption { |
|
86
|
type = types.package; |
|
87
|
default = self.packages.${pkgs.system}.mugit; |
|
88
|
defaultText = literalExpression "self.packages.\${pkgs.system}.mugit"; |
|
89
|
description = "The mugit package to use."; |
|
90
|
}; |
|
91
|
|
|
92
|
openFirewall = mkOption { |
|
93
|
type = types.bool; |
|
94
|
default = false; |
|
95
|
description = "Whether to open the firewall for mugit. Can only be used with `config`, not `configFile`."; |
|
96
|
}; |
|
97
|
|
|
98
|
exposeCli = mkOption { |
|
99
|
type = types.bool; |
|
100
|
default = true; |
|
101
|
description = "Whether to expose the mugit CLI to all users with the service configuration."; |
|
102
|
}; |
|
103
|
|
|
104
|
dataDir = mkOption { |
|
105
|
type = types.path; |
|
106
|
default = "/var/lib/mugit"; |
|
107
|
description = "Directory where mugit stores its data."; |
|
108
|
}; |
|
109
|
|
|
110
|
configFile = mkOption { |
|
111
|
type = types.nullOr types.path; |
|
112
|
default = null; |
|
113
|
description = "Path to an existing mugit configuration file. Mutually exclusive with `config`."; |
|
114
|
}; |
|
115
|
|
|
116
|
config = mkOption { |
|
117
|
type = format.type; |
|
118
|
default = { }; |
|
119
|
description = '' |
|
120
|
Configuration for mugit. See documentation for available options. |
|
121
|
https://github.com/olexsmir/mugit/blob/main/README.md |
|
122
|
''; |
|
123
|
example = literalExpression '' |
|
124
|
{ |
|
125
|
server.port = 8080; |
|
126
|
repo.dir = "/var/lib/mugit"; |
|
127
|
} |
|
128
|
''; |
|
129
|
}; |
|
130
|
|
|
131
|
user = mkOption { |
|
132
|
type = types.str; |
|
133
|
default = "mugit"; |
|
134
|
description = "User account under which mugit runs."; |
|
135
|
}; |
|
136
|
|
|
137
|
group = mkOption { |
|
138
|
type = types.str; |
|
139
|
default = "mugit"; |
|
140
|
description = "Group under which mugit runs."; |
|
141
|
}; |
|
142
|
|
|
143
|
}; |
|
144
|
|
|
145
|
config = mkIf cfg.enable { |
|
146
|
assertions = [ |
|
147
|
{ |
|
148
|
assertion = !(cfg.config != { } && cfg.configFile != null); |
|
149
|
message = "services.mugit: `config` and `configFile` are mutually exclusive. Only one can be set."; |
|
150
|
} |
|
151
|
{ |
|
152
|
assertion = !(cfg.openFirewall && cfg.configFile != null); |
|
153
|
message = "services.mugit: `openFirewall` cannot be used with `configFile`. Set firewall rules manually or use `config` instead."; |
|
154
|
} |
|
155
|
]; |
|
156
|
|
|
157
|
environment.systemPackages = mkIf cfg.exposeCli [ mugitWithCompletions ]; |
|
158
|
|
|
159
|
networking.firewall = mkIf cfg.openFirewall { |
|
160
|
allowedTCPPorts = |
|
161
|
let |
|
162
|
serverPort = cfg.config.server.port or 8080; |
|
163
|
sshPort = cfg.config.ssh.port or 2222; |
|
164
|
sshEnabled = cfg.config.ssh.enable or false; |
|
165
|
in |
|
166
|
[ serverPort ] ++ lib.optional sshEnabled sshPort; |
|
167
|
}; |
|
168
|
|
|
169
|
users.users.${cfg.user} = { |
|
170
|
isSystemUser = true; |
|
171
|
group = cfg.group; |
|
172
|
home = cfg.dataDir; |
|
173
|
createHome = true; |
|
174
|
description = "mugit service user"; |
|
175
|
}; |
|
176
|
|
|
177
|
users.groups.${cfg.group} = { }; |
|
178
|
|
|
179
|
systemd.services.mugit = { |
|
180
|
description = "mugit service"; |
|
181
|
wantedBy = [ "multi-user.target" ]; |
|
182
|
after = [ "network.target" ]; |
|
183
|
path = [ pkgs.git ]; |
|
184
|
|
|
185
|
serviceConfig = |
|
186
|
let |
|
187
|
serverPort = cfg.config.server.port or 8080; |
|
188
|
sshPort = cfg.config.ssh.port or 2222; |
|
189
|
sshEnabled = cfg.config.ssh.enable or false; |
|
190
|
needsPrivPort = serverPort < 1024 || (sshEnabled && sshPort < 1024); |
|
191
|
in |
|
192
|
{ |
|
193
|
Type = "simple"; |
|
194
|
User = cfg.user; |
|
195
|
Group = cfg.group; |
|
196
|
WorkingDirectory = cfg.dataDir; |
|
197
|
StateDirectory = "mugit"; |
|
198
|
ExecStart = "${cfg.package}/bin/mugit serve --config ${configFile}"; |
|
199
|
Restart = "on-failure"; |
|
200
|
RestartSec = "5s"; |
|
201
|
NoNewPrivileges = true; |
|
202
|
PrivateTmp = true; |
|
203
|
ProtectSystem = "strict"; |
|
204
|
ProtectHome = true; |
|
205
|
ReadWritePaths = [ cfg.dataDir ]; |
|
206
|
ProtectKernelTunables = true; |
|
207
|
ProtectKernelModules = true; |
|
208
|
ProtectControlGroups = true; |
|
209
|
} |
|
210
|
// lib.optionalAttrs needsPrivPort { |
|
211
|
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; |
|
212
|
}; |
|
213
|
}; |
|
214
|
}; |
|
215
|
}; |
|
216
|
}; |
|
217
|
} |