gitscope
← rgit / main / flake.nix
https://dev.kronoz.win/r/rgit.git
flake.nix · Nix
Blame Raw
  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}