<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Benjamin.dog</title>
    <description>The latest articles on DEV Community by Benjamin.dog (@bendog).</description>
    <link>https://dev.to/bendog</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F327475%2Fa9d24df4-8108-4393-b70e-6c85337aaad2.jpeg</url>
      <title>DEV Community: Benjamin.dog</title>
      <link>https://dev.to/bendog</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bendog"/>
    <language>en</language>
    <item>
      <title>How to configure a date and datetime picker in Django using a global widget template override</title>
      <dc:creator>Benjamin.dog</dc:creator>
      <pubDate>Mon, 14 Feb 2022 05:06:00 +0000</pubDate>
      <link>https://dev.to/bendog/how-to-configure-a-date-and-datetime-picker-in-django-using-a-global-widget-template-override-4d6k</link>
      <guid>https://dev.to/bendog/how-to-configure-a-date-and-datetime-picker-in-django-using-a-global-widget-template-override-4d6k</guid>
      <description>&lt;p&gt;So after using Django on-and-off for close to 15 years, I recently learnt of a cool new (to me at least) trick. You can override the widget templates used to generate the field components for the generation of forms. These can be found here &lt;a href="https://github.com/django/django/tree/main/django/forms/templates/django/forms/widgets"&gt;https://github.com/django/django/tree/main/django/forms/templates/django/forms/widgets&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The biggest benefit to this, is not having to write custom forms, or widget over-rides in all of your Forms and ModelForms. Once you have changed the default widget template, all of your DateTimeFields will automatically use those settings.&lt;/p&gt;

&lt;p&gt;Less code, less duplication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling the template engine
&lt;/h2&gt;

&lt;p&gt;Update &lt;code&gt;settings.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;'blog.apps.BlogConfig'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'django.contrib.admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'django.contrib.auth'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'django.contrib.contenttypes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'django.contrib.sessions'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'django.contrib.messages'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'django.contrib.staticfiles'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'django.forms'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;- add this app to installed apps
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Validate APP_DIRS and DIRS are configured
&lt;/span&gt;&lt;span class="n"&gt;TEMPLATES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'BACKEND'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'django.template.backends.django.DjangoTemplates'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'DIRS'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BASE_DIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s"&gt;'templates'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="s"&gt;'APP_DIRS'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'OPTIONS'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;'context_processors'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s"&gt;'django.template.context_processors.debug'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;'django.template.context_processors.request'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="s"&gt;'django.contrib.auth.context_processors.auth'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="s"&gt;'django.contrib.messages.context_processors.messages'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Add this line to change the form renderer to TemplateSetting
&lt;/span&gt;&lt;span class="n"&gt;FORM_RENDERER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'django.forms.renderers.TemplatesSetting'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the override templates
&lt;/h2&gt;

&lt;p&gt;From your project template directory, I'm using &lt;code&gt;./templates/&lt;/code&gt; create the following directories&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir -p django/forms/widgets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;so you should now have a set of directories that look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── templates
│  └── django
│     └── forms
│        └── widgets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To override the Django widgets we need to select the widget we wish to override, in this case we will be using &lt;code&gt;DateTimeField&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Look at the original source file for &lt;a href="https://github.com/django/django/blob/stable/4.0.x/django/forms/templates/django/forms/widgets/datetime.html"&gt;DateTime.html&lt;/a&gt; from the Django Repo.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;datetime.html&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{% include "django/forms/widgets/input.html" %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that &lt;code&gt;datetime.html&lt;/code&gt; inherits from the default &lt;code&gt;input.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;input.html&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; 
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"{{ widget.type }}"&lt;/span&gt;
  &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"{{ widget.name }}"&lt;/span&gt;
  &lt;span class="err"&gt;{%&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;widget.value&lt;/span&gt; &lt;span class="err"&gt;!=&lt;/span&gt; &lt;span class="na"&gt;None&lt;/span&gt; &lt;span class="err"&gt;%}&lt;/span&gt;
    &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{ widget.value|stringformat:'s' }}"&lt;/span&gt;
  &lt;span class="err"&gt;{%&lt;/span&gt; &lt;span class="na"&gt;endif&lt;/span&gt; &lt;span class="err"&gt;%}&lt;/span&gt;
  &lt;span class="err"&gt;{%&lt;/span&gt; &lt;span class="na"&gt;include&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;django&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;forms&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;widgets&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;attrs.html&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;%}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use this as our basis for our new &lt;code&gt;datetime.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;create a file &lt;code&gt;./django/forms/widgets/datetime.html&lt;/code&gt; and add the following content.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that have changed the &lt;code&gt;type="{{ widget.type }}"&lt;/code&gt; to &lt;code&gt;type="datetime-local"&lt;/code&gt; as defined here &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local"&gt;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local&lt;/a&gt; .&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; 
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"datetime-local"&lt;/span&gt;
  &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"{{ widget.name }}"&lt;/span&gt;
  &lt;span class="err"&gt;{%&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;widget.value&lt;/span&gt; &lt;span class="err"&gt;!=&lt;/span&gt; &lt;span class="na"&gt;None&lt;/span&gt; &lt;span class="err"&gt;%}&lt;/span&gt;
    &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{ widget.value|stringformat:'s' }}"&lt;/span&gt;
  &lt;span class="err"&gt;{%&lt;/span&gt; &lt;span class="na"&gt;endif&lt;/span&gt; &lt;span class="err"&gt;%}&lt;/span&gt;
  &lt;span class="err"&gt;{%&lt;/span&gt; &lt;span class="na"&gt;include&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;django&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;forms&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;widgets&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;attrs.html&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;%}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now simply &lt;code&gt;manage.py runserver&lt;/code&gt; and you should see your browser now shows a date and time picker.&lt;/p&gt;

&lt;p&gt;If you wish to configure a date picker, create a &lt;code&gt;date.html&lt;/code&gt; file and set the type to &lt;code&gt;type="date"&lt;/code&gt;.&lt;br&gt;
To configure a time picker, create a &lt;code&gt;time.html&lt;/code&gt; file and set the type to &lt;code&gt;type="time"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Congrats!&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
    </item>
    <item>
      <title>Traefik 2 and Ubuntu 18.04 with systemd and https redirect</title>
      <dc:creator>Benjamin.dog</dc:creator>
      <pubDate>Fri, 21 Feb 2020 03:59:56 +0000</pubDate>
      <link>https://dev.to/bendog/traefik-2-and-ubuntu-18-04-with-systemd-and-https-redirect-4fpo</link>
      <guid>https://dev.to/bendog/traefik-2-and-ubuntu-18-04-with-systemd-and-https-redirect-4fpo</guid>
      <description>&lt;h2&gt;
  
  
  get the latest binary file
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;go to &lt;a href="https://github.com/containous/traefik/releases"&gt;https://github.com/containous/traefik/releases&lt;/a&gt; and download the latest binary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;extract the binary &lt;code&gt;tar -zxvf traefik_${traefik_version}_linux_${arch}.tar.gz&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check the binary works &lt;code&gt;./traefik --help&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if you can't execute the file, run &lt;code&gt;chmod +x traefik&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  copy traefik to /usr/local/bin
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo cp /path/to/traefik /usr/local/bin
sudo chown root:root /usr/local/bin/traefik
sudo chmod 755 /usr/local/bin/traefik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;give the traefik binary the ability to bind to privileged ports (80, 443) as non-root&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/traefik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  setup traefik user and group and permissions
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo groupadd -g 321 traefik
sudo useradd \
  -g traefik --no-user-group \
  --home-dir /var/www --no-create-home \
  --shell /usr/sbin/nologin \
  --system --uid 321 traefik
sudo usermod -aG docker traefik

sudo mkdir /etc/traefik
sudo mkdir /etc/traefik/acme
sudo mkdir /etc/traefik/dynamic
sudo chown -R root:root /etc/traefik
sudo chown -R traefik:traefik /etc/traefik/dynamic

sudo touch /var/log/traefik.log
sudo chown traefik:traefik /var/log/traefik.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  add traefik config files
&lt;/h2&gt;

&lt;p&gt;create the following files, replace 'bendog' and 'bendog.org' with your project name and project base url&lt;/p&gt;

&lt;p&gt;create the file &lt;code&gt;/etc/traefik/traefik.toml&lt;/code&gt; with the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Configuration sample for Traefik v2.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# For Traefik v1: https://github.com/containous/traefik/blob/v1.7/traefik.sample.toml&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;################################################################&lt;/span&gt;

&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Global configuration&lt;/span&gt;
&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="nn"&gt;[global]&lt;/span&gt;
  &lt;span class="py"&gt;checkNewVersion&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="py"&gt;sendAnonymousUsage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Entrypoints configuration&lt;/span&gt;
&lt;span class="c"&gt;################################################################&lt;/span&gt;

&lt;span class="c"&gt;# Entrypoints definition&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Optional&lt;/span&gt;
&lt;span class="c"&gt;# Default:&lt;/span&gt;
&lt;span class="nn"&gt;[entryPoints]&lt;/span&gt;
  &lt;span class="nn"&gt;[entryPoints.web]&lt;/span&gt;
    &lt;span class="py"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;":80"&lt;/span&gt;

  &lt;span class="nn"&gt;[entryPoints.websecure]&lt;/span&gt;
    &lt;span class="py"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;":443"&lt;/span&gt;

&lt;span class="nn"&gt;[certificatesResolvers.bendog.acme]&lt;/span&gt;
  &lt;span class="py"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ben@bendog.org"&lt;/span&gt;
  &lt;span class="py"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/etc/traefik/acme/bendog.json"&lt;/span&gt;
  &lt;span class="nn"&gt;[certificatesResolvers.bendog.acme.httpChallenge]&lt;/span&gt;
    &lt;span class="c"&gt;# used during the challenge&lt;/span&gt;
    &lt;span class="py"&gt;entryPoint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"web"&lt;/span&gt;

&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Traefik logs configuration&lt;/span&gt;
&lt;span class="c"&gt;################################################################&lt;/span&gt;

&lt;span class="c"&gt;# Traefik logs&lt;/span&gt;
&lt;span class="c"&gt;# Enabled by default and log to stdout&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Optional&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="nn"&gt;[log]&lt;/span&gt;

  &lt;span class="c"&gt;# Log level&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: "ERROR"&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="py"&gt;level&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"DEBUG"&lt;/span&gt;

  &lt;span class="c"&gt;# Sets the filepath for the traefik log. If not specified, stdout will be used.&lt;/span&gt;
  &lt;span class="c"&gt;# Intermediate directories are created if necessary.&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: os.Stdout&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="py"&gt;filePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/var/log/traefik.log"&lt;/span&gt;

  &lt;span class="c"&gt;# Format is either "json" or "common".&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: "common"&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# format = "json"&lt;/span&gt;

&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Access logs configuration&lt;/span&gt;
&lt;span class="c"&gt;################################################################&lt;/span&gt;

&lt;span class="c"&gt;# Enable access logs&lt;/span&gt;
&lt;span class="c"&gt;# By default it will write to stdout and produce logs in the textual&lt;/span&gt;
&lt;span class="c"&gt;# Common Log Format (CLF), extended with additional fields.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Optional&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# [accessLog]&lt;/span&gt;

  &lt;span class="c"&gt;# Sets the file path for the access log. If not specified, stdout will be used.&lt;/span&gt;
  &lt;span class="c"&gt;# Intermediate directories are created if necessary.&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: os.Stdout&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# filePath = "/path/to/log/log.txt"&lt;/span&gt;

  &lt;span class="c"&gt;# Format is either "json" or "common".&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: "common"&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# format = "json"&lt;/span&gt;

&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="c"&gt;# API and dashboard configuration&lt;/span&gt;
&lt;span class="c"&gt;################################################################&lt;/span&gt;

&lt;span class="c"&gt;# Enable API and dashboard&lt;/span&gt;
&lt;span class="nn"&gt;[api]&lt;/span&gt;

  &lt;span class="c"&gt;# Enable the API in insecure mode&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: true&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# insecure = false&lt;/span&gt;

  &lt;span class="c"&gt;# Enabled Dashboard&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: true&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# dashboard = false&lt;/span&gt;

&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Ping configuration&lt;/span&gt;
&lt;span class="c"&gt;################################################################&lt;/span&gt;

&lt;span class="c"&gt;# Enable ping&lt;/span&gt;
&lt;span class="nn"&gt;[ping]&lt;/span&gt;

  &lt;span class="c"&gt;# Name of the related entry point&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: "traefik"&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# entryPoint = "traefik"&lt;/span&gt;

&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Docker configuration backend&lt;/span&gt;
&lt;span class="c"&gt;################################################################&lt;/span&gt;

&lt;span class="c"&gt;# Enable Docker configuration backend&lt;/span&gt;
&lt;span class="nn"&gt;[providers.docker]&lt;/span&gt;

  &lt;span class="c"&gt;# Docker server endpoint. Can be a tcp or a unix socket endpoint.&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Required&lt;/span&gt;
  &lt;span class="c"&gt;# Default: "unix:///var/run/docker.sock"&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="py"&gt;endpoint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"unix:///var/run/docker.sock"&lt;/span&gt;

  &lt;span class="c"&gt;# Default host rule.&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: "Host(`{{ normalize .Name }}`)"&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# defaultRule = "Host(`{{ normalize .Name }}.docker.localhost`)"&lt;/span&gt;
  &lt;span class="py"&gt;defaultRule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Host(`{{ normalize .Name }}.bendog.org`)"&lt;/span&gt;

  &lt;span class="c"&gt;# Expose containers by default in traefik&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="c"&gt;# Optional&lt;/span&gt;
  &lt;span class="c"&gt;# Default: true&lt;/span&gt;
  &lt;span class="c"&gt;#&lt;/span&gt;
  &lt;span class="py"&gt;exposedByDefault&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Docker configuration backend&lt;/span&gt;
&lt;span class="c"&gt;################################################################&lt;/span&gt;
&lt;span class="nn"&gt;[providers.file]&lt;/span&gt;
  &lt;span class="py"&gt;directory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/etc/traefik/dynamic/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;setup the global http -&amp;gt; https redirect&lt;/p&gt;

&lt;p&gt;create the file &lt;code&gt;/etc/traefik/dynamic/redirect.toml&lt;/code&gt; with the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;## dynamic configuration&lt;/span&gt;

&lt;span class="nn"&gt;[http.routers]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.routers.redirecttohttps]&lt;/span&gt;
    &lt;span class="py"&gt;entryPoints&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;["web"]&lt;/span&gt;
    &lt;span class="py"&gt;middlewares&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;["httpsredirect"]&lt;/span&gt;
    &lt;span class="py"&gt;rule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HostRegexp(`{host:.+}`)"&lt;/span&gt;
    &lt;span class="py"&gt;service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"noop"&lt;/span&gt;

&lt;span class="nn"&gt;[http.services]&lt;/span&gt;
  &lt;span class="c"&gt;# noop service, the URL will be never called&lt;/span&gt;
  &lt;span class="nn"&gt;[http.services.noop.loadBalancer]&lt;/span&gt;
    &lt;span class="nn"&gt;[[http.services.noop.loadBalancer.servers]]&lt;/span&gt;
      &lt;span class="py"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://127.0.0.1"&lt;/span&gt;

&lt;span class="nn"&gt;[http.middlewares]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.middlewares.httpsredirect.redirectScheme]&lt;/span&gt;
    &lt;span class="py"&gt;scheme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  setup and start the systemd service
&lt;/h2&gt;

&lt;p&gt;create the file &lt;code&gt;/etc/systemd/system/traefik.service&lt;/code&gt; with the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;traefik proxy&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;
&lt;span class="py"&gt;Wants&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target systemd-networkd-wait-online.service&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-abnormal&lt;/span&gt;
&lt;span class="c"&gt;; User and group the process will run as.
&lt;/span&gt;&lt;span class="py"&gt;User&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;traefik&lt;/span&gt;
&lt;span class="py"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;traefik&lt;/span&gt;
&lt;span class="c"&gt;; Always set "-root" to something safe in case it gets forgotten in the traefikfile.
&lt;/span&gt;&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/traefik --configfile=/etc/traefik/traefik.toml&lt;/span&gt;
&lt;span class="c"&gt;; Limit the number of file descriptors; see `man systemd.exec` for more limit settings.
&lt;/span&gt;&lt;span class="py"&gt;LimitNOFILE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1048576&lt;/span&gt;
&lt;span class="c"&gt;; Use private /tmp and /var/tmp, which are discarded after traefik stops.
&lt;/span&gt;&lt;span class="py"&gt;PrivateTmp&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="c"&gt;; Use a minimal /dev (May bring additional security if switched to 'true', but it may not work on Raspberry Pi's or other devices, so it has been disabled in this dist.)
&lt;/span&gt;&lt;span class="py"&gt;PrivateDevices&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;
&lt;span class="c"&gt;; Hide /home, /root, and /run/user. Nobody will steal your SSH-keys.
&lt;/span&gt;&lt;span class="py"&gt;ProtectHome&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="c"&gt;; Make /usr, /boot, /etc and possibly some more folders read-only.
&lt;/span&gt;&lt;span class="py"&gt;ProtectSystem&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;full&lt;/span&gt;
&lt;span class="c"&gt;; … except /etc/ssl/traefik, because we want Letsencrypt-certificates there.
;   This merely retains r/w access rights, it does not add any new. Must still be writable on the host!
&lt;/span&gt;&lt;span class="py"&gt;ReadWriteDirectories&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/etc/traefik/acme&lt;/span&gt;
&lt;span class="c"&gt;; The following additional security directives only work with systemd v229 or later.
; They further restrict privileges that can be gained by traefik. Uncomment if you like.
; Note that you may have to add capabilities required by any plugins in use.
&lt;/span&gt;&lt;span class="py"&gt;CapabilityBoundingSet&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;CAP_NET_BIND_SERVICE&lt;/span&gt;
&lt;span class="py"&gt;AmbientCapabilities&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;CAP_NET_BIND_SERVICE&lt;/span&gt;
&lt;span class="py"&gt;NoNewPrivileges&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then run the following commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chown root:root /etc/systemd/system/traefik.service
sudo chmod 644 /etc/systemd/system/traefik.service
sudo systemctl daemon-reload
sudo systemctl start traefik.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if it doens't work correctly, use this command to investigate why&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;journalctl --boot -u traefik.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to enable autoboot use this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl enable traefik.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  testing the service with whoami
&lt;/h2&gt;

&lt;p&gt;create the following docker-compose file, replacing 'bendog' and 'bendog.org' with the values you specified in your traefik.toml file.&lt;/p&gt;

&lt;p&gt;create the file &lt;code&gt;~/docker/whoami/docker-compose.yml&lt;/code&gt; with the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;whoami&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# A container that exposes an API to show its IP address&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;containous/whoami&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.enable=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.whoami.rule=Host(`whoami.bendog.org`)"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.whoami.tls=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.whoami.tls.certresolver=bendog"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then start the docker image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  references:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/containous/traefik/blob/v2.1.4/traefik.sample.toml"&gt;https://github.com/containous/traefik/blob/v2.1.4/traefik.sample.toml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.traefik.io/https/acme/"&gt;https://docs.traefik.io/https/acme/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/ubergesundheit/7c9d875befc2d7bfd0bf43d8b3862d85"&gt;https://gist.github.com/ubergesundheit/7c9d875befc2d7bfd0bf43d8b3862d85&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/questions/how-to-fix-docker-got-permission-denied-while-trying-to-connect-to-the-docker-daemon-socket"&gt;https://www.digitalocean.com/community/questions/how-to-fix-docker-got-permission-denied-while-trying-to-connect-to-the-docker-daemon-socket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.containo.us/t/global-http-to-https-redirect-in-v2/1658/3"&gt;https://community.containo.us/t/global-http-to-https-redirect-in-v2/1658/3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>traefik</category>
      <category>docker</category>
      <category>ubuntu</category>
      <category>deployment</category>
    </item>
  </channel>
</rss>
