Two dates decide whether your app is still reachable next year: the day the domain renews and the day the certificate does. To add https to website traffic on a managed host is a setting; keeping it means HSTS, a CAA record, a locked registrar and a named renewal owner. An expired domain or a misissued certificate is an outage no code fix repairs.

What it takes to add https to website traffic and keep it

Adding HTTPS to a website and keeping it takes more than the certificate: a permanent redirect from HTTP with HSTS, a CAA record naming the certificate authority, a locked registrar, the DNS records exported into the runbooks, a named owner for both renewals, and an external TLS scan that proves the result.

This is one control in DevOps for startups: the release path, and it is the one that breaks on a calendar date rather than on a deploy. How to set up HTTPS depends on who runs the server; what has to be true afterwards does not. The table is my DNS and TLS launch checklist: each item, where it is set, and the date it depends on.

ItemWhere it is setThe date it depends on
HTTPS on every hostname, with a permanent redirect from HTTPThe host or CDN (Vercel forwards HTTP to HTTPS with a 308); a port 80 server block on your own nginxNone, until someone edits the config
HSTS on the HTTPS responseVercel’s default on custom domains (max-age=63072000); your server config elsewhereNone
Mixed content clearedYour app: every http:// image, video, stylesheet or script URL on an HTTPS pageEvery release that adds an asset
A CAA record naming the issuing authorityYour DNS hostThe host’s next issuance or renewal
The registrar locked against transferYour registrar account (clientTransferProhibited)None
The DNS records exported into the runbooksYour DNS host’s export, filed with a dateEvery DNS change
A named owner for both renewalsA shared calendar and one personThe domain’s renewal date and the certificate’s expiry date
An external TLS scan as the proofAn outside scanner, run per hostnameEach certificate renewal

The last two rows are what make this an SSL testing checklist rather than a setup list: the owner catches the lapse before it happens, and the scan is the evidence that the rest is true on the day it runs.

On a managed host most of the table is done for you. Vercel’s SSL documentation says Vercel will automatically try to generate a certificate for every domain once it is added to a project, and that this only works once the DNS records are added and propagated; it automatically attempts to renew the certificates it issues 14 to 30 days before they expire, and it cannot automatically renew certificates you upload yourself. Vercel’s encryption page adds that its CDN forwards any HTTP request to HTTPS with the 308 status code, and that custom domains use HSTS, but only for the particular subdomain, with max-age=63072000. On any other host, read that host’s own certificate page before assuming Vercel’s behavior carries over. On Lovable, the custom-domain and SSL states have their own write-up: a Lovable custom domain that will not go live.

Mixed content is the row no host can clear for you. web.dev on mixed content defines it as a page whose initial HTML loads over HTTPS while other resources, such as images, videos, stylesheets and scripts, load over HTTP, and says most browsers now block mixed content for security reasons. The API version of the problem, an https page that will not load your http API, is covered separately.

On a server you run, Certbot’s user guide describes both halves: obtaining a certificate, saving it to /etc/letsencrypt/live/ and renewing it on a regular schedule, with most installations running certbot renew from a scheduled task that comes preconfigured. To force SSL on nginx, add a server block for port 80 whose only job is a redirect: nginx’s page on converting rewrite rules documents the return 301 ...$request_uri form, and pointing it at HTTPS, as in server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; }, is my adaptation of its example, which redirects to another host.

The HSTS header’s value, the preload question and the rest of the security headers are in content security policy without unsafe-inline, HSTS and framing. This page covers getting the certificate there and keeping it there.

In the Production Hardening Sprint this is deliverable 7.13, Domain, DNS and TLS hygiene: we enforce HTTPS everywhere with HSTS and a CAA record, lock the registrar, document the DNS records, and confirm renewal ownership.

My audits put a number on the area this belongs to: across the 21 third-party apps scored on it, the Deployment & Operations pillar averages 37.0 out of 100. Those 21 are the 11 public and 10 held-out third-party apps I audited in June and July 2026, a selected set of audited apps, not a random sample or a rate for AI-built apps in general.

Your DNS records are a security control: DNSSEC, CAA, and certificate transparency

A CAA record is a DNS line that tells certificate authorities which of them may issue for your domain. DNSSEC signs the zone so a resolver can detect a forged answer. Certificate transparency logs publish issued certificates, so a certificate you never requested for your name can be found.

For one app, DNS cybersecurity comes down to those three plus the registrar settings further down (my reading). The CAA record is one line at your DNS host. RFC 8659 says it allows a domain name holder to specify the certificate authorities authorized to issue certificates for that domain name, and that where one exists a compliant CA must not issue unless the request is consistent with it or an exception in the CA’s own certificate policy or practice statement applies. Let’s Encrypt’s CAA page gives its identifying name as letsencrypt.org, so for a host that issues from Let’s Encrypt the line is example.com. CAA 0 issue "letsencrypt.org", and dig CAA example.com shows what is published.

The condition matters more than the syntax. Vercel’s guide on A records and CAA says a CAA record that doesn’t permit Let’s Encrypt blocks issuance, so a record naming the wrong authority stops the host’s next certificate. Vercel’s SSL page names the same cause among the issues to check if certificate renewal fails, so the damage shows up on renewal day, not on the day you edited DNS.

DNSSEC answers a different attack. ICANN’s DNSSEC explainer says that as the DNS was originally designed, a resolver cannot easily detect a forged response, and that DNSSEC strengthens DNS authentication using digital signatures; if a signature does not validate, the resolver assumes an attack and discards the data. My working rule is to turn it on where both the registrar and the DNS host support it.

Certificate transparency is the check that finds what CAA was meant to stop. crt.sh searches issued certificates by domain name, its advanced search offers a CT Entry ID search type, and its maintainers publish a certificate transparency log monitor alongside it. Search your domain there once and read the list: every certificate should be one you or your host asked for. A certificate transparency monitoring service then runs the same search on a schedule and alerts on anything new. If you would rather wire it into your own alerting, query the certificate transparency logs through a certificate monitoring API; crt.sh’s own pages do not state an API or an output format, so pick a tool whose docs do.

The quickest DNS safety check is the one for a hijack, and my working rule is to run it after every DNS change: compare the nameservers dig NS example.com returns with the ones your registrar shows, and the live records with your dated export. Alerting when a record or a nameserver changes belongs to your uptime monitor, which the key length section below links. As a checklist, my DNS security best practices for a one-app company are four items:

  1. 01 Publish a CAA record naming the authority your host issues from, then confirm it with dig CAA
  2. 02 Turn on DNSSEC where both the registrar and the DNS host support it
  3. 03 Search crt.sh for your domain and account for every certificate it lists
  4. 04 Compare dig NS and the live records with the dated export after every DNS change

What goes wrong without it: the domain expired and the site went offline

The expired domain is the slower outage and the harder one to undo. The pattern is dull: the card on file expired, or belonged to someone who has left, the renewal failed, and the site, the API and the email on that domain stopped together. A code fix cannot help, because the name no longer points at your app (my reading).

ICANN’s Expired Registration Recovery Policy sets the floor for gTLD names. Registrars must notify the registered name holder at least two times before expiration, approximately one month and approximately one week before, and send one more notice within five days after it. Registrars may delete a registration at any time after it expires; before that, they must interrupt the existing DNS resolution path for at least part of the time, to the extent the registry permits, and let the holder renew during that interruption. After a deletion, every gTLD registry except the sponsored ones must offer a Redemption Grace Period of 30 days, during which DNS resolution stays disabled. The policy requires registrars to make their redemption and restore fees available; it states no amount. It also says that when those notices normally go to an address on the domain in question and delivery is interrupted, they should go to another contact point, which matters if your renewal email lives on the same domain.

An SSL certificate that expired leaves the site not loading for everyone at once. Browsers refuse the connection, and so do API clients and webhook senders. Stripe’s webhook documentation says Stripe uses HTTPS to send webhook events, that registered webhook endpoints must be publicly accessible HTTPS URLs, and that it validates the connection is secure before sending, so the server needs a valid server certificate; its TLS error entry says issues with the certificate or an intermediate certificate in the chain usually cause those failures.

OutageWhat users seeWhat happenedWho can fix it
Expired domainThe site, the API and the email on the name stop resolving, or a registrar page says the name expiredThe registration was not renewed; the registrar interrupts the DNS resolution path, and after deletion the registry disables resolution for the 30-day Redemption Grace PeriodOnly whoever controls the registrar account
Expired certificateA browser warning page; API clients and webhook senders refuse the connectionThe certificate’s notAfter date passed because renewal failed, or nobody renewed an uploaded certificateWhoever controls the host’s domain settings or the server
Misissued certificateUsually nothing, because the certificate is valid for your nameAn authority issued a certificate for your name that you did not requestYou: a CAA record limits who may issue, and crt.sh shows what was issued

Certificate lifetimes are also shrinking on a fixed schedule. The CA/Browser Forum’s ballot SC-081 set out an eventual reduction of maximum validity from 398 days to 47 days, starting in March 2026 and concluding in March 2029. The Baseline Requirements put the steps at 200 days for certificates issued from March 15, 2026, 100 days from March 15, 2027, and 47 days from March 15, 2029. Let’s Encrypt’s default certificates already last 90 days, with six-day certificates as an opt-in. At those lengths renewal is automated or it fails, and an expired certificate does not quietly keep working: every client that checks it refuses, and the error table further down shows what they print.

Google’s incident report on Google Voice shows the same failure on a large system. Google says that due to an issue with updating certificate configurations, the active certificate in Google Voice frontend systems inadvertently expired at 23:51 on February 15, 2021 (US/Pacific); clients trying to establish or reestablish a SIP connection could not, and some new calls failed to connect over February 15 and 16, for a total of 4 hours 22 minutes. The team generated updated certificates and rolled them out, and its follow-up actions include additional proactive alerting for upcoming certificate expiration. The lesson I take from it is that automatic renewal moves the risk rather than removing it: someone has to be told when renewal fails, before the expiry date tells them.

What HTTPS prevents on a plain-HTTP first request is a separate topic: man-in-the-middle prevention. Pointing the domain at your host, and how long propagation takes, is in how to publish a website you built with AI.

Who controls the domain: domain management, the registrar lock and the accounts behind it

Domain management for a one-app company comes down to a few registrar settings: the transfer lock on, auto-renew on with a payment method the company controls, two-factor on the registrar and DNS host accounts, a dated DNS export in the runbooks, and a renewal date in a calendar with a named owner.

Whose account the domain and its DNS sit in, and the one-minute test for each, is covered in whether the domain is really in your name. This section is the settings once it is. Domain management tools for a one-domain company are the registrar’s console plus the export below; no extra product is needed (my reading). The service behind a domain, in the registrar sense, is the company that holds your registration; a transfer agent, despite the name, is a securities role, not a domain registrar (my reading).

To lock a registrar and prevent transfers you never asked for, turn on the transfer lock. ICANN’s EPP status codes page says clientTransferProhibited tells your domain’s registry to reject requests to transfer the domain from your current registrar to another, which will help prevent unauthorized transfers resulting from hijacking and/or fraud.

  1. 01 Transfer lock on: the registrar shows the status clientTransferProhibited
  2. 02 Auto-renew on, paid by a card the company controls, with a second payment method on file
  3. 03 Two-factor authentication on the registrar account and the DNS host account
  4. 04 A DNS export in the runbooks, dated, with every record including the verification TXT records
  5. 05 Both renewal dates in a shared calendar, each with one named owner

Items 2 and 5 are my working rule. The two-factor item has its own page: implement two factor authentication on every owner account. The export matters most for the TXT records: each domain verification key a service asked you to add is a line nobody remembers until it goes missing and the service that asked for it can no longer verify the domain (my reading). The verify section below says what proves item 4.

How to do it: the certificate, the server, and the checks

Getting HTTPS right after the certificate means five checks: the key file never leaves the server, the key is at least the size public certificate authorities accept, TLS 1.2 is the floor, the server sends the full chain, and a self-signed certificate never reaches production.

The commands and settings below are the tools’ and standards’ own documented behavior, read from their pages, not something I ran against your stack. Run each one against your own domain before you rely on its output.

The certificate files: crt, key, pem, p12, and the mismatch that breaks an install

The .key file is the private key and never leaves the server. The .crt is the certificate: the public key plus the certificate authority’s signature. A .pem file is a text encoding either one can use, fullchain.pem adds the intermediates, and a .p12 bundles key and certificate behind a password.

FileWhat it holdsWho may see it
.key, or Certbot’s privkey.pemThe private keyThe server only; Certbot says it must be kept secret at all times
.crt or .cerThe certificate: your public key and names, signed by the certificate authorityAnyone; the server sends it on every connection
.pemA text encoding that can hold a key, a certificate or several certificatesDepends on what is inside
fullchain.pem (Certbot)The server certificate first, followed by any intermediatesAnyone; it is what nginx’s ssl_certificate points at
.p12 or .pfxThe private key and the certificate bundled behind a passwordThe server only, because the key is inside
.csrThe certificate signing request: your public key and names, sent to the authorityThe certificate authority

Most cert key confusion sits in the first two rows. The certificate carries the public key and the private key stays with its owner, which is the whole difference between certificate and key. The two halves form a key pair, and a certificate is only usable with the private key it was issued for. My working rule is to generate the certificate signing request from a private key on your own server, never with an online CSR generator, because a generator that creates the key has held your private key.

The error saying the certificate and private key doesn’t match means the certificate was issued for a different key. The offline check compares the public key inside each file: OpenSSL’s x509 manual documents -pubkey, which prints the certificate’s public key, and OpenSSL’s pkey command derives the public key from the private key with -pubout. If the two outputs are identical, the files belong together; the last line prints the expiry date the next section relies on.

openssl x509 -in cert.pem -noout -pubkey > cert-pub.pem
openssl pkey -in privkey.pem -pubout > key-pub.pem
diff cert-pub.pem key-pub.pem && echo "same key pair"
openssl x509 -in cert.pem -noout -enddate

The same two commands tell you whether a key file on the server belongs to a certificate at all, since a certificate never holds its private key. Never paste a private key into an online certificate and key matcher or private key checker: once you do, the key is that site’s too, and the only fix is a new key and a new certificate (my reading). What to do after a mismatch, and how to rotate the pair, is in how to rotate API keys safely, certificates included.

Key length and expiry: the checks that catch a certificate before it lapses

Certificate key length for a public certificate starts at RSA 2048 bits, the Baseline Requirements minimum, with ECDSA P-256, the curve TLSRef recommends, as the alternative. A private key does not expire; the certificate does, and maximum validity is shrinking on a published schedule, so expiry is watched by a monitor, not a memory.

The CA/Browser Forum Baseline Requirements say that for RSA key pairs the CA shall ensure the modulus size is at least 2048 bits, that ECDSA keys must be a valid point on the NIST P-256, P-384 or P-521 curve, and that no other algorithms or key sizes are permitted. That makes 2048 bits the minimum certificate key length a public authority will accept. Going above it with a larger RSA certificate key size adds handshake cost for little gain on a web certificate, in my reading.

To check the RSA key length of a certificate you already have, openssl x509 -in cert.pem -noout -text prints the whole certificate, and its public key line shows the size in bits (my reading of the output). To check a private key’s expiration date, check the certificate instead: openssl x509 -enddate prints its notAfter date, because the key itself has none.

RSA is on a proposed exit path, and ECDSA with it. NIST’s draft IR 8547, an initial public draft published November 12, 2024, lists RSA and ECDSA at 112 bits of security strength as “Deprecated after 2030” and “Disallowed after 2035”, and at 128 bits of security strength or more as “Disallowed after 2035”; it is still a draft, so treat the dates as proposed, not final.

  1. 01 Key size: RSA of at least 2048 bits, or ECDSA on P-256, P-384 or P-521
  2. 02 Expiry date: openssl x509 -enddate on the certificate the server actually sends
  3. 03 Chain: the server sends its certificate followed by the intermediates, as in Certbot's fullchain.pem
  4. 04 Monitor: an expiry alert that reaches a named owner, plus the transparency search from the DNS section

The expiry alert belongs in uptime monitoring for founders, which covers certificate and domain expiry monitors alongside the uptime check.

TLS configuration and TLS security: protocol versions, ciphers and what an A+ grade means

TLS security on a web app means TLS 1.2 or 1.3 only, a current cipher set, a complete certificate chain and HSTS. On a managed host the platform sets most of this; on your own server the TLSRef configurator, formerly Mozilla’s generator, writes it. SSL Labs’ rating guide explains what caps a grade.

Mozilla’s server-side TLS guidelines now live outside Mozilla: its wiki says the public guidelines moved to a community working group managed project, TLSRef, and Mozilla’s SSL Config Generator has moved to the TLSRef configurator, which writes configuration for nginx, Apache, Caddy, HAProxy, Traefik and other servers. TLSRef calls its intermediate profile the recommended configuration for the vast majority of services, and on your own server it looks like this:

SettingValueWhySource
ProtocolsTLS 1.2, TLS 1.3TLS 1.2 is the minimum supported protocolTLSRef, intermediate profile
TLS 1.3 cipher suitesTLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256All cipher suites are forward secret and authenticatedTLSRef, intermediate profile
TLS 1.2 cipher suitesECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-ECDSA-CHACHA20-POLY1305, ECDHE-RSA-CHACHA20-POLY1305Same rationaleTLSRef, intermediate profile
Cipher preferenceClient choosesThe client knows best whether it has hardware-accelerated AESTLSRef, intermediate profile
CertificateECDSA P-256 (recommended) or RSA 2048 bitsKeys below 2048 bits cap the SSL Labs grade at BTLSRef; SSL Labs rating guide
ChainThe full chain, intermediates includedAn incomplete chain caps the grade at BSSL Labs rating guide
HSTSmax-age=63072000 (two years)A+ needs HSTS with a max-age of at least 6 monthsTLSRef; SSL Labs rating guide

On a managed host you check these rather than set them. Qualys SSL Labs grades the same handshake: its SSL Server Rating Guide says it first verifies that the certificate is valid and trusted, then scores protocol support, key exchange support and cipher support. Supporting TLS 1.0 or TLS 1.1 caps the grade at B, missing TLS 1.3 brings a warning and a cap at A-, and HSTS that is disabled or invalid sets the grade to A-. An SSL Labs test gives an A plus grade, written A+, to servers with good configuration, no warnings and HSTS with a max-age of at least 6 months, which is why HSTS sits on this page’s checklist even though its value is set on the headers page.

A free HTTPS checker opens the same kind of TLS handshake your browser opens and reports what came back (my reading). An SSL checker API does the same from a script, which is how the check gets into CI. An SSL certificate check API that returns only the expiry date is still useful for the monitor, but it is not a grade. Whatever SSL certificate audit tool you choose, file its dated result with the runbooks.

When TLS breaks: handshake failures, missing issuer certificates, and what curl is telling you

TLS errors on a custom domain come down to a short list: a missing intermediate certificate (unable to get local issuer certificate), no shared protocol or cipher (alert number 40), an expired or mismatched certificate, or a self-signed certificate in the chain. curl --insecure is for diagnosis, never for application code.

Error stringWhat it meansFirst check
unable to get local issuer certificateOpenSSL: the issuer certificate of an untrusted certificate cannot be foundDoes the server send fullchain.pem rather than cert.pem? If it does, is the client’s CA store out of date?
self-signed certificate in certificate chain (SELF_SIGNED_CERT_IN_CHAIN)OpenSSL: the chain could be built, but no suitable trust anchor could be found in the trust storeIs a proxy or antivirus intercepting TLS, or did a development certificate reach the server?
sslv3 alert handshake failure, alert number 40Alert 40 is handshake_failure: the sender was unable to negotiate an acceptable set of security parametersThe client’s TLS version and ciphers, and whether it sends the server name (SNI)
certificate has expiredOpenSSL: the notAfter date is before the current timeopenssl x509 -enddate, then why renewal did not run
hostname mismatchOpenSSL: hostname mismatch, meaning the certificate does not list the name the client asked for (my reading)The names in openssl x509 -noout -text against the hostname in the URL
Cloudflare error 525Cloudflare: the SSL handshake between Cloudflare and the origin web server failed, with Full or Full (Strict) SSL setCloudflare’s causes, in its order: no valid SSL certificate installed, port 443 not open, no SNI support, cipher suites that do not match

The handshake strings usually arrive together, as sslv3 alert handshake failure followed by SSL alert number 40, and both name the same alert (my reading). When curl says unable to get local issuer certificate against your own site, the likeliest cause is a server sending the certificate without its intermediates, so fix the server before touching the client (my reading). For Cloudflare’s error 525, Cloudflare’s error 525 page gives the causes above, and its SSL modes page says Full (strict) adds validation of the origin server’s certificate, which can come from a public CA like Let’s Encrypt or from Cloudflare Origin CA.

Two commands read the handshake for you. curl -vI https://example.com prints the server certificate’s details in its verbose output, which is how to make curl show the certificate; curl’s manual documents -v as verbose output and -I as fetching the headers only, and the certificate lines are my reading of what that output contains. openssl s_client -connect example.com:443 -servername example.com -showcerts displays the certificate list as the server sent it, which OpenSSL’s manual notes is not a verified chain; that is how to validate the server certificate an SSL client actually receives, and a missing intermediate shows up as a list with no intermediate in it.

The --insecure flag, -k, makes curl skip the verification step, and curl’s manual warns that using it makes the transfer insecure. Use it once, to see whether verification is the only thing failing, and never in application code. Node’s version is broader because it covers the whole process: Node’s CLI documentation says that if NODE_TLS_REJECT_UNAUTHORIZED equals '0', certificate validation is disabled for TLS connections, which makes TLS, and HTTPS by extension, insecure. My working rule is that it never appears in a production environment.

A client that says it can’t verify the certificate from the server has found a chain or trust problem to fix, not a reason to switch checking off. When a hosted service reports that it generated warnings while checking SSL certificates, match the warning text to a row of the table before changing anything.

Self-signed certificates in local development

A self-signed certificate is trusted only by machines told to trust it, which makes it right for a laptop and wrong for anything a customer or a webhook sender reaches. mkcert gives local browsers a certificate they trust without warnings, from a local certificate authority it creates.

A self-signed certificate lasts as long as whoever created it set it to last. mkcert’s README says it automatically creates and installs a local CA in the system root store and generates locally-trusted certificates, which is the clean way to get Chrome to trust a self-signed certificate for local work instead of clicking through the warning each time. Rather than create a self-signed certificate for testing on one laptop, run mkcert with the hostnames you need; its README also warns that the rootCA-key.pem file it generates gives complete power to intercept secure requests from your machine, and that mkcert is meant for development purposes, not production.

For a fetch API call from Node against that self-signed certificate, point Node at the local CA with NODE_EXTRA_CA_CERTS, as mkcert’s README instructs, rather than disabling validation with the setting in the previous section. An SSL certificate for testing on a shared staging server is a different job: give staging a real hostname and a real certificate, and run the same checks as production (my reading).

On Azure, the app service self signed certificate question has a short answer. Azure App Service’s certificate guide says a certificate that helps secure a custom domain in a TLS binding must be signed by a trusted certificate authority. A self-signed certificate is signed by no such authority, so it cannot fill that role (my reading).

How to verify it: the TLS scan, the redirect, and what actually serves your domain

Domain and TLS hygiene is verified with 8 checks: an external TLS scan per hostname, a permanent redirect from every HTTP URL, the HSTS header present, the CAA record resolving, the registrar showing the lock and auto-renew, the DNS export dated in the runbooks, the expiry monitor tested, and the headers naming what serves the domain.

Each check below ends in something you can see and keep.

  1. 01 Run an external TLS scan on every hostname and save a dated screenshot of the result: the grade, the protocols and the chain
  2. 02 Run curl -I on http:// for the apex and for www: the status line shows a permanent redirect, 301 from nginx's return 301 form or 308 on Vercel, with a location on https://
  3. 03 Check that the HTTPS response carries a Strict-Transport-Security header
  4. 04 Run dig CAA on the apex: the record names the authority that issues your certificates
  5. 05 Open the registrar: the domain shows clientTransferProhibited and auto-renew is on
  6. 06 Open the runbooks: the DNS export is there, dated after the last DNS change
  7. 07 Send the expiry monitor's test alert and confirm the named owner received it
  8. 08 Run dig for the records and curl -I on https:// for the headers: a cf-ray header identifies the Cloudflare data center that processed the request, and x-vercel-id lists the Vercel regions it hit
curl -I http://example.com
curl -I http://www.example.com
curl -sI https://example.com | grep -i -E 'strict-transport-security|cf-ray|x-vercel-id|server'
dig CAA example.com +short
dig NS example.com +short

The last of those checks is the whole CDN check: the response headers name whatever sits in front of the app, and dig shows where the name points (my reading). The meaning of each header is in Cloudflare’s HTTP headers reference and Vercel’s response headers page, and Vercel’s page adds that its server header can be overridden by other proxies such as Cloudflare, so read cf-ray and x-vercel-id together rather than trusting server alone.

How fast that CDN serves the app is web performance optimization, and a firewall in front of the origin is how to set up a web application firewall. Checks 2 to 4 are worth running on a schedule, which belongs with your CI/CD best practices. A staging domain gets the same eight checks; if you have one database and no staging, that comes first.

In the sprint, deliverable 7.13 is verified this way: pass an external TLS scan at the top grade and file a DNS record export in the runbooks.

Where the sprint does this

Deliverable 7.13 is the work in the first section’s table and the proof in the verify section’s checklist. The production readiness report, deliverable 13.1, delivers the result for every scope item, the work completed, and its verification evidence. Hosting, paid tools and API usage are paid through your accounts, and we explain any required costs before enabling them. Every item is listed on the sprint’s 13 areas and 123 items.

Common questions about HTTPS, certificates and domains

Are .PEM and .key the same?

No. PEM is a text encoding and .key is a naming habit for a file that holds a private key, usually written in PEM. A .pem file can hold a certificate, a key or several certificates: Certbot’s privkey.pem is a private key and its fullchain.pem is certificates, so read the file’s first line rather than trusting the extension.

What are the three types of certificates?

For a website, the three usually meant are domain validated (DV), organization validated (OV) and extended validation (EV). The CA/Browser Forum’s Baseline Requirements list four subscriber certificate types, adding individual validated (IV), and say all of them provide the same level of assurance of the device identity. Vercel uses Let’s Encrypt, which offers Domain Validation certificates and not OV or EV.

Should I use 2048 or 4096 RSA key?

Use 2048. It meets the Baseline Requirements minimum for RSA; 4096 bits makes every handshake slower for a benefit a web certificate rarely needs (my reading). If your host or server supports it, ECDSA on P-256, which TLSRef recommends over RSA, is the other good choice.

How long will an SSL certificate be valid for in 2026?

At most 200 days for a public certificate issued on or after March 15, 2026, under the CA/Browser Forum schedule that ballot SC-081 introduced; the limit drops to 100 days in March 2027. Let’s Encrypt issues 90-day certificates by default and six-day ones on request, and recommends renewing the 90-day kind every 60 days.

How do I switch to HTTPS?

Get a certificate (a managed host like Vercel issues and renews one once your DNS records point at it), redirect every HTTP URL permanently to HTTPS, turn on HSTS, and replace every http:// asset URL so the page has no mixed content. Then keep it: a CAA record, a locked registrar, a named owner for both renewal dates, and a scan after each renewal.

Is a CAA record necessary?

No, a certificate can be issued without one: RFC 8659 only restricts issuance where a CAA record exists. It is still worth publishing because it limits which certificate authorities may issue for your domain, provided it names the one your host uses.

Can a self-signed certificate be trusted?

Only by machines someone told to trust it. That makes it fine on a developer laptop, where mkcert’s local certificate authority does the telling, and wrong anywhere a customer, a browser you do not control or a webhook sender connects.