at 22.05-pre 5.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4let 5 cfg = config.services.sourcehut; 6 scfg = cfg.hg; 7 iniKey = "hg.sr.ht"; 8 9 rcfg = config.services.redis; 10 drv = pkgs.sourcehut.hgsrht; 11in 12{ 13 options.services.sourcehut.hg = { 14 user = mkOption { 15 type = types.str; 16 internal = true; 17 readOnly = true; 18 default = "hg"; 19 description = '' 20 User for hg.sr.ht. 21 ''; 22 }; 23 24 port = mkOption { 25 type = types.port; 26 default = 5010; 27 description = '' 28 Port on which the "hg" module should listen. 29 ''; 30 }; 31 32 database = mkOption { 33 type = types.str; 34 default = "hg.sr.ht"; 35 description = '' 36 PostgreSQL database name for hg.sr.ht. 37 ''; 38 }; 39 40 statePath = mkOption { 41 type = types.path; 42 default = "${cfg.statePath}/hgsrht"; 43 description = '' 44 State path for hg.sr.ht. 45 ''; 46 }; 47 48 cloneBundles = mkOption { 49 type = types.bool; 50 default = false; 51 description = '' 52 Generate clonebundles (which require more disk space but dramatically speed up cloning large repositories). 53 ''; 54 }; 55 }; 56 57 config = with scfg; lib.mkIf (cfg.enable && elem "hg" cfg.services) { 58 # In case it ever comes into being 59 environment.etc."ssh/hgsrht-dispatch" = { 60 mode = "0755"; 61 text = '' 62 #! ${pkgs.stdenv.shell} 63 ${cfg.python}/bin/gitsrht-dispatch $@ 64 ''; 65 }; 66 67 environment.systemPackages = [ pkgs.mercurial ]; 68 69 users = { 70 users = { 71 "${user}" = { 72 isSystemUser = true; 73 group = user; 74 # Assuming hg.sr.ht needs this too 75 shell = pkgs.bash; 76 description = "hg.sr.ht user"; 77 }; 78 }; 79 80 groups = { 81 "${user}" = { }; 82 }; 83 }; 84 85 services = { 86 cron.systemCronJobs = [ "*/20 * * * * ${cfg.python}/bin/hgsrht-periodic" ] 87 ++ optional cloneBundles "0 * * * * ${cfg.python}/bin/hgsrht-clonebundles"; 88 89 openssh.authorizedKeysCommand = ''/etc/ssh/hgsrht-dispatch "%u" "%h" "%t" "%k"''; 90 openssh.authorizedKeysCommandUser = "root"; 91 openssh.extraConfig = '' 92 PermitUserEnvironment SRHT_* 93 ''; 94 95 postgresql = { 96 authentication = '' 97 local ${database} ${user} trust 98 ''; 99 ensureDatabases = [ database ]; 100 ensureUsers = [ 101 { 102 name = user; 103 ensurePermissions = { "DATABASE \"${database}\"" = "ALL PRIVILEGES"; }; 104 } 105 ]; 106 }; 107 }; 108 109 systemd = { 110 tmpfiles.rules = [ 111 # /var/log is owned by root 112 "f /var/log/hg-srht-shell 0644 ${user} ${user} -" 113 114 "d ${statePath} 0750 ${user} ${user} -" 115 "d ${cfg.settings."${iniKey}".repos} 2755 ${user} ${user} -" 116 ]; 117 118 services.hgsrht = import ./service.nix { inherit config pkgs lib; } scfg drv iniKey { 119 after = [ "redis.service" "postgresql.service" "network.target" ]; 120 requires = [ "redis.service" "postgresql.service" ]; 121 wantedBy = [ "multi-user.target" ]; 122 123 path = [ pkgs.mercurial ]; 124 description = "hg.sr.ht website service"; 125 126 serviceConfig.ExecStart = "${cfg.python}/bin/gunicorn ${drv.pname}.app:app -b ${cfg.address}:${toString port}"; 127 }; 128 }; 129 130 services.sourcehut.settings = { 131 # URL hg.sr.ht is being served at (protocol://domain) 132 "hg.sr.ht".origin = mkDefault "http://hg.${cfg.originBase}"; 133 # Address and port to bind the debug server to 134 "hg.sr.ht".debug-host = mkDefault "0.0.0.0"; 135 "hg.sr.ht".debug-port = mkDefault port; 136 # Configures the SQLAlchemy connection string for the database. 137 "hg.sr.ht".connection-string = mkDefault "postgresql:///${database}?user=${user}&host=/var/run/postgresql"; 138 # The redis connection used for the webhooks worker 139 "hg.sr.ht".webhooks = mkDefault "redis://${rcfg.bind}:${toString rcfg.port}/1"; 140 # A post-update script which is installed in every mercurial repo. 141 "hg.sr.ht".changegroup-script = mkDefault "${cfg.python}/bin/hgsrht-hook-changegroup"; 142 # hg.sr.ht's OAuth client ID and secret for meta.sr.ht 143 # Register your client at meta.example.org/oauth 144 "hg.sr.ht".oauth-client-id = mkDefault null; 145 "hg.sr.ht".oauth-client-secret = mkDefault null; 146 # Path to mercurial repositories on disk 147 "hg.sr.ht".repos = mkDefault "/var/lib/hg"; 148 # Path to the srht mercurial extension 149 # (defaults to where the hgsrht code is) 150 # "hg.sr.ht".srhtext = mkDefault null; 151 # .hg/store size (in MB) past which the nightly job generates clone bundles. 152 # "hg.sr.ht".clone_bundle_threshold = mkDefault 50; 153 # Path to hg-ssh (if not in $PATH) 154 # "hg.sr.ht".hg_ssh = mkDefault /path/to/hg-ssh; 155 156 # The authorized keys hook uses this to dispatch to various handlers 157 # The format is a program to exec into as the key, and the user to match as the 158 # value. When someone tries to log in as this user, this program is executed 159 # and is expected to omit an AuthorizedKeys file. 160 # 161 # Uncomment the relevant lines to enable the various sr.ht dispatchers. 162 "hg.sr.ht::dispatch"."/run/current-system/sw/bin/hgsrht-keys" = mkDefault "${user}:${user}"; 163 }; 164 165 # TODO: requires testing and addition of hg-specific requirements 166 services.nginx.virtualHosts."hg.${cfg.originBase}" = { 167 forceSSL = true; 168 locations."/".proxyPass = "http://${cfg.address}:${toString port}"; 169 locations."/query".proxyPass = "http://${cfg.address}:${toString (port + 100)}"; 170 locations."/static".root = "${pkgs.sourcehut.hgsrht}/${pkgs.sourcehut.python.sitePackages}/hgsrht"; 171 }; 172 }; 173}