232 lines
7.1 KiB
Nix
232 lines
7.1 KiB
Nix
{ config, pkgs, lib, ... }:
|
|
|
|
with lib;
|
|
{
|
|
# Invidious - Privacy-focused YouTube frontend
|
|
# Replaces Piped with native NixOS service
|
|
|
|
# Secret for Invidious companion authentication
|
|
sops.secrets.invidious-companion-key = {
|
|
key = "invidious-companion-key";
|
|
};
|
|
|
|
# Main Invidious service
|
|
services.invidious = {
|
|
enable = true;
|
|
domain = "invidious.cloonar.com";
|
|
port = 3000;
|
|
|
|
# PostgreSQL database configuration
|
|
database = {
|
|
createLocally = true;
|
|
};
|
|
|
|
# Enable nginx reverse proxy with automatic TLS
|
|
nginx.enable = true;
|
|
|
|
# Enable http3-ytproxy for video/image proxying
|
|
# Handles /videoplayback, /vi/, /ggpht/, /sb/ paths
|
|
http3-ytproxy.enable = true;
|
|
|
|
# Signature helper - crashes with current YouTube player format
|
|
# sig-helper = {
|
|
# enable = true;
|
|
# };
|
|
|
|
# Service settings
|
|
settings = {
|
|
# Disable registration - admin user created via init script
|
|
registration_enabled = false;
|
|
|
|
# Disable CAPTCHA (not needed for private instance)
|
|
captcha_enabled = false;
|
|
|
|
# Database configuration
|
|
check_tables = true;
|
|
db = {
|
|
user = "invidious";
|
|
dbname = "invidious";
|
|
};
|
|
|
|
# Optional: Instance customization
|
|
default_home = "Popular";
|
|
feed_menu = [ "Popular" "Trending" "Subscriptions" ];
|
|
|
|
# HTTPS configuration for proper URL generation
|
|
external_port = mkForce 443;
|
|
https_only = mkForce true;
|
|
|
|
# YouTube compatibility settings
|
|
use_quic = true;
|
|
force_resolve = "ipv4";
|
|
};
|
|
};
|
|
|
|
# Use Podman for OCI containers
|
|
virtualisation.oci-containers.backend = "podman";
|
|
|
|
# Create Invidious network for container communication
|
|
systemd.services.init-invidious-network = {
|
|
description = "Create Podman network for Invidious companion";
|
|
wantedBy = [ "multi-user.target" ];
|
|
before = [ "podman-invidious-companion.service" ];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
RemainAfterExit = true;
|
|
};
|
|
script = ''
|
|
${pkgs.podman}/bin/podman network exists invidious-net || \
|
|
${pkgs.podman}/bin/podman network create --interface-name=podman2 --subnet=10.90.0.0/24 invidious-net
|
|
'';
|
|
};
|
|
|
|
# Create systemd tmpfiles directory for Invidious config
|
|
systemd.tmpfiles.rules = [
|
|
"d /var/lib/invidious 0755 root root - -"
|
|
"d /run/invidious-companion 0700 root root - -"
|
|
];
|
|
|
|
# Generate companion environment file with secret key
|
|
systemd.services.invidious-companion-env-generate = {
|
|
description = "Generate Invidious companion environment file";
|
|
wantedBy = [ "multi-user.target" ];
|
|
before = [ "podman-invidious-companion.service" ];
|
|
after = [ "init-invidious-network.service" ];
|
|
requires = [ "init-invidious-network.service" ];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
RemainAfterExit = true;
|
|
};
|
|
script = ''
|
|
COMPANION_KEY=$(cat ${config.sops.secrets.invidious-companion-key.path})
|
|
cat > /run/invidious-companion/env <<EOF
|
|
PORT=8282
|
|
HOST=0.0.0.0
|
|
SERVER_SECRET_KEY=$COMPANION_KEY
|
|
EOF
|
|
chmod 600 /run/invidious-companion/env
|
|
'';
|
|
};
|
|
|
|
# Invidious Companion container (handles PO token generation and video streams)
|
|
virtualisation.oci-containers.containers.invidious-companion = {
|
|
image = "quay.io/invidious/invidious-companion:latest";
|
|
ports = [ "127.0.0.1:8282:8282" ];
|
|
volumes = [
|
|
"invidious-companion-cache:/var/tmp:rw"
|
|
];
|
|
environmentFiles = [
|
|
"/run/invidious-companion/env"
|
|
];
|
|
extraOptions = [
|
|
"--pull=newer"
|
|
"--network=invidious-net"
|
|
"--cap-drop=ALL"
|
|
"--security-opt=no-new-privileges:true"
|
|
"--read-only"
|
|
];
|
|
};
|
|
|
|
# Ensure companion container depends on env file generation
|
|
systemd.services."podman-invidious-companion" = {
|
|
after = mkAfter [ "invidious-companion-env-generate.service" ];
|
|
requires = mkAfter [ "invidious-companion-env-generate.service" ];
|
|
};
|
|
|
|
# Generate Invidious companion config with actual secret key
|
|
systemd.services.invidious-companion-config-generate = {
|
|
description = "Generate Invidious companion configuration";
|
|
wantedBy = [ "multi-user.target" ];
|
|
before = [ "invidious.service" ];
|
|
after = [ "init-invidious-network.service" ];
|
|
requires = [ "init-invidious-network.service" ];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
RemainAfterExit = true;
|
|
};
|
|
script = ''
|
|
mkdir -p /var/lib/invidious
|
|
COMPANION_KEY=$(cat ${config.sops.secrets.invidious-companion-key.path})
|
|
cat > /var/lib/invidious/companion-config.json <<EOF
|
|
{
|
|
"invidious_companion": [
|
|
{
|
|
"private_url": "http://127.0.0.1:8282/companion"
|
|
}
|
|
],
|
|
"invidious_companion_key": "$COMPANION_KEY"
|
|
}
|
|
EOF
|
|
chmod 644 /var/lib/invidious/companion-config.json
|
|
chown root:root /var/lib/invidious/companion-config.json
|
|
'';
|
|
};
|
|
|
|
# Configure Invidious to use companion via extraSettingsFile
|
|
services.invidious.extraSettingsFile = "/var/lib/invidious/companion-config.json";
|
|
|
|
# Ensure Invidious service depends on companion config generation
|
|
systemd.services.invidious = {
|
|
after = mkAfter [ "invidious-companion-config-generate.service" ];
|
|
requires = mkAfter [ "invidious-companion-config-generate.service" ];
|
|
};
|
|
|
|
# Override nginx vhost configuration
|
|
services.nginx.virtualHosts."invidious.cloonar.com" = {
|
|
acmeRoot = null;
|
|
|
|
# Complete http3-ytproxy configuration with proper headers and buffering
|
|
# This overrides the minimal config from the NixOS module
|
|
locations."~ (^/videoplayback|^/vi/|^/ggpht/|^/sb/)" = {
|
|
proxyPass = "http://unix:/run/http3-ytproxy/socket/http-proxy.sock";
|
|
extraConfig = ''
|
|
# Enable buffering for large video files
|
|
proxy_buffering on;
|
|
proxy_buffers 1024 16k;
|
|
proxy_buffer_size 128k;
|
|
proxy_busy_buffers_size 256k;
|
|
|
|
# Use HTTP/1.1 with keepalive for better performance
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Connection "";
|
|
|
|
# Hide headers that might cause issues
|
|
proxy_hide_header Cache-Control;
|
|
proxy_hide_header etag;
|
|
proxy_hide_header "alt-svc";
|
|
proxy_hide_header Access-Control-Allow-Origin;
|
|
proxy_hide_header Access-Control-Allow-Methods;
|
|
proxy_hide_header Access-Control-Allow-Headers;
|
|
proxy_hide_header Access-Control-Expose-Headers;
|
|
|
|
# CORS headers for iOS clients like Yattee
|
|
add_header Access-Control-Allow-Origin * always;
|
|
add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always;
|
|
add_header Access-Control-Allow-Headers "Range, Content-Type" always;
|
|
add_header Access-Control-Expose-Headers "Content-Length, Content-Range" always;
|
|
|
|
# Handle preflight requests
|
|
if ($request_method = OPTIONS) {
|
|
return 204;
|
|
}
|
|
|
|
# Optimize for large file transfers
|
|
sendfile on;
|
|
sendfile_max_chunk 512k;
|
|
tcp_nopush on;
|
|
|
|
# Disable access logging for video traffic
|
|
access_log off;
|
|
'';
|
|
};
|
|
};
|
|
|
|
# Firewall configuration for Invidious
|
|
# (nginx handles external access on ports 80/443)
|
|
|
|
# PostgreSQL backup for Invidious database
|
|
services.postgresqlBackup = {
|
|
databases = [ "invidious" ];
|
|
};
|
|
}
|