Jugando con Docker: Crear un Contenedor de Bitwarden Usando Vaultwarden

Nota editorial: este artículo fue publicado originalmente en julio de 2024 y revisado en julio de 2026 para actualizar algunos aspectos técnicos e incorporar el criterio adquirido al desplegar y mantener Vaultwarden en mi laboratorio. La instalación sigue siendo válida, pero mi forma de entender un servicio tan crítico ha evolucionado.

No buscaba únicamente un gestor de contraseñas

Cuando empecé a probar Vaultwarden no buscaba simplemente instalar otra aplicación en Docker.

Quería comprender mejor cómo proteger uno de los activos más importantes de cualquier infraestructura: las credenciales.

Una contraseña permite acceder al correo, los servidores, los dominios, los servicios en la nube, los repositorios, los paneles de administración o los dispositivos de red. Por muchas medidas de seguridad que apliquemos, si las credenciales terminan comprometidas, una parte importante de esas defensas puede perder su eficacia.

Por eso un gestor de contraseñas no es una aplicación cualquiera. Se convierte en la llave que protege muchas otras llaves.

Vaultwarden me permitía desplegar ese servicio en mi propio laboratorio, mantener el control de la infraestructura y, sobre todo, entender el ciclo completo:

  • Cómo se instala.
  • Cómo se configura.
  • Cómo se publica o se mantiene dentro de una red privada.
  • Cómo se actualiza.
  • Cómo se protege.
  • Cómo se copia.
  • Y cómo se recupera cuando algo falla.

No fue una decisión ideológica ni una forma de demostrar que todo debe estar autoalojado.

Fue una decisión práctica y de aprendizaje.

Quería comprobar si realmente compensaba asumir la responsabilidad de mantener un servicio tan sensible.

Por qué Vaultwarden

Vaultwarden es una implementación alternativa y ligera del servidor compatible con Bitwarden, desarrollada en Rust y pensada especialmente para entornos donde se busca reducir el consumo de recursos sin renunciar a los clientes y extensiones del ecosistema de Bitwarden.

En mi caso encajaba bien por varias razones:

  • Podía desplegarlo fácilmente mediante Docker.
  • Tenía un consumo contenido para un laboratorio personal.
  • Era compatible con los clientes de Bitwarden que ya existen para navegadores, ordenadores y dispositivos móviles.
  • Podía integrarlo con el proxy inverso y las redes Docker que ya utilizaba.
  • Me permitía entender y controlar la infraestructura que sostenía el servicio.

No elegí Vaultwarden porque el servicio oficial de Bitwarden fuera una mala opción.

Para muchas personas, utilizar el servicio oficial será una decisión más sencilla, segura y razonable. No tendrán que ocuparse del servidor, las actualizaciones, las copias, el correo, los certificados ni la recuperación.

En mi caso quería aprender precisamente esa parte.

Autoalojar no significa únicamente tener más control. También significa aceptar más responsabilidad.

Antes de confiar, necesito probar

Mi laboratorio personal es el lugar donde pruebo las tecnologías antes de decidir si merecen formar parte de mi forma de trabajar.

No me basta con comprobar que una aplicación arranca y muestra una pantalla de acceso.

Necesito entender:

  • Qué dependencias introduce.
  • Dónde persiste los datos.
  • Qué ocurre al recrear el contenedor.
  • Cómo se actualiza.
  • Qué ocurre si desaparece el servidor.
  • Qué necesito para restaurarla en otra infraestructura.
  • Y qué superficie de exposición estoy creando.

Una tecnología no demuestra su valor únicamente cuando funciona.

También debe demostrar que puede mantenerse y recuperarse.

En un gestor de contraseñas esa exigencia es todavía mayor. Si el servicio falla, no estamos perdiendo una aplicación secundaria. Podemos estar perdiendo temporalmente el acceso organizado a una parte importante de nuestra identidad digital.

Qué vamos a montar

El despliegue utiliza:

  • Vaultwarden en Docker.
  • Un archivo .env separado para la configuración y los secretos.
  • Persistencia de datos en el directorio /data.
  • Una red Docker compartida con Caddy.
  • HTTPS mediante proxy inverso.
  • Registro cerrado después de crear los usuarios necesarios.
  • Autenticación multifactor.
  • Copias de seguridad que puedan restaurarse.

El patrón general será:

Cliente Bitwarden
 ↓
HTTPS / Caddy
 ↓
Red Docker privada
 ↓
Vaultwarden

No publicaré directamente el puerto interno de Vaultwarden en el host. Caddy se comunicará con el contenedor mediante una red Docker compartida.

Crear el entorno de trabajo

Creo un directorio independiente para mantener juntos la configuración, los datos y el archivo de Compose:

mkdir -p /opt/vaultwarden
cd /opt/vaultwarden
mkdir -p data

La estructura será sencilla:

/opt/vaultwarden/
├── docker-compose.yml
├── .env
└── data/

La carpeta data contendrá la información persistente de Vaultwarden. El contenedor puede recrearse; los datos no.

Separar la configuración sensible

Para evitar introducir secretos directamente en el archivo de Compose, utilizo un archivo .env:

DOMAIN=https://vault.tudominio.com
SIGNUPS_ALLOWED=true
INVITATIONS_ALLOWED=true
ADMIN_TOKEN=CAMBIA_ESTE_TOKEN
TZ=Europe/Madrid

SMTP_HOST=smtp.tudominio.com
[email protected]
SMTP_FROM_NAME=Vaultwarden
[email protected]
SMTP_PASSWORD=CAMBIA_ESTA_CONTRASEÑA
SMTP_SECURITY=starttls
SMTP_PORT=587

Después restrinjo sus permisos:

chmod 600 .env

El archivo .env contiene secretos y debe tratarse como tal. No debería subirse a un repositorio, enviarse sin protección ni permanecer incluido en copias sin cifrar.

Generar el token de administración

El panel de administración de Vaultwarden utiliza la variable ADMIN_TOKEN. Para generar un valor aleatorio:

openssl rand -base64 48

Actualmente es preferible utilizar un token protegido mediante Argon2, en lugar de mantenerlo como texto plano. Vaultwarden incluye mecanismos para generar y utilizar ese hash, y las versiones actuales advierten cuando el token está almacenado sin proteger.

El panel de administración no debería convertirse en otra puerta expuesta sin necesidad. Si no se utiliza, puede no activarse. Si se mantiene, debe recibir una protección acorde con su sensibilidad.

El archivo docker-compose.yml

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - "./data:/data"
    networks:
      - proxy

networks:
  proxy:
    external: true

Antes de levantar el servicio, la red externa debe existir:

docker network create proxy

Si ya la creamos para Caddy u otros servicios, Docker indicará que existe y no será necesario recrearla.

Vaultwarden y Caddy pueden estar definidos en proyectos Compose distintos y compartir esa misma red.

No publico ningún puerto de Vaultwarden en el host. El contenedor seguirá escuchando internamente, pero será Caddy quien reciba las peticiones y las dirija a vaultwarden:80.

Reducir puertos expuestos no convierte por sí solo el servicio en seguro, pero evita accesos directos innecesarios y simplifica el punto desde el que controlo la publicación.

Configurar Caddy

En el Caddyfile añado el proxy correspondiente:

vault.tudominio.com {
    reverse_proxy vaultwarden:80
}

Caddy y Vaultwarden deben compartir la red proxy.

Dentro de Docker, localhost representa al propio contenedor. Por eso no utilizo:

reverse_proxy localhost:80

Utilizo el nombre del servicio dentro de la red Docker:

reverse_proxy vaultwarden:80

Después valido y recargo la configuración de Caddy:

docker compose exec -w /etc/caddy caddy caddy validate
docker compose exec -w /etc/caddy caddy caddy reload

Si Caddy se encuentra en otro proyecto Compose, ejecutaré esos comandos desde su directorio o utilizaré el nombre real de su contenedor.

Desplegar Vaultwarden

docker compose up -d
docker ps
docker logs vaultwarden

Antes de dar el servicio por terminado, compruebo:

  • Que el contenedor permanece en ejecución.
  • Que el dominio resuelve correctamente.
  • Que Caddy obtiene y sirve el certificado.
  • Que puedo crear el primer usuario.
  • Que los clientes pueden iniciar sesión y sincronizar.
  • Que el correo funciona si voy a utilizar invitaciones o recuperación.

Cuando los usuarios necesarios ya existen, cierro el registro:

SIGNUPS_ALLOWED=false

Después recreo el servicio para aplicar el cambio:

docker compose up -d

Correo SMTP: no es un detalle secundario

Configurar SMTP permite enviar invitaciones, verificar direcciones y gestionar determinados avisos.

En un servicio de este tipo no conviene dejar el correo para el final como si fuera un complemento. Forma parte del funcionamiento y de la capacidad de recuperación.

Después de configurar las variables, pruebo el envío desde el panel de administración y reviso los registros si falla:

docker logs vaultwarden

Los problemas más habituales suelen estar relacionados con:

  • Puerto SMTP incorrecto.
  • Tipo de seguridad mal configurado.
  • Credenciales incorrectas.
  • Restricciones del proveedor.
  • Dirección remitente no permitida.

El panel de administración

Con ADMIN_TOKEN configurado, el panel está disponible en:

https://vault.tudominio.com/admin

Desde ahí pueden revisarse distintos parámetros de la instancia y probar la configuración SMTP.

Pero disponer de un panel cómodo no significa que deba permanecer expuesto sin más.

Puede protegerse adicionalmente desde Caddy, restringirse por dirección IP o mantenerse accesible únicamente desde una red privada o una VPN.

También puede no habilitarse si no resulta necesario.

Autenticación multifactor

Una contraseña maestra fuerte es imprescindible, pero no debería ser la única barrera de acceso.

Activo autenticación multifactor siempre que sea posible. Vaultwarden permite utilizar, entre otros mecanismos:

  • Aplicaciones TOTP.
  • Llaves de seguridad compatibles con FIDO2/WebAuthn.
  • Códigos de recuperación.

Los códigos de recuperación deben almacenarse fuera del propio gestor. Guardarlos únicamente dentro de Vaultwarden sería como guardar la llave de emergencia dentro de la caja que intentamos abrir.

Publicarlo con Caddy o acceder por VPN

Vaultwarden necesita ser accesible desde los dispositivos que deben sincronizar sus credenciales. Eso no significa que exista una única forma correcta de hacerlo.

Una VPN puede ser la mejor opción cuando:

  • Los usuarios y dispositivos pueden conectarse siempre a la red privada.
  • Queremos minimizar la exposición directa a Internet.
  • Podemos aceptar que el servicio solo funcione después de establecer la VPN.

Publicarlo mediante Caddy puede resultar más cómodo cuando necesitamos acceso directo desde distintos dispositivos y ubicaciones, pero exige evaluar cuidadosamente la exposición y aplicar controles adicionales.

Entre esos controles se encuentran:

  • HTTPS correctamente configurado.
  • Registro cerrado.
  • Contraseñas maestras fuertes.
  • Autenticación multifactor.
  • Actualizaciones controladas.
  • Monitorización.
  • Protección del panel de administración.
  • Copias y restauraciones probadas.
  • Restricciones adicionales de acceso cuando tengan sentido.

No existe una respuesta universal.

La decisión depende del contexto, los usuarios, la disponibilidad necesaria y el nivel de riesgo que estemos dispuestos a asumir.

Cuando una tecnología protege un activo crítico, la pregunta no debería ser únicamente «¿cómo puedo publicarla?», sino «¿qué nivel de exposición estoy dispuesto a aceptar y por qué?».

HTTPS cifra la comunicación. No elimina por sí solo los riesgos del servicio, del servidor, de las credenciales o de una configuración incorrecta.

Las copias de seguridad son parte del servicio

Instalar Vaultwarden es sencillo. Ser capaz de recuperarlo es lo que permite confiar en el despliegue.

La información persistente se encuentra en el directorio data. También necesito conservar:

  • docker-compose.yml.
  • .env.
  • La configuración de Caddy relacionada.
  • La documentación necesaria para reconstruir el servicio.

Un ejemplo básico de copia sería:

cd /opt
tar -czf vaultwarden-backup-$(date +%F).tar.gz vaultwarden

Pero crear un archivo comprimido no resuelve por sí solo el problema.

Ese archivo incluye secretos y debe protegerse adecuadamente. Además, una copia que nunca se ha restaurado es solo una esperanza.

La prueba real consiste en reconstruir el servicio en otro entorno, recuperar los datos y comprobar que los clientes pueden volver a acceder y sincronizar.

Cuando autoalojamos un gestor de contraseñas también asumimos la responsabilidad de poder levantarlo en otra infraestructura si el servidor original deja de estar disponible.

Esa capacidad de recuperación pesa tanto como la configuración inicial.

Actualizar sin perder el control

Antes de actualizar hago una copia de los datos y reviso las notas de versión.

Después descargo la nueva imagen y recreo el servicio:

docker compose pull
docker compose up -d
docker logs vaultwarden

La actualización no termina cuando Docker informa de que el contenedor está en ejecución.

Compruebo:

  • El acceso web.
  • La sincronización de los clientes.
  • El inicio de sesión.
  • El segundo factor.
  • El envío de correo.
  • El panel de administración, si está habilitado.
  • Los registros del servicio.

En un servicio crítico prefiero controlar cuándo actualizo y comprobar el resultado, en lugar de asumir que una imagen nueva será siempre transparente.

Errores que revisaría primero

El contenedor funciona, pero el dominio no abre

Revisaría DNS, Caddy, la red Docker compartida y los registros de ambos contenedores.

Caddy devuelve un error al conectar

Comprobaría que ambos servicios comparten la red proxy y que el destino utilizado es vaultwarden:80, no localhost.

Los usuarios no reciben correos

Revisaría las variables SMTP, el puerto, el cifrado, el remitente permitido y los registros de Vaultwarden.

El panel de administración no aparece

Debe existir un ADMIN_TOKEN válido y el contenedor debe haber cargado la configuración actual.

Una actualización recrea el contenedor y desaparecen los datos

Eso indica que la persistencia no estaba correctamente configurada o que se inició otro contenedor con una ruta distinta. La carpeta data debe conservarse y formar parte de las copias.

El servicio tiene HTTPS y se considera automáticamente seguro

El certificado protege la comunicación. La seguridad real depende también de la autenticación, la exposición, las actualizaciones, el servidor, las copias y la capacidad de detectar y responder a un problema.

Mi criterio después de desplegarlo

Vaultwarden me sigue pareciendo una solución muy interesante para un laboratorio personal o para usuarios que entienden la responsabilidad que están asumiendo.

Su ligereza, la compatibilidad con los clientes de Bitwarden y la facilidad de despliegue mediante Docker permiten construir un servicio muy completo con pocos recursos.

Pero no lo recomendaría automáticamente a todo el mundo.

Si alguien no quiere ocuparse de actualizaciones, monitorización, certificados, correo, copias y restauraciones, el servicio oficial de Bitwarden puede ser una decisión mejor.

Autoalojar no consiste únicamente en controlar dónde están los datos.

Consiste en aceptar que, si algo falla, la responsabilidad de recuperarlos también es tuya.

En mi caso, desplegar Vaultwarden me permitió comprender mucho mejor qué implica proteger uno de los activos más importantes de cualquier infraestructura: las credenciales.

La herramienta es importante, pero el criterio con el que se instala, se expone, se mantiene y se recupera lo es todavía más.

Contenido relacionado

Fuentes técnicas

Continúa leyendo

Corre modelos de IA locales en tu homelab con Ollama

¿Quieres seguir explorando?

Puedes descubrir más artículos, seguir mis publicaciones en LinkedIn o escribirme.

Deja un comentario

Julio Rodas

Tecnología sin humo. Cómo pienso, pruebo y tomo decisiones tecnológicas.

Cómo trabajo  ·  Sobre mí  ·  Artículos  ·  Contacto

Invítame a un café

Aviso Legal  ·  Política de Privacidad  ·  Política de Cookies

Las opiniones expresadas en esta web son personales y no representan necesariamente la posición de mi empleador ni de ninguna organización con la que mantenga una relación profesional.

© 2026 Julio Rodas