SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-26

Como instalar Rocket.Chat com Docker Compose

Instale o Rocket.Chat em um VPS com Docker Compose, configure o replica set de um único nó do MongoDB, TLS e backups para evitar falhas na implantação.

O que você vai criar

Um chat privado de equipa sob o seu controlo: Rocket.Chat a correr no seu próprio VPS com Docker Compose, com terminação TLS e todas as mensagens armazenadas numa base de dados MongoDB que pode salvaguardar e mover. O Rocket.Chat é uma alternativa open source madura ao Slack e ao Teams, com canais, mensagens diretas, threads, partilha de ficheiros e chamadas de voz e vídeo, tudo em hardware que arrenda e controla. No entanto, não é a única opção credível. Se ainda estiver a escolher, Mattermost, Rocket.Chat, Synapse e Zulip comparados apresenta as diferenças nos aspetos que causam problemas mais tarde: RAM, base de dados, notificações push em dispositivos móveis, SSO e atualizações. A aplicação é um único contentor que fica disponível em poucos minutos. Tudo o que realmente falha fica na base de dados ao lado, por isso a maior parte deste guia é dedicada ao MongoDB, em particular ao requisito que surpreende toda a gente na primeira utilização: o Rocket.Chat não funciona com um MongoDB autónomo. Precisa de um replica set, mesmo que esse "conjunto" tenha um único nó.

Pré-requisitos e a matemática da RAM que ninguém explica

Dimensione o servidor de forma realista. O mínimo prático para uma equipa pequena é 2 vCPU e 4 GB de RAM. O processo Node.js do Rocket.Chat precisa de aproximadamente 1 a 1.5 GB por si só, e a cache WiredTiger do MongoDB utiliza, por predefinição, cerca de metade da RAM restante. Num VPS com 2 GB, os dois serviços cabem durante o arranque, mas entram em conflito assim que chega tráfego real: o MongoDB aumenta a cache, o Node aumenta a heap, o kernel fica sem páginas e o out-of-memory killer termina o processo maior, normalmente mongod. O contentor apresenta Killed, o Docker reinicia-o e o servidor de chat começa a desligar-se a cada poucos minutos sob uma carga que deveria suportar sem problemas. 2 GB são suficientes para testar o serviço com duas pessoas, mas não para um servidor de equipa. Comece com 4 GB e escolha 8 GB se esperar dezenas de utilizadores simultâneos, videochamadas ou um histórico de uploads em crescimento. Reserve também recursos para tudo o que o servidor tiver de alojar: colocar um workspace AFFiNE semelhante ao Notion no mesmo VPS adiciona mais quatro contentores a competir pelas mesmas páginas de memória, pelo que a RAM deles deve ser acrescentada à do Rocket.Chat, e não retirada dela.

Também precisa de ter três elementos preparados antes de começar. Um nome de domínio com um registo A a apontar para o IP público do VPS, porque os recursos em tempo real do Rocket.Chat e os clientes móveis precisam de um hostname estável, não de um IP isolado. As portas 80 e 443 abertas tanto na firewall do servidor como na firewall de rede do fornecedor, que é um controlo separado na maioria dos painéis. E um VPS KVM novo com Ubuntu 24.04 e acesso root ou sudo. Se ainda estiver a decidir se um servidor de chat é o primeiro serviço adequado para executar, o guia sobre o que vale a pena alojar por conta própria em 2026 apresenta os principais compromissos.

Instale o motor Docker e o plugin Compose

Use o próprio repositório apt do Docker, não o pacote docker.io fornecido pelo Ubuntu nem o antigo binário Python autónomo docker-compose. O Compose moderno é um plugin do Docker que deve ser chamado como docker compose, com um espaço, e não com um hífen. A versão antiga docker-compose v1 chegou ao fim da vida útil e trata incorretamente a sintaxe de healthcheck e de dependências apresentada abaixo.

sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Confirme que ambos os componentes estão presentes:

sudo docker version
sudo docker compose version

docker compose version apresentar algo como Docker Compose version v2.x é a verificação relevante. Se devolver um erro com docker: 'compose' is not a docker command, o plugin não foi instalado. Corrija o problema agora para evitar falhas confusas mais tarde.

O ficheiro Compose: MongoDB como replica set de um único nó

Esta é a parte que costuma ser configurada incorretamente, por isso leia-a com atenção. O Rocket.Chat usa change streams do MongoDB para enviar novas mensagens aos clientes ligados em tempo real, e os change streams só estão disponíveis num replica set. Aponte o Rocket.Chat para um mongod autónomo comum e ele vai ligar-se, falhar ao abrir um change stream e entrar num ciclo de reinícios contínuo. A correção não é complexa: execute um único contentor MongoDB normal, mas inicie-o com --replSet e inicialize depois um replica set com um membro.

Crie um diretório de trabalho e um compose.yml:

services:
  mongodb:
    image: mongo:8.0
    restart: always
    command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--oplogSize", "128"]
    volumes:
      - mongodb_data:/data/db
      - mongodb_config:/data/configdb
    healthcheck:
      test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping')"]
      interval: 10s
      timeout: 10s
      retries: 12

  rocketchat:
    image: registry.rocket.chat/rocketchat/rocket.chat:8.5.1
    restart: always
    depends_on:
      mongodb:
        condition: service_healthy
    environment:
      MONGO_URL: "mongodb://mongodb:27017/rocketchat?replicaSet=rs0"
      MONGO_OPLOG_URL: "mongodb://mongodb:27017/local?replicaSet=rs0"
      ROOT_URL: "https://chat.example.com"
      PORT: "3000"
    ports:
      - "127.0.0.1:3000:3000"

volumes:
  mongodb_data:
  mongodb_config:

Algumas opções são deliberadas. A porta do Rocket.Chat é publicada em 127.0.0.1:3000, não em 0.0.0.0. A própria aplicação não usa TLS, por isso apenas o reverse proxy no mesmo servidor deve conseguir aceder-lhe; associá-la a todas as interfaces exporia diretamente uma página de início de sessão sem encriptação à Internet pública. O MongoDB não é publicado no host; só pode ser acedido através da rede interna do Compose, com o nome mongodb, que é exatamente o hostname usado por MONGO_URL. MONGO_URL transporta ?replicaSet=rs0. Se o omitir, o driver trata o servidor como autónomo, mesmo sendo um replica set, e os change streams continuam a falhar. MONGO_OPLOG_URL aponta para a base de dados local, onde reside o oplog. As versões atuais do Rocket.Chat preferem change streams, mas definir esta opção não causa problemas e mantém compatibilidade com caminhos de código mais antigos. depends_on usa condition: service_healthy, por isso o Compose espera até o MongoDB responder a um ping antes de iniciar o Rocket.Chat. Essa é a finalidade do healthcheck.

Fixe tags de versão reais nas duas imagens, mongo:8.0 e uma versão explícita do Rocket.Chat, como 8.5.1 neste caso, e nunca use :latest. Isso transforma uma docker pull não supervisionada numa atualização acidental que não pode ser migrada. Consulte a versão estável atual do Rocket.Chat e as versões do MongoDB compatíveis antes de fixar as versões. O Rocket.Chat publica um documento de informações legível por máquina para cada versão: curl -s https://releases.rocket.chat/8.5.1/info | jq '{compatibleMongoVersions, lts}' devolve compatibleMongoVersions: ["8.0"] para a versão 8.5.1. Portanto, mongo:8.0 é o único motor compatível, além de um sinalizador lts que indica se essa versão é uma compilação de suporte de longo prazo adequada para fixar num servidor que não pretende administrar continuamente. Nem todos os projetos publicam uma imagem versionada. Nesse caso, a fixação passa para o código-fonte: alojar o rastreador de treinos openGym significa fazer checkout de uma tag específica do git e compilar a partir dela, em vez de seguir uma branch que pode mudar.

Inicialize o conjunto de réplicas

Inicie a stack:

sudo docker compose up -d

O Rocket.Chat começará a falhar imediatamente, e o Docker continuará a reiniciá-lo. Isso é esperado porque o conjunto de réplicas ainda não existe. Crie-o uma vez, manualmente:

sudo docker compose exec mongodb mongosh --eval 'rs.initiate({_id: "rs0", members: [{_id: 0, host: "mongodb:27017"}]})'

O resultado correto é { ok: 1 }. Em poucos segundos, o nó único elege-se como primary. Confirme com:

sudo docker compose exec mongodb mongosh --quiet --eval 'rs.status().members[0].stateStr'

Deve ver PRIMARY. O detalhe mais importante de toda esta página é o argumento host: "mongodb:27017". Se executar um rs.initiate() simples, sem uma lista de membros, o MongoDB anuncia o conjunto de réplicas usando o hostname interno do contentor, um hash aleatório como a1b2c3d4e5f6. O Rocket.Chat, ao ligar-se a partir do seu próprio contentor, não consegue resolver esse nome. Por isso, o driver do MongoDB falha a resolução DNS desse nome e fica num ciclo infinito, registando MongoServerSelectionError: getaddrinfo ENOTFOUND a1b2c3d4e5f6. Inicialize sempre o conjunto com o nome explícito do serviço correspondente ao seu MONGO_URL.

Primeiro arranque: acompanhe a inicialização

Depois de o conjunto estar definido como primário, o próximo reinício do Rocket.Chat estabelece a ligação corretamente e inicia as migrações da primeira execução. Acompanhe os logs:

sudo docker compose logs -f rocketchat

A linha que deve aguardar é o banner de arranque:

+--------------------------------------------+
        SERVER RUNNING
   Rocket.Chat Version: 8.5.1
        NodeJS Version: 22.22.3 - x64
+--------------------------------------------+

O primeiro arranque é lento. A aplicação executa migrações da base de dados e cria índices, por isso aguarde um ou dois minutos antes de investigar. Se o log repetir MongoServerSelectionError: Server selection timed out after 30000 ms com uma descrição da topologia do tipo ReplicaSetNoPrimary, o conjunto de réplicas não foi iniciado. Se repetir getaddrinfo ENOTFOUND com um hash aleatório, foi iniciado com o host incorreto. Em qualquer dos casos, volte um passo. Quando vir SERVER RUNNING, o Rocket.Chat estará a escutar em 127.0.0.1:3000 e será altura de colocar um nome de host real e TLS à frente dele.

Coloque-o atrás de TLS

Nunca exponha o Rocket.Chat através de HTTP simples. Depois de iniciar sessão em http://, a sua palavra-passe de administrador fica disponível para qualquer pessoa no caminho da ligação. Termine o TLS num reverse proxy no mesmo servidor e encaminhe para 127.0.0.1:3000. Há dois pontos importantes: o proxy tem de encaminhar os cabeçalhos de atualização do WebSocket, porque o Rocket.Chat funciona em tempo real e deixa de funcionar sem eles; e o ROOT_URL do contentor tem de corresponder exatamente ao endereço HTTPS público introduzido pelos utilizadores.

Comece com um bloco de servidor HTTP simples do nginx que faça proxy para a aplicação e encaminhe os cabeçalhos de atualização. Guarde-o como /etc/nginx/sites-available/rocketchat, crie um link simbólico para sites-enabled e recarregue a configuração:

server {
    listen 80;
    server_name chat.example.com;

    client_max_body_size 100M;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Deixe-o na porta 80 por agora. Um bloco com listen 443 ssl; e sem certificado nem sequer passa sudo nginx -t. Recarregue o nginx (sudo nginx -t && sudo systemctl reload nginx) e depois emita o certificado. No Ubuntu, a opção mais simples é Certificados TLS Let's Encrypt com Certbot e nginx: certbot --nginx reescreve o bloco anterior no próprio local, adicionando listen 443 ssl;, as linhas ssl_certificate e um redirecionamento automático de 80 para 443. Também agenda a renovação automaticamente. Se já executar vários contentores atrás de um único proxy, Traefik com TLS automático para várias aplicações Docker é a opção mais organizada. Adicione etiquetas de router e serviço ao serviço rocketchat, e o Traefik solicita e renova o certificado automaticamente, sem qualquer bloco do nginx. Em qualquer dos casos, defina ROOT_URL como https://chat.example.com em compose.yml e execute novamente sudo docker compose up -d para que o contentor aplique a alteração. Se quiser que o servidor seja acessível apenas a partir da sua própria rede, e não da Internet pública, coloque à frente uma VPN WireGuard auto-hospedada no VPS e associe o proxy ao endereço do túnel.

O assistente de configuração inicial

Aceda a https://chat.example.com e o Rocket.Chat apresenta um assistente curto. Primeiro, a conta de admin, o nome real, o nome de utilizador, o email e uma palavra-passe forte; esta é a única conta existente, por isso não a perca. Em seguida, as informações da organização e do servidor, incluindo o nome, o setor, a dimensão, o nome do site e o idioma predefinido; são definições cosméticas, preencha-as e avance. Depois, a escolha que realmente importa: registar este workspace no Rocket.Chat Cloud ou mantê-lo autónomo.

O registo ativa as notificações push móveis através do gateway do Rocket.Chat e o marketplace de add-ons, mas cria uma relação de controlo com a cloud do Rocket.Chat. O modo autónomo mantém o servidor totalmente privado e sem dependências externas, mas as notificações push no iOS e no Android deixam de funcionar, porque a Apple e a Google não permitem que uma aplicação criada internamente mantenha os certificados push; as aplicações oficiais encaminham as notificações através do gateway da cloud. Escolha o modo autónomo se a privacidade for o objetivo principal e os seus utilizadores usarem a aplicação web; escolha o registo se as notificações push móveis forem indispensáveis. Pode alterar esta opção mais tarde em Admin.

Bloqueie o acesso antes de convidar alguém

O Rocket.Chat é distribuído com o registo aberto ativado. Por predefinição, o Registration Form está definido como Public, por isso qualquer pessoa que encontre o URL pode criar uma conta. Num hostname público, isso permite o acesso a qualquer pessoa. Aceda a Admin → Settings → Accounts → Registration e defina Registration Form como Disabled, para criar contas manualmente ou através de um link de convite, ou como Secret URL. Enquanto estiver nessa secção, desative Allow Anonymous Read e Allow Anonymous Write, exceto se pretender especificamente um canal público apenas de leitura. Se criar cada conta manualmente parecer trabalhoso e este não for o único serviço em que a sua equipa inicia sessão, configure o login OAuth do Rocket.Chat para usar um servidor SSO Authentik autoalojado. Assim, as entradas e saídas de utilizadores são geridas uma vez, num único local, em vez de aplicação por aplicação.

Defina também o destino dos uploads. O armazenamento predefinido de File Upload é o GridFS, que guarda cada imagem e anexo dentro do próprio MongoDB. É simples, mas significa que a base de dados, e todas as mongodump que fizer, aumenta sem limite à medida que as pessoas colam capturas de ecrã. Em Admin → Settings → File Upload, pode mudar o armazenamento para o sistema de ficheiros local ou para um bucket compatível com S3, e definir um tamanho máximo de ficheiro razoável. Se a sua equipa troca bibliotecas fotográficas completas em vez de capturas de ecrã ocasionais, esses ficheiros devem ficar num servidor de fotografias dedicado, não numa base de dados de chat. A comparação entre PhotoPrism e Immich avalia o custo de cada opção em RAM e os comandos de backup necessários. Para uma equipa pequena, o GridFS é adequado; tenha apenas em conta que os backups ficam maiores com o tempo.

Backups com mongodump

Todos os seus dados estão no volume mongodb_data. Não copie o volume enquanto a base de dados está em execução. Crie um dump consistente com mongodump, transmitido para um ficheiro no host:

sudo docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > rocketchat-$(date +%F).archive.gz

Esse único arquivo compactado com gzip contém todo o seu workspace: utilizadores, canais, mensagens, definições e, se deixou os uploads no GridFS, também os ficheiros. Se moveu os uploads para o sistema de ficheiros ou para o S3, faça uma cópia de segurança desse armazenamento separadamente. Restaure numa stack nova inicializando primeiro o replica set e, em seguida:

sudo docker compose exec -T mongodb mongorestore --archive --gzip --drop < rocketchat-2026-07-15.archive.gz

Copie o arquivo para fora do servidor, para armazenamento de objetos, outro servidor ou qualquer local em que a falha do VPS não destrua também a cópia de segurança. Execute o dump todas as noites pelo cron. Uma cópia de segurança que nunca foi restaurada é uma expectativa, não uma cópia de segurança. Teste o restauro uma vez num VPS descartável para confirmar que funciona antes de precisar dele.

Atualizações: fixe as tags, leia as notas e respeite a matriz do MongoDB

Duas regras tornam as atualizações previsíveis. Primeiro, atualize o Rocket.Chat uma versão principal de cada vez. Ele executa migrações de esquema no arranque e recusa deliberadamente saltar versões principais; se tentar passar diretamente de 6.x para 8.x, o processo termina com um erro de migração em vez de corromper os dados. Altere a tag da imagem para a versão mais recente da versão principal seguinte, leia as notas dessa versão para identificar alterações incompatíveis, execute docker compose up -d e monitorize os logs até a migração terminar antes de prosseguir. Segundo, respeite a matriz de suporte do MongoDB. Cada versão do Rocket.Chat suporta um conjunto específico de versões do MongoDB, e curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions indica quais. Ao atualizar o MongoDB, por exemplo, de 7.0 para 8.0, avance uma versão principal de cada vez e defina a versão de compatibilidade de funcionalidades depois de cada salto. No MongoDB 8.0, esse comando requer um confirm: true explícito; caso contrário, termina com uma mensagem a indicar que deve executá-lo novamente com a flag de confirmação:

sudo docker compose exec mongodb mongosh --eval 'db.adminCommand({setFeatureCompatibilityVersion: "8.0", confirm: true})'

Faça um mongodump antes de cada atualização de qualquer um dos componentes. Essa é toda a política de segurança necessária.

Modos de falha, com as strings exatas

O Rocket.Chat entra em ciclos de reinício logo depois de docker compose up, e docker compose logs rocketchat fica preenchido com um MongoServerSelectionError. O MongoDB está em execução, mas o driver não consegue selecionar um primary, e a string exata indica qual foi o erro. Server selection timed out after 30000 ms com um tipo de topologia ReplicaSetNoPrimary significa que nunca executou rs.initiate(); o set ainda não tem configuração. getaddrinfo ENOTFOUND seguido por um hash aleatório significa que iniciou sem host: "mongodb:27017" explícito, por isso o MongoDB anunciou um nome de host de contentor que não pode ser resolvido. Diagnostique com sudo docker compose exec mongodb mongosh --eval 'rs.status()': se devolver o erro MongoServerError: no replset config has been received, inicie o set; se mostrar um membro cujo name é um hash aleatório, reinicie a configuração usando o nome do serviço.

A interface Web carrega, mas o login fica indefinidamente em processamento e nunca termina. Abra a consola do browser e verá WebSocket connection to 'wss://chat.example.com/websocket' failed. Quase sempre se trata de uma incompatibilidade de ROOT_URL ou de um proxy que não encaminha os cabeçalhos de upgrade. Confirme se ROOT_URL corresponde ao endereço público exato, incluindo https://, e se o bloco location do nginx define Upgrade e Connection "upgrade" com proxy_http_version 1.1. Altere uma destas definições e execute novamente docker compose up -d.

Um contentor continua a terminar e docker compose ps mostra Restarting. docker compose logs é interrompido a meio da linha e sudo dmesg | tail mostra Out of memory: Killed process 12345 (mongod) do oom-killer; o código de saída é 137. O servidor ficou sem RAM. A correção adequada é usar um VPS maior, com 4 GB no mínimo. Como medida temporária, adicione swap e limite a cache do MongoDB com --wiredTigerCacheSizeGB 1 no respetivo command, mas a swap apenas adia o próximo OOM sob carga real:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

docker compose up falha com Error response from daemon: driver failed programming external connectivity ... bind: address already in use. Algo já está a usar a porta 3000, frequentemente um contentor Rocket.Chat anterior que não terminou corretamente ou outra aplicação. Encontre-o com sudo ss -ltnp | grep :3000, pare esse processo ou contentor, ou altere o lado do host do mapeamento para 127.0.0.1:3001:3000 e atualize proxy_pass no proxy para corresponder.

FAQ

O Rocket.Chat precisa mesmo de um replica set do MongoDB?

Sim, mesmo num único servidor com um nó de base de dados. O Rocket.Chat entrega mensagens em tempo real através de change streams do MongoDB. Os change streams só estão disponíveis em replica sets, e um mongod autónomo não pode abrir um. Não precisa de várias máquinas. Execute um único contentor MongoDB iniciado com --replSet rs0 e inicialize um conjunto com um membro usando rs.initiate(). Se ignorar esse passo, o driver nunca encontra um primary. O Rocket.Chat entra num ciclo de reinícios com MongoServerSelectionError: Server selection timed out e nunca termina o arranque.

Quanta RAM é necessária para um Rocket.Chat autoalojado?

Considere 4 GB como o mínimo prático e 8 GB para uma equipa com utilização intensa. O processo Node do Rocket.Chat usa cerca de 1 a 1.5 GB, e o MongoDB reserva aproximadamente metade da RAM restante para a cache WiredTiger. Num servidor com 2 GB, os dois entram em conflito e o out-of-memory killer termina mongod sob qualquer carga real. Os logs mostram Killed e o código de saída é 137. Dois GB só são suficientes para avaliar o software com alguns utilizadores de teste.

Como coloco o Rocket.Chat atrás de HTTPS?

Execute um reverse proxy no mesmo VPS. Esse proxy termina o TLS e encaminha as ligações para 127.0.0.1:3000. Defina ROOT_URL do contentor para o endereço público https://. O proxy tem de encaminhar os cabeçalhos de upgrade do WebSocket. Caso contrário, o início de sessão fica bloqueado. Certbot com nginx é a configuração mais simples para uma única aplicação. Traefik é mais prático se executar vários contentores atrás de um único proxy e quiser gerir certificados automaticamente.

Como faço uma cópia de segurança de um Rocket.Chat autoalojado?

Crie um dump consistente da base de dados com mongodump, em vez de copiar o volume: docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > backup.archive.gz. Esse arquivo contém utilizadores, canais, mensagens e definições. Também inclui os ficheiros carregados se mantiver o armazenamento em GridFS. Copie o arquivo para fora do servidor. Automatize a tarefa todas as noites com cron. Teste uma mongorestore num servidor descartável para confirmar que a reposição funciona realmente.

Como atualizo o Rocket.Chat sem incompatibilizar o MongoDB?

Atualize o Rocket.Chat uma versão principal de cada vez. O Rocket.Chat executa migrações no arranque e recusa saltar versões principais. Leia as notas de cada versão antes de alterar a tag da imagem fixada. Verifique as versões do MongoDB suportadas pela versão de destino com curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions. Ao atualizar o MongoDB, avance uma versão principal de cada vez e defina setFeatureCompatibilityVersion com confirm: true depois de cada etapa. Crie sempre uma mongodump primeiro.