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.