Tutorial: Installing Traefik for hosting multiple websites with SSL on your VPS

Suppose you had deployed several microservices using Docker and you want to connect these microservices to the outside world. You will probably use some reverse proxy solution that will act as a frontend for these microservices. Nginx is the most popular and efficient reverse proxy solution, but it was written before before container technology (Docker) became so popular.

Say, for example, you want to remove one of the microservices from the container or change its port, and, as a result, you have to edit the Nginx configuration file to reflect the new container settings. Now, consider another situation where you add, delete, or scale the microservices application several times in a day—now, you’re editing the routes and other settings several times in the reverse proxy configuration file.

There’s a need for new generation of reverse proxy solution. Traefik is a modern reverse proxy solution written in GO to meet new these new containerized challenges.

“Træfik listens to your service registry/orchestrator API and instantly generates the routes so your microservices are connected to the outside world – without further intervention from your part.” Source: https://Traefik.io/

Traefik was developed with containerized technology in mind, which means there’s a lot of new features available in comparison with other reverse proxy solutions. When running, Traefik does the following and more:

  • Dynamically updates the configuration and loads it without restart.
  • Load balances requests from the outside world using multiple available algorithms.
  • Enables HTTPS for microservices using Let’s Encrypt.
  • A clean web UI.
  • Support for Websocket, HTTP/2, GRPC.
  • Provides metrics to Rest, Prometheus, Datadog, Statsd, InfluxDB.

In this article, we will check how to install and configure Traefik in a standalone and Dockerized environment, and then give examples of connecting it to your microservices in the backend.

Prerequisites:

  • A VPS running Ubuntu 16.04.
  • A non-root, sudo-enabled user. If you only have a root user, see our SSH tutorial for details on creating new users.
  • A working Docker installation—for information about how to install Docker, check out our getting started with Docker tutorial

Step 1. Install Docker

To install the Docker use the following command.

$ sudo curl -sS https://get.docker.com/ | sh

The above command will update your system and install the correct version of docker.

Enable the docker service and start it.

$ sudo systemctl enable docker
$ sudo systemctl start docker

Step 2. Installing non-Dockerized backend applications

Our first goal is to route few applications (backend) using Traefik (frontend) without Dockerizing them. To do that, we’ll install Apache and Nginx and configure them to use different ports, as they will act as a backend.

$ sudo apt-get install apache2

Change the port number to 8083 from 80 in /etc/apache2/ports.conf and restart Apache.

$ sudo vi /etc/apache2/ports.conf
$ sudo systemctl restart apache2

Install Nginx and change the port number to 8082 in the following two files. Then, restart Nginx.

$ sudo apt-get install nginx
$ sudo vi /etc/nginx/sites-available/default
$ sudo vi /etc/nginx/sites-enabled/default
$ sudo systemctl restart nginx

Now both Apache and Nginx will be available in the port number 8083 and 8082, respectively.

Step 3. Run Traefik from the binary

To install Traefik as a standalone environment, we need to download the binary and edit the Traefik configuration file and rules files.

Download the Traefik binary from the releases page and make it executable.

$ mkdir Traefik && cd Traefik
$ wget https://github.com/containous/Traefik/releases/download/v1.6.0/Traefik
$ chmod u+x Traefik

Next, download the sample Traefik configuration file and use it as a reference for many of the available Traefik options. We will use only a few of the options to get started.

$ wget https://raw.githubusercontent.com/containous/Traefik/master/Traefik.sample.toml
$ mv Traefik.sample.toml Traefik.toml
$ vi Traefik.toml

Once you have the Traefik.toml open, you can add the following at the beginning of the file, just beneath the Global configuration block.

logLevel = "DEBUG"
defaultEntryPoints = ["http"]
[entryPoints]
    [entryPoints.http]
    address = ":80"
[file]
filename = "./rules.toml"
watch = true

Next, create the rules file:

# vi rules.toml

Add the following to this file, replacing YOURDOMAIN with the domain name you’re going to use for this application:

[entryPoints]
  [entryPoints.http]
  address = ":8080"

[frontends]

  [frontends.frontend1]
  backend = "backend1"
    [frontends.frontend1.routes.test_1]
    rule = "Host: Traefik.YOURDOMAIN"

  [frontends.frontend2]
  backend = "backend2"
    [frontends.frontend2.routes.test_1]
    rule = "Host: apache.YOURDOMAIN"

[backends]

  [backends.backend1]
    [backends.backend1.servers.server1]
    url = "http://127.0.0.1:8082"

  [backends.backend2]
    [backends.backend2.servers.server1]
    url = "http://127.0.0.1:8083"

In the above Traefik rules configuration file, we have created two frontends with two domain names, and they will proxy the two backends we created earlier: the Apache and Nginx instances.

Finally, you can start the Traefik binary:

# ./traefik -c Traefik.toml

The subdomains (i.e the frontends) that you defined in the above rules files will now be available on port 80.

With little modification to the above rules file, we can make Traefik to act as a load balancer between both Apache and Nginx instances.

# vi rules.toml

Either delete the file’s contents and replace with the following:

[entryPoints]
  [entryPoints.http]
  address = ":8080"

[frontends]
  [frontends.frontend1]
  backend = "backend1"
    [frontends.frontend1.routes.test_1]
    rule = "Host: Traefik.YOURDOMAIN"
    
[backends]
  [backends.backend1]
    [backends.backend1.LoadBalancer]
      method = "drr"

    [backends.backend1.servers.server1]
    url = "http://127.0.0.1:8082"
    weight = 1

    [backends.backend1.servers.server2]
    url = "http://127.0.0.1:8083"
    weight = 2

Now, you can start Traefik again—but remember you have to kill previous instances of it first.

./traefik -c traefik.toml

Use your browser to visit the domain name that you entered into the rules.toml file and hit refresh. You’ll find that Traefik is both proxying load balancing the Apache and Nginx backends.

Now, let’s look at this same process, but using Docker, docker-compose, and containerized/Dockerized microservices, which is likely how many of you will end up using Traefik.

Step 4. Installing Traefik via docker-compose

First, you should install docker-compose if you don’t have it already.

curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` > ./docker-compose
$ sudo mv ./docker-compose /usr/bin/docker-compose
$ sudo chmod +x /usr/bin/docker-compose

To run Traefik using docker-compose, let’s create a docker-compose.yml file, in which we will define services for Traefik and other two microservices—Apache and Nginx, just like before.

# vi docker-compose.yml

Add the following:

version: '3'

services:
  proxy:
    image: traefik:latest
    command: --web --docker --docker.domain=YOURDOMAIN.local --logLevel=DEBUG
    networks:
      - traefik
    ports:
      - 80:80
      - 443:443
      - 8080:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /root/traefik.toml:/traefik.toml
      - /root/acme.json:/acme.json
          
  apache:
    image: httpd:latest
    labels:
      - "traefik.frontend.rule=Host:apache.YOURDOMAIN"
    networks:
      - traefik
  nginx:
    image: nginx:latest
    labels:
      - "traefik.frontend.rule=Host:Traefik.YOURDOMAIN"
    networks:
      - traefik

networks:
  traefik:
    external: true

Three services have been defined in the above docker-compose.yml file, and they are proxy, apache and nginx. The --web option enables the web interface for Traefik, the --docker option instructs Traefik that you are using docker configuration, and the --docker.domain sets the default URL for containers to *.tuxlab.local.

In the port section, 8080 is the port used by Traefik for its web interface and port 80is used for all default http requests. In the volume section, the Docker socket is accessed by Traefik to route requests to the right container. We need to knit all the three services together so that they can communicate with each other, which is why we created the Traefik network at the end of the file.

In the Apache/Nginx service section, the Traefik.frontend.rule is used to route request to the right container. And, at last, we had defined a network that can communicate with other containers with the option external: true.

Next we will create a Traefik configuration file:

# vi traefik.toml

Add the following, being sure to change the domain = "YOURDOMAIN.local" and email="YOUREMAIL" lines accordingly.

logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"]

[web]
address = ":8080"

[docker]
domain = "YOURDOMAIN.local"
watch = true

[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
 
[acme]
  email="YOUREMAIL"
  storage="acme.json"
  entryPoint="https"
  acmeLogging=true
  onDemand=false
  OnHostRule=true

[acme.httpChallenge]
  entryPoint = "http"

The above Traefik configuration file sets the log level to debug and allows both HTTP and HTTPS requests to the frontend. We then force HTTP (80) traffic to redirect to HTTPS (443) in entrypoints section. The Traefik web interface is configured on port 8080, and the Docker section instructs Traefik to use Docker as a configuration source.

The acme section is used by Traefik to fetch a Let’s Encrypt certificate for the domain that appears in the docker-compose.yml. The great thing about Traefik is that these certificates are dynamic, meaning that if you add a new domain or subdomain to docker-compose.yml, Traefik will automatically fetch the key/certificate and store them in acme.json.

The onDemand option in acme section will let Traefik request certificates whenever a web request is received for a domain or subdomain which does not already have a certificate. The onHostRule only requests new certificates for domain names that are listed in the docker-compose.yml file.

Create an empty JSON file to hold Let’s Encrypt data that and make this file readable/writable to only the root user.

# touch /root/acme.json
# chmod 600 /root/acme.json

Since we have configured all the three containers to use the network by the name Traefik, we should create it through terminal before starting the container.

# docker network create Traefik

Fire up the containers with the following command in the terminal.

# docker-compose up -d 

The two backends you created will be served by Traefik at http://traefik.YOURDOMAIN and http://apache.YOURDOMAIN. You can visit the Traefik dashboard at either http://traefik.YOURDOMAIN:8080/dashboard or http://apache.YOURDOMAIN:8080/dashboard.

You’re up and running with a proxied, load-balanced, fully Dockerized reverse proxy that’s fully HTTPS-enabled. Congratulations!

Moving forward with Traefik

Now that you have run Traefik from both the binary and using docker-compose, you’re ready to add more microservices! If you add new Docker images in the docker-compose.yml, Traefik will recognize newly added backends immediately and route the request to it without any further configuration of Traefik or restarting it.

For more configuration options, see the Traefik documentation.

Now, you might be asking, “What should I install behind this amazing Traefik reverse proxy?”

Well, how about you start with self-hosting an RSS reader? Or, check out these five cool self-hosted apps. Maybe you want to put Alphabet’s Outline VPN behind a reverse proxy? The options are endless—have fun and get more from your VPS at the same time.

Get 24GB RAM for $9.99/mo!

Save $3,960 with SSD Nodes versus competitors like Digital Ocean or Amazon Lightsail.

Snag limited-time prices: