Vaultwarden 1.37.5 no arranca cuando una variable de tu .env vale 0 en un límite de peticiones, en DATABASE_TIMEOUT o en DATABASE_IDLE_TIMEOUT, o cuando un horario de purga no es una expresión cron válida: el contenedor sale con código 12 y Docker lo reinicia en bucle. El arreglo es poner un valor válido en cada variable que nombra el registro, una por arranque, y comprobar el .env antes de actualizar. Lo reproduje el 2 de noviembre de 2026 pasando de vaultwarden/server:1.37.4 a 1.37.5 en Linux arm64 con Docker 29.5.2 y Compose v2.40.3. Tienes la versión en inglés de esta guía.

Puntos clave

  • La 1.37.5 se publicó el 1 de noviembre de 2026 y la etiqueta latest de Docker Hub ya apunta a ella, así que un docker compose pull sin versión fijada te la instala.
  • Un 0 en cualquiera de las seis variables de límite de peticiones (*_RATELIMIT_SECONDS y *_RATELIMIT_MAX_BURST) para el arranque con must be at least 1, y lo mismo pasa con PURGE_INCOMPLETE_SSO_AUTH y DUO_CONTEXT_PURGE_SCHEDULE si no son cron válidos.
  • Vaultwarden solo informa del primer error de cada arranque: con cuatro valores malos necesitas cuatro vueltas, o el script de 24 líneas de esta guía, que los lista todos antes de actualizar.
  • Un número negativo o fuera de rango en el .env no para el arranque: se registra como [ERROR], se ignora y se aplica el valor por defecto, que puede no ser el que querías.
  • Si el valor fuera de rango está en config.json, el fichero del panel de administración, Vaultwarden descarta el fichero entero; en mi prueba el dominio configurado volvió a http://localhost.

¿Qué significa el error Error loading config en Vaultwarden 1.37.5?

Significa que la validación de la configuración encontró un valor que la 1.37.5 ya no admite y abortó el arranque antes de abrir el puerto. Este es el estado que vi tras cambiar la imagen en un compose con restart: unless-stopped que funcionaba con la 1.37.4:

$ docker compose ps -a --format '{{.Name}} {{.Status}}'
vaultwarden Restarting (12) 2 seconds ago

$ docker compose logs --no-log-prefix vaultwarden
[ERROR] `TRASH_AUTO_DELETE_DAYS` contains an invalid value for its
type and is ignored, the default is used instead.
Error loading config:
  `PURGE_INCOMPLETE_SSO_AUTH` is not a valid cron expression

docker compose ps muestra Restarting (12) porque el proceso sale con código 12 y la política de reinicio lo relanza. En otra pasada vi Up 1 second (health: starting) justo entre dos reinicios, así que no te fíes de un vistazo: mira RestartCount con docker inspect o el registro. Sin política de reinicio, el contenedor se queda en Exited (12). La guía de healthchecks y políticas de reinicio en Docker Compose explica por qué el bucle no se detiene solo.

Las notas de la versión lo anuncian en una línea. Según las notas de Vaultwarden 1.37.5[1], "invalid values now stop startup with an error". La frase es cierta para unas variables y no para otras, y esa diferencia es lo que decide si tu servidor arranca.

¿Qué valores paran el arranque y cuáles se ignoran?

Probé cada variable por separado con las dos versiones, arrancando un contenedor de usar y tirar por valor. Esta tabla resume lo que pasó con los valores que más se ven en ficheros .env antiguos:

Variable Valor 1.37.4 1.37.5
LOGIN_RATELIMIT_SECONDS, ADMIN_RATELIMIT_SECONDS, UNAUTHENTICATED_RATELIMIT_SECONDS 0 arranca se para: must be at least 1 second
LOGIN_RATELIMIT_MAX_BURST, ADMIN_RATELIMIT_MAX_BURST, UNAUTHENTICATED_RATELIMIT_MAX_BURST 0 arranca se para: must be at least 1
PURGE_INCOMPLETE_SSO_AUTH, DUO_CONTEXT_PURGE_SCHEDULE every hour, * * * arranca se para: is not a valid cron expression
DATABASE_TIMEOUT, DATABASE_IDLE_TIMEOUT 0 se para con un pánico de r2d2 se para: must be at least 1 second
DATABASE_MIN_CONNS mayor que DATABASE_MAX_CONNS 20 y 10 se para se para
SEND_PURGE_SCHEDULE, TRASH_PURGE_SCHEDULE, EVENT_CLEANUP_SCHEDULE cron no válido se para se para
TRASH_AUTO_DELETE_DAYS, EVENTS_DAYS_RETAIN -1 o 70000 arranca arranca, ignora el valor
LOGIN_RATELIMIT_MAX_BURST, SMTP_TIMEOUT 70000 arranca arranca, ignora el valor
EMAIL_ATTEMPTS_LIMIT 300 arranca arranca, ignora el valor
TRASH_AUTO_DELETE_DAYS, EVENTS_DAYS_RETAIN, EMAIL_ATTEMPTS_LIMIT 0 arranca arranca

La 1.37.4 ya rechazaba DATABASE_MIN_CONNS por encima del máximo y los cron mal escritos de los trabajos antiguos, así que esos no son nuevos aunque las notas los citen. Lo nuevo son los ceros en los límites de peticiones y los dos horarios de purga de inicio de sesión único (SSO) y Duo. @hourly sigue siendo válido en las dos versiones.

Por qué los números fuera de rango no dan error al arrancar

La 1.37.5 cambió el tipo de 24 opciones numéricas a enteros sin signo más estrechos, según el diff de src/config.rs entre las dos etiquetas. TRASH_AUTO_DELETE_DAYS pasó de i64 a u16, y EMAIL_ATTEMPTS_LIMIT de u64 a u8. Un valor que no cabe en el tipo nuevo no se convierte, y desde una variable de entorno el resultado es este aviso:

[ERROR] `TRASH_AUTO_DELETE_DAYS` contains an invalid value for its
type and is ignored, the default is used instead.

El servidor arranca con el valor por defecto, y eso cambia el comportamiento sin pararlo. Con LOGIN_RATELIMIT_MAX_BURST=70000 buscabas quitar el límite de intentos de inicio de sesión, y ahora tienes el valor por defecto, 10. Con TRASH_AUTO_DELETE_DAYS=-1 no cambia nada, porque el valor por defecto ya es no borrar la papelera. El fichero .env.template de la 1.37.5[2] documenta además que 0 desactiva esas dos tareas, así que 0 es la forma correcta de decir "nunca".

El panel de administración también lo detecta. En Diagnostics, la fila Environment variables are valid pasó de Yes a No al añadir TRASH_AUTO_DELETE_DAYS=-1 al .env, con el servidor ya funcionando en la 1.37.5. Es la comprobación visual más corta después de actualizar.

El caso de config.json: se ignora el fichero entero

config.json es donde el panel de administración guarda los ajustes que cambias desde la web, y esos ajustes mandan sobre el .env. La plantilla oficial lo dice así: "Be aware that most of these settings will be overridden if they were changed in the admin interface". Si ese fichero contiene un número fuera de rango, la 1.37.5 no lo para, pero tampoco lo usa:

[ERROR] Failed to load configuration from `data/config.json`
# The file seems to exist but might contain invalid JSON or invalid
# values. Check the syntax and make sure every value is valid and
# within its allowed range.
# This file is not used until those errors are resolved.
[CAUSE] Error("invalid value: integer `-1`, expected u16", line: 1,
column: 92)

He recortado el marco de almohadillas para que quepa. En mi prueba, un config.json con "domain": "https://vw.ejemplo.test", "signups_allowed": false y "trash_auto_delete_days": -1 dejó el dominio en http://localhost según /api/config. Con la 1.37.4, el mismo fichero devolvía https://vw.ejemplo.test. Cualquier ajuste guardado desde el panel vuelve a su valor del .env o al de serie hasta que corrijas el número.

Revisa config.json antes de actualizar con este filtro de jq. Lista los números negativos, los que pasan de 65535, email_attempts_limit por encima de 255 y los ceros en límites de peticiones y tiempos de espera:

jq -r 'to_entries[] | select(.value | type == "number")
  | select(.value < 0 or .value > 65535
      or (.key == "email_attempts_limit" and .value > 255)
      or (.value == 0 and (.key | test("ratelimit|timeout"))))
  | "\(.key)=\(.value)"' vw-data/config.json

Sobre un fichero de prueba con esos tres problemas, la salida fue trash_auto_delete_days=-1, login_ratelimit_seconds=0 y email_attempts_limit=300. Corrígelos desde el panel en la 1.37.4 o edita el fichero con el contenedor parado.

Cómo arreglar el .env para que Vaultwarden 1.37.5 arranque

Pon cada variable que nombre el registro en un valor válido o bórrala para usar el de serie, y vuelve a crear el contenedor. Este es el .env con el que reproduje el fallo:

DOMAIN=http://127.0.0.1:32500
SIGNUPS_ALLOWED=true
LOGIN_RATELIMIT_SECONDS=0
ADMIN_RATELIMIT_MAX_BURST=0
PURGE_INCOMPLETE_SSO_AUTH=every hour
TRASH_AUTO_DELETE_DAYS=-1

Con él, la 1.37.5 se paró tres veces seguidas, una por variable. Primero dijo PURGE_INCOMPLETE_SSO_AUTH y, tras corregirla, LOGIN_RATELIMIT_SECONDS y luego ADMIN_RATELIMIT_MAX_BURST. TRASH_AUTO_DELETE_DAYS=-1 solo generó el aviso. Este es el .env con el que arrancó, con los valores de serie de la plantilla para los límites:

DOMAIN=http://127.0.0.1:32500
SIGNUPS_ALLOWED=true
LOGIN_RATELIMIT_SECONDS=60
ADMIN_RATELIMIT_MAX_BURST=3
PURGE_INCOMPLETE_SSO_AUTH=0 20 0 * * *

La única línea borrada es TRASH_AUTO_DELETE_DAYS, porque vacía ya significa no borrar la papelera. Los cron de Vaultwarden tienen seis campos, con los segundos delante: 0 20 0 * * * es cada día a las 00:20:00. Tras docker compose up -d --force-recreate, RestartCount quedó en 0, /alive devolvió 200 y /version.json dijo 2026.10.1, la nueva bóveda web empaquetada. Si guardas secretos en ese fichero, la guía de variables de entorno y secretos en Docker Compose explica cómo separarlos.

Comprobar el .env antes de actualizar

El script siguiente lee la configuración ya resuelta con docker compose config, que junta env_file y environment, y marca cada valor con STOP si para la 1.37.5 o con IGNORED si la 1.37.5 lo descartará:

#!/usr/bin/env bash
# Flags values that Vaultwarden 1.37.5 rejects (STOP) or ignores (IGNORED)
f=${1:?usage: vw-precheck.sh compose.yaml [service]}; svc=${2:-vaultwarden}
u16() { [[ $1 =~ ^[0-9]+$ ]] && (($1 <= ${2:-65535})); }
docker compose -f "$f" config --format json |
jq -r --arg s "$svc" '.services[$s].environment // {} | to_entries[]
  | "\(.key)=\(.value // "")"' | {
while IFS='=' read -r k v; do
  [[ -z $v ]] && continue
  case $k in
    *_RATELIMIT_SECONDS|*_RATELIMIT_MAX_BURST|DATABASE_*TIMEOUT)
      [[ $v == 0 ]] && echo "STOP    $k=$v (minimum 1)"
      [[ $k == DATABASE_* ]] && lim=99999999999 || lim=65535
      u16 "$v" $lim || echo "IGNORED $k=$v";;
    TRASH_AUTO_DELETE_DAYS|EVENTS_DAYS_RETAIN|SMTP_TIMEOUT)
      u16 "$v" || echo "IGNORED $k=$v (0-65535)";;
    EMAIL_ATTEMPTS_LIMIT) u16 "$v" 255 || echo "IGNORED $k=$v (0-255)";;
    DATABASE_MIN_CONNS) min=$v;; DATABASE_MAX_CONNS) max=$v;;
    *_SCHEDULE|PURGE_INCOMPLETE_SSO_AUTH) n=$(wc -w <<<"$v")
      [[ $v == @* || $n == 6 || $n == 7 ]] || echo "STOP    $k=$v (cron)";;
  esac
done
if ((${min:-2} > ${max:-10})); then echo "STOP    DATABASE_MIN_CONNS > MAX"; fi
}

Lo ejecuté contra el .env roto con cinco líneas extra: DATABASE_MIN_CONNS=20, SEND_PURGE_SCHEDULE=@hourly, DATABASE_TIMEOUT=70000, LOGIN_RATELIMIT_MAX_BURST=70000 y EMAIL_ATTEMPTS_LIMIT=300. Marcó cuatro STOP y tres IGNORED, y dejó pasar @hourly y DATABASE_TIMEOUT=70000, que la 1.37.5 acepta porque esa opción es u32. Contra el .env corregido no imprimió nada. La comprobación de cron solo cuenta campos, así que un cron de seis campos con un valor imposible se le escapa; el arranque lo sigue detectando.

Actualizar de 1.37.4 a 1.37.5 paso a paso

Con el .env limpio, la actualización es copiar los datos, comprobar, cambiar la etiqueta y mirar el registro. Este es el compose de la prueba:

services:
  vaultwarden:
    image: vaultwarden/server:1.37.5
    restart: unless-stopped
    env_file: .env
    volumes:
      - ./vw-data:/data
    ports:
      - "127.0.0.1:32500:80"

Y estos son los pasos, en el directorio del compose, tal como los ejecuté sobre una instalación de la 1.37.4 en marcha:

cp -a vw-data "vw-data.antes-1.37.5.$(date +%F)"
./vw-precheck.sh "$PWD/compose.yaml"
sed -i 's|vaultwarden/server:1.37.4|vaultwarden/server:1.37.5|' compose.yaml
docker compose pull && docker compose up -d
docker compose logs --no-log-prefix vaultwarden | grep -E 'ERROR|Error loading'
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:32500/alive
curl -s http://127.0.0.1:32500/version.json

El grep no devolvió nada, /alive dio 200 y la bóveda web pasó de 2026.7.0 a 2026.10.1. Si sigues la guía de instalación de Vaultwarden con Docker, tu compose fija 1.36.0: cambia esa etiqueta igual. Con Watchtower actualizando contenedores sobre latest, la 1.37.5 ya puede estar instalada; revisa el registro hoy mismo.

¿Puedo volver a la 1.37.4?

Sí, en mi prueba la 1.37.4 arrancó sobre el directorio de datos que la 1.37.5 ya había migrado, aunque no lo recomiendo más que como paso de unas horas. La 1.37.5 añade una migración de esquema (add_org_policy_revision_date, una columna nueva en las políticas de organización) y corrige dos avisos de seguridad, GHSA-x9cq-f669-vrr4 y GHSA-9pjj-f9g5-3x4c. Vuelve atrás desde la copia de vw-data que hiciste antes, no sobre los datos migrados, y corrige el .env para subir cuanto antes.

Las notas añaden dos cambios que no afectan al arranque. Si sirves tu propia bóveda web anterior a la v2026.7.1, puedes tener problemas de compatibilidad. Además, la bóveda web 2026.7.1 o posterior necesita la 1.37.5 para activar o desactivar métodos de doble factor. Si usas el SSO con Pocket ID en Vaultwarden, comprueba PURGE_INCOMPLETE_SSO_AUTH antes que nada: es una de las dos variables con validación nueva.

Preguntas frecuentes

¿Por qué el contenedor de Vaultwarden se reinicia en bucle tras actualizar?

Porque la 1.37.5 sale con código 12 al encontrar un valor no válido y tu política restart lo vuelve a lanzar. docker compose logs vaultwarden muestra la variable culpable debajo de Error loading config:.

¿Sigue valiendo 0 para desactivar la papelera automática o la retención de eventos?

Sí. TRASH_AUTO_DELETE_DAYS=0 y EVENTS_DAYS_RETAIN=0 arrancan en la 1.37.5, y la plantilla oficial documenta 0 como desactivado. Lo que ya no vale es -1, que se ignora con un [ERROR].

¿Cómo desactivo ahora el límite de intentos de inicio de sesión?

No puedes con 0. El mínimo es 1 y el máximo, 65535 para LOGIN_RATELIMIT_MAX_BURST, así que el valor más permisivo es LOGIN_RATELIMIT_SECONDS=1 con LOGIN_RATELIMIT_MAX_BURST=65535. Valora antes si quieres quitar la protección contra fuerza bruta de un gestor de contraseñas.

Conclusión

Antes de pasar a la 1.37.5, ejecuta el script contra tu compose y el filtro de jq contra config.json, y corrige cada STOP e IGNORED. Los ceros en límites de peticiones y los cron de purga mal escritos tumban el servidor, y los números fuera de rango cambian su comportamiento sin avisar más que en el registro. Después de actualizar, abre Diagnostics en /admin y confirma que Environment variables are valid dice Yes.

Fuentes: [1] Vaultwarden 1.37.5, notas de la versión[1], [2] Vaultwarden 1.37.5, .env.template[2], [3] Diferencias entre 1.37.4 y 1.37.5[3], [4] Etiquetas de vaultwarden/server en Docker Hub[4], [5] Docker, políticas de reinicio[5].

Fuentes

  1. notas de Vaultwarden 1.37.5
  2. fichero .env.template de la 1.37.5
  3. Diferencias entre 1.37.4 y 1.37.5
  4. Etiquetas de vaultwarden/server en Docker Hub
  5. Docker, políticas de reinicio