all repos

mugit @ dc62a68

🐮 git server that your cow will love

mugit/flake.nix (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
feat: add rss feeds, 3 months ago
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-rY/O5padrE0cwwnvLIR3lM9xdpwloy0OFbp6/ge5gAc=";
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
}