How to Set Up HTTPS on Your Website with Docker, Nginx and Let‘s Encrypt

If you own a website in 2023, securing it with HTTPS is no longer optional—it‘s a must. HTTPS protects your website and your users by encrypting traffic between the browser and server. This prevents hackers and third parties from intercepting sensitive data like passwords, credit card numbers, and personal information. What‘s more, HTTPS is a ranking factor for SEO, and many browsers now warn users when they visit a website that doesn‘t have a valid SSL/TLS certificate.

Fortunately, in this day and age, there‘s no reason not to use HTTPS. Let‘s Encrypt is a free certificate authority that provides SSL/TLS certificates to anyone who owns a domain name. What‘s more, the process of obtaining and installing certificates can be fully automated. And by using Docker and Nginx, you can set up a secure reverse proxy for your website in just a few simple steps.

In this post, I‘ll walk you through the process of setting up HTTPS on your website with Docker, Nginx, and Let‘s Encrypt. By the end, you‘ll have a website that‘s more secure, trustworthy, and optimized for search engines. Let‘s get started!

Prerequisites

Before we begin, make sure you have the following:

  • A registered domain name
  • A server with Docker and Docker Compose installed
  • Port 80 and 443 open on your server‘s firewall

I‘ll be using Ubuntu 20.04 in the examples, but the instructions should be similar for other Linux distributions.

Step 1: Create a Docker Compose File

The first step is to create a Docker Compose file that defines the services for your website. Create a new file called docker-compose.yml and add the following:

version: ‘3‘

services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./certbot/www:/var/www/certbot
    command: "/bin/sh -c ‘while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"‘"

  certbot:
    image: certbot/certbot
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c ‘trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;‘"

This file defines two services:

  • nginx: This is the Nginx web server that will act as a reverse proxy for your website. It listens on ports 80 and 443, and mounts two volumes: one for the Nginx configuration files, and one for the Let‘s Encrypt certificate files.
  • certbot: This is the Let‘s Encrypt client that will handle obtaining and renewing SSL certificates. It mounts the same volumes as the Nginx service.

The command and entrypoint options for each service ensure that the containers keep running and automatically renew the SSL certificates.

Step 2: Configure Nginx

Next, you need to configure Nginx to act as a reverse proxy for your website. Create a new directory called nginx/conf.d, and inside it, create a file called default.conf with the following contents:

server {
    listen 80;
    server_name example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name example.com;

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

    location / {
        proxy_pass http://backend;
    }
}

Replace example.com with your domain name. This configuration file does the following:

  • Listens on port 80 and serves the Let‘s Encrypt challenge files from the /var/www/certbot directory. This is necessary for Let‘s Encrypt to verify that you own the domain.
  • Redirects all HTTP traffic to HTTPS.
  • Listens on port 443 and serves your website over HTTPS. It uses the SSL certificate and private key obtained by Let‘s Encrypt.
  • Proxies requests to the backend service, which is assumed to be running on the same Docker network. You‘ll need to update this to match your actual backend service.

Step 3: Obtain SSL Certificates

With the Nginx configuration in place, you can now obtain SSL certificates from Let‘s Encrypt. Run the following command:

docker-compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot -d example.com

Replace example.com with your domain name. This command will obtain a new SSL certificate for your domain and store it in the ./certbot/conf directory.

Step 4: Start the Containers

Now that everything is configured, you can start the containers:

docker-compose up -d

This will start the Nginx and Certbot containers in detached mode. You should now be able to access your website over HTTPS!

Step 5: Set Up Automatic Certificate Renewal

Let‘s Encrypt certificates are valid for 90 days, so you‘ll need to renew them regularly. Fortunately, the Certbot container is configured to automatically renew the certificates before they expire.

To test the renewal process, you can run:

docker-compose run --rm certbot renew --dry-run

This will simulate the renewal process without actually renewing the certificates. If everything looks good, you‘re all set!

Advanced Configuration

Now that you have a basic HTTPS setup working, there are a few additional things you can do to strengthen your website‘s security and performance:

  1. Configure Diffie-Hellman Parameters: Diffie-Hellman key exchange provides additional security for your SSL/TLS connections. You can generate a strong set of DH parameters with the following command:

    openssl dhparam -out ./certbot/conf/ssl-dhparams.pem 2048

    Then, add the following line to your Nginx configuration file in the server block for port 443:

    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
  2. Enable HTTP/2: HTTP/2 is a newer version of the HTTP protocol that provides better performance and security. To enable it, simply add the http2 parameter to the listen directive in your Nginx configuration file:

    listen 443 ssl http2;
  3. Earn an A+ SSL Rating: SSL Labs is a free online service that analyzes your website‘s SSL/TLS configuration and assigns it a letter grade. To get an A+ rating, you‘ll need to configure Nginx to use only strong ciphers and protocols. Add the following lines to your Nginx configuration file in the server block for port 443:

    ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
  4. Secure the Nginx Docker Container: By default, the Nginx container runs as the root user, which can be a security risk. To run Nginx as an unprivileged user, add the following lines to your Nginx service in the docker-compose.yml file:

    user: "101"
    cap_drop:
      - ALL

    This runs Nginx as the user with ID 101 (which is the nginx user in the container) and drops all Linux capabilities for added security.

Conclusion

In this post, we‘ve seen how to set up HTTPS on your website using Docker, Nginx, and Let‘s Encrypt. By using these tools, you can easily secure your website with a free SSL/TLS certificate and automatically renew it before it expires.

We‘ve also covered some advanced configuration options to strengthen your website‘s security and performance, such as configuring Diffie-Hellman parameters, enabling HTTP/2, earning an A+ SSL rating, and securing the Nginx Docker container.

Securing your website with HTTPS is essential in today‘s web landscape. Not only does it protect your users‘ data from interception and tampering, but it also improves your search engine rankings and builds trust with your visitors. With Docker, Nginx, and Let‘s Encrypt, there‘s no excuse not to use HTTPS on your website.

So what are you waiting for? Go forth and secure your website!

Similar Posts