<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Serzhan Akhmetov</title>
    <description>The latest articles on DEV Community by Serzhan Akhmetov (@siaarzh).</description>
    <link>https://dev.to/siaarzh</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%2F55491%2Fc25dcb2d-bfb0-41f5-88fc-aaa7d34626f4.png</url>
      <title>DEV Community: Serzhan Akhmetov</title>
      <link>https://dev.to/siaarzh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/siaarzh"/>
    <language>en</language>
    <item>
      <title>InfluxDB 2.0 - Quickly Enabling TLS Encryption with Traefik</title>
      <dc:creator>Serzhan Akhmetov</dc:creator>
      <pubDate>Wed, 24 Mar 2021 11:25:34 +0000</pubDate>
      <link>https://dev.to/siaarzh/influxdb-2-0-quickly-enabling-tls-encryption-with-traefik-17ni</link>
      <guid>https://dev.to/siaarzh/influxdb-2-0-quickly-enabling-tls-encryption-with-traefik-17ni</guid>
      <description>&lt;p&gt;Jumpstart your influxdb stack with automated TLS certificate management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use case
&lt;/h2&gt;

&lt;p&gt;So you're running a bunch of IoT/Finance or Cryptocurrency services with Docker or Kubernetes and decided to use that shiny InfluxDB 2.0 dashboard in &lt;em&gt;production&lt;/em&gt;. Heck, maybe even play around with the &lt;a href="https://docs.influxdata.com/influxdb/cloud/reference/flux/stdlib/" rel="noopener noreferrer"&gt;flux&lt;/a&gt; API too - for those &lt;a href="https://www.influxdata.com/blog/top-5-hurdles-for-flux-beginners-and-resources-for-learning-to-use-flux/" rel="noopener noreferrer"&gt;extra fancy&lt;/a&gt; queries.&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%2Fwww.influxdata.com%2Fwp-content%2Fuploads%2Fnext-gen-data-exploration-analytics-influxdb-2.0.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%2Fwww.influxdata.com%2Fwp-content%2Fuploads%2Fnext-gen-data-exploration-analytics-influxdb-2.0.png" alt="infludb 2.0 dashboard"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Who needs Grafana?)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Obviously, at this point you'll need to secure the traffic between your web application and your server (plus the microservices). This is exactly what &lt;a href="https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/" rel="noopener noreferrer"&gt;TLS&lt;/a&gt; encryption does - you know, adds that &lt;code&gt;https://&lt;/code&gt; you see everywhere.&lt;/p&gt;
&lt;h2&gt;
  
  
  What you will need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You are running running your backend in Docker containers. This is either Docker, Docker Swarm or Kubernetes, or any other vendor that runs docker containers defined thru a YAML compose file or similar.&lt;/li&gt;
&lt;li&gt;You are either running or planning to run &lt;a href="https://doc.traefik.io/traefik/" rel="noopener noreferrer"&gt;Traefik&lt;/a&gt; as your proxy.&lt;/li&gt;
&lt;li&gt;You own a domain name and can manage its DNS records.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your DNS Service allows &lt;a href="https://letsencrypt.org/docs/challenge-types/" rel="noopener noreferrer"&gt;DNS-01 ACME Challenge&lt;/a&gt; to generate wildcard TLS certificates.&lt;/li&gt;
&lt;li&gt;You have the &lt;a href="https://doc.traefik.io/traefik/https/acme/#providers" rel="noopener noreferrer"&gt;necessary credentials&lt;/a&gt; to access your DNS Service API.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Instructions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If you opt for the simpler &lt;a href="https://letsencrypt.org/docs/challenge-types/#http-01-challenge" rel="noopener noreferrer"&gt;HTTP-01 ACME Challenge&lt;/a&gt;, make sure you &lt;strong&gt;create all the necessary DNS records beforehand&lt;/strong&gt; (i.e. create &lt;em&gt;A&lt;/em&gt; or &lt;em&gt;CNAME&lt;/em&gt; records), including any wildcard subdomain names. Having said that, if your &lt;em&gt;really need&lt;/em&gt; wildcard certificates for subdomains, you should use the DNS-01 ACME Challenge.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;CAUTION: There are &lt;a href="https://letsencrypt.org/docs/challenge-types/" rel="noopener noreferrer"&gt;pros and cons&lt;/a&gt; for using each type of challenge. Use industry best practices and your own judgement when deciding which method to use for your project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Below is an example of typical DNS record table for a &lt;em&gt;HTTP-01 Challenge&lt;/em&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Hostname&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;TTL (seconds)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;example.com&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;directs to&lt;/em&gt; 203.0.113.123&lt;/td&gt;
&lt;td&gt;3600&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;traefik.example.com&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;directs to&lt;/em&gt; 203.0.113.123&lt;/td&gt;
&lt;td&gt;3600&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;influxdb.example.com&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;is an alias of&lt;/em&gt; example.com&lt;/td&gt;
&lt;td&gt;43200&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Our main domain name is &lt;em&gt;example.com&lt;/em&gt; and we are running two services that will be exposed via subdomain names &lt;em&gt;traefik.*&lt;/em&gt; and &lt;em&gt;influxdb.*&lt;/em&gt;. If you have more services you want accessible via subdomain, now's the time to add them here. TTL settings are irrelevant for this tutorial, so feel free to &lt;a href="https://en.wikipedia.org/wiki/Time_to_live" rel="noopener noreferrer"&gt;dive deeper&lt;/a&gt; into DNS on your own time.&lt;/p&gt;

&lt;p&gt;And here is the same table when attempting the &lt;em&gt;DNS-01 Challenge&lt;/em&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Hostname&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;TTL (seconds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;*.example.com&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;directs to&lt;/em&gt; 203.0.113.123&lt;/td&gt;
&lt;td&gt;3600&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;example.com&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;directs to&lt;/em&gt; 203.0.113.123&lt;/td&gt;
&lt;td&gt;3600&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will store our certificates in a bind mounted &lt;code&gt;acme.json&lt;/code&gt;. Therefore, appropriate permissions need to be set beforehand for Traefik to access (accept it as secure) this file:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;acme.json&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;chmod &lt;/span&gt;600 acme.json
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;(Re)define your InfluxDB container by applying the following &lt;code&gt;labels&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;For Docker (using Compose):&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="s"&gt;my-influxdb&lt;/span&gt;&lt;span class="err"&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;influxdb:2.0&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# traefik router settings&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.my-influxdb.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Host(`influxdb.example.com`)"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.my-influxdb.tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.my-influxdb.tls.certresolver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;myresolver"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.my-influxdb.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websecure"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;For Docker Swarm:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="s"&gt;my-influxdb&lt;/span&gt;&lt;span class="err"&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;influxdb:2.0&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# traefik router settings&lt;/span&gt;
        &lt;span class="na"&gt;traefik.http.routers.my-influxdb.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Host(`influxdb.example.com`)"&lt;/span&gt;
        &lt;span class="na"&gt;traefik.http.routers.my-influxdb.tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
        &lt;span class="na"&gt;traefik.http.routers.my-influxdb.tls.certresolver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;myresolver"&lt;/span&gt;
        &lt;span class="na"&gt;traefik.http.routers.my-influxdb.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websecure"&lt;/span&gt;

        &lt;span class="c1"&gt;# traefik service settings&lt;/span&gt;
        &lt;span class="na"&gt;traefik.http.services.my-influxdb.loadbalancer.server.port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8086"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



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

&lt;blockquote&gt;
&lt;p&gt;Note: for Swarm, Traefik requires you explicitly define at least one port the service is running on, even it if has no listening ports. (see &lt;a href="https://doc.traefik.io/traefik/providers/docker/#port-detection_1" rel="noopener noreferrer"&gt;Port Detection&lt;/a&gt; - Traefik Docs)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don't forget to deploy this new configuration using &lt;code&gt;docker compose up&lt;/code&gt; or &lt;code&gt;docker stack deploy -c docker-compose.yml &amp;lt;stack_name&amp;gt;&lt;/code&gt;.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Let's now add the Traefik container to your compose file.&lt;/p&gt;

&lt;p&gt;Below are 4 different ways to do this - depending on the combination of orchestrator and type of ACME Challenge.&lt;/p&gt;

&lt;p&gt;In all cases, we are using the &lt;em&gt;staging&lt;/em&gt; Let's Encrypt server - this helps us to generate new certificates in case we mess up much faster since the &lt;a href="https://community.letsencrypt.org/t/staging-endpoint-for-acme-v2/49605" rel="noopener noreferrer"&gt;rate limit is much higher&lt;/a&gt;. Once everything works, simply delete the line defining &lt;code&gt;certificateresolvers.myresolver.acme.caserver&lt;/code&gt; and redeploy your Traefik container.&lt;/p&gt;

&lt;p&gt;In addition, the DNS server I'm using for the DNS-01 Challenge is &lt;code&gt;digitalocean&lt;/code&gt;, which requires I define a &lt;code&gt;DO_AUTH_TOKEN&lt;/code&gt;. Depending on your DNS provider, you will need to &lt;a href="https://doc.traefik.io/traefik/https/acme/#providers" rel="noopener noreferrer"&gt;define different credentials&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;For Docker (Compose) + HTTP-01 Challenge:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik:v2.0.0"&lt;/span&gt;
  &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--entrypoints.web.address=:80&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--entrypoints.websecure.address=:443&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--providers.docker&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--api&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.email=sample@email.com&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.storage=acme.json&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="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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock:ro"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./acme.json:/acme.json"&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Traefik Dashboard&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.traefik.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Host(`traefik.sample.com`)"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.traefik.service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api@internal"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.traefik.tls.certresolver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;myresolver"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.traefik.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websecure"&lt;/span&gt;

    &lt;span class="c1"&gt;# Redirect to HTTPS&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.middlewares.redirect-to-https.redirectscheme.scheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.http-catchall.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hostregexp(`{host:.+}`)"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.http-catchall.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.http-catchall.middlewares&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redirect-to-https"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For Docker (Compose) + DNS-01 Challenge:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik:v2.0.0"&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;DO_AUTH_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0f923jf..."&lt;/span&gt;
  &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--entrypoints.web.address=:80&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--entrypoints.websecure.address=:443&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--providers.docker&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--api&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.dnschallenge.provider=digitalocean&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.dnschallenge.delaybeforecheck=0&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.email=sample@email.com&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.storage=acme.json&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="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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock:ro"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./acme.json:/acme.json"&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Traefik Dashboard&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.traefik.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Host(`traefik.sample.com`)"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.traefik.service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api@internal"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.traefik.tls.certresolver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;myresolver"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.traefik.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websecure"&lt;/span&gt;

    &lt;span class="c1"&gt;# Redirect to HTTPS&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.middlewares.redirect-to-https.redirectscheme.scheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.http-catchall.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hostregexp(`{host:.+}`)"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.http-catchall.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web"&lt;/span&gt;
    &lt;span class="na"&gt;traefik.http.routers.http-catchall.middlewares&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redirect-to-https"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For Docker Swarm + HTTP-01 Challenge:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik:v2.0.0"&lt;/span&gt;
  &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--entrypoints.web.address=:80&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--entrypoints.websecure.address=:443&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--providers.docker&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--api&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.email=sample@email.com&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.storage=acme.json&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="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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock:ro"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./acme.json:/acme.json"&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Traefik Dashboard&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.traefik.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Host(`traefik.sample.com`)"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.traefik.service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api@internal"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.traefik.tls.certresolver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;myresolver"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.traefik.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websecure"&lt;/span&gt;

      &lt;span class="c1"&gt;# Redirect to HTTPS&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.middlewares.redirect-to-https.redirectscheme.scheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.http-catchall.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hostregexp(`{host:.+}`)"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.http-catchall.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.http-catchall.middlewares&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redirect-to-https"&lt;/span&gt;

      &lt;span class="c1"&gt;# service definitions&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.services.traefik.loadbalancer.server.port&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"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.services.traefik.loadbalancer.server.port&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"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For Docker Swarm + DNS-01 Challenge:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik:v2.0.0"&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;DO_AUTH_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0f923jf..."&lt;/span&gt;
  &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--entrypoints.web.address=:80&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--entrypoints.websecure.address=:443&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--providers.docker&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--api&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.dnschallenge.provider=digitalocean&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.dnschallenge.delaybeforecheck=0&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.email=sample@email.com&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.storage=acme.json&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="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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock:ro"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./acme.json:/acme.json"&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Traefik Dashboard&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.traefik.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Host(`traefik.sample.com`)"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.traefik.service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api@internal"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.traefik.tls.certresolver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;myresolver"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.traefik.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;websecure"&lt;/span&gt;

      &lt;span class="c1"&gt;# Redirect to HTTPS&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.middlewares.redirect-to-https.redirectscheme.scheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.http-catchall.rule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hostregexp(`{host:.+}`)"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.http-catchall.entrypoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;web"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.routers.http-catchall.middlewares&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redirect-to-https"&lt;/span&gt;

      &lt;span class="c1"&gt;# service definitions&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.services.traefik.loadbalancer.server.port&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"&lt;/span&gt;
      &lt;span class="na"&gt;traefik.http.services.traefik.loadbalancer.server.port&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"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Again, don't forget to deploy this new service and after a couple of seconds you should be up and running.&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Switch to Production
&lt;/h2&gt;

&lt;p&gt;As mentioned in step 4, you'll be using the &lt;em&gt;staging&lt;/em&gt; Let's Encrypt server for certificate generation. Thus, your certificate won't be trusted by the browser yet:&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%2For09mi6ngfmqfc929gt7.jpg" 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%2For09mi6ngfmqfc929gt7.jpg" alt="before TLS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Easy fix: as soon as everything works as expected with the &lt;em&gt;invalid&lt;/em&gt; certificate simply delete the line defining &lt;code&gt;certificateresolvers.myresolver.acme.caserver&lt;/code&gt; and redeploy your Traefik container.&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%2F1fuqkjpsjfj7ga4okchu.jpg" 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%2F1fuqkjpsjfj7ga4okchu.jpg" alt="After TLS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Still confused?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://snyk.io/blog/10-reasons-to-use-https/" rel="noopener noreferrer"&gt;Why use HTTPS?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/" rel="noopener noreferrer"&gt;What is TLS&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>docker</category>
      <category>security</category>
      <category>microservices</category>
      <category>devops</category>
    </item>
    <item>
      <title>Start All Your DEV Programs in one Shortcut on Windows 10</title>
      <dc:creator>Serzhan Akhmetov</dc:creator>
      <pubDate>Fri, 29 Nov 2019 11:35:03 +0000</pubDate>
      <link>https://dev.to/siaarzh/start-all-your-dev-programs-in-one-shortcut-on-windows-10-2feo</link>
      <guid>https://dev.to/siaarzh/start-all-your-dev-programs-in-one-shortcut-on-windows-10-2feo</guid>
      <description>&lt;p&gt;If you're like me - god help us - then you have this constant itch to automate every single part of your existence. The following two scripts will give a blueprint for creating your own start-my-dev-environment scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Launching apps in batch file
&lt;/h3&gt;

&lt;p&gt;We'll be launching 3 programs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spotify&lt;/li&gt;
&lt;li&gt;Chrome&lt;/li&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;additionally, we'll start an OpenVPN client connection.&lt;/p&gt;

&lt;p&gt;You'll want to create a batch file like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight batchfile"&gt;&lt;code&gt;@ECHO &lt;span class="kd"&gt;OFF&lt;/span&gt;
&lt;span class="nb"&gt;tasklist&lt;/span&gt; &lt;span class="na"&gt;/FI &lt;/span&gt;&lt;span class="s2"&gt;"IMAGENAME eq Spotify.exe"&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;NUL&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;find&lt;/span&gt; &lt;span class="na"&gt;/I /N &lt;/span&gt;&lt;span class="s2"&gt;"Spotify.exe"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;NUL&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="kd"&gt;NOT&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;%ERRORLEVEL%&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="nb"&gt;start&lt;/span&gt; &lt;span class="s2"&gt;"spotify_play_lofi-playlist.vbs"&lt;/span&gt; &lt;span class="s2"&gt;"C:\Users\&amp;lt;username&amp;gt;\Documents\batch_scripts\spotify_play_lofi-playlist.vbs"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="kd"&gt;TIMEOUT&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;

&lt;span class="nb"&gt;tasklist&lt;/span&gt; &lt;span class="na"&gt;/FI &lt;/span&gt;&lt;span class="s2"&gt;"IMAGENAME eq chrome.exe"&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;NUL&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;find&lt;/span&gt; &lt;span class="na"&gt;/I /N &lt;/span&gt;&lt;span class="s2"&gt;"chrome.exe"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;NUL&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="kd"&gt;NOT&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;%ERRORLEVEL%&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="nb"&gt;start&lt;/span&gt; &lt;span class="s2"&gt;"chrome.exe"&lt;/span&gt; &lt;span class="s2"&gt;"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"&lt;/span&gt;

&lt;span class="nb"&gt;start&lt;/span&gt; &lt;span class="s2"&gt;" "&lt;/span&gt; &lt;span class="s2"&gt;"C:\Program Files\OpenVPN\bin\openvpn-gui.exe"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="na"&gt;-command &lt;/span&gt;&lt;span class="kd"&gt;disconnect_all&lt;/span&gt;
&lt;span class="nb"&gt;start&lt;/span&gt; &lt;span class="s2"&gt;"openvpn-gui.exe"&lt;/span&gt; &lt;span class="s2"&gt;"C:\Program Files\OpenVPN\bin\openvpn-gui.exe"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="na"&gt;-connect &lt;/span&gt;&lt;span class="kd"&gt;my_conf&lt;/span&gt;.ovpn

&lt;span class="nb"&gt;tasklist&lt;/span&gt; &lt;span class="na"&gt;/FI &lt;/span&gt;&lt;span class="s2"&gt;"IMAGENAME eq Code.exe"&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;NUL&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;find&lt;/span&gt; &lt;span class="na"&gt;/I /N &lt;/span&gt;&lt;span class="s2"&gt;"Code.exe"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;NUL&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="kd"&gt;NOT&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;%ERRORLEVEL%&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="nb"&gt;start&lt;/span&gt; &lt;span class="s2"&gt;"Code"&lt;/span&gt; &lt;span class="s2"&gt;"C:\Users\&amp;lt;username&amp;gt;\AppData\Local\Programs\Microsoft VS Code\Code.exe"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, the &lt;code&gt;tasklist&lt;/code&gt; commands are there to make sure we don't run a second instance of an app. For OpenVPN, it's easier to just reconnect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Spotify Autoplay Script
&lt;/h3&gt;

&lt;p&gt;The spotify VB script is there to launch Spotify and start a playlist in shuffle mode. Save it in the same folder as your batch script, for safekeeping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight vb"&gt;&lt;code&gt;&lt;span class="k"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;WshShell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WScript.Shell"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Comandline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"C:\Users\&amp;lt;username&amp;gt;\AppData\Roaming\Spotify\Spotify.exe"&lt;/span&gt;
&lt;span class="n"&gt;WScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="n"&gt;CreateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WScript.Shell"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spotify:playlist:74sUjcvpGfdOvCHvgzNEDO"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;WScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;
&lt;span class="n"&gt;WshShell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SendKeys&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;
&lt;span class="n"&gt;WScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="n"&gt;WshShell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SendKeys&lt;/span&gt; &lt;span class="s"&gt;"^{RIGHT}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can get the playlist URI by right-clicking the playlist &amp;gt; Share &amp;gt; Copy Spotify URI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Shortcut Placement
&lt;/h3&gt;

&lt;p&gt;This is simple, create a shortcut to your batch file and place it in your Start Menu Programs folder (&lt;code&gt;%ProgramData%\Microsoft\Windows\Start Menu\Programs&lt;/code&gt;). You may then move it to the quick-launch bar if you wish.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.spotify.com/t5/Desktop-Windows/Is-there-a-command-to-play-a-playlist-using-command-line/m-p/1185322"&gt;Spotify Forums&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://henryreith.co/open-multiple-programs-at-once-on-windows/"&gt;Opening multiple programs on Windows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>automation</category>
    </item>
    <item>
      <title>VS Code with Python in Docker Quickstart</title>
      <dc:creator>Serzhan Akhmetov</dc:creator>
      <pubDate>Tue, 25 Jun 2019 06:44:38 +0000</pubDate>
      <link>https://dev.to/siaarzh/vs-code-with-python-in-docker-quickstart-3ph4</link>
      <guid>https://dev.to/siaarzh/vs-code-with-python-in-docker-quickstart-3ph4</guid>
      <description>&lt;p&gt;You love VS Code? Get ready to love it even more!&lt;/p&gt;

&lt;p&gt;Recently, a new extension pack has come out from the good folks at Microsoft that enables remote development! Not only SSH, but also using local containers with either single containers or multiple containers with docker-compose!&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://code.visualstudio.com/"&gt;VS Code&lt;/a&gt; and the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack"&gt;Remote Development&lt;/a&gt; extension pack&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start a new project by opening a new directory with VS Code Insiders and create a &lt;em&gt;requirements.txt&lt;/em&gt; file with the Python packages you wish to have, e.g.:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;django==2.2.2
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ctrl+shift+p and start typing "remdev", select "Remote-Containers: Add Dev Container Configuration Files..."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Search for "pypo" and select "Python 3 &amp;amp; PostgreSQL" as your environmet. This will create a &lt;em&gt;.devcontainer&lt;/em&gt; folder with the files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;devcontainer.json&lt;/li&gt;
&lt;li&gt;docker-compose.yml&lt;/li&gt;
&lt;li&gt;Dockerfile&lt;/li&gt;
&lt;li&gt;noop.txt&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ctrl+shift+p and start typing "rerefo", select "Remote-Containers: Reopen Folder in Container"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start coding ☕💻&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  A note on opening ports
&lt;/h3&gt;

&lt;p&gt;So how do you open a port to your container? Easy! VS Code already knows which ports are open in your container.&lt;/p&gt;

&lt;p&gt;Say you started your server with &lt;code&gt;python manage.py runserver&lt;/code&gt;, which would open a port on 127.0.0.1:8000 in your container. VS Code is aware of this and will give you the option to forward your system ports to that port.&lt;/p&gt;

&lt;p&gt;Press ctrl+shift+p, search "port" and select "Remote-Containers: Forward Port from Container...". A list of open ports will come up, select port 8000.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/siaarzh/python-vscode-starter"&gt;https://github.com/siaarzh/python-vscode-starter&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/docs/remote/containers"&gt;Container Remote Development&lt;/a&gt; with VS Code&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/2.2/intro/tutorial01/"&gt;Django Tutorial part 1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>vscode</category>
      <category>python</category>
    </item>
  </channel>
</rss>
