Generate a self-signed certificate

To generate a self-signed certificate and its key in one command, run `openssl req -x509 -newkey rsa:2048 -nodes -keyout private.key -out certificate.crt -days 365 -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"`. The `-addext` argument is not optional in practice: browsers ignore the Common Name and match hostnames against the SAN extension only, so a self-signed certificate without SANs is rejected even after you trust it. For local development across several hostnames, creating a small local CA is usually less painful than trusting individual self-signed certificates.

Updated August 19, 2026 Verified against OpenSSL 3.5.7

The command #

Key and self-signed certificate in one step
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout private.key -out certificate.crt \
-days 365 \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,DNS:*.localhost,IP:127.0.0.1"

Replace these values

PlaceholderWhat to put there
-x509Produce a self-signed certificate instead of a CSR.
-newkey rsa:2048Generate a new key alongside it.
-nodesLeave the key unencrypted so a dev server can start unattended.
-days 365Validity period.
-addext subjectAltName=...The hostnames. Without this, browsers reject the certificate.

Covering several hostnames #

openssl req -x509 -newkey rsa:2048 -nodes \
-keyout private.key -out certificate.crt -days 365 \
-subj "/CN=dev.local" \
-addext "subjectAltName=DNS:dev.local,DNS:api.dev.local,DNS:localhost,IP:127.0.0.1,IP:::1"

An EC certificate #

openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes \
-keyout private.key -out certificate.crt -days 365 \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"

Verify before trusting it #

openssl x509 -in certificate.crt -noout -subject -dates -ext subjectAltName
Expected output
subject=CN = localhost
notBefore=Aug 19 12:00:00 2026 GMT
notAfter=Aug 19 12:00:00 2027 GMT
X509v3 Subject Alternative Name:
  DNS:localhost, DNS:*.localhost, IP Address:127.0.0.1

If the SAN section is missing, stop and regenerate — trusting it will not help.

Trusting it locally #

sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain certificate.crt

Chrome and Safari use the system keychain. Firefox does not — see its tab.

sudo cp certificate.crt /usr/local/share/ca-certificates/dev-local.crt
sudo update-ca-certificates

The file must end in .crt and contain PEM, or it is silently skipped.

sudo cp certificate.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust extract

Firefox ships its own trust store and ignores the operating system’s on most platforms. Import through Settings → Privacy & Security → Certificates → View Certificates → Authorities → Import, and tick “Trust this CA to identify websites”.

Consider a local CA instead #

Trusting a self-signed certificate means one trust-store operation per certificate, repeated on every machine and every time it expires. A small local CA is trusted once, and every certificate it signs afterwards is accepted automatically:

  1. Create a root CA — one time
  2. Trust that root on your machines — one time
  3. Sign a CSR with it — whenever you need a certificate

For anything beyond a single throwaway hostname, that is less total work.

Inspecting what you made #

A self-signed certificate is its own issuer
openssl x509 -in certificate.crt -noout -subject -issuer
Expected output
subject=CN = localhost
issuer=CN = localhost

Identical subject and issuer is the definition of self-signed. See self-signed vs CA-signed.

Frequently asked questions

Why does my browser still reject the certificate after I trusted it?
Almost always missing subject alternative names. Trust and hostname matching are separate checks — trusting the certificate satisfies the first, but without a SAN covering the hostname the second still fails. Regenerate with -addext "subjectAltName=DNS:...".
How long should a self-signed certificate last?
For local development, 365 days is convenient. Longer is tempting and a bad habit, because a self-signed certificate cannot be revoked — if the key leaks, your only remedy is to wait for expiry or manually remove it from every trust store it reached.
Should I use a self-signed certificate in production?
No. Every client has to be configured to trust it individually, there is no revocation, and the usual workaround is to disable verification entirely, which removes the protection TLS provides. Use a public CA, or an internal CA if the service is internal.
What is the difference between self-signed and a private CA?
A self-signed certificate is its own issuer, so each one has to be trusted individually. A private CA is trusted once, after which every certificate it issues is accepted automatically. For more than one or two certificates, the CA is far less work.

References