https://dev.kronoz.win/r/rgit.git
1{
2 inputs = {
3 nixpkgs.url = "github:NixOS/nixpkgs";
4
5 crane.url = "github:ipetkov/crane";
6 utils.url = "github:numtide/flake-utils";
7 treefmt-nix.url = "github:numtide/treefmt-nix";
8
9 advisory-db = {
10 url = "github:rustsec/advisory-db";
11 flake = false;
12 };
13
14 helix = {
15 url = "github:JordanForks/helix";
16 flake = false;
17 };
18
19 nix-github-actions = {
20 url = "github:nix-community/nix-github-actions";
21 inputs.nixpkgs.follows = "nixpkgs";
22 };
23 };
24
25 outputs = { self, nixpkgs, utils, crane, advisory-db, treefmt-nix, helix, nix-github-actions }:
26 {
27 githubActions = nix-github-actions.lib.mkGithubMatrix {
28 checks =
29 builtins.mapAttrs
30 (name: value: if name != "x86_64-linux" then removeAttrs value [ "clippy" "audit" "formatting" "doc" ] else value)
31 { inherit (self.checks) x86_64-linux aarch64-darwin; };
32 };
33 }
34 //
35 utils.lib.eachDefaultSystem (system:
36 let
37 pkgs = import nixpkgs { inherit system; };
38 craneLib = crane.mkLib pkgs;
39 cargoOnlySrc = craneLib.cleanCargoSource ./.;
40 src = pkgs.lib.fileset.toSource {
41 root = ./.;
42 fileset = pkgs.lib.fileset.unions [
43 ./.cargo
44 ./Cargo.toml
45 ./Cargo.lock
46 ./tree-sitter-grammar-repository
47 ./src
48 ./statics
49 ./templates
50 ./themes
51 ./deny.toml
52 ./build.rs
53 ];
54 };
55 rgit-grammar = pkgs.callPackage ./grammars.nix { inherit helix; };
56 commonArgs = {
57 inherit src;
58 strictDeps = true;
59 buildInputs = pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.libiconv ];
60 nativeBuildInputs = with pkgs; [ cmake clang makeBinaryWrapper ];
61 LIBCLANG_PATH = "${pkgs.clang.cc.lib}/lib";
62 ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib";
63 SNAPPY_LIB_DIR = "${pkgs.snappy}/lib";
64 };
65 cargoArtifacts = craneLib.buildDepsOnly (commonArgs // { src = cargoOnlySrc; });
66 buildArgs = commonArgs // {
67 inherit cargoArtifacts;
68 buildInputs = [ rgit-grammar ] ++ commonArgs.buildInputs;
69 TREE_SITTER_GRAMMAR_LIB_DIR = rgit-grammar;
70 };
71 rgit = craneLib.buildPackage (buildArgs // {
72 doCheck = false;
73 postInstall = ''
74 wrapProgram $out/bin/rgit \
75 --set PATH ${pkgs.lib.makeBinPath [ pkgs.gitMinimal ]}
76 '';
77 });
78 treefmt = treefmt-nix.lib.evalModule pkgs ./treefmt.nix;
79 in
80 {
81 checks = {
82 build = rgit;
83 clippy = craneLib.cargoClippy buildArgs;
84 doc = craneLib.cargoDoc buildArgs;
85 audit = craneLib.cargoAudit { inherit advisory-db; src = cargoOnlySrc; };
86 deny = craneLib.cargoDeny { inherit src; };
87 test = craneLib.cargoNextest (buildArgs // {
88 partitions = 1;
89 partitionType = "count";
90 });
91 formatting = treefmt.config.build.check self;
92 };
93
94 formatter = treefmt.config.build.wrapper;
95
96 packages.default = rgit;
97 apps.default = utils.lib.mkApp { drv = rgit; };
98
99 devShells.default = craneLib.devShell {
100 checks = self.checks.${system};
101 packages = with pkgs; [ rust-analyzer clang ];
102 RUST_SRC_PATH = pkgs.rustPlatform.rustLibSrc;
103 LIBCLANG_PATH = "${pkgs.clang.cc.lib}/lib";
104 TREE_SITTER_GRAMMAR_LIB_DIR = rgit-grammar;
105 ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib";
106 SNAPPY_LIB_DIR = "${pkgs.snappy}/lib";
107 };
108
109 nixosModules.default = { config, lib, pkgs, ... }:
110 with lib;
111 let
112 cfg = config.services.rgit;
113 in
114 {
115 options.services.rgit = {
116 enable = mkEnableOption "rgit";
117 bindAddress = mkOption {
118 default = "[::]:8333";
119 description = "Address and port to listen on";
120 type = types.str;
121 };
122 dbStorePath = mkOption {
123 default = "/tmp/rgit.db";
124 description = "Path to store the temporary cache";
125 type = types.path;
126 };
127 repositoryStorePath = mkOption {
128 default = "/git";
129 description = "Path to repositories";
130 type = types.path;
131 };
132 requestTimeout = mkOption {
133 default = "10s";
134 description = "Timeout for incoming HTTP requests";
135 type = types.str;
136 };
137 package = mkOption {
138 default = rgit;
139 description = "rgit package to use";
140 type = types.package;
141 };
142 };
143
144 config = mkIf cfg.enable {
145 users.groups.rgit = { };
146 users.users.rgit = {
147 description = "RGit service user";
148 group = "rgit";
149 isSystemUser = true;
150 home = "/git";
151 };
152
153 systemd.services.rgit = {
154 enable = true;
155 wantedBy = [ "multi-user.target" ];
156 wants = [ "network-online.target" ];
157 after = [ "network-online.target" ];
158 path = [ pkgs.git ];
159 serviceConfig = {
160 Type = "exec";
161 ExecStart = "${cfg.package}/bin/rgit --request-timeout ${cfg.requestTimeout} --db-store ${cfg.dbStorePath} ${cfg.bindAddress} ${cfg.repositoryStorePath}";
162 Restart = "on-failure";
163
164 User = "rgit";
165 Group = "rgit";
166
167 CapabilityBoundingSet = "";
168 NoNewPrivileges = true;
169 PrivateDevices = true;
170 PrivateTmp = true;
171 PrivateUsers = true;
172 PrivateMounts = true;
173 ProtectHome = true;
174 ProtectClock = true;
175 ProtectProc = "noaccess";
176 ProcSubset = "pid";
177 ProtectKernelLogs = true;
178 ProtectKernelModules = true;
179 ProtectKernelTunables = true;
180 ProtectControlGroups = true;
181 ProtectHostname = true;
182 RestrictSUIDSGID = true;
183 RestrictRealtime = true;
184 RestrictNamespaces = true;
185 LockPersonality = true;
186 RemoveIPC = true;
187 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
188 SystemCallFilter = [ "@system-service" "~@privileged" ];
189 };
190 };
191 };
192 };
193 });
194
195 nixConfig = {
196 extra-substituters = [ "https://rgit.cachix.org" ];
197 extra-trusted-public-keys = [ "rgit.cachix.org-1:3Wva/GHhrlhbYx+ObbEYQSYq1Yzk8x9OAvEvcYazgL0=" ];
198 };
199}