Create a self-signed development certificate with SANs

Generate a certificate with DNS and IP subject alternative names, then distinguish name matching from client trust.

Best practices
Illustration of encrypted network connections

A development certificate needs a Subject Alternative Name (SAN) matching the address used by the client. Modern browsers do not rely on the Common Name alone for hostname validation. Adding SANs fixes that part of the certificate; it does not make a self-signed certificate trusted.

Generate a certificate with OpenSSL

On OpenSSL 3.x, use -addext to supply the names directly:

umask 077
openssl req -x509 -newkey rsa:2048 -noenc -days 365 \
  -keyout server.key -out server.crt \
  -subj "/CN=dev.test" \
  -addext "subjectAltName=DNS:dev.test,DNS:*.dev.test,IP:127.0.0.1"

This creates an unencrypted private key. Keep it private, outside version control, and readable only by the identity that needs it. The one-year lifetime is an example for local development, not a recommendation for publicly trusted certificates.

-addext was introduced in OpenSSL 1.1.1. Older examples use -nodes; OpenSSL 3.x deprecates that spelling in favor of -noenc. Check openssl version rather than assuming the executable matches the operating system's branding.

Put multiple names in a configuration file

For a repeatable setup, save this as san.cnf:

[req]
prompt = no
distinguished_name = dn
req_extensions = ext
x509_extensions = ext

[dn]
CN = dev.test

[ext]
subjectAltName = DNS:dev.test,DNS:*.dev.test,IP:127.0.0.1

Then generate a separate certificate and key with the same restrictions:

umask 077
openssl req -x509 -newkey rsa:2048 -noenc -days 365 \
  -keyout server.key -out server.crt -config san.cnf

The configuration method avoids relying on -addext, but it is not a reason to keep an unsupported OpenSSL installation. Use the options supported by a maintained version.

Inspect the result

openssl x509 -in server.crt -noout -ext subjectAltName
openssl x509 -in server.crt -noout -fingerprint -sha256

DNS:*.dev.test covers a single label such as api.dev.test, not the bare dev.test or a.b.dev.test. The explicit DNS:dev.test covers the bare name. An IP URL needs an IP SAN; a DNS SAN containing the characters 127.0.0.1 is not equivalent.

Configure local name resolution so dev.test reaches the intended server. .test is reserved for testing and avoids the multicast-DNS meaning of .local.

Establish trust deliberately

On controlled development machines, verify the generated certificate's fingerprint and follow the browser or operating system's trust policy. Windows Certificate Manager and macOS Keychain Access expose certificate trust settings, but scope matters: machine-wide trust can affect other users and applications. Do not ask visitors to trust an unfamiliar root.

For several development sites, a tool such as mkcert can manage a local CA and issue certificates with the required names. Its root private key must remain private. A local CA installation is a trust change, not simply another certificate file to share.

References: OpenSSL req, SAN configuration, and reserved testing names.

Related reading

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting