Back to Guides
Certificates > Guides > Linux

Linux Certificate Management

A comprehensive OpenSSL command reference, system trust store management, Let's Encrypt automation, and web server SSL configuration for Linux.

OpenSSL Reference

Generate keys

Generate a 2048-bit RSA key:

openssl genrsa -out server.key 2048

Generate a 4096-bit RSA key with passphrase:

openssl genrsa -aes256 -out server.key 4096

Generate a CSR

Create a CSR from an existing key:

openssl req -new -key server.key -out server.csr \
  -subj "/CN=example.com/O=MyOrg/C=US/ST=California/L=San Francisco"

Self-signed certificate

Generate a self-signed certificate with SANs:

openssl req -x509 -new -nodes \
  -key server.key \
  -sha256 -days 365 \
  -out server.crt \
  -subj "/CN=example.com/O=MyOrg/C=US" \
  -addext "subjectAltName=DNS:example.com,DNS:www.example.com,IP:10.0.0.1" \
  -addext "keyUsage=digitalSignature,keyEncipherment" \
  -addext "extendedKeyUsage=serverAuth"

View and verify certificates

Display certificate details:

openssl x509 -in server.crt -text -noout

Verify a certificate against a CA:

openssl verify -CAfile ca.crt server.crt

Verify a chain with an intermediate:

openssl verify -CAfile ca.crt -untrusted intermediate.crt server.crt

PKCS#12 operations

Create a PKCS#12 (PFX) file:

openssl pkcs12 -export \
  -in server.crt \
  -inkey server.key \
  -certfile ca.crt \
  -out server.pfx \
  -name "myserver"

Extract certificate and key from PKCS#12:

# Extract certificate
openssl pkcs12 -in server.pfx -clcerts -nokeys -out server.crt

# Extract private key
openssl pkcs12 -in server.pfx -nocerts -nodes -out server.key

Check a remote server

Connect to a server and display its certificate:

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

Check certificate expiry of a remote server:

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

Show the full chain returned by the server:

openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null

System Trust Store

Linux distributions store trusted CA certificates in different locations and use different update commands.

Debian / Ubuntu

Add a custom CA certificate:

# Copy to the trusted CA directory
sudo cp myca.crt /usr/local/share/ca-certificates/myca.crt

# Update the trust store
sudo update-ca-certificates
# Trusted store location
/etc/ssl/certs/                             # Symlinks to trusted certs
/usr/local/share/ca-certificates/           # Where you add custom CAs
/etc/ssl/certs/ca-certificates.crt          # Bundle used by most apps

RHEL / CentOS / Fedora

Add a custom CA certificate:

# Copy to the trust anchors directory
sudo cp myca.crt /etc/pki/ca-trust/source/anchors/myca.crt

# Update the trust store
sudo update-ca-trust

Tip

The certificate file must be in PEM format (Base64 encoded, starting with -----BEGIN CERTIFICATE-----) and have a .crt extension.

Certbot (Let's Encrypt)

Install certbot:

# Ubuntu/Debian
sudo apt update && sudo apt install certbot

# With Nginx plugin
sudo apt install python3-certbot-nginx

# With Apache plugin
sudo apt install python3-certbot-apache

Obtain a certificate (standalone mode):

sudo certbot certonly --standalone -d example.com -d www.example.com

Obtain a certificate with Nginx plugin:

sudo certbot --nginx -d example.com -d www.example.com

Renew all certificates:

sudo certbot renew

Test renewal without actually renewing:

sudo certbot renew --dry-run

Add a post-renewal hook to reload the web server:

sudo certbot renew --deploy-hook "systemctl reload nginx"

Certbot stores certificates at /etc/letsencrypt/live/example.com/ with symlinks to the current version:

/etc/letsencrypt/live/example.com/
  fullchain.pem   # Certificate + intermediate chain
  privkey.pem     # Private key
  cert.pem        # Certificate only
  chain.pem       # Intermediate chain only

Nginx SSL Configuration

Nginx HTTPS server block:

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Modern TLS settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS
    add_header Strict-Transport-Security "max-age=63072000" always;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

Apache SSL Configuration

Apache HTTPS virtual host:

<VirtualHost *:443>
    ServerName example.com

    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/example.com/privkey.pem

    # Modern TLS settings
    SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
    SSLHonorCipherOrder     off

    # HSTS
    Header always set Strict-Transport-Security "max-age=63072000"

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/
</VirtualHost>

# Redirect HTTP to HTTPS
<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>

Warning

Ensure mod_ssl, mod_headers, and mod_proxy are enabled: sudo a2enmod ssl headers proxy proxy_http.

Checking a Remote Certificate

Quick one-liner to check a site's certificate expiry:

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

Test TLS connection with specific protocol:

openssl s_client -connect example.com:443 -tls1_3 </dev/null

Download and save a remote certificate:

echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
  | openssl x509 -out remote.crt