2023-09-08 10:59:27 +01:00
|
|
|
{
|
|
|
|
config,
|
|
|
|
lib,
|
|
|
|
pkgs,
|
|
|
|
...
|
2023-09-08 11:36:35 +01:00
|
|
|
}: let
|
|
|
|
inherit (lib.modules) mkIf;
|
|
|
|
inherit (lib.trivial) boolToString;
|
|
|
|
inherit (lib.attrsets) mapAttrsToList optionalAttrs;
|
2023-09-08 11:47:19 +01:00
|
|
|
inherit (lib.strings) coptionalString concatStringsSep;
|
2023-09-08 11:36:35 +01:00
|
|
|
inherit (pkgs) writeText writeShellScript;
|
|
|
|
|
2023-09-08 10:59:27 +01:00
|
|
|
cfg = config.services.piped;
|
|
|
|
|
2023-09-08 11:36:35 +01:00
|
|
|
sedEscapeSlashes = "sed 's#/#\\\/#'";
|
|
|
|
sedEscapeSingleQuotes = "sed \"s#'#\\\'#\"";
|
|
|
|
|
|
|
|
backendConfig =
|
2023-09-08 10:59:27 +01:00
|
|
|
{
|
|
|
|
PORT = cfg.internalBackendPort;
|
|
|
|
HTTP_WORKERS = cfg.httpWorkers;
|
|
|
|
PROXY_PART = "https://${cfg.proxyDomain}";
|
|
|
|
API_URL = "https://${cfg.backendDomain}";
|
|
|
|
FRONTEND_URL = "https://${cfg.frontendDomain}";
|
|
|
|
DISABLE_REGISTRATION = cfg.disableRegistrations;
|
|
|
|
COMPROMISED_PASSWORD_CHECK = cfg.enableCompromisedPasswordCheck;
|
|
|
|
FEED_RETENTION = cfg.feedRetentionDays;
|
|
|
|
SUBSCRIPTIONS_EXPIRY = cfg.subscriptionRetentionDays;
|
|
|
|
SPONSORBLOCK_SERVERS = concatStringsSep "," cfg.sponsorblockServers;
|
|
|
|
DISABLE_RYD = cfg.disableRYD;
|
|
|
|
DISABLE_LBRY = cfg.disableLBRYStreams;
|
|
|
|
RYD_PROXY_URL = cfg.rydAPIURL;
|
|
|
|
SENTRY_DSN = cfg.sentryDSN;
|
2023-09-08 11:36:35 +01:00
|
|
|
"hibernate.connection.url" = "jdbc:postgresql://${cfg.postgresDBHost}:${toString cfg.postgresDBPort}/${cfg.postgresDBName}";
|
2023-09-08 10:59:27 +01:00
|
|
|
"hibernate.connection.driver_class" = "org.postgresql.Driver";
|
|
|
|
"hibernate.dialect" = "org.hibernate.dialect.PostgreSQLDialect";
|
2023-09-08 11:36:35 +01:00
|
|
|
"hibernate.connection.username" = "${cfg.postgresDBUsername}";
|
2023-09-08 10:59:27 +01:00
|
|
|
"hibernate.connection.password" =
|
2023-09-08 11:36:35 +01:00
|
|
|
if cfg.postgresDBPasswordFile == null
|
|
|
|
then cfg.postgresDBPassword
|
|
|
|
else "POSTGRES_PASSWORD_PLACEHOLDER";
|
2023-09-08 10:59:27 +01:00
|
|
|
}
|
|
|
|
// (optionalAttrs cfg.enableCaptcha {
|
|
|
|
CAPTCHA_API_URL = cfg.captchaAPIURL;
|
|
|
|
# This is substituted in the PreStart of piped-backend.service
|
|
|
|
CAPTCHA_API_KEY =
|
|
|
|
if cfg.captchaAPIKeyFile != ""
|
2023-09-08 11:36:35 +01:00
|
|
|
then "CAPTCHA_API_KEY_FILE_PLACEHOLDER"
|
2023-09-08 10:59:27 +01:00
|
|
|
else cfg.captchaAPIKey;
|
|
|
|
})
|
|
|
|
// (optionalAttrs cfg.enableFederation {
|
|
|
|
MATRIX_SERVER = cfg.matrixServerAddr;
|
|
|
|
# also substituted
|
|
|
|
MATRIX_TOKEN =
|
|
|
|
if cfg.matrixTokenFile != ""
|
2023-09-08 11:36:35 +01:00
|
|
|
then "MATRIX_TOKEN_FILE_PLACEHOLDER"
|
2023-09-08 10:59:27 +01:00
|
|
|
else cfg.matrixToken;
|
|
|
|
});
|
|
|
|
|
2023-09-08 11:36:35 +01:00
|
|
|
cfgValueToString = value:
|
|
|
|
if builtins.isBool value
|
|
|
|
then boolToString value
|
|
|
|
else toString value;
|
|
|
|
|
|
|
|
cfgToLine = key: value: "${key}:${cfgValueToString value}";
|
|
|
|
|
|
|
|
cfgToString = config: (concatStringsSep "\n"
|
|
|
|
(mapAttrsToList cfgToLine config));
|
|
|
|
|
|
|
|
backendConfigFile =
|
|
|
|
writeText "config.properties"
|
|
|
|
(cfgToString backendConfig);
|
2023-09-08 10:59:27 +01:00
|
|
|
in {
|
2023-09-08 11:36:35 +01:00
|
|
|
config = mkIf (cfg.enable && !cfg.disableBackend) {
|
2023-09-08 10:59:27 +01:00
|
|
|
systemd.tmpfiles.rules = ["d /run/piped-backend - piped piped"];
|
|
|
|
|
|
|
|
systemd.services.piped-backend = {
|
|
|
|
wantedBy = ["multi-user.target"];
|
|
|
|
serviceConfig = {
|
|
|
|
WorkingDirectory = "/run/piped-backend";
|
|
|
|
ExecStartPre = let
|
|
|
|
confFile = "/run/piped-backend/config.properties";
|
2023-09-08 11:36:35 +01:00
|
|
|
in
|
|
|
|
writeShellScript "piped-backend-init" ''
|
|
|
|
[ -f "${confFile}" ] && rm ${confFile}
|
|
|
|
cp ${backendConfigFile} ${confFile}
|
|
|
|
chmod 660 ${confFile}
|
|
|
|
|
|
|
|
${optionalString (cfg.enableCaptcha && cfg.captchaAPIKeyFile != "") ''
|
|
|
|
sed -i "s/CAPTCHA_API_KEY_FILE_PLACEHOLDER/$(cat ${cfg.captchaAPIKeyFile} | ${sedEscapeSlashes})/" ${confFile}
|
2023-09-08 10:59:27 +01:00
|
|
|
''}
|
2023-09-08 11:36:35 +01:00
|
|
|
|
|
|
|
${optionalString
|
|
|
|
(cfg.enableFederation && cfg.matrixTokenFile != "") ''
|
|
|
|
sed -i "s/MATRIX_TOKEN_FILE_PLACEHOLDER/$(cat ${cfg.matrixTokenFile} | ${sedEscapeSlashes})/" ${confFile}
|
|
|
|
''}
|
|
|
|
|
|
|
|
${optionalString
|
|
|
|
(cfg.postgresDBPasswordFile != null) ''
|
|
|
|
sed -i "s/POSTGRES_PASSWORD_PLACEHOLDER/$(cat ${cfg.postgresDBPasswordFile} | ${sedEscapeSlashes})/" ${confFile}
|
|
|
|
''}
|
|
|
|
'';
|
|
|
|
|
2023-09-08 10:59:27 +01:00
|
|
|
ExecStart = "${pkgs.piped-backend}/bin/piped-backend";
|
|
|
|
|
|
|
|
RestartSec = "5s";
|
|
|
|
User = "piped";
|
|
|
|
|
|
|
|
CapabilityBoundingSet = "";
|
|
|
|
PrivateDevices = true;
|
|
|
|
PrivateUsers = true;
|
|
|
|
ProtectHome = true;
|
|
|
|
ProtectKernelLogs = true;
|
|
|
|
ProtectProc = "invisible";
|
|
|
|
RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
|
|
|
|
RestrictNamespaces = true;
|
|
|
|
SystemCallArchitectures = "native";
|
|
|
|
SystemCallFilter = ["@system-service" "~@privileged" "~@resources"];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-09-08 11:36:35 +01:00
|
|
|
# Set password for piped when running postgres as piped won't run with
|
|
|
|
# passwordless authentication
|
|
|
|
systemd.services.piped-password = mkIf (!cfg.disablePostgresDB) {
|
|
|
|
serviceConfig = {
|
|
|
|
Type = "oneshot";
|
|
|
|
User = "postgres";
|
|
|
|
};
|
|
|
|
|
2023-09-08 10:59:27 +01:00
|
|
|
wantedBy = ["piped-backend.service"];
|
|
|
|
wants = ["postgresql.service"];
|
|
|
|
after = ["postgresql.service"];
|
2023-09-08 11:36:35 +01:00
|
|
|
|
2023-09-08 10:59:27 +01:00
|
|
|
script = ''
|
2023-09-08 11:36:35 +01:00
|
|
|
${config.services.postgresql.package}/bin/psql -c "ALTER USER ${cfg.postgresDBUsername} WITH PASSWORD '${
|
|
|
|
if cfg.postgresDBPasswordFile != null
|
|
|
|
then "$(cat ${cfg.postgresDBPasswordFile} | ${sedEscapeSingleQuotes})"
|
|
|
|
else cfg.postgresDBPassword
|
2023-09-08 10:59:27 +01:00
|
|
|
}';"
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2023-09-08 11:36:35 +01:00
|
|
|
services.postgresql = mkIf (!cfg.disablePostgresDB) {
|
2023-09-08 10:59:27 +01:00
|
|
|
enable = true;
|
|
|
|
ensureUsers = [
|
|
|
|
{
|
2023-09-08 11:36:35 +01:00
|
|
|
name = cfg.postgresDBUsername;
|
|
|
|
ensurePermissions."DATABASE ${cfg.postgresDBName}" = "ALL PRIVILEGES";
|
2023-09-08 10:59:27 +01:00
|
|
|
}
|
|
|
|
];
|
2023-09-08 11:36:35 +01:00
|
|
|
ensureDatabases = [cfg.postgresDBName];
|
2023-09-08 10:59:27 +01:00
|
|
|
};
|
|
|
|
|
2023-09-08 11:36:35 +01:00
|
|
|
services.nginx.virtualHosts."${cfg.backendDomain}" = mkIf (!cfg.disableNginx) {
|
2023-09-08 10:59:27 +01:00
|
|
|
forceSSL = cfg.nginxForceSSL;
|
|
|
|
enableACME = cfg.nginxEnableACME;
|
|
|
|
locations."/" = {
|
|
|
|
proxyPass = "http://127.0.0.1:${toString cfg.internalBackendPort}";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|