InfluxDB 2.0 - Quickly Enabling TLS Encryption with Traefik

siaarzh

Serzhan Akhmetov

Posted on March 24, 2021

InfluxDB 2.0 - Quickly Enabling TLS Encryption with Traefik

Jumpstart your influxdb stack with automated TLS certificate management.

Use case

So you're running a bunch of IoT/Finance or Cryptocurrency services with Docker or Kubernetes and decided to use that shiny InfluxDB 2.0 dashboard in production. Heck, maybe even play around with the flux API too - for those extra fancy queries.

infludb 2.0 dashboard
(Who needs Grafana?)

Obviously, at this point you'll need to secure the traffic between your web application and your server (plus the microservices). This is exactly what TLS encryption does - you know, adds that https:// you see everywhere.

What you will need

  • You are running running your backend in Docker containers. This is either Docker, Docker Swarm or Kubernetes, or any other vendor that runs docker containers defined thru a YAML compose file or similar.
  • You are either running or planning to run Traefik as your proxy.
  • You own a domain name and can manage its DNS records.

Optional:

Instructions

  1. If you opt for the simpler HTTP-01 ACME Challenge, make sure you create all the necessary DNS records beforehand (i.e. create A or CNAME records), including any wildcard subdomain names. Having said that, if your really need wildcard certificates for subdomains, you should use the DNS-01 ACME Challenge.

    CAUTION: There are pros and cons for using each type of challenge. Use industry best practices and your own judgement when deciding which method to use for your project.

    Below is an example of typical DNS record table for a HTTP-01 Challenge:

    Type Hostname Value TTL (seconds)
    A example.com directs to 203.0.113.123 3600
    A traefik.example.com directs to 203.0.113.123 3600
    CNAME influxdb.example.com is an alias of example.com 43200

    Our main domain name is example.com and we are running two services that will be exposed via subdomain names traefik.* and influxdb.*. If you have more services you want accessible via subdomain, now's the time to add them here. TTL settings are irrelevant for this tutorial, so feel free to dive deeper into DNS on your own time.

    And here is the same table when attempting the DNS-01 Challenge:

    Type Hostname Value TTL (seconds
    A *.example.com directs to 203.0.113.123 3600
    A example.com directs to 203.0.113.123 3600
  2. We will store our certificates in a bind mounted acme.json. Therefore, appropriate permissions need to be set beforehand for Traefik to access (accept it as secure) this file:

    touch acme.json; chmod 600 acme.json
    
  3. (Re)define your InfluxDB container by applying the following labels:

    For Docker (using Compose):

      ...
      my-influxdb:
        image: influxdb:2.0
        labels:
          # traefik router settings
          traefik.http.routers.my-influxdb.rule: "Host(`influxdb.example.com`)"
          traefik.http.routers.my-influxdb.tls: "true"
          traefik.http.routers.my-influxdb.tls.certresolver: "myresolver"
          traefik.http.routers.my-influxdb.entrypoints: "websecure"
    

    For Docker Swarm:

      ...
      my-influxdb:
        image: influxdb:2.0
        deploy:
          labels:
            # traefik router settings
            traefik.http.routers.my-influxdb.rule: "Host(`influxdb.example.com`)"
            traefik.http.routers.my-influxdb.tls: "true"
            traefik.http.routers.my-influxdb.tls.certresolver: "myresolver"
            traefik.http.routers.my-influxdb.entrypoints: "websecure"
    
            # traefik service settings
            traefik.http.services.my-influxdb.loadbalancer.server.port: "8086"
    

    The names my-influxdb, myresolver, and websecure are unique identifiers in the Traefik configuration representing the router (service), the certificate resolver, and the entrypoint (port 443), respectively. Here, we defined the router my-influxdb for now, whereas the latter two will be defined in the following step. Notice that we do not expose service ports in our compose file anymore, since all traffic will now be handled by Traefik.

    Note: for Swarm, Traefik requires you explicitly define at least one port the service is running on, even it if has no listening ports. (see Port Detection - Traefik Docs)

    Don't forget to deploy this new configuration using docker compose up or docker stack deploy -c docker-compose.yml <stack_name>.

  4. Let's now add the Traefik container to your compose file.

    Below are 4 different ways to do this - depending on the combination of orchestrator and type of ACME Challenge.

    In all cases, we are using the staging Let's Encrypt server - this helps us to generate new certificates in case we mess up much faster since the rate limit is much higher. Once everything works, simply delete the line defining certificateresolvers.myresolver.acme.caserver and redeploy your Traefik container.

    In addition, the DNS server I'm using for the DNS-01 Challenge is digitalocean, which requires I define a DO_AUTH_TOKEN. Depending on your DNS provider, you will need to define different credentials.

    1. For Docker (Compose) + HTTP-01 Challenge:

      traefik:
        image: "traefik:v2.0.0"
        command:
          - --entrypoints.web.address=:80
          - --entrypoints.websecure.address=:443
          - --providers.docker
          - --api
          - --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
          - --certificatesresolvers.myresolver.acme.email=sample@email.com
          - --certificatesresolvers.myresolver.acme.storage=acme.json
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
          - "./acme.json:/acme.json"
        labels:
          # Traefik Dashboard
          traefik.http.routers.traefik.rule: "Host(`traefik.sample.com`)"
          traefik.http.routers.traefik.service: "api@internal"
          traefik.http.routers.traefik.tls.certresolver: "myresolver"
          traefik.http.routers.traefik.entrypoints: "websecure"
      
          # Redirect to HTTPS
          traefik.http.middlewares.redirect-to-https.redirectscheme.scheme: "https"
          traefik.http.routers.http-catchall.rule: "hostregexp(`{host:.+}`)"
          traefik.http.routers.http-catchall.entrypoints: "web"
          traefik.http.routers.http-catchall.middlewares: "redirect-to-https"
      
    2. For Docker (Compose) + DNS-01 Challenge:

      traefik:
        image: "traefik:v2.0.0"
        environment:
          DO_AUTH_TOKEN: "0f923jf..."
        command:
          - --entrypoints.web.address=:80
          - --entrypoints.websecure.address=:443
          - --providers.docker
          - --api
          - --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
          - --certificatesresolvers.myresolver.acme.dnschallenge.provider=digitalocean
          - --certificatesresolvers.myresolver.acme.dnschallenge.delaybeforecheck=0
          - --certificatesresolvers.myresolver.acme.email=sample@email.com
          - --certificatesresolvers.myresolver.acme.storage=acme.json
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
          - "./acme.json:/acme.json"
        labels:
          # Traefik Dashboard
          traefik.http.routers.traefik.rule: "Host(`traefik.sample.com`)"
          traefik.http.routers.traefik.service: "api@internal"
          traefik.http.routers.traefik.tls.certresolver: "myresolver"
          traefik.http.routers.traefik.entrypoints: "websecure"
      
          # Redirect to HTTPS
          traefik.http.middlewares.redirect-to-https.redirectscheme.scheme: "https"
          traefik.http.routers.http-catchall.rule: "hostregexp(`{host:.+}`)"
          traefik.http.routers.http-catchall.entrypoints: "web"
          traefik.http.routers.http-catchall.middlewares: "redirect-to-https"
      
    3. For Docker Swarm + HTTP-01 Challenge:

      traefik:
        image: "traefik:v2.0.0"
        command:
          - --entrypoints.web.address=:80
          - --entrypoints.websecure.address=:443
          - --providers.docker
          - --api
          - --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
          - --certificatesresolvers.myresolver.acme.email=sample@email.com
          - --certificatesresolvers.myresolver.acme.storage=acme.json
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
          - "./acme.json:/acme.json"
        deploy:
          labels:
            # Traefik Dashboard
            traefik.http.routers.traefik.rule: "Host(`traefik.sample.com`)"
            traefik.http.routers.traefik.service: "api@internal"
            traefik.http.routers.traefik.tls.certresolver: "myresolver"
            traefik.http.routers.traefik.entrypoints: "websecure"
      
            # Redirect to HTTPS
            traefik.http.middlewares.redirect-to-https.redirectscheme.scheme: "https"
            traefik.http.routers.http-catchall.rule: "hostregexp(`{host:.+}`)"
            traefik.http.routers.http-catchall.entrypoints: "web"
            traefik.http.routers.http-catchall.middlewares: "redirect-to-https"
      
            # service definitions
            traefik.http.services.traefik.loadbalancer.server.port: "80"
            traefik.http.services.traefik.loadbalancer.server.port: "443"
      
    4. For Docker Swarm + DNS-01 Challenge:

      traefik:
        image: "traefik:v2.0.0"
        environment:
          DO_AUTH_TOKEN: "0f923jf..."
        command:
          - --entrypoints.web.address=:80
          - --entrypoints.websecure.address=:443
          - --providers.docker
          - --api
          - --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
          - --certificatesresolvers.myresolver.acme.dnschallenge.provider=digitalocean
          - --certificatesresolvers.myresolver.acme.dnschallenge.delaybeforecheck=0
          - --certificatesresolvers.myresolver.acme.email=sample@email.com
          - --certificatesresolvers.myresolver.acme.storage=acme.json
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
          - "./acme.json:/acme.json"
        deploy:
          labels:
            # Traefik Dashboard
            traefik.http.routers.traefik.rule: "Host(`traefik.sample.com`)"
            traefik.http.routers.traefik.service: "api@internal"
            traefik.http.routers.traefik.tls.certresolver: "myresolver"
            traefik.http.routers.traefik.entrypoints: "websecure"
      
            # Redirect to HTTPS
            traefik.http.middlewares.redirect-to-https.redirectscheme.scheme: "https"
            traefik.http.routers.http-catchall.rule: "hostregexp(`{host:.+}`)"
            traefik.http.routers.http-catchall.entrypoints: "web"
            traefik.http.routers.http-catchall.middlewares: "redirect-to-https"
      
            # service definitions
            traefik.http.services.traefik.loadbalancer.server.port: "80"
            traefik.http.services.traefik.loadbalancer.server.port: "443"
      

    Again, don't forget to deploy this new service and after a couple of seconds you should be up and running.

Switch to Production

As mentioned in step 4, you'll be using the staging Let's Encrypt server for certificate generation. Thus, your certificate won't be trusted by the browser yet:

before TLS

Easy fix: as soon as everything works as expected with the invalid certificate simply delete the line defining certificateresolvers.myresolver.acme.caserver and redeploy your Traefik container.

After TLS

Still confused?

  1. Why use HTTPS?
  2. What is TLS
💖 💪 🙅 🚩
siaarzh
Serzhan Akhmetov

Posted on March 24, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related