Caddy now serves both :80 (plain HTTP, unchanged default) and :443 with tls internal — it generates its own per-box root CA on first start, stored under /var/lib/caddy/.local/share/caddy/pki/authorities/local/. Users can download rootCA.crt at /rootCA.crt (served on both listeners) and install it per-OS via the new /https-install/ guide. Settings page grows a Local HTTPS card with CA fingerprint, download button, reachability probe, and an opt-in "force HTTPS" toggle. The toggle only unhides itself once the current browser already trusts the cert, so enabling it can't lock the user out of the settings page. Backend: GET /api/furtka/https/status and POST /api/furtka/https/force in furtka.https. The force toggle drops a Caddy import snippet into /etc/caddy/furtka.d/redirect.caddyfile and reloads Caddy; reload failure rolls the snippet state back so a bad config can't wedge the next service start. updater._refresh_caddyfile() ensures /etc/caddy/furtka.d exists before every reload so 26.3-alpha → 26.4-alpha self-updates don't trip on the new glob import directive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
65 lines
2.1 KiB
Caddyfile
65 lines
2.1 KiB
Caddyfile
# Serves the Furtka landing page + live JSON on :80 (plain HTTP) and :443
|
|
# (HTTPS via Caddy's built-in `tls internal` — locally-issued certs signed
|
|
# by a root CA that Caddy generates on first start and stores under
|
|
# /var/lib/caddy/.local/share/caddy/pki/authorities/local/). Static pages
|
|
# are read from /opt/furtka/current/ — updates flip the symlink and
|
|
# everything picks up the new content without a Caddy restart (a
|
|
# `systemctl reload caddy` is still triggered post-swap to flush the
|
|
# file-server's handle cache). /apps and /api are reverse-proxied to the
|
|
# resource-manager API (furtka serve, bound to 127.0.0.1:7000).
|
|
#
|
|
# Force-HTTPS: /etc/caddy/furtka.d/*.caddyfile gets imported into the :80
|
|
# block. The /api/furtka/https/force endpoint creates or removes
|
|
# redirect.caddyfile there to toggle the HTTP→HTTPS redirect, then reloads
|
|
# Caddy. Glob imports silently no-op on an empty/missing directory, so the
|
|
# toggle-off state is "no file present" rather than "empty file".
|
|
(furtka_routes) {
|
|
handle /api/* {
|
|
reverse_proxy localhost:7000
|
|
}
|
|
handle /apps* {
|
|
reverse_proxy localhost:7000
|
|
}
|
|
# Runtime JSON lives under /var/lib/furtka/ so it survives self-updates
|
|
# (which only swap /opt/furtka/current).
|
|
handle /status.json {
|
|
root * /var/lib/furtka
|
|
file_server
|
|
}
|
|
handle /furtka.json {
|
|
root * /var/lib/furtka
|
|
file_server
|
|
}
|
|
handle /update-state.json {
|
|
root * /var/lib/furtka
|
|
file_server
|
|
}
|
|
# Download the local root CA cert Caddy generated for `tls internal`.
|
|
# Available on both :80 and :443 so users can grab it before they've
|
|
# trusted it. The private key next to it stays 0600 / caddy-owned.
|
|
handle /rootCA.crt {
|
|
root * /var/lib/caddy/.local/share/caddy/pki/authorities/local
|
|
rewrite * /root.crt
|
|
file_server
|
|
header Content-Type "application/x-x509-ca-cert"
|
|
header Content-Disposition "attachment; filename=furtka-local-rootCA.crt"
|
|
}
|
|
handle {
|
|
root * /opt/furtka/current/assets/www
|
|
file_server
|
|
encode gzip
|
|
}
|
|
log {
|
|
output stdout
|
|
}
|
|
}
|
|
|
|
:80 {
|
|
import /etc/caddy/furtka.d/*.caddyfile
|
|
import furtka_routes
|
|
}
|
|
|
|
:443 {
|
|
tls internal
|
|
import furtka_routes
|
|
}
|