2023-09-08 10:59:27 +01:00
|
|
|
{
|
|
|
|
config,
|
|
|
|
lib,
|
2023-09-14 16:56:17 +01:00
|
|
|
pkgs,
|
2023-09-08 10:59:27 +01:00
|
|
|
...
|
2023-09-08 11:36:35 +01:00
|
|
|
}: let
|
|
|
|
inherit (lib) types;
|
2023-09-08 11:38:45 +01:00
|
|
|
inherit (lib.modules) mkIf;
|
2023-09-14 16:56:17 +01:00
|
|
|
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
|
2023-09-08 11:36:35 +01:00
|
|
|
|
2023-09-08 10:59:27 +01:00
|
|
|
cfg = config.services.piped;
|
|
|
|
in {
|
|
|
|
options.services.piped = {
|
|
|
|
enable = mkEnableOption "piped";
|
|
|
|
|
2023-09-19 17:50:52 +01:00
|
|
|
frontend = {
|
|
|
|
# Enable implies turning on nginx for frontend as it is static files
|
|
|
|
enable = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = cfg.enable;
|
|
|
|
};
|
|
|
|
package = mkPackageOption pkgs "piped-frontend" {};
|
|
|
|
domain = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
description = "Domain where the frontend will be displayed";
|
|
|
|
};
|
|
|
|
|
|
|
|
nginx = {
|
|
|
|
forceSSL = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
enableACME = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
backend = {
|
|
|
|
enable = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = cfg.enable;
|
|
|
|
};
|
|
|
|
package = mkPackageOption pkgs "piped-backend" {};
|
|
|
|
domain = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
description = "Domain used for the backend server";
|
|
|
|
};
|
|
|
|
|
|
|
|
internalPort = mkOption {
|
|
|
|
type = types.number;
|
|
|
|
default = 3001;
|
|
|
|
};
|
|
|
|
|
|
|
|
nginx = {
|
|
|
|
disableNginx = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = "Turn off nginx for proxying backend, use backend.internalPort instead";
|
|
|
|
};
|
|
|
|
|
|
|
|
forceSSL = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
enableACME = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
database = {
|
|
|
|
disablePostgresDB = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = "Manually configure a database instead";
|
|
|
|
};
|
|
|
|
|
|
|
|
host = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "127.0.0.1";
|
|
|
|
description = "Database host";
|
|
|
|
};
|
|
|
|
|
|
|
|
port = mkOption {
|
|
|
|
type = types.number;
|
|
|
|
default = 5432;
|
|
|
|
description = "Database port";
|
|
|
|
};
|
|
|
|
|
|
|
|
name = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "piped";
|
|
|
|
description = "Database name";
|
|
|
|
};
|
|
|
|
|
|
|
|
username = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "piped";
|
|
|
|
description = "Database username";
|
|
|
|
};
|
|
|
|
|
|
|
|
usePassword = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
description = "Should use database password? If false then use passwordless auth or configure cert-based auth in databaseOptions";
|
|
|
|
};
|
|
|
|
|
|
|
|
password = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "";
|
|
|
|
description = "Database password (default is to allow passwordless auth for samehost for piped when empty)";
|
|
|
|
};
|
|
|
|
|
|
|
|
passwordFile = mkOption {
|
|
|
|
type = types.nullOr types.path;
|
|
|
|
default = null;
|
|
|
|
description = "Database password file, loaded at runtime";
|
|
|
|
};
|
|
|
|
|
|
|
|
databaseOptions = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "";
|
|
|
|
description = "Appended to end of ";
|
|
|
|
};
|
|
|
|
|
|
|
|
driverClass = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "org.postgresql.Driver";
|
|
|
|
description = "The driver class to be used for the database connection";
|
|
|
|
};
|
|
|
|
|
|
|
|
dialect = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "org.hibernate.dialect.PostgreSQLDialect";
|
|
|
|
example = "org.hibernate.dialect.CockroachDialect";
|
|
|
|
description = "The dialect class to be used for the database connection";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
captcha = {
|
|
|
|
enable = mkEnableOption "piped-backend-captcha";
|
|
|
|
|
|
|
|
apiURL = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "";
|
|
|
|
description = "API URL for Captcha (unknown protocol/standard, upstream project uses api.capmonster.cloud in example config)";
|
|
|
|
};
|
|
|
|
|
|
|
|
apiKey = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "";
|
|
|
|
description = "API Key for Captcha";
|
|
|
|
};
|
|
|
|
|
|
|
|
apiKeyFile = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
|
|
|
description = "API Key File for Captcha";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
ryd = {
|
|
|
|
disable = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = "Disables querying a Return YouTube Dislike server";
|
|
|
|
};
|
|
|
|
|
|
|
|
apiURL = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "https://ryd-proxy.kavin.rocks";
|
|
|
|
description = "API URL for a Return YouTube Dislike server";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
federation = {
|
|
|
|
# for Piped's Federation Shenanigan
|
|
|
|
# https://github.com/TeamPiped/piped-federation#how-to-join
|
|
|
|
enable = mkEnableOption "piped-backend-federation";
|
|
|
|
|
|
|
|
matrixServerAddr = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "";
|
|
|
|
description = "Matrix server address for federation";
|
|
|
|
};
|
|
|
|
|
|
|
|
matrixToken = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "";
|
|
|
|
description = "Matrix access token";
|
|
|
|
};
|
|
|
|
|
|
|
|
matrixTokenFile = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
|
|
|
description = "Matrix access token file";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
settings = {
|
|
|
|
extraSettings = mkOption {
|
|
|
|
type = types.attrs;
|
|
|
|
default = {};
|
|
|
|
description = "extra settings to pass to config.properties";
|
|
|
|
};
|
|
|
|
|
|
|
|
disableRegistrations = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = "Disable user registrations";
|
|
|
|
};
|
|
|
|
|
|
|
|
httpWorkers = mkOption {
|
|
|
|
type = types.number;
|
|
|
|
default = 2;
|
|
|
|
description = "Number of workers for HTTP backend tasks";
|
|
|
|
};
|
|
|
|
|
|
|
|
feedRetentionDays = mkOption {
|
|
|
|
type = types.number;
|
|
|
|
default = 30;
|
|
|
|
description = "Days feed is stored for";
|
|
|
|
};
|
|
|
|
|
|
|
|
subscriptionRetentionDays = mkOption {
|
|
|
|
type = types.number;
|
|
|
|
default = 30;
|
|
|
|
description = "Days subscriptions are stored for unauthenticated users";
|
|
|
|
};
|
|
|
|
|
|
|
|
sponsorblockServers = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = ["https://sponsor.ajay.app" "https://sponsorblock.kavin.rocks"];
|
|
|
|
description = "Days subscriptions are stored for unauthenticated users";
|
|
|
|
};
|
|
|
|
|
|
|
|
disableLBRYStreams = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = "Disable showing streams provided by LBRY";
|
|
|
|
};
|
|
|
|
|
|
|
|
enableCompromisedPasswordCheck = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
description = "Use the haveibeenpwned API to check if user password have been compromised";
|
|
|
|
};
|
|
|
|
|
|
|
|
sentryDSN = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
|
|
|
description = "Public DSN for sentry error reporting";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
proxy = {
|
|
|
|
enable = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = cfg.enable;
|
|
|
|
};
|
|
|
|
package = mkPackageOption pkgs "piped-proxy" {};
|
|
|
|
domain = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
description = "Domain used for the proxy server";
|
|
|
|
};
|
|
|
|
|
|
|
|
internalPort = mkOption {
|
|
|
|
type = types.number;
|
|
|
|
default = 3002;
|
|
|
|
};
|
|
|
|
|
2023-09-30 18:17:15 +01:00
|
|
|
disallowImageTranscoding = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = "turns off transcoding thumbnails/other to webp/avif if client adds those to allowed mime types on image requests; may use a lot of CPU depending on how many users";
|
|
|
|
};
|
|
|
|
|
2023-09-19 17:50:52 +01:00
|
|
|
nginx = {
|
|
|
|
disableNginx = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = "Turn off nginx for proxying proxy, use proxy.internalPort instead, you will need the relevant extra nginx config in proxy.nix or similar for good performance";
|
|
|
|
};
|
|
|
|
|
|
|
|
forceSSL = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
enableACME = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
proxyIPv4Only = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = "Only use IPv4 when querying youtube's servers";
|
|
|
|
};
|
2023-09-08 10:59:27 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-09-19 17:50:52 +01:00
|
|
|
config = mkIf (cfg.enable && (cfg.backend.enable || cfg.proxy.enable)) {
|
|
|
|
assertions = [
|
|
|
|
{
|
|
|
|
assertion = cfg.backend.captcha.enable && cfg.backend.captcha.apiKey != "" && cfg.backend.captcha.apiKeyFile != null -> cfg.certsDir != null;
|
|
|
|
message = "you must use either of services.piped.backend.captcha.{apiKey,apiKeyFile}";
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
2023-09-08 10:59:27 +01:00
|
|
|
users.users."piped" = {
|
|
|
|
isSystemUser = true;
|
|
|
|
group = "piped";
|
|
|
|
};
|
|
|
|
users.groups.piped = {};
|
|
|
|
};
|
2023-09-08 11:46:37 +01:00
|
|
|
|
|
|
|
imports = [
|
|
|
|
./backend.nix
|
|
|
|
./frontend.nix
|
|
|
|
./proxy.nix
|
|
|
|
];
|
2023-09-08 10:59:27 +01:00
|
|
|
}
|