Install and Configure Nginx with SSL on a KVM VPS

By Raman Kumar

Updated on Apr 09, 2025

In this tutorial, we'll learn how to install and configure Nginx with SSL on a KVM VPS. Secure it with Let’s Encrypt SSL certificates, and optimize some of the basic settings. This tutorial performed on Ubuntu 24.04 server.

Prerequisites

  • A Ubuntu 24.04 installed dedicated server or KVM VPS.
  • A root user or normal user with administrative privileges.
  • A domain name point A record to server's IP

1. Preparation

Server Updates: It is a best practice to update your VPS packages before installing new software:

sudo apt update && sudo apt upgrade -y

2. Installing Nginx

Most Linux distributions provide Nginx in their official package repositories. On Ubuntu/Debian:

sudo apt install nginx -y

2.1 Verifying Nginx Status

After the installation completes, check whether Nginx is running and enabled:

sudo systemctl status nginx

You should see an output indicating that nginx is “active (running).” If it is inactive, start and enable Nginx with:

sudo systemctl start nginx
sudo systemctl enable nginx

2.2 Firewall Configuration

If you are using UFW on Ubuntu/Debian, allow HTTP and HTTPS traffic:

sudo ufw allow 'Nginx HTTP'
sudo ufw allow 'Nginx HTTPS'

Confirm that the rules are applied:

sudo ufw status

You should see rules for 80/tcp and 443/tcp.

3. Obtaining and Installing Let’s Encrypt SSL Certificates

Let’s Encrypt provides free SSL/TLS certificates. To manage the certificate issuance and renewal, you will use Certbot.

3.1 Install Certbot

sudo apt install certbot python3-certbot-nginx -y

If you are on a different distribution, Certbot might be packaged differently, or you might have to download it from the snap package or EPEL repository (for CentOS-based systems). But in most Ubuntu/Debian systems, certbot and python3-certbot-nginx are sufficient.

3.2 Configure a Server Block (Optional but Recommended)

Before you request a certificate, it is best practice to set up an Nginx server block (virtual host configuration) for your domain. Let’s say your domain is example.com; create a configuration file in /etc/nginx/sites-available/:

sudo nano /etc/nginx/sites-available/example.com

Insert something like this basic configuration:

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;
    root /var/www/example.com;    # Path to your web root folder
    index index.html index.htm;   # Or index.php if you use PHP

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

Then enable this configuration by creating a symbolic link to /etc/nginx/sites-enabled/:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

Make sure that /var/www/example.com/ exists:

sudo mkdir -p /var/www/example.com
sudo chown -R www-data:www-data /var/www/example.com

Finally, test Nginx configuration syntax and reload:

sudo nginx -t
sudo systemctl reload nginx

3.3 Obtain Let’s Encrypt SSL Certificate

Now that your domain is served on HTTP port 80, Certbot can verify ownership of the domain. Issue the certificate by running:

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

Certbot will:

  • Ask for an email address (for expiry notices).
  • Ask whether you agree to the terms of service.

When finished, you can verify by visiting https://example.com in your browser. You should see a valid SSL padlock in the URL bar.

3.4 Automatic Certificate Renewal

Let’s Encrypt certificates are valid for 90 days. The package certbot should install a systemd timer or a cron job by default that automates renewal. Confirm your renewal timer:

systemctl list-timers | grep certbot

or

sudo certbot renew --dry-run

The --dry-run test verifies that everything is properly configured. If successful, you do not need to do anything else for renewal.

4. Basic Nginx SSL Configuration and Security Best Practices

Now that you have a valid SSL certificate, you should refine your Nginx configurations to increase security and performance.

4.1 Enforce Strong TLS Protocols

By default, Nginx supports multiple TLS versions. Modern best practice is to enable TLS 1.2 and TLS 1.3 only, disabling older protocols (TLS 1.0, 1.1). Inside your server block that handles SSL (/etc/nginx/sites-available/example.com or in a broader /etc/nginx/nginx.conf SSL configuration segment), adjust the SSL directives:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;

ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';

You can fetch updated ciphers from the Mozilla SSL Configuration Generator.

4.2 HTTP Strict Transport Security (HSTS)

HSTS forces clients to use HTTPS for a specified period. This can prevent certain man-in-the-middle attacks. Add it to your server block:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Note: Once you enable HSTS with a high max-age, browsers will remember it. If you later decide to revert to HTTP or change domains/subdomains, be aware that HSTS remains cached.

4.3 OCSP Stapling

To speed up certificate verification, enable OCSP Stapling. You need the fullchain and trusted CA certificate from Let’s Encrypt:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;  # Example resolvers
resolver_timeout 5s;

4.4 Enable HTTP/2

For better performance over SSL, enable HTTP/2:

listen 443 ssl http2;

Then reload Nginx:

sudo systemctl reload nginx

5. Basic Nginx Performance Tuning

5.1 Adjust Worker Processes

Edit the main configuration file /etc/nginx/nginx.conf to set worker processes and connections. By default, Nginx sets them automatically. A common baseline is:

worker_processes auto;
events {
    worker_connections 1024;
}
  • worker_processes auto;: Detects the number of CPU cores and assigns worker processes automatically.
  • worker_connections 1024;: The number of connections each worker can handle.

5.2 Gzip Compression

You can enable Gzip compression to reduce bandwidth usage:

gzip on;
gzip_types text/plain text/css application/json application/javascript application/xml image/svg+xml;
gzip_vary on;

Place these directives in the http block of /etc/nginx/nginx.conf or in a separate file included by the http block.

5.3 Caching Static Files

If you serve static assets (images, CSS, JS), you can set caching headers:

location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg)$ {
    expires 30d;
    add_header Cache-Control "public, no-transform";
}

Place this inside your server block for optimal performance with static files.

6. Testing Your Configuration

Nginx Syntax: Before you reload or restart Nginx, always test the configuration:

sudo nginx -t

Fix any syntax errors or typos reported.

Service Reload: After updates:

sudo systemctl reload nginx

or

sudo systemctl restart nginx

Browser Test: Visit https://example.com and confirm that the padlock icon is present, and that you’re being redirected from HTTP to HTTPS if you attempt to connect over http://example.com.

SSL Labs Test: (Optional) If internet access was available, you could test your site using SSL Labs’ SSL Server Test. Aim for an A rating or higher. Since direct external web access isn’t possible here, keep this as a general best practice recommendation.

7. Maintenance and Updates

Nginx Updates: Keep your system and Nginx updated:

sudo apt update && sudo apt upgrade -y

Certificate Renewal: Check periodically that Certbot’s renewal is successful. If you receive emails about upcoming certificate expiration, try sudo certbot renew manually to see if it works, or troubleshoot any issues.

Log Rotation: Nginx logs typically rotate automatically via /etc/logrotate.d/nginx. Confirm that logs are rotating properly to avoid large log files.

Monitor Performance: Tools like htop, top, or netstat can help monitor usage. If your site receives high traffic, you may need to tune worker connections, caching, or spin up more CPU cores and memory on your VPS.

8. Summary

  • Install Nginx from your distribution’s repository and enable it.
  • Open Firewall Ports to allow web traffic on ports 80 and 443.
  • Install Certbot and use it to obtain a Let’s Encrypt certificate, configuring Nginx automatically.
  • Optimize SSL to use modern protocols like TLS 1.2 and 1.3, enable OCSP Stapling, and consider HTTP/2.
  • Enhance Security with HSTS and carefully select SSL ciphers for a strong security posture.
  • Optimize Nginx with the right number of worker processes, gzip compression, and caching for static files.
  • Keep Everything Updated: Nginx, Certbot, and your system for security patches, performance improvements, and reliability.

Following these steps will result in a secure, performant, and well-maintained Nginx server. This forms a solid foundation for hosting web applications or static websites with HTTPS enabled by default, which is the modern standard for web security.

Additional Tips

Backup Configuration: Always keep a backup of your main config files (in /etc/nginx/ and /etc/letsencrypt/) in case you need to revert.

Least Privilege Principle: Use a non-root user for routine operations and limit service permissions as much as possible.

Monitoring: Setting up server monitoring (using tools like Prometheus, Grafana, or Nagios) helps you catch potential issues early (high CPU, memory usage, etc.).

Auto Renewal Checking: You can set up an email alert (or any other alerting mechanism) if for some reason renewal fails.

With these best practices and configurations, your KVM VPS should deliver content securely and efficiently. If you need advanced configuration (like load balancing, reverse proxy, or advanced caching strategies), Nginx offers a wide array of features you can explore in the official documentation.

Check out robust data center services in New Zealand