bg-tutorials

How to Install an SSL Certificate on NGINX

This guide shows you how to install an SSL/TLS certificate on NGINX. It covers the part that trips most people up: building the correct certificate chain (“fullchain”) that NGINX requires, pointing the right directives at the right files, testing the configuration before reloading, and adding a clean HTTP to HTTPS redirect so every visitor lands on the secure version of your site.

Generate a CSR code for NGINX

If you already generated your CSR and have the issued certificate files in hand, skip ahead to Install an SSL certificate on NGINX.

Before a Certificate Authority can issue your certificate, you need to submit a CSR (Certificate Signing Request): a small text block that contains your domain details and a public key, paired with a private key kept on the server. You have two options:

  • Generate the CSR automatically with our CSR Generator. The tool returns both the CSR and the matching private key, which you then upload to the server.
  • Generate the CSR on the server itself with OpenSSL by following our tutorial on how to generate a CSR on NGINX. The private key stays on the server.

Open the resulting .csr file in any text editor; the block of text inside (including the —–BEGIN CERTIFICATE REQUEST—– and —–END CERTIFICATE REQUEST—– lines) is what you paste into the SSL application form during checkout. If you want to confirm the CSR contents before submitting, paste it into our CSR decoder.

Install an SSL certificate on NGINX

Once the CA has issued the certificate, you will typically receive:

  • Your primary (server) certificate, usually a .crt file named after your domain.
  • The intermediate (and sometimes root) certificates, either as separate .crt files or bundled into one .ca-bundle file.
  • The private key (a .key file) that was generated together with your CSR.

NGINX needs the server certificate and the intermediate chain combined into a single file (the “fullchain”) and pointed to by ssl_certificate; the private key is pointed to separately by ssl_certificate_key. Skipping the chain is the single most common installation mistake: the certificate looks fine in a desktop browser but fails on Android, in API clients, and on tools like our SSL Checker.

Step 1: Combine the certificates into one file

The order of certificates in the combined file matters. Your server certificate comes first, then each intermediate from the leaf-issuing CA upward, with the root last (or omitted, since browsers already trust roots from their built-in store):

  • Your primary certificate for the domain name.
  • Intermediate certificate(s).
  • Root certificate (optional).

You can build the fullchain file by hand in a text editor (paste each PEM block in order), or with a single cat command. If you received separate intermediate and root files, run:

cat your_domain.crt intermediate.crt root.crt > ssl-bundle.crt

If the intermediates and root are already in one .ca-bundle file, run:

cat example_com.crt example_com.ca-bundle > ssl-bundle.crt

Replace the file names with your own. Move the combined file (and the private key, if it is not already there) into the SSL directory on your server, for example /etc/ssl/ or /etc/nginx/ssl/. Keep the key file readable only by root:

sudo chmod 600 /etc/ssl/your_domain.key
sudo chown root:root /etc/ssl/your_domain.key

Step 2: Edit the NGINX configuration file

Open the NGINX configuration file for your site. On Debian and Ubuntu it lives in /etc/nginx/sites-available/ (with a symlink in sites-enabled/); on RHEL, CentOS, AlmaLinux, and Rocky Linux it lives in /etc/nginx/conf.d/. Add or edit the server block that listens on port 443 so it points at the fullchain file and the private key:

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

    ssl_certificate     /etc/ssl/ssl-bundle.crt;
    ssl_certificate_key /etc/ssl/your_domain.key;

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

    ssl_session_timeout 1d;
    ssl_session_cache shared:NginxSSL:10m;
    ssl_session_tickets off;

    access_log /var/log/nginx/example.com.access.log;
    error_log  /var/log/nginx/example.com.error.log;

    root /var/www/example.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

A few notes on the directives above:

  • listen 443 ssl; enables TLS on port 443. The legacy ssl on; directive was removed in NGINX 1.25 and should not appear in modern configurations.
  • http2 on; turns on HTTP/2 as its own directive (NGINX 1.25.1 and later). Older configurations used listen 443 ssl http2;, which still works but is deprecated.
  • ssl_protocols TLSv1.2 TLSv1.3; disables the obsolete TLS 1.0 and 1.1. From NGINX 1.27.3 onward, this is also the default if you omit the directive, but setting it explicitly is the clear, audit-friendly choice.
  • The cipher list matches the Mozilla “intermediate” profile and works on every recent client. If you only need TLS 1.3 clients, you can drop ssl_ciphers entirely.

Step 3: Redirect HTTP to HTTPS

Add a separate server block on port 80 that permanently redirects every request to HTTPS, so visitors arriving over plain HTTP land on the secure URL:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Using return 301 is faster and safer than a regex-based rewrite rule and is the pattern NGINX itself recommends.

Step 4: Test the configuration and reload NGINX

Always validate the configuration before reloading, so a typo cannot take the service offline:

sudo nginx -t

You should see syntax is ok and test is successful. If it reports an error, the message includes the file and line number; fix it and run the test again. When the test passes, reload NGINX so it picks up the new configuration without dropping existing connections:

sudo systemctl reload nginx

On systems without systemd, use NGINX’s own reload signal instead:

sudo nginx -s reload

Prefer reload over restart: a reload re-reads the configuration without closing active connections, while a restart drops them.

Step 5 (optional): Enable OCSP stapling

OCSP stapling lets NGINX deliver a fresh, signed revocation status alongside the certificate, so clients do not have to contact the CA on every handshake. Add the following inside your HTTPS server block:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/ssl-bundle.crt;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;

Reload NGINX again with sudo systemctl reload nginx. Stapling is a small but worthwhile hardening step, and most modern certificates support it out of the box.

Verify the installation

Open your site over https:// in a browser and check that the padlock is closed and the certificate matches your domain. Then run a deeper scan with our SSL Checker for an instant report on the certificate, the chain, and the protocols and ciphers your server is offering. A green result there means clients on every major platform will trust the certificate, including mobile and API clients.

Frequently Asked Questions

Where do I install the SSL certificate on NGINX?

NGINX itself does not require a specific directory, but most administrators keep certificates and keys under /etc/ssl/ or /etc/nginx/ssl/. You then reference them from your server block with ssl_certificate (pointing to the combined certificate + intermediates file) and ssl_certificate_key (pointing to the private key).

Why is my certificate trusted in Chrome but not on mobile or API clients?

Almost always because the intermediate chain is missing. Desktop browsers can fetch missing intermediates on their own (“AIA fetching”), but Android, iOS, and most command-line and language HTTP clients cannot. Rebuild your fullchain file so it includes the server certificate followed by every intermediate, point ssl_certificate at that combined file, reload NGINX, and rerun the SSL Checker.

Should I use restart or reload after editing the NGINX config?

Reload. sudo systemctl reload nginx (or sudo nginx -s reload) re-reads the configuration and gracefully replaces the worker processes, so existing connections are not dropped. A full restart stops and starts the service and is rarely needed for a configuration change. Always run sudo nginx -t first so you catch syntax errors before the reload.

Do I still need ssl on; in my server block?

No. The standalone ssl on; directive was deprecated in NGINX 1.15.0 and removed entirely in 1.25. On any supported NGINX release you enable TLS with listen 443 ssl; on the listen line instead. If you are copying an older configuration, delete any ssl on; lines.

How do I enable HTTP/2 (and HTTP/3) on NGINX?

Use the dedicated http2 on; directive inside your HTTPS server block (NGINX 1.25.1 and later). The older syntax that added http2 as an argument to the listen line still works but is deprecated. HTTP/3 (QUIC) is supported since NGINX 1.25 and is enabled with a separate UDP listener (listen 443 quic reuseport;) plus an Alt-Svc header; it is optional and can be added once HTTP/2 is stable on your site.

How often do I need to renew the certificate?

As of March 15, 2026, publicly trusted SSL/TLS certificates are capped at 200 days, and the CA/Browser Forum has scheduled further reductions (to 100 days in 2027 and 47 days in 2029). Plan to repeat the steps above well before each expiry, or automate renewals with ACME.

Save 10% on SSL Certificates when ordering from SSL Dragon today!

Fast issuance, strong encryption, 99.99% browser trust, dedicated support, and 25-day money-back guarantee. Coupon code: SAVE10

A detailed image of a dragon in flight
Written by

I've been writing for SSL Dragon for over 10 years, focusing entirely on SSL certificates and digital security. My job is to take complex cybersecurity topics and strip away the jargon, making sure you get the clear, practical information you need to keep your website safe.