--- author: Alvie Rahman date: \today title: Setting Up Nginx and Let's Encrypt in Docker tags: [ linux, docker, programming ] --- # Setting Up Nginx and Let's Encrypt in Docker This turned out to be way harder than I thought it would be. I tried to follow [this](https://pentacent.medium.com/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71) post here but the `init-letsencrypt.sh` script didn't work for me. Most of the content here is from that post. ## Create the necessary files ### `docker-compose.yaml` Notice how `certbot`'s `entrypoint` field is commented out? Yeah, that's one of the things that tripped me up. When the autorenew entrypoint is specified, you can't perform one of the future steps. ```yaml version: '3' services: nginx: image: nginx:1.15-alpine ports: - "80:80" - "443:443" volumes: - ./data/nginx:/etc/nginx/conf.d - ./data/certbot/conf:/etc/letsencrypt - ./data/certbot/www:/var/www/certbot certbot: image: certbot/certbot # entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" volumes: - ./data/certbot/conf:/etc/letsencrypt - ./data/certbot/www:/var/www/certbot ``` ### `data/nginx/app.conf` Again, things are commented out in this file. The SSL section is commented out as Nginx cannot start an SSL server without first having SSL certificates but certbot won't give us SSL certificates unless we have a webserver (the certbot Docker image supports hosting a standalone server for this purpose but that would mean changing around the ports in `docker-compose.yaml`). Also the 301 redirect in the port 80 section is commented out as we don't want to immediately redirect certbot to a https URL we aren't listening for. ``` server { listen 80; server_name DOMAIN.NAME; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { #return 301 https://$host$request_uri; proxy_pass http://example.com; } } # server { # listen 443 ssl; # server_name DOMAIN.NAME; # # location / { # # anything you want can go in here, of course # proxy_pass http://example.com; # } # ssl_certificate /etc/letsencrypt/live/DOMAIN.NAME/fullchain.pem; # ssl_certificate_key /etc/letsencrypt/live/DOMAIN.NAME/privkey.pem; # include /etc/letsencrypt/options-ssl-nginx.conf; # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # } ``` ## Set your domain Run the following command, replacing `REPLACEME` with your domain name: ``` sed -i 's/DOMAIN.NAME/REPLACEME/g' data/nginx/app.conf ``` ## Get your first certificates Run the following commands: docker-compose up -d nginx docker-compose run certbot certonly --webroot /var/www/certbot Enter the information your are prompted for. ## Enable HTTPS on Nginx and auto renew certificates 1. Uncomment the commented out server block in `data/nginx/app.conf`. 2. Remove the `proxy_pass` line in the port 80 server block. 3. Uncomment the line starting with `return 301` 4. Restart Nginx (`docker-compose restart nginx`) 5. Uncomment line beginning with `entrypoint` in `docker-compose.yaml`