Skip to content

soc-ai 1.5.2

soc-ai 1.5.2 is the TLS release. TLS has two paths. The proxy path is the production path: Caddy terminates TLS in front of soc-ai and renews the certificate. The direct path is the default after setup.sh. On that path, uvicorn terminates TLS with a certificate file and a key file. soc-ai now validates those files, reports them, and warns before they expire. The full list is in CHANGELOG.md under 1.5.2.

The proxy path

One command puts Caddy in front of soc-ai:

scripts/tls-proxy.sh enable soc-ai.example.com [auto|internal|<cert.pem> <key.pem>]

The caddy service lives in docker-compose.yml under the proxy profile. The script writes the proxy settings to .env, starts the stack and waits for the certificate. It writes COMPOSE_PROFILES=proxy, so every later docker compose up -d keeps Caddy. Caddy gets its certificate in one of three ways:

  • auto, the default: automatic HTTPS from Let's Encrypt. The name must resolve to the host on the public internet. Ports 80 and 443 must be reachable from the internet.
  • internal: a certificate from Caddy's own CA. The script exports the root as caddy-root.crt and prints the steps to trust it on each client.
  • <cert.pem> <key.pem>: a certificate from your own CA. The script copies the two files into ./certs/.

soc-ai serves plain HTTP inside the compose network. SOC_AI_TLS_CERT and SOC_AI_TLS_KEY stay blank. SOC_AI_BIND=127.0.0.1 keeps port 8443 on the host loopback. PROXY_TRUSTED_IPS holds the compose network subnet, so soc-ai trusts the forwarded headers from Caddy. The Caddy container receives two variables, SOC_AI_DOMAIN and SOC_AI_CADDY_TLS, and no soc-ai secret. Caddy reloads a renewed certificate without downtime. scripts/tls-proxy.sh disable restores the direct path. scripts/tls-proxy.sh status prints the mode and one health check. setup.sh asks for the HTTPS domain, so a new install can start on the proxy path. DOCKER.md, TLS paths, holds the details. DEPLOYMENT.md holds the host Caddy recipe for a source install.

The direct path

soc-ai reads the certificate and the key at start. It states the subject, the issuer, the names, the validity window, the chain order, the key match and the SHA-256 fingerprint.

  • The start log states the result. soc-ai starts with a bad certificate. The doctor, the bell and the webhook carry the warning.
  • soc-ai doctor has a tls check. PASS for a valid chain. INFO for a self-signed certificate. WARN 30 days before expiry, for a broken chain, and for plain HTTP on a non-loopback bind with no trusted proxy. FAIL for an expired or not yet valid certificate, a key that does not match, or a file that cannot be read.
  • The Config screen has a TLS panel. It shows the same record and a "Check again" button that reads the files on disk. After a swap it says "Restart soc-ai to load them" and names the restart command.
  • GET /api/v1/config/tls returns the record for an admin.
  • A daily check compares the days left on the certificate soc-ai serves against 30, 14 and 7. When the band changes it fires the tls_expiry notification and puts a row on the bell. A restart does not repeat the webhook. A swap on disk without a restart keeps the alarm.

Proxy trust

PROXY_TRUSTED_IPS accepts addresses and CIDR blocks. The HSTS header and the CSRF guard follow the same trusted proxy rule as the Secure cookie flag. A cookie write from the console therefore works behind Caddy. uvicorn's own proxy-header rewrite is off, so soc-ai holds one rule. The doctor warns when a trusted block covers every address.

Upgrade

  1. Docker: docker compose up -d --build. The container healthcheck now tries HTTPS and then HTTP. Source install: uv sync, copy scripts/systemd/soc-ai.service over the unit, run systemctl daemon-reload, then restart soc-ai. The unit now passes --no-proxy-headers and the cipher list.
  2. A self-signed certificate reads as INFO in the doctor and on the setup health card. Nothing turns amber on a stock install.
  3. To move to the proxy path, run scripts/tls-proxy.sh enable <domain>. The move needs one restart of soc-ai. The script does it.
  4. Set NOTIFY_ON_TLS_EXPIRY=false to keep the webhook quiet. The bell row stays.

Known limits

  • soc-ai loads the certificate once at start. A swap on disk needs a restart. The TLS panel and the doctor say so.
  • The doctor reads the files on disk. It cannot see the certificate a running soc-ai serves. The TLS panel and GET /api/v1/config/tls can, and they flag the difference.
  • soc-ai does not run ACME itself. The proxy path covers it.