[REPORT] From Vision to Code: A Guide to Aligning Business Strategy with Software Development Goals is published!
GET IT here

Load Balancing and Reverse Proxy With Traefik

readtime
Last updated on
September 18, 2023

A QUICK SUMMARY – FOR THE BUSY ONES

Traefik load balancer and reverse proxy server

Traefik is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. Traefik integrates with your existing infrastructure components and configures itself automatically and dynamically.

In this article, you'll see how to:

  • set up Traefik v1.7.12 (version 2.0 alpha has been made available recently, more about the subject here) on Rancher infrastructure.

Goal:

  • to simplify the process of exposing your app and optaining SSL/TLS certificates.

TABLE OF CONTENTS

Load Balancing and Reverse Proxy With Traefik

Introduction

Traefik is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. Traefik integrates with your existing infrastructure components (Docker, Swarm mode, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS, …) and configures itself automatically and dynamically. Pointing Traefik at your orchestrator should be the only configuration step you need.

In this article, I will show you how to set up Traefik v1.7.12 (version 2.0 alpha has been made available recently, more about the subject here) on Rancher infrastructure. It simplifies the process of exposing your applications and obtaining SSL/TLS certificates from “Let’s Encrypt” service.

This tutorial assumes that you have basic knowledge of Docker and Rancher.

Requirements:

  • Rancher (already configured and running)
  • Traefik – no worries, it’s free
  • Some web app to deploy

Let’s begin by creating a configuration file

As we will use it on Rancher, first we need to enable the Rancher provider:

# Enable Rancher Provider.
[rancher]

 # Default base domain used for the frontend rules.
 domain = "<BASE_DOMAIN>"

 # Expose Rancher services by default in Traefik.
 # If true all services will be accessed on <PROTOCOL>://<SERVICE_NAME>.<STACK_NAME>.<DOMAIN>:<HTTP_PORT>
 exposedByDefault = false

 # Expose only services with a healthy state.
 enableServiceHealthFilter = true

 # Credentials for Rancher API
 [rancher.api]

   # Endpoint to use when connecting to the Rancher API.
   # It is a little bit tricky as we will configure the domain for Rancher later in this article.
   endpoint = "https://<RANCHER_DOMAIN>/v1"

   # Credentials for Rancher API
   accessKey = "<RANCHER_ACCESS_KEY>"
   secretKey = "<RANCHER_SECRET_KEY>"

Credentials can be generated on the API/Keys page on Rancher. Just click the “Add Environment API Key” button.

Then we will configure entrypoints for all of the applications.

# Entrypoints to be used by frontends that do not specify any entrypoint.
# Each frontend can specify its own entrypoints.
defaultEntryPoints = ["http", "https"]

# Entrypoints definition.
[entryPoints]

 # HTTP definition.
 [entryPoints.http]

   # Default 80 port for HTTP requests.
   address = ":80"

   # Enable gzip compression
   # Responses are compressed when:
   # - The response body is larger than 512 bytes
   # - And the Accept-Encoding request header contains gzip
   # - And the response is not already compressed
   compress: true

 # HTTPS definition.
 [entryPoints.https]

   # Default 443 port for HTTPS requests.
   address = ":443"

   # Enable TLS encryption on HTTPS endpoints.
   [entryPoints.https.tls]

In order to correctly obtain certificates from “Let’s encrypt”, we need to enable ACME (Automatic Certificate Management Environment) Protocol.

# Enable ACME.
[acme]

# Email address used for registration on Let’s Encrypt.
email = "<EMAIL_ADDRESS>"

# File used for certificate storage.
storage = "/etc/traefik/acme/acme.json"

# Entrypoint to proxy acme apply certificates to.
entryPoint = "https"

# Enable certificate generation on frontend host rules.
onHostRule = true

# Use a HTTP-01 ACME challenge.
[acme.httpChallenge]

 # USE HTTP endpoint for this challenge.
 entrypoint = "http"

Now we can configure the domain for Rancher.

[file]

[backends]

 # Set name of backend describing Rancher. We name it "rancher".
 [backends.rancher]

   [backends.rancher.servers]

     [backends.rancher.servers.server0]

       # URL to Rancher server.
       url = "http://<RANCHER_IP>:<RANCHER_PORT>"

       # As this is a single instance Rancher, we can set the weight to 1. All requests will be handled by this server.
       weight = 1

[frontends]

 # Set name of frontend describing Rancher. We use the same name "rancher".
 [frontends.rancher]

   # Backend which will handle requests.
   backend = "rancher"

   # Forward client Host header to the backend.
   passHostHeader = true

     [frontends.rancher.routes]

       [frontends.rancher.routes.route0]

         # Use this frontend only when the request contains Host header with our domain.
         rule = "Host:<RANCHER_DOMAIN>"

Now Traefik should correctly handle all requests to Rancher server. Additionally, it should obtain a new certificate for <RANCHER_DOMAIN> and allows connection to it over encrypted HTTPS protocol.

We can also set an option for retrying to send requests in case of network errors.

[retry]

We will save the configuration file under /home/docker/traefik/traefik.toml directory on the server. The whole configuration file for Traefik:

defaultEntryPoints = ["http", "https"]

[rancher]
 domain = "<BASE_DOMAIN>"
 exposedByDefault = false
 enableServiceHealthFilter = true

 [rancher.api]
   endpoint = "https://<RANCHER_DOMAIN>/v1"
   accessKey = "<RANCHER_ACCESS_KEY>"
   secretKey = "<RANCHER_SECRET_KEY>"

[entryPoints]

 [entryPoints.http]
   address = ":80"

 [entryPoints.https]
   address = ":443"

   [entryPoints.https.tls]

[acme]
 email = "<EMAIL_ADDRESS>"
 storage = "/etc/traefik/acme/acme.json"
 entryPoint = "https"
 onHostRule = true

 [acme.httpChallenge]
   entrypoint = "http"

[retry]

[file]

[backends]
 [backends.rancher]
   [backends.rancher.servers]
     [backends.rancher.servers.server0]
       url = "http://<RANCHER_IP>:<RANCHER_PORT>"
       weight = 1

[frontends]
 [frontends.rancher]
   backend = "rancher"
   passHostHeader = true

     [frontends.rancher.routes]
       [frontends.rancher.routes.route0]
         rule = "Host:<RANCHER_DOMAIN>"

After saving this configuration file on the server, create a new empty file acme.json next to it. Now we are ready to create a new stack on Rancher for Traefik.

Create a new stack for Traefik

Important note: You have to disable any other publicly available reverse proxies and to be able to do that you have to open Rancher via IP address.

After stopping the previously working reverse proxy and making sure that there are no containers with publicly exposed ports 80 or 443, click on “create a new stack”. Upload following docker-compose.yml file (of course update volumes accordingly to the directory where you saved the configuration file):

version: '2'
services:
 traefik:
   image: traefik:v1.7.12
   stdin_open: true
   volumes:
   - /home/docker/traefik/traefik.toml:/etc/traefik/traefik.toml
   - /home/docker/traefik/acme.json:/etc/traefik/acme/acme.json
   tty: true
   ports:
   - 80:80/tcp
   - 443:443/tcp
   labels:
     io.rancher.container.pull_image: traefik:v1.7.12

After deploying it, we are ready to use Traefik to handle requests made by our own applications. Also, Rancher should be available on encrypted URL: https://<RANCHER_DOMAIN>

Use Traefik on our own applications

In the last step, we need a web application. I will use a very sophisticated Hello World application.

I will create a new stack for it. Things that are important for Traefik are labels set for a specific container.

Enable this container in Traefik:

traefik.enable: 'true'

Sets the container name of the backend:

traefik.backend: node-hello-world

Registers port on which the application is listening (internal docker port):

traefik.port: '8080'

Use this container only when the request contains Host header with our domain:

traefik.frontend.rule: Host:<DOMAIN>

Sets the domain:

traefik.domain: <DOMAIN>

Overrides the default HTTP protocol:

traefik.frontend.protocol: https

Sets redirect from HTTP to encrypted HTTPS protocol:

traefik.frontend.redirect.entryPoint: https

Returns 301 instead of 302 for redirect:

traefik.frontend.redirect.permanent: 'true'

After setting correct labels to our application, it will be accessible on provided domain. The docker-compose.yml file that I will use for my Hello World application looks like this:

version: '2'
services:
 node-hello-world:
   image: heroku/nodejs-hello-world
   environment:
     PORT: '8080'
   stdin_open: true
   tty: true
   labels:
     io.rancher.container.pull_image: always
     traefik.enable: 'true'
     traefik.backend: node-hello-world
     traefik.port: '8080'
     traefik.frontend.rule: Host:<DOMAIN>
     traefik.domain: <DOMAIN>
     traefik.frontend.protocol: https
     traefik.frontend.redirect.entryPoint: https
     traefik.frontend.redirect.permanent: 'true'

Summary

Traefik is a reverse proxy that allows developers to expose their application on domains with ease. Built-in support for “Let’s Encrypt” will automatically discover new services and obtain SSL/TLS certificates. Also, it continuously updates its configuration, so no restarts are needed.

More information about Traefik can be found on the official page: https://docs.traefik.io/

Frequently Asked Questions

No items found.

Our promise

Every year, Brainhub helps 750,000+ founders, leaders and software engineers make smart tech decisions. We earn that trust by openly sharing our insights based on practical software engineering experience.

Authors

Adam Gołąb
github
JavaScript Software Engineer

Full-stack software engineer with 11 years of professional experience. React.js & Node.js enthusiast.

Bianka Pluszczewska
github
Tech Editor

Software development enthusiast with 8 years of professional experience in this industry.

Adam Gołąb
github
JavaScript Software Engineer

Full-stack software engineer with 11 years of professional experience. React.js & Node.js enthusiast.

Bianka Pluszczewska
github
Tech Editor

Software development enthusiast with 8 years of professional experience in this industry.

Read next

No items found...