<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.7.3">Jekyll</generator><link href="https://bengtssondd.it/feed.xml" rel="self" type="application/atom+xml" /><link href="https://bengtssondd.it/" rel="alternate" type="text/html" hreflang="en" /><updated>2022-02-20T20:28:09+01:00</updated><id>https://bengtssondd.it/</id><title type="html">Bengtsson Driven Development</title><subtitle>Bengtsson Driven Development is a plethora of thoughts, ideas and adventures into the world of DevOps.
</subtitle><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><entry><title type="html">When a health check makes its host unhealthy</title><link href="https://bengtssondd.it/devops/containerization/docker/debugging/2020/04/13/When-a-healthcheck-makes-the-host-unhealthy/" rel="alternate" type="text/html" title="When a health check makes its host unhealthy" /><published>2020-04-13T00:00:00+02:00</published><updated>2020-04-13T00:00:00+02:00</updated><id>https://bengtssondd.it/devops/containerization/docker/debugging/2020/04/13/When-a-healthcheck-makes-the-host-unhealthy</id><content type="html" xml:base="https://bengtssondd.it/devops/containerization/docker/debugging/2020/04/13/When-a-healthcheck-makes-the-host-unhealthy/">&lt;p&gt;Leading up to this post, I’ve been fiddling with my &lt;a href=&quot;https://bengtssondd.it/anonymity/privacy/security/2020/04/02/HushDNS-can-I-please-get-me-some-DNS-privacy/&quot; class=&quot;no-mark-external&quot;&gt;&lt;strong&gt;HushDNS&lt;/strong&gt;&lt;/a&gt; project for quite some time. In the words of the project. It’s all about:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;....The DNS queries your system/browser and whatever software you use execute, leave you exposed to tracking by
prying outsiders. Leaving you with little privacy in regards to e.g. which websites you visit. This is so. 
Because the data (requests and responses) involved when using DNS, is in the clear.
Meaning --&amp;gt; everybody can determine the websites and other Internet related services you use.
Furthermore, a DNS query you execute can be mingled with. So you could end up on a website
controlled be ill intended people. Rather on the one YOU intended.

Luckily, it's possible to seriously combat the issues that DNS have......
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Early April 2020 I finally got everything to work. From a functionality point of view. However, after a couple of days, DNS queries came to a halt. Either taking a very long time to complete, or not being answered at all. Worse was it, that the host on which &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Pi-hole&lt;/code&gt; is running, came to a halt. So I put on my superman debug cape and pursued the issue.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/triedRestarting.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Come with me. Follow my debug tracks to see what I found.&lt;/p&gt;

&lt;h2 id=&quot;initial-brute-force-debugging&quot;&gt;Initial brute-force debugging&lt;/h2&gt;

&lt;p&gt;So yes, I must admit, the first action I took was restarting the box hosting the &lt;strong&gt;HushDNS&lt;/strong&gt; containers. It did help. However, only temporarily. Not really a surprise though. Excuse me my laziness. Just how it is at times :innocent:.&lt;/p&gt;

&lt;p&gt;I quickly came to the conclusion that restarting the host was not going to be a permanent solution. I had to go deeper, way deeper.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/sleepingTomorrowLoad.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;spearhead-debugging&quot;&gt;Spearhead debugging&lt;/h2&gt;

&lt;p&gt;The next time it happened, I was lucky enough to already be &lt;em&gt;SSH&lt;/em&gt; connected to the container host. So I did my cmd fu. Calling upon &lt;code class=&quot;highlighter-rouge&quot;&gt;top&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;ps&lt;/code&gt; and the like. To my frustration the commands :collision: right in my face. With a very worrying fault: &lt;code class=&quot;highlighter-rouge&quot;&gt;fork: Resource temporarily unavailable&lt;/code&gt;. This usually means that a resource limit on &lt;code class=&quot;highlighter-rouge&quot;&gt;Linux&lt;/code&gt; has been reached.&lt;/p&gt;

&lt;p&gt;As I couldn’t really interact with the host because of its rotten state. I had to restart it again. Hopefully for the last time (related to this issue :wink:) :pray:.&lt;/p&gt;

&lt;p&gt;With the host up again. I SSH’ed on to it and decided to do some monitoring to determine what could be hogging resources in such an aggressive way. Furthermore, I went over what recent changes I had made to the host. They where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Updating the OS of my &lt;code class=&quot;highlighter-rouge&quot;&gt;QNAP&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Setting up &lt;strong&gt;HushDNS&lt;/strong&gt; related containers
    &lt;ul&gt;
      &lt;li&gt;Pi-hole had been running for a long time already&lt;/li&gt;
      &lt;li&gt;the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; container is running on a host outside my LAN&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; was rather new and had its configuration changed several times&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It could be some bug in the newest &lt;code class=&quot;highlighter-rouge&quot;&gt;QNAP&lt;/code&gt; OS release. I categorized that as the less likely of the two. I therefore went with looking at the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; container. But how is that container resource exhausting the host?&lt;/p&gt;

&lt;h3 id=&quot;determining-resource-limit-values&quot;&gt;Determining resource limit values&lt;/h3&gt;

&lt;p&gt;On &lt;code class=&quot;highlighter-rouge&quot;&gt;Linux&lt;/code&gt; we do that with the &lt;a href=&quot;https://ss64.com/bash/ulimit.html&quot; class=&quot;no-mark-external&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ulimit&lt;/code&gt;&lt;/a&gt; cmd. E.g. execute:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ulimit -a&lt;/code&gt; to eye-gaze values for all the different types of resource limits that can be configured&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ulimit -u&lt;/code&gt; to determine the value of the &lt;code class=&quot;highlighter-rouge&quot;&gt;max user processes&lt;/code&gt; setting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the &lt;code class=&quot;highlighter-rouge&quot;&gt;fork: Resource temporarily unavailable&lt;/code&gt; error is often an issue of too many open files by an user or a max number of running  processes met for a user, I had a look at the values of the &lt;code class=&quot;highlighter-rouge&quot;&gt;max user processes&lt;/code&gt;- and the &lt;code class=&quot;highlighter-rouge&quot;&gt;open files&lt;/code&gt; setting.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;max user processes&lt;/code&gt; is at &lt;em&gt;31335&lt;/em&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;open files&lt;/code&gt; at &lt;em&gt;1024&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The brute-force way of fixing this would be to set these two to unlimited. But, that would be a peasant solution and would open us up to a &lt;a href=&quot;https://en.wikipedia.org/wiki/Fork_bomb&quot; class=&quot;no-mark-external&quot;&gt;fork bomb attack&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;determining-the-cause-of-the-resource-exhaustion&quot;&gt;Determining the cause of the resource exhaustion&lt;/h3&gt;

&lt;p&gt;Next up was to determine the current value of &lt;code class=&quot;highlighter-rouge&quot;&gt;max user processes&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;open files&lt;/code&gt;. What to do? Hmmmm let’s pull out the &lt;code class=&quot;highlighter-rouge&quot;&gt;top&lt;/code&gt; cmd again and fire it of on the host.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/changeOfCMD.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Don’t tell me that you would honestly have any better idea at this point :punch: :stuck_out_tongue_winking_eye:. &lt;code class=&quot;highlighter-rouge&quot;&gt;top&lt;/code&gt; is as warm and fuzzy as they come. So let’s hold on to it and squeeze it tightly :older_man:.&lt;/p&gt;

&lt;p&gt;Sooooo what did &lt;code class=&quot;highlighter-rouge&quot;&gt;top&lt;/code&gt; tell us? :point_down:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;.....
   PID PPID User     Stat                     Command
   67     1 root     Z        0   0%   0   0% [drill]
   60     1 root     Z        0   0%   2   0% [drill]
   74     1 root     Z        0   0%   3   0% [drill]
   89     1 root     Z        0   0%   3   0% [drill]
   97     1 root     Z        0   0%   1   0% [drill]
  104     1 root     Z        0   0%   3   0% [drill]
  110     1 root     Z        0   0%   3   0% [drill]
  117     1 root     Z        0   0%   3   0% [drill]
   47     1 root     Z        0   0%   3   0% [drill]
  131     1 root     Z        0   0%   2   0% [drill]
  138     1 root     Z        0   0%   2   0% [drill]
  145     1 root     Z        0   0%   0   0% [drill]
  152     1 root     Z        0   0%   1   0% [drill]
  159     1 root     Z        0   0%   0   0% [drill]
  166     1 root     Z        0   0%   0   0% [drill]
  173     1 root     Z        0   0%   2   0% [drill]
  180     1 root     Z        0   0%   2   0% [drill]
  189     1 root     Z        0   0%   3   0% [drill]
   32     1 root     Z        0   0%   1   0% [drill]
  203     1 root     Z        0   0%   2   0% [drill]
  209     1 root     Z        0   0%   1   0% [drill]
  216     1 root     Z        0   0%   0   0% [drill]
  223     1 root     Z        0   0%   1   0% [drill]
  230     1 root     Z        0   0%   0   0% [drill]
  237     1 root     Z        0   0%   2   0% [drill]
  244     1 root     Z        0   0%   0   0% [drill]
  251     1 root     Z        0   0%   3   0% [drill]
  258     1 root     Z        0   0%   0   0% [drill]
  265     1 root     Z        0   0%   1   0% [drill]
  272     1 root     Z        0   0%   1   0% [drill]
  279     1 root     Z        0   0%   2   0% [drill]
  286     1 root     Z        0   0%   0   0% [drill]
  292     1 root     Z        0   0%   0   0% [drill]
  299     1 root     Z        0   0%   2   0% [drill]
   40     1 root     Z        0   0%   3   0% [drill]
  313     1 root     Z        0   0%   1   0% [drill]
  321     1 root     Z        0   0%   3   0% [drill]
  328     1 root     Z        0   0%   1   0% [drill]
  335     1 root     Z        0   0%   1   0% [drill]
  342     1 root     Z        0   0%   3   0% [drill]
  349     1 root     Z        0   0%   0   0% [drill]
.....
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;N.B. The above output is a snippet of the output from &lt;code class=&quot;highlighter-rouge&quot;&gt;top&lt;/code&gt;. And for good measure I changed the username in the output to the generic value of &lt;code class=&quot;highlighter-rouge&quot;&gt;root&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oh wow! Holy hamster :hamster:. That looks bad bad not good! Something is firing of the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; command again and again for some reason. We can live with that, if &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; is actually killed. But its not and therefore just keeps hanging. This is likely to be the culprit of the resource exhaustion state that the hosts ends up in.&lt;/p&gt;

&lt;p&gt;Let’s go after the many hanging &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; commands and save looking at this potentially being an &lt;code class=&quot;highlighter-rouge&quot;&gt;open files&lt;/code&gt; limit reached issue for later.&lt;/p&gt;

&lt;p&gt;If we take a look at the output of the &lt;code class=&quot;highlighter-rouge&quot;&gt;top&lt;/code&gt; command again, focussing specifically on the &lt;code class=&quot;highlighter-rouge&quot;&gt;stat&lt;/code&gt; column we see that it has a value of &lt;strong&gt;Z&lt;/strong&gt; for all of the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; commands. This stands for &lt;em&gt;zombie&lt;/em&gt; and in essence means that the process is dead, it has done its job and what’s left is the structure describing it on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Linux&lt;/code&gt; kernel. It is in &lt;em&gt;zombie&lt;/em&gt; mode because it awaits its parent process to pick up its exit code.
Based on that we can conclude that the exit code of the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; command is not picked up. Or it is, but the process is for whatever reason not killed.
Duly note that a &lt;em&gt;zombie&lt;/em&gt; process have released its recourses. However, it still remains in the system process table and therefore counts against the &lt;code class=&quot;highlighter-rouge&quot;&gt;max user processes&lt;/code&gt; limit.&lt;/p&gt;

&lt;p&gt;So what is invoking all those &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; commands? Let’s use one of my other favorite old timer &lt;code class=&quot;highlighter-rouge&quot;&gt;Linux&lt;/code&gt; commands. Namely &lt;code class=&quot;highlighter-rouge&quot;&gt;ps&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;ps -efl -o pid,ppid,user,comm | grep drill&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here is the output (a sample):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;.....
 5453 24102 root    drill
 7012 24102 root    drill
16851 24102 root    drill
24217 24102 root    drill
.....
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With the &lt;code class=&quot;highlighter-rouge&quot;&gt;-o&lt;/code&gt; parameter we defined the columns that the &lt;code class=&quot;highlighter-rouge&quot;&gt;ps&lt;/code&gt; command should output. The column to take note of is the second column. Namely the &lt;code class=&quot;highlighter-rouge&quot;&gt;ppid&lt;/code&gt; column. &lt;code class=&quot;highlighter-rouge&quot;&gt;ppid&lt;/code&gt; stands for &lt;em&gt;parent id&lt;/em&gt;. So there you have it, the &lt;code class=&quot;highlighter-rouge&quot;&gt;pid&lt;/code&gt; of the process that invoked the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Next step. Gathering info on the parent process. We simply do that by executing: &lt;code class=&quot;highlighter-rouge&quot;&gt;cat /proc/{pid}/cmdline&lt;/code&gt;, in this case replace &lt;code class=&quot;highlighter-rouge&quot;&gt;{pid}&lt;/code&gt; with &lt;em&gt;24102&lt;/em&gt;. The result: &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy-config/config/dnscrypt-proxy.toml&lt;/code&gt;. For a reason unknown to me, all whitespace have been stripped from the output. I guess its because the &lt;code class=&quot;highlighter-rouge&quot;&gt;cat&lt;/code&gt; command cannot read the special separator character of the content in the process &lt;code class=&quot;highlighter-rouge&quot;&gt;cmdline&lt;/code&gt; file. Because, if we execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;vi /proc/{pid}/cmdline&lt;/code&gt; we see that the content of the &lt;code class=&quot;highlighter-rouge&quot;&gt;cmdline&lt;/code&gt; file is &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy^@-config^@/config/dnscrypt-proxy.toml^@&lt;/code&gt;. So whitespace is marked with a &lt;code class=&quot;highlighter-rouge&quot;&gt;^@&lt;/code&gt; character sequence. With this knowledge obtained we can conclude that the actual &lt;code class=&quot;highlighter-rouge&quot;&gt;cmdline&lt;/code&gt; of the parent process is: &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy -config /config/dnscrypt-proxy.toml&lt;/code&gt;. So :bow: …. there you have it. It’s the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; that invokes all these &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; commands.&lt;/p&gt;

&lt;h3 id=&quot;solving-the-cause-of-the-resource-exhaustion&quot;&gt;Solving the cause of the resource exhaustion&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; runs in a container on my &lt;code class=&quot;highlighter-rouge&quot;&gt;QNAP&lt;/code&gt;. In order to determine what is calling the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; command I had a look at its &lt;code class=&quot;highlighter-rouge&quot;&gt;dockerfile&lt;/code&gt;. At the time of writing the &lt;code class=&quot;highlighter-rouge&quot;&gt;dockerfile&lt;/code&gt; looked like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;FROM alpine:edge

ENV DNSCRYPT_LISTEN_PORT=5053 \
    DNSCRYPT_SERVER_NAMES=&quot;&quot; \
    PUID=1000 \
    PGID=100

COPY entrypoint.sh /

RUN apk add --no-cache dnscrypt-proxy drill \
    &amp;amp;&amp;amp; chmod +x /entrypoint.sh

HEALTHCHECK --interval=5s --timeout=3s --start-period=10s \
    CMD drill -p $DNSCRYPT_LISTEN_PORT cloudflare.com @127.0.0.1 || exit 1

ENTRYPOINT [&quot;/entrypoint.sh&quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/djaydev/docker-dnscrypt-proxy/blob/6f3aa7688dee4734a73f69432cee9f2cecb696a7/Dockerfile&quot; class=&quot;no-mark-external&quot;&gt;Here’s&lt;/a&gt; a link to the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;dockerfile&lt;/code&gt;. As it looked at the time of writing.&lt;/p&gt;

&lt;p&gt;By eye-gazing the file we can determine that the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; command is used as a part of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Docker&lt;/code&gt; container &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt;. Oh Shoot! It is actually the &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; making the host “sick”. This is sooooo :point_down:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/DumbDumber.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But why is this happening. Again looking at the &lt;code class=&quot;highlighter-rouge&quot;&gt;dockerfile&lt;/code&gt; we can see that the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; cmd queries a DNS server on port &lt;em&gt;5053&lt;/em&gt;. Okay fine. But wait, I have this volume mapping in my &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;docker-compose&lt;/code&gt; YML file.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;    volumes:
      - &quot;./conf/dnscrypt-proxy.toml:/config/dnscrypt-proxy.toml&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I had a look in the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy.toml&lt;/code&gt; file and found that I had configured the listening port of &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; to a different port than the one that the &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; queries.
&lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; still works even though there is a mismatch between the &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; and the configured listening port in the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy.toml&lt;/code&gt; file. But the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; command will of course fail and fail and fail and fail ….. But why isn’t the &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; just returning the &lt;code class=&quot;highlighter-rouge&quot;&gt;|| exit 1&lt;/code&gt; part? And the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; command killed!&lt;/p&gt;

&lt;p&gt;Let’s go into that.&lt;/p&gt;

&lt;p&gt;For King Canute :crown: let’s peep at that &lt;code class=&quot;highlighter-rouge&quot;&gt;dockerfile&lt;/code&gt; once more. Notice that &lt;code class=&quot;highlighter-rouge&quot;&gt;--timeout=3s&lt;/code&gt;? Yes you do, you see it :eyes:. After spotting that, I suspected this being an issue of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Docker&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; not leaving enough time for the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; cmd to timeout in the case that the DNS server is not answering. Reading the documentation on the &lt;code class=&quot;highlighter-rouge&quot;&gt;Docker&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; reveals that if the cmd used in the &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; takes more than, in this case, three seconds, the &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; will be considered as unhealthy. More &lt;a href=&quot;https://docs.docker.com/engine/reference/builder/#healthcheck&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;. After executing the cmd used in the &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; inside the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; container, I could conclude that the three second timeout would certainly not be enough to allow the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; command to naturally time out.&lt;/p&gt;

&lt;p&gt;I used these commands:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;time drill -p 5354 cloudflare.com @127.0.0.1&lt;/code&gt; &amp;lt; query on a port that the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; &lt;em&gt;is not&lt;/em&gt; listening on
    &lt;ul&gt;
      &lt;li&gt;Result: &lt;code class=&quot;highlighter-rouge&quot;&gt;15.01s&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;time drill -p 5053 cloudflare.co @127.0.0.1&lt;/code&gt; &amp;lt; query on the port that the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; &lt;em&gt;is&lt;/em&gt; listening on
    &lt;ul&gt;
      &lt;li&gt;Result: &lt;code class=&quot;highlighter-rouge&quot;&gt;0.00s&lt;/code&gt;. The speed of the answer is because it was served from the DNS cache&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;When the &lt;code class=&quot;highlighter-rouge&quot;&gt;Docker&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; times out after three seconds the exit code of the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; cmd is not caught and it just hangs as a &lt;em&gt;zombie&lt;/em&gt; process and counts against the &lt;code class=&quot;highlighter-rouge&quot;&gt;max user processes&lt;/code&gt;. Then when the max is reached. The disaster occurs as the host experiences resource exhaustion.&lt;/p&gt;

&lt;h3 id=&quot;the-fix&quot;&gt;The fix&lt;/h3&gt;

&lt;p&gt;Initially I fixed this by simply making sure that the listening port configured in the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy.toml&lt;/code&gt; file matched the one the &lt;code class=&quot;highlighter-rouge&quot;&gt;Docker&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; uses.
However, after running the container for a couple of days I still saw &lt;em&gt;zombie&lt;/em&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; cmd’s. Though a very limited number, compared to before.
But of course the wise one thinks. E.g. if for some reason the &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; command cannot reach the local DNS server. If the domain does not exist or an network issue occurs, &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; does not get the necessary time it needs to time out naturally. Leaving us with hanging &lt;em&gt;zombie&lt;/em&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;drill&lt;/code&gt; processes.&lt;/p&gt;

&lt;h4 id=&quot;the-real-fix&quot;&gt;The real fix&lt;/h4&gt;

&lt;p&gt;As part of my troubleshooting I created this &lt;a href=&quot;https://github.com/djaydev/docker-dnscrypt-proxy/issues/1&quot; class=&quot;no-mark-external&quot;&gt;GitHub issue&lt;/a&gt;. On the repository for the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; container image I use. For better or worse I was referred to &lt;a href=&quot;https://github.com/klutchell/dnscrypt-proxy&quot; class=&quot;no-mark-external&quot;&gt;the klutchell &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; container image&lt;/a&gt; by the image creator. As the creator thinks that image is better maintained. I therefore had a look at that projects &lt;code class=&quot;highlighter-rouge&quot;&gt;dockerfile&lt;/code&gt; and what do I see. No &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt;. Hmmmm, interesting.
Further investigation. This time into the commit history of the klutchell image. In there I found a commit with this revealing title: &lt;code class=&quot;highlighter-rouge&quot;&gt;remove drill and internal healthcheck&lt;/code&gt;. But the commit had no reasoning on why. So I created an &lt;a href=&quot;https://github.com/klutchell/dnscrypt-proxy/issues/19&quot; class=&quot;no-mark-external&quot;&gt;GitHub issue&lt;/a&gt; on the klutchell image repository. Where I simply asked for the reason behind removing the &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt;.
The creator told me that he did so in order to simplify the image and give users control on whether or not they want a &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt;. That knowledge made me decide to continue with the image I was using. However, with the change that I would control its &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; in the &lt;code class=&quot;highlighter-rouge&quot;&gt;docker-compose&lt;/code&gt; file I’m using for the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; container.&lt;/p&gt;

&lt;p&gt;Like so:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3.4'&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;....&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;healthcheck&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;CMD&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;drill&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-p&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;5053&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;cloudflare.com&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;||&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;exit&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;20s&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;20s&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;3&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;start_period&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;5s&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;N.B. the above is a snippet of the &lt;code class=&quot;highlighter-rouge&quot;&gt;docker-compose&lt;/code&gt; file. Ensure to specify the docker-compose file version to be v3.4 or above, if you want use the &lt;code class=&quot;highlighter-rouge&quot;&gt;start_period&lt;/code&gt; parameter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Overwriting the &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; gives the following benefits:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Controlling the value of the &lt;code class=&quot;highlighter-rouge&quot;&gt;timeout&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;HEALTHCHECK&lt;/code&gt; parameter (&lt;strong&gt;the actual fix&lt;/strong&gt;)&lt;/li&gt;
  &lt;li&gt;And, if I want to, the freedom to set the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; listening port as I see fit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Completing that, I then manually monitored the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; container for the next day or so. It ran without any issues and even better, there was no longer any hanging &lt;em&gt;zombie&lt;/em&gt; processes. There you have it, job done :dart:.&lt;/p&gt;

&lt;p&gt;Thank you for reading along. I hope you enjoyed it and that you found useful knowledge.&lt;/p&gt;

&lt;p&gt;Over and out :dash: and stay :house:&lt;/p&gt;</content><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><category term="docker" /><category term="HEALTHCHECK" /><category term="containerization" /><category term="virtualization" /><category term="debugging" /><category term="resource" /><category term="limit" /><category term="ulimit" /><summary type="html">Leading up to this post, I’ve been fiddling with my HushDNS project for quite some time. In the words of the project. It’s all about:</summary></entry><entry><title type="html">HushDNS, can I please get me some DNS privacy</title><link href="https://bengtssondd.it/anonymity/privacy/security/2020/04/02/HushDNS-can-I-please-get-me-some-DNS-privacy/" rel="alternate" type="text/html" title="HushDNS, can I please get me some DNS privacy" /><published>2020-04-02T00:00:00+02:00</published><updated>2020-04-02T00:00:00+02:00</updated><id>https://bengtssondd.it/anonymity/privacy/security/2020/04/02/HushDNS-can-I-please-get-me-some-DNS-privacy</id><content type="html" xml:base="https://bengtssondd.it/anonymity/privacy/security/2020/04/02/HushDNS-can-I-please-get-me-some-DNS-privacy/">&lt;h1 id=&quot;motivation--background&quot;&gt;Motivation &amp;amp; background&lt;/h1&gt;

&lt;p&gt;I continuously try to improve my digital privacy. Which in todays world also means my general privacy.&lt;/p&gt;

&lt;p&gt;So DNS.&lt;/p&gt;

&lt;p&gt;Hmmm I don’t really need to say much more. But, I should. To properly set the scene and give an overview of the current state of domain name to IP issues.&lt;/p&gt;

&lt;p&gt;The DNS queries your system/browser and whatever software you use execute, leave you exposed to tracking by prying outsiders. Leaving you with little privacy in regards to e.g. which websites you visit. This is so. Because the data (requests and responses) involved when using DNS, is in the clear. Meaning –&amp;gt; everybody can determine the websites and other Internet related services you use.
Furthermore, a DNS query you execute can be mingled with. So you could end up on a website controlled be ill intended people. Rather on the one &lt;em&gt;you&lt;/em&gt; intended.&lt;/p&gt;

&lt;p&gt;Luckily, it’s possible to seriously combat the issues that DNS have. The rest of this post will be about how-to do exactly that.&lt;/p&gt;

&lt;p&gt;Let’s do this!&lt;/p&gt;

&lt;hr /&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#motivation--background&quot;&gt;Motivation &amp;amp; background&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#action-points&quot;&gt;Action points&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#determining-resolutions-to-the-action-points&quot;&gt;Determining resolutions to the action points&lt;/a&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#anonymity-and-logging&quot;&gt;Anonymity and logging&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#encrypt-all-the-things&quot;&gt;Encrypt all the things&lt;/a&gt;
            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#dnscrypt-server&quot;&gt;dnscrypt-server&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#dnscrypt-proxy&quot;&gt;dnscrypt-proxy&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#integrity-and-anti-forging&quot;&gt;Integrity and anti-forging&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#limit-tracking&quot;&gt;Limit tracking&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#executing-on-the-findings&quot;&gt;Executing on the findings&lt;/a&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#a-jaw-dropping-project-name&quot;&gt;A jaw dropping project name&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#resolving-the-anonymity-and-logging-issue&quot;&gt;Resolving the anonymity and logging issue&lt;/a&gt;
            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#blocking-dns-requests-at-the-application-layer&quot;&gt;Blocking DNS requests at the Application layer&lt;/a&gt;
                &lt;ul&gt;
                  &lt;li&gt;&lt;a href=&quot;#configuring-pi-hole&quot;&gt;Configuring Pi-hole&lt;/a&gt;
                    &lt;ul&gt;
                      &lt;li&gt;&lt;a href=&quot;#kick-of-the-pi-hole-container&quot;&gt;Kick of the Pi-hole container&lt;/a&gt;&lt;/li&gt;
                      &lt;li&gt;&lt;a href=&quot;#settings-for-the-pi-hole-container&quot;&gt;Settings for the Pi-hole container&lt;/a&gt;&lt;/li&gt;
                      &lt;li&gt;&lt;a href=&quot;#qnap-specifics&quot;&gt;QNAP specifics&lt;/a&gt;&lt;/li&gt;
                    &lt;/ul&gt;
                  &lt;/li&gt;
                  &lt;li&gt;&lt;a href=&quot;#useful-docs&quot;&gt;Useful docs&lt;/a&gt;&lt;/li&gt;
                &lt;/ul&gt;
              &lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#tumbling-dns-queries&quot;&gt;Tumbling DNS queries&lt;/a&gt;
                &lt;ul&gt;
                  &lt;li&gt;&lt;a href=&quot;#considering-anonymized-dns-when-you-run-your-own-dnscrypt-server&quot;&gt;Considering Anonymized-DNS when you run your own &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
                  &lt;li&gt;&lt;a href=&quot;#configuring-dnscrypt-proxy&quot;&gt;Configuring dnscrypt-proxy&lt;/a&gt;
                    &lt;ul&gt;
                      &lt;li&gt;&lt;a href=&quot;#kick-of-the-dnscrypt-proxy-container&quot;&gt;Kick of the dnscrypt-proxy container&lt;/a&gt;&lt;/li&gt;
                      &lt;li&gt;&lt;a href=&quot;#settings-for-the-dnscrypt-proxy-container&quot;&gt;Settings for the dnscrypt-proxy container&lt;/a&gt;&lt;/li&gt;
                    &lt;/ul&gt;
                  &lt;/li&gt;
                &lt;/ul&gt;
              &lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#i-said-%22dont-log-me%22&quot;&gt;I said: “don’t log me”&lt;/a&gt;
                &lt;ul&gt;
                  &lt;li&gt;&lt;a href=&quot;#disabling-logging-in-pi-hole&quot;&gt;Disabling logging in Pi-hole&lt;/a&gt;&lt;/li&gt;
                  &lt;li&gt;&lt;a href=&quot;#disabling-logging-in-dnscrypt-proxy&quot;&gt;Disabling logging in dnscrypt-proxy&lt;/a&gt;&lt;/li&gt;
                  &lt;li&gt;&lt;a href=&quot;#disabling-logging-in-dnscrypt-server&quot;&gt;Disabling logging in dnscrypt-server&lt;/a&gt;&lt;/li&gt;
                &lt;/ul&gt;
              &lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#encrypting-all-the-things&quot;&gt;Encrypting all the things&lt;/a&gt;
            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#configuring-dnscrypt-server&quot;&gt;Configuring dnscrypt-server&lt;/a&gt;
                &lt;ul&gt;
                  &lt;li&gt;&lt;a href=&quot;#using-it-together-with-dnscrypt-proxy&quot;&gt;Using it together with &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
                  &lt;li&gt;&lt;a href=&quot;#verifying-that-the-dnscrypt-server-works&quot;&gt;Verifying that the dnscrypt-server works&lt;/a&gt;
                    &lt;ul&gt;
                      &lt;li&gt;&lt;a href=&quot;#with-a-dns-query&quot;&gt;With a DNS query&lt;/a&gt;&lt;/li&gt;
                      &lt;li&gt;&lt;a href=&quot;#verifying-the-use-of-anonymized-dns&quot;&gt;Verifying the use of Anonymized-DNS&lt;/a&gt;&lt;/li&gt;
                    &lt;/ul&gt;
                  &lt;/li&gt;
                &lt;/ul&gt;
              &lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#dont-forge-my-integrity&quot;&gt;Don’t forge my integrity&lt;/a&gt;
            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#how-dnssec-works-and-some-background&quot;&gt;How DNSSEC works and some background&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#configuring-dnssec&quot;&gt;Configuring DNSSEC&lt;/a&gt;
                &lt;ul&gt;
                  &lt;li&gt;&lt;a href=&quot;#verifying-that-dnssec-works&quot;&gt;Verifying that DNSSEC works&lt;/a&gt;&lt;/li&gt;
                  &lt;li&gt;&lt;a href=&quot;#dnssec-documentation&quot;&gt;DNSSEC documentation&lt;/a&gt;&lt;/li&gt;
                &lt;/ul&gt;
              &lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#limiting-tracking&quot;&gt;Limiting tracking&lt;/a&gt;
            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#dns-query-name-minimisation&quot;&gt;DNS Query Name Minimisation&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#sni--esni-firefox&quot;&gt;SNI &amp;amp; ESNI, Firefox&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#plf-aka-page-load-fingerprints&quot;&gt;PLF AKA Page Load Fingerprints&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;action-points&quot;&gt;Action points&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Make DNS queries anonymous
    &lt;ul&gt;
      &lt;li&gt;Avoid being logged in as many locations en route to a DNS authoritative server answering ‘x’ DNS query&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Encrypt DNS communication. From today until Halloween … so always ultra&lt;/li&gt;
  &lt;li&gt;Use some form of response validation control. So that the response can be controlled for integrity and forging (e.g. &lt;a href=&quot;https://en.wikipedia.org/wiki/DNS_cache_poisoning&quot; class=&quot;no-mark-external&quot;&gt; DNS cache poisoning&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;The origin of ‘x’ DNS query should be as hard to track back to as possible&lt;/li&gt;
  &lt;li&gt;Give this project a name. Rememberable and catchy. All IT projects need such a name. Do they not?&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;determining-resolutions-to-the-action-points&quot;&gt;Determining resolutions to the action points&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/obama_you_can_do_it_meme.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Charged with motivation I then started investigating, analyzing and trawling through information on how-to make DNS private and secure.
After scouring the corners of the Internet and reading plenty of blogposts and whatnot. I felt ready to get into the heat of the action.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A boring life is a life without action&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;anonymity-and-logging&quot;&gt;Anonymity and logging&lt;/h3&gt;

&lt;p id=&quot;anonymity-and-logging-header&quot;&gt;To avoid being logged and be in greater control of potentially what my DNS queries leak. I came to the conclusion that I needed to run my own DNS recursive name-server.&lt;/p&gt;

&lt;p&gt;I ended up choosing &lt;a href=&quot;https://nlnetlabs.nl/projects/unbound/about/&quot; class=&quot;no-mark-external&quot;&gt;Unbound&lt;/a&gt;. It is OSS. I can run it on my own hardware. And it can be containerized. The documentation on it is solid and it is build be a highly skilled group of people at &lt;a href=&quot;https://nlnetlabs.nl/about/&quot; class=&quot;no-mark-external&quot;&gt;&lt;strong&gt;NLNETLABS&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because &lt;code class=&quot;highlighter-rouge&quot;&gt;Unbound&lt;/code&gt; have support for &lt;a href=&quot;https://tools.ietf.org/html/rfc7816&quot; class=&quot;no-mark-external&quot;&gt;DNS Query Name Minimisation&lt;/a&gt;. Your privacy is improved by only sending the parts of a domain name, that the different actors involved in a DNS query, really needs to process a request. That alleviates the pain of leaking DNS query data. Good stuff :+1:.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;N.B. specifically I’ll be running &lt;code class=&quot;highlighter-rouge&quot;&gt;Unbound&lt;/code&gt; as part of the &lt;a href=&quot;https://github.com/DNSCrypt/dnscrypt-server-docker&quot; class=&quot;no-mark-external&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;&lt;/a&gt; in a container “package”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;encrypt-all-the-things&quot;&gt;Encrypt all the things&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/encryptAllTheThings.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But with what? I’ll tell you my DNS security compadre.&lt;/p&gt;

&lt;p&gt;With….&lt;/p&gt;

&lt;h4 id=&quot;dnscrypt-server&quot;&gt;dnscrypt-server&lt;/h4&gt;

&lt;p&gt;In the &lt;a href=&quot;https://github.com/DNSCrypt/dnscrypt-server-docker#details&quot; class=&quot;no-mark-external&quot;&gt;words&lt;/a&gt; of the &lt;a href=&quot;https://github.com/DNSCrypt/dnscrypt-server-docker&quot; class=&quot;no-mark-external&quot;&gt;dnscrypt-server project&lt;/a&gt;, it is:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;- A minimal Ubuntu Linux as a base image.
- Caching resolver: Unbound, with DNSSEC, prefetching, and no logs. The number of threads and memory usage are automatically adjusted. Latest stable version, compiled from source. qname minimisation is enabled.
- encrypted-dns-server. Compiled from source.

Keys and certificates are automatically rotated every 8 hour.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is great. Some really cool people made this project. Ripe and ready for me to piggy back on. I was quite ecstatic when I found it.&lt;/p&gt;

&lt;p&gt;It fits right into the needs of the HushDNS project. Because:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;DNS queries will be encrypted&lt;/li&gt;
  &lt;li&gt;It can easily be run on an external server. Making it harder to traceback the origin of the DNS query&lt;/li&gt;
  &lt;li&gt;especially combined with the &lt;a href=&quot;https://github.com/DNSCrypt/dnscrypt-proxy/wiki/Anonymized-DNS&quot; class=&quot;no-mark-external&quot;&gt;Anonymized DNS&lt;/a&gt; feature of dnscrypt-server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;dnscrypt-proxy&quot;&gt;dnscrypt-proxy&lt;/h4&gt;

&lt;p&gt;It wraps a DNS recursive name-server that natively does not support encrypting DNS queries. Enabling communication from the DNS recursive name-server to the externally running dnscrypt-server. To be wrapped in this case is le Pi-hole. Oui oui. More on Pi-hole in a few.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Both of the above systems is developed by the &lt;a href=&quot;https://dnscrypt.info/&quot; class=&quot;no-mark-external&quot;&gt;DNSCrypt project&lt;/a&gt;. Thank you for that! Great stuff :smile:.&lt;/p&gt;

&lt;p&gt;They are OSS and have solid documentation. It’s all good in the hood-ie.&lt;/p&gt;

&lt;h3 id=&quot;integrity-and-anti-forging&quot;&gt;Integrity and anti-forging&lt;/h3&gt;

&lt;p&gt;The answer is &lt;a href=&quot;https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions&quot; class=&quot;no-mark-external&quot;&gt;DNSSEC&lt;/a&gt; (&lt;strong&gt;Domain Name System Security Extensions&lt;/strong&gt;) provides anti-forging and validation.&lt;/p&gt;

&lt;h3 id=&quot;limit-tracking&quot;&gt;Limit tracking&lt;/h3&gt;

&lt;p id=&quot;limit-tracking-header&quot;&gt;I’ve already been onto this subject. As I mentioned in the &lt;a href=&quot;#anonymity-and-logging-header&quot;&gt;Anonymity and logging&lt;/a&gt; section. &lt;code class=&quot;highlighter-rouge&quot;&gt;Unbound&lt;/code&gt; gives me control over DNS query logging as well as the &lt;strong&gt;DNS Query Name Minimisation&lt;/strong&gt; feature. But there is more to combatting being tracked.&lt;/p&gt;

&lt;p&gt;When you visit e.g. a website a request for a name to IP translation takes place. As DNS is designed, this request will be in the clear. If we encrypt it, use &lt;strong&gt;DNS Query Name Minimisation&lt;/strong&gt;, avoid it being logged in as many places as possible and use &lt;strong&gt;DNSSEC&lt;/strong&gt; to get integrity and prevent forging. We traverse into greener fields.&lt;/p&gt;

&lt;p&gt;But &amp;lt;- there it was - Hi!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/thereButt.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When a domain name has been properly translated to an IP address that IP address will be accessed. Of course. It’s your ticket to the destination website. If this is done over a tunneled connection (HTTPS) the &lt;a href=&quot;https://en.wikipedia.org/wiki/Server_Name_Indication&quot; class=&quot;no-mark-external&quot;&gt;SNI&lt;/a&gt; HTTP header will be sent along with the request. So that the receiving end (the web-server) can serve the correct certificate (public key cryptography my friend). This header reveals what you are visiting. If HTTPS is &lt;em&gt;not&lt;/em&gt; involved, the web-server will look at the hostname part of the URI. However, everything is in the clear anyway. So tracking in that scenario is easy peasy.&lt;/p&gt;

&lt;p&gt;Hey! Mr. Lars Bengtsson. Haven’t you heard. &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-tls-esni-01&quot; class=&quot;no-mark-external&quot;&gt;ESNI (Encrypted Server Name Indication)&lt;/a&gt; is a thing now! Yes I have. But it is not supported by all web-browsers. And if you rely on e.g. the Firefox &amp;lt;-&amp;gt; Cloudflare DoH ESNI solution. You basically trust them not to forge and log your DNS requests. This is an issue. By some, considered to be of major proportions. See:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.potaroo.net/ispcol/2019-04/angst.html&quot; class=&quot;no-mark-external&quot;&gt;DNS Privacy at IETF 104&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.potaroo.net/ispcol/2019-04/moredoh.html&quot; class=&quot;no-mark-external&quot;&gt;More DOH&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both articles are by &lt;a href=&quot;https://www.linkedin.com/in/geoff-huston-89182842/&quot; class=&quot;no-mark-external&quot;&gt;Geoff Huston&lt;/a&gt;. The chief scientist at &lt;a href=&quot;https://www.apnic.net/about-apnic/organization/&quot; class=&quot;no-mark-external&quot;&gt;APNIC (the Asia Pacific Network Information Centre)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, I’ll try to see if I can configure Firefox to use my DoH DNS setup. Then again, I control logging or no logging. Encryption and on we go.
Follow along to see if I succeed. If (when) I do, ESNI can be used and we are a tad more safe. However, there is still the caveat that the web-server hosting the destination website have to support ESNI. So we are not home-free.
And even with ESNI there is &lt;a href=&quot;https://blog.apnic.net/2019/08/23/what-can-you-learn-from-an-ip-address/&quot; class=&quot;no-mark-external&quot;&gt;PLF (Page Load Fingerprints)&lt;/a&gt;, which is a way to determine the website you are accessing by analyzing the meta-data “surrounding” that visit.
In other words. Even though your DNS query was secure, unforgeable and so forth. Accessing the IP address that was returned as a response to the DNS query and the other resources involved in loading a website, can reveal the identity of the website you are visiting. Because most websites have a unique set of resources they need. Integration with facebook (need, yeah right), ad networks, CDN’s and on we go. So basically. Identify this set and you know the website being visited.&lt;/p&gt;

&lt;p&gt;It is possible to combat PLF. By using an ad-blocker that works on the application layer.
By blocking DNS requests to the resources that ‘x’ website thinks it needs, but doesn’t really, for the website to be useful to you. This is where &lt;a href=&quot;https://docs.pi-hole.net/&quot; class=&quot;no-mark-external&quot;&gt;Pi-hole&lt;/a&gt; comes in.&lt;/p&gt;

&lt;p&gt;E.g. you can often block ads or metrics software on a website and the website continues to work. In this way, prying eyes, trying to identify the website you are visiting, would not be able to utilize PLF. As the resources actually being requested when accessing a website do not match the PLF set determined by analyzing the website.&lt;/p&gt;

&lt;p&gt;But the issue around SNI and ESNI still persists. Nothing else to do there than push for companies to host their website on platforms supporting &lt;strong&gt;AND&lt;/strong&gt; using ESNI. Unless you go the VPN or Tor route. However, using Tor comes with its own caveats. See &lt;a href=&quot;https://restoreprivacy.com/tor/&quot; class=&quot;no-mark-external&quot;&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;executing-on-the-findings&quot;&gt;Executing on the findings&lt;/h2&gt;

&lt;h3 id=&quot;a-jaw-dropping-project-name&quot;&gt;A jaw dropping project name&lt;/h3&gt;

&lt;p&gt;HushDNS it is. Because those DNS queries should “shut up and be quiet”. I’ll let it be up to you to grade the name.&lt;/p&gt;

&lt;p&gt;I like IT - and I like it a looooot :dash:. HushDNS, who can’t remember that?
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;N.B. the rest of the practical part of this blog post, will be going through the components one by one. In order to detail how each component work.
However, if you quickly want to reap the benefits of using HushDNS follow the installation guidelines on the &lt;a href=&quot;https://github.com/larssb/HushDNS&quot; class=&quot;no-mark-external&quot;&gt;HushDNS repository&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;resolving-the-anonymity-and-logging-issue&quot;&gt;Resolving the anonymity and logging issue&lt;/h3&gt;

&lt;h4 id=&quot;blocking-dns-requests-at-the-application-layer&quot;&gt;Blocking DNS requests at the Application layer&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.pi-hole.net/&quot; class=&quot;no-mark-external&quot;&gt;Pi-hole&lt;/a&gt; is a blackhole for Internet advertisements. Technically you configure it to be your DNS server on your LAN and then, when ‘x’ software on your computer needs to resolve a domain name to an IP address. Pi-hole is requested to do that. If it finds that the requested domain name is on a blacklist it responds with its own IP, and the software making the request gets an empty payload back when requesting data from the returned Pi-hole IP. This results in an empty space on the website you are accessing. E.g. where an ad should have been shown.&lt;/p&gt;

&lt;p&gt;This is a great way to combat the effectiveness of page load fingerprinting. Simultaneously you limit the amount of 3rd parties that know of your IP and website surfing habits.&lt;/p&gt;

&lt;h5 id=&quot;configuring-pi-hole&quot;&gt;Configuring Pi-hole&lt;/h5&gt;

&lt;p&gt;I’ll be running Pi-hole &lt;a href=&quot;https://en.wikipedia.org/wiki/Container_(virtualization)&quot; class=&quot;no-mark-external&quot;&gt;in a container&lt;/a&gt;. Using &lt;a href=&quot;https://github.com/larssb/HushDNS/blob/master/unit-deployment/pi-hole/docker-compose.yml&quot; class=&quot;no-mark-external&quot;&gt;this&lt;/a&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;h6 id=&quot;kick-of-the-pi-hole-container&quot;&gt;Kick of the Pi-hole container&lt;/h6&gt;

&lt;ol&gt;
  &lt;li&gt;Download the above mentioned file&lt;/li&gt;
  &lt;li&gt;Execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;docker-compose -f PATH_TO/docker-compose.yml -p &quot;PiHole&quot; up -d&lt;/code&gt;
    &lt;ol&gt;
      &lt;li&gt;This will install &lt;code class=&quot;highlighter-rouge&quot;&gt;Pi-hole&lt;/code&gt;. Name the compose “project” and container &lt;strong&gt;PiHole&lt;/strong&gt; and detach from the container&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h6 id=&quot;settings-for-the-pi-hole-container&quot;&gt;Settings for the Pi-hole container&lt;/h6&gt;

&lt;p id=&quot;pi-hole-settings-header&quot;&gt;The Pi-hole docker-compose file is specified to setup Pi-hole in the following way.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;CONDITIONAL_FORWARDING: &quot;true&quot;&lt;/code&gt;: Used in the case that Pi-hole is not the DHCP server on the network&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;CONDITIONAL_FORWARDING_IP: &quot;IP_ADDRESS&quot;&lt;/code&gt;: The IP address of the DHCP server on the network&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;CONDITIONAL_FORWARDING_DOMAIN: &quot;DOMAIN_NAME&quot;&lt;/code&gt;: A DNS suffix name. It has to match the DNS suffix name used in the DHCP server&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;DNS_BOGUS_PRIV: &quot;true&quot;&lt;/code&gt;: Specifies that reverse IP lookups for LAN IP addresses should never be forwarded to upstream DNS servers&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;DNSMASQ_LISTENING: &quot;local&quot;&lt;/code&gt;: Controls which network interface dnsmasq will listen on. Specifying “local” results in &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;Allows only queries from devices that are at most one hop away (local devices)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;DNS1&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;DNS2&lt;/code&gt;. As Pi-hole complains if you don’t specify two addresses I had to trick it to query on the localhost IP and the regular IP of the same network interface. The port part, &lt;code class=&quot;highlighter-rouge&quot;&gt;#5354&lt;/code&gt; is important. This is the port that &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; listens to. And that is where queries from Pi-hole is being sent. More on that &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; later on&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ServerIP: &quot;IP_ADDRESS&quot;&lt;/code&gt;: Needed when running the container in &lt;code class=&quot;highlighter-rouge&quot;&gt;host&lt;/code&gt; network mode&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;TZ: 'Europe/Copenhagen'&lt;/code&gt;: The timezone that Pi-hole runs in&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;WEB_PORT: &quot;808&quot;&lt;/code&gt;: Need when Pi-hole runs in &lt;code class=&quot;highlighter-rouge&quot;&gt;host&lt;/code&gt; network mode. Can break that you see a “beautiful”, blocked by Pi-hole block where an ad would’ve been displayed. I can live with that&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dns: - 127.0.0.1&lt;/code&gt;. Used to specify the DNS server used inside the container. Should end up in the container /etc/resolv.conf file. However, not always do. There is an &lt;a href=&quot;https://github.com/pi-hole/docker-pi-hole/issues/431&quot; class=&quot;no-mark-external&quot;&gt;issue&lt;/a&gt; on this on GitHub. Still have the setting here, to remember the issue and that this is the intended configuration&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;volumes: - &quot;./etc-pihole/:/etc/pihole/&quot;&lt;/code&gt; &amp;amp;&amp;amp; &lt;code class=&quot;highlighter-rouge&quot;&gt;- &quot;./etc-dnsmasq.d/:/etc/dnsmasq.d/&quot;&lt;/code&gt;: To store Pihole data between upgrades&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;volumes: - &quot;./resolv.conf:/etc/resolv.conf:ro&quot;&lt;/code&gt;: A trick I needed to do. More on this in the &lt;a href=&quot;#QNAP-specifics-header&quot;&gt;QNAP specifics section&lt;/a&gt; below.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;N.B. I haven’t configured Pi-hole to use &lt;code class=&quot;highlighter-rouge&quot;&gt;DNSSEC&lt;/code&gt; as the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; is per default configured to do this. And validating DNS answers via &lt;code class=&quot;highlighter-rouge&quot;&gt;dnssec&lt;/code&gt; in several locations will not do us any good. Just slow things down and potentially causes failed DNS queries. However, if you are not going to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; make sure to enable it via the &lt;code class=&quot;highlighter-rouge&quot;&gt;DNSSEC&lt;/code&gt; environment variable in the docker-compose file&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h6 id=&quot;qnap-specifics&quot;&gt;QNAP specifics&lt;/h6&gt;

&lt;p id=&quot;QNAP-specifics-header&quot;&gt;If you’ve been following my blog here, you will know that I run much of workloads on a QNAP NAS. Because of that, I often times need to go through loopholes to get “things” to run like I want it. Which in turn is also why I’m often considering abandoning my QNAP.&lt;/p&gt;

&lt;p&gt;So here is another one of those sections :unamused:. How-to get ‘x’ to run properly on a QNAP.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Fixing resolve.conf
    &lt;ol&gt;
      &lt;li&gt;Create a &lt;code class=&quot;highlighter-rouge&quot;&gt;resolve.conf&lt;/code&gt; file with the following content. The file needs to be located relative to the &lt;code class=&quot;highlighter-rouge&quot;&gt;resolve.conf&lt;/code&gt; container volume mapping mentioned in &lt;a href=&quot;#pi-hole-settings-header&quot;&gt;The settings&lt;/a&gt; above&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;nameserver 127.0.0.1
options ndots:0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;this content will overwrite whatever is in the &lt;code class=&quot;highlighter-rouge&quot;&gt;etc/resolv.conf&lt;/code&gt; inside the Pi-hole container. Making dns work as intended inside the container.&lt;/p&gt;

&lt;p&gt;This setting also relates to the &lt;code class=&quot;highlighter-rouge&quot;&gt;dns: - 127.0.0.1&lt;/code&gt; setting. As it didn’t always work without overwriting the &lt;code class=&quot;highlighter-rouge&quot;&gt;resolve.conf&lt;/code&gt; file.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Disable &lt;code class=&quot;highlighter-rouge&quot;&gt;dnsmasq&lt;/code&gt;. To do that execute the below&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/port=53/port=0/g'&lt;/span&gt; &amp;lt; /etc/dnsmasq.conf.orig &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/etc/dnsmasq.conf
/usr/bin/killall dnsmasq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively follow &lt;a href=&quot;https://wiki.qnap.com/wiki/Running_Your_Own_Application_at_Startup&quot; class=&quot;no-mark-external&quot;&gt;Running your own application at startup (on QNAP)&lt;/a&gt;, to avoid doing that on every QNAP boot&lt;/p&gt;

&lt;h5 id=&quot;useful-docs&quot;&gt;Useful docs&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://forum.qnap.com/viewtopic.php?f=142&amp;amp;t=143669&amp;amp;start=15&quot; class=&quot;no-mark-external&quot;&gt;disable dnsmasq on QNAP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://forum.qnap.com/viewtopic.php?t=147501&quot; class=&quot;no-mark-external&quot;&gt;resolve.conf QNAP issue&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blogging.dragon.org.uk/howto-setup-dnsmasq-as-dns-dhcp/&quot; class=&quot;no-mark-external&quot;&gt;dnsmasq as dns &amp;amp; dhcp&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html&quot; class=&quot;no-mark-external&quot;&gt;dnsmasq manual&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;tumbling-dns-queries&quot;&gt;Tumbling DNS queries&lt;/h4&gt;

&lt;p&gt;By using &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; we gain access to the DNSCrypt projects Anonymized-DNS feature. This feature makes it harder to origin trace our DNS queries. It does its magic by … aaah no, allow me to use a word by word copy of &lt;a href=&quot;https://github.com/DNSCrypt/dnscrypt-proxy/wiki/Anonymized-DNS#how-does-it-work&quot; class=&quot;no-mark-external&quot;&gt;this description&lt;/a&gt;. So:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;Instead of directly reaching a server, an Anonymized DNS client encrypts the query for the final server, but sends it to a relay.

The relay doesn't know the secret key, and cannot learn anything about the content of the query. It can only blindly forward the query to the actual DNS server, the only server that can decrypt it.

The DNS server itself receives a connection from the relay, not from the actual client. So the only IP address is knows about is the one of the relay, making it impossible to map queries to clients
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id=&quot;considering-anonymized-dns-when-you-run-your-own-dnscrypt-server&quot;&gt;Considering Anonymized-DNS when you run your own &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;&lt;/h5&gt;

&lt;p id=&quot;considering-anonymized-dns-header&quot;&gt;The question is, however, if it’s necessary and/or beneficial to use &lt;code class=&quot;highlighter-rouge&quot;&gt;Anonymized-DNS&lt;/code&gt; if you run your own &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;. In comparison, you really should if you use an external provider like &lt;code class=&quot;highlighter-rouge&quot;&gt;CloudFlare&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After having used &lt;code class=&quot;highlighter-rouge&quot;&gt;Anonymized-DNS&lt;/code&gt; for several days, with my own isolated &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; I weighted the pros and the cons. Then re-considered. The feature is simply not stable enough. Then, when it also entails added latency, it is currently not worth it. But, I will revisit this in the feature as it does add an extra layer of anonymization.&lt;/p&gt;

&lt;p&gt;For good measure. Here is my list of pros and cons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Extra anonymity, yes even if you run your own &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;, specifically if someone tries to sniff on you. By analyzing traffic between the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; and the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; they could be able to see that its DNS traffic going out of the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; endpoint and then on the other side, what IP that’s connecting to it. And if its very few IP’s, it should be possible to analyze the source of the DNS traffic and thereby de-anonymize your :shit:.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Extra latency&lt;/li&gt;
  &lt;li&gt;Depending on the external &lt;code class=&quot;highlighter-rouge&quot;&gt;Anonymized-DNS&lt;/code&gt; relay servers being up and working&lt;/li&gt;
  &lt;li&gt;The implementation of &lt;code class=&quot;highlighter-rouge&quot;&gt;Anonymized-DNS&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt;, at least up until v2.0.42, selects one relay server and then stays on that until reboot. So if that relay goes down you’ll have to reboot. Instead the &lt;code class=&quot;highlighter-rouge&quot;&gt;Anonymized-DNS&lt;/code&gt; feature should be able to switch over to another configured relay server if there is problems with the currently selected one&lt;/li&gt;
  &lt;li&gt;Added complexity when troubleshooting&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;configuring-dnscrypt-proxy&quot;&gt;Configuring dnscrypt-proxy&lt;/h5&gt;

&lt;p&gt;Another workload I’ll be running &lt;a href=&quot;https://en.wikipedia.org/wiki/Container_(virtualization)&quot; class=&quot;no-mark-external&quot;&gt;in a container&lt;/a&gt;. This time by using &lt;a href=&quot;https://github.com/larssb/HushDNS/blob/master/unit-deployment/dnscrypt-proxy/provider-own-server/docker-compose.yml&quot; class=&quot;no-mark-external&quot;&gt;this&lt;/a&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;h6 id=&quot;kick-of-the-dnscrypt-proxy-container&quot;&gt;Kick of the dnscrypt-proxy container&lt;/h6&gt;

&lt;ol&gt;
  &lt;li&gt;Download the above mentioned file&lt;/li&gt;
  &lt;li&gt;Execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;docker-compose -f PATH_TO/docker-compose.yml -p &quot;dnscrypt-proxy&quot; up -d&lt;/code&gt;
    &lt;ol&gt;
      &lt;li&gt;This will install &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt;. Name the compose “project” and container &lt;strong&gt;dnscrypt-proxy&lt;/strong&gt; and detach from the container&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h6 id=&quot;settings-for-the-dnscrypt-proxy-container&quot;&gt;Settings for the dnscrypt-proxy container&lt;/h6&gt;

&lt;ul id=&quot;dnscrypt-proxy-settings-header&quot;&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;DNSCRYPT_LISTEN_PORT&lt;/code&gt;: “5354”: Self-explanatory&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;DNSCRYPT_SERVER_NAMES&lt;/code&gt;: “[‘MY_SECRET_DNSCRYPT-SERVER’]”: The dnscrypt-server or DoH server that &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; should connect to&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;network_mode&lt;/code&gt;: “host”: The port was not reachable for Pi-hole if this network mode was not used&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to setup &lt;code class=&quot;highlighter-rouge&quot;&gt;Anonymized-DNS&lt;/code&gt; we need to complete the following steps (if you still want to set it up, &lt;a href=&quot;#considering-anonymized-dns-header&quot;&gt;considering the pros and cons of Anonymized-DNS&lt;/a&gt;):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Ensure that there is a sub-folder named &lt;code class=&quot;highlighter-rouge&quot;&gt;conf&lt;/code&gt; in the folder of the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt; file 1. In this folder create a file named &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy.toml&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Use &lt;a href=&quot;https://github.com/larssb/HushDNS/blob/master/unit-deployment/dnscrypt-proxy/provider-own-server/conf/dnscrypt-proxy.toml&quot; class=&quot;no-mark-external&quot;&gt;this dnscrypt-proxy.toml file as a template&lt;/a&gt;
    &lt;ol&gt;
      &lt;li&gt;Change the value of &lt;code class=&quot;highlighter-rouge&quot;&gt;server_names&lt;/code&gt; in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Global settings&lt;/code&gt; section to the name you will give your &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Potentially change the &lt;code class=&quot;highlighter-rouge&quot;&gt;listen_addresses&lt;/code&gt; to the port you want (in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Global section&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;Under the &lt;code class=&quot;highlighter-rouge&quot;&gt;Anonymized DNS&lt;/code&gt; section change the &lt;code class=&quot;highlighter-rouge&quot;&gt;routes&lt;/code&gt; array to contain one or more &lt;code class=&quot;highlighter-rouge&quot;&gt;Anonymized DNS&lt;/code&gt; relay servers of your choice. Find available relay servers &lt;a href=&quot;https://github.com/DNSCrypt/dnscrypt-resolvers/blob/master/v2/relays.md&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;. Make sure to change the &lt;code class=&quot;highlighter-rouge&quot;&gt;server_name&lt;/code&gt; in the &lt;code class=&quot;highlighter-rouge&quot;&gt;routes&lt;/code&gt; definition, to reflect the value of the &lt;code class=&quot;highlighter-rouge&quot;&gt;server_names&lt;/code&gt; property in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Global section&lt;/code&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;N.B. if you look at the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;docker-compose.yml&lt;/code&gt; file you’ll notice that there is a &lt;code class=&quot;highlighter-rouge&quot;&gt;volumes&lt;/code&gt; mapping. This volume mapping is what the above steps relate to&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;i-said-dont-log-me&quot;&gt;I said: “don’t log me”&lt;/h4&gt;

&lt;p&gt;And “they” listened. Good for them. So what “they” did was to ensure that neither &lt;code class=&quot;highlighter-rouge&quot;&gt;Pi-hole&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; was in any form of logging mode.&lt;/p&gt;

&lt;h5 id=&quot;disabling-logging-in-pi-hole&quot;&gt;Disabling logging in Pi-hole&lt;/h5&gt;

&lt;p&gt;When you feel certain that your &lt;code class=&quot;highlighter-rouge&quot;&gt;Pi-Hole&lt;/code&gt; installation is working, it’s a good time to disable its logging behavior. By:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Going to &lt;em&gt;Settings&lt;/em&gt; in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Pi-Hole&lt;/code&gt; web-interface&lt;/li&gt;
  &lt;li&gt;Clicking on the &lt;em&gt;Privacy&lt;/em&gt;  tab&lt;/li&gt;
  &lt;li&gt;Then activating the radio button: &lt;em&gt;Anonymous mode: This disables basically everything except the live anonymous statistics…..&lt;/em&gt;. This setting is very privacy minded but still makes it possible to verify that &lt;code class=&quot;highlighter-rouge&quot;&gt;Pi-Hole&lt;/code&gt; is actually blocking certain queries. You’ll also still have the main stats available, now just politely anonymized&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;There is currently no way to do the above in an automated fashion. As the &lt;a href=&quot;https://github.com/pi-hole/docker-pi-hole&quot; class=&quot;no-mark-external&quot;&gt;Pi-hole in a docker container&lt;/a&gt; project does not support configuration on this on container initialization. However, you could overwrite the &lt;code class=&quot;highlighter-rouge&quot;&gt;PRIVACYLEVEL=0|1|2|3|4&lt;/code&gt; (optionally read &lt;a href=&quot;https://docs.pi-hole.net/ftldns/configfile/#privacylevel&quot; class=&quot;no-mark-external&quot;&gt;this&lt;/a&gt;) setting, by using a Docker volume mapping to &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/pihole/&lt;/code&gt; in order to overwrite the &lt;code class=&quot;highlighter-rouge&quot;&gt;pihole-FTL.conf&lt;/code&gt; file with your own customized one. I chose not to, as this is the only setting I would need to overwrite. Making the extra work required too much in my opinion&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5 id=&quot;disabling-logging-in-dnscrypt-proxy&quot;&gt;Disabling logging in dnscrypt-proxy&lt;/h5&gt;

&lt;p&gt;Not much to do here. The &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; is already non-logging in its default setup.&lt;/p&gt;

&lt;h5 id=&quot;disabling-logging-in-dnscrypt-server&quot;&gt;Disabling logging in dnscrypt-server&lt;/h5&gt;

&lt;p&gt;Not much to do here. The &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; is already non-logging in its default setup.&lt;/p&gt;

&lt;h3 id=&quot;encrypting-all-the-things&quot;&gt;Encrypting all the things&lt;/h3&gt;

&lt;p&gt;This is achieved by using &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As I have already explained how-to setup &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; and there is no more to it. This part focuses on the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;configuring-dnscrypt-server&quot;&gt;Configuring dnscrypt-server&lt;/h4&gt;

&lt;p&gt;As &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; needs an &lt;code class=&quot;highlighter-rouge&quot;&gt;init&lt;/code&gt; container, and that is &lt;a href=&quot;https://github.com/docker/compose/issues/6855&quot; class=&quot;no-mark-external&quot;&gt;not supported&lt;/a&gt; by the &lt;code class=&quot;highlighter-rouge&quot;&gt;Docker&lt;/code&gt; engine, you’ll have to do with a shell script.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Download this &lt;a href=&quot;https://github.com/larssb/HushDNS/blob/master/unit-deployment/dnscrypt-server/setup.sh&quot; class=&quot;no-mark-external&quot;&gt;bash script&lt;/a&gt; and ensure to update the placeholders (capital words, separated by an underscore) with actual useful values
    &lt;ol&gt;
      &lt;li&gt;Change the port of the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; if you need to (already have ‘x’ service running on port 443). Change from port 443 to “your” port, in &lt;strong&gt;all&lt;/strong&gt; the locations where it is specified&lt;/li&gt;
      &lt;li&gt;Make the file executable by executing: &lt;code class=&quot;highlighter-rouge&quot;&gt;sudo chmod +x ./THE_NAME_YOU_GAVE_THE_FILE&lt;/code&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Execute the file on the system that is to host the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Note down the output of the &lt;code class=&quot;highlighter-rouge&quot;&gt;init -N NAME_TO_GIVE_YOUR_DNSCRYPT_SERVER...&lt;/code&gt; command as you need the info when configuring &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt;
    &lt;ol&gt;
      &lt;li&gt;you can also get the output after the fact by executing &lt;code class=&quot;highlighter-rouge&quot;&gt;docker logs dnscrypt-server&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;The output to copy is the generated &lt;code class=&quot;highlighter-rouge&quot;&gt;stamp&lt;/code&gt;. You need this in order to connect to the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; via the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&quot;using-it-together-with-dnscrypt-proxy&quot;&gt;Using it together with &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt;&lt;/h5&gt;

&lt;p&gt;As we can see in the &lt;a href=&quot;#dnscrypt-proxy-settings-header&quot;&gt;Settings for the dnscrypt-proxy container&lt;/a&gt; section. Configuring the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; involves its &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy.toml&lt;/code&gt; file.
So, in order to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; you just spun up together with your &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; server, you need to update the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy.toml&lt;/code&gt; file.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Find the &lt;code class=&quot;highlighter-rouge&quot;&gt;[static]&lt;/code&gt; section in the file&lt;/li&gt;
  &lt;li&gt;Change the server name part of &lt;code class=&quot;highlighter-rouge&quot;&gt;[static.'hush.dns']&lt;/code&gt; to the server name you’ve used throughout the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy.toml&lt;/code&gt; file&lt;/li&gt;
  &lt;li&gt;Finally set the value of the &lt;code class=&quot;highlighter-rouge&quot;&gt;stamp&lt;/code&gt; property to the &lt;code class=&quot;highlighter-rouge&quot;&gt;DNSCrypt&lt;/code&gt; stamp that the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; spit out when it was initialized&lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&quot;verifying-that-the-dnscrypt-server-works&quot;&gt;Verifying that the dnscrypt-server works&lt;/h5&gt;

&lt;blockquote&gt;
  &lt;p&gt;N.B. if you are on &lt;code class=&quot;highlighter-rouge&quot;&gt;Docker Desktop for Mac you cannot ping or use dig/drill directly to the container. Even though it is in &lt;/code&gt;host&lt;code class=&quot;highlighter-rouge&quot;&gt; network mode. This is because &lt;/code&gt;Docker Desktop for Mac&lt;code class=&quot;highlighter-rouge&quot;&gt; cannot route traffic to containers. That's the reason for the below way to test whether the &lt;/code&gt;dnscrypt-server` is working&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More on that &lt;a href=&quot;https://docs.docker.com/docker-for-mac/networking/&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h6 id=&quot;with-a-dns-query&quot;&gt;With a DNS query&lt;/h6&gt;

&lt;p&gt;&lt;strong&gt;On Mac&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;docker exec -it DNSCRYPT_PROXY_CONTAINER_NAME /bin/sh&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Then: &lt;code class=&quot;highlighter-rouge&quot;&gt;drill -p THE_PORT_YOU_CHOSE @127.0.0.1 SOME_DOMAIN&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;On Linux&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I haven’t tested this but it should be possible to execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;drill -p THE_PORT_YOU_CHOSE @127.0.0.1 SOME_DOMAIN&lt;/code&gt; directly to the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; container. In other words you don’t have to &lt;code class=&quot;highlighter-rouge&quot;&gt;exec&lt;/code&gt; into the container.&lt;/p&gt;

&lt;p&gt;For both of the above examples. If you get back a valid answer you know that the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; works. To get even more reassurance, stop the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; container and try again. Now you should get no answer back. Rather a timeout/network error.&lt;/p&gt;

&lt;h6 id=&quot;verifying-the-use-of-anonymized-dns&quot;&gt;Verifying the use of Anonymized-DNS&lt;/h6&gt;

&lt;p&gt;It makes the most sense to verify Anonymized-DNS from the point of the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;. As this is the server that will get the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; forwarded DNS query. And therefore is the server that should &lt;em&gt;NOT&lt;/em&gt; see your WAN IP (from where the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; is running). Rather the WAN IP it sees making a DNS query is an Anonymized-DNS relay server.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;On the server where the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; is running execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;tcpdump -nnSX port 443&lt;/code&gt; this will sniff on HTTPS (port 443).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An example output could look like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;20:35:10.770590 IP SOME_WAN_IP.443 &amp;gt; ANONYMIZED_DNS_RELAY_SERVER_WAN_IP.38756: UDP, length 240
        0x0000:  4500 010c 2a4a 4000 4011 6c80 82e2 d9de  E...*J@.@.l.....
        0x0010:  5410 f245 01bb 9764 00f8 a420 7236 666e  T..E...d....r6fn
        0x0020:  7657 6a38 f984 9650 3145 710b a9ff c436  vWj8...P1Eq....6
        0x0030:  f999 4174 d7ae a874 b313 08f7 aa9b 7c9c  ..At...t......|.
        0x0040:  5dc6 0da6 3c19 1adc d272 30ee 0927 472a  ]...&amp;lt;....r0..'G*
        0x0050:  83e5 6fa9 8ac8 7a9f a8c7 6201 1dbf ff06  ..o...z...b.....
        0x0060:  7703 e04c 0023 c681 6e47 7b37 1b2b cb35  w..L.#..nG{7.+.5
        0x0070:  a740 edbc c232 0fb5 15d5 8036 fe57 6525  .@...2.....6.We%
        0x0080:  5925 e324 d25b 376d 5d0a 4e4d 320d c6d8  Y%.$.[7m].NM2...
        0x0090:  58d2 7697 1aff d2f0 37a7 cc19 48be d066  X.v.....7...H..f
        0x00a0:  1e68 ff34 fb35 d231 651f 8b33 0033 93e1  .h.4.5.1e..3.3..
        0x00b0:  6ceb f9e1 1676 a592 f69e fe62 a3f5 688f  l....v.....b..h.
        0x00c0:  2db6 ea30 0e6b ff56 fa8a 4223 4520 767c  -..0.k.V..B#E.v|
        0x00d0:  79d1 dcb9 cf66 6aba a748 2de8 223f d2dd  y....fj..H-.&quot;?..
        0x00e0:  d2af 3179 47ac 85a6 b7cd a8ab ef7a cfa9  ..1yG........z..
        0x00f0:  ee99 9df9 70ce 2049 c657 f686 906c 0c41  ....p..I.W...l.A
        0x0100:  1f13 1f07 dd0c 0154 0871 4a46            .......T.qJF
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can be all :+1: up if the WAN IP making the DNS query is not your WAN IP but the WAN IP of a DNSCrypt Anonymized-DNS relay server. Getting the IP of a relay server is easy with the &lt;a href=&quot;https://dnscrypt.info/stamps/&quot; class=&quot;no-mark-external&quot;&gt;online DNSCrypt Stamp calculator&lt;/a&gt;. Just insert the stamp of the Anonymized-DNS server you use in the stamp field on the page and you should be able to see the WAN IP of the relay server in the &lt;em&gt;IP Address&lt;/em&gt; field :clap:.&lt;/p&gt;

&lt;p&gt;Optionally you can go-to the &lt;a href=&quot;https://www.dnsleaktest.com/&quot; class=&quot;no-mark-external&quot;&gt;DNS leak test site&lt;/a&gt; to see whether it’s your private WAN IP or a WAN IP of an &lt;code class=&quot;highlighter-rouge&quot;&gt;Anonymized-DNS&lt;/code&gt; relay server.&lt;/p&gt;

&lt;h3 id=&quot;dont-forge-my-integrity&quot;&gt;Don’t forge my integrity&lt;/h3&gt;

&lt;p&gt;As you may remember, the answer is &lt;code class=&quot;highlighter-rouge&quot;&gt;DNSSEC&lt;/code&gt;. We got a little :gift: here. In that it is already enabled when we use the &lt;code class=&quot;highlighter-rouge&quot;&gt;jedisct1/dnscrypt-server&lt;/code&gt; container image. The devil is the detail, or maybe in the detail. Whatsoever,  &lt;code class=&quot;highlighter-rouge&quot;&gt;DNSSEC&lt;/code&gt; is availble via the &lt;code class=&quot;highlighter-rouge&quot;&gt;Unbound&lt;/code&gt; DNS recursive name-server that &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; uses internally. Therefore gifting us with &lt;code class=&quot;highlighter-rouge&quot;&gt;DNSSEC&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;how-dnssec-works-and-some-background&quot;&gt;How DNSSEC works and some background&lt;/h4&gt;

&lt;p&gt;To my surprise &lt;a href=&quot;https://ietf.org/&quot; class=&quot;no-mark-external&quot;&gt;the IETF (Internet Engineering Task Force)&lt;/a&gt; have been working on DNSSEC since 1993.&lt;/p&gt;

&lt;p&gt;It is designed to protect against:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;packet interception (in its various forms)&lt;/li&gt;
  &lt;li&gt;ID Guessing and Query Prediction&lt;/li&gt;
  &lt;li&gt;Name chaining (a subset of “cache poisoning” attacks)&lt;/li&gt;
  &lt;li&gt;Betrayal By Trusted Server. E.g. an ISP DNS server configured to forward statistics to a 3rd party unbeknownst to the end-user&lt;/li&gt;
  &lt;li&gt;Authenticated Denial of Domain Names&lt;/li&gt;
  &lt;li&gt;Data integrity and data origin authentication for “wildcard” DNS names&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, it does &lt;strong&gt;NOT&lt;/strong&gt; protect against:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;modification of the DNS message header. Meaning that the response is digitally signed. But the message packet header could still be mingled with. A properly configured DNS recursive name-server, however, combat that&lt;/li&gt;
  &lt;li&gt;unless configured to do so, &lt;code class=&quot;highlighter-rouge&quot;&gt;DNSSEC&lt;/code&gt; does not cover glue records, which are records that combat circular lookup dependencies, e.g. when ‘x’ domains name-servers are on the same root domain as the general resource records&lt;/li&gt;
  &lt;li&gt;Denial of Service. Actually enabling &lt;code class=&quot;highlighter-rouge&quot;&gt;DNSSEC&lt;/code&gt; might make the problem worse&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It works by….nah, let’s just unscrupulously copy in the description on wikipedia&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;DNSSEC works by digitally signing records for DNS lookup using public-key cryptography. The correct DNSKEY record is authenticated via a chain of trust, starting with a set of verified public keys for the DNS root zone which is the trusted third party. Domain owners generate their own keys, and upload them using their DNS control panel at their domain-name registrar, which in turn pushes the keys via secDNS to the zone operator (e.g., Verisign for .com) who signs and publishes them in DNS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;N.B!&lt;/p&gt;

&lt;p&gt;DNSSEC &lt;strong&gt;does NOT&lt;/strong&gt; give us confidentiality. That is why we need a solution like the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;. That wraps the &lt;code class=&quot;highlighter-rouge&quot;&gt;Unbound&lt;/code&gt; DNS recursive name-server in the &lt;a href=&quot;https://github.com/jedisct1/encrypted-dns-server&quot; class=&quot;no-mark-external&quot;&gt;encrypted-dns-server proxy&lt;/a&gt;. Only then, prying eyes will not be able to sniff (on) the data-stream between the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; and the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;configuring-dnssec&quot;&gt;Configuring DNSSEC&lt;/h4&gt;

&lt;p&gt;Both the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; container, if you use the example &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy.toml&lt;/code&gt; file, and the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; is all ready and prepped for using &lt;code class=&quot;highlighter-rouge&quot;&gt;DNSSEC&lt;/code&gt;. Nothing more to do. Perfect days :gem:&lt;/p&gt;

&lt;h5 id=&quot;verifying-that-dnssec-works&quot;&gt;Verifying that DNSSEC works&lt;/h5&gt;

&lt;ol&gt;
  &lt;li&gt;Enter the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; container by executing: &lt;code class=&quot;highlighter-rouge&quot;&gt;docker exec -it dnscrypt-proxy /bin/sh&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Fire of: &lt;code class=&quot;highlighter-rouge&quot;&gt;drill -p PORT_DNSCRYPT_PROXY_LISTENS_ON @127.0.0.1 dig sigfail.verteiltesysteme.net&lt;/code&gt;
    &lt;ol&gt;
      &lt;li&gt;Should return &lt;code class=&quot;highlighter-rouge&quot;&gt;-&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, rcode: SERVFAIL, id: 64618&lt;/code&gt; if it doesn’t on your first try (you might see &lt;code class=&quot;highlighter-rouge&quot;&gt;Error: error sending query: Could not send or receive, because of network error&lt;/code&gt;), try again.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Then fire of: &lt;code class=&quot;highlighter-rouge&quot;&gt;drill -p 5354 @127.0.0.1 dig sigok.verteiltesysteme.net&lt;/code&gt;
    &lt;ol&gt;
      &lt;li&gt;Should return &lt;code class=&quot;highlighter-rouge&quot;&gt;;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, rcode: NOERROR, id: 36866&lt;/code&gt; and the A record of the domain in the resulting payload&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&quot;dnssec-documentation&quot;&gt;DNSSEC documentation&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://tools.ietf.org/html/rfc3833&quot; class=&quot;no-mark-external&quot;&gt;DNSSEC RFC3833&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions&quot; class=&quot;no-mark-external&quot;&gt;Wikipedia on DNSSEC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;limiting-tracking&quot;&gt;Limiting tracking&lt;/h3&gt;

&lt;h4 id=&quot;dns-query-name-minimisation&quot;&gt;DNS Query Name Minimisation&lt;/h4&gt;

&lt;p&gt;Already enabled in the default &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-server&lt;/code&gt; settings (more specifically, its actually the &lt;code class=&quot;highlighter-rouge&quot;&gt;Unbound&lt;/code&gt; configuration). So that can be :white_check_mark:&lt;/p&gt;

&lt;h4 id=&quot;sni--esni-firefox&quot;&gt;SNI &amp;amp; ESNI, Firefox&lt;/h4&gt;

&lt;p&gt;I decided that it is too early days for using &lt;code class=&quot;highlighter-rouge&quot;&gt;ESNI&lt;/code&gt;. It is simply not supported broadly enough. Still very much an experimental feature and the performance cost is too steep to my liking. The &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; project describes some facts on &lt;code class=&quot;highlighter-rouge&quot;&gt;ESNI&lt;/code&gt; to consider &lt;a href=&quot;https://github.com/DNSCrypt/dnscrypt-proxy/wiki/Local-DoH#how-to-enable-esni-in-firefox&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In all fairness I should mention that it &lt;em&gt;would be&lt;/em&gt; possible to use &lt;code class=&quot;highlighter-rouge&quot;&gt;ESNI&lt;/code&gt; by taking advantage of the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; and then configure &lt;code class=&quot;highlighter-rouge&quot;&gt;Firefox&lt;/code&gt; to direct its &lt;code class=&quot;highlighter-rouge&quot;&gt;ESNI&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;DoH&lt;/code&gt; traffic through your &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt;. Therefore, if you still feel that &lt;code class=&quot;highlighter-rouge&quot;&gt;ESNI&lt;/code&gt; is something you want to experiment with, then follow the &lt;code class=&quot;highlighter-rouge&quot;&gt;dnscrypt-proxy&lt;/code&gt; &lt;a href=&quot;https://github.com/DNSCrypt/dnscrypt-proxy/wiki/Local-DoH&quot; class=&quot;no-mark-external&quot;&gt;ESNI guide&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;plf-aka-page-load-fingerprints&quot;&gt;PLF AKA Page Load Fingerprints&lt;/h4&gt;

&lt;p&gt;I’ve already touched upon this issue in the &lt;a href=&quot;#limit-tracking-header&quot;&gt;Limit tracking&lt;/a&gt; section.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Here we are at the end of the rainbow … and what do we, you, somebody find?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/endOfTheRainbow.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nothing more. Sorry for destroying your imagination :smile:.&lt;/p&gt;

&lt;p&gt;What you did find via this post though, was a &lt;strong&gt;HushDNS&lt;/strong&gt; setup to make your DNS life more private, anonymous and secure. What a tremendous :gift:.&lt;/p&gt;

&lt;p&gt;Over and out :dash:&lt;/p&gt;</content><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><category term="unbound" /><category term="pi-hole" /><category term="dnscrypt" /><category term="DNS" /><category term="privacy" /><category term="anonymity" /><summary type="html">Motivation &amp;amp; background</summary></entry><entry><title type="html">Signaling without exposing your private phone number</title><link href="https://bengtssondd.it/anonymity/privacy/security/communication/2019/12/28/Signaling-without-exposing-your-private-phone-number/" rel="alternate" type="text/html" title="Signaling without exposing your private phone number" /><published>2019-12-28T00:00:00+01:00</published><updated>2019-12-28T00:00:00+01:00</updated><id>https://bengtssondd.it/anonymity/privacy/security/communication/2019/12/28/Signaling-without-exposing-your-private-phone-number</id><content type="html" xml:base="https://bengtssondd.it/anonymity/privacy/security/communication/2019/12/28/Signaling-without-exposing-your-private-phone-number/">&lt;h2 id=&quot;the-situation&quot;&gt;The situation&lt;/h2&gt;

&lt;p&gt;I wanted a way to avoid revealing my private phone number when using Signal. There can be many reasons for this. E.g.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Privacy&lt;/li&gt;
  &lt;li&gt;Safety&lt;/li&gt;
  &lt;li&gt;Annoyance over why it is necessary in the first place when using Signal&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;end-goal&quot;&gt;End goal&lt;/h2&gt;

&lt;p&gt;Accomplishing the above will be considered a success when:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I’m able to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal Desktop&lt;/code&gt; application both with my private phone number and my
public phone number. On the same computer&lt;/li&gt;
  &lt;li&gt;Linking the &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal Desktop&lt;/code&gt; application can happen without using a secondary phone
or needing to uninstall and install the &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal&lt;/code&gt; mobile application (as this would result
in a need to be verified by my private contacts)&lt;/li&gt;
  &lt;li&gt;Getting a public phone number should be as cheap as possible&lt;/li&gt;
  &lt;li&gt;If possible, avoiding the registration of my address&lt;/li&gt;
  &lt;li&gt;I should be able to hold onto the public phone number for as long as I want&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;findings&quot;&gt;Findings&lt;/h2&gt;

&lt;h3 id=&quot;using-signal-desktop-with-both-phone-numbers-on-the-same-computer&quot;&gt;Using &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal Desktop&lt;/code&gt; with both phone numbers on the same computer&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal Desktop&lt;/code&gt; application is not multi-instance capable in the non-development version. Therefore one need to run
the general available version and the beta version side-by-side.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/signalapp/Signal-Desktop/issues/1720&quot; class=&quot;no-mark-external&quot;&gt;More on that here&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;linking-without-a-secondary-phone&quot;&gt;Linking without a secondary phone&lt;/h3&gt;

&lt;p&gt;This proved to be possible even though it required some nice nerdy magic&lt;/p&gt;

&lt;h3 id=&quot;as-cheap-as-possible--registration&quot;&gt;As cheap as possible &amp;amp; registration&lt;/h3&gt;

&lt;p&gt;I spent a lot of hours on different vendor pages. Vendors selling virtual phone numbers and the like.
&lt;a href=&quot;https://www.twilio.com/&quot; class=&quot;no-mark-external&quot;&gt;Twilio&lt;/a&gt; ended up being the vendor I chose.
As with them it is possible to acquire an US phone number for 1$ a month. With an initial top-up of 20$. Therefore giving you 20 months of Twilio.&lt;/p&gt;

&lt;p&gt;Twilio also makes it possible to use &lt;code class=&quot;highlighter-rouge&quot;&gt;Paypal&lt;/code&gt; as a payment service. Limiting the number of stakeholders that will get parts of my personal information.&lt;/p&gt;

&lt;h3 id=&quot;holding-onto-the-phone-number&quot;&gt;Holding onto the phone number&lt;/h3&gt;

&lt;p&gt;Using a prepaid mobile phone card is not an option. Even though it nicely comes with no registration. As the phone number falls out of my control at some point. Per say, you’re leasing it.&lt;/p&gt;

&lt;p&gt;Again &lt;code class=&quot;highlighter-rouge&quot;&gt;Twilio&lt;/code&gt; makes this possible. As long as I pay my dues.&lt;/p&gt;

&lt;h2 id=&quot;guidance-on-achieving-the-above&quot;&gt;Guidance on achieving the above&lt;/h2&gt;

&lt;p&gt;Parts of the below, have for documentation purposes, been copied from &lt;a href=&quot;https://source.opennews.org/articles/shields-using-signal-without-your-phone-number/&quot; class=&quot;no-mark-external&quot;&gt;Shields Up: Using Signal Without Giving Your Phone Number&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Sign-up for Twilio
    &lt;ol&gt;
      &lt;li&gt;Verify your account as asked&lt;/li&gt;
      &lt;li&gt;Top-up the account via &lt;code class=&quot;highlighter-rouge&quot;&gt;Paypal&lt;/code&gt; with the required 20$&lt;/li&gt;
      &lt;li&gt;Choose an American phone-number, with voice and SMS capabilities&lt;/li&gt;
      &lt;li&gt;In Twilio, navigate to “All Products and Services” &amp;gt; “Runtime” &amp;gt; “TwiML Bins”&lt;/li&gt;
      &lt;li&gt;Create two TwiML bins
        &lt;ol&gt;
          &lt;li&gt;One for SMS, that should contain the following code&lt;/li&gt;
        &lt;/ol&gt;

        &lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;Response&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;Message&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;to=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;YOUR PHONE NUMBER&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
     : 
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Message&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Response&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;ol&gt;
          &lt;li&gt;And the one for voice&lt;/li&gt;
        &lt;/ol&gt;

        &lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;Response&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;Dial&amp;gt;&lt;/span&gt;
     YOUR PHONE NUMBER
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Dial&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Response&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;N.B. In the above, insert your phone number. When doing so, it should contain the country code it belongs to. Pre-fixed with the plus character.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Now navigate to “All Products &amp;amp; Services” &amp;gt; “Phone Numbers” &amp;gt; “Manage Numbers” &amp;gt; “Active Numbers”
        &lt;ol&gt;
          &lt;li&gt;Click on your Twilio phone number. Change the “A call comes in” field from “Webbook” to “TwiML” and switch to your custom voice forwarding settings by selecting the appropriate bin name (e.g., “my voice forwarding”). Do the same for the messaging settings.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Install the beta of Signal
    &lt;ol&gt;
      &lt;li&gt;Windows: First, download &lt;a href=&quot;https://updates.signal.org/desktop/beta.yml&quot; class=&quot;no-mark-external&quot;&gt;this&lt;/a&gt; file and look for the url property that specifies the location for the latest beta installer. Download the installer by constructing a final URL that looks like this: &lt;code class=&quot;highlighter-rouge&quot;&gt;https://updates.signal.org/desktop/&amp;lt;installer location&amp;gt;&lt;/code&gt;. Then run the installer&lt;/li&gt;
      &lt;li&gt;macOS: First, download &lt;a href=&quot;https://updates.signal.org/desktop/beta-mac.yml&quot; class=&quot;no-mark-external&quot;&gt;this&lt;/a&gt; file and look for the url property that specifies the location for the latest beta installer. Download the installer by constructing a final URL that looks like this: &lt;code class=&quot;highlighter-rouge&quot;&gt;https://updates.signal.org/desktop/&amp;lt;package location&amp;gt;&lt;/code&gt;. Then unzip that package and copy the .app file into the /Applications folder using &lt;code class=&quot;highlighter-rouge&quot;&gt;Finder&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Linux: Follow the production instructions to set up the APT repository and run &lt;code class=&quot;highlighter-rouge&quot;&gt;apt install signal-desktop-beta&lt;/code&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;If it isn’t already install the official, general available version of Signal. As you will have to run the Beta and the Official one side-by-side. A further guide on how-to install the Official one would be the one on &lt;a href=&quot;https://www.signal.org/download/&quot; class=&quot;no-mark-external&quot;&gt;Signal’s homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Install &lt;code class=&quot;highlighter-rouge&quot;&gt;signal-cli&lt;/code&gt; which is a command-line interface for Signal and will be used for registering, linking and testing Signal with the
acquired public phone number. Get it from &lt;a href=&quot;https://github.com/AsamK/signal-cli/releases&quot; class=&quot;no-mark-external&quot;&gt;Signal-cli download&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;You are now ready and prepped for registering Signal with your phone number provided by &lt;code class=&quot;highlighter-rouge&quot;&gt;Twilio&lt;/code&gt;. So change directory to the folder whereto you installed &lt;code class=&quot;highlighter-rouge&quot;&gt;signal-cli&lt;/code&gt; and…
    &lt;ol&gt;
      &lt;li&gt;Execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;./bin/signal-cli -u PHONE_NUMBER_AKA_USERNAME register&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;./bin/signal-cli -u PHONE_NUMBER_AKA_USERNAME verify THE_CODE_YOU_RECEIVED_ON_YOUR_PHONE&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;To test that the new &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal&lt;/code&gt; account with the &lt;code class=&quot;highlighter-rouge&quot;&gt;Twilio&lt;/code&gt; phone number works, execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;./bin/signal-cli -u PHONE_NUMBER_AKA_USERNAME send -m &quot;crazy stuff&quot; PHONE_NUMBER_AKA_USERNAME_TO_PRIVATE_ACCOUNT&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;Optionally&lt;/em&gt; execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;./bin/signal-cli -u PHONE_NUMBER_AKA_USERNAME_TO_PRIVATE_ACCOUNT receive&lt;/code&gt; if you want to send a message the other way. Meaning, from your private phone number to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal&lt;/code&gt; account with the &lt;code class=&quot;highlighter-rouge&quot;&gt;Twilio&lt;/code&gt; phone number&lt;/li&gt;
      &lt;li&gt;Now we want to &lt;strong&gt;link&lt;/strong&gt; the &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal&lt;/code&gt; account with the &lt;code class=&quot;highlighter-rouge&quot;&gt;Twilio&lt;/code&gt; phone number, but without using a secondary phone
        &lt;ol&gt;
          &lt;li&gt;Ensure that &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal Beta&lt;/code&gt; is started, you must see the QR code screen in the application&lt;/li&gt;
          &lt;li&gt;Scan the QR code with a QR scanner on your phone, to derive the URI that it contains&lt;/li&gt;
          &lt;li&gt;Get the URI to your computer in one way or the other&lt;/li&gt;
          &lt;li&gt;Now with &lt;code class=&quot;highlighter-rouge&quot;&gt;signal-cli&lt;/code&gt; execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;./bin/signal-cli addDevice -u PHONE_NUMBER_AKA_USERNAME --uri &quot;tsdevice:/?uuid=....&lt;/code&gt;
            &lt;ol&gt;
              &lt;li&gt;In the &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal Beta&lt;/code&gt; application you should now be prompted to name the device&lt;/li&gt;
              &lt;li&gt;Name it and proceed, &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal Beta&lt;/code&gt; will load users and groups and finally …. after some loading your are in :+1:&lt;/li&gt;
            &lt;/ol&gt;
          &lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Optionally&lt;/em&gt; heighten the security of your new &lt;code class=&quot;highlighter-rouge&quot;&gt;Signal&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;Twilio&lt;/code&gt; phone number account by setting a &lt;strong&gt;Registration Lock&lt;/strong&gt; pin. Here’s how:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Execute: &lt;code class=&quot;highlighter-rouge&quot;&gt;./bin/signal-cli -u PHONE_NUMBER_AKA_USERNAME setPin PIN_BETWEEN_4_20_CHARS&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And make sure to read the &lt;a href=&quot;https://support.signal.org/hc/en-us/articles/360007059792-Registration-Lock&quot; class=&quot;no-mark-external&quot;&gt;Registration Lock&lt;/a&gt;  article by &lt;code class=&quot;highlighter-rouge&quot;&gt;Whisper Systems&lt;/code&gt;. As there is some pointers to be aware of. Namely that the pin expires if there are no activity on the account for more than 7 days.&lt;/p&gt;

&lt;h2 id=&quot;readings-i-found-useful&quot;&gt;Readings I found useful&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Does Signal send my number to my contacts?&lt;/em&gt; read &lt;code class=&quot;highlighter-rouge&quot;&gt;Whisper Systems&lt;/code&gt; notes on that &lt;a href=&quot;https://support.signal.org/hc/en-us/articles/360007061452-Does-Signal-send-my-number-to-my-contacts-&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;How to Use Signal Without Giving Out Your Phone Number&lt;/em&gt; read The Intercept article on that &lt;a href=&quot;https://theintercept.com/2017/09/28/signal-tutorial-second-phone-number/?comments=1#comments&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;How to install and use Signal messenger without a smartphone&lt;/em&gt; read that guide &lt;a href=&quot;https://ctrl.alt.coop/en/post/signal-without-a-smartphone/&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for reading along.&lt;/p&gt;

&lt;p&gt;Over and out :dash:&lt;/p&gt;</content><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><category term="Signal" /><category term="secure-communication" /><category term="phone-number" /><category term="privacy" /><category term="anonymity" /><summary type="html">The situation</summary></entry><entry><title type="html">OCSP stapling with HAProxy. From pitfall to euphoria</title><link href="https://bengtssondd.it/security/2018/12/30/OCSP-stapling-with-HAProxy-from-pitfall-to-euphoria/" rel="alternate" type="text/html" title="OCSP stapling with HAProxy. From pitfall to euphoria" /><published>2018-12-30T13:00:00+01:00</published><updated>2018-12-30T13:00:00+01:00</updated><id>https://bengtssondd.it/security/2018/12/30/OCSP-stapling-with-HAProxy-from-pitfall-to-euphoria</id><content type="html" xml:base="https://bengtssondd.it/security/2018/12/30/OCSP-stapling-with-HAProxy-from-pitfall-to-euphoria/">&lt;p&gt;It’s that time of the year. Christmas holidays. So I thought to myself. Why be naughty this year? This year I’ll be a good boy.&lt;/p&gt;

&lt;p&gt;Jææææs I will (as if :stuck_out_tongue_winking_eye:).&lt;/p&gt;

&lt;p&gt;I decided to optimize security and a bit of privacy for the websites I’m hosting. Namely:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://bengtssondd.it&quot; class=&quot;no-mark-external&quot;&gt;The bengtssondd blog&lt;/a&gt;. This site.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://skakmatdigte.dk&quot; class=&quot;no-mark-external&quot;&gt;Skakmat digte&lt;/a&gt;. A website for my poems.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://retshjaelp.eu&quot; class=&quot;no-mark-external&quot;&gt;Retshjaelp&lt;/a&gt;. The personal website of the lawyer Kaaveh Piroz.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After having optimized various HTTP security headers for the above websites I wanted to enable OCSP stapling for them as well. Now, this was more of a challenge. I needed to leap over several obstacles.&lt;/p&gt;

&lt;p&gt;They where:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Understanding OCSP stapling&lt;/li&gt;
  &lt;li&gt;Configuring HAProxy to use it&lt;/li&gt;
  &lt;li&gt;Automatizing the continued use of OCSP stapling for the certificates used by the websites in question&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ocsp-stapling&quot;&gt;OCSP stapling&lt;/h1&gt;

&lt;p&gt;OCSP is an acronym for Online Certificate Status Protocol. It is a way for website servers to save on network IO and performance. A way to increase the privacy of your website users. And it makes your website less vulnerable to failing or overloaded CA provider infrastructure.&lt;/p&gt;

&lt;p&gt;OCSP gives you these advantages by:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Taking away the need for end-users to issue calls to the certificate issuer. By offloading certificate revocation calls to the website server
    &lt;ul&gt;
      &lt;li&gt;Resulting in more privacy to the end-user in that their visit to the website is not revealed to the certificate issuer&lt;/li&gt;
      &lt;li&gt;Saving performance for the end-user as their browser will not have to make the lookup&lt;/li&gt;
      &lt;li&gt;Websites loading a tiny tad quicker for the end-user than without OCSP stapling&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Saving on the number of necessary certificate lookup calls to the certificate issuer. As an OCSP file is saved for each certificate on the server and data from that file is presented to visiting users
    &lt;ul&gt;
      &lt;li&gt;While not actually saving performance for the web-server, it is implemented in a way that is well thought out, in regards to lessening the performance burden&lt;/li&gt;
      &lt;li&gt;CA provider infrastructure is a known target for ill intended people. So by caching OCSP responses a website is less vulnerable to DoS attacks on CA’s&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Who doesn’t want that?&lt;/p&gt;

&lt;h1 id=&quot;configuring-haproxy-to-use-ocsp-stapling&quot;&gt;Configuring HAProxy to use OCSP stapling&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://www.haproxy.org/&quot; class=&quot;no-mark-external&quot;&gt;HAProxy&lt;/a&gt; is the load-balancer fronting the mentioned websites. Let’s configure it.&lt;/p&gt;

&lt;p&gt;All HAProxy requires in order to use OCSP stapling is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;An &lt;code class=&quot;highlighter-rouge&quot;&gt;.ocsp&lt;/code&gt; file. Named as the crt/pem file it is covering. With the sole addition that it should have the &lt;code class=&quot;highlighter-rouge&quot;&gt;.ocsp&lt;/code&gt; extension
    &lt;ul&gt;
      &lt;li&gt;The OCSP file for e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;my-certificate.pem&lt;/code&gt; has to be named &lt;code class=&quot;highlighter-rouge&quot;&gt;my-certificate.pem.ocsp&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;.ocsp&lt;/code&gt; file should be valid and in the DER format. To be valid:
    &lt;ul&gt;
      &lt;li&gt;it has to indicate a good status&lt;/li&gt;
      &lt;li&gt;it has to be a single response for the certificate of the PEM file, and it&lt;/li&gt;
      &lt;li&gt;has to be valid at the moment of addition&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More &lt;a href=&quot;https://cbonte.github.io/haproxy-dconv/1.8/configuration.html#5.1-crt&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;readying-haproxy&quot;&gt;Readying HAProxy&lt;/h2&gt;

&lt;p&gt;The stats socket will be utilized for the automatization of HAProxy. This socket is not enabled by default. You need to do the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Enable the stats socket in the &lt;code class=&quot;highlighter-rouge&quot;&gt;haproxy.cfg&lt;/code&gt; file&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    stats socket /haproxysocket/haproxy.sock mode 660 level admin
    stats timeout 2m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;add the above to the &lt;code class=&quot;highlighter-rouge&quot;&gt;global&lt;/code&gt; section in the &lt;code class=&quot;highlighter-rouge&quot;&gt;haproxy.cfg&lt;/code&gt; file.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Reload/restart HAProxy for the above to take effect&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;N.B. If you run HAProxy via a Docker container you need to do something along the lines of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;docker run.... -v /folder/to/contain/the/socket:/haproxysocket/&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;the folder referenced in the &lt;code class=&quot;highlighter-rouge&quot;&gt;-v&lt;/code&gt; specification above is the same folder you use in the script below&lt;/strong&gt;. So by referring to /folder/to/contain/the/socket/haproxy.sock in your &lt;code class=&quot;highlighter-rouge&quot;&gt;socat&lt;/code&gt; cmd you will be “talking” to the socket inside the HAProxy container.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;generating-the-ocsp-file&quot;&gt;Generating the OCSP file&lt;/h2&gt;

&lt;p&gt;So how does one generate the OCSP file. You dig around and find someone like &lt;a href=&quot;https://github.com/icicimov&quot; class=&quot;no-mark-external&quot;&gt;Igor Cicimov&lt;/a&gt;. He made a nice script for generating the OCSP file and configuring HAProxy with it. See his &lt;a href=&quot;https://icicimov.github.io/blog/server/HAProxy-OCSP-stapling/&quot; class=&quot;no-mark-external&quot;&gt;blog post&lt;/a&gt;. However I had to update the script a few places.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This part was not working on my QNAP: &lt;code class=&quot;highlighter-rouge&quot;&gt;ISSUER_NAME=$(echo ${ISSUER_URI##*/}&lt;/code&gt; I had to change it to &lt;code class=&quot;highlighter-rouge&quot;&gt;ISSUER_NAME=$(echo ${ISSUER_URI##*//}&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;And because HAProxy did not like the issuer certificate to be in the same folder as the actual website certificates (because the issuer certificate do not contain a private key), I had to update &lt;code class=&quot;highlighter-rouge&quot;&gt;-out ${DIR}/${ISSUER_NAME}.pem&lt;/code&gt; on the &lt;code class=&quot;highlighter-rouge&quot;&gt;wget&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;openssl ocsp&lt;/code&gt; commands to &lt;code class=&quot;highlighter-rouge&quot;&gt;/tmp/${ISSUER_NAME}_CHOOSE_YOUR_POSTFIX.pem&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I also removed &lt;code class=&quot;highlighter-rouge&quot;&gt;[[ $? -eq 0 ]] &amp;amp;&amp;amp; [[ $(pidof haproxy) ]] &amp;amp;&amp;amp; [[ -s ${DIR}/${CERT}.ocsp ]] &amp;amp;&amp;amp;&lt;/code&gt; from the &lt;code class=&quot;highlighter-rouge&quot;&gt;set ssl ocsp...&lt;/code&gt; line. As I don’t see the use for it and don’t fully grasp what it is trying to do. Feel very free to ping me if you are able to decipher this black magic :smile:. Find my Twitter under “About” in the lower left corner of this site.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After the above changes the script works. However, if you have several certificates and try to run the script for another certificate, the &lt;code class=&quot;highlighter-rouge&quot;&gt;set ssl ocsp.....&lt;/code&gt; command will fail, if there isn’t already an OCSP file for the respective certificate.
The error will be: &lt;code class=&quot;highlighter-rouge&quot;&gt;OCSP single response: Certificate ID does not match any certificate or issuer.&lt;/code&gt; To alleviate this you’ll have to generate the OCSP file for all your certificates and reload HAProxy.
The above issue apparently happens because of the way that OCSP support for HAProxy was designed. Its initial purpose was to update the pre-loaded OCSP record. So if there is no OCSP file for a certificate already, and you execute the &lt;code class=&quot;highlighter-rouge&quot;&gt;set ssl ocsp.....&lt;/code&gt; command, the mentioned error will be thrown.&lt;/p&gt;

&lt;p&gt;More on that error &lt;a href=&quot;https://www.mail-archive.com/haproxy@formilux.org/msg24895.html&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;the-leftovers&quot;&gt;The leftovers&lt;/h1&gt;

&lt;p&gt;With the OCSP file generated and the ability to reload HAProxy when the OCSP file has been updated all there is left now is to do this automatically.&lt;/p&gt;

&lt;p&gt;Simply setup a cron job. Timing it to once a day should suffice.&lt;/p&gt;

&lt;p&gt;When your are satisfied with your setup and want to see the fruits of your effort. Go-to &lt;a href=&quot;https://ssldecoder.org/&quot; class=&quot;no-mark-external&quot;&gt;SSL Decoder&lt;/a&gt; and give it a spin. Under &lt;code class=&quot;highlighter-rouge&quot;&gt;OCSP Stapling&lt;/code&gt;, in the result table it should say &lt;code class=&quot;highlighter-rouge&quot;&gt;Cert status	good&lt;/code&gt; and so forth.&lt;/p&gt;

&lt;p&gt;Congrats on using OCSP stapling. We can all be happy with that.&lt;/p&gt;

&lt;h1 id=&quot;useful-resources&quot;&gt;Useful resources&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://cbonte.github.io/haproxy-dconv/1.8/management.html#9.3-set%20ssl%20ocsp-response&quot; class=&quot;no-mark-external&quot;&gt;The set ssl ocsp-response cmd&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/44869004/volume-mount-haproxy-socket-from-haproxy-docker-container&quot; class=&quot;no-mark-external&quot;&gt;Talking to the HAProxy socket inside a Docker container&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.haproxy.com/blog/dynamic-configuration-haproxy-runtime-api/&quot; class=&quot;no-mark-external&quot;&gt;HAProxy configuration via the API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;Thank you for reading along.&lt;/p&gt;

&lt;p&gt;Over and out :dash:&lt;/p&gt;</content><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><category term="HAProxy" /><category term="OCSP-stapling" /><category term="certificates" /><category term="revocation" /><category term="LetsEncrypt" /><category term="bash" /><summary type="html">It’s that time of the year. Christmas holidays. So I thought to myself. Why be naughty this year? This year I’ll be a good boy.</summary></entry><entry><title type="html">When you are lucky good. A story on a rotten character. That trashed .netrc and therefore ConcourseCI resources.</title><link href="https://bengtssondd.it/devops/troubleshooting/2018/10/16/When-you-are-lucky-good/" rel="alternate" type="text/html" title="When you are lucky good. A story on a rotten character. That trashed .netrc and therefore ConcourseCI resources." /><published>2018-10-16T00:00:00+02:00</published><updated>2018-10-16T00:00:00+02:00</updated><id>https://bengtssondd.it/devops/troubleshooting/2018/10/16/When-you-are-lucky-good</id><content type="html" xml:base="https://bengtssondd.it/devops/troubleshooting/2018/10/16/When-you-are-lucky-good/">&lt;p&gt;This is a journey into the world of troubleshooting, pulling out ones own hair and coming out wiser and happier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So I had this issue:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;resource script '/opt/resource/check []' failed: exit status 1

stderr:
Cloning into '/tmp/semver-git-repo'...
fatal: could not read Username for 'https://bengtssondd.it': No such device or address
error checking for new versions: exit status 128`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This happened when the &lt;code class=&quot;highlighter-rouge&quot;&gt;semver&lt;/code&gt; (semantic versioning) resource of the CI product named ConcourseCI tried to poll my private Git backend. It was rather frustrating, as it meant my tirade into setting up a proper build pipeline for the &lt;a href=&quot;https://github.com/larssb/HealOps&quot; class=&quot;no-mark-external&quot;&gt;HealOps&lt;/a&gt; project went into a total halt. Furthermore, the same error occurred for the &lt;code class=&quot;highlighter-rouge&quot;&gt;git&lt;/code&gt; ConcourseCI resource.&lt;/p&gt;

&lt;p&gt;Then what is a man to do? Find the culprit of course. Then smack it in the face….like…kapow!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/gif/smack.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So I tried&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Downgradring to v3.10 of ConourseCI where it used to work. It still didn’t.&lt;/li&gt;
  &lt;li&gt;Thinking about what I had changed in my ConcourseCI setup.
    &lt;ul&gt;
      &lt;li&gt;I had “upgraded” the docker-compose file to v3.2.&lt;/li&gt;
      &lt;li&gt;Updated the Postgres SQL database backend used by ConcourseCI to v10.5.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Then I tried setting up ConcourseCI, the HealOps build pipelin on another Macbook I have. And no error. It works. But why in the world.
    &lt;ul&gt;
      &lt;li&gt;Then I considered what the difference between the two Macbooks is. The MacBook where it works do have a newer version of Git installed. But could that really be it? Does the semver and git resources really use the local version of Git? What is going on here? It would be great to get a clearer view on this issue.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;I followed that line of thought and updated Git on the non-working Mac. I even did a full Docker restart on MacOS. And a full re-install of ConcourseCI (I also removed the Postgres docker volume). The issue remained.&lt;/li&gt;
  &lt;li&gt;Then I saw someone mentioning the &lt;code class=&quot;highlighter-rouge&quot;&gt;fly hijack&lt;/code&gt; command that ConcourseCI have. I went ahead and “hijacked” the worker container in which the semver resource is running. I executed &lt;code class=&quot;highlighter-rouge&quot;&gt;git clone https://bengtssondd.it/git/healops.git&lt;/code&gt; to test git and was prompted for a username and password. When entering those two correctly the git clone command executed without problems. The issue still remained though.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hmmm. Now what. What do you do when you are in the center of the mist are kinda lost. You poke around. Try out new routes. Wave your arms. Find your smartphone flashlight.&lt;/p&gt;

&lt;p&gt;So I poked around while in &lt;code class=&quot;highlighter-rouge&quot;&gt;fly hijack&lt;/code&gt; mode. Did a little &lt;code class=&quot;highlighter-rouge&quot;&gt;ls -la&lt;/code&gt; in various places. Aaaand what was that. In the root of the container filesystem there was a .gitconfig file. Let’s &lt;code class=&quot;highlighter-rouge&quot;&gt;cat .gitconfig&lt;/code&gt; that. Hmmmm nothing in there of interest. Oh my. There is also a .netrc file in the. Let’s hit that with a &lt;code class=&quot;highlighter-rouge&quot;&gt;cat .netrc&lt;/code&gt; as well. Aaaand what do we have in there my friend?&lt;/p&gt;

&lt;p&gt;We had.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;default login myusername password \!MyPassword((88))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Immediately I noticed the leading &lt;code class=&quot;highlighter-rouge&quot;&gt;\&lt;/code&gt;. It shouldn’t be there as it is not a part of the password. It is there in order to act as a escape character to the &lt;code class=&quot;highlighter-rouge&quot;&gt;!&lt;/code&gt; character. Necessary when executing the &lt;code class=&quot;highlighter-rouge&quot;&gt;fly -t myConcoursePipeline set-pipeline --config ./pipeline.yml -p PipelineName --var myusername=\!MyPassword((88))&lt;/code&gt;. If not the &lt;code class=&quot;highlighter-rouge&quot;&gt;!&lt;/code&gt; character will be interpreted as a special-character and not as a regular character that should be a part of the value to the myusername variable.
As soon as I saw that I removed the &lt;code class=&quot;highlighter-rouge&quot;&gt;\&lt;/code&gt; character via Vi. Then tried my &lt;code class=&quot;highlighter-rouge&quot;&gt;git clone https://bengtssondd.it/git/healops.git&lt;/code&gt; command again. This time with no prompts. I think we are there. A nice bubbly feeling started to ooze in my chest :yum:. I looked up .netrc and I was further re-assured in this being the culprit. .netrc is a part of the Linux auto-login system. It is used for providing login info automatically as the name implies.
I tested by updating the HealOps pipeline yml file » comitted it to ConcourseCI with the &lt;code class=&quot;highlighter-rouge&quot;&gt;fly -t myConcoursePipeline set-pipeline....&lt;/code&gt; command. Waiting … tic … toc … tic … toc :watch:.&lt;/p&gt;

&lt;p&gt;Ta-da freaking laaaaaa. It worked. That was it. A special-character f&lt;strong&gt;**&lt;/strong&gt; up my life. However, nice that I was able to half troubleshoot myself en route to the culprit, half stumble over it.&lt;/p&gt;

&lt;p&gt;Now I just have some failing Pester tests when HealOps is building. More on that in a later post.&lt;/p&gt;

&lt;p&gt;For now, onto filling out a bug report on the Concourse semver and git resource GitHub pages. I think special characters should be supported. The &lt;a href=&quot;https://github.com/concourse/git-resource/issues/219&quot; class=&quot;no-mark-external&quot;&gt;bug report&lt;/a&gt; for reference.&lt;/p&gt;

&lt;p&gt;Thank you for reading along.&lt;/p&gt;

&lt;p&gt;Over and out :dash:&lt;/p&gt;</content><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><category term="ConcourseCI" /><category term=".netrc" /><category term="git" /><category term="special-characters" /><summary type="html">This is a journey into the world of troubleshooting, pulling out ones own hair and coming out wiser and happier.</summary></entry><entry><title type="html">HealOps, the healing monitoring framework. Part 1 - Why HealOps?</title><link href="https://bengtssondd.it/devops/healops/2018/08/11/HealOps-the-self-healing-monitoring-framework-part1/" rel="alternate" type="text/html" title="HealOps, the healing monitoring framework. Part 1 - Why HealOps?" /><published>2018-08-11T19:00:00+02:00</published><updated>2018-08-11T19:00:00+02:00</updated><id>https://bengtssondd.it/devops/healops/2018/08/11/HealOps-the-self-healing-monitoring-framework-part1</id><content type="html" xml:base="https://bengtssondd.it/devops/healops/2018/08/11/HealOps-the-self-healing-monitoring-framework-part1/">&lt;h1 id=&quot;intro-and-info&quot;&gt;Intro and info.&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/HealOps_Part1_WhyHealOps_pic2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The diagram above is a context diagram over HealOps. It displays the components that are a part of HealOps. What they deliver to the system and whether they input or extract data in relation to their role in the system. Finally the actors of the system can be identified.&lt;/p&gt;

&lt;p&gt;HealOps is a monitoring and healing framework, developed primarily in PowerShell, for IT systems and their components. I designed and developed it with the motivation of getting fewer on-duty calls, save time and as a way to reach a system uptime that is as near 100% as possible.
The thought is that by creating a system, that uses the TDD (Test Driven Development) process. You have a clear and formalized set of rules to test the state of an IT system and its components. This then makes it possible to act and repair an identified broken system state. The identification and repairing of a broken system state happens automatically.
Throughout this cycle of testing and potentially repairing state, state data is automatically reported to a Time Series Database. State data can then be pulled into a monitoring and visualization system like &lt;a href=&quot;https://grafana.com/&quot; class=&quot;no-mark-external&quot;&gt;Graphana&lt;/a&gt;. From Grafana and other systems like it, it is possible to integrate with an incident management system. With this setup a potential broken state of an IT system, that could &lt;strong&gt;not&lt;/strong&gt; be fixed, is reported to Grafana, which in turn sends a request to an incident management system. Then the incident management system can be configured to automatically trigger an alert to the on-call duty personnel. Thereby getting us some human eyeballs on the issue.&lt;/p&gt;

&lt;p&gt;A visualization of the above description of state monitoring and repairing will likely help on understanding HealOps. A sequence diagram comes in handy.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/HealOps_Part1_WhyHealOps.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The above image shows the main functions involved when testing and repairing the state of an IT system component.&lt;/p&gt;

&lt;p&gt;For everything related to HealOps, look now further:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Code &amp;gt; &lt;a href=&quot;https://github.com/larssb/HealOps&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;News &amp;gt; Right here where you are. My Bengtssondd blog.&lt;/li&gt;
  &lt;li&gt;The occasional update &amp;gt; &lt;a href=&quot;https://twitter.com/SkakmatP&quot; class=&quot;no-mark-external&quot;&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;spill-the-beans-what-are-the-benefits-of-using-healops&quot;&gt;Spill the beans. What are the benefits of using HealOps?&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;You save time by reducing the number of times where you have to “pull the chestnuts out of the fire”.&lt;/li&gt;
  &lt;li&gt;You save up energy and lust for fixing and improving instead of just maintaining and keeping above water.&lt;/li&gt;
  &lt;li&gt;Monitoring and healing via HealOps happens automatically. A scheduler is used as a facilitator for running jobs that monitors the state of one or more components of an IT system. Thereby reducing the reaction time from identifying a broken state of a service until a repair of that service kicks in.&lt;/li&gt;
  &lt;li&gt;What is being done and what was done is clear to everyone.
    &lt;ul&gt;
      &lt;li&gt;How and what is tested is clearly formalized in code in a test file.&lt;/li&gt;
      &lt;li&gt;State data is reported to a monitoring and visualization backend system.&lt;/li&gt;
      &lt;li&gt;Reports can be generated on state data. As well as on the cases where an alarm was triggered for human intervention.&lt;/li&gt;
      &lt;li&gt;HealOps logs what it does along the way.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;When you are on-call duty and get an alarm. The info you get along with the alarm is at a high detail level. As you can send along a screenshot of what triggered an alarm in Grafana. Also, it is possible, in most incident management systems to specify information to send with a triggered alarm. This could be a wiki article, tips and tricks, what often resolves a given case and so forth.&lt;/li&gt;
  &lt;li&gt;HealOps could save you money on personnel that is employed only to glance at screens in order to &lt;em&gt;react&lt;/em&gt;  in case of a state going bunkers. As HealOps automatically identifies a state, very likely quicker than a human, and then automatically tries to repair the broken state.
    &lt;ul&gt;
      &lt;li&gt;The money saved could then be used on personnel that improves the product you sell. The end-customer experience. Company facilities and so on.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;It is open-source and free.
    &lt;ul&gt;
      &lt;li&gt;You can review the code.&lt;/li&gt;
      &lt;li&gt;Help and commit new features and fix bugs. And thereby speed-up the delivery of the features you would like to have included or the bugs that needs to be fixed.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;any-downsides&quot;&gt;Any downsides?&lt;/h1&gt;

&lt;p&gt;Fair question. Here’s the ones I’ve been able to identify so far.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Only one Time Series Database backend is currently supported. Namely &lt;a href=&quot;http://opentsdb.net/&quot; class=&quot;no-mark-external&quot;&gt;OpenTSDB&lt;/a&gt;.
    &lt;ul&gt;
      &lt;li&gt;It’s the plan to support several more over time.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;There is only a few HealOps packages currently available. A HealOps package is the entity that holds Tests and Repairs files. A Tests file is invoked in order to verify the state of a component of an IT system. If its state is broken it will be tried repaired via the Repairs file. As you can understand, these packages are both an integral part, as well as very useful.
So you will have to do a little bit of work here, in order to be able to us HealOps together with the IT systems you have.
Luckily I’ve designed the way to develop a HealOps package so that it could be standardized and easy to follow. So with a little bit of practice and by reading the (upcoming) documentation you should be able to do like a boss.&lt;/li&gt;
  &lt;li&gt;Running HealOps on Linux and MacOS is right now not officially supported. But it is the number one priority. The plan is to support it within the next 2-4 months.&lt;/li&gt;
  &lt;li&gt;As HealOps is developed in PowerShell it is not extremely performant. However, I’m considering refactoring parts of HealOps. Meaning that HealOps, in the future, might become a binary PowerShell module.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;healops-needs-a-back-rub&quot;&gt;HealOps needs a back rub.&lt;/h1&gt;

&lt;p&gt;There are several features I would like to implement in HealOps. Number one on the list is job scheduling on Linux and MacOS. But there is more. Full testing of the HealOps code. In Pester. Documentation. Considering supporting container virtualization. Creating prototypes for that….and the list goes on.
But time is flying.&lt;/p&gt;

&lt;p&gt;So, if you think HealOps is a cool system and the type of project you could see yourself spend time on. Be my guest. I would highly appreciate it. If you have any questions or need more info, before you commit yourself. Feel free to hit me up on Twitter or LinkedIn (links for those services can be found in the lower left corner on this blog).&lt;/p&gt;

&lt;h1 id=&quot;coming-up&quot;&gt;Coming up.&lt;/h1&gt;

&lt;p&gt;In part two on HealOps, I plan to describe the components of HealOps itself in great detail. The technical nerdy stuff. I hope you will read along when that comes out.&lt;/p&gt;

&lt;p&gt;Until then you are more than welcome to have a look at the code. Find it &lt;a href=&quot;https://github.com/larssb/HealOps&quot; class=&quot;no-mark-external&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;adieu&quot;&gt;Adieu.&lt;/h1&gt;

&lt;p&gt;I hope you enjoyed this post and that you will checkout HealOps. Thank you for reading along.&lt;/p&gt;

&lt;p&gt;Over and out :dash:&lt;/p&gt;</content><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><category term="HealOps" /><category term="Healing" /><category term="Monitoring" /><category term="DevOps" /><category term="PowerShell" /><category term="Framework" /><category term="Programming" /><summary type="html">Intro and info.</summary></entry><entry><title type="html">Wording my graphing</title><link href="https://bengtssondd.it/programming/powershell/static-analysis/2018/08/05/Wording-my-graphing/" rel="alternate" type="text/html" title="Wording my graphing" /><published>2018-08-05T00:00:00+02:00</published><updated>2018-08-05T00:00:00+02:00</updated><id>https://bengtssondd.it/programming/powershell/static-analysis/2018/08/05/Wording-my-graphing</id><content type="html" xml:base="https://bengtssondd.it/programming/powershell/static-analysis/2018/08/05/Wording-my-graphing/">&lt;p&gt;I bet you know the feeling of running &lt;code class=&quot;highlighter-rouge&quot;&gt;Install-Module -Name SomeInterestingModule&lt;/code&gt;, waiting, then, with your fingers on the keys, so ready to go play with &lt;code class=&quot;highlighter-rouge&quot;&gt;SomeInterestingModule&lt;/code&gt; just downloaded. You stop. Pause. Thinking to yourself: &lt;em&gt;where do I start with this module?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Okay, you could run &lt;code class=&quot;highlighter-rouge&quot;&gt;Get-Command -Module SomeInterestingModule&lt;/code&gt; and then &lt;code class=&quot;highlighter-rouge&quot;&gt;Get-Help Get-CommandInSomeInterestingModule&lt;/code&gt;. However, the module would still be a blackbox. This is where my function &lt;code class=&quot;highlighter-rouge&quot;&gt;Out-PSModuleCallGraph&lt;/code&gt; comes into play. It helps you dive into the inner workings of &lt;code class=&quot;highlighter-rouge&quot;&gt;SomeInterestingModule&lt;/code&gt;. The commands the public commands of the module are calling, what those commands are calling and so forth. In other words. A way for you to get a look behind the scenes. And thereby an idea into which commands to go-to in specific situations.&lt;/p&gt;

&lt;p&gt;Here is some goodies on how to use &lt;code class=&quot;highlighter-rouge&quot;&gt;Out-PSModuleCallGraph&lt;/code&gt; and the experience I had developing it.&lt;/p&gt;

&lt;h1 id=&quot;use-it&quot;&gt;Use it!&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Run &lt;code class=&quot;highlighter-rouge&quot;&gt;Save-Script -Name Out-PSModuleCallGraph -Path &quot;PATH_WHERE_YOU_WANT_TO_STORE_THE_FILE&quot;&lt;/code&gt; (you could also use &lt;code class=&quot;highlighter-rouge&quot;&gt;Install-Script&lt;/code&gt;. But with Save-Script you have more control and can look through the code (for security reasons))
    &lt;ol&gt;
      &lt;li&gt;Pre-requisites:
        &lt;ul&gt;
          &lt;li&gt;A connection to the Internet.&lt;/li&gt;
          &lt;li&gt;The PSGallery should be registered for the PowerShellGet module to use (&lt;a href=&quot;https://www.powershellgallery.com/&quot;&gt;Guide to the PowerShellGallery&lt;/a&gt;).&lt;/li&gt;
          &lt;li&gt;PowerShell 5.1+ on your box. (PSCore if on Linux or MacOS).&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Dot-source the script. E.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;. &quot;PATH_WHERE_YOU_STORED_THE_FILE&quot;&lt;/code&gt;. When you want to use it.
    &lt;ul&gt;
      &lt;li&gt;Here is an example of dot-sourcing &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;. ./usr/local/share/powershell/Scripts/Out-PSModuleCallGraph.ps1&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;After you have dot-sourced the Out-PSModuleCallGraph script, the Out-PSModuleCallGraph command is available in your PowerShell session. So now execute Out-PSModuleCallGraph. E.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;Out-PSModuleCallGraph -ModuleName Pester -ShowGraph&lt;/code&gt;. That cmdline will generate a call graph on the Pester module and show you the Graph after it has been generated.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;learning-outcomes-of-developing-out-psmodulecallgraph&quot;&gt;Learning outcomes of developing Out-PSModuleCallGraph.&lt;/h1&gt;

&lt;p&gt;The best thing about programming is that you learn so much and it gets you deeper into the labyrinth of how stuff works in the world of IT. Not the least, it strongly requires your talent for being creative. It’s just b e a utiful…..Allllllrighty then!!! Let’s go. In the below I will share learnings and tips that I got out of developing Out-PSModuleCallGraph.&lt;/p&gt;

&lt;h2 id=&quot;attacking-the-problem&quot;&gt;Attacking the problem.&lt;/h2&gt;

&lt;p&gt;In this case it was all about identifying the info I needed to derive from a PowerShell module being analyzed in order to be able to generate a call-graph on the module.
I came up with the following list.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Identify the public functions.&lt;/li&gt;
  &lt;li&gt;Identify the private functions.&lt;/li&gt;
  &lt;li&gt;Somehow, parse these functions in order to infer what commands/functions they use.&lt;/li&gt;
  &lt;li&gt;Find a way to tag the commands each function uses. So that it can be identified what the scope of the command is. Meaning. If it is a public command in the same module. A private command in the same module or an external command, so not a part of the module.&lt;/li&gt;
  &lt;li&gt;Register the chronological order of the commands called in the functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s concentrate on the tough challenges &amp;gt; Identifying the private functions and how to tell the boundaries of a function via code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to tell where a function ends&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yeah how exactly do you do that? Especially when you can’t glance at the code with those preying eyeballs. The solution I came up with, was to count brackets (these guys &amp;gt; {}). Funny how something you learned when walking your baby programmer shoes comes in handy later on.
So the story goes…..When I started out programming and was so foolish not to use a proper IDE. It was before the days of &lt;code class=&quot;highlighter-rouge&quot;&gt;VS Code&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Atom&lt;/code&gt; and the like. You could somewhat easily end-up “forgetting” to end a function declaration or so. You would then get a run-time error along the lines of &lt;code class=&quot;highlighter-rouge&quot;&gt;...missing closing bracket }....&lt;/code&gt;.
So now you had to figure out where this ending bracket was missing. You then had to count from the starting bracket. Add to your brain memory counter every time you encountered a starting bracket in the code. Detract when a closing bracket was encountered. You then knew you had the closing bracket when the calculation was at a nice round 0.
So I basically programmed a function to use with Out-PSModuleCallGraph that calculates the boundaries of a function by counting brackets. Lovely!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identifying private functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Identifying the public functions is quite easy. It’s just = Import the module being analyzed » then use the &lt;code class=&quot;highlighter-rouge&quot;&gt;Get-Command&lt;/code&gt; Cmdlet to get the public functions of the module.&lt;/p&gt;

&lt;p&gt;The private functions though, that is quite different. A private function is … yeah … private. So there is nothing else to do than parse the code of every file in a PowerShell module » determine the declared functions in the files » look into a list of the public functions » if the function is not in the list » it is private. It takes some time and requires juggling around with several collections. But that’s how I did it.
You might have asked yourself. What does this dude mean by “…parse the code….” in the above. Let me explain. What is really going on there is e.g.:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Tokenize the content of the file
$ast = [System.Management.Automation.PSParser]::Tokenize( (Get-Content -Path $PS1File.FullName), [ref]$null)

# Identify the declared functions in the file. Goes from top to bottom. So the first declared function will be at idx 0
[Array]$DeclaredFunctions = $ast.where( { $_.Type -eq &quot;Keyword&quot; -and $_.Content -eq &quot;function&quot; } )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The code above is from the code section in Out-PSModuleCallGraph where private functions is being processed. A PS1 file is read » the internal .NET class *.Automation.PSParser is being used to divide the code in the file into AST tokens. AST stands for abstract syntax tree and is something you can read more about &lt;a href=&quot;https://en.wikipedia.org/wiki/Abstract_syntax_tree&quot;&gt;here&lt;/a&gt;. It is really powerful so give the link a friendly click.
I then, throughout the code use the &lt;code class=&quot;highlighter-rouge&quot;&gt;.Where()&lt;/code&gt; method of the AST object to filter on the AST. In order to e.g. get me the declared functions, the AST tokens containing brackets and so forth. What a joy / the AST is my toy.&lt;/p&gt;

&lt;h2 id=&quot;tips-and-tricks&quot;&gt;Tips and tricks&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tips on PowerShell parameter validation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don’t often see people validate collections. It is the nice thing to do :smile: and it is easy. E.g.:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Parameter(Mandatory, ParameterSetName=&quot;LinesToExclude&quot;)]
[ValidateScript({$_.Count -ge 1})]
[System.Collections.ArrayList]$LinesToExclude
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;validates that the collection of type ArrayList actually contains members. I would say that it is good coding style to fail early. Especially in regards to parameter validation. Whenever you can do that early, please do! It helps the end-user and makes your code cleaner, as some conditionals can be avoided in the code.&lt;/p&gt;

&lt;p&gt;Another one is to be specific on the type of the parameter. PowerShell is not a strongly typed language. However, as for many other programming languages it helps to declare the type when declaring variables. The IDE you use can infer much more on the code you are writing. And you will be helping the end-user by declaring the type of a parameter. As PowerShell will be able to tell the end-user that the value they are trying to feed into a parameter is wrong and state what the type needs to be.
As you can see by the below example you can get pretty crazy when specifying the type. So be as specific as needs be.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Parameter(Mandatory)]
[ValidateScript({$_.Count -ge 1})] # Validate that it is not an empty collection.
[System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSToken]]$AST
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The type declaration is the &lt;code class=&quot;highlighter-rouge&quot;&gt;[System.Collections.ObjectModel.Collection&lt;/code&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;1[System.Management.Automation.PSToken]]$AST&lt;/code&gt; part.&lt;/p&gt;

&lt;h1 id=&quot;let-me-use-out-psmodulecallgraph-to-exemplify&quot;&gt;Let me use Out-PSModuleCallGraph to exemplify.&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;I followed the guide under &lt;a href=&quot;#use-it&quot;&gt;Use it!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Ran &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;Out-PSModuleCallGraph -ModuleRoot ./FranzJaeger/FranzJaegerClient/ -OutputFormat jpg -ShowGraph&lt;/code&gt;. Which gave me:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/wordingMyGraphing_pic1.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wonderful. What can we reason from that picture.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;We can quickly get an overview over the number of public functions in the module.&lt;/li&gt;
  &lt;li&gt;The names of every function in the module.&lt;/li&gt;
  &lt;li&gt;What calls what.&lt;/li&gt;
  &lt;li&gt;Which external commands are used.&lt;/li&gt;
  &lt;li&gt;The chronological order by which a function calls the commands it uses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;kudos&quot;&gt;Kudos&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;Thank you Brian Bunke. Your &lt;a href=&quot;http://www.brianbunke.com/blog/2017/01/09/publishing-scripts/&quot; class=&quot;no-mark-external&quot;&gt;publishing-scripts&lt;/a&gt; blog post helped me publish the script to the PSGallery.&lt;/li&gt;
  &lt;li&gt;Thank you &lt;a href=&quot;https://kevinmarquette.github.io/blog&quot; class=&quot;no-mark-external&quot;&gt;Kevin Marquette&lt;/a&gt;. For developing &lt;a href=&quot;https://github.com/KevinMarquette/PSGraph&quot;&gt;PSGraph&lt;/a&gt;. Out-PSModuleCallgraph uses PSGraph to generate the graph after analyzing a PowerShell module.&lt;/li&gt;
  &lt;li&gt;Thank you &lt;a href=&quot;https://www.linkedin.com/in/mikkel-r%C3%B8mer/&quot; class=&quot;no-mark-external&quot;&gt;Mikkel Rømer&lt;/a&gt;. For discussing this idea with me and for giving me some tips on how to possibly attack the challenge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;postludium&quot;&gt;Postludium&lt;/h1&gt;

&lt;p&gt;Thank you for reading along. I hope you learned something and that you can use the Out-PSModuleCallGraph script/function.&lt;/p&gt;

&lt;p&gt;Nota bene. If you bump into a bug or have a feature request feel free to report them to the issues section on this GitHub repository &lt;a href=&quot;https://github.com/larssb/PowerShellTooling/issues&quot;&gt;PowerShellTooling-Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Over and out :dash:&lt;/p&gt;</content><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><category term="PowerShell" /><category term="Static-Analysis" /><category term="Call-Graphs" /><summary type="html">I bet you know the feeling of running Install-Module -Name SomeInterestingModule, waiting, then, with your fingers on the keys, so ready to go play with SomeInterestingModule just downloaded. You stop. Pause. Thinking to yourself: where do I start with this module?</summary></entry><entry><title type="html">Publishing the blog with ConcourseCI</title><link href="https://bengtssondd.it/blog-devops/2018/04/21/publishing-the-blog-with-ConcourseCI/" rel="alternate" type="text/html" title="Publishing the blog with ConcourseCI" /><published>2018-04-21T00:00:00+02:00</published><updated>2018-04-21T00:00:00+02:00</updated><id>https://bengtssondd.it/blog-devops/2018/04/21/publishing-the-blog-with-ConcourseCI</id><content type="html" xml:base="https://bengtssondd.it/blog-devops/2018/04/21/publishing-the-blog-with-ConcourseCI/">&lt;p&gt;Okay. The blog is up and running (yeah &lt;a href=&quot;https://bengtssondd.it/blog-launch/2018/03/18/booting-up-the-blog/&quot; class=&quot;no-mark-external&quot;&gt;it’s alive&lt;/a&gt;). With that of the bucket list on to the next work item on the list: Build and publish. 
My process of publishing new posts and generating the website with Jekyll, has up until now been quite cumbersome. Furthermore, some time ago I heard about a piece of CI software called ConcourseCI. I felt so enthused about it that I wanted to try it out. See if it could make it work for my own software pipelines as well maybe use it at work.&lt;/p&gt;

&lt;p&gt;How I made publishing of my blog easy with ConcourseCI will be the spicy ingredients of this post.&lt;/p&gt;

&lt;h1 id=&quot;concourseCI-what-about-it-header&quot;&gt;ConcourseCI - yeah what about it?&lt;/h1&gt;

&lt;p&gt;ConcourseCI is the work child of &lt;a href=&quot;https://github.com/vito&quot; class=&quot;no-mark-external&quot;&gt;Alex Suraci&lt;/a&gt; and &lt;a href=&quot;https://github.com/xoebus&quot; class=&quot;no-mark-external&quot;&gt;Christopher Brown&lt;/a&gt;. They, and a team of engineers has, for some years, been sponsored by &lt;a href=&quot;https://pivotal.io/&quot; class=&quot;no-mark-external&quot;&gt;Pivotal&lt;/a&gt;. A spin-out from EMC and VMWare. And a major player in the CloudFoundry project. ConcourseCI, as the name implies, is a continuous integration software product. Its advantages and what separates it from its competitors are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Build config is entirely codified. Nothing is in a hard to find sub-menu in a GUI.&lt;/li&gt;
  &lt;li&gt;Can run in Docker containers.&lt;/li&gt;
  &lt;li&gt;Builds are always atomic.
    &lt;ul&gt;
      &lt;li&gt;Builds run inside a container (the virtualization technology), spun up to execute that single build.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Build ‘x’ cannot effect build ‘y’. As builds run inside a sealed of container you won’t have e.g. a global variable spill into the next build. That could be a serious issue if that build also uses the variable.&lt;/li&gt;
  &lt;li&gt;It is very comforting that you can stand to loose your build server and its setup. As all you have to do is spin-up your ConcourseCI setup once again, which you can do easily. Because you:
    &lt;ul&gt;
      &lt;li&gt;Used technology such as Docker Compose or Docker Stack.&lt;/li&gt;
      &lt;li&gt;Used Infrastructure As Code (I like to call it “Infrastructure From Code”).&lt;/li&gt;
      &lt;li&gt;Described your build pipelines in YAML. So you’ll just have to push them to ConcourseCI, when it’s up again after a breakdown and you are good to go.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;It has a very friendly community at least to the extend I have been involved with it. And that is around five-six times the last month.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of its disadvantages are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Its a rather new CI product on the market. So it hasn’t been battle-tested in a great number of companies. However, it is part of some major software build pipelines. E.g. at Pivotal.&lt;/li&gt;
  &lt;li&gt;At least for me, was an entirely new way of designing your build pipelines. Learning the syntax of ConcourseCI to write the required YAML for a Jekyll build required some trial and error and a lot of reading. It takes time to get around the concepts of ConcourseCI. But that’s how it goes whenever a new kid arrives on the block. You have to get acquainted with the kid first before you find out that, yes they are actually befriend-able.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;concourseci-lets-get-at-it&quot;&gt;ConcourseCI, let’s get at it.&lt;/h1&gt;

&lt;h2 id=&quot;what-i-wanted-to-accomplish-with-concourseci&quot;&gt;What I wanted to accomplish with ConcourseCI&lt;/h2&gt;

&lt;p&gt;Primarily to get a way to automatize and formalize the build and publish of my Jekyll website (the one you are reading on right now). However, I especially wanted to find out if ConcourseCI could hone up to the impressions reading about it gave me.&lt;/p&gt;

&lt;p&gt;In work-items this measures into:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Trigger a build whenever a push to the git repository, holding the bengtssondd.it code, happens.&lt;/li&gt;
  &lt;li&gt;Use semantic versioning to bump builds and thereby software releases.&lt;/li&gt;
  &lt;li&gt;Generate bengtssondd.it with the &lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll build --destination /PATH/&lt;/code&gt; cmd.&lt;/li&gt;
  &lt;li&gt;Notify myself on telegram, when the build is done, with my own little telegram bot.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;installing-it&quot;&gt;Installing it&lt;/h2&gt;

&lt;p&gt;Initially I wanted to run ConcourseCI on my QNAP NAS. However, I wasn’t able to make it work. I created a case with QNAP support. Waited, pinged them for status updates again and again. I have to say. Their response time is certainly not impressive. However, they did end up giving me the cause of the issue. The conntrack kernel module is not enabled in the current QNAP firmware version. It will be for the next one == v4.3.5. Yay! That won’t help me now, but it’s always good to know the whys.
So. I ended up running ConcourseCI on my Mac.&lt;/p&gt;

&lt;h4 id=&quot;the-nitty-gritty-details-of-the-conntrack-issue-feel-free-to-jump-this&quot;&gt;&lt;em&gt;The nitty gritty details of the conntrack issue (feel free to jump this)&lt;/em&gt;&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;It was the ConcourseCI worker container that did not want to start up. It would just throw the error &lt;code class=&quot;highlighter-rouge&quot;&gt;concourse-worker_1 | iptables: No chain/target/match by that name.&lt;/code&gt; I sought help on the ConcourseCI Slack channel and got plenty. That helped me identify the source of the error. Which was &lt;a href=&quot;https://github.com/cloudfoundry/guardian/blob/6d47432dcf401d08ea00b2da13741412e656503d/kawasaki/iptables/global_chains.go&quot; class=&quot;no-mark-external&quot;&gt;this line in the CloudFoundry Guardian software&lt;/a&gt;. So this script tries to create some iptables rules in order for the ConcourseCI software to work as intended network wise. But! Because the conntrack network kernel module isn’t enabled on my QNAP right now, this fails.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I used the following docker-compose.yml file to run ConcourseCI on my Mac.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;version: '3'

services:
  concourse-db:
    image: postgres:9.6
    environment:
      POSTGRES_DB: concourse
      POSTGRES_USER: concourse
      POSTGRES_PASSWORD: 
      PGDATA: /database

  concourse-web:
    image: concourse/concourse:3.10.0
    links: [concourse-db]
    command: web
    depends_on: [concourse-db]
    ports: [&quot;9090:8080&quot;]
    volumes: [&quot;./keys/web:/concourse-keys&quot;]
    restart: unless-stopped # required so that it retries until concourse-db comes up
    environment:
      CONCOURSE_BASIC_AUTH_USERNAME: concourse
      CONCOURSE_BASIC_AUTH_PASSWORD: 
      CONCOURSE_EXTERNAL_URL: http://IP_OR_DOMAIN:9090
      CONCOURSE_POSTGRES_HOST: concourse-db
      CONCOURSE_POSTGRES_USER: concourse
      CONCOURSE_POSTGRES_PASSWORD: 
      CONCOURSE_POSTGRES_DATABASE: concourse

  concourse-worker:
    image: concourse/concourse:3.10.0
    privileged: true
    links: [concourse-web]
    depends_on: [concourse-web]
    command: worker
    volumes: [&quot;./keys/worker:/concourse-keys&quot;]
    environment:
      CONCOURSE_TSA_HOST: concourse-web:2222
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And generally followed &lt;a href=&quot;https://concourse-ci.org/install.html.&quot; class=&quot;no-mark-external&quot;&gt;the ConcourseCI installation guide&lt;/a&gt;. Especially the key generating part is important to get right. As a difference from the docker-compose.yml files I found in places like the ConcourseCI website, their Slack channel and the like, I had to explicitly define the SSH port of the TSA Host, that the ConcourseCI worker should use. Notice the &lt;code class=&quot;highlighter-rouge&quot;&gt;CONCOURSE_TSA_HOST: concourse-web:2222&lt;/code&gt; line in the docker-compose.yml file above. This is because I don’t run SSH on the standard port.&lt;/p&gt;

&lt;h3 id=&quot;the-doh-doʊʔ-doh-segment-to-installing-it&quot;&gt;The “D’oh!” (/doʊʔ/ DOH) segment to “Installing it”&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Please don’t do the same mistake as me. I defined a password for my generated SSH key. As ConcourseCI uses the generated SSH keys to setup an SSH tunnel and does not use password prompting it won’t work if you define a password. I had to bow my head and go back to the cmdline to re-generate the SSH keys. But, hey I got wiser by troubleshooting why the *€#&amp;amp;%/&amp;amp;/””!€%# thing wasn’t working.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;configuring-it&quot;&gt;Configuring it&lt;/h2&gt;

&lt;h3 id=&quot;the-concourseci-pipeline-yaml-file&quot;&gt;The ConcourseCI pipeline YAML file&lt;/h3&gt;

&lt;p&gt;I made myself a fine little YAML file for my ConcourseCI pipeline. You can call it whatever, but a saying name is likely going to help you in the long run. So please contain yourself. I called mine: &lt;code class=&quot;highlighter-rouge&quot;&gt;bengtssondd-pipeline.yml&lt;/code&gt;.
I won’t go through the entire file. Rather I’ll describe the concepts on which I stumbled and the issues I had when configuring ConcourseCI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;input / output and paths&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ConcourseCI has the concept of input and output.&lt;/p&gt;

&lt;p&gt;Names in your output definition will make ConcourseCI create directories in which your build task should store artifacts for later steps to digest.&lt;/p&gt;

&lt;p&gt;Inputs uses outputs from others steps or resources. The names you use for input and output will logically be the root folders or at least part of your folder path to be used in other elements of your build pipeline. E.g. if you have a resource named repo (that gets you the commit in a repository), that you use in a &lt;code class=&quot;highlighter-rouge&quot;&gt;get&lt;/code&gt; step and therefore use as input for your &lt;code class=&quot;highlighter-rouge&quot;&gt;task&lt;/code&gt;. Then you should also use this name as part of the logical path in e.g. a build script. Keep this in mind at all times, when working with ConcourseCI. Because it is such an integral part of building your pipeline and using artifacts between job steps.&lt;/p&gt;

&lt;p&gt;Now seeing is believing, at least for most people, so let me finish this section by providing you with the slightly edited&lt;code class=&quot;highlighter-rouge&quot;&gt;bengtssondd-pipeline.yml&lt;/code&gt;file. Of course I removed passwords and other telling data bits.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;resource_types:
- name: rsync-resource
  type: docker-image
  source:
      repository: mrsixw/concourse-rsync-resource
      tag: latest
- name: telegram-notification
  type: docker-image
  source:
    repository: w32blaster/concourse-telegram-notifier
    tag: latest

resources:
- name: status-message
  type: telegram-notification
  source:
    bot_token: ((tgram_token))
- name: repo
  type: git
  source: 
    branch: master
    password: ((qgit_pass))
    uri: https://URI_TO_GIT_REPO/myRepo.git
    username: qgit
- name: version
  type: semver
  source:
    branch: version
    driver: git
    file: version
    initial_version: 1.0.0
    password: ((qgit_pass))
    uri: https://URI_TO_GIT_REPO/myRepo.git
    username: qgit
- name: sync-resource
  type: rsync-resource
  source:
    base_dir: /PATH_TO_WEBROOT/FOLDER
    disable_version_path: true
    port: 2222
    server: IP_OF_THE_SERVER
    user : someUser
    private_key: |
            -----BEGIN RSA PRIVATE KEY-----
            NOT_GOOD_BAD_TO_HAVE_KEY_HERE_BUT_THAT_IS_HOW_IT_IS_RIGHT_NOW
            -----END RSA PRIVATE KEY-----

jobs:
- name: publish-bengtssondd
  plan:
  - get: version
    params: {bump: minor}
  - get: repo
    trigger: true
  - task: generateSite
    config:
      platform: linux
      image_resource:
        source:
          repository: jekyll/jekyll
          tag: builder
        type: docker-image
      inputs:
        - name: repo
      outputs:
        - name: build-generated
      run:
        path: repo/ci/build/generate_site.sh
  - put: version
    params: {file: version/version}
  - put: sync-resource
    params: {&quot;sync_dir&quot; : &quot;build-generated&quot; }
  - put: status-message
    params:
      chat_id: &quot;id_of_telegram_user&quot;
      text: &quot;MESSAGE TO SEND&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;the-doh-doʊʔ-doh-segment-to-configuring-it&quot;&gt;The “D’oh!” (/doʊʔ/ DOH) segment to “Configuring it”&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Notice the&lt;code class=&quot;highlighter-rouge&quot;&gt;private_key&lt;/code&gt;property in the pipeline YAML file. That is not good. You should not have keys, password and the like in files that commit to a repository. That is accepted knowledge. Why did I do it then? Because this is a hobby project. I’m the only one with access to the key and the repository. So it’s okay for now. But only for now. On the positive side. Then I have something to look into for an upcoming blog-post. Because, believe me! I have noted that this is something I have to look at.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;pushing-the-pipeline-to-concourseci&quot;&gt;Pushing the pipeline to ConcourseCI&lt;/h3&gt;

&lt;p&gt;Fly. Yeah let’s fly. As in hit the skies with the ConcourseCI cli AKA &lt;a href=&quot;https://concourse-ci.org/fly.html&quot; class=&quot;no-mark-external&quot;&gt;fly&lt;/a&gt;. Fly is a very integral part of ConcourseCI. As pointed out earlier in this blog post in the &lt;a href=&quot;#concourseCI-what-about-it-header&quot;&gt;ConcourseCI - yeah what about it? section&lt;/a&gt;. When you feel confident and ready to throw your pipeline YAML file at the ConcourseCI backend do it like they do it where they do it, like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install fly.
    &lt;ol&gt;
      &lt;li&gt;Go to your ConcourseCI backend root landing page. You’ll find the below. &lt;img src=&quot;/assets/img/concourseCI_fly_download.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;Download the fly client for your OS.&lt;/li&gt;
      &lt;li&gt;Put it in whatever folder.&lt;/li&gt;
      &lt;li&gt;Make sure to put the folder in your OS environment PATH variable. You’ll know you have done it correctly when you can open up a new cmd/bash window and execute &lt;code class=&quot;highlighter-rouge&quot;&gt;fly --version&lt;/code&gt; and get back a non-erring result (a version number).&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Register the ConcourseCI backend.
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;fly --target &quot;NAME_TO_GIVE_THE_TARGET&quot; login --concourse-url http://&quot;DOMAIN_OR_IP&quot;:&quot;PORT&quot;&lt;/code&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Login to the ConcourseCI backend.
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;fly -t &quot;THE_NAME_YOU_GAVE_THE_TARGET&quot; login&lt;/code&gt;. You will be prompted for a password and a username. This is the one you specified when installing the ConcourseCI backend.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Push the pipeline.
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;fly -t &quot;THE_NAME_YOU_GAVE_THE_TARGET&quot; set-pipeline --config /PATH_TO_YOUR/pipeline.yml --pipeline &quot;THE_NAME_TO_GIVE_YOUR_PIPELINE&quot; --var qgit_pass=&quot;PASSWORD_TO_GIT&lt;/code&gt;&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Notice the&lt;code class=&quot;highlighter-rouge&quot;&gt;--var qgit_pass=****&lt;/code&gt;part of the fly set-pipeline cmdline. This is a great feature of ConcourseCI, that helps you avoid having passwords in your YAML file. So please use it :wink:.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Pro-tip!&lt;/em&gt; &amp;gt; use the&lt;code class=&quot;highlighter-rouge&quot;&gt;\&lt;/code&gt;character to escape special characters in e.g. a password.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have followed along with vigour and a bright smile on your face. You will be able see something similar to the below on your ConcourseCI backend.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/concourseCI_pipelineSet.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;specifics-about-the-resources-used-in-the-concourseci-pipeline&quot;&gt;Specifics about the resources used in the ConcourseCI pipeline.&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;semver&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Do remember to create a branch. Allow me to suggest you to name it “version” or something similar. As this will store the release version of the ‘thing’ you build.
    &lt;ul&gt;
      &lt;li&gt;If you don’t you will get a &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;fatal: Remote branch version not found in upstream origin&lt;/code&gt; type error.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;If you have a &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;SSL certificate problem: unable to get local issuer certificate error checking for new versions: exit status 128&lt;/code&gt; type problem you should likely look into:
    &lt;ul&gt;
      &lt;li&gt;that the entire certificate chain can be downloaded. Use the openssl cmdline tool to troubleshoot that. A la&lt;code class=&quot;highlighter-rouge&quot;&gt;openssl s_client -connect &quot;troubling_domain&quot;:443 -servername &quot;troubling_domain&quot; -showcerts&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;that you don’t have a LetsEncrypt certificate that was generated in a way that malformed it. Sorry I can’t be more specific as of now.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;git&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use a proper certificate and ensure that the entire chain can be verified and downloaded. Use the same tips mentioned in the &lt;code class=&quot;highlighter-rouge&quot;&gt;semver&lt;/code&gt; section above.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;telegram&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Getting the chat id. The easiest way I found was to:
    &lt;ul&gt;
      &lt;li&gt;Create the bot by adding @BotFather to your Telegram CLI.&lt;/li&gt;
      &lt;li&gt;Follow the instructions in order to create your bot.&lt;/li&gt;
      &lt;li&gt;Send a message to your bot. Just some random crap. It doesn’t matter. &lt;em&gt;this step is important!&lt;/em&gt; if you don’t execute it the response from the API endpoint below will just be an empty array/[].&lt;/li&gt;
      &lt;li&gt;Execute &lt;code class=&quot;highlighter-rouge&quot;&gt;https://api.telegram.org/bot'API-TOKEN'/getUpdates&lt;/code&gt; where the ‘API-TOKEN’ part is the token of your bot you just created via BotFather.&lt;/li&gt;
      &lt;li&gt;In the JSON returned you will see a chat id in the chat section. That is the one you want to specify in the chat_id property in your pipeline YAML.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;learning-outcomes-schools-out&quot;&gt;Learning outcomes. School’s out.&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Eat your breakfast. Everyday. Yes! Everyday. Ooooops sorry. This is not some freakin’ paleo blog. Then again. We can all use a foodie tip now and then.&lt;/li&gt;
  &lt;li&gt;Seriously. Read the documentation on the software products you are trying to learn. Here is the good sources that helped me during my travels through the world of ConcourseCI.
    &lt;ol&gt;
      &lt;li&gt;https://github.com/concourse/docker-image-resource&lt;/li&gt;
      &lt;li&gt;https://concourse-ci.org/docs.html&lt;/li&gt;
      &lt;li&gt;https://github.com/concourse/git-resource&lt;/li&gt;
      &lt;li&gt;https://github.com/mrsixw/concourse-rsync-resource&lt;/li&gt;
      &lt;li&gt;https://github.com/w32blaster/telegram-notification-resource&lt;/li&gt;
      &lt;li&gt;https://wiki.qnap.com/wiki/SSH:_How_To_Set_Up_Authorized_Keys for connecting over SSH with Rsync.&lt;/li&gt;
      &lt;li&gt;https://stackoverflow.com/questions/667992/rsync-error-failed-to-set-times-on-foo-bar-operation-not-permitted#668049 helped me in finding out why the files could not be written to the destination folder. It was a permissions issue. Owner had to be the user running the rsync job.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thank you for reading along. Also a thank you to the kind people that helped me along my journey of getting this to work. They are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/vito&quot; class=&quot;no-mark-external&quot;&gt;Alex Suraci&lt;/a&gt;. One of the initial creators of ConcourseCI.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/xoebus&quot; class=&quot;no-mark-external&quot;&gt;Christopher Brown&lt;/a&gt;. One of the initial creators of ConcourseCI.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mrmcmuffinz&quot; class=&quot;no-mark-external&quot;&gt;Abraham Cabrera&lt;/a&gt;. A friendly ConcourseCI user on the ConcourseCI Discord need-help channel.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/morten-frydensberg-a69397143&quot; class=&quot;no-mark-external&quot;&gt;Morten Frydensberg&lt;/a&gt;. He’s a DevOps Engineer at Danske Spil and was so kind to listen to, both my clever and stupid ideas, as well as to troubleshoot the ConcourseCI worker container issue with me.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over and out :dash:&lt;/p&gt;</content><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><category term="concourse" /><category term="concourseci" /><category term="fly" /><category term="ci" /><category term="building" /><category term="continous-integration" /><category term="qnap" /><category term="jekyll" /><category term="docker" /><category term="containerization" /><summary type="html">Okay. The blog is up and running (yeah it’s alive). With that of the bucket list on to the next work item on the list: Build and publish. My process of publishing new posts and generating the website with Jekyll, has up until now been quite cumbersome. Furthermore, some time ago I heard about a piece of CI software called ConcourseCI. I felt so enthused about it that I wanted to try it out. See if it could make it work for my own software pipelines as well maybe use it at work.</summary></entry><entry><title type="html">Booting up the blog</title><link href="https://bengtssondd.it/blog-launch/2018/03/19/booting-up-the-blog/" rel="alternate" type="text/html" title="Booting up the blog" /><published>2018-03-19T00:29:48+01:00</published><updated>2018-03-19T00:29:48+01:00</updated><id>https://bengtssondd.it/blog-launch/2018/03/19/booting-up-the-blog</id><content type="html" xml:base="https://bengtssondd.it/blog-launch/2018/03/19/booting-up-the-blog/">&lt;p&gt;Hi there and thank you for visiting &lt;strong&gt;Bengtsson Driven Development&lt;/strong&gt;. My name is Lars Bengtsson and I’m currently working for &lt;a href=&quot;https://om.danskespil.dk&quot;&gt;Danske Spil&lt;/a&gt; as a DevOps Engineer. For quite some time I have thought about starting up a blog. However, throughout that process all the hows, can I’s and so forth, started to ooze out from my brain.
But then, a few months back, as I wandered about on the interwebs I bumped into this static site generator called &lt;a href=&quot;https://jekyllrb.com/docs/home/&quot;&gt;Jekyll&lt;/a&gt;. Not only hope came to me. The feeling of triumphant victory as well. I quickly hit up &lt;code class=&quot;highlighter-rouge&quot;&gt;Ctrl-D&lt;/code&gt; to have myself a bookmark…..aaaaand went back to my regular routines.&lt;/p&gt;

&lt;p&gt;Many a day went by. Finally I conquered my usual process of ‘let me do this other “thing”’, ‘let me do that “thing” right here’ and went about it. So without further ado…..&lt;/p&gt;
&lt;h2 id=&quot;wassup-jekyll&quot;&gt;Wassup Jekyll&lt;/h2&gt;

&lt;p&gt;“Say hello to my little friend” AKA Jekyll. A ruby based static site generator. You write your posts in markdown. Oh wee. Easy peasy, nah think again (at least I would come to think better of it). However, it reads to be very well suited for the CI/build happy people out there ;-). You know, markdown/static text. Can I program a parser for that? Yes you can! A converter then? Yes you can! Hooray, let’s:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;go make the web great again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or is it US of A? Anyways. If nothing else, GitHub is pretty happy about Jekyll. So much that you can use GitHub as a webserver for your Jekyll based site (see: &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt;). Furthermore, there seems to be a good community around Jekyll, its free and several pre-cooked, customizable themes are available. These are some of the features that made me realize that Jekyll was exactly what I had been looking for. So please, come a long for a trip down memory lane.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.imdb.com/title/tt0204001/?ref_=ttmi_tt&quot; class=&quot;no-mark-external&quot;&gt;&lt;img src=&quot;/assets/img/post1_tripdownmemorylane.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;…as I go back into my short-term memory. Through the process of launching this very website/blog.&lt;/p&gt;
&lt;h3 id=&quot;setting-up-jekyll&quot;&gt;Setting up Jekyll&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;em&gt;In bulletproof bullet points the frog croaked.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;A good old follow this &lt;a href=&quot;https://jekyllrb.com/docs/installation/&quot;&gt;how-to&lt;/a&gt; was my friend.&lt;/li&gt;
  &lt;li&gt;Finding a theme was needed, so I gave this &lt;a href=&quot;https://rubygems.org/search?utf8=%E2%9C%93&amp;amp;query=jekyll-theme&quot;&gt;web-query&lt;/a&gt; a hit-up (&lt;a href=&quot;https://www.urbandictionary.com/define.php?term=Hit%20up&quot;&gt;hit-up explained, if needs be.&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Now lets read that Hydejack theme &lt;a href=&quot;https://qwtel.com/hydejack/docs&quot;&gt;documentation&lt;/a&gt;.
    &lt;ol&gt;
      &lt;li&gt;And some more Jekyll doc.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;To the SoThem links, okay SoMe, but isn’t it really about the social media companies themselves, at the end of the day? You tell me!? Oh hey, so what I did was to make sure that URI’s to twitter, GitHub and so forth, pointed to the correct SoThem websites.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;customization&quot;&gt;Customization&lt;/h3&gt;

&lt;h4 id=&quot;--pictures&quot;&gt;- &lt;em&gt;pictures&lt;/em&gt;&lt;/h4&gt;

&lt;p&gt;I went looking in my digital archives and found a good picture for the left sidebar. The picture is from Japan. It’s a Jellyfish my friend, and the pic was taken at &lt;a href=&quot;https://maps.google.com/maps?ll=35.627829,139.735087&amp;amp;z=16&amp;amp;t=m&amp;amp;hl=en-US&amp;amp;gl=JP&amp;amp;mapclient=embed&amp;amp;cid=16690285742223308056&quot;&gt;Aqua Park Shinagawa&lt;/a&gt;. Then one of myself. With glasses, even though I don’t use focal aids. But hey, I call myself a connoisseur, so the least I could do is to pretend to look like one.&lt;/p&gt;

&lt;h4 id=&quot;--the-favicon&quot;&gt;- &lt;em&gt;the favicon&lt;/em&gt;&lt;/h4&gt;

&lt;p&gt;A had a little gem laying around. So I used that. If you can guess/see what it is I will give the very fine price of a digital high-five. What, to you, is probably more interesting, is how I overruled the favicon that the HydeJack theme uses. So….&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A general rule is that a Jekyll theme has an “assets” folder. In this folder the theme author would store images, favicons and so forth. I therefore created such a folder in my websites local Git repo.&lt;/li&gt;
  &lt;li&gt;Inside the assets folder I created a folder named “icons”.&lt;/li&gt;
  &lt;li&gt;You guessed it? Store the favicon you want to use inside the “icons” folder. And! Make sure to name it “favicon.ico”.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Pro tip!&lt;/em&gt; In order to see the folder structure of the theme you are using. Execute &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;open $(bundle show minima)&lt;/code&gt; on macOS© or &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;explorer /usr/local/lib/ruby/gems/&quot;Ruby_Gems_Version&quot;/gems/&quot;theme_name_and_version&quot;&lt;/code&gt; on Windows©&lt;/p&gt;

&lt;h3 id=&quot;the-first-post&quot;&gt;The first post&lt;/h3&gt;

&lt;p&gt;Hey there, look at my monkey AKA my first blog post.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=DVWYcn04sDY&quot; class=&quot;no-mark-external&quot;&gt;&lt;img src=&quot;/assets/img/lookAtMyMonkey.png&quot; alt=&quot;&amp;quot;Look at my monkey&amp;quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In fact you are. Right here.&lt;/p&gt;

&lt;p&gt;You write your posts in Markdown when you use Jekyll. What’s more though is the fact that writing in markdown is not intuitively straight forward. Much the same as learning pretty much any other new language, whether that is Swedish (jävla bra) or &lt;a href=&quot;https://en.wikipedia.org/wiki/Brainfuck&quot;&gt;Brainfuck&lt;/a&gt;. Markdown it is though. 
Markdown has its own syntax and various people have made it fit specific scenarios. However, Jekyll seems to respect the Markdown language at its core standard. What’s the fuzz then? The exact syntax! That’s whats up. How-to do a comment, a link reference and for example a clickable picture without the anchor icon. Which by the way on this HydeJack Jekyll theme, is not mentioned in the &lt;a href=&quot;https://qwtel.com/hydejack/docs&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I had to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open the HydeJack theme folder. As mentioned in the “Pro tip!” above.&lt;/li&gt;
  &lt;li&gt;Look around, looking for clues on how-to exclude the anchor icon.
    &lt;ol&gt;
      &lt;li&gt;The “_mark-external.scss file under */jekyll-theme-hydejack-“versionNumber”/_sass/hydejack/__link” looked promising.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;I opened it up and found a CSS class named “{.no-mark-external}”.&lt;/li&gt;
  &lt;li&gt;Added it to the image link:
    &lt;ol&gt;
      &lt;li&gt;before == &lt;code class=&quot;highlighter-rouge&quot;&gt;[![](/somewhere/image/yesSir.jpg)][linkSectionName]&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;after == &lt;code class=&quot;highlighter-rouge&quot;&gt;[![](/somewhere/image/yesSir.jpg)][linkSectionName]{:.no-mark-external}&lt;/code&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The anchor was gone and daddy was happy :clap:{:style=”display: inline”}. Notice that clap emoticon being displayed “inline”? Oh yeah, thank you Jekyll for using kramdown as your converter. As this converter supports setting style related settings in markdown directly. As I did with that clap emoticon.&lt;/p&gt;

&lt;p&gt;I had to:&lt;/p&gt;

&lt;p&gt;Write &amp;gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;: clap :{:style=&quot;display: inline&quot;}&lt;/code&gt; in markdown. The &lt;code class=&quot;highlighter-rouge&quot;&gt;: clap :&lt;/code&gt; part (normally without spaces) is what is rendered to be the clap emoticon image. The &lt;code class=&quot;highlighter-rouge&quot;&gt;: clap :&lt;/code&gt; placeholder works because I have installed the &lt;code class=&quot;highlighter-rouge&quot;&gt;emoji_for_jekyll&lt;/code&gt; plugin. It took me a while to figure this out, but I arrived in due time. Documentation, tests and fiery helps A LOT.&lt;/p&gt;

&lt;h2 id=&quot;getting-the-blog-on-its-wings&quot;&gt;Getting the blog on its wings&lt;/h2&gt;

&lt;p&gt;Hmm now to the question of where to host it. A domain for it and all these other peripheral practical tasks of getting myself a blog.&lt;/p&gt;

&lt;h3 id=&quot;the-domain-and-a-story-on-the-name&quot;&gt;The domain and a story on the name&lt;/h3&gt;

&lt;p&gt;Yeah why that freaking name? I mean, come on, &lt;em&gt;Bengtsson Driven Development&lt;/em&gt;? Wassup with that! Listen up :smile:{:style=”display: inline”}. Have you heard of Behavior Driven Development (BDD)? Experienced the jolly-go happy developers at Danske Spil? And now what’s my name? What do I do, DevOps. A development driven methodology towards running software platforms and services.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It’s aaaaaaalive and its perfect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That mesh of influences made me land on &lt;em&gt;Bengtsson Driven Development&lt;/em&gt; as the name for my blog. A special thanks goes to Micki and Kasper, two developers at Danske Spil, for opening my drowsy DevOps eyes towards the potential of &lt;em&gt;Bengtsson driven&lt;/em&gt;/&lt;em&gt;bentze driven&lt;/em&gt;/&lt;em&gt;#kanViFåOsNogetBDD&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That being the name. A little long though, so decided on bengtssondd.it as the domain. .IT &amp;lt; yeah it is the Italian tld but it is also my subject area :computer:.&lt;/p&gt;

&lt;h3 id=&quot;dns&quot;&gt;DNS&lt;/h3&gt;

&lt;p&gt;From my days in the hosting biz I had come to know of &lt;a href=&quot;https://web.gratisdns.dk/om-os/&quot;&gt;GratisDNS&lt;/a&gt;. But, do they support DDNS? Oh yes they do. Do they have an API, I can call to update DNS records for the bengtssondd.it domain? Yes they have. Wicked times :dancers:.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;In order to be able to use the GratisDNS DDNS API service you have to setup a DDNS password on your account. See more &lt;a href=&quot;https://larsendata.wiki/gratisdns:ddns&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Generate the URI to use for updating the IP for the domain &amp;gt; &lt;a href=&quot;https://larsendata.wiki/tools/ddns/index.php&quot;&gt;GratisDDNS&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;From a ‘box’ on the same network from where you will host the website (the WAN source address has to resolve to the same address as on the ‘box’ that actually hosts the website.)
    &lt;ol&gt;
      &lt;li&gt;Query the URI you generated in step 1 with cURL or something similar.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Test that it works.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;Seriously consider creating a cron job or whatever so that the WAN IP is automatically updated on the GratisDNS servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;https-on-bengtssonddit&quot;&gt;HTTPS on bengtssondd.it&lt;/h3&gt;

&lt;p&gt;This 1 was “more” fun. But hey, I learned myself some more HAProxy and Letsencrypt. What I wanted was to have a setup where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I get a certificate that is approved by a trustable certificate authority and it should be free.&lt;/li&gt;
  &lt;li&gt;It is possible to renew the certificate automatically.&lt;/li&gt;
  &lt;li&gt;Ceritificate revocation should be possible.&lt;/li&gt;
  &lt;li&gt;It should be possible to use with HAProxy.&lt;/li&gt;
  &lt;li&gt;Also, it should be possible to use more than one certificatae with HAProxy. As I have different websites going through the same HAProxy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I already had experience with Letsencrypt and it supports my other requirements as well. So I continued with that. Buuuuut! Because I’m using a QNAP NAS to host my websites there is some quirks to handle.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We are talking a Busybox flavored Linux distribution.&lt;/li&gt;
  &lt;li&gt;The QNAP per default has an old Python install (Letsencrypt likes Python in several CLI versions).&lt;/li&gt;
  &lt;li&gt;How exactly would I have HAProxy read more than one *.pem file when going over HTTPS?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I really had to put my max GoGoDuck lmgtfy skills to the test. After going back and forth. Testing. Thinking out a way to do ‘x’ and going back to T H E searchengine I arrived at the following recipe for setting up what I wanted.&lt;/p&gt;

&lt;h4 id=&quot;recipe-for---1-website-with-a-letsencrypt-certificate-on-a-qnap-nas-through-the-haproxy-load-balancer&quot;&gt;Recipe for = &amp;gt; 1 website with a Letsencrypt certificate. On a QNAP NAS, through the HAProxy load-balancer&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Check your Python version. If below v2.7.6 update or install a newer version.
    &lt;ol&gt;
      &lt;li&gt;IF you choose to install a newer version, do it throught the QNAP App-center.&lt;/li&gt;
      &lt;li&gt;When installed make sure to use the Python installation in the .qpkg folder on your QNAP. E.g. by &lt;code class=&quot;highlighter-rouge&quot;&gt;export PATH=/share/DATA_DRIVE/.qpkg/Python/src/bin/:$PATH&lt;/code&gt; in your scripts or on the cmdline.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Install the Python package manager pip.
    &lt;ol&gt;
      &lt;li&gt;Download get-pip.py script.&lt;/li&gt;
      &lt;li&gt;Run it.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Install the cryptography Python module: &lt;code class=&quot;highlighter-rouge&quot;&gt;pip install cryptography&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Install the python version of certbot, the Letsencrypt certificate cli program.&lt;/li&gt;
  &lt;li&gt;Check that certbot works by executing: &lt;code class=&quot;highlighter-rouge&quot;&gt;certbot -h&lt;/code&gt;. If nothing happens or the cmd fails, make sure that the correct version of Python is in your environment path.&lt;/li&gt;
  &lt;li&gt;I choose to use the webroot plugin method of Letsencrypt. As I did not want to shutdown HAProxy or any other web-related server. I therefore executed the following in order to get myself a certificate for bengtssondd.it: &lt;code class=&quot;highlighter-rouge&quot;&gt;sudo certbot certonly --webroot -w /PATH_TO_WEBROOT_FOLDER/ -d bengtssondd.it --non-interactive --agree-tos --email myEmail@bentze.klartder&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Of course, I prooved ownership by having ensured that the bengtssondd.it domain points to the WAN that the Letsencrypt certbot request would come from. See &lt;a href=&quot;#dns&quot;&gt;dns&lt;/a&gt; above.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Then we need to concatenate the certificate files that the certbot cmd above spits out. This is done by executing: &lt;code class=&quot;highlighter-rouge&quot;&gt;sudo cat /etc/letsencrypt/live/bengtssondd.it/fullchain.pem /etc/letsencrypt/live/bengtssondd.it/privkey.pem | sudo tee /FOLDER_TO_STORE_PEM_FILE/PEM_FILENAME.pem&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;The order of concatenation is in fact very important.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Now to the haproxy.cfg file.
    &lt;ol&gt;
      &lt;li&gt;First I edited the line that said &lt;code class=&quot;highlighter-rouge&quot;&gt;bind *:443 ssl crt /usr/local/etc/haproxy/ssl.pem&lt;/code&gt;, so that it would now say &lt;code class=&quot;highlighter-rouge&quot;&gt;bind *:443 ssl crt /PATH_TO_PEM_FOLDER/&quot;FILENAME&quot;.pem crt /ANOTHER_PATH_TO_PEM_FOLDER/&quot;FILENAME&quot;.pem&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Then I added
 &lt;code class=&quot;highlighter-rouge&quot;&gt;Bengtssondd.it website acl
 bengtssondd hdr_beg(host) -i bengtssondd.it
 use_backend my_back if bengtssondd
&lt;/code&gt;
 …to my two frontend sections in the haproxy.cfg file.&lt;/li&gt;
      &lt;li&gt;And ended that of by reloading the HAProxy container.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Tested the site and things where :thumb: up.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following reads helped me.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Python installation steps &amp;gt; https://community.letsencrypt.org/t/dont-know-how-to-bootstrap-certbot-on-your-os/29905/2&lt;/li&gt;
  &lt;li&gt;Python pip installation steps &amp;gt; https://pip.pypa.io/en/stable/installing/&lt;/li&gt;
  &lt;li&gt;Configuring HAProxy &amp;gt; https://serversforhackers.com/c/letsencrypt-with-haproxy&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;time-for-celebration&quot;&gt;Time for celebration&lt;/h2&gt;

&lt;p&gt;Yehaaarrr….we are live. #FartPå AKA #PedalToTheMetal. That’s all for now folks. Thank you for reading a long. Come back for the next 1. Where I’ll have a look at some CI and CD for &lt;em&gt;Bengtsson Driven Developement&lt;/em&gt; (we might be talking Docker as well…oooh wee). Because right now the CI and CD process is pretty ugly:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Build with &lt;code class=&quot;highlighter-rouge&quot;&gt;bundle exec jekyll serve&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;scp the files to my QNAP NAS from my dev. machine.&lt;/li&gt;
  &lt;li&gt;F5 for a refreshing “deploy and pray”.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think you get the idea. We are talking nasty pastry :suspect:.&lt;/p&gt;

&lt;p&gt;Thank you for reading along. Over and out :dash:&lt;/p&gt;</content><author><name>Lars Bengtsson</name><email>bingchonglars@gmail.com</email></author><category term="Jekyll" /><category term="GratisDNS" /><category term="HydeJack" /><category term="Bengtsson-Driven-Development" /><category term="Letsencrypt" /><category term="HAProxy" /><summary type="html">Hi there and thank you for visiting Bengtsson Driven Development. My name is Lars Bengtsson and I’m currently working for Danske Spil as a DevOps Engineer. For quite some time I have thought about starting up a blog. However, throughout that process all the hows, can I’s and so forth, started to ooze out from my brain. But then, a few months back, as I wandered about on the interwebs I bumped into this static site generator called Jekyll. Not only hope came to me. The feeling of triumphant victory as well. I quickly hit up Ctrl-D to have myself a bookmark…..aaaaand went back to my regular routines.</summary></entry></feed>