Como configurar Nginx RTMP para streaming live a partir do OBS

Guia técnico pra instalar o módulo Nginx RTMP no Ubuntu, configurar a stream key, publicar do OBS e gerar HLS pra distribuição em navegador.

Servidor de streaming próprio significa controle total: ingestão RTMP do OBS, distribuição em HLS pra navegador, possibilidade de gravar tudo em disco e zero dependência de plataformas terceiras com regras de conteúdo opacas. O módulo nginx-rtmp resolve isso em uma única peça — recebe a stream do encoder e empacota em fragmentos HLS no mesmo processo.

Este tutorial cobre a instalação do Nginx com o módulo RTMP compilado a partir do código fonte no Ubuntu 24.04 LTS, configuração de uma aplicação live com autenticação por chave, geração de manifesto HLS pra distribuição e regras de firewall pra fechar a superfície de ataque. No final, você publica do OBS e assiste no navegador via HTML5.

Tempo estimado: 30-40 minutos numa VPS limpa. Custo de execução: ~80 MB de pacotes de build + ~30 MB do binário Nginx final.

Pré-requisitos

Antes de começar

Você precisa de Ubuntu 24.04 LTS com acesso sudo, ao menos 2 GB de RAM (a compilação consome ~1 GB em pico) e portas 80, 443 e 1935 liberadas no firewall externo do provedor. SSH conectado e funcionando.

Sistema operacional Ubuntu 24.04 LTS
Porta RTMP 1935/tcp
Porta HLS 80/tcp ou 443/tcp
Encoder testado OBS Studio 30+

Pacotes que vamos instalar pra compilação: build-essential, libpcre3-dev, libssl-dev, zlib1g-dev e git. Todos do repositório oficial — nenhum PPA externo.

Instalar dependências de build

Antes de baixar o código fonte, prepare o sistema com as bibliotecas que o Nginx precisa pra compilar com suporte a SSL/TLS, regex e compressão gzip.

01

Atualize o índice de pacotes do APT:

sudo apt update

Esse comando sincroniza as listas de pacotes disponíveis. Necessário antes de instalar qualquer coisa nova num servidor que ficou parado.

02

Instale o compilador e as bibliotecas de desenvolvimento:

sudo apt install -y build-essential libpcre3-dev libssl-dev zlib1g-dev git wget

build-essential traz gcc e make. libpcre3-dev é necessário pro módulo de regex do Nginx, libssl-dev pro HTTPS e zlib1g-dev pra gzip. Total de ~250 MB instalados.

Baixar o código fonte do Nginx e do módulo RTMP

O módulo nginx-rtmp-module é mantido em fork — o original do Arut está arquivado desde 2017. Pra produção em 2026 use o fork da arut/nginx-rtmp-module ainda funcional pra recursos clássicos, ou o sergey-dryabzhinsky/nginx-rtmp-module que continua recebendo patches.

03

Crie um diretório de trabalho e baixe o Nginx estável:

mkdir -p ~/build && cd ~/build
wget https://nginx.org/download/nginx-1.26.2.tar.gz
tar -xzvf nginx-1.26.2.tar.gz

A versão 1.26.x é a linha estável atual. Evite a mainline (1.27.x) em produção a menos que precise de feature específica.

04

Clone o módulo RTMP:

cd ~/build
git clone https://github.com/sergey-dryabzhinsky/nginx-rtmp-module.git

Esse fork mantém compatibilidade com Nginx moderno e tem bugfixes que o original arquivado não recebeu.

Compilar e instalar o Nginx com módulo RTMP

A compilação leva 4-5 minutos em vCPU moderna. O configure aceita dezenas de flags — abaixo mantemos o conjunto mínimo necessário pra um servidor de streaming HTTPS funcional.

05

Configure o build apontando pro módulo RTMP:

cd ~/build/nginx-1.26.2
./configure \
  --prefix=/etc/nginx \
  --sbin-path=/usr/sbin/nginx \
  --conf-path=/etc/nginx/nginx.conf \
  --pid-path=/var/run/nginx.pid \
  --with-http_ssl_module \
  --with-http_v2_module \
  --add-module=../nginx-rtmp-module

Se algum --with-* reclamar de biblioteca faltando, instale o -dev correspondente via apt e re-rode o configure.

06

Compile e instale:

make -j$(nproc)
sudo make install

-j$(nproc) paraleliza a compilação no número de núcleos disponíveis. Numa vCPU única leva ~7 minutos; em 4 vCPUs, ~2 minutos.

07

Crie o serviço systemd pra gerenciar o Nginx:

sudo tee /etc/systemd/system/nginx.service > /dev/null <<'EOF'
[Unit]
Description=Nginx HTTP and RTMP server
After=network.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/usr/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable nginx

ExecStartPre valida a configuração antes de subir — evita serviço quebrado após edit.

Configurar a aplicação RTMP live

Agora editamos o nginx.conf pra adicionar o bloco rtmp (fora do bloco http, no nível raiz) e configurar uma aplicação live que aceita publicação do OBS e gera fragmentos HLS.

08

Crie o diretório onde os fragmentos HLS serão escritos:

sudo mkdir -p /var/www/hls
sudo chown -R nobody:nogroup /var/www/hls

O Nginx, sem usuário customizado configurado, roda como nobody. Ajuste se você definir user www-data no nginx.conf.

09

Substitua /etc/nginx/nginx.conf por uma configuração que combina HTTP + RTMP:

worker_processes auto;
events {
    worker_connections 1024;
}

rtmp {
    server {
        listen 1935;
        chunk_size 4096;

        application live {
            live on;
            record off;

            hls on;
            hls_path /var/www/hls;
            hls_fragment 3s;
            hls_playlist_length 60s;

            allow publish 127.0.0.1;
            allow publish 198.51.100.0/24;
            deny publish all;
        }
    }
}

http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;

    server {
        listen 80;
        server_name _;

        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /var/www;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
        }

        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            root /var/www;
        }
    }
}

Substitua 198.51.100.0/24 pelo seu IP/rede de origem real. O bloco allow publish é a primeira camada de defesa — sem ele, qualquer pessoa com sua URL RTMP publica.

Bloco rtmp fica fora do http

Erro clássico: colocar o bloco rtmp dentro de http {}. Ele é top-level, paralelo ao http. Se você colar dentro, o Nginx vai falhar no nginx -t com mensagem confusa sobre unknown directive.

10

Valide a sintaxe e suba o serviço:

sudo nginx -t
sudo systemctl start nginx

nginx -t deve responder configuration file ... test is successful. Qualquer erro aqui aponta a linha exata — corrija antes de continuar.

Liberar portas no firewall

Sem regras de firewall, a porta 1935 fica exposta pro mundo inteiro. UFW no Ubuntu controla isso de forma simples.

11

Habilite UFW e libere as portas necessárias:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 1935/tcp
sudo ufw enable

Confirme com sudo ufw status numbered que as 4 regras aparecem antes de desconectar do SSH.

Não esqueça o SSH antes do enable

ufw enable aplica o default de negar todo tráfego entrante imediatamente. Se você esquecer de liberar o OpenSSH primeiro, perde a sessão e precisa acessar pelo console serial do provedor pra desbloquear.

Publicar do OBS

Com o servidor pronto, configure o OBS pra ingestão.

12

Abra OBS → Configurações → Transmissão e preencha:

Serviço Personalizado
Servidor rtmp://SEU-IP/live
Chave de transmissão minha-stream-001

A “chave” é o nome (name) que aparece nos fragmentos HLS e nos logs do Nginx-RTMP. Pode ser qualquer string ASCII sem espaços.

13

Clique em “Iniciar transmissão” no OBS. O OBS conecta no rtmp://SEU-IP/live e começa a publicar a stream com o nome minha-stream-001.

Verificar a transmissão

Confira que os fragmentos HLS estão sendo gerados e tocam num player web.

14

Liste os arquivos em /var/www/hls:

ls -la /var/www/hls/

Output esperado, ~3 segundos após começar a publicar:

minha-stream-001-0.ts
minha-stream-001-1.ts
minha-stream-001.m3u8

Os .ts são fragmentos MPEG-TS de ~3 segundos cada. O .m3u8 é o manifesto que aponta pros fragmentos atuais.

15

Teste no navegador via https://hls-js.netlify.app/demo/ ou qualquer player que aceite HLS. Cole http://SEU-IP/hls/minha-stream-001.m3u8 e dê play.

Pra um teste rápido sem player web, use ffplay:

ffplay http://SEU-IP/hls/minha-stream-001.m3u8

A latência esperada do OBS ao player é de 9-15 segundos com a configuração padrão acima (hls_fragment 3s × buffer de 3 fragmentos no player).

Resolução de problemas

OBS conecta mas nada aparece no /var/www/hls

Verifique permissão do diretório:

sudo -u nobody touch /var/www/hls/teste && rm /var/www/hls/teste

Se reclamar “Permission denied”, reaplique chown -R nobody:nogroup /var/www/hls.

Erro “Failed to connect to server” no OBS

Cheque se a porta 1935 está aberta de fora:

nc -zv SEU-IP 1935

Se falhar, confira UFW (sudo ufw status) e o firewall do provedor da VPS — alguns têm firewall externo separado.

Player carrega o m3u8 mas dá “no supported source”

Falta CORS ou MIME type errado. Confirme que o response do .m3u8 traz Content-Type: application/vnd.apple.mpegurl e Access-Control-Allow-Origin: *:

curl -I http://SEU-IP/hls/minha-stream-001.m3u8

Próximos passos

Você tem agora um servidor RTMP funcional convertendo pra HLS. Daqui dá pra aprofundar em várias direções:

  • Adicionar HTTPS com Let’s Encrypt no servidor HTTP (Certbot funciona normal — o RTMP em si não recebe TLS direto, mas o HLS sim).
  • Implementar autenticação via on_publish apontando pra um endpoint seu que valida tokens contra banco.
  • Habilitar gravação automática com record all + record_path /var/www/recordings pra arquivar tudo em FLV.
  • Transcodificar pra múltiplos bitrates com exec ffmpeg dentro do bloco application — necessário pra ABR (adaptive bitrate) decente.
  • Trocar HLS por LL-HLS (hls_fragment 1s) ou WebRTC se precisar de latência sub-segundo.

Se você está colocando isso em produção, uma VPS Hostini de streaming já vem com banda dedicada e portas RTMP/1935 liberadas por padrão — sem precisar abrir ticket pra firewall externo.

Perguntas frequentes

Por que preciso compilar o Nginx do zero em vez de usar o pacote do apt?

O módulo nginx-rtmp não é dinâmico no Nginx estável do Ubuntu — ele precisa ser linkado em tempo de compilação via `--add-module`. O pacote `libnginx-mod-rtmp` existe em alguns mirrors, mas costuma ficar travado em versões antigas do módulo (1.2.1 de 2017). Compilar leva 4-5 minutos e te dá controle total da versão.

Qual a latência real de uma stream RTMP convertida pra HLS?

Entre 8 e 30 segundos com configuração padrão, dependendo do `hls_fragment` (default 5s) e do `hls_playlist_length`. Pra reduzir abaixo de 5s, considere LL-HLS com `hls_fragment 1s` e player compatível (hls.js 1.x), ou troque pra WebRTC se precisar de sub-segundo.

Posso transmitir do OBS direto pra HLS sem RTMP?

Não nativamente. O OBS exporta em RTMP, SRT ou WHIP (WebRTC). HLS é formato de distribuição pra player, não de ingestão. O fluxo padrão é OBS → RTMP → Nginx-RTMP gera HLS → player consome HLS via HTTP.

Como restrinjo quem pode publicar na stream sem expor a chave?

Use `on_publish` apontando pra um endpoint HTTP seu que valida o `name` (stream key) contra banco de dados. Nginx-RTMP só permite a publicação se o endpoint retornar 2xx. Combine com firewall fechando a porta 1935 só pra IPs autorizados se a base de transmissores for fixa.

Quantas streams simultâneas um servidor médio aguenta?

Depende de CPU e banda. Numa VPS de 4 vCPU + 8 GB sem transcodificação (apenas repassando RTMP e gerando HLS por fragmento de cópia direta), você atende 50-100 publishers concorrentes. Com transcodificação H.264 via ffmpeg pra múltiplos bitrates, cai pra 4-8 streams por CPU.

Os fragmentos HLS estão sendo gerados mas o player não consegue tocar — o que verificar?

Três causas comuns: 1) CORS — adicione `add_header 'Access-Control-Allow-Origin' '*'` no location HLS; 2) MIME type — confirme que `.m3u8` é `application/vnd.apple.mpegurl` e `.ts` é `video/mp2t`; 3) permissão do diretório — `/var/www/hls` precisa ser gravável pelo usuário do Nginx (geralmente www-data).

Tópicos:
Próximos passos Infraestrutura otimizada pra transmissão ao vivo, gravação e VOD.Monte seu servidor de streaming na Hostini →
Esse tutorial foi útil?
Falar no WhatsApp