nixos/sourcehut: reformat expressions using nixpkgs-fmt

This commit is contained in:
Tomas Antonio Lopez 2023-11-27 03:06:54 +01:00 committed by Anderson Torres
parent e35216204b
commit 087c83f45c

View File

@ -3,10 +3,10 @@ srv:
, srvsrht ? "${srv}srht" # Because "buildsrht" does not follow that pattern (missing an "s"). , srvsrht ? "${srv}srht" # Because "buildsrht" does not follow that pattern (missing an "s").
, iniKey ? "${srv}.sr.ht" , iniKey ? "${srv}.sr.ht"
, webhooks ? false , webhooks ? false
, extraTimers ? {} , extraTimers ? { }
, mainService ? {} , mainService ? { }
, extraServices ? {} , extraServices ? { }
, extraConfig ? {} , extraConfig ? { }
, port , port
}: }:
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
@ -19,101 +19,112 @@ let
cfg = config.services.sourcehut; cfg = config.services.sourcehut;
configIni = configIniOfService srv; configIni = configIniOfService srv;
srvCfg = cfg.${srv}; srvCfg = cfg.${srv};
baseService = serviceName: { allowStripe ? false }: extraService: let baseService = serviceName: { allowStripe ? false }: extraService:
runDir = "/run/sourcehut/${serviceName}"; let
rootDir = "/run/sourcehut/chroots/${serviceName}"; runDir = "/run/sourcehut/${serviceName}";
rootDir = "/run/sourcehut/chroots/${serviceName}";
in in
mkMerge [ extraService { mkMerge [
after = [ "network.target" ] ++ extraService
optional cfg.postgresql.enable "postgresql.service" ++ {
optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service"; after = [ "network.target" ] ++
requires = optional cfg.postgresql.enable "postgresql.service" ++
optional cfg.postgresql.enable "postgresql.service" ++ optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service";
optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service"; requires =
path = [ pkgs.gawk ]; optional cfg.postgresql.enable "postgresql.service" ++
environment.HOME = runDir; optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service";
serviceConfig = { path = [ pkgs.gawk ];
User = mkDefault srvCfg.user; environment.HOME = runDir;
Group = mkDefault srvCfg.group; serviceConfig = {
RuntimeDirectory = [ User = mkDefault srvCfg.user;
"sourcehut/${serviceName}" Group = mkDefault srvCfg.group;
# Used by *srht-keys which reads ../config.ini RuntimeDirectory = [
"sourcehut/${serviceName}/subdir" "sourcehut/${serviceName}"
"sourcehut/chroots/${serviceName}" # Used by *srht-keys which reads ../config.ini
]; "sourcehut/${serviceName}/subdir"
RuntimeDirectoryMode = "2750"; "sourcehut/chroots/${serviceName}"
# No need for the chroot path once inside the chroot ];
InaccessiblePaths = [ "-+${rootDir}" ]; RuntimeDirectoryMode = "2750";
# g+rx is for group members (eg. fcgiwrap or nginx) # No need for the chroot path once inside the chroot
# to read Git/Mercurial repositories, buildlogs, etc. InaccessiblePaths = [ "-+${rootDir}" ];
# o+x is for intermediate directories created by BindPaths= and like, # g+rx is for group members (eg. fcgiwrap or nginx)
# as they're owned by root:root. # to read Git/Mercurial repositories, buildlogs, etc.
UMask = "0026"; # o+x is for intermediate directories created by BindPaths= and like,
RootDirectory = rootDir; # as they're owned by root:root.
RootDirectoryStartOnly = true; UMask = "0026";
PrivateTmp = true; RootDirectory = rootDir;
MountAPIVFS = true; RootDirectoryStartOnly = true;
# config.ini is looked up in there, before /etc/srht/config.ini PrivateTmp = true;
# Note that it fails to be set in ExecStartPre= MountAPIVFS = true;
WorkingDirectory = mkDefault ("-"+runDir); # config.ini is looked up in there, before /etc/srht/config.ini
BindReadOnlyPaths = [ # Note that it fails to be set in ExecStartPre=
builtins.storeDir WorkingDirectory = mkDefault ("-" + runDir);
"/etc" BindReadOnlyPaths = [
"/run/booted-system" builtins.storeDir
"/run/current-system" "/etc"
"/run/systemd" "/run/booted-system"
] ++ "/run/current-system"
optional cfg.postgresql.enable "/run/postgresql" ++ "/run/systemd"
optional cfg.redis.enable "/run/redis-sourcehut-${srvsrht}"; ] ++
# LoadCredential= are unfortunately not available in ExecStartPre= optional cfg.postgresql.enable "/run/postgresql" ++
# Hence this one is run as root (the +) with RootDirectoryStartOnly= optional cfg.redis.enable "/run/redis-sourcehut-${srvsrht}";
# to reach credentials wherever they are. # LoadCredential= are unfortunately not available in ExecStartPre=
# Note that each systemd service gets its own ${runDir}/config.ini file. # Hence this one is run as root (the +) with RootDirectoryStartOnly=
ExecStartPre = mkBefore [("+"+pkgs.writeShellScript "${serviceName}-credentials" '' # to reach credentials wherever they are.
set -x # Note that each systemd service gets its own ${runDir}/config.ini file.
# Replace values beginning with a '<' by the content of the file whose name is after. ExecStartPre = mkBefore [
gawk '{ if (match($0,/^([^=]+=)<(.+)/,m)) { getline f < m[2]; print m[1] f } else print $0 }' ${configIni} | ("+" + pkgs.writeShellScript "${serviceName}-credentials" ''
${optionalString (!allowStripe) "gawk '!/^stripe-secret-key=/' |"} set -x
install -o ${srvCfg.user} -g root -m 400 /dev/stdin ${runDir}/config.ini # Replace values beginning with a '<' by the content of the file whose name is after.
'')]; gawk '{ if (match($0,/^([^=]+=)<(.+)/,m)) { getline f < m[2]; print m[1] f } else print $0 }' ${configIni} |
# The following options are only for optimizing: ${optionalString (!allowStripe) "gawk '!/^stripe-secret-key=/' |"}
# systemd-analyze security install -o ${srvCfg.user} -g root -m 400 /dev/stdin ${runDir}/config.ini
AmbientCapabilities = ""; '')
CapabilityBoundingSet = ""; ];
# ProtectClock= adds DeviceAllow=char-rtc r # The following options are only for optimizing:
DeviceAllow = ""; # systemd-analyze security
LockPersonality = true; AmbientCapabilities = "";
MemoryDenyWriteExecute = true; CapabilityBoundingSet = "";
NoNewPrivileges = true; # ProtectClock= adds DeviceAllow=char-rtc r
PrivateDevices = true; DeviceAllow = "";
PrivateMounts = true; LockPersonality = true;
PrivateNetwork = mkDefault false; MemoryDenyWriteExecute = true;
PrivateUsers = true; NoNewPrivileges = true;
ProcSubset = "pid"; PrivateDevices = true;
ProtectClock = true; PrivateMounts = true;
ProtectControlGroups = true; PrivateNetwork = mkDefault false;
ProtectHome = true; PrivateUsers = true;
ProtectHostname = true; ProcSubset = "pid";
ProtectKernelLogs = true; ProtectClock = true;
ProtectKernelModules = true; ProtectControlGroups = true;
ProtectKernelTunables = true; ProtectHome = true;
ProtectProc = "invisible"; ProtectHostname = true;
ProtectSystem = "strict"; ProtectKernelLogs = true;
RemoveIPC = true; ProtectKernelModules = true;
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; ProtectKernelTunables = true;
RestrictNamespaces = true; ProtectProc = "invisible";
RestrictRealtime = true; ProtectSystem = "strict";
RestrictSUIDSGID = true; RemoveIPC = true;
#SocketBindAllow = [ "tcp:${toString srvCfg.port}" "tcp:${toString srvCfg.prometheusPort}" ]; RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
#SocketBindDeny = "any"; RestrictNamespaces = true;
SystemCallFilter = [ RestrictRealtime = true;
"@system-service" RestrictSUIDSGID = true;
"~@aio" "~@keyring" "~@memlock" "~@privileged" "~@timer" #SocketBindAllow = [ "tcp:${toString srvCfg.port}" "tcp:${toString srvCfg.prometheusPort}" ];
"@chown" "@setuid" #SocketBindDeny = "any";
]; SystemCallFilter = [
SystemCallArchitectures = "native"; "@system-service"
}; "~@aio"
} ]; "~@keyring"
"~@memlock"
"~@privileged"
"~@timer"
"@chown"
"@setuid"
];
SystemCallArchitectures = "native";
};
}
];
in in
{ {
options.services.sourcehut.${srv} = { options.services.sourcehut.${srv} = {
@ -173,7 +184,7 @@ in
gunicorn = { gunicorn = {
extraArgs = mkOption { extraArgs = mkOption {
type = with types; listOf str; type = with types; listOf str;
default = ["--timeout 120" "--workers 1" "--log-level=info"]; default = [ "--timeout 120" "--workers 1" "--log-level=info" ];
description = lib.mdDoc "Extra arguments passed to Gunicorn."; description = lib.mdDoc "Extra arguments passed to Gunicorn.";
}; };
}; };
@ -181,7 +192,7 @@ in
webhooks = { webhooks = {
extraArgs = mkOption { extraArgs = mkOption {
type = with types; listOf str; type = with types; listOf str;
default = ["--loglevel DEBUG" "--pool eventlet" "--without-heartbeat"]; default = [ "--loglevel DEBUG" "--pool eventlet" "--without-heartbeat" ];
description = lib.mdDoc "Extra arguments passed to the Celery responsible for webhooks."; description = lib.mdDoc "Extra arguments passed to the Celery responsible for webhooks.";
}; };
celeryConfig = mkOption { celeryConfig = mkOption {
@ -192,216 +203,237 @@ in
}; };
}; };
config = lib.mkIf (cfg.enable && srvCfg.enable) (mkMerge [ extraConfig { config = lib.mkIf (cfg.enable && srvCfg.enable) (mkMerge [
users = { extraConfig
{
users = { users = {
"${srvCfg.user}" = { users = {
isSystemUser = true; "${srvCfg.user}" = {
group = mkDefault srvCfg.group; isSystemUser = true;
description = mkDefault "sourcehut user for ${srv}.sr.ht"; group = mkDefault srvCfg.group;
}; description = mkDefault "sourcehut user for ${srv}.sr.ht";
};
groups = {
"${srvCfg.group}" = { };
} // optionalAttrs (cfg.postgresql.enable
&& hasSuffix "0" (postgresql.settings.unix_socket_permissions or "")) {
"postgres".members = [ srvCfg.user ];
} // optionalAttrs (cfg.redis.enable
&& hasSuffix "0" (redis.settings.unixsocketperm or "")) {
"redis-sourcehut-${srvsrht}".members = [ srvCfg.user ];
};
};
services.nginx = mkIf cfg.nginx.enable {
virtualHosts."${srv}.${cfg.settings."sr.ht".global-domain}" = mkMerge [ {
forceSSL = mkDefault true;
locations."/".proxyPass = "http://${cfg.listenAddress}:${toString srvCfg.port}";
locations."/static" = {
root = "${pkgs.sourcehut.${srvsrht}}/${pkgs.sourcehut.python.sitePackages}/${srvsrht}";
extraConfig = mkDefault ''
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 ];
};
services.postgresql = mkIf cfg.postgresql.enable {
authentication = ''
local ${srvCfg.postgresql.database} ${srvCfg.user} trust
'';
ensureDatabases = [ srvCfg.postgresql.database ];
ensureUsers = map (name: {
inherit name;
# 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.settings = mkMerge [
{
"${srv}.sr.ht".origin = mkDefault "https://${srv}.${cfg.settings."sr.ht".global-domain}";
}
(mkIf cfg.postgresql.enable {
"${srv}.sr.ht".connection-string = mkDefault "postgresql:///${srvCfg.postgresql.database}?user=${srvCfg.user}&host=/run/postgresql";
})
];
services.redis.servers."sourcehut-${srvsrht}" = mkIf cfg.redis.enable {
enable = true;
databases = 3;
syslog = true;
# TODO: set a more informed value
save = mkDefault [ [1800 10] [300 100] ];
settings = {
# TODO: set a more informed value
maxmemory = "128MB";
maxmemory-policy = "volatile-ttl";
};
};
systemd.services = mkMerge [
{
"${srvsrht}" = baseService srvsrht { allowStripe = srv == "meta"; } (mkMerge [
{
description = "sourcehut ${srv}.sr.ht website service";
before = optional cfg.nginx.enable "nginx.service";
wants = optional cfg.nginx.enable "nginx.service";
wantedBy = [ "multi-user.target" ];
path = optional cfg.postgresql.enable postgresql.package;
# Beware: change in credentials' content will not trigger restart.
restartTriggers = [ configIni ];
serviceConfig = {
Type = "simple";
Restart = mkDefault "always";
#RestartSec = mkDefault "2min";
StateDirectory = [ "sourcehut/${srvsrht}" ];
StateDirectoryMode = "2750";
ExecStart = "${cfg.python}/bin/gunicorn ${srvsrht}.app:app --name ${srvsrht} --bind ${cfg.listenAddress}:${toString srvCfg.port} " + concatStringsSep " " srvCfg.gunicorn.extraArgs;
}; };
preStart = let };
version = pkgs.sourcehut.${srvsrht}.version; groups = {
stateDir = "/var/lib/sourcehut/${srvsrht}"; "${srvCfg.group}" = { };
in mkBefore '' } // optionalAttrs
set -x (cfg.postgresql.enable
# Use the /run/sourcehut/${srvsrht}/config.ini && hasSuffix "0" (postgresql.settings.unix_socket_permissions or ""))
# installed by a previous ExecStartPre= in baseService
cd /run/sourcehut/${srvsrht}
if test ! -e ${stateDir}/db; then
# Setup the initial database.
# Note that it stamps the alembic head afterward
${cfg.python}/bin/${srvsrht}-initdb
echo ${version} >${stateDir}/db
fi
${optionalString cfg.settings.${iniKey}.migrate-on-upgrade ''
if [ "$(cat ${stateDir}/db)" != "${version}" ]; then
# Manage schema migrations using alembic
${cfg.python}/bin/${srvsrht}-migrate -a upgrade head
echo ${version} >${stateDir}/db
fi
''}
# Update copy of each users' profile to the latest
# See https://lists.sr.ht/~sircmpwn/sr.ht-admins/<20190302181207.GA13778%40cirno.my.domain>
if test ! -e ${stateDir}/webhook; then
# Update ${iniKey}'s users' profile copy to the latest
${cfg.python}/bin/srht-update-profiles ${iniKey}
touch ${stateDir}/webhook
fi
'';
} mainService ]);
}
(mkIf webhooks {
"${srvsrht}-webhooks" = baseService "${srvsrht}-webhooks" {}
{ {
description = "sourcehut ${srv}.sr.ht webhooks service"; "postgres".members = [ srvCfg.user ];
after = [ "${srvsrht}.service" ]; } // optionalAttrs
wantedBy = [ "${srvsrht}.service" ]; (cfg.redis.enable
partOf = [ "${srvsrht}.service" ]; && hasSuffix "0" (redis.settings.unixsocketperm or ""))
preStart = '' {
cp ${pkgs.writeText "${srvsrht}-webhooks-celeryconfig.py" srvCfg.webhooks.celeryConfig} \ "redis-sourcehut-${srvsrht}".members = [ srvCfg.user ];
/run/sourcehut/${srvsrht}-webhooks/celeryconfig.py };
};
services.nginx = mkIf cfg.nginx.enable {
virtualHosts."${srv}.${cfg.settings."sr.ht".global-domain}" = mkMerge [{
forceSSL = mkDefault true;
locations."/".proxyPass = "http://${cfg.listenAddress}:${toString srvCfg.port}";
locations."/static" = {
root = "${pkgs.sourcehut.${srvsrht}}/${pkgs.sourcehut.python.sitePackages}/${srvsrht}";
extraConfig = mkDefault ''
expires 30d;
''; '';
serviceConfig = { };
Type = "simple"; locations."/query" = mkIf (cfg.settings.${iniKey} ? api-origin) {
Restart = "always"; proxyPass = cfg.settings.${iniKey}.api-origin;
ExecStart = "${cfg.python}/bin/celery --app ${srvsrht}.webhooks worker --hostname ${srvsrht}-webhooks@%%h " + concatStringsSep " " srvCfg.webhooks.extraArgs; extraConfig = ''
# Avoid crashing: os.getloadavg() add_header 'Access-Control-Allow-Origin' '*';
ProcSubset = mkForce "all"; 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];
};
services.postgresql = mkIf cfg.postgresql.enable {
authentication = ''
local ${srvCfg.postgresql.database} ${srvCfg.user} trust
'';
ensureDatabases = [ srvCfg.postgresql.database ];
ensureUsers = map
(name: {
inherit name;
# 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.settings = mkMerge [
{
"${srv}.sr.ht".origin = mkDefault "https://${srv}.${cfg.settings."sr.ht".global-domain}";
}
(mkIf cfg.postgresql.enable {
"${srv}.sr.ht".connection-string = mkDefault "postgresql:///${srvCfg.postgresql.database}?user=${srvCfg.user}&host=/run/postgresql";
})
];
services.redis.servers."sourcehut-${srvsrht}" = mkIf cfg.redis.enable {
enable = true;
databases = 3;
syslog = true;
# TODO: set a more informed value
save = mkDefault [ [ 1800 10 ] [ 300 100 ] ];
settings = {
# TODO: set a more informed value
maxmemory = "128MB";
maxmemory-policy = "volatile-ttl";
};
};
systemd.services = mkMerge [
{
"${srvsrht}" = baseService srvsrht { allowStripe = srv == "meta"; } (mkMerge [
{
description = "sourcehut ${srv}.sr.ht website service";
before = optional cfg.nginx.enable "nginx.service";
wants = optional cfg.nginx.enable "nginx.service";
wantedBy = [ "multi-user.target" ];
path = optional cfg.postgresql.enable postgresql.package;
# Beware: change in credentials' content will not trigger restart.
restartTriggers = [ configIni ];
serviceConfig = {
Type = "simple";
Restart = mkDefault "always";
#RestartSec = mkDefault "2min";
StateDirectory = [ "sourcehut/${srvsrht}" ];
StateDirectoryMode = "2750";
ExecStart = "${cfg.python}/bin/gunicorn ${srvsrht}.app:app --name ${srvsrht} --bind ${cfg.listenAddress}:${toString srvCfg.port} " + concatStringsSep " " srvCfg.gunicorn.extraArgs;
};
preStart =
let
version = pkgs.sourcehut.${srvsrht}.version;
stateDir = "/var/lib/sourcehut/${srvsrht}";
in
mkBefore ''
set -x
# Use the /run/sourcehut/${srvsrht}/config.ini
# installed by a previous ExecStartPre= in baseService
cd /run/sourcehut/${srvsrht}
if test ! -e ${stateDir}/db; then
# Setup the initial database.
# Note that it stamps the alembic head afterward
${cfg.python}/bin/${srvsrht}-initdb
echo ${version} >${stateDir}/db
fi
${optionalString cfg.settings.${iniKey}.migrate-on-upgrade ''
if [ "$(cat ${stateDir}/db)" != "${version}" ]; then
# Manage schema migrations using alembic
${cfg.python}/bin/${srvsrht}-migrate -a upgrade head
echo ${version} >${stateDir}/db
fi
''}
# Update copy of each users' profile to the latest
# See https://lists.sr.ht/~sircmpwn/sr.ht-admins/<20190302181207.GA13778%40cirno.my.domain>
if test ! -e ${stateDir}/webhook; then
# Update ${iniKey}'s users' profile copy to the latest
${cfg.python}/bin/srht-update-profiles ${iniKey}
touch ${stateDir}/webhook
fi
'';
}
mainService
]);
}
(mkIf webhooks {
"${srvsrht}-webhooks" = baseService "${srvsrht}-webhooks" { }
{
description = "sourcehut ${srv}.sr.ht webhooks service";
after = [ "${srvsrht}.service" ];
wantedBy = [ "${srvsrht}.service" ];
partOf = [ "${srvsrht}.service" ];
preStart = ''
cp ${pkgs.writeText "${srvsrht}-webhooks-celeryconfig.py" srvCfg.webhooks.celeryConfig} \
/run/sourcehut/${srvsrht}-webhooks/celeryconfig.py
'';
serviceConfig = {
Type = "simple";
Restart = "always";
ExecStart = "${cfg.python}/bin/celery --app ${srvsrht}.webhooks worker --hostname ${srvsrht}-webhooks@%%h " + concatStringsSep " " srvCfg.webhooks.extraArgs;
# Avoid crashing: os.getloadavg()
ProcSubset = mkForce "all";
};
}; };
}; })
})
(mapAttrs (timerName: timer: (baseService timerName {} (mkMerge [ (mapAttrs
{ (timerName: timer: (baseService timerName { } (mkMerge [
description = "sourcehut ${timerName} service"; {
after = [ "network.target" "${srvsrht}.service" ]; description = "sourcehut ${timerName} service";
serviceConfig = { after = [ "network.target" "${srvsrht}.service" ];
Type = "oneshot"; serviceConfig = {
ExecStart = "${cfg.python}/bin/${timerName}"; Type = "oneshot";
}; ExecStart = "${cfg.python}/bin/${timerName}";
} };
(timer.service or {}) }
]))) extraTimers) (timer.service or { })
])))
extraTimers)
(mapAttrs (serviceName: extraService: baseService serviceName {} (mkMerge [ (mapAttrs
{ (serviceName: extraService: baseService serviceName { } (mkMerge [
description = "sourcehut ${serviceName} service"; {
# So that extraServices have the PostgreSQL database initialized. description = "sourcehut ${serviceName} service";
after = [ "${srvsrht}.service" ]; # So that extraServices have the PostgreSQL database initialized.
wantedBy = [ "${srvsrht}.service" ]; after = [ "${srvsrht}.service" ];
partOf = [ "${srvsrht}.service" ]; wantedBy = [ "${srvsrht}.service" ];
serviceConfig = { partOf = [ "${srvsrht}.service" ];
Type = "simple"; serviceConfig = {
Restart = mkDefault "always"; Type = "simple";
}; Restart = mkDefault "always";
} };
extraService }
])) extraServices) extraService
]))
extraServices)
# Work around 'pq: permission denied for schema public' with postgres v15. # Work around 'pq: permission denied for schema public' with postgres v15.
# See https://github.com/NixOS/nixpkgs/issues/216989 # See https://github.com/NixOS/nixpkgs/issues/216989
# Workaround taken from nixos/forgejo: https://github.com/NixOS/nixpkgs/pull/262741 # Workaround taken from nixos/forgejo: https://github.com/NixOS/nixpkgs/pull/262741
# TODO(to maintainers of sourcehut): please migrate away from this workaround # TODO(to maintainers of sourcehut): please migrate away from this workaround
# by migrating away from database name defaults with dots. # by migrating away from database name defaults with dots.
(lib.mkIf ( (lib.mkIf
cfg.postgresql.enable (
&& lib.strings.versionAtLeast config.services.postgresql.package.version "15.0" 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}";' {
''); postgresql.postStart = (lib.mkAfter ''
} $PSQL -tAc 'ALTER DATABASE "${srvCfg.postgresql.database}" OWNER TO "${srvCfg.user}";'
) '');
]; }
)
];
systemd.timers = mapAttrs (timerName: timer: systemd.timers = mapAttrs
{ (timerName: timer:
description = "sourcehut timer for ${timerName}"; {
wantedBy = [ "timers.target" ]; description = "sourcehut timer for ${timerName}";
inherit (timer) timerConfig; wantedBy = [ "timers.target" ];
}) extraTimers; inherit (timer) timerConfig;
} ]); })
extraTimers;
}
]);
} }