<?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>Forem: Tomaz Lovrec</title>
    <description>The latest articles on Forem by Tomaz Lovrec (@slax0rr).</description>
    <link>https://forem.com/slax0rr</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%2F364327%2F84c9c1c2-3b15-4f8f-9bfd-570d564c921c.png</url>
      <title>Forem: Tomaz Lovrec</title>
      <link>https://forem.com/slax0rr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/slax0rr"/>
    <language>en</language>
    <item>
      <title>ForwardAuth with Traefik: Streamlining Security for Microservices</title>
      <dc:creator>Tomaz Lovrec</dc:creator>
      <pubDate>Fri, 11 Oct 2024 19:49:30 +0000</pubDate>
      <link>https://forem.com/slax0rr/forwardauth-with-traefik-streamlining-security-for-microservices-10jo</link>
      <guid>https://forem.com/slax0rr/forwardauth-with-traefik-streamlining-security-for-microservices-10jo</guid>
      <description>&lt;p&gt;In the information age, nothing is more important than the security of our services—and more importantly, the security of our users and their data. Ensuring security within a (micro)services architecture can quickly become complex and burdensome. As services grow and more spring to life within the ecosystem, maintaining consistent and reliable access control becomes a top priority. To streamline access control, we can leverage &lt;strong&gt;Forward Authentication&lt;/strong&gt;, which centralizes the authentication mechanism and simplifies securing our (micro)services.&lt;/p&gt;

&lt;p&gt;While many reverse proxies offer functionality for routing and authentication, &lt;strong&gt;Traefik&lt;/strong&gt; stands out with its ease of use and flexibility. In addition to efficiently routing traffic, Traefik’s integration with Forward Authentication (&lt;strong&gt;ForwardAuth&lt;/strong&gt;) enables us to centralize user authentication across all services. Using a centralized authentication not only makes the access management easier, but also strengthens the security of our services at the gateway level, making &lt;strong&gt;Traefik&lt;/strong&gt; an excellent choice for the task.&lt;/p&gt;

&lt;p&gt;In this post, we will look into the process of setting up and configuring &lt;strong&gt;ForwardAuth&lt;/strong&gt; with &lt;strong&gt;Traefik&lt;/strong&gt; and explore some advantages of using this authentication method within a (micro)services architecture to secure access to a protected &lt;em&gt;Order&lt;/em&gt; resource in our hypothetical application.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Authentication
&lt;/h3&gt;

&lt;p&gt;First a quick look into what authentication actually is. When we ask our users to authenticate, we are essentially asking them to prove to our application that they are who they say they are. In the most basic form of authentication, the users often prove their identity by supplying our application with an email address, or a unique username, and a password. Since the communication between the user/client and the server in the application leveraging the HTTP protocol is more often than not stateless, the user must prove their identity with every request.&lt;/p&gt;

&lt;p&gt;If an attacker can obtain the users password which they are using to prove their identity with, the attacker can now identify as the user to our application at any time, until the user changes their password. And since users must prove their identity with the password on every request, the attacker has a lot of chances to get to the users password. To mitigate this, the access control system in our application will usually issue a short lived access token to our user, after they have proven their identity with their password. After this point, the user can use this access token to prove their identity, until the token expires, and they have to obtain a new one.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Forward Authentication
&lt;/h3&gt;

&lt;p&gt;When our application now receives a request to the protected &lt;em&gt;GET /order/{id}&lt;/em&gt; resource endpoint, it verifies that the request also contains the access token, and it ensures that the token is valid and belonging to a user. Since we are in a (micro)services architecture and we are using multiple services to serve different resources to our users, as in example, the request to retrieve an order with the ID &lt;em&gt;{id}&lt;/em&gt; is handled by the &lt;code&gt;order&lt;/code&gt; service, we would typically need to implement identity verification in each service, or rather implement an &lt;code&gt;authentication&lt;/code&gt; service which will verify the identity of the users for us through the &lt;em&gt;POST /auth/verify&lt;/em&gt; endpoint.&lt;/p&gt;

&lt;p&gt;Instead of having each service verify user identities by calling the &lt;code&gt;authentication&lt;/code&gt; service to verify the users identity, which quickly becomes cumbersome and can lead to inconsistencies between services, we can employ the Forward Authentication mechanism in our reverse proxy, &lt;strong&gt;Traefik&lt;/strong&gt;. When using &lt;strong&gt;ForwardAuth&lt;/strong&gt; each request that is received to a protected URI, like in example &lt;em&gt;GET /order/{id}&lt;/em&gt;, &lt;strong&gt;Traefik&lt;/strong&gt; will automatically forward the request to our &lt;code&gt;authentication&lt;/code&gt; service for user authentication, before sending the request onward to the resource service, in our example, &lt;code&gt;order&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig1jkhjwy9ig2s2klly3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig1jkhjwy9ig2s2klly3.png" alt="ForwardAuth Diagram 1" width="800" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring ForwardAuth in Traefik
&lt;/h3&gt;

&lt;p&gt;Below we have hypothetical service and http router definitions for our &lt;code&gt;authentication&lt;/code&gt; and &lt;code&gt;order&lt;/code&gt; services and routers in &lt;strong&gt;Traefik&lt;/strong&gt;:&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="nn"&gt;[http]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.routers]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathPrefix(`/order`)"&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;"order"&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.authentication]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathPrefix(`/login`)"&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;"order"&lt;/span&gt;

  &lt;span class="nn"&gt;[http.services]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.services.order.loadbalancer]&lt;/span&gt;
      &lt;span class="nn"&gt;[[http.services.order.loadbalancer.server]]&lt;/span&gt;
        &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;
    &lt;span class="nn"&gt;[http.services.authentication.loadbalancer]&lt;/span&gt;
      &lt;span class="nn"&gt;[[http.services.authentication.loadbalancer.server]]&lt;/span&gt;
        &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this configuration we have configured 2 services that we are running with docker, &lt;code&gt;order&lt;/code&gt; and &lt;code&gt;authentication&lt;/code&gt;, and &lt;strong&gt;Traefik&lt;/strong&gt; will route all requests to &lt;em&gt;&lt;a href="https://order.domain.tld/order" rel="noopener noreferrer"&gt;https://order.domain.tld/order&lt;/a&gt;&lt;/em&gt; to the &lt;code&gt;order&lt;/code&gt; service and all requests made to &lt;em&gt;&lt;a href="https://order.domain.tld/login" rel="noopener noreferrer"&gt;https://order.domain.tld/login&lt;/a&gt;&lt;/em&gt; the &lt;code&gt;authentication&lt;/code&gt; service. We do not need to route the &lt;em&gt;/auth/verify&lt;/em&gt; route, since we are going to be calling this only inside the same &lt;em&gt;docker network bridge&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;With this setup, the &lt;code&gt;order&lt;/code&gt; service would have to manually call &lt;em&gt;&lt;a href="https://authentication:8000/auth/verify" rel="noopener noreferrer"&gt;https://authentication:8000/auth/verify&lt;/a&gt;&lt;/em&gt; manually on each request made to the &lt;em&gt;/order/{id}&lt;/em&gt; endpoint, and of course any other endpoint or service would need to do the same. To centralize the authentication and not require each service to handle it individually, we are going to use &lt;strong&gt;ForwardAuth&lt;/strong&gt; by defining a middleware in &lt;strong&gt;Traefik&lt;/strong&gt; and add it to our router for the order service:&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="nn"&gt;[http]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.middlewares]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.middlewares.auth-user.forwardauth]&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;"https://authentication:8000/auth/verify"&lt;/span&gt;

  &lt;span class="nn"&gt;[http.routers]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order-secure]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathRegexp(`/order/[0-9]+`)"&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;"order"&lt;/span&gt;
      &lt;span class="py"&gt;middlewares&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"auth-user"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order]&lt;/span&gt;
      &lt;span class="c"&gt;# kept the same as before&lt;/span&gt;

  &lt;span class="c"&gt;# services defined as before&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have not defined a new &lt;strong&gt;ForwardAuth&lt;/strong&gt; middleware with the name &lt;code&gt;auth-user&lt;/code&gt;, and instructed &lt;strong&gt;Traefik&lt;/strong&gt; to redirect all requests made to all routers that employ this middleware to the &lt;em&gt;&lt;a href="https://authentication:8000/auth/verify" rel="noopener noreferrer"&gt;https://authentication:8000/auth/verify&lt;/a&gt;&lt;/em&gt; address. Further on, we have now added a new router, &lt;code&gt;order-secure&lt;/code&gt; which uses the &lt;code&gt;auth-user&lt;/code&gt; middleware, and catches only requests that are made to &lt;em&gt;&lt;a href="https://order.domain.tld/order/%7Bid%7D" rel="noopener noreferrer"&gt;https://order.domain.tld/order/{id}&lt;/a&gt;&lt;/em&gt; address while keeping the &lt;em&gt;&lt;a href="https://order.domain.tld/order" rel="noopener noreferrer"&gt;https://order.domain.tld/order&lt;/a&gt;&lt;/em&gt; requests non-authenticated.&lt;/p&gt;

&lt;p&gt;Now whenever the &lt;code&gt;order&lt;/code&gt; service receives a request to the &lt;em&gt;/order/{id}&lt;/em&gt; URI, we know we can trust this request as it was already forwarded to our &lt;code&gt;authentication&lt;/code&gt; service for user identity verification by &lt;strong&gt;Traefik&lt;/strong&gt; and we can proceed servicing the request right away.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing information between the services
&lt;/h3&gt;

&lt;p&gt;In real-world scenarios, we might also want to share some user information from the &lt;code&gt;authentication&lt;/code&gt; service to the &lt;code&gt;order&lt;/code&gt; service once the user has been authenticated, since the &lt;code&gt;authentication&lt;/code&gt; service will already have probably accessed the database, and we want to limit the access to the database in the downstream services in order to help maintain high performance.&lt;/p&gt;

&lt;p&gt;To achieve this, we have a couple of options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use of &lt;em&gt;JSON Web Tokens&lt;/em&gt; or &lt;em&gt;JWT&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;set any required data to the response headers with the &lt;code&gt;authentication&lt;/code&gt; service&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Use of JSON Web Tokens
&lt;/h4&gt;

&lt;p&gt;If we are using JWTs for authentication of the users, we can already keep the required user data in the JWT itself, since it was designed for exactly this. When the user sends the JWT in the request headers, &lt;strong&gt;Traefik&lt;/strong&gt; will naturally forward this JWT to the &lt;code&gt;authentication&lt;/code&gt; service through the &lt;strong&gt;ForwardAuth&lt;/strong&gt; middleware, as well as send this JWT on to the &lt;code&gt;order&lt;/code&gt; service, where the &lt;code&gt;authentication&lt;/code&gt; service can check the validity of the JWT token and the &lt;code&gt;order&lt;/code&gt; service can extract user data from it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting required data to response headers after authentication
&lt;/h4&gt;

&lt;p&gt;Since JWTs expose user data, we might want to avoid that, and can therefore set any user data that the downstream services will require in the response headers of the &lt;em&gt;/auth/verify&lt;/em&gt; call and instruct &lt;strong&gt;Traefik&lt;/strong&gt; to add data from that specific header to the follow-up request headers that will be sent to the &lt;code&gt;order&lt;/code&gt; service. Ideally in a way where the downstream services will be able to verify that the data was indeed set by the &lt;code&gt;authentication&lt;/code&gt; service. We achieve this by adding a slight modification in our &lt;strong&gt;ForwardAuth&lt;/strong&gt; middleware:&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="nn"&gt;[http]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.middlewares]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.middlewares.auth-user.forwardauth]&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;"https://authentication:8000/auth/verify"&lt;/span&gt;
      &lt;span class="py"&gt;authResponseHeaders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"X-Authenticated-User"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c"&gt;# all else remains the same&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Putting it all together
&lt;/h3&gt;

&lt;p&gt;Now let’s put everything we have learned together:&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="nn"&gt;[http]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.middlewares]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.middlewares.auth-user.forwardauth]&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;"https://authentication:8000/auth/verify"&lt;/span&gt;
      &lt;span class="py"&gt;authResponseHeaders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"X-Authenticated-User"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nn"&gt;[http.routers]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order-secure]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathRegexp(`/order/[0-9]+`)"&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;"order"&lt;/span&gt;
      &lt;span class="py"&gt;middlewares&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"auth-user"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathPrefix(`/order`)"&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;"order"&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.authentication]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathPrefix(`/login`)"&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;"order"&lt;/span&gt;

  &lt;span class="nn"&gt;[http.services]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.services.order.loadbalancer]&lt;/span&gt;
      &lt;span class="nn"&gt;[[http.services.order.loadbalancer.server]]&lt;/span&gt;
        &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;
    &lt;span class="nn"&gt;[http.services.authentication.loadbalancer]&lt;/span&gt;
      &lt;span class="nn"&gt;[[http.services.authentication.loadbalancer.server]]&lt;/span&gt;
        &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; the above configuration is omitting HTTPS configuration as it is beyond the scope of this post.&lt;/p&gt;

&lt;p&gt;And here we have it, congratulations! We now have a secure &lt;em&gt;GET /order/{id}&lt;/em&gt; endpoint in our &lt;code&gt;order&lt;/code&gt; service, and to secure any more services or endpoints, we simply need to add the middleware to their route definitions. Now let's take look at the lifecycle of the &lt;em&gt;GET /order/{id}&lt;/em&gt; request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6dx9rxnp0kcwzrs4rzp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6dx9rxnp0kcwzrs4rzp.png" alt="ForwardAuth Diagram 2" width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>traefik</category>
      <category>authentication</category>
      <category>security</category>
      <category>forwardauth</category>
    </item>
    <item>
      <title>ForwardAuth with Traefik: Streamlining Security for Microservices</title>
      <dc:creator>Tomaz Lovrec</dc:creator>
      <pubDate>Fri, 11 Oct 2024 19:49:30 +0000</pubDate>
      <link>https://forem.com/slax0rr/forwardauth-with-traefik-streamlining-security-for-microservices-e3g</link>
      <guid>https://forem.com/slax0rr/forwardauth-with-traefik-streamlining-security-for-microservices-e3g</guid>
      <description>&lt;p&gt;In the information age, nothing is more important than the security of our services—and more importantly, the security of our users and their data. Ensuring security within a (micro)services architecture can quickly become complex and burdensome. As services grow and more spring to life within the ecosystem, maintaining consistent and reliable access control becomes a top priority. To streamline access control, we can leverage &lt;strong&gt;Forward Authentication&lt;/strong&gt;, which centralizes the authentication mechanism and simplifies securing our (micro)services.&lt;/p&gt;

&lt;p&gt;While many reverse proxies offer functionality for routing and authentication, &lt;strong&gt;Traefik&lt;/strong&gt; stands out with its ease of use and flexibility. In addition to efficiently routing traffic, Traefik’s integration with Forward Authentication (&lt;strong&gt;ForwardAuth&lt;/strong&gt;) enables us to centralize user authentication across all services. Using a centralized authentication not only makes the access management easier, but also strengthens the security of our services at the gateway level, making &lt;strong&gt;Traefik&lt;/strong&gt; an excellent choice for the task.&lt;/p&gt;

&lt;p&gt;In this post, we will look into the process of setting up and configuring &lt;strong&gt;ForwardAuth&lt;/strong&gt; with &lt;strong&gt;Traefik&lt;/strong&gt; and explore some advantages of using this authentication method within a (micro)services architecture to secure access to a protected &lt;em&gt;Order&lt;/em&gt; resource in our hypothetical application.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Authentication
&lt;/h3&gt;

&lt;p&gt;First a quick look into what authentication actually is. When we ask our users to authenticate, we are essentially asking them to prove to our application that they are who they say they are. In the most basic form of authentication, the users often prove their identity by supplying our application with an email address, or a unique username, and a password. Since the communication between the user/client and the server in the application leveraging the HTTP protocol is more often than not stateless, the user must prove their identity with every request.&lt;/p&gt;

&lt;p&gt;If an attacker can obtain the users password which they are using to prove their identity with, the attacker can now identify as the user to our application at any time, until the user changes their password. And since users must prove their identity with the password on every request, the attacker has a lot of chances to get to the users password. To mitigate this, the access control system in our application will usually issue a short lived access token to our user, after they have proven their identity with their password. After this point, the user can use this access token to prove their identity, until the token expires, and they have to obtain a new one.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Forward Authentication
&lt;/h3&gt;

&lt;p&gt;When our application now receives a request to the protected &lt;em&gt;GET /order/{id}&lt;/em&gt; resource endpoint, it verifies that the request also contains the access token, and it ensures that the token is valid and belonging to a user. Since we are in a (micro)services architecture and we are using multiple services to serve different resources to our users, as in example, the request to retrieve an order with the ID &lt;em&gt;{id}&lt;/em&gt; is handled by the &lt;code&gt;order&lt;/code&gt; service, we would typically need to implement identity verification in each service, or rather implement an &lt;code&gt;authentication&lt;/code&gt; service which will verify the identity of the users for us through the &lt;em&gt;POST /auth/verify&lt;/em&gt; endpoint.&lt;/p&gt;

&lt;p&gt;Instead of having each service verify user identities by calling the &lt;code&gt;authentication&lt;/code&gt; service to verify the users identity, which quickly becomes cumbersome and can lead to inconsistencies between services, we can employ the Forward Authentication mechanism in our reverse proxy, &lt;strong&gt;Traefik&lt;/strong&gt;. When using &lt;strong&gt;ForwardAuth&lt;/strong&gt; each request that is received to a protected URI, like in example &lt;em&gt;GET /order/{id}&lt;/em&gt;, &lt;strong&gt;Traefik&lt;/strong&gt; will automatically forward the request to our &lt;code&gt;authentication&lt;/code&gt; service for user authentication, before sending the request onward to the resource service, in our example, &lt;code&gt;order&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig1jkhjwy9ig2s2klly3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig1jkhjwy9ig2s2klly3.png" alt="ForwardAuth Diagram 1" width="800" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring ForwardAuth in Traefik
&lt;/h3&gt;

&lt;p&gt;Below we have hypothetical service and http router definitions for our &lt;code&gt;authentication&lt;/code&gt; and &lt;code&gt;order&lt;/code&gt; services and routers in &lt;strong&gt;Traefik&lt;/strong&gt;:&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="nn"&gt;[http]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.routers]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathPrefix(`/order`)"&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;"order"&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.authentication]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathPrefix(`/login`)"&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;"order"&lt;/span&gt;

  &lt;span class="nn"&gt;[http.services]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.services.order.loadbalancer]&lt;/span&gt;
      &lt;span class="nn"&gt;[[http.services.order.loadbalancer.server]]&lt;/span&gt;
        &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;
    &lt;span class="nn"&gt;[http.services.authentication.loadbalancer]&lt;/span&gt;
      &lt;span class="nn"&gt;[[http.services.authentication.loadbalancer.server]]&lt;/span&gt;
        &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this configuration we have configured 2 services that we are running with docker, &lt;code&gt;order&lt;/code&gt; and &lt;code&gt;authentication&lt;/code&gt;, and &lt;strong&gt;Traefik&lt;/strong&gt; will route all requests to &lt;em&gt;&lt;a href="https://order.domain.tld/order" rel="noopener noreferrer"&gt;https://order.domain.tld/order&lt;/a&gt;&lt;/em&gt; to the &lt;code&gt;order&lt;/code&gt; service and all requests made to &lt;em&gt;&lt;a href="https://order.domain.tld/login" rel="noopener noreferrer"&gt;https://order.domain.tld/login&lt;/a&gt;&lt;/em&gt; the &lt;code&gt;authentication&lt;/code&gt; service. We do not need to route the &lt;em&gt;/auth/verify&lt;/em&gt; route, since we are going to be calling this only inside the same &lt;em&gt;docker network bridge&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;With this setup, the &lt;code&gt;order&lt;/code&gt; service would have to manually call &lt;em&gt;&lt;a href="https://authentication:8000/auth/verify" rel="noopener noreferrer"&gt;https://authentication:8000/auth/verify&lt;/a&gt;&lt;/em&gt; manually on each request made to the &lt;em&gt;/order/{id}&lt;/em&gt; endpoint, and of course any other endpoint or service would need to do the same. To centralize the authentication and not require each service to handle it individually, we are going to use &lt;strong&gt;ForwardAuth&lt;/strong&gt; by defining a middleware in &lt;strong&gt;Traefik&lt;/strong&gt; and add it to our router for the order service:&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="nn"&gt;[http]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.middlewares]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.middlewares.auth-user.forwardauth]&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;"https://authentication:8000/auth/verify"&lt;/span&gt;

  &lt;span class="nn"&gt;[http.routers]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order-secure]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathRegexp(`/order/[0-9]+`)"&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;"order"&lt;/span&gt;
      &lt;span class="py"&gt;middlewares&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"auth-user"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order]&lt;/span&gt;
      &lt;span class="c"&gt;# kept the same as before&lt;/span&gt;

  &lt;span class="c"&gt;# services defined as before&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have not defined a new &lt;strong&gt;ForwardAuth&lt;/strong&gt; middleware with the name &lt;code&gt;auth-user&lt;/code&gt;, and instructed &lt;strong&gt;Traefik&lt;/strong&gt; to redirect all requests made to all routers that employ this middleware to the &lt;em&gt;&lt;a href="https://authentication:8000/auth/verify" rel="noopener noreferrer"&gt;https://authentication:8000/auth/verify&lt;/a&gt;&lt;/em&gt; address. Further on, we have now added a new router, &lt;code&gt;order-secure&lt;/code&gt; which uses the &lt;code&gt;auth-user&lt;/code&gt; middleware, and catches only requests that are made to &lt;em&gt;&lt;a href="https://order.domain.tld/order/%7Bid%7D" rel="noopener noreferrer"&gt;https://order.domain.tld/order/{id}&lt;/a&gt;&lt;/em&gt; address while keeping the &lt;em&gt;&lt;a href="https://order.domain.tld/order" rel="noopener noreferrer"&gt;https://order.domain.tld/order&lt;/a&gt;&lt;/em&gt; requests non-authenticated.&lt;/p&gt;

&lt;p&gt;Now whenever the &lt;code&gt;order&lt;/code&gt; service receives a request to the &lt;em&gt;/order/{id}&lt;/em&gt; URI, we know we can trust this request as it was already forwarded to our &lt;code&gt;authentication&lt;/code&gt; service for user identity verification by &lt;strong&gt;Traefik&lt;/strong&gt; and we can proceed servicing the request right away.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing information between the services
&lt;/h3&gt;

&lt;p&gt;In real-world scenarios, we might also want to share some user information from the &lt;code&gt;authentication&lt;/code&gt; service to the &lt;code&gt;order&lt;/code&gt; service once the user has been authenticated, since the &lt;code&gt;authentication&lt;/code&gt; service will already have probably accessed the database, and we want to limit the access to the database in the downstream services in order to help maintain high performance.&lt;/p&gt;

&lt;p&gt;To achieve this, we have a couple of options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use of &lt;em&gt;JSON Web Tokens&lt;/em&gt; or &lt;em&gt;JWT&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;set any required data to the response headers with the &lt;code&gt;authentication&lt;/code&gt; service&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Use of JSON Web Tokens
&lt;/h4&gt;

&lt;p&gt;If we are using JWTs for authentication of the users, we can already keep the required user data in the JWT itself, since it was designed for exactly this. When the user sends the JWT in the request headers, &lt;strong&gt;Traefik&lt;/strong&gt; will naturally forward this JWT to the &lt;code&gt;authentication&lt;/code&gt; service through the &lt;strong&gt;ForwardAuth&lt;/strong&gt; middleware, as well as send this JWT on to the &lt;code&gt;order&lt;/code&gt; service, where the &lt;code&gt;authentication&lt;/code&gt; service can check the validity of the JWT token and the &lt;code&gt;order&lt;/code&gt; service can extract user data from it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting required data to response headers after authentication
&lt;/h4&gt;

&lt;p&gt;Since JWTs expose user data, we might want to avoid that, and can therefore set any user data that the downstream services will require in the response headers of the &lt;em&gt;/auth/verify&lt;/em&gt; call and instruct &lt;strong&gt;Traefik&lt;/strong&gt; to add data from that specific header to the follow-up request headers that will be sent to the &lt;code&gt;order&lt;/code&gt; service. Ideally in a way where the downstream services will be able to verify that the data was indeed set by the &lt;code&gt;authentication&lt;/code&gt; service. We achieve this by adding a slight modification in our &lt;strong&gt;ForwardAuth&lt;/strong&gt; middleware:&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="nn"&gt;[http]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.middlewares]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.middlewares.auth-user.forwardauth]&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;"https://authentication:8000/auth/verify"&lt;/span&gt;
      &lt;span class="py"&gt;authResponseHeaders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"X-Authenticated-User"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c"&gt;# all else remains the same&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Putting it all together
&lt;/h3&gt;

&lt;p&gt;Now let’s put everything we have learned together:&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="nn"&gt;[http]&lt;/span&gt;
  &lt;span class="nn"&gt;[http.middlewares]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.middlewares.auth-user.forwardauth]&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;"https://authentication:8000/auth/verify"&lt;/span&gt;
      &lt;span class="py"&gt;authResponseHeaders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"X-Authenticated-User"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nn"&gt;[http.routers]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order-secure]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathRegexp(`/order/[0-9]+`)"&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;"order"&lt;/span&gt;
      &lt;span class="py"&gt;middlewares&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"auth-user"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.order]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathPrefix(`/order`)"&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;"order"&lt;/span&gt;
    &lt;span class="nn"&gt;[http.routers.authentication]&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;"Host(`order.domain.tld`) &amp;amp;&amp;amp; PathPrefix(`/login`)"&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;"order"&lt;/span&gt;

  &lt;span class="nn"&gt;[http.services]&lt;/span&gt;
    &lt;span class="nn"&gt;[http.services.order.loadbalancer]&lt;/span&gt;
      &lt;span class="nn"&gt;[[http.services.order.loadbalancer.server]]&lt;/span&gt;
        &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;
    &lt;span class="nn"&gt;[http.services.authentication.loadbalancer]&lt;/span&gt;
      &lt;span class="nn"&gt;[[http.services.authentication.loadbalancer.server]]&lt;/span&gt;
        &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; the above configuration is omitting HTTPS configuration as it is beyond the scope of this post.&lt;/p&gt;

&lt;p&gt;And here we have it, congratulations! We now have a secure &lt;em&gt;GET /order/{id}&lt;/em&gt; endpoint in our &lt;code&gt;order&lt;/code&gt; service, and to secure any more services or endpoints, we simply need to add the middleware to their route definitions. Now let's take look at the lifecycle of the &lt;em&gt;GET /order/{id}&lt;/em&gt; request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6dx9rxnp0kcwzrs4rzp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6dx9rxnp0kcwzrs4rzp.png" alt="ForwardAuth Diagram 2" width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>traefik</category>
      <category>authentication</category>
      <category>security</category>
      <category>forwardauth</category>
    </item>
    <item>
      <title>Proper Way of Using a Makefile</title>
      <dc:creator>Tomaz Lovrec</dc:creator>
      <pubDate>Fri, 29 Jan 2021 16:17:18 +0000</pubDate>
      <link>https://forem.com/slax0rr/proper-way-of-using-a-makefile-3dca</link>
      <guid>https://forem.com/slax0rr/proper-way-of-using-a-makefile-3dca</guid>
      <description>&lt;p&gt;The &lt;code&gt;Makefile&lt;/code&gt; has been with us for quite a long time. Primarily used with C or C++ software, but in the recent years it has seen use in projects using almost any programming language. And why not, it is a powerful tool. Although, I have seen many people arguing that "it is just another task manager", which is of course far from the truth.&lt;/p&gt;

&lt;p&gt;I understand why you might think so, because like me, you are probably using &lt;code&gt;make&lt;/code&gt; and the &lt;code&gt;Makefile&lt;/code&gt; wrong. I knew that it is capable of doing things that need to be done and not simply do everything all the time, but I never bothered to actually dive into it to see how I can improve my build times. There are countless resources in the internet how to get you started with &lt;code&gt;Makefile&lt;/code&gt;, but most if not all simply just present it as a task runner, even if they do comment that it is just a basic usage for it.&lt;/p&gt;

&lt;p&gt;Basic usage is completely fine, but imagine you are creating a &lt;br&gt;
build target to build multiple services that are built from the source code in a shared repository. You could rebuild all of them every time you change something, but why, if you only need to rebuild those that you actually changed? And here comes &lt;code&gt;Makefile&lt;/code&gt; to the rescue. Lets start with a hypothetical source code structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-awesome-project
|-dist/
|-pkg/
| |-libA/
|   `-libA.go
| |-libB/
|   `-libB.go
| `-libC/
|   `-libC.go
`-internal/
  |-serviceA/
  |  |-main.go
  |  `-functionality.go
  `-serviceB/
    |-main.go
    `-functionality.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The general idea is, that we want to rebuild both services A and B if the libraries in the &lt;code&gt;pkg&lt;/code&gt; directory change and rebuild only service A or B if their source files change. You might want a &lt;code&gt;Makefile&lt;/code&gt; something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;dist/serviceA dist/serviceB&lt;/span&gt;

&lt;span class="nl"&gt;dist/serviceA&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;internal/serviceA/*.go pkg/*/*.go&lt;/span&gt;
    go build &lt;span class="nt"&gt;-o&lt;/span&gt; dist/serviceA ./internal/serviceA/

&lt;span class="nl"&gt;dist/serviceB&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;internal/serviceA/*.go pkg/*/*.go&lt;/span&gt;
    go build &lt;span class="nt"&gt;-o&lt;/span&gt; dist/serviceB ./internal/serviceB/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line, &lt;code&gt;all: dist/serviceA dist/serviceB&lt;/code&gt; is just an alias and allows you to run simply &lt;code&gt;make&lt;/code&gt; and it will execute all of the targets listed on its line. The further lines are actual build targets, but they are named after the file that the build will produce followed by files that are used to build it. Using this format allows &lt;code&gt;make&lt;/code&gt; to track the file change timestamps and when a run for a specific target is requested &lt;code&gt;make&lt;/code&gt; will check if any of the specified files have a newer timestamp than the target file and only if they do will it run run that target.&lt;/p&gt;

&lt;p&gt;Of course you can specify aliases for those as well so you do not need to type &lt;code&gt;make dist/serviceA&lt;/code&gt; should you wish so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;serviceA&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;dist/serviceA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now you can execute &lt;code&gt;make serviceA&lt;/code&gt; and it will build service A, but only if the source has changed.&lt;/p&gt;

&lt;p&gt;This can be applied to anything of course, like generating code, tests, etc. Of course this seems like an overkill for smaller projects and you will spend more time configuring and writing a &lt;code&gt;Makefile&lt;/code&gt; than you will save by shorter build times, but if you have a larger project on hand it can be very beneficial to&lt;br&gt;
have certain tasks run only if they are necessary.&lt;/p&gt;

</description>
      <category>development</category>
      <category>makefile</category>
      <category>build</category>
    </item>
    <item>
      <title>Ancient art of Git-fu</title>
      <dc:creator>Tomaz Lovrec</dc:creator>
      <pubDate>Tue, 28 Apr 2020 11:22:36 +0000</pubDate>
      <link>https://forem.com/slax0rr/ancient-art-of-git-fu-693</link>
      <guid>https://forem.com/slax0rr/ancient-art-of-git-fu-693</guid>
      <description>&lt;p&gt;I have been using Git for quite some time now, my &lt;a href="https://github.com/slax0rr/"&gt;GitHub profile&lt;/a&gt; is almost 8 years old, and I have been using Git before joining GitHub for at least 2 years. I think I can safely say I have been using it for around 10 years. Not just as a contributor to the various repositories on Git, but also as a tool to help me debug an error in the application or library. You might wonder how Git could provide help with that, well, it holds the secrets to when something was changed, why it was changed, and by who it was changed. Its a treasure, and you should treat it like on as well.&lt;/p&gt;

&lt;p&gt;Of course there are some unwritten rules or guidelines on how to treat your Git history like a treasure, and I will try to run through a couple of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commit soon, commit often
&lt;/h2&gt;

&lt;p&gt;This first guideline might seem a bit backward, since to keep the history clean you might want to reduce the number of commits, but committing sooner and more often will help your with writing the code, more specifically when you need to make alterations, because you've decided to design your code in a different way.  So for now, do not worry how your history looks like, make commits as soon as some logical piece of your code is finished. If you later find out you don't need some piece of your code, you can simply remove that commit, and presto, that piece of code or that change of code is gone.&lt;/p&gt;

&lt;p&gt;This will hopefully keep you from keeping up with another guideline, &lt;strong&gt;don't commit commented code&lt;/strong&gt;. Seriously, just don't. When searching through the history you create a whole lot more false positives, extending the time to find what you are actually looking for in the history as all those commits which commit commented code also show up. You don't need to comment some old code in case you'll need it later or you're not sure about the change. That code you changed is still kept in the original form in git history, even if you don't commit anything, you can still find it by issuing a &lt;code&gt;git diff -- filename&lt;/code&gt; command.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clean up commits before publishing
&lt;/h3&gt;

&lt;p&gt;If you are following the above guideline, you probably now have a pretty messy history on your hands. And hopefully you also haven't already have published your commits to the remote, and you have them only locally. It's time to clean them up. To start, execute &lt;code&gt;git rebase --interactive&lt;/code&gt;, if you still have some uncommitted changes, commit them now, or stash them using &lt;code&gt;git stash&lt;/code&gt;. The &lt;strong&gt;rebase&lt;/strong&gt; command will open your git set editor with something similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pick a4e64eb canged the error response text
pick 919f447 return an error when record not found
pick c7d7e82 bubble the error object up to the handler

# Rebase f2b16ac..c7d7e82 onto f2b16ac (3 commands)
#
# Commands:

... description of the commands follows bellow in the article ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the very beginning each line is one commit in the following form:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;command&amp;gt; &amp;lt;commit short hash&amp;gt; &amp;lt;commit message title&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To edit the history you simply edit the command for each line that you want to edit. Available commands are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;pick&lt;/strong&gt; - use commit as is&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;reword&lt;/strong&gt; - use commit as is but edit the commit message&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;edit&lt;/strong&gt; - pause the &lt;em&gt;rebase&lt;/em&gt; and allow for amending of the commit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;squash&lt;/strong&gt; - merge the commit with the previous commit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;fixup&lt;/strong&gt; - same as squash and use previous commits message&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;exec&lt;/strong&gt; - execute the shell command found on the same line (add a new line with this command, i.e.: &lt;code&gt;exec ls&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;drop&lt;/strong&gt; - remove the commit (removing the line will also remove the commit)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the above example I would want to squash the &lt;code&gt;919f447&lt;/code&gt; and &lt;code&gt;c7d7e82&lt;/code&gt; commits together, which would mean I would change the 3rd commits command from &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;squash&lt;/code&gt; or &lt;code&gt;fixup&lt;/code&gt;, depending if I want to edit the commit message or not.  After the change, simply save the file and quit the editor and &lt;em&gt;rebase&lt;/em&gt; will run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finish your work before committing
&lt;/h2&gt;

&lt;p&gt;Don't use git as a means to transfer your work from one machine to another. Or at least don't do this in any branches that are used by you or your team. If you absolutely HAVE to use git to transfer your edited files to a different machine then at least create a brand new branch, commit your changes there, and once you've transferred your work, remove that commit and branch from the remote immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="c"&gt;# I guess you will want to, but this step is optional&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; yourhandle_temp &lt;span class="c"&gt;# create a new branch with your uncommited changes&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"transfering my work"&lt;/span&gt;

&lt;span class="c"&gt;# on the other machine:&lt;/span&gt;
git fetch
git checkout yourhandle_temp
git push origin :yourhandle_temp &lt;span class="c"&gt;# remove the remote branch&lt;/span&gt;
git reset HEAD~1 &lt;span class="c"&gt;# remove the temp commit and leave files unstaged&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Alternatives
&lt;/h3&gt;

&lt;p&gt;A much more cleaner approach would be to stash your changes and export them to a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash
git stash show &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; some.patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now take this file to your other machine via a thumb drive or some file sharing service, or however you want and apply this patch on your other machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git apply some.patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way you are not polluting the remote with your temp commits or temporary branches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test your work before you publish
&lt;/h2&gt;

&lt;p&gt;Always test your work before you publish your work. If you want to do yourself a favour, also test before committing, because it will save you some time needed to edit/squash the commits where you fix your newly created bugs right away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write sensible commit messages
&lt;/h2&gt;

&lt;p&gt;There is literally nothing worse than a non-descriptive commit message when you need to inspect Git history. Imagine the following history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
* fd4befe 
|          [3 days ago]     Tomaz Lovrec: more work 
* 08a128a 
|          [3 days ago]     Tomaz Lovrec: fix 
* 84a43f1 
|          [3 days ago]     Tomaz Lovrec: work 
* d8de94b 
|          [3 days ago]     Tomaz Lovrec: fix 
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you are looking through the history trying to piece together when and where some change was made, to understand maybe why it was made. Now you have to open every commit and inspect all the changes in the commit. Painful work. And since all the commit messages are almost the same it is much harder to keep track of which you already inspected and remembering which does what.&lt;/p&gt;

&lt;p&gt;This is why it is recommended to write commits in the following form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;short descriptive title, up to 60-80 chars

Longer description about what you did, why did you do it, what you were trying
to solve. Your goal here should be to explain the change enough that someone
inspecting your commit does not need to contact you. Although, do try and keep
it short, because no one has time to spend 5 minutes on each commits message.
And keep the lines shorter than 80 characters.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Furthermore the title should describe what you have done in the code, not the effect the change had. Instead of writing &lt;code&gt;fixed the wrong error response&lt;/code&gt; write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error response to ErrFoo in foo endpoint

The previous error message was false and did not properly describe the error to
the client. ErrFoo is a better alternative since it......
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Those are just some of the guidelines you should keep in mind when working with Git in order to maintain some sensibility in your Git history and transmit your changes more effectively to the rest of your team, and also maybe to just get your co-worker of your back "bugging" you all the time why you did something.&lt;/p&gt;

&lt;p&gt;There are a lot more guidelines, but most important is, that you and your team agree on them and follow them, even if you deem some of them unnecessary or stupid.&lt;/p&gt;

&lt;p&gt;Do you have any other guidelines you think I should have mentioned? Please feel free to add them to the comments bellow!&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>My Go Toolset</title>
      <dc:creator>Tomaz Lovrec</dc:creator>
      <pubDate>Fri, 17 Apr 2020 12:42:49 +0000</pubDate>
      <link>https://forem.com/slax0rr/my-go-toolset-3h7f</link>
      <guid>https://forem.com/slax0rr/my-go-toolset-3h7f</guid>
      <description>&lt;p&gt;When developing some software, you very often tend to use some 3rd party tools or libraries to enable yourself to focus more on the task at hand. And this makes perfect sense, imagine if you had to write your own HTTP server everytime you wanted to develop a web application. Or a router, or, or, or... This would be insane and nothing would get done. Ever.&lt;/p&gt;

&lt;p&gt;We as developers also grow used to certain tools, and don't switch much between them, unless we really have to due to many reasons. And here is the list of my tools and libraries that I tend to use, with short description of each of thembellow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/go-delve/delve"&gt;go-delve/delve&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/spf13/cobra"&gt;spf13/cobra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/spf13/viper"&gt;spf13/viper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sirupsen/logrus"&gt;sirupsen/logrus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gorilla/mux"&gt;gorilla/mux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/adams-sarah/test2doc"&gt;adams-sarah/test2doc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets dig in!&lt;/p&gt;

&lt;h2&gt;
  
  
  go-delve/delve - Debugging
&lt;/h2&gt;

&lt;p&gt;When it comes to debugging Go applications, &lt;a href="https://github.com/go-delve/delve"&gt;go-delve/delve&lt;/a&gt; is my go-to library. To start debugging your source code, simply execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dlv debug gitlab.com/youruser/project/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or to debug a built binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dlv &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;$GOPATH&lt;/span&gt;/bin/built_bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even debug your pesky tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dlv &lt;span class="nb"&gt;test &lt;/span&gt;gitlab.com/youruser/project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can start setting breakpoints using &lt;code&gt;break pkg_name.FuncName&lt;/code&gt; or &lt;code&gt;break filename.go:&amp;lt;linenum&amp;gt;&lt;/code&gt; and then starting the execution by calling &lt;code&gt;continue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can also start the debugging session with the &lt;code&gt;--headless&lt;/code&gt; flag to start the debugger in headless mode and connect to it with your editor or IDE.&lt;/p&gt;

&lt;h2&gt;
  
  
  spf13/cobra - CLI commands
&lt;/h2&gt;

&lt;p&gt;Creating a CLI interface to my applications is really simple when using the &lt;a href="https://github.com/spf13/cobra"&gt;spf13/cobra&lt;/a&gt; library, all you need to do is execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cobra init nameofexec &lt;span class="nt"&gt;--pkg-name&lt;/span&gt; gitlab.com/yourname/yourproject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;em&gt;cobra&lt;/em&gt; will create everything, the directory structure inside a new directory named &lt;strong&gt;nameofexec&lt;/strong&gt;, the root command inside &lt;strong&gt;nameofexec/cmd/root.go&lt;/strong&gt;, all you need to do is open the file, edit the descriptions and tell the command what you want it to actually do.&lt;/p&gt;

&lt;p&gt;Need a new command to go with your executable? No problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cobra add mycmd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create the &lt;strong&gt;nameofexec/cmd/mycmd.go&lt;/strong&gt; file and register the command. Again, all you need to do is set descriptions and tell it what to do.&lt;/p&gt;

&lt;p&gt;Of course you can also add flags and options to your executable and/or commands, but this is beyond the scope of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  spf13/viper - Configuration
&lt;/h2&gt;

&lt;p&gt;Need to parse configuration files? Need to parse configuration from a distributed key-value store like &lt;em&gt;etcd&lt;/em&gt;? Look no further, &lt;a href="https://github.com/spf13/viper"&gt;spf13/viper&lt;/a&gt; got you covered! If you're using &lt;em&gt;spf13/cobra&lt;/em&gt; from above, it already imports and configures &lt;em&gt;spf13/viper&lt;/em&gt; for you, if not, configuration is really simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// initConfig reads in config file and ENV variables if set.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;initConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cfgFile&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Use config file from the flag.&lt;/span&gt;
        &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetConfigFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfgFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Find home directory.&lt;/span&gt;
        &lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;homedir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Search config in home directory with name ".yourproject" (without extension).&lt;/span&gt;
        &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddConfigPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetConfigName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".yourproject"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AutomaticEnv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// read in environment variables that match&lt;/span&gt;

    &lt;span class="c"&gt;// If a config file is found, read it in.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadInConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using config file:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConfigFileUsed&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accessing the configuration is even simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/spf13/viper"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my.key"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It supports multiple file types, &lt;em&gt;JSON&lt;/em&gt;, &lt;em&gt;YAML&lt;/em&gt;, &lt;em&gt;TOML&lt;/em&gt;,... Whatever you need!&lt;/p&gt;

&lt;h2&gt;
  
  
  sirupsen/logrus - Logging
&lt;/h2&gt;

&lt;p&gt;To log my messages nicely under different levels or even to different destinations I let &lt;a href="https://github.com/sirupsen/logrus"&gt;sirupsen/logrus&lt;/a&gt; handle it. It doesn't even need any configuration, you can just use it from the get go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/sirupsen/logrus"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"important stuff"&lt;/span&gt;
    &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"details"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I've got something important to tell you"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;anything&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I couldn't do anything!"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course this is just basic usage, you can set the desired log level to ignore messages that are in lower levels and log just the errors, you have countless hooks readily available to help you send your log messages to any service you want, and if the hook isn't available, it's really easy to write one yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  gorilla/mux - HTTP Router
&lt;/h2&gt;

&lt;p&gt;When writing a web application or a RESTful API, you need a HTTP router and dispatcher. I tend to always use &lt;a href="https://github.com/gorilla/mux"&gt;gorilla/mux&lt;/a&gt; in my projects. It satisfies all my needs, and is very simple to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gorilla/mux"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rtr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;rtr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rtr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compile, run and visit &lt;code&gt;http://localhost:8080/hello&lt;/code&gt; and there you go! Want to make it more personal? No problem let's just change the above &lt;code&gt;HandleFunc&lt;/code&gt; to include a parameter or leave the above one in place and create a new route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;span class="n"&gt;rtr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello/{name}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, %s!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Vars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compile, run and visit &lt;code&gt;http://localhost:8080/hello/foo&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  adams-sarah/test2doc - API documentation
&lt;/h2&gt;

&lt;p&gt;I must say I simply love &lt;a href="https://github.com/adams-sarah/test2doc"&gt;adams-sarah/test2doc&lt;/a&gt;! Writing tests can be a daunting task, and then you still need to write documentation. Well here comes &lt;strong&gt;test2doc&lt;/strong&gt; to the rescue! Simply write up a test for a handler using the &lt;strong&gt;test2doc&lt;/strong&gt; server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"testing"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/adams-sarah/test2doc/test"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/adams-sarah/test2doc/vars"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestMyHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// init the router and register a handler to a route&lt;/span&gt;
    &lt;span class="n"&gt;rtr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;rtr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;helloHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// register the mux extractor&lt;/span&gt;
    &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterURLVarExtractor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeGorillaMuxExtractor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rtr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c"&gt;// start the server and defer the Finish call&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rtr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unable to create test server, %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Finish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// get the named route from mux and get its URL&lt;/span&gt;
    &lt;span class="n"&gt;urlPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rtr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unable to get route URL, %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;urlPath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unable to process the request, %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now simply execute the test with &lt;code&gt;go test&lt;/code&gt; and you should get a new file in your directory ending with an &lt;code&gt;.apib&lt;/code&gt; extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web application directory layout
&lt;/h2&gt;

&lt;p&gt;I have also prepared a small bare-bones project that I tend to use often when starting a new project, since I already have a lot of the above tools and libraries already incorporated, as well as some deployment options. It is personalized to my own use, but can probably be useful for someone else too, since it does not enforce anything. Please check it out at my &lt;a href="https://gitlab.com/slax0rr/go-web-scaffold"&gt;GitLab repository&lt;/a&gt; and feel free to use it if you find it useful!&lt;/p&gt;

</description>
      <category>go</category>
      <category>development</category>
    </item>
    <item>
      <title>Deploying Secure Web Applications With Docker</title>
      <dc:creator>Tomaz Lovrec</dc:creator>
      <pubDate>Fri, 10 Apr 2020 17:14:42 +0000</pubDate>
      <link>https://forem.com/slax0rr/deploying-secure-web-applications-with-docker-28li</link>
      <guid>https://forem.com/slax0rr/deploying-secure-web-applications-with-docker-28li</guid>
      <description>&lt;p&gt;Over the past few we have seen more and more use of containers and I think this will continue in the future. And from a developers point of view, rightly so. I still remember using cumbersome and slow Virtual Machines that would take ages to provision and start up. Then along came containers and Docker. Yes there are some &lt;a href="https://www.channelfutures.com/open-source/docker-downsides-container-cons-to-consider-before-adopting-docker"&gt;drawbacks&lt;/a&gt; to be considered before you start using it, but the bottom line is, I can quickly fire up a container or multiple containers, do my work on the project, tear everything down at the end and switch to a different project, where I can do more of the same. &lt;/p&gt;

&lt;p&gt;Aside from helping out in the local environment, there is one other advantage that Docker and containers bring to the table. Deployments, and ease of it. It is fairly simple to ship your application with Docker. There are tools that allow you to set up everything in a matter of minutes. This is what this article will try to walk you through, and at the end you will have shipped your application to the web, and better yet, you have it deployed behind a HTTPS secured server. &lt;/p&gt;

&lt;h2&gt;
  
  
  The basics
&lt;/h2&gt;

&lt;p&gt;For this you will need a server with Docker installed. As long as you have a server running Linux you can easily &lt;a href="https://docs.docker.com/get-docker/"&gt;install docker&lt;/a&gt; on it. If you do not have a server you can get one fairly cheap nowadays at different providers. And be sure to install &lt;a href="https://docs.docker.com/compose/install/"&gt;docker-compose&lt;/a&gt; as well, as it will simplify a lot of the tasks before us. &lt;/p&gt;

&lt;p&gt;In this walk through we will build and deploy a very simple &lt;em&gt;expressjs&lt;/em&gt; frontend application, but you can deploy basically anything you want. To achieve our goal we will use the &lt;a href="https://containo.us/traefik/"&gt;traefik&lt;/a&gt; as our ingress router which will route the incoming traffic from the public to our &lt;em&gt;expressjs&lt;/em&gt; app. &lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing the server
&lt;/h2&gt;

&lt;p&gt;Now that you have &lt;code&gt;docker&lt;/code&gt; and &lt;code&gt;docker-compose&lt;/code&gt; installed, we are going to bring the ingress router up and running and apply a small configuration to it. To do this, create a &lt;code&gt;docker-compose.yml&lt;/code&gt; file somewhere in your system, i.e. in &lt;code&gt;/opt/env/&lt;/code&gt;. Create the directory and file, and paste in the following contents:&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="s2"&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;traefik&lt;/span&gt;&lt;span class="pi"&gt;:&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;traefik:2.2&lt;/span&gt;
    &lt;span class="na"&gt;ports&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;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./traefik.toml:/etc/traefik/traefik.toml:ro&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;traefik&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;public&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;public&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we define a pretty straight forward docker network and a service connected to that network. Note that the image version of &lt;em&gt;traefik&lt;/em&gt;, &lt;code&gt;2.2&lt;/code&gt; might be outdated when you are reading this article, but at the moment it is the newest version. Setting the &lt;code&gt;container_name&lt;/code&gt; is optional, but it is highly recommended to set the restart policy for &lt;em&gt;traefik&lt;/em&gt; as you want it up all the time. Of course you will also have to bind the service to the port 80. And the volume mounts, you need to bind the Docker socket to the service, since &lt;em&gt;traefik&lt;/em&gt; connects to it, listening for Docker container creations, and the &lt;code&gt;traefik.toml&lt;/code&gt; file:&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="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;[providers]&lt;/span&gt;
  &lt;span class="nn"&gt;[providers.docker]&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="nn"&gt;[log]&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="nn"&gt;[accessLog]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this simple configuration file we enable the access logging, turn the logging level up to debug, which you can lower later to &lt;em&gt;info&lt;/em&gt;, set the location of the Docker socket as the provider, and define an &lt;em&gt;entrypoint&lt;/em&gt;. This is it, you can start &lt;em&gt;traefik&lt;/em&gt; now by simply executing &lt;code&gt;docker-compose up -d&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Create the sample application
&lt;/h2&gt;

&lt;p&gt;You can skip this step if you wish to build your own application. And even though we are using a JavaScript application here, you can use whatever you want. &lt;/p&gt;

&lt;p&gt;Now, lets create the sample &lt;em&gt;expressjs&lt;/em&gt; application on your local machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;docker-deploy
&lt;span class="nb"&gt;cd &lt;/span&gt;docker-deploy
npm init
&lt;span class="c"&gt;# simply use all default values&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;express &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in that same directory create a new &lt;code&gt;index.js&lt;/code&gt; file with the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Example app listening at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quickly make sure it's working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And open &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt; in your browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy the application
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create the image
&lt;/h3&gt;

&lt;p&gt;To deploy your application we must first create the Docker image which will hold your application and from which a container will be created on the server later. First we create a &lt;code&gt;.dockerignore&lt;/code&gt; file, telling Docker which files to ignore when creating the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules
npm-debug.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will ignore the debug log, because we don't want it in the container, and our local &lt;strong&gt;node_modules&lt;/strong&gt; usually hold some development version files, and we want the container to be production ready, so we will install production ready modules at image creation. Now that we have this in place, lets create the &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:13.12-alpine3.10&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci &lt;span class="nt"&gt;--only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["node","index.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our sort of a blueprint for creating our own Docker image, where we tell Docker to create our image &lt;code&gt;FROM&lt;/code&gt; the &lt;strong&gt;node&lt;/strong&gt; base image, more specifically the &lt;strong&gt;13.12-alpine3.10&lt;/strong&gt; version of the &lt;strong&gt;node&lt;/strong&gt; Docker image. We must use the &lt;strong&gt;node&lt;/strong&gt; image in order to have tools like &lt;code&gt;npm&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt; available. Of course if your application is using other technology, you will want to use a different base image. However, it is recommended to use the &lt;strong&gt;alpine&lt;/strong&gt; version of the image if it is available. Alpine Linux is a small Linux distribution perfect for Docker, since it is very basic and small and reduces the size of your Docker images. &lt;/p&gt;

&lt;p&gt;Next we set the &lt;code&gt;WORKDIR&lt;/code&gt; to &lt;strong&gt;/usr/src/app&lt;/strong&gt; and &lt;code&gt;COPY&lt;/code&gt; any &lt;strong&gt;package*.json&lt;/strong&gt; files to that directory and &lt;em&gt;clean install&lt;/em&gt; the node modules. After that we copy the rest of our application to the image, which in our case will only copy the &lt;strong&gt;index.js&lt;/strong&gt; file, since the rest is ignored anyway.&lt;/p&gt;

&lt;p&gt;Finally we set the &lt;code&gt;EXPOSE&lt;/code&gt;d port to &lt;strong&gt;3000&lt;/strong&gt;, since our application will listening on port &lt;strong&gt;3000&lt;/strong&gt; inside the container, and we set the &lt;code&gt;ENTRYPOINT&lt;/code&gt;, which is basically a command that will be executed when the container is created using this image. &lt;/p&gt;

&lt;p&gt;Before we go on to create the image, head on over to the&lt;a href="https://hub.docker.com"&gt;Docker Hub&lt;/a&gt; and register, since we will be pushing the newly created image there. And while you're there, go ahead and create a new repository there.&lt;/p&gt;

&lt;p&gt;Now, let's create the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; your_dockerhub_name/express-sample &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a short while, a new image should be created. Now lets see if everything is ok by creating a new container with it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 your_dockerhub_name/express-sample
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again open &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt; in your browser. If you see the same result, this means we have successfully created a Docker image and a Docker container from it.&lt;/p&gt;

&lt;p&gt;Now we must push that image to Docker Hub, before proceeding to deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# if you have not yet logged in to Docker Hub from your shell do so now&lt;/span&gt;
docker login
docker tag your_dockerhub_name/express-sample:latest your_dockerhub_name/express-sample:1.0.0
docker push your_dockerhub_name/express-sample:1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we pushed the image, we have also tagged it with a new version, because our command above has created  a new image with the &lt;strong&gt;latest&lt;/strong&gt; tag by default.We could have specified this version there as well. This is an optional step,but recommended, since you want to tag images with versions if you are doing to deploy them, to avoid overwriting them and breaking something on the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying the image
&lt;/h3&gt;

&lt;p&gt;Now we have finally come to the deployment part. To execute the deployment, we will once again use the power of &lt;code&gt;docker-compose&lt;/code&gt; and create yet another  &lt;code&gt;docker-compose.yml&lt;/code&gt; file, not on the server, but locally, right there by your code:&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="s2"&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;express&lt;/span&gt;&lt;span class="pi"&gt;:&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;your_dockerhub_name/express-sample:1.0.0&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.http.routers.express-sample.rule=Host(`express-sample.yourdomain.com`)"&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.services.express-sample.loadbalancer.server.port=3000"&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;express-sample&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;env_public&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;env_public&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may also want to add this file to &lt;code&gt;.dockerignore&lt;/code&gt; since its of no use inside the container. To quickly walk through the file again, we again define a network, but this time the name is &lt;strong&gt;env_public&lt;/strong&gt;. &lt;strong&gt;public&lt;/strong&gt; comes from the network defined by the &lt;em&gt;traefik&lt;/em&gt; container but we must prepend it with &lt;strong&gt;env_&lt;/strong&gt;, since &lt;code&gt;docker-compose&lt;/code&gt; will by default prepend the created network with directory name of where the &lt;code&gt;docker-compose.yml&lt;/code&gt; is located. &lt;/p&gt;

&lt;p&gt;We assign this network to the service, set a restart policy, and optional container name. Ports do not need to be bound, since &lt;em&gt;traefik&lt;/em&gt; will handle the traffic. &lt;/p&gt;

&lt;p&gt;What we absolutely do need to define are the &lt;code&gt;labels&lt;/code&gt;, those tell &lt;em&gt;traefik&lt;/em&gt; which host will be routed to this service, and which port is in use. There are more rules that can be used for routing, but they are beyond the scope of this article and I invite you to check the wonderful &lt;a href="https://docs.traefik.io/v2.0/"&gt;traefik docs&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;All that there is now is to fire up the &lt;code&gt;docker-compose&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;DOCKER_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ssh://root@your-server-ip"&lt;/span&gt; docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By setting the &lt;code&gt;DOCKER_HOST&lt;/code&gt; variable we instruct &lt;code&gt;docker-compose&lt;/code&gt; to execute all commands through the SSH connection that it establishes. If all has gone well you should be able to view your deployed application by visiting &lt;a href="http://express-sample.yourdomain.com"&gt;http://express-sample.yourdomain.com&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Securing the application
&lt;/h2&gt;

&lt;p&gt;Since all of this is now served over the insecure HTTP connection it is time for us to secure it. To do this we must re-configure &lt;em&gt;traefik&lt;/em&gt; and instruct it to try and obtain a valid SSL certificate from &lt;a href="https://letsencrypt.org/"&gt;Lets Encrypt&lt;/a&gt; for every new registered container.&lt;/p&gt;

&lt;p&gt;First open up the &lt;code&gt;docker-compose.yml&lt;/code&gt; file on the server and edit the &lt;em&gt;traefik&lt;/em&gt; service:&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="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="na"&gt;traefik&lt;/span&gt;&lt;span class="pi"&gt;:&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;traefik:2.2&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.http.middlewares.redirect-to-https.redirectscheme.scheme=https"&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.global-redirect.rule=HostRegexp(`{host:.+}`)"&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.global-redirect.entrypoints=web"&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.global-redirect.middlewares=redirect-to-https"&lt;/span&gt;
    &lt;span class="na"&gt;ports&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;80:80"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we added a couple of rules to the labels to instruct &lt;em&gt;traefik&lt;/em&gt; to redirect all HTTP traffic straight to HTTPS, and bound the servers 443 port to the services 443 port for HTTPS traffic. Now, let's tell it to use Lets Encrypt, by editing the &lt;code&gt;traefik.toml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[entryPoints]
  [entryPoints.web]
    address = ":80"
  [entryPoints.web-secure]
    address = ":443"

[certificatesResolvers.myresolver.acme]
  email = "your@email.com"
  storage = "acme.json"
  [certificatesResolvers.myresolver.acme.httpChallenge]
    # used during the challenge
    entryPoint = "web"

# ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we added a new &lt;strong&gt;web-secure&lt;/strong&gt; &lt;em&gt;entrypoint&lt;/em&gt; and an acme certificate resolver which uses http challenges, that will be handled by the insecure &lt;strong&gt;web&lt;/strong&gt; &lt;em&gt;entrypoint&lt;/em&gt;. Now we need to recreate the &lt;em&gt;traefik&lt;/em&gt; service which can be done by simply running &lt;code&gt;docker-compose up -d&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;After the server reloads, add the following two labels to your applications &lt;code&gt;docker-compose.yml&lt;/code&gt; file:&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="c1"&gt;# ...&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.http.routers.express-sample.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.express-sample.tls.certresolver=myresolver"&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have instructed the service to use the &lt;strong&gt;myresolvre&lt;/strong&gt; certificate resolver, defined in the servers &lt;code&gt;traefik.toml&lt;/code&gt; configuration file, to handle SSL certificates for it. To apply this simply run the following command again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;DOCKER_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ssh://root@your-server-ip"&lt;/span&gt; docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker can make your life easier, be it locally for your development needs, or deployments, or,... but it is not the silver bullet. There are some considerations to make before you start using it, you should also take care with the containers, since there is a possibility that you hand your whole server to an attacker on a silver platter. But this is beyond the scope of this article.  However, I do invite you to educate yourself about Docker and containers in general further, as they are already playing a big part in software development and I sense that they will not go away any time soon.&lt;/p&gt;

&lt;p&gt;I hope you were able to get your application deployed, and you found this article helpful and informative. If you have run into issues, please, leave me a comment, and I will be more than happy to help!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>traefik</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
