2 files changed,
122 insertions(+),
72 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-02-17 23:51:55 +0200
Authored at:
2026-02-17 23:51:26 +0200
Change ID:
tkpqotyyyspmzmroxuoyumqtxmrsslov
Parent:
5a3f570
jump to
| M | flake.nix |
| M | internal/config/config.go |
M
flake.nix
路路路 49 49 let 50 50 cfg = config.services.mugit; 51 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 - }; 52 + configFile = format.generate "config.yaml" cfg.config; 80 53 in 81 54 { 82 55 options.services.mugit = { 路路路 95 68 description = "Whether to open the firewall for mugit. Can only be used with `config`, not `configFile`."; 96 69 }; 97 70 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 71 configFile = mkOption { 111 72 type = types.nullOr types.path; 112 73 default = null; 113 74 description = "Path to an existing mugit configuration file. Mutually exclusive with `config`."; 114 75 }; 115 76 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 77 user = mkOption { 132 78 type = types.str; 133 79 default = "mugit"; 路路路 140 86 description = "Group under which mugit runs."; 141 87 }; 142 88 89 + config = mkOption { 90 + default = {}; 91 + description = '' 92 + The primary mugit configuration. 93 + See [docs](https://github.com/olexsmir/mugit) for possible values. 94 + ''; 95 + example = literalExpression '' 96 + { 97 + meta.host = "git.example.org"; 98 + repo.dir = "/var/lib/mugit"; 99 + ssh = { 100 + enable = true; 101 + host_key = "/var/lib/mugit/key"; 102 + }; 103 + } 104 + ''; 105 + type = types.submodule { 106 + options.meta = { 107 + title = mkOption { 108 + type = types.str; 109 + default = "mugit"; 110 + description = "Website title"; 111 + }; 112 + description = mkOption { 113 + type = types.str; 114 + default = ""; 115 + description = "Website description"; 116 + }; 117 + host = mkOption { 118 + type = types.str; 119 + default = ""; 120 + description = "Website CNAME (required)"; 121 + }; 122 + }; 123 + options.server = { 124 + host = mkOption { 125 + type = types.str; 126 + default = ""; 127 + description = "Host address"; 128 + }; 129 + port = mkOption { 130 + type = types.port; 131 + default = 8080; 132 + description = "Website port"; 133 + }; 134 + }; 135 + options.repo = { 136 + dir = mkOption { 137 + type = types.str; 138 + default = ""; 139 + description = "Directory which mugit will scan for repositories (required)"; 140 + }; 141 + masters = mkOption { 142 + type = types.listOf types.str; 143 + default = ["master" "main"]; 144 + description = "Master branch to look for"; 145 + }; 146 + readmes = mkOption { 147 + type = types.listOf types.str; 148 + default = ["README.md" "readme.md" "README.html" "readme.html" "README.txt" "readme.txt" "readme"]; 149 + description = "Readme files to look for"; 150 + }; 151 + }; 152 + options.ssh = { 153 + enable = mkOption { 154 + type = types.bool; 155 + default = false; 156 + description = "Wharever to run ssh server"; 157 + }; 158 + port = mkOption { 159 + type = types.port; 160 + default = 2222; 161 + description = "Website port"; 162 + }; 163 + host_key = mkOption { 164 + type = types.str; 165 + default = ""; 166 + description = "Path to ssh private key (required if ssh enabled)"; 167 + }; 168 + keys = mkOption { 169 + type = types.listOf types.str; 170 + default = []; 171 + description = "List of public ssh keys which are allows to do git pushes, and access private repositories"; 172 + }; 173 + }; 174 + options.mirror = { 175 + enable = mkOption { 176 + type = types.bool; 177 + default = false; 178 + description = "Wharever to run mirroring worker"; 179 + }; 180 + interval = mkOption { 181 + type = types.str; 182 + default = "8h"; 183 + description = "Interval in which mirroring will happen"; 184 + }; 185 + github_token = mkOption { 186 + type = types.str; 187 + default = ""; 188 + description = "Github token for pulling from github repos"; 189 + }; 190 + }; 191 + options.cache = { 192 + home_page = mkOption { 193 + type = types.str; 194 + default = "5m"; 195 + description = "For how long index page is cached"; 196 + }; 197 + readme = mkOption { 198 + type = types.str; 199 + default = "1m"; 200 + description = "For how long repos readme is cached"; 201 + }; 202 + }; 203 + }; 204 + }; 143 205 }; 144 206 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 207 157 - environment.systemPackages = mkIf cfg.exposeCli [ mugitWithCompletions ]; 158 - 208 + config = mkIf cfg.enable { 159 209 networking.firewall = mkIf cfg.openFirewall { 160 210 allowedTCPPorts = 161 211 let 路路路 169 219 users.users.${cfg.user} = { 170 220 isSystemUser = true; 171 221 group = cfg.group; 172 - home = cfg.dataDir; 222 + home = cfg.config.repo.dir; 173 223 createHome = true; 174 224 description = "mugit service user"; 175 225 }; 路路路 193 243 Type = "simple"; 194 244 User = cfg.user; 195 245 Group = cfg.group; 196 - WorkingDirectory = cfg.dataDir; 246 + WorkingDirectory = cfg.config.repo.dir; 197 247 StateDirectory = "mugit"; 198 248 ExecStart = "${cfg.package}/bin/mugit serve --config ${configFile}"; 199 249 Restart = "on-failure"; 路路路 202 252 PrivateTmp = true; 203 253 ProtectSystem = "strict"; 204 254 ProtectHome = true; 205 - ReadWritePaths = [ cfg.dataDir ]; 255 + ReadWritePaths = [ cfg.config.repo.dir ]; 206 256 ProtectKernelTunables = true; 207 257 ProtectKernelModules = true; 208 258 ProtectControlGroups = true;