← Blog

Hospede o Jitsi Meet para chamadas de vídeo

Railyard

14 de junho de 2026 · 7 min de leitura

Siga isso no seu próprio servidor. Comece grátis, sem cartão

Zoom e Google Meet limitam chamadas gratuitas por tempo ou número de participantes, e os planos pagos cobram por host, por mês, usando ou não naquele mês. O Jitsi Meet é uma videoconferência open-source que faz o mesmo trabalho essencial, chamadas pelo navegador com compartilhamento de tela e sem instalação, como software self-hosted: quatro containers, um domínio, e nenhuma cobrança por minuto ou por assento depois que estiver no ar. Este guia monta tudo a partir de um servidor vazio usando as imagens oficiais, com o Caddy cuidando do HTTPS na frente, e explica a única peça (uma única porta UDP) que determina se as chamadas de fato conectam quando mais de uma pessoa está em redes diferentes.

No final, você vai ter uma instância do Jitsi Meet funcionando no seu próprio domínio, vai entender por que essa porta UDP importa, e vai saber o estado honesto do caminho de um clique do Railyard para esse app específico.

O que você vai precisar

  • Um servidor com folga real. Uma única chamada de teste entre duas pessoas numa rede local cabe num Hetzner CX23 (2 vCPUs, 4 GB de RAM, €5,99/mês sem VAT), mas reuniões de equipe contínuas pedem mais: um CX33 (4 vCPUs, 8 GB de RAM, €8,99/mês) é uma base mais segura quando várias pessoas realmente dependem disso diariamente.
  • Um domínio com um registro A de DNS apontado para o servidor (este guia usa meet.example.com).
  • O endereço IPv4 público do servidor, conhecido com antecedência, não só atribuído (você vai precisar dele para o NAT traversal na Etapa 3).
  • Acesso SSH e cerca de 20 minutos.

Etapa 1: Provisione o servidor e instale o Docker

Crie o servidor no Ubuntu 24.04, aponte o DNS para ele e instale o Docker:

ssh root@203.0.113.30
apt update && apt upgrade -y
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
docker --version
docker compose version

Etapa 2: Pegue os diretórios de configuração oficiais

A própria documentação do Jitsi orienta a baixar uma release com tag em vez de clonar o repositório direto, já que o arquivo compose na branch padrão pode estar mais adiantado do que o que as imagens publicadas de fato suportam. Este guia usa a release atual, stable-11248-1:

mkdir -p ~/.jitsi-meet-cfg/{web,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb}
chmod 777 ~/.jitsi-meet-cfg/transcripts

Esses diretórios guardam a configuração gerada pelo próprio Jitsi e persistem entre upgrades; perdê-los significa regenerar senhas e qualquer customização.

Etapa 3: Escreva o arquivo de ambiente

CONFIG=~/.jitsi-meet-cfg
HTTP_PORT=8000
HTTPS_PORT=8443
JVB_PORT=10000
PUBLIC_URL=https://meet.example.com
DISABLE_HTTPS=1
ENABLE_LETSENCRYPT=0
ENABLE_HTTP_REDIRECT=0
XMPP_DOMAIN=meet.jitsi
XMPP_AUTH_DOMAIN=auth.meet.jitsi
XMPP_MUC_DOMAIN=muc.meet.jitsi
XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
XMPP_GUEST_DOMAIN=guest.meet.jitsi
XMPP_SERVER=xmpp.meet.jitsi
JICOFO_COMPONENT_SECRET=
JICOFO_AUTH_PASSWORD=
JVB_AUTH_PASSWORD=
JVB_ADVERTISE_IPS=203.0.113.30
ENABLE_GUESTS=1
TZ=Etc/UTC

Gere os três segredos em branco com:

for v in JICOFO_COMPONENT_SECRET JICOFO_AUTH_PASSWORD JVB_AUTH_PASSWORD; do
  echo "$v=$(openssl rand -hex 16)"
done

Cole cada valor no .env no lugar do espaço em branco. DISABLE_HTTPS=1 e ENABLE_LETSENCRYPT=0 importam especificamente porque o Caddy está cuidando do HTTPS aqui em vez da opção embutida do próprio container web, que de outra forma disputaria a porta 443 com o Caddy. JVB_ADVERTISE_IPS é a configuração que a maioria dos guias de Jitsi self-hosted esconde: é o IP público do servidor, informado explicitamente ao videobridge para que ele consiga anunciar um endereço alcançável para participantes atrás de NAT, em vez de só o endereço da rede privada do Docker.

Etapa 4: Escreva o arquivo Docker Compose

services:
  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy-data:/data
      - caddy-config:/config
    depends_on:
      - web

  web:
    image: ghcr.io/jitsi/web:stable-11248-1
    restart: unless-stopped
    volumes:
      - ${CONFIG}/web:/config
      - ${CONFIG}/transcripts:/usr/share/jitsi-meet/transcripts
    env_file:
      - .env
    depends_on:
      - jvb

  prosody:
    image: ghcr.io/jitsi/prosody:stable-11248-1
    restart: unless-stopped
    expose:
      - "5222"
      - "5269"
      - "5347"
      - "5280"
    volumes:
      - ${CONFIG}/prosody/config:/config
      - ${CONFIG}/prosody/prosody-plugins-custom:/prosody-plugins-custom
    env_file:
      - .env

  jicofo:
    image: ghcr.io/jitsi/jicofo:stable-11248-1
    restart: unless-stopped
    volumes:
      - ${CONFIG}/jicofo:/config
    env_file:
      - .env
    depends_on:
      - prosody

  jvb:
    image: ghcr.io/jitsi/jvb:stable-11248-1
    restart: unless-stopped
    ports:
      - "${JVB_PORT:-10000}:${JVB_PORT:-10000}/udp"
    volumes:
      - ${CONFIG}/jvb:/config
    env_file:
      - .env
    depends_on:
      - prosody

volumes:
  caddy-data:
  caddy-config:

O serviço jvb é o único com uma porta real do host publicada diretamente, 10000/udp, em vez de escondida atrás do Caddy. Isso não é uma simplificação; o HTTPS pode passar por proxy, mas o fluxo real de áudio e vídeo não pode, já que o WebRTC precisa de um caminho UDP direto. Valide antes de iniciar:

docker compose config

Etapa 5: Escreva o Caddyfile

meet.example.com {
    reverse_proxy web:8000
}

Etapa 6: Suba a stack e abra o firewall

docker compose up -d
docker compose ps

Você deve ver os cinco serviços (caddy, web, prosody, jicofo, jvb) como running. Abra a porta UDP explicitamente se o servidor tiver um firewall ativo:

ufw allow 10000/udp
ufw allow 80/tcp
ufw allow 443/tcp

Acesse https://meet.example.com; você deve ver a própria página inicial do Jitsi Meet com um certificado válido. Inicie uma reunião e entre a partir de duas redes diferentes, não duas abas na mesma máquina, já que testar na mesma rede não revela um problema de NAT ou firewall na porta UDP.

O caminho curto: faça com o Railyard, com honestidade

O Railyard tem um template de stack para o Jitsi Meet que provisiona os quatro containers da aplicação (web, prosody, jicofo, jvb) juntos: escolha Jitsi Meet no catálogo de templates. Vale ser direto sobre onde isso está hoje: o manifesto de deploy do Railyard ainda não tem como publicar uma porta UDP ou anunciar o IP público de um servidor para um container do jeito que JVB_ADVERTISE_IPS e o mapeamento UDP do host na Etapa 4 fazem. Os containers sobem e a interface web carrega, mas chamadas entre participantes em redes diferentes não vão ter um caminho de mídia funcionando até isso ser resolvido. Se você precisa do Jitsi Meet realmente atendendo chamadas hoje, as Etapas 1 a 6 acima são o caminho real; o template do Railyard está marcado como uma lacuna conhecida, não escondido debaixo do tapete.

Solução de problemas

A página carrega, mas as chamadas nunca conectam entre duas redes diferentes. Isso quase sempre é JVB_ADVERTISE_IPS não definido, ou definido com o endereço privado do servidor em vez do público, combinado com a porta UDP não estar de fato aberta no firewall. Confirme os dois; uma chamada entre duas abas do navegador na mesma máquina vai funcionar mesmo com isso quebrado, e é por isso que esse não é um teste válido.

O HTTPS não carrega, ou o Caddy registra um conflito de porta. Confira se DISABLE_HTTPS=1 e ENABLE_LETSENCRYPT=0 estão de fato definidos no .env; sem eles, o nginx embutido do próprio container web também tenta ocupar a porta 443.

Um participante tem áudio mas não vídeo, ou o contrário. Geralmente é uma rede restritiva do lado desse participante específico (firewall corporativo, wifi de hotel) e não o servidor; peça para ele tentar numa rede diferente antes de assumir que o servidor está mal configurado.

Falta de memória com mais de um punhado de participantes. O videobridge do Jitsi roteia mídia para cada participante, e isso é trabalho real de CPU e memória que escala com o número de pessoas, não um custo fixo. docker stats jvb enquanto uma chamada está rolando mostra se essa é a restrição; um CX33 ou maior tem mais margem do que um CX23.

Mudanças no .env não têm efeito. A maioria das variáveis de ambiente do Jitsi só é lida uma vez, quando um container inicia; docker compose up -d depois de uma mudança no .env nem sempre recria um container que já está rodando sem mudanças. Force com docker compose up -d --force-recreate.

Perguntas frequentes

Posso gravar reuniões? Sim, através do Jibri, um componente de gravação separado que este guia não configura; ele precisa do próprio container e de mais recursos de servidor, e vale a pena adicionar só depois que a configuração base acima estiver confirmada funcionando.

Quantas pessoas um servidor aguenta? Depende mais da qualidade de vídeo e do tamanho do servidor do que de um número fixo; um CX33 aguenta com conforto as reuniões regulares de uma equipe pequena, e a CPU no container jvb é o que vale observar conforme o número de participantes cresce.

Eu preciso de TURN para isso funcionar? Na maioria das vezes, não, já que JVB_ADVERTISE_IPS mais uma porta UDP aberta cobre o caso comum. Um servidor TURN ajuda especificamente quando um participante está atrás de um firewall que bloqueia UDP direto por completo, que é uma fatia menor das redes do mundo real do que costumava ser.

O Jitsi Meet é mesmo de graça para rodar? O software é; o servidor e a largura de banda dele são o custo real, e chamadas de vídeo usam consideravelmente mais largura de banda do que um app web típico, algo que vale considerar se um provedor mede o tráfego de saída de perto.

Como é a experiência no celular? O Jitsi tem apps nativos para iOS e Android que funcionam com qualquer servidor self-hosted; aponte eles para https://meet.example.com da mesma forma que a versão no navegador.

Posso rodar isso atrás de um roteador com NAT em casa em vez de um servidor na nuvem? Sim, com uma etapa extra: redirecione tanto a porta UDP de mídia quanto a TCP 443 do roteador para a máquina rodando o Docker, e defina JVB_ADVERTISE_IPS com o IP público do próprio roteador em vez do endereço local da máquina, já que é isso que o videobridge precisa entregar para participantes remotos.

O Jitsi Meet é uma das histórias mais honestas de self-hosting aqui justamente porque a única coisa que de fato importa, se uma chamada conecta entre duas redes, se resume a uma porta UDP e um endereço IP configurados corretamente, não um mistério. Acerte essas duas coisas e o resto são quatro containers e um proxy reverso, rodando chamadas sem ninguém contando os minutos.

Por que escolhem o Railyard para isso

  • Sua própria conta de cloud. Faça deploy no DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, ou em qualquer servidor Linux via SSH, cobrado direto pelo seu provedor, sem markup.
  • Um preço fixo por equipe. O Free é grátis para sempre: um servidor mais um servidor de banco de dados, três apps, sem cartão. O Pro custa US$19 por mês para até cinco servidores e apps ilimitados. O Team custa US$49 por mês com servidores ilimitados. Sem cobrança por app, por deploy, por assento ou por gigabyte.
  • Templates de um clique. Faça deploy de apps open source, como bancos de dados, analytics e ferramentas de dev, no seu próprio servidor em um clique.
  • Bancos de dados gerenciados. Postgres, MySQL e Redis com backups programados, verificados por restauração, e recuperação point-in-time.
  • Push-to-deploy. Faça deploy a partir do GitHub, GitLab ou da CLI, com HTTPS automático e releases sem downtime.

Veja a versão honesta do atalho

Escolha Jitsi Meet no catálogo de templates do Railyard, e leia a limitação real antes de seguir.

Plano grátis, sem cartão, e 14 dias de Pro para cada equipe nova. Um preço fixo por equipe.