Autoalojar Vaultwarden en un VPS con Docker Compose
Despliega un gestor de contraseñas Vaultwarden fortificado en tu VPS. Docker Compose con contenedores de solo lectura, fail2ban, SMTP para 2FA, copias de seguridad y restauración, y acceso de emergencia.
Vaultwarden almacena todas las contraseñas que posees. Un despliegue descuidado es peor que no tener ninguno. Este tutorial configura Vaultwarden en un VPS con contenedores Docker fortificados, fail2ban, SMTP para autenticación de dos factores y un procedimiento de copia de seguridad y restauración.
Asumimos que Docker Engine y un reverse proxy (Nginx o Caddy) ya están funcionando en tu servidor. Si no es así, empieza con Docker en producción en un VPS: qué falla y cómo solucionarlo y Cómo configurar Nginx como reverse proxy.
¿Qué es Vaultwarden y en qué se diferencia de Bitwarden?
Vaultwarden es una reimplementación en Rust de la API del servidor Bitwarden. Se ejecuta como un único contenedor Docker, usa SQLite por defecto, consume alrededor de 50 MB de RAM en reposo y es totalmente compatible con todos los clientes oficiales de Bitwarden (extensiones de navegador, apps móviles, escritorio, CLI). El despliegue autoalojado oficial de Bitwarden requiere más de 11 contenedores y al menos 4 GB de RAM.
| Vaultwarden | Bitwarden autoalojado | |
|---|---|---|
| Lenguaje | Rust | C# (.NET) |
| Contenedores | 1 | 11+ |
| RAM (reposo) | ~50 MB | ~2-4 GB |
| Base de datos | SQLite (defecto), MySQL, PostgreSQL | MSSQL (obligatorio) |
| Clientes Bitwarden | Compatibilidad total | Compatibilidad total |
| SSO (OpenID Connect) | Desde la versión 1.35.0 | Solo plan Enterprise |
| Soporte oficial | Comunidad | Bitwarden Inc. |
| Licencia | AGPL-3.0 | Propietaria (SSPL para el servidor) |
Vaultwarden se llamaba anteriormente bitwarden_rs. Si encuentras ese nombre en guías antiguas, se refiere al mismo proyecto.
¿Cómo despliego Vaultwarden con Docker Compose en un VPS?
Crea una estructura de directorios para los datos y la configuración de Vaultwarden. Todos los datos persistentes residen en un único directorio que respaldarás más adelante.
mkdir -p /opt/vaultwarden/data
cd /opt/vaultwarden
Genera un token de administración hasheado con argon2. Nunca almacenes el token de admin en texto plano.
docker run --rm -it vaultwarden/server:1.35.4 /vaultwarden hash
El comando pide una contraseña dos veces y luego muestra una cadena PHC argon2id:
Generate an Argon2id PHC string using the 'bitwarden' preset:
Password:
Confirm Password:
ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$S2mMOA8VnTtIOb3J8Gj9Jw$9cZ0YIKmGxfWEqSMKFMbORkBiW7hMGCls3SXAFXSIVE'
Guarda esa cadena. La necesitarás en el archivo de entorno.
Crea el archivo de secretos con permisos restringidos:
touch /opt/vaultwarden/.env
chmod 600 /opt/vaultwarden/.env
Edita /opt/vaultwarden/.env con tus valores:
DOMAIN=https://vault.example.com
ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$your-hash-here'
SIGNUPS_ALLOWED=true
INVITATIONS_ALLOWED=true
EMERGENCY_ACCESS_ALLOWED=true
ORG_CREATION_USERS=all
SHOW_PASSWORD_HINT=false
IP_HEADER=X-Real-IP
LOG_FILE=/data/vaultwarden.log
LOG_LEVEL=warn
SMTP_HOST=smtp.example.com
SMTP_FROM=vault@example.com
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=vault@example.com
SMTP_PASSWORD=your-smtp-password
SHOW_PASSWORD_HINT=false evita la filtración de pistas a cualquiera que conozca un nombre de usuario. IP_HEADER=X-Real-IP indica a Vaultwarden que lea la IP del cliente desde la cabecera de tu reverse proxy, necesario para que fail2ban bloquee la dirección correcta.
Ahora crea el archivo Compose.
¿Cómo fortifico el contenedor Docker de Vaultwarden?
El archivo Compose a continuación fija la versión de la imagen, elimina todas las capabilities de Linux, habilita un sistema de archivos raíz de solo lectura, bloquea la escalada de privilegios y establece límites de memoria. Estos son los valores por defecto de esta guía, no complementos opcionales.
Crea /opt/vaultwarden/compose.yaml:
services:
vaultwarden:
image: vaultwarden/server:1.35.4
container_name: vaultwarden
restart: unless-stopped
env_file: .env
user: "1000:1000"
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
read_only: true
tmpfs:
- /tmp
volumes:
- ./data:/data
ports:
- "127.0.0.1:8080:80"
deploy:
resources:
limits:
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/alive"]
interval: 30s
timeout: 5s
retries: 3
user: "1000:1000"ejecuta el proceso como usuario no-root dentro del contenedor. Debes ajustar la propiedad del directorio de datos:chown -R 1000:1000 /opt/vaultwarden/data.cap_drop: ALLelimina todas las capabilities de Linux. Vaultwarden no necesita ninguna porque escucha en el puerto 80 dentro del contenedor (un puerto no privilegiado en este contexto ya que Docker gestiona el mapeo).read_only: trueimpide que el contenedor escriba en cualquier lugar excepto en los volúmenes montados explícitamente y tmpfs. Si algo explota Vaultwarden, no puede escribir en el sistema de archivos del contenedor.ports: "127.0.0.1:8080:80"vincula solo a localhost. El reverse proxy gestiona el tráfico externo. Nunca expongas Vaultwarden directamente a Internet.deploy.resources.limits.memory: 512Mevita que un proceso descontrolado consuma toda la RAM del servidor. Vaultwarden usa ~50 MB en reposo y ~100-150 MB bajo carga. 512 MB dan margen de sobra.
Corrige la propiedad del directorio de datos e inicia el contenedor:
chown -R 1000:1000 /opt/vaultwarden/data
docker compose up -d
[+] Running 1/1
✔ Container vaultwarden Started
Comprueba el estado del contenedor:
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
vaultwarden vaultwarden/server:1.35.4 "/start.sh" vaultwarden Up 30 seconds (healthy) 127.0.0.1:8080->80/tcp
El estado (healthy) significa que el healthcheck pasó. Revisa los logs en busca de errores de inicio:
docker compose logs --tail 20
Los logs muestran Vaultwarden arrancando en el puerto 80 dentro del contenedor, sin errores.
Configuración del reverse proxy
Tu reverse proxy reenvía el tráfico HTTPS a 127.0.0.1:8080. Aquí tienes un bloque de servidor Nginx mínimo:
server {
listen 443 ssl;
http2 on;
server_name vault.example.com;
ssl_certificate /etc/letsencrypt/live/vault.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vault.example.com/privkey.pem;
client_max_body_size 525M;
server_tokens off;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
client_max_body_size 525M permite la subida de archivos adjuntos hasta el límite de Bitwarden. server_tokens off oculta la versión de Nginx en las respuestas, ya que la divulgación de versión ayuda a los atacantes a apuntar a vulnerabilidades conocidas.
Desde Vaultwarden 1.29.0, el tráfico WebSocket se sirve en el mismo puerto que HTTP. No se necesita una ruta proxy separada para /notifications/hub. Si ves WEBSOCKET_ENABLED en tutoriales antiguos, ignóralo. Esa variable se depreció en 1.29.0 y se eliminó en 1.31.0.
Para detalles de configuración de Nginx, consulta Cómo configurar Nginx como reverse proxy y Configurar SSL/TLS de Let's Encrypt para Nginx en Debian 12 y Ubuntu 24.04.
¿Cómo configuro el correo SMTP para Vaultwarden?
Vaultwarden necesita SMTP para enviar códigos de verificación por correo, emails de configuración 2FA, invitaciones de organización y notificaciones de acceso de emergencia. Sin SMTP, funciones como el registro por invitación, 2FA por email y acceso de emergencia no funcionan.
Las variables de entorno principales son SMTP_HOST, SMTP_PORT, SMTP_SECURITY, SMTP_USERNAME, SMTP_PASSWORD y SMTP_FROM. Usa SMTP_PORT=587 con SMTP_SECURITY=starttls para la mayoría de proveedores, o SMTP_PORT=465 con SMTP_SECURITY=force_tls para TLS implícito.
Estas variables ya están incluidas en el archivo .env anterior. Después de iniciar el contenedor, prueba el envío de correo: inicia sesión en la bóveda web en https://vault.example.com, crea tu cuenta, ve a Settings > Security > Two-step Login y activa la 2FA por email. Si recibes el código de verificación, SMTP funciona.
Revisa los logs si el envío falla:
docker compose logs | grep -i smtp
Problemas frecuentes:
- Fallo de autenticación: comprueba
SMTP_USERNAMEySMTP_PASSWORD. Los caracteres especiales en la contraseña pueden necesitar comillas simples en el archivo.env. - Conexión rechazada en el puerto 587: algunos proveedores de VPS bloquean los puertos salientes 25 y 587 por defecto. Consulta con tu proveedor o prueba el puerto 465 con
force_tls. - Error de certificado: el certificado TLS del servidor SMTP debe ser válido. Los certificados autofirmados requieren
SMTP_ACCEPT_INVALID_CERTS=true(no recomendado en producción).
| Variable | Propósito | Ejemplo |
|---|---|---|
SMTP_HOST |
Nombre del servidor de correo | smtp.example.com |
SMTP_PORT |
Puerto de conexión | 587 |
SMTP_SECURITY |
Método TLS | starttls o force_tls |
SMTP_FROM |
Dirección del remitente | vault@example.com |
SMTP_USERNAME |
Usuario de autenticación | vault@example.com |
SMTP_PASSWORD |
Contraseña de autenticación | (almacenada en .env, chmod 600) |
SMTP_AUTH_MECHANISM |
Tipo de autenticación (opcional) | Login |
¿Cómo protejo el panel de administración de Vaultwarden?
El panel de administración en /admin permite gestionar usuarios, ver la configuración y cambiar ajustes. Está protegido por el ADMIN_TOKEN que generaste antes. El hash argon2 significa que el token sin procesar nunca se almacena en tu archivo .env. Aunque alguien lea el archivo, obtiene un hash, no la contraseña.
Después de la configuración inicial (creación de cuenta, configuración SMTP, desactivación de registros), tienes dos opciones:
Opción 1: Desactivar el panel de administración por completo. Elimina o comenta ADMIN_TOKEN en .env y reinicia:
docker compose down && docker compose up -d
Sin ADMIN_TOKEN definido, el endpoint /admin devuelve un 404. Es la opción más segura para despliegues de un solo usuario.
Opción 2: Restringir el acceso mediante el reverse proxy. Mantén el panel activo pero bloquea el acceso externo:
location /admin {
allow 127.0.0.1;
deny all;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Accede al panel de administración a través de un túnel SSH cuando lo necesites:
ssh -L 8888:127.0.0.1:443 user@your-vps
Luego abre https://127.0.0.1:8888/admin en tu navegador.
Desactivar el registro público
Una vez que tu cuenta existe, desactiva los registros abiertos. Edita /opt/vaultwarden/.env:
SIGNUPS_ALLOWED=false
Reinicia el contenedor:
cd /opt/vaultwarden && docker compose down && docker compose up -d
Los nuevos usuarios aún pueden unirse mediante invitaciones de organización si INVITATIONS_ALLOWED=true. Esto te permite añadir miembros al equipo sin abrir el registro a todo el mundo.
¿Cómo configuro fail2ban para Vaultwarden en Docker?
Fail2ban monitoriza el archivo de logs de Vaultwarden en busca de intentos de inicio de sesión fallidos y bloquea las IPs infractoras. Como Vaultwarden se ejecuta en Docker, la regla de bloqueo debe apuntar a la cadena iptables DOCKER-USER. Las reglas de la cadena INPUT estándar no afectan al tráfico enrutado por Docker.
El contenedor Vaultwarden escribe los logs en /opt/vaultwarden/data/vaultwarden.log (mapeado desde /data/vaultwarden.log dentro del contenedor) porque definimos LOG_FILE=/data/vaultwarden.log en el entorno.
Para una guía detallada de instalación de fail2ban, consulta Instalar y configurar Fail2Ban en un VPS Linux.
Filtro de inicio de sesión
Crea /etc/fail2ban/filter.d/vaultwarden.local:
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =
Filtro del panel de administración
Crea /etc/fail2ban/filter.d/vaultwarden-admin.local:
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*?Invalid admin token\. IP: <ADDR>.*$
ignoreregex =
Configuración del jail
Crea /etc/fail2ban/jail.d/vaultwarden.local:
[vaultwarden]
enabled = true
port = http,https
filter = vaultwarden
action = iptables-allports[name=vaultwarden, chain=DOCKER-USER]
logpath = /opt/vaultwarden/data/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
backend = pyinotify
[vaultwarden-admin]
enabled = true
port = http,https
filter = vaultwarden-admin
action = iptables-allports[name=vaultwarden-admin, chain=DOCKER-USER]
logpath = /opt/vaultwarden/data/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
backend = pyinotify
| Parámetro | Valor | Por qué |
|---|---|---|
chain |
DOCKER-USER |
Docker sortea la cadena INPUT. Las reglas deben ir en DOCKER-USER para afectar al tráfico de contenedores. |
maxretry |
3 |
Tres intentos fallidos activan el bloqueo. Un usuario legítimo rara vez falla más de dos veces. |
bantime |
14400 |
Bloqueo de cuatro horas. Suficiente para disuadir la fuerza bruta, no tanto como para bloquear permanentemente a un usuario legítimo que tecleó mal. |
findtime |
14400 |
Cuenta los fallos dentro de una ventana de cuatro horas. |
backend |
pyinotify |
Monitorización de logs basada en archivos. El backend systemd por defecto no puede leer archivos de log de contenedores Docker. |
Reinicia fail2ban y comprueba el jail:
systemctl restart fail2ban
fail2ban-client status vaultwarden
Status for the jail: vaultwarden
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /opt/vaultwarden/data/vaultwarden.log
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
Prueba la regex contra el formato de log real:
fail2ban-regex /opt/vaultwarden/data/vaultwarden.log /etc/fail2ban/filter.d/vaultwarden.local
Si aún no existen intentos fallidos, la salida muestra 0 matched. Es lo esperado. Provoca un inicio de sesión fallido a través de la bóveda web y vuelve a ejecutar para confirmar que la regex coincide.
¿Cómo conecto las extensiones del navegador y las apps móviles a Vaultwarden?
Todos los clientes oficiales de Bitwarden funcionan con Vaultwarden. El único cambio es apuntarlos a la URL de tu servidor en lugar de bitwarden.com.
Extensión del navegador (Chrome, Firefox, Safari):
- Instala la extensión Bitwarden desde la tienda de complementos de tu navegador
- En la pantalla de inicio de sesión, haz clic en el icono del engranaje (o «Self-hosted» en versiones recientes)
- Establece Server URL en
https://vault.example.com - Guarda e inicia sesión con tus credenciales
App móvil (iOS, Android):
- Instala la app Bitwarden desde App Store o Google Play
- Antes de iniciar sesión, pulsa el icono del engranaje en la pantalla de inicio de sesión
- Establece Server URL en
https://vault.example.com - Guarda e inicia sesión
App de escritorio:
- Antes de iniciar sesión, haz clic en el icono del engranaje
- Establece Server URL en
https://vault.example.com
CLI:
bw config server https://vault.example.com
bw login
Todos los clientes se sincronizan a través de tu instancia Vaultwarden. Los datos de la bóveda nunca pasan por los servidores de Bitwarden.
¿Cómo configuro el acceso de emergencia en Vaultwarden?
El acceso de emergencia permite que un contacto de confianza acceda a tu bóveda o la tome bajo su control si no estás disponible. Requiere que SMTP esté configurado porque Vaultwarden envía correos de notificación durante el proceso.
Confirma que la función está habilitada en tu .env:
EMERGENCY_ACCESS_ALLOWED=true
Configurar un contacto de confianza:
- Inicia sesión en la bóveda web en
https://vault.example.com - Ve a Settings > Emergency Access
- Haz clic en Add emergency contact
- Introduce el correo de la persona de confianza (debe tener cuenta en tu instancia Vaultwarden)
- Elige el nivel de acceso:
- View: el contacto puede ver los elementos de tu bóveda (solo lectura)
- Takeover: el contacto puede restablecer tu contraseña maestra y tomar el control total
- Establece el tiempo de espera (1 a 90 días). Es el plazo entre la solicitud de acceso del contacto y la obtención efectiva. Recibes una notificación por correo y puedes rechazar la solicitud durante ese período.
- Haz clic en Save
El contacto de confianza recibe un correo de invitación. Tras aceptar, aparece como contacto de emergencia pendiente. El tiempo de espera funciona como un mecanismo de seguridad: si no respondes dentro de los días configurados, el acceso se concede automáticamente.
Para una bóveda personal, 7 días de espera con acceso View es razonable. Para infraestructura de equipo compartida, considera tiempos más cortos.
¿Cómo hago copias de seguridad y restauro una instancia Vaultwarden?
Vaultwarden almacena todo en el directorio /data: la base de datos SQLite (db.sqlite3), archivos adjuntos, caché de iconos y configuración. Una copia de seguridad correcta captura todo esto de forma consistente.
La base de datos SQLite debe respaldarse con sqlite3 .backup, no copiando el archivo directamente. Copiar un archivo SQLite en uso puede producir una copia corrupta si ocurre una escritura durante la copia. El comando .backup crea una instantánea consistente.
| Qué respaldar | Ubicación | Método | Frecuencia |
|---|---|---|---|
| Base de datos SQLite | /opt/vaultwarden/data/db.sqlite3 |
sqlite3 .backup |
Diaria |
| Adjuntos | /opt/vaultwarden/data/attachments/ |
rsync o cp -a |
Diaria |
| Caché de iconos | /opt/vaultwarden/data/icon_cache/ |
Omitir (se regenera automáticamente) | - |
| Archivo de entorno | /opt/vaultwarden/.env |
cp |
Al modificar |
| Archivo Compose | /opt/vaultwarden/compose.yaml |
cp |
Al modificar |
Script de copia de seguridad
Para copias automatizadas, el script usa age con un archivo de clave de destinatario. Esto evita solicitudes interactivas de frase de paso para que el script pueda ejecutarse desde cron.
Genera un par de claves (una sola vez):
apt install age
age-keygen -o /opt/vaultwarden/backup-key.txt
chmod 600 /opt/vaultwarden/backup-key.txt
El comando muestra la clave pública en stdout. Guárdala en un archivo de destinatario:
age-keygen -y /opt/vaultwarden/backup-key.txt > /opt/vaultwarden/backup-key.pub
Guarda una copia de backup-key.txt (la clave privada) fuera del servidor. La necesitas para descifrar las copias de seguridad. Si pierdes esta clave, tus copias cifradas serán irrecuperables.
Crea /opt/vaultwarden/backup.sh:
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/opt/vaultwarden/backups"
DATA_DIR="/opt/vaultwarden/data"
DATE=$(date +%Y-%m-%d_%H%M)
BACKUP_FILE="${BACKUP_DIR}/vaultwarden-${DATE}.tar"
RECIPIENT="/opt/vaultwarden/backup-key.pub"
mkdir -p "${BACKUP_DIR}"
# Back up SQLite database consistently
sqlite3 "${DATA_DIR}/db.sqlite3" ".backup '${BACKUP_DIR}/db-${DATE}.sqlite3'"
# Package database + attachments + config
tar cf "${BACKUP_FILE}" \
-C "${BACKUP_DIR}" "db-${DATE}.sqlite3" \
-C "${DATA_DIR}" attachments/ \
-C /opt/vaultwarden .env compose.yaml 2>/dev/null || true
# Encrypt with age recipient key (non-interactive)
age -R "${RECIPIENT}" -o "${BACKUP_FILE}.age" "${BACKUP_FILE}"
# Clean up unencrypted files
rm -f "${BACKUP_FILE}" "${BACKUP_DIR}/db-${DATE}.sqlite3"
# Remove backups older than 30 days
find "${BACKUP_DIR}" -name "*.age" -mtime +30 -delete
echo "Backup complete: ${BACKUP_FILE}.age"
chmod 700 /opt/vaultwarden/backup.sh
Para copias de seguridad diarias automatizadas, añade una tarea cron:
echo "0 3 * * * root /opt/vaultwarden/backup.sh >> /var/log/vaultwarden-backup.log 2>&1" > /etc/cron.d/vaultwarden-backup
chmod 644 /etc/cron.d/vaultwarden-backup
Para copias fuera del servidor, envía la copia cifrada a un servidor remoto o almacenamiento de objetos:
rsync -az /opt/vaultwarden/backups/*.age backup-user@remote-server:/backups/vaultwarden/
Procedimiento de restauración
Una copia de seguridad que nunca has restaurado es una copia en la que no puedes confiar. El procedimiento completo:
# Stop the container
cd /opt/vaultwarden && docker compose down
# Decrypt the backup
age -d -i /opt/vaultwarden/backup-key.txt -o /tmp/vaultwarden-restore.tar /opt/vaultwarden/backups/vaultwarden-2026-03-20_0300.tar.age
# Extract
mkdir -p /tmp/vaultwarden-restore
tar xf /tmp/vaultwarden-restore.tar -C /tmp/vaultwarden-restore
# Replace the database (delete WAL files first)
rm -f /opt/vaultwarden/data/db.sqlite3-wal /opt/vaultwarden/data/db.sqlite3-shm
cp /tmp/vaultwarden-restore/db-2026-03-20_0300.sqlite3 /opt/vaultwarden/data/db.sqlite3
chown 1000:1000 /opt/vaultwarden/data/db.sqlite3
# Restore attachments
rsync -a /tmp/vaultwarden-restore/attachments/ /opt/vaultwarden/data/attachments/
chown -R 1000:1000 /opt/vaultwarden/data/attachments/
# Start the container
docker compose up -d
# Clean up
rm -rf /tmp/vaultwarden-restore /tmp/vaultwarden-restore.tar
Debes eliminar los archivos WAL (Write-Ahead Log) y SHM antes de restaurar. Estos archivos pertenecen al estado anterior de la base de datos. Iniciar Vaultwarden con una base de datos restaurada pero archivos WAL obsoletos corrompe los datos.
Tras la restauración, inicia sesión en la bóveda web y confirma que tus entradas están presentes.
¿Cómo actualizo Vaultwarden de forma segura?
Fija tu imagen a un tag de versión específico (usamos 1.35.4). Nunca uses :latest en producción porque no puedes rastrear qué cambió ni revertir de forma fiable.
Para actualizar:
cd /opt/vaultwarden
# Back up first
./backup.sh
# Pull the new version
docker compose pull
# Recreate the container
docker compose up -d
Antes de hacer pull, edita compose.yaml para cambiar el tag de la imagen a la nueva versión. Consulta las notas de la versión en busca de cambios que rompan compatibilidad.
docker compose logs --tail 30
Si la actualización causa problemas, restaura desde tu copia de seguridad:
# Revert compose.yaml to the old version tag
docker compose down
# Follow the restore procedure above
docker compose up -d
¿Algo salió mal?
El contenedor se detiene inmediatamente:
docker compose logs
Busca errores de permisos. La directiva user: 1000:1000 requiere propiedad correspondiente en /opt/vaultwarden/data. Ejecuta chown -R 1000:1000 /opt/vaultwarden/data e inténtalo de nuevo.
No se puede acceder a la bóveda web:
Comprueba que el reverse proxy está reenviando a 127.0.0.1:8080:
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/alive
Una respuesta 200 significa que Vaultwarden está funcionando. El problema está en la configuración de tu reverse proxy.
Fail2ban no bloquea:
fail2ban-regex /opt/vaultwarden/data/vaultwarden.log /etc/fail2ban/filter.d/vaultwarden.local
Si la regex no coincide con ninguna línea, comprueba que LOG_FILE=/data/vaultwarden.log esté definido en .env y que el archivo de log exista en /opt/vaultwarden/data/vaultwarden.log.
Los correos no se envían:
docker compose logs | grep -i "smtp\|mail\|email"
Verifica que tu VPS permite conexiones salientes en el puerto SMTP:
nc -zv smtp.example.com 587
Errores de base de datos bloqueada:
Esto puede ocurrir si copias el archivo de base de datos mientras Vaultwarden está en ejecución. Usa siempre sqlite3 .backup para las copias de seguridad y detén siempre el contenedor antes de restaurar.
Ubicación de los logs:
# Application logs
docker compose logs -f
# Log file (if LOG_FILE is set)
tail -f /opt/vaultwarden/data/vaultwarden.log
# Fail2ban logs
journalctl -u fail2ban -f
Para seguridad de contenedores Docker más allá de lo que cubre este tutorial, consulta Hardening de seguridad en Docker: modo rootless, seccomp y AppArmor en un VPS. Para estrategias de copia de seguridad de todos tus servicios Docker, consulta Copia de seguridad y restauración de volúmenes Docker en un VPS.
Copyright 2026 Virtua.Cloud. Todos los derechos reservados. Este contenido es una obra original del equipo de Virtua.Cloud. La reproducción, republicación o redistribución sin permiso escrito está prohibida.
¿Listo para probarlo?
Despliega tu propio servidor en segundos. Linux, Windows o FreeBSD.
Ver planes VPS