HTTPS and Let's Encrypt
The Orchestrator serves plain HTTP unless you give it a certificate. It supports four setups.
| Setup | Settings |
|---|---|
| Plain HTTP (the default) | None. Port ORC_PORT (8080). |
| Your own certificate | ORC_CERT_FILE, plus ORC_CERT_FILE_PRIVATE_KEY for a PEM, and ORC_CERT_PWD for a PFX or an encrypted key. |
| A self-signed certificate | ORC_CERT_SELF_SIGNED=true. |
| Let's Encrypt | ORC_LETSENCRYPT=true with ORC_LETSENCRYPT_EMAIL and ORC_LETSENCRYPT_ACCEPT_TERMS=true. |
With a certificate, ORC_PORT defaults to 443. ORC_PORT_LOCAL (default 8080) adds a plain HTTP port that listens on loopback only, or on every address with ORC_REDIRECT_TO_HTTPS=true. Set it to 0 to disable it. ORC_USE_HSTS=true adds HSTS headers.
Your own certificate
ORC_CERT_FILE takes a PFX, a CER or a PEM certificate. For a PEM, set ORC_CERT_FILE_PRIVATE_KEY to the key. To redirect http:// to HTTPS, set ORC_PORT_HTTP=80. The certificate has to cover *.<your host> as well when you use subdomain routing.
Self-signed
ORC_CERT_SELF_SIGNED=true generates a certificate valid for 5 years (RSA 2048) into ORC_STORAGE/self.pfx and reuses it. It names the host of ORC_PUBLIC_ADDRESS and *.<that host>. Browsers warn about it. It is the right choice for a try-out or for traffic inside a private network.
Let's Encrypt
ORC_ADMIN_PASSWORD='choose-a-password' ORC_PUBLIC_ADDRESS=https://workspaces.example.com \
ORC_LETSENCRYPT=true ORC_LETSENCRYPT_EMAIL=ops@example.com ORC_LETSENCRYPT_ACCEPT_TERMS=true \
curiosity-orchestrator
The Orchestrator picks a certificate per host name (SNI).
| Host name | Certificate |
|---|---|
workspaces.example.com (ORC_LETSENCRYPT_DOMAINS) |
One certificate for all of the Orchestrator's own names, issued at start-up. |
aviation.workspaces.example.com |
The workspace's own, issued at start-up or, for a workspace created later, on the next pass (10 minutes, or 15 after an issuance). |
| Anything else: an IP address, no SNI, a name still waiting | The fallback: ORC_CERT_FILE when set, otherwise the self-signed certificate. |
Requirements
- Ports 443 and 80 reachable from the internet, and DNS for every name pointing at the server. A wildcard record covers the workspaces.
- Validation uses TLS-ALPN-01 on 443, with HTTP-01 on
ORC_PORT_HTTPas the alternative.ORC_PORT_HTTPdefaults to80with Let's Encrypt. It answers challenges and redirects everything else to HTTPS with a307. ORC_LETSENCRYPT_EMAILandORC_LETSENCRYPT_ACCEPT_TERMS=trueare required. The second accepts the subscriber agreement.
What it does not do
- No wildcard certificate. That needs a DNS challenge, so each workspace gets its own certificate. Turn per-workspace certificates off with
ORC_LETSENCRYPT_WORKSPACES=false. - Rate limits apply. Let's Encrypt issues 50 certificates per registered domain per week, and each workspace is one. Use
ORC_LETSENCRYPT_STAGING=truewhile trying things out.
Renewal, failures and status
- Renewal starts 30 days before expiry. Certificates and the account key are kept in
ORC_STORAGE/letsencryptand loaded at start-up, so a restart orders nothing. Back that folder up with the rest ofORC_STORAGE. - Failures (DNS not set up yet, a port closed) are retried after 15 minutes. That stays under Let's Encrypt's limit of 5 failed validations per name per hour, and the fallback answers meanwhile. If certificate management stops on an unexpected error, for example the CA being unreachable at start-up, it starts again after 15 minutes.
- Status: Settings in the console lists every name with its state (valid, waiting, expiring, expired, fallback), its issuer and its expiry. Scripts can read
GET /api/admin/https.
Staging first
Start with ORC_LETSENCRYPT_STAGING=true. The certificates are untrusted, so browsers warn, but the rate limits are much higher. When everything works, remove the setting and delete the staging certificates:
sudo systemctl stop curiosity-orchestrator
sudo rm -rf "$ORC_STORAGE/letsencrypt"
sudo systemctl start curiosity-orchestrator
A private CA
ORC_LETSENCRYPT_SERVER points at another ACME directory, and ORC_LETSENCRYPT_ISSUERS lists PEM files of that CA's root and intermediates, comma separated. The ACME client follows Let's Encrypt's behavior. A CA that requires POST-as-GET to read an account's orders fails the first order, and one that rejects a repeated terms of service agreement fails on every restart. Try a private CA with staging data first.
A separate host for the console
ORC_MANAGEMENT_HOST=manage.example.com makes the console and its API answer only on that host, and workspaces are not served there. Let's Encrypt includes the name in the Orchestrator's certificate. See Security.