All you have to do: Provide a config.json that looks like this:
{
"email": "myemail@example.com",
"domains": [
{
"name": "example.com",
"aliases": ["www.example.com"],
"dest": "http://app:8000"
}
]
}
and then start the service like so:
services:
reverse-proxy:
image: ghcr.io/intentionally-left-nil/reverse-proxy:latest
volumes:
- ./config.json:/etc/reverse_proxy/config.json
- reverse-proxy-data:/etc/reverse_proxy/data
ports:
- 80:80
- 443:443
networks:
- www
volumes:
reverse-proxy-data:
networks:
www:
name: reverse-proxy
And then when you run reverse-proxy it will:
- Automatically generate a nginx.conf file which serves https://example.com and https://www.example.com and forwards the traffic to http://app:8000
- Automatically generate a SSL certificate for example.com and www.example.com
- Automatically renew the SSL certificate every ~60 days
- Redirect HTTP traffic to HTTPS
So. that's basically it :)
SKIP_BOOTSTRAP=1
- don't create any config files, or self-signed certsSKIP_CREATE_CERTS=1
- don't call acme --issue to generate the SSL certificatesSKIP_RENEW_CERTS=1
- don't call acme --install-cronjob to renew the certificatesSKIP_WRITE_NGINX_CONF=1
- that /etc/reverse_proxy/nginx.conf is not overriden during the config processDEBUG=1
- add verbose logging (set -x) to figure out what's going wrongCONFIG_JSON={...}
- Instead of using a config.json file, you can instead set it as an environment variable instead
Since this is just nginx, you can customize the nginx.conf file to meet your exact needs
First, run the docker container, which will generate the nginx.conf (even when running locally). Use a bind mount for the volume so it's easy to access the data. For example: docker run --rm -v ./my_local_folder:/etc/reverse_proxy
(make sure to add a config.json with the correct data to my_local_folder).
Then, make the custom changes to my_local_folder/nginx.conf that you want to.
Finally, merge these config lines with your existing docker-compose.yml file
services:
reverse-proxy:
volumes:
- ./my_nginx.conf:/etc/reverse_proxy/nginx.conf
environment:
- SKIP_WRITE_NGINX_CONF=1
The SKIP_WRITE_NGINX_CONF
prevents the code from re-creating nginx.conf from the config
This uses the stateless mode to generate a SSL certificate. Basically, you do a one-time registration flow, which generates a token. Then, you just need to handle the URL <your_domain>/.well-known/acme-challenge/<random>
and return back <token>.<random>
.
location ~ ^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$ {
default_type text/plain;
return 200 "\$1.$account_thumbprint";
}
So, all of the devops revolves around making this happen. Some hoops to jump through include:
- To return the value you need a working webserver. However, you can't run nginx if there are certs missing. So, the code generates a temporary self-signed certificate so that nginx will start
- You need to start nginx before running the certs, so the cert generation is done as a cron job
- acme.sh uses a different cron job to renew the certs, so we need to make sure nginx is running
- To proxy_pass the data to the remote host, the DNS records need to be set. However, if you just start the reverse proxy, then the DNS entries aren't there. So we use the
set $variable
nginx trick to get around it
- cd ./test
- sudo docker compose up --build
- curl -k https://localhost
The docker image was last updated July 29, 2024