<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>The Hidden Blog</title>
    <link>https://blog.notmyhostna.me/</link>
    <description>Recent content on The Hidden Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>mail@notmyhostna.me (Philipp Defner)</managingEditor>
    <webMaster>mail@notmyhostna.me (Philipp Defner)</webMaster>
    <lastBuildDate>Thu, 01 Feb 2024 14:20:17 +0100</lastBuildDate>
    
	<atom:link href="https://blog.notmyhostna.me/rss.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Lock Contention on Google Cloud SQL and Postgres</title>
      <link>https://blog.notmyhostna.me/posts/lock-contention-on-google-cloud-sql-and-postgres/</link>
      <pubDate>Thu, 01 Feb 2024 14:20:17 +0100</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/lock-contention-on-google-cloud-sql-and-postgres/</guid>
      <description>
        
          
        &lt;p&gt;I recently looked into some performance issues on a large PostgreSQL 13.12 instance. One part of that was to make sure we don’t have too much locking going on in busy tables.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/lock-contention-on-google-cloud-sql-and-postgres/Screenshot%202024-02-01%20at%2014.21.12.png@2x.png&#34; alt=&#34;Locking metrics on the Cloud SQL dashboard&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    Locking metrics on the Cloud SQL dashboard
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The first step was to enable &lt;code&gt;log_lock_waits&lt;/code&gt;, one of the &lt;a href=&#34;https://www.postgresql.org/docs/current/runtime-config-logging.html&#34;&gt;runtime flags&lt;/a&gt;. In Cloud SQL that’s just one of the default database flags you can flip to true. It doesn’t require a restart.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/lock-contention-on-google-cloud-sql-and-postgres/Screenshot%202024-02-01%20at%2014.29.11.png@2x.png&#34; alt=&#34;Cloud SQL database flags&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    Cloud SQL database flags
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;After keeping that in production for a while you can query the instance through the Log Explorer with something like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;resource&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cloudsql_database&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      resource&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;labels&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;database_id&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;db&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      log_name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;projects/company/logs/cloudsql.googleapis.com&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;%2F&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;postgres.log&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;textPayload:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ExclusiveLock&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If your locks are hitting the (default) 1 second threshold they will log something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zed&#34; data-lang=&#34;zed&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;db&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;db,user&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;db_write LOG&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;  process &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;2026853&lt;/span&gt; acquired ShareRowExclusiveLock on &lt;span style=&#34;color:#f92672&#34;&gt;relation&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;19062&lt;/span&gt; of database &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;16448&lt;/span&gt; after &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;3267&lt;/span&gt;.&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;563&lt;/span&gt; ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then you can look up the relation id like &lt;code&gt;select 19062::regclass;&lt;/code&gt; and it’ll tell you which table is affected. This should give you a good start for your investigation.&lt;/p&gt;
&lt;p&gt;A great article about the topic can be found as always on the &lt;a href=&#34;https://pganalyze.com/blog/5mins-postgres-lock-monitoring-lwlock-log-lock-waits&#34;&gt;pganalyze blog&lt;/a&gt;.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Two months in Hong Kong</title>
      <link>https://blog.notmyhostna.me/posts/two-months-in-hong-kong/</link>
      <pubDate>Sat, 30 Dec 2023 17:26:59 +0100</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/two-months-in-hong-kong/</guid>
      <description>
        
          
        &lt;p&gt;In 2023 I spent two months in Hong Kong, here’s a small subset of places that I remember and liked. More inspiration for places to visit are in my vlog episodes I shared &lt;a href=&#34;https://blog.notmyhostna.me/posts/vlogging/&#34;&gt;in a previous post&lt;/a&gt;. There’s a lot of things missing but half the fun is finding places yourself anyway.&lt;/p&gt;
&lt;h2 id=&#34;essentials&#34;&gt;Essentials&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://apps.apple.com/us/app/octopus-for-tourists/id1505492952&#34;&gt;Octopus Card for iOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cash for Taxi&lt;/li&gt;
&lt;li&gt;Take all the Ding Dings (Trams) and ferries&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;skyline-watching&#34;&gt;Skyline watching&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/FtykPjbauteT6di86&#34;&gt;Peak Lookout&lt;/a&gt;, don’t pay for the Peak Tower&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/UD54QCrv24JFH2JP7&#34;&gt;Eyebar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;buying&#34;&gt;Buying&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/4MopYHFhSSnDtvhb9&#34;&gt;80M Bus Model Shop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cha-chaan-teeng-breakfast--lunch&#34;&gt;Cha chaan teeng (Breakfast / Lunch)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/oTbs4RwrfoXhBuLK9&#34;&gt;Boss House&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/LJTXgg7LKNRGwTSDA&#34;&gt;Kam Fung Restaurant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/dWQkvcRWU9sKt1Vc8&#34;&gt;Waso Cafe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/JzAKTyf8ZPWtKrmL7&#34;&gt;Men Wah Bing Teng&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;restaurants&#34;&gt;Restaurants&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/N2L9uFgDbteXmbQb8&#34;&gt;Yat Lok&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/EeR6pjMyWUmUa8Jt5&#34;&gt;Joy Hing Roasted Meat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;areas-to-walk-around&#34;&gt;Areas to walk around&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/8nAAib3o79x9inhu9&#34;&gt;Lily St&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/NdZ3fhfXamRmyLDe8&#34;&gt;Victoria Park Model Boat Pool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/9kz36sz5jVamPtL27&#34;&gt;Blue Bottle Coffee&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/aFnp6SNAH2WKJNXW9&#34;&gt;Hong Kong Trail from the Peak&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/MXX8eiw5KJJhyb3M9&#34;&gt;Hong Kong Park&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;chill-beer-drinking-place&#34;&gt;Chill beer drinking place&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/igHvxdb7XP8Txxpy5&#34;&gt;Inn Side Out&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;hackerspace&#34;&gt;Hackerspace&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/mhmSctDsLtTtfpfE9&#34;&gt;Dim Sum Labs&lt;/a&gt;, every Tuesday there’s &lt;a href=&#34;https://www.dimsumlabs.com&#34;&gt;an open hack night&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;running--hiking&#34;&gt;Running / Hiking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/U2K1zDR1tUu37Auh8&#34;&gt;Happy Valley Recreation Ground&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/KGHz2hZqXrWduhSM9&#34;&gt;Lamma Island for hiking and Dim Sum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/1qrvGcSc9A5ZcFcf6&#34;&gt;Shek O Beach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/eXHrg9aqkXUZaYW38&#34;&gt;Big Wave Beach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/8HGyEU6h6JDCAMbA6&#34;&gt;Pui O Beach&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;best-public-toilets&#34;&gt;Best public toilets&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://maps.app.goo.gl/SfmkuuSf6ZqEV6XD8&#34;&gt;Pacific Place&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Vlogging</title>
      <link>https://blog.notmyhostna.me/posts/vlogging/</link>
      <pubDate>Wed, 27 Dec 2023 21:40:08 +0100</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/vlogging/</guid>
      <description>
        
          
        &lt;p&gt;This year I started playing around with creating video content. The goal was to create low-effort semi-frequent video summaries of what I have been up to. I didn’t want to do narration or anything else that would raise the barrier of publishing a video.&lt;/p&gt;
&lt;p&gt;All videos are available on my YouTube channel which I called &lt;a href=&#34;https://www.youtube.com/@infrequentupdates&#34;&gt;Infrequent Updates&lt;/a&gt;. In retrospect the name is quite accurate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Berlin to Hong Kong, Star Ferry, walking around and taking pictures of taxis&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/cD2aMxezIc0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Hong Kong Park, Peak Tram to Victoria Peak, Hiking down and Kennedy Town&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/FitLpQI93PQ&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Macaroni Soup for breakfast, visiting old Kai Tak Airport, Checkerboard Hill and finding an old Taxi&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/1a3iGSOsX84&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Breakfast at Blue Bottle Coffee, walking stairs, Crew Coffee Shop and the burned Kimpton hotel&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/ceqc5ycbHtA&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Fast boats in the park, a very small TV and a hike to Big Wave Bay Beach (Big waves, many stairs!)&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/WFO2C-oqVt0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Running in Happy Valley, fast bus to Clear Water Bay Beach, Ferraris and Ding Dings&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/GMQZQQOcll0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Symphony of Lights, Ice cream truck music, taking ferry at night and driving to Tai Po&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/TD5BvaiSN10&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Hiking Victoria Peak to Kennedy Town in the fog for 4 hours&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/uJf9OReTkq8&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;October in Berlin. Walking from Kreuzberg to Mitte&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/Imqg4MyvqyU&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Fall in Berlin with leaves and trams&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/e_823F_yMyY&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;I do still enjoy creating these little visual diaries and will continue to publish new videos on the channel.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Taking a look at Nostr</title>
      <link>https://blog.notmyhostna.me/posts/taking-a-look-at-nostr/</link>
      <pubDate>Tue, 07 Feb 2023 22:00:52 +0100</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/taking-a-look-at-nostr/</guid>
      <description>
        
          
        &lt;p&gt;After hearing about &lt;a href=&#34;https://github.com/nostr-protocol/nostr&#34;&gt;Nostr&lt;/a&gt; from multiple people over the past weeks I decided to take a look and learn more about it. I found &lt;a href=&#34;https://github.com/nostr-protocol/nostr&#34;&gt;nostr-resources.com&lt;/a&gt;, &lt;a href=&#34;https://github.com/nostr-protocol/nostr&#34;&gt;usenostr.org&lt;/a&gt; and &lt;a href=&#34;https://github.com/nostr-protocol/nostr&#34;&gt;github.com/aljazceru/awesome-nostr&lt;/a&gt; to be helpful to get an initial overview.&lt;/p&gt;
&lt;h2 id=&#34;running-a-nostr-relay&#34;&gt;Running a nostr relay&lt;/h2&gt;
&lt;p&gt;As a next step I looked into setting up my own relay and it’s surprisingly simple. I now have a relay based on &lt;a href=&#34;https://github.com/scsibug/nostr-rs-relay&#34;&gt;github.com/scsibug/nostr-rs-relay&lt;/a&gt; running at &lt;code&gt;wss://nostr.notmyhostna.me&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I was looking for a simple Go + Postgres relay project but that doesn&amp;rsquo;t seem to exist yet. This is a fast-moving landscape right now though, so this might be outdated information in a week.&lt;/p&gt;
&lt;p&gt;If you are using &lt;code&gt;docker-compose&lt;/code&gt; it&amp;rsquo;s a simple as the following snippet, additionally you&amp;rsquo;ll have to configure your reverse proxy (nginx, in my case) to point that container.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  nostr:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    image: scsibug/nostr-rs-relay:latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    restart: always
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ports:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &amp;#34;7000:8080&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - /home/ubuntu/services/nostr/nostr-config/config.toml:/usr/src/app/config.toml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - /home/ubuntu/services/nostr/nostr-data:/usr/src/app/db
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The relay starting up and listening to web socket connections:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.606  INFO nostr_rs_relay: Starting up from main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.607  INFO nostr_rs_relay::server: listening on: 0.0.0.0:8080
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.610  INFO nostr_rs_relay::repo::sqlite: Built a connection pool &amp;#34;writer&amp;#34; (min=1, max=2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.611  INFO nostr_rs_relay::repo::sqlite: Built a connection pool &amp;#34;maintenance&amp;#34; (min=1, max=2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.612  INFO nostr_rs_relay::repo::sqlite: Built a connection pool &amp;#34;reader&amp;#34; (min=4, max=8)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.612  INFO nostr_rs_relay::repo::sqlite_migration: DB version = 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.810  INFO nostr_rs_relay::repo::sqlite_migration: database pragma/schema initialized to v15, and ready
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.810  INFO nostr_rs_relay::repo::sqlite_migration: All migration scripts completed successfully.  Welcome to v15.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.811  INFO nostr_rs_relay::server: db writer created
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb 07 19:39:39.811  INFO nostr_rs_relay::server: control message listener started
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;writing-my-first-post&#34;&gt;Writing my first &amp;ldquo;post&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;I used &lt;a href=&#34;https://iris.to/#/post/note1u46qrha7f8x3n8nquzeugjzmjmyzs6vq7pauj5f6vmkzruypmqysc4vg40&#34;&gt;iris.to&lt;/a&gt; to write my first &amp;ldquo;post&amp;rdquo;. What I found scary is that for all clients you have to use your one-and-only private key as the password to log into your account. I didn&amp;rsquo;t look too much into existing plans to have finer grained &amp;ldquo;sub-keys&amp;rdquo; in the future, but I&amp;rsquo;m sure that&amp;rsquo;s something that&amp;rsquo;s being discussed.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what an event payload looks like, every field is explained in the protocol specification &lt;a href=&#34;https://github.com/nostr-protocol/nips/blob/master/README.md#event-kinds&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;content&amp;#34;: &amp;#34;Testing Nostr!&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;created_at&amp;#34;: 1675799677,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;id&amp;#34;: &amp;#34;e57401dfbe49cd199e60e0b3c4485b96c8286980f07bc9513a66ec21f081d809&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;kind&amp;#34;: 1,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;pubkey&amp;#34;: &amp;#34;6e5d92642b2a5e03ff59b50ff14b5c54a08ceceb465146985b8ffa3527523c8b&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;sig&amp;#34;: &amp;#34;fdf1b3f635cd706b216970c86ec3db35e075369d4feabe64e3789c695bf18dabb2468424aece8885bcad6c8f0aa2d786d055d3c940a2b7da4d5550d6d2555830&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;tags&amp;#34;: []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Replies to that post will then reference this id in their &lt;code&gt;tags&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;created_at&amp;#34;: 1675799932,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;pubkey&amp;#34;: &amp;#34;fe2d5cf62e95aab419b07b6f8a7b75d3cb3066fae25c6b44ace0f9f30c59303d&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;kind&amp;#34;: 1,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;content&amp;#34;: &amp;#34;We hear you!&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;sig&amp;#34;: &amp;#34;b8313fcc6644fe8cd7841da7e0dcb0381f3155c7b3802fc54d655e60808f29b88c513db3c45c323e6738abf44d96f0e3866893858ae54fc230f971f1c93ca7d9&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;id&amp;#34;: &amp;#34;21b120394430ad51188c6fe62632ecb269d41bb5ae9bc6a18a90448e864c6932&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;tags&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;e&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;e57401dfbe49cd199e60e0b3c4485b96c8286980f07bc9513a66ec21f081d809&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;p&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;6e5d92642b2a5e03ff59b50ff14b5c54a08ceceb465146985b8ffa3527523c8b&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;finding-people-to-follow&#34;&gt;Finding people to follow&lt;/h2&gt;
&lt;p&gt;The best way I&amp;rsquo;ve found so far is &lt;a href=&#34;https://nostr.directory&#34;&gt;nostr.directory&lt;/a&gt;. This tool scans people you follow on Twitter and checks if they posted a &amp;ldquo;proof&amp;rdquo; tweet to verify their nostr.directory entry.&lt;/p&gt;
&lt;h2 id=&#34;current-impression&#34;&gt;Current impression&lt;/h2&gt;
&lt;p&gt;The project is still in a very early stage. It is more confusing than Mastodon for non-technical newcomers but from a technical point of view it&amp;rsquo;s very simple.&lt;/p&gt;
&lt;p&gt;The iOS app &lt;a href=&#34;https://github.com/damus-io/damus&#34;&gt;Damus&lt;/a&gt; looks more polished than expected, but is also buggy. I was not able to add my own relay to it, for example. That there&amp;rsquo;s an app at all in the iOS app store at this early stage is a big plus though. It makes giving this a try so much easier.&lt;/p&gt;
&lt;p&gt;For now I&amp;rsquo;ll keep an eye on the project and keep my relay running. I&amp;rsquo;m looking forward to seeing more projects being built on this protocol.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Fixing failed installation of EPSON printer driver</title>
      <link>https://blog.notmyhostna.me/posts/fixing-failed-installation-of-epson-printer-driver/</link>
      <pubDate>Tue, 03 Jan 2023 13:10:42 +0100</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/fixing-failed-installation-of-epson-printer-driver/</guid>
      <description>
        
          
        &lt;p&gt;Recently I ran into the issue where installing an &lt;a href=&#34;https://epson.com/Support/Printers/Single-Function-Inkjet-Printers/SureColor-Series/Epson-SureColor-P900/s/SPT_C11CH37201?review-filter=Mac+OS+X+10.7.x&#34;&gt;EPSON SC-P900&lt;/a&gt; printer driver on macOS (before and after the update to Ventura) always failed with a generic &amp;ldquo;Installation failed&amp;rdquo; message.&lt;/p&gt;
&lt;p&gt;I started my investigation by looking at the installation log with the following command while clicking through the installation dialog.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tail &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;f &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;log&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;install&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;log
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the logs it became clear that it&amp;rsquo;s a permission problem. The installation process tried to copy data from the installation sandbox to &lt;code&gt;/Library/Extensions/EPSONUSBPrintClass.kext&lt;/code&gt;. This failed with: &lt;code&gt;operation not permitted&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I tried running the package installation with &lt;code&gt;sudo&lt;/code&gt;, restarting and updating macOS but that didn&amp;rsquo;t fix it.&lt;/p&gt;
&lt;p&gt;After checking this directory I saw that &lt;code&gt;EPSONUSBPrintClass.kext&lt;/code&gt; was created in 2014 and probably got carried over through many macOS updates. Somewhere along the way permissions likely got messed up.&lt;/p&gt;
&lt;p&gt;I decided to delete the file and I tried to just delete the file while macOS is running, this doesn&amp;rsquo;t work via the Finder or through the Terminal as the Library volume is read-only in the new macOS versions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The solution is to &lt;a href=&#34;https://support.apple.com/en-us/HT201255&#34;&gt;start in recovery mode&lt;/a&gt; by holding Command (⌘)-R while starting your Mac. Then navigate to Utilities &amp;gt; Terminal and start a Terminal. Everything in recovery mode is a bit slower so be patient.&lt;/p&gt;
&lt;p&gt;Navigate to the directory where the kext is located. Keep in mind that it&amp;rsquo;s not in &lt;code&gt;/Library&lt;/code&gt; but &lt;code&gt;/Volumes/Macintosh HD/Library&lt;/code&gt; while you are in recovery mode. Replace Macintosh HD with the name of your boot volume. Both directories exist but &lt;code&gt;/Library&lt;/code&gt; won&amp;rsquo;t have the non-standard kernel extensions (kext) files so this might be confusing.&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;rm -rf /Volumes/Macintosh HD/Library/Extensions/EPSONUSBPrintClass.kext&lt;/code&gt; to delete the wrong file. Reboot the Mac and re-install the driver. Now everything should work!&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Convert video for Twitter</title>
      <link>https://blog.notmyhostna.me/posts/convert-video-for-twitter/</link>
      <pubDate>Tue, 11 Oct 2022 20:59:40 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/convert-video-for-twitter/</guid>
      <description>
        
          
        &lt;p&gt;If you want to post a video on Twitter there&amp;rsquo;s a &lt;a href=&#34;https://help.twitter.com/en/using-twitter/twitter-videos&#34;&gt;few rules&lt;/a&gt; that are important for the video to be accepted.&lt;/p&gt;
&lt;p&gt;Unfortunately the interface will only show &amp;ldquo;The video file is not compatible&amp;rdquo; while only the actual API request in the background will tell you exactly what is wrong. If you know where to look, that is.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/convert-video-for-twitter/Screen%20Shot%202022-10-11%20at%2020.44.24.png&#34; alt=&#34;Twitter API showing exactly why the video doesn&amp;rsquo;t work&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    Twitter API showing exactly why the video doesn&amp;rsquo;t work
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;On of the rules is a max frame rate of 60fps. If your video has more you have to change that.&lt;/p&gt;
&lt;h2 id=&#34;first-extract-the-raw-bit-stream&#34;&gt;First, extract the raw bit stream&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i your-high-framerate-video.mp4 -c copy -f h264 raw-stream.h264
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;remux-that-back-into-a-new-mp4-container&#34;&gt;Remux that back into a new mp4 container&lt;/h2&gt;
&lt;p&gt;With the &lt;code&gt;-r&lt;/code&gt; flag we can &lt;code&gt;set frame rate (Hz value, fraction or abbreviation)&lt;/code&gt; according to the documentation.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -r 60 -i raw-stream.h264 -c copy your-60-fps-video.mp4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;upload&#34;&gt;Upload&lt;/h2&gt;
&lt;p&gt;Now we can upload the video to Twitter. If you want to know what&amp;rsquo;s the &lt;em&gt;real&lt;/em&gt; reason your video doesn&amp;rsquo;t work you can check that in the network inspector. Look for the request hitting the &lt;code&gt;upload.json&lt;/code&gt; endpoint.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is one of these posts I&amp;rsquo;m writing for myself so future-me can copy paste from here.&lt;/em&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Push notifications from AppSignal with Pushover</title>
      <link>https://blog.notmyhostna.me/posts/push-notifications-from-appsignal-with-pushover/</link>
      <pubDate>Fri, 16 Sep 2022 20:06:58 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/push-notifications-from-appsignal-with-pushover/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/push-notifications-from-appsignal-with-pushover/feature.jpeg" width="1700" height="600"/>]]>
           
        &lt;p&gt;I&amp;rsquo;m using &lt;a href=&#34;https://www.appsignal.com&#34;&gt;AppSignal&lt;/a&gt; to monitor &lt;a href=&#34;https://getbirdfeeder.com&#34;&gt;Birdfeeder&lt;/a&gt;. Birdfeeder&amp;rsquo;s job is to send your Twitter bookmarks to your email inbox so you don&amp;rsquo;t forget about them.&lt;/p&gt;
&lt;p&gt;On the technical side it&amp;rsquo;s a Rails app which relies on Sidekiq to process background jobs. Bookmarks have to be fetched, accounts have to be refreshed, tokens have to be kept fresh. To make sure all of that happens and there&amp;rsquo;s no spike of errors that goes unnoticed I&amp;rsquo;m using AppSignal.&lt;/p&gt;
&lt;h2 id=&#34;set-up-appsignal-webhook&#34;&gt;Set up AppSignal Webhook&lt;/h2&gt;
&lt;p&gt;I was looking for a way to send specific, critical alerts to my phone as push notification without relying on another paid service like PagerDuty.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/push-notifications-from-appsignal-with-pushover/appsignal_integrations.png&#34; alt=&#34;Available integrations on AppSignal&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    Available integrations on AppSignal
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;After checking the available integrations on AppSignal I was happy to see that they support &lt;a href=&#34;https://en.wikipedia.org/wiki/Webhook&#34;&gt;Webhooks&lt;/a&gt;. Webhooks are requests that are sent based on an action. You define a http endpoint on service2 and service1 will perform a post request to service2 once a specific event occurs.&lt;/p&gt;
&lt;h2 id=&#34;connect-appsignal-and-pushover-with-pipedream&#34;&gt;Connect AppSignal and Pushover with Pipedream&lt;/h2&gt;
&lt;p&gt;For the push notifications I already use &lt;a href=&#34;https://pushover.net&#34;&gt;Pushover&lt;/a&gt; to receive notifications from other services like Sonarr or Plex on my phone. Pushover doesn&amp;rsquo;t have a Webhook receiver, that means we need to use another service to receive the Webhook from Appsignal, extract the necessary information and then trigger the Pushover notification.&lt;/p&gt;
&lt;p&gt;I found a service called &lt;a href=&#34;https://pipedream.com&#34;&gt;Pipedream&lt;/a&gt; which does exactly that and offers a bunch of other integrations. Setting it up is easy but you have to provide an example payload (The one that AppSignal would send) to configure which fields you want to use in the Pushover message.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/push-notifications-from-appsignal-with-pushover/pipedream_integrations.png&#34; alt=&#34;Pipedream.com dashboard&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    Pipedream.com dashboard
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;You can find examples for the various hooks in &lt;a href=&#34;https://docs.appsignal.com/application/integrations/webhooks.html&#34;&gt;AppSignal&amp;rsquo;s documentation&lt;/a&gt;. Copy these JSON responses and paste them on Pipedream. Then you can set up which variables should be used in the push notification in the interface shown below.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/push-notifications-from-appsignal-with-pushover/pushover_payload.png&#34; alt=&#34;Configuring the Pushover message based on variables received from the Webhook&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    Configuring the Pushover message based on variables received from the Webhook
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;That&amp;rsquo;s already it, after that set up which alerts or exceptions should be sent via push notifications on AppSignal. Our final setup looks like this:&lt;/p&gt;
&lt;img src=&#34;diagram.svg&#34; alt=&#34;Final setup to connect AppSignal to Pushover&#34;&gt;
&lt;p&gt;If you are interested in signing up feel free to use my affiliate link for &lt;a href=&#34;https://appsignal.com/r/20aab2dfa4&#34;&gt;AppSignal&lt;/a&gt;.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Building container images in Kubernetes with kaniko</title>
      <link>https://blog.notmyhostna.me/posts/building-container-images-in-kubernetes-with-kaniko/</link>
      <pubDate>Tue, 13 Sep 2022 09:37:17 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/building-container-images-in-kubernetes-with-kaniko/</guid>
      <description>
        
          
        &lt;p&gt;A few weeks ago I rebuilt a GitLab CI pipeline at JustWatch. One part of that was to move the step building the container images in the Kubernetes cluster from &lt;a href=&#34;https://github.com/justwatchcom/artificer&#34;&gt;artificer&lt;/a&gt; to &lt;a href=&#34;https://github.com/GoogleContainerTools/kaniko&#34;&gt;kaniko&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I wrote up a short guide on the &lt;a href=&#34;https://www.justwatch.com/blog/post/building-container-images-in-kubernetes-with-kaniko/&#34;&gt;JustWatch blog&lt;/a&gt; in case you are curious.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Listening to a movie as an audiobook</title>
      <link>https://blog.notmyhostna.me/posts/listening-to-a-movie-as-an-audiobook/</link>
      <pubDate>Wed, 27 Jul 2022 18:55:51 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/listening-to-a-movie-as-an-audiobook/</guid>
      <description>
        
          
        &lt;p&gt;Today I was reading a &lt;a href=&#34;https://news.ycombinator.com/item?id=32248964&#34;&gt;comment on HN&lt;/a&gt; that piqued my interest.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I used to rip the audio of my favourite movies and listen to them like audiobooks. Because I was usually familiar with the visual parts, I could enjoy the dialogue and the music in a different way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This sounded like a simple enough task with FFmpeg, so I wanted to give it a try with my favorite movie.&lt;/p&gt;
&lt;h2 id=&#34;find-audio-track-in-the-file&#34;&gt;Find audio track in the file&lt;/h2&gt;
&lt;p&gt;First step is to check what kind of tracks are in the movie file. The best tool for that depends on your source file, in my case that&amp;rsquo;s an MKV file so I used &lt;code&gt;mkvinfo&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkvinfo My\ favorite\ movie.mkv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It will give information about the video and audio tracks available in the file. Being interested in the audio track only we look for a section showing &lt;code&gt;Track type: audio&lt;/code&gt;. It will look similar to that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| + Track
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  + Track number: 2 (track ID for mkvmerge &amp;amp; mkvextract: 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  + Track UID: 2018713736
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  + Track type: audio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  + Codec ID: A_DTS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  + Name: 5.1 DTS 1510 Kbps - DTSHD MA Core
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The important part is the information about &lt;code&gt;mkvextract&lt;/code&gt; which tells us that it is &amp;ldquo;track 1&amp;rdquo; if we use &lt;code&gt;mkvextract&lt;/code&gt; to extract the audio track.&lt;/p&gt;
&lt;h2 id=&#34;extract-audio-track&#34;&gt;Extract audio track&lt;/h2&gt;
&lt;p&gt;We use &lt;code&gt;mkvextract&lt;/code&gt; to extract the audio track from the file and define that we want to extract the first track (&lt;code&gt;tracks 1:output.dtshd&lt;/code&gt;) and store it as &lt;code&gt;output.dtshd&lt;/code&gt;. The file ending doesn&amp;rsquo;t matter.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkvextract My\ favorite\ movie.mkv tracks 1:output.dtshd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;transcode-to-apple-lossless--flac&#34;&gt;Transcode to Apple Lossless / FLAC&lt;/h2&gt;
&lt;p&gt;Next step is to transcode that file from DTS-HD to something that&amp;rsquo;s more portable like ALAC or FLAC.&lt;/p&gt;
&lt;p&gt;ALAC:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i output.dtshd -acodec alac my-favorite-movie-as-an-audiobook.m4a
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;FLAC:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i output.dtshd -acodec flac my-favorite-movie-as-an-audiobook.flac
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want to double check the bitrate / sampling rate of the FLAC file you can use &lt;code&gt;metaflac&lt;/code&gt; like &lt;code&gt;metaflac --list my-favorite-movie-as-an-audiobook.flac&lt;/code&gt; to inspect the file.&lt;/p&gt;
&lt;h2 id=&#34;update-extraction--transcode-with-ffmpeg&#34;&gt;Update: Extraction &amp;amp; transcode with ffmpeg&lt;/h2&gt;
&lt;p&gt;As Manu correctly &lt;a href=&#34;https://twitter.com/manu_faktur/status/1552357098096320513&#34;&gt;pointed out on Twitter&lt;/a&gt; you can also combine some of these steps into one.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Also don&amp;rsquo;t have to do a separate extraction step, ffmpeg can do it all in one go: &amp;ldquo;ffmpeg -i input.mkv -map 0:1 -acodec alac output.m4a&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;

      </description>
    </item>
    
    <item>
      <title>Migrating from self-hosted Postgres to DigitalOcean</title>
      <link>https://blog.notmyhostna.me/posts/migrating-from-self-hosted-postgres-to-digitalocean/</link>
      <pubDate>Thu, 14 Jul 2022 21:31:20 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/migrating-from-self-hosted-postgres-to-digitalocean/</guid>
      <description>
        
          
        &lt;p&gt;Until now &lt;a href=&#34;https://getbirdfeeder.com&#34;&gt;Birdfeeder&lt;/a&gt; was powered by a self-hosted Postgres instance which is used by &lt;a href=&#34;https://lastcast.fm&#34;&gt;various&lt;/a&gt; &lt;a href=&#34;https://editorialsync.com&#34;&gt;other&lt;/a&gt; side projects. It was running out of space and decided to migrate to a managed Postgres instance on &lt;a href=&#34;https://m.do.co/c/4c9ebc04eec1&#34;&gt;DigitalOcean (Affiliate link, giving you $100 in credits)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The reason for going managed was that I didn&amp;rsquo;t want to deal with backups and have the option to scale up with the click of a button.&lt;/p&gt;
&lt;p&gt;I couldn&amp;rsquo;t find a simple guide on how to move from a self-hosted instance to a managed instance on DigitalOcean and decided to write a short summary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;: Move database from source instance to target instance with little read/write downtime.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Out of scope&lt;/strong&gt;: No read / write downtime&lt;/p&gt;
&lt;h1 id=&#34;create-new-instance&#34;&gt;Create new instance&lt;/h1&gt;
&lt;p&gt;Start by creating a new Postgres instance on DigitalOcean. This will take a couple of minutes. After this is done verify that the IP you are accessing the database from is added to &amp;ldquo;Trusted sources&amp;rdquo; in the control panel.&lt;/p&gt;
&lt;h1 id=&#34;create-database&#34;&gt;Create database&lt;/h1&gt;
&lt;p&gt;Once the database is running log in with the &lt;code&gt;doadmin&lt;/code&gt; user that DigitalOcean is displaying in the interface. I prefer to use a GUI client like &lt;a href=&#34;https://eggerapps.at/postico2/&#34;&gt;Postico&lt;/a&gt; to query the database.&lt;/p&gt;
&lt;p&gt;Run the following command to create the database and the role you&amp;rsquo;ll be using to access the database. The naming doesn&amp;rsquo;t matter, it&amp;rsquo;s a personal preference.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;create&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;role&lt;/span&gt; birdfeederdb_prod_write &lt;span style=&#34;color:#66d9ef&#34;&gt;WITH&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;createdb&lt;/span&gt; password &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;some-very-secure-password&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;create&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt; birdfeederdb_prod;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;set-permissions-for-role-and-schema&#34;&gt;Set permissions for role and schema&lt;/h2&gt;
&lt;p&gt;Create the schema under which the tables will be created. The new role will get the permissions to use the schema and create tables.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;create&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;schema&lt;/span&gt; birdfeederdb;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;alter&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;role&lt;/span&gt; birdfeederdb_prod_write &lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; search_path &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;birdfeederdb&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;grant&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;usage&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;on&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;schema&lt;/span&gt; birdfeederdb &lt;span style=&#34;color:#66d9ef&#34;&gt;to&lt;/span&gt; birdfeederdb_prod_write;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;grant&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;create&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;on&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;schema&lt;/span&gt; birdfeederdb &lt;span style=&#34;color:#66d9ef&#34;&gt;to&lt;/span&gt; birdfeederdb_prod_write;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;alter&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt; birdfeederdb_prod &lt;span style=&#34;color:#66d9ef&#34;&gt;owner&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;to&lt;/span&gt; birdfeederdb_prod_write;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;alter&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;schema&lt;/span&gt; birdfeederdb &lt;span style=&#34;color:#66d9ef&#34;&gt;owner&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;to&lt;/span&gt; birdfeederdb_prod_write;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;create-backup-from-source-instance&#34;&gt;Create backup from source instance&lt;/h2&gt;
&lt;p&gt;Stop all writes to the old database. In my case I shut down my app and everything accessing the database.&lt;/p&gt;
&lt;p&gt;Replace the value behind the &lt;code&gt;-h&lt;/code&gt; flag with the IP or hostname of the source database. You have to provide the username and the database name. It&amp;rsquo;s likely that this is the same information that your app is currently using to access the database.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pg_dump -h 10.0.0.1 -U birdfeederdb_prod_write -p 5432 -Fc birdfeederdb_prod &amp;gt; birdfeederdb_prod.pgsql
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;restore-backup-to-target-instance&#34;&gt;Restore backup to target instance&lt;/h2&gt;
&lt;p&gt;Now it&amp;rsquo;s time to import the backup into the new managed Postgres running on DigitalOcean.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pg_restore -d &amp;#39;postgresql://birdfeederdb_prod_write:some-very-secure-password@your.instance.hostname.db.ondigitalocean.com:25060/birdfeederdb_prod?sslmode=require&amp;#39; --no-owner --role=birdfeederdb_prod_write --clean --jobs 4 --if-exists birdfeederdb_prod_.pgsql
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not using the &lt;code&gt;--if-exists&lt;/code&gt; flag will result in seeing non-critical errors. More about that can be read in the &lt;a href=&#34;https://www.postgresql.org/docs/current/app-pgrestore.html&#34;&gt;Postgres documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;restart-your-services&#34;&gt;Restart your services&lt;/h2&gt;
&lt;p&gt;Now you can update the hostname/port in your app and it will start talking to the new database.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Check Postgres table dependencies for cascade</title>
      <link>https://blog.notmyhostna.me/posts/check-postgres-table-dependencies-for-cascade/</link>
      <pubDate>Wed, 13 Jul 2022 20:28:44 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/check-postgres-table-dependencies-for-cascade/</guid>
      <description>
        
          
        &lt;p&gt;Currently I&amp;rsquo;m working on a better staging setup for &lt;a href=&#34;https://getbirdfeeder.com&#34;&gt;Birdfeeder&lt;/a&gt;. A big part of that is syncing the production database to the staging database while cleaning out user specific information. An easy way to do that is to use SQL to truncate the &lt;code&gt;users&lt;/code&gt; table.&lt;/p&gt;
&lt;p&gt;When I tried to truncate my &lt;code&gt;users&lt;/code&gt; table I noticed that my foreign keys don&amp;rsquo;t have an &lt;code&gt;ON DELETE&lt;/code&gt; action set. In that case deleting a row that is referenced from another row would fail instead of cascading the delete action further up the tree.&lt;/p&gt;
&lt;p&gt;I was wondering what&amp;rsquo;s the best way to see the dependencies between entities in Postgres and found &lt;a href=&#34;https://www.postgresql.org/docs/9.5/catalog-pg-depend.html&#34;&gt;pg_depend&lt;/a&gt; which does exactly that.&lt;/p&gt;
&lt;h2 id=&#34;query&#34;&gt;Query&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;with recursive chain as (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    select classid, objid, objsubid, conrelid
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    from pg_depend d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    join pg_constraint c on c&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;oid &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; objid
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    where refobjid &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;users&amp;#39;&lt;/span&gt;::regclass &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; deptype &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;n&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;union all
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    select d&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;classid, d&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;objid, d&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;objsubid, c&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;conrelid
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    from pg_depend d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    join pg_constraint c on c&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;oid &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; objid
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    join chain on d&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;refobjid &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; chain&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;conrelid &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; d&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;deptype &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;n&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;select pg_describe_object(classid, objid, objsubid), pg_get_constraintdef(objid)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from chain;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Source: Thanks to &lt;a href=&#34;https://stackoverflow.com/a/37977656/989919&#34;&gt;klin on StackOverflow&lt;/a&gt; for that neat snippet.&lt;/p&gt;
&lt;h2 id=&#34;output&#34;&gt;Output&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;pg_describe_object&lt;/th&gt;
&lt;th&gt;pg_get_constraintdef&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;constraint fk_rails_c1ff6fa4ac on table bookmarks&lt;/td&gt;
&lt;td&gt;FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;example-from-birdfeeder&#34;&gt;Example from Birdfeeder&lt;/h2&gt;
&lt;p&gt;The bookmark mapping table maps a tweet to a user. If I would delete the user from the &lt;code&gt;users&lt;/code&gt; table that is referenced in the &lt;code&gt;bookmarks&lt;/code&gt; table it would fail.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CREATE TABLE birdfeederdb.bookmarks (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    id BIGSERIAL PRIMARY KEY,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tweet_id bigint NOT NULL REFERENCES birdfeederdb.tweets(id),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user_id bigint NOT NULL REFERENCES birdfeederdb.users(id),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We have to add a migration to tell the database that it can also delete the row if the row it&amp;rsquo;s referencing got deleted (&amp;ldquo;If someone deletes the user, delete the bookmarks of that user&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;After running the migration the schema will look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CREATE TABLE birdfeederdb.bookmarks (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    id BIGSERIAL PRIMARY KEY,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tweet_id bigint NOT NULL REFERENCES birdfeederdb.tweets(id),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user_id bigint NOT NULL REFERENCES birdfeederdb.users(id) ON DELETE CASCADE,);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you use Rails the migration is as simple as that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;class AddCascadeToBookmarks &amp;lt; ActiveRecord::Migration[7.0]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  def change
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    remove_foreign_key &amp;#34;bookmarks&amp;#34;, &amp;#34;users&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    add_foreign_key &amp;#34;bookmarks&amp;#34;, &amp;#34;users&amp;#34;, on_delete: :cascade
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  end
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;end
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you can just delete a user from the &lt;code&gt;users&lt;/code&gt; table and the database will take care of cleaning up the entities that reference that user.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Birdfeeder Tech Stack</title>
      <link>https://blog.notmyhostna.me/posts/birdfeeder-tech-stack/</link>
      <pubDate>Tue, 22 Mar 2022 20:44:54 +0100</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/birdfeeder-tech-stack/</guid>
      <description>
        
          
        &lt;p&gt;After &lt;a href=&#34;https://blog.notmyhostna.me/posts/birdfeeder-twitter-bookmarks-in-your-email-inbox/&#34;&gt;sharing some information&lt;/a&gt; about how Birdfeeder collects your Twitter bookmarks and sends them to your inbox we are going to take a look at the technical foundation of the project in this blog post.&lt;/p&gt;
&lt;p&gt;Spoiler: It&amp;rsquo;s a boring Rails app and it&amp;rsquo;s good that way.&lt;/p&gt;
&lt;h2 id=&#34;collecting-the-bookmarks&#34;&gt;Collecting the bookmarks&lt;/h2&gt;
&lt;p&gt;This would be a straight forward project if you could use the Twitter API for it. Unfortunately this is not supported by the old Twitter API and not yet implemented in the new one. Luckily it&amp;rsquo;s on the roadmap for the &lt;a href=&#34;https://trello.com/b/myf7rKwV/twitter-developer-platform-roadmap&#34;&gt;Twitter API V2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because of that limitation I had to build a browser extension that collects the bookmarks while you interact with your Twitter account in the browser. Right now there&amp;rsquo;s an extension for &lt;a href=&#34;https://chrome.google.com/webstore/detail/birdfeeder-twitter-bookma/mnichhhjlmpefomikojlgbejdpgijdbh&#34;&gt;Google Chrome&lt;/a&gt; and one for &lt;a href=&#34;https://addons.mozilla.org/en-US/firefox/addon/birdfeeder-twitter-bookmarks/&#34;&gt;Mozilla Firefox&lt;/a&gt;. I wrote about my experiences with building the extension &lt;a href=&#34;https://blog.notmyhostna.me/posts/building-web-extensions-for-chrome-firefox-and-safari/&#34;&gt;in another blog post&lt;/a&gt; in case you are curious.&lt;/p&gt;
&lt;h2 id=&#34;storing-the-bookmark-information&#34;&gt;Storing the bookmark information&lt;/h2&gt;
&lt;p&gt;The backend of Birdfeeder is built using Rails 7, Postgres, Redis and Sidekiq. The browser extension is using cookies to figure out the Birdfeeder User ID and Twitter User ID (That&amp;rsquo;s why you have to be logged into both Twitter and Birdfeeder). Periodically it submits new bookmarks to the getbirdfeeder.com/bookmarks endpoint where they will be stored if they don&amp;rsquo;t exist yet.&lt;/p&gt;
&lt;p&gt;When a bookmark is stored we have to fetch the meta information for the Tweet ID. This is done through a cron job which executes a Redis-backed Sidekiq task. This task is using the user&amp;rsquo;s Twitter information to fetch metadata for the tweet that will then be displayed in the weekly email. Using the user&amp;rsquo;s Twitter token to fetch this information makes sure that they can see bookmarked tweets that are private and only visible to them.&lt;/p&gt;
&lt;h2 id=&#34;sending-the-email&#34;&gt;Sending the email&lt;/h2&gt;
&lt;p&gt;If there&amp;rsquo;s one thing I learned from this project it&amp;rsquo;s that building email templates is hard if you have to do it by hand.&lt;/p&gt;
&lt;p&gt;Luckily I found a framework called &lt;a href=&#34;https://maizzle.com/docs/introduction/&#34;&gt;Maizzle&lt;/a&gt; that makes it as easy as it gets. It is based on Tailwind and compiles your template into email-ready HTML with inline CSS (HTML Emails have a lot of limitations, one of them is that the styles have to be inline).&lt;/p&gt;
&lt;p&gt;Can&amp;rsquo;t recommend it enough!&lt;/p&gt;
&lt;h2 id=&#34;frontend&#34;&gt;Frontend&lt;/h2&gt;
&lt;p&gt;Rails, TailwindCSS and TailwindUI.&lt;/p&gt;
&lt;h2 id=&#34;infrastructure&#34;&gt;Infrastructure&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s running in Docker on a boring server and I&amp;rsquo;m using Gitlab for one-click deployments. Emails are being sent by &lt;a href=&#34;https://postmarkapp.com&#34;&gt;Postmark&lt;/a&gt;. I&amp;rsquo;m using &lt;a href=&#34;https://plausible.io&#34;&gt;Plausible&lt;/a&gt; for analytics as for all my projects.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;That&amp;rsquo;s already all there is to it. &lt;a href=&#34;https://twitter.com/tehwey&#34;&gt;Follow me on Twitter&lt;/a&gt; if you want to follow the project progress.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Birdfeeder: Twitter bookmarks in your email inbox</title>
      <link>https://blog.notmyhostna.me/posts/birdfeeder-twitter-bookmarks-in-your-email-inbox/</link>
      <pubDate>Tue, 22 Mar 2022 19:55:55 +0100</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/birdfeeder-twitter-bookmarks-in-your-email-inbox/</guid>
      <description>
        
          
        &lt;p&gt;I&amp;rsquo;m a heavy user of Twitter bookmarks but I always forget checking them when I would actually have time to do so. I use them to bookmark tweets I later want to share with someone or tweets that point to longer articles when I&amp;rsquo;m in a hurry.&lt;/p&gt;
&lt;p&gt;To change that I decided to work on a new project. It&amp;rsquo;s called &lt;a href=&#34;https://getbirdfeeder.com&#34;&gt;Birdfeeder&lt;/a&gt; and it is a simple tool that collects your bookmarked tweets and sends them to you once a week. You can customize the day and time you want to receive the summary email to suit your schedule.&lt;/p&gt;
&lt;p&gt;Once a week you&amp;rsquo;ll get an email like that with your Twitter bookmarks:&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/birdfeeder-twitter-bookmarks-in-your-email-inbox/screenshot-mail.png&#34; alt=&#34;Screenshot of a Birdfeeder weekly email&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    Screenshot of a Birdfeeder weekly email
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;p&gt;Using Birdfeeder is really simple as the browser extension automatically recognizes you if you are logged into Birdfeeder and Twitter at the same time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Log in with your Twitter account on &lt;a href=&#34;https://getbirdfeeder.com&#34;&gt;getbirdfeeder.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install the extension for your browser. Currently &lt;a href=&#34;https://chrome.google.com/webstore/detail/birdfeeder-twitter-bookma/mnichhhjlmpefomikojlgbejdpgijdbh&#34;&gt;Google Chrome&lt;/a&gt; or &lt;a href=&#34;https://addons.mozilla.org/en-US/firefox/addon/birdfeeder-twitter-bookmarks/&#34;&gt;Mozilla Firefox&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Make sure you are logged into &lt;a href=&#34;https://twitter.com/home&#34;&gt;twitter.com&lt;/a&gt; in your browser.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To be sure everything is working correctly click on the small Birdfeeder icon in your browser and verify that everything is green.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/birdfeeder-twitter-bookmarks-in-your-email-inbox/Screen%20Shot%202022-03-16%20at%2022.54.02.png&#34; alt=&#34;The Birdfeeder browser extension&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    The Birdfeeder browser extension
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;If you decide to give it a try &lt;a href=&#34;https://twitter.com/tehwey&#34;&gt;let me know what&lt;/a&gt; you think.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Building Web Extensions for Chrome, Firefox and Safari</title>
      <link>https://blog.notmyhostna.me/posts/building-web-extensions-for-chrome-firefox-and-safari/</link>
      <pubDate>Wed, 19 Jan 2022 22:50:34 +0100</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/building-web-extensions-for-chrome-firefox-and-safari/</guid>
      <description>
        
          
        &lt;p&gt;For my new side project I needed to build a browser extension. I was hesitant to build one as the development experience of doing everything in the browser seemed annoying to debug.&lt;/p&gt;
&lt;p&gt;After hearing more and more about Web Extensions and even Safari adding support recently I assumed that now is the time to take this on.&lt;/p&gt;
&lt;p&gt;I found out that it was optimistic to think that now you&amp;rsquo;ll write one extension, compile it for the 3 platforms, upload it to the respective extension stores and you are done.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Write_once,_run_anywhere&#34;&gt;“Write once, run anywhere”&lt;/a&gt; was once again a lie.&lt;/p&gt;
&lt;h2 id=&#34;misconception-1&#34;&gt;Misconception 1:&lt;/h2&gt;
&lt;p&gt;Manifest 3 is the new hotness and that&amp;rsquo;s what you should use&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reality:&lt;/strong&gt; Mozilla and Google are still fighting over what Manifest v3 is supposed to be. For now Firefox doesn&amp;rsquo;t really support Manifest 3, their &lt;a href=&#34;https://www.extensiontest.com&#34;&gt;extension testing website&lt;/a&gt; is only working with v2 (&lt;a href=&#34;https://twitter.com/tehwey/status/1483531515631919106&#34;&gt;or at least is broken in general&lt;/a&gt;) and all the tooling to build a Safari extension is &lt;a href=&#34;https://developer.apple.com/forums/thread/687783&#34;&gt;only working for Manifest v2&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;misconception-2&#34;&gt;Misconception 2:&lt;/h2&gt;
&lt;p&gt;The Web Extension shares the same code for all platforms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reality:&lt;/strong&gt; There&amp;rsquo;s subtle differences so you&amp;rsquo;ll still end up with either platform conditions or separate code bases. Even small differences like &lt;code&gt;browser.webRequest.onBeforeSendHeaders&lt;/code&gt; and &lt;code&gt;chrome.webRequest.onBeforeSendHeaders&lt;/code&gt; behaving differently.&lt;/p&gt;
&lt;h2 id=&#34;misconception-3&#34;&gt;Misconception 3:&lt;/h2&gt;
&lt;p&gt;A simple fetch will behave the same in Chrome and Firefox.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reality:&lt;/strong&gt; Firefox does something differently and you&amp;rsquo;ll run into CORS issues. I think it might be related to &lt;a href=&#34;https://stackoverflow.com/a/49098515/989919&#34;&gt;this issue&lt;/a&gt; but I wasn&amp;rsquo;t able so solve it yet. Currently I just whitelisted the &lt;code&gt;moz-ext://...&lt;/code&gt; header in the backend which is not ideal.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In general it seems to be that the Mozilla Firefox tooling for developing extensions is more polished. They have a CLI build tool: &lt;code&gt;web-ext build&lt;/code&gt; and &lt;code&gt;web-ext run&lt;/code&gt; which runs and auto-reloads the extension. Including for Manifest changes where Chrome always needed me to remove and re-add the extension.&lt;/p&gt;
&lt;p&gt;It is possible that some of my solutions or understandings of the issues are wrong, I&amp;rsquo;m still new to this. If you spot something off, let me know!&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Review: GL-iNet Beryl MT1300 Travel Router (Apple TV on a VPN)</title>
      <link>https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/</link>
      <pubDate>Thu, 14 Jan 2021 21:00:51 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/feature.JPG" width="1500" height="1125"/>]]>
           
        &lt;p&gt;This is a short review of a new gadget I recently purchased. I sometimes have the need to route my Apple TV&amp;rsquo;s traffic through a VPN. This can be for simple geolocation issues but also to prevent ISPs throttling IPTV traffic.&lt;/p&gt;
&lt;p&gt;The Apple TV currently doesn&amp;rsquo;t support running a VPN directly on the device. If it would be possible it wouldn&amp;rsquo;t be that useful as apps could then check if a VPN is running and refuse to work. The solution is to move the VPN one layer up so the Apple TV (or any other device) is just connected to a network and don&amp;rsquo;t know anything about the VPN.&lt;/p&gt;
&lt;p&gt;There are multiple ways to achieve that, I tried some of them but decided against them after testing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Integrated &lt;a href=&#34;https://support.apple.com/guide/mac-help/share-internet-connection-mac-network-users-mchlp1540/mac&#34;&gt;Internet Sharing&lt;/a&gt; on macOS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is a feature of macOS that allows your Mac that’s connected to the internet with a wired connection to act as an access point providing WiFi to other devices. This works but I couldn’t figure out how to redirect traffic through the VPN running on the Mac. After playing around with &lt;code&gt;ipfw&lt;/code&gt; and L2TP I couldn’t get it to work and moved on. It sometimes worked but wasn&amp;rsquo;t stable or fast enough.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Provisioning the Apple TV with a &lt;a href=&#34;https://community.tealiumiq.com/t5/Installation-Libraries/Setting-up-Apple-Configurator-and-Charles-to-Proxy-an-Apple-TV/ta-p/17518&#34;&gt;custom Network proxy profile&lt;/a&gt; via the Apple Configurator&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This worked but some apps didn’t work or realized they were on a   proxy or VPN. I suspect the OS is telling the apps that a Proxy Profile is running. In my test case I used authenticated HTTP proxies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Raspberry Pi&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I thought about using a Raspberry Pi that’s on a wired connection, connecting it to a VPN and sharing this connection via WiFi with the Apple TV. There’s multiple ways to do that but setting up a VPN, updating and monitoring this sounded like work I didn&amp;rsquo;t want to do.&lt;/p&gt;
&lt;p&gt;In the end I wanted the Raspberry Pi solution but in a nicely packaged version where I don’t have to play system administrator.&lt;/p&gt;
&lt;h2 id=&#34;solution&#34;&gt;Solution&lt;/h2&gt;
&lt;p&gt;After more research I found &lt;a href=&#34;https://www.gl-inet.com&#34;&gt;GL-iNet&lt;/a&gt;, a Hong Kong based company building all kinds of devices like that.&lt;/p&gt;
&lt;p&gt;I pre-ordered the new &lt;a href=&#34;https://www.gl-inet.com/products/gl-mt1300/&#34;&gt;Beryl MT1300 Travel Router&lt;/a&gt; and after a trip around the world it arrived after a few weeks.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/delivery.jpg&#34; alt=&#34;Router Delivery&#34;/&gt; &lt;/figure&gt;

&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;
&lt;p&gt;The setup was straight forward. Connect to power with the included USB-C power adapter and plug Ethernet cable to the WAN port of the Beryl. Wait a 1-2 minutes until it started up and then connect to the pre-configured WiFi with the GL-MT1300 SSID.&lt;/p&gt;
&lt;p&gt;There are easy to follow printed instructions (and stickers) included that make all of this a breeze.&lt;/p&gt;
&lt;p&gt;Once you are connected to the WiFi open the web interface available on &lt;code&gt;http://192.168.8.1&lt;/code&gt; and start configuring the router. Everything is mostly self-explanatory.&lt;/p&gt;
&lt;h2 id=&#34;features&#34;&gt;Features&lt;/h2&gt;
&lt;p&gt;The full overview with hardware specs can be found on GL-iNet&amp;rsquo;s &lt;a href=&#34;https://www.gl-inet.com/products/gl-mt1300/#specs&#34;&gt;website&lt;/a&gt;. This is a brief overview covering the features I used so far.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Status dashboard&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the main view where you can see which uplink is used, which WiFi SSIDs are active and how many clients are connected. In my case you can see that out of the four networks that are available only one is enabled. I currently don&amp;rsquo;t have a use case for the guest network (With captive portal) or 2.4GHz networks.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/Screen%20Shot%202021-01-14%20at%2019.14.39.jpg&#34; alt=&#34;The  main status dashboard&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Easy one-click updates&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the main reason why I got a ready-made solution and am not using a home-brew Raspberry Pi version where I have to keep dependencies updated, resolve issues and edit configs.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/Screen%20Shot%202021-01-14%20at%2019.14.47.png&#34; alt=&#34;Update screen&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Using the hardware buttons&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The router has a small hardware button where frequently used actions can be toggled without visiting the web interface. You can define which one with a single click through the interface:&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/Screen%20Shot%202021-01-14%20at%2019.15.16.png&#34; alt=&#34;Configure buttons&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Custom DNS servers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&#34;https://nextdns.io&#34;&gt;NextDNS&lt;/a&gt; on all my devices for ad-blocking and tracking prevention directly on the network level. It&amp;rsquo;s like &lt;a href=&#34;https://pi-hole.net&#34;&gt;Pi-hole&lt;/a&gt; without the fiddling. Setting this up for all devices connected to the Beryl is also just one click.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: If you haven&amp;rsquo;t used NextDNS you should give it a try. Read their Privacy Policy while you are at it, it&amp;rsquo;s very brief: &lt;a href=&#34;https://nextdns.io/privacy&#34;&gt;NextDNS Privacy Policy&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/Screen%20Shot%202021-01-14%20at%2019.15.34.png&#34; alt=&#34;Set custom DNS servers&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;WireGuard Server&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Probably the easiest way to set up a WireGuard server and you don&amp;rsquo;t even have to do &lt;code&gt;iptables&lt;/code&gt; gymnastics.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/Screen%20Shot%202021-01-14%20at%2019.16.11.png&#34; alt=&#34;Set up WireGuard server&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Tor&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now you can order from the dark net just by connecting to your own Tor WiFi. Neat, I guess?&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/Screen%20Shot%202021-01-14%20at%2019.16.16.png&#34; alt=&#34;Passing all your traffic through Tor&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;VPN Client&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the feature I bought the device for, you can just import your WireGuard or OpenVPN profiles and connect. Then if enabled all traffic going through the Beryl will get passed through the VPN.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/review-gl-inet-beryl-mt1300-travel-router-apple-tv-on-a-vpn/Screen%20Shot%202021-01-14%20at%2019.16.22.png&#34; alt=&#34;Connecting to a OpenVPN&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;So far this works very well for me. If you have any questions feel free to reach out on &lt;a href=&#34;https://twitter.com/tehwey&#34;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Almost Paperless Office</title>
      <link>https://blog.notmyhostna.me/posts/almost-paperless-office/</link>
      <pubDate>Wed, 15 Jul 2020 22:00:51 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/almost-paperless-office/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/almost-paperless-office/feature.JPG" width="2000" height="1328"/>]]>
           
        &lt;p&gt;Recently I looked at my increasingly large pile of &lt;em&gt;important&lt;/em&gt; documents and decided to make sorting them a small project. After a while it was clear that a lot of them are not important enough to keep around. Invoices, warranty certificates or insurance status updates are likely not necessary to have in their original paper form.&lt;/p&gt;
&lt;p&gt;Having them in a big binder makes it very hard to quickly find a document that you know you have &lt;em&gt;somewhere&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The obvious solution was to look into a good setup for a paperless “office”. Before starting my research I narrowed it down to a number of features that I deemed non-negotiable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Good OCR (Text recognition)&lt;/li&gt;
&lt;li&gt;Native Mac app&lt;/li&gt;
&lt;li&gt;Syncing with iCloud Drive possible&lt;/li&gt;
&lt;li&gt;Easy way to fulltext search through all documents&lt;/li&gt;
&lt;li&gt;A way to tag and organize documents by topics or categories&lt;/li&gt;
&lt;li&gt;No closed source or proprietary archiving format / container&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That means that at a higher level my setup consists of three parts: A scanner, software to organize documents and a shredder to destroy the documents before throwing them out.&lt;/p&gt;
&lt;h2 id=&#34;step-1-scanning&#34;&gt;Step 1: Scanning&lt;/h2&gt;
&lt;p&gt;I spent some time reading reviews and in the end decided on buying the &lt;strong&gt;Fujitsu ScanSnap iX1500&lt;/strong&gt;. Its predecessors were well regarded and while everyone agreed that the software was not particularly beautiful it did its job well enough.&lt;/p&gt;
&lt;h2 id=&#34;step-2-organizing&#34;&gt;Step 2: Organizing&lt;/h2&gt;
&lt;p&gt;Even before starting this project I played around with &lt;a href=&#34;https://c-command.com/eaglefiler/&#34;&gt;EagleFiler&lt;/a&gt; and enjoyed it. It&amp;rsquo;s from a reputable developer (and &lt;a href=&#34;https://mjtsai.com/blog/&#34;&gt;blogger&lt;/a&gt;) who&amp;rsquo;s apps have been around for a long time.&lt;/p&gt;
&lt;p&gt;EagleFiler makes having a &lt;a href=&#34;https://c-command.com/eaglefiler/help/the-library-is-open&#34;&gt;open format&lt;/a&gt; a feature and not just an afterthought. This, to me, is very important for a software that should keep my documents safe and accessible for a long time.&lt;/p&gt;
&lt;p&gt;As written on the &lt;a href=&#34;https://c-command.com/eaglefiler/&#34;&gt;website&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;EagleFiler libraries use an open format: regular files and folders that are fully accessible to your other applications.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The site has a very exhaustive help section documenting every distinct feature of the app. One relevant example: &lt;a href=&#34;https://c-command.com/eaglefiler/help/importing-from-a-scanne&#34;&gt;Importing from a Scanner&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Right now I have the included scanner software (ScanSnap Home) set up to scan directly into a directory (&lt;code&gt;~/Documents/Incoming Scans&lt;/code&gt;). ScanSnap is configured to hand over its scanned documents directly to &lt;a href=&#34;https://www.pfu.fujitsu.com/imaging/downloads/manual/ss_webhelp/en/help/webhelp/topic/ope_appli_abbyy_detail.html&#34;&gt;ABBYY FineReader for ScanSnap&lt;/a&gt; which performs OCR and stores the resulting file in the mentioned &lt;code&gt;Incoming Scans&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;EagleFiler has a special watch directory called &amp;ldquo;To Import&amp;rdquo; located in its library directory (&lt;code&gt;~/Documents/EagleFiler Library&lt;/code&gt; in my case) which promptly imports files thrown in there into its internal library. Unfortunately I had issues with that as then ABBYY FineReader complained that it can only work on files directly coming from ScanSnap or failed with the following obscure error message.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/almost-paperless-office/abbyerror.png&#34; alt=&#34;Error shown in ABBYY FineReader&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;I contacted the — very helpful and quick to respond — ABBYY support but they said the issue isn&amp;rsquo;t known after escalating it. My guess is that this is some kind of race condition if multiple apps try to access the same file. I resolved the issue by using Hazel to monitor the &amp;ldquo;Incoming Scans&amp;rdquo; folder and moving the file to EagleFiler&amp;rsquo;s &amp;ldquo;To Import&amp;rdquo; directory once the file was processed by ABBYY FineReader and received its &lt;code&gt;_OCR.pdf&lt;/code&gt; suffix.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/almost-paperless-office/hazel.png&#34; alt=&#34;Hazel task to moved finished documents&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;With this glue component everything now works without a hitch and the ABBYY error message never showed up again. I was able to scan 100 documents without it showing up. In my first iteration I stored my &amp;ldquo;EagleFiler Library&amp;rdquo; directory in iCloud Drive and suspected that that&amp;rsquo;s a problem but it seems to only be related to ABBYY accessing the file at the same time. I did have some other issue with putting it in iCloud Drive but that was mostly related to ScanSnap not being able to deal with long file paths and a workaround was swiftly explained by the developer &lt;a href=&#34;https://forum.c-command.com/t/alternative-to-to-import-folder-symlinking/12790?u=dewey&#34;&gt;in the support forum&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Update: In the EagleFiler 1.8.14 &lt;a href=&#34;https://c-command.com/eaglefiler/help/version-history&#34;&gt;Changelog&lt;/a&gt; I spotted an interesting improvement that sounds like it’ll help with that.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The To Import folder can now be replaced by an alias if you want to relocate it to another location (e.g. to work around a ScanSnap path length limitation).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tagging &amp;amp; Organizing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is one of the areas where I&amp;rsquo;m not completely satisfied with EagleFiler yet as the importing workflow seems unnecessarily unoptimized for an action that will be done very frequently.&lt;/p&gt;
&lt;p&gt;These days I’m importing a lot of documents which don&amp;rsquo;t have metadata yet as they come — with a slight detour through the OCR app — from the scanner. They do have a filename but I want to set the &amp;ldquo;From&amp;rdquo; field (Phone Company Ltd., Insurance Company,&amp;hellip;) and optionally tag them based on what kind of document it is (Insurance, Taxes, Invoices,&amp;hellip;).&lt;/p&gt;
&lt;p&gt;When a new file comes in I open its info panel via &lt;code&gt;Command + I&lt;/code&gt; and I am presented with the following options.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/almost-paperless-office/import.png&#34; alt=&#34;Info panel of a document in EagleFiler&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s easy to navigate through them with the keyboard but only the &amp;ldquo;Tags&amp;rdquo; field auto completes existing tags. That means that I have to use a clipboard manager or external tool (&lt;a href=&#34;https://forum.c-command.com/t/some-issues-and-suggestions/10513/5?u=dewey&#34;&gt;Thread in support forum&lt;/a&gt;) to make sure I use a consistent spelling of the source name. (Was it Telekom AG or Telekom GmbH again?). Also to reach the (for me) often used Tags field I have to hit tab 9 times to jump through the date and time fields.&lt;/p&gt;
&lt;p&gt;I would love to have a kind of more “Inbox&amp;quot; view optimized for quick tagging similar to how the &amp;ldquo;New To-Do&amp;rdquo; modal in Things.app works. It does this exceptionally well and adding / tagging a new task is &lt;em&gt;fast&lt;/em&gt;.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/almost-paperless-office/thingsimport.png&#34; alt=&#34;Add a new task in Things.app&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;Another usability issue I found was tagging multiple entries. If I scan 10 related documents it would be helpful if I can just select all of them, open the Info panel and set the “From” field. This doesn’t seem to be possible right now as the field is disabled in this view.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/almost-paperless-office/batchtagging.png&#34; alt=&#34;Info panel of a document in EagleFiler&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;Even with this small annoyance I&amp;rsquo;m personally happy with the solution as the search works very well and is extremely fast. Knowing that the developer is actively responding to threads in the support forum and continuously developing the app are more important to me. There&amp;rsquo;s also a lot of features that I haven&amp;rsquo;t used yet and will have to incorporate into my workflow at some point.&lt;/p&gt;
&lt;h2 id=&#34;step-3-destroying-the-evidedocuments&#34;&gt;Step 3: Destroying the evide&amp;hellip;documents&lt;/h2&gt;
&lt;p&gt;Once the documents are scanned it has to be decided if it&amp;rsquo;s worth keeping the original or not. Documents where the original needs to be kept around like insurance policies, most tax documents and salary slips go back into the binder.&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t feel comfortable with throwing my bank and some tax documents in the regular paper trash so I ordered a small document shredder. In my case that&amp;rsquo;s a &lt;a href=&#34;https://www.leitz.com/en-nu/products/shredder-leitz-iq-home-office-p4_80090000/&#34;&gt;Leitz IQ Home Office Document Shredder&lt;/a&gt;. It does the job just fine, any of these will probably do.&lt;/p&gt;
&lt;p&gt;Make sure you have proper backups, losing a bunch of files is sometimes easier than a big stack of paper documents.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>My Ghost to Hugo migration</title>
      <link>https://blog.notmyhostna.me/posts/my-ghost-to-hugo-migration/</link>
      <pubDate>Sun, 12 Apr 2020 21:40:34 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/my-ghost-to-hugo-migration/</guid>
      <description>
        
          
        &lt;p&gt;If you&amp;rsquo;ve visited this blog before you might have noticed that it looks a bit different than before. You are not mistaken and the reason is that I spent some time on migrating it from the &lt;a href=&#34;https://ghost.org&#34;&gt;Ghost&lt;/a&gt; blogging platform to a static site generator called &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;. For this post I tried to document my migration steps a bit, maybe it&amp;rsquo;s useful to other people.&lt;/p&gt;
&lt;p&gt;They are not 100% comparable as one of them is a full blown publishing platform with features like newsletters, running paid membership programs and other features for professionals. Hugo on the other hand is — while also being extremely powerful — much more focused on being customizable and fast. It also doesn&amp;rsquo;t serve the pages dynamically but pre-generates the html pages that then get served by the web server (&lt;code&gt;nginx&lt;/code&gt; in my case). This makes the whole operation a lot faster but with the downside of not being able to just update a post and have it show up on the page without regenerating the html files.&lt;/p&gt;
&lt;p&gt;You might ask: &amp;ldquo;If both are so great why switch then?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;My Ghost workflow consisted of writing posts on iOS or macOS in &lt;a href=&#34;https://ia.net/writer&#34;&gt;iA Writer&lt;/a&gt;. Once I was ready to publish a post I directly pushed it to Ghost &lt;a href=&#34;https://blog.notmyhostna.me/posts/ia-writer-and-ghost-blog/&#34;&gt;from within iA Writer&lt;/a&gt;. This works well but there are multiple problems:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I can&amp;rsquo;t sync back changes from Ghost (Like when I fix a typo in the Ghost CMS) to my local machine&lt;/li&gt;
&lt;li&gt;The format that Ghost stores isn&amp;rsquo;t plain markdown but some more powerful format for embedding images, quotes etc.&lt;/li&gt;
&lt;li&gt;The theme I was using for Ghost required me to add an image for every post. This always added some friction to the process of writing that I didn&amp;rsquo;t like.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;migration&#34;&gt;Migration&lt;/h2&gt;
&lt;p&gt;There were a few things that I had to make sure were being taken care of in the process, unfortunately there&amp;rsquo;s no shortcut our out of the box solution for that.&lt;/p&gt;
&lt;p&gt;What I definitely wanted to achieve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don&amp;rsquo;t lose the post history&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t break existing URLs&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t mess up post formats / break images&lt;/li&gt;
&lt;li&gt;Keep the &amp;ldquo;featured&amp;rdquo; image of a post in place, that&amp;rsquo;s the one that Ghost shows in the post header&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;1-export-posts-from-ghost&#34;&gt;1) Export posts from Ghost&lt;/h3&gt;
&lt;p&gt;To export the posts from Ghost I used their export feature which gives you a nice JSON file to work with. Then I used a tool called &lt;a href=&#34;https://github.com/jbarone/ghostToHugo&#34;&gt;ghostToHugo&lt;/a&gt; which converts them into Markdown files with the correct file names and a &lt;a href=&#34;https://gohugo.io/content-management/front-matter/&#34;&gt;Front Matter&lt;/a&gt; that Hugo expects.&lt;/p&gt;
&lt;p&gt;Images are not included in the export from Ghost so you have to get them yourself from your server with &lt;code&gt;scp&lt;/code&gt; / &lt;code&gt;ftp&lt;/code&gt; or whatever you were using before and temporarily store them in a directory somewhere. We need them for step 3.&lt;/p&gt;
&lt;h3 id=&#34;2-set-up-new-hugo-blog&#34;&gt;2) Set up new Hugo blog&lt;/h3&gt;
&lt;p&gt;Create a new Hugo site, customize theme, make sure it has working full RSS feeds. This doesn&amp;rsquo;t sound like a lot but that&amp;rsquo;s what took up most of my time.&lt;/p&gt;
&lt;h3 id=&#34;3-cleaning-data-migrating-posts-fixing-images&#34;&gt;3) Cleaning data, migrating posts, fixing images&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;This is not a step-by-step tutorial as this always depends on how your data looks like, I&amp;rsquo;m just trying to give an idea of which things I had to do and have some code snippets for inspiration.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This step was the most annoying one as I had to write a bunch of scripts to fix the exported and converted posts. After using &lt;code&gt;ghostToHugo&lt;/code&gt; they were in the right format but in the wrong location, images were embedded in different ways, the images were not in the directory of the post and the &amp;ldquo;featured&amp;rdquo; image of the posts was not set.&lt;/p&gt;
&lt;p&gt;This also took up way more time than expected as I was using Hugo&amp;rsquo;s &lt;a href=&#34;https://gohugo.io/content-management/page-bundles/&#34;&gt;Page bundles&lt;/a&gt;. That means that each post would be one directory called &lt;code&gt;2020-01-01-slug-of-post&lt;/code&gt; containing a &lt;code&gt;index.md&lt;/code&gt; file with the actual blog post and any images used in the post would just be stored in this directory too. I went with this approach over the default way of having a list of flat files and storing all your images in &lt;code&gt;static/&lt;/code&gt; because that becomes messy very fast.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Script 1: Fix directory structure&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The first step was a script that creates these directories and &lt;code&gt;index.md&lt;/code&gt; files from the list of flat files exported from Ghost.&lt;/p&gt;
&lt;p&gt;Input:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;my-old-blog-post.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Output after my script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2015-01-01-my-old-blog-post
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── index.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Most of these scripts are roughly the same so I just include one for reference and then some snippets, it basically just iterates over the directory of posts, extracts the data we need for the new directory structure (data, slug) from the old &lt;code&gt;.md&lt;/code&gt; file, creates the directory, moves the &lt;code&gt;.md&lt;/code&gt; file and renames it to &lt;code&gt;index.md&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;files&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ioutil&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ReadDir&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/philipp/export-hugo/content/post&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Fatal&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;files&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Open&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/philipp/export-hugo/content/post/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;bufio&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewScanner&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Split&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;bufio&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ScanLines&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;date&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;slug&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Scan&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reDate&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FindStringSubmatch&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Text&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(&lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;date&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;reSlug&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FindStringSubmatch&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Text&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(&lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;slug&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Parse&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RFC3339&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;date&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;newDir&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Format&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2006-01-02&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;slug&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Mkdir&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;newDir&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0755&lt;/span&gt;); &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Rename&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/philipp/export-hugo/content/post/&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;(), &lt;span style=&#34;color:#a6e22e&#34;&gt;newDir&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/index.md&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Fatal&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Script 2: Extract image names, find image and move it&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Current state: Posts are in the correct format and in the correct location (directory with date and slug containing &lt;code&gt;index.md&lt;/code&gt; file with the post body)&lt;/p&gt;
&lt;p&gt;We now have to extract all image names from each post, find the images in our directory of images we downloaded, then move the image to the corresponding post directory.&lt;/p&gt;
&lt;p&gt;The images are linked in different ways in Ghost, depending on which options you choose or if it&amp;rsquo;s a pure Markdown post or a mix. I had a bunch of posts that were purely in Markdown format, and a bunch of them that used &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; for image captions.&lt;/p&gt;
&lt;p&gt;I used the following regular expressions to extract them from the &lt;code&gt;index.md&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;reImageCaption&lt;/span&gt;   = &lt;span style=&#34;color:#a6e22e&#34;&gt;regexp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;MustCompile&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;`figure\ssrc=&amp;#34;(.+?)&amp;#34;.+caption=&amp;#34;&amp;lt;em&amp;gt;(.+?)&amp;lt;\/em&amp;gt;&amp;#34;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;reImageNoCaption&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;regexp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;MustCompile&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;`figure\ssrc=&amp;#34;(.+?)&amp;#34;.+?`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;reImagesInline&lt;/span&gt;   = &lt;span style=&#34;color:#a6e22e&#34;&gt;regexp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;MustCompile&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;`!\[.*\]\((.+?)\)`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script in essence iterates over all posts, tries to find images with the before-mentioned regular expressions and then moves them from their old location to the new one.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;files&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ioutil&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ReadDir&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/philipp/Blog/blog.notmyhostna.me/content/posts&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Fatal&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;files&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;.DS_Store&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Open&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/philipp/Blog/blog.notmyhostna.me/content/posts/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;postFiles&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ioutil&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ReadDir&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Fatal&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;pfl&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;postFiles&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; !&lt;span style=&#34;color:#a6e22e&#34;&gt;strings&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Contains&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;pfl&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;(), &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;.md&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#75715e&#34;&gt;//fmt.Println(&amp;#34;&amp;gt; found post file in directory&amp;#34;, pfl.Name())
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;pf&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Open&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;pfl&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;bufio&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewScanner&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;pf&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Split&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;bufio&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ScanLines&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;imageWithCaption&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;     &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;caption&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;imageWithCaption&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt; []&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Scan&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Text&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reImageCaption&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FindStringSubmatch&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;found&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(&lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#a6e22e&#34;&gt;found&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;imageWithCaption&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;:     &lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6e22e&#34;&gt;caption&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;strings&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Contains&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;], &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/content/images&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;![%s](%s)\n\n%s&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;filepath&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Base&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;filepath&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Base&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;caption&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; !&lt;span style=&#34;color:#a6e22e&#34;&gt;found&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#a6e22e&#34;&gt;matches2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reImageNoCaption&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FindStringSubmatch&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(&lt;span style=&#34;color:#a6e22e&#34;&gt;matches2&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6e22e&#34;&gt;found&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;imageWithCaption&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;							&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;matches2&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;strings&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Contains&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;matches2&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;], &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/content/images&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;							&lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;![%s](%s)&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;filepath&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Base&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;filepath&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Base&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; !&lt;span style=&#34;color:#a6e22e&#34;&gt;found&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#a6e22e&#34;&gt;matches3&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reImagesInline&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FindStringSubmatch&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(&lt;span style=&#34;color:#a6e22e&#34;&gt;matches3&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6e22e&#34;&gt;found&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;imageWithCaption&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;							&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;matches3&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;strings&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Contains&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;matches3&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;], &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/content/images&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;							&lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; !&lt;span style=&#34;color:#a6e22e&#34;&gt;found&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(&lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;images&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;images&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;oldPath&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/philipp/export-hugo-images&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;oldPath: &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;oldPath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;filepath&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Base&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;iwc&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;newPath&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;new path: &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;newPath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Rename&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;oldPath&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;newPath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;err but moving on&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Script 3: Set featured image of post&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the converted files there&amp;rsquo;s a key called &lt;code&gt;image&lt;/code&gt; in the Front Matter of each post. This contains the file name of an image that used to be the &amp;ldquo;Featured&amp;rdquo; image of a post in Ghost (the big image above a post).&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t want to be forced to set an image for each post I&amp;rsquo;m publishing in the future so I just wanted Hugo to set an image if there&amp;rsquo;s a file called &lt;code&gt;feature.{jpg,png}&lt;/code&gt; in the post directory. To achieve that I added a condition in my template that does just that.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;image&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{.RelPermalink}}&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{{ $image := .Resources.GetMatch &amp;#34;feature.*&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{{ with $image }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;img&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ .RelPermalink }}&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The next step was to copy the image that was defined in the &lt;code&gt;image&lt;/code&gt; key of my post from the downloaded images to my post directory and rename it to &lt;code&gt;feature.{jpg,png}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That was pretty easy as I just had to extract the image name from the post, iterate over the image files, take the matching one and rename / move it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;reImage&lt;/span&gt;        = &lt;span style=&#34;color:#a6e22e&#34;&gt;regexp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;MustCompile&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;`image\s=\s&amp;#34;(.+)&amp;#34;`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Scan&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reImage&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FindStringSubmatch&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Text&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(&lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#a6e22e&#34;&gt;image&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;matches&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;image&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;oldPath&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/philipp/export-hugo-images/content&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;old image path: &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;oldPath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;filepath&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Ext&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;filepath&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Base&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;image&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;newPath&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;feature&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;new image path: &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;newPath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Rename&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;oldPath&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;newPath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Fatal&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The last step was a bunch of search / replace actions in VS Code sprinkled with some regex magic to remove old file paths for images from the post bodies and to clean up unused keys in the Front Matter (author, image, unnecessary new lines,&amp;hellip;).&lt;/p&gt;
&lt;h3 id=&#34;4-migrate-urls&#34;&gt;4) Migrate URLs&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s very important to not break URLs that are referenced elsewhere or indexed by Google so there&amp;rsquo;s already a system in place in Hugo to take care of that. First we have to look at what we are dealing with.&lt;/p&gt;
&lt;p&gt;The Ghost URLs for a blog post were in the following format:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;blog.notmyhostna.me/slug-of-post
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I defined my URL structure in &lt;code&gt;config.yaml&lt;/code&gt; to look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;permalinks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;posts&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;:section/:title/&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This results in URLs in this format:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;blog.notmyhostna.me/posts/slug-of-posts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hugo&amp;rsquo;s solution to the problem is called &lt;a href=&#34;https://gohugo.io/content-management/urls/#how-hugo-aliases-work&#34;&gt;Aliases&lt;/a&gt; and you only have to provide alternative URLs for the given resource in the Front Matter of the post. This was easily done by duplicating the &lt;code&gt;slug&lt;/code&gt; key that ghostToHugo created for us and renaming it to aliases. Be aware that aliases accepts a list of URLs that&amp;rsquo;s why the format looks a bit different in YAML.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;slug&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;apple-ruined-itunes-what-now&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;aliases&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/apple-ruined-itunes-what-now&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Apple ruined iTunes — What now?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Your post is now reachable from both URLs but with the correct canonical URL set in the header.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I hope this was somewhat helpful and if you have any specific questions feel free to reach out. Happy to help!&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>RSS is luckily not dead yet</title>
      <link>https://blog.notmyhostna.me/posts/rss-is-luckily-not-dead-yet/</link>
      <pubDate>Fri, 10 Apr 2020 21:40:34 +0200</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/rss-is-luckily-not-dead-yet/</guid>
      <description>
        
          
        &lt;p&gt;I&amp;rsquo;m a big proponent of using RSS feeds for your daily news intake instead of relying on algorithmically shuffled news streams &lt;a href=&#34;https://blog.notmyhostna.me/sad-state-of-rss-on-the-mac/&#34;&gt;for a while&lt;/a&gt; now. This works especially well if you want to follow smaller blogs and sites with irregular posting schedules that would otherwise just not show up in any algorithmically sorted timelines or get drowned out in the noise of the daily news cycle.&lt;/p&gt;
&lt;p&gt;While it&amp;rsquo;s true that RSS support is probably not growing these days it&amp;rsquo;s still around for a surprisingly amount of sites. Shockingly even &lt;a href=&#34;https://help.medium.com/hc/en-us/articles/214874118-RSS-feeds&#34;&gt;Medium.com&lt;/a&gt; offers RSS feeds, you just have to construct the URL yourself. Most likely this is done so you have to use their proprietary &amp;ldquo;Follow&amp;rdquo; feature and not use an open standard.&lt;/p&gt;
&lt;p&gt;The current arrangement I&amp;rsquo;m using consists of three parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A hosted feed reader and source of truth&lt;/li&gt;
&lt;li&gt;Apps that sync with that through the Fever API offered by the feed reader&lt;/li&gt;
&lt;li&gt;Browser extension to help with subscribing and identifying feeds on websites&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;hosted-feed-reader&#34;&gt;Hosted feed reader&lt;/h2&gt;
&lt;p&gt;My current selection of tools hasn&amp;rsquo;t changed in a long time and I&amp;rsquo;m still fairly happy with it. The main source of truth for all my feeds is &lt;a href=&#34;https://miniflux.app&#34;&gt;Miniflux&lt;/a&gt;. It&amp;rsquo;s a self-hosted feed reader, written in Go that I run in Docker on my server. I&amp;rsquo;m a happy user for years already and if you don&amp;rsquo;t want the hassle of hosting it yourself you can also support development and let them do the job with the &lt;a href=&#34;https://miniflux.app/hosting.html&#34;&gt;hosted version&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s very stable, light on resources and offers a &lt;a href=&#34;https://feedafever.com/api&#34;&gt;Fever&lt;/a&gt; compatible API which makes it possible to use any app that supports Fever to sync with it.&lt;/p&gt;
&lt;p&gt;How Fever became the one of the &amp;ldquo;standards&amp;rdquo; of syncing is still not clear to me. Do you know?&lt;/p&gt;
&lt;p&gt;Alternatively there&amp;rsquo;s the low effort hosted (paid) services: &lt;a href=&#34;https://feedbin.com&#34;&gt;Feedbin&lt;/a&gt; and &lt;a href=&#34;https://feedly.com&#34;&gt;Feedly&lt;/a&gt;. I haven&amp;rsquo;t tried them but they both have been around for a while now and seem reputable.&lt;/p&gt;
&lt;h2 id=&#34;apps&#34;&gt;Apps&lt;/h2&gt;
&lt;p&gt;I currently use &lt;a href=&#34;https://reederapp.com&#34;&gt;Reeder&lt;/a&gt; on macOS and iOS  but I&amp;rsquo;m very much looking forward to switching to &lt;a href=&#34;https://ranchero.com/netnewswire/&#34;&gt;NewsNetWire&lt;/a&gt; once syncing via the Fever API is supported. It&amp;rsquo;s an open source re-issue of the classic NewsNetWire (&lt;a href=&#34;http://netnewswireapp.com&#34;&gt;History &amp;amp; Announcement&lt;/a&gt;) developed by the original author &lt;a href=&#34;https://inessential.com&#34;&gt;Brent Simmons&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;safari-extension&#34;&gt;Safari Extension&lt;/h2&gt;
&lt;p&gt;Being a Safari user I also found a neat extension called &lt;a href=&#34;https://rss-extension.bitpiston.com&#34;&gt;&amp;ldquo;RSS Button for Safari&amp;rdquo;&lt;/a&gt;. It&amp;rsquo;s main feature is to add a button to the browser that detects RSS feeds offered by websites and makes it easy to subscribe with a few clicks. In case you also use Miniflux just select the option &amp;ldquo;Custom URL&amp;rdquo; in the extension&amp;rsquo;s settings window and set it to the following URL. Clicking on the &amp;ldquo;+&amp;rdquo; button in the extension will then take you directly to the &amp;ldquo;New Subscription&amp;rdquo; section of your Miniflux instance.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;https://rss.example.com/bookmarklet?uri=%@
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember when this was a standard feature of every browser and was located right in the address bar?&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Apple ruined iTunes — What now?</title>
      <link>https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/</link>
      <pubDate>Fri, 11 Oct 2019 18:55:06 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/feature.png" width="2000" height="1236"/>]]>
           
        &lt;p&gt;I didn&amp;rsquo;t exactly love iTunes during the last few iterations but even with Apple Music slowly creeping into the interface it was still the same old — powerful — iTunes under the hood.&lt;/p&gt;
&lt;p&gt;I could still tag it with my own tools, tags were written to the files, the folder structure was organized nicely and all was well. After messing up my library once, by enabling Cloud Music Library, in the early days of Apple Music and ending up with duplicate Apple Music tracks injected in my own ripped albums I ran with a hybrid solution for now.&lt;/p&gt;
&lt;p&gt;That hybrid solution was to have Apple Music enabled but without the Cloud Music Library. This meant I couldn&amp;rsquo;t download tracks for offline consumption and always felt a bit awkward as I actively had to jump through hoops to use both of them which obviously didn&amp;rsquo;t feel right.&lt;/p&gt;
&lt;p&gt;Over the years I fed my library with ALAC files converted from FLAC files via &lt;a href=&#34;https://tmkk.undo.jp/xld/index_e.html&#34;&gt;XLD&lt;/a&gt; and meticulously maintained my library. Incoming files were tagged with &lt;a href=&#34;https://2manyrobots.com/yate/&#34;&gt;Yate&lt;/a&gt; and &lt;a href=&#34;https://beets.io&#34;&gt;Beets&lt;/a&gt;. Both of them are amazing tools in the music organizer&amp;rsquo;s tool box.&lt;/p&gt;
&lt;p&gt;Until today, when &lt;a href=&#34;https://twitter.com/tehwey/status/1182407720202309632&#34;&gt;I switched&lt;/a&gt; from macOS Mojave to Catalina and Music.app messing up my library. It wasn&amp;rsquo;t opening it any more and was asking for the &amp;ldquo;Library File&amp;rdquo;. After looking into the directory where said library was supposed to be I only saw years of different iTunes libraries, directories for Podcasts, Audio-books, iTunes libraries from 2011 and other cruft. I decided to clean up this mess and look for something new. On top of that my trusted last.fm scrobbler &lt;a href=&#34;https://twitter.com/tehwey/status/1182402432497848340&#34;&gt;NepTunes&lt;/a&gt; stopped working.&lt;/p&gt;
&lt;p&gt;Passively looking for iTunes alternatives for the past 10 years there was never anything that could convince me to switch. Most of them weren&amp;rsquo;t really promising or I disregarded them based on their landing page screenshots.&lt;/p&gt;
&lt;p&gt;Over the years I downloaded and &lt;a href=&#34;https://twitter.com/tehwey/status/1182729966078836739&#34;&gt;tried&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.clementine-player.org&#34;&gt;Clementine&lt;/a&gt;, ugly and crashed on startup&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vox.rocks/mac-music-player&#34;&gt;Vox&lt;/a&gt;, not enough features, you need an account even to use the free version properly&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://flavio.tordini.org/musique&#34;&gt;Musique&lt;/a&gt;, not enough features, took very long to read my library&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.mediamonkey.com/addons/browse/item/mac-osx-mediamonkey/&#34;&gt;MusicMonkey&lt;/a&gt;, too ugly, deprecated&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swinsian.com&#34;&gt;Swinsian&lt;/a&gt;, a bit of an odd interface with these Next / Previous buttons that always put me off&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The only really promising one of these was Swinsian and I&amp;rsquo;m glad I did gave it another go. While it has some odd corners that don&amp;rsquo;t look like a proper Mac app it&amp;rsquo;s very fast and imported my 80MB iTunes library file with 900GB worth of tracks in a couple of minutes. Fetching the album art took a bit longer but that&amp;rsquo;s understandable. I was briefly worried that it&amp;rsquo;s not actively developed any more as the last Tweet on &lt;a href=&#34;https://twitter.com/Swinsian&#34;&gt;their account&lt;/a&gt; was from 2011 but then I saw the public &lt;a href=&#34;https://swinsian.com/support/changelog/&#34;&gt;changelog&lt;/a&gt; which was just updated a few days ago to support Apple&amp;rsquo;s new Music.app.&lt;/p&gt;
&lt;h2 id=&#34;whats-great-about-swinsian&#34;&gt;What&amp;rsquo;s great about Swinsian&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Fast&lt;/li&gt;
&lt;li&gt;Native &lt;a href=&#34;https://www.last.fm/user/apfeltalkdewey&#34;&gt;last.fm scrobbler&lt;/a&gt; support&lt;/li&gt;
&lt;li&gt;Imports iTunes library file (The .xml) and keeps all play counts and playlists!&lt;/li&gt;
&lt;li&gt;Very nice power users features for library management&lt;/li&gt;
&lt;li&gt;Very customizable, you can define every column, or where the art work is displayed&lt;/li&gt;
&lt;li&gt;Nice SQLite DB under the hood&lt;/li&gt;
&lt;li&gt;Vanity statistics about your library&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;not-so-great&#34;&gt;Not so great&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Menu bar icons in the app look a bit out of place&lt;/li&gt;
&lt;li&gt;The &amp;ldquo;Info&amp;rdquo; panel on the right side of the screen is a bit hard to parse&lt;/li&gt;
&lt;li&gt;Some UI glitches happen from time to time&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;migrate-from-itunes&#34;&gt;Migrate from iTunes&lt;/h3&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-21.43.11.png&#34;/&gt; &lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-21.43.42.png&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;That playlist count is most likely a bug, but the import worked flawlessly and all my old playlists were there again.&lt;/p&gt;
&lt;h3 id=&#34;library-management&#34;&gt;Library management&lt;/h3&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-22.12.09.png&#34;/&gt; &lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-22.12.12.png&#34;/&gt; &lt;/figure&gt;

&lt;h3 id=&#34;main-window&#34;&gt;Main window&lt;/h3&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-22.51.32-1.png&#34;/&gt; &lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-22.31.19.png&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s also very easy to customize everything, down to how the main window should be structured.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-22.32.22.png&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;You can even enable an iTunes like grid view.&lt;/p&gt;
&lt;h3 id=&#34;more-numbers&#34;&gt;More numbers&lt;/h3&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-21.36.41.png&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;There&amp;rsquo;s a lot of garbage in there from not-properly tagged things in my old library or where the information wasn&amp;rsquo;t written into the files correctly it seems. Now that I have a good interface for that it&amp;rsquo;ll be easier to track these down.&lt;/p&gt;
&lt;h3 id=&#34;ui-weirdness&#34;&gt;UI Weirdness&lt;/h3&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-22.19.45.png&#34;/&gt; &lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-22.20.44.png&#34;/&gt; &lt;/figure&gt;

&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s next?&lt;/h2&gt;
&lt;p&gt;I will now once again use a hybrid strategy with Apple Music via the Music App but without having a local library connected to that. Then I can use all the features that make Apple Music great from all devices without having to use a different setup on different devices.&lt;/p&gt;
&lt;p&gt;For my &amp;ldquo;real&amp;rdquo; local library I&amp;rsquo;ll use Swinsian, based on my imported iTunes library. I don&amp;rsquo;t really need to sync my phone with iTunes as I&amp;rsquo;m just streaming there from Apple Music anyway.&lt;/p&gt;
&lt;p&gt;Give it a try!&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/apple-ruined-itunes-what-now/Screenshot-2019-10-11-at-22.33.53.png&#34;/&gt; &lt;/figure&gt;


      </description>
    </item>
    
    <item>
      <title>Set Apple Touch Icon for any website</title>
      <link>https://blog.notmyhostna.me/posts/set-apple-touch-icon-for-any-website/</link>
      <pubDate>Wed, 25 Sep 2019 06:47:56 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/set-apple-touch-icon-for-any-website/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/set-apple-touch-icon-for-any-website/feature.jpeg" width="1125" height="715"/>]]>
           
        &lt;p&gt;There are some websites that I use via the &amp;ldquo;Add to Home Screen&amp;rdquo; feature of iOS to make them easily accessible on my Home Screen. The problem is that websites that are running a more conservative tech stack tend to not always cater to new and shiny browser and OS features like dark mode, High DPI favicons or the &lt;a href=&#34;https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html&#34;&gt;Apple Touch Icon specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Apple Touch Icon specification gives you a way to specify a bunch of assets in various sizes to make a website behave more app-like on iOS. With a launch screen, an app icon or an app title. Most of these are probably from the days before the app store where the Apple &lt;a href=&#34;https://www.macstories.net/stories/before-the-app-store-the-sweet-solution-of-web-apps-and-developers-relentless-passion/&#34;&gt;”sweet solution”&lt;/a&gt; for third party apps was to build web apps that behave like ”native” apps. Now the biggest use case (which is probably still very small) is to provide an icon for websites pinned to the Home Screen.&lt;/p&gt;
&lt;p&gt;In the HTML markup of a site this can look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;link rel=&amp;#34;apple-touch-icon&amp;#34; href=&amp;#34;touch-icon-iphone.png&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;link rel=&amp;#34;apple-touch-icon&amp;#34; sizes=&amp;#34;152x152&amp;#34; href=&amp;#34;touch-icon-ipad.png&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;link rel=&amp;#34;apple-touch-icon&amp;#34; sizes=&amp;#34;180x180&amp;#34; href=&amp;#34;touch-icon-iphone-retina.png&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;link rel=&amp;#34;apple-touch-icon&amp;#34; sizes=&amp;#34;167x167&amp;#34; href=&amp;#34;touch-icon-ipad-retina.png&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A website that I use a lot doesn&amp;rsquo;t have a proper Apple Touch Icon set which bothers me every time I unlock my phone and see the Home Screen. I was about to email them but then realized that it&amp;rsquo;s probably a very small edge case and they have more important things to do.&lt;/p&gt;
&lt;p&gt;If a website doesn&amp;rsquo;t set the Apple Touch Icon in the HTML markup iOS just creates an icon based on a screenshot of the website. This works but isn&amp;rsquo;t really elegant, especially if it&amp;rsquo;s on your main Home Screen.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_9753.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;I set out to find a solution to force iOS to use a custom icon and couldn&amp;rsquo;t really find anything. After searching for a bit longer I stumbled upon an &lt;a href=&#34;https://allinthehead.com/retro/319/how-to-set-an-apple-touch-icon-for-any-site&#34;&gt;old blog post from 2008&lt;/a&gt; that explained exactly what I needed. The problem was that something happened with the website since then and all the links were automatically removed. Even in the comments only parts of some links were visible, the site probably went through a few tech transitions over the years. Luckily the site got captured by the amazing Internet Archive and &lt;a href=&#34;https://web.archive.org/web/20100318061128/https://allinthehead.com/retro/319/how-to-set-an-apple-touch-icon-for-any-site&#34;&gt;this snapshot&lt;/a&gt; still works.&lt;/p&gt;
&lt;h2 id=&#34;create-bookmarklet&#34;&gt;Create bookmarklet&lt;/h2&gt;
&lt;p&gt;I created a new bookmark in Safari (⌘D), set the name to &amp;ldquo;Set touch icon&amp;rdquo; and left the description empty.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Screen-Shot-2019-09-25-at-16.20.08.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Then right click the bookmark and select &amp;ldquo;Edit Address&amp;rdquo;. In here paste the following snippet:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;javascript:&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;s&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;document&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;createElement(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;link&amp;#39;&lt;/span&gt;);s&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;setAttribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rel&amp;#39;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;apple-touch-icon&amp;#39;&lt;/span&gt;);s&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;setAttribute(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;href&amp;#39;&lt;/span&gt;,prompt(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Touch&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;%20i&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;con%20URL?&amp;#39;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://&amp;#39;&lt;/span&gt;));document&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;getElementsByTagName(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;head&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;B0&lt;span style=&#34;color:#f92672&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;D&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;appendChild(s);void(s);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s injecting a &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; element as a child of the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; in the website&amp;rsquo;s HTML markup. Then when iOS reads the website to create the bookmark it sees the new link element and follows the link for the custom Apple Touch Icon.&lt;/p&gt;
&lt;p&gt;Now this should also show up on iOS in your bookmarks if you have bookmark sync via iCloud enabled in Safari.&lt;/p&gt;
&lt;h2 id=&#34;use-bookmarklet&#34;&gt;Use bookmarklet&lt;/h2&gt;
&lt;p&gt;Use Safari on iOS to navigate to the website you want to bookmark on your Home Screen. Once the site is loaded open your Favorites in Safari and click on your bookmarklet (&lt;code&gt;Set touch icon&lt;/code&gt;). It&amp;rsquo;ll ask you for a URL and you have to paste the direct URL to your (square) icon you want to use. In my case I uploaded something to Imgur and used the direct link. It&amp;rsquo;s important to use a direct link like &lt;code&gt;https://i.imgur.com/12345.png&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;add-touch-icon.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The linked guide explains what it&amp;rsquo;s technically doing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This will bring up a dialogue to prompt for the URL of the icon you wish to use – so make sure your icon is online somewhere. Clicking OK will seemingly do nothing, but what’s actually happened is that the LINK element has been set and the script has finished. Just go ahead and add the site, and your new icon should be used.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I noticed that after I ran the bookmarklet and injected the &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; element the old screenshot icon was still showing up in the &amp;ldquo;Add to Home Screen&amp;rdquo; preview for a few seconds. I had to wait a bit and then it refreshed the icon to the new custom icon we injected.&lt;/p&gt;
&lt;p&gt;The result is a beautiful custom icon on our Home Screen.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_26398D857B9D-1.jpeg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Downgrade Go installed with Homebrew</title>
      <link>https://blog.notmyhostna.me/posts/downgrade-go-installed-with-homebrew/</link>
      <pubDate>Fri, 13 Sep 2019 05:58:01 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/downgrade-go-installed-with-homebrew/</guid>
      <description>
        
          
        &lt;p&gt;I just had the issue that I installed Go 1.13 which messed up VSCode auto completion and is also not supported by the CI pipeline I wanted to use. This meant I needed to downgrade to Go 1.12.9.&lt;/p&gt;
&lt;p&gt;This took me a bit longer than I&amp;rsquo;d be willing to admit. Partially because the naming in Homebrew is sometimes a bit hard to follow &lt;a href=&#34;https://github.com/Homebrew/homebrew-core/issues/11091&#34;&gt;#11091&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are 3 simple steps involved: Install wanted version, unlink old one, link new one.&lt;/p&gt;
&lt;h2 id=&#34;check-current-version&#34;&gt;Check current version&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~|⇒ go version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go version go1.13 darwin/amd64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;install-specific-version-you-want&#34;&gt;Install specific version you want&lt;/h2&gt;
&lt;p&gt;The available versions are listed in the Hombrew directory. The Example for Go would be &lt;a href=&#34;https://formulae.brew.sh/formula/go&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;~|&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;⇒&lt;/span&gt; brew install go&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Updating Homebrew&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;==&amp;gt;&lt;/span&gt; Auto&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;updated Homebrew&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Updated &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; taps (homebrew&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;core &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; homebrew&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;cask)&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;==&amp;gt;&lt;/span&gt; Updated Formulae
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;openssl&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.1&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;✔&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;==&amp;gt;&lt;/span&gt; Downloading https:&lt;span style=&#34;color:#f92672&#34;&gt;//&lt;/span&gt;homebrew&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;bintray&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;bottles&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;go&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;9.&lt;/span&gt;mojave&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;bottle&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;tar&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Already downloaded: &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;Users&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;username&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;Library&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;Caches&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;Homebrew&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;downloads&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;6392e5&lt;/span&gt;d3faa67a6132d43699cf470ecc764ba42f38cce8cdccb785c587b8bda8&lt;span style=&#34;color:#f92672&#34;&gt;--&lt;/span&gt;go&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;9.&lt;/span&gt;mojave&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;bottle&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;tar&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;==&amp;gt;&lt;/span&gt; Pouring go&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;9.&lt;/span&gt;mojave&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;bottle&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;tar&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;==&amp;gt;&lt;/span&gt; Caveats
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt; is keg&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;only, which means it was &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; symlinked into &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;usr&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;local,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;because this is an alternate version of another formula&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;If you need to have go&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt; first &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; your PATH run:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;export PATH=&amp;#34;/usr/local/opt/go@1.12/bin:$PATH&amp;#34;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;~/.&lt;/span&gt;zshrc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;==&amp;gt;&lt;/span&gt; Summary
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;🍺&lt;/span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;usr&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;local&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;Cellar&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;go&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;9&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;9&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;819&lt;/span&gt; files, &lt;span style=&#34;color:#ae81ff&#34;&gt;452.8&lt;/span&gt;MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;unlink-currently-installed-version&#34;&gt;Unlink currently installed version&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~|⇒ brew unlink go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Unlinking /usr/local/Cellar/go/1.13... 3 symlinks removed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;force-link-the-specific-version&#34;&gt;Force link the specific version&lt;/h2&gt;
&lt;p&gt;As the specific formula we want (&lt;code&gt;go@1.12&lt;/code&gt;) is a keg-only formula it must be linked with &lt;code&gt;--force&lt;/code&gt;. If you try without it&amp;rsquo;ll tell you just that. As explained in the &lt;a href=&#34;https://docs.brew.sh/FAQ.html#what-does-keg-only-mean&#34;&gt;FAQ&lt;/a&gt; a key-only formula is one that&amp;rsquo;s only installed into our &lt;code&gt;/usr/local/Cellar&lt;/code&gt; directory without being linked automatically.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;~|&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;⇒&lt;/span&gt; brew link &lt;span style=&#34;color:#f92672&#34;&gt;--&lt;/span&gt;force go&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Linking &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;usr&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;local&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;Cellar&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;go&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.12&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;9.&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; symlinks created
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;If you need to have this software first &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; your PATH instead consider running:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;export PATH=&amp;#34;/usr/local/opt/go@1.12/bin:$PATH&amp;#34;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;~/.&lt;/span&gt;zshrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;check-version&#34;&gt;Check version&lt;/h2&gt;
&lt;p&gt;Now that everything is linked correctly it should show the specific version we want:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~|⇒ go version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go version go1.12.9 darwin/amd64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I hope this was helpful, if you like posts like this follow me on Twitter: &lt;a href=&#34;https://twitter.com/tehwey&#34;&gt;@tehwey&lt;/a&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>BOM there it is</title>
      <link>https://blog.notmyhostna.me/posts/bom-there-it-is/</link>
      <pubDate>Tue, 20 Aug 2019 19:02:03 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/bom-there-it-is/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/bom-there-it-is/feature.png" width="2072" height="764"/>]]>
           
        &lt;p&gt;Came across an interesting behavior the other day and thought I&amp;rsquo;ll share my frustration, maybe someone else runs into the same issue.&lt;/p&gt;
&lt;p&gt;I received a report as an Excel (&lt;code&gt;.xlsx&lt;/code&gt;) file that I had to import into our system. First step is usually to convert it to a CSV file and feed it into our importer—a service written in Go. The Go libraries for Excel files are &lt;em&gt;not very nice&lt;/em&gt; to say the least so CSV is the way to go. I converted it by using Microsoft Excel for Mac. After running the import I saw that it was silently discarding the first column of the imported file.&lt;/p&gt;
&lt;p&gt;I build a quick example to replicate the problem and figure out if it&amp;rsquo;s related to the CSV library we are using: &lt;a href=&#34;https://github.com/gocarina/gocsv&#34;&gt;gocarina/gocsv&lt;/a&gt;. The neat feature of the library is that you can just unmarshal into a struct without using a loop, check for &lt;code&gt;EOF&lt;/code&gt; and other error cases. It behaves more like the &lt;a href=&#34;https://golang.org/pkg/encoding/json/&#34;&gt;json&lt;/a&gt; package of the standard library.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Go&#34; data-lang=&#34;Go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;encoding/csv&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/gocarina/gocsv&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Row is a row with columns
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Row&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;One&lt;/span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`csv:&amp;#34;One&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;Two&lt;/span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`csv:&amp;#34;Two&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;Three&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`csv:&amp;#34;Three&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;cf&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;OpenFile&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Getenv&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;FILEPATH&amp;#34;&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;O_RDWR&lt;/span&gt;|&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;O_CREATE&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ModePerm&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        panic(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cf&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Use ; as separator as that&amp;#39;s what Excel gives us
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;gocsv&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SetCSVReader&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;io&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Reader&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;gocsv&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;CSVReader&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;csv&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewReader&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;in&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Comma&lt;/span&gt; = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;Row&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;gocsv&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;UnmarshalFile&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;cf&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt;); &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;row&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;rows&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;row&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;row&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Even with the minimal example the first column never got unmarshaled into the struct. To narrow down it&amp;rsquo;s not a problem with the library I quickly built a second example using &lt;a href=&#34;https://github.com/smartystreets/scanners&#34;&gt;smartystreets/scanners&lt;/a&gt; which also didn&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Now when I tried to replicate it at home I couldn&amp;rsquo;t actually replicate it and &lt;code&gt;smartystreets/scanners&lt;/code&gt; worked using this minimal example. I&amp;rsquo;m not sure why it didn&amp;rsquo;t work when I tried it the first time, maybe I was using an older version. For completeness sake this is the code I&amp;rsquo;m using now that works.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Go&#34; data-lang=&#34;Go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/smartystreets/scanners/csv&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Row is a row with columns
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Row&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;One&lt;/span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`csv:&amp;#34;One&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;Two&lt;/span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`csv:&amp;#34;Two&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;Three&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`csv:&amp;#34;Three&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;cf&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;OpenFile&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Getenv&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;FILEPATH&amp;#34;&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;O_RDWR&lt;/span&gt;|&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;O_CREATE&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ModePerm&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        panic(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cf&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;csv&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewScanner&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;cf&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;csv&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Comma&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;;&amp;#39;&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;csv&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Comment&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;csv&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ContinueOnError&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Scan&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Error&lt;/span&gt;(); &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Panic&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;scanner&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Record&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After seeing that both libraries (at least at the time of the investigation) failed on picking up the first column I realized that it&amp;rsquo;s probably a problem with the file itself.&lt;/p&gt;
&lt;p&gt;I ran a file from a previous report through the importer and it worked. At that point it was clear that it&amp;rsquo;s a problem with the actual file and not the importer. I did what I should&amp;rsquo;ve done at the beginning and looked at the raw file with &lt;a href=&#34;http://ridiculousfish.com/hexfiend/&#34;&gt;Hex Fiend&lt;/a&gt; which is one of my favorite tools and an incredible addition to everyone&amp;rsquo;s toolbox.&lt;/p&gt;
&lt;p&gt;After comparing the Hex representation of the working and non-working file it was very clear what was happening.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/bom-there-it-is/Screenshot-2019-08-20-at-22.14.56.png&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;The non-working file was prepended with three invisible characters: &lt;code&gt;...&lt;/code&gt; which upon closer inspection is &lt;code&gt;EFBBBF&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you know a thing or two about encodings you know that&amp;rsquo;s the BOM (&lt;a href=&#34;https://en.wikipedia.org/wiki/Byte_order_mark&#34;&gt;Byte Order Mark&lt;/a&gt;) and that Go doesn&amp;rsquo;t like it (”We don&amp;rsquo;t like BOMs.” - bradfitz on the &lt;a href=&#34;https://github.com/golang/go/issues/12254&#34;&gt;Go issue tracker&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Wikipedia says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The byte order mark (BOM) is a Unicode character, U+FEFF BYTE ORDER MARK (BOM), whose appearance as a magic number at the start of a text stream can signal several things to a program reading the text:[1]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The byte order, or endianness, of the text stream; The fact that the text stream&amp;rsquo;s encoding is Unicode, to a high level of confidence; Which Unicode encoding the text stream is encoded as.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As it turns out Microsoft adds these if you save a CSV from Excel.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Microsoft compilers and interpreters, and many pieces of software on Microsoft Windows such as Notepad treat the BOM as a required magic number rather than use heuristics. These tools add a BOM when saving text as UTF-8, and cannot interpret UTF-8 unless the BOM is present or the file contains only ASCII. Google Docs also adds a BOM when converting a document to a plain text file for download.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On top of that: This behavior is different between &lt;em&gt;Microsoft Excel for Mac: Version 15.12.3&lt;/em&gt; and &lt;em&gt;Microsoft Excel for Mac: Version 16.28&lt;/em&gt;. I tried to replicate the issue on Version 15 at first, exported the CSV and the BOM control characters weren&amp;rsquo;t inserted. I then upgraded and saw that they added the UTF-8 CSV option additionally to the &amp;ldquo;normal&amp;rdquo; CSV export which is now buried all the way at the bottom of the save dialog (Not even pictured in this screenshot) and the default one is UTF-8 with the additional BOM characters.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/bom-there-it-is/Screenshot-2019-08-20-at-21.32.22.png&#34;/&gt; &lt;/figure&gt;

&lt;h2 id=&#34;example-to-replicate&#34;&gt;Example to replicate&lt;/h2&gt;
&lt;p&gt;I created 3 files, two from Excel Version 16 with the UTF-8 and the &amp;ldquo;normal&amp;rdquo; export. One from the only available CSV export in Excel Version 15 where you can easily spot the difference.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/bom-there-it-is/Screenshot-2019-08-20-at-22.14.56.png&#34; alt=&#34;csv_excel_16_utf8_example.csv&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;strong&gt;csv_excel_16_utf8_example.csv&lt;/strong&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/bom-there-it-is/Screenshot-2019-08-20-at-22.14.58.png&#34; alt=&#34;csv_excel_16_example.csv&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;strong&gt;csv_excel_16_example.csv&lt;/strong&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/bom-there-it-is/Screenshot-2019-08-20-at-22.15.00.png&#34; alt=&#34;csv_excel_15_example.csv&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;strong&gt;csv_excel_15_example.csv&lt;/strong&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;Running the Go importer with &lt;code&gt;gocsv&lt;/code&gt; and the three example files, the first column is missing in the example using the UTF-8 version of the file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;csv|master⚡ ⇒ FILEPATH=csv_excel_15_example.csv go run csv.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;row {Foo Bar Baz}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;csv|master⚡ ⇒ FILEPATH=csv_excel_16_example.csv go run csv.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;row {Foo Bar Baz}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;csv|master⚡ ⇒ FILEPATH=csv_excel_16_utf8_example.csv go run csv.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;row { Bar Baz}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After removing the BOM characters and running the importer everything worked as expected:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;csv|master⚡ ⇒ FILEPATH=csv_excel_15_example.csv go run csv.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;row {Foo Bar Baz}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;csv|master⚡ ⇒ FILEPATH=csv_excel_16_example.csv go run csv.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;row {Foo Bar Baz}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;csv|master⚡ ⇒ FILEPATH=csv_excel_16_utf8_example.csv go run csv.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;row {Foo Bar Baz}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;workaround--hack&#34;&gt;Workaround / Hack&lt;/h2&gt;
&lt;p&gt;If you can&amp;rsquo;t touch the file, do a properly encoded export or can switch to a different CSV library you could also use this &lt;a href=&#34;https://github.com/dimchansky/utfbom&#34;&gt;dimchansky/utfbom&lt;/a&gt; library to remove encoding information after parsing the file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Go&#34; data-lang=&#34;Go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;o&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ioutil&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ReadAll&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;utfbom&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SkipOnly&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;bufio&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewReader&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;cf&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s always the “Schei? Encoding” in the end isn&amp;rsquo;t it?&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Restic: Backup cloud server to Synology NAS</title>
      <link>https://blog.notmyhostna.me/posts/restic-backup-cloud-server-to-synology-nas/</link>
      <pubDate>Thu, 18 Jul 2019 19:35:11 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/restic-backup-cloud-server-to-synology-nas/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/restic-backup-cloud-server-to-synology-nas/feature.png" width="1944" height="1080"/>]]>
           
        &lt;p&gt;After migrating to a new server host I set up a reminder in my reminders app to create a proper backup strategy. This was nagging me every day but I always bumped it to some other time as it&amp;rsquo;s not exactly the most fulfilling task. I &lt;a href=&#34;https://blog.notmyhostna.me/automated-and-encrypted-backups-with-duplicity/&#34;&gt;wrote about doing backups&lt;/a&gt; via Duplicity / Duply before but that setup was always a bit more complicated than it should&amp;rsquo;ve been. Especially as it involved GPG for the encryption.&lt;/p&gt;
&lt;p&gt;Today I finally sat down to get this done before something bad happens to my data. After doing some research I had to decide between &lt;a href=&#34;https://restic.net&#34;&gt;restic&lt;/a&gt; and &lt;a href=&#34;https://www.borgbackup.org&#34;&gt;Borg&lt;/a&gt;. Both of them looked very promising but in the end I settled on restic as it&amp;rsquo;s &lt;a href=&#34;https://github.com/restic/restic&#34;&gt;written in Go&lt;/a&gt; and not &lt;a href=&#34;https://github.com/borgbackup/borg&#34;&gt;Python like Borg&lt;/a&gt; is.&lt;/p&gt;
&lt;h2 id=&#34;goal&#34;&gt;Goal&lt;/h2&gt;
&lt;p&gt;Scheduled backups from my server hosted at OVH to my Synology NAS running in my local network at home.&lt;/p&gt;
&lt;h2 id=&#34;setup-and-preparations&#34;&gt;Setup and preparations&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Install restic&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t really need to explain much about how to do that as it&amp;rsquo;s all well explained in other popular guides like Jake Jarvis&amp;rsquo; blog post &lt;a href=&#34;https://jarv.is/notes/how-to-backup-linux-server/&#34;&gt;&amp;ldquo;Automatically Backup a Linux VPS to a Separate Cloud Storage Service&amp;rdquo;&lt;/a&gt;. There&amp;rsquo;s also a very easy to follow &lt;a href=&#34;https://restic.readthedocs.io/en/stable/010_introduction.html&#34;&gt;official documentation&lt;/a&gt; which I mostly followed for my setup.&lt;/p&gt;
&lt;p&gt;Just install it based on the instructions for your operating system. Run &lt;code&gt;restic version&lt;/code&gt; to see if you are on the latest version and then continue with the next step.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SSH configuration&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You have to make sure to have a working public key authenticated SSH connection between your backup source and backup target.&lt;/p&gt;
&lt;p&gt;In my case I had to create an SSH key on my server and then copy that one to my NAS. This can be done by using these two commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-keygen -t ed25519 -o -a 100
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sshh-copy-id -i ~/.ssh/id_ed25519.pub -p 57564 username@username.synology.me
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the SSH server on the target is running on a non-standard SSH port make sure to set up a &lt;code&gt;~/.ssh/config&lt;/code&gt; file to set all these parameters as you can&amp;rsquo;t set it in the restic backup command later on. I run the backup as root so all this is done while being logged in as root. If you don&amp;rsquo;t like that there&amp;rsquo;s a section in the &lt;a href=&#34;https://restic.readthedocs.io/en/latest/080_examples.html#backing-up-your-system-without-running-restic-as-root&#34;&gt;documentation&lt;/a&gt; explaining how to do just that.&lt;/p&gt;
&lt;p&gt;The SSH config file could look like this, the &lt;code&gt;ServerAliveInterval&lt;/code&gt; and &lt;code&gt;ServerAliveCountMax&lt;/code&gt; parameters were suggested in the forum.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host username.synology.me
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        HostName username.synology.me
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        User username
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Port 12345
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ServerAliveInterval 60
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ServerAliveCountMax 240
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you type &lt;code&gt;ssh username.synology.me&lt;/code&gt; it should connect via SSH and you should be logged into your NAS without typing a password. This has to work before moving on to the next step.&lt;/p&gt;
&lt;h2 id=&#34;create-repository-aka-backup-target&#34;&gt;Create Repository (aka. backup target)&lt;/h2&gt;
&lt;p&gt;This sets up the directory where the backups are going to be stored at. In my case I did the backups over SFTP to my NAS so make sure you can log into your backup target via SSH / SFTP if you use this strategy. Of course there&amp;rsquo;s also a lot of &lt;a href=&#34;https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html&#34;&gt;other backup targets&lt;/a&gt; you can use (S3, Backblaze, DigitalOcean etc). I tried to use Google Cloud Storage on my first attempt but couldn&amp;rsquo;t get it to work but you might have more patience than me.&lt;/p&gt;
&lt;p&gt;With this command we create the backup repository on the remote host via SFTP:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;restic -r sftp:username@username.synology.me:/backup-remote/notmyhostname-2019 init --verbose
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After running this you can double check that by logging into your NAS and making sure the directory got created. In the directory should be a config file and a bunch of other standard directories that restic creates.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dewey@alexandria:/volume1/Archive/backup-remote/notmyhostname-2019$ ls -lah
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total 4.0K
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxrwxrwx+ 1 dewey users   66 Jul 18 21:38 .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxrwxrwx+ 1 dewey users   98 Jul 18 20:53 ..
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-------  1 dewey users  155 Jul 18 21:31 config
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwx------  1 dewey users 1.0K Jul 18 21:29 data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwx------  1 dewey users  256 Jul 18 22:18 index
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwx------  1 dewey users  128 Jul 18 21:31 keys
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwx------  1 dewey users    0 Jul 18 22:18 locks
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwx------  1 dewey users  384 Jul 18 22:18 snapshots
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Warning for Synology users&lt;/strong&gt;If you look closely you see that there&amp;rsquo;s a mismatch between the path on the NAS from the &lt;code&gt;ls -lah&lt;/code&gt; output and where the restic command is supposed to create the repository:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/backup-remote/notmyhostname-2019&lt;/code&gt; vs. &lt;code&gt;/volume1/Archive/backup-remote/notmyhostname-2019&lt;/code&gt;. You&amp;rsquo;d think that the repository command would need to look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/volume1/Archive/backup-remote/notmyhostname-2019 init --verbose
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s what I thought too but as I later found out and confirmed via the official restic forum (which was very helpful and active) this is a &amp;ldquo;feature&amp;rdquo; of Synology where the root directory of a SFTP user is actually the user&amp;rsquo;s home directory. So what would be &lt;code&gt;/&lt;/code&gt; for an SSH user is actually &lt;code&gt;/volume1/Archive/&lt;/code&gt; for a SFTP user. I also answered that question in &lt;a href=&#34;https://forum.restic.net/t/sftp-backup-not-showing-up-where-is-my-repository/1919&#34;&gt;my thread&lt;/a&gt; on the forum for other Synology users.&lt;/p&gt;
&lt;h2 id=&#34;define-includes-and-excludes&#34;&gt;Define includes and excludes&lt;/h2&gt;
&lt;p&gt;We need to define which files we need to include in or exclude from the backup. I prefer the options of providing both, an inclusion an and an exclusion file. This makes it very explicit which files are supposed to be in the backup.&lt;/p&gt;
&lt;p&gt;I created two files for that purpose:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@notmyhostname:~/.config/restic# cat includes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/etc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/home/ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@notmyhostname:~/.config/restic# cat excludes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/home/ubuntu/services/**/deluge-data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/home/ubuntu/.cache
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;How the rules work is all defined in the &lt;a href=&#34;https://restic.readthedocs.io/en/stable/040_backup.html#backing-up-special-items-and-metadata&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;first-backup&#34;&gt;First backup&lt;/h2&gt;
&lt;p&gt;Every time you run a restic command you have to provide the repository path and the password via an environment variable or command line flag. To make this a bit less annoying I&amp;rsquo;d suggest you create a file like &lt;code&gt;backup.sh&lt;/code&gt; and export the variables there before running the actual command.&lt;/p&gt;
&lt;p&gt;After creating the file with the following content just make it executable with &lt;code&gt;chmod +x backup.sh&lt;/code&gt; and run it with &lt;code&gt;./backup.sh&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export RESTIC_REPOSITORY&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sftp:username@username.synology.me:/backup-remote/notmyhostname-2019&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export RESTIC_PASSWORD&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;changeme&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;restic backup --verbose --files-from /root/.config/restic/includes --exclude-file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/root/.config/restic/excludes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will create your first backup and if everything is working the only thing you have to do is to run it via a cronjob.&lt;/p&gt;
&lt;h2 id=&#34;automate&#34;&gt;Automate&lt;/h2&gt;
&lt;p&gt;Add this to your &lt;code&gt;/etc/crontab&lt;/code&gt; file and your backup will run at the given interval. I&amp;rsquo;m logging errors to a file but you can also use a script to send an email, push notification or whatever you prefer.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;12&lt;/span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;   root    &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;root&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;backup&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sh &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;log&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;restic&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;log
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;prune-old-backups&#34;&gt;Prune old backups&lt;/h2&gt;
&lt;p&gt;As we don&amp;rsquo;t want to keep the entire backup history we can clean up old backups after a while. The easiest way is to add the forget command at the end of your &lt;code&gt;backup.sh&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;restic forget --verbose --prune --keep-hourly 6 --keep-daily 7 --keep-weekly 4 --keep-monthly 12
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should be all that&amp;rsquo;s needed. To make sure it works perform a restore of some example files by following &lt;a href=&#34;https://restic.readthedocs.io/en/latest/050_restore.html#restoring-from-a-snapshot&#34;&gt;this step&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;check-successful-backups&#34;&gt;Check successful backups&lt;/h2&gt;
&lt;p&gt;By running the &lt;code&gt;restic snapshots&lt;/code&gt; command you can double check the backup history, as we see here the backups are created every 12h just like we defined it in the cron job.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@notmyhostname:~# RESTIC_REPOSITORY&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sftp:username@username.synology.me:/backup-remote/notmyhostname-2019&amp;#34;&lt;/span&gt; RESTIC_PASSWORD&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;changeme&amp;#34;&lt;/span&gt; restic snapshots
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;repository 070c204c opened successfully, password is correct
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ID        Time                 Host           Tags        Paths
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;88eb6cda  2019-07-18 19:36:01  notmyhostname              /etc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1e0dda19  2019-07-18 20:17:47  notmyhostname              /etc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                          /home/ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;988c8b69  2019-07-18 21:37:22  notmyhostname              /etc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                          /home/ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c713b4ad  2019-07-19 00:00:02  notmyhostname              /etc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                          /home/ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;651853b0  2019-07-19 12:00:01  notmyhostname              /etc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                          /home/ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;56571ab6  2019-07-20 00:00:01  notmyhostname              /etc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                          /home/ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;5a4b7500  2019-07-20 12:00:01  notmyhostname              /etc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                          /home/ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; snapshots
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@notmyhostname:~#
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you have any questions or suggestions, let me know via &lt;a href=&#34;https://twitter.com/tehwey&#34;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Trip Report: Working in Kuala Lumpur, Malaysia</title>
      <link>https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/</link>
      <pubDate>Thu, 27 Jun 2019 18:18:27 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/feature.jpeg" width="2000" height="1500"/>]]>
           
        &lt;p&gt;After checking my countdown app far too many times it was finally time to make my way down to Kuala Lumpur again. I was going to stay in Asia for 4 weeks this time, 3 weeks of remote work from Kuala Lumpur and one week of vacation in China. I usually try to travel very light and so I set off to Berlin Tegel airport to start my 18h trip with my cabin-sized suitcase and a small backpack.&lt;/p&gt;
&lt;p&gt;At the end of this post there&amp;rsquo;s a &amp;ldquo;Recommended reading music&amp;rdquo; for some background tunes.&lt;/p&gt;
&lt;p&gt;Thanks to Manu for his &lt;a href=&#34;https://twitter.com/manu_faktur/status/1137612697049194496&#34;&gt;encouraging words&lt;/a&gt; that motivated me to write this up!&lt;/p&gt;
&lt;h2 id=&#34;flight&#34;&gt;Flight&lt;/h2&gt;
&lt;p&gt;This time with Singapore Air after going with Lufthansa (via BKK) last time, and Qatar Airways (via DIA) before that. The itinerary was not bookable through the web but with the help of a family member working in a travel agency I was able to book the following routing:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;From&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;To&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Aircraft&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Duration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;TXL&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;MUC&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;A321-200&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;1h&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;MUC&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;SIN&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;A350-900&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;11h50m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;SIN&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;KUL&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;B737-800&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;1h&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Return flight was the same routing but operated by Lufthansa:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;From&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;To&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Aircraft&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;Duration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;KUL&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;SIN&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;A330-300&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;1h&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;SIN&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;MUC&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;A350-900&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;13h&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;MUC&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;TXL&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;A319-200&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;1h&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Full details on my &lt;a href=&#34;https://my.flightradar24.com/dewey/flights&#34;&gt;FlightRadar24&lt;/a&gt; account.&lt;/p&gt;
&lt;p&gt;In the end I wasn&amp;rsquo;t able to make use of my layover in Singapore because I only had one hour to spend there.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6003.jpg&#34; alt=&#34;Approaching Singapore Changi Airport&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Approaching Singapore Changi Airport&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;Originally I was excited about seeing the &lt;a href=&#34;https://www.youtube.com/watch?v=qqAByBD-P_c&#34;&gt;Jewel&lt;/a&gt; at Changi Airport but I will have to do that some other time.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_5994-1.jpeg&#34; alt=&#34;Starting the last leg of the trip, SIN to KUL&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Starting the last leg of the trip, SIN to KUL&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The flight was pretty enjoyable and the crew on Singapore Airlines was very welcoming. There were lots of food options, ice cream and even in Economy everyone received a Singapore branded amenity bag with a toothbrush, toothpaste and socks which is very different from other carriers. They didn&amp;rsquo;t get to be #1 this year (Qatar passed them) but they are a close second place in Skytrax&amp;rsquo;s &amp;ldquo;World’s Top 100 Airlines 2019&amp;rdquo; ranking for a reason.&lt;/p&gt;
&lt;p&gt;In hindsight I would probably try not to have two layovers again as the connection was a bit tight. If possible I&amp;rsquo;d also try to get on the A380 again like last time. The problem with booking it through a third party was that I wasn&amp;rsquo;t able to properly assign the seats in the Singapore Airlines app, I got an aisle seat—essential on a long flight like that—but I would&amp;rsquo;ve preferred a bulkhead seat. I wrote more about my other preferences in &lt;a href=&#34;https://blog.notmyhostna.me/how-to-survive-a-long-haul-flight&#34;&gt;this&lt;/a&gt; post.&lt;/p&gt;
&lt;h2 id=&#34;kuala-lumpur&#34;&gt;Kuala Lumpur&lt;/h2&gt;
&lt;p&gt;After being in Kuala Lumpur a couple of times already it was easy to get around, take the train to the other terminal and finally see &lt;a href=&#34;https://www.instagram.com/indica.trix/&#34;&gt;Trix&lt;/a&gt; again after what felt like a very long time.&lt;/p&gt;
&lt;p&gt;It was great to be back and we only had one week until we had to leave for our trip to China already. There are two things about KL that surprise me every time I&amp;rsquo;m back even though I expect them already by now:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s hotter than expected outside&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s colder than expected inside&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I always end up wearing long pants, wearing a light sweater on my way to the office and having a second thicker sweater in the office locker to get through the day. I started to turn off the AC units that were blowing directly on me in the office and as it turns out the other people in the office also appreciated that as they were freezing too.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s easier to get used to the heat and it doesn&amp;rsquo;t really bother me any more.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7919.jpg&#34; alt=&#34;There are a lot of walkways and tunnels connecting malls with each other and public transport hubs. It&amp;rsquo;s sometimes tricky to move on the ground or cross streets as they are not very walkable&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;There are a lot of walkways and tunnels connecting malls with each other and public transport hubs. It&amp;rsquo;s sometimes tricky to move on the ground or cross streets as they are not very walkable&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7907.jpg&#34; alt=&#34;Older parts of the city are more pedestrian friendly&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Older parts of the city are more pedestrian friendly&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7799.jpg&#34; alt=&#34;Sometimes it rains&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Sometimes it rains&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7602.jpg&#34; alt=&#34;Sometimes it rains a lot and you are stuck in the mall&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Sometimes it rains a lot and you are stuck in the mall&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7760.jpg&#34;/&gt; &lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6054.jpg&#34; alt=&#34;The Petronas Twin Towers, world&amp;rsquo;s highest structure from 1998 to 2004&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;The Petronas Twin Towers, world&amp;rsquo;s highest structure from 1998 to 2004&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;office&#34;&gt;Office&lt;/h3&gt;
&lt;p&gt;After evaluating a bunch of co-working spaces in Kuala Lumpur (KL) last time I settled on &lt;a href=&#34;https://colony.work&#34;&gt;Colony&lt;/a&gt;, close to KLCC, which I also went back to this time. This time I decided to get a reserved desk which meant I could access the office 24/7, had a desk that was mine and a locker to leave my things. This was way better than last time where I only had a pre-paid pass and had to leave when the co-working space closed (6pm) or on public holidays. This time I could just come and go whenever I wanted which was great as I was working my usual German working hours of 10am — 7pm. I&amp;rsquo;ll definitely do that again next time.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6032.jpg&#34; alt=&#34;Access card for the co-working space&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Access card for the co-working space&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7768.jpg&#34; alt=&#34;Reserved desk, room for calls in the back and the AC that I quickly learned how to turn off&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Reserved desk, room for calls in the back and the AC that I quickly learned how to turn off&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;Biggest selling point of this office over the others is that it&amp;rsquo;s very close to KLCC and after crossing the street you can already enter the pedestrian tunnel (with AC!) which ends in the basement of the Petronas Towers with the LRT station.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6031.jpg&#34; alt=&#34;Last part of my commute, glass building on the right is the office&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Last part of my commute, glass building on the right is the office&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6034.jpg&#34; alt=&#34;The only part of the commute (also most dangerous part) that&amp;rsquo;s not covered by AC&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;The only part of the commute (also most dangerous part) that&amp;rsquo;s not covered by AC&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;LRT to the office usually took me 10 minutes of walking through the tunnel, with a short break at a grocery store to buy my breakfast chocolate bread.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7743.jpg&#34; alt=&#34;One feature of the equator living is that it sometimes rains very heavily, in this case I have to admit that I hailed a cab (or Grab—the asian Uber equivalent) to cross this street&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;One feature of the equator living is that it sometimes rains very heavily, in this case I have to admit that I hailed a cab (or Grab—the asian Uber equivalent) to cross this street&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The office also has a gym and a &lt;a href=&#34;https://colony.work/colony-klcc-a-closer-look-part-4/&#34;&gt;great rooftop pool&lt;/a&gt; with a great view of the towers. I didn&amp;rsquo;t take them up on the offer for now but I&amp;rsquo;ll go there next time as you need a gym membership that I didn&amp;rsquo;t sign up for this time and realized when it was already too late.&lt;/p&gt;
&lt;h3 id=&#34;internet&#34;&gt;Internet&lt;/h3&gt;
&lt;p&gt;Data plans for phones are very cheap in Malaysia, especially if you are used to the highway robbery that&amp;rsquo;s practiced by the German phone providers. I signed up for MAXIS&amp;rsquo;s pre-paid plan HotLink.&lt;/p&gt;
&lt;p&gt;While providers start to undermine net neutrality with offers like StreamOn (Telekom.de) it&amp;rsquo;s already a lost cause in Malaysia and having your data volume sliced up into different companies is the standard. Need more traffic for Instagram, WhatsApp, Facebook? Book the social plan. Want to have traffic that doesn&amp;rsquo;t count between 1am and 7am? Get yourself the night owl plan. There&amp;rsquo;s something for everybody and it&amp;rsquo;s very hard to keep track of or even understand what&amp;rsquo;s free and what&amp;rsquo;s not. At some point I had 5 different kinds of traffic I could use up. This is the case across multiple providers I checked before settling on one.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;State of net neutrality in Malaysia &lt;a href=&#34;https://t.co/w0Tj3dCRGU&#34;&gt;pic.twitter.com/w0Tj3dCRGU&lt;/a&gt;&lt;/p&gt;&amp;mdash; dewey (@tehwey) &lt;a href=&#34;https://twitter.com/tehwey/status/1126973077785542663?ref_src=twsrc%5Etfw&#34;&gt;May 10, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7586.jpg&#34; alt=&#34;Is this really better?&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Is this really better?&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6068.jpg&#34; alt=&#34;Want the social, chat or video plan?&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Want the social, chat or video plan?&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;On the other side residential internet via fast and cheap Fiber is readily available. I have yet to see an ad for residential 1Gbit internet connections in Germany.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6021.jpg&#34; alt=&#34;Ad for 1Gbit FTTH are visible everywhere.&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Ad for 1Gbit FTTH are visible everywhere.&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6052.jpg&#34; alt=&#34;Ad showing prices of 42 Euros for 1Gbit, 30 Euros for 500Mbit and 20 Euros for 100Mbit. For reference, I&amp;rsquo;m currently paying 40 for 100Mbit in Germany and it took 2 weeks to install.&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Ad showing prices of 42 Euros for 1Gbit, 30 Euros for 500Mbit and 20 Euros for 100Mbit. For reference, I&amp;rsquo;m currently paying 40 for 100Mbit in Germany and it took 2 weeks to install.&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;commute&#34;&gt;Commute&lt;/h3&gt;
&lt;p&gt;Getting around is very easy if you are close to the LRT stations, for the rest there&amp;rsquo;s &lt;a href=&#34;https://www.grab.com&#34;&gt;Grab&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Our morning commute was just a few stations with the train which is running on an elevated track and therefore has a rather scenic view.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7578.jpg&#34;/&gt; &lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6016.jpg&#34;/&gt; &lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7668.jpg&#34;/&gt; &lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7823.jpg&#34;/&gt; &lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7828.jpg&#34;/&gt; &lt;/figure&gt;

&lt;h3 id=&#34;food&#34;&gt;Food&lt;/h3&gt;
&lt;p&gt;Food, so much good food. There&amp;rsquo;s probably no country that I&amp;rsquo;ve been to that has a bigger variety of amazing food than Malaysia. Excellent Chinese, Indian and Malay restaurants are everywhere. The Late night &lt;a href=&#34;https://en.wikipedia.org/wiki/Mamak_stall&#34;&gt;Mamak&lt;/a&gt; or &lt;a href=&#34;https://en.wikipedia.org/wiki/Kopi_tiam&#34;&gt;Kopi tiam&lt;/a&gt; is easy to find and have become my favorite places to go back to.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7620.jpg&#34; alt=&#34;On our way to get breakfast beef noodle soup&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;On our way to get breakfast beef noodle soup&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7624.jpg&#34; alt=&#34;Nature taking back some part of the street&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Nature taking back some part of the street&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7629.jpg&#34; alt=&#34;Breakfast with beef noodle soup, milk tea and toast with coconut paste&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Breakfast with beef noodle soup, milk tea and toast with coconut paste&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7643.jpg&#34; alt=&#34;My favorite kind of place&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;My favorite kind of place&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7713.jpg&#34; alt=&#34;A new Nasi Lemak place we tried, it was excellent&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;A new Nasi Lemak place we tried, it was excellent&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7706.jpg&#34; alt=&#34;The national dish, Nasi Lemak&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;The national dish, Nasi Lemak&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7717.jpg&#34; alt=&#34;Assembly line, chickens were harmed in the process&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Assembly line, chickens were harmed in the process&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7900.jpg&#34; alt=&#34;One of our favorites we have to visit every time&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;One of our favorites we have to visit every time&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7896.jpg&#34; alt=&#34;That crust, doesn&amp;rsquo;t get much better than that&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;That crust, doesn&amp;rsquo;t get much better than that&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7898.jpg&#34; alt=&#34;Inside of Ali, Muthu and Ah Hak&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Inside of Ali, Muthu and Ah Hak&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6113.jpg&#34; alt=&#34;Colorful Ramadan Bazaar&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Colorful Ramadan Bazaar&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6118.jpg&#34; alt=&#34;On our way from the Ramadan Bazaar&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;On our way from the Ramadan Bazaar&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6145.jpg&#34; alt=&#34;We bought this as take-away from the Bazaar&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;We bought this as take-away from the Bazaar&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6149.jpg&#34; alt=&#34;Some fresh mango drink which came in a bag, turns out it&amp;rsquo;s a bit trickier to drink than I originally thought&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Some fresh mango drink which came in a bag, turns out it&amp;rsquo;s a bit trickier to drink than I originally thought&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_6151.jpg&#34; alt=&#34;Very environmentally friendly packaging made out of a leaf&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Very environmentally friendly packaging made out of a leaf&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7752.jpg&#34; alt=&#34;Another dish we always have to have, banana leaf rice&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Another dish we always have to have, banana leaf rice&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7848.jpg&#34; alt=&#34;Enjoying that plastic chair life at the A.B.C (&amp;ldquo;Always Best Choice&amp;rdquo;, not kidding)&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;Enjoying that plastic chair life at the A.B.C (&amp;ldquo;Always Best Choice&amp;rdquo;, not kidding)&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;




&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7684.jpg&#34; alt=&#34;At the downstairs Mamak&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;At the downstairs Mamak&lt;/em&gt;
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&#34;going-home&#34;&gt;Going Home&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&#34;https://twitter.com/herrherrmann&#34;&gt;Sebastian&lt;/a&gt; mentioned that this post didn&amp;rsquo;t really have an ending, so I tried to add one. Thanks for the feedback!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;After the four very eventful weeks (with a short trip to China in between) passed quickly it was time to head back to Berlin again and leave the equator behind me. I wish I could&amp;rsquo;ve stayed longer as I was just getting used to my new commute and meeting up for lunch every day. Adjusted to the climate, public transport and the food, but, alas, the office was waiting for me in Berlin.&lt;/p&gt;
&lt;p&gt;The flight was pretty decent and rather uneventful, with Lufthansa as mentioned in the beginning. When I finally arrived in Munich I had 3 hours until my connection flight to Berlin so I decided to take the airport up on its great food choices. I found a good spot in the Käfer restaurant and had a proper bavarian breakfast with Weißwurst, sweet mustard and Breze which I enjoyed until it was time to head to the gate. I arrived in Berlin at 11am on Saturday which meant I had still some weekend left to adjust and rest.&lt;/p&gt;
&lt;p&gt;That was my first trip report so let me know if you have any questions or improvements! Danke you!&lt;/p&gt;
&lt;h3 id=&#34;recommended-reading-music&#34;&gt;Recommended reading music&lt;/h3&gt;
&lt;iframe allow=&#34;autoplay *; encrypted-media *;&#34; frameborder=&#34;0&#34; height=&#34;450&#34; style=&#34;width:100%;max-width:660px;overflow:hidden;background:transparent;&#34; sandbox=&#34;allow-forms allow-popups allow-same-origin allow-scripts allow-storage-access-by-user-activation allow-top-navigation-by-user-activation&#34; src=&#34;https://embed.music.apple.com/my/album/abadi/1442311817?app=music&#34;&gt;&lt;/iframe&gt;
&lt;iframe allow=&#34;autoplay *; encrypted-media *;&#34; frameborder=&#34;0&#34; height=&#34;450&#34; style=&#34;width:100%;max-width:660px;overflow:hidden;background:transparent;&#34; sandbox=&#34;allow-forms allow-popups allow-same-origin allow-scripts allow-storage-access-by-user-activation allow-top-navigation-by-user-activation&#34; src=&#34;https://embed.music.apple.com/my/album/pilihan-emas/1442225152?app=music&#34;&gt;&lt;/iframe&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/trip-report-working-in-kuala-lumpur-malaysia/IMG_7927-1.jpeg&#34; alt=&#34;In the Grab to Kuala Lumpur International Airport. Until next time!&#34;/&gt; &lt;figcaption&gt;
                
                &lt;p&gt;
                    &lt;em&gt;In the Grab to Kuala Lumpur International Airport. &lt;/em&gt;Until next time!
                    
                        
                        &lt;/p&gt;
                
            &lt;/figcaption&gt;&lt;/figure&gt;


      </description>
    </item>
    
    <item>
      <title>Podcast Recommendations 2019</title>
      <link>https://blog.notmyhostna.me/posts/podcast-recommendations-2019/</link>
      <pubDate>Tue, 25 Jun 2019 16:43:58 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/podcast-recommendations-2019/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/podcast-recommendations-2019/feature.JPG" width="2000" height="1500"/>]]>
           
        &lt;p&gt;I love getting recommendations for new Podcasts so I thought I&amp;rsquo;ll write up a list of my favorites so far. Receiving great recommendations is also the reason why I still have a long list of Podcasts waiting for me in my podcast app.&lt;/p&gt;
&lt;p&gt;There are some ongoing shows that I am following for years already and haven&amp;rsquo;t worked my way through the full backlog yet, but usually I try to listen to everything I started.&lt;/p&gt;
&lt;p&gt;I still keep ended shows around in case there&amp;rsquo;s a follow up episode or the host is announcing a new related show. These are marked with &amp;ldquo;(ended)&amp;rdquo; here. The dots from 1 to 3 visualize how often I listen to them. Three dots (∙∙∙) mean I listen to all episodes, 2 all of them since I started but not the backlog, 1 from time to time.&lt;/p&gt;
&lt;h2 id=&#34;tech&#34;&gt;Tech&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://daringfireball.net/thetalkshow/&#34;&gt;&amp;ldquo;The Talkshow&amp;rdquo; with John Gruber&lt;/a&gt; ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://atp.fm&#34;&gt;Accidental Tech Podcast&lt;/a&gt; ∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://appstories.net&#34;&gt;AppStories&lt;/a&gt; ∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.vice.com/en_us/topic/cyber&#34;&gt;Cyber from Motherboard&lt;/a&gt; ∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.macintosh.fm&#34;&gt;Welcome to Macintosh&lt;/a&gt; ∙∙∙&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;aviation&#34;&gt;Aviation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.comeflywithus.de&#34;&gt;Come fly with us&lt;/a&gt; (German) ∙∙∙&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;motorsport&#34;&gt;Motorsport&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.f1.cool&#34;&gt;Shift+F1&lt;/a&gt; (Plus their Patreon feed) ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.formula1.com/en/toolbar/beyond-the-grid-f1-podcast.html&#34;&gt;Beyond the Grid&lt;/a&gt; ∙∙∙&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;crime&#34;&gt;Crime&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://stownpodcast.org&#34;&gt;S-Town&lt;/a&gt; (ended) ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://serialpodcast.org&#34;&gt;Serial&lt;/a&gt; (ended) ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.theaustralian.com.au/the-teachers-pet&#34;&gt;The Teacher&amp;rsquo;s Pet&lt;/a&gt; (ended) ∙∙∙&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;art--entertainment--interviews&#34;&gt;Art / Entertainment / Interviews&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://oe1.orf.at/leporello&#34;&gt;Ö1 Leporello&lt;/a&gt; (German) ∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://craigmod.com/onmargins/&#34;&gt;On Margins&lt;/a&gt; ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://podcasts.apple.com/us/podcast/sw945-a-walk-in-japan/id1459792188&#34;&gt;SW945: A Walk in Japan&lt;/a&gt; ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://podcasts.apple.com/us/podcast/the-chernobyl-podcast/id1459712981&#34;&gt;Chernobyl Podcast&lt;/a&gt; ∙∙∙&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;politics--society&#34;&gt;Politics / Society&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gimletmedia.com/shows/the-habitat&#34;&gt;The Habitat&lt;/a&gt; (ended) ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.earhustlesq.com&#34;&gt;Ear Hustle&lt;/a&gt; ∙∙∙&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;deep-dives&#34;&gt;Deep-dives&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://slate.com/slow-burn&#34;&gt;Slow Burn&lt;/a&gt; (ended) ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.nytimes.com/interactive/2018/podcasts/caliphate-isis-rukmini-callimachi.html&#34;&gt;Caliphate&lt;/a&gt; (ended) ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.flexport.com/blog/alexis-madrigal-containers-podcast/&#34;&gt;Containers&lt;/a&gt; (ended) ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.npr.org/podcasts/500692140/making-oprah&#34;&gt;Making Obama / Making Oprah&lt;/a&gt; (ended) ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://revisionisthistory.com/about&#34;&gt;Revisionist History&lt;/a&gt; ∙∙∙&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bradyheywood.libsyn.com&#34;&gt;Brady Heywood&amp;rsquo;s Apollo 13&lt;/a&gt; ∙∙∙&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;recommendations&#34;&gt;Recommendations&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m a huge fan of the podcasts that do a deep dive on very specific topics like &lt;strong&gt;Slow Burn&lt;/strong&gt; (Watergate scandal), Brady Heywood&amp;rsquo;s &lt;strong&gt;Apollo 13&lt;/strong&gt; episodes, &lt;strong&gt;Caliphate&lt;/strong&gt; (ISIS), &lt;strong&gt;Containers&lt;/strong&gt; (Container shipping, the ones on the sea, not on your computer) and &lt;strong&gt;Welcome to Macintosh&lt;/strong&gt; (History of the Apple Macintosh) so try these if you are interested in one of these topics. &lt;strong&gt;Revisionist History&lt;/strong&gt; is also a great on-going show that&amp;rsquo;s best described in their own words:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Revisionist History will go back and reinterpret something from the past: an event, a person, an idea. Something overlooked. Something misunderstood&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The host, Malcolm Gladwell, does an excellent job in explaining a large variety of topics in depth and has an amazing lineup of guests to help him dig deeper into specific ideas.&lt;/p&gt;
&lt;p&gt;If you watched the HBO show &lt;strong&gt;Chernobyl&lt;/strong&gt; and were sometimes wondering what was real and what was dramatized for TV the accompanying podcast gives you all the answers directly from the show&amp;rsquo;s creator.&lt;/p&gt;
&lt;p&gt;Listen to &lt;strong&gt;Ear Hustle&lt;/strong&gt; if you ever wondered how life in an American prison is like. It has likeable hosts both from inside and outside the prison. It&amp;rsquo;s one of my all-time favorites and I learned a lot about something I didn&amp;rsquo;t know much about before.&lt;/p&gt;
&lt;p&gt;Give &lt;strong&gt;On Margins&lt;/strong&gt; a try if you like to know more about very interesting people doing various book projects. The first episode is already a very good one. &lt;strong&gt;SW945&lt;/strong&gt; is also produced by Craig Mod and is a podcast mostly consisting of field recordings from Japan during his long hike. &lt;em&gt;Strong recommendation&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you like crime shows, the three listed ones are all great in their own way and mostly deal with unsolved mysteries. &lt;strong&gt;The Teacher&amp;rsquo;s Pet&lt;/strong&gt; even has some current developments going on so there might be another episode coming some time. I probably don&amp;rsquo;t have to say anything about &lt;strong&gt;Serial&lt;/strong&gt; as it&amp;rsquo;s probably the most famous podcast that put them on the map.&lt;/p&gt;
&lt;p&gt;The tech, aviation and Formula 1 podcasts are the ones I currently listen to as they are all on-going and a bit more niche than the other ones. If you are interested in these topics you probably already have your favorite show in that area. I can highly recommend &lt;strong&gt;Shift+F1&lt;/strong&gt; though and even if you don&amp;rsquo;t know anything about F1 you can start with their &amp;ldquo;What&amp;rsquo;s this Formula 1 thing anyway?&amp;rdquo; &lt;a href=&#34;https://www.f1.cool/blog/2019/3/7/episode-59-preseason-primer-2019&#34;&gt;season primer&lt;/a&gt; which explains everything for a complete beginner.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Survive a long-haul flight in Economy class</title>
      <link>https://blog.notmyhostna.me/posts/survive-a-long-haul-flight-in-economy-class/</link>
      <pubDate>Mon, 24 Jun 2019 16:03:00 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/survive-a-long-haul-flight-in-economy-class/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/survive-a-long-haul-flight-in-economy-class/feature.jpeg" width="2000" height="1124"/>]]>
           
        &lt;p&gt;If you have to sit in an aircraft for more than 10h there&amp;rsquo;s a few things that are absolutely essential to not feel completely dead on arrival. Some of these are very obvious, some of them took me a few flights to figure out and some of them are just opinionated and very much debatable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Noise cancelling headphones (Non negotiable)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Even if you don&amp;rsquo;t listen to music and just wear them with the noise cancelling mode activated these are life savers and if you did it once you won&amp;rsquo;t be able to go back or even understand how people can fly without a pair of these. I usually listen to podcasts or random noises through apps like &lt;a href=&#34;https://www.rainrainapp.com&#34;&gt;Rain Rain&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My recommendation: &lt;a href=&#34;https://amzn.to/2RrvuPQ&#34;&gt;Bose QuietComfort 35&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One of my favorite recent discoveries was Craig Mod&amp;rsquo;s new podcast called &lt;a href=&#34;https://podcasts.apple.com/us/podcast/sw945-a-walk-in-japan/id1459792188&#34;&gt;SW945&lt;/a&gt; which consists of daily field recordings from his walk in Japan. You can read more about it in &lt;a href=&#34;https://www.wired.com/story/six-weeks-100s-miles-hours-glorious-boredom-japan/&#34;&gt;&amp;ldquo;The Glorious, Almost-Disconnected Boredom of My Walk in Japan&amp;rdquo;&lt;/a&gt; published on Wired. I listend to all episodes on my flight to Kuala Lumpur and was enjoying it so much that I immediately sent an email to him sharing the experience after landing.&lt;/p&gt;
&lt;p&gt;My inner fanboy got a bit excited when I saw that this somehow made it into the Wired piece:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My hope was that others could “listen along” to the walk. Someone emailed and said that, on a recent long-haul flight, they had put in noise-canceling headphones, covered their head with a blanket, and listened to the walk for five hours. This made me unreasonably happy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This describes my way of traveling pretty accurately, I try to sleep as much as I can, listen to relaxing background noises when I&amp;rsquo;m not sleeping and use the provided blanket to block out all the distractions as good as possible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Food &amp;amp; Drinks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Nothing with caffeine as my feet get nervous if I drink too much of that and then have to sit for a long time. Lots of water, sometimes beer to help me sleep. Be very selective with the food that gets served, as everything will be thrown away anyway eat the part that is easily digestible and leave the rest. Bring cereal bars and proper sandwiches instead (Except on AirAsia, food is excellent). Don&amp;rsquo;t bring food that smells and bothers people.&lt;/p&gt;
&lt;p&gt;Bring your own empty bottle and ask them to fill it up with water when they do the first service. That way you don&amp;rsquo;t have to pay attention for them to come by, have to find a place for the plastic cups and wait for the next cycle of them picking up the trash again. Makes everything easier and you can drink more while not producing more unnecessary trash. The air in planes is very dry.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Seat&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I was always a big fan of window seats but if I can&amp;rsquo;t get a bulkhead seat or one where I can easily leave I&amp;rsquo;ll stick with the aisle seats now if the flight is longer than 3 hours. That way you can get up as often as you want, walk around, get more water if you need to and use the bathroom. Do your seat research with &lt;a href=&#34;https://www.seatguru.com&#34;&gt;SeatGuru&lt;/a&gt; and pay for a good seat. It&amp;rsquo;s usually well worth it and you don&amp;rsquo;t have to worry about being late for online check-in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Seat pockets&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t use them and especially don&amp;rsquo;t put important things like boarding passes, phones, passports in there. It&amp;rsquo;s a recipe for disaster apart from them being one of the &lt;a href=&#34;https://www.cbc.ca/news/canada/flights-filthy-surfaces-airplane-marketplace-1.4873586&#34;&gt;filthiest spots&lt;/a&gt; on a plane. Also don&amp;rsquo;t use the bathroom without shoes, it&amp;rsquo;s probably more disgusting than you think and planes are not cleaned as often as you might think.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;(Don&amp;rsquo;t) Recline your seat&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Nothing gets my blood boiling more than people who recline all the way in Economy class. Once everyone is sleeping that&amp;rsquo;s probably fine, any other time not so much. There&amp;rsquo;s a very good article on the subject from the &lt;a href=&#34;https://thepointsguy.com/guide/jetiquette-reclining-airplane-seat/&#34;&gt;Points Guy&lt;/a&gt;. If you want a flat bed you should probably pay a bit more.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Board early&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While it may seem very cool to sit around at the gate until the very last minute it&amp;rsquo;s actually just making life harder for yourself. The overhead bins for cabin luggage are usually filled up pretty quickly and people coming in last have to find some spot for luggage which may not be close to their actual row or worse, a few rows behind them. If you have a tight connection and then have to go against the stream of disembarking passengers with huge suitcase to get your luggage first you are going to have a bad time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Travel light, if possible&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Traveling with just your cabin sized luggage will make your life so much easier and less stressful. Queue to check-in your luggage? Nope. Stare at the slowly moving luggage belt waiting for it to spit our your luggage? Nope. Worrying about what you are going to wear if it doesn&amp;rsquo;t spit it out? Nope. On top of that you are also not the person that needs 4 seats on the airport train for their luggage. Wins all around. Roll your clothes tightly, don&amp;rsquo;t bring things you can easily buy at the destination (Toothpaste and other things that you&amp;rsquo;d have to separate out at the airport security).&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>iA Writer and Ghost Blog</title>
      <link>https://blog.notmyhostna.me/posts/ia-writer-and-ghost-blog/</link>
      <pubDate>Sat, 22 Jun 2019 13:00:02 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/ia-writer-and-ghost-blog/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/ia-writer-and-ghost-blog/feature.png" width="2502" height="1114"/>]]>
           
        &lt;p&gt;I just found out that you can directly push drafts from &lt;a href=&#34;https://ia.net/writer&#34;&gt;iA Writer&lt;/a&gt; to a blog running on &lt;a href=&#34;https://ghost.org&#34;&gt;Ghost&lt;/a&gt; with just one click.&lt;/p&gt;
&lt;p&gt;Excited about this fact I followed the short &lt;a href=&#34;https://docs.ghost.org/integrations/ia-writer/&#34;&gt;official guide&lt;/a&gt; and set everything up. Unfortunately I ran into a problem which took me a bit to resolve: Every time I linked images from my blog post the push to Ghost would fail with a very generic error message:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Failed to upload some images. Received an error when connecting to the service&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I figured that it was maybe related to me self-hosting the blog. It&amp;rsquo;s currently running behind nginx so my guess was that something is going wrong with the proxying, caching or other annoying to debug settings.&lt;/p&gt;
&lt;p&gt;After testing with a few different sized images I realized it only happens on images that are bigger than 1MB which pointed me to the file upload limit of nginx. After changing it everything worked and so the fix was to set it a bit higher by tweaking the limit via &lt;code&gt;client_max_body_size&lt;/code&gt; and reloading nginx.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example from my configuration&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;server&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;listen&lt;/span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;443&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;server_name&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;blog.notmyhostna.me&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;client_max_body_size&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;50M&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;}&lt;/span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After doing that I also found that it&amp;rsquo;s something that&amp;rsquo;s being mentioned in the Ghost Docs &lt;a href=&#34;https://ghost.org/faq/image-upload-issues/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hope that&amp;rsquo;s helpful to someone else finding that through a search engine.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>The sad state of RSS on the Mac</title>
      <link>https://blog.notmyhostna.me/posts/the-sad-state-of-rss-on-the-mac/</link>
      <pubDate>Fri, 20 Jul 2018 16:13:02 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/the-sad-state-of-rss-on-the-mac/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/the-sad-state-of-rss-on-the-mac/feature.jpg" width="4127" height="3095"/>]]>
           
        &lt;p&gt;I stopped using an RSS feed reader for a while because at some point my inbox got a bit out of hand by having too many unread items piled up. I slowly stopped looking at them before abandoning the idea completely and moving the apps into some subfolder on the 7th page of the home screen.&lt;/p&gt;
&lt;p&gt;Recently, mostly after being annoyed by algorithmically sorted news feeds everywhere, I decided to get back in the game.&lt;/p&gt;
&lt;p&gt;As a huge fan of RSS feeds I tested my way through a bunch of RSS readers over the years. The ones I used most are NewsNetWire (Mac and iOS), Reeder (Mac and iOS), Newsbeuter (Terminal based), Miniflux (Web) and recently also ReadKit (Mac).&lt;/p&gt;
&lt;p&gt;First step of rebooting my RSS setup was to set up my favorite self-hosted RSS reader &lt;a href=&#34;https://miniflux.app&#34;&gt;Miniflux&lt;/a&gt;. It deals with periodically fetching all your feeds and providing an API based on the &lt;a href=&#34;https://feedafever.com&#34;&gt;Fever&lt;/a&gt; &amp;ldquo;standard&amp;rdquo;. That API format is supported by a lot of apps across platforms. This makes it very easy to use your favorite app and keep it in sync with your Miniflux instance. Miniflux itself doesn&amp;rsquo;t provide any mobile or native apps and only lives in your browser. The web interface is fast, easy to use and the author is rightly &lt;a href=&#34;https://docs.miniflux.app/en/latest/opinionated.html&#34;&gt;opinionated&lt;/a&gt; on keeping it that way.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/the-sad-state-of-rss-on-the-mac/Screen-Shot-2018-07-20-at-00.56.27.png&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;Preferably I like to have a native app that I can maximize without being stuck in a browser window surrounded by distractions but that&amp;rsquo;s where the problems start:&lt;/p&gt;
&lt;p&gt;There are not that many great feed readers for macOS right now that work with the Fever API and have the Look &amp;amp; Feel of a native Mac app and I&amp;rsquo;m hoping that I missed one that matches my criteria:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for the Fever API&lt;/li&gt;
&lt;li&gt;Native Mac app, no Electron&lt;/li&gt;
&lt;li&gt;Not ugly&lt;/li&gt;
&lt;li&gt;Optional: Bonus points if there&amp;rsquo;s also an app for iOS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What mostly sparked my blog post was that the two apps which looked most promising seem to have been abandoned or buggy to the degree that they are unusable. There&amp;rsquo;s a big selection of very polished and feature-rich apps for iOS but the counterpart for macOS seems to be missing. If you are only interested in iOS apps for iPhone and iPad and don&amp;rsquo;t need an app for macOS there&amp;rsquo;s a good selection of reviews and articles over at MacStories.net (&lt;a href=&#34;https://www.macstories.net/reviews/fiery-feeds-2-review/&#34;&gt;Fiery Feeds&lt;/a&gt;, &lt;a href=&#34;https://www.macstories.net/linked/the-rss-revival/&#34;&gt;The RSS revival&lt;/a&gt;, &lt;a href=&#34;https://www.macstories.net/ios/lire-rss-client-adds-deeper-ios-11-drag-and-drop-support/&#34;&gt;lire&lt;/a&gt;)&lt;/p&gt;
&lt;h1 id=&#34;rss-feed-readers-for-macos&#34;&gt;RSS feed readers for macOS&lt;/h1&gt;
&lt;h2 id=&#34;readkithttpsreadkitappcom&#34;&gt;&lt;a href=&#34;https://readkitapp.com&#34;&gt;ReadKit&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I bought ReadKit for Mac a while ago as it supports &lt;a href=&#34;https://pinboard.in&#34;&gt;Pinboard&lt;/a&gt; and the Fever API and would collect all my unread items in one neat and native app. Unfortunately it crashes a lot when I refresh my feeds and it&amp;rsquo;s too frequently to keep using it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hey, I didn’t get any reply when I sent it to the support email address so I wanted to ask if there’s anything else I can do to help you track down the bug? Is ReadKit still being actively maintained? I attached two more crash reports in case that’s helpful.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I reported the bug and sent bug reports multiple times but never got a reply via Mail and Twitter.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;&lt;a href=&#34;https://twitter.com/ReadKit?ref_src=twsrc%5Etfw&#34;&gt;@ReadKit&lt;/a&gt; Hey, is the app still being developed actively? Sent some bug report via email 2 weeks ago but haven&amp;#39;t heard anything back yet.&lt;/p&gt;&amp;mdash; dewey (@tehwey) &lt;a href=&#34;https://twitter.com/tehwey/status/1006302052253945857?ref_src=twsrc%5Etfw&#34;&gt;June 11, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;p&gt;Last update on the App Store: &lt;a href=&#34;https://itunes.apple.com/app/readkit/id588726889?ls=1&amp;amp;mt=12&#34;&gt;January 12, 2018&lt;/a&gt;Last update on Twitter: &lt;a href=&#34;https://twitter.com/readkit?lang=en&#34;&gt;February 20, 2018&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;reederhttpreederappcom&#34;&gt;&lt;a href=&#34;http://reederapp.com&#34;&gt;Reeder&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I bought Reeder for Mac a long time ago when the first version came out. It looked polished back then and it still does to this day, supports the Fever API and even has a iOS app with the same familiar theme. Some time after I bought it a new version came out and I had to buy the new version. I was not too happy about it as the previous version was without updates for a long time but I understand the limitations of the App Store and the missing upgrade pricing option. I went ahead and updated to the new version. Unfortunately just like the previous versions that I bought it seems that it&amp;rsquo;s undergoing long stretches of abandonment where it&amp;rsquo;s not sure if the developer is still interested in updating it.&lt;/p&gt;
&lt;p&gt;I wrote a quick Mail but didn&amp;rsquo;t get a reply.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Subject: Should I buy?Hey, I was using an older version of Reeder and then stopped using it after the first paid upgrade. I’m just looking into RSS readers again and Reeder still looks like my top choice. ReadKit is too buggy…I just wanted to ask if the app is still actively maintained or if there’s a new version coming out soon? Don’t want to get bitten again by a paid upgrade shortly after I bought it. Last update in the app store was 2017 and the Twitter account was mostly tweeting in 2015 so I’m a bit unsure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Last update on the App Store: &lt;a href=&#34;https://itunes.apple.com/us/app/reeder-3/id880001334?mt=12&#34;&gt;November 22, 2017&lt;/a&gt;Last update on Twitter: &lt;a href=&#34;https://twitter.com/reederapp?lang=en&#34;&gt;November 25, 2015&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I know I&amp;rsquo;m not entitled to a reply from developers, especially the ones where I&amp;rsquo;m not a current customer but some sign of activity on Twitter, the company blog or via email would go a long way of convincing people that they should spend their money on these apps.&lt;/p&gt;
&lt;h2 id=&#34;others&#34;&gt;Others&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://itunes.apple.com/app/id576338668?mt=12&#34;&gt;Leaf&lt;/a&gt;, looks nice but doesn&amp;rsquo;t support the Fever API&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://itunes.apple.com/us/app/netnewswire/id635060292?mt=12&#34;&gt;NewsNetWire&lt;/a&gt;, when I started using RSS feeds this was the gold standard and I used it heavily for years. Now it got acquired and after seeing &lt;a href=&#34;http://netnewswireapp.com/mac/&#34;&gt;the landing page&lt;/a&gt; I got excited. It looks great!&lt;/p&gt;
&lt;p&gt;Unfortunately it seems that the app is extremely buggy and for that quite expensive.&lt;/p&gt;



&lt;figure&gt;
    
        &lt;img src=&#34;https://blog.notmyhostna.me/posts/the-sad-state-of-rss-on-the-mac/Screen-Shot-2018-07-20-at-19.50.04.png&#34;/&gt; &lt;/figure&gt;

&lt;p&gt;&lt;a href=&#34;https://newsbeuter.org&#34;&gt;Newsbeuter&lt;/a&gt;, a CLI based feed reader. Similar to mutt for email. I used this for a while and described my setup in &lt;a href=&#34;https://blog.notmyhostna.me/using-newsbeuter-to-read-your-rss-feeds/&#34;&gt;another blog post&lt;/a&gt; but it&amp;rsquo;s not something I still want to use.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Based on this disappointing selection I&amp;rsquo;m currently just relying on the Miniflux web interface and Reeder on iOS that I bought a while ago. I hope it just keeps working.&lt;/p&gt;
&lt;p&gt;If there are any apps I missed that check off my requirements please let me know. You can find me on Twitter as &lt;a href=&#34;https://twitter.com/tehwey&#34;&gt;@tehwey&lt;/a&gt;, the discussion is at &lt;a href=&#34;https://news.ycombinator.com/item?id=17577442&#34;&gt;Hackernews&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&#34;https://unsplash.com/photos/9-QUC4fm8Lo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&#34;&gt;Flipboard&lt;/a&gt; on &lt;a href=&#34;https://unsplash.com/search/photos/newsstand?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&#34;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Hong Kong</title>
      <link>https://blog.notmyhostna.me/posts/hong-kong/</link>
      <pubDate>Sat, 07 Jul 2018 18:54:45 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/hong-kong/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/hong-kong/feature.jpg" width="4032" height="3024"/>]]>
           
        &lt;p&gt;A short, picture-heavy summary of my two weeks trip to Hong Kong earlier this summer. To set the mood there&amp;rsquo;s some recommended songs to play if you are interested. They are to be found at the end of this post in the section named “Recommended Cantopop”—so scroll away. But don&amp;rsquo;t forget to come back!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7925-1--1-.jpg&#34; alt=&#34;IMG_7925-1&amp;ndash;1-&#34;&gt;&lt;/p&gt;
&lt;p&gt;It would sound very cliché to say that I was interested in Hong Kong since I watched early Jacky Chan movies but there&amp;rsquo;s probably a bit of truth to that. The city with it&amp;rsquo;s neon lights, red taxis, twisted roads and dark alleys always fascinated me. A construction site featuring bamboo scaffolding and the ubiquitous green fabric wrapped around it has been my background image for a long time now, perfectly captured by &lt;a href=&#34;https://www.petersteinhauer.com/#/home-page-1/&#34;&gt;Peter Steinhauer&amp;rsquo;s&lt;/a&gt; “Cocoon” series.&lt;/p&gt;
&lt;p&gt;This year I finally had the chance to visit the city for two weeks and planned out an itinerary. I set out to evaluate if I could potentially live there so the goal was to see not just the city with it&amp;rsquo;s various neighbourhoods itself but also the surrounding nature and beaches.&lt;/p&gt;
&lt;p&gt;I choose end of march to beginning of June as my time frame which later turned out to be a good choice. It was hot but never too hot and most importantly not too humid. I expected differently but only once was there any rain.&lt;/p&gt;
&lt;p&gt;Usually I try not to plan too much ahead as I&amp;rsquo;m the kind of traveler who walks around trying to get lost and not checking off the top list of tourist destinations with hordes of Lonely Planet carrying tourists. This time I decided to plan ahead a bit more and created a list of experiences I wanted to have.&lt;/p&gt;
&lt;p&gt;Mostly it was food places I found, got recommended or saw on Anthony Bourdain&amp;rsquo;s shows which I&amp;rsquo;m a huge fan of and partly it was the classic tourist destinations like Victoria Park, Happy Valley&amp;rsquo;s horse racing track, Dragon&amp;rsquo;s Back hike, Star Ferry and others.&lt;/p&gt;
&lt;p&gt;During our stay we were living at Chunking Mansion which was both affordable and close to the MTR.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While many locals avoid it for its reputation and for some of its less legitimate business enterprises, it offers cheap rooms and asylum for people, specifically refugees, from all around the world&amp;hellip;and even a taste of home.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another fitting quote from Bourdain.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7031-1.jpg&#34; alt=&#34;IMG_7031-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;A side street located within 5 minutes of walking from Chunking Mansion&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not ashamed to admit that I make a habit out of visiting the local Apple Stores everywhere I go if time permits. They are usually located in nice neighbourhoods and architecturally interesting. To me that seems like a good enough reason.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7184-1.jpg&#34; alt=&#34;IMG_7184-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_8266-1.jpg&#34; alt=&#34;IMG_8266-1&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;cooked-food-center&#34;&gt;Cooked Food Center&lt;/h2&gt;
&lt;p&gt;Or also called CFC, usually located in buildings that could be mistaken for a parking garage or a deserted warehouse. Conveniently located next to bigger MTR stations the food centers are a collection point for street food vendors. To free up the precious space on the street and to keep an eye on the food quality it was decided to move them from the open streets to multi story buildings also housing the wet markets. The ground floor of the CFC usually houses a wet market where you can buy fresh fish, vegetables and all kinds of different spices.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7754-1.jpg&#34; alt=&#34;IMG_7754-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;Up the gray, slow moving escalator and you&amp;rsquo;ll find yourself in a huge floor filled with different kinds of restaurants. These places don&amp;rsquo;t look fancy; green plastic chairs and big round tables are lining the corridor that takes you by all the different restaurants. It&amp;rsquo;s hard to even distinguish which tables belong to which place, the chair color can sometimes be an indicator. Walking down the corridor is an experience itself, tables filled with all kinds of food, fresh fish swimming their last rounds in the aquariums next to the kitchen. The noise of plates being thrown into barrels to wash them later mixes with the blaring TVs that are trying to get your attention. The monotonous humming of the numerous fans on the ceiling fades in the background.&lt;/p&gt;
&lt;p&gt;Or as Anthony Bourdain on the “Hong Kong” episode of Parts Unknown sums it up nicely:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cheap delicious food served from open-air stalls. Pull up a plastic stool. Crack a beer. Fire up the wok.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Plastic tables, toilet paper rolls as napkins - the focus is on the food, not the interior.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_8177.jpg&#34; alt=&#34;IMG_8177&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7739-1.jpg&#34; alt=&#34;IMG_7739-1&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;breakfast&#34;&gt;Breakfast&lt;/h2&gt;
&lt;p&gt;Tsui Wah, a chain diner-like restaurant with great comfort food and breakfast options. If you are like me and you don&amp;rsquo;t eat a lot of meat for breakfast there&amp;rsquo;s sugar buns. Bread, toasted and drenched in condensed milk and sugar, paired with a thick rimmed cup of milk tea it&amp;rsquo;s a good way to start your day.&lt;/p&gt;
&lt;h2 id=&#34;beaches&#34;&gt;Beaches&lt;/h2&gt;
&lt;p&gt;Having multiple beaches in close vicinity is one of the cool features of Hong Kong. They are clean, easily accessible by public transport or taxis and have bathroom and changing room facilities. The concrete structures on the beach paired with the pastel colors of the late afternoon sky always had a very Japanese vibe or - haven&amp;rsquo;t been to Japan yet - what I think it would look like.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_8147-1.jpg&#34; alt=&#34;IMG_8147-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_8162-2.jpg&#34; alt=&#34;IMG_8162-2&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_8198-3.jpg&#34; alt=&#34;IMG_8198-3&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;housing&#34;&gt;Housing&lt;/h2&gt;
&lt;p&gt;Everyone knows them, the gray spikes pushing through the green surroundings of Hong Kong like beehives.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_8204-1.jpg&#34; alt=&#34;IMG_8204-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_8212-1.jpg&#34; alt=&#34;IMG_8212-1&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;neon-signs--night&#34;&gt;Neon signs / Night&lt;/h2&gt;
&lt;p&gt;Unfortunately on the decline I was still able to enjoy some last remains before they are all replaced by modern LED alternatives.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7156-1.jpg&#34; alt=&#34;IMG_7156-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7414-11.jpg&#34; alt=&#34;IMG_7414-11&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7451-1.jpg&#34; alt=&#34;IMG_7451-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7459-1--1-.jpg&#34; alt=&#34;IMG_7459-1&amp;ndash;1-&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_8358-1.jpg&#34; alt=&#34;IMG_8358-1&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;yau-ma-tei-police-station&#34;&gt;Yau Ma Tei police station&lt;/h2&gt;
&lt;p&gt;The police station of Rush Hour 2 fame is now closed down but you can still visit it as all the signs are still there.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7333-7.jpg&#34; alt=&#34;IMG_7333-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7349-8.jpg&#34; alt=&#34;IMG_7349-8&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;choi-hung-estate&#34;&gt;Choi Hung Estate&lt;/h2&gt;
&lt;p&gt;Too busy with Instagrammers these days, that&amp;rsquo;s the one thing that makes it interesting now if you enjoy people watching.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7886-1.jpg&#34; alt=&#34;IMG_7886-1&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;walking&#34;&gt;Walking&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7245-2.jpg&#34; alt=&#34;IMG_7245-2&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7246-3.jpg&#34; alt=&#34;IMG_7246-3&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7253-4.jpg&#34; alt=&#34;IMG_7253-4&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7168-1.jpg&#34; alt=&#34;IMG_7168-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;IMG_7264-5.jpg&#34; alt=&#34;IMG_7264-5&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;recommended-cantopop&#34;&gt;Recommended Cantopop&lt;/h2&gt;
&lt;p&gt;I want to highlight two albums that I have been listening too a lot in the past months.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;400x400bb.jpg&#34; alt=&#34;400x400bb&#34;&gt;&lt;/p&gt;
&lt;p&gt;Leslie Cheung&amp;rsquo;s album 常在心頭 with my favorite song: 癡心 and 一片痴 (&lt;a href=&#34;https://www.youtube.com/watch?v=WC43x4TtBlQ&#34;&gt;YouTube&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://geo.itunes.apple.com/at/album/%E5%B8%B8%E5%9C%A8%E5%BF%83%E9%A0%AD/892623754?mt=1&amp;app=music&#34; style=&#34;display:inline-block;overflow:hidden;background:url(https://linkmaker.itunes.apple.com/assets/shared/badges/en-us/music-lrg.svg) no-repeat;width:158px;height:45px;background-size:contain;&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;400x400bb-2.jpg&#34; alt=&#34;400x400bb-2&#34;&gt;&lt;/p&gt;
&lt;p&gt;Anita Mui&amp;rsquo;s album 妖女 with my favorite song: 邁向新一天 (&lt;a href=&#34;https://www.youtube.com/watch?v=J8w8EMRB0JM&#34;&gt;YouTube&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://geo.itunes.apple.com/at/album/%E9%82%81%E5%90%91%E6%96%B0%E4%B8%80%E5%A4%A9/892394861?i=892394871&amp;mt=1&amp;app=music&#34; style=&#34;display:inline-block;overflow:hidden;background:url(https://linkmaker.itunes.apple.com/assets/shared/badges/en-us/music-lrg.svg) no-repeat;width:158px;height:45px;background-size:contain;&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Overall it was a great trip and I can only recommend the city, if you are going make sure to plan some down days to go to the beach or do a hike.&lt;/p&gt;
&lt;p&gt;If this sparked your interest I&amp;rsquo;d suggest to watch Anthony Bourdain&amp;rsquo;s &lt;a href=&#34;https://explorepartsunknown.com/destination/hong-kong/&#34;&gt;Hong Kong&lt;/a&gt; episode as it was one of his best. Featuring an array of interesting people like Christopher Doyle who was the cinematographer of “In the mood for love”. Sadly Bourdain &lt;a href=&#34;https://explorepartsunknown.com/remembering-bourdain/&#34;&gt;passed away&lt;/a&gt; since I started writing this post.&lt;/p&gt;
&lt;p&gt;For more pictures follow me on the &lt;a href=&#34;https://www.instagram.com/tehwey/&#34;&gt;&amp;lsquo;gram&lt;/a&gt; or &lt;a href=&#34;https://twitter.com/tehwey&#34;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Essential apps on macOS</title>
      <link>https://blog.notmyhostna.me/posts/essential-apps-on-macos/</link>
      <pubDate>Thu, 10 Nov 2016 22:06:46 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/essential-apps-on-macos/</guid>
      <description>
        
          
        &lt;p&gt;Someone who just bought his first Mac asked me which essential (GUI) apps I currently use that I could recommend to him. As this will probably happen again I&amp;rsquo;ll just keep this list here so I can easily link to it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1Password&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Password management&lt;/li&gt;
&lt;li&gt;iOS sync, all my important documents / certificates are stored in there and sync with my phone and browser extensions&lt;/li&gt;
&lt;li&gt;1Password also has a web interface so you don&amp;rsquo;t have to install the program if you are on some other computer&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://1password.com/&#34;&gt;https://1password.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;AppCleaner&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delete apps and clean up related files like preferences and other clutter&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://freemacsoft.net/appcleaner/&#34;&gt;https://freemacsoft.net/appcleaner/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Arq&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Client side encrypted backups to a bunch of services, I use it for Amazon Drive, Google Drive and my own server via SCP.&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://www.arqbackup.com/&#34;&gt;https://www.arqbackup.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Atom&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Text editor for Go development with &lt;a href=&#34;https://atom.io/packages/go-plus&#34;&gt;go-plus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://atom.io/&#34;&gt;https://atom.io/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;BetterSnapTool&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use it as a window manager (cmd + shift + arrow key to move window around the screen), couldn&amp;rsquo;t live without that&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://itunes.apple.com/de/app/bettersnaptool/id417375580?mt=12&#34;&gt;https://itunes.apple.com/de/app/bettersnaptool/id417375580?mt=12&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Calibre&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Converting eBooks and move them to Kindle, ugly but it&amp;rsquo;s the best for this use case&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://calibre-ebook.com/&#34;&gt;https://calibre-ebook.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Captured&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automatically upload screenshots to your own server and copying URL to clipboard&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://itunes.apple.com/at/app/captured/id414675451?l=en&amp;amp;mt=12&#34;&gt;https://itunes.apple.com/at/app/captured/id414675451?l=en&amp;amp;mt=12&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Carbon Copy Cloner&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bootable Backups to an external HD on top of TimeMachine and Arq&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://bombich.com/&#34;&gt;https://bombich.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Charles&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mitm proxy capatable of mitm&amp;rsquo;ing SSL connections, very useful for reverse engineering APIs&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://www.charlesproxy.com/&#34;&gt;https://www.charlesproxy.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Docker&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Docker.app is a very easy way to have the docker deamon running on your Mac&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://docs.docker.com/docker-for-mac/&#34;&gt;https://docs.docker.com/docker-for-mac/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Flux&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Screen is less bright at night so your eyes start to hurt&amp;hellip;later&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://justgetflux.com/&#34;&gt;https://justgetflux.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;iTerm&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Terminal replacement with great tmux support&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://www.iterm2.com/&#34;&gt;https://www.iterm2.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;MacDown&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Markdown editor with preview and syntax highlighting, you could also get this done in Atom though&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;http://macdown.uranusjr.com/&#34;&gt;http://macdown.uranusjr.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Paw&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;REST client with a bunch of great features, especially the sync and a way to set variables in routes is super useful.&lt;/li&gt;
&lt;li&gt;Free alternative: &lt;a href=&#34;https://www.getpostman.com/&#34;&gt;Postman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://paw.cloud/&#34;&gt;https://paw.cloud/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Postico&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Postgres client&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://eggerapps.at/postico/&#34;&gt;https://eggerapps.at/postico/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Pixelmator&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Image editing, has all the features I need and I don&amp;rsquo;t have to use annoying Adobe things&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;http://www.pixelmator.com/mac/&#34;&gt;http://www.pixelmator.com/mac/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Textual&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One of my most used apps and the best IRC client on macOS, lots of features, ZNC support, Tor support included&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://www.codeux.com/textual/&#34;&gt;https://www.codeux.com/textual/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Tweetbot&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Twitter client without sponsored tweets and ads, supports multiple accounts, muting etc.&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;http://tapbots.com/tweetbot/mac/&#34;&gt;http://tapbots.com/tweetbot/mac/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Viscosity&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My favorite OpenVPN client because it doesn&amp;rsquo;t look as ugly as Tunnelblick and does everything I need&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://www.sparklabs.com/viscosity/&#34;&gt;https://www.sparklabs.com/viscosity/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Tower&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I like GUI git clients, sue me&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://www.git-tower.com/mac/&#34;&gt;https://www.git-tower.com/mac/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Transmission&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Torrent client, whitelisted on most trackers&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://transmissionbt.com/&#34;&gt;https://transmissionbt.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Dash&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Offline documentation and snippets, I mostly use it for the snippets because it supports placeholders in snippets too&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://kapeli.com/dash&#34;&gt;https://kapeli.com/dash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;XLD&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lossless audio decoder, I use this to convert Flac to Apple Lossless while automatically dropping this into the iTunes watch folder so it gets added automatically&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;http://tmkk.undo.jp/xld/index_e.html&#34;&gt;http://tmkk.undo.jp/xld/index_e.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;LICEcap&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Screen recording with gif output&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;http://www.cockos.com/licecap/&#34;&gt;http://www.cockos.com/licecap/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;TripMode&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Useful if you tether through your phone a lot while travelling, enable network access on a per application basis.&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://www.tripmode.ch/&#34;&gt;https://www.tripmode.ch/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;NepTunes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scrobble to Last.FM from Apple Music / iTunes&lt;/li&gt;
&lt;li&gt;If you don&amp;rsquo;t need Apple Music integration there&amp;rsquo;s also &lt;a href=&#34;http://haunold.me/quickscrobbler/&#34;&gt;QuickScrobbler&lt;/a&gt; as a free alternative&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://itunes.apple.com/us/app/neptunes-for-itunes-spotify/id1006739057?mt=12&#34;&gt;https://itunes.apple.com/us/app/neptunes-for-itunes-spotify/id1006739057?mt=12&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;GPGTools&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GPG encryption integration for Mail.app and GPG Keychain to manage your GPG keys (Mail integration not updated for Sierra yet)&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://gpgtools.org/&#34;&gt;https://gpgtools.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Kaleidoscope&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Diff client with great Tower integration&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;http://www.kaleidoscopeapp.com/&#34;&gt;http://www.kaleidoscopeapp.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Yate&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Music tagger&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://2manyrobots.com/yate/&#34;&gt;https://2manyrobots.com/yate/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The Unarchiver&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extract rar archives and a lot of other formats&lt;/li&gt;
&lt;li&gt;Web: &lt;a href=&#34;https://itunes.apple.com/app/the-unarchiver/id425424353?mt=12&amp;amp;ls=1&#34;&gt;https://itunes.apple.com/app/the-unarchiver/id425424353?mt=12&amp;amp;ls=1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Use Google Hangouts via Bitlbee / IRC</title>
      <link>https://blog.notmyhostna.me/posts/use-google-hangouts-via-bitlbee-/-irc/</link>
      <pubDate>Sat, 24 Sep 2016 11:47:18 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/use-google-hangouts-via-bitlbee-/-irc/</guid>
      <description>
        
          
        &lt;p&gt;As someone who hates Google Hangouts with a passion it took me surprisingly long to look into a way to use it via an IRC bridge to get rid of the annoying Chrome app.  Today I finally had some spare time to look into it and found some promising projects that enabled me to do exactly what I wanted: Getting rid of the shitty desktop client and use Hangouts directly through IRC.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m already using Twitter and AIM through &lt;a href=&#34;https://www.bitlbee.org/main.php/news.r.html&#34;&gt;Bitlbee&lt;/a&gt; so checking if there&amp;rsquo;s support for Hangouts was the first thing I did. Bitlbee is an amazing piece of software enabling you to use a lot of different chat services through a unified IRC interface. Unfortunately Hangouts is a propritary protocol now and you can&amp;rsquo;t just use Jabber like it was the case with &lt;a href=&#34;https://wiki.bitlbee.org/HowtoGtalk&#34;&gt;GTalk&lt;/a&gt; back in the days. There&amp;rsquo;s a new library now that reverse engineered the protocol and enables developers to still build on the protocol: &lt;a href=&#34;https://github.com/tdryer/hangups&#34;&gt;&lt;code&gt;hangups&lt;/code&gt;&lt;/a&gt;. There&amp;rsquo;s a &lt;a href=&#34;https://github.com/tdryer/hangups&#34;&gt;whole list of other projects&lt;/a&gt; using that library now.&lt;/p&gt;
&lt;p&gt;One of the project that got inspired by hangups is &lt;a href=&#34;https://bitbucket.org/EionRobb/purple-hangouts&#34;&gt;&lt;code&gt;purple-hangouts&lt;/code&gt;&lt;/a&gt; which is an additional plugin for the already existing &lt;a href=&#34;https://developer.pidgin.im/wiki/WhatIsLibpurple&#34;&gt;&lt;code&gt;libpurple&lt;/code&gt;&lt;/a&gt; library. libpurple is the IM library behind Pidgin.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Install purple-hangouts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The overlay we need to install &lt;code&gt;purple-hangouts&lt;/code&gt; is already in the official overlays so we can just run &lt;code&gt;layman -L | grep mrueg&lt;/code&gt; to see if it&amp;rsquo;s still there and then add the repository to our overlays with &lt;code&gt;layman -a mrueg&lt;/code&gt;. Then just run &lt;code&gt;eix-sync&lt;/code&gt; to update your &lt;code&gt;eix&lt;/code&gt; index and install it with &lt;code&gt;emerge -av purple-hangouts&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enable libpurple support in Bitlbee&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To use the
&lt;code&gt;purple-hangouts&lt;/code&gt; is just some additional plugins for the already existing &lt;a href=&#34;https://developer.pidgin.im/wiki/WhatIsLibpurple&#34;&gt;&lt;code&gt;libpurple&lt;/code&gt;&lt;/a&gt; library so we have to make sure &lt;code&gt;bitlbee&lt;/code&gt; is already compiled with these enabled. To do that just set the use flags of the bitlbee package to include &lt;code&gt;purple&lt;/code&gt; and then emerge the package again.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@notmyhostname /etc/portage$ cat package.use | grep bitlbee
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net-im/bitlbee otr twitter purple
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Configure Bitlbee&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After restarting Bitlbee (&lt;code&gt;/etc/init.d/bitlbee restart&lt;/code&gt;) you should be able to connect to your server again. Type &lt;code&gt;help purple&lt;/code&gt; in your &lt;code&gt;&amp;amp;bitlbee&lt;/code&gt; channel and you should see &lt;code&gt;hangouts&lt;/code&gt; in the list of available services.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:21:25]  dewey	help purple
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:21:30]  root	BitlBee libpurple module supports the following IM protocols:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:21:30]  root	 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:21:30]  root	* aim (AIM)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:21:30]  root	* hangouts (Hangouts)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To add the account to your bitlbee configuration just run &lt;code&gt;add hangouts example@gmail.com&lt;/code&gt; with your Google Account email. To set the password you&amp;rsquo;ll have to use the &lt;code&gt;/OPER&lt;/code&gt; command which should look like that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/OPER hangouts &amp;lt;your google password&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:23:15]  dewey	account add hangouts example@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:23:15]  root	Account successfully added with tag hangouts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:23:15]  root	You can now use the /OPER command to enter the password
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:24:00]  dewey	account list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:24:00]  root	 0 (twitter): twitter, tehwey (connected)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:24:00]  root	 2 (hangouts): hangouts, example@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:24:00]  root	End of account list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:24:43]  dewey	account on hangouts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once that is done we are ready to just turn it on which is done by running &lt;code&gt;account hangouts on&lt;/code&gt; which will in turn trigger the authentication process with Google. This will open a new IRC query that prompts you to click an URL and paste an oAuth token. This URL is currently broken so to finalize the login process we&amp;rsquo;ll have to get an oAuth token from Google through another way.&lt;/p&gt;
&lt;p&gt;Google is trying to prevent this so there are some additional hoops we have to jump through. A workaround is currently &lt;a href=&#34;https://bitbucket.org/EionRobb/purple-hangouts/issues/71/cannot-authenticate-error-invalid_scope&#34;&gt;being discussed&lt;/a&gt; on the issue tracker.&lt;/p&gt;
&lt;p&gt;Just follow the instructions in &lt;a href=&#34;https://github.com/tdryer/hangups/issues/260#issuecomment-246578670&#34;&gt;this comment&lt;/a&gt; and grab the oAuth token, then just paste it in the IRC query that prompted you for the token and hit return. Now we are ready to finally login with &lt;code&gt;accounts hangouts on&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:34:29]  dewey	account hangouts on
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:34:35]  root	hangouts - Logging in: Authenticating
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[14:34:35]  root	hangouts - Logging in: Logged in
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Done, that was easy!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Show real names instead of IDs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you prefer not to memorize long IDs I&amp;rsquo;d recommend to enable full names for the hangouts plugin. This will just show the real name people set on their Hangouts profile instead. To do that just run the following commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;account hangouts set nick_format %full_name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;accounts hangouts off
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;accounts hangouts on
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it!&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Let&#39;s Encrypt with auto-renewal and nginx</title>
      <link>https://blog.notmyhostna.me/posts/lets-encrypt-with-auto-renewal-and-nginx/</link>
      <pubDate>Sat, 25 Jun 2016 13:03:42 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/lets-encrypt-with-auto-renewal-and-nginx/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/lets-encrypt-with-auto-renewal-and-nginx/feature.jpg" width="1664" height="946"/>]]>
           
        &lt;p&gt;I recently moved from using a wildcard certificate to using a bunch of certificates from &lt;a href=&#34;https://letsencrypt.org/&#34;&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt;. I was a bit hesitant in the beginning because it seemed like a lot of work and hassle to deal with auto-renewal every 90 days but as it turned out it&amp;rsquo;s all really simple and free.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Screen-Shot-2016-06-25-at-17-02-40.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m just documenting this here so I can be lazy and just go back to this post in the future. As usual I&amp;rsquo;m using Gentoo and nginx here but this should work for almost every other configuration. This is the minimal nginx config I usually use that scores A+ on &lt;a href=&#34;https://www.ssllabs.com/&#34;&gt;SSLLabs&lt;/a&gt; and works well for all my needs.&lt;/p&gt;
&lt;h1 id=&#34;lets-encrypt&#34;&gt;Let&amp;rsquo;s Encrypt&lt;/h1&gt;
&lt;p&gt;To get the certificates I&amp;rsquo;m using the official tool that is now under the umbrella of the EFF: &lt;a href=&#34;https://certbot.eff.org/&#34;&gt;certbot&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Install this tool on your system, stop your currently running web server to free up the port and then just run the tool:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ certbot certonly&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you run it for the first time it&amp;rsquo;ll ask you to accept some terms and to enter your email address. After that you&amp;rsquo;ll see this screen:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Screen-Shot-2016-06-25-at-16-45-46.png&#34; alt=&#34;how to authenticate&#34;&gt;&lt;/p&gt;
&lt;p&gt;Selection option 2 here and continue, on the next screen just enter the domain you want to get your certificate for and press &lt;code&gt;OK&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Screen-Shot-2016-06-25-at-16-48-02.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;After that the certificate and private key will be generated and are located in &lt;code&gt;/etc/letsencrypt/live/example.com/&lt;/code&gt;. I usually use this path directly in nginx so I don&amp;rsquo;t have to copy around certificates once I renew them.&lt;/p&gt;
&lt;h1 id=&#34;nginx&#34;&gt;nginx&lt;/h1&gt;
&lt;p&gt;The nginx config is really basic and just looks like this. I split off the &lt;code&gt;ssl.conf&lt;/code&gt; because it&amp;rsquo;s the same for every domain&amp;rsquo;s config and I didn&amp;rsquo;t want to duplicate all that. That&amp;rsquo;s why it&amp;rsquo;s just imported and that way I don&amp;rsquo;t have to update all configs if I update the cipherlist in the future.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    listen      &lt;span style=&#34;color:#ae81ff&#34;&gt;443&lt;/span&gt; default_server ssl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    server_name example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ssl_certificate     &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;etc&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;letsencrypt&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;live&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;fullchain&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;pem;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ssl_certificate_key &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;etc&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;letsencrypt&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;live&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;privkey&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;pem;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    include &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;etc&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;nginx&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;ssl&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;conf;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error_log   &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;log&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;nginx&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;error&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;ssl&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;log;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    access_log  &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;log&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;nginx&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;access&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;ssl&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;log;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    root &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;www&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    index index&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;html;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    location &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        alias &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;www&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    listen      &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    server_name example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;301&lt;/span&gt; https:&lt;span style=&#34;color:#f92672&#34;&gt;//$&lt;/span&gt;server_name&lt;span style=&#34;color:#f92672&#34;&gt;$&lt;/span&gt;request_uri;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;ssl.conf&lt;/code&gt; looks like that right now, make sure you generated the dhparam.pem file with openssl and it&amp;rsquo;s located in that directory.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl on;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl_prefer_server_ciphers on;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl_session_cache shared:SSL:10m;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl_dhparam /etc/nginx/ssl/example.com/dhparam.pem;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl_ciphers &amp;#34;EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;add_header Strict-Transport-Security &amp;#34;max-age=15768000; includeSubDomains&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;add_header X-Frame-Options DENY;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;add_header X-Content-Type-Options nosniff;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl_stapling on;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl_stapling_verify on;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;resolver 8.8.4.4 8.8.8.8 valid=300s;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;resolver_timeout 10s;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;autorenewal&#34;&gt;Autorenewal&lt;/h1&gt;
&lt;p&gt;The Let&amp;rsquo;s Encrypt certificates expire every 90 days right now (&lt;a href=&#34;https://letsencrypt.org/2015/11/09/why-90-days.html&#34;&gt;Reason&lt;/a&gt;). For that reason we have to set up a script to check if they are still valid every once in a while and if not, renew them. Luckily this is all really easy and we just have to add a new cronjob. For the tool to run we have to stop the web server again so it can use the included webserver to set up the endpoint to talk to the Let&amp;rsquo;s Encrypt API. We can just do that with the &lt;code&gt;--pre-hook&lt;/code&gt; and &lt;code&gt;--post-hook&lt;/code&gt; parameters.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@weekly  /usr/bin/certbot renew --standalone --pre-hook &amp;#34;/etc/init.d/nginx stop&amp;#34; --post-hook &amp;#34;/etc/init.d/nginx st    art&amp;#34; --quiet
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This also makes it very easy to just run shell scripts to do some more things in case of a renewal. For ZNC for example you can use a tiny script like that to update the certificates the web interface of the bouncer is using.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root@examplecom ~$ cat znc-ssl-update.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/bash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat /etc/letsencrypt/live/example.com/&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;privkey,cert,chain&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;.pem &amp;gt; /home/dewey/.znc/znc.pem
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chown dewey:dewey /home/dewey/.znc/znc.pem
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once this is all done just restart nginx and enjoy your free certificates.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Screen-Shot-2016-06-25-at-17-01-48.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you want to support this organization please consider donating to the EFF: &lt;a href=&#34;https://supporters.eff.org/donate/&#34;&gt;https://supporters.eff.org/donate/&lt;/a&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Duplicity with PyDrive backend for Google Drive</title>
      <link>https://blog.notmyhostna.me/posts/duplicity-with-pydrive-backend-for-google-drive/</link>
      <pubDate>Sat, 15 Aug 2015 14:22:52 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/duplicity-with-pydrive-backend-for-google-drive/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/duplicity-with-pydrive-backend-for-google-drive/feature.jpg" width="3165" height="2374"/>]]>
           
        &lt;p&gt;Storing backups in Google Drive with &lt;code&gt;duplicity&lt;/code&gt; was broken for a long time now. Luckily someone wrote a new backend that is now able to make use of the new OAuth API requirement enforced by Google.&lt;/p&gt;
&lt;p&gt;To make use of that new backend we&amp;rsquo;ll have to run the latest version of &lt;code&gt;duplicity&lt;/code&gt; and &lt;code&gt;duply&lt;/code&gt;. Both of them aren&amp;rsquo;t in portage yet so in an attempt to fix that we are going to use our own local overlay that will be located in &lt;code&gt;/usr/local/portage&lt;/code&gt;. This is not to be confused with the regular location of portage: &lt;code&gt;/etc/portage&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Create the necessary directories and set the appropriate permissions:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p /usr/local/portage/{metadata,profiles}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &amp;#39;LocalOverlay&amp;#39; &amp;gt; /usr/local/portage/profiles/repo_name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &amp;#39;masters = gentoo&amp;#39; &amp;gt; /usr/local/portage/metadata/layout.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chown -R portage:portage /usr/local/portage
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Step 2: Create the make.conf for local ebuilds&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Edit or create your &lt;code&gt;local.conf&lt;/code&gt; located in &lt;code&gt;/etc/portage/repos.conf/local.conf&lt;/code&gt; and add the new overlay:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[LocalOverlay]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location = /usr/local/portage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;masters = gentoo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;auto-sync = no
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Step 3: Add the ebuild to your local overlay&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Because the version we are looking for is not &lt;a href=&#34;https://bugs.gentoo.org/show_bug.cgi?id=539674&#34;&gt;located in portage right now&lt;/a&gt; we&amp;rsquo;ll have to use our own ebuild. We can just grab the one someone posted on Gentoo&amp;rsquo;s Bugtracker (Thanks!):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;wget -O duplicity-0.7.03.ebuild https://bugs.gentoo.org/attachment.cgi\?id\=404618&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This one&amp;rsquo;s a few weeks old already and the &lt;code&gt;duplicity&lt;/code&gt; maintainers already released a new version so just rename it to &lt;code&gt;duplicity-0.7.04.ebuild&lt;/code&gt;, which is the latest development version right now.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p /usr/local/portage/app-backup/duplicity
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir /usr/local/portage/app-backup/duplicity/files
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp duplicity-0.7.04.ebuild /usr/local/portage/app-backup/duplicity
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chown -R portage:portage /usr/local/portage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pushd /usr/local/portage/app-backup/duplicity
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;repoman manifest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;popd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This ebuild also needs a patch (&lt;code&gt;duplicity-0.6.24-skip-test.patch&lt;/code&gt;) to work. This patch skips some failing tests and was patched into an earlier version. We need to provide that file so emerge will be able to apply it (The ebuild is looking for that file at the wrong place).&lt;/p&gt;
&lt;p&gt;You should be able to find that file in &lt;code&gt;/usr/portage/app-backup/duplicity/files&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Just copy it into our local &lt;code&gt;files&lt;/code&gt; directory
&lt;code&gt;cp duplicity-0.6.24-skip-test.patch /usr/local/portage/app-backup/duplicity/files&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;and run &lt;code&gt;ebuild duplicity-0.7.04.ebuild manifest&lt;/code&gt; to generate a new manifest with the new patch file included.&lt;/p&gt;
&lt;p&gt;Now you should be able to emerge the latest version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;root&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;notmyhostname &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;usr&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;local&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;portage&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;app&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;backup&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;duplicity&lt;span style=&#34;color:#f92672&#34;&gt;$&lt;/span&gt; emerge &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;av1 app&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;backup&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;duplicity
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;These are the packages that would be merged, &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; order:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Calculating dependencies&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt; done&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[ebuild  N    &lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;] app&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;backup&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;duplicity&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0.7&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;04&lt;/span&gt;::LocalOverlay  USE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-s3 {-test}&amp;#34;&lt;/span&gt; PYTHON_TARGETS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;python2_7&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; KiB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Total: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; package (&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; new), Size of downloads: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; KiB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Would you like to merge these packages&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;?&lt;/span&gt; [Yes&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;No]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If &lt;code&gt;duplicity&lt;/code&gt; isn&amp;rsquo;t in your &lt;code&gt;package.accepted_keywords&lt;/code&gt; file yet and portage is trying to emerge an old version just edit &lt;code&gt;/etc/portage/package.accepted_keywords&lt;/code&gt; and add the following keywords:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app-backup/duplicity ~amd64
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app-backup/duply ~amd64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we also added &lt;code&gt;duply&lt;/code&gt; we can also install the latest version of &lt;code&gt;duply&lt;/code&gt; via emerge (Version 1.10).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 4: Install PyDrive&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Right now there&amp;rsquo;s no version of PyDrive listed in the portage tree so we&amp;rsquo;ll have to install it via &lt;code&gt;pip&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;pip install PyDrive&lt;/code&gt; to install the latest version.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 5: Create Google API credentials&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The whole process is explained on the &lt;code&gt;duplicity&lt;/code&gt; man page (&lt;code&gt;man duplicity&lt;/code&gt;) but either Google changed their interface or the man page isn&amp;rsquo;t very detailed because the process is a little bit different now.&lt;/p&gt;
&lt;p&gt;First log into your Google Account and access:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://console.developers.google.com&#34;&gt;https://console.developers.google.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click on &amp;ldquo;Create Project&amp;rdquo; and wait for Google to process/create the Project. Once it&amp;rsquo;s done click on the project and then on &amp;ldquo;APIs &amp;amp; auth&amp;rdquo; in the sidebar. You&amp;rsquo;ll see a bunch of different APIs listed there but we only need &amp;ldquo;Drive API&amp;rdquo; which is located in the section called &amp;ldquo;Google Apps APIs&amp;rdquo;. Make sure to click on &amp;ldquo;Enable API&amp;rdquo; on the top.&lt;/p&gt;
&lt;p&gt;Once it&amp;rsquo;s enabled navigate to &amp;ldquo;Credentials&amp;rdquo; also located in the sidebar and click on &amp;ldquo;Add Credentials&amp;rdquo;. Select &amp;ldquo;OAuth Client ID&amp;rdquo;, then &amp;ldquo;Other&amp;rdquo; and then &amp;ldquo;Create&amp;rdquo;. In the next step you&amp;rsquo;ll be able to obtain your &amp;ldquo;Client ID&amp;rdquo; and &amp;ldquo;Client Secret&amp;rdquo;. We are going to make use of these credentials later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 6: Make duplicity use the new backend&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In our duply config file (usually located in &lt;code&gt;~/.duply/&amp;lt;server name&amp;gt;/config&lt;/code&gt;) I was using the following target until the API broke:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;TARGET=&#39;gdocs://username:password@example.com/backup-incoming/notmyhostna.me&#39;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In the latest version of duplicity the default backend for &lt;code&gt;gdocs&lt;/code&gt; is now pydrive and gdocs is an alias to that, we don&amp;rsquo;t need to change anything here. The username and password will be ignored by duplicity because we are going to supply the credentials another way.&lt;/p&gt;
&lt;p&gt;Create a file called &lt;code&gt;gdrive&lt;/code&gt; in &lt;code&gt;~/.duply/&amp;lt;server name&amp;gt;/&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;client_config_backend: settings
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;client_config:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   client_id: xxx.apps.googleusercontent.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   client_secret: yyyy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;save_credentials: True
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;save_credentials_backend: file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;save_credentials_file: gdrive.cache
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;get_refresh_token: True
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure to change &lt;code&gt;client_id&lt;/code&gt; and &lt;code&gt;client_secret&lt;/code&gt; to the values you created earlier and keep the identation like that, otherwise you&amp;rsquo;ll run into errors later on.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;gdrive.cache&lt;/code&gt; file will be created by &lt;code&gt;duplicity&lt;/code&gt; after logging in for the first time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 7: Run duply / duplicity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To pass the name of the file containing our credentials to duplicity we could use a environment variable called &lt;code&gt;GOOGLE_DRIVE_SETTINGS&lt;/code&gt; like that:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GOOGLE_DRIVE_SETTINGS=gdrive duply &amp;lt;server name&amp;gt; status&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t want to use the variable like that it&amp;rsquo;s possible to add &lt;code&gt;export GOOGLE_DRIVE_SETTINGS=gdrive&lt;/code&gt; to the top of duply&amp;rsquo;s configuration file.&lt;/p&gt;
&lt;p&gt;This was suggested on the &lt;a href=&#34;https://lists.nongnu.org/archive/html/duplicity-talk/&#34;&gt;duplicity-talk&lt;/a&gt; mailing list and is already present in the new configuration files for duply 1.10.&lt;/p&gt;
&lt;p&gt;Running &lt;code&gt;duply &amp;lt;server name&amp;gt; status&amp;gt;&lt;/code&gt; for the first time will start the authentication process with Google by displaying a link to start the OAuth authentication flow. Click on that link, log into your account and copy the string Google presents to you after being logged in successfully. Paste the string into your terminal and press return to finish the login process.&lt;/p&gt;
&lt;p&gt;The whole process looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GOOGLE_DRIVE_SETTINGS=./gdrive duply notmyhostname status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Start duply v1.10, time is 2015-08-15 17:34:56.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- Start running command STATUS at 17:34:56.933 ---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Go to the following link in your browser:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    https://accounts.google.com/o/oauth2/auth...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Enter verification code: yyyyy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Authentication successful.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Local and Remote metadata are synchronized, no sync needed.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Last full backup date: Sun Apr 12 00:00:04 2015
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should now be the duply output you are already familiar with!&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it!&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Setting up a Tor hidden service with nginx</title>
      <link>https://blog.notmyhostna.me/posts/setting-up-a-tor-hidden-service-with-nginx/</link>
      <pubDate>Fri, 13 Feb 2015 13:37:43 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/setting-up-a-tor-hidden-service-with-nginx/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/setting-up-a-tor-hidden-service-with-nginx/feature.jpg" width="2164" height="1440"/>]]>
           
        &lt;p&gt;Quick guide based on &lt;a href=&#34;https://twitter.com/CthulhuSec&#34;&gt;@CthulhuSec&lt;/a&gt;&amp;rsquo;s tutorial for setting up a Tor hidden service. If you don&amp;rsquo;t know what a hidden service is read &lt;a href=&#34;https://www.torproject.org/docs/hidden-services.html.en&#34;&gt;this high-level description&lt;/a&gt; before continuing.&lt;/p&gt;
&lt;h2 id=&#34;install-tor&#34;&gt;Install Tor&lt;/h2&gt;
&lt;p&gt;Install the Tor client, make sure you are running a recent version.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;emerge -av net-misc/tor
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to automatically start Tor at boot just add the service with the default run level: &lt;code&gt;rc-update add tor default&lt;/code&gt;. If you want to start the service right away just use &lt;code&gt;rc-service tor start&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;configure&#34;&gt;Configure&lt;/h2&gt;
&lt;p&gt;In this step we are going to add our hidden service to the Tor configuration file called &lt;code&gt;torrc&lt;/code&gt; located in &lt;code&gt;/etc/tor/torrc&lt;/code&gt;. It&amp;rsquo;s possible to run multiple hidden services, and it&amp;rsquo;s not a problem to service the same hidden service from multiple ports. In that case just duplicate the &lt;code&gt;HiddenServiceDir&lt;/code&gt; and &lt;code&gt;HiddenServicePort&lt;/code&gt; lines like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;HiddenServiceDir /usr/local/etc/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:8080

HiddenServiceDir /usr/local/etc/tor/other_hidden_service/
HiddenServicePort 6667 127.0.0.1:6667
HiddenServicePort 22 127.0.0.1:22
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We are only going to add one service for now.&lt;/p&gt;
&lt;p&gt;Open the configuration file using a text editor (&lt;code&gt;vim /etc/tor/torrc&lt;/code&gt;) and add your hidden service:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#
# Minimal torrc so tor will work out of the box
#
User tor
PIDFile /var/run/tor/tor.pid
Log notice syslog
DataDirectory /var/lib/tor/data

HiddenServiceDir /var/lib/tor/data/hs_notmyhostna.me/
HiddenServicePort 80 127.0.0.1:80
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reload your Tor service after that.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/init.d/tor reload&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Once you do that the new hostnames and the private keys for your hidden services will be created and are now located in your &lt;code&gt;DataDirectory&lt;/code&gt;. In my case it&amp;rsquo;ll look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@notmyhostname /var/lib/tor$ tree
.
└── data
    ├── cached-certs
    ├── cached-microdesc-consensus
    ├── cached-microdescs
    ├── cached-microdescs.new
    ├── hidden_service
    │   ├── hostname
    │   └── private_key
    ├── hs_example.com
    │   ├── hostname
    │   └── private_key
    ├── hs_notmyhostna.me
    │   ├── hostname
    │   └── private_key
    ├── lock
    └── state

4 directories, 12 files
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;
First, Tor will generate a new public/private keypair for your hidden service. The file called &lt;code&gt;private_key&lt;/code&gt; contains your private key, make sure you don&amp;rsquo;t share that with others. They&amp;rsquo;ll be able to impersonate your hidden service.&lt;/p&gt;
&lt;p&gt;The file &lt;code&gt;hostname&lt;/code&gt; will contain the .onion URL for your new hidden service (That&amp;rsquo;s the beforementioned public key, or to be specific: The hash of the public key). In my case that&amp;rsquo;s j5wfzhvvrf2dwm2v.onion. Write that down somewhere because you&amp;rsquo;ll need that in the next step.&lt;/p&gt;
&lt;h2 id=&#34;configure-the-web-server-nginx&#34;&gt;Configure the web server (nginx)&lt;/h2&gt;
&lt;p&gt;Create a new configuration file for the service you want to serve. In my case I&amp;rsquo;ll call it &lt;code&gt;tor_notmyhostna.me&lt;/code&gt; just so it&amp;rsquo;s easier to differentiate between that and the config file for the non-Tor site.&lt;/p&gt;
&lt;p&gt;vim /etc/nginx/sites-available/tor_notmyhostna.me could look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server {
    listen      127.0.0.1:80;
    server_name cc7yjqvfpwtl6uhy.onion;

    error_log   /var/log/nginx/tor_notmyhostna.me.error.log;
    access_log  off;

    location / {
        root /var/www/notmyhostna.me/;
        index index.html;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure to replace the server_name with the &lt;code&gt;hostname&lt;/code&gt; from the earlier step.&lt;/p&gt;
&lt;p&gt;Now just enable that new configuration by symlinking it to the sites-available directory and reload nginx:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ln -s /etc/nginx/sites-available/tor_notmyhostna.me /etc/nginx/sites-enabled/tor_notmyhostna.me
/etc/init.d/nginx reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To test it just download or start TorBrowser and try to access your personal .onion URL. Unfortunately serving a hidden service over https is not yet possible (There are &lt;a href=&#34;https://facebookcorewwwi.onion/&#34;&gt;exceptions&lt;/a&gt;&amp;hellip;). If you want more information about that read &lt;a href=&#34;https://blog.torproject.org/blog/facebook-hidden-services-and-https-certs&#34;&gt;this blog post&lt;/a&gt; by the Tor developers.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all. Easy!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Source:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This is all based on &lt;a href=&#34;https://twitter.com/CthulhuSec&#34;&gt;@CthulhuSec&lt;/a&gt;&amp;rsquo;s awesome &lt;a href=&#34;https://www.thecthulhu.com/setting-up-a-hidden-service-with-nginx/&#34;&gt;tutorial&lt;/a&gt;, just with some tiny changes for Gentoo users.&lt;/li&gt;
&lt;li&gt;Detailed documentation of &lt;a href=&#34;https://www.torproject.org/docs/tor-hidden-service.html.en&#34;&gt;Hidden Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cover image by &lt;a href=&#34;https://unsplash.com/kappuru&#34;&gt;Israel Sundseth&lt;/a&gt; via Unsplash. Cheers!&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>31C3</title>
      <link>https://blog.notmyhostna.me/posts/31c3/</link>
      <pubDate>Thu, 01 Jan 2015 17:38:53 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/31c3/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/31c3/feature.jpg" width="1500" height="1125"/>]]>
           
        &lt;p&gt;Just like every year the time between Christmas and New Years is best spent at the &lt;a href=&#34;http://en.wikipedia.org/wiki/Chaos_Communication_Congress&#34;&gt;Chaos Communication Congress&lt;/a&gt; happening at the CCH in Hamburg.&lt;/p&gt;
&lt;p&gt;Following is a list of all the talks I went to see. Unfortunately there are always some talks happening in parallel but you&amp;rsquo;ll still be able to &lt;a href=&#34;http://streaming.media.ccc.de/&#34;&gt;watch the stream&lt;/a&gt; to catch up. At the end you&amp;rsquo;ll find a list of talks I liked and would recommend even if it&amp;rsquo;s not a topic you are very knowledgable about.&lt;/p&gt;
&lt;h1 id=&#34;day-1&#34;&gt;Day 1&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;31C3 Opening Event&lt;/li&gt;
&lt;li&gt;31C3 Keynote&lt;/li&gt;
&lt;li&gt;3D Casting Aluminum&lt;/li&gt;
&lt;li&gt;Reproducible Builds&lt;/li&gt;
&lt;li&gt;Practical EMV PIN interception and fraud detection&lt;/li&gt;
&lt;li&gt;SS7: Locate. Track. Manipulate.&lt;/li&gt;
&lt;li&gt;Mobile self-defense&lt;/li&gt;
&lt;li&gt;(In)Security of Mobile Banking&lt;/li&gt;
&lt;li&gt;Crypto Tales from the Trenches&lt;/li&gt;
&lt;li&gt;Citizenfour&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;day-2&#34;&gt;Day 2&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Why is GPG &amp;ldquo;damn near unusable&amp;rdquo;?&lt;/li&gt;
&lt;li&gt;Beyond PNR: Exploring airline systems&lt;/li&gt;
&lt;li&gt;Cyber Necromancy&lt;/li&gt;
&lt;li&gt;Finding the Weak Crypto Needle in a Byte Haystack&lt;/li&gt;
&lt;li&gt;Forging the USB armory&lt;/li&gt;
&lt;li&gt;Fernvale: An Open Hardware and Software Platform, Based on the (nominally) Closed-Source MT6260 SoC&lt;/li&gt;
&lt;li&gt;The Matter of Heartbleed&lt;/li&gt;
&lt;li&gt;Heartache and Heartbleed: The insider’s perspective on the aftermath of Heartbleed&lt;/li&gt;
&lt;li&gt;Fnord News Show&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;day-3&#34;&gt;Day 3&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Funky File Formats&lt;/li&gt;
&lt;li&gt;CAESAR and NORX&lt;/li&gt;
&lt;li&gt;DP5: PIR for Privacy-preserving Presence&lt;/li&gt;
&lt;li&gt;Thunderstrike: EFI bootkits for Apple MacBooks&lt;/li&gt;
&lt;li&gt;The Magical Secrecy Tour&lt;/li&gt;
&lt;li&gt;The Perl Jam: Exploiting a 20 Year-old Vulnerability&lt;/li&gt;
&lt;li&gt;UNHash - Methods for better password cracking&lt;/li&gt;
&lt;li&gt;Googlequiz – 2015er Edition&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;day-4&#34;&gt;Day 4&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;The rise and fall of Internet voting in Norway&lt;/li&gt;
&lt;li&gt;Why are computers so @#!*, and what can we do about it?&lt;/li&gt;
&lt;li&gt;State of the Onion&lt;/li&gt;
&lt;li&gt;Tor: Hidden Services and Deanonymisation&lt;/li&gt;
&lt;li&gt;31C3 Closing Event&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;recommendations&#34;&gt;Recommendations&lt;/h2&gt;
&lt;p&gt;If you don&amp;rsquo;t have time to watch all of them I&amp;rsquo;d recommend to watch:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://media.ccc.de/browse/congress/2014/31c3_-_6571_-_en_-_saal_1_-_201412271130_-_31c3_keynote_-_alecempire.html#video&#34;&gt;31C3 Keynote&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://media.ccc.de/browse/congress/2014/31c3_-_6120_-_en_-_saal_1_-_201412271600_-_practical_emv_pin_interception_and_fraud_detection_-_andrea_barisani.html#video&#34;&gt;Practical EMV PIN interception and fraud detection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://media.ccc.de/browse/congress/2014/31c3_-_6249_-_en_-_saal_1_-_201412271715_-_ss7_locate_track_manipulate_-_tobias_engel.html#video&#34;&gt;SS7: Locate. Track. Manipulate.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://media.ccc.de/browse/congress/2014/31c3_-_5956_-_en_-_saal_2_-_201412281400_-_cyber_necromancy_-_joseph_tartaro_-_matthew_halchyshak.html#video&#34;&gt;Cyber Necromancy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://media.ccc.de/browse/congress/2014/31c3_-_6128_-_en_-_saal_1_-_201412291830_-_thunderstrike_efi_bootkits_for_apple_macbooks_-_trammell_hudson.html#video&#34;&gt;Thunderstrike: EFI bootkits for Apple MacBooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://media.ccc.de/browse/congress/2014/31c3_-_5966_-_en_-_saal_1_-_201412292245_-_unhash_-_methods_for_better_password_cracking_-_tonimir_kisasondi.html#video&#34;&gt;UNHash - Methods for better password cracking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;State of the Onion (No recording yet)&lt;/li&gt;
&lt;li&gt;Try to catch &lt;a href=&#34;http://www.imdb.com/title/tt4044364/&#34;&gt;Citizenfour&lt;/a&gt; at your local cinema&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Push(over) notifications for Gentoo updates</title>
      <link>https://blog.notmyhostna.me/posts/pushover-notifications-for-gentoo-updates/</link>
      <pubDate>Sat, 06 Dec 2014 17:40:38 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/pushover-notifications-for-gentoo-updates/</guid>
      <description>
        
          
        &lt;p&gt;This shell script will send you a push notification if there are new Gentoo updates available. It&amp;rsquo;s based on &lt;a href=&#34;https://twitter.com/ftf&#34;&gt;ftf&lt;/a&gt;&amp;rsquo;s Ruby script for Prowl.&lt;/p&gt;
&lt;script src=&#34;https://gist.github.com/dewey/902a0da58f85feca974a.js&#34;&gt;&lt;/script&gt;

&lt;p&gt;&lt;strong&gt;Application Token&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To get the Application token just create a new application on the Pushover website: &lt;a href=&#34;https://pushover.net/apps/build&#34;&gt;https://pushover.net/apps/build&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;User Token&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;User Key&amp;rdquo; is displayed on your user profile.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cronjob&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add this cronjob and make sure the user has permissions to run the emerge command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0 20 * * * /bin/zsh /root/tools/updatecheck.sh &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Boom!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;update2.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all!&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Automated and encrypted backups with duplicity</title>
      <link>https://blog.notmyhostna.me/posts/automated-and-encrypted-backups-with-duplicity/</link>
      <pubDate>Tue, 02 Dec 2014 21:00:16 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/automated-and-encrypted-backups-with-duplicity/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/automated-and-encrypted-backups-with-duplicity/feature.jpg" width="2000" height="1373"/>]]>
           
        &lt;p&gt;If you don&amp;rsquo;t like ending up like the plane in the header image (Jeff Sheldon, &lt;a href=&#34;https://unsplash.com/&#34;&gt;Unsplash&lt;/a&gt;) you should probably make sure you do have a good backup and restore strategy.&lt;/p&gt;
&lt;p&gt;The goal of this short guide is to have automated, encrypted and incremental backups from one server to another remote server. To achieve this we are going to use &lt;a href=&#34;http://duplicity.nongnu.org/&#34;&gt;duplicity&lt;/a&gt; and it&amp;rsquo;s simplified wrapper &lt;a href=&#34;http://duply.net/&#34;&gt;duply&lt;/a&gt;. There are more detailed guides out there but these are the steps I used and they work for me, the sources used for this guide are linked at the bottom.&lt;/p&gt;
&lt;h2 id=&#34;backup-master&#34;&gt;Backup master&lt;/h2&gt;
&lt;p&gt;This is the machine where we are going to store all the backups from the various remote servers on. I added a new user called &lt;code&gt;backup&lt;/code&gt; for this purpose. If you don&amp;rsquo;t trust the other servers use a different user for each server.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;useradd -m -G users,wheel,audio -s /bin/zsh backup
passwd backup
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All the backups will be stored in it&amp;rsquo;s home directory where we&amp;rsquo;ll now create the following directories and remember the path, we&amp;rsquo;ll need that at a later stage. Make sure you replace &lt;code&gt;&amp;lt;server name&amp;gt;&lt;/code&gt; with something like the hostname of the server you want to backup in that directory so it&amp;rsquo;ll be easier to figure out which backup is stored where if you are using multiple servers.&lt;/p&gt;
&lt;p&gt;A good example would be: &lt;code&gt;/home/backup/incoming-backups/example.com&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/home/backup/incoming-backups/&amp;lt;server name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;backup-slave&#34;&gt;Backup slave&lt;/h2&gt;
&lt;p&gt;This is one of many remote servers we want to backup to the master server.&lt;/p&gt;
&lt;h3 id=&#34;install-dependencies&#34;&gt;Install dependencies&lt;/h3&gt;
&lt;p&gt;The first step is to install the dependencies. There&amp;rsquo;s no stable version available for Gentoo at the moment so you&amp;rsquo;ll have to unmask the latest version by adding &lt;code&gt;app-backup/duply ~amd64&lt;/code&gt; to your &lt;code&gt;package.keywords&lt;/code&gt; file. Once this is done just install it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;emerge -av app-backup/duply app-backup/duplicity
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are using Ubuntu/Debian a simple &lt;code&gt;apt-get install duply&lt;/code&gt; should also grab the other dependencies.&lt;/p&gt;
&lt;h3 id=&#34;first-steps&#34;&gt;First Steps&lt;/h3&gt;
&lt;p&gt;Type &lt;code&gt;duply &amp;lt;server name&amp;gt; create&lt;/code&gt; to initialize a new backup. You should probably run this as the root user if you want to backup directories only accessible by &lt;code&gt;root&lt;/code&gt;. The &lt;code&gt;&amp;lt;server name&amp;gt;&lt;/code&gt; is a placeholder for whatever you want to call your backup set. I usually just use the hostname with no spaces, dots or any special characters.&lt;/p&gt;
&lt;p&gt;This will create a new directory in your home directory containing two files: &lt;code&gt;conf&lt;/code&gt; and &lt;code&gt;exclude&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/root/.duply/&amp;lt;server name&amp;gt;/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;generate-gpg-key&#34;&gt;Generate GPG Key&lt;/h3&gt;
&lt;p&gt;Because we want to encrypt all our backups so we can store them on an untrusted host we need to create a new GPG key. To do that just run &lt;code&gt;gpg --gen-key&lt;/code&gt; and accept the default options except the keylength which I usually set to &lt;code&gt;4096&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll probably see a message like that telling you to generate new entropy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In that case you could run some commands on the server, install updates or just emerge &lt;code&gt;sys-apps/rng-tools&lt;/code&gt; and generate some new entryopy with &lt;code&gt;rngd -r /dev/urandom&lt;/code&gt;. This should usually do the trick.&lt;/p&gt;
&lt;p&gt;Once the key is generated it&amp;rsquo;ll ask you for some information like &amp;ldquo;Full Name&amp;rdquo;, &amp;ldquo;Email&amp;rdquo; and &amp;ldquo;Comment&amp;rdquo;. In my case I use the name of the backup set for the full name, my regular email and the FQDM of the server as the comment. This will make it easier to find the private key for the server later on.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t forget to write down / store the passphrase somewhere safe. We are going to need it for the following step.&lt;/p&gt;
&lt;h3 id=&#34;configuration&#34;&gt;Configuration&lt;/h3&gt;
&lt;p&gt;Now it&amp;rsquo;s time to edit the &lt;code&gt;conf&lt;/code&gt; file to fit out needs. There are a lot of comments in that file explaining the various options so I&amp;rsquo;m just going to go over my settings without explaining all of these.&lt;/p&gt;
&lt;p&gt;Open the &lt;code&gt;conf&lt;/code&gt; file and add / uncomment the following values:&lt;/p&gt;
&lt;h4 id=&#34;gpg_key--gpg_pw&#34;&gt;GPG_KEY &amp;amp; GPG_PW&lt;/h4&gt;
&lt;p&gt;If you don&amp;rsquo;t remember your KEY ID just run: &lt;code&gt;gpg --list-secret-keys&lt;/code&gt; to get a list of all your secret keys in your keychain. The output will look something like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sec   4096R/XXXXXXXX 2014-11-30
uid                  dewey &amp;lt;mail@example.com&amp;gt;
ssb   4096R/YYYYYYYY 2014-11-30
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The X&amp;rsquo;ed value is the GPG_KEY you are looking for, the passphrase is the one you wrote down earlier.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GPG_KEY=&#39;XXXXXXXX&#39;
GPG_PW=&#39;YOURPASSPHRASE&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;gpg_opts&#34;&gt;GPG_OPTS&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;GPG_OPTS=&#39;--compress-algo=bzip2 --personal-cipher-preferences AES256,AES192&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;target&#34;&gt;TARGET&lt;/h4&gt;
&lt;p&gt;There are a lot of options to choose from, pick the one your master server supports.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Backup to Master Server&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TARGET=&#39;rsync://backup@example.com/incoming-backup/&amp;lt;server name&amp;gt;&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Backup to Google Drive (with PyDrive)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the new and working method, please follow this guide:
&lt;a href=&#34;https://blog.notmyhostna.me/duplicity-with-pydrive-backend-for-google-drive/&#34;&gt;https://blog.notmyhostna.me/duplicity-with-pydrive-backend-for-google-drive/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;del&gt;&lt;strong&gt;Backup to Google Drive (with gdata)&lt;/strong&gt;&lt;/del&gt; [Deprecated due to Google API changes]&lt;/p&gt;
&lt;p&gt;If you want to store your backups in your Google Drive just install the API library via &lt;code&gt;dev-python/gdata&lt;/code&gt; and add the Google Drive target. The &lt;code&gt;user&lt;/code&gt; is the part in front of the @ of your Google (Apps) email address, the password your the one you are using for that account. The path you specify after the domain part will be created automatically.&lt;/p&gt;
&lt;p&gt;If you are using Gentoo make sure to switch your Python interpreter to &lt;code&gt;python2.7&lt;/code&gt; (by using &lt;code&gt;eselect python&lt;/code&gt;), 3.x is not supported by the gdata library yet.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TARGET=&#39;gdocs://user:password@example.com/backup-incoming/notmyhostna.me&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;source&#34;&gt;SOURCE&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;SOURCE=&#39;/&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;manual-exclude-parameters&#34;&gt;Manual exclude parameters&lt;/h4&gt;
&lt;p&gt;If you want to manually ignore directories you can just create a &lt;code&gt;.duplicity-ignore&lt;/code&gt; file in that directory and it won&amp;rsquo;t be included in the backup. This is a good option if you want to back up the entire &lt;code&gt;/home/&lt;/code&gt; directory but not the directory of temporary files in your own home directory.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;FILENAME=&#39;.duplicity-ignore&#39;
DUPL_PARAMS=&amp;quot;$DUPL_PARAMS --exclude-if-present &#39;$FILENAME&#39;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;backup-history&#34;&gt;Backup History&lt;/h4&gt;
&lt;p&gt;With these parameters you&amp;rsquo;ll be able to define how many full or incremental backups will be kept. You should read the documentation / comments and make sure it fits your environment.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MAX_AGE=1M
MAX_FULL_BACKUPS=2
MAX_FULLS_WITH_INCRS=1
MAX_FULLBKP_AGE=2M
DUPL_PARAMS=&amp;quot;$DUPL_PARAMS --full-if-older-than $MAX_FULLBKP_AGE &amp;quot;
VOLSIZE=50
DUPL_PARAMS=&amp;quot;$DUPL_PARAMS --volsize $VOLSIZE &amp;quot;
VERBOSITY=5
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;exclude&#34;&gt;Exclude&lt;/h4&gt;
&lt;p&gt;The other important file is called &lt;code&gt;exclude&lt;/code&gt; and it defines the directories included or excluded from your backup. It&amp;rsquo;s very simple:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- /etc/.git/
+ /etc/
+ /home/user2/imporant.txt
+ /home/dewey/
+ /var/www/
+ /root/.duply/
- **
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every line starting with &lt;code&gt;+&lt;/code&gt; will be included in the backup, everything with &lt;code&gt;-&lt;/code&gt; will be skipped. &lt;code&gt;- **&lt;/code&gt; will exclude everything not matched by the parent rules. The order matters so make sure you don&amp;rsquo;t exclude &lt;code&gt;/home/someuser/&lt;/code&gt; and later on add &lt;code&gt;/home/someuser/coup.txt&lt;/code&gt; - it won&amp;rsquo;t be included that way.&lt;/p&gt;
&lt;h4 id=&#34;public-key-authentification&#34;&gt;Public Key Authentification&lt;/h4&gt;
&lt;p&gt;We want to be able to log into the master server without entering our password so the backup task will be able to run automatically in the background. We achieve that by copying our public key (&lt;code&gt;id_rsa.pub&lt;/code&gt; to the remote server&amp;rsquo;s &lt;code&gt;authorized_keys&lt;/code&gt; file. Luckily there&amp;rsquo;s an easy way to do just that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-copy-id -i ~/.ssh/id_rsa.pub backup@example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enter your password one last time and we are set. Try to login via ssh to see if it works and if you don&amp;rsquo;t have to enter the password again we succeeded.&lt;/p&gt;
&lt;h4 id=&#34;first-backup&#34;&gt;First Backup&lt;/h4&gt;
&lt;p&gt;If you want to see the available duply commands just use &lt;code&gt;duply usage&lt;/code&gt;. In our case we are going to use:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;duply &amp;lt;server name&amp;gt; backup
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;for the first full backup. From now on just use&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;duply &amp;lt;server name&amp;gt; incr
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to trigger incremental backups. If you want to see the list of backups stored on the remote host use &lt;code&gt;duply &amp;lt;server name&amp;gt; status&lt;/code&gt; and you&amp;rsquo;ll see something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Found primary backup chain with matching signature chain:
-------------------------
Chain start time: Sun Nov 30 21:12:22 2014
Chain end time: Tue Dec  2 00:00:04 2014
Number of contained backup sets: 5
Total number of contained volumes: 10
 Type of backup set:                            Time:      Num volumes:
                Full         Sun Nov 30 21:12:22 2014                 1
         Incremental         Sun Nov 30 21:16:34 2014                 1
         Incremental         Sun Nov 30 21:53:00 2014                 6
         Incremental         Mon Dec  1 00:00:03 2014                 1
         Incremental         Tue Dec  2 00:00:04 2014                 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The first backup also exported the private and public gpg keys to the &lt;code&gt;~/.duply/&amp;lt;server name&amp;gt;&lt;/code&gt; directory. Please don&amp;rsquo;t skip the section called &amp;ldquo;Restore&amp;rdquo; at the end of the guide. We are going to deal with these files there.**&lt;/p&gt;
&lt;h4 id=&#34;automation&#34;&gt;Automation&lt;/h4&gt;
&lt;p&gt;Nobody likes to do things manually so we are going to tell cronjob to do all the heavy lifting for us. Use &lt;code&gt;crontab -e&lt;/code&gt; to view your available cronjobs and add:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0	0	*	*	7	/usr/bin/duply /root/.duply/&amp;lt;server name&amp;gt; full_verify_purge --force
0	0	*	*	1-6	/usr/bin/duply /root/.duply/&amp;lt;server name&amp;gt; incr
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;include-mysql-databases&#34;&gt;Include (mySQL) Databases&lt;/h4&gt;
&lt;p&gt;If you want to backup mySQL databases too you&amp;rsquo;ll have to grab a database dump, move it to some location included in your &lt;code&gt;exclude&lt;/code&gt; file and clean up that location after the backup. Duply got us covered there.&lt;/p&gt;
&lt;p&gt;Just create a file called &lt;code&gt;post&lt;/code&gt; and &lt;code&gt;pre&lt;/code&gt; in your &lt;code&gt;.duply/&amp;lt;server name&amp;gt;/&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;pre&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/usr/bin/mysqldump --all-databases -u root -pXXXXXXXX | gzip -9 &amp;gt; /var/backups/sql/sqldump_$(date +&amp;quot;%d-%m-%Y&amp;quot;).sql.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;post&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/bin/rm /var/backups/sql/sqldump_$(date +&amp;quot;%d-%m-%Y&amp;quot;).sql.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If your dump takes a long time make sure the timestamps are still covered by your &lt;code&gt;post&lt;/code&gt; command and the archives don&amp;rsquo;t build up in that directory.&lt;/p&gt;
&lt;p&gt;Once you created these don&amp;rsquo;t forget to add that directory to your &lt;code&gt;exclude&lt;/code&gt; file like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+ /var/backups/sql/
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;restore&#34;&gt;Restore&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Important: After the first backup make sure to copy the whole .duply directory to some place safe. It&amp;rsquo;ll now include your private key.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Your &lt;code&gt;~/.duply/&amp;lt;server name&amp;gt;&lt;/code&gt; directory should now contain your config files and the public and private encryption key. It&amp;rsquo;s very important to store this directory somewhere safe. If you don&amp;rsquo;t have access to this directory it won&amp;rsquo;t be possible to restore and decrypt the backup.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.
├── conf
├── exclude
├── gpgkey.XXXXXXXX.pub.asc
├── gpgkey.XXXXXXXX.sec.asc
├── post
└── pre
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you don&amp;rsquo;t have a way to transfer &lt;code&gt;scp&lt;/code&gt; this to a safe place just encrypt it, move it to a public directory and download it.&lt;/p&gt;
&lt;p&gt;Generate a password:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;openssl rand -base64 32
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create an archive:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tar cvzf duply-&amp;lt;server name&amp;gt;.tar.gz .duply
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Encrypt it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;openssl enc -aes-256-cbc -salt -in duply-&amp;lt;server name&amp;gt;.tar.gz -out duply-&amp;lt;server name&amp;gt;.tar.gz.enc -k &amp;lt;your password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Decrypt it on the target machine:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;openssl enc -d -aes-256-cbc -in duply-&amp;lt;server name&amp;gt;.tar.gz.enc -out duply-&amp;lt;server name&amp;gt;.tar.gz -k &amp;lt;your password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to store the private key in the keychain on your main machine just import &lt;code&gt;gpgkey.XXXXXXXX.sec.asc&lt;/code&gt; to &lt;a href=&#34;https://gpgtools.org/&#34;&gt;GPG Keychain&lt;/a&gt; (Mac only) or do it via the command line:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gpg --allow-secret-key-import --import gpgkey.XXXXXXXX.sec.asc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&amp;rsquo;ll now show up if you run &lt;code&gt;gpg --list-secret-keys&lt;/code&gt; on that machine.&lt;/p&gt;
&lt;p&gt;Now if you want to restore a server just install duply and duplicity on the new machine, restore the &lt;code&gt;.duply&lt;/code&gt; directory, set up the public key authentication and use the following commands:&lt;/p&gt;
&lt;p&gt;Restore a single file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;duply &amp;lt;profile&amp;gt; fetch &amp;lt;src_path&amp;gt; &amp;lt;target_path&amp;gt; [&amp;lt;age&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restore a directory:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;duply &amp;lt;profile&amp;gt; restore &amp;lt;target_path&amp;gt; [&amp;lt;age&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The default value for &lt;code&gt;&amp;lt;age&amp;gt;&lt;/code&gt; is &lt;code&gt;$now&lt;/code&gt;, but you may also enter values like &lt;code&gt;1M&lt;/code&gt; or &lt;code&gt;10H&lt;/code&gt;, depends on how frequently your backups run.&lt;/p&gt;
&lt;h2 id=&#34;optional&#34;&gt;Optional&lt;/h2&gt;
&lt;p&gt;If you want to take this to the next level and also backup your backup master server you could use something like Tarsnap which I already wrote about some time ago: &lt;a href=&#34;https://blog.notmyhostna.me/backup-your-server-with-tarsnap/&#34;&gt;Backup your server with Tarsnap&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it!&lt;/p&gt;
&lt;h2 id=&#34;sources&#34;&gt;Sources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.thomas-krenn.com/en/wiki/Backup_on_Linux_with_duply&#34;&gt;thomas-krenn.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://duplicity.nongnu.org/&#34;&gt;duplicity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://duply.net/wiki/index.php/Duply-documentation&#34;&gt;duply Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://raymii.org/s/tutorials/Website-and-database-backup-with-Duplicity.html&#34;&gt;raymii.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Calculate total filesize of multiple torrent files</title>
      <link>https://blog.notmyhostna.me/posts/calculate-total-filesize-of-multiple-torrent-files/</link>
      <pubDate>Thu, 06 Nov 2014 22:10:00 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/calculate-total-filesize-of-multiple-torrent-files/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/calculate-total-filesize-of-multiple-torrent-files/feature.jpg" width="1732" height="1154"/>]]>
           
        &lt;p&gt;Quick script which lets you check if you have enough storage space to download all these sweet Linux distributions you already grabbed the &lt;code&gt;.torrent&lt;/code&gt; file for. Nested directories (&lt;em&gt;*cough*&lt;/em&gt; collages) are no problem.&lt;/p&gt;
&lt;h3 id=&#34;usage&#34;&gt;Usage&lt;/h3&gt;
&lt;p&gt;Install dependencies listed in the script, create a directory called &lt;code&gt;torrent&lt;/code&gt; or just customize the path in the script and then run &lt;code&gt;node app.js&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;output&#34;&gt;Output&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;RatioHit|⇒ node app.js
Total size:
694263227494 bytes
662101 MB
647 GB
Number of Torrents: 1728
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;script&#34;&gt;Script&lt;/h3&gt;
&lt;script src=&#34;https://gist.github.com/dewey/e96e4cd80d2a8033eb10.js&#34;&gt;&lt;/script&gt;


      </description>
    </item>
    
    <item>
      <title>ScreenUpload: Automatically upload screenshots with scp</title>
      <link>https://blog.notmyhostna.me/posts/screenupload-automatically-upload-screenshots-with-scp/</link>
      <pubDate>Thu, 06 Nov 2014 18:15:47 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/screenupload-automatically-upload-screenshots-with-scp/</guid>
      <description>
        
          
        &lt;p&gt;&lt;img src=&#34;https://img.notmyhostna.me/047df78a4eac436396d9f6b0957c0a8ddfc198b6.png&#34; alt=&#34;notification&#34;&gt;&lt;/p&gt;
&lt;p&gt;There are a lot of scripts and applications out there acomplishing the same task, most of them are probably more polished than what I came up with, but there was always something missing which made me switch back to some old unmaintained PrefPane called &amp;ldquo;ScreenGrab&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Unfortunately it was FTP only and I wasn&amp;rsquo;t really keen on running an ftpd on my server any more.&lt;/p&gt;
&lt;p&gt;My &lt;a href=&#34;https://news.ycombinator.com/item?id=8039708&#34;&gt;requirements&lt;/a&gt; were (and still are):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simple and lightweight&lt;/li&gt;
&lt;li&gt;Retina ready&lt;/li&gt;
&lt;li&gt;Using the default Mac OS screenshot shortcuts&lt;/li&gt;
&lt;li&gt;Moving screenshots from the default location (Desktop) to a specified directory or deleting them after a successful upload&lt;/li&gt;
&lt;li&gt;sFTP / SCP upload using public keys located in ~/.ssh&lt;/li&gt;
&lt;li&gt;Uploading to my own server, no third party service&lt;/li&gt;
&lt;li&gt;Editing features are not needed&lt;/li&gt;
&lt;li&gt;Keep history of past uploads&lt;/li&gt;
&lt;li&gt;Direct link in clipboard (&lt;a href=&#34;https://example.com/example.png&#34;&gt;https://example.com/example.png&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A long and not easy to guess unique filename.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Like the comment in that thread suggests most of this would be possible with Automator but where&amp;rsquo;s the fun in that.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know what took me that long but I wrote a simple tool powered by Node.JS doing just that.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/VErKWU0.gif&#34; alt=&#34;ScreenUpload&#34;&gt;&lt;/p&gt;
&lt;p&gt;Grab it here: &lt;a href=&#34;https://github.com/dewey/ScreenUpload&#34;&gt;ScreenUpload&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the future I&amp;rsquo;m planning on adding a simple web interface running on the remote server which should make it easier to delete screenshots, search for screenshots from a specific time range or just browse the archive. Another neat feature would be drag-to-upload on the web interface.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Backup ZNC Logs automatically</title>
      <link>https://blog.notmyhostna.me/posts/backup-znc-logs-automatically/</link>
      <pubDate>Tue, 19 Aug 2014 18:54:02 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/backup-znc-logs-automatically/</guid>
      <description>
        
          
        &lt;p&gt;This is a short script to automatically backup the ZNC logs from multiple remote servers to a local directory.&lt;/p&gt;
&lt;p&gt;If you want to run it on a system which isn&amp;rsquo;t Mac OS you&amp;rsquo;ll probably have to tweak a few things. Especially the lines containing &lt;code&gt;terminal-notifier&lt;/code&gt; because they make use of the Mac OS notification center. Just replace them with &lt;code&gt;echo&lt;/code&gt; statements or a similar notification framework for your operating system.&lt;/p&gt;
&lt;h2 id=&#34;the-script&#34;&gt;The script&lt;/h2&gt;
&lt;script src=&#34;https://gist.github.com/dewey/d2f364a60e4384b8d44e.js&#34;&gt;&lt;/script&gt;

&lt;h3 id=&#34;dependencies&#34;&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;To get the notifications to the notification center install you&amp;rsquo;ll have to install terminal-notifier. You can grab it from &lt;a href=&#34;https://github.com/alloy/terminal-notifier&#34;&gt;Github&lt;/a&gt; or install it via Homebrew.&lt;/p&gt;
&lt;h3 id=&#34;get-the-script&#34;&gt;Get the script&lt;/h3&gt;
&lt;p&gt;Download the script and make it executable.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git clone https://gist.github.com/d2f364a60e4384b8d44e.git backup-znc-logs
chmod +x backup-znc-logs/backup-znc-logs.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open the script and edit the line which defines the &lt;code&gt;SCRIPT_HOME&lt;/code&gt;. That&amp;rsquo;s the directory where you&amp;rsquo;ll create subdirectories for the various servers. In our case we&amp;rsquo;ll create a directory called &amp;ldquo;notmyhostna.me&amp;rdquo; and &amp;ldquo;example.com&amp;rdquo; because these are the two servers we want to back up.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd ~/Documents/Textual\ Logs/ZNC/
mkdir notmyhostna.me
mkdir example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;create-config-files&#34;&gt;Create config files&lt;/h3&gt;
&lt;p&gt;Now it&amp;rsquo;s time to create a config file to tell the script where it should grab the files from and where to store them. We do this by creating an invisible file called &lt;code&gt;.config-backup&lt;/code&gt; in the server directory.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;vim ~/Documents/Textual\ Logs/ZNC/notmyhostna.me/.config-backup
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add these lines and costomize them to your needs. (You don&amp;rsquo;t have to copy the comments) Make sure not to excape the spaces in the path names because rsync doesn&amp;rsquo;t like this.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# The name of the server which is used in notifications.
SERVERNAME=&amp;quot;notmyhostna.me&amp;quot;

# The name of the file where we store the timestamp of the last backup. Just in case you feel like changing it. You probably won&#39;t have to change this.
TIMESTAMP_FILE=&amp;quot;.last-backup&amp;quot;

# The path and username of the remote server where the logs are stored
PATH_REMOTE=&amp;quot;dewey@notmyhostna.me:/home/dewey/.znc/users/dewey/moddata/log/&amp;quot;

# The path the logs should be synced to on the machine the script is running from. `${HOME}` is used instead of `~`.
PATH_LOCAL=&amp;quot;${HOME}/Documents/Textual Logs/ZNC/notmyhostna.me/&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You have to create a file like this for every server you want to backup. For this to work it&amp;rsquo;s required that you are using ssh keys and not passwords.&lt;/p&gt;
&lt;h3 id=&#34;run-the-script&#34;&gt;Run the script&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Note: Per default the script will only create a backup every 24h. If you want to change that search for the value &lt;code&gt;86400&lt;/code&gt; and change that to something you prefer.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you run the script and the last backup isn&amp;rsquo;t older than 24h the output you&amp;rsquo;ll see looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Scripts|⇒ ./backup-znc-logs.sh
example.com : Last backup &amp;lt; 24h old. Do nothing.
notmyhostna.me : Last backup &amp;lt; 24h old. Do nothing.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to automatically run the script you could use something like this:
&lt;a href=&#34;http://stackoverflow.com/questions/9522324/running-python-in-background-on-os-x/9523030#9523030&#34;&gt;http://stackoverflow.com/questions/9522324/running-python-in-background-on-os-x/9523030#9523030&lt;/a&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Setting up a new Munin slave node</title>
      <link>https://blog.notmyhostna.me/posts/setting-up-a-new-munin-slave-node/</link>
      <pubDate>Fri, 11 Jul 2014 20:06:44 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/setting-up-a-new-munin-slave-node/</guid>
      <description>
        
          
        &lt;p&gt;Filing this away for future reference.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Install munin from package sources&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt-get install munin-node
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Add master node to allowed IPs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;vim etc/munin/munin-node.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately it&amp;rsquo;s only allowed to add IPs and not hostname. The format you&amp;rsquo;ll have to follow is:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;allow ^xxx\.xxx\.xxx\.xxx$&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Clone the official plugin repository&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We are going to clone the repository with the latest third-party plugins to &lt;code&gt;/etc/munin/plugins-get&lt;/code&gt;. Once you&amp;rsquo;ve done this just symlink the plugins you want to use into Munin&amp;rsquo;s plugin directory. This also makes it very easy to update.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git clone https://github.com/munin-monitoring/contrib.git /etc/munin/plugins-git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example we are going to symlink a plugin which accepts an additional parameter. In our case the network interface on this OpenVZ server.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ln -s /etc/munin/plugins-git/plugins/network/vnstat_ /etc/munin/plugins/vnstat_venet0
&lt;/code&gt;&lt;/pre&gt;

      </description>
    </item>
    
    <item>
      <title>Nginx, Wildcard SSL and Subdomains</title>
      <link>https://blog.notmyhostna.me/posts/nginx-wildcard-ssl-and-subdomains/</link>
      <pubDate>Tue, 10 Jun 2014 16:29:01 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/nginx-wildcard-ssl-and-subdomains/</guid>
      <description>
        
          
        &lt;p&gt;I just setup SSL on all my &lt;code&gt;*.notmyhostna.me&lt;/code&gt; domains and here&amp;rsquo;s how I did it.&lt;/p&gt;
&lt;h2 id=&#34;buy-certificate&#34;&gt;Buy certificate&lt;/h2&gt;
&lt;p&gt;First you need to buy a wildcard certificate, I bought one from &lt;a href=&#34;https://cheapsslsecurity.com/&#34;&gt;cheapsslsecurity.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to secure subdomains you&amp;rsquo;ll need to spend a little bit more and go for one of their wildcard certificates listed under the &amp;ldquo;Secure Sub-Domains&amp;rdquo; section. I went for the cheapest one, costing me ~130$ for two years, which is reasonable.&lt;/p&gt;
&lt;p&gt;During the checkout process they ask you for your &amp;ldquo;CSR&amp;rdquo; - and that&amp;rsquo;s what we are going to give them. Because we are now going to generate a bunch of files and want to store them all in our nginx directory we are going to create a new directory in the nginx directory called &lt;code&gt;ssl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Navigate to your nginx directory usually located at &lt;code&gt;/etc/nginx/&lt;/code&gt; and create a new subfolder called &lt;code&gt;ssl&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In public key infrastructure (PKI) systems, a certificate signing request (also CSR or certification request) is a message sent from an applicant to a certificate authority in order to apply for a digital identity certificate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To generate the CSR and your private key run the following command while being located at &lt;code&gt;/etc/nginx/ssl&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;openssl req -nodes -newkey rsa:2048 -keyout notmyhostna.me.key -out notmyhostna.me.csr
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;During this process the key tool will ask you for some information:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Country Name (2 letter code) [AU]: AT
...
Common Name (e.g. server FQDN or YOUR name) []: *.notmyhostna.me                     
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The important part here is to set the Common Name to &lt;code&gt;*.notmyhostna.me&lt;/code&gt;. This will allow us to use this certificate for multiple subdomains in the future.&lt;/p&gt;
&lt;p&gt;The result of this step will be two files called &lt;code&gt;notmyhostna.me.csr&lt;/code&gt; and &lt;code&gt;notmyhostna.me.key&lt;/code&gt; in your current directory. Now open the csr file and copy/paste the content into cheapsslsecurity&amp;rsquo;s CSR form.&lt;/p&gt;
&lt;p&gt;I wish I&amp;rsquo;d be kidding when I tell you the mail looks like some cheap phishing mail but it does. With broken images and everything.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;screen1.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The Comodo site where it&amp;rsquo;s redirecting you isn&amp;rsquo;t any better so get used to it:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;blah.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The next mail you&amp;rsquo;ll get is one with an attached zip file containing the root certificates and your purchased wildcard certificate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Root CA Certificate - AddTrustExternalCARoot.crt&lt;/li&gt;
&lt;li&gt;Intermediate CA Certificate - PositiveSSLCA2.crt&lt;/li&gt;
&lt;li&gt;Your PositiveSSL Wildcard Certificate - STAR_notmyhostna_me.crt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Transfer this zip file to your server, unzip it and move the files to your &lt;code&gt;ssl&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;Build the certificate chain for nginx with the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat STAR_notmyhostna_me.crt PositiveSSLCA2.crt AddTrustExternalCARoot.crt &amp;gt;&amp;gt; notmyhostna.me.crt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(The order matters, so don&amp;rsquo;t get creative here)&lt;/p&gt;
&lt;p&gt;Now we are going to setup nginx. Create another child directory called &lt;code&gt;/etc/nginx/ssl/notmyhostna.me&lt;/code&gt; and move &lt;code&gt;notmyhostna.me.crt&lt;/code&gt; and &lt;code&gt;notmyhostna.me.key&lt;/code&gt; to this directory. These are the only files nginx will need.&lt;/p&gt;
&lt;h2 id=&#34;nginx&#34;&gt;Nginx&lt;/h2&gt;
&lt;p&gt;I usually have one main config file for every domain, and multiple sub configurations for the subdomains. I think it makes dealing with multiple configurations for the different subdomains easier than having one massive file containing everything.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The &amp;ldquo;main&amp;rdquo; configuration file&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server {
    listen  443 default_server ssl;
    # _; is used for the default vHost
    server_name         _;

    ssl_certificate     /etc/nginx/ssl/notmyhostna.me/notmyhostna.me.crt;
    ssl_certificate_key /etc/nginx/ssl/notmyhostna.me/notmyhostna.me.key;

    ssl_session_cache    shared:SSL:10m;
    ssl_session_timeout  10m;

    # Perfect Forward Security
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers &amp;quot;EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS +RC4 RC4&amp;quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to read a more in-depth description of these options follow this link: &lt;a href=&#34;http://axiacore.com/blog/enable-perfect-forward-secrecy-nginx/&#34;&gt;http://axiacore.com/blog/enable-perfect-forward-secrecy-nginx/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s our main server block listening on the SSL port 443. It&amp;rsquo;ll use the SSL settings we defined in the server block above (The &amp;ldquo;default&amp;rdquo; server). Add this to the same file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server {
    listen      443;
    server_name notmyhostna.me;

    error_log   /var/log/nginx/notmyhostna.me.error.ssl.log;
    access_log  /var/log/nginx/notmyhostna.me.access.ssl.log;

    root /var/www/notmyhostna.me/;
    index index.html;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to redirect all requests on port 80 to the SSL version add another server block with a redirect to the same file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server {
    listen      80;
    server_name notmyhostna.me;
    rewrite     ^   https://$server_name$request_uri? permanent;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;A configuration file for a subdomain&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This configuration file will still use our default server we setup in the main file that&amp;rsquo;s why we just need our regular server blocks here. Ignore the &lt;code&gt;proxy_&lt;/code&gt; settings, they are just used for this blog because it&amp;rsquo;s using nginx as a reverse proxy for the NodeJS backend.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server {
    listen      443;
    server_name blog.notmyhostna.me;

    error_log   /var/log/nginx/blog.notmyhostna.me.error.ssl.log;
    access_log  /var/log/nginx/blog.notmyhostna.me.access.ssl.log;

    root /var/www/blog.notmyhostna.me/;
    index index.html;

    location / {
        proxy_pass http://localhost:2368/;
        proxy_set_header Host $host;
        proxy_buffering off;
        autoindex  off;
    }
}

server {
    listen      80;
    server_name blog.notmyhostna.me;
    rewrite     ^   https://$server_name$request_uri? permanent;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, after enabling the sites (symlinking from &lt;code&gt;sites-available&lt;/code&gt; to &lt;code&gt;sites-enabled&lt;/code&gt;) use &lt;code&gt;nginx -t&lt;/code&gt; to check if there are any errors in the config and if there are none restart nginx and your sites should be available on https.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Optional last step is to check your SSL setup via &lt;a href=&#34;https://www.ssllabs.com/ssltest/analyze.html&#34;&gt;SSL Labs Server Test&lt;/a&gt; &amp;hellip; &lt;em&gt;zwecks da security warads gwesen.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This setup should result in an &lt;code&gt;A&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Further links if you want to know why things are done this way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://serverfault.com/questions/548938/multiple-ssl-vhosts-using-wildcard-certificate-in-nginx/548942#548942&#34;&gt;http://serverfault.com/questions/548938/multiple-ssl-vhosts-using-wildcard-certificate-in-nginx/548942#548942&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-certificate-on-nginx-for-ubuntu-12-04&#34;&gt;https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-certificate-on-nginx-for-ubuntu-12-04&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Atlas of the Conflict</title>
      <link>https://blog.notmyhostna.me/posts/atlas-of-the-conflict/</link>
      <pubDate>Tue, 15 Apr 2014 13:31:19 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/atlas-of-the-conflict/</guid>
      <description>
        
          
        &lt;p&gt;The &lt;a href=&#34;http://www.atlasoftheconflict.com/&#34;&gt;Atlas of the Conflict&lt;/a&gt; is a beautiful book containing over 500 maps and diagrams providing both a great overview and very detailed information about the Israeli-Palestinian conflict.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;DSCN0690.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The author of the book is Malkit Shoshan and the design was done by &lt;a href=&#34;http://www.grootens.nl/2/10/11/881.html&#34;&gt;Joost Grootens&lt;/a&gt; who also designed a lot of &lt;a href=&#34;http://www.grootens.nl/2/10/11.html&#34;&gt;other&lt;/a&gt; atlases like the &lt;a href=&#34;http://www.grootens.nl/2/10/11/3.html&#34;&gt;Metropolitan World Atlas&lt;/a&gt;, compiling interesting facts about different metropolises through an easy to grasp system of orange dots.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;DSCN0695.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;DSCN0693.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;DSCN0696.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Mass renaming files - now with more Vim!</title>
      <link>https://blog.notmyhostna.me/posts/mass-renaming-files-now-with-more-vim/</link>
      <pubDate>Fri, 04 Apr 2014 14:02:59 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/mass-renaming-files-now-with-more-vim/</guid>
      <description>
        
          
        &lt;p&gt;As it happens you sometimes end up with a bunch of files which you would rather rename to something else and it&amp;rsquo;d be pretty sweet to just rename them like you would search and replace strings while working with Vim. Guess what, there&amp;rsquo;s a tool just like that and it&amp;rsquo;s fittingly called &lt;a href=&#34;https://github.com/laurent22/massren&#34;&gt;massren&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The instructions on how to install this tool are on the Github page of the project. If you are on a Mac just use homebrew as usual.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew tap laurent22/massren
brew install massren
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will tap a specialized repository because it&amp;rsquo;s not in the main Homebrew formulas (yet?). One of the main dependencies is &lt;code&gt;go&lt;/code&gt; so this will probably take a minute to install.&lt;/p&gt;
&lt;p&gt;Now just tell massren to use Vim as the default editor with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;massren --config editor &amp;quot;vim&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are already familiar with string manipulation in Vim you already know how to rename files with massren.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The working directory:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;demo|⇒ ls
blah0.txt~ blah2.txt~ blah3.txt~ blah4.txt~
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Navigate to the directory where your files are located and type &lt;code&gt;massren&lt;/code&gt;. It&amp;rsquo;ll open the regular Vim editor and you will see a list of all the files in the directory.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;125177e5_0e7e_45f6_9b14_e56446b113a2.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Our goal is to remove all these nasty &lt;code&gt;~&lt;/code&gt; from the filename of these automatically created backup files.&lt;/p&gt;
&lt;p&gt;Now we are just going to use Vim expression we are all familiar with already. If you are not there&amp;rsquo;s a &lt;a href=&#34;http://vim.wikia.com/wiki/Search_and_replace&#34;&gt;wiki&lt;/a&gt; explaining the various expressions.&lt;/p&gt;
&lt;p&gt;Just type the following expression (Don&amp;rsquo;t forget to escape the tilde) and confirm by pressing &lt;code&gt;Return&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:%s/txt\~/txt/g
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;2a1c4d75_c8bb_4f7b_abd5_bdbc92a46fe6_1.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you see something like &amp;ldquo;4 substitutions on 4 lines&amp;rdquo; it worked. Now we just have to save our &amp;ldquo;file&amp;rdquo; like we always do. Use &lt;code&gt;:wq&lt;/code&gt; to save and quit Vim.&lt;/p&gt;
&lt;p&gt;The output should look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    demo|⇒ ls
    blah0.txt~ blah2.txt~ blah3.txt~ blah4.txt~
    demo|⇒ massren
    massren: Waiting for file list to be saved... (Press Ctrl + C to abort)
    demo|⇒ ls
    blah0.txt blah2.txt blah3.txt blah4.txt
    demo|⇒
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No &lt;code&gt;~&lt;/code&gt;. Perfect!&lt;/p&gt;
&lt;p&gt;The End.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Recover photos from storage devices</title>
      <link>https://blog.notmyhostna.me/posts/recover-photos-from-storage-devices/</link>
      <pubDate>Tue, 25 Mar 2014 19:49:32 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/recover-photos-from-storage-devices/</guid>
      <description>
        
          
        &lt;p&gt;Today I got asked if I could recover some photos from an accidentally formatted CompactFlash memory card. I knew about &lt;a href=&#34;http://www.cgsecurity.org/wiki/TestDisk&#34;&gt;TestDisk&lt;/a&gt; already because I used it in the past to recover some files from corrupted harddisks but I was looking for another, easier tool for the task.&lt;/p&gt;
&lt;p&gt;I wasn&amp;rsquo;t able to find anything free and decent looking so I went back and gave TestDisk another look. Browsing their wiki I stumbled upon &lt;a href=&#34;http://www.cgsecurity.org/wiki/PhotoRec&#34;&gt;PhotoRec&lt;/a&gt; which is a tool dedicated for the exact task I was going to need it for. And the best part: It already ships with TestDisk per default.&lt;/p&gt;
&lt;p&gt;If you are using homebrew (and you should!) just install it with a quick and painless&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew install testdisk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we are ready to use it.&lt;/p&gt;
&lt;p&gt;If you are not a homebrew fan just download the version for your operating system from the &lt;a href=&#34;http://www.cgsecurity.org/wiki/TestDisk_Download&#34;&gt;downloads page&lt;/a&gt; and unpack it with double click or&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tar -xvf testdisk-x.xx.mac_intel.tar.bz2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Navigate to the directory and run it with &lt;code&gt;sudo ./photorec&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you have installed it with homebrew get yourself a new and shiny terminal window and run &lt;code&gt;sudo photorec&lt;/code&gt;. It&amp;rsquo;ll prompt for your password. After that you&amp;rsquo;ll see an interface like the following:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;6ab97763_e879_4aff_8bb0_ed1465b0fee4.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now just select the disk you want to recover files from, navigate with the arrow keys and proceed with &lt;code&gt;Enter&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Select the partition you want to recover files from and proceed with &lt;code&gt;Enter&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;40d13c62_e428_4af3_83a5_345ad117f1f6.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;In the next step you&amp;rsquo;ll have to select the filesystem type. If it&amp;rsquo;s a memory card for a camera it&amp;rsquo;s usually &lt;code&gt;Other&lt;/code&gt;. Proceed with &lt;code&gt;Enter&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Screen_Shot_2014_03_25_at_21_27_12.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The next step will ask you which strategy the tool is going to use. Just searching the free space or everything. Select &lt;code&gt;Whole&lt;/code&gt; and continue with &lt;code&gt;Enter&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once we have done that we&amp;rsquo;ll have to choose the location where PhotoRec is restoring the files to. Navigate through your file system and press &lt;code&gt;C&lt;/code&gt; and the restore process will start. It&amp;rsquo;ll look like this and will take quite some time, depending on how much storage it needs to go through.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;9779ad88_ad59_4aa8_9ba5_39f24e50af2a.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The displayed ETA is usually pretty accurate. Once this is done it&amp;rsquo;ll display a summary on how many files it was able to recover.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll find all your restored files in a directory called &lt;code&gt;recup_dir.x&lt;/code&gt; in the destination directory you specified in the previous step.&lt;/p&gt;
&lt;p&gt;The End.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Have you ever heard of Austria? - Kangaroo!</title>
      <link>https://blog.notmyhostna.me/posts/have-you-ever-heard-of-austria-kangaroo/</link>
      <pubDate>Tue, 25 Mar 2014 18:55:10 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/have-you-ever-heard-of-austria-kangaroo/</guid>
      <description>
        
          
        &lt;p&gt;Sometimes I interview people on IRC and one of the questions I&amp;rsquo;m asking is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Have you ever heard of Austria? If you have, what are the first three words that come to your mind?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Because I have text files (IRC logs) of all these conversations it almost asks for being analysed so we&amp;rsquo;ll use some basic shell scripting to extract the relevant lines from the logs. It&amp;rsquo;s not trivial to automize that because the way the answers are given is in no way uniform. Instead we are just going to grab the whole section and manually clean out the irrelevant answers to the other questions.&lt;/p&gt;
&lt;p&gt;Once we have a list of words which looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;schnitzel
AKG
red, white
Vienna
German, Europe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&amp;rsquo;ll just going to use &lt;code&gt;tr&lt;/code&gt; to do some basic text analysis:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat answers.txt | tr -d &#39;[:punct:]&#39; | tr &#39; &#39; &#39;\n&#39; | tr &#39;A-Z&#39; &#39;a-z&#39; | sort | uniq -c | sort -rn
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We are removing the punctuation, replace whitespace with a linebreak, convert everything to lowercase, sort alphabetically, filter out dupes and in the last step we are going to reverse the sort order and display the numeric value (The frequency) of the string.&lt;/p&gt;
&lt;p&gt;Sometimes you don&amp;rsquo;t want to split the lines if there&amp;rsquo;s a space between the words; use the following command in that case:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat answers.txt | tr &#39;A-Z&#39; &#39;a-z&#39; | sort | uniq -c | sort -rn
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The end result should look something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;10 vienna
6 europe
5 hitler
3 kangaroo
3 german
3 beer
3 australia
3 alps
2 wien
2 terminator
2 sydney
2 schnitzel
2 mozart
2 mountains
2 country
2 arnold
2 apfelstrudel
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If that does pique your interest check out the following link for a more in-depth explanation:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://williamjturkel.net/2013/06/15/basic-text-analysis-with-command-line-tools-in-linux/&#34;&gt;http://williamjturkel.net/2013/06/15/basic-text-analysis-with-command-line-tools-in-linux/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The End.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Overwriting Textual&#39;s shortcuts</title>
      <link>https://blog.notmyhostna.me/posts/overwriting-textuals-shortcuts/</link>
      <pubDate>Sun, 09 Mar 2014 08:57:01 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/overwriting-textuals-shortcuts/</guid>
      <description>
        
          
        &lt;p&gt;If you are anything like me, you are connected to a large number of IRC networks and the accompanying channels. As it happens, I&amp;rsquo;m also developing for the web at the same time which usually involves reloading your browser window from time to time. (Shortcut: &lt;code&gt;cmd + R&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;Coincidentally, that&amp;rsquo;s also a shortcut used by Textual to rearrange the channels alphabetically, which is usually not what you want.&lt;/p&gt;
&lt;p&gt;The likelihood of hitting &lt;code&gt;cmd + R&lt;/code&gt; which Textual still being the active window and not the browser/inspector is very high and that&amp;rsquo;s why we are going to reassign the shortcut to something less disastrous. (Yes, the correct order of IRC channels is serious business)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Restoring your old channel order:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;s/o to the people with working backups!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Luckily Textual stores the way the channels are sorted in the application&amp;rsquo;s plist file so we are going to grab the old one from our TimeMachine backup and replace the new one.&lt;/p&gt;
&lt;p&gt;Open your terminal and navigate to path where the correct plist file is stored. The path usually looks a bit like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /Volumes/MobileBackup/Backups.backupdb/monki/2014-03-07-125854/Macintosh\ HD/Users/dewey/Library/Containers/com.codeux.irc.textual/Data/Library/Preferences
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are two files directly related to Textual in there. Use &lt;code&gt;ls | grep textual&lt;/code&gt; to list them:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Preferences|⇒ ls | grep textual
com.codeux.irc.textual.LSSharedFileList.plist
com.codeux.irc.textual.plist
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We only need to restore the second one.&lt;/p&gt;
&lt;p&gt;Make sure you quit Textual at this point and then use &lt;code&gt;cp&lt;/code&gt; to copy/overwrite the &amp;ldquo;new&amp;rdquo; (wrong channel order) with the old plist file containing the correct order:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cp com.codeux.irc.textual.plist ~/Library/Containers/com.codeux.irc.textual/Data/Library/Preferences/com.codeux.irc.textual.plist
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we are done here, but due to Mavericks caching plist files and the inner workings on how to flush the cache manually not being known you&amp;rsquo;ll have to reboot your computer to update the cache.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prevent this from happening in the future:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s great that we are able to restore these old settings but how can we prevent this from happening in the future? Easy, we&amp;rsquo;ll just reassign the Textual shortcut like mentioned earlier.&lt;/p&gt;
&lt;p&gt;Open &amp;ldquo;System Preferences / Keyboard / Shortcuts&amp;rdquo; and reassign &lt;code&gt;cmd + R&lt;/code&gt; to &lt;code&gt;Main Window&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;Screen_Shot_2014_03_09_at_10_34_20.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: If you really need the rearrange shortcut it&amp;rsquo;s possible to do it the other way round and just assign some obscure shortcut so you don&amp;rsquo;t hit it accidentally. To do that just use &amp;ldquo;Sort Channel List&amp;rdquo; instead of &amp;ldquo;Main Window&amp;rdquo; and a shortcut of your choice.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s also a neat way to list all your custom shortcuts we could use to verify that our new shortcut is in place. Just run &lt;code&gt;defaults find NSUserKeyEquivalents&lt;/code&gt; and you&amp;rsquo;ll get something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~|⇒ defaults find NSUserKeyEquivalents
Found 1 keys in domain &#39;com.codeux.irc.textual&#39;: {
    NSUserKeyEquivalents =     {
        &amp;quot;Main Window&amp;quot; = &amp;quot;@r&amp;quot;;
        &amp;quot;Next Unread Channel&amp;quot; = &amp;quot;@7&amp;quot;;
    };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see everything worked as expected. Happy reloading!&lt;/p&gt;
&lt;p&gt;The End.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Fixing things - the ugly way</title>
      <link>https://blog.notmyhostna.me/posts/fixing-things-the-ugly-way/</link>
      <pubDate>Tue, 04 Mar 2014 12:45:40 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/fixing-things-the-ugly-way/</guid>
      <description>
        
          
              <![CDATA[<img src="https://blog.notmyhostna.me/posts/fixing-things-the-ugly-way/feature.jpg" width="2000" height="1418"/>]]>
           
        &lt;p&gt;Because sometimes it&amp;rsquo;s just easier to find a dirty workaround than actually fixing the underlying problem.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For some unknown reason &lt;a href=&#34;https://github.com/jimrollenhagen/pywhatauto&#34;&gt;pywhatauto&lt;/a&gt; is replacing my working cookie file for BTN with an incomplete one. Probably due to a failed authentication with the site. (I blame Cloudflare and the ongoing DDoS). So we have a problem which occurs &lt;em&gt;repeatedly&lt;/em&gt;. Repeatedly sounds like a perfect use case for a &lt;code&gt;cronjob&lt;/code&gt; to me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*/5 * * * * /home/dewey/fixcookies.sh &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don&amp;rsquo;t forget to make the script executable with &lt;code&gt;chmod +x fixcookies.sh&lt;/code&gt;.&lt;/p&gt;
&lt;script src=&#34;https://gist.github.com/dewey/9346561.js&#34;&gt;&lt;/script&gt;

&lt;p&gt;The End.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Pick a random file from a directory</title>
      <link>https://blog.notmyhostna.me/posts/pick-a-random-file-from-a-directory/</link>
      <pubDate>Sun, 16 Feb 2014 23:59:24 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/pick-a-random-file-from-a-directory/</guid>
      <description>
        
          
        &lt;p&gt;AKA. Which movie should I watch today?&lt;/p&gt;
&lt;p&gt;Unfortunately the version of &lt;code&gt;sort&lt;/code&gt; shipped with Mac OS doesn&amp;rsquo;t include the &lt;code&gt;-R&lt;/code&gt; / &lt;code&gt;--random-sort&lt;/code&gt; option and &lt;code&gt;shuf&lt;/code&gt; doesn&amp;rsquo;t come by default. We&amp;rsquo;ll have to install GNU&amp;rsquo;s &lt;a href=&#34;https://www.gnu.org/software/coreutils/&#34;&gt;coreutils&lt;/a&gt; to use them.&lt;/p&gt;
&lt;p&gt;If you are using homebrew it&amp;rsquo;s as simple as running &lt;code&gt;brew install coreutils&lt;/code&gt;. Once installed it&amp;rsquo;s available via &lt;code&gt;gsort&lt;/code&gt;. All the GNU coreutils are prefixed with &lt;code&gt;g&lt;/code&gt; so they are not conflicting with the system provided tools.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ls Movies/ | gshuf -n 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&amp;rsquo;s also possible to be used with &lt;code&gt;find&lt;/code&gt; if you need more flexibility (Only want it to choose between all 720p *.mkv files? No problem!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find Movies/*.mkv -name &amp;quot;*720p*&amp;quot; -type f | gshuf -n 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And because I&amp;rsquo;m lazy I wrote a little shell script* with suggests a random movie based on some input parameters.&lt;/p&gt;
&lt;script src=&#34;https://gist.github.com/dewey/9042882.js&#34;&gt;&lt;/script&gt;

&lt;p&gt;And this is how it works:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Movies|⇒ popcorntime -p ~/Movies -e mkv -q 720p
You should watch:
Where.the.Trail.Ends.2012.720p.Bluray.x264-ESiR.mkv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to call it with &lt;code&gt;popcorntime&lt;/code&gt; instead of &lt;code&gt;./popcorntime.sh&lt;/code&gt; you&amp;rsquo;ll have to add an alias to your &lt;code&gt;~/.zshrc&lt;/code&gt; like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alias popcorntime=&amp;quot;sh ~/path/to/popcorntime.sh&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure the script is executable with:
&lt;code&gt;chmod +x ~/path/to/popcorntime.sh&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The End.&lt;/p&gt;
&lt;p&gt;*As usual writing a quick zsh function turned into a shell script and that task turned into a 2h &lt;a href=&#34;http://mywiki.wooledge.org/BashFAQ/050&#34;&gt;BashFAQ&lt;/a&gt; binge.&lt;/p&gt;
&lt;p&gt;Relevant XKCD:
&lt;a href=&#34;https://xkcd.com/1319/&#34;&gt;https://xkcd.com/1319/&lt;/a&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Running OpenVPN with OpenVZ</title>
      <link>https://blog.notmyhostna.me/posts/running-openvpn-with-openvz/</link>
      <pubDate>Thu, 06 Feb 2014 20:12:16 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/running-openvpn-with-openvz/</guid>
      <description>
        
          
        &lt;p&gt;Just filing this away for future reference.&lt;/p&gt;
&lt;p&gt;If you want to run OpenVPN within a OpenVZ container you&amp;rsquo;ll have to setup the &lt;code&gt;iptables&lt;/code&gt; rules for the correct network interface (&lt;a href=&#34;http://i.imgur.com/F603ZSh.jpg&#34;&gt;You don&amp;rsquo;t say!&lt;/a&gt;). Most likely it&amp;rsquo;s called &lt;code&gt;venet0&lt;/code&gt;. You can double check this with &lt;code&gt;ifconfig&lt;/code&gt; as root or just&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ifconfig -a | sed &#39;s/[ \t].*//;/^\(lo\|\)$/d&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to get a list of network interfaces. The proper iptables rules should look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s 10.8.0.0/24 -j ACCEPT
iptables -A FORWARD -j REJECT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o venet0 -j MASQUERADE
iptables -A INPUT -i tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -j ACCEPT
iptables -A INPUT -i tap+ -j ACCEPT
iptables -A FORWARD -i tap+ -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don&amp;rsquo;t forget to add them to your &lt;code&gt;/etc/rc.local&lt;/code&gt; file to make them persistent across reboots.&lt;/p&gt;
&lt;p&gt;The End.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Make calibre updates less annoying</title>
      <link>https://blog.notmyhostna.me/posts/make-calibre-updates-less-annoying/</link>
      <pubDate>Wed, 05 Feb 2014 21:36:58 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/make-calibre-updates-less-annoying/</guid>
      <description>
        
          
        &lt;p&gt;If you are dealing with ebooks you are probably aware of &lt;a href=&#34;http://calibre-ebook.com/&#34;&gt;Calibre&lt;/a&gt;. It&amp;rsquo;s ugly and a pain to use but it&amp;rsquo;s currently the only application to use if you are serious about organizing your books and/or sync books not purchased on Amazon to your Kindle.&lt;/p&gt;
&lt;p&gt;One of Calibres quirks is that it&amp;rsquo;s updated frequently but isn&amp;rsquo;t coming with an auto updater. Your only way to update is to re-download the ~82MB binary and replace your version with the new one.&lt;/p&gt;
&lt;p&gt;I usually try to use &lt;a href=&#34;https://github.com/phinze/homebrew-cask&#34;&gt;cask&lt;/a&gt; for these kind of apps to make the process of updating them less annoying. In this case cask &lt;a href=&#34;https://github.com/phinze/homebrew-cask/issues/309&#34;&gt;isn&amp;rsquo;t working&lt;/a&gt; as expected because Calibre switched to just using &lt;code&gt;latest&lt;/code&gt; instead of explicit version numbers. This makes it (currently) impossible for cask to figure the right version to install.&lt;/p&gt;
&lt;p&gt;What we are going to do is just removing the old &lt;code&gt;calibre-latest&lt;/code&gt; files from the cask cache, remove the old &lt;code&gt;Calibre.app&lt;/code&gt; from our system and reinstall the new one.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t very elegant but it&amp;rsquo;s a workaround until they figured out how to handle updates for applications installed via cask consistently.&lt;/p&gt;
&lt;p&gt;Add this to your &lt;code&gt;~/.zshrc&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function update-cask {
    BREW_CACHE=$(brew --cache)
    rm -r $BREW_CACHE/calibre-latest
    brew cask uninstall calibre
    brew cask install calibre
    echo &amp;quot;Calibre updated to latest version! Updating other apps now...&amp;quot;
    for c in `brew cask list`; do ! brew cask info $c | grep -qF &amp;quot;Not installed&amp;quot; || brew cask install $c; done
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now run &lt;code&gt;source ~/.zshrc&lt;/code&gt; to reload your shell config and it&amp;rsquo;ll be available via &lt;code&gt;update-cask&lt;/code&gt; in your Terminal.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Backup your server with Tarsnap</title>
      <link>https://blog.notmyhostna.me/posts/backup-your-server-with-tarsnap/</link>
      <pubDate>Sun, 02 Feb 2014 17:28:39 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/backup-your-server-with-tarsnap/</guid>
      <description>
        
          
        &lt;p&gt;Regular and automated backups are hard to get right if you are not on a Mac using TimeMachine.&lt;/p&gt;
&lt;p&gt;There are multiple ways to keep and maintain backups on a linux box (rsnapshot, rsync,&amp;hellip;). I was searching for a service to create and store encrypted offsite backups which is reasonable cheap. I stumbled upon &lt;a href=&#34;https://www.tarsnap.com&#34;&gt;Tarsnap&lt;/a&gt; a number of times now and finally decided to give it a shot.&lt;/p&gt;
&lt;p&gt;I just want to have a couple of revisions of a small number of directories in case of a hardware or user fail. Tarsnap&amp;rsquo;s default script isn&amp;rsquo;t covering the revision/rolling backup feature I need, that&amp;rsquo;s why I&amp;rsquo;m using &lt;a href=&#34;https://github.com/Gestas/Tarsnap-generations&#34;&gt;Tarsnap-generations&lt;/a&gt;. It&amp;rsquo;s just a simple script to create new archives from a list of directories and prune old archives after a given timespan. Think of it as a rsnapshot for Tarsnap.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: This is not a tutorial, this is just to document my setup for future reference.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For it to work you&amp;rsquo;ll need to set one parameter which isn&amp;rsquo;t set in the default Tarsnap config so just create a &lt;code&gt;.tarsnaprc&lt;/code&gt; in your &lt;code&gt;~&lt;/code&gt; and add&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;humanize-numbers
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could also exclude some directories and files from your backup path. To do this just use the &lt;code&gt;exclude&lt;/code&gt; parameter like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;exclude /.ssh/
exclude /var/logs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The directories you want to backup should be added to a file called &lt;code&gt;tarsnap.folders&lt;/code&gt; in your home directory. (If you are using the same cronjob from Tarsnap-generation&amp;rsquo;s example on Github).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/home/dewey/.znc
/home/dewey/.zsh*
/var/www
/etc
/usr/share
/var/lib/bitlbee
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you manually run the script without waiting for a cronjob to run it, it&amp;rsquo;ll look like this:&lt;/p&gt;
&lt;pre&gt;
tarsnap: Removing leading &#39;/&#39; from member names
                                       Total size  Compressed size
All archives                               2.1 GB           638 MB
  (unique data)                            1.2 GB           371 MB
This archive                               6.2 kB           2.8 kB
New data                                   6.2 kB           2.8 kB
20140202-18-HOURLY-at-notmyhostname-/var/lib/bitlbee backup done.
Verifying backups, please wait.
20140202-18-HOURLY-at-notmyhostname-/var/lib/bitlbee backup OK.
Finding backups to be deleted.
&lt;/pre&gt;
&lt;p&gt;Once the script ran you&amp;rsquo;ll see all your archived backups with the &lt;code&gt;tarsnap --list-archives&lt;/code&gt; command.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@at-notmyhostname ~$ tarsnap --list-archives
20140202-18-HOURLY-at-notmyhostname-/home/dewey/.znc
20140202-18-HOURLY-at-notmyhostname-/home/dewey/.config
20140202-18-HOURLY-at-notmyhostname-/home/dewey/.zshrc
20140202-18-HOURLY-at-notmyhostname-/var/lib/bitlbee
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.tarsnap.com/documentation.html&#34;&gt;https://www.tarsnap.com/documentation.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.tarsnap.com/man.html&#34;&gt;https://www.tarsnap.com/man.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/Gestas/Tarsnap-generations&#34;&gt;https://github.com/Gestas/Tarsnap-generations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Using Newsbeuter to read your RSS feeds</title>
      <link>https://blog.notmyhostna.me/posts/using-newsbeuter-to-read-your-rss-feeds/</link>
      <pubDate>Sat, 01 Feb 2014 21:47:47 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/using-newsbeuter-to-read-your-rss-feeds/</guid>
      <description>
        
          
        &lt;p&gt;After the shutdown of &lt;a href=&#34;http://www.google.com/reader/about/&#34;&gt;Google Reader&lt;/a&gt; I was in desperate need of a new feed reader. After using &lt;a href=&#34;https://feedbin.me/&#34;&gt;Feedbin&lt;/a&gt; for a few months I finally settled on &lt;a href=&#34;http://newsbeuter.org/&#34;&gt;Newsbeuter&lt;/a&gt;. It&amp;rsquo;s a beautiful, highly customizable and text based RSS feed reader for your terminal - some even call it the &lt;a href=&#34;http://www.zedshaw.com/essays/i_want_the_mutt_of_feed_readers.html&#34;&gt;&amp;ldquo;Mutt of Feed Readers&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After playing around for a while my current setup looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;8abfbb4a_8182_4662_8753_e7d7a058e155.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;There are a lot of parameters to tailor it to your needs in the Newsbeuter &lt;a href=&#34;http://newsbeuter.org/doc/newsbeuter.html&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My current &lt;code&gt;.newsbeuter/config&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;script src=&#34;https://gist.github.com/dewey/8526742.js&#34;&gt;&lt;/script&gt;

&lt;p&gt;&lt;strong&gt;Installation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you are on Mac OS 10.9.x and want to install it via homebrew you&amp;rsquo;ll have to edit the formula so it&amp;rsquo;s using the &lt;code&gt;c++11&lt;/code&gt; branch of the repository because there&amp;rsquo;s a namespace problem with the &lt;a href=&#34;https://github.com/Homebrew/homebrew/pull/25115&#34;&gt;current branch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To do that just run a &lt;code&gt;brew edit newsbeuter&lt;/code&gt; and replace the line containing &lt;code&gt;head&lt;/code&gt; with&lt;/p&gt;
&lt;p&gt;&lt;code&gt;head &#39;https://github.com/akrennmair/newsbeuter.git&#39;, :branch =&amp;gt; &#39;c++11&#39;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It should look like this at the time of this writing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;homepage &#39;http://newsbeuter.org/&#39;
url &#39;http://newsbeuter.org/downloads/newsbeuter-2.7.tar.gz&#39;
sha1 &#39;e49e00b57b98dacc95ce73ddaba91748665e992c&#39;

head &#39;https://github.com/akrennmair/newsbeuter.git&#39;, :branch =&amp;gt; &#39;c++11&#39;

depends_on &#39;pkg-config&#39; =&amp;gt; :build
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After editing the formula just &lt;code&gt;brew install homebrew&lt;/code&gt; as usual and start editing your config.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.newsbeuter.org/doc/newsbeuter.html#_example_configuration&#34;&gt;newsbeuter.org/doc/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.sanctum.geek.nz/rss-with-newsbeuter/&#34;&gt;http://blog.sanctum.geek.nz/rss-with-newsbeuter/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/akrennmair/newsbeuter/tree/master/contrib&#34;&gt;https://github.com/akrennmair/newsbeuter/tree/master/contrib&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Deploy websites using git</title>
      <link>https://blog.notmyhostna.me/posts/deploy-websites-using-git/</link>
      <pubDate>Fri, 10 Jan 2014 10:00:00 +0000</pubDate>
      <author>mail@notmyhostna.me (Philipp Defner)</author>
      <guid>https://blog.notmyhostna.me/posts/deploy-websites-using-git/</guid>
      <description>
        
          
        &lt;p&gt;This guide explains how to deploy to a remote server by pushing to a remote git repository which is using a custom post-receive hook to checkout the contents of the repository to the webservers public www root.&lt;/p&gt;
&lt;h2 id=&#34;the-local-repository&#34;&gt;The local repository&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;cd ~/sites
mkdir example.com
cd example.com
git init
&amp;gt; Initialized empty Git repository in /Users/dewey/sites/example.com/.git/
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;the-remote-repository&#34;&gt;The remote repository&lt;/h2&gt;
&lt;h3 id=&#34;creating-a-bare-repository&#34;&gt;Creating a bare repository&lt;/h3&gt;
&lt;p&gt;This is the bare repository we are going to push to.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd ~/git/
mkdir example.com.git &amp;amp;&amp;amp; cd example.com.git
git init --bare
&amp;gt; Initialized empty Git repository in /home/user/git/example.com.git/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;adding-a-custom-post-receive-hook&#34;&gt;Adding a custom post-receive hook&lt;/h3&gt;
&lt;p&gt;This hook will run after each push to the bare repository, checking out the changes to the working tree (Which isn&amp;rsquo;t located in the bare repository because that&amp;rsquo;s how it works). The working tree will have no &lt;code&gt;.git&lt;/code&gt; directory (That&amp;rsquo;s how we want it) and will be served by nginx.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;vim ~/git/example.com/hooks/post-receive
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this content:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/sh
echo &amp;quot;********************&amp;quot;
echo &amp;quot;Post receive hook: Updating website&amp;quot;
echo &amp;quot;********************&amp;quot;

export GIT_WORK_TREE=/home/user/www/example.com
cd $GIT_WORK_TREE
git --work-tree=/usr/share/nginx/www/example.com --git-dir=$HOME/git/example.com.git pull
git --work-tree=/usr/share/nginx/www/example.com --git-dir=$HOME/git/example.com.git checkout master -f
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;creating-the-work-tree-directory&#34;&gt;Creating the Work Tree directory&lt;/h3&gt;
&lt;p&gt;This is the directory where all the files should end up after each push. We will create it within nginx&amp;rsquo;s document root so it&amp;rsquo;ll be served up by the webserver.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /usr/share/nginx/www/
mkdir example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;permissions&#34;&gt;Permissions&lt;/h3&gt;
&lt;p&gt;We have to add our regular user to the &lt;code&gt;www-data&lt;/code&gt; group which owns the files in nginx&amp;rsquo;s document root so we&amp;rsquo;ll be able to checkout the files.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo chown www-data /usr/share/nginx/www/example.com
sudo usermod -a -G www-data user
sudo chgrp -R www-data /usr/share/nginx/www/example.com
sudo chmod -R g+w /usr/share/nginx/www/example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;push-to-remote-repository&#34;&gt;Push to remote repository&lt;/h3&gt;
&lt;p&gt;Now we have to add the remote repository to our local repository so we can push to it.&lt;/p&gt;
&lt;p&gt;Our local repository&amp;rsquo;s &lt;code&gt;.git/config&lt;/code&gt; should look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[remote &amp;quot;production&amp;quot;]
    url = ssh://user@example.com/~/git/example.com.git
    fetch = +refs/heads/*:refs/remotes/production/*
    gtSSHKey = /Users/user/.ssh/id_rsa
[branch &amp;quot;master&amp;quot;]
    remote = production
    merge = refs/heads/master
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once this is added &lt;code&gt;git remote&lt;/code&gt; will show the remote repository:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git remote
&amp;gt; production
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pushing via&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git push production
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;should now be possible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://halfthetruth.de/2011/09/13/using-git-to-deploy-a-website/&#34;&gt;https://halfthetruth.de/2011/09/13/using-git-to-deploy-a-website/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
  </channel>
</rss>