πŸš€ Release Roundup

CaddyUI v2.12.12 β€” AI tool calling: chat the assistant into actually building proxy hosts

The headline of this patch wave: the AI assistant grew real tool calling. Describe what you want β€” "create a proxy host for AdGuardHome on adguardhome:3000" β€” and the model emits a structured create_proxy_host call instead of a Caddyfile snippet. The chat panel renders a confirmation card with the exact arguments, you click Apply, and the resource gets created. No copy-paste. Every exec writes an audit-log entry. Plus dashboard cards now respect the active-server picker (including wildcard SAN traffic), markdown in chat replies, conversation memory, custom system prompts, per-section Save buttons on Settings, and 13 CodeQL XSS-through-DOM fixes.

v2.12.12 β˜• ~10 min read

πŸ”§ AI tool calling β€” chat the assistant into building things v2.12.11

The AI assistant always knew how to write Caddyfile snippets β€” copy/paste them into /caddyfile-import and you'd get a proxy host. v2.12.11 closes that loop: the model emits a structured tool call, you see a confirmation card with the parameters, click Apply, and CaddyUI creates the resource for real.

Two tools shipped today:

ToolArgumentsResult
create_proxy_host domains, forward_scheme, forward_host, forward_port, ssl_enabled, ssl_forced New row in proxy_hosts; syncCaddy fires immediately
create_redirection domains, forward_scheme, forward_domain, forward_http_code, preserve_path New row in redirection_hosts

The system prompt tells the model when to call a tool vs. just write a snippet:

Implemented over Ollama's OpenAI-compatible tools array. Works on qwen2.5, qwen2.5-coder, llama3.1+, gemma2; older or smaller models silently ignore the tools field, so back-compat is automatic. Every successful exec writes an ai_tool_call row to the activity log with the resource ID + a human-readable summary, so admins can audit what the AI actually did.

Trade-off, deliberate. The tool exec doesn't continue the conversation back into the model β€” you don't get a "Done! Created proxy host #42…" follow-up automatically. Multi-step tool flows ("now redirect old to new") still work because each turn is independent and the model sees the conversation history. Keeps v1 simple and the user keeps full control over what gets created.

πŸ’¬ Chat polish β€” memory, markdown, custom prompts v2.12.7, v2.12.10

Three rounds of polish on the AI panel that landed alongside tool calling:


πŸ“Š Dashboard cards scoped to the active server v2.12.8, v2.12.9

The Requests / Visitors / Bandwidth Today cards on the dashboard were calling AccessTotalsSince(..., "") with no host filter, so they summed every access event across the entire fleet β€” ignoring which server the picker had selected. On a multi-server install with a busy edge node, the active server's dashboard would show another server's traffic.

v2.12.8 scopes the cards to the active server's hostnames (loops over each Domain in the active server's proxy hosts / redirections / raw routes and sums per-host).

v2.12.9 fixed a related bug: hosts with wildcard SAN domains (*.example.com) were being passed as a literal host = '*.example.com' filter to the analytics queries β€” which never matched a real recorded hostname. New hostMatchClause helper detects the *. prefix and translates to host LIKE '%.example.com'. Wildcard-routed traffic now contributes to the per-server totals correctly.


⌘ Command palette + keyboard nav v2.11.0 β†’ v2.11.5

v2.11 leans hard on keyboard navigation. ⌘K on macOS or Ctrl+K anywhere else opens a global palette that searches across every Proxy Host, Redirection, Advanced route, and Cert visible to the active user on the active server. ↑/↓ navigates, Enter opens, Esc closes. Backed by a new GET /api/search endpoint that shares the same viewer / peer / admin permission filtering the list pages already use; frontend caches the response per palette open with a 60-second freshness window.

Around the palette, v2.11.0 ships a tri-state theme toggle (auto / light / dark), live filter inputs on every list page, a ? overlay listing every binding, and Vim-style g+letter chord nav:

ChordGoes to
g dDashboard
g p/proxy-hosts
g r/redirection-hosts
g c/certificates
g a/raw-routes
g n/analytics

πŸ“‹ Bulk ops + drag-to-reorder v2.11.6 β†’ v2.11.11

Every list page now has a per-row checkbox, a select-all in the header, and a floating bulk-action bar at the bottom. The pattern /proxy-hosts already had is now everywhere:

PageBulk actionsVersion
/proxy-hostsEnable Β· Disable Β· Delete Β· Maintenanceexisting
/redirection-hostsEnable Β· Disable Β· Deletev2.11.6
/raw-routesEnable Β· Disable Β· Deletev2.11.9
/certificatesDelete (honours in-use guard)v2.11.10

v2.11.11 adds an HTML5 β Ώ drag handle on every row of /proxy-hosts and /redirection-hosts. Drag the handle to reflow the row immediately; the new order POSTs to /proxy-hosts/reorder (or the redirection equivalent) and persists. UI-only β€” no Caddy sync on reorder. The sort_order writes are index * 10 so future single-row Sort Order edits can wedge between drag-saved rows without renumbering.


πŸ› οΈ Proxy-host form rebuilt top-down v2.11.4 β†’ v2.11.8

After v2.10 added ~70 per-host options, the proxy-host edit form became a wall of toggles. The v2.11 cycle puts essentials at the top and collapses the rest. The form now reads top-down:

  1. Domain names + www redirect + trailing slash
  2. Forward Scheme + Host + Port + Test upstream ← v2.11.8
  3. Enabled / Auto SSL / Force SSL ← v2.11.4
  4. Managed DNS ← v2.11.7
  5. TLS Certificate ← v2.11.7
  6. Path matching, query string, tags & notes (collapsed)
  7. Upstream TLS & advanced settings (collapsed)
  8. Options & Forwarded Headers (collapsed, ~70 fields)

Every <details> section carries a configured-field count badge in its summary, so users editing an existing host can see at a glance which sections are non-default without expanding any. Plus a sticky save bar that floats at the bottom whenever the in-form Save button scrolls offscreen.


πŸ”¬ Live route-JSON preview v2.11.13

A new collapsed <details> at the bottom of the proxy-host edit form shows the exact Caddy route JSON the form would push, refreshing ~500ms after the last keystroke or toggle. Reuses the same parseProxyHostForm + caddy.BuildProxyRoute path as createProxyHost, so what the user sees here is exactly what gets pushed on save β€” byte-for-byte.

Lenient on missing required fields (v2.11.17 / v2.11.18): empty forward_port / forward_host / domains render as visible placeholders instead of leaking the raw strconv.Atoi error to the user. The strict parser is still used at save time β€” only the preview path is forgiving.

Why this matters in practice. Debugging "why isn't this header being added" or "why isn't path matching firing" used to mean save β†’ check caddy_config β†’ adjust β†’ save again. Now the JSON updates as you toggle. First-class loop closure for the form-driven workflow.

πŸ“Š Dashboard widgets β€” Recent edits + fleet health v2.11.12, v2.11.16

Two new strips on the dashboard:


πŸ€– AI assistant via local Ollama v2.11.15

Opt-in floating chat button (bottom-right) that proxies prompts to a local Ollama instance for "explain this proxy host", "convert this Caddyfile snippet", "suggest headers for Nextcloud", etc. Runs locally on your GPU β€” no cloud calls, no telemetry, no third-party API keys.

Configure under Settings β†’ AI assistant:

The backend wraps the user prompt in a CaddyUI-flavoured system prompt that steers generic-knowledge models toward Caddy / TLS / DNS answers. 60-second context-deadline on the upstream call so a slow Ollama doesn't park a request handler indefinitely.


🌐 Managed DNS β€” wildcards, ACME, redirections v2.11.14, v2.11.19, v2.12.2

Three big DNS / cert improvements stitched together this cycle:

v2.11.14 β€” Notifier covers Caddy-managed live certs

The expiry notifier used to inspect only custom certs stored in CaddyUI's DB. Production deployments using ACME / Let's Encrypt auto-issuance got no warning when those expired. v2.11.14 adds a daily TLS dial against {first_domain}:443 for every enabled SSL-on proxy host, reads the peer cert, and fires the same webhook + email channels when expiry is within the configured threshold. Wildcard SANs are skipped (can't dial them directly). Dedup keys are prefixed proxy: so they don't collide with custom-cert keys.

v2.11.19 β€” Wildcard cert auto-issuance via DNS-01

Type *.example.com in Domains and a yellow callout appears under the field: "Wildcard SAN detected. Wildcards can only be issued via the ACME DNS-01 challenge β€” HTTP-01 can't validate them." Pick Cloudflare in the Managed DNS section below and syncCaddy automatically pushes a matching apps.tls.automation.policies entry using the Cloudflare token already stored for managed-DNS A-record CRUD. No second token entry, no manual JSON.

Caveat. Caddy must include the matching caddy-dns/cloudflare plugin (xcaddy build). Default caddy:2-alpine has no DNS plugins; CaddyUI surfaces "unknown module" errors as sync_apply_automation_failed in the activity log if the plugin's missing. Cloudflare-only at GA β€” other DNS providers slot into caddyDNSProviderConfig as their plugin schemas are confirmed.

v2.12.2 β€” Managed DNS for redirection hosts

The long-standing gap closed. Proxy hosts got Managed DNS in v2.5.6, raw routes got it in v2.5.6 β€” but redirections were skipped. The db.go comment even said "redirection_hosts don't create records." Not anymore.

Providers supported: Cloudflare, DigitalOcean, Hetzner, Porkbun, GoDaddy, Namecheap. Same picker, same flow, every resource type.


πŸ“¦ Upgrade

docker compose pull && docker compose up -d

Or in Portainer: Recreate β†’ enable Re-pull image. Migrations run automatically on startup. No downtime beyond the container restart.

Multi-arch on Docker Hub (linux/amd64 + linux/arm64, SBOM + provenance attestations, scratch base, non-root UID 10001):

# pinned to this exact release (recommended)
docker pull applegater/caddyui:v2.12.12

# rolling tags β€” all four point at the same image right now
docker pull applegater/caddyui:latest
docker pull applegater/caddyui:stable
docker pull applegater/caddyui:preview

:latest and :stable retag here, replacing v2.12.4. Eight patch versions in this wave (v2.12.5 β†’ v2.12.12), headlined by the AI tool-calling feature.

πŸ—ΊοΈ On the whiteboard

Want something specific? Open an issue on GitHub.