openssl network

generate certs without begging your IT department.

The openssl documentation is sprawling — hundreds of subcommands, thousands of options. You need about eight commands and you can generate certificates, inspect them, and debug TLS connections without a GUI or a prayer to your IT department.

You needed an SSL certificate. For local development. Or for an internal service. Or because Let’s Encrypt doesn’t cover your use case. So you Googled “generate ssl certificate.” You found a tutorial from 2018. You followed it. It didn’t work because the tutorial used deprecated options. You found another tutorial. It generated a certificate but your browser showed “NET::ERR_CERT_AUTHORITY_INVALID.” You tried adding it to your trust store. It didn’t help. You spent two hours on something that should have taken two minutes.

Or worse — you needed to debug why HTTPS wasn’t working on a server. The certificate was expired. Or the chain was incomplete. Or the cert didn’t match the domain. You couldn’t tell because the error message was “SSL_ERROR_HANDSHAKE_FAILURE_ALERT” and that could mean seventeen different things.

openssl generates certificates, inspects them, and tests TLS connections. It’s the Swiss army knife of cryptography — installed on every Linux system, zero GUI required.

Unless you’re running Windows then wtf none of this applies to you. But hey, come to the dark side, go install WSL2 and you can follow along. We’ll wait. Impatiently.

If you’re lazy like me (all sysadmins are!) then click here for the openssl cheat sheet.


Generate a self-signed certificate

openssl req -x509 -newkey rsa:4096 -sha256 -days 365 \
  -nodes -keyout key.pem -out cert.pem \
  -subj "/CN=localhost" \
  -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"

One command. Generates a 4096-bit RSA private key (key.pem) and a self-signed certificate (cert.pem) valid for 365 days. The subjectAltName is critical — modern browsers require it and will reject certificates without it.

  • -nodes — don’t encrypt the private key with a passphrase (for dev use)
  • -subj — skip the interactive questions about country, state, org, etc.
  • -addext — add the Subject Alternative Name extension

For local development, this is all you need. Drop these files into your web server config and HTTPS works.


Generate a CSR (Certificate Signing Request)

When you need a real certificate from a CA (Certificate Authority):

Generate a key and CSR together

openssl req -newkey rsa:4096 -nodes -keyout key.pem -out request.csr \
  -subj "/CN=example.com/O=My Company/C=US"

Send request.csr to your CA. Keep key.pem private — never share the private key.

Generate a CSR from an existing key

openssl req -new -key existing-key.pem -out request.csr \
  -subj "/CN=example.com"

If you already have a key and just need a new CSR (for renewal, for example).


Inspect a certificate

View a certificate file

openssl x509 -in cert.pem -text -noout

Shows everything: subject, issuer, validity dates, serial number, extensions, signature algorithm. The -noout suppresses the raw base64-encoded certificate.

Check expiration date

openssl x509 -in cert.pem -noout -dates
notBefore=Mar 15 10:00:00 2026 GMT
notAfter=Mar 15 10:00:00 2027 GMT

Two lines. When it started, when it expires. This is how you check if a certificate is about to expire before your monitoring catches it.

Check the subject and issuer

openssl x509 -in cert.pem -noout -subject -issuer
subject=CN = example.com
issuer=CN = Let's Encrypt Authority X3

Does the certificate match the domain? Who issued it? Two questions answered instantly.

Check Subject Alternative Names

openssl x509 -in cert.pem -noout -ext subjectAltName

Shows which domains and IPs the certificate covers. A certificate for example.com might also cover www.example.com, api.example.com, etc.


Inspect a remote server’s certificate

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -text -noout

Connects to a remote server, grabs its certificate, and displays it. No browser needed. No clicking the padlock icon. One command from your terminal.

Quick expiration check on a remote server

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

When does this server’s certificate expire? Check it from anywhere. Script it to check all your domains.

Check the certificate chain

echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null

Shows the full certificate chain — the server cert, any intermediates, and the root. If intermediates are missing, browsers will show an error even if the server cert is valid. This is one of the most common TLS configuration mistakes.


Test a TLS connection

openssl s_client -connect example.com:443 -servername example.com

Shows the full TLS handshake — protocol version, cipher suite, certificate chain, and verification result. If something is wrong with HTTPS, this tells you what.

Check supported TLS versions

openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3

Force a specific TLS version. If -tls1_2 works but -tls1_3 fails, you know TLS 1.3 isn’t supported (or is misconfigured).


Generate keys

RSA key

openssl genrsa -out key.pem 4096

4096-bit RSA private key. The standard for most use cases.

EC (Elliptic Curve) key

openssl ecparam -genkey -name prime256v1 -out key.pem

Smaller key, equivalent security to much larger RSA keys. Faster handshakes. Modern preference for TLS.

View key details

openssl rsa -in key.pem -text -noout
openssl ec -in key.pem -text -noout

Verify a key was generated correctly and check its parameters.


Verify a key matches a certificate

openssl x509 -in cert.pem -noout -modulus | md5sum
openssl rsa -in key.pem -noout -modulus | md5sum

If the MD5 hashes match, the key and certificate are a pair. If they don’t match, you’re using the wrong key — a surprisingly common mistake when dealing with multiple certificates.


Convert between formats

PEM to DER

openssl x509 -in cert.pem -outform DER -out cert.der

PEM to PKCS12 (for importing into browsers/Java)

openssl pkcs12 -export -out cert.p12 -inkey key.pem -in cert.pem

Prompts for a password. The .p12 file contains both the key and certificate.

PKCS12 to PEM

openssl pkcs12 -in cert.p12 -out combined.pem -nodes

Extracts the key and certificate from a .p12 file.


The flags that actually matter

Command What it does
req -x509 -newkey rsa:4096 Generate self-signed cert + key.
req -new -key key.pem Generate a CSR from an existing key.
x509 -in cert.pem -text -noout Inspect a certificate.
x509 -noout -dates Check expiration dates.
s_client -connect host:443 Test TLS connection and get cert.
s_client -showcerts Show full certificate chain.
genrsa -out key.pem 4096 Generate RSA key.
rsa -in key.pem -noout -modulus Get key modulus (for matching).
pkcs12 -export Convert to PKCS12 format.

“But I use—”

We both know where this is going.

“Let’s Encrypt handles everything.” Let’s Encrypt is amazing for public-facing websites. But it doesn’t cover internal services, development environments, non-HTTP protocols, or anything without a public DNS name. For those, you need to generate your own certificates.

“I use the AWS Certificate Manager.” ACM provisions certificates for AWS services. If your cert isn’t on AWS, ACM can’t help. And when you need to debug why a certificate isn’t working, openssl s_client is how you diagnose it — regardless of who issued the cert.

“I check certs by clicking the padlock in Chrome.” The padlock shows you the certificate for one domain in one browser. openssl s_client shows you the certificate, the chain, the protocol version, and the cipher suite from any machine — including servers without browsers. And you can script it to check fifty domains in a loop.

“I use a GUI like KeyStore Explorer.” KeyStore Explorer is 15MB of Java to inspect and convert certificates. openssl x509 -text does the same thing in one command, on every Linux box, without Java. For key stores and PKCS12 management, the GUI can be useful. For everything else, openssl is faster.


openssl cheat sheet

You made it. Or you skipped straight here. Either way, no judgment. Copy and paste these. Pin them. Tattoo them on your forearm. Whatever works.

What you’re doing Command
Self-signed cert (dev) openssl req -x509 -newkey rsa:4096 -sha256 -days 365 -nodes -keyout key.pem -out cert.pem -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
Generate a CSR openssl req -newkey rsa:4096 -nodes -keyout key.pem -out req.csr -subj "/CN=example.com"
Inspect a certificate openssl x509 -in cert.pem -text -noout
Check expiration openssl x509 -in cert.pem -noout -dates
Check remote cert echo | openssl s_client -connect host:443 -servername host 2>/dev/null | openssl x509 -noout -dates
Test TLS connection openssl s_client -connect host:443 -servername host
Show cert chain openssl s_client -connect host:443 -showcerts
Verify key matches cert Compare: openssl x509 -noout -modulus | md5sum vs openssl rsa -noout -modulus | md5sum
Generate RSA key openssl genrsa -out key.pem 4096
PEM to PKCS12 openssl pkcs12 -export -out cert.p12 -inkey key.pem -in cert.pem

The debug command: openssl s_client -connect host:443 -servername host — shows you the TLS handshake, certificate, chain, and any errors. When HTTPS isn’t working, start here.

Back to the top, you overachiever.