We use cookies to enhance your browsing experience, analyze traffic, and personalize advertisements. By clicking "Accept", you consent to the use of cookies. You can change your settings at any time. For more information, please see our Privacy Policy

How to Enable HTTPS Access Using Docker Compose Reverse Proxy and HTTP-01 Challenge

2024-06-17

Introduction

This article is a continuation of the previous one.

Last time, we built a reverse proxy using Docker Compose, then issued a Let's Encrypt certificate using Certbot and performed authentication via the HTTP-01 challenge.

 

How to Use Certbot in Docker Containers for HTTP-01 Challenge (Preparing for Zero Downtime Renewal)

This time, we’ll describe how to enable HTTPS access using the issued certificate.

From Certificate Issuance to HTTPS Access

Move the Certificate

Certificates issued by Certbot are usually added to /etc/letsencrypt/archive.

volumes:
   ...
- ./certbot/conf/archive:/etc/letsencrypt/archive
- ./certbot/conf/live:/etc/letsencrypt/live

Since the reverse proxy container can't access the certificates as-is, move them to the reverse proxy directory.

sudo mv /etc/letsencrypt/archive/example(domain) /home/docker/reverse-proxy/certbot/conf/archive/

Move the Symbolic Link

Move the symbolic link for the certificate as well.

sudo mv /etc/letsencrypt/live/example(domain) /home/docker/reverse-proxy/certbot/conf/live/

No need to change the relative path of the symlink.

Change Permissions

Set minimal permissions especially for confidential files such as private keys.

Path Permissions
reverse-proxy/certbot/conf/archive/example(domain) 700 (drwx------)
cert1.pem, chain1.pem, fullchain1.pem under above 644 (-rw-r--r--)
privkey1.pem under above 600 (-rw-------)
reverse-proxy/certbot/conf/live/example(domain) 700 (drwx------)

 

Configure Certificate Renewal

If you skip this step, renewed certs will go to the default path (/etc/letsencrypt/archive/...).

Update paths in the renewal config.

・/etc/letsencrypt/renewal/example(domain).conf

archive_dir = /etc/letsencrypt/archive/example(domain)
cert = /etc/letsencrypt/live/example(domain)/cert.pem
privkey = /etc/letsencrypt/live/example(domain)/privkey.pem
chain = /etc/letsencrypt/live/example(domain)/chain.pem
fullchain = /etc/letsencrypt/live/example(domain)/fullchain.pem

Update to:

archive_dir = /home/docker/reverse-proxy/certbot/conf/archive/example(domain)
cert = /home/docker/reverse-proxy/certbot/conf/live/example(domain)/cert.pem
privkey = /home/docker/reverse-proxy/certbot/conf/live/example(domain)/privkey.pem
chain = /home/docker/reverse-proxy/certbot/conf/live/example(domain)/chain.pem
fullchain = /home/docker/reverse-proxy/certbot/conf/live/example(domain)/fullchain.pem

Test with:

sudo certbot renew --dry-run
Congratulations, all simulated renewals succeeded:
  /home/docker/reverse-proxy/certbot/conf/live/example(domain)/fullchain.pem (success)

To force renewal for a specific domain:
sudo certbot renew --cert-name example(domain) --force-renewal

Confirm Certificate Update

Check issuance and expiration dates.

sudo openssl x509 -startdate -enddate -noout -in /home/docker/reverse-proxy/certbot/conf/live/example(domain)/fullchain.pem
notBefore=Jun 22 12:34:53 2024 GMT  
notAfter=Sep 20 12:34:52 2024 GMT

Previous certs aren’t deleted automatically.
Use a script if you want to clean them. Symlinks will update from xxx1 to xxx2 automatically.

Enable HTTPS Access

Update the nginx config file:

/home/docker/reverse-proxy/certbot/conf.d/reverse-proxy.conf

server {
    listen 80;
    server_name example(domain);
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    location / {
        proxy_pass http://webapp01-web-1/;
        proxy_redirect off;
    }
}

Add HTTPS support:

server_name example(domain);
 location /.well-known/acme-challenge/ {
     root /var/www/certbot;
 }
 location / {
     return 301 https://$host$request_uri;
  }
}

server {
    listen 443 ssl;
    server_name example(domain);
    ssl_certificate /etc/letsencrypt/live/example(domain)/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example(domain)/privkey.pem;

    location / {
        proxy_pass http://webapp01-web-1/;
        proxy_redirect off;
    }
}

 

Now HTTP requests are redirected to HTTPS with 301 redirect.

Conclusion

Be cautious when setting permissions on keys and directories.

If renewal fails or certs are issued in the wrong place:

・Check file permissions and ownership
Ensure proper access on both host and container.

・Check renewal config
Are paths to archive and live certs correct?

・Check symlink paths
Make sure symlinks point to the right location from both host and container.

Related Articles

https://it.hasethblog.com/archives/286
How to Enable HTTPS Access Using Docker Compose Reverse Proxy and HTTP-01 Challenge
Automating SSL Renewal for Custom Domains on Sakura VPS Using Docker Compose Reverse Proxy