Introduction
SSL/TLS certificates are the foundation of secure communication on the internet. Every time you see HTTPS in your browser, a certificate is working behind the scenes to encrypt traffic and verify identity. As an infrastructure engineer, you'll manage certificates for web servers, internal services, APIs, and more.
How TLS Works (Quick Overview)
When a client connects to a server:
- Client sends "Hello" with supported TLS versions and cipher suites
- Server responds with its certificate and chosen cipher
- Client verifies the certificate against trusted Certificate Authorities (CAs)
- Both sides derive encryption keys using asymmetric cryptography
- All subsequent data is encrypted symmetrically
Certificate Types
| Type | Use Case | Cost |
|---|---|---|
| DV (Domain Validation) | Basic HTTPS | Free (Let's Encrypt) |
| OV (Organization Validation) | Business sites | Paid |
| EV (Extended Validation) | High-trust sites | Expensive |
| Wildcard *.domain.com | Multiple subdomains | Varies |
| SAN (Multi-domain) | Multiple domains | Varies |
Installing OpenSSL
# Ubuntu/Debian
apt install openssl
# Verify version
openssl version
# OpenSSL 3.0.2 15 Mar 2022Generating a Self-Signed Certificate
For internal/test use:
# Generate private key + self-signed cert in one command
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt -days 365 -nodes -subj "/C=IR/ST=Tehran/L=Tehran/O=Company/CN=server.company.local"
# Verify the certificate
openssl x509 -in server.crt -text -nooutGetting a Free Certificate with Let's Encrypt
Certbot automates Let's Encrypt certificate issuance and renewal:
# Install certbot
apt install certbot python3-certbot-nginx
# Get certificate for nginx (automatic configuration)
certbot --nginx -d example.com -d www.example.com
# Get certificate only (manual nginx config)
certbot certonly --nginx -d example.com
# Certificates are stored in:
# /etc/letsencrypt/live/example.com/fullchain.pem (cert + chain)
# /etc/letsencrypt/live/example.com/privkey.pem (private key)Auto-Renewal
Let's Encrypt certs expire in 90 days. Certbot sets up automatic renewal:
# Test renewal (dry run, doesn't actually renew)
certbot renew --dry-run
# Check renewal timer
systemctl status certbot.timer
# Manual renewal
certbot renewGenerating CSR for Paid Certificates
When buying from a commercial CA, you submit a Certificate Signing Request:
# Step 1: Generate private key
openssl genrsa -out company.key 4096
# Step 2: Generate CSR
openssl req -new -key company.key -out company.csr -subj "/C=IR/ST=Tehran/O=Company Ltd/CN=www.company.com"
# Step 3: Verify CSR content
openssl req -in company.csr -text -noout
# Step 4: Submit company.csr to your CA (DigiCert, Sectigo, etc.)
# Step 5: CA sends back company.crt — install itNginx SSL Configuration
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;
ssl_prefer_server_ciphers off;
# HSTS - tell browsers to always use HTTPS
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP Stapling - speeds up TLS handshake
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 1.1.1.1 valid=300s;
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}Building an Internal CA (PKI)
For internal services (not public internet), build your own CA:
# Create CA directory structure
mkdir -p /etc/ssl/myca/{certs,private,newcerts}
echo "01" > /etc/ssl/myca/serial
touch /etc/ssl/myca/index.txt
# Generate CA private key (keep this VERY secure)
openssl genrsa -aes256 -out /etc/ssl/myca/private/ca.key 4096
# Generate CA certificate (valid 10 years)
openssl req -new -x509 -days 3650 -key /etc/ssl/myca/private/ca.key -out /etc/ssl/myca/certs/ca.crt -subj "/C=IR/O=Company Internal CA/CN=Company Root CA"
# Sign a server certificate with your CA
openssl ca -config /etc/ssl/openssl.cnf -in server.csr -out server.crt -days 365Useful OpenSSL Commands
# Check certificate expiry
openssl x509 -in cert.pem -noout -dates
# Check remote server certificate
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -text
# Check certificate matches private key (MD5 should match)
openssl x509 -noout -modulus -in cert.pem | md5sum
openssl rsa -noout -modulus -in key.pem | md5sum
# Convert PFX to PEM (common for Windows certificates)
openssl pkcs12 -in cert.pfx -out cert.pem -nodes
# Convert PEM to PFX
openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -certfile ca.pemCertificate Monitoring
Set up monitoring to alert before certificates expire:
#!/bin/bash
# check-cert-expiry.sh
DOMAIN="example.com"
DAYS_WARN=30
EXPIRY=$(echo | openssl s_client -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
if [ $DAYS_LEFT -lt $DAYS_WARN ]; then
echo "WARNING: $DOMAIN cert expires in $DAYS_LEFT days!"
fiSummary
- Use Let's Encrypt for public-facing services — it's free and auto-renews
- Build an internal CA for internal services and device authentication
- Always use TLS 1.2 or 1.3 — disable older versions
- Monitor certificate expiry proactively — expired certs cause outages
- Never put private keys in version control
