How To Set Up A Reverse Proxy With Free SSL Using Nginx-Proxy
Are you looking to set up a reverse proxy for your hosted application and secure it with a free SSL certificate? Look no further! In this comprehensive guide, we’ll take you through the entire process step-by-step. From setting up nginx-proxy as a reverse proxy and automating SSL certificates with Let’s Encrypt!
In this four-part series, we already learned how to set up a server (VPS), and we successfully hosted a simple application using Docker, making it accessible through a domain using an A record. The next essential step is to secure our application with SSL to ensure safe data transfer between the server and the client. With services like Let’s Encrypt, obtaining an SSL certificate has become a breeze, and it’s free! So, in this post, we will learn how to set up a reverse proxy for your application and how to secure it with free SSL certificates. By the end of this post, you’ll be able to access your application under your domain with HTTPS, giving your project a more professional and secure look.
This post has two alternatives
- traefik: a bit more complex but more powerful and automated
- caddy: simple, powerful, but manual
- nginx-proxy and letsencrypt-companion (this post): simple and automated
You can read a comparison here.
Use nginx-proxy as a reverse proxy for your application
Now that we set up the domain for the server (If you did not set up a domain yet, do so before continuing. Learn how to do in the last post.), we can use nginx as a reverse proxy to direct the traffic from a certain domain to a certain container. Nginx-proxy is a docker image that automatically generates all the configurations etc., automatically for you. That way, you have to set one environment variable while creating the container, and nginx-proxy will take care of the rest for you. If you are interested in learning how to write a config yourself, check this post here.
The environment variable you have to set is called
VIRTUAL_HOST, and to set it, we need to modify the
docker-compose.yml file from the last post. In addition to setting the variable, we can also remove the port mapping because nginx-proxy will now take care of this for us. Nginx-proxy needs an exposed port. We exposed port 80 inside the Dockerfile already. If you did not do so, you need to expose the port in the docker-compose file.
In addition to modifying our application container, we also need to add the nginx-proxy container (for a more in-depth explanation of the nginx-proxy container, check this post here). The new file looks like this:
services: nginx: container_name: nginx image: nginxproxy/nginx-proxy restart: unless-stopped ports: - 80:80 - 443:443 volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./nginx/html:/usr/share/nginx/html - ./nginx/certs:/etc/nginx/certs - ./nginx/vhost:/etc/nginx/vhost.d logging: options: max-size: "10m" max-file: "3" frontend: container_name: frontend image: ghcr.io/<username>/<image-name>:latest environment: VIRTUAL_HOST: <domain.tld>
If you run this file using
docker compose up -d now, you can already access your application with your domain using the http protocol. But before we do so, we will also set up free SSL certificates for it so that we can access it using https.
Set up free and automated SSL certificates for your server (VPS)
To do so, we will create another container called
letsencrypt-companion. This container is an add-on to nginx-proxy and takes care of the SSL certificates for you. For it to work, we have to specify the container inside the compose file and additionally add the LETSENCRYPT_HOST variable to our application container.
The final file will then look like this:
services: nginx: container_name: nginx image: nginxproxy/nginx-proxy restart: unless-stopped ports: - 80:80 - 443:443 volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./nginx/html:/usr/share/nginx/html - ./nginx/certs:/etc/nginx/certs - ./nginx/vhost:/etc/nginx/vhost.d logging: options: max-size: "10m" max-file: "3" letsencrypt-companion: container_name: letsencrypt-companion image: jrcs/letsencrypt-nginx-proxy-companion restart: unless-stopped volumes_from: - nginx volumes: - /var/run/docker.sock:/var/run/docker.sock - ./nginx/acme:/etc/acme.sh environment: DEFAULT_EMAIL: <email@example.com> frontend: container_name: frontend image: ghcr.io/<username>/<image-name>:latest environment: VIRTUAL_HOST: <domain.tld> LETSENCRYPT_HOST: <domain.tld>
With that, we created an easy-to-use template for your applications. You can simply add a new application container, set the
LETSENCRYPT_HOST variables, and you are done!
In this series of posts, we learned how to set up a server (VPS), how to host our first application using docker, and lastly, how to set up a domain and secure it using a reverse proxy with free SSL certificates. Our application is now reachable through https and our chosen domain!
I hope these posts were helpful to you. If so, share them with your friends, and let me know if you have questions!
In case you liked this consider subscribing to my newsletter and joining my discord community!