version: '3' services: vaultwarden: image: vaultwarden/server:alpine container_name: vaultwarden restart: unless-stopped environment: - WEBSOCKET_ENABLED=true # Enable WebSocket notifications. - DATABASE_URL=postgresql://vaultwarden:YOUR_POSTGRESQL_PASSWORD@postgres:5432/vaultwarden - ADMIN_TOKEN=YOUR_ADMIN_PASSWORD volumes: - vaultwarden:/data networks: - vaultwarden - postgres read_only: true security_opt: - no-new-privileges:true cap_drop: - ALL cap_add: - CAP_NET_BIND_SERVICE caddy: image: caddy:alpine container_name: caddy restart: unless-stopped ports: - 80:80 # Needed for the ACME HTTP-01 challenge. - 443:443 volumes: - ./Caddyfile:/etc/caddy/Caddyfile:Z - ./caddy-config:/config:Z - ./caddy-data:/data:Z environment: - DOMAIN=YOUR_DOMAIN # Your domain. - EMAIL=YOUR_EMAIL # The email address to use for ACME registration. - LOG_FILE=/data/access.log networks: - vaultwarden read_only: true security_opt: - no-new-privileges:true cap_drop: - ALL cap_add: - CAP_NET_BIND_SERVICE postgres: image: docker.io/postgres-15:alpine container_name: postgres restart: unless-stopped volumes: - postgres:/var/lib/postgresql/data environment: - POSTGRES_USER=vaultwarden - POSTGRES_PASSWORD=YOUR_POSTGRESQL_PASSWORD networks: - postgres healthcheck: test: ["CMD", "pg_isready", "-U", "vaultwarden"] interval: 15s timeout: 5s user: "70:70" read_only: true tmpfs: - /var/run/postgresql:size=50M,mode=0770,uid=70,gid=70,noexec,nosuid,nodev security_opt: - no-new-privileges:true cap_drop: - ALL volumes: vaultwarden: postgres: networks: vaultwarden: postgres: