When should I use a self-signed certificate?
Self-signed certificates are appropriate for local development (https://localhost), internal staging behind a corporate VPN, automated testing of TLS code paths, mTLS between trusted internal services where you control both endpoints, and any environment where you can pre-install the cert into the trust store of every client. Anything public-facing must use a CA-issued certificate (Let’s Encrypt is free) so browsers do not warn visitors.
Why does my browser show "Not secure" for a self-signed cert?
Browsers trust certificates that chain up to a Certificate Authority listed in their root store (DigiCert, Let’s Encrypt, Sectigo, etc.). A self-signed certificate has no such chain — it signs itself — so the browser cannot verify identity and shows NET::ERR_CERT_AUTHORITY_INVALID. Either install the cert into the OS/browser trust store, or use a real CA for anything outside your machine.
How do I trust a self-signed cert in Chrome, Firefox, and macOS?
macOS / Chrome / Safari (system keychain): sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain server.crt. Linux Chrome: sudo cp server.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates. Firefox uses its own trust store — Settings → Privacy & Security → Certificates → View Certificates → Authorities → Import. Windows: certutil -addstore -f "ROOT" server.crt.
How long should validity be for development certificates?
For local dev pick 365 days so you re-generate yearly and reset the trust store. For CI fixtures, 30–90 days is fine — they are regenerated by automation. Avoid setting the validity beyond 825 days because Apple, Chrome, and Mozilla now reject server certs with longer lifetimes even if you trust the issuer manually.
Can I use a self-signed cert in production?
No — never for a public website. Visitors will see browser warnings, search engines deprioritize the site, and any HSTS header will permanently lock users out. Use Let’s Encrypt (free, automated via certbot, acme.sh, or Caddy) or a paid CA. Self-signed is acceptable only for non-public infrastructure where you control the trust store on every client.
What are SANs (Subject Alternative Names) and why do I need them?
Modern browsers ignore the Common Name field entirely and look only at the SAN extension to validate the hostname. A certificate with CN=localhost but no SAN will fail validation in Chrome, Firefox, and Safari since 2017. Always include subjectAltName with at least DNS:localhost,IP:127.0.0.1 (and IP:::1 for IPv6 loopback) when generating a cert for local HTTPS.
How do I generate a self-signed certificate for localhost?
Use this generator with CN=localhost and SANs DNS:localhost,DNS:*.localhost,IP:127.0.0.1,IP:::1. Run the produced openssl req -x509 command in your project directory; you will get server.key (private) and server.crt (public). Point your dev server (Vite, Next.js https mode, Express https) at the two files and trust the cert in your OS keychain.
How do I include 127.0.0.1 in the certificate?
Add IP:127.0.0.1 to the SAN field — for example DNS:localhost,IP:127.0.0.1,IP:::1. Note the IP: prefix is required (DNS: is the default if you omit it). Without an IP SAN, Chrome will reject https://127.0.0.1 even if it accepts https://localhost on the same cert, because IP literals must be matched against IP-type SAN entries.