Vaultwarden: Bitwarden self-hosted no Linux

Mascote do LinuxPro girando o volante de um cofre com o emblema do Vaultwarden, com notebook e celular sincronizando senhas e o cachorro caramelo deitado de guarda

Atualização (05/10/2026): guia revisado para a versão 1.37.3, de 13/09/2026. Entraram o comando de backup embutido, a exigência de volume persistente, o SSO nativo, as correções de segurança da 1.37.0 e um diagrama da instalação.

O Vaultwarden é um servidor compatível com os clientes oficiais do Bitwarden, escrito em Rust. Cabe num Raspberry Pi, consome pouquíssima memória e entrega no self-host recursos que no Bitwarden oficial pedem plano pago, como o autenticador TOTP integrado e o acesso de emergência. Não é o Bitwarden Inc.: é o projeto da comunidade (ex-bitwarden_rs), sob licença AGPL-3.0, hoje na 1.37.3.

Se você já tem um Linux na internet e não quer mandar o cofre para a nuvem de ninguém, este é o caminho curto: um container, HTTPS na frente e os apps oficiais apontando para o seu domínio.

O que é (e o que não é)

Os apps (Android, iOS, desktop, extensão, CLI) falam a API do Bitwarden, e o Vaultwarden implementa essa API. O cofre continua criptografado no cliente (zero-knowledge): os itens chegam ao servidor já cifrados com uma chave derivada da senha mestra, e o servidor não consegue lê-los.

  • Serve para você, a família, o homelab, um time pequeno. Roda em SQLite (padrão), MySQL ou PostgreSQL. No nosso teste, o container recém-iniciado e sem usuários ocupou cerca de 10 MiB de RAM.
  • Não serve para empresa que precisa de SOC 2, SLA e suporte da Bitwarden Inc. O projeto não tem auditoria formal equivalente. Você é o backup, o patch e o firewall.

Acompanhe as versões, porque os clientes oficiais evoluem rápido: a 1.37.0 é necessária para os clientes 2026.7.0 em diante, e a 1.37.2 para os 2026.8.0 em diante. A 1.37.0, de julho de 2026, também corrigiu um pacote de falhas de segurança (SSRF no endpoint de ícones, acesso a itens entre organizações, inundação de WebSocket sem autenticação, entre outras), e a 1.37.3 passou a revogar os tokens de “lembrar este dispositivo” do 2FA quando a senha ou o 2FA mudam. Desde a 1.35.0 (dezembro de 2025), o login único (SSO) via OpenID Connect é nativo, ativado com SSO_ENABLED. SCIM e Secrets Manager continuam exclusivos do Bitwarden oficial.

Subir com Docker e Caddy

A via recomendada pelo projeto é o container. O HTTPS é obrigatório: o web vault usa a Web Crypto API, que o navegador só libera em contexto seguro. O Caddy obtém e renova o certificado sozinho. (Se Docker ainda é novidade, tem o curso de Docker.)

Diagrama: clientes Bitwarden acessam por HTTPS o container do Caddy, que encaminha para o container do Vaultwarden; os dados ficam no volume vw-data, com db.sqlite3, rsa_key.pem, anexos, sends e config.json; o comando vaultwarden backup gera uma cópia do banco, que segue com o tar para uma cópia externa
O Caddy termina o TLS e só ele publica portas; o Vaultwarden fica na rede interna do Compose; o volume de dados é o que precisa de backup.

Gere o token do painel admin (Argon2) antes do compose. O comando pede a senha duas vezes e imprime o hash:

docker run --rm -it vaultwarden/server:1.37.3 /vaultwarden hash

Cole a string $argon2id$... no YAML. No Compose, cada $ vira $$.

mkdir -p /opt/vaultwarden && cd /opt/vaultwarden
# /opt/vaultwarden/compose.yaml
services:
  vaultwarden:
    image: vaultwarden/server:1.37.3
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.exemplo.com.br"
      SIGNUPS_ALLOWED: "true"
      ADMIN_TOKEN: "$$argon2id$$v=19$$m=65540,t=3,p=4$$COLE_O_HASH"
    volumes:
      - ./vw-data:/data

  caddy:
    image: caddy:2
    container_name: vw-caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - vaultwarden

volumes:
  caddy_data:
  caddy_config:
# /opt/vaultwarden/Caddyfile
vault.exemplo.com.br {
	encode zstd gzip
	reverse_proxy vaultwarden:80
}
# DNS do domínio → IP desta máquina, depois:
docker compose up -d
docker compose logs -f
curl -s https://vault.exemplo.com.br/alive

O /alive responde com a data e hora do servidor quando tudo está de pé. Não esqueça o volume ./vw-data:/data: sem um volume persistente, o Vaultwarden atual se recusa a iniciar e mostra No persistent volume! no log. É uma proteção para você não perder o cofre ao recriar o container.

Quem já tem nginx (ISPConfig, por exemplo) dispensa o serviço Caddy: publique o Vaultwarden só em 127.0.0.1:8000 e faça proxy com Let’s Encrypt no nginx. O WebSocket usa a mesma porta 80 do container; a antiga porta 3012 não é mais necessária.

Primeiro login e travar o cadastro

Abra https://vault.exemplo.com.br e crie a sua conta. Depois feche a porta:

SIGNUPS_ALLOWED: "false"
docker compose up -d

Convites posteriores saem do painel /admin, com o token que você gerou. Sem ADMIN_TOKEN, o painel nem existe — e é assim que deve ficar se você não for usá-lo. Se usar SSO, a 1.37.3 trouxe o SSO_SIGNUPS_ALLOWED para controlar à parte o cadastro por esse caminho.

Ligue o 2FA no cofre (TOTP ou FIDO2) no primeiro dia. É o mesmo app Bitwarden; a diferença é só o servidor.

Apontar os clientes oficiais

Em qualquer app Bitwarden, na tela de login: Self-hosted → cole https://vault.exemplo.com.br. Entre com o e-mail da conta que você criou. Extensão do navegador, celular e CLI (bw config server) usam o mesmo URL.

Não reporte bug do Vaultwarden no suporte da Bitwarden Inc. O README é explícito: issues e discussões vão para o GitHub e o Matrix do projeto.

Backup — se não tem, não tem cofre

O volume ./vw-data é o cofre: db.sqlite3, rsa_key.pem (assina os tokens de login), anexos, Sends e o config.json do painel admin. Copiar o arquivo do SQLite com o serviço rodando pode gerar uma cópia inconsistente; o próprio binário tem um comando que faz a cópia segura do banco, sem parar nada:

docker compose exec vaultwarden /vaultwarden backup
# Backup to 'data/db_20261005_170645.sqlite3' was successful

Um script diário que gera essa cópia, empacota o volume sem o banco “vivo” e limpa o temporário:

#!/bin/sh
# /usr/local/sbin/vw-backup
set -eu
cd /opt/vaultwarden
docker compose exec -T vaultwarden /vaultwarden backup
tar -czf "/backup/vw-$(date +%F).tar.gz" -C vw-data \
  --exclude='db.sqlite3*' --exclude='icon_cache' .
rm -f vw-data/db_*.sqlite3

Para restaurar, extraia o pacote num vw-data vazio, renomeie o db_AAAAMMDD_HHMMSS.sqlite3 para db.sqlite3 e suba o Compose. Guarde a cópia fora da máquina — outro disco, outro VPS, um bucket via rclone — e teste a restauração ao menos uma vez. O OnCalendar= do systemd resolve o agendamento se você não quiser cron.

Atualizando

Troque a tag da imagem no compose.yaml pela nova versão, faça o backup e recrie o container:

/usr/local/sbin/vw-backup
docker compose pull
docker compose up -d
docker compose logs --tail=30 vaultwarden

Fixar a versão (em vez de latest) deixa a atualização sob o seu controle e o rollback simples: basta voltar a tag. Leia as notas da release antes, principalmente quando mencionarem compatibilidade com uma nova versão dos clientes.

Referências

Um binário Rust, um volume e HTTPS. O cofre fica no hardware que você controla — e o app no bolso continua o mesmo.