How To Set Up A Reverse Proxy With Free SSL Using Nginx-Proxy

4 Comments
Modified: 13.05.2023

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!

Don’t want to read? Watch the video instead!

Introduction

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.

Server icon

VPS Hosting Course

Learn everything you need to know about servers and hosting your own applications!

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.

Need help or want to share feedback? Join my discord community!

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.

KOFI Logo

If this guide is helpful to you and you like what I do, please support me with a coffee!

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: <your@email.tld>

  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 VIRTUAL_HOST and LETSENCRYPT_HOST variables, and you are done!

Conclusion

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!

[convertkit form=2303042]

Discussion (4)