{ config, lib, ... }: let inherit (lib) types; inherit (lib.modules) mkIf; inherit (lib.options) mkOption mkEnableOption; cfg = config.services.piped; in { options.services.piped = { enable = mkEnableOption "piped"; frontendDomain = mkOption { type = types.str; description = "Domain where the frontend will be displayed"; }; backendDomain = mkOption { type = types.nullOr types.str; description = "Domain where the backend will be hosted. Set to null for project's default backend"; }; proxyDomain = mkOption { type = types.str; description = "Domain used for the proxy server"; }; disableNginx = mkOption { type = types.bool; default = false; description = "Turn off module's nginx servers, this means you will need to manually proxy everything"; }; nginxForceSSL = mkOption { type = types.bool; default = false; description = "Should SSL/TLS be force enabled by nginx"; }; nginxEnableACME = mkOption { type = types.bool; default = false; description = "Should ACME be force enabled by nginx"; }; disableFrontend = mkOption { type = types.bool; default = false; description = "Don't host frontend"; }; disableBackend = mkOption { type = types.bool; default = false; description = "Don't host backend"; }; disableProxy = mkOption { type = types.bool; default = false; description = "Don't host proxy"; }; disablePostgresDB = mkOption { type = types.bool; default = false; description = "Manually configure postgres instead"; }; postgresDBHost = mkOption { type = types.str; default = "127.0.0.1"; description = "Host for postgres"; }; postgresDBPort = mkOption { type = types.number; default = 5432; description = "Port for postgres"; }; postgresDBName = mkOption { type = types.str; default = "piped"; description = "Database name for piped"; }; postgresDBUsername = mkOption { type = types.str; default = "piped"; description = "Postgres username"; }; postgresDBPassword = mkOption { type = types.str; default = "password"; description = "Password to use for postgres"; }; postgresDBPasswordFile = mkOption { type = types.nullOr types.str; default = null; description = "Password file to use for postgres, loaded at runtime"; }; proxyIPv4Only = mkOption { type = types.bool; default = false; description = "Only use IPv4 when querying youtube's servers"; }; proxyNginxExtraConfig = mkOption { type = types.lines; default = '' proxy_buffering on; proxy_buffers 1024 16k; proxy_set_header X-Forwarded-For ""; proxy_set_header CF-Connecting-IP ""; proxy_hide_header "alt-svc"; sendfile on; sendfile_max_chunk 512k; tcp_nopush on; aio threads=default; aio_write on; directio 16m; proxy_hide_header Cache-Control; proxy_hide_header etag; proxy_http_version 1.1; proxy_set_header Connection keep-alive; proxy_max_temp_file_size 32m; access_log off; ''; description = "Extra config for nginx on piped-proxy"; }; 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"; }; disableRegistrations = mkOption { type = types.bool; default = true; description = "Disable user registrations"; }; disableLBRYStreams = mkOption { type = types.bool; default = false; description = "Disable showing streams provided by LBRY Youtube Partnership"; }; enableCompromisedPasswordCheck = mkOption { type = types.bool; default = true; description = "Use the haveibeenpwned API to check if user password have been compromised"; }; enableCaptcha = mkOption { type = types.bool; default = true; description = "Enable captcha for registrations"; }; sentryDSN = mkOption { type = types.str; default = ""; description = "Public DSN for sentry error reporting"; }; captchaAPIURL = mkOption { type = types.str; default = ""; description = "API URL for Captcha"; }; # TODO: Key & KeyFile should be only one or the other used captchaAPIKey = mkOption { type = types.str; default = ""; description = "API Key for Captcha"; }; captchaAPIKeyFile = mkOption { type = types.str; default = ""; description = "API Key File for Captcha"; }; # TODO: run this, requires a go app and Tor server for proxy #enableRYDServer = mkOption { # type = types.bool; # default = true; # description = "Run a RYD Proxy Server to use"; #}; disableRYD = mkOption { type = types.bool; #default = if cfg.enableRYDServer then false else true; default = false; description = "Disables querying a Return YouTube Dislike server"; }; rydAPIURL = mkOption { type = types.str; #default = if cfg.enableRYDServer then cfg.rydProxyDomain else "https://ryd-proxy.kavin.rocks"; default = "https://ryd-proxy.kavin.rocks"; description = "API URL for a Return YouTube Dislike server"; }; # for Piped's Federation Shenanigan # https://github.com/TeamPiped/piped-federation#how-to-join enableFederation = mkOption { type = types.bool; default = false; description = "Enable federation of something"; }; matrixServerAddr = mkOption { type = types.str; default = ""; description = "Matrix server address for federation"; }; # TODO: make so only one of these options can be used matrixToken = mkOption { type = types.str; default = ""; description = "Matrix access token"; }; matrixTokenFile = mkOption { type = types.str; default = ""; description = "Matrix access token file"; }; internalBackendPort = mkOption { type = types.number; default = 3001; }; internalProxyPort = mkOption { type = types.number; default = 3002; }; }; config = mkIf (cfg.enable && (!cfg.disableBackend || !cfg.disableProxy)) { users.users."piped" = { isSystemUser = true; group = "piped"; }; users.groups.piped = {}; }; imports = [ ./backend.nix ./frontend.nix ./proxy.nix ./nginx.nix ]; }