Appearance
HTTPS Certificates
Last updated
The appliance serves the web interface over HTTPS through nginx. Appliance → Certificates (admin only) shows the current certificate and lets you re-issue it, install your own, and help client devices trust it.
The current certificate
| Field | Meaning |
|---|---|
| Mode | ca (signed by the appliance's own certificate authority), self-signed, or uploaded (your own) |
| Expires | Expiry date |
| Covers | Every host name and IP address in the certificate. A browser reports a name mismatch for any address not listed. |
| Fingerprint | SHA-256 fingerprint, to compare with what a browser shows |
With no certificate installed the card says No certificate is installed — this appliance is serving plain HTTP.
Choosing a mode
| Mode | Client devices | Use for |
|---|---|---|
Certificate authority (ca, default) | Install the appliance's CA once per device; warnings then stop. No internet needed. | Most plants |
| Self-signed | Nothing to install; a warning on every new device (Self-signed: browsers warn on every new device…) | Bench tests and demos |
| Your own certificate | Nothing to install if your devices already trust the issuer | Sites with their own PKI or a real domain |
Appliance-issued certificates are valid for 824 days. Apple devices refuse certificates valid for more than 825 days, including those from private CAs.
Install the appliance CA on client devices
When a CA is present, the card Install this appliance's certificate authority on a device… shows a QR code and Open the setup instructions. Both point at http://<appliance>/tls-setup — plain HTTP on purpose, because a device that does not trust the appliance yet cannot load the HTTPS page without the warning.
- Windows / Chrome / Edge: download
scadaink-ca.crtfrom the setup page and install it into Trusted Root Certification Authorities. - iPhone / iPad: download the profile (
scadaink-ca.mobileconfig), install it in Settings, then turn it on under Settings → General → About → Certificate Trust Settings. The second step is the one people miss. - Android: install
scadaink-ca.crtas a CA certificate in security settings. - Firefox uses its own certificate store on every platform; import the CA in Firefox's settings as well.
Re-issue the certificate
- Under Re-issue certificate, pick
caorself-signed. - Tick Also generate a new certificate authority only if you must replace the CA (Every device that trusts this appliance will have to install the new authority again.).
- Click Re-issue certificate.
- A banner Confirm this certificate works counts down. Reload the page over HTTPS. If it loads without a warning, click Keep this certificate.
- If something is wrong, click Restore the previous certificate, or wait: the old certificate returns automatically after 5 minutes, or 30 minutes when the CA changed (time to install the new CA on the device you are using).
Re-issuing with the same CA keeps every client trusting the appliance; nothing needs reinstalling. While a change awaits confirmation, further changes are refused (A certificate change is still awaiting confirmation…).
The certificate is also re-issued automatically, without a confirm step, after a hostname or IP address change.
Use your own certificate
1. Request a certificate
- Enter Common name (e.g.
scada.plant.example), optional Organization, and the Addresses this appliance is reached on, comma separated — every DNS name and IP clients use, e.g.scada.plant.example, scada-line3, 192.168.10.50. At least one is required; browsers ignore the common name. - Click Generate request, then Download .csr. The private key is created on the appliance and never leaves it.
- Send the
.csrto your certificate authority.
2. Install the signed certificate
- Paste the signed certificate (PEM) into the first box.
- Paste intermediate certificates, leaf first, into the second box (optional, but most CAs need it).
- Leave the key box empty if you generated the request here. Paste an unencrypted PEM key only if the certificate was requested elsewhere.
- Click Install certificate, then confirm within 30 minutes as above.
Before nginx sees it, the appliance rejects an expired certificate, a key that does not match, and a chain in the wrong order, each with the reason. It warns (but installs) when the certificate covers none of the appliance's current addresses, or when no intermediates were supplied. If nginx rejects the files, the previous certificate is restored at once.
An uploaded certificate is not re-issued automatically when the hostname or IP changes; the API log warns that it may no longer match.
Expiry
From 60 days before expiry the tab shows This certificate expires soon (or has expired), and the appliance logs a reminder daily. Re-issue before it lapses: an expired certificate makes browsers refuse to connect over HTTPS.
ACME (Let's Encrypt)
Requires the acme_certificates license feature, outbound internet to the CA, and a real domain name that resolves to the appliance. Validation is DNS-01: you publish a _acme-challenge TXT record, so no inbound access is needed. The only DNS option shipped is manual (Add the TXT record myself).
Set it up on System → Appliance → Certificates, in the Certificate from a public authority card (administrators only; the card is hidden when the feature is not licensed, and the endpoints answer ACME certificates are not enabled on this appliance.).
- Tick Keep this certificate up to date automatically.
- Enter the Domain names — comma-separated, each pointing at this appliance — and a Contact email, which the authority uses for expiry warnings.
- Leave Practice mode on for the first run. It uses Let's Encrypt's staging service, so a mistake doesn't use up your few real attempts per week; the certificate it issues is not trusted by browsers. Turn it off and issue again for the real one.
- Leave How the DNS record is published on Add the TXT record myself — it is the only option shipped.
- Save settings, then Get the certificate now. Leave the page open: the request waits for the authority, which takes minutes.
- A Waiting for DNS records box appears with the TXT records to publish. Create them at your DNS host; the page rechecks every 10 seconds.
- The certificate installs like an uploaded one and must be confirmed within 30 minutes — the confirm banner appears at the top of the tab.
The directory URL follows Practice mode on its own, so switching practice off cannot leave the staging service in place. To use a different authority, send your own directoryUrl over the API; a URL that is not one of Let's Encrypt's is kept as given.
The same thing over the API:
bash
curl -sk -X PUT $HOST/api/appliance/tls/acme -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"enabled": true, "directoryUrl": "https://acme-v02.api.letsencrypt.org/directory",
"email": "controls@plant.example", "domains": ["scada-line3.plant.example"],
"dnsProvider": "manual"}'- Start the order with
POST /api/appliance/tls/acme/issue. The request waits until validation finishes, which can take minutes. - Meanwhile, read the record to publish from
GET /api/appliance/tls/acme(pendingChallenges) or the API log (ACME: waiting for a DNS TXT record. Create _acme-challenge.… with value …), and create it in DNS. - The certificate is installed like an uploaded one and must be confirmed within 30 minutes: read the token from
GET /api/appliance/tls(pendingRollback.token) and send it toPOST /api/appliance/tls/confirm. Otherwise the previous certificate is restored.
Renewal is attempted hourly once the certificate is within 30 days of expiry. With the manual DNS option each renewal needs a new TXT record, and an unattended renewal is not confirmed, so it reverts after 30 minutes — plan to renew by hand. Domains must be names, not IP addresses ("…" is an IP address. A public CA cannot issue for one…).
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /api/appliance/tls | Status, SANs, expiry, pending change and its token |
| POST | /api/appliance/tls/regenerate | { "mode": "ca" } or "self-signed"; "force": true for a new CA |
| POST | /api/appliance/tls/confirm | { "token" } |
| POST | /api/appliance/tls/revert | Restore the previous certificate now |
| POST | /api/appliance/tls/csr | { "commonName", "organization", "sans": [...] } → CSR text |
| GET | /api/appliance/tls/csr | Download the outstanding CSR again |
| POST | /api/appliance/tls/upload | { "cert", "chain", "key" } |
| GET | /api/appliance/tls/acme | ACME config, DNS providers, pending TXT records |
| PUT | /api/appliance/tls/acme | Save ACME config |
| POST | /api/appliance/tls/acme/issue | Order a certificate |
Troubleshooting
| Message | Cause | Fix |
|---|---|---|
| This private key does not match this certificate. | Certificate was issued for another key | Use the CSR generated here, or paste the matching key |
| This certificate expired on … | Expired certificate | Get a new one |
| The chain does not contain any PEM certificates. / chain order error | Intermediates missing or root listed first | Paste intermediates leaf-first, without the root |
| No private key. Upload the key alongside the certificate, or generate a CSR here first… | Requested elsewhere and no key pasted | Paste the key |
| The private key could not be read. It must be an unencrypted PEM key. | Encrypted key | Decrypt it (openssl pkey -in key.pem -out plain.pem) |
| At least one DNS name or IP address is required — browsers ignore the common name. | Addresses box empty | Fill in addresses |
| Browser says name mismatch | The address you typed is not under Covers | Re-issue (appliance modes) or get a certificate that includes it |
| iPhone still warns after installing the profile | Trust not enabled | Settings → General → About → Certificate Trust Settings |
| Certificate reverted on its own | Not confirmed in time | Re-issue and click Keep this certificate |