Domains and automatic HTTPS

Serve Workforce Intelligence on your own domain with a certificate that Caddy obtains and renews for you.

For: Administrators configuring a domain · Last updated

The web container runs Caddy. Without a domain it serves plain HTTP on port 80. When you give it a domain, Caddy's automatic HTTPS takes over: it obtains a real Let's Encrypt certificate, listens on port 443, redirects HTTP to HTTPS, and renews the certificate on its own. There is nothing else to configure.

Set up a domain#

  1. Point a DNS record for your domain at the box's public address. On AWS you can have the CloudFormation template create the Route 53 record with the DomainName and HostedZoneId parameters. That requires AllocateElasticIp=true, because a record pointing at an ephemeral IP would break on every stop and start. See Install on AWS with CloudFormation.

  2. Make sure ports 80 and 443 are reachable from the public internet. The certificate authority verifies the domain over them, and a box that is only reachable through NAT cannot complete verification.

  3. Edit .env (/opt/wi/.env on AWS) and set these keys. Each must appear once, so edit an existing line rather than adding a second one.

    WI_DOMAIN=wi.example.com
    WI_ALLOWED_ORIGIN=https://wi.example.com
    WI_DOKKU_SSH_HOST=wi.example.com
    

    WI_API_BASE_URL and WI_PUBLIC_BASE_URL follow WI_ALLOWED_ORIGIN automatically.

  4. Apply it:

    cd /opt/wi
    sudo docker compose -f docker-compose.prod.yml up -d
    

    On a first install, skip this step. install.sh starts everything.

WI_DOMAIN is the bare domain name. WI_ALLOWED_ORIGIN is the full origin, with https://. If WI_DOMAIN is blank or unset, the web container serves plain HTTP on port 80.

Where the certificate is kept#

Caddy keeps its certificates and its account with the certificate authority in the wi-prod-caddy-data Docker volume. Only the very first start of web runs the issuance. Later recreations, such as docker compose up -d or an in-app update, reuse the stored certificate.

Never delete the wi-prod-caddy-data volume. Let's Encrypt limits repeat issuance for the same domain, so deleting it can leave you unable to get a new certificate for a while.

Domains on the .dev top-level domain#

Chrome has the entire .dev top-level domain on its HSTS preload list. Chrome refuses plain HTTP for any .dev domain, so HTTPS has to work before the site is usable in that browser. Testing with curl over http:// can appear to work while the real browser does not.

Custom ports#

If you change WI_HTTP_PORT or WI_HTTPS_PORT, put the port in WI_ALLOWED_ORIGIN. Automatic certificate issuance still needs the certificate authority to reach the standard ports 80 or 443 on your domain.

What Caddy routes#

On the one origin, the web container serves the web app and forwards /api/*, /auth/*, and /healthz to the application. Deployed Apps are served under /apps/serve/<app id>/ on the same origin, so they need no separate hostname or wildcard certificate.