feat: move piped to fw host

This commit is contained in:
2025-11-02 14:34:30 +01:00
parent 04cdf1bd2f
commit 794d5c2dad
6 changed files with 104 additions and 108 deletions

View File

@@ -1,280 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
# Piped domain
domain = "piped.cloonar.com";
# Port configuration
backendPort = 8082;
proxyPort = 8081;
# Database configuration
dbName = "piped";
dbUser = "piped";
# Piped backend configuration file
backendConfig = pkgs.writeText "config.properties" ''
# Database configuration
# 10.88.0.1 is the default Podman bridge gateway IP
hibernate.connection.url=jdbc:postgresql://10.88.0.1:5432/${dbName}
hibernate.connection.driver_class=org.postgresql.Driver
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.connection.username=${dbUser}
hibernate.connection.password=PLACEHOLDER_DB_PASSWORD
# Server configuration
PORT=${toString backendPort}
HTTP_WORKERS=2
# Proxy configuration
PROXY_PART=https://${domain}/proxy
# API URL
API_URL=https://${domain}/api
# Frontend URL
FRONTEND_URL=https://${domain}
# Disable registration (private instance)
DISABLE_REGISTRATION=true
# ReCaptcha (disabled for private instance)
CAPTCHA_ENABLED=false
# Matrix support (optional)
MATRIX_SERVER=
# Sentry (disabled)
SENTRY_DSN=
# Compromised password check (optional)
COMPROMISED_PASSWORD_CHECK=true
# Feed retention (days)
FEED_RETENTION=30
'';
# Piped frontend configuration
# Note: Piped requires the config in a specific format as a JSON file served at /config/config.json
frontendConfig = pkgs.writeText "config.json" (builtins.toJSON {
apiUrl = "https://${domain}";
disableRegistration = true;
instanceName = "Piped (Private)";
});
in
{
# Required secrets (add to hosts/web-arm/secrets.yaml):
# - piped-db-password: PostgreSQL password for piped user
# - piped-http-auth: HTTP basic auth file (htpasswd format)
#
# To generate HTTP basic auth file:
# $ echo "username:$(openssl passwd -apr1)" > piped-http-auth
#
# To add to secrets.yaml:
# $ nix-shell -p sops --run 'sops hosts/web-arm/secrets.yaml'
sops.secrets = {
# Database password for postgres user (used by piped-db-init)
piped-db-password-postgres = {
key = "piped-db-password";
owner = "postgres";
};
# Database password for piped user (used by piped-config-generate)
piped-db-password-piped = {
key = "piped-db-password";
owner = "piped";
};
piped-http-auth = {
owner = "nginx";
};
};
# Create system user for Piped
users.users.piped = {
isSystemUser = true;
group = "piped";
home = "/var/lib/piped";
createHome = true;
};
users.groups.piped = { };
# Note: piped user doesn't need special group membership for Podman
# Create piped config directory structure
systemd.tmpfiles.rules = [
"d /var/lib/piped 0700 piped piped - -"
"d /var/lib/piped/config 0700 piped piped - -"
];
# PostgreSQL database setup
services.postgresql = {
enable = true;
ensureDatabases = [ dbName ];
ensureUsers = [{
name = dbUser;
ensureDBOwnership = true;
}];
# Allow connections from Podman containers
settings = {
listen_addresses = mkForce "*";
};
authentication = pkgs.lib.mkOverride 10 ''
# Allow local connections
local all all trust
# Allow connections from localhost
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
# Allow connections from Podman network (typically 10.88.0.0/16)
host ${dbName} ${dbUser} 10.88.0.0/16 scram-sha-256
host ${dbName} ${dbUser} 10.89.0.0/16 scram-sha-256
'';
};
# PostgreSQL backup
services.postgresqlBackup.databases = [ dbName ];
# Allow Podman containers to connect to PostgreSQL
networking.firewall.interfaces."podman0".allowedTCPPorts = [ 5432 ];
# Setup database password (runs before containers start)
systemd.services.piped-db-init = {
description = "Initialize Piped database password";
wantedBy = [ "multi-user.target" ];
after = [ "postgresql.service" ];
requires = [ "postgresql.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = "postgres";
Group = "postgres";
};
script = ''
password=$(cat ${config.sops.secrets.piped-db-password-postgres.path})
${config.services.postgresql.package}/bin/psql -c "ALTER USER ${dbUser} WITH PASSWORD '$password';"
'';
};
# Create Piped backend config with actual password
systemd.services.piped-config-generate = {
description = "Generate Piped backend configuration";
wantedBy = [ "multi-user.target" ];
before = [ "podman-piped-backend.service" ];
after = [ "piped-db-init.service" ];
requires = [ "piped-db-init.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = "piped";
Group = "piped";
};
script = ''
mkdir -p /var/lib/piped/config
password=$(cat ${config.sops.secrets.piped-db-password-piped.path})
sed "s|PLACEHOLDER_DB_PASSWORD|$password|" ${backendConfig} > /var/lib/piped/config/config.properties
chmod 600 /var/lib/piped/config/config.properties
'';
};
# Use Podman for OCI containers
virtualisation.oci-containers.backend = "podman";
# Piped Backend Podman container
virtualisation.oci-containers.containers.piped-backend = {
image = "1337kavin/piped:latest";
ports = [ "127.0.0.1:${toString backendPort}:${toString backendPort}" ];
volumes = [
"/var/lib/piped/config/config.properties:/app/config.properties:ro"
];
extraOptions = [
"--pull=newer"
# Using default bridge network - connects to PostgreSQL via 10.88.0.1
];
};
# Ensure config is generated before backend container starts
systemd.services."podman-piped-backend" = {
after = mkAfter [ "piped-config-generate.service" ];
requires = mkAfter [ "piped-config-generate.service" ];
};
# Piped Proxy Podman container
virtualisation.oci-containers.containers.piped-proxy = {
image = "1337kavin/piped-proxy:latest";
ports = [ "${toString proxyPort}:${toString proxyPort}" ];
environment = {
PORT = toString proxyPort;
UDS = "0"; # Disable Unix domain sockets
};
extraOptions = [
"--pull=newer"
];
};
# Nginx configuration
services.nginx.virtualHosts.${domain} = {
forceSSL = true;
enableACME = true;
acmeRoot = null;
# Serve Piped frontend static files
root = "${pkgs.piped}";
# HTTP Basic Auth for private access
extraConfig = ''
auth_basic "Piped - Private Instance";
auth_basic_user_file ${config.sops.secrets.piped-http-auth.path};
'';
# Frontend (root)
locations."/" = {
extraConfig = ''
try_files $uri $uri/ /index.html;
# Inject instance configuration before Piped loads
sub_filter '<head>' '<head><script>if(!localStorage.getItem("instance")){localStorage.setItem("instance","https://${domain}");}</script>';
sub_filter_once on;
sub_filter_types text/html;
'';
};
# Serve custom frontend config
locations."= /config/config.json" = {
alias = frontendConfig;
extraConfig = ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
'';
};
# Backend API
locations."/api/" = {
proxyPass = "http://127.0.0.1:${toString backendPort}/";
proxyWebsockets = true;
extraConfig = ''
# Increase timeouts for long-running requests
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
'';
};
# YouTube Proxy
locations."/proxy/" = {
proxyPass = "http://127.0.0.1:${toString proxyPort}/";
extraConfig = ''
proxy_buffering on;
# Increase buffer sizes for video streaming
proxy_buffer_size 128k;
proxy_buffers 256 16k;
proxy_busy_buffers_size 256k;
# Increase timeouts for video streaming
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
'';
};
};
}