Set up HTTPS
Prism needs HTTPS for anything other than a private trial. KiCad’s remote
symbol panel refuses a Prism that advertises http:// addresses, and most
identity providers refuse http:// redirect addresses.
How requests reach Prism
Section titled “How requests reach Prism”browser or KiCad -> HTTPS proxy -> frontend:80 -> backend:8000Point the proxy at the frontend container. It serves the web app and passes
/api/, /oauth/, /mcp, /git/, /remote-provider/ and the
/.well-known/ discovery documents to the API.
Whatever terminates HTTPS must:
- keep the public
Hostheader; - send
X-Forwarded-Proto: https.
Then set the public address in the environment file:
PUBLIC_BASE_URL=https://prism.example.comCORS_ORIGINS_STR=https://prism.example.comThe session cookie becomes Secure on its own once PUBLIC_BASE_URL is
https://. See Public address.
Choose a scheme
Section titled “Choose a scheme”| Scheme | Use it when | What you provide |
|---|---|---|
| Public certificate over HTTP-01 | The host is reachable from the internet. | A DNS name; ports 80 and 443 open. |
| Public certificate over DNS-01 | The host must stay internal, but browsers should trust it without a private CA. | A DNS provider API credential. |
| Your own certificate | You have an internal CA. | prism.crt and prism.key. |
| Tailscale | Your team already uses Tailscale. | MagicDNS and HTTPS certificates turned on. Installer only. |
| Existing reverse proxy | nginx, Traefik or a load balancer already terminates TLS. | Its configuration. |
| Plain HTTP | You are trying Prism on one machine. | Nothing. |
The guided installer offers all six and writes the files for you. The steps below are for a release bundle, which you configure by hand.
Public certificate over HTTP-01
Section titled “Public certificate over HTTP-01”-
Point a DNS record for your host name at the server.
-
Open ports 80 and 443 to the internet.
-
In
Caddyfile, replaceprism.example.comwith your host name. -
Set
PUBLIC_BASE_URLandCORS_ORIGINS_STRtohttps://and that name. -
Start with the proxy profile:
Terminal window docker compose --profile proxy up -d --wait
Caddy obtains and renews the certificate from Let’s Encrypt.
If port 80 or 443 is already taken on the host, set PRISM_CADDY_HTTP_PORT and
PRISM_CADDY_HTTPS_PORT in .env and include the port in the public address,
for example https://prism.example.com:8443. HTTP-01 needs ports 80 and 443
reachable from the internet, so with other ports use DNS-01 or your own
certificate.
Public certificate over DNS-01
Section titled “Public certificate over DNS-01”DNS-01 proves you own the name by publishing a TXT record. Ports 80 and 443 stay closed to the internet, the DNS record may exist only in internal DNS, and no private CA has to reach the KiCad workstations. In exchange the host holds a DNS credential and runs a custom Caddy image.
-
Build a Caddy image with your DNS provider’s module. The stock
caddy:2image cannot do DNS-01. From the bundle directory:Terminal window docker build -f Dockerfile.caddy-dns --build-arg DNS_PROVIDER_MODULE=github.com/caddy-dns/cloudflare -t kicad-prism-caddy-dns:2 . -
Check that the module is in the image. The command must print a line:
Terminal window docker run --rm kicad-prism-caddy-dns:2 caddy list-modules | grep dns.providers -
Create the narrowest credential your provider allows. For Cloudflare that is an API token with Zone / DNS / Edit on the one zone, not the Global API Key.
-
Copy
Caddyfile.dns-01overCaddyfile. Set the host name and your provider’sdnsline, and uncomment the stagingcaline for the first run. -
Set
PRISM_CADDY_IMAGE=kicad-prism-caddy-dns:2and the credential, for exampleCLOUDFLARE_API_TOKEN, in.env. -
Pass the credential to the proxy with an override file, so
compose.ymlstays untouched:docker-compose.dns-01.yml services:caddy:environment:- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN:?Set CLOUDFLARE_API_TOKEN in .env} -
Start, and watch issuance in the proxy log:
Terminal window docker compose -f compose.yml -f docker-compose.dns-01.yml --profile proxy up -d --waitTerminal window docker compose -f compose.yml -f docker-compose.dns-01.yml logs -f caddy -
When the staging certificate is issued, comment the
caline out again, stop the stack, remove the Caddy data volume so the staging account goes with it, and start again:Terminal window docker volume rm kicad-prism_caddy-data
An installer deployment does step 8 with ./deploy.sh --promote.
Check issuance in the proxy log, not in a browser. Prism sends
Strict-Transport-Security for one year, so once a name has served a trusted
certificate, browsers refuse to make an exception for the staging one.
If your DNS team will not hand out a credential for the whole zone, delegate only the challenge record to a separate zone that this deployment controls:
_acme-challenge.prism.example.com. CNAME prism.acme-delegation.example.Things to know:
-
Container traffic must reach the certificate authority and the DNS provider’s API. A filter that intercepts them makes the failure look like a TLS error against
acme-v02.api.letsencrypt.org. Test from inside the container:Terminal window docker compose exec caddy nslookup acme-v02.api.letsencrypt.org -
Every certificate is published in Certificate Transparency logs, so the host name becomes public within minutes even though the service is internal.
-
Renewal is automatic at about 30 days before expiry, but needs the DNS credential to still be valid. Track its expiry too.
Your own certificate
Section titled “Your own certificate”-
Copy
Caddyfile.internaloverCaddyfileand set your host name. -
Put
prism.crtandprism.keyincerts/. -
Install the issuing root CA on every browser and KiCad workstation.
-
Start with the proxy profile:
Terminal window docker compose --profile proxy up -d --wait
Bare IP addresses
Section titled “Bare IP addresses”Browsers and Windows send no server name when the address is an IP, so Caddy
cannot pick a certificate and the handshake fails (ERR_SSL_PROTOCOL_ERROR in
Chrome). Name the IP in a global default_sni block at the top of the
Caddyfile and use it as the site address:
{ default_sni 192.168.1.20}
192.168.1.20 { tls /certs/prism.crt /certs/prism.key # the rest of the site block from Caddyfile.internal}The certificate must list the address as an IP subject alternative name, and
PUBLIC_BASE_URL must be https://192.168.1.20. Public certificates cannot be
issued for a private IP. A DNS name, even an internal-only one, avoids all of
this.
Tailscale
Section titled “Tailscale”Tailscale Serve terminates HTTPS under the node’s MagicDNS name and issues and renews the certificate. There is no public DNS record, no open inbound port and nothing to renew. Only devices on your tailnet can reach Prism.
Turn on MagicDNS and HTTPS Certificates on the DNS page of the Tailscale admin console, then run the installer and choose Tailscale. It offers two modes:
-
Use this host’s Tailscale, when the server is already on the tailnet. No container is added. Point Serve at the frontend once; it survives reboots:
Terminal window tailscale serve --bg 8080 -
Sidecar, when it is not. The installer adds a Tailscale container that joins the tailnet with a reusable auth key. Leave the key’s Ephemeral option off, or the node may come back under a new name and certificate.
Existing reverse proxy
Section titled “Existing reverse proxy”- Start Prism without the proxy profile.
- Route your proxy to
http://127.0.0.1:8080. - Keep the
Hostheader and setX-Forwarded-Proto: https. - Allow request bodies up to 2 GB and read timeouts of a few minutes. Library imports upload large files, and some API calls run long.
deploy/nginx-tls.conf.example in the repository is a starting point for
nginx. With several proxies in a row, set PUBLIC_BASE_URL; it wins over any
forwarded header.
Plain HTTP for a trial
Section titled “Plain HTTP for a trial”The installer’s plain HTTP scheme runs Prism without TLS on one machine. The
KiCad remote symbol panel does not work with it, and most identity providers
refuse its redirect address, so the installer offers to turn sign-in off. The
guest then gets the viewer role, and the port is bound to 127.0.0.1.
Everything else works.
Prism refuses to start with sign-in off when PUBLIC_BASE_URL is https://,
or when it names another host and the guest role is admin.
Check the result
Section titled “Check the result”Every address in these two documents must start with your public https://
address:
curl -fsS https://prism.example.com/.well-known/kicad-remote-providercurl -fsS https://prism.example.com/oauth/.well-known/oauth-authorization-serverIf they show http://:
- Set
PUBLIC_BASE_URL=https://<your host>. - Make the outer proxy keep
Hostand sendX-Forwarded-Proto: https. - Recreate the containers and fetch the documents again.