<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Docker – Yeri Tiete</title>
    <link>https://yeri.be/tag/docker/</link>
    <description>Yeri Tiete&#39;s blog</description>
    <language>en</language>
    <copyright>© Yeri Tiete</copyright>
    <lastBuildDate>Sun, 17 May 2026 06:32:54 +0200</lastBuildDate>
    <atom:link href="https://yeri.be/tag/docker/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Scheduling posts on a static blog</title>
      <link>https://yeri.be/scheduling-posts-on-a-static-blog/</link>
      <pubDate>Sun, 17 May 2026 06:32:54 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/scheduling-posts-on-a-static-blog/</guid><enclosure url="https://static.yeri.be/posts/scheduled-posts/box.mp4" length="0" type="video/mp4" />
      <description>&lt;p&gt;One of the things I missed &lt;a href=&#34;https://yeri.be/from-wordpress-to-hugo/&#34;&gt;moving from WordPress to Hugo&lt;/a&gt;: scheduled posts.&#xA;WP just&amp;hellip; does that. Set a future date, and forget about it.&lt;/p&gt;&#xA;&lt;p&gt;And static site generators don&amp;rsquo;t&amp;hellip; The site only rebuilds when you &lt;code&gt;git push&lt;/code&gt;, and that&amp;rsquo;s it. 😢&lt;/p&gt;&#xA;&lt;p&gt;Why schedule posts, you ask? Because at times I write 3-4 posts in a day, and I don&amp;rsquo;t want to spam. ¯\&lt;em&gt;(ツ)&lt;/em&gt;/¯ I have a rule that there should only be a single published post a day, and if I know I&amp;rsquo;m out of topics (especially for FlatTurtle) I tend to add a week or 2 between posts to spread it out evenly.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><video controls preload="metadata"><source src="https://static.yeri.be/posts/scheduled-posts/box.mp4" type="video/mp4"></video></p><p>One of the things I missed <a href="/from-wordpress-to-hugo/">moving from WordPress to Hugo</a>: scheduled posts.
WP just&hellip; does that. Set a future date, and forget about it.</p>
<p>And static site generators don&rsquo;t&hellip; The site only rebuilds when you <code>git push</code>, and that&rsquo;s it. 😢</p>
<p>Why schedule posts, you ask? Because at times I write 3-4 posts in a day, and I don&rsquo;t want to spam. ¯\<em>(ツ)</em>/¯ I have a rule that there should only be a single published post a day, and if I know I&rsquo;m out of topics (especially for FlatTurtle) I tend to add a week or 2 between posts to spread it out evenly.</p>
<p>So I wrote (aka vibe coded) a little thing about a year or two ago, originally called <em>BlogTurtle Rebuilder</em>, because it was meant for <a href="https://flatturtle.xyz" target="_blank" rel="noopener noreferrer">FlatTurtle</a>&rsquo;s hugo <a href="https://flatturtle.link/blog" target="_blank" rel="noopener noreferrer">blog</a>. I&rsquo;ve since repurposed it for this site.</p>
<p>The flow is quite simple:</p>
<ol>
<li>I push a Markdown post to GitLab with <code>date = &quot;...&quot;</code> set to whenever I want it published.</li>
<li>Gitlab runs CI and deploys to Cloudflare Pages. Hugo will, however, hide posts with a <code>date</code> in the future.</li>
<li>On push, GitLab also pings a webhook (a docker container on a server).</li>
<li>Said container does a <code>git pull</code> and scans every <code>.md</code> for that date field.</li>
<li>Anything in the future gets an in-memory timer for that exact moment. Anything already due gets ignored at Gitlab CI would&rsquo;ve deployed it.</li>
<li>When the timer pops, it triggers the GitLab CI/CD pipeline (through another webhook) that does a new Hugo build + deploy.</li>
<li>As an added bonus, I get an email telling me the post is live, with a <a href="https://culturedcode.com/things/" target="_blank" rel="noopener noreferrer">Things3</a> deep-link to add a follow-up task to share it somewhere. It&rsquo;s one click away.</li>
</ol>
<p>That&rsquo;s the whole thing.</p>
]]></content:encoded>
      <category>software</category><category>www</category>
      <category>blog</category><category>docker</category><category>python</category><category>hugo</category><category>gitlab</category><category>flatturtle</category>
    </item>
    
    <item>
      <title>PoC: Betteruptime &#43; Python-kasa</title>
      <link>https://yeri.be/poc-betteruptime-python-kasa/</link>
      <pubDate>Tue, 04 Jul 2023 15:20:06 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/poc-betteruptime-python-kasa/</guid><enclosure url="https://static.yeri.be/2023/07/kasa-smart-plug.jpg" length="0" type="image/jpeg" />
      <description>&lt;p&gt;&lt;strong&gt;Content Update&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;The provided scripts have been updated on 16 Jul 2023. Specifically the SmartStrip part was not working as intended. &lt;/p&gt;&#xA;&lt;hr class=&#34;wp-block-separator has-alpha-channel-opacity&#34;/&gt;&#xA;&lt;p&gt;I&#39;ve been a big fan of &lt;a rel=&#34;noreferrer noopener&#34; href=&#34;https://uptime.betterstack.com/&#34; target=&#34;_blank&#34;&gt;Betteruptime&lt;/a&gt;. I&#39;ve started using it to monitor all my assets online (websites, DNS, ping, successful script runs) as well as my servers (using &lt;a rel=&#34;noreferrer noopener&#34; href=&#34;https://betterstack.com/docs/uptime/cron-and-heartbeat-monitor/&#34; target=&#34;_blank&#34;&gt;heartbeats&lt;/a&gt;). &lt;/p&gt;&#xA;&lt;figure class=&#34;wp-block-image alignwide size-large&#34;&gt;&lt;a href=&#34;https://static.yeri.be/2023/07/mammoth.png&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;&lt;img src=&#34;https://static.yeri.be/2023/07/mammoth-1024x570.png&#34; alt=&#34;Screenshot of Betteruptime showing a heartbeat that failed for several hours. &#34; class=&#34;wp-image-72880&#34;/&gt;&lt;/a&gt;&lt;figcaption class=&#34;wp-element-caption&#34;&gt;Image of a heartbeat that failed for several hours. After 2 hours of no hearbeat, it turned into an incident, and several hours later the heartbeats resumed. &lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;p&gt;I have a few Raspberry Pi&#39;s, and once in a while they hang (not sure why, maybe USB-to-SSD issues or something). Nothing too critical, but annoying. &lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://static.yeri.be/2023/07/kasa-smart-plug.jpg" alt="PoC: Betteruptime + Python-kasa"></p><p><strong>Content Update</strong></p>
<p>The provided scripts have been updated on 16 Jul 2023. Specifically the SmartStrip part was not working as intended. </p>
<hr class="wp-block-separator has-alpha-channel-opacity"/>
<p>I've been a big fan of <a rel="noreferrer noopener" href="https://uptime.betterstack.com/" target="_blank">Betteruptime</a>. I've started using it to monitor all my assets online (websites, DNS, ping, successful script runs) as well as my servers (using <a rel="noreferrer noopener" href="https://betterstack.com/docs/uptime/cron-and-heartbeat-monitor/" target="_blank">heartbeats</a>). </p>
<figure class="wp-block-image alignwide size-large"><a href="https://static.yeri.be/2023/07/mammoth.png" target="_blank" rel="noreferrer noopener"><img src="https://static.yeri.be/2023/07/mammoth-1024x570.png" alt="Screenshot of Betteruptime showing a heartbeat that failed for several hours. " class="wp-image-72880"/></a><figcaption class="wp-element-caption">Image of a heartbeat that failed for several hours. After 2 hours of no hearbeat, it turned into an incident, and several hours later the heartbeats resumed. </figcaption></figure>
<p>I have a few Raspberry Pi's, and once in a while they hang (not sure why, maybe USB-to-SSD issues or something). Nothing too critical, but annoying. </p>
<p>I've plugged them all on <a href="https://www.tp-link.com/sg/home-networking/smart-plug/" target="_blank" rel="noreferrer noopener">TP-Link Kasa</a> smart plugs to remotely restart them if I had to (once or twice a year). </p>
<pre class="wp-block-verse">Note, to confuse everyone, TP-Link also launched Tapo, which... competes with Kasa and is not compatible, but does the exact same thing... ¯\_(ツ)_/¯</pre>
<p>After some <a rel="noreferrer noopener" href="https://medium.com/geekculture/use-raspberry-pi-and-tp-link-kasa-to-automate-your-devices-9f936a6243c1" target="_blank">Googling</a> (actually <a href="https://kagi.com" target="_blank" rel="noreferrer noopener">Kagi'ing</a>) I found out, there's a <a rel="noreferrer noopener" href="https://python-kasa.readthedocs.io/en/latest/" target="_blank">Python library</a> that lets you control your smart plugs. </p>
<p>So, the idea was born to:</p>
<ul>
<li>Check Betteruptime heartbeats, if down, power cycle the smart plug</li>
<li>Do this at most once per day (in case something else is causing issues)</li>
<li>Betteruptime <a rel="noreferrer noopener" href="https://betterstack.com/docs/uptime/api/get-a-single-hearbeat/" target="_blank">heartbeats</a> manage when a device is marked as offline (i.e.: it expects a heartbeat every 5 minutes, but will only consider the device down if no heartbeats are received for 2 hours).  </li>
<li>The bulk of the code had to be written by ChatGPT. Let ChatGPT choose the language (it ended up being a mix of Bash and Python)</li>
<li>Everything needs to run in Docker (using a cron, the Docker container doesn't daemonise)</li>
<li>These run on Raspberry Pi's (but of course the RPi can't check itself: so RPi1 checks for RPi2, and vice versa. As these RPis are on different networks (my parent's home, my own home, etc) I had to enable "<code>--net=host</code>" in <code>Docker run</code> to get the correct routes from the host system, but you may not actually need this</li>
<li>To top if off, sent an email (using Mailgun EU servers) to warn me something broke and it rebooted</li>
</ul>
<p>So, after some fiddling (half an evening or so) the proof-of-concept worked. </p>
<p>I should probably throw this in a Git repo but shrug. I don't want to give the impression that I'll maintain this and provide support.  </p>
<p>Dockerfile:</p>
<pre class="wp-block-code"><code>FROM python:alpine
RUN apk add bash curl jq
RUN pip3 install python-kasa
COPY heartbeat.sh kasa-api.py /
VOLUME /tmp/kasa/
CMD &#91;"/heartbeat.sh"]</code></pre>
<p>Python script <code>kasa-api.py</code> (this works with both <a href="https://www.tp-link.com/sg/home-networking/smart-plug/kp303/" target="_blank" rel="noreferrer noopener">smart strips</a> and <a href="https://www.kasasmart.com/us/products/smart-plugs/kasa-smart-wifi-plug-hs100" target="_blank" rel="noreferrer noopener">smart plugs</a>):</p>
<pre class="wp-block-code"><code>import sys
import asyncio
from kasa import SmartPlug, SmartStrip

async def main():
	if len(sys.argv) != 4:
		print("Usage: python kasa-api.py type IP-address outlet-index")
		return

	device_type = sys.argv&#91;1]
	ip_address = sys.argv&#91;2]
	outlet_index = int(sys.argv&#91;3])

	if device_type == "smartplug":
		await control_smart_plug(ip_address)
	elif device_type == "smartstrip":
		await control_smart_strip(ip_address, outlet_index)
	else:
		print(f"Unsupported device type: {device_type}")

async def control_smart_plug(ip_address):
	plug = SmartPlug(ip_address)

	try:
		await plug.update()

		# Retrieve the current state
		plug_state = plug.is_on

		# Turn off the plug
		await plug.turn_off()

		print(f"Turned off SmartPlug at {ip_address}")
		await asyncio.sleep(5)

		# Turn on the plug if it was previously on
		if plug_state:
			await plug.turn_on()

		print(f"Turned on SmartPlug at {ip_address}")
	except Exception as e:
		print(f"Failed to control SmartPlug at {ip_address}: {e}")

async def control_smart_strip(ip_address, outlet_index):
	strip = SmartStrip(ip_address)

	try:
		await strip.update()

		# Retrieve the current state of the specified child plug
		child_state = strip.children&#91;outlet_index].is_on

		# Turn off the specified child plug
		await strip.children&#91;outlet_index].turn_off()

		print(f"Turned off child plug {outlet_index} in SmartStrip at {ip_address}")
		await asyncio.sleep(5)

		# Turn on the child plug if it was previously on
		await strip.children&#91;outlet_index].turn_on()

		print(f"Turned on child plug {outlet_index} in SmartStrip at {ip_address}")
	except Exception as e:
		print(f"Failed to control SmartStrip at {ip_address}: {e}")

# Run the asyncio event loop
asyncio.run(main())</code></pre>
<p><code>heartbeat.sh</code> -- with example devices. Be sure to fill in the variables (including <code>hb</code>, that's the heartbeat ID you can get from the Betteruptime URL and the IP or DNS hostname of the smartplug):</p>
<pre class="wp-block-code"><code>#!/bin/bash

API_KEY="BetterUptime API token"
BU="https://uptime.betterstack.com/api/v2/heartbeats/" # no need to change this

MAILGUN_API_KEY="Mailgun API token"
MAILGUN_DOMAIN="mg.you.com" # use your own domain

if &#91;&#91; "$DEVICE" = tyr ]] || &#91;&#91; "$1" = tyr ]]; then

	# Tyr
	device="Tyr"
	hb=1111
	bu="https://uptime.betterstack.com/team/1/heartbeats/$hb"
	plug_type="smartplug"
	plug_host="smartplug1.kasa.you.com"

elif &#91;&#91; "$DEVICE" = mammoth ]] || &#91;&#91; "$1" = mammoth ]]; then

	# Mammoth
	device="mammoth"
	hb=2222
	bu="https://uptime.betterstack.com/team/1/heartbeats/$hb"
	plug_type="smartstrip"
	plug_host="smartstrip1.kasa.you.com"
	plug_index=0 # plug 2 is rly plug 3 because the index counts from 0 to 2 and not from 1 to 3.

elif &#91;&#91; "$DEVICE" = liana ]] || &#91;&#91; "$1" = liana ]]; then

	# Liana
	device="liana"
	hb=3333
	bu="https://uptime.betterstack.com/team/1/heartbeats/$hb"
	plug_type="smartstrip"
	plug_host="smartstrip1.kasa.you.com"
	plug_index=1 # plug 2 is rly plug 3 because the index counts from 0 to 2 and not from 1 to 3.

elif &#91;&#91; "$DEVICE" = eagle ]] || &#91;&#91; "$1" = eagle ]]; then

	device="eagle"
	hb=4444
	bu="https://uptime.betterstack.com/team/1/heartbeats/$hb"
	plug_type="smartstrip"
	plug_host="smartstrip1.kasa.yeri.be"
	plug_index=2 # plug 2 is rly plug 3 because the index counts from 0 to 2 and not from 1 to 3.

else
	echo "Unknown device."
	exit 1
fi

url=$BU/$hb

send_alert() {
	MAILGUN_URL="https://api.eu.mailgun.net/v3/$MAILGUN_DOMAIN/messages"
	from="kasa@you.com"
	to="alert@you.com"
	subject="Smartplug power cycled: $device"
	body="rebooted device $device!"$'\n'"Kasa IP: $plug_host."$'\n'"$bu"

	# Send alert email
	curl -s --user "api:$MAILGUN_API_KEY" \
		"$MAILGUN_URL" \
		-F from="$from" \
		-F to="$to" \
		-F subject="$subject" \
		-F text="$body"
}

kasa_cycle() {
	echo "Betteruptime heartbeat ($hb) says the service for $device is down, restarting."
	python /kasa-api.py "$plug_type" "$plug_host" "$plug_index"
	# Update the last execution date in the file
	echo "$current_date" &gt; "$file"
}

kasa_info() {
	kasa --host $plug_host
}

response=$(curl -sL "$url" -H "Authorization: Bearer $API_KEY")
status=$(echo "$response" | jq -r '.data.attributes.status')

if &#91;&#91; "$status" == "down" ]]; then
	dir="/tmp/.kasa/"
	mkdir -p "$dir"
	file="${dir}${device}.txt"

	# Get current date
	current_date=$(date "+%F")
	# Check if the file exists
	if &#91; -f "$file" ]; then
		# Get last execution date from the file
		last_execution=$(cat "$file")
		# We only want to run this once every 24hrs. If a reboot doesn't fix it, something more
		# serious is going on and likely needs manual intervention. No point spam rebooting the device.
		if &#91;&#91; "$current_date" != "$last_execution" ]]; then
			kasa_cycle
			send_alert
		else
			echo "Power cycle already executed today."
		fi
	else
		kasa_cycle
		send_alert
	fi
elif &#91;&#91; "$status" == "up" ]]; then
	echo "Betteruptime heartbeat says the service ($hb) for $device is up."
else
	# this could happen if the heartbeat is paused.
	echo "Unknown status."
	kasa_info
	exit 1
fi</code></pre>
<p>I run Docker with two scripts, a builder (<code>rebuild.sh</code>) and a file that runs it (<code>start.sh</code>). It should rebuild in case a docker cleanup script ran (and deleted dangling containers). </p>
<p>I run this as <code>root</code> and probably shouldn't, but yeah... That'll be for another lifetime. </p>
<p>Be sure to change the paths (<code>/root/git/kasa-api</code>) in both scripts. </p>
<p><code>rebuild.sh</code>:</p>
<pre class="wp-block-code"><code>#!/bin/bash
cd /root/git/kasa-api # the path where this project exists

git pull &gt; /dev/null

BASEIMAGE=`cat Dockerfile | grep FROM | awk '{print $2}'`
docker pull $BASEIMAGE
docker build -q -t kasa-api .
rm -f /tmp/.kasa/*.txt</code></pre>
<p><code>start.sh</code>:</p>
<pre class="wp-block-code"><code>#!/bin/bash

if &#91; -z "$1" ]; then
	echo "Missing device name."
	exit 1
fi

docker stop kasa-api 2&gt; /dev/null
docker rm kasa-api 2&gt; /dev/null

run_kasa() {
	DEVICE=$1
	docker run --net=host -v /tmp/.kasa:/tmp/.kasa --rm -e DEVICE=$DEVICE --name kasa-api kasa-api
}

if &#91;&#91; $(docker image ls | grep kasa-api) ]]; then
	run_kasa $1
else
	cd /root/git/kasa-api
	/root/git/kasa-api/rebuild.sh &gt; /dev/null
	run_kasa $1
fi</code></pre>
<p>And that's pretty much it. I run this using with cron in <code>/etc/cron.d/</code>. For example (be sure to edit the parameter/device name/path):</p>
<pre class="wp-block-code"><code>#
# cron-jobs for kasa-api
#

MAILTO=root

*/15 * * * *	root	if &#91; -x /root/git/kasa-api/start.sh ] &amp;&amp; &#91; -f /root/git/kasa-api/start.sh ]; then /root/git/kasa-api/start.sh tyr &gt;/dev/null; fi</code></pre>
<p>I'm sure there must be bugs in this ChatGPT generated code but... so far, it has actually worked.</p>
]]></content:encoded>
      <category>hardware</category><category>linux</category><category>networking</category><category>software</category>
      <category>bash</category><category>dailyprompt</category><category>dailyprompt-2001</category><category>docker</category><category>python</category>
    </item>
    
    <item>
      <title>Feed2Toot</title>
      <link>https://yeri.be/feed2toot/</link>
      <pubDate>Sat, 12 Nov 2022 16:36:32 +0100</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/feed2toot/</guid><enclosure url="https://static.yeri.be/2023/10/toot.jpg" length="0" type="image/jpeg" />
      <description>&lt;p&gt;Started looking into a service to auto-post from this blog onto my &lt;a href=&#34;https://m.superuser.one&#34; data-type=&#34;URL&#34; data-id=&#34;m.superuser.one&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;Mastodon&lt;/a&gt; feed. &lt;a href=&#34;https://feed2toot.readthedocs.io/en/latest/&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;Feed2Toot&lt;/a&gt; fit the bill perfectly. &lt;/p&gt;&#xA;&lt;p&gt;I wanted to run the whole thing from a Docker container, though, so I&#39;ll quickly write a how-to.&lt;/p&gt;&#xA;&lt;p&gt;This whole thing runs from a Raspberry Pi, as root. No k8s or k3s for me. The path I use is &lt;code&gt;/root/git/feed2toot/&lt;/code&gt;, so be sure to modify that to whatever you&#39;re using.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://static.yeri.be/2023/10/toot.jpg" alt="Feed2Toot"></p><p>Started looking into a service to auto-post from this blog onto my <a href="https://m.superuser.one" data-type="URL" data-id="m.superuser.one" target="_blank" rel="noreferrer noopener">Mastodon</a> feed. <a href="https://feed2toot.readthedocs.io/en/latest/" target="_blank" rel="noreferrer noopener">Feed2Toot</a> fit the bill perfectly. </p>
<p>I wanted to run the whole thing from a Docker container, though, so I'll quickly write a how-to.</p>
<p>This whole thing runs from a Raspberry Pi, as root. No k8s or k3s for me. The path I use is <code>/root/git/feed2toot/</code>, so be sure to modify that to whatever you're using.</p>
<p>First off, <a rel="noreferrer noopener" href="https://feed2toot.readthedocs.io/en/latest/configure.html" target="_blank">get your credentials</a> for the app. You can either install the Feed2Toot package on a system (i.e. throwaway VM, to keep it clean), or use the Docker container below, but add <code>RUN apk add bash</code> and change the last line to <code>CMD ["bash"]</code> and then chroot into it via <code>docker exec -it feed2toot bash</code>.</p>
<p>This will generate two files (<code>feed2toot_clientcred.txt</code> and <code>feed2toot_usercred.txt</code>). Be sure to save these.</p>
<p>You can also try to run Feed2Toot at least once to make sure it's working and to fine-tune your <code>ini</code> file. This is mine:</p>
<pre class="wp-block-code"><code>&#91;mastodon]
instance_url=https://m.superuser.one
; Here you need the two files created by register_feed2toot_app
user_credentials=/etc/feed2toot/feed2toot_usercred.txt
client_credentials=/etc/feed2toot/feed2toot_clientcred.txt
; Default visibility is public, but you can override it:
; toot_visibility=unlisted

&#91;cache]
cachefile=/feed2toot/feed2toot.db
cache_limit=10000

&#91;lock]
lock_file=/var/lock/feed2toot.lock
lock_timeout=3600

&#91;rss]
uri=https://yeri.be/feed
; uri_list=/feed2toot/rsslist.txt
toot={title} {link}
; toot_max_len=500
title_pattern=Open Source
title_pattern_case_sensitive=true
no_uri_pattern_no_global_pattern=true
; ignore_ssl=false

&#91;hashtaglist]
; several_words_hashtags_list=/feed2toot/hashtags.txt
; no_tags_in_toot=false

&#91;feedparser]
; accept_bozo_exceptions=true

&#91;media]
; custom=/var/lib/feed2toot/media/logo.png</code></pre>
<p>I have three other files to make this work, first off <code>Dockerfile</code>:</p>
<pre class="wp-block-code"><code>FROM python:3.6-alpine
RUN pip3 install feed2toot &amp;&amp; mkdir -p /etc/feed2toot/
COPY feed2toot.ini feed2toot_clientcred.txt feed2toot_usercred.txt /etc/feed2toot/
VOLUME /feed2toot/
CMD &#91;"feed2toot", "-c", "/etc/feed2toot/feed2toot.ini"]</code></pre>
<p>The script I run to build the container (<code>start.sh</code>):</p>
<pre class="wp-block-code"><code>#!/bin/bash
git pull

BASEIMAGE=`cat Dockerfile | grep FROM | awk '{print $2}'`
docker pull $BASEIMAGE
docker stop feed2toot
docker rm feed2toot
docker build -t feed2toot .
./run.sh</code></pre>
<p>And finally, the script to run the container every so often (<code>run.sh</code>):</p>
<pre class="wp-block-code"><code>#!/bin/bash
docker run -d --rm -v /srv/mastodon/feed2toot/:/feed2toot/ --name feed2toot feed2toot</code></pre>
<p>This will save the database file under <code>/srv/mastodon/</code>, to preserve states across rebuilds.</p>
<p>Note that once Feed2Toot runs, it'll exit, and the container will be stopped. So it does not automatically run all the time. </p>
<p>So, you'll want to run this every so often. You can add a file to <code>/etc/cron.d/</code> to run it, for example, every six hours:</p>
<pre class="wp-block-code"><code>#
# cron-jobs for feed2toot
#

MAILTO=root

0 */6 * * *		root	if &#91; -x /root/git/feed2toot/run.sh ]; then /root/git/feed2toot/run.sh &gt;/dev/null; fi</code></pre>
<p>That's it. Should do the trick. It'll now post stuff from your RSS feed onto your timeline. </p>
<p>Oh, and Jeroen has <a rel="noreferrer noopener" href="https://www.forceflow.be/2022/11/11/moving-from-twitter-to-mastodon/" target="_blank">a good post</a> about Mastodon.</p>
]]></content:encoded>
      <category>linux</category><category>software</category><category>virtualisation</category>
      <category>blog</category><category>docker</category><category>fediverse</category><category>mastodon</category>
    </item>
    
    <item>
      <title>Smokeping.eu</title>
      <link>https://yeri.be/smokeping-eu/</link>
      <pubDate>Thu, 14 Jul 2022 10:57:00 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/smokeping-eu/</guid><enclosure url="https://static.yeri.be/2022/07/sg_last_2592000.png" length="0" type="image/png" />
      <description>&lt;p&gt;I&#39;ve revamped my Smokeping infra a bit &lt;a href=&#34;https://yeri.be/smokeping&#34;&gt;since 2020&lt;/a&gt;. &lt;/p&gt;&#xA;&lt;p&gt;First off, starting to use the &lt;a href=&#34;http://www.smokeping.eu&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;smokeping.eu&lt;/a&gt;&lt;sup&gt;1&lt;/sup&gt; domain that &lt;a href=&#34;https://github.com/BiancoZandbergen&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;Bianco&lt;/a&gt; got 10 or so years ago instead of using weird URLs under &lt;a href=&#34;http://superuser.one&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;superuser.one&lt;/a&gt; domain. &lt;/p&gt;&#xA;&lt;p&gt;It&#39;s running on four nodes as we speak: &lt;/p&gt;&#xA;&lt;ul&gt;&lt;li&gt;a virtual machine on a &lt;a href=&#34;https://yeri.be/tag/rootspirit/page/2&#34;&gt;colocation server&lt;/a&gt; in Leaseweb, Amsterdam, NL -&amp;gt; &lt;a href=&#34;https://leaseweb.nl.smokeping.eu/smokeping/&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;leaseweb.nl.smokeping.eu&lt;/a&gt;&lt;/li&gt;&lt;li&gt;a RPi3 (+SD card, slowest of all), Telenet, Belgium -&amp;gt; &lt;a href=&#34;http://telenet.be.smokeping.eu/&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;telenet.be.smokeping.eu&lt;/a&gt;&lt;/li&gt;&lt;li&gt;a RPi4, EDPnet, Belgium -&amp;gt; &lt;a href=&#34;https://edpnet.be.smokeping.eu/&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;edpnet.be.smokeping.eu&lt;/a&gt;&lt;/li&gt;&lt;li&gt;a RPi4, Starhub, Singapore -&amp;gt; &lt;a href=&#34;http://starhub.sg.smokeping.eu&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;starhub.sg.smokeping.eu&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&#xA;&lt;p&gt;This is achieved using Smokeping &lt;a href=&#34;https://docs.linuxserver.io/images/docker-smokeping&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;in a docker&lt;/a&gt; container, &lt;a href=&#34;https://www.cloudflare.com/en-gb/products/tunnel/&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;Cloudflare tunnel&lt;/a&gt; and Cloudflare CDN/DNS.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://static.yeri.be/2022/07/sg_last_2592000.png" alt="Smokeping.eu"></p><p>I've revamped my Smokeping infra a bit <a href="https://yeri.be/smokeping">since 2020</a>. </p>
<p>First off, starting to use the <a href="http://www.smokeping.eu" target="_blank" rel="noreferrer noopener">smokeping.eu</a><sup>1</sup> domain that <a href="https://github.com/BiancoZandbergen" target="_blank" rel="noreferrer noopener">Bianco</a> got 10 or so years ago instead of using weird URLs under <a href="http://superuser.one" target="_blank" rel="noreferrer noopener">superuser.one</a> domain. </p>
<p>It's running on four nodes as we speak: </p>
<ul><li>a virtual machine on a <a href="https://yeri.be/tag/rootspirit/page/2">colocation server</a> in Leaseweb, Amsterdam, NL -&gt; <a href="https://leaseweb.nl.smokeping.eu/smokeping/" target="_blank" rel="noreferrer noopener">leaseweb.nl.smokeping.eu</a></li><li>a RPi3 (+SD card, slowest of all), Telenet, Belgium -&gt; <a href="http://telenet.be.smokeping.eu/" target="_blank" rel="noreferrer noopener">telenet.be.smokeping.eu</a></li><li>a RPi4, EDPnet, Belgium -&gt; <a href="https://edpnet.be.smokeping.eu/" target="_blank" rel="noreferrer noopener">edpnet.be.smokeping.eu</a></li><li>a RPi4, Starhub, Singapore -&gt; <a href="http://starhub.sg.smokeping.eu" target="_blank" rel="noreferrer noopener">starhub.sg.smokeping.eu</a></li></ul>
<p>This is achieved using Smokeping <a href="https://docs.linuxserver.io/images/docker-smokeping" target="_blank" rel="noreferrer noopener">in a docker</a> container, <a href="https://www.cloudflare.com/en-gb/products/tunnel/" target="_blank" rel="noreferrer noopener">Cloudflare tunnel</a> and Cloudflare CDN/DNS.</p>
<pre class="wp-block-verse"><sup>1</sup> Doesn't point at anything at the moment. To do later.</pre>
]]></content:encoded>
      <category>linux</category><category>misc</category><category>networking</category><category>software</category><category>virtualisation</category>
      <category>docker</category><category>smokeping</category>
    </item>
    
    <item>
      <title>Running WireGuard in a Docker container (RPi)</title>
      <link>https://yeri.be/running-wireguard-in-a-docker-container-rpi/</link>
      <pubDate>Fri, 08 May 2020 18:10:00 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/running-wireguard-in-a-docker-container-rpi/</guid><enclosure url="https://static.yeri.be/2020/04/wg-liana.png" length="0" type="image/png" />
      <description>&lt;p&gt;This follows the my two other posts about &lt;a href=&#34;https://yeri.be/wireguard&#34; target=&#34;_blank&#34; aria-label=&#34;WireGuard (opens in a new tab)&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;WireGuard&lt;/a&gt;. &lt;/p&gt;&#xA;&lt;p&gt;Most of this can be copied from &lt;a aria-label=&#34;the amd64 post (opens in a new tab)&#34; href=&#34;https://yeri.be/running-wireguard-in-a-docker-container-(amd64)&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;the amd64 post&lt;/a&gt; -- with a minor change for making it work on RPi4. &lt;a aria-label=&#34;This is the full Git repo (opens in a new tab)&#34; href=&#34;https://gitlab.com/yeri/wireguard-docker/&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;This is the full &lt;/a&gt;&lt;a href=&#34;https://gitlab.com/yeri/wireguard-docker/&#34; target=&#34;_blank&#34; aria-label=&#34;This is the full Git repo (opens in a new tab)&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;g&lt;/a&gt;&lt;a aria-label=&#34;This is the full Git repo (opens in a new tab)&#34; href=&#34;https://gitlab.com/yeri/wireguard-docker/&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;it repo&lt;/a&gt; (including both rpi and amd64). &lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://static.yeri.be/2020/04/wg-liana.png" alt="Running WireGuard in a Docker container (RPi)"></p><p>This follows the my two other posts about <a href="https://yeri.be/wireguard" target="_blank" aria-label="WireGuard (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">WireGuard</a>. </p>
<p>Most of this can be copied from <a aria-label="the amd64 post (opens in a new tab)" href="https://yeri.be/running-wireguard-in-a-docker-container-(amd64)" target="_blank" rel="noreferrer noopener" class="aioseop-link">the amd64 post</a> -- with a minor change for making it work on RPi4. <a aria-label="This is the full Git repo (opens in a new tab)" href="https://gitlab.com/yeri/wireguard-docker/" target="_blank" rel="noreferrer noopener" class="aioseop-link">This is the full </a><a href="https://gitlab.com/yeri/wireguard-docker/" target="_blank" aria-label="This is the full Git repo (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">g</a><a aria-label="This is the full Git repo (opens in a new tab)" href="https://gitlab.com/yeri/wireguard-docker/" target="_blank" rel="noreferrer noopener" class="aioseop-link">it repo</a> (including both rpi and amd64). </p>
<p>The main difference is in the <a aria-label="run.sh file (opens in a new tab)" href="https://gitlab.com/yeri/wireguard-docker/-/blob/master/liana.run.sh" target="_blank" rel="noreferrer noopener" class="aioseop-link">run.sh file</a>. The installation is a bit different and we'll need to install the Raspberry Pi kernel headers. </p>
<p>WireGuard is also installed from testing instead of Debian backports. </p>
<p>Note that for older RPi's (ie gen 1) you'll need to <a href="https://github.com/adrianmihalko/raspberrypiwireguard" target="_blank" aria-label="compile from scratch (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">compile from scratch</a>. </p>
]]></content:encoded>
      <category>linux</category><category>networking</category><category>software</category>
      <category>debian</category><category>docker</category><category>raspberrypi</category><category>wireguard</category>
    </item>
    
    <item>
      <title>Error! Bad return status for module build on kernel: 4.19.0-8-amd64 (x86_64)</title>
      <link>https://yeri.be/error-bad-return-status-for-module-build-on-kernel-4-19-0-8-amd64-x86-64/</link>
      <pubDate>Mon, 04 May 2020 14:01:00 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/error-bad-return-status-for-module-build-on-kernel-4-19-0-8-amd64-x86-64/</guid><enclosure url="https://static.yeri.be/2020/05/WireGuard-dkms-crash.png" length="0" type="image/png" />
      <description>&lt;p&gt;I was rebuilding my &lt;a aria-label=&#34;WireGuard (opens in a new tab)&#34; href=&#34;https://yeri.be/tag/wireguard&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;WireGuard&lt;/a&gt; &lt;a aria-label=&#34;Docker (opens in a new tab)&#34; href=&#34;https://yeri.be/running-wireguard-in-a-docker-container-amd64&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;Docker&lt;/a&gt; container today and this error started popping up:&lt;/p&gt;&#xA;&lt;pre class=&#34;wp-block-code&#34;&gt;&lt;code&gt;Setting up dkms (2.6.1-4) ...&#xA;Setting up wireguard-dkms (1.0.20200429-1~bpo10+1) ...&#xA;Loading new wireguard-1.0.20200429 DKMS files...&#xA;It is likely that 4.19.0-8-cloud-amd64 belongs to a chroot&#39;s host&#xA;Building for 4.19.0-8-amd64 and 4.19.0-8-cloud-amd64&#xA;Building initial module for 4.19.0-8-amd64&#xA;Error! Bad return status for module build on kernel: 4.19.0-8-amd64 (x86_64)&#xA;Consult /var/lib/dkms/wireguard/1.0.20200429/build/make.log for more information.&#xA;dpkg: error processing package wireguard-dkms (--configure):&#xA; installed wireguard-dkms package post-installation script subprocess returned error exit status 10&#xA;Setting up build-essential (12.6) ...&#xA;Setting up libalgorithm-diff-xs-perl (0.04-5+b1) ...&#xA;Setting up libalgorithm-merge-perl (0.08-3) ...&#xA;dpkg: dependency problems prevent configuration of wireguard:&#xA; wireguard depends on wireguard-dkms (&gt;= 0.0.20200121-2) | wireguard-modules (&gt;= 0.0.20191219); however:&#xA;  Package wireguard-dkms is not configured yet.&#xA;  Package wireguard-modules is not installed.&#xA;&#xA;dpkg: error processing package wireguard (--configure):&#xA; dependency problems - leaving unconfigured&#xA;Processing triggers for systemd (241-7~deb10u3) ...&#xA;Processing triggers for libc-bin (2.28-10) ...&#xA;Errors were encountered while processing:&#xA; wireguard-dkms&#xA; wireguard&#xA;E: Sub-process /usr/bin/dpkg returned an error code (1)&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The solution was to install &lt;code&gt;bc&lt;/code&gt;. Seems like Debian is not pulling the right dependencies. I&#39;ll be adding it to my Dockerfile.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://static.yeri.be/2020/05/WireGuard-dkms-crash.png" alt="Error! Bad return status for module build on kernel: 4.19.0-8-amd64 (x86_64)"></p><p>I was rebuilding my <a aria-label="WireGuard (opens in a new tab)" href="https://yeri.be/tag/wireguard" target="_blank" rel="noreferrer noopener" class="aioseop-link">WireGuard</a> <a aria-label="Docker (opens in a new tab)" href="https://yeri.be/running-wireguard-in-a-docker-container-amd64" target="_blank" rel="noreferrer noopener" class="aioseop-link">Docker</a> container today and this error started popping up:</p>
<pre class="wp-block-code"><code>Setting up dkms (2.6.1-4) ...
Setting up wireguard-dkms (1.0.20200429-1~bpo10+1) ...
Loading new wireguard-1.0.20200429 DKMS files...
It is likely that 4.19.0-8-cloud-amd64 belongs to a chroot's host
Building for 4.19.0-8-amd64 and 4.19.0-8-cloud-amd64
Building initial module for 4.19.0-8-amd64
Error! Bad return status for module build on kernel: 4.19.0-8-amd64 (x86_64)
Consult /var/lib/dkms/wireguard/1.0.20200429/build/make.log for more information.
dpkg: error processing package wireguard-dkms (--configure):
 installed wireguard-dkms package post-installation script subprocess returned error exit status 10
Setting up build-essential (12.6) ...
Setting up libalgorithm-diff-xs-perl (0.04-5+b1) ...
Setting up libalgorithm-merge-perl (0.08-3) ...
dpkg: dependency problems prevent configuration of wireguard:
 wireguard depends on wireguard-dkms (>= 0.0.20200121-2) | wireguard-modules (>= 0.0.20191219); however:
  Package wireguard-dkms is not configured yet.
  Package wireguard-modules is not installed.

dpkg: error processing package wireguard (--configure):
 dependency problems - leaving unconfigured
Processing triggers for systemd (241-7~deb10u3) ...
Processing triggers for libc-bin (2.28-10) ...
Errors were encountered while processing:
 wireguard-dkms
 wireguard
E: Sub-process /usr/bin/dpkg returned an error code (1)</code></pre>
<p>The solution was to install <code>bc</code>. Seems like Debian is not pulling the right dependencies. I'll be adding it to my Dockerfile.</p>
]]></content:encoded>
      <category>linux</category><category>networking</category><category>software</category>
      <category>debian</category><category>docker</category><category>wireguard</category>
    </item>
    
    <item>
      <title>Running WireGuard in a Docker container (amd64)</title>
      <link>https://yeri.be/running-wireguard-in-a-docker-container-amd64/</link>
      <pubDate>Fri, 01 May 2020 17:09:00 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/running-wireguard-in-a-docker-container-amd64/</guid><enclosure url="https://static.yeri.be/2020/05/wg-ocean.png" length="0" type="image/png" />
      <description>&lt;p&gt;This is the 2nd post about &lt;a aria-label=&#34;WireGuard (opens in a new tab)&#34; href=&#34;https://yeri.be/tag/wireguard&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;WireGuard&lt;/a&gt;. &lt;/p&gt;&#xA;&lt;p&gt;So I am running two &lt;a aria-label=&#34;WireGuard (opens in a new tab)&#34; href=&#34;https://yeri.be/wireguard&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;WireGuard&lt;/a&gt; servers -- one on a Raspberry Pi 4, and one in an amd64 virtual machine. This post will be about getting WireGuard working on amd64 in a Docker container. &lt;/p&gt;&#xA;&lt;p&gt;As this container rarely get rebuild, I am running &lt;a aria-label=&#34;unattended-upgrades (opens in a new tab)&#34; href=&#34;https://wiki.debian.org/UnattendedUpgrades&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;unattended-upgrades&lt;/a&gt; inside the container to make sure security updates are applied. &lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://static.yeri.be/2020/05/wg-ocean.png" alt="Running WireGuard in a Docker container (amd64)"></p><p>This is the 2nd post about <a aria-label="WireGuard (opens in a new tab)" href="https://yeri.be/tag/wireguard" target="_blank" rel="noreferrer noopener" class="aioseop-link">WireGuard</a>. </p>
<p>So I am running two <a aria-label="WireGuard (opens in a new tab)" href="https://yeri.be/wireguard" target="_blank" rel="noreferrer noopener" class="aioseop-link">WireGuard</a> servers -- one on a Raspberry Pi 4, and one in an amd64 virtual machine. This post will be about getting WireGuard working on amd64 in a Docker container. </p>
<p>As this container rarely get rebuild, I am running <a aria-label="unattended-upgrades (opens in a new tab)" href="https://wiki.debian.org/UnattendedUpgrades" target="_blank" rel="noreferrer noopener" class="aioseop-link">unattended-upgrades</a> inside the container to make sure security updates are applied. </p>
<p>I am also running <a aria-label="Bind9 (opens in a new tab)" href="https://wiki.debian.org/Bind9" target="_blank" rel="noreferrer noopener" class="aioseop-link">Bind9</a> to act as a caching DNS server inside the container. Ideally this should be running from its dedicated container but that makes everything more complicated and not worth it for what I am trying. </p>
<p>I am also </p>
<p>The public repo that acts as a proof of concept can be found <a href="https://gitlab.com/yeri/wireguard-docker" target="_blank" aria-label=" (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">here</a>. </p>
<p><a href="https://gitlab.com/yeri/wireguard-docker/-/blob/master/start.sh" target="_blank" aria-label=" (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">start.sh</a> -- this file starts (or restarts) and builds the container. It will also create the files as needed, set the forwarding DNS server, etc. </p>
<p><a href="https://gitlab.com/yeri/wireguard-docker/-/blob/master/Dockerfile" target="_blank" aria-label=" (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">Dockerfile</a> -- the example will start a basic container based on debian-slim, set up the port forwarding, install the tools we need, and copy over the configs</p>
<p><a href="https://gitlab.com/yeri/wireguard-docker/-/blob/master/ocean.run.sh" target="_blank" aria-label=" (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">run.sh</a> -- this file will be executed after the container has been built. We need to install WireGuard from this file or it will fail due to the volume not being mounted and not having the right params. <br />This will also start the named (bind9) server. <br />I manually set <code>ip address add dev wg0 10.200.200.1/24</code> because using Address in <code>wg0.conf</code> caused issues. I haven't recently tested if that's still the case. </p>
<p><a aria-label=" (opens in a new tab)" href="https://gitlab.com/yeri/wireguard-docker/-/blob/master/files/named.conf.options.default" target="_blank" rel="noreferrer noopener" class="aioseop-link">named.conf.options</a> -- pretty standard bind9 config file; I want to be in control of my <a aria-label="forwarding (opens in a new tab)" href="https://docstore.mik.ua/orelly/networking_2ndEd/dns/ch10_05.htm" target="_blank" rel="noreferrer noopener" class="aioseop-link">forwarding</a> server because I am using <a aria-label="NextDNS (opens in a new tab)" href="https://yeri.be/tag/nextdns" target="_blank" rel="noreferrer noopener" class="aioseop-link">NextDNS</a> and want to apply a different config. </p>
<p>And of course your <a aria-label="wg0.conf (opens in a new tab)" href="https://gitlab.com/yeri/wireguard-docker/-/blob/master/files/ocean.wg0.conf" target="_blank" rel="noreferrer noopener" class="aioseop-link">wg0.conf</a>. </p>
<p>Running <code>docker exec wireguard wg</code> should give details about your connected hosts. </p>
]]></content:encoded>
      <category>linux</category><category>networking</category><category>software</category>
      <category>debian</category><category>docker</category><category>wireguard</category>
    </item>
    
    <item>
      <title>WireGuard</title>
      <link>https://yeri.be/wireguard/</link>
      <pubDate>Mon, 27 Apr 2020 20:34:00 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/wireguard/</guid><enclosure url="https://static.yeri.be/2020/04/WireGuard-network.png" length="0" type="image/png" />
      <description>&lt;p&gt;This is the first post of &lt;a href=&#34;https://yeri.be/tag/wireguard&#34; target=&#34;_blank&#34; aria-label=&#34; (opens in a new tab)&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;several&lt;/a&gt;. Next posts will focus on running WireGuard inside a Docker container on &lt;a href=&#34;https://yeri.be/running-wireguard-in-a-docker-container-(amd64)&#34; target=&#34;_blank&#34; aria-label=&#34;amd64 Linux (opens in a new tab)&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;amd64 Linux&lt;/a&gt; and a &lt;a href=&#34;https://yeri.be/running-wireguard-in-a-docker-container-rpi&#34; target=&#34;_blank&#34; aria-label=&#34;Raspberry Pi (opens in a new tab)&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;Raspberry Pi&lt;/a&gt;. &lt;/p&gt;&#xA;&lt;p&gt;I&#39;ve been running &lt;a aria-label=&#34;Wireguard (opens in a new tab)&#34; href=&#34;https://www.wireguard.com/&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;WireGuard&lt;/a&gt; for a few months now and I&#39;ve been loving it. &lt;/p&gt;&#xA;&lt;p&gt;I first started using it about a year ago when in &lt;a aria-label=&#34;China (opens in a new tab)&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34; href=&#34;https://yeri.be/tag/china&#34; target=&#34;_blank&#34;&gt;China&lt;/a&gt; — OpenVPN was once again being actively blocked and it was driving me nuts. Overnight I set up a &lt;a aria-label=&#34;DigitalOcean (opens in a new tab)&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34; href=&#34;https://m.do.co/c/3276c58fdbfd&#34; target=&#34;_blank&#34;&gt;DigitalOcean&lt;/a&gt; server in Singapore and ran WireGuard from it — both my phone and laptop were able to actively bypass the &lt;a aria-label=&#34;GFW (opens in a new tab)&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34; href=&#34;https://yeri.be/tag/gfw&#34; target=&#34;_blank&#34;&gt;GFW&lt;/a&gt; and (at that time) surf the internet freely once more. As WireGuard gains popularity, I am sure the GFW will start detecting it — it&#39;s a quiet but not a stealthy &lt;a aria-label=&#34;protocol (opens in a new tab)&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34; href=&#34;https://www.wireguard.com/protocol/&#34; target=&#34;_blank&#34;&gt;protocol&lt;/a&gt;. &lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://static.yeri.be/2020/04/WireGuard-network.png" alt="WireGuard"></p><p>This is the first post of <a href="https://yeri.be/tag/wireguard" target="_blank" aria-label=" (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">several</a>. Next posts will focus on running WireGuard inside a Docker container on <a href="https://yeri.be/running-wireguard-in-a-docker-container-(amd64)" target="_blank" aria-label="amd64 Linux (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">amd64 Linux</a> and a <a href="https://yeri.be/running-wireguard-in-a-docker-container-rpi" target="_blank" aria-label="Raspberry Pi (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">Raspberry Pi</a>. </p>
<p>I've been running <a aria-label="Wireguard (opens in a new tab)" href="https://www.wireguard.com/" target="_blank" rel="noreferrer noopener" class="aioseop-link">WireGuard</a> for a few months now and I've been loving it. </p>
<p>I first started using it about a year ago when in <a aria-label="China (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link" href="https://yeri.be/tag/china" target="_blank">China</a> — OpenVPN was once again being actively blocked and it was driving me nuts. Overnight I set up a <a aria-label="DigitalOcean (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link" href="https://m.do.co/c/3276c58fdbfd" target="_blank">DigitalOcean</a> server in Singapore and ran WireGuard from it — both my phone and laptop were able to actively bypass the <a aria-label="GFW (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link" href="https://yeri.be/tag/gfw" target="_blank">GFW</a> and (at that time) surf the internet freely once more. As WireGuard gains popularity, I am sure the GFW will start detecting it — it's a quiet but not a stealthy <a aria-label="protocol (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link" href="https://www.wireguard.com/protocol/" target="_blank">protocol</a>. </p>
<p>Since then I've dug quite a bit deeper in WireGuard and am really looking forward to what it's going to bring. </p>
<p>WireGuard differentiates itself to be an extremely simple VPN server (which can make getting started and debugging a bit more challenging) — but it wants to seamlessly work together with existing tools. One of the main features still missing is for example running a DHCP server on the server and dynamically assigning IPs (like oVPN does). </p>
<figure class="wp-block-image size-large"><a href="https://static.yeri.be/2020/04/WireGuard-network.png" target="_blank" rel="noopener noreferrer"><img src="https://static.yeri.be/2020/04/WireGuard-network.png" alt="WireGuard network" class="wp-image-8750"/></a><figcaption>Simplified diagram of my network. Using static routing my clients can access the WireGuard network even without running WireGuard directly. (Some of) my containers are also able to access the network, this allows me to run Resilio Sync over WireGuard. It's using one big subnet to create one big LAN. </figcaption></figure>
<p>It's also pretty cool because any node can both be a server and a client at the same time. In my setup I am running two servers: one running at home in Singapore on a RPi4 (1Gbit fiber connection) and one on a virtual machine in <a aria-label="Amsterdam (opens in a new tab)" href="https://yeri.be/tag/rootspirit/" target="_blank" rel="noreferrer noopener" class="aioseop-link">Amsterdam</a> (1Gbit as well). The RPis at my parents are connected to the server in Amsterdam, my iPad and phones are connected to the server in Singapore. If I am in Europe I might switch over and let my iDevices connect to the AMS server instead. </p>
<figure class="wp-block-image size-large"><a href="https://static.yeri.be/2020/04/WireGuard-and-traffic-shaping.png" target="_blank" rel="noopener noreferrer"><img src="https://static.yeri.be/2020/04/WireGuard-and-traffic-shaping-1024x150.png" alt="WireGuard and traffic shaping" class="wp-image-8751"/></a><figcaption>Click to enlarge. <br />Bandwidth stats from Resilio Sync, transferring several big files. We can clearly see a speed increase (from 2-5mb/s to 11mb/s) when routing the exact same traffic over WireGuard. <a aria-label="Traffic shaping (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link" href="https://en.wikipedia.org/wiki/Traffic_shaping" target="_blank">Traffic shaping</a> at its best.</figcaption></figure>
<p>The example above clearly shows speed gains by cloaking the traffic in UDP packets. The shared folder has only two nodes (sender and receiver) and shows several big files being transferred from Amsterdam to Singapore. <a aria-label="Resilio Sync (opens in a new tab)" href="https://www.resilio.com/individuals/" target="_blank" rel="noreferrer noopener" class="aioseop-link">Resilio Sync</a> uses the <a aria-label="Bittorrent protocol (opens in a new tab)" href="https://en.wikipedia.org/wiki/Resilio_Sync#Technology" target="_blank" rel="noreferrer noopener" class="aioseop-link">Bittorrent protocol</a>, something ISPs generally hate and tend to slow down as much as they can — thanks Starhub. </p>
<p>Wireguard also allows the client to decide what to route through the server: only the VPN LAN traffic, or a whole subnet, or 0.0.0.0/0? So for my iPhone I for example route all traffic through VPN to avoid hotel/airport/... WiFi's to mine/log/scan my data. For my laptop I have two configs, one to only connect to the LAN, but another that routes all my traffic through the VPN if I want to avoid exposure or circumvent censoring. </p>
<p>Note that I am not running WireGuard to remain anonymous and I'll definitely leak some information — just trying to minimise and remain in control of what I leak. This is not a <a aria-label="Tor (opens in a new tab)" rel="noreferrer noopener" href="https://www.torproject.org/" target="_blank" class="aioseop-link">Tor</a> replacement. </p>
]]></content:encoded>
      <category>linux</category><category>networking</category><category>software</category>
      <category>debian</category><category>docker</category><category>raspberrypi</category><category>vpn</category><category>wireguard</category>
    </item>
    
    <item>
      <title>Box — Docker shell server</title>
      <link>https://yeri.be/box-docker-shell-server/</link>
      <pubDate>Fri, 24 Apr 2020 10:27:00 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/box-docker-shell-server/</guid><enclosure url="https://static.yeri.be/2020/04/box.png" length="0" type="image/png" />
      <description>&lt;p&gt;A couple of months ago I had the great idea to set up a shell server in Docker. Simply because my docker skillz were quite rusty and a shell server was something I actually genuinely needed. &lt;/p&gt;&#xA;&lt;p&gt;Shell servers... so 2005. I remember in the good old IRC days people asking for (free) shell servers to run their &lt;a aria-label=&#34;eggdrop (opens in a new tab)&#34; href=&#34;https://eggheads.org/&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34; class=&#34;aioseop-link&#34;&gt;eggdrop&lt;/a&gt; and stuff. OMG am I getting old? Anyhow... &lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://static.yeri.be/2020/04/box.png" alt="Box — Docker shell server"></p><p>A couple of months ago I had the great idea to set up a shell server in Docker. Simply because my docker skillz were quite rusty and a shell server was something I actually genuinely needed. </p>
<p>Shell servers... so 2005. I remember in the good old IRC days people asking for (free) shell servers to run their <a aria-label="eggdrop (opens in a new tab)" href="https://eggheads.org/" target="_blank" rel="noreferrer noopener" class="aioseop-link">eggdrop</a> and stuff. OMG am I getting old? Anyhow... </p>
<p>I ssh quite often. I manage quite a few <a href="https://yeri.be/tag/rootspirit" target="_blank" aria-label="servers (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">servers</a> (~15?) and <a href="https://yeri.be/?s=edgerouter" target="_blank" aria-label="routers (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">routers</a> that require me to login and do some random stuff. I also work on a laptop quite often and that means closing the lid and moving around. </p>
<p>First of all, <a aria-label=" (opens in a new tab)" href="https://mosh.org/" target="_blank" rel="noreferrer noopener" class="aioseop-link">mosh</a> is amazing and allows you to stay connected via ssh, even with crappy (airport/hotel) internet as well as moving around networks -- that solves half the problem. If you are not using it, start using it now!</p>
<p>Second, during my <a aria-label="datacenter technician (opens in a new tab)" href="https://www.google.com/about/datacenters/" target="_blank" rel="noreferrer noopener" class="aioseop-link">datacenter technician</a> days at Google we used to have a "jump server" -- a shell server that allowed us to bridge the corporate network and ssh into prod machines. Doubt that's still used nowadays, but the idea stuck. I wanted something similar to ssh from, wherever I was, and easily connect to my servers. And as the network the shell server is running on is stable, I only need to use mosh to the shell server. Thereafter, the connection very rarely dies. </p>
<p>And I guess, third, I recently purchased an iPad Pro and I really need to have my local "dev" environment with my git repo that I edit quite frequently but iPadOS isn't really your average computer, and doesn't even have a proper terminal. This is my experiment to make iPadOS work as a main computer when on the move. </p>
<p>Enter box -- <a href="https://gitlab.com/yeri/box-public" target="_blank" aria-label="Docker shell server (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">Docker shell server</a>... <a href="https://gitlab.com/yeri/box-public" class="aioseop-link"></a></p>
<p>I've copied over the files I use to this <a aria-label="example repo (opens in a new tab)" href="https://gitlab.com/yeri/box-public" target="_blank" rel="noreferrer noopener" class="aioseop-link">example repo</a>, and added some comments. Mind you that this repo acts as a proof of concept and isn't kept up to date, as I have my own private repo -- but this should give you a good idea on how to set up your own shell server with Docker. </p>
<p><a aria-label=" (opens in a new tab)" href="https://gitlab.com/yeri/box-public/-/blob/master/start.sh" target="_blank" rel="noreferrer noopener" class="aioseop-link">start.sh</a> -- this is a simple script that I execute when I first run or need to update the container. I execute the same file on two different servers: <a label="Liana (opens in a new tab)" href="http://smokeping-sg.superuser.one/" target="_blank" rel="noreferrer noopener" class="aioseop-link">Liana</a>, my Raspberry Pi at home and <a aria-label="Ocean (opens in a new tab)" href="http://smokeping.rootspirit.com/" target="_blank" rel="noreferrer noopener" class="aioseop-link">Ocean</a>, my server in <a aria-label="Amsterdam (opens in a new tab)" href="https://yeri.be/tag/rootspirit" target="_blank" rel="noreferrer noopener" class="aioseop-link">Amsterdam</a>. </p>
<p><a href="https://gitlab.com/yeri/box-public/-/blob/master/zsh.sh" target="_blank" aria-label=" (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">zsh.sh</a> -- this installs what I care about for zsh. This could be part of the Dockerfile but for some reason I separated it. ¯\_(ツ)_/¯ </p>
<p><a aria-label=" (opens in a new tab)" href="https://gitlab.com/yeri/box-public/-/blob/master/git.sh" target="_blank" rel="noreferrer noopener" class="aioseop-link">git.sh</a> -- this clones my Git repos so I can edit and commit stuff from the shell server. </p>
<p><a aria-label="run.sh (opens in a new tab)" href="https://gitlab.com/yeri/box-public/-/blob/master/run.sh" target="_blank" rel="noreferrer noopener" class="aioseop-link">run.sh</a> -- this file is launched by Dockerfile at the end and executes what matters: the ssh daemon. It also adds a <a aria-label="Wireguard (opens in a new tab)" href="https://yeri.be/tag/wireguard" target="_blank" rel="noreferrer noopener" class="aioseop-link">Wireguard</a> route and executes the scripts above. </p>
<p><a aria-label=" (opens in a new tab)" href="https://gitlab.com/yeri/box-public/-/blob/master/Dockerfile" target="_blank" rel="noreferrer noopener" class="aioseop-link">Dockerfile</a> -- this installs everything I need and configures the whole thing. I've added tons of comments that should get you going. </p>
<p>I am also cloning <a aria-label="misc (opens in a new tab)" href="https://gitlab.com/yeri/homefiles/" target="_blank" rel="noreferrer noopener" class="aioseop-link">misc</a> and <a aria-label="homefiles (opens in a new tab)" href="https://gitlab.com/yeri/homefiles/" target="_blank" rel="noreferrer noopener" class="aioseop-link">homefiles</a> as submodules in <a aria-label="files/ (opens in a new tab)" href="https://gitlab.com/yeri/box-public/-/tree/master/files" target="_blank" rel="noreferrer noopener" class="aioseop-link">files/</a> -- but you should change this to something that works for you. See the Dockerfile for more info. </p>
]]></content:encoded>
      <category>apple</category><category>linux</category><category>networking</category><category>software</category><category>virtualisation</category>
      <category>debian</category><category>docker</category><category>raspberrypi</category><category>rootspirit</category><category>vpn</category><category>wireguard</category>
    </item>
    
  </channel>
</rss>
