Explorar o código

feat: add Gogs Git service NixOS module and package

- Add packages/gogs.nix with buildGoModule derivation for Gogs v0.14.3
- Add modules/nixos/gogs.nix with managed user/group, tmpfiles, systemd
  hardening (NoNewPrivileges, ProtectSystem, PrivateTmp), INI config
  generation, and optional environmentFile for secrets
- Register gogs in packages/default.nix
Zander Hawke hai 1 día
pai
achega
0c502fa50c
Modificáronse 5 ficheiros con 174 adicións e 0 borrados
  1. 1 0
      .gitignore
  2. 4 0
      home/features/cli/git.nix
  3. 125 0
      modules/nixos/gogs.nix
  4. 1 0
      packages/default.nix
  5. 43 0
      packages/gogs.nix

+ 1 - 0
.gitignore

@@ -9,3 +9,4 @@ key*
 home/features/desktop/vivaldi
 hosts/heimdall/
 lima.yaml
+.agents

+ 4 - 0
home/features/cli/git.nix

@@ -64,6 +64,10 @@ in
         condition = "gitdir/i:~/workspace/control/**";
         contents = control;
       }
+      {
+        condition = "gitdir/i:~/workspace/enesis/**";
+        contents = control;
+      }
       {
         condition = "gitdir/i:~/workspace/zofie/**";
         contents = zofie-architect;

+ 125 - 0
modules/nixos/gogs.nix

@@ -0,0 +1,125 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+let
+  cfg = config.services.gogs;
+  iniFormat = pkgs.formats.ini { };
+  configFile = iniFormat.generate "gogs.ini" cfg.settings;
+in
+{
+  options.services.gogs = {
+    enable = lib.mkEnableOption "Gogs Git service";
+
+    package = lib.mkPackageOption pkgs "gogs" { };
+
+    user = lib.mkOption {
+      type = lib.types.str;
+      default = "gogs";
+      description = "User account under which Gogs runs.";
+    };
+
+    group = lib.mkOption {
+      type = lib.types.str;
+      default = "gogs";
+      description = "Group under which Gogs runs.";
+    };
+
+    stateDir = lib.mkOption {
+      type = lib.types.str;
+      default = "/var/lib/gogs";
+      description = "Persistent data directory.";
+    };
+
+    environmentFile = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
+      default = null;
+      description = ''
+        File containing environment variables to pass to the Gogs service,
+        formatted as VARIABLE=VALUE per line. Values set here are merged into
+        the service's environment and can be used to pass secrets (e.g.
+        database passwords) without putting them in the Nix store.
+      '';
+    };
+
+    settings = lib.mkOption {
+      type = iniFormat.type;
+      default = { };
+
+      example = lib.literalExpression ''
+        {
+          server = {
+            DOMAIN = "git.example.com";
+            ROOT_URL = "https://git.example.com/";
+            HTTP_PORT = 3000;
+          };
+
+          database = {
+            TYPE = "sqlite3";
+            PATH = "/var/lib/gogs/data/gogs.db";
+          };
+        }
+      '';
+
+      description = ''
+        Settings written to app.ini.
+
+        See:
+        https://gogs.io/docs/advanced/configuration_cheat_sheet
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+
+    users.users.${cfg.user} = {
+      isSystemUser = true;
+      group = cfg.group;
+      home = cfg.stateDir;
+      createHome = true;
+    };
+
+    users.groups.${cfg.group} = { };
+
+    systemd.tmpfiles.rules = [
+      "d ${cfg.stateDir} 0750 ${cfg.user} ${cfg.group} -"
+      "d ${cfg.stateDir}/repositories 0750 ${cfg.user} ${cfg.group} -"
+      "d ${cfg.stateDir}/data 0750 ${cfg.user} ${cfg.group} -"
+      "d ${cfg.stateDir}/log 0750 ${cfg.user} ${cfg.group} -"
+    ];
+
+    systemd.services.gogs = {
+      description = "Gogs Git Service";
+
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        Type = "simple";
+
+        User = cfg.user;
+        Group = cfg.group;
+
+        WorkingDirectory = cfg.stateDir;
+
+        ExecStart = "${lib.getExe cfg.package} web --config ${configFile}";
+
+        Restart = "on-failure";
+
+        EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
+
+        NoNewPrivileges = true;
+        PrivateTmp = true;
+        ProtectSystem = "strict";
+        ProtectHome = true;
+
+        ReadWritePaths = [
+          cfg.stateDir
+        ];
+      };
+    };
+  };
+}

+ 1 - 0
packages/default.nix

@@ -19,6 +19,7 @@
   default = pkgs.callPackage ./quick-setup.nix { };
   grist-core = pkgs.callPackage ./grist-core { };
   go-avahi-cname = pkgs.callPackage ./go-avahi-cname.nix { };
+  gogs = pkgs.callPackage ./gogs.nix { };
   hello = pkgs.callPackage ./hello.nix { };
   nct6775-pwm-udev-package = pkgs.callPackage ./nct6775-pwm-udev-package.nix { };
   photo-cli = pkgs.callPackage ./photo-cli.nix { };

+ 43 - 0
packages/gogs.nix

@@ -0,0 +1,43 @@
+{
+  lib,
+  fetchFromGitHub,
+  buildGoModule,
+  pam,
+  stdenv,
+}:
+
+buildGoModule rec {
+  pname = "gogs";
+  version = "0.14.3";
+
+  src = fetchFromGitHub {
+    owner = "gogs";
+    repo = "gogs";
+    rev = "v${version}";
+    hash = "sha256-/WWOH6Tx/zxhYJlIaK6kcEKUUzUXOT30ONAx1FpZLMY=";
+  };
+
+  vendorHash = "sha256-k+PdCynhcnerlk7Ut+GbA0P7KEC/eDW8RY1tCmIEeWQ=";
+  buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ pam ];
+
+  tags = [
+    "cert"
+    "sqlite"
+  ]
+  ++ lib.optionals stdenv.hostPlatform.isLinux [ "pam" ];
+
+  subPackages = [ "." ];
+
+  postInstall = ''
+    mkdir -p $out/share/gogs
+    cp -r conf templates public $out/share/gogs/
+  '';
+
+  meta = {
+    description = "Painless self-hosted Git service customized for isolated environment execution";
+    homepage = "https://gogs.io";
+    license = lib.licenses.mit;
+    platforms = lib.platforms.unix;
+    mainProgram = "gogs";
+  };
+}