From 714602f3da3ac0bc638969308f236b68d9dcb9ca Mon Sep 17 00:00:00 2001 From: Emiliano Frascaro Date: Mon, 10 Aug 2026 20:29:47 +0200 Subject: [PATCH] Aggiunge overlay Compose per collaudo con RTMP su porta 11935. Isola MediaMTX dal :1935 di produzione sullo stesso IP pubblico e documenta env/helper per il container Proxmox di test. Co-authored-by: Cursor --- infra/.env.collaudo.example | 109 +++++++++++++++++++++++ infra/docker-compose.collaudo.yml | 30 +++++++ infra/scripts/setup_garage_production.sh | 10 +-- scripts/deploy/collaudo_compose.sh | 11 +++ 4 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 infra/.env.collaudo.example create mode 100644 infra/docker-compose.collaudo.yml create mode 100755 scripts/deploy/collaudo_compose.sh diff --git a/infra/.env.collaudo.example b/infra/.env.collaudo.example new file mode 100644 index 0000000..d4b0b5c --- /dev/null +++ b/infra/.env.collaudo.example @@ -0,0 +1,109 @@ +# Copia come infra/.env sul container di collaudo e genera i secret. +# cp .env.collaudo.example .env && openssl rand -hex 32 (ripeti per ogni CHANGE_ME) + +POSTGRES_PASSWORD=CHANGE_ME_STRONG_PASSWORD +SECRET_KEY_BASE=CHANGE_ME_openssl_rand_hex_64 +JWT_SECRET=CHANGE_ME_openssl_rand_hex_32 +MEDIAMTX_WEBHOOK_SECRET=CHANGE_ME_openssl_rand_hex_32 + +# RTMP collaudo: porta host 11935 (vedi docker-compose.collaudo.yml). +# LAN: rtmp://192.168.1.157:11935 +# WAN (opzionale): apri SOLO 11935 sul router → .157 — NON toccare :1935 di produzione. +MEDIAMTX_RTMP_URL=rtmp://192.168.1.157:11935 + +APP_PUBLIC_URL=https://collaudo.matchlivetv.it +HLS_PUBLIC_URL=https://collaudo.matchlivetv.it/hls +CORS_ORIGINS=https://collaudo.matchlivetv.it +ALLOWED_HOSTS=collaudo.matchlivetv.it,192.168.1.157,localhost +YOUTUBE_REDIRECT_URI=https://collaudo.matchlivetv.it/api/v1/youtube/callback + +YOUTUBE_CLIENT_ID= +YOUTUBE_CLIENT_SECRET= +YOUTUBE_PLATFORM_REFRESH_TOKEN= + +# Stripe: preferisci chiavi Test su collaudo +STRIPE_SECRET_KEY= +STRIPE_WEBHOOK_SECRET= +STRIPE_PREMIUM_LIGHT_MONTHLY_PRICE_ID= +STRIPE_PREMIUM_LIGHT_YEARLY_PRICE_ID= +STRIPE_PREMIUM_FULL_MONTHLY_PRICE_ID= +STRIPE_PREMIUM_FULL_YEARLY_PRICE_ID= +STRIPE_PREMIUM_LIGHT_PRICE_ID= +STRIPE_PREMIUM_FULL_PRICE_ID= + +RAILS_LOG_LEVEL=info + +PRIVACY_CONTROLLER_NAME=Emiliano Frascaro +PRIVACY_CONTROLLER_ADDRESS=Via Guido De Ruggiero, 89 - 20142 - Milano (MI) +PRIVACY_CONTACT_EMAIL=privacy@matchlivetv.it +PRIVACY_CONTROLLER_VAT= + +MAILER_FROM=Match Live TV Collaudo +SMTP_ADDRESS= +SMTP_PORT=465 +SMTP_USERNAME= +SMTP_PASSWORD= +SMTP_AUTH=plain +SMTP_SSL=true +SMTP_STARTTLS=false +PASSWORD_RESET_EXPIRY_HOURS=2 + +MATCHLIVETV_VIDEOS_ROOT=/media/videos/matchlivetv + +REPLAY_STORAGE_ENDPOINT=http://garage:3900 +REPLAY_STORAGE_BUCKET=matchlivetv-replays +REPLAY_STORAGE_REGION=garage +REPLAY_STORAGE_ACCESS_KEY_ID= +REPLAY_STORAGE_SECRET_ACCESS_KEY= +REPLAY_STORAGE_FORCE_PATH_STYLE=true +REPLAY_MEDIA_PUBLIC_BASE_URL=https://collaudo.matchlivetv.it/media +REPLAY_MEDIA_REDIRECT=true + +RAILS_MAX_THREADS=5 + +OPS_HTTP_RAILS_URL=http://edge/up +OPS_HTTP_PUBLIC_INTERVAL_SECS=900 +NTFY_PUBLIC_URL=http://192.168.1.157:18090 +OPS_NTFY_URL= +OPS_NTFY_TOKEN= +OPS_ALERT_EMAIL= +OPS_NOTIFY_SEVERITIES=critical,warning +OPS_NOTIFY_COOLDOWN_MINUTES=30 +OPS_HEALTH_INTERVAL_SECS=180 +OPS_HEALTH_TOKEN= +OPS_DISK_WARN_PERCENT=80 +OPS_DISK_CRIT_PERCENT=90 +OPS_RECORDINGS_WARN_GB=20 +OPS_RECORDINGS_CRIT_GB=50 +OPS_SIDEKIQ_STALE_SECS=300 +OPS_LOG_SUBSCRIBER=false + +SENTRY_DSN= + +# Stream autoscale — token Hetzner da compilare; kill-switch cloud off finché WG non è ok +HCLOUD_TOKEN= +HCLOUD_LOCATION=nbg1 +HCLOUD_SERVER_TYPE=cpx12 +HCLOUD_IMAGE=debian-12 +HCLOUD_SSH_KEY=matchlivetv-stream-hetzner +HCLOUD_NETWORK_ID= +HCLOUD_USER_DATA_FILE=/opt/matchlivetv/infra/stream-node/cloud-init.yaml +STREAM_DNS_ZONE=mltv-stream.net +STREAM_DNS_TTL=60 +STREAM_CLOUD_DNS_SUFFIX=mltv-stream.net +STREAM_CLOUD_MAX_PUBLISHERS=4 +STREAM_NODE_ENV=collaudo +STREAM_CLOUD_PROVIDER=local_lab +RELAY_MAX_CONCURRENT=4 +YOUTUBE_RELAY_WORKER=1 + +STREAM_AUTOSCALE_ENABLED=0 +STREAM_AUTOSCALE_KIND=lab +STREAM_AUTOSCALE_ALLOW_CLOUD=0 +STREAM_AUTOSCALE_SOFT_FREE_SLOTS=2 +STREAM_AUTOSCALE_WARM_SPARE=1 +STREAM_AUTOSCALE_IDLE_MINUTES=30 +STREAM_AUTOSCALE_MAX_NODES=5 +STREAM_AUTOSCALE_NODE_EUR_PER_HOUR=0.015 +STREAM_AUTOSCALE_MONTHLY_BUDGET_EUR=40 +STREAM_OVERFLOW_ORPHAN_HOURS=3 diff --git a/infra/docker-compose.collaudo.yml b/infra/docker-compose.collaudo.yml new file mode 100644 index 0000000..158b921 --- /dev/null +++ b/infra/docker-compose.collaudo.yml @@ -0,0 +1,30 @@ +# Collaudo Proxmox (es. 192.168.1.157) — overlay su docker-compose.prod.yml +# +# Uso: +# export COMPOSE_FILE=docker-compose.prod.yml:docker-compose.collaudo.yml +# docker compose --env-file .env up -d --build +# +# Porte host MediaMTX diverse da produzione per non competere sullo stesso IP pubblico: +# prod WAN :1935 → 192.168.1.146 +# collaudo LAN/WAN opzionale :11935 → 192.168.1.157 +# HTTP resta :3000 (NPM → collaudo.matchlivetv.it); IP LAN diversi = nessun conflitto. + +services: + mediamtx: + ports: !override + - "11935:1935" # RTMP collaudo (NON usare WAN :1935 di produzione) + - "18888:8888" # HLS diretto opzionale; in genere basta /hls via edge+NPM + + # Passa tutto .env (HCLOUD_*, STREAM_*, …) ai processi Rails/Sidekiq + rails: + env_file: + - .env + + sidekiq: + env_file: + - .env + + # ntfy collaudo su porta diversa (evita confusione se si punta per sbaglio l'host) + ntfy: + ports: !override + - "18090:80" diff --git a/infra/scripts/setup_garage_production.sh b/infra/scripts/setup_garage_production.sh index 92a3417..1a931ad 100755 --- a/infra/scripts/setup_garage_production.sh +++ b/infra/scripts/setup_garage_production.sh @@ -5,14 +5,14 @@ set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$ROOT" -export COMPOSE_FILE="docker-compose.prod.yml" +export COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.prod.yml}" export ENV_FILE="${ROOT}/.env" export CREDS_FILE="${ROOT}/garage/prod-credentials.env" bash "${ROOT}/scripts/ensure_garage_prod_config.sh" -echo "Avvio Garage..." -docker compose -f docker-compose.prod.yml --env-file .env up -d garage +echo "Avvio Garage (COMPOSE_FILE=${COMPOSE_FILE})..." +docker compose --env-file .env up -d garage videos_root="${MATCHLIVETV_VIDEOS_ROOT:-/media/videos/matchlivetv}" capacity_df="${videos_root}" @@ -27,8 +27,8 @@ echo "Capacità nodo Garage: ${GARAGE_NODE_CAPACITY} (disco ~${avail_gb}G, riser bash "${ROOT}/scripts/setup_garage_replays.sh" echo "Riavvio Rails e Sidekiq..." -docker compose -f docker-compose.prod.yml --env-file .env up -d rails sidekiq +docker compose --env-file .env up -d rails sidekiq echo "Verifica storage:" -docker compose -f docker-compose.prod.yml --env-file .env exec -T rails bundle exec rails runner \ +docker compose --env-file .env exec -T rails bundle exec rails runner \ 'puts({local: MatchLiveTv.replay_storage_local?, backend: Recordings::Storage.new.backend_name}.inspect)' diff --git a/scripts/deploy/collaudo_compose.sh b/scripts/deploy/collaudo_compose.sh new file mode 100755 index 0000000..71882cb --- /dev/null +++ b/scripts/deploy/collaudo_compose.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# Helper collaudo Proxmox: forza sempre prod + overlay porte isolate. +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +INFRA="${MATCHLIVETV_INFRA:-$ROOT/infra}" +if [ -d /opt/matchlivetv/infra ]; then + INFRA=/opt/matchlivetv/infra +fi +cd "$INFRA" +export COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.prod.yml:docker-compose.collaudo.yml}" +exec docker compose --env-file .env "$@"