Home

ugit @main - refs - log -
-
https://git.jolheiser.com/ugit.git
The code powering this h*ckin' site
tree log patch
feat: split out nix package/module Signed-off-by: jolheiser <git@jolheiser.com>
Signature
-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgBTEvCQk6VqUAdN2RuH6bj1dNkY oOpbPWj+jw4ua1B1cAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQIvYV9j5vtr2DsQMnLRC61y2+OZJbCAaURVN2Qpe1YldvExJqWykfry5PEIJBW2Bif wtk4zS8yunOp0gJbwpgwo= -----END SSH SIGNATURE-----
jolheiser <git@jolheiser.com>
3 months ago
8 changed files, 295 additions(+), 614 deletions(-)
M flake.lock -> flake.lock
diff --git a/flake.lock b/flake.lock
index 6e136355501a7bd20ed340e161b8a9c3bb6f2232..401c49c1b22e48b7a61e6369c038b8dce12c0711 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,44 +1,5 @@
 {
   "nodes": {
-    "flake-utils": {
-      "inputs": {
-        "systems": "systems"
-      },
-      "locked": {
-        "lastModified": 1694529238,
-        "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
-    },
-    "gomod2nix": {
-      "inputs": {
-        "flake-utils": "flake-utils",
-        "nixpkgs": [
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1717050755,
-        "narHash": "sha256-C9IEHABulv2zEDFA+Bf0E1nmfN4y6MIUe5eM2RCrDC0=",
-        "owner": "nix-community",
-        "repo": "gomod2nix",
-        "rev": "31b6d2e40b36456e792cd6cf50d5a8ddd2fa59a1",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-community",
-        "repo": "gomod2nix",
-        "type": "github"
-      }
-    },
     "nixpkgs": {
       "locked": {
         "lastModified": 1719379843,
@@ -58,26 +19,9 @@     },
     "root": {
       "inputs": {
     "flake-utils": {
-        "systems": "systems"
-    "flake-utils": {
       },
         "tailwind-ctp": "tailwind-ctp",
         "tailwind-ctp-lsp": "tailwind-ctp-lsp"
-      }
-    },
-    "systems": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
       }
     },
     "tailwind-ctp": {
M flake.nix -> flake.nix
diff --git a/flake.nix b/flake.nix
index a7aedde25dd2d58ef845a996061106319e23ae97..cad65fe16198ecb1284d5246af9d2186eb90e6fa 100644
--- a/flake.nix
+++ b/flake.nix
@@ -3,10 +3,6 @@   description = "Minimal git server";
 
   inputs = {
     nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
-    gomod2nix = {
-      url = "github:nix-community/gomod2nix";
-      inputs.nixpkgs.follows = "nixpkgs";
-    };
     tailwind-ctp = {
       url = "git+https://git.jolheiser.com/tailwind-ctp";
       inputs.nixpkgs.follows = "nixpkgs";
@@ -18,238 +14,112 @@     };
   };
 
 {
-    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
-{
+  inputs = {
     gomod2nix = {
 {
+  inputs = {
       url = "github:nix-community/gomod2nix";
 {
+  inputs = {
       inputs.nixpkgs.follows = "nixpkgs";
 {
+  inputs = {
     };
-    tailwind-ctp-lsp,
-  description = "Minimal git server";
 {
-    system = "x86_64-linux";
-    pkgs = nixpkgs.legacyPackages.${system};
-    tailwind-ctp = inputs.tailwind-ctp.packages.${system}.default;
-  description = "Minimal git server";
     nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
-    ugit = gomod2nix.legacyPackages.${system}.buildGoApplication rec {
-      name = "ugitd";
-      src = pkgs.nix-gitignore.gitignoreSource [] (builtins.path {
-        inherit name;
-
-
 {
-      pwd = ./.;
-      subPackages = ["cmd/ugitd" "cmd/ugit-uci"];
-      CGO_ENABLED = 0;
-
     nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
-        "-trimpath"
-      ];
-      ldflags = [
-        "-s"
-        "-w"
-  inputs = {
 {
-      ];
-      meta = with pkgs.lib; {
-        description = "Minimal git server";
-        homepage = "https://git.jolheiser.com/ugit";
-        maintainers = with maintainers; [jolheiser];
-        mainProgram = "ugitd";
-      };
-    };
-  in {
-    packages.${system}.default = ugit;
-    devShells.${system}.default = pkgs.mkShell {
-    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
 {
         go
+{
         gopls
+{
         gomod2nix.legacyPackages.${system}.gomod2nix
+{
         templ
+{
         tailwind-ctp
+{
         tailwind-ctp-lsp
+{
         vscode-langservers-extracted
-      ];
-    };
-    nixosModules.default = {
-      pkgs,
-    gomod2nix = {
 {
-      config,
-      ...
-    }: let
-    gomod2nix = {
     nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
-      yamlFormat = pkgs.formats.yaml {};
-      configFile = pkgs.writeText "ugit.yaml" (builtins.readFile (yamlFormat.generate "ugit-yaml" cfg.config));
-      authorizedKeysFile = pkgs.writeText "ugit_keys" (builtins.concatStringsSep "\n" cfg.authorizedKeys);
-    gomod2nix = {
     };
-      options = let
-      url = "github:nix-community/gomod2nix";
 {
-      in {
-        services.ugit = {
-          enable = mkEnableOption "Enable ugit";
-
-          package = mkOption {
-      url = "github:nix-community/gomod2nix";
     gomod2nix = {
-            description = "ugit package to use";
-            default = ugit;
-          };
-
-      inputs.nixpkgs.follows = "nixpkgs";
-            type = types.str;
-            description = "Tailscale one-time auth-key";
-      inputs.nixpkgs.follows = "nixpkgs";
 
       url = "github:nix-community/gomod2nix";
-    };
-
-          repoDir = mkOption {
-      inputs.nixpkgs.follows = "nixpkgs";
 {
-            description = "where ugit stores repositories";
-      inputs.nixpkgs.follows = "nixpkgs";
     gomod2nix = {
-          };
-
-          authorizedKeys = mkOption {
-            type = types.listOf types.str;
-            description = "list of keys to use for authorized_keys";
-            default = [];
-          };
-
-    };
 {
-      inputs.nixpkgs.follows = "nixpkgs";
 {
-    };
+    gomod2nix = {
   description = "Minimal git server";
-            default = "/var/lib/ugit/authorized_keys";
-          };
-
-          hostKeyFile = mkOption {
-      inputs.nixpkgs.follows = "nixpkgs";
 {
-            description = "path to host key file (will be created if it doesn't exist)";
-    };
     gomod2nix = {
-          };
 
-          config = mkOption {
-            type = types.attrs;
-            default = {};
 {
-          };
-
-          user = mkOption {
-            type = types.str;
-            default = "ugit";
+    }: let
 {
-
-          };
-
-    tailwind-ctp = {
   inputs = {
-            type = types.str;
-            default = "ugit";
-            description = "Group account under which ugit runs";
       url = "github:nix-community/gomod2nix";
-    };
-
 {
     gomod2nix = {
-            type = types.bool;
-            default = false;
-          };
-        };
-      };
-      config = lib.mkIf cfg.enable {
-        users.users."${cfg.user}" = {
-          home = "/var/lib/ugit";
-          createHome = true;
-          group = "${cfg.group}";
-      url = "git+https://git.jolheiser.com/tailwind-ctp";
     nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
 {
-{
+    gomod2nix = {
     gomod2nix = {
 {
-{
+    gomod2nix = {
       url = "github:nix-community/gomod2nix";
 {
-    };
-      url = "git+https://git.jolheiser.com/tailwind-ctp";
+    gomod2nix = {
       inputs.nixpkgs.follows = "nixpkgs";
 {
-{
+    gomod2nix = {
     };
 {
-  description = "Minimal git server";
+      url = "github:nix-community/gomod2nix";
 {
-    };
-
-    tailwind-ctp-lsp = {
+      url = "github:nix-community/gomod2nix";
 {
 {
-  description = "Minimal git server";
+      url = "github:nix-community/gomod2nix";
   description = "Minimal git server";
 {
-  description = "Minimal git server";
+      url = "github:nix-community/gomod2nix";
 
 {
-  description = "Minimal git server";
+      url = "github:nix-community/gomod2nix";
   inputs = {
 {
-  description = "Minimal git server";
+      url = "github:nix-community/gomod2nix";
     nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
 {
-  description = "Minimal git server";
+      url = "github:nix-community/gomod2nix";
     gomod2nix = {
 {
-  description = "Minimal git server";
+      url = "github:nix-community/gomod2nix";
       url = "github:nix-community/gomod2nix";
 {
-  description = "Minimal git server";
+      url = "github:nix-community/gomod2nix";
       inputs.nixpkgs.follows = "nixpkgs";
 {
-  description = "Minimal git server";
+      url = "github:nix-community/gomod2nix";
     };
       url = "git+https://git.jolheiser.com/tailwind-ctp-intellisense";
-{
 
-{
-              "--ssh.host-key=${cfg.hostKeyFile}"
-            ];
-          in "${cfg.package}/bin/ugitd ${builtins.concatStringsSep " " args}";
-          wantedBy = ["multi-user.target"];
-          after = ["network.target"];
-      url = "git+https://git.jolheiser.com/tailwind-ctp-intellisense";
       url = "github:nix-community/gomod2nix";
+    };
 {
-
       inputs.nixpkgs.follows = "nixpkgs";
-            User = cfg.user;
-  };
 {
-  inputs = {
+      inputs.nixpkgs.follows = "nixpkgs";
 {
 {
-  inputs = {
+      inputs.nixpkgs.follows = "nixpkgs";
   description = "Minimal git server";
-            WorkingDirectory = "/var/lib/ugit";
-            Environment = ["TS_AUTHKEY=${cfg.tsAuthKey}"];
-      url = "github:nix-community/gomod2nix";
     };
-        };
-      };
-    };
-  };
 }
I go.mod.sri
diff --git a/go.mod.sri b/go.mod.sri
new file mode 100644
index 0000000000000000000000000000000000000000..0b80bc88828f5c9249871e9ec9d93c694830401f
--- /dev/null
+++ b/go.mod.sri
@@ -0,0 +1 @@
+sha256-F0NrjQA92ckDdEzlvXsycXLMOF/995CyzsSrR3j08Gs=
\ No newline at end of file
D gomod2nix.toml
diff --git a/gomod2nix.toml b/gomod2nix.toml
deleted file mode 100644
index 53153eb6db6f04c40480a5c63abbfa6b3be50a92..0000000000000000000000000000000000000000
--- a/gomod2nix.toml
+++ /dev/null
@@ -1,399 +0,0 @@
-schema = 3
-
-[mod]
-  [mod."dario.cat/mergo"]
-    version = "v1.0.0"
-    hash = "sha256-jlpc8dDj+DmiOU4gEawBu8poJJj9My0s9Mvuk9oS8ww="
-  [mod."filippo.io/edwards25519"]
-    version = "v1.1.0"
-    hash = "sha256-9ACANrgWZSd5HYPfDZHY8DVbPSC9LOMgy8deq3rDOoc="
-  [mod."github.com/Microsoft/go-winio"]
-    version = "v0.6.1"
-    hash = "sha256-BL0BVaHtmPKQts/711W59AbHXjGKqFS4ZTal0RYnR9I="
-  [mod."github.com/ProtonMail/go-crypto"]
-    version = "v1.0.0"
-    hash = "sha256-Gflazvyv+457FpUTtPafJ+SdolYSalpsU0tragTxNi8="
-  [mod."github.com/a-h/templ"]
-    version = "v0.2.543"
-    hash = "sha256-1BvIj9UPZJp8SOXMPIGdHyZLIvjORHg2UY3pRZJM01s="
-  [mod."github.com/akutz/memconn"]
-    version = "v0.1.0"
-    hash = "sha256-WOs/RQYjQbn41ui8ztHgWSd4jxydE+fvIrl/0dmHD9Y="
-  [mod."github.com/alecthomas/chroma/v2"]
-    version = "v2.12.0"
-    hash = "sha256-w3gKGPwsoayknuU4ifPaF0JOMNqnKjIEutbIkR9c2Ag="
-  [mod."github.com/alexbrainman/sspi"]
-    version = "v0.0.0-20231016080023-1a75b4708caa"
-    hash = "sha256-Joa/NfBofK7lRlknQ5LVYD4M/dpd9xaCqsvYUBhKW0I="
-  [mod."github.com/anmitsu/go-shlex"]
-    version = "v0.0.0-20200514113438-38f4b401e2be"
-    hash = "sha256-L3Ak4X2z7WXq7vMKuiHCOJ29nlpajUQ08Sfb9T0yP54="
-  [mod."github.com/aws/aws-sdk-go-v2"]
-    version = "v1.24.1"
-    hash = "sha256-qZDUrodVDWWtdQ6zYuNHxpXt2quK56pPoZsKdRGmYzk="
-  [mod."github.com/aws/aws-sdk-go-v2/config"]
-    version = "v1.26.5"
-    hash = "sha256-RAXQlnUAsxgi2BndS+Uh2Cw+TCbtUx9BB0Tqqz50rLE="
-  [mod."github.com/aws/aws-sdk-go-v2/credentials"]
-    version = "v1.16.16"
-    hash = "sha256-qjtE3/VxNAEtS68nLXULgjO+LO3EkayGkr2iU300xdA="
-  [mod."github.com/aws/aws-sdk-go-v2/feature/ec2/imds"]
-    version = "v1.14.11"
-    hash = "sha256-j8LHZYM+rBmWHV1PT/H6lDL/3vgBqvQxoY2bVuOi7zo="
-  [mod."github.com/aws/aws-sdk-go-v2/internal/configsources"]
-    version = "v1.2.10"
-    hash = "sha256-fhrws72g+ecgXnkiip0GQ206XfVdxDA7/Rz9X3nvgd8="
-  [mod."github.com/aws/aws-sdk-go-v2/internal/endpoints/v2"]
-    version = "v2.5.10"
-    hash = "sha256-Rbj+matn96a/3Nj8EpLgrTycSV+331+WWJd5Lpk1LlQ="
-  [mod."github.com/aws/aws-sdk-go-v2/internal/ini"]
-    version = "v1.7.2"
-    hash = "sha256-6ev22rRSz4TuoX1AoCDr67qA15kg+cHMuQeTXwp8AFg="
-  [mod."github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding"]
-    version = "v1.10.4"
-    hash = "sha256-Wvbil3pNKlCyn0SWNXCobxzJGeE+2Eb7GNP2OZATTfY="
-  [mod."github.com/aws/aws-sdk-go-v2/service/internal/presigned-url"]
-    version = "v1.10.10"
-    hash = "sha256-vUSnrZzo3mzfZsthjjZRmGNrXkQ4D2B7Glzu66N5MrQ="
-  [mod."github.com/aws/aws-sdk-go-v2/service/ssm"]
-    version = "v1.44.7"
-    hash = "sha256-U7XGN5O0Ksp6O3a2Nkb0WinTwuIHjCw5UNSwPjrMo8k="
-  [mod."github.com/aws/aws-sdk-go-v2/service/sso"]
-    version = "v1.18.7"
-    hash = "sha256-+1q43+9Cx/K3/T+LJJLV1h2PLHsG/YKHUSgwC5r3uNQ="
-  [mod."github.com/aws/aws-sdk-go-v2/service/ssooidc"]
-    version = "v1.21.7"
-    hash = "sha256-aoolSWOU3Sb3weV2yf2wACuh3fYaUmyGXCZ2dTvcg4A="
-  [mod."github.com/aws/aws-sdk-go-v2/service/sts"]
-    version = "v1.26.7"
-    hash = "sha256-0LGfjSa65wNKuV/TH66XfN/uF4lZF9bSszbfTFWcLjY="
-  [mod."github.com/aws/smithy-go"]
-    version = "v1.19.0"
-    hash = "sha256-KsQMOHJFIXRF+8c4WxiXA/u1Ok6hEF6eylvnfdRGivg="
-  [mod."github.com/aymanbagabas/go-osc52/v2"]
-    version = "v2.0.1"
-    hash = "sha256-6Bp0jBZ6npvsYcKZGHHIUSVSTAMEyieweAX2YAKDjjg="
-  [mod."github.com/bits-and-blooms/bitset"]
-    version = "v1.13.0"
-    hash = "sha256-1jccFEH9In72Jt3wSn4vi4/MJd/UDfDrC9DlmsGVc9o="
-  [mod."github.com/charmbracelet/bubbletea"]
-    version = "v0.25.0"
-    hash = "sha256-A0WjFRFAUhwO3m7uvCOeefPPIM8ReU+xTtIRxG0aH+Y="
-  [mod."github.com/charmbracelet/keygen"]
-    version = "v0.5.0"
-    hash = "sha256-JFD2SdFL7tq3oVhnBEgiBTrJvjqdUtIuodAJuSFcJoA="
-  [mod."github.com/charmbracelet/lipgloss"]
-    version = "v0.9.1"
-    hash = "sha256-AHbabOymgDRIXsMBgJHS25/GgBWT54oGbd15EBWKeZc="
-  [mod."github.com/charmbracelet/log"]
-    version = "v0.3.1"
-    hash = "sha256-Er60POPID2eNrRZnBHxoI4yHn0mIKnXYftGKSslbXx0="
-  [mod."github.com/charmbracelet/ssh"]
-    version = "v0.0.0-20240201134204-3f297de25560"
-    hash = "sha256-r4h4bym47rs3C2us+sCgVfwAl4TCbm3bDCTsXKYREz8="
-  [mod."github.com/charmbracelet/wish"]
-    version = "v1.3.0"
-    hash = "sha256-3Uq1PDu5DMoWgJykFx/roGk20x8jdb7o5JFPpmEtX/c="
-  [mod."github.com/charmbracelet/x/errors"]
-    version = "v0.0.0-20240130180102-bafe6fbaee60"
-    hash = "sha256-GO8hf0lhVtl00C+xoTzvBtPU2cO0PymSLc2szBRUNtE="
-  [mod."github.com/charmbracelet/x/exp/term"]
-    version = "v0.0.0-20240130180102-bafe6fbaee60"
-    hash = "sha256-hEj/Gj1U1ahk5EFVZVAL52yrdBNO47yXykpiehJICbc="
-  [mod."github.com/cloudflare/circl"]
-    version = "v1.3.7"
-    hash = "sha256-AkOpcZ+evLxLJStvvr01+TLeWDqcLxY3e/AhGggzh40="
-  [mod."github.com/containerd/console"]
-    version = "v1.0.4-0.20230706203907-8f6c4e4faef5"
-    hash = "sha256-mxRERsgS6TmI5I0UYblhzl2FZlbtkJhUkfF1x6mZINw="
-  [mod."github.com/coreos/go-iptables"]
-    version = "v0.7.1-0.20240112124308-65c67c9f46e6"
-    hash = "sha256-kjnry8ld5Keew5q+tX7GSdGVZaXlehs2Lt+z8Rokhns="
-  [mod."github.com/creack/pty"]
-    version = "v1.1.21"
-    hash = "sha256-pjGw6wQlrVhN65XaIxZueNJqnXThGu00u24rKOLzxS0="
-  [mod."github.com/cyphar/filepath-securejoin"]
-    version = "v0.2.4"
-    hash = "sha256-heCD0xMxlwnHCHcRBgTjVexHOLyWI2zRW3E8NFKoLzk="
-  [mod."github.com/dblohm7/wingoes"]
-    version = "v0.0.0-20240119213807-a09d6be7affa"
-    hash = "sha256-zUj7jSZQiX53+4OyRq7LaQXp8nx8+JRpyT6IFdktyw0="
-  [mod."github.com/digitalocean/go-smbios"]
-    version = "v0.0.0-20180907143718-390a4f403a8e"
-    hash = "sha256-Hgx1ML3rigdYXx5ntnEYD5JEk6kJv1cL0+/GDbnPkbo="
-  [mod."github.com/dlclark/regexp2"]
-    version = "v1.10.0"
-    hash = "sha256-Jxzj/O/Q9tIWBOOgCkCibhrgJBzzfVIxYDsabt7O8ow="
-  [mod."github.com/dustin/go-humanize"]
-    version = "v1.0.1"
-    hash = "sha256-yuvxYYngpfVkUg9yAmG99IUVmADTQA0tMbBXe0Fq0Mc="
-  [mod."github.com/emirpasic/gods"]
-    version = "v1.18.1"
-    hash = "sha256-hGDKddjLj+5dn2woHtXKUdd49/3xdsqnhx7VEdCu1m4="
-  [mod."github.com/fxamacker/cbor/v2"]
-    version = "v2.5.0"
-    hash = "sha256-2rhvuNZjeidDP+Og6Q0u4ROiaPrEOjoI5wCb17XRnOQ="
-  [mod."github.com/gaissmai/bart"]
-    version = "v0.4.1"
-    hash = "sha256-Zz+8yx+y6QtF2raJo01ldzKIlqfxLX3eqLr6ub+Byzw="
-  [mod."github.com/go-chi/chi/v5"]
-    version = "v5.0.11"
-    hash = "sha256-95LKg/OVzhik2HUz6cirHH3eAT4qbHSg52bSvkc+XOY="
-  [mod."github.com/go-chi/httplog/v2"]
-    version = "v2.1.1"
-    hash = "sha256-bMpoHUSNk3Uds9NfrStwhDsdCONR4pJso9sVUhqfidk="
-  [mod."github.com/go-git/gcfg"]
-    version = "v1.5.1-0.20230307220236-3a3c6141e376"
-    hash = "sha256-f4k0gSYuo0/q3WOoTxl2eFaj7WZpdz29ih6CKc8Ude8="
-  [mod."github.com/go-git/go-billy/v5"]
-    version = "v5.5.0"
-    hash = "sha256-4XUoD2bOCMCdu83egb/y8kY/Fm0s1rWgPMtiahh38OQ="
-  [mod."github.com/go-git/go-git/v5"]
-    version = "v5.11.0"
-    hash = "sha256-2yUM/FlV+nYxacVynJCnDZeMub4Iu8JL2WBHmlnwOkE="
-  [mod."github.com/go-json-experiment/json"]
-    version = "v0.0.0-20231102232822-2e55bd4e08b0"
-    hash = "sha256-ltOLec3r0dGA/k1TTrQjuMuHxdxBlALkfLbdKuUNvmg="
-  [mod."github.com/go-logfmt/logfmt"]
-    version = "v0.6.0"
-    hash = "sha256-RtIG2qARd5sT10WQ7F3LR8YJhS8exs+KiuUiVf75bWg="
-  [mod."github.com/go-ole/go-ole"]
-    version = "v1.3.0"
-    hash = "sha256-tF8t3VcV71jQ4jbPL91BwR59AKDpUAFV1waIKzkXJu8="
-  [mod."github.com/godbus/dbus/v5"]
-    version = "v5.1.1-0.20230522191255-76236955d466"
-    hash = "sha256-OdcyeoGQ4xWUpl21WKXkbAm8yZHMDp8giY02arupjb4="
-  [mod."github.com/golang/groupcache"]
-    version = "v0.0.0-20210331224755-41bb18bfe9da"
-    hash = "sha256-7Gs7CS9gEYZkbu5P4hqPGBpeGZWC64VDwraSKFF+VR0="
-  [mod."github.com/google/btree"]
-    version = "v1.1.2"
-    hash = "sha256-K7V2obq3pLM71Mg0vhhHtZ+gtaubwXPQx3xcIyZDCjM="
-  [mod."github.com/google/go-cmp"]
-    version = "v0.6.0"
-    hash = "sha256-qgra5jze4iPGP0JSTVeY5qV5AvEnEu39LYAuUCIkMtg="
-  [mod."github.com/google/nftables"]
-    version = "v0.2.1-0.20240414091927-5e242ec57806"
-    hash = "sha256-OXMzx4Exf++E4UzCUE1gw3TOrfyI187cFu3cDZ9ifKU="
-  [mod."github.com/google/uuid"]
-    version = "v1.6.0"
-    hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw="
-  [mod."github.com/gorilla/csrf"]
-    version = "v1.7.2"
-    hash = "sha256-pzOWbw8AOjhdRJYKlPBfh1j9a8TGNxgrlS4AmZpE1s8="
-  [mod."github.com/gorilla/securecookie"]
-    version = "v1.1.2"
-    hash = "sha256-KeMHNM9emxX+N0WYiZsTii7n8sNsmjWwbnQ9SaJfTKE="
-  [mod."github.com/hdevalence/ed25519consensus"]
-    version = "v0.2.0"
-    hash = "sha256-KTbeKMOT/HCJjDHqyciQjJPPgpNk6H0VyQCCbeGgs7Y="
-  [mod."github.com/illarion/gonotify"]
-    version = "v1.0.1"
-    hash = "sha256-73KDUfk5iNo12u+nNN2H4UTfJ1FlLifahnFNPzV1P/k="
-  [mod."github.com/insomniacslk/dhcp"]
-    version = "v0.0.0-20231206064809-8c70d406f6d2"
-    hash = "sha256-PHiso7HGNjCGbGdZ7TMGnSGzPDUTpvWpqAccoKPAaWM="
-  [mod."github.com/jbenet/go-context"]
-    version = "v0.0.0-20150711004518-d14ea06fba99"
-    hash = "sha256-VANNCWNNpARH/ILQV9sCQsBWgyL2iFT+4AHZREpxIWE="
-  [mod."github.com/jmespath/go-jmespath"]
-    version = "v0.4.0"
-    hash = "sha256-xpT9g2qIXmPq7eeHUXHiDqJeQoHCudh44G/KCSFbcuo="
-  [mod."github.com/josharian/native"]
-    version = "v1.1.1-0.20230202152459-5c7d0dd6ab86"
-    hash = "sha256-dgyrLXuM55z8FAoUjyt5TDlzim6HfphWo5wx1/DHLwE="
-  [mod."github.com/jsimonetti/rtnetlink"]
-    version = "v1.4.0"
-    hash = "sha256-GnrF2yxgm/h1JSTN1PwI4ysTl+oY0AyWzf3Ni7LZqRM="
-  [mod."github.com/kevinburke/ssh_config"]
-    version = "v1.2.0"
-    hash = "sha256-Ta7ZOmyX8gG5tzWbY2oES70EJPfI90U7CIJS9EAce0s="
-  [mod."github.com/klauspost/compress"]
-    version = "v1.17.4"
-    hash = "sha256-5E7dDtDKfL3jy7zJxHBMV57WlHZrP/OoEX5e6cOPba0="
-  [mod."github.com/kortschak/wol"]
-    version = "v0.0.0-20200729010619-da482cc4850a"
-    hash = "sha256-lnr9r/KNv4EeeNohFImC3Vd5E9nJ0N+4ZZ0VHFjwHps="
-  [mod."github.com/lucasb-eyer/go-colorful"]
-    version = "v1.2.0"
-    hash = "sha256-Gg9dDJFCTaHrKHRR1SrJgZ8fWieJkybljybkI9x0gyE="
-  [mod."github.com/mattn/go-isatty"]
-    version = "v0.0.20"
-    hash = "sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ="
-  [mod."github.com/mattn/go-localereader"]
-    version = "v0.0.1"
-    hash = "sha256-JlWckeGaWG+bXK8l8WEdZqmSiTwCA8b1qbmBKa/Fj3E="
-  [mod."github.com/mattn/go-runewidth"]
-    version = "v0.0.15"
-    hash = "sha256-WP39EU2UrQbByYfnwrkBDoKN7xzXsBssDq3pNryBGm0="
-  [mod."github.com/mdlayher/genetlink"]
-    version = "v1.3.2"
-    hash = "sha256-pgwXkyDY1dlB8tmV1lQ0Bz/2g0zmJOyXvQjacACy924="
-  [mod."github.com/mdlayher/netlink"]
-    version = "v1.7.2"
-    hash = "sha256-08qlkKvG1+XFY3MDx7M1jdvaDMsmF9qv5/xMNaw3snc="
-  [mod."github.com/mdlayher/sdnotify"]
-    version = "v1.0.0"
-    hash = "sha256-O7MJt6Bam2bUoede07Z1T6EtW+kCJ+/4dJtYopZct1s="
-  [mod."github.com/mdlayher/socket"]
-    version = "v0.5.0"
-    hash = "sha256-3zEbix66G+LQ2xAQW9XmkyubK9R+Vwnm09H5fqqLC7w="
-  [mod."github.com/miekg/dns"]
-    version = "v1.1.58"
-    hash = "sha256-UGvyC1Abh2S5VaAUCV9AUuDMrCvpiWQy/UnYM9DfIB8="
-  [mod."github.com/mitchellh/go-ps"]
-    version = "v1.0.0"
-    hash = "sha256-HzxVHNLHZpnsBuPcub0G+9jjDcDOsxM/6wifbsxf7EY="
-  [mod."github.com/muesli/ansi"]
-    version = "v0.0.0-20230316100256-276c6243b2f6"
-    hash = "sha256-qRKn0Bh2yvP0QxeEMeZe11Vz0BPFIkVcleKsPeybKMs="
-  [mod."github.com/muesli/cancelreader"]
-    version = "v0.2.2"
-    hash = "sha256-uEPpzwRJBJsQWBw6M71FDfgJuR7n55d/7IV8MO+rpwQ="
-  [mod."github.com/muesli/reflow"]
-    version = "v0.3.0"
-    hash = "sha256-Pou2ybE9SFSZG6YfZLVV1Eyfm+X4FuVpDPLxhpn47Cc="
-  [mod."github.com/muesli/termenv"]
-    version = "v0.15.2"
-    hash = "sha256-Eum/SpyytcNIchANPkG4bYGBgcezLgej7j/+6IhqoMU="
-  [mod."github.com/peterbourgon/ff/v3"]
-    version = "v3.4.0"
-    hash = "sha256-rmRl4GSmc2atnMbw6hTs6jwxW5lO4ivYuF2VN3jacZM="
-  [mod."github.com/pierrec/lz4/v4"]
-    version = "v4.1.21"
-    hash = "sha256-u47Lm4tN2ChGDLGyR+Jpi/Mi0bOFBVT6PTpPFdu2rMU="
-  [mod."github.com/pjbgf/sha1cd"]
-    version = "v0.3.0"
-    hash = "sha256-kX9BdLh2dxtGNaDvc24NORO+C0AZ7JzbrXrtecCdB7w="
-  [mod."github.com/prometheus-community/pro-bing"]
-    version = "v0.4.0"
-    hash = "sha256-3TH0wB85OITw3uzTcEva2EcEF6jNf98sAoSOsnL2G9g="
-  [mod."github.com/rivo/uniseg"]
-    version = "v0.4.6"
-    hash = "sha256-zGfzO8FWj03POzo47SzrK1B4yLMKJ7iic6ium76ZLzI="
-  [mod."github.com/safchain/ethtool"]
-    version = "v0.3.0"
-    hash = "sha256-q5bQGHB7cyEejA9tQkrhpvzpfYRvXcmClbWBgfs3Ymc="
-  [mod."github.com/sergi/go-diff"]
-    version = "v1.3.1"
-    hash = "sha256-XLA/BLIPuUU76yikXqIeRSXr7T7A3Uz6I27+mDxGj7w="
-  [mod."github.com/skeema/knownhosts"]
-    version = "v1.2.1"
-    hash = "sha256-u0jB6ahTdGa+SvcIvPNRLnbSHvgmW9X/ThRq0nWQrJs="
-  [mod."github.com/tailscale/certstore"]
-    version = "v0.1.1-0.20231202035212-d3fa0460f47e"
-    hash = "sha256-Q0HLTQPRsIizRqvdBBaLGoLascQiSpQm+X3NW3ytpDQ="
-  [mod."github.com/tailscale/go-winio"]
-    version = "v0.0.0-20231025203758-c4f33415bf55"
-    hash = "sha256-WFW20c02gIk2MhafeVVNydmSfszPZegshDd2Y5abGgY="
-  [mod."github.com/tailscale/golang-x-crypto"]
-    version = "v0.0.0-20240604161659-3fde5e568aa4"
-    hash = "sha256-vIrSd0emexe1lcjJqLbEtg7/TaZDnpGrDs96mxjANyE="
-  [mod."github.com/tailscale/goupnp"]
-    version = "v1.0.1-0.20210804011211-c64d0f06ea05"
-    hash = "sha256-PRMJcYY+wjpbHkC9dQWTPErh2ID29UnFxehxmYR704I="
-  [mod."github.com/tailscale/hujson"]
-    version = "v0.0.0-20221223112325-20486734a56a"
-    hash = "sha256-q9c2IjwbL0IgYPznVpQP1XT/8lrzH1niI3E+wjNcf5Y="
-  [mod."github.com/tailscale/netlink"]
-    version = "v1.1.1-0.20211101221916-cabfb018fe85"
-    hash = "sha256-bMK5qqObMcxIbPy5XhOZP8TGDaXvDAHsE0FR68VMLi8="
-  [mod."github.com/tailscale/peercred"]
-    version = "v0.0.0-20240214030740-b535050b2aa4"
-    hash = "sha256-82cdwvTUr47qMP2MHiMdY5O8vr/hA2aJ/KW2VTu97KI="
-  [mod."github.com/tailscale/web-client-prebuilt"]
-    version = "v0.0.0-20240226180453-5db17b287bf1"
-    hash = "sha256-iE8PCr0At4P75cG7dDa6fwhARJUIUw9pwvgtQNMOjAA="
-  [mod."github.com/tailscale/wireguard-go"]
-    version = "v0.0.0-20240429185444-03c5a0ccf754"
-    hash = "sha256-XhfEG8esndgZDoI2AeRvs95XRYiIrj/0NiVDBpOcacY="
-  [mod."github.com/tcnksm/go-httpstat"]
-    version = "v0.2.0"
-    hash = "sha256-bCWn8E+DcZY6+yPu07AF3hCcDZx3CFdD74qfpDIgVqI="
-  [mod."github.com/u-root/u-root"]
-    version = "v0.12.0"
-    hash = "sha256-B9Qoq1S0l0W6twET54uxiWjh2ulxN/zMLAeWJX4cXW0="
-  [mod."github.com/u-root/uio"]
-    version = "v0.0.0-20240118234441-a3c409a6018e"
-    hash = "sha256-rUjQMG+HprbgHKzrIPFrQ6S3BCEyYQyUbA/D72mY8iU="
-  [mod."github.com/vishvananda/netlink"]
-    version = "v1.2.1-beta.2"
-    hash = "sha256-ePReedgYT0KuAx/HOUgG76zDZ2XpW/u8bGlsWysxKzE="
-  [mod."github.com/vishvananda/netns"]
-    version = "v0.0.4"
-    hash = "sha256-tEba2cxyk3GdCYvEIttQ8aZCzHcB0ZiUt6fUEARDkWU="
-  [mod."github.com/x448/float16"]
-    version = "v0.8.4"
-    hash = "sha256-VKzMTMS9pIB/cwe17xPftCSK9Mf4Y6EuBEJlB4by5mE="
-  [mod."github.com/xanzy/ssh-agent"]
-    version = "v0.3.3"
-    hash = "sha256-l3pGB6IdzcPA/HLk93sSN6NM2pKPy+bVOoacR5RC2+c="
-  [mod."github.com/yuin/goldmark"]
-    version = "v1.6.0"
-    hash = "sha256-0PeGjGxxM7lUSx2dn8yPUBpilPQzEN9nkgf3s+5zGTY="
-  [mod."github.com/yuin/goldmark-emoji"]
-    version = "v1.0.2"
-    hash = "sha256-RvzhNXlF98fu9SD/Rve9JMtR4bcRh7rN56Twhh/kmt4="
-  [mod."github.com/yuin/goldmark-highlighting/v2"]
-    version = "v2.0.0-20230729083705-37449abec8cc"
-    hash = "sha256-HpiwU7jIeDUAg2zOpTIiviQir8dpRPuXYh2nqFFccpg="
-  [mod."go.jolheiser.com/tailroute"]
-    version = "v0.0.0-20240726150858-67ef456b46b5"
-    hash = "sha256-NJBg8m3ukwBycuXj3lUtTclX1kmdw3xBW+YCKnPuU8g="
-  [mod."go4.org/mem"]
-    version = "v0.0.0-20220726221520-4f986261bf13"
-    hash = "sha256-H2Fsuvzbqp/6JKzC03XPTQTSQBcGs+B5VGsBjrQDY3c="
-  [mod."go4.org/netipx"]
-    version = "v0.0.0-20231129151722-fdeea329fbba"
-    hash = "sha256-qFrVlacz5R3Lpkzqeg1/1MYew3DJzY9hG0Uh/ua+SOU="
-  [mod."golang.org/x/crypto"]
-    version = "v0.21.0"
-    hash = "sha256-Z4k1LvFh4Jai7HUe6TTuXSG3VnuiRpMwdARIdZZqSYk="
-  [mod."golang.org/x/exp"]
-    version = "v0.0.0-20240119083558-1b970713d09a"
-    hash = "sha256-JQ3JLywTjgboNhs12blhOkS3ty7m8sUa/zaWv1k/X28="
-  [mod."golang.org/x/mod"]
-    version = "v0.16.0"
-    hash = "sha256-aN1Cz5Wqd9YCjK8nFW6JWn+n1HfFoEcgYZmGO/FYtbw="
-  [mod."golang.org/x/net"]
-    version = "v0.23.0"
-    hash = "sha256-ZB4504rtgsHbcRfijjlqt4/2ddb8tyQB5IBn126uVTQ="
-  [mod."golang.org/x/sync"]
-    version = "v0.6.0"
-    hash = "sha256-LLims/wjDZtIqlYCVHREewcUOX4hwRwplEuZKPOJ/HI="
-  [mod."golang.org/x/sys"]
-    version = "v0.19.0"
-    hash = "sha256-cmuL31TYLJmDm/fDnI2Sn0wB88cpdOHV1+urorsJWx4="
-  [mod."golang.org/x/term"]
-    version = "v0.18.0"
-    hash = "sha256-lpze9arFZIhBV8Ht3VZyoiUwqPkeH2IwfXt8M3xljiM="
-  [mod."golang.org/x/text"]
-    version = "v0.14.0"
-    hash = "sha256-yh3B0tom1RfzQBf1RNmfdNWF1PtiqxV41jW1GVS6JAg="
-  [mod."golang.org/x/time"]
-    version = "v0.5.0"
-    hash = "sha256-W6RgwgdYTO3byIPOFxrP2IpAZdgaGowAaVfYby7AULU="
-  [mod."golang.org/x/tools"]
-    version = "v0.19.0"
-    hash = "sha256-Xf05Ao398gBzxn5C8H6x+XsLjFLIm+UUfpDekQYA0cw="
-  [mod."golang.zx2c4.com/wintun"]
-    version = "v0.0.0-20230126152724-0fa3db229ce2"
-    hash = "sha256-cjMLNjKnnupVROWmeASORVieAL9ieYdzX3cFzG8bCpo="
-  [mod."golang.zx2c4.com/wireguard/windows"]
-    version = "v0.5.3"
-    hash = "sha256-wcJWS/4Fqbc+1RHSntex0zBdlHiZfzrea4QabYkNKvU="
-  [mod."gopkg.in/warnings.v0"]
-    version = "v0.1.2"
-    hash = "sha256-ATVL9yEmgYbkJ1DkltDGRn/auGAjqGOfjQyBYyUo8s8="
-  [mod."gopkg.in/yaml.v2"]
-    version = "v2.4.0"
-    hash = "sha256-uVEGglIedjOIGZzHW4YwN1VoRSTK8o0eGZqzd+TNdd0="
-  [mod."gvisor.dev/gvisor"]
-    version = "v0.0.0-20240306221502-ee1e1f6070e3"
-    hash = "sha256-veCyTYMx5N/K7xU86GgQupjAjjiL3hlvIjz+jhBFM/0="
-  [mod."nhooyr.io/websocket"]
-    version = "v1.8.10"
-    hash = "sha256-EsUWUFIA2uJTap1DfsYuSxlPMH3UHDpxEohJMalDOcI="
-  [mod."tailscale.com"]
-    version = "v1.68.2"
-    hash = "sha256-GdYdZ/FA2m0dw5maZ9QFkiMo89UZtnzjUoWK+fLLV/c="
I nix/default.nix
diff --git a/nix/default.nix b/nix/default.nix
new file mode 100644
index 0000000000000000000000000000000000000000..07317370bfffc442b384102e32cde32e0f1042de
--- /dev/null
+++ b/nix/default.nix
@@ -0,0 +1,10 @@
+{
+  pkgs ? import <nixpkgs>,
+}:
+let
+  pkg = pkgs.callPackage ./pkg.nix { inherit pkgs; };
+in
+{
+  ugit = pkg;
+  default = pkg;
+}
I nix/module.nix
diff --git a/nix/module.nix b/nix/module.nix
new file mode 100644
index 0000000000000000000000000000000000000000..fd45cccebcfe3581dc2e0ff1e29189985913e59f
--- /dev/null
+++ b/nix/module.nix
@@ -0,0 +1,196 @@
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+let
+  cfg = config.services.ugit;
+  pkg = pkgs.callPackage ./pkg.nix { inherit pkgs; };
+  yamlFormat = pkgs.formats.yaml { };
+  configFile = pkgs.writeText "ugit.yaml" (
+    builtins.readFile (yamlFormat.generate "ugit-yaml" cfg.config)
+  );
+  authorizedKeysFile = pkgs.writeText "ugit_keys" (builtins.concatStringsSep "\n" cfg.authorizedKeys);
+in
+{
+  options =
+    let
+      inherit (lib) mkEnableOption mkOption types;
+    in
+    {
+      services.ugit = {
+        enable = mkEnableOption "Enable ugit";
+
+        package = mkOption {
+          type = types.package;
+          description = "ugit package to use";
+          default = pkg;
+        };
+
+        tsAuthKey = mkOption {
+          type = types.str;
+          description = "Tailscale one-time auth-key";
+          default = "";
+        };
+
+        repoDir = mkOption {
+          type = types.str;
+          description = "where ugit stores repositories";
+          default = "/var/lib/ugit/repos";
+        };
+
+        authorizedKeys = mkOption {
+          type = types.listOf types.str;
+          description = "list of keys to use for authorized_keys";
+          default = [ ];
+        };
+
+        authorizedKeysFile = mkOption {
+          type = types.str;
+          description = "path to authorized_keys file ugit uses for auth";
+          default = "/var/lib/ugit/authorized_keys";
+        };
+
+        hostKeyFile = mkOption {
+          type = types.str;
+          description = "path to host key file (will be created if it doesn't exist)";
+          default = "/var/lib/ugit/ugit_ed25519";
+        };
+
+        config = mkOption {
+          type = types.attrs;
+          default = { };
+          description = "config.yaml contents";
+        };
+
+        user = mkOption {
+          type = types.str;
+          default = "ugit";
+          description = "User account under which ugit runs";
+        };
+
+        group = mkOption {
+          type = types.str;
+          default = "ugit";
+          description = "Group account under which ugit runs";
+        };
+
+        openFirewall = mkOption {
+          type = types.bool;
+          default = false;
+        };
+
+        hooks = mkOption {
+          type = types.listOf (
+            types.submodule {
+              options = {
+                name = mkOption {
+                  type = types.str;
+                  description = "Hook name";
+                };
+                content = mkOption {
+                  type = types.str;
+                  description = "Hook contents";
+                };
+              };
+            }
+          );
+          description = "A list of pre-receive hooks to run";
+          default = [ ];
+        };
+      };
+    };
+  config = lib.mkIf cfg.enable {
+    users.users."${cfg.user}" = {
+      home = "/var/lib/ugit";
+      createHome = true;
+      group = "${cfg.group}";
+      isSystemUser = true;
+      isNormalUser = false;
+      description = "user for ugit service";
+    };
+    users.groups."${cfg.group}" = { };
+    networking.firewall = lib.mkIf cfg.openFirewall {
+      allowedTCPPorts = [
+        8448
+        8449
+      ];
+    };
+
+    systemd.services = {
+      ugit = {
+        enable = true;
+        script =
+          let
+            authorizedKeysPath =
+              if (builtins.length cfg.authorizedKeys) > 0 then authorizedKeysFile else cfg.authorizedKeysFile;
+            args = [
+              "--config=${configFile}"
+              "--repo-dir=${cfg.repoDir}"
+              "--ssh.authorized-keys=${authorizedKeysPath}"
+              "--ssh.host-key=${cfg.hostKeyFile}"
+            ];
+          in
+          "${cfg.package}/bin/ugitd ${builtins.concatStringsSep " " args}";
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
+        path = [
+          cfg.package
+          pkgs.git
+          pkgs.bash
+        ];
+        serviceConfig = {
+          User = cfg.user;
+          Group = cfg.group;
+          Restart = "always";
+          RestartSec = "15";
+          WorkingDirectory = "/var/lib/ugit";
+          Environment = [ "TS_AUTHKEY=${cfg.tsAuthKey}" ];
+        };
+      };
+      ugit-hooks = {
+        wantedBy = [ "multi-user.target" ];
+        after = [ "ugit.service" ];
+        requires = [ "ugit.service" ];
+        serviceConfig = {
+          Type = "oneshot";
+          ExecStart =
+            let
+              script = pkgs.writeShellScript "ugit-hooks-link" (
+                builtins.concatStringsSep "\n" (
+                  map (
+                    hook:
+                    let
+                      script = pkgs.writeShellScript hook.name hook.content;
+                      path = "${cfg.repoDir}/hooks/pre-receive.d/${hook.name}";
+                    in
+                    "ln -s ${script} ${path}"
+                  ) cfg.hooks
+                )
+              );
+            in
+            "${script}";
+        };
+      };
+    };
+
+    systemd.tmpfiles.settings.ugit = builtins.listToAttrs (
+      map (
+        hook:
+        let
+          script = pkgs.writeShellScript hook.name hook.content;
+          path = "${cfg.repoDir}/hooks/pre-receive.d/${hook.name}";
+        in
+        {
+          name = path;
+          value = {
+            "L" = {
+              argument = "${script}";
+            };
+          };
+        }
+      ) cfg.hooks
+    );
+  };
+}
I nix/pkg.nix
diff --git a/nix/pkg.nix b/nix/pkg.nix
new file mode 100644
index 0000000000000000000000000000000000000000..1d64f3e79ad253d5a492d985e94ff3236138c122
--- /dev/null
+++ b/nix/pkg.nix
@@ -0,0 +1,33 @@
+{
+  pkgs ? import <nixpkgs>,
+}:
+let
+  name = "ugitd";
+in
+pkgs.buildGoModule {
+  pname = name;
+  version = "main";
+  src = pkgs.nix-gitignore.gitignoreSource [ ] (
+    builtins.path {
+      inherit name;
+      path = ../.;
+    }
+  );
+  subPackages = [
+    "cmd/ugitd"
+    "cmd/ugit-uci"
+  ];
+  vendorHash = pkgs.lib.fileContents ../go.mod.sri;
+  CGO_ENABLED = 0;
+  flags = [ "-trimpath" ];
+  ldflags = [
+    "-s"
+    "-w"
+    "-extldflags -static"
+  ];
+  meta = {
+    description = "Minimal git server";
+    homepage = "https://git.jolheiser.com/ugit";
+    mainProgram = "ugitd";
+  };
+}
I nix/test.nix
diff --git a/nix/test.nix b/nix/test.nix
new file mode 100644
index 0000000000000000000000000000000000000000..9b5e625a43c5b62114b86572cbf29c2abe007bf1
--- /dev/null
+++ b/nix/test.nix
@@ -0,0 +1,26 @@
+{ config, pkgs, ... }:
+{
+  imports = [ ./module.nix ];
+
+  users.users.jolheiser = {
+    isNormalUser = true;
+    extraGroups = [ "wheel" ];
+    initialPassword = "test";
+  };
+
+  services.ugit = {
+    enable = true;
+    hooks = [
+      {
+        name = "pre-receive";
+        content = ''
+          echo "Pre-receive hook executed"
+        '';
+      }
+      {
+        name = "ugit-uci";
+        content = "${config.services.ugit.package}/bin/ugit-uci";
+      }
+    ];
+  };
+}