diff options
Diffstat (limited to 'nixos/modules/services/misc')
-rw-r--r-- | nixos/modules/services/misc/atuin.nix | 4 | ||||
-rw-r--r-- | nixos/modules/services/misc/autofs.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/misc/forgejo.md | 79 | ||||
-rw-r--r-- | nixos/modules/services/misc/forgejo.nix | 22 | ||||
-rw-r--r-- | nixos/modules/services/misc/gitea.nix | 10 | ||||
-rw-r--r-- | nixos/modules/services/misc/mediatomb.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/misc/redmine.nix | 4 | ||||
-rw-r--r-- | nixos/modules/services/misc/soft-serve.nix | 4 | ||||
-rw-r--r-- | nixos/modules/services/misc/sourcehut/default.nix | 158 | ||||
-rw-r--r-- | nixos/modules/services/misc/sourcehut/service.nix | 40 |
10 files changed, 209 insertions, 116 deletions
diff --git a/nixos/modules/services/misc/atuin.nix b/nixos/modules/services/misc/atuin.nix index 8d2c1b5242ff..2d6ffc510ce5 100644 --- a/nixos/modules/services/misc/atuin.nix +++ b/nixos/modules/services/misc/atuin.nix @@ -73,9 +73,7 @@ in enable = true; ensureUsers = [{ name = "atuin"; - ensurePermissions = { - "DATABASE atuin" = "ALL PRIVILEGES"; - }; + ensureDBOwnership = true; }]; ensureDatabases = [ "atuin" ]; }; diff --git a/nixos/modules/services/misc/autofs.nix b/nixos/modules/services/misc/autofs.nix index 55ab15ff003d..723b67e8bb6b 100644 --- a/nixos/modules/services/misc/autofs.nix +++ b/nixos/modules/services/misc/autofs.nix @@ -74,7 +74,7 @@ in config = mkIf cfg.enable { - boot.kernelModules = [ "autofs4" ]; + boot.kernelModules = [ "autofs" ]; systemd.services.autofs = { description = "Automounts filesystems on demand"; diff --git a/nixos/modules/services/misc/forgejo.md b/nixos/modules/services/misc/forgejo.md new file mode 100644 index 000000000000..3df8bc20976a --- /dev/null +++ b/nixos/modules/services/misc/forgejo.md @@ -0,0 +1,79 @@ +# Forgejo {#module-forgejo} + +Forgejo is a soft-fork of gitea, with strong community focus, as well +as on self-hosting and federation. [Codeberg](https://codeberg.org) is +deployed from it. + +See [upstream docs](https://forgejo.org/docs/latest/). + +The method of choice for running forgejo is using [`services.forgejo`](#opt-services.forgejo.enable). + +::: {.warning} +Running forgejo using `services.gitea.package = pkgs.forgejo` is no longer +recommended. +If you experience issues with your instance using `services.gitea`, +**DO NOT** report them to the `services.gitea` module maintainers. +**DO** report them to the `services.forgejo` module maintainers instead. +::: + +## Migration from Gitea {#module-forgejo-migration-gitea} + +::: {.note} +Migrating is, while not strictly necessary at this point, highly recommended. +Both modules and projects are likely to divide further with each release. +Which might lead to an even more involved migration. +::: + +### Full-Migration {#module-forgejo-migration-gitea-default} + +This will migrate the state directory (data), rename and chown the database and +delete the gitea user. + +::: {.note} +This will also change the git remote ssh-url user from `gitea@` to `forgejo@`, +when using the host's openssh server (default) instead of the integrated one. +::: + +Instructions for PostgreSQL (default). Adapt accordingly for other databases: + +```sh +systemctl stop gitea +mv /var/lib/gitea /var/lib/forgejo +runuser -u postgres -- psql -c ' + ALTER USER gitea RENAME TO forgejo; + ALTER DATABASE gitea RENAME TO forgejo; +' +nixos-rebuild switch +systemctl stop forgejo +chown -R forgejo:forgejo /var/lib/forgejo +systemctl restart forgejo +``` + +### Alternatively, keeping the gitea user {#module-forgejo-migration-gitea-impersonate} + +Alternatively, instead of renaming the database, copying the state folder and +changing the user, the forgejo module can be set up to re-use the old storage +locations and database, instead of having to copy or rename them. +Make sure to disable `services.gitea`, when doing this. + +```nix +services.gitea.enable = false; + +services.forgejo = { + enable = true; + user = "gitea"; + group = "gitea"; + stateDir = "/var/lib/gitea"; + database.name = "gitea"; + database.user = "gitea"; +}; + +users.users.gitea = { + home = "/var/lib/gitea"; + useDefaultShell = true; + group = "gitea"; + isSystemUser = true; +}; + +users.groups.gitea = {}; +``` diff --git a/nixos/modules/services/misc/forgejo.nix b/nixos/modules/services/misc/forgejo.nix index 90b5f16f4189..454febda5893 100644 --- a/nixos/modules/services/misc/forgejo.nix +++ b/nixos/modules/services/misc/forgejo.nix @@ -357,6 +357,14 @@ in assertion = cfg.database.createDatabase -> useSqlite || cfg.database.user == cfg.user; message = "services.forgejo.database.user must match services.forgejo.user if the database is to be automatically provisioned"; } + { assertion = cfg.database.createDatabase && usePostgresql -> cfg.database.user == cfg.database.name; + message = '' + When creating a database via NixOS, the db user and db name must be equal! + If you already have an existing DB+user and this assertion is new, you can safely set + `services.forgejo.createDatabase` to `false` because removal of `ensureUsers` + and `ensureDatabases` doesn't have any effect. + ''; + } ]; services.forgejo.settings = { @@ -423,22 +431,11 @@ in ensureUsers = [ { name = cfg.database.user; - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; + ensureDBOwnership = true; } ]; }; - # Work around 'pq: permission denied for schema public' with postgres v15, until a - # solution for `services.postgresql.ensureUsers` is found. - # See https://github.com/NixOS/nixpkgs/issues/216989 - systemd.services.postgresql.postStart = lib.mkIf ( - usePostgresql - && cfg.database.createDatabase - && lib.strings.versionAtLeast config.services.postgresql.package.version "15.0" - ) (lib.mkAfter '' - $PSQL -tAc 'ALTER DATABASE "${cfg.database.name}" OWNER TO "${cfg.database.user}";' - ''); - services.mysql = optionalAttrs (useMysql && cfg.database.createDatabase) { enable = mkDefault true; package = mkDefault pkgs.mariadb; @@ -677,5 +674,6 @@ in }; }; + meta.doc = ./forgejo.md; meta.maintainers = with lib.maintainers; [ bendlas emilylange ]; } diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix index 3f690f85d623..be528a298991 100644 --- a/nixos/modules/services/misc/gitea.nix +++ b/nixos/modules/services/misc/gitea.nix @@ -394,6 +394,14 @@ in { assertion = cfg.database.createDatabase -> useSqlite || cfg.database.user == cfg.user; message = "services.gitea.database.user must match services.gitea.user if the database is to be automatically provisioned"; } + { assertion = cfg.database.createDatabase && usePostgresql -> cfg.database.user == cfg.database.name; + message = '' + When creating a database via NixOS, the db user and db name must be equal! + If you already have an existing DB+user and this assertion is new, you can safely set + `services.gitea.createDatabase` to `false` because removal of `ensureUsers` + and `ensureDatabases` doesn't have any effect. + ''; + } ]; services.gitea.settings = { @@ -461,7 +469,7 @@ in ensureDatabases = [ cfg.database.name ]; ensureUsers = [ { name = cfg.database.user; - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; + ensureDBOwnership = true; } ]; }; diff --git a/nixos/modules/services/misc/mediatomb.nix b/nixos/modules/services/misc/mediatomb.nix index 632b7caaac40..335b1b684b1a 100644 --- a/nixos/modules/services/misc/mediatomb.nix +++ b/nixos/modules/services/misc/mediatomb.nix @@ -186,7 +186,7 @@ let defaultFirewallRules = { # udp 1900 port needs to be opened for SSDP (not configurable within # mediatomb/gerbera) cf. - # http://docs.gerbera.io/en/latest/run.html?highlight=udp%20port#network-setup + # https://docs.gerbera.io/en/latest/run.html?highlight=udp%20port#network-setup allowedUDPPorts = [ 1900 cfg.port ]; allowedTCPPorts = [ cfg.port ]; }; diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix index a296fd3816bb..20fa71507b6b 100644 --- a/nixos/modules/services/misc/redmine.nix +++ b/nixos/modules/services/misc/redmine.nix @@ -267,7 +267,7 @@ in { assertion = cfg.database.passwordFile != null || cfg.database.socket != null; message = "one of services.redmine.database.socket or services.redmine.database.passwordFile must be set"; } - { assertion = cfg.database.createLocally -> cfg.database.user == cfg.user; + { assertion = cfg.database.createLocally -> cfg.database.user == cfg.user && cfg.database.user == cfg.database.name; message = "services.redmine.database.user must be set to ${cfg.user} if services.redmine.database.createLocally is set true"; } { assertion = cfg.database.createLocally -> cfg.database.socket != null; @@ -315,7 +315,7 @@ in ensureDatabases = [ cfg.database.name ]; ensureUsers = [ { name = cfg.database.user; - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; + ensureDBOwnership = true; } ]; }; diff --git a/nixos/modules/services/misc/soft-serve.nix b/nixos/modules/services/misc/soft-serve.nix index 0f246493880b..2b63b6bcd867 100644 --- a/nixos/modules/services/misc/soft-serve.nix +++ b/nixos/modules/services/misc/soft-serve.nix @@ -12,7 +12,7 @@ in { options = { services.soft-serve = { - enable = mkEnableOption "Enable soft-serve service"; + enable = mkEnableOption "soft-serve"; package = mkPackageOption pkgs "soft-serve" { }; @@ -20,7 +20,7 @@ in type = format.type; default = { }; description = mdDoc '' - The contents of the configuration file. + The contents of the configuration file for soft-serve. See <${docUrl}>. ''; diff --git a/nixos/modules/services/misc/sourcehut/default.nix b/nixos/modules/services/misc/sourcehut/default.nix index bee971662972..f2b09f4bc4b6 100644 --- a/nixos/modules/services/misc/sourcehut/default.nix +++ b/nixos/modules/services/misc/sourcehut/default.nix @@ -25,7 +25,7 @@ let || head srvMatch == srv # Include sections for the service being configured then v # Enable Web links and integrations between services. - else if tail srvMatch == [ null ] && elem (head srvMatch) cfg.services + else if tail srvMatch == [ null ] && cfg.${head srvMatch}.enable then { inherit (v) origin; # mansrht crashes without it @@ -38,9 +38,9 @@ let # for services needing access to them. "builds.sr.ht::worker".buildlogs = "/var/log/sourcehut/buildsrht-worker"; "git.sr.ht".post-update-script = "/usr/bin/gitsrht-update-hook"; - "git.sr.ht".repos = "/var/lib/sourcehut/gitsrht/repos"; + "git.sr.ht".repos = cfg.settings."git.sr.ht".repos; "hg.sr.ht".changegroup-script = "/usr/bin/hgsrht-hook-changegroup"; - "hg.sr.ht".repos = "/var/lib/sourcehut/hgsrht/repos"; + "hg.sr.ht".repos = cfg.settings."hg.sr.ht".repos; # Making this a per service option despite being in a global section, # so that it uses the redis-server used by the service. "sr.ht".redis-host = cfg.${srv}.redis.host; @@ -77,6 +77,14 @@ let type = types.path; apply = s: "<" + toString s; }; + api-origin = mkOption { + description = lib.mdDoc "Origin URL for the API"; + type = types.str; + default = "http://${cfg.listenAddress}:${toString (cfg.${srv}.port + 100)}"; + defaultText = lib.literalMD '' + `"http://''${`[](#opt-services.sourcehut.listenAddress)`}:''${toString (`[](#opt-services.sourcehut.${srv}.port)` + 100)}"` + ''; + }; }; # Specialized python containing all the modules @@ -112,15 +120,6 @@ in and account management services ''); - services = mkOption { - type = with types; listOf (enum - [ "builds" "git" "hg" "hub" "lists" "man" "meta" "pages" "paste" "todo" ]); - defaultText = "locally enabled services"; - description = lib.mdDoc '' - Services that may be displayed as links in the title bar of the Web interface. - ''; - }; - listenAddress = mkOption { type = types.str; default = "localhost"; @@ -400,8 +399,8 @@ in This setting is propagated to newer and existing repositories. ''; type = types.str; - default = "${cfg.python}/bin/hgsrht-hook-changegroup"; - defaultText = "\${cfg.python}/bin/hgsrht-hook-changegroup"; + default = "${pkgs.sourcehut.hgsrht}/bin/hgsrht-hook-changegroup"; + defaultText = "\${pkgs.sourcehut.hgsrht}/bin/hgsrht-hook-changegroup"; }; repos = mkOption { description = lib.mdDoc '' @@ -501,12 +500,6 @@ in options."meta.sr.ht" = removeAttrs (commonServiceSettings "meta") ["oauth-client-id" "oauth-client-secret"] // { - api-origin = mkOption { - description = lib.mdDoc "Origin URL for API, 100 more than web."; - type = types.str; - default = "http://${cfg.listenAddress}:${toString (cfg.meta.port + 100)}"; - defaultText = lib.literalMD ''`"http://''${`[](#opt-services.sourcehut.listenAddress)`}:''${toString (`[](#opt-services.sourcehut.meta.port)` + 100)}"`''; - }; webhooks = mkOption { description = lib.mdDoc "The Redis connection used for the webhooks worker."; type = types.str; @@ -784,6 +777,7 @@ in extraConfig = '' PermitUserEnvironment SRHT_* ''; + startWhenNeeded = false; }; environment.etc."ssh/sourcehut/config.ini".source = settingsFormat.generate "sourcehut-dispatch-config.ini" @@ -792,15 +786,28 @@ in environment.etc."ssh/sourcehut/subdir/srht-dispatch" = { # sshd_config(5): The program must be owned by root, not writable by group or others mode = "0755"; - source = pkgs.writeShellScript "srht-dispatch" '' + source = pkgs.writeShellScript "srht-dispatch-wrapper" '' set -e + set -x cd /etc/ssh/sourcehut/subdir - ${cfg.python}/bin/gitsrht-dispatch "$@" + ${pkgs.sourcehut.gitsrht}/bin/gitsrht-dispatch "$@" ''; }; + systemd.tmpfiles.settings."10-sourcehut-gitsrht" = mkIf cfg.git.enable ( + builtins.listToAttrs (map (name: { + name = "/var/log/sourcehut/gitsrht-${name}"; + value.f = { + inherit (cfg.git) user group; + mode = "0644"; + }; + }) [ "keys" "shell" "update-hook" ]) + ); systemd.services.sshd = { - #path = optional cfg.git.enable [ cfg.git.package ]; + preStart = mkIf cfg.hg.enable '' + chown ${cfg.hg.user}:${cfg.hg.group} /var/log/sourcehut/hgsrht-keys + ''; serviceConfig = { + LogsDirectory = "sourcehut"; BindReadOnlyPaths = # Note that those /usr/bin/* paths are hardcoded in multiple places in *.sr.ht, # for instance to get the user from the [git.sr.ht::dispatch] settings. @@ -813,7 +820,6 @@ in "${pkgs.writeShellScript "buildsrht-keys-wrapper" '' set -e cd /run/sourcehut/buildsrht/subdir - set -x exec -a "$0" ${pkgs.sourcehut.buildsrht}/bin/buildsrht-keys "$@" ''}:/usr/bin/buildsrht-keys" "${pkgs.sourcehut.buildsrht}/bin/master-shell:/usr/bin/master-shell" @@ -825,31 +831,26 @@ in "${pkgs.writeShellScript "gitsrht-keys-wrapper" '' set -e cd /run/sourcehut/gitsrht/subdir - set -x exec -a "$0" ${pkgs.sourcehut.gitsrht}/bin/gitsrht-keys "$@" ''}:/usr/bin/gitsrht-keys" "${pkgs.writeShellScript "gitsrht-shell-wrapper" '' set -e cd /run/sourcehut/gitsrht/subdir - set -x + export PATH="${cfg.git.package}/bin:$PATH" + export SRHT_CONFIG=/run/sourcehut/gitsrht/config.ini exec -a "$0" ${pkgs.sourcehut.gitsrht}/bin/gitsrht-shell "$@" ''}:/usr/bin/gitsrht-shell" "${pkgs.writeShellScript "gitsrht-update-hook" '' set -e - test -e "''${PWD%/*}"/config.ini || - # Git hooks are run relative to their repository's directory, - # but gitsrht-update-hook looks up ../config.ini - ln -s /run/sourcehut/gitsrht/config.ini "''${PWD%/*}"/config.ini + export SRHT_CONFIG=/run/sourcehut/gitsrht/config.ini # hooks/post-update calls /usr/bin/gitsrht-update-hook as hooks/stage-3 # but this wrapper being a bash script, it overrides $0 with /usr/bin/gitsrht-update-hook # hence this hack to put hooks/stage-3 back into gitsrht-update-hook's $0 if test "''${STAGE3:+set}" then - set -x exec -a hooks/stage-3 ${pkgs.sourcehut.gitsrht}/bin/gitsrht-update-hook "$@" else export STAGE3=set - set -x exec -a "$0" ${pkgs.sourcehut.gitsrht}/bin/gitsrht-update-hook "$@" fi ''}:/usr/bin/gitsrht-update-hook" @@ -860,13 +861,11 @@ in "${pkgs.writeShellScript "hgsrht-keys-wrapper" '' set -e cd /run/sourcehut/hgsrht/subdir - set -x exec -a "$0" ${pkgs.sourcehut.hgsrht}/bin/hgsrht-keys "$@" ''}:/usr/bin/hgsrht-keys" "${pkgs.writeShellScript "hgsrht-shell-wrapper" '' set -e cd /run/sourcehut/hgsrht/subdir - set -x exec -a "$0" ${pkgs.sourcehut.hgsrht}/bin/hgsrht-shell "$@" ''}:/usr/bin/hgsrht-shell" # Mercurial's changegroup hooks are run relative to their repository's directory, @@ -875,8 +874,7 @@ in set -e test -e "''$PWD"/config.ini || ln -s /run/sourcehut/hgsrht/config.ini "''$PWD"/config.ini - set -x - exec -a "$0" ${cfg.python}/bin/hgsrht-hook-changegroup "$@" + exec -a "$0" ${pkgs.sourcehut.hgsrht}/bin/hgsrht-hook-changegroup "$@" ''}:/usr/bin/hgsrht-hook-changegroup" ]; }; @@ -1066,10 +1064,11 @@ in }; }) ]; - extraServices.gitsrht-api = { - serviceConfig.Restart = "always"; - serviceConfig.RestartSec = "5s"; - serviceConfig.ExecStart = "${pkgs.sourcehut.gitsrht}/bin/gitsrht-api -b ${cfg.listenAddress}:${toString (cfg.git.port + 100)}"; + extraServices.gitsrht-api.serviceConfig = { + Restart = "always"; + RestartSec = "5s"; + ExecStart = "${pkgs.sourcehut.gitsrht}/bin/gitsrht-api -b ${cfg.listenAddress}:${toString (cfg.git.port + 100)}"; + BindPaths = [ "${cfg.settings."git.sr.ht".repos}:/var/lib/sourcehut/gitsrht/repos" ]; }; extraServices.gitsrht-fcgiwrap = mkIf cfg.nginx.enable { serviceConfig = { @@ -1188,7 +1187,7 @@ in extraServices.listssrht-lmtp = { wants = [ "postfix.service" ]; unitConfig.JoinsNamespaceOf = optional cfg.postfix.enable "postfix.service"; - serviceConfig.ExecStart = "${cfg.python}/bin/listssrht-lmtp"; + serviceConfig.ExecStart = "${pkgs.sourcehut.listssrht}/bin/listssrht-lmtp"; # Avoid crashing: os.chown(sock, os.getuid(), sock_gid) serviceConfig.PrivateUsers = mkForce false; }; @@ -1252,55 +1251,30 @@ in ) cfg.settings)); serviceConfig.ExecStart = "${pkgs.sourcehut.metasrht}/bin/metasrht-api -b ${cfg.listenAddress}:${toString (cfg.meta.port + 100)}"; }; - extraConfig = mkMerge [ - { - assertions = [ - { assertion = let s = cfg.settings."meta.sr.ht::billing"; in - s.enabled == "yes" -> (s.stripe-public-key != null && s.stripe-secret-key != null); - message = "If meta.sr.ht::billing is enabled, the keys must be defined."; - } - ]; - environment.systemPackages = optional cfg.meta.enable - (pkgs.writeShellScriptBin "metasrht-manageuser" '' - set -eux - if test "$(${pkgs.coreutils}/bin/id -n -u)" != '${cfg.meta.user}' - then exec sudo -u '${cfg.meta.user}' "$0" "$@" - else - # In order to load config.ini - if cd /run/sourcehut/metasrht - then exec ${cfg.python}/bin/metasrht-manageuser "$@" - else cat <<EOF - Please run: sudo systemctl start metasrht - EOF - exit 1 - fi + extraConfig = { + assertions = [ + { assertion = let s = cfg.settings."meta.sr.ht::billing"; in + s.enabled == "yes" -> (s.stripe-public-key != null && s.stripe-secret-key != null); + message = "If meta.sr.ht::billing is enabled, the keys must be defined."; + } + ]; + environment.systemPackages = optional cfg.meta.enable + (pkgs.writeShellScriptBin "metasrht-manageuser" '' + set -eux + if test "$(${pkgs.coreutils}/bin/id -n -u)" != '${cfg.meta.user}' + then exec sudo -u '${cfg.meta.user}' "$0" "$@" + else + # In order to load config.ini + if cd /run/sourcehut/metasrht + then exec ${pkgs.sourcehut.metasrht}/bin/metasrht-manageuser "$@" + else cat <<EOF + Please run: sudo systemctl start metasrht + EOF + exit 1 fi - ''); - } - (mkIf cfg.nginx.enable { - services.nginx.virtualHosts."meta.${domain}" = { - locations."/query" = { - proxyPass = cfg.settings."meta.sr.ht".api-origin; - extraConfig = '' - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; - add_header 'Access-Control-Max-Age' 1728000; - add_header 'Content-Type' 'text/plain; charset=utf-8'; - add_header 'Content-Length' 0; - return 204; - } - - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; - add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; - ''; - }; - }; - }) - ]; + fi + ''); + }; }) (import ./service.nix "pages" { @@ -1356,7 +1330,7 @@ in extraServices.todosrht-lmtp = { wants = [ "postfix.service" ]; unitConfig.JoinsNamespaceOf = optional cfg.postfix.enable "postfix.service"; - serviceConfig.ExecStart = "${cfg.python}/bin/todosrht-lmtp"; + serviceConfig.ExecStart = "${pkgs.sourcehut.todosrht}/bin/todosrht-lmtp"; # Avoid crashing: os.chown(sock, os.getuid(), sock_gid) serviceConfig.PrivateUsers = mkForce false; }; @@ -1388,6 +1362,10 @@ in dispatch is deprecated. See https://sourcehut.org/blog/2022-08-01-dispatch-deprecation-plans/ for more information. '') + + (mkRemovedOptionModule [ "services" "sourcehut" "services"] '' + This option was removed in favor of individual <service>.enable flags. + '') ]; meta.doc = ./default.md; diff --git a/nixos/modules/services/misc/sourcehut/service.nix b/nixos/modules/services/misc/sourcehut/service.nix index aae13e0cc2c9..f08d5eb46871 100644 --- a/nixos/modules/services/misc/sourcehut/service.nix +++ b/nixos/modules/services/misc/sourcehut/service.nix @@ -108,7 +108,7 @@ let #SocketBindDeny = "any"; SystemCallFilter = [ "@system-service" - "~@aio" "~@keyring" "~@memlock" "~@privileged" "~@resources" "~@timer" + "~@aio" "~@keyring" "~@memlock" "~@privileged" "~@timer" "@chown" "@setuid" ]; SystemCallArchitectures = "native"; @@ -222,6 +222,23 @@ in expires 30d; ''; }; + locations."/query" = mkIf (cfg.settings.${iniKey} ? api-origin) { + proxyPass = cfg.settings.${iniKey}.api-origin; + extraConfig = '' + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + + add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; + ''; + }; } cfg.nginx.virtualHost ]; }; @@ -232,12 +249,12 @@ in ensureDatabases = [ srvCfg.postgresql.database ]; ensureUsers = map (name: { inherit name; - ensurePermissions = { "DATABASE \"${srvCfg.postgresql.database}\"" = "ALL PRIVILEGES"; }; + # We don't use it because we have a special default database name with dots. + # TODO(for maintainers of sourcehut): migrate away from custom preStart script. + ensureDBOwnership = false; }) [srvCfg.user]; }; - services.sourcehut.services = mkDefault (filter (s: cfg.${s}.enable) - [ "builds" "dispatch" "git" "hg" "hub" "lists" "man" "meta" "pages" "paste" "todo" ]); services.sourcehut.settings = mkMerge [ { @@ -363,6 +380,21 @@ in } extraService ])) extraServices) + + # Work around 'pq: permission denied for schema public' with postgres v15. + # See https://github.com/NixOS/nixpkgs/issues/216989 + # Workaround taken from nixos/forgejo: https://github.com/NixOS/nixpkgs/pull/262741 + # TODO(to maintainers of sourcehut): please migrate away from this workaround + # by migrating away from database name defaults with dots. + (lib.mkIf ( + cfg.postgresql.enable + && lib.strings.versionAtLeast config.services.postgresql.package.version "15.0" + ) { + postgresql.postStart = (lib.mkAfter '' + $PSQL -tAc 'ALTER DATABASE "${srvCfg.postgresql.database}" OWNER TO "${srvCfg.user}";' + ''); + } + ) ]; systemd.timers = mapAttrs (timerName: timer: |