Enterprise Caddy UI with guided publishing, certificate cleanup, TLS, SQLite, and MariaDB.
10K+
A modern, self-hosted web UI for Caddy — manage proxy hosts, redirections, SSL certificates, and advanced routes through a clean interface, without touching config files.
Lighthouse: Performance 99 · Accessibility 100 · Best Practices 100 · SEO 100
(measured on /login from Google's PageSpeed Insights — :v2.12.53 and later)
GitHub · Issues · CHANGELOG · Releases
docker pull applegater/caddyui:latest
SQLite is included and remains the zero-configuration default. For larger
installations, CaddyUI also supports MariaDB with concurrent connections,
platform-managed backups, and a built-in read-only SQLite → MariaDB migration
command. See the GitHub README's MariaDB (optional enterprise backend)
section and the included docker-compose.mariadb.yml overlay.
services:
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports: ["80:80", "443:443", "443:443/udp"]
volumes:
- caddy_data:/data
- caddy_config:/config
environment:
CADDY_ADMIN: 0.0.0.0:2019
command: >-
mkdir -p /config/caddy;
[ -f /config/caddy/autosave.json ] || echo '{}' > /config/caddy/autosave.json;
exec caddy run --config /config/caddy/autosave.json --resume --adapter json
caddyui:
image: applegater/caddyui:latest
restart: unless-stopped
ports: ["8080:8080"]
volumes:
- caddyui_data:/data # named volume — no chown needed
environment:
CADDY_ADMIN_URL: http://caddy:2019
volumes:
caddy_data:
caddy_config:
caddyui_data:
💡 Fresh install: On first boot Caddy has no saved config yet. The
commandabove seeds an empty{}config automatically so Caddy starts cleanly without any extra steps. Without--resume, admin-API pushes from CaddyUI would be lost on everydocker compose restart.
DNS-01 note: Managed ACME certificates require a Caddy build containing the matching
caddy-dnsprovider module. The stockcaddy:2-alpineimage in this minimal example does not include those modules. Use the repository'sDockerfile.caddy, which includes every DNS provider supported by CaddyUI, or supply your own compatible Caddy build.
If you bind-mount a host directory to /data instead of using a named volume, the host directory must be owned by uid 10001 (the non-root user the container runs as):
sudo chown 10001:10001 /path/to/caddyui_data
The container will print a clear error message at startup if the directory isn't writable.
CaddyUI v2.25 makes the source and state of fleet activity visible without replacing Caddy's normal logs:
The structured log listener should stay on a private Docker, LAN, WireGuard, or Tailscale network. CaddyUI adds named streams and does not redirect or suppress the node's existing container, journal, or file output.
CaddyUI v2.24 manages Caddy metrics without clobbering global options loaded elsewhere:
observe_catchall_hosts with target-side Caddy 2.11+ validation/metrics scrape target from SettingsKeep the Caddy admin endpoint private. Prometheus should reach it through the same Docker, LAN, loopback, WireGuard, or Tailscale network used by CaddyUI.
CaddyUI v2.21 adds independent rotating file access logs and CrowdSec request protection:
crowdsec and http.handlers.crowdsec modules before enabling protectionThe repository Dockerfile.caddy includes the required CrowdSec HTTP bouncer module. Custom Caddy images must include github.com/hslatman/caddy-crowdsec-bouncer/http.
CaddyUI v2.20.1 makes the Operations Unused custom certificates recommendation precise and controllable:
CaddyUI v2.20 organizes setup and daily work around operator intent and the active environment:
DNS automation is an optional readiness capability, so ordinary deployments can reach 100% without provider credentials. The guide stays available after initial setup and works as an ongoing environment checklist.
After an eleven-version perf + a11y wave (v2.12.38 → v2.12.48), CaddyUI's /login page hits 99/100/100/100 on Google PageSpeed Insights against a residential-ISP install:
/static/app.js so it caches across navigationsaria-current nav, label↔input pairing across every formOpt-in floating chat button that answers Caddy / TLS / DNS questions and writes production-grade Caddyfile snippets. Pick any backend in Settings → AI assistant:
| Backend | Best for | What you need |
|---|---|---|
| Ollama (local) | Fully-offline, runs on your GPU | Reachable Ollama; recommended qwen2.5:14b / gemma2:9b |
| Ollama Cloud | MoE models that won't fit on a homelab GPU | API key from ollama.com/settings/keys |
| Anthropic Claude | Strongest Caddy reasoning out of the box | API key from console.anthropic.com; Haiku 4.5 / Sonnet 4.6 / Opus 4.7 |
| OpenAI-compatible | OpenAI itself + OpenRouter, Groq, Together, vLLM, LM Studio | Base URL + API key + model |
AI auto-fill — describe what you want in natural language ("set up nextcloud at cloud.example.com pointing to nextcloud:80 with auto-SSL") and the assistant emits a create_proxy_host / create_redirection tool call. Click Apply on the confirmation card and the resource is created, the form is filled in for you, and Caddy is auto-synced. Every AI-driven exec writes an ai_tool_call activity-log entry. Works on Claude 4.x, GPT-4, qwen2.5+, llama3.1+, gemma2.
Inverse of CaddyUI's existing /caddyfile-import paste flow. Click Export Caddyfile on /proxy-hosts to download every enabled proxy host, redirection, and raw route on the active server as a single Caddyfile snapshot:
example.com {
@blocked path /.env* /wp-admin* /wp-login* /phpmyadmin* /.git/* /xmlrpc.php
respond @blocked 403
encode zstd gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
...
}
reverse_proxy backend:8080 {
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto {scheme}
header_up X-Real-IP {remote_host}
}
}
Per-host # Notes: block lists settings that don't fit cleanly into Caddyfile syntax (maintenance windows, basic-auth users, etc.) so users see what was elided rather than silently losing it on round-trip. Stable sort by hostname so two exports of the same DB diff cleanly. Same RBAC scoping as the existing JSON exports — admin gets the full server config, non-admin only their own resources.
Per-host export also available from the proxy-host edit page.
*.example.com.No PEM upload, fake proxy upstream, or private-key transfer is required.
| Tag | What it points at |
|---|---|
:vX.Y.Z | Specific release, immutable. Recommended for production. |
:stable | The current release. Updated on every release. |
:latest | Kept in lockstep with :stable. |
:stable, :latest and the newest :vX.Y.Z all resolve to the same image.
:previewis retired. It was a rolling per-commit channel; releases now go straight to:stable. The tag still exists and points atv2.28.0, but it is no longer updated — switch to:stableor pin a version.
Multi-arch: linux/amd64 + linux/arm64. Scratch base image, runs as non-root uid 10001.
| Environment variable | Default | Purpose |
|---|---|---|
CADDY_ADMIN_URL | http://caddy:2019 | Caddy's admin API (the docker service name in the same compose network) |
CADDYUI_DB_DRIVER | sqlite | Database backend: sqlite or mariadb |
CADDYUI_DB | /data/caddyui.db | SQLite database path |
CADDYUI_DB_DSN | (none) | MariaDB DSN; required when CADDYUI_DB_DRIVER=mariadb |
CADDYUI_LISTEN | :8080 | HTTP listen address |
CADDYUI_INGEST_LISTEN | :9019 | Structured Caddy log ingest for analytics, certificate lifecycle, and temporary runtime streams (empty string disables all three) |
CADDYFILE_PATH | /etc/caddy/Caddyfile | Optional — only read if you mount a Caddyfile into the CaddyUI container for the paste-import auto-classifier reference |
CADDY_ADMIN_USER / CADDY_ADMIN_PASS | (none) | Optional HTTP basic auth for Caddy's admin endpoint when proxied |
CaddyUI Source Available License 1.0
Free for personal use, non-profits, educational institutions, small businesses (<50 employees, <$5M revenue), and any organization using it internally. Commercial license required to offer CaddyUI as a hosted/managed service.
Open an issue on GitHub: https://github.com/X4Applegate/caddyui/issues
— Richard
Content type
Image
Digest
sha256:aa5dd4c47…
Size
8.8 MB
Last updated
about 23 hours ago
docker pull applegater/caddyui