From ee8ce3f99fd5a284c0ada84165eec240465f59bb Mon Sep 17 00:00:00 2001 From: mikl Date: Sun, 12 Jul 2026 21:56:37 +0300 Subject: [PATCH] heather: enable jitsi meet stack (jitsi.iscg.dev) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Стек: web + prosody + jicofo + jvb + coturn. Перенесено с jul11 (2026-07-12): - config (web/prosody/jicofo/jvb) → named volumes heather_jitsi-{web,prosody,jicofo,jvb,transcripts} - prosody user mikl.dat сохранён (internal auth) - образ PIN: stable-11031 (как на jul11, НЕ :latest) - пароли (jicofo/jvb/jigasi/jibri/turn) НОВЫЕ, в pass iscg.dev/jitsi/ - env-файл /var/lib/jitsi-secrets/jitsi.env (root:docker 0640) - coturn в host network (real client IPs), realm=turn.iscg.dev - JVB 10000/udp публично (YC SG уже ANY ANY open) - Caddy: WebSocket routes /xmpp-websocket, /colibri-ws (hop-by-hop upgrade) - DISABLE_HTTPS=1 (Caddy терминирует TLS) --- hosts/heather/arion-compose.nix | 135 +++++++++++++++++++++++++++++++- hosts/heather/caddy.nix | 16 +++- 2 files changed, 147 insertions(+), 4 deletions(-) diff --git a/hosts/heather/arion-compose.nix b/hosts/heather/arion-compose.nix index dd4eb4f..5a000b2 100644 --- a/hosts/heather/arion-compose.nix +++ b/hosts/heather/arion-compose.nix @@ -34,9 +34,12 @@ teable-db = {}; teable-redis = {}; teable-assets = {}; - # jitsi-стек (когда добавим): - # jitsi-prosody-config = {}; - # jitsi-jvb-config = {}; + # jitsi-стек + jitsi-web = {}; + jitsi-prosody = {}; + jitsi-jicofo = {}; + jitsi-jvb = {}; + jitsi-transcripts = {}; }; services = { # === Forgejo (git.iscg.dev) === @@ -139,6 +142,132 @@ service.volumes = [ "teable-redis:/data" ]; }; + # === Jitsi Meet (jitsi.iscg.dev) === + # Стек: web, prosody, jicofo, jvb, coturn. Перенесено с jul11 (2026-07-12): + # - config (web/prosody/jicofo/jvb) → named volumes (включая prosody user mikl) + # - образ PIN: stable-11031 (как на jul11, НЕ :latest) + # - пароли (jicofo/jvb/jigasi/jibri/turn) НОВЫЕ, в pass iscg.dev/jitsi/ + # - env-файл /var/lib/jitsi-secrets/jitsi.env на heather (root:docker 0640) + # Coturn в host network (нужно для real client IPs). JVB 10000/udp публично. + # Caddy терминирует TLS, web внутренне HTTP (DISABLE_HTTPS=1). + # Документация: https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker/ + # WebSocket routes (/xmpp-websocket, /colibri-ws) — в caddy.nix. + jitsi-web = { + service.image = "jitsi/web:stable-11031"; + service.container_name = "jitsi-web"; + service.restart = "unless-stopped"; + service.ports = [ "127.0.0.1:8000:80" ]; + service.volumes = [ + "jitsi-web:/config" + "jitsi-web:/var/spool/cron/crontabs" + "jitsi-transcripts:/usr/share/jitsi-meet/transcripts" + ]; + service.depends_on = [ "jitsi-jvb" ]; + service.env_file = [ "/var/lib/jitsi-secrets/jitsi.env" ]; + service.environment = { + PUBLIC_URL = "https://jitsi.iscg.dev"; + DISABLE_HTTPS = "1"; + ENABLE_HTTP_REDIRECT = "0"; + ENABLE_HSTS = "0"; + ENABLE_LETSENCRYPT = "0"; + TZ = "Europe/Moscow"; + HTTP_PORT = "8000"; + JVB_ADVERTISE_IPS = "51.250.45.111"; + APP_NAME = "mikl meet"; + PROVIDER_NAME = "mikl meet"; + SHOW_JITSI_WATERMARK = "false"; + SHOW_POWERED_BY = "false"; + DISABLE_JOIN_LEAVE_NOTIFICATIONS = "true"; + DISABLE_VIDEO_BACKGROUND = "true"; + ENABLE_AUTH = "1"; + AUTH_TYPE = "internal"; + ENABLE_GUESTS = "1"; + ENABLE_XMPP_WEBSOCKET = "1"; + ENABLE_COLIBRI_WEBSOCKET = "1"; + RESOLUTION = "1080"; + RESOLUTION_MIN = "360"; + ENABLE_SIMULCAST = "true"; + ENABLE_P2P = "true"; + ENABLE_CODEC_VP8 = "1"; + ENABLE_CODEC_VP9 = "1"; + ENABLE_CODEC_H264 = "1"; + ENABLE_CODEC_AV1 = "0"; + VIDEOQUALITY_BITRATE_VP8_STANDARD = "1500"; + VIDEOQUALITY_BITRATE_VP8_HIGH = "2500"; + VIDEOQUALITY_BITRATE_VP8_LOW = "200"; + }; + }; + + jitsi-prosody = { + service.image = "jitsi/prosody:stable-11031"; + service.container_name = "jitsi-prosody"; + service.restart = "unless-stopped"; + service.expose = [ "5222" "5269" "5347" "5280" ]; + service.volumes = [ + "jitsi-prosody:/config" + ]; + service.env_file = [ "/var/lib/jitsi-secrets/jitsi.env" ]; + service.environment = { + TZ = "Europe/Moscow"; + ENABLE_AUTH = "1"; + AUTH_TYPE = "internal"; + ENABLE_GUESTS = "1"; + ENABLE_XMPP_WEBSOCKET = "1"; + ENABLE_IPV6 = "0"; + PUBLIC_URL = "https://jitsi.iscg.dev"; + }; + }; + + jitsi-jicofo = { + service.image = "jitsi/jicofo:stable-11031"; + service.container_name = "jitsi-jicofo"; + service.restart = "unless-stopped"; + service.ports = [ "127.0.0.1:8888:8888" ]; + service.volumes = [ "jitsi-jicofo:/config" ]; + service.depends_on = [ "jitsi-prosody" ]; + service.env_file = [ "/var/lib/jitsi-secrets/jitsi.env" ]; + service.environment = { + TZ = "Europe/Moscow"; + ENABLE_AUTH = "1"; + AUTH_TYPE = "internal"; + JICOFO_MAX_MEMORY = "1024m"; + MAX_PARTICIPANTS = "10"; + }; + }; + + jitsi-jvb = { + service.image = "jitsi/jvb:stable-11031"; + service.container_name = "jitsi-jvb"; + service.restart = "unless-stopped"; + service.ports = [ + "10000:10000/udp" # публично — media traffic + "127.0.0.1:8080:8080" # colibri REST (localhost only) + ]; + service.volumes = [ "jitsi-jvb:/config" ]; + service.depends_on = [ "jitsi-prosody" ]; + service.env_file = [ "/var/lib/jitsi-secrets/jitsi.env" ]; + service.environment = { + TZ = "Europe/Moscow"; + PUBLIC_URL = "https://jitsi.iscg.dev"; + JVB_ADVERTISE_IPS = "51.250.45.111"; + JVB_PORT = "10000"; + JVB_DISABLE_STUN = "0"; + VIDEOBRIDGE_MAX_MEMORY = "2048m"; + DOCKER_HOST_ADDRESS = "51.250.45.111"; + }; + }; + + jitsi-coturn = { + # Coturn в host network: нужно для real client IPs и корректной NAT traversal. + # Конфликтов с systemd coturn на heather НЕТ (мы его не поднимаем, в отличие от jul11). + service.image = "coturn/coturn:4.7"; + service.container_name = "jitsi-coturn"; + service.restart = "unless-stopped"; + service.network_mode = "host"; + service.env_file = [ "/var/lib/jitsi-secrets/jitsi.env" ]; + service.command = "-v --log-file=stdout --realm=turn.iscg.dev --external-ip=51.250.45.111 --use-auth-secret --static-auth-secret=$${TURN_STATIC_AUTH_SECRET} --min-port=49160 --max-port=49200 --no-tls --no-dtls --fingerprint --no-cli --simple-log"; + }; + # === Silverbullet (note.iscg.dev) — ИСКЛЮЧЕНИЕ: bind mount === # Space = /srv/syncthing/herbarium (sync'ается syncthing на устройства). # Единственный сервис без named volume — по твоему решению, чтобы notes diff --git a/hosts/heather/caddy.nix b/hosts/heather/caddy.nix index 86925a6..a793bb7 100644 --- a/hosts/heather/caddy.nix +++ b/hosts/heather/caddy.nix @@ -73,8 +73,22 @@ in { encode zstd gzip ''; - # Jitsi Meet + # Jitsi Meet (web + WebSocket routes) "jitsi.iscg.dev".extraConfig = '' + # WebSocket routes — hop-by-hop, требуют явного upgrade + @xmpp path /xmpp-websocket* + reverse_proxy @xmpp 127.0.0.1:8000 { + header_up Host {host} + header_up Upgrade {http.upgrade} + header_up Connection {http.connection} + } + @colibri path /colibri-ws* + reverse_proxy @colibri 127.0.0.1:8000 { + header_up Host {host} + header_up Upgrade {http.upgrade} + header_up Connection {http.connection} + } + # Остальное → web контейнер reverse_proxy 127.0.0.1:8000 encode zstd gzip '';