{
  "schema_version": 2,
  "app": "vaultwarden-caddy",
  "display_name": "Vaultwarden with Caddy",
  "upstream_repo": "https://github.com/dani-garcia/vaultwarden",
  "docs_url": "https://github.com/dani-garcia/vaultwarden/wiki/Using-Docker-Compose",
  "status": "ok",
  "summary": {
    "primary_service": "vaultwarden",
    "app_version": "1.37.3",
    "app_version_pinned": true,
    "idle_total_mem_mib": 23.62,
    "idle_total_cpu_pct": 0.0,
    "peak_total_mem_mib": 82.77,
    "peak_is_under_load": true,
    "startup_seconds": 3.7,
    "startup_peak_total_mem_mib": 23.65,
    "settled": true,
    "settle_seconds_used": 120.6
  },
  "run": {
    "started_at": "2026-10-02T11:16:06Z",
    "date": "2026-10-02",
    "harness_version": "2.0.0",
    "docker_host": null,
    "remote": false
  },
  "host": {
    "cpu_model": "Intel(R) Xeon(R) Processor @ 2.10GHz",
    "cpu_model_note": null,
    "cores": 4,
    "mem_total_mib": 16095,
    "kernel": "6.18.44-fc-v51",
    "os": "Ubuntu 24.04.4 LTS",
    "arch": "x86_64",
    "oci_arch": "amd64",
    "docker_server_version": "29.6.2",
    "docker_client_version": "29.6.2",
    "compose_client_version": "5.3.1",
    "storage_driver": "overlayfs",
    "containerd_image_store": true,
    "source": "docker info + throwaway container reading /proc/cpuinfo on the daemon host",
    "compose_note": "Compose runs on the client machine; Docker server fields are from the daemon host"
  },
  "helper_images": {
    "curlimages/curl:latest": {
      "pulled_as": "curlimages/curl:latest",
      "digest": "curlimages/curl@sha256:58adaa4e8dca9c988bae2aba4ab3434a0bb2da16bbe3f92dec39ec7785166777"
    },
    "python:3.12-slim": {
      "pulled_as": "python:3.12-slim",
      "digest": "python@sha256:dddfd7e07f9d15aeeca61529320492139d21cac7f0070c00609243e51e4e0016"
    }
  },
  "pull_seconds": 2.1,
  "startup": {
    "seconds": 3.7,
    "ok": true,
    "checks": [
      {
        "type": "http",
        "url": "https://vault.example.com/alive",
        "expect_status": [
          200
        ],
        "ok": true,
        "ready_after_s": 3.7,
        "detail": "OK 200"
      }
    ],
    "up_command_seconds": 3.2,
    "definition": "wall clock from starting `docker compose up -d` until every health check passed; checks poll every 0.5 s from a throwaway container on the compose network, so resolution is about +/- 1 s"
  },
  "services": {
    "caddy": {
      "image_ref": "caddy:2",
      "image_repo": "caddy",
      "image_tag": "2",
      "digest": "sha256:0c994536bddb66445885237f1a5dcc1916bccea922661c76b4e9fc24061f9b52",
      "digest_note": null,
      "version": "v2.11.4",
      "version_source": "label:org.opencontainers.image.version",
      "version_pinned": true,
      "version_note": null,
      "resolved_tag": "2.11.4",
      "resolved_tag_note": null,
      "image_size": {
        "unpacked_mb": 88.8,
        "unpacked_source": "docker image ls Size: unpacked image on the daemon host, rounded by docker to 3 significant figures",
        "compressed_mb": 23.9,
        "compressed_source": "sum of compressed layer sizes in the registry manifest for linux/amd64",
        "compressed_null_reason": null,
        "unit_note": "MB = 10^6 bytes. unpacked = disk used on the host; compressed = what is downloaded"
      },
      "compose_image": "caddy:2.11.4",
      "compose_comment": "sha256:0c994536bddb66445885237f1a5dcc1916bccea922661c76b4e9fc24061f9b52  (version v2.11.4, from label:org.opencontainers.image.version)",
      "restart_count": 0,
      "oom_killed": false
    },
    "vaultwarden": {
      "image_ref": "vaultwarden/server:latest",
      "image_repo": "vaultwarden/server",
      "image_tag": "latest",
      "digest": "sha256:1587c45feaa479f1f5e8af3b00eded36bff77bcf1880cf8dbf0541706dd470e0",
      "digest_note": null,
      "version": "1.37.3",
      "version_source": "label:org.opencontainers.image.version",
      "version_pinned": true,
      "version_note": null,
      "resolved_tag": "1.37.3",
      "resolved_tag_note": null,
      "image_size": {
        "unpacked_mb": 402.0,
        "unpacked_source": "docker image ls Size: unpacked image on the daemon host, rounded by docker to 3 significant figures",
        "compressed_mb": 90.3,
        "compressed_source": "sum of compressed layer sizes in the registry manifest for linux/amd64",
        "compressed_null_reason": null,
        "unit_note": "MB = 10^6 bytes. unpacked = disk used on the host; compressed = what is downloaded"
      },
      "compose_image": "vaultwarden/server:1.37.3",
      "compose_comment": "sha256:1587c45feaa479f1f5e8af3b00eded36bff77bcf1880cf8dbf0541706dd470e0  (version 1.37.3, from label:org.opencontainers.image.version)",
      "restart_count": 0,
      "oom_killed": false
    }
  },
  "setup": [
    {
      "exit_code": 0,
      "duration_s": 4.2,
      "reported": {
        "account_created": true,
        "admin_login_with_plaintext_token": true,
        "uninvited_registration_status": 400
      },
      "output_tail": [
        "admin login with the plaintext token -> 200 cookie set: True",
        "admin invite -> 200",
        "register -> {'captchaBypassToken': '', 'object': 'register'}",
        "login ok; kdf 0 iterations 600000",
        "cipher created: c76c88b0-743c-437f-8516-ab64182b1484",
        "uninvited registration -> 400 b'{\"message\":\"Registration not allowed or user already exists\",\"validationErrors\":{\"\":[\"Registration not allowed or user already exists\"]},\"errorModel\":'"
      ],
      "description": "Log in to the admin page with the plaintext admin password (the stack holds only its Argon2 hash), invite an e-mail address, register that account with real client-side cryptography, log in, create one vault item, and confirm an uninvited registration is refused (SIGNUPS_ALLOWED=false)."
    }
  ],
  "idle": {
    "per_service": {
      "caddy": {
        "samples": 16,
        "mem_mean_mib": 13.75,
        "mem_max_mib": 13.75,
        "cpu_mean_pct": 0.0,
        "cpu_max_pct": 0.03
      },
      "vaultwarden": {
        "samples": 16,
        "mem_mean_mib": 9.87,
        "mem_max_mib": 9.9,
        "cpu_mean_pct": 0.0,
        "cpu_max_pct": 0.01
      }
    },
    "total": {
      "samples": 16,
      "dropped_for_total": 0,
      "mem_mean_mib": 23.62,
      "mem_max_mib": 23.65,
      "cpu_mean_pct": 0.0,
      "cpu_max_pct": 0.03
    },
    "window_seconds": 30.1,
    "series": [
      {
        "t_offset_s": 0.0,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.03
      },
      {
        "t_offset_s": 2.0,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 4.0,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 6.0,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 8.0,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 10.0,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 12.1,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 14.1,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.01
      },
      {
        "t_offset_s": 16.1,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 18.1,
        "total_mem_mib": 23.65,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 20.1,
        "total_mem_mib": 23.56,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 22.1,
        "total_mem_mib": 23.56,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 24.1,
        "total_mem_mib": 23.56,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 26.1,
        "total_mem_mib": 23.56,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 28.1,
        "total_mem_mib": 23.56,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 30.1,
        "total_mem_mib": 23.56,
        "total_cpu_pct": 0.0
      }
    ]
  },
  "settle": {
    "settled": true,
    "mode": "detected",
    "settle_seconds_used": 120.6,
    "settle_started_after_healthy_s": 10.1,
    "params": {
      "window_seconds": 60,
      "threshold_pct": 2.0,
      "threshold_min_mib": 10.0,
      "min_seconds": 120,
      "max_seconds": 600
    },
    "last_window": {
      "n": 30,
      "mean_mib": 23.29,
      "min_mib": 23.21,
      "max_mib": 23.65,
      "spread_mib": 0.44,
      "threshold_mib": 10.0
    },
    "rechecks": 0,
    "rule": "settled = over the last window_seconds the stack total varied (max - min) by less than max(threshold_pct of the window mean, threshold_min_mib); not before min_seconds, at the latest max_seconds, both counted from the end of the setup steps; the idle window must also be flat and agree with it. If max_seconds passes without settling, settled=false and the idle window is measured anyway."
  },
  "startup_peak": {
    "per_service_mem_mib": {
      "caddy": 13.91,
      "vaultwarden": 9.94
    },
    "total_mem_mib": 23.65,
    "samples": 65,
    "note": "highest value across docker stats samples (about one every 2-3 s) from healthy until the stack settled; shorter spikes between samples are not seen"
  },
  "timeline": {
    "step_s": 10,
    "t0": "healthy",
    "offsets_s": [
      10,
      20,
      30,
      40,
      50,
      60,
      70,
      80,
      90,
      100,
      110,
      120,
      130,
      140,
      150,
      160,
      170
    ],
    "total_mem_mib": [
      21.3,
      22.6,
      22.7,
      23.2,
      23.2,
      23.2,
      23.3,
      23.3,
      23.3,
      23.2,
      23.2,
      23.2,
      23.4,
      23.7,
      23.7,
      23.6,
      23.6
    ],
    "per_service_mem_mib": {
      "caddy": [
        13.4,
        13.5,
        13.5,
        13.5,
        13.5,
        13.5,
        13.5,
        13.5,
        13.5,
        13.5,
        13.5,
        13.5,
        13.5,
        13.8,
        13.8,
        13.8,
        13.8
      ],
      "vaultwarden": [
        7.8,
        9.1,
        9.2,
        9.7,
        9.7,
        9.7,
        9.9,
        9.9,
        9.9,
        9.8,
        9.8,
        9.8,
        9.9,
        9.9,
        9.9,
        9.8,
        9.8
      ]
    }
  },
  "load": {
    "per_service": {
      "caddy": {
        "samples": 32,
        "mem_mean_mib": 17.23,
        "mem_max_mib": 17.83,
        "cpu_mean_pct": 69.18,
        "cpu_max_pct": 78.03
      },
      "vaultwarden": {
        "samples": 32,
        "mem_mean_mib": 61.47,
        "mem_max_mib": 65.71,
        "cpu_mean_pct": 70.91,
        "cpu_max_pct": 79.84
      }
    },
    "total": {
      "samples": 32,
      "dropped_for_total": 0,
      "mem_mean_mib": 78.7,
      "mem_max_mib": 82.77,
      "cpu_mean_pct": 140.09,
      "cpu_max_pct": 157.01
    },
    "description": "One account, one user, over HTTPS through Caddy. The script first creates 100 encrypted vault items, then for 60 seconds four threads loop over GET /alive, GET /api/config and GET /api/sync (the full vault, about 100 items), and every fifth loop update one item (a database write). It is a synthetic single-user load: no browser, no browser extension, no websocket connections, no attachments. The memory peak is measured over those 60 seconds.",
    "duration_s": 60.5,
    "window": "from LAB_MARK load_start (or step start) until 2 s after the step ended",
    "reported_by_script": {
      "seconds": 60,
      "threads": 4,
      "items": 100,
      "errors": 0,
      "alive": {
        "requests": 8321,
        "p50_ms": 6.3,
        "p95_ms": 10.4
      },
      "config": {
        "requests": 8321,
        "p50_ms": 6.2,
        "p95_ms": 10.2
      },
      "sync": {
        "requests": 8321,
        "p50_ms": 13.1,
        "p95_ms": 19.6
      },
      "update": {
        "requests": 1663,
        "p50_ms": 9.8,
        "p95_ms": 15.2
      },
      "requests_total": 26626
    },
    "output_tail": [
      "created 100 vault items",
      "errors sample: []"
    ],
    "series": [
      {
        "t_offset_s": 0.0,
        "total_mem_mib": 56.74,
        "total_cpu_pct": 148.88
      },
      {
        "t_offset_s": 2.0,
        "total_mem_mib": 67.98,
        "total_cpu_pct": 157.01
      },
      {
        "t_offset_s": 4.0,
        "total_mem_mib": 68.87,
        "total_cpu_pct": 152.72
      },
      {
        "t_offset_s": 6.0,
        "total_mem_mib": 70.45,
        "total_cpu_pct": 153.35
      },
      {
        "t_offset_s": 8.1,
        "total_mem_mib": 70.78,
        "total_cpu_pct": 152.6
      },
      {
        "t_offset_s": 10.1,
        "total_mem_mib": 71.62,
        "total_cpu_pct": 142.13
      },
      {
        "t_offset_s": 12.1,
        "total_mem_mib": 71.26,
        "total_cpu_pct": 151.55
      },
      {
        "t_offset_s": 14.1,
        "total_mem_mib": 78.79,
        "total_cpu_pct": 150.15
      },
      {
        "t_offset_s": 16.1,
        "total_mem_mib": 79.04,
        "total_cpu_pct": 150.7
      },
      {
        "t_offset_s": 18.1,
        "total_mem_mib": 79.61,
        "total_cpu_pct": 150.36
      },
      {
        "t_offset_s": 20.1,
        "total_mem_mib": 79.85,
        "total_cpu_pct": 146.08
      },
      {
        "t_offset_s": 22.1,
        "total_mem_mib": 81.02,
        "total_cpu_pct": 147.92
      },
      {
        "t_offset_s": 24.1,
        "total_mem_mib": 80.92,
        "total_cpu_pct": 146.29
      },
      {
        "t_offset_s": 26.2,
        "total_mem_mib": 81.69,
        "total_cpu_pct": 146.9
      },
      {
        "t_offset_s": 28.2,
        "total_mem_mib": 81.19,
        "total_cpu_pct": 151.42
      },
      {
        "t_offset_s": 30.2,
        "total_mem_mib": 81.48,
        "total_cpu_pct": 150.26
      },
      {
        "t_offset_s": 32.2,
        "total_mem_mib": 81.66,
        "total_cpu_pct": 149.24
      },
      {
        "t_offset_s": 34.2,
        "total_mem_mib": 81.37,
        "total_cpu_pct": 151.38
      },
      {
        "t_offset_s": 36.2,
        "total_mem_mib": 82.43,
        "total_cpu_pct": 147.88
      },
      {
        "t_offset_s": 38.2,
        "total_mem_mib": 82.4,
        "total_cpu_pct": 147.88
      },
      {
        "t_offset_s": 40.3,
        "total_mem_mib": 82.62,
        "total_cpu_pct": 136.87
      },
      {
        "t_offset_s": 42.3,
        "total_mem_mib": 82.67,
        "total_cpu_pct": 152.13
      },
      {
        "t_offset_s": 44.3,
        "total_mem_mib": 81.83,
        "total_cpu_pct": 148.24
      },
      {
        "t_offset_s": 46.3,
        "total_mem_mib": 82.07,
        "total_cpu_pct": 150.07
      },
      {
        "t_offset_s": 48.3,
        "total_mem_mib": 82.56,
        "total_cpu_pct": 150.94
      },
      {
        "t_offset_s": 50.3,
        "total_mem_mib": 82.77,
        "total_cpu_pct": 155.91
      },
      {
        "t_offset_s": 52.3,
        "total_mem_mib": 82.47,
        "total_cpu_pct": 147.13
      },
      {
        "t_offset_s": 54.3,
        "total_mem_mib": 82.75,
        "total_cpu_pct": 151.15
      },
      {
        "t_offset_s": 56.4,
        "total_mem_mib": 82.73,
        "total_cpu_pct": 149.35
      },
      {
        "t_offset_s": 58.4,
        "total_mem_mib": 82.75,
        "total_cpu_pct": 146.44
      },
      {
        "t_offset_s": 60.4,
        "total_mem_mib": 81.97,
        "total_cpu_pct": 0.0
      },
      {
        "t_offset_s": 62.4,
        "total_mem_mib": 81.97,
        "total_cpu_pct": 0.0
      }
    ],
    "peak_note": "peak = highest value seen across docker stats samples (about one every 2-3 s); shorter spikes between samples are not seen"
  },
  "finished_at": "2026-10-02T11:20:06Z",
  "elapsed_seconds": 239.2,
  "teardown": {
    "done": true,
    "volumes_removed": true,
    "images_removed": false,
    "error": null
  },
  "load_defined": true,
  "notes": [
    "Caddy uses `tls internal` (no public domain in the lab); health check and scripts skip certificate verification for that reason.",
    "ADMIN_TOKEN in the stack is an Argon2 PHC hash made with `vaultwarden hash`; the plaintext lab password is only in test.yaml.",
    "The idle figure includes Caddy. The vault is idle (one account, one item) until the load step.",
    "Run behind a TLS-intercepting proxy: an extra CA bundle was mounted read-only into every container and the SSL_CERT_FILE-style variables pointed at it (lab-only override, NOT in the published compose). It changes outbound TLS trust, nothing else."
  ],
  "warnings": [],
  "files": {
    "compose": "vaultwarden-caddy.compose.yaml",
    "env": "vaultwarden-caddy.env"
  },
  "definitions": {
    "memory": "cgroup working set as reported by `docker stats` (usage minus inactive file cache), MiB = 2^20 bytes",
    "cpu": "percent of ONE core as reported by `docker stats` (4 busy cores = 400)",
    "total": "stats over the sum of all containers at the same instant",
    "sample_interval": "docker stats --no-stream takes about 1-2 s per call, so samples are 2-3 s apart"
  }
}
