Così un CPX nuovo non richiede worker Docker a mano, l'agent è nel cloud-init e gli E2E restano non in elenco. Co-authored-by: Cursor <cursoragent@cursor.com>
386 lines
18 KiB
Markdown
386 lines
18 KiB
Markdown
# Autoscale streaming — Proxmox attuale + Hetzner Cloud
|
||
|
||
**Stato:** fasi 0–4 implementate sul branch — **solo test lab; nessun deploy produzione**
|
||
**Branch:** `feature/streaming-autoscale-hetzner`
|
||
**Ultimo aggiornamento:** 2026-08-09 (Fase 4 hardening + runbook)
|
||
|
||
**Sostituisce / estende:** il piano overflow-only [`HETZNER_CLOUD_RELAY_OVERFLOW.md`](HETZNER_CLOUD_RELAY_OVERFLOW.md). Questo documento copre **MediaMTX + ffmpeg**, warm spare, DNS, storage, disco e lab sul Proxmox di produzione.
|
||
|
||
Documenti correlati: [`ARCHITECTURE.md`](../ARCHITECTURE.md), [`LIVE_STREAMING.md`](../LIVE_STREAMING.md), [`REPLAY_MODULE.md`](../REPLAY_MODULE.md), [`OPS_MONITORING.md`](../OPS_MONITORING.md).
|
||
|
||
---
|
||
|
||
## 1. Obiettivo
|
||
|
||
Scalare molte dirette contemporanee (sito e/o YouTube) senza saturare un unico box:
|
||
|
||
- **Control plane (ora):** Proxmox **già in produzione** (`192.168.1.146` / `/opt/matchlivetv`) — sito, API, DB, Redis, Garage, MediaMTX/ffmpeg “home”.
|
||
- **Data plane elastico:** **Hetzner Cloud** — nodi `MediaMTX + ffmpeg` con warm spare (+1).
|
||
- **DNS ingest:** secondo dominio su **Hetzner DNS** (API).
|
||
- **Lab:** stesso Proxmox, con `ProxmoxLabProvider`, prima di affidarsi al Cloud in produzione.
|
||
- **Futuro (non bloccante):** migrazione control plane su **Hetzner Auction + Proxmox** (vSwitch nativo, hardware dedicato).
|
||
|
||
---
|
||
|
||
## 2. Decisioni chiuse
|
||
|
||
| # | Decisione | Scelta |
|
||
|---|----------|--------|
|
||
| D1 | Host primario **ora** | **Proxmox già usato in produzione** (non attendere Auction) |
|
||
| D1b | Host primario **futuro** | Hetzner Server Auction + Proxmox (quando si migra) |
|
||
| D2 | Overflow / warm spare | **Hetzner Cloud** (attivato per questo progetto) |
|
||
| D3 | Unità di scala | Nodo **stream** = MediaMTX + worker `youtube_relay` (ffmpeg remux copy) |
|
||
| D4 | Warm pool | Almeno **1 spare ready** quando il carico si avvicina al cap |
|
||
| D5 | DNS ingest | Dominio **`mltv-stream.net`** (registrar Aruba, NS → Hetzner DNS). `matchlivetv.it` resta su Aruba intatto |
|
||
| D6 | Aruba | Nessuna delega NS; niente Floating IP prenotate |
|
||
| D7a | Rete **ora** (casa/Proxmox ↔ Cloud) | **WireGuard** (o Tailscale) privato: Redis, DB, API MediaMTX home. Non esporre Redis/Postgres su WAN |
|
||
| D7b | Rete **futuro** (Auction ↔ Cloud) | vSwitch Robot + Cloud Network (stessa location) |
|
||
| D8 | Object storage | **Garage resta**. **B2** = migrazione pronta quando misurato |
|
||
| D9 | Staging | Segmenti su disco VM `stream-*` in live; upload Garage a fine sessione |
|
||
| D10 | Prodotto | Consigliare **YouTube** per alleggerire storage/egress replay |
|
||
| D11 | Disco | Separazione volumi + **monitoraggio attivo** obbligatorio (§6) |
|
||
| D12 | Lab prima del Cloud prod | `ProxmoxLabProvider` + DNS lab sullo stesso Proxmox; poi `HetznerCloudProvider` |
|
||
|
||
---
|
||
|
||
## 3. Topologia — fase attuale (Proxmox prod + Cloud)
|
||
|
||
```text
|
||
Internet
|
||
│ HTTPS :443 · RTMP :1935
|
||
▼
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ Proxmox produzione (attuale) │
|
||
│ eminux@192.168.1.146 · /opt/matchlivetv │
|
||
│ │
|
||
│ edge · rails · sidekiq-core · postgres · redis │
|
||
│ garage · stream-home (MediaMTX + youtube_relay) │
|
||
│ autoscaler (Rails/Sidekiq) │
|
||
│ │
|
||
│ Lab (opz.): clone VM stream-* via ProxmoxLabProvider │
|
||
└────────────────────────┬─────────────────────────────────┘
|
||
│ WireGuard / tunnel privato
|
||
▼
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ Hetzner Cloud — pool stream nodes │
|
||
│ stream-01 … stream-N MediaMTX + ffmpeg │
|
||
│ + 1 spare ready (warm) │
|
||
└────────────────────────┬─────────────────────────────────┘
|
||
│
|
||
Hetzner DNS (secondo dominio)
|
||
ingest-XX.<dominio> → IP pubblico nodo
|
||
```
|
||
|
||
**Futuro Auction:** stesso schema, tunnel sostituito da vSwitch; control plane migrato sul bare metal Hetzner.
|
||
|
||
**Principio:** Rails solo controllo. Live sui MediaMTX del nodo assegnato. Replay su Garage (poi eventualmente B2).
|
||
|
||
---
|
||
|
||
## 4. DNS (secondo dominio)
|
||
|
||
RTMP **non** tollera round-robin su un unico hostname.
|
||
|
||
1. Dominio **`mltv-stream.net`** registrato su Aruba; zona DNS su Hetzner Console (progetto `matchlivetv-stream`).
|
||
2. NS Aruba del dominio → `hydrogen` / `oxygen` / `helium` Hetzner (delegazione OK).
|
||
3. Autoscaler a VM ready → upsert `A` `ingest-03.mltv-stream.net` → health-check → nodo `ready`.
|
||
4. API create/start sessione → URL del nodo assegnato:
|
||
|
||
```text
|
||
rtmp://ingest-03.mltv-stream.net:1935/live/match_<uuid>
|
||
https://ingest-03.mltv-stream.net/hls/... # o via edge matchlivetv.it che proxya il nodo
|
||
```
|
||
|
||
5. Scale-in: drain → delete DNS → destroy VM.
|
||
|
||
Hostname pubblici dei nodi vivono sotto `*.mltv-stream.net`. In lab: `LabDnsProvider` (`/etc/hosts`, dnsmasq).
|
||
|
||
---
|
||
|
||
## 5. Autoscaler e warm spare
|
||
|
||
Ogni nodo: `max_publishers` / `max_relays` (es. 4).
|
||
|
||
| Regola | Comportamento |
|
||
|--------|----------------|
|
||
| Scale-out | `free_slots` sotto soglia soft → crea 1 nodo |
|
||
| Warm spare | Se `spare_ready < 1` vicino al carico → crea spare |
|
||
| Scale-in | Idle da X min e non unica spare → destroy |
|
||
| Floor | `stream-home` sul Proxmox sempre on |
|
||
|
||
`CloudProvider`: `HetznerCloudProvider` (prod overflow) + `ProxmoxLabProvider` (test).
|
||
Code Sidekiq: coda `youtube_relay` isolata; sticky owner Redis.
|
||
|
||
---
|
||
|
||
## 6. Disco Proxmox — requisito critico
|
||
|
||
**Non** mettere OS, DB e video sullo stesso volume che può riempirsi al 100%.
|
||
|
||
Vale **già** sul Proxmox di produzione (rinforzare ora), e di nuovo alla migrazione Auction.
|
||
|
||
### 6.1 Layout volumi (target)
|
||
|
||
| Volume / disco | Contenuto | Note |
|
||
|----------------|-----------|------|
|
||
| `os` | Proxmox / sistema host | Quasi statico |
|
||
| `vm-system` / root stack | rails, edge, redis, … | Snapshot |
|
||
| `vm-data-db` | Postgres | Separato; backup prioritari |
|
||
| `vm-data-video` | Garage + staging MediaMTX | **Disco che può riempirsi** |
|
||
| `backup` | Backup / PBS | **Mai** sullo stesso disco dei video |
|
||
|
||
Regole: cap Garage/staging; se staging pieno → **rifiutare nuove sessioni**, non far cadere DB/API.
|
||
|
||
### 6.2 Monitoraggio attivo (obbligatorio)
|
||
|
||
| Metrica | Warn | Critical |
|
||
|---------|------|----------|
|
||
| Uso `%` volume video | ≥ 70% | ≥ 85% |
|
||
| Spazio libero GB | sotto soglia | < X GB |
|
||
| Inode liberi | bassi | esaurimento |
|
||
| Crescita GB/giorno Garage | anomalia | — |
|
||
| Purge/retention falliti | — | immediato |
|
||
| Staging per nodo `stream-*` | ≥ 70% | ≥ 85% + blocco live su quel nodo |
|
||
|
||
Checklist:
|
||
|
||
- [ ] Alert ntfy disco testati
|
||
- [ ] Vista ops “disco video”
|
||
- [ ] Test periodico “80% pieno”
|
||
- [ ] Restore di prova Postgres
|
||
|
||
---
|
||
|
||
## 7. Storage: Garage ora, B2 dopo
|
||
|
||
| Ora | **Garage** |
|
||
| Dopo | **Backblaze B2** quando metriche/€ lo giustificano |
|
||
|
||
Client S3-ready; staging locale invariato. Spinta prodotto YouTube riduce pressione replay.
|
||
|
||
---
|
||
|
||
## 8. Prodotto: YouTube consigliato
|
||
|
||
Suggerire YouTube in app/dashboard quando ha senso → meno storage/egress MatchLiveTV; middle-tier (slate + relay) resta il valore. Live solo-sito restano supportate.
|
||
|
||
---
|
||
|
||
## 9. Astrazioni codice
|
||
|
||
```text
|
||
CloudProvider
|
||
create_node / destroy_node / list_nodes / wait_until_running / public_ip
|
||
→ HetznerCloudProvider | ProxmoxLabProvider
|
||
|
||
DnsProvider
|
||
upsert_a / delete_a
|
||
→ HetznerDnsProvider | LabDnsProvider
|
||
|
||
StreamNodeRegistry
|
||
register / mark_ready / allocate_for_session / drain / release
|
||
|
||
Autoscaler
|
||
reconcile!(metrics) → ensure spare / scale-in idle
|
||
```
|
||
|
||
Tag VM Cloud: `matchlivetv`, `role=stream-node`, `env=prod|lab`.
|
||
|
||
---
|
||
|
||
## 10. Lab sul Proxmox attuale
|
||
|
||
Prima (o in parallelo) al Cloud “vero”:
|
||
|
||
1. Template VM `stream-node` su Proxmox.
|
||
2. `CLOUD_PROVIDER=proxmox_lab` → clone/start/stop via API Proxmox.
|
||
3. DNS lab (hosts/dnsmasq).
|
||
4. Soft cap basso; N sessioni di test; verifica assignment, spare, scale-in, alert disco.
|
||
5. Poi smoke su Hetzner Cloud (1 CX piccolo) + DNS reale.
|
||
|
||
Cosa il lab **non** replica al 100%: tempi boot Hetzner, vSwitch, RTMP 4G multi-nodo (smoke WAN dopo).
|
||
|
||
### Relay ffmpeg sul nodo (lab locale / collaudo)
|
||
|
||
L’overflow deve spostare **ffmpeg**, non solo l’ingest RTMP. In lab `local_lab` il MediaMTX resta quello home; si alza un secondo Sidekiq che ascolta solo `youtube_relay_<slug>` così la CPU del remux è isolata.
|
||
|
||
1. Provisiona il nodo: admin **Nodi stream** o `rails streams:nodes:provision_lab` (slug tipo `ingest-lab-01`).
|
||
2. Worker locale: `STREAM_NODE_SLUG=ingest-lab-01 bash scripts/dev_sidekiq_relay.sh`
|
||
3. Collaudo: `STREAM_NODE_SLUG=ingest-lab-01 bash scripts/deploy/collaudo_relay_worker.sh up`
|
||
4. Per assegnare sessioni al lab: riempi home (`STREAM_NODE_HOME_MAX_PUBLISHERS=1`) oppure alza `max_publishers` del lab e satura home.
|
||
5. Verifica: `docker top` / log `[YoutubeRelay] started ... worker=ingest-lab-01` sul container relay, **non** su `sidekiq` home.
|
||
6. Nodo Cloud Hetzner: stesso modello quando WireGuard espone Redis/Postgres; cloud-init dovrà avviare Sidekiq con `STREAM_NODE_SLUG` e `STREAM_NODE_LOCAL_RTMP_URL=rtmp://127.0.0.1:1935`.
|
||
|
||
---
|
||
|
||
## 11. Fasi di implementazione
|
||
|
||
| Fase | Cosa | Esito |
|
||
|------|------|--------|
|
||
| **L — Lab Proxmox** | `LocalLab` / `ProxmoxLab`, DNS lab, admin nodi | **implementata sul branch** |
|
||
| **0 — Multi-nodo ready** | Registry + URL RTMP/HLS in API (`StreamNode`, `Streams::NodeRegistry`) | **implementata sul branch** |
|
||
| **1 — Hetzner Cloud + DNS** | `HetznerCloudProvider` + `HetznerDnsProvider`, `mltv-stream.net`, cloud-init, WireGuard (§16) | **implementata sul branch** (WG ops manuale) |
|
||
| **2 — Routing relay** | Coda `youtube_relay_<slug>` per nodo, worker overflow senza code `default`, sticky owner, cap `RELAY_MAX_CONCURRENT` | **implementata sul branch** (lab Docker/collaudo; Cloud dopo WG) |
|
||
| **3 — Autoscaler** | Soglie + warm spare (+1), kill-switch `STREAM_AUTOSCALE_ENABLED` | **implementata sul branch** |
|
||
| **4 — Hardening** | Drain sicuro, budget, kill-switch Redis/admin, alert overflow, runbook | **implementata sul branch** (solo test lab — **non in prod**) |
|
||
| **A — Auction (futuro)** | Migrazione control plane + vSwitch al posto di WireGuard | Hardware dedicato Hetzner |
|
||
| **B2 (opz.)** | Switch object storage | Quando misurato |
|
||
|
||
### Fase 0 — dettagli implementati
|
||
|
||
- Tabella `stream_nodes` + `stream_sessions.stream_node_id`
|
||
- `Streams::NodeRegistry.ensure_home_from_env!` / `allocate!` (least-loaded)
|
||
- `Sessions::Create` assegna il nodo e crea il path MediaMTX sul client del nodo
|
||
- URL RTMP/HLS/API/internal per sessione derivati dal nodo (fallback ENV se nodo assente)
|
||
- API JSON espone `stream_node` (slug)
|
||
- Dominio ingest pubblico futuro: `*.mltv-stream.net`
|
||
|
||
### Fase L — dettagli implementati
|
||
|
||
- `Streams::CloudProviders` (`local_lab`, `proxmox_lab`, stub `hetzner`)
|
||
- `Streams::DnsProviders` (`lab` su Redis, stub `hetzner`)
|
||
- `Streams::NodeProvisioner` (provision / drain / decommission)
|
||
- Admin **Nodi stream** (`/admin/stream_nodes`): lista, provision lab, drain, delete
|
||
- Rake: `streams:nodes:ensure_home`, `streams:nodes:provision_lab`, `streams:nodes:dns_lab_dump`
|
||
- Default sicuro: `STREAM_CLOUD_PROVIDER=local_lab` (nessuna chiamata Proxmox finché non configuri token)
|
||
|
||
### Fase 1 — dettagli implementati
|
||
|
||
- `Streams::CloudProviders::Hetzner` (create/destroy server, wait running, labels)
|
||
- `Streams::DnsProviders::Hetzner` (upsert/delete A su zona `mltv-stream.net`)
|
||
- `NodeProvisioner#provision_cloud!` + bottone admin **Provisiona nodo Hetzner**
|
||
- Cloud-init: `infra/stream-node/cloud-init.yaml` (`HCLOUD_USER_DATA_FILE`)
|
||
- Decommission usa il provider del nodo (non solo ENV globale)
|
||
- WireGuard: vedi §16
|
||
|
||
### Fase 2 — dettagli implementati
|
||
|
||
- Coda Sidekiq `youtube_relay_home` (ffmpeg locale) e `youtube_relay_cloud` (home chiama l’agent `:9100` sul CPX). Lab overflow resta `youtube_relay_<slug>`
|
||
- `YoutubeRelayEnsureJob` / `YoutubeRelayStopJob` sulla coda del **nodo assegnato** (cloud → `youtube_relay_cloud`)
|
||
- Stop sticky: non cancella owner da Rails; lo stop gira sull’owner o requeue (`:wrong_host`)
|
||
- Cap per worker: `RELAY_MAX_CONCURRENT` (default 4) + set Redis `youtube_relay:owned:HOSTNAME` (non si applica al dispatch agent dal home)
|
||
- Ensure a capacità piena → requeue 5s sulla stessa coda nodo
|
||
- Worker home ascolta `youtube_relay_home`, `youtube_relay_cloud` (+ `youtube_relay` legacy). Un CPX nuovo non richiede `prod_relay_worker.sh`
|
||
- Intake locale: `STREAM_NODE_LOCAL_RTMP_URL` (loopback sul CPX, `mediamtx` in Docker lab)
|
||
|
||
### Fase 3 — dettagli implementati
|
||
|
||
- `Streams::Autoscaler` + job chain `Streams::AutoscalerJob` (come health monitor)
|
||
- Kill-switch: `STREAM_AUTOSCALE_ENABLED=1` per attivare
|
||
- Scale-out se `free_slots ≤ STREAM_AUTOSCALE_SOFT_FREE_SLOTS`
|
||
- Warm spare (+N) se carico/soglia e `spare_ready < WARM_SPARE`
|
||
- Scale-in overflow idle da `IDLE_MINUTES` (non tocca home; rispetta warm spare)
|
||
- Cap `STREAM_AUTOSCALE_MAX_NODES`; kind `lab|cloud`
|
||
- Metriche in admin Nodi stream
|
||
|
||
### Fase 4 — hardening (implementata sul branch)
|
||
|
||
> **NON rilasciare in produzione** finché lab + smoke Cloud non sono verdi. Su questo branch restano `STREAM_AUTOSCALE_ENABLED=0` e `STREAM_AUTOSCALE_ALLOW_CLOUD=0`.
|
||
|
||
- Scale-in **sicuro**: `drain!` → attesa sessioni zero → `decommission!`
|
||
- Budget soft: `STREAM_AUTOSCALE_MONTHLY_BUDGET_EUR` + `STREAM_AUTOSCALE_NODE_EUR_PER_HOUR` (stima 24/7); scale-out bloccato se sforerebbe
|
||
- Cloud autoscale solo con `STREAM_AUTOSCALE_ALLOW_CLOUD=1` **e** `HCLOUD_TOKEN`
|
||
- Kill-switch runtime Redis `streams:autoscaler:kill_switch` (bottoni admin ON/OFF) oltre all’ENV
|
||
- Health check `stream_overflow` → incidente Ops/ntfy su nodi idle orfani, over-budget, capacità al max
|
||
- Admin: metriche budget + stato kill-switch
|
||
|
||
#### Runbook operativo (lab / pre-prod)
|
||
|
||
| Situazione | Azione |
|
||
|------------|--------|
|
||
| Dubbio / picco anomalo | Admin → **Kill-switch ON** (o `STREAM_AUTOSCALE_ENABLED=0`) |
|
||
| Nodo spillato | Drain dal admin; dopo fine live → Destroy |
|
||
| Budget alert Ops | Abbassa `MAX_NODES` / alza budget solo dopo review costi Hetzner |
|
||
| Smoke Cloud | Provision **manuale** admin (kind cloud), non autoscaler; verifica WG + RTMP 1935 |
|
||
| Scale-out lab OK | Solo dopo: considerare `ENABLED=1` + `KIND=lab` su staging/lab Proxmox |
|
||
| Produzione overflow | Solo dopo checklist §12 punto 6 |
|
||
|
||
Ordine di lavoro consigliato sul branch: **0 → L → 1 → 2 → 3 → 4**; **A** quando si decide di lasciare il Proxmox casa.
|
||
|
||
---
|
||
|
||
## 12. Ordine operativo “ora” (senza Auction)
|
||
|
||
1. Rinforzare dischi/alert sul Proxmox prod (§6).
|
||
2. Secondo dominio + zona Hetzner DNS.
|
||
3. Progetto Hetzner Cloud + immagine/snapshot `stream-node`.
|
||
4. Tunnel WireGuard Proxmox ↔ Cloud (Redis/DB/API private).
|
||
5. Implementare fasi 0 → L → 1… sul branch.
|
||
6. Cutover overflow in produzione solo dopo lab + smoke Cloud verdi.
|
||
|
||
---
|
||
|
||
## 13. Criteri di successo
|
||
|
||
| Criterio | Misura |
|
||
|----------|--------|
|
||
| Lab | Scale-out/in e assignment verificati su Proxmox senza Hetzner |
|
||
| Picco | N live oltre soft cap home con spare Cloud ready |
|
||
| Continuità | Drop telefono → slate YT attiva |
|
||
| Disco | Nessun outage DB/API per disco video; alert prima del critical |
|
||
| DNS | Aruba intatto; ingest sul secondo dominio |
|
||
| Futuro | Path chiaro verso Auction senza riscrivere autoscaler |
|
||
|
||
---
|
||
|
||
## 14. Aperto / da calibrare
|
||
|
||
| Voce | Note |
|
||
|------|------|
|
||
| Nome secondo dominio | **`mltv-stream.net`** (chiuso) |
|
||
| Soft cap `stream-home` | es. 4 vs 6 |
|
||
| Tipo VM Cloud | CPX vs CCX |
|
||
| `OVERFLOW_MAX` / budget | — |
|
||
| Spare di notte | 0 vs 1 |
|
||
| Dettaglio WireGuard | subnet, peer, MTU |
|
||
| Soglie GB disco | da size reale volume video |
|
||
|
||
---
|
||
|
||
## 15. Riepilogo esecutivo
|
||
|
||
**Ora:** restiamo sul Proxmox di produzione; attiviamo Hetzner Cloud (spare MediaMTX+ffmpeg) + Hetzner DNS (secondo dominio) + WireGuard. Testiamo prima in lab sullo stesso Proxmox. Garage resta; B2 dopo. YouTube consigliato in prodotto. Disco e alert sono vincolo non negoziabile.
|
||
|
||
**Dopo:** eventuale Auction Hetzner sostituisce il control plane casa e WireGuard → vSwitch, senza cambiare il modello nodi/autoscaler.
|
||
|
||
---
|
||
|
||
## 16. WireGuard (Proxmox casa ↔ Hetzner Cloud)
|
||
|
||
Obiettivo: Rails/Sidekiq sull’host di produzione raggiungono `api_base_url` / `internal_rtmp_url` dei nodi Cloud (es. `http://10.0.0.9:9997`) **senza** esporre Redis/Postgres/MediaMTX API su Internet.
|
||
|
||
### Setup consigliato (una tantum)
|
||
|
||
1. Su Hetzner Console: crea **Network** privata (es. `10.0.0.0/16`) nella location `fsn1`, subnet `10.0.1.0/24` per i server Cloud.
|
||
2. Imposta `HCLOUD_NETWORK_ID=<id>` così i nodi stream entrano nella network al create.
|
||
3. Su Proxmox (VM o LXC gateway): installa WireGuard; peer verso una VM “gateway” Cloud **sempre on** (CX22 piccola) *oppure* peer site-to-site verso un server Cloud fisso.
|
||
4. Alternativa più semplice per i primi test: **Tailscale** su Proxmox host + su ogni stream-node (cloud-init) — stesso effetto, meno ops.
|
||
5. Firewall Hetzner Cloud:
|
||
- WAN: `1935/tcp` (RTMP), `443/tcp` o `8888` se HLS diretto
|
||
- Solo rete privata / WG: `9997` (MediaMTX API), niente Postgres/Redis sui nodi stream
|
||
6. Verifica da Rails: `curl http://<private_ip>:9997/v3/paths/list`
|
||
|
||
Finché WireGuard/Tailscale non è pronto, `api_base_url` punta comunque alla private IP (o pubblica se manca private_net): il path MediaMTX da Create fallirà dal control plane se non raggiungibile — provisionare nodi Cloud solo dopo connettività privata OK, oppure smoke con API su IP pubblico temporaneo + firewall allowlist IP casa.
|
||
|
||
### ENV produzione (stream autoscale)
|
||
|
||
```bash
|
||
HCLOUD_TOKEN=...
|
||
HCLOUD_LOCATION=nbg1
|
||
HCLOUD_SERVER_TYPE=cpx12
|
||
HCLOUD_IMAGE=debian-12
|
||
HCLOUD_SSH_KEY=matchlivetv-stream-hetzner
|
||
HCLOUD_NETWORK_ID= # opzionale
|
||
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=prod
|
||
|
||
# Default lab sicuro; in prod per overflow usa hetzner esplicitamente dal bottone admin
|
||
STREAM_CLOUD_PROVIDER=local_lab
|
||
STREAM_DNS_PROVIDER=lab
|
||
```
|