0.4 HTTPS, certificates and trust
Checked against the curl reference and Let's Encrypt's own documentation, August 2026
What this is and why it exists
Everybody has clicked through a certificate warning. In your own browsing that is a small gamble; on a server you run, it is the moment you stop being able to tell a broken renewal from an interception. This lesson gives you the model to read the error instead of dismissing it — and the model is short, because a certificate does exactly one job and people expect it to do four.
The vocabulary
- Certificate — a file holding a public key plus the names it is valid for, signed by somebody else.
- Certificate authority (CA) — an organisation browsers and operating systems have agreed to believe, which signs certificates after checking something.
- Chain — the ladder from your certificate up through intermediates to a root the client already holds.
- Root store — the list of roots your browser or operating system trusts; it ships with the software, not with the website.
- Domain validation — the check that you control the name, and the only thing most certificates prove.
- Expiry — the end of validity, which arrives on a fixed date whether or not anyone is watching.
- ACME — the protocol an automated client uses to request and renew a certificate without a human.
- Self-signed certificate — one signed by its own key, so it encrypts fine and vouches for nothing.
The mental model
A certificate vouches for one thing: whoever holds this private key controls this name. It does not say the site is honest, safe, well-run, or the company you had in mind. Let's Encrypt describes the client proving control "by either provisioning a DNS record or creating an HTTP resource at a specified location", after which the authority verifies the challenge "from multiple network perspectives". Control of the name, nothing more — which is why a phishing site can hold a perfectly valid certificate for its own misspelled domain, and the padlock will be entirely honest about it.
Trust arrives as a chain, and that is where the confusing failures live. Your server sends its own certificate and, if configured correctly, the intermediates above it; the client walks upward until it reaches a root in its store. Forget an intermediate and the ladder has a rung missing — with the maddening symptom that it works in your browser and fails on a server, because browsers often cache intermediates they have met before and command-line tools do not. "Works for me" is not evidence here.
Expiry is a deadline, not a warning: at that instant every client rejects the certificate, with no grace period and no degraded mode. Let's Encrypt puts the numbers plainly — "our default certificates are valid for 90 days", short-lived ones "valid for six days", and "we recommend renewing 90 day certificates every 60 days and six day certificates every three days". Renewing at sixty of ninety is not caution for its own sake: it buys thirty days in which a failed renewal is a problem you notice rather than an outage. That is also why renewal is automated — a task nobody performs for two months is a task nobody remembers — and the one part of the loop a human must still own is being told when it fails.
The errors themselves are four families, however differently each browser words them:
- Expired — the date has passed. Renewal stopped working, usually weeks ago and silently.
- Name mismatch — a valid certificate, for some other name. Reaching a site by its IP address, or by a subdomain the certificate never listed, does this.
- Unknown issuer — the chain does not reach a root in this client's store: either a missing intermediate, or a signer nobody publicly trusts.
- Self-signed — a certificate vouching for itself, common inside private networks and on freshly built machines. Encrypted; nothing verified.
Only the last is ever routine to accept, and only on a machine you built, on a network you control, for a name you know. Everywhere else the fix is on the server.
Portable operations
The same tool inspects the connection everywhere; the manual lines are checked against the curl reference.
curl -I -L example.com
curl -v example.com-I fetches "the headers only" and -L follows redirects, so you see whether plain HTTP hands you to HTTPS as it should. -v enables "a full verbose printout of all incoming and outgoing data, including headers" — where the negotiation and the certificate problem appear in words rather than as a picture of a padlock.
There is one flag to know so you never reach for it casually. -k, also written --insecure, allows curl — in the manual's own wording — to perform insecure SSL connections, which is to say it proceeds when verification fails. It is a debugging instrument: use it once to confirm verification is the failing step, then go and fix the certificate. A script carrying it permanently has quietly made encryption-without-identity its normal state, and that is precisely the state certificate errors exist to warn about.
Renewal belongs to whichever ACME client your platform uses and the commands differ between them, so this lesson names the operation rather than guessing syntax: the client renews on a timer, writes the new certificate, and reloads the web server. Your client's reference is under Go deeper. What is portable is the check — confirm renewal has run at least once on its own before the first sixty days are up, and confirm you would hear about it if it stopped.
What you should now be able to explain or do
Say in one sentence what a domain-validated certificate proves, and name two things people wrongly assume it proves. Explain what an incomplete chain is and why it can fail on a server while working in your browser. Place a certificate error in one of the four families. Say why renewal is automated and scheduled well before expiry. Explain what -k does, and why a script that uses it permanently has given away the thing it thinks it has.
Check yourself
What does a domain-validated certificate actually vouch for?
That whoever holds the matching private key demonstrated control of that domain name. Not the honesty, safety or identity of the organisation behind it.
A page loads for you but a colleague's server-side script rejects the certificate. What is the likely cause?
A missing intermediate in what the server sends. Browsers often have it cached from other sites; a command-line client has nothing cached, so the chain never reaches a trusted root.
Certificates last ninety days by default. Why renew at sixty?
Because expiry has no grace period. Renewing thirty days early turns a failed renewal into a warning you have a month to act on, instead of an outage that starts at a fixed minute.
Your browser says the certificate is for a different name. What did you probably do?
Reached the site by its IP address, or by a hostname the certificate does not list. The certificate is fine; the name you used is not one it covers.
When is --insecure an acceptable thing to use?
Once, deliberately, to confirm that certificate verification is the failing step. Never as a permanent setting — that keeps the encryption and throws away the identity check, which is the whole point.
Go deeper
We haven't checked most of these for screen reader use yet.
Back to HTTPS, certificates and trust: work through the checklist