# LiveKit 셀프호스팅 배포 가이드 (화상회의 단계 6) 운영에서 LiveKit(SFU)을 직접 호스팅하는 방법. **단일 노드 → 멀티 노드 클러스터** 순으로 설명한다. (간단히 가려면 운영도 LiveKit Cloud 를 그대로 쓸 수 있다 — 그 경우 `.env.production` 의 `LIVEKIT_*` 만 Cloud 값으로 두고 아래 셀프호스팅 절차는 생략.) > 로컬 dev 에서 셀프호스팅이 막혔던 건 WSL2/Docker Desktop 네트워킹 제약 때문이며, **공인 IP 가 있는 실서버에서는 발생하지 않는다.** --- ## 1. 사전 준비 - 공인 IP 를 가진 리눅스 서버(도커 설치) - 도메인 + DNS: `livekit.<도메인>` A 레코드 → 서버 공인 IP - **리버스 프록시(TLS 종단)**: 기존 `proxy` 외부 네트워크의 프록시(Traefik/nginx 등) - 방화벽 개방: - `443/tcp` — 시그널링(wss, 프록시 경유) - `7881/tcp` — ICE/TCP 폴백 - `7882/udp` — ICE/UDP(미디어) --- ## 2. 키 생성 API Key 는 임의 식별자, Secret 은 32자 이상 강력한 난수. ```bash echo "LIVEKIT_API_KEY=$(openssl rand -hex 8)" echo "LIVEKIT_API_SECRET=$(openssl rand -hex 32)" ``` `.env.production` 에 채운다: ```dotenv LIVEKIT_API_KEY=<생성한 key> LIVEKIT_API_SECRET=<생성한 secret(32자+)> LIVEKIT_WS_URL=wss://livekit.<도메인> # 브라우저 접속(프론트 빌드에 주입) LIVEKIT_URL=http://livekit:7880 # 백엔드 → LiveKit 내부 API ``` > `LIVEKIT_WS_URL` 은 프론트 빌드 시 `VITE_LIVEKIT_URL` 로 **굽혀진다**. 값 변경 시 프론트 재빌드 필요. --- ## 3. 기동 (단일 노드) ```bash docker compose --profile selfhost-livekit --env-file .env.production up -d --build ``` - `selfhost-livekit` 프로파일을 켜야 LiveKit 컨테이너가 생성된다(미지정 시 미생성). - 설정: `livekit/livekit.prod.yaml`(키는 `LIVEKIT_KEYS` env 로 주입), `use_external_ip: true` 로 공인 IP 자동 광고. --- ## 4. 리버스 프록시 라우팅 (시그널링 wss) `wss://livekit.<도메인>` → 컨테이너 `livekit:7880` 으로 라우팅(WebSocket 업그레이드 + TLS 종단). 미디어(7881/7882)는 프록시를 거치지 않는다 — 직접 공인 IP 로 통신. **Traefik(라벨) 예:** ```yaml # docker-compose 의 livekit 서비스에 labels 추가(운영 프록시 구성에 맞게): labels: - "traefik.enable=true" - "traefik.http.routers.livekit.rule=Host(`livekit.<도메인>`)" - "traefik.http.routers.livekit.entrypoints=websecure" - "traefik.http.routers.livekit.tls.certresolver=" - "traefik.http.services.livekit.loadbalancer.server.port=7880" ``` **nginx 예:** ```nginx server { listen 443 ssl; server_name livekit.<도메인>; # ssl_certificate ... ; location / { proxy_pass http://livekit:7880; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 600s; } } ``` --- ## 5. 검증 1. 브라우저에서 회의 입장(두 기기/네트워크에서 영상 확인) 2. 부하 테스트: ```bash LIVEKIT_URL=wss://livekit.<도메인> \ LIVEKIT_API_KEY= LIVEKIT_API_SECRET= \ ./livekit/load-test.sh full ``` --- ## 6. 멀티 노드 클러스터링 (수평 확장) 대규모(예: 160명 다수 방)에서 노드 간 트래픽을 분산하려면 Redis 로 LiveKit 노드들을 묶는다. 1. **설정에 redis 블록 추가** — 비밀번호가 들어가므로 커밋 파일이 아닌 사본에 둔다. ```bash cp livekit/livekit.prod.yaml livekit/livekit.prod.local.yaml # gitignore 대상 ``` `livekit.prod.local.yaml` 에 추가: ```yaml redis: address: redis:6379 db: 1 # 앱 캐시(db 0)와 분리 password: # 루트 .env 의 REDIS_PASSWORD ``` compose 의 livekit 볼륨을 이 사본으로 교체(override 파일 권장). 2. **노드 확장** - 단일 호스트에서 replica 만 늘리는 것은 **진짜 분산이 아니다**(같은 머신·NIC). - 실제 분산 = **여러 호스트** 각각 LiveKit 실행 + **공유 Redis** + 시그널링은 프록시가 여러 노드로 LB. RTC 는 각 노드의 공인 IP 로 직접. - LiveKit 이 방을 노드에 분배(room→node)하고, 한 방이 여러 노드에 걸치면 **캐스케이딩**으로 노드 간 미디어를 릴레이한다. - Simulcast/SVC 로 수신측 상황에 맞는 화질 레이어만 전달(기본 활성). 3. 부하 분산 검증: `./livekit/load-test.sh full` 로 다수 참여자를 투입하고, 노드별 참여자/대역폭 분포를 모니터링. --- ## 7. 운영 팁 - **UDP 수신 버퍼 상향**(권장): `sysctl -w net.core.rmem_max=16777216 net.core.wmem_max=16777216` (영구화는 `/etc/sysctl.conf`). 미설정 시 LiveKit 이 경고 로그를 남긴다. - **모니터링**: LiveKit Prometheus 메트릭(`/metrics`) + Grafana — 노드별 참여자/트랙/CPU/대역폭. - **리소스**: compose 의 `deploy.resources.limits` 를 트래픽에 맞게 조정(기본 2 CPU / 2GB). - `.gitignore` 에 `livekit/*.local.yaml` 추가(비밀번호 포함 사본 커밋 방지).