mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-12-25 23:23:07 +00:00
1eb6cc1582
1. Removed the #!/bin/sh shebang at the beginning, because systemd.services.<name>.script already adds a #!/nix/store/.../bin/bash shebang. Previously: #!/nix/store/516kai7nl5dxr792c0nzq0jp8m4zvxpi-bash-5.2p32/bin/bash set -e #!/bin/sh umask 077 ... 2. Exec into nodejs, so that the startup script is no longer running but replaces itself by nodejs. This way, only one processus is running inside peertube.service.
857 lines
28 KiB
Nix
857 lines
28 KiB
Nix
{ lib, pkgs, config, options, ... }:
|
|
|
|
let
|
|
cfg = config.services.peertube;
|
|
opt = options.services.peertube;
|
|
|
|
settingsFormat = pkgs.formats.json {};
|
|
configFile = settingsFormat.generate "production.json" cfg.settings;
|
|
|
|
env = {
|
|
NODE_CONFIG_DIR = "/var/lib/peertube/config";
|
|
NODE_ENV = "production";
|
|
NODE_EXTRA_CA_CERTS = "/etc/ssl/certs/ca-certificates.crt";
|
|
NPM_CONFIG_CACHE = "/var/cache/peertube/.npm";
|
|
NPM_CONFIG_PREFIX = cfg.package;
|
|
HOME = cfg.package;
|
|
};
|
|
|
|
systemCallsList = [ "@cpu-emulation" "@debug" "@keyring" "@ipc" "@memlock" "@mount" "@obsolete" "@privileged" "@setuid" ];
|
|
|
|
cfgService = {
|
|
# Proc filesystem
|
|
ProcSubset = "pid";
|
|
ProtectProc = "invisible";
|
|
# Access write directories
|
|
UMask = "0027";
|
|
# Capabilities
|
|
CapabilityBoundingSet = "";
|
|
# Security
|
|
NoNewPrivileges = true;
|
|
# Sandboxing
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
PrivateDevices = true;
|
|
PrivateUsers = true;
|
|
ProtectClock = true;
|
|
ProtectHostname = true;
|
|
ProtectKernelLogs = true;
|
|
ProtectKernelModules = true;
|
|
ProtectKernelTunables = true;
|
|
ProtectControlGroups = true;
|
|
RestrictNamespaces = true;
|
|
LockPersonality = true;
|
|
RestrictRealtime = true;
|
|
RestrictSUIDSGID = true;
|
|
RemoveIPC = true;
|
|
PrivateMounts = true;
|
|
# System Call Filtering
|
|
SystemCallArchitectures = "native";
|
|
};
|
|
|
|
envFile = pkgs.writeText "peertube.env" (lib.concatMapStrings (s: s + "\n") (
|
|
(lib.concatLists (lib.mapAttrsToList (name: value:
|
|
lib.optional (value != null) ''${name}="${toString value}"''
|
|
) env))));
|
|
|
|
peertubeEnv = pkgs.writeShellScriptBin "peertube-env" ''
|
|
set -a
|
|
source "${envFile}"
|
|
eval -- "\$@"
|
|
'';
|
|
|
|
nginxCommonHeaders = lib.optionalString config.services.nginx.virtualHosts.${cfg.localDomain}.forceSSL ''
|
|
add_header Strict-Transport-Security 'max-age=31536000';
|
|
'' + lib.optionalString (config.services.nginx.virtualHosts.${cfg.localDomain}.quic && config.services.nginx.virtualHosts.${cfg.localDomain}.http3) ''
|
|
add_header Alt-Svc 'h3=":$server_port"; ma=604800';
|
|
'';
|
|
|
|
nginxCommonHeadersExtra = ''
|
|
add_header Access-Control-Allow-Origin '*';
|
|
add_header Access-Control-Allow-Methods 'GET, OPTIONS';
|
|
add_header Access-Control-Allow-Headers 'Range,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
|
|
'';
|
|
|
|
in {
|
|
options.services.peertube = {
|
|
enable = lib.mkEnableOption "Peertube";
|
|
|
|
user = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "peertube";
|
|
description = "User account under which Peertube runs.";
|
|
};
|
|
|
|
group = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "peertube";
|
|
description = "Group under which Peertube runs.";
|
|
};
|
|
|
|
localDomain = lib.mkOption {
|
|
type = lib.types.str;
|
|
example = "peertube.example.com";
|
|
description = "The domain serving your PeerTube instance.";
|
|
};
|
|
|
|
listenHttp = lib.mkOption {
|
|
type = lib.types.port;
|
|
default = 9000;
|
|
description = "The port that the local PeerTube web server will listen on.";
|
|
};
|
|
|
|
listenWeb = lib.mkOption {
|
|
type = lib.types.port;
|
|
default = 9000;
|
|
description = "The public-facing port that PeerTube will be accessible at (likely 80 or 443 if running behind a reverse proxy). Clients will try to access PeerTube at this port.";
|
|
};
|
|
|
|
enableWebHttps = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Whether clients will access your PeerTube instance with HTTPS. Does NOT configure the PeerTube webserver itself to listen for incoming HTTPS connections.";
|
|
};
|
|
|
|
dataDirs = lib.mkOption {
|
|
type = lib.types.listOf lib.types.path;
|
|
default = [ ];
|
|
example = [ "/opt/peertube/storage" "/var/cache/peertube" ];
|
|
description = "Allow access to custom data locations.";
|
|
};
|
|
|
|
serviceEnvironmentFile = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.path;
|
|
default = null;
|
|
example = "/run/keys/peertube/password-init-root";
|
|
description = ''
|
|
Set environment variables for the service. Mainly useful for setting the initial root password.
|
|
For example write to file:
|
|
PT_INITIAL_ROOT_PASSWORD=changeme
|
|
'';
|
|
};
|
|
|
|
settings = lib.mkOption {
|
|
type = settingsFormat.type;
|
|
example = lib.literalExpression ''
|
|
{
|
|
listen = {
|
|
hostname = "0.0.0.0";
|
|
};
|
|
log = {
|
|
level = "debug";
|
|
};
|
|
storage = {
|
|
tmp = "/opt/data/peertube/storage/tmp/";
|
|
logs = "/opt/data/peertube/storage/logs/";
|
|
cache = "/opt/data/peertube/storage/cache/";
|
|
};
|
|
}
|
|
'';
|
|
description = "Configuration for peertube.";
|
|
};
|
|
|
|
configureNginx = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Configure nginx as a reverse proxy for peertube.";
|
|
};
|
|
|
|
secrets = {
|
|
secretsFile = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.path;
|
|
default = null;
|
|
example = "/run/secrets/peertube";
|
|
description = ''
|
|
Secrets to run PeerTube.
|
|
Generate one using `openssl rand -hex 32`
|
|
'';
|
|
};
|
|
};
|
|
|
|
database = {
|
|
createLocally = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Configure local PostgreSQL database server for PeerTube.";
|
|
};
|
|
|
|
host = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = if cfg.database.createLocally then "/run/postgresql" else null;
|
|
defaultText = lib.literalExpression ''
|
|
if config.${opt.database.createLocally}
|
|
then "/run/postgresql"
|
|
else null
|
|
'';
|
|
example = "192.168.15.47";
|
|
description = "Database host address or unix socket.";
|
|
};
|
|
|
|
port = lib.mkOption {
|
|
type = lib.types.port;
|
|
default = 5432;
|
|
description = "Database host port.";
|
|
};
|
|
|
|
name = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "peertube";
|
|
description = "Database name.";
|
|
};
|
|
|
|
user = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "peertube";
|
|
description = "Database user.";
|
|
};
|
|
|
|
passwordFile = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.path;
|
|
default = null;
|
|
example = "/run/keys/peertube/password-postgresql";
|
|
description = "Password for PostgreSQL database.";
|
|
};
|
|
};
|
|
|
|
redis = {
|
|
createLocally = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Configure local Redis server for PeerTube.";
|
|
};
|
|
|
|
host = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = if cfg.redis.createLocally && !cfg.redis.enableUnixSocket then "127.0.0.1" else null;
|
|
defaultText = lib.literalExpression ''
|
|
if config.${opt.redis.createLocally} && !config.${opt.redis.enableUnixSocket}
|
|
then "127.0.0.1"
|
|
else null
|
|
'';
|
|
description = "Redis host.";
|
|
};
|
|
|
|
port = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.port;
|
|
default = if cfg.redis.createLocally && cfg.redis.enableUnixSocket then null else 31638;
|
|
defaultText = lib.literalExpression ''
|
|
if config.${opt.redis.createLocally} && config.${opt.redis.enableUnixSocket}
|
|
then null
|
|
else 6379
|
|
'';
|
|
description = "Redis port.";
|
|
};
|
|
|
|
passwordFile = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.path;
|
|
default = null;
|
|
example = "/run/keys/peertube/password-redis-db";
|
|
description = "Password for redis database.";
|
|
};
|
|
|
|
enableUnixSocket = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = cfg.redis.createLocally;
|
|
defaultText = lib.literalExpression "config.${opt.redis.createLocally}";
|
|
description = "Use Unix socket.";
|
|
};
|
|
};
|
|
|
|
smtp = {
|
|
createLocally = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Configure local Postfix SMTP server for PeerTube.";
|
|
};
|
|
|
|
passwordFile = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.path;
|
|
default = null;
|
|
example = "/run/keys/peertube/password-smtp";
|
|
description = "Password for smtp server.";
|
|
};
|
|
};
|
|
|
|
package = lib.mkOption {
|
|
type = lib.types.package;
|
|
default = pkgs.peertube;
|
|
defaultText = lib.literalExpression "pkgs.peertube";
|
|
description = "PeerTube package to use.";
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
assertions = [
|
|
{ assertion = cfg.serviceEnvironmentFile == null || !lib.hasPrefix builtins.storeDir cfg.serviceEnvironmentFile;
|
|
message = ''
|
|
<option>services.peertube.serviceEnvironmentFile</option> points to
|
|
a file in the Nix store. You should use a quoted absolute path to
|
|
prevent this.
|
|
'';
|
|
}
|
|
{ assertion = cfg.secrets.secretsFile != null;
|
|
message = ''
|
|
<option>services.peertube.secrets.secretsFile</option> needs to be set.
|
|
'';
|
|
}
|
|
{ assertion = !(cfg.redis.enableUnixSocket && (cfg.redis.host != null || cfg.redis.port != null));
|
|
message = ''
|
|
<option>services.peertube.redis.createLocally</option> and redis network connection (<option>services.peertube.redis.host</option> or <option>services.peertube.redis.port</option>) enabled. Disable either of them.
|
|
'';
|
|
}
|
|
{ assertion = cfg.redis.enableUnixSocket || (cfg.redis.host != null && cfg.redis.port != null);
|
|
message = ''
|
|
<option>services.peertube.redis.host</option> and <option>services.peertube.redis.port</option> needs to be set if <option>services.peertube.redis.enableUnixSocket</option> is not enabled.
|
|
'';
|
|
}
|
|
{ assertion = cfg.redis.passwordFile == null || !lib.hasPrefix builtins.storeDir cfg.redis.passwordFile;
|
|
message = ''
|
|
<option>services.peertube.redis.passwordFile</option> points to
|
|
a file in the Nix store. You should use a quoted absolute path to
|
|
prevent this.
|
|
'';
|
|
}
|
|
{ assertion = cfg.database.passwordFile == null || !lib.hasPrefix builtins.storeDir cfg.database.passwordFile;
|
|
message = ''
|
|
<option>services.peertube.database.passwordFile</option> points to
|
|
a file in the Nix store. You should use a quoted absolute path to
|
|
prevent this.
|
|
'';
|
|
}
|
|
{ assertion = cfg.smtp.passwordFile == null || !lib.hasPrefix builtins.storeDir cfg.smtp.passwordFile;
|
|
message = ''
|
|
<option>services.peertube.smtp.passwordFile</option> points to
|
|
a file in the Nix store. You should use a quoted absolute path to
|
|
prevent this.
|
|
'';
|
|
}
|
|
];
|
|
|
|
environment.systemPackages = [ cfg.package.cli ];
|
|
|
|
services.peertube.settings = lib.mkMerge [
|
|
{
|
|
listen = {
|
|
port = cfg.listenHttp;
|
|
};
|
|
webserver = {
|
|
https = (if cfg.enableWebHttps then true else false);
|
|
hostname = "${cfg.localDomain}";
|
|
port = cfg.listenWeb;
|
|
};
|
|
database = {
|
|
hostname = "${cfg.database.host}";
|
|
port = cfg.database.port;
|
|
name = "${cfg.database.name}";
|
|
username = "${cfg.database.user}";
|
|
};
|
|
redis = {
|
|
hostname = "${toString cfg.redis.host}";
|
|
port = (lib.optionalString (cfg.redis.port != null) cfg.redis.port);
|
|
};
|
|
storage = {
|
|
tmp = lib.mkDefault "/var/lib/peertube/storage/tmp/";
|
|
tmp_persistent = lib.mkDefault "/var/lib/peertube/storage/tmp_persistent/";
|
|
bin = lib.mkDefault "/var/lib/peertube/storage/bin/";
|
|
avatars = lib.mkDefault "/var/lib/peertube/storage/avatars/";
|
|
web_videos = lib.mkDefault "/var/lib/peertube/storage/web-videos/";
|
|
streaming_playlists = lib.mkDefault "/var/lib/peertube/storage/streaming-playlists/";
|
|
redundancy = lib.mkDefault "/var/lib/peertube/storage/redundancy/";
|
|
logs = lib.mkDefault "/var/lib/peertube/storage/logs/";
|
|
previews = lib.mkDefault "/var/lib/peertube/storage/previews/";
|
|
thumbnails = lib.mkDefault "/var/lib/peertube/storage/thumbnails/";
|
|
storyboards = lib.mkDefault "/var/lib/peertube/storage/storyboards/";
|
|
torrents = lib.mkDefault "/var/lib/peertube/storage/torrents/";
|
|
captions = lib.mkDefault "/var/lib/peertube/storage/captions/";
|
|
cache = lib.mkDefault "/var/lib/peertube/storage/cache/";
|
|
plugins = lib.mkDefault "/var/lib/peertube/storage/plugins/";
|
|
well_known = lib.mkDefault "/var/lib/peertube/storage/well_known/";
|
|
client_overrides = lib.mkDefault "/var/lib/peertube/storage/client-overrides/";
|
|
};
|
|
import = {
|
|
videos = {
|
|
http = {
|
|
youtube_dl_release = {
|
|
python_path = "${pkgs.python3}/bin/python";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|
|
(lib.mkIf cfg.redis.enableUnixSocket { redis = { socket = "/run/redis-peertube/redis.sock"; }; })
|
|
];
|
|
|
|
systemd.tmpfiles.rules = [
|
|
"d '/var/lib/peertube/config' 0700 ${cfg.user} ${cfg.group} - -"
|
|
"z '/var/lib/peertube/config' 0700 ${cfg.user} ${cfg.group} - -"
|
|
"d '/var/lib/peertube/www' 0750 ${cfg.user} ${cfg.group} - -"
|
|
"z '/var/lib/peertube/www' 0750 ${cfg.user} ${cfg.group} - -"
|
|
];
|
|
|
|
systemd.services.peertube-init-db = lib.mkIf cfg.database.createLocally {
|
|
description = "Initialization database for PeerTube daemon";
|
|
after = [ "network.target" "postgresql.service" ];
|
|
requires = [ "postgresql.service" ];
|
|
|
|
script = let
|
|
psqlSetupCommands = pkgs.writeText "peertube-init.sql" ''
|
|
SELECT 'CREATE USER "${cfg.database.user}"' WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${cfg.database.user}')\gexec
|
|
SELECT 'CREATE DATABASE "${cfg.database.name}" OWNER "${cfg.database.user}" TEMPLATE template0 ENCODING UTF8' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${cfg.database.name}')\gexec
|
|
\c '${cfg.database.name}'
|
|
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
|
CREATE EXTENSION IF NOT EXISTS unaccent;
|
|
'';
|
|
in "${config.services.postgresql.package}/bin/psql -f ${psqlSetupCommands}";
|
|
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
WorkingDirectory = cfg.package;
|
|
# User and group
|
|
User = "postgres";
|
|
Group = "postgres";
|
|
# Sandboxing
|
|
RestrictAddressFamilies = [ "AF_UNIX" ];
|
|
MemoryDenyWriteExecute = true;
|
|
# System Call Filtering
|
|
SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@resources" ]);
|
|
} // cfgService;
|
|
};
|
|
|
|
systemd.services.peertube = {
|
|
description = "PeerTube daemon";
|
|
after = [ "network.target" ]
|
|
++ lib.optional cfg.redis.createLocally "redis-peertube.service"
|
|
++ lib.optionals cfg.database.createLocally [ "postgresql.service" "peertube-init-db.service" ];
|
|
requires = lib.optional cfg.redis.createLocally "redis-peertube.service"
|
|
++ lib.optionals cfg.database.createLocally [ "postgresql.service" "peertube-init-db.service" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
environment = env;
|
|
|
|
path = with pkgs; [ nodejs_18 yarn ffmpeg-headless openssl ];
|
|
|
|
script = ''
|
|
umask 077
|
|
cat > /var/lib/peertube/config/local.yaml <<EOF
|
|
${lib.optionalString (cfg.secrets.secretsFile != null) ''
|
|
secrets:
|
|
peertube: '$(cat ${cfg.secrets.secretsFile})'
|
|
''}
|
|
${lib.optionalString ((!cfg.database.createLocally) && (cfg.database.passwordFile != null)) ''
|
|
database:
|
|
password: '$(cat ${cfg.database.passwordFile})'
|
|
''}
|
|
${lib.optionalString (cfg.redis.passwordFile != null) ''
|
|
redis:
|
|
auth: '$(cat ${cfg.redis.passwordFile})'
|
|
''}
|
|
${lib.optionalString (cfg.smtp.passwordFile != null) ''
|
|
smtp:
|
|
password: '$(cat ${cfg.smtp.passwordFile})'
|
|
''}
|
|
EOF
|
|
umask 027
|
|
ln -sf ${configFile} /var/lib/peertube/config/production.json
|
|
ln -sf ${cfg.package}/config/default.yaml /var/lib/peertube/config/default.yaml
|
|
ln -sf ${cfg.package}/client/dist -T /var/lib/peertube/www/client
|
|
ln -sf ${cfg.settings.storage.client_overrides} -T /var/lib/peertube/www/client-overrides
|
|
exec node dist/server
|
|
'';
|
|
serviceConfig = {
|
|
Type = "simple";
|
|
Restart = "always";
|
|
RestartSec = 20;
|
|
TimeoutSec = 60;
|
|
WorkingDirectory = cfg.package;
|
|
SyslogIdentifier = "peertube";
|
|
# User and group
|
|
User = cfg.user;
|
|
Group = cfg.group;
|
|
# State directory and mode
|
|
StateDirectory = "peertube";
|
|
StateDirectoryMode = "0750";
|
|
# Cache directory and mode
|
|
CacheDirectory = "peertube";
|
|
CacheDirectoryMode = "0750";
|
|
# Access write directories
|
|
ReadWritePaths = cfg.dataDirs;
|
|
# Environment
|
|
EnvironmentFile = cfg.serviceEnvironmentFile;
|
|
# Sandboxing
|
|
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK" ];
|
|
MemoryDenyWriteExecute = false;
|
|
# System Call Filtering
|
|
SystemCallFilter = [ ("~" + lib.concatStringsSep " " systemCallsList) "pipe" "pipe2" ];
|
|
} // cfgService;
|
|
};
|
|
|
|
services.nginx = lib.mkIf cfg.configureNginx {
|
|
enable = true;
|
|
upstreams."peertube".servers = {
|
|
"127.0.0.1:${toString cfg.listenHttp}".fail_timeout = "0";
|
|
};
|
|
virtualHosts."${cfg.localDomain}" = {
|
|
root = "/var/lib/peertube/www";
|
|
|
|
# Application
|
|
locations."/" = {
|
|
tryFiles = "/dev/null @api";
|
|
priority = 1110;
|
|
};
|
|
|
|
locations."~ ^/api/v1/videos/(upload-resumable|([^/]+/source/replace-resumable))$" = {
|
|
tryFiles = "/dev/null @api";
|
|
priority = 1120;
|
|
|
|
extraConfig = ''
|
|
client_max_body_size 0;
|
|
proxy_request_buffering off;
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
locations."~ ^/api/v1/videos/(upload|([^/]+/studio/edit))$" = {
|
|
tryFiles = "/dev/null @api";
|
|
root = cfg.settings.storage.tmp;
|
|
priority = 1130;
|
|
|
|
extraConfig = ''
|
|
limit_except POST HEAD { deny all; }
|
|
|
|
client_max_body_size 12G;
|
|
add_header X-File-Maximum-Size 8G always;
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
locations."~ ^/api/v1/runners/jobs/[^/]+/(update|success)$" = {
|
|
tryFiles = "/dev/null @api";
|
|
root = cfg.settings.storage.tmp;
|
|
priority = 1135;
|
|
|
|
extraConfig = ''
|
|
client_max_body_size 12G;
|
|
add_header X-File-Maximum-Size 8G always;
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
locations."~ ^/api/v1/(videos|video-playlists|video-channels|users/me)" = {
|
|
tryFiles = "/dev/null @api";
|
|
priority = 1140;
|
|
|
|
extraConfig = ''
|
|
client_max_body_size 6M;
|
|
add_header X-File-Maximum-Size 4M always;
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
locations."@api" = {
|
|
proxyPass = "http://peertube";
|
|
priority = 1150;
|
|
|
|
extraConfig = ''
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
proxy_connect_timeout 10m;
|
|
|
|
proxy_send_timeout 10m;
|
|
proxy_read_timeout 10m;
|
|
|
|
client_max_body_size 100k;
|
|
send_timeout 10m;
|
|
''+ nginxCommonHeaders;
|
|
};
|
|
|
|
# Websocket
|
|
locations."/socket.io" = {
|
|
tryFiles = "/dev/null @api_websocket";
|
|
priority = 1210;
|
|
};
|
|
|
|
locations."/tracker/socket" = {
|
|
tryFiles = "/dev/null @api_websocket";
|
|
priority = 1220;
|
|
|
|
extraConfig = ''
|
|
proxy_read_timeout 15m;
|
|
'';
|
|
};
|
|
|
|
locations."~ ^/plugins/[^/]+(/[^/]+)?/ws/" = {
|
|
tryFiles = "/dev/null @api_websocket";
|
|
priority = 1230;
|
|
};
|
|
|
|
locations."@api_websocket" = {
|
|
proxyPass = "http://peertube";
|
|
priority = 1240;
|
|
|
|
extraConfig = ''
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection 'upgrade';
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
# Bypass PeerTube for performance reasons.
|
|
locations."~ ^/client/(assets/images/(icons/icon-36x36\.png|icons/icon-48x48\.png|icons/icon-72x72\.png|icons/icon-96x96\.png|icons/icon-144x144\.png|icons/icon-192x192\.png|icons/icon-512x512\.png|logo\.svg|favicon\.png|default-playlist\.jpg|default-avatar-account\.png|default-avatar-account-48x48\.png|default-avatar-video-channel\.png|default-avatar-video-channel-48x48\.png))$" = {
|
|
tryFiles = "/client-overrides/$1 /client/$1 $1";
|
|
priority = 1310;
|
|
|
|
extraConfig = nginxCommonHeaders;
|
|
};
|
|
|
|
locations."~ ^/client/(.*\.(js|css|png|svg|woff2|otf|ttf|woff|eot))$" = {
|
|
alias = "${cfg.package}/client/dist/$1";
|
|
priority = 1320;
|
|
extraConfig = ''
|
|
add_header Cache-Control 'public, max-age=604800, immutable';
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
locations."^~ /download/" = {
|
|
proxyPass = "http://peertube";
|
|
priority = 1410;
|
|
extraConfig = ''
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
proxy_limit_rate 5M;
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
locations."^~ /static/streaming-playlists/hls/private/" = {
|
|
proxyPass = "http://peertube";
|
|
priority = 1420;
|
|
extraConfig = ''
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
proxy_limit_rate 5M;
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
locations."^~ /static/web-videos/private/" = {
|
|
proxyPass = "http://peertube";
|
|
priority = 1430;
|
|
extraConfig = ''
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
proxy_limit_rate 5M;
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
locations."^~ /static/webseed/private/" = {
|
|
proxyPass = "http://peertube";
|
|
priority = 1440;
|
|
extraConfig = ''
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
proxy_limit_rate 5M;
|
|
'' + nginxCommonHeaders;
|
|
};
|
|
|
|
locations."^~ /static/redundancy/" = {
|
|
tryFiles = "$uri @api";
|
|
root = cfg.settings.storage.redundancy;
|
|
priority = 1450;
|
|
extraConfig = ''
|
|
set $peertube_limit_rate 800k;
|
|
|
|
if ($request_uri ~ -fragmented.mp4$) {
|
|
set $peertube_limit_rate 5M;
|
|
}
|
|
|
|
if ($request_method = 'OPTIONS') {
|
|
${nginxCommonHeaders}
|
|
${nginxCommonHeadersExtra}
|
|
add_header Access-Control-Max-Age 1728000;
|
|
add_header Content-Type 'text/plain charset=UTF-8';
|
|
add_header Content-Length 0;
|
|
return 204;
|
|
}
|
|
if ($request_method = 'GET') {
|
|
${nginxCommonHeaders}
|
|
${nginxCommonHeadersExtra}
|
|
|
|
access_log off;
|
|
}
|
|
|
|
aio threads;
|
|
sendfile on;
|
|
sendfile_max_chunk 1M;
|
|
|
|
limit_rate $peertube_limit_rate;
|
|
limit_rate_after 5M;
|
|
|
|
rewrite ^/static/redundancy/(.*)$ /$1 break;
|
|
'';
|
|
};
|
|
|
|
locations."^~ /static/streaming-playlists/" = {
|
|
tryFiles = "$uri @api";
|
|
root = cfg.settings.storage.streaming_playlists;
|
|
priority = 1460;
|
|
extraConfig = ''
|
|
set $peertube_limit_rate 800k;
|
|
|
|
if ($request_uri ~ -fragmented.mp4$) {
|
|
set $peertube_limit_rate 5M;
|
|
}
|
|
|
|
if ($request_method = 'OPTIONS') {
|
|
${nginxCommonHeaders}
|
|
${nginxCommonHeadersExtra}
|
|
add_header Access-Control-Max-Age 1728000;
|
|
add_header Content-Type 'text/plain charset=UTF-8';
|
|
add_header Content-Length 0;
|
|
return 204;
|
|
}
|
|
if ($request_method = 'GET') {
|
|
${nginxCommonHeaders}
|
|
${nginxCommonHeadersExtra}
|
|
|
|
access_log off;
|
|
}
|
|
|
|
aio threads;
|
|
sendfile on;
|
|
sendfile_max_chunk 1M;
|
|
|
|
limit_rate $peertube_limit_rate;
|
|
limit_rate_after 5M;
|
|
|
|
rewrite ^/static/streaming-playlists/(.*)$ /$1 break;
|
|
'';
|
|
};
|
|
|
|
locations."^~ /static/web-videos/" = {
|
|
tryFiles = "$uri @api";
|
|
root = cfg.settings.storage.web_videos;
|
|
priority = 1470;
|
|
extraConfig = ''
|
|
set $peertube_limit_rate 800k;
|
|
|
|
if ($request_uri ~ -fragmented.mp4$) {
|
|
set $peertube_limit_rate 5M;
|
|
}
|
|
|
|
if ($request_method = 'OPTIONS') {
|
|
${nginxCommonHeaders}
|
|
${nginxCommonHeadersExtra}
|
|
add_header Access-Control-Max-Age 1728000;
|
|
add_header Content-Type 'text/plain charset=UTF-8';
|
|
add_header Content-Length 0;
|
|
return 204;
|
|
}
|
|
if ($request_method = 'GET') {
|
|
${nginxCommonHeaders}
|
|
${nginxCommonHeadersExtra}
|
|
|
|
access_log off;
|
|
}
|
|
|
|
aio threads;
|
|
sendfile on;
|
|
sendfile_max_chunk 1M;
|
|
|
|
limit_rate $peertube_limit_rate;
|
|
limit_rate_after 5M;
|
|
|
|
rewrite ^/static/web-videos/(.*)$ /$1 break;
|
|
'';
|
|
};
|
|
|
|
locations."^~ /static/webseed/" = {
|
|
tryFiles = "$uri @api";
|
|
root = cfg.settings.storage.web_videos;
|
|
priority = 1480;
|
|
extraConfig = ''
|
|
set $peertube_limit_rate 800k;
|
|
|
|
if ($request_uri ~ -fragmented.mp4$) {
|
|
set $peertube_limit_rate 5M;
|
|
}
|
|
|
|
if ($request_method = 'OPTIONS') {
|
|
${nginxCommonHeaders}
|
|
${nginxCommonHeadersExtra}
|
|
add_header Access-Control-Max-Age 1728000;
|
|
add_header Content-Type 'text/plain charset=UTF-8';
|
|
add_header Content-Length 0;
|
|
return 204;
|
|
}
|
|
if ($request_method = 'GET') {
|
|
${nginxCommonHeaders}
|
|
${nginxCommonHeadersExtra}
|
|
|
|
access_log off;
|
|
}
|
|
|
|
aio threads;
|
|
sendfile on;
|
|
sendfile_max_chunk 1M;
|
|
|
|
limit_rate $peertube_limit_rate;
|
|
limit_rate_after 5M;
|
|
|
|
rewrite ^/static/webseed/(.*)$ /web-videos/$1 break;
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
services.postgresql = lib.mkIf cfg.database.createLocally {
|
|
enable = true;
|
|
};
|
|
|
|
services.redis.servers.peertube = lib.mkMerge [
|
|
(lib.mkIf cfg.redis.createLocally {
|
|
enable = true;
|
|
})
|
|
(lib.mkIf (cfg.redis.createLocally && !cfg.redis.enableUnixSocket) {
|
|
bind = "127.0.0.1";
|
|
port = cfg.redis.port;
|
|
})
|
|
(lib.mkIf (cfg.redis.createLocally && cfg.redis.enableUnixSocket) {
|
|
unixSocket = "/run/redis-peertube/redis.sock";
|
|
unixSocketPerm = 660;
|
|
})
|
|
];
|
|
|
|
services.postfix = lib.mkIf cfg.smtp.createLocally {
|
|
enable = true;
|
|
hostname = lib.mkDefault "${cfg.localDomain}";
|
|
};
|
|
|
|
users.users = lib.mkMerge [
|
|
(lib.mkIf (cfg.user == "peertube") {
|
|
peertube = {
|
|
isSystemUser = true;
|
|
group = cfg.group;
|
|
home = cfg.package;
|
|
};
|
|
})
|
|
(lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ peertubeEnv pkgs.nodejs_18 pkgs.yarn pkgs.ffmpeg-headless ])
|
|
(lib.mkIf cfg.redis.enableUnixSocket {${config.services.peertube.user}.extraGroups = [ "redis-peertube" ];})
|
|
];
|
|
|
|
users.groups = {
|
|
${cfg.group} = {
|
|
members = lib.optional cfg.configureNginx config.services.nginx.user;
|
|
};
|
|
};
|
|
};
|
|
}
|