<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>moritzvd.eu - Docker</title>
      <link>https://moritzvd.eu</link>
      <description></description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://moritzvd.eu/tags/docker/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Wed, 06 May 2020 12:47:00 +0000</lastBuildDate>
      <item>
          <title>Monitoring Traefik 2 with Icinga</title>
          <pubDate>Wed, 06 May 2020 12:47:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://moritzvd.eu/posts/monitor-traefik-icinga/</link>
          <guid>https://moritzvd.eu/posts/monitor-traefik-icinga/</guid>
          <description xml:base="https://moritzvd.eu/posts/monitor-traefik-icinga/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;traefik-icinga-banner.png&quot; alt=&quot;Monitoring Traefik 2 with Icinga&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Checking if a specific website or web application is alive and well is a classic task of monitoring software. I monitor personal web services with good old Icinga2. Last year I wrote a small Python script that runs on a Icinga2 master or satellite node that queries the Traefik API to automate the generation of Icinga2 rules. For me this was a nice and useful exercise to learn how to use REST APIs together with Python for system administration. In the process of &lt;a href=&quot;https:&#x2F;&#x2F;moritzvd.eu&#x2F;upgrade-traefik-2&#x2F;&quot;&gt;upgrading Traefik 1.7 to 2.0&lt;&#x2F;a&gt; I also had to modify this script.&lt;&#x2F;p&gt;
&lt;p&gt;So without further ado lets jump right in. The way my script works:&lt;&#x2F;p&gt;
&lt;p&gt;It fetches the exposed Traefik Routers with their coresponding hostnames and services and creates Icinga2 &lt;a href=&quot;https:&#x2F;&#x2F;icinga.com&#x2F;docs&#x2F;icinga2&#x2F;latest&#x2F;doc&#x2F;03-monitoring-basics&#x2F;#apply-rules&quot;&gt;apply rules&lt;&#x2F;a&gt; that use the &lt;a href=&quot;https:&#x2F;&#x2F;icinga.com&#x2F;docs&#x2F;icinga2&#x2F;latest&#x2F;doc&#x2F;10-icinga-template-library&#x2F;#http&quot;&gt;HTTP check&lt;&#x2F;a&gt;. The script is designed to run as a nightly cronjob so that new services that should be monitored are added automatically.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;requirements&quot;&gt;Requirements&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#requirements&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;A working Traefik v2.x reverse proxy with it&#x27;s API exposed&lt;&#x2F;li&gt;
&lt;li&gt;Icinga2 monitoring server&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Before proceeding please make shure you can access Traefik&#x27;s API. For example in this way:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;curl -s --user&lt;&#x2F;span&gt;&lt;span&gt; admin:passw0rd http:&#x2F;&#x2F;example.lan:8080&#x2F;api&#x2F;http&#x2F;routers | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;jq
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;[
&lt;&#x2F;span&gt;&lt;span&gt;  {
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;entryPoints&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dashboard&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;middlewares&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dashboard-auth@file&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#installation&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Run all this steps on a Icinga 2 master or satellite node.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;download-script-and-install-script&quot;&gt;Download script and install script&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#download-script-and-install-script&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span&gt; clone https:&#x2F;&#x2F;github.com&#x2F;movd&#x2F;traefik_icinga_check
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sudo -u&lt;&#x2F;span&gt;&lt;span&gt; nagios mkdir &#x2F;etc&#x2F;icinga2&#x2F;cronjobs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;chmod&lt;&#x2F;span&gt;&lt;span&gt; +x traefik_icinga_check&#x2F;traefik2_to_icinga.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; cp traefik_icinga_check&#x2F;traefik2_to_icinga.py  &#x2F;etc&#x2F;icinga2&#x2F;cronjobs&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt; chown nagios:nagios &#x2F;etc&#x2F;icinga2&#x2F;cronjobs&#x2F;traefik2_to_icinga.py
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;set-up-parameters-via-env&quot;&gt;Set up parameters via .env&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#set-up-parameters-via-env&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -u&lt;&#x2F;span&gt;&lt;span&gt; nagios touch &#x2F;etc&#x2F;icinga2&#x2F;cronjobs&#x2F;.env
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Open and insert parameters &lt;code&gt;&#x2F;etc&#x2F;icinga2&#x2F;cronjobs&#x2F;.env&lt;&#x2F;code&gt; (same as Traefik dashboard)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;TRAEFIK_API_HOSTNAME&lt;&#x2F;span&gt;&lt;span&gt;=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;example.lan:8000&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;TRAEFIK_USERNAME&lt;&#x2F;span&gt;&lt;span&gt;=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;TRAEFIK_PASSWORD&lt;&#x2F;span&gt;&lt;span&gt;=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;passw0rd&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;test-the-script-manually-by-printing-to-stdout&quot;&gt;Test the script manually by printing to STDOUT&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#test-the-script-manually-by-printing-to-stdout&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; sudo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -u&lt;&#x2F;span&gt;&lt;span&gt; nagios &#x2F;etc&#x2F;icinga2&#x2F;cronjobs&#x2F;traefik2_to_icinga.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;apply&lt;&#x2F;span&gt;&lt;span&gt; Service &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;example.com https apache-apache&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;                import &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;generic-service&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                check_command = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                vars.http_address = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                vars.http_vhost = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                vars.http_ssl = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                vars.http_sni = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                vars.notification&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;mail&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt; = {
&lt;&#x2F;span&gt;&lt;span&gt;                    groups = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[ &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;icingaadmins&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;configure-the-host-that-runs-traefik&quot;&gt;Configure the Host that runs Traefik&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#configure-the-host-that-runs-traefik&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Edit your Traefik host and add the &lt;code&gt;vars.services&lt;&#x2F;code&gt; array, so that it matches the rules set in &lt;code&gt;traefik2_to_icinga.py&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span&gt; Host &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Reverse Proxy&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  import &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;generic-host&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  address = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;10.0.0.254&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  vars.os = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Linux&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  vars.services = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;create-cronjob-for-nagios-user&quot;&gt;Create cronjob for &lt;code&gt;nagios&lt;&#x2F;code&gt; user&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#create-cronjob-for-nagios-user&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sudo -u&lt;&#x2F;span&gt;&lt;span&gt; nagios crontab&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -e
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Edit and insert nightly cronjob. Something like that should suffice.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# Daily at 2am: Generate Icinga checks from Traefik API and restart Icinga2 service
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt; 2 * * * &#x2F;etc&#x2F;icinga2&#x2F;cronjobs&#x2F;traefik2_to_icinga.py &amp;gt; &#x2F;etc&#x2F;icinga2&#x2F;zones.d&#x2F;YOUR-ZONE&#x2F;traefik_services.conf &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;span&gt; restart icinga2 &amp;gt;&#x2F;dev&#x2F;null &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;&#x2F;em&gt; Of course you need to print the output of &lt;code&gt;traefik2_to_icinga.py&lt;&#x2F;code&gt; to a directory that is either inside your zone or in conf.d&lt;&#x2F;p&gt;
&lt;p&gt;The end result should look like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;screenshot-monitoring-traefik-icinga.png&quot; alt=&quot;Screenshot of Icinga2 with Traefik Service&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I am looking forward to any feedback or even &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;movd&#x2F;traefik_icinga_check&quot;&gt;pull-requests&lt;&#x2F;a&gt; for the small script.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;small&gt;&lt;em&gt;Source for the graphics used in the header: &lt;a href=&quot;https:&#x2F;&#x2F;www.freepik.com&#x2F;free-photos-vectors&#x2F;background&quot;&gt;Background vector created by vectorpouch - www.freepik.com&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Upgrading to Traefik 2 with Docker</title>
          <pubDate>Fri, 13 Dec 2019 22:20:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://moritzvd.eu/posts/upgrade-traefik-2/</link>
          <guid>https://moritzvd.eu/posts/upgrade-traefik-2/</guid>
          <description xml:base="https://moritzvd.eu/posts/upgrade-traefik-2/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;traefik2-upgrade.gif&quot; alt=&quot;Banner Upgrading to Traefik 2 with Docker&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m running some web services for personal use. These services are mostly running from containers with a reverse proxy to expose them to the web. I leave this task to &lt;a href=&quot;https:&#x2F;&#x2F;traefik.io&#x2F;&quot;&gt;Traefik&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Before that I used a popular triad of &lt;code&gt;nginx&lt;&#x2F;code&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jwilder&#x2F;nginx-proxy&quot;&gt;&lt;code&gt;docker-gen&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;evertramos&#x2F;docker-compose-letsencrypt-nginx-proxy-companion&quot;&gt;&lt;code&gt;letsencrypt-nginx-proxy-companion&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. This for the most part worked great but three services for one task also meant three sources for possible errors. Around this time last year I learned about Traefik with its single binary approach and general small footprint. After following a &lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;community&#x2F;tutorials&#x2F;how-to-use-traefik-as-a-reverse-proxy-for-docker-containers-on-ubuntu-18-04&quot;&gt;guide by Keith Thompson&lt;&#x2F;a&gt; I jumped ships.&lt;&#x2F;p&gt;
&lt;p&gt;This fall &lt;em&gt;containous&lt;&#x2F;em&gt; the company behind Traefik &lt;a href=&quot;https:&#x2F;&#x2F;blog.containo.us&#x2F;traefik-2-0-6531ec5196c2&quot;&gt;released version 2.0&lt;&#x2F;a&gt;. This is a major release including cool stuff like reusable &lt;a href=&quot;https:&#x2F;&#x2F;docs.traefik.io&#x2F;middlewares&#x2F;overview&#x2F;&quot;&gt;middlewares&lt;&#x2F;a&gt;, a new fun web dashboard and advanced stuff for production deployments like canary deployments. This changes come with a trade off. The new version has lots of breaking changes because of that I had to update my deployment and understand the new paradigms introduced. In this post I want to help share my findings and show a path to upgrade from 1.7 to 2. So without further ado, let’s jump right in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-0-our-initial-traefik-v1-7-setup&quot;&gt;Step 0 - Our initial Traefik v1.7 setup&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#step-0-our-initial-traefik-v1-7-setup&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Before we go further, we are setting up a small Docker based environment in Traefik 1.7 that we are going to upgrade. For that I&#x27;ll assume that you already have &lt;code&gt;docker&lt;&#x2F;code&gt; and &lt;code&gt;docker-compose&lt;&#x2F;code&gt; installed and know your way around these tools.&lt;&#x2F;p&gt;
&lt;p&gt;We are exposing two Docker containers and Traefik&#x27;s dashboard. The setup is quite simple and can be described as follows: &lt;em&gt;Of course you need to use your own subdomains&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Frontend&lt;&#x2F;th&gt;&lt;th&gt;Backend&lt;&#x2F;th&gt;&lt;th&gt;Rules&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;dashboard.traefik.moritzvd.eu&lt;&#x2F;code&gt; (HTTP, HTTPS and :8080)&lt;&#x2F;td&gt;&lt;td&gt;dashboard&lt;&#x2F;td&gt;&lt;td&gt;basic authentication via &lt;code&gt;traefik.toml&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;traefik.moritzvd.eu&lt;&#x2F;code&gt; (HTTPS)&lt;&#x2F;td&gt;&lt;td&gt;httpd&lt;&#x2F;td&gt;&lt;td&gt;permanent redirect from &lt;code&gt;http:&#x2F;&#x2F;&lt;&#x2F;code&gt; to &lt;code&gt;https:&#x2F;&#x2F;&lt;&#x2F;code&gt; and security headers&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;whoami.moritzvd.eu&lt;&#x2F;code&gt; (HTTP, HTTPS)&lt;&#x2F;td&gt;&lt;td&gt;whoami&lt;&#x2F;td&gt;&lt;td&gt;default setup&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Folder structure:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;├──&lt;&#x2F;span&gt;&lt;span&gt; acme.json &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# stores SSL certs and keys
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;├──&lt;&#x2F;span&gt;&lt;span&gt; docker-compose.yml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# defines containers
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;├──&lt;&#x2F;span&gt;&lt;span&gt; htdocs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;│&lt;&#x2F;span&gt;&lt;span&gt;   └── index.html &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# super awesome website
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;└──&lt;&#x2F;span&gt;&lt;span&gt; traefik.toml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# Traefik`s configuration:
&lt;&#x2F;span&gt;&lt;span&gt;                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# defines entrypoints, enables dashboard,
&lt;&#x2F;span&gt;&lt;span&gt;                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# ACME, Docker provider and access logging
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I created a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;movd&#x2F;upgrade-to-traefik2&quot;&gt;repository at GitHub&lt;&#x2F;a&gt; that follows our upgrade steps. You can take a look at the initial situation &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;movd&#x2F;upgrade-to-traefik2&#x2F;tree&#x2F;e13fccbbda583a57f85502b07d78323d9c90d59a&quot;&gt;in this commit&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-frontends-and-backends-to-routers-services-and-middlewares&quot;&gt;From Frontends and Backends to Routers, Services and Middlewares&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#from-frontends-and-backends-to-routers-services-and-middlewares&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Before we upgrade this setup we need to understand some key differences between Traefik v1.7 and v2. The notion of &amp;quot;Frontends&amp;quot; and &amp;quot;Backends&amp;quot; is gone, in the new version the concepts of &amp;quot;Routers&amp;quot;, &amp;quot;Middlewares&amp;quot; and &amp;quot;Services&amp;quot; were introduced. Especially against the backdrop of our planned upgrade, these concepts can be considered as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Frontends become Routers&lt;&#x2F;li&gt;
&lt;li&gt;Backends become Services&lt;&#x2F;li&gt;
&lt;li&gt;Things like &lt;code&gt;frontend.redirect&lt;&#x2F;code&gt; or &lt;code&gt;frontend.headers&lt;&#x2F;code&gt; become middlewares&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The great part about middlewares is that they can be reused. For instance a scheme redirection from &lt;code&gt;http&lt;&#x2F;code&gt; to &lt;code&gt;https&lt;&#x2F;code&gt; can be defined once and used again all over the setup by just adding it to a router.&lt;&#x2F;p&gt;
&lt;p&gt;Please &lt;a href=&quot;https:&#x2F;&#x2F;docs.traefik.io&#x2F;v2.0&#x2F;migration&#x2F;v1-to-v2&#x2F;#frontends-and-backends-are-dead-long-live-routers-middlewares-and-services&quot;&gt;check out the documentation&lt;&#x2F;a&gt; for more background on these new concepts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-1-upgrading-the-traefik-dashboard&quot;&gt;Step 1 - Upgrading the Traefik dashboard&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#step-1-upgrading-the-traefik-dashboard&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;We will start of by focusing on the basic setup and enabling dashboard. Begin by stopping your 1.7 setup with &lt;code&gt;docker-compose stop &amp;amp;&amp;amp; docker-compose rm -f&lt;&#x2F;code&gt; after that comment out the services &lt;code&gt;whoami&lt;&#x2F;code&gt; and &lt;code&gt;httpd&lt;&#x2F;code&gt;, they&#x27;ll be enabled again later on. Next we&#x27;ll replace the tag of the Traefik image with &lt;code&gt;v2.1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Like before Traefik uses a &lt;em&gt;static&lt;&#x2F;em&gt; and a &lt;em&gt;dynamic&lt;&#x2F;em&gt; configuration. The first are set during startup. The later are fully dynamic and can change while Traefik is running.&lt;&#x2F;p&gt;
&lt;p&gt;In v2 both can&#x27;t be mixed that&#x27;s why we are creating two new configuration files. The new version also introduced YAML support, since we are already using it for &lt;code&gt;docker-compose&lt;&#x2F;code&gt; I suggest we switch from TOML to YAML. Of course this is a purely subjective decision on my part.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; touch dynamic_conf.yml traefik.yml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both files need to be mounted in our &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; file like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;volumes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;traefik.yml:&#x2F;traefik.yml
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;dynamic_conf.yml:&#x2F;dynamic_conf.yml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;static-configuration-entrypoints-acme-providers&quot;&gt;Static configuration (Entrypoints, ACME, Providers...)&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#static-configuration-entrypoints-acme-providers&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Now we can start reworking our static configuration &lt;code&gt;traefik.yml&lt;&#x2F;code&gt;. &lt;em&gt;I&#x27;m following the structure of the old TOML file from top to bottom&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;entrypoints&quot;&gt;Entrypoints&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#entrypoints&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;First lets refactor the Entrypoints to YAML. In the same step we&#x27;re also removing the basic authentication for the dashboard&#x2F;API and the &lt;code&gt;https&lt;&#x2F;code&gt; redirect. Don&#x27;t worry they&#x27;ll be added again as middlewares 🚀&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entryPoints&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dashboard&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;:8080
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;:80
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;https&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;:443
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;dashboard-and-api&quot;&gt;Dashboard and API&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#dashboard-and-api&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Next up the Dashboard&#x2F;API. We just tell Traefik to enable both like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;api&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dashboard&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Entrypoint definition will be part of our dynamic configuration as part of a router. Remember in v2 static and dynamic configuration don&#x27;t mix!&lt;&#x2F;p&gt;
&lt;h4 id=&quot;acme-let-s-encrypt&quot;&gt;ACME (Let&#x27;s Encrypt)&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#acme-let-s-encrypt&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;First up: In v2 the format of the &lt;code&gt;acme.json&lt;&#x2F;code&gt; changed. This file needs to be converted from v1 to v2. For this task &lt;em&gt;containous&lt;&#x2F;em&gt; released the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;containous&#x2F;traefik-migration-tool&quot;&gt;traefik-migration-tool&lt;&#x2F;a&gt;. Run it from your working directory:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; docker run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --rm -v &lt;&#x2F;span&gt;&lt;span&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;PWD&lt;&#x2F;span&gt;&lt;span&gt;}:&#x2F;data containous&#x2F;traefik-migration-tool \
&lt;&#x2F;span&gt;&lt;span&gt;    acme&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;data&#x2F;acme.json \
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;    -o&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;data&#x2F;acme-new.json
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; sudo chmod 600 acme-new.json
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; sudo mv acme-new.json acme.json
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ACME now is a certificate resolver that needs to be defined:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;certificatesResolvers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;myhttpchallenge&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;acme&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;httpChallenge&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# used during the challenge
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entryPoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;http
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;email&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hi+letsencrypt@moritzvd.eu
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;acme.json
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# Use Let&amp;#39;s Encrypt Staging CA when testing!
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# caServer: https:&#x2F;&#x2F;acme-staging-v02.api.letsencrypt.org&#x2F;directory
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;providers&quot;&gt;Providers&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#providers&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.traefik.io&#x2F;providers&#x2F;overview&#x2F;&quot;&gt;documentation tells us&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Configuration discovery in Traefik is achieved through Providers.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;For us that means we need two providers &lt;code&gt;docker&lt;&#x2F;code&gt; and &lt;code&gt;file&lt;&#x2F;code&gt; the latter for our &lt;code&gt;dynamic_conf.yml&lt;&#x2F;code&gt; that we&#x27;ll be adding in a couple of minutes.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;providers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;exposedByDefault&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;network&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;web
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dynamic_conf.yml
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;watch&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;access-logging-and-traefik-debugging&quot;&gt;Access Logging and Traefik Debugging&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#access-logging-and-traefik-debugging&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;We want to keep logging access and also increase the verbosity of Traefik. That&#x27;s why we just add:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;INFO
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;accessLog&lt;&#x2F;span&gt;&lt;span&gt;: {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Our static configuration is now finished.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dynamic-configuration-for-dashboard-and-api&quot;&gt;Dynamic Configuration for Dashboard and API&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#dynamic-configuration-for-dashboard-and-api&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we have defined the static configuration we need to work on our dynamic routers and middlewares. Remember they have the job of exposing our services and can change while Traefik is running.&lt;&#x2F;p&gt;
&lt;p&gt;Like on 1.7 we want our dashboard to be available on :8080 and &lt;code&gt;https&lt;&#x2F;code&gt;. For that we need two &lt;del&gt;Frontend&lt;&#x2F;del&gt; routers that expose the service &lt;code&gt;api@internal&lt;&#x2F;code&gt;. These routers also need a use a &lt;code&gt;basicAuth&lt;&#x2F;code&gt; middleware so that users are asked for our super secure &lt;code&gt;passw0rd&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Check &lt;code&gt;create_docker_compose_basic_auth_string_for_traefik.sh&lt;&#x2F;code&gt; (&lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;movd&#x2F;7fb5da40cdd61b05cbe3eba48720e4b1&quot;&gt;my fork at gist&lt;&#x2F;a&gt;) to generate you own authentication string.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We start by defining our basic authentication middleware. We use the same password that was used in the old &lt;code&gt;traefik.toml&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;dynamic_conf.yml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;middlewares&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dashboard-auth&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;basicAuth&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;users&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# admin:passw0rd
&lt;&#x2F;span&gt;&lt;span&gt;          - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;admin:$2y$05$kqK7GlhnGCnt&#x2F;fYdrCL2AeZykK2T0cN4sBcCaRs61vMz7yMWaR9M.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next we define our first router:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;routers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;my-api&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entryPoints&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dashboard
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rule&lt;&#x2F;span&gt;&lt;span&gt;: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;PathPrefix(`&#x2F;dashboard`) || PathPrefix(`&#x2F;api`)&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;api@internal
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;middlewares&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dashboard-auth
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;What did we do here?&lt;&#x2F;em&gt; This router gets activated when the Route &lt;code&gt;&#x27;&#x2F;dashboard&#x27;&lt;&#x2F;code&gt; or &lt;code&gt;&#x27;&#x2F;api&#x27;&lt;&#x2F;code&gt; gets requested (the given &lt;code&gt;rule&lt;&#x2F;code&gt; condition is fulfilled). It adds the &lt;code&gt;dashboard-auth&lt;&#x2F;code&gt; middleware and than forwards the request to the &lt;code&gt;api@internal&lt;&#x2F;code&gt; service. The router is only exposed on Port 8080 aka our &lt;code&gt;dashboard&lt;&#x2F;code&gt; entrypoint.&lt;&#x2F;p&gt;
&lt;p&gt;No we can run first tests on our setup. The Traefik API should reply with a list of our active routers:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; docker-compose up&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -d
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; curl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -s --user&lt;&#x2F;span&gt;&lt;span&gt; admin:passw0rd http:&#x2F;&#x2F;localhost:8080&#x2F;api&#x2F;http&#x2F;routers | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;jq
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;[
&lt;&#x2F;span&gt;&lt;span&gt;  {
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;entryPoints&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: [
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dashboard&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    ],
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;middlewares&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: [
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dashboard-auth@file&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    ],
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;api@internal&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;,
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;rule&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;PathPrefix(`&#x2F;dashboard`) || PathPrefix(`&#x2F;api`)&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;,
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;status&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;,
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: [
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dashboard&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    ],
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;my-api@file&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;,
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;provider&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next we add a second router that is in charge of securely exposing the dashboard and API via &lt;code&gt;https&lt;&#x2F;code&gt;. It&#x27;s mostly the same but uses a more precise rule and our ACME HTTP Challenge from &lt;code&gt;traefik.yml&lt;&#x2F;code&gt;. The longer rule gets a &lt;a href=&quot;https:&#x2F;&#x2F;docs.traefik.io&#x2F;routing&#x2F;routers&#x2F;#priority&quot;&gt;higher priority&lt;&#x2F;a&gt; by Traefik than the one defined for port 8080.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;my-secure-api&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entryPoints&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# Activate this router if Client requests specific subdomain and &amp;#39;&#x2F;dashboard&amp;#39; or &amp;#39;&#x2F;api&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rule&lt;&#x2F;span&gt;&lt;span&gt;: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Host(`dashboard.traefik.moritzvd.eu`) &amp;amp;&amp;amp; (PathPrefix(`&#x2F;api`) || PathPrefix(`&#x2F;dashboard`))&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;api@internal
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;middlewares&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dashboard-auth
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tls&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# Use ACME HTTP Challenge defined in &amp;#39;traefik.yml&amp;#39; to get valid cert
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;certResolver&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;myhttpchallenge
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can access the Dashboard securely from our Browser:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;dashboard-first-run.gif&quot; alt=&quot;Using the Traefik Dashboard in a Browser&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Finally we want to redirect from &lt;code&gt;http:&#x2F;&#x2F;&lt;&#x2F;code&gt; to &lt;code&gt;https:&#x2F;&#x2F;&lt;&#x2F;code&gt;. This great &lt;a href=&quot;https:&#x2F;&#x2F;blog.containo.us&#x2F;traefik-2-0-docker-101-fc2893944b9d&quot;&gt;article by Gérald Croë&lt;&#x2F;a&gt; gave me the idea to just do this as a general catch-all router. Since at the end we all just want https everywhere right?&lt;&#x2F;p&gt;
&lt;p&gt;For this we first define a &lt;code&gt;redirectScheme&lt;&#x2F;code&gt; middleware:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;redirect-to-https&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;redirectScheme&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;scheme&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;permanent&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we add our catch-all router:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;https-redirect&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entryPoints&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;http
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# Activate this Router on any Host requested
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rule&lt;&#x2F;span&gt;&lt;span&gt;: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hostregexp(`{host:.+}`)&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;dummy
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;middlewares&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;redirect-to-https
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because Traefik always requires a service when defining routers in a configuration file we add a &amp;quot;dummy&amp;quot; &lt;code&gt;service&lt;&#x2F;code&gt;. This service will never be reached because the middleware will redirect them to the requested service on &lt;code&gt;https&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;service&lt;&#x2F;code&gt; of course needs to be defined:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;services&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dummy&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;loadBalancer&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;servers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;localhost
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now all clients get permanently redirected to the secure version:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; curl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -sI&lt;&#x2F;span&gt;&lt;span&gt; http:&#x2F;&#x2F;dashboard.traefik.moritzvd.eu&#x2F;api&#x2F;http&#x2F;routers
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HTTP&#x2F;1.1&lt;&#x2F;span&gt;&lt;span&gt; 308 Permanent Redirect
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Location:&lt;&#x2F;span&gt;&lt;span&gt; https:&#x2F;&#x2F;dashboard.traefik.moritzvd.eu&#x2F;api&#x2F;http&#x2F;routers
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Date:&lt;&#x2F;span&gt;&lt;span&gt; Tue, 03 Dec 2019 16:24:09 GMT
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Content-Length:&lt;&#x2F;span&gt;&lt;span&gt; 18
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Content-Type:&lt;&#x2F;span&gt;&lt;span&gt; text&#x2F;plain; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;charset&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;utf-8
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;step-2-upgrading-the-whoami-service&quot;&gt;Step 2 - Upgrading the &lt;em&gt;whoami&lt;&#x2F;em&gt; service&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#step-2-upgrading-the-whoami-service&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have the nice dashboard and the practical API running we focus on our services. As before we directly setup the Traefik configuration via labels in our &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt;. We start of by upgrading the simple &lt;code&gt;whoami&lt;&#x2F;code&gt; service. The service is a &lt;em&gt;&amp;quot;tiny Go web server that prints OS information and HTTP requests&amp;quot;&lt;&#x2F;em&gt; (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;containous&#x2F;whoami&quot;&gt;containous&#x2F;whoami&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;First we uncomment the services definition that we disabled before.&lt;&#x2F;p&gt;
&lt;p&gt;Our old Traefik 1.7 service definition looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;whoami&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;containous&#x2F;whoami
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;container_name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;whoami
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;restart&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;unless-stopped
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;networks&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;web
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.enable=true&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.backend=whoami&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.frontend.rule=Host:whoami.traefik.moritzvd.eu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.docker.network=web&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The former configuration tells us the following: We need one router that activates when the &lt;code&gt;whoami.traefik.moritzvd.eu&lt;&#x2F;code&gt; is requested. We name this router &lt;code&gt;whoami-secure&lt;&#x2F;code&gt; as the name suggests we only want it to be accessible via &lt;code&gt;https&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We define the &lt;code&gt;router&lt;&#x2F;code&gt; and the &lt;code&gt;rule&lt;&#x2F;code&gt; and the &lt;code&gt;entrypoint&lt;&#x2F;code&gt; in two label lines:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# The router is named inline
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.whoami-secure.entrypoints=https&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.whoami-secure.rule=Host(`whoami.traefik.moritzvd.eu`)&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.whoami-secure.tls.certresolver=myhttpchallenge&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because we defined a global catch-all redirect router the &lt;code&gt;http&lt;&#x2F;code&gt; to &lt;code&gt;https&lt;&#x2F;code&gt; redirection is already taken care of. Our finished service definition looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;whoami&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;containous&#x2F;whoami
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;container_name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;whoami
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;restart&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;unless-stopped
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;networks&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;web
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.enable=true&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.whoami-secure.entrypoints=https&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.whoami-secure.rule=Host(`whoami.traefik.moritzvd.eu`)&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.whoami-secure.tls.certresolver=myhttpchallenge&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now bring up the service by closing the file. Docker compose will pick up on the new service.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; docker-compose up&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -d
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;traefik&lt;&#x2F;span&gt;&lt;span&gt; is up-to-date
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Creating&lt;&#x2F;span&gt;&lt;span&gt; whoami ... done
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Traefik will generate a new certificate and key, and will ask Let&#x27;s Encrypt to give us a signed certificate. This normally happens within a couple of seconds. After that we can access the service:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; curl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -s &lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;whoami.traefik.moritzvd.eu&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Hostname:&lt;&#x2F;span&gt;&lt;span&gt; edf3d71d3412
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;IP:&lt;&#x2F;span&gt;&lt;span&gt; 127.0.0.1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;IP:&lt;&#x2F;span&gt;&lt;span&gt; 172.18.0.3
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;RemoteAddr:&lt;&#x2F;span&gt;&lt;span&gt; 172.18.0.2:39308
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;GET&lt;&#x2F;span&gt;&lt;span&gt; &#x2F; HTTP&#x2F;1.1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Host:&lt;&#x2F;span&gt;&lt;span&gt; whoami.traefik.moritzvd.eu
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;User-Agent:&lt;&#x2F;span&gt;&lt;span&gt; curl&#x2F;7.58.0
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Accept: &lt;&#x2F;span&gt;&lt;span&gt;*&#x2F;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Accept-Encoding:&lt;&#x2F;span&gt;&lt;span&gt; gzip
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;X-Forwarded-For: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;X-Forwarded-Host:&lt;&#x2F;span&gt;&lt;span&gt; whoami.traefik.moritzvd.eu
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;X-Forwarded-Port:&lt;&#x2F;span&gt;&lt;span&gt; 443
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;X-Forwarded-Proto:&lt;&#x2F;span&gt;&lt;span&gt; https
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;X-Forwarded-Server:&lt;&#x2F;span&gt;&lt;span&gt; 248ac49c7b90
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;X-Real-Ip: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;step-3-upgrading-the-httpd-service&quot;&gt;Step 3 - Upgrading the &lt;em&gt;httpd&lt;&#x2F;em&gt; service&lt;a class=&quot;anchor&quot; aria-hidden=&quot;true&quot; href=&quot;#step-3-upgrading-the-httpd-service&quot; hidden=&quot;&quot;&gt;#&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Now we can upgrade our final service. For the sake of this guide we want to expose a good old Apache httpd. We also want to add some security headers like STS and CORS Headers. These become part of a new middleware that we call in our router.&lt;&#x2F;p&gt;
&lt;p&gt;In order to upgrade, we first uncomment the old Traefik 1.7 style definition. Afterward we do the following modifications:&lt;&#x2F;p&gt;
&lt;p&gt;Delete the lines:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;    - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.backend=httpd&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# The new router is named inline
&lt;&#x2F;span&gt;&lt;span&gt;    - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.docker.network=web&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# already defined this as default in `traefik.yml`
&lt;&#x2F;span&gt;&lt;span&gt;    - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.port=80&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# We are using the standard port exposed by httpd
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Than we define our new router. We&#x27;ll call it &lt;code&gt;httpd-secure&lt;&#x2F;code&gt; and we want to expose it on our &lt;code&gt;https&lt;&#x2F;code&gt; entrypoint.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;    - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.httpd-secure.entrypoints=https&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.httpd-secure.rule=Host(`traefik.moritzvd.eu`)&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.httpd-secure.tls.certresolver=myhttpchallenge&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# Don&amp;#39;t forget the certresolver
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we need to rework our header definitions. Fortunately, the definitions have remained the same. But they now need to be defined as part of a &lt;code&gt;headers&lt;&#x2F;code&gt; middleware. We just need to Replace &lt;code&gt;traefik.frontend.headers&lt;&#x2F;code&gt; with &lt;code&gt;traefik.http.middlewares.httpd-security.headers&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Our labels now look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.middlewares.httpd-security.headers.browserXSSFilter=true&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.middlewares.httpd-security.headers.customFrameOptionsValue=SAMEORIGIN&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.middlewares.httpd-security.headers.forceSTSHeader=true&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.middlewares.httpd-security.headers.frameDeny=true&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.middlewares.httpd-security.headers.SSLHost=traefik.moritzvd.eu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.middlewares.httpd-security.headers.SSLRedirect=true&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.middlewares.httpd-security.headers.STSIncludeSubdomains=true&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.middlewares.httpd-security.headers.STSSeconds=63072000&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By doing this we created a new middleware called &lt;code&gt;httpd-security&lt;&#x2F;code&gt;. Of course this middleware needs to be added to our &lt;code&gt;httpd-secure&lt;&#x2F;code&gt; router. This middleware could also be added to any other service that is in need of some nice security headers.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;      - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;traefik.http.routers.httpd-secure.middlewares=httpd-security&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After firing &lt;code&gt;docker-compose up -d&lt;&#x2F;code&gt; all our services are now back again and served with Traefik 2.1. 🏁&lt;&#x2F;p&gt;
&lt;p&gt;I hope I could help in upgrading your setup from 1.7 to 2.1. We could go the extra mile and refactor everything even further by including all of the configuration in the &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Credits for sources used in the banner: &lt;a href=&quot;https:&#x2F;&#x2F;www.freepik.com&#x2F;free-photos-vectors&#x2F;background&quot;&gt;Background vector created by vectorpouch - www.freepik.com&lt;&#x2F;a&gt;  and the Traefik logo &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;containous&#x2F;traefik#credits&quot;&gt;licensed under the Creative Commons 3.0 Attributions license&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
