<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Past and Current Projects on East of the Sun, West of the Moon</title>
    <link>https://is-here.com/project/</link>
    <description>Recent content in Past and Current Projects on East of the Sun, West of the Moon</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>Erwin Harte</copyright>
    <lastBuildDate>Wed, 31 Dec 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://is-here.com/project/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Mastodon server</title>
      <link>https://is-here.com/project/mastodon/</link>
      <pubDate>Wed, 31 Dec 2025 00:00:00 +0000</pubDate>
      
      <category>AWS</category><category>Mastodon</category><category>Terraform</category><guid>https://is-here.com/project/mastodon/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Status
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Active since December 2022.&lt;/p&gt;
&lt;p&gt;
Moved from AWS to Hetzner in November 2025.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
What
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;My personal &lt;a href=&#34;https://joinmastodon.org/&#34;&gt;Mastodon&lt;/a&gt; server. The accounts on there are all &lt;em&gt;me&lt;/em&gt;, at this time.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Where
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://strangeweb.page/&#34;&gt;https://strangeweb.page/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
I wanted to keep this relatively separate from other projects, so I registered a &lt;code class=&#34;verbatim&#34;&gt;.page&lt;/code&gt; domain.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
How
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;When I migrated to Hetzner, I simplified the setup a bit:&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;A single VM&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
More than enough CPU, RAM, storage, and of course an IPv4 and an IPv6 address.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Access via &lt;code class=&#34;verbatim&#34;&gt;ssh&lt;/code&gt; locked down&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
Only my home IP address can get in. Easily updated when that changes (which is rare).&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;The other ports available&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
Port 80 (&lt;code class=&#34;verbatim&#34;&gt;http&lt;/code&gt;, in practice really only for LetsEncrypt, but also the classic &lt;code class=&#34;verbatim&#34;&gt;http&lt;/code&gt; to &lt;code class=&#34;verbatim&#34;&gt;https&lt;/code&gt; redirect), and of course 443 (&lt;code class=&#34;verbatim&#34;&gt;https&lt;/code&gt;) for the main attraction.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Still using the S3 bucket&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
I plan to migrate that to different object storage in the near future.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Terraform code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
It creates the VM, updates the DNS (A and AAAA records which now live at &lt;a href=&#34;https://desec.io/&#34;&gt;deSEC.io&lt;/a&gt;), as well as reverse DNS managed by Hetzner, then throws &lt;code class=&#34;verbatim&#34;&gt;cloud-init&lt;/code&gt; at it.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;The &lt;code class=&#34;verbatim&#34;&gt;cloud-init&lt;/code&gt; setup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
This takes care of basic conveniences (things like &lt;code class=&#34;verbatim&#34;&gt;emacs&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;jq&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;rsync&lt;/code&gt;, and others) but also installs dependencies for Mastodon and prepare it most of the way (skipping the interactive configuration of Mastodon itself).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Code and related things
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Mastodon &lt;a href=&#34;https://docs.joinmastodon.org/user/run-your-own/&#34;&gt;instructions&lt;/a&gt; for setting up your own server&lt;/p&gt;
&lt;p&gt;
The &lt;a href=&#34;https://codeberg.org/jochie/strangeweb.page/&#34;&gt;Infrastructure as Code&lt;/a&gt; at &lt;a href=&#34;https://codeberg.org/.&#34;&gt;https://codeberg.org/.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Previously
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;The setup in AWS (from 2022-2025) was as follows:&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Basic Virtual Private Cloud (VPC)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
Pretty standard setup. A subnet for public facing things (which is the only things in here right now), and one for resources that don&amp;#39;t connect out to the internet. Right now there aren&amp;#39;t any of the latter, but it is good to be prepared&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;A bastion server&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
A locked down instance that is intended to be the only way to get into the VPC with &lt;code class=&#34;verbatim&#34;&gt;ssh&lt;/code&gt;, with an IP address that is separate from the actual service.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;The actual Mastodon server&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;An S3 bucket&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
This is where Mastodon stores media associated with posts (in the timeline of my accounts, or my own), with a CloudFront shield in front of it&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Terraform code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
This managed all of the above.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;For Mastodon upgrades&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
I created &lt;a href=&#34;https://codeberg.org/jochie/misc/src/branch/master/AWS/upscale-downscale.sh&#34;&gt;a script&lt;/a&gt; to temporarily bump up the instance size, because it was unhappy for some of those steps but perfectly content running in a smaller instance during normal operations.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Teletekst Bot</title>
      <link>https://is-here.com/project/teletekst/</link>
      <pubDate>Sun, 28 Dec 2025 00:00:00 +0000</pubDate>
      
      <category>Mastodon</category><category>Python</category><comments>https://strangeweb.page/@jochie/115805471217337649</comments><guid>https://is-here.com/project/teletekst/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Status
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Active since July 2024&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
What
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Monitor the news (&amp;#34;Nieuws&amp;#34; in Dutch) such as it is shared by the &lt;a href=&#34;https://nos.nl/teletekst&#34;&gt;NOS Teletekst&lt;/a&gt;, by checking the references from the index pages at 101, 102, and 103, and then scan for any other pages from 104 to 199.&lt;/p&gt;
&lt;p&gt;
When a new page is found, or an existing page is updated (using a relatively basic heuristic), post the new or updated page to the Mastodon account. It also attempts to detect when a page is moved around.&lt;/p&gt;
&lt;p&gt;
Because occasionally pages are included for sport (in general) or soccer (voetbal), it will use an appropriate &lt;code class=&#34;verbatim&#34;&gt;#TeletekstXYZ&lt;/code&gt; hashtag for that, so people can mute that. The same goes for the content updates, which can be a bit much especially for emerging stories, and get tagged with &lt;code class=&#34;verbatim&#34;&gt;#TeletekstUpdate&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
For content updates the posts also includes comparison of the previous and current version with color-coding for words or lines that have been removed, were added, or stayed the same. It&amp;#39;s similar to &lt;code class=&#34;verbatim&#34;&gt;git diff&lt;/code&gt; but has been adapted to make more sense in this text context.&lt;/p&gt;
&lt;p&gt;
If the content was unchanged and only the page number or title changed, the existing Mastodon post is updated in place.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Where
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://mstdn.social/@teletekst&#34;&gt;https://mstdn.social/@teletekst&lt;/a&gt; (originally at &lt;a href=&#34;https://botsin.space/@teletekst,&#34;&gt;https://botsin.space/@teletekst,&lt;/a&gt; but that server shut down at the end of 2024).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
How
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;There are two Cron jobs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Every 5 minutes a program &lt;em&gt;walks&lt;/em&gt; all the pages from 101 to 199, using the &lt;code class=&#34;verbatim&#34;&gt;next page&lt;/code&gt; references. If all pages are exactly identical, discard the results.

It needs to gracefully handle broken &lt;code class=&#34;verbatim&#34;&gt;next page&lt;/code&gt; links and other quirks.&lt;/li&gt;
&lt;li&gt;Also every 5 minutes, but a minute later, a second program checks if changes were found. If so, look for new pages, deletes pages, moved pages, and modified pages.

Two pages are treated differently, namely the &amp;#34;Kort nieuws binnenland&amp;#34; and &amp;#34;Kort nieuws buitenland&amp;#34;, where one or two short national or international news items are dumped.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Disclaimer
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; an (official or endorsed) &lt;a href=&#34;https://nos.nl/&#34;&gt;NOS.nl&lt;/a&gt; service!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Code
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://codeberg.org/jochie/Teletekst&#34;&gt;https://codeberg.org/jochie/Teletekst&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Read Later</title>
      <link>https://is-here.com/project/read-later/</link>
      <pubDate>Sun, 13 Jul 2025 00:00:00 +0000</pubDate>
      
      <category>Self-hosting</category><category>Docker</category><category>Python</category><comments>https://strangeweb.page/@@jochie/114848668662470733</comments><guid>https://is-here.com/project/read-later/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Status
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Active since July 2025.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
What
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;A self-hosted bookmark/read-later service&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Where
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://readeck.is-here.com/&#34;&gt;https://readeck.is-here.com/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
How
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;This service is setup as one of several virtual hosts on a virtual machine that is dedicated to a couple of these self-hosted things (the project page for is still WIP/AWOL for now).&lt;/p&gt;
&lt;p&gt;
To try and keep the maintenance requirements relatively low I used the docker approach, only sharing the data with the host system so that it is preserved over restarts and can be backed up regularly:&lt;/p&gt;
&lt;div class=&#34;src src-shell&#34;&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-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  docker run &lt;span style=&#34;color:#ae81ff&#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;&lt;/span&gt;         --detach &lt;span style=&#34;color:#ae81ff&#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;&lt;/span&gt;         --rm -ti &lt;span style=&#34;color:#ae81ff&#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;&lt;/span&gt;         -p 6080:8000 &lt;span style=&#34;color:#ae81ff&#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;&lt;/span&gt;         -v /var/www/readeck:/readeck &lt;span style=&#34;color:#ae81ff&#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;&lt;/span&gt;         codeberg.org/readeck/readeck:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
A fragment of the Apache configuration file:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ProxyPreserveHost On
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ProxyPass / http://0.0.0.0:6080/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ProxyPassReverse / http://0.0.0.0:6080/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  RequestHeader set X-Forwarded-Proto https&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Disclaimer: I don&amp;#39;t have a lot of experience with the &lt;code class=&#34;verbatim&#34;&gt;proxy&lt;/code&gt; or &lt;code class=&#34;verbatim&#34;&gt;proxy_http&lt;/code&gt; modules, so it&amp;#39;s possible that could be done better. There are more complete instructions on the Readeck &lt;a href=&#34;https://readeck.org/en/docs/deploy&#34;&gt;Deployment&lt;/a&gt; documentation page.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Integrating it:
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;ul&gt;
&lt;li&gt;For Firefox I use this &lt;a href=&#34;https://addons.mozilla.org/en-US/firefox/user/18046494/&#34;&gt;Readeck add-on&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;There is no iOS (or Android, for that matter) app but the (self-hosted) website can be added as a pseudo-app on iOS by using Safari&amp;#39;s &amp;#34;Add to Home Screen&amp;#34;.&lt;/li&gt;
&lt;li&gt;That pseudo-app doesn&amp;#39;t get you a &amp;#34;Share to …&amp;#34; entry, but thankfully there are acceptable workarounds (listed in the &lt;a href=&#34;https://readeck.org/en/docs/faq#is-there-an-android-or-ios-application&#34;&gt;FAQ&lt;/a&gt;) in the form of shortcuts.
It took a little bit of fidgeting to figure out how to configure the shortcut, but after that it was relatively smooth sailing.&lt;/li&gt;
&lt;li&gt;Although it&amp;#39;s somewhat redundant, I also created a script to check my Mastodon bookmarks and import new ones into Readeck. So if I&amp;#39;m in a hurry, I&amp;#39;ll quickly bookmark a &lt;del&gt;post&lt;/del&gt; toot, otherwise I&amp;#39;ll use the &amp;#34;Send Page + Tags To Readeck&amp;#34; shortcut.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Code and related things
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Originally I had planned to migrate from Instapaper (the read-later service I used for ~15 years) to a self-hosted &lt;a href=&#34;https://wallabag.it/en/&#34;&gt;Wallabag&lt;/a&gt; instance, but before the dust had even settled on that (meaning figuring out what browser add-on to use or how to integrate it on my phone) &lt;a href=&#34;https://shom.dev/posts/20250629_bookmarking-i-mean-omnivoring-no-hoarding-no-bagging-dot-dot-dot-wait-decking/&#34;&gt;this post&lt;/a&gt; by Shom pointed me towards &lt;a href=&#34;https://readeck.org/en/&#34;&gt;Readeck&lt;/a&gt;. That&amp;#39;s why the scripts below have a migration path from Instapaper -&amp;gt; Wallabag -&amp;gt; Readeck, and not Instapaper -&amp;gt; Readeck.&lt;/p&gt;
&lt;p&gt;
My collection of scripts in this &lt;a href=&#34;https://codeberg.org/jochie/read-later&#34;&gt;read-later repository&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;wallabag_import.py&lt;/code&gt;: Iterate over the Instapaper entries and add them one by one to my (also self-hosted) Wallabag service. For the ~17k bookmarks that I had that took multiple hours and possibly got my IP in trouble with a few websites.&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;readeck_wallabag.py&lt;/code&gt;: Initiate a migration from Wallabag to Readeck (handled entirely by Readeck after that).&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;reprocess_readeck.py&lt;/code&gt;: Loop over all bookmarks in a Readeck collection, re-adding them and deleting the original ones as it goes.&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;bookmark_readeck.py&lt;/code&gt;: Check my Mastodon bookmarks and add any new ones to Readeck&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>WARN Act Bot</title>
      <link>https://is-here.com/project/warn-act/</link>
      <pubDate>Sun, 13 Jul 2025 00:00:00 +0000</pubDate>
      
      <category>AWS</category><category>Terraform</category><category>Mastodon</category><comments>https://strangeweb.page/@@jochie/114849277939604707</comments><guid>https://is-here.com/project/warn-act/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Status
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Active since around April 2023.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
What
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;As I understand it, there are WARN Acts in most states (maybe all) that require employers of companies over a certain size to give a heads-up to the state when they plan to let go for one reason or another. This could be for permanent closure of a place of business, redundancies for whatever reason, and some other reasons I can&amp;#39;t think of right now. Many states make the notices available in some form on the web. Sadly they don&amp;#39;t seem to have considered standardizing that, so automation based on the content found online is a challenge.&lt;/p&gt;
&lt;p&gt;
In my case, I decided to automate checking the notices for the &lt;a href=&#34;https://edd.ca.gov/en/jobs_and_training/Layoff_Services_WARN&#34;&gt;California EDD&lt;/a&gt;, and post the incremental changes (summarized where possible) on the Fediverse.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Where
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://sfba.social/@warn_act_ca&#34;&gt;https://sfba.social/@warn_act_ca&lt;/a&gt; (originally at &lt;a href=&#34;https://botsin.space/@warn_act_ca,&#34;&gt;https://botsin.space/@warn_act_ca,&lt;/a&gt; but that server shut down at the end of 2024).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
How
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;The setup (in AWS) is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An S3 bucket to maintain state from one run to another&lt;/li&gt;
&lt;li&gt;A few Systems Manager Parameter Store entries for the knowledge of where the bot is and the token to post to its timeline&lt;/li&gt;
&lt;li&gt;A Lambda that is triggered from EventBridge on a regular basis that checks the California website&lt;/li&gt;
&lt;li&gt;An SQS queue through which to manage the posts to the bot account, with a Lambda consumer that does that work&lt;/li&gt;
&lt;li&gt;Terraform code to create these resources and some tangentially related ones&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Cost
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;$0.00!&lt;/p&gt;
&lt;p&gt;
Actually, the dedicated AWS account in which this runs had a bill for (literally) a few pennies one time, apparently related to AWS Cost Explorer of all things, but otherwise the monthly bills have been $0.00 since I started.&lt;/p&gt;
&lt;p&gt;
The reason is that all of the service usage (S3, Lambda, SNS, SQS, CloudWatch, and data transfer) are all flying well under the limits of the permanent AWS free tiers. The biggest risk is probably S3 where the it&amp;#39;s running up a bill of about $0.005 per month, so each month that is rounded down to $0.00 but when you request an annual total it lists that as ~$0.05. 😁&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Code
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://codeberg.org/jochie/WARN&#34;&gt;https://codeberg.org/jochie/WARN&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Website</title>
      <link>https://is-here.com/project/website/</link>
      <pubDate>Mon, 13 Nov 2023 00:00:00 +0000</pubDate>
      
      <category>AWS</category><category>Hugo</category><category>Docker</category><guid>https://is-here.com/project/website/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Status
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Active in its current form since November 2023 and its current location since March 2025.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
What
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;My personal website.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Where
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Right &lt;a href=&#34;https://is-here.com/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
Content
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Everything on here has been generated once by a so-called &lt;a href=&#34;https://en.wikipedia.org/wiki/Static_site_generator&#34;&gt;SSG&lt;/a&gt; and then dropped in place.&lt;/p&gt;
&lt;p&gt;
The content is generated with &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt;. I picked the &lt;a href=&#34;https://themes.gohugo.io/themes/gohugo-theme-ananke/&#34;&gt;Ananke&lt;/a&gt; theme, and made some minor modifications:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Modified the default Hugo RSS template (&lt;code class=&#34;verbatim&#34;&gt;layouts/_default/rss.xml&lt;/code&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Change the feed to include full posts instead of just the summary&lt;/li&gt;
&lt;li&gt;Add &lt;code class=&#34;verbatim&#34;&gt;&amp;lt;category&amp;gt;&lt;/code&gt; tag(s)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copied and modified the default single (post/project) page (&lt;code class=&#34;verbatim&#34;&gt;layouts/_default/single.html&lt;/code&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Include an optional &amp;#34;Updated …&amp;#34; bit after the original post date&lt;/li&gt;
&lt;li&gt;Move the context menu (with the table of contents and related posts) before the content, which places it to the left of the text, or at the top of page instead of at the bottom in a small screen situation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Copied and adapted the main page (&lt;code class=&#34;verbatim&#34;&gt;layouts/index.html&lt;/code&gt;) just to make the text there &lt;em&gt;not&lt;/em&gt; be centered.&lt;/li&gt;
&lt;li&gt;Copied and adapted the footer (&lt;code class=&#34;verbatim&#34;&gt;layouts/partials/site-footer.html&lt;/code&gt;) just so I could make the copyright years be a range instead of just the current year. I tried to put the beginning of the range in the &lt;code class=&#34;verbatim&#34;&gt;copyright&lt;/code&gt; configuration setting but then that ended up looking funny in the RSS source&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Beyond that, I&amp;#39;ve left the theme as-is and I&amp;#39;m taking advantage of its (and Hugo&amp;#39;s) features.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Hosting
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Until March 2025 the static site was hosted in an &lt;a href=&#34;https://aws.amazon.com/&#34;&gt;AWS&lt;/a&gt; S3 bucket, made available through a Cloudfront distribution to make it available via &lt;code class=&#34;verbatim&#34;&gt;https&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
At that point, I moved it to &lt;a href=&#34;https://www.statichost.eu/&#34;&gt;statichost.eu&lt;/a&gt;, which specializes in hosting SSGs, directly from Git repositories, and hosting it with &lt;code class=&#34;verbatim&#34;&gt;http&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;https&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Keeping up with the Joneses?
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;As so often happens, I looked away for one minute (alright, closer to 4-5 months) and the version of Hugo that I get when I do a fresh install (from &lt;a href=&#34;https://brew.sh/&#34;&gt;Brew&lt;/a&gt;) is a &lt;em&gt;bit&lt;/em&gt; different than what I started with, and that is going to break some things.&lt;/p&gt;
&lt;p&gt;
To give myself a stable work environment and breathing space I decided to run the &lt;code class=&#34;verbatim&#34;&gt;hugo&lt;/code&gt; command inside a quick&amp;#39;n&amp;#39;dirty container:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code class=&#34;verbatim&#34;&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  FROM cibuilds/hugo:0.119.0
&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;  EXPOSE 1313&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A super simple &lt;code class=&#34;verbatim&#34;&gt;Makefile&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  hugo-docker:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          docker build --tag myhugo .
&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-beta:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          docker-helper server --bind 0.0.0.0 --environment beta
&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-live:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          ./docker-helper server --bind 0.0.0.0 --environment live
&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;  deploy-beta:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          ./docker-helper --environment beta &amp;amp;&amp;amp; ./docker-helper deploy --environment beta
&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;  deploy-live:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          ./docker-helper --environment live &amp;amp;&amp;amp; ./docker-helper deploy --environment live&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And a shell script to glue it all together:&lt;/p&gt;
&lt;div class=&#34;src src-shell&#34;&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-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/sh&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:#f92672&#34;&gt;[&lt;/span&gt; $# -eq &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:#66d9ef&#34;&gt;then&lt;/span&gt;
&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;#34;Usage: &lt;/span&gt;$0&lt;span style=&#34;color:#e6db74&#34;&gt; &amp;lt;hugo-arguments&amp;gt;&amp;#34;&lt;/span&gt; 1&amp;gt;&amp;amp;&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;      exit &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:#66d9ef&#34;&gt;fi&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;  DIR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;git rev-parse --show-toplevel&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  docker run -v $HOME/.aws:/home/circleci/.aws -v $DIR:$DIR -p 1313:1313 -w &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;pwd&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt; -it myhugo hugo $*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;That script fires up the container with only the current Git repo exposed within the container, and starting off at the current working directory as well, then running the &lt;code class=&#34;verbatim&#34;&gt;hugo&lt;/code&gt; version that I grabbed. It also shares &lt;code class=&#34;verbatim&#34;&gt;~/.aws&lt;/code&gt; for the deployment steps.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now I can run a command like this and I can sanity check that the site is going to look ok with that particular version, and then later figure out what needs to be fixed as I nudge the version along at my own pace:&lt;/p&gt;
&lt;div class=&#34;src src-shell&#34;&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-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make server-beta&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
And then deploy when I&amp;#39;m happy:&lt;/p&gt;
&lt;div class=&#34;src src-shell&#34;&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-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make deploy-live&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Noting that now that I&amp;#39;ve moved to &lt;a href=&#34;https://www.statichost.eu/&#34;&gt;statichost.eu&lt;/a&gt; the &lt;code class=&#34;verbatim&#34;&gt;deploy-*&lt;/code&gt; targets are obsolete, but it&amp;#39;s still useful to test locally with &lt;code class=&#34;verbatim&#34;&gt;server-*&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
