Skip to content

Latest commit

 

History

History
89 lines (65 loc) · 3.9 KB

File metadata and controls

89 lines (65 loc) · 3.9 KB

SSL Certificates & HTTPS

Chronicle uses Caddy for automatic HTTPS — for both the advanced backend and the speaker-recognition service — so certificates are obtained and renewed automatically.

Why HTTPS is Needed

Modern browsers require HTTPS for:

  • Microphone access over network (not localhost)
  • Secure WebSocket connections (WSS)
  • Remote access via Tailscale/VPN
  • Production deployments

Note: the native mobile app does not require HTTPS — only browsers do.

How certificates are managed

Both services front their containers with Caddy:

Service Config HTTP → HTTPS ports
Advanced Backend backends/advanced/Caddyfile 80443
Speaker Recognition extras/speaker-recognition/Caddyfile 80818444

The wizard records the chosen approach as HTTPS_CERT_MODE in each service's .env:

caddy mode (default)

Caddy obtains and auto-renews the certificate itself — no cert files on disk, no renewal cron. The Caddyfile has no tls directive; Caddy picks the right source from the site address:

  • *.ts.net (Tailscale) → fetched from the local tailscaled at TLS-handshake time. The wizard mounts the host tailscaled.sock into the Caddy container via a generated docker-compose.override.yml. Trusted on all devices in your tailnet.
  • Real domain → Let's Encrypt via ACME (requires ports 80/443 reachable). Trusted everywhere.
  • IP address / localhost → Caddy's internal CA (self-signed). Browsers show a warning you can accept; the native app connects fine.

Renewal is automatic (~30 days before expiry), so a Caddy-managed deployment never hits an expired cert.

static mode (Docker Desktop + Tailscale fallback)

On Docker Desktop (macOS/Windows) the tailscaled socket isn't reachable from the Docker VM, so Caddy can't fetch a *.ts.net cert. There the wizard issues the cert on the host (tailscale certcerts/server.crt/server.key, mounted into Caddy) and the Caddyfile includes a tls /certs/... directive. services.py renews it on every ./start.sh / ./restart.sh if it's within 21 days of expiry — no cron needed, since those boxes restart frequently.

Setup via Wizard

When you run ./wizard.sh, the wizard:

  1. Asks if you want to enable HTTPS
  2. Prompts for your Tailscale name, domain, or IP
  3. Picks caddy or static mode automatically (based on the address and whether the tailscaled socket is available)
  4. Generates the Caddyfile (and, for Caddy-managed Tailscale, the socket-mount override)
  5. Updates CORS settings for HTTPS origins

No manual certificate generation required.

Browser Certificate Warnings

For *.ts.net and real domains the certificate is publicly trusted — no warning. For an IP or localhost address Caddy serves a self-signed internal-CA cert, so browsers warn:

  1. Click "Advanced"
  2. Click "Proceed … (unsafe)"
  3. Microphone access will now work

Troubleshooting

HTTPS not working:

  • Check the Caddy containers are running: docker compose ps (look for caddy)
  • Confirm the served cert: echo | openssl s_client -connect localhost:443 -servername <your-name> 2>/dev/null | openssl x509 -noout -issuer -enddate
  • For Caddy-managed Tailscale, confirm the socket is mounted: docker inspect <caddy-container> --format '{{range .Mounts}}{{.Destination}} {{end}}' should list /var/run/tailscale/tailscaled.sock
  • Check you're using https:// not http://

Tailscale cert won't issue (500 ... failed to create DNS record):

Microphone not accessible:

  • Ensure you're accessing via HTTPS (not HTTP)
  • Accept the browser certificate warning (IP/localhost only)
  • From a remote device use the Tailscale name/IP, not localhost