How to Install an SSL Certificate on Nginx and Apache

Installing an SSL certificate enables HTTPS on your website. This guide covers Let's Encrypt with Certbot (free, automated) and manual certificate installation for both Nginx and Apache.


Installing an SSL certificate enables HTTPS on your website, encrypting traffic between the server and visitors. This guide covers two approaches: Let's Encrypt with Certbot (free and automated — the recommended choice for most sites) and manual certificate installation for paid certificates.

Prerequisites

  • A domain name pointing to your server (A record confirmed resolving to your server IP).
  • Root or sudo access to your server.
  • Web server software installed (Nginx or Apache).
  • Port 80 open on your firewall (required for HTTP-01 challenge during Let's Encrypt issuance).

Option 1: Let's Encrypt with Certbot (Recommended)

Let's Encrypt provides free, trusted SSL certificates with automated renewal. Certbot is the official client.

Install Certbot on Ubuntu/Debian

bash
sudo apt update sudo apt install certbot python3-certbot-nginx # For Nginx # Or sudo apt install certbot python3-certbot-apache # For Apache

Install Certbot on RHEL/CentOS/AlmaLinux

bash
sudo dnf install epel-release sudo dnf install certbot python3-certbot-nginx # For Nginx # Or sudo dnf install certbot python3-certbot-apache # For Apache

Obtain and Install Certificate for Nginx

bash
# Certbot automatically configures Nginx sudo certbot --nginx -d example.com -d www.example.com # You will be prompted for: # - Email address (for expiry notifications) # - Agreement to terms of service # - Whether to redirect HTTP to HTTPS

Obtain and Install Certificate for Apache

bash
# Certbot automatically configures Apache sudo certbot --apache -d example.com -d www.example.com
Test automatic renewalCertbot installs a cron job or systemd timer that automatically renews certificates before they expire. Test it with:sudo certbot renew --dry-run

Option 2: Manual Certificate Installation

If you have purchased a certificate from a CA (e.g., DigiCert, Sectigo, Comodo), the installation process is:

Step 1: Generate a CSR (if not already done)

bash
# Generate a private key and CSR openssl req -new -newkey rsa:2048 -nodes -keyout example.com.key -out example.com.csr # You will be prompted for: # - Country, State, City, Organization, Common Name (domain), email

Step 2: Obtain Your Certificate

Submit the CSR content to your CA. They will validate your domain ownership and issue a certificate. Download the certificate files — typically a .crt file and a CA bundle.

Step 3: Create the Full Chain File

bash
# Combine your certificate with the CA bundle cat your-certificate.crt ca-bundle.crt > fullchain.crt # Copy files to a secure location sudo mkdir -p /etc/ssl/example.com sudo cp fullchain.crt /etc/ssl/example.com/ sudo cp example.com.key /etc/ssl/example.com/ sudo chmod 600 /etc/ssl/example.com/example.com.key

Step 4: Configure Nginx

nginx
server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name example.com www.example.com; ssl_certificate /etc/ssl/example.com/fullchain.crt; ssl_certificate_key /etc/ssl/example.com/example.com.key; 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; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; root /var/www/html; index index.html; location / { try_files $uri $uri/ =404; } }
bash
# Test and reload Nginx sudo nginx -t && sudo systemctl reload nginx

Step 5: Configure Apache

apache
<VirtualHost *:80> ServerName example.com ServerAlias www.example.com Redirect permanent / https://example.com/ </VirtualHost> <VirtualHost *:443> ServerName example.com ServerAlias www.example.com DocumentRoot /var/www/html SSLEngine on SSLCertificateFile /etc/ssl/example.com/fullchain.crt SSLCertificateKeyFile /etc/ssl/example.com/example.com.key SSLProtocol -all +TLSv1.2 +TLSv1.3 SSLHonorCipherOrder off Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" </VirtualHost>
bash
# Enable required modules and restart Apache sudo a2enmod ssl headers sudo systemctl restart apache2

Verifying the SSL Installation

After installation, verify the certificate is correctly configured:

bash
# Check certificate details openssl s_client -connect example.com:443 -showcerts # Check expiry date openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates # Test HTTPS redirect curl -I http://example.com

Use the ShowDNS SSL Checker to verify the full certificate chain, expiry, and TLS configuration from outside your network.

Common Installation Errors

ErrorCauseFix
Certificate chain incompleteOnly leaf cert configured, no intermediateUse fullchain.crt including intermediate
Private key mismatchKey does not match the certificateVerify key matches CSR used to request cert
Permission denied on key fileKey file permissions too open or too restrictiveSet permissions to 600 (chmod 600 key.pem)
Certbot challenge failsPort 80 blocked or DNS not propagatedOpen port 80, confirm A record points to server

Frequently Asked Questions

How do I renew a Let's Encrypt certificate?

Certbot handles renewal automatically via a cron job. To manually renew: sudo certbot renew. Certificates are renewed when they have less than 30 days remaining.

Can I install one certificate for multiple domains?

Yes. Include multiple -d flags with Certbot to issue a single certificate covering multiple domains (SAN certificate): certbot --nginx -d example.com -d www.example.com -d api.example.com.

What is the difference between the certificate file and fullchain file?

The certificate file contains only your domain's certificate. The fullchain file contains your certificate plus any intermediate certificates. Always use the fullchain file in your web server configuration to ensure browsers can verify the complete chain.

Related Articles