<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Olivier Forget</title>
    <link>https://olivierforget.net/</link>
    <description>Olivier Forget's blog post feed</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-US</language>
    <copyright>Copyright © 2020, Olivier Forget</copyright>
    <lastBuildDate>Sat, 07 Mar 2026 11:35:00 -0800</lastBuildDate>
    
        <atom:link href="https://olivierforget.net/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Dropserver Progress - February 2026</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2026/dropserver-progress-feb-2026/</link>
      <pubDate>Sat, 07 Mar 2026 11:35:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2026/dropserver-progress-feb-2026/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for February 2026. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2026/dropserver-progress-jan-2026/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This month I kept grinding away on removing DropIDs from the hot path of authentication in appspaces. See the &lt;a href=&#34;https://olivierforget.net/blog/2026/dropserver-progress-nov-2025/&#34;&gt;November-December update&lt;/a&gt; for an explanation of what it&amp;rsquo;s all about.&lt;/p&gt;
&lt;h2 id=&#34;showing-user-conflicts-in-the-ui&#34;&gt;Showing User Conflicts in the UI&lt;/h2&gt;
&lt;p&gt;A consequence of removing dependence on DropIDs and also adding authentication via Tailscale means that each appspace user can be identified through different identifiers (their tailnet ID, their DropID, and in the future probably their email address.)&lt;/p&gt;
&lt;p&gt;Having multiple ways for each user to authenticate is great but you might get in a situation where one appspace user might be associated with two separate &lt;code&gt;ds-host&lt;/code&gt; instance users. This is a confusing situation to be in and is best not allowed. Similarly it is possible to associate one instance user with two appspace users. Again, confusing. But also, it means the system doesn&amp;rsquo;t know which appspace user to authenticate when an instance user wants to access an appspace. It&amp;rsquo;s best to disallow this situation.&lt;/p&gt;
&lt;p&gt;Note that if I do my work correctly &lt;code&gt;ds-host&lt;/code&gt; will prevent you from creating these conflicts in most cases. For example it won&amp;rsquo;t let you select an instance user for an appspace user if that instance user is already associated with a different appspace user.&lt;/p&gt;
&lt;p&gt;But conflicts are still unavoidable. I am serious about making appspaces &amp;ldquo;movable&amp;rdquo;, meaning that you can export the data and import it on a different instance and, as much as it&amp;rsquo;s possible, things should work. In other words an appspace, along with its list of users and associated auth identifiers, can be imported into a &lt;code&gt;ds-host&lt;/code&gt; instance, and there is no guarantee that this set of auth ids doesn&amp;rsquo;t conflict with auth ids and instance users of the new host.&lt;/p&gt;
&lt;p&gt;As such, I have to assume conflicts can happen and make it possible for appspace owners to deal with them.&lt;/p&gt;
&lt;p&gt;The first step is to display the conflicts as clearly as possible. See below for where I&amp;rsquo;m at with this right now. The first screenshot shows no conflicts, just one warning about a user that is not an instance user at all. (It&amp;rsquo;s technically possible to have non-instance appspace users, but it&amp;rsquo;s not implemented yet.)&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2026/dropserver-progress-feb-2026/user-no-conflicts_hue33a4c958d1098218291ca7f3e64d781_31699_757x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2026/dropserver-progress-feb-2026/user-no-conflicts_hue33a4c958d1098218291ca7f3e64d781_31699_757x0_resize_box_3.png, https://olivierforget.net/blog/2026/dropserver-progress-feb-2026/user-no-conflicts_hue33a4c958d1098218291ca7f3e64d781_31699_1514x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing Dropserver appspace&amp;#39;s users list with no conflicts.&#34;&gt;
&lt;p&gt;Now if I change the DropID of the first user to &amp;ldquo;dropid.local.dropserver.org/altoli&amp;rdquo; and then set the DropID for the &amp;ldquo;Alt Oli&amp;rdquo; instance user to the same, then everything falls apart, and orange appears everywhere.&lt;/p&gt;
&lt;p&gt;(nb: I still need to replace &amp;ldquo;User 1&amp;rdquo; with the actual instance user name and profile pic, and tweak some alignments, but you get the idea.)&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2026/dropserver-progress-feb-2026/users-with-conflicts_hu3c1f8eab59d17603b0621d5e076cb6dd_43129_751x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2026/dropserver-progress-feb-2026/users-with-conflicts_hu3c1f8eab59d17603b0621d5e076cb6dd_43129_751x0_resize_box_3.png, https://olivierforget.net/blog/2026/dropserver-progress-feb-2026/users-with-conflicts_hu3c1f8eab59d17603b0621d5e076cb6dd_43129_1502x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing Dropserver appspace&amp;#39;s users list with multiple conflicts.&#34;&gt;
&lt;p&gt;If an appspace owner encounters this, clicking on the &amp;ldquo;Edit&amp;rdquo; link allows them to remove or change the problematic auth identifiers. Hopefully that&amp;rsquo;s clear enough.&lt;/p&gt;
&lt;h2 id=&#34;instance-user-display-name-and-images&#34;&gt;Instance User Display Name and Images&lt;/h2&gt;
&lt;p&gt;I had punted on display name and images for &lt;code&gt;ds-host&lt;/code&gt; instance users until now. With instance users becoming more important and DropIDs becoming irrelevant I needed to give instance users these display names and profile pics, and make them available to all other instance users so they can see for example who  owns an appspace that they are using, etc&amp;hellip;&lt;/p&gt;
&lt;h1 id=&#34;moving-along&#34;&gt;Moving Along&lt;/h1&gt;
&lt;p&gt;Overall decent progress in February, especially considering that I was on vacation from the 20th onwards. I can see the light at the end of the tunnel with this work. See you next month.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - January 2026</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2026/dropserver-progress-jan-2026/</link>
      <pubDate>Sun, 15 Feb 2026 16:35:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2026/dropserver-progress-jan-2026/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for January 2026. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2026/dropserver-progress-nov-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I started the year by refreshing my personal note taking app, then I got back to work making &lt;code&gt;ds-host&lt;/code&gt; more flexible with domain names, in particular making them unnecessary.&lt;/p&gt;
&lt;h2 id=&#34;updates-to-illuminoted-dropserver-app&#34;&gt;Updates to Illuminoted Dropserver App&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/teleclimber/Illuminoted&#34;&gt;Illuminoted&lt;/a&gt; is an app I wrote after getting &lt;a href=&#34;https://olivierforget.net/blog/2019/note-taking-apps/&#34;&gt;fully fed up&lt;/a&gt; with the state of note-taking apps. It&amp;rsquo;s a very personal app, full of quirks and inadequate user experiences which is why I haven&amp;rsquo;t yet formally published it online as an installable Dropserver app, though I probably should.&lt;/p&gt;
&lt;p&gt;As with all my personal apps I only touch the code when it&amp;rsquo;s sorely needed. With the &lt;a href=&#34;https://leftovers.olivierforget.net/&#34;&gt;Leftovers&lt;/a&gt; app I usually go half a year before I get in there and change things up. This is a key thing about home cooked apps: unlike commercial apps that are always after a bigger number for their KPIs, the changes are few and far between. Or rather you only change them when you strongly feel that something needs to change. Maybe there is a badly needed feature that you just don&amp;rsquo;t want to work around anymore, or a papercut bug that has snagged you so many times you&amp;rsquo;ve run out of virtual band-aids. I find that a few months is the right amount of distillation to surface the truly necessary changes.&lt;/p&gt;
&lt;p&gt;Oddly, with Illuminoted, though it&amp;rsquo;s the app I use more than any (I&amp;rsquo;m on it all day every day, 19,360 notes deep, documenting all work stuff, non-work coding stuff, but also mundane things like my car tire shopping and research notes) it&amp;rsquo;s the one that has gone the longest without any significant upgrade.&lt;/p&gt;
&lt;p&gt;October 2023! That&amp;rsquo;s the last time I did anything. Naturally after such a long time I had a long list of things improve. I didn&amp;rsquo;t get to all of them but I did knock out quite a few wins and I am happier for it. You can get an idea from the &lt;a href=&#34;https://github.com/teleclimber/Illuminoted/commits/main/?since=2025-12-31&amp;amp;until=2026-01-15&#34;&gt;commit log&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I now have better threads management, better navigate-to-note support, better UX to create a new note, and proper full text search thanks to sqlite&amp;rsquo;s &lt;a href=&#34;https://sqlite.org/fts5.html&#34;&gt;FTS5&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;back-to-work-removing-dropids&#34;&gt;Back To Work Removing DropIDs&lt;/h2&gt;
&lt;p&gt;In the &lt;a href=&#34;https://olivierforget.net/blog/2026/dropserver-progress-nov-2025/&#34;&gt;previous progress report&lt;/a&gt; I talked about my goal of removing the hard dependency on domain names in &lt;code&gt;ds-host&lt;/code&gt; and how that meant I had to remove the hard requirement for users to set up a &amp;ldquo;DropID&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;This creates a cascade of &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commits/rm-dropids-1/?since=2026-01-01&amp;amp;until=2026-01-31&#34;&gt;changes&lt;/a&gt; around users and &lt;a href=&#34;https://dropserver.org/docs/application-model&#34;&gt;appspaces&lt;/a&gt;. I&amp;rsquo;ll try to summarize it all below:&lt;/p&gt;
&lt;h3 id=&#34;eliminate-remote-appspaces&#34;&gt;Eliminate &amp;ldquo;remote&amp;rdquo; appspaces&lt;/h3&gt;
&lt;p&gt;These are appspaces hosted on other &lt;code&gt;ds-host&lt;/code&gt; instances that can be accessed via federation (DropIDs were central to this). It turns out that a bug in my federation code prevented any such federation, so the &amp;ldquo;remote appspaces&amp;rdquo; could only be on the instance the user is on. A convenient mistake&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;make-it-possible-for-users-to-access-an-appspace-on-the-same-instance&#34;&gt;Make it possible for users to access an appspace on the same instance&lt;/h3&gt;
&lt;p&gt;Originally &amp;ldquo;remote&amp;rdquo; was used for both other instances and appspaces owned by others on the same instance. With federation gone, the latter capability had to be restored.&lt;/p&gt;
&lt;h3 id=&#34;double-down-on-multiple-identifiers-for-appspace-users&#34;&gt;Double down on multiple identifiers for appspace users&lt;/h3&gt;
&lt;p&gt;When I integrated &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; into &lt;code&gt;ds-host&lt;/code&gt; I made sure to use that network&amp;rsquo;s native IDs to identify users in an appspace. A good move, but then I had multiple ways of identifying a user: DropID and Tailnet ID. Once you allow that, the potential for conflicts is inevitable. An appspace user could match with multiple &lt;code&gt;ds-host&lt;/code&gt; users and a &lt;code&gt;ds-host&lt;/code&gt; user could match multiple appspace users. To avoid problems I wrote a system to detect such conflicts and report them to the frontend.&lt;/p&gt;
&lt;p&gt;A reminder that all of this stems form the principle that appspaces should be &amp;ldquo;moveable&amp;rdquo;: you can download an appspace from a &lt;code&gt;ds-host&lt;/code&gt; instance and move to another without losing all connections to the users. This is possible because appspace users are identified with established globally unique identifiers, not the instance&amp;rsquo;s user ID.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s good to have this work done because I will probably add more types of identifiers in the future, like the venerable email address.&lt;/p&gt;
&lt;h2 id=&#34;cleanup-on-aisle-6&#34;&gt;Cleanup on aisle 6&lt;/h2&gt;
&lt;p&gt;Finally I was able to remove remote appspaces from the code as well as the faulty &amp;ldquo;federation&amp;rdquo; code. A few months ago I said I was about to do a &amp;ldquo;cleanup on aisle 6&amp;rdquo;. This was that cleanup, and it felt great to mop up &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/1659790fa418212680f654078d0c2271cdcd1dc7&#34;&gt;over 2000 lines of code&lt;/a&gt; away.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next&lt;/h2&gt;
&lt;p&gt;I still have a number of loose ends to finish up before I can ship these changes, sadly. As always the pace of development of Dropserver isn&amp;rsquo;t what I&amp;rsquo;d like it to be. So it goes.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m late posting this progress update. Even later than usual in fact. January was stressful for reasons unrelated to Dropserver. See you for the February update, hopefully not as late this time!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - November December 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2026/dropserver-progress-nov-2025/</link>
      <pubDate>Sat, 10 Jan 2026 10:23:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2026/dropserver-progress-nov-2025/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for November and December 2025. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-oct-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In November I began work on removing the dependence on domain names in &lt;a href=&#34;dropserver.org/docs/ds-host&#34;&gt;&lt;code&gt;ds-host&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;domain-names-in-dropserver&#34;&gt;Domain Names in Dropserver&lt;/h2&gt;
&lt;p&gt;When I started writing Dropserver I thought of it as a very standard server program. The main difference was that it served apps that could be easily installed through an interface.&lt;/p&gt;
&lt;p&gt;Lately I have started peeling away the assumptions that go into making a server. In particular I started seeing that the server might actually be serving on different networks, or have requests funneled to it via a diversity of technologies.&lt;/p&gt;
&lt;p&gt;The first sign that I had made some incorrect assumptions came when I wrote the &lt;a href=&#34;https://dropserver.org/docs/connect-tailnet&#34;&gt;integration with Tailscale&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In a typical server program the configuration file expects that there is a domain name that points to the server. Because of course there is, right? What&amp;rsquo;s a web server without a web address?&lt;/p&gt;
&lt;p&gt;So &lt;code&gt;ds-host&lt;/code&gt; was built with the idea that there was a domain name, and that the &lt;a href=&#34;https://dropserver.org/docs/application-model&#34;&gt;appspaces&lt;/a&gt; would live at subdomains on that domain, and that&amp;rsquo;s how you could refer to an appspace, because its address is its name. Nice and easy.&lt;/p&gt;
&lt;p&gt;Then came Tailscale, and each appsapce is its own Tailscale node, and all of a sudden appspaces have two names: the subdomain based one, and the Tailscale one, which is somename.tailxxxxx.ts.net for example.&lt;/p&gt;
&lt;p&gt;The Tailscale integration works really well. It&amp;rsquo;s a fantastic way of accessing a personal web-app from your phone or laptop from anywhere in the world. In fact it&amp;rsquo;s so good that if you only use Dropserver for personal stuff, a domain name pointing to your Dropserver instance is kind of unnecessary.&lt;/p&gt;
&lt;p&gt;Not just unnecessary! It can be painful to set up and it costs money too.&lt;/p&gt;
&lt;p&gt;Using a domain name to access &lt;code&gt;ds-host&lt;/code&gt; typically involves making your instance accessible via a public IP, which makes it a target of bots and crackers. You need to buy and renew that domain name, point it to the right IP etc&amp;hellip; All these things are surmountable, especially for regular web developers. But my goal is to bring self-hosting to non-tech people, and ditching the requirement for a domain name is a big win.&lt;/p&gt;
&lt;p&gt;Going beyond Tailscale I am thinking about creating an integration with a &lt;a href=&#34;https://github.com/anderspitman/awesome-tunneling&#34;&gt;tunneling service&lt;/a&gt;. Those also sometimes offer use of their own domains, so once again, no need to bring your own.&lt;/p&gt;
&lt;p&gt;In the end the goal is to let people run Dropserver on some small computer in their home, and use one of these tunneling for software-defined network services to make that instance accessible as appropriate for their use case. But this all means that &amp;ldquo;the domain is defined in the config file&amp;rdquo; is completely inappropriate.&lt;/p&gt;
&lt;h2 id=&#34;removing-the-requirement-for-domain-names&#34;&gt;Removing the Requirement for Domain Names&lt;/h2&gt;
&lt;p&gt;The problem right now is the entire Dropserver code assumes a domain is set in the config file. When you think you&amp;rsquo;re building something in a bog standard way from day one, as I was doing with Dropserver, the assumptions you made have had all that time to take root and spread their tentacles all over the code.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll need to figure out how I &amp;ldquo;name&amp;rdquo; appspaces when their subdomain+domain is no longer necessarily a thing. But that will be for a different time.&lt;/p&gt;
&lt;p&gt;As I explored the code, I found that a big dependent of domain name is the &amp;ldquo;DropID&amp;rdquo; concept that I hallucinated long ago and baked deep into the system.&lt;/p&gt;
&lt;p&gt;A DropID is a handle (username) and a domain. It&amp;rsquo;s like an email address, but there is no mailbox. It&amp;rsquo;s just a way of uniquely identifying a user (the &lt;code&gt;ds-host&lt;/code&gt; instance ensures usernames are unique, and on a public domain name the domain part is unique too.)&lt;/p&gt;
&lt;p&gt;Why did I create this thing?&lt;/p&gt;
&lt;h2 id=&#34;appspaces-users-and-dropids&#34;&gt;Appspaces, Users, and DropIDs&lt;/h2&gt;
&lt;p&gt;I dislike having to create a username and password for every new service I do anything with. I dislike using &lt;a href=&#34;https://en.wikipedia.org/wiki/OAuth&#34;&gt;OAuth&lt;/a&gt; because it gives too much control to the identity provider (usually giant megacorps) over my access to that service.&lt;/p&gt;
&lt;p&gt;Should Dropserver become popular one day, with each person running their own instance, then joining a friend&amp;rsquo;s appspace would mean becoming a user on their instance (username + password). That&amp;rsquo;s friction and I don&amp;rsquo;t like it.&lt;/p&gt;
&lt;p&gt;So I decided that Dropserver should be federated in some way. Two instances would be able to talk to each other and a user of one instance could obtain a login token to a different appspace from their own instance.&lt;/p&gt;
&lt;p&gt;(Totally not reinventing OAuth over here 🤦‍♂️)&lt;/p&gt;
&lt;p&gt;This works if instances are on the public internet with a registered domain and TLS. That was my assumption back then so I didn&amp;rsquo;t question it.&lt;/p&gt;
&lt;p&gt;(I am not going to go into the details of how this worked because I can tell this post is going to be long enough.)&lt;/p&gt;
&lt;p&gt;Instead of referring to users by the instance&amp;rsquo;s &lt;code&gt;user_id&lt;/code&gt;, appspaces referred to users by their dropIDs, which are ids that are globally unique, and that allows people to log in from a different instance.&lt;/p&gt;
&lt;p&gt;There are few things wrong here. First, it was half-baked. This kind of thing needs a lot of work to get right. I didn&amp;rsquo;t spend the  time, and it showed in the completely lame implementation.&lt;/p&gt;
&lt;p&gt;Second, really not a great idea to reinvent the wheel.&lt;/p&gt;
&lt;p&gt;Third, it&amp;rsquo;s only useful when people have their own instance. It leaves potential users who have not gone down the road of setting up the &lt;code&gt;ds-host&lt;/code&gt; (meaning everybody on the planet except me and maybe one or two other nerds) completely out of the loop.&lt;/p&gt;
&lt;h3 id=&#34;walls-versus-ramps&#34;&gt;Walls Versus Ramps&lt;/h3&gt;
&lt;p&gt;This could be its own blog post, but I&amp;rsquo;ve been thinking a lot about walls versus ramps. In short: what I should focus on is an easy way for non-Dropserver people to gain access to a DS appspace. Let them get into the system in the easiest way possible for the first time. Give them a ramp.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been talking lately about making Dropserver work on computers users already have at home like a Mac or Windows machine (a ramp) instead of asking them to learn Linux (wall).&lt;/p&gt;
&lt;p&gt;By implementing DropIDs I was assuming many people would successfully climb walls. Instead I should focus on building ramps that help people get into Dropserver to begin with.&lt;/p&gt;
&lt;h2 id=&#34;its-a-new-year&#34;&gt;It&amp;rsquo;s a New Year&lt;/h2&gt;
&lt;p&gt;In 2025 I managed to ship Tailscale integration, and got &lt;code&gt;ds-host&lt;/code&gt; builds for the Mac and for arm64. Then I got to work on simplifying configuration and installation of Dropserver. Work is slow, but steady.&lt;/p&gt;
&lt;p&gt;In 2026 I&amp;rsquo;ll continue to make Dropserver easier to get into (ramp) by reducing the requirements for a basic minimal install that is useful and safe for serving personal web apps.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - October 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-oct-2025/</link>
      <pubDate>Sat, 15 Nov 2025 15:19:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-oct-2025/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for October 2025. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-sept-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This month I continued thinking about how to make &lt;a href=&#34;dropserver.org/docs/ds-host&#34;&gt;&lt;code&gt;ds-host&lt;/code&gt;&lt;/a&gt; easy to install, but I also got to work on some real improvements. In particular I found out that my MacOS build of &lt;a href=&#34;https://dropserver.org/docs/ds-dev&#34;&gt;&lt;code&gt;ds-dev&lt;/code&gt;&lt;/a&gt; was broken&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;fixing-releases-to-support-arm64&#34;&gt;Fixing Releases to Support arm64&lt;/h2&gt;
&lt;p&gt;My Github Action that builds the Dropserver releases used the &lt;code&gt;macos-latest&lt;/code&gt; &lt;a href=&#34;https://github.com/actions/runner-images&#34;&gt;image&lt;/a&gt; to build &lt;code&gt;ds-dev&lt;/code&gt;. That image used to be Intel-powered. At some point Github decided to make it an arm64 machine.&lt;/p&gt;
&lt;p&gt;The result: my builds of &lt;code&gt;ds-dev&lt;/code&gt; that stopped working on Intel.&lt;/p&gt;
&lt;p&gt;Since I had been wanting to release an arm64 version of &lt;code&gt;ds-host&lt;/code&gt; and &lt;code&gt;ds-dev&lt;/code&gt; for Linux to support the Raspberry Pi and other SBCs I decided to rewrite the Github Actions to fully support multi-arch and multi-OS releases.&lt;/p&gt;
&lt;p&gt;I also separated the building of release artifacts from the actual release, allowing me to build for platforms even if I don&amp;rsquo;t release them. This lets me test on unreleased platforms without having to build on that platform.&lt;/p&gt;
&lt;p&gt;See all these &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commits/master/?since=2025-10-13&amp;amp;until=2025-10-24&#34;&gt;commits&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;0142-release-for-linuxarm64&#34;&gt;0.14.2 Release for Linux/Arm64&lt;/h2&gt;
&lt;p&gt;Dropserver &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.14.2&#34;&gt;0.14.2&lt;/a&gt; includes binaries for Linux-arm64 for &lt;code&gt;ds-host&lt;/code&gt; and &lt;code&gt;ds-dev&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I tested &lt;code&gt;ds-host&lt;/code&gt; out on my old Raspberry Pi 4B (4 Gigs of RAM) and it worked fine. Sandbox start times are a bit slower (300ms instead of 150ish), but that&amp;rsquo;s still highly usable. So now Dropserver works on a small cheap SBC! Nice.&lt;/p&gt;
&lt;h2 id=&#34;0144-release-ds-host-for-macos-on-intel-and-arm64&#34;&gt;0.14.4 Release ds-host for MacOS on Intel and Arm64&lt;/h2&gt;
&lt;p&gt;I have long had a &lt;code&gt;ds-dev&lt;/code&gt; build for Mac, and while working on the Tailscale integration I tested &lt;code&gt;ds-host&lt;/code&gt; locally on my Mac to save time. So I have some confidence that Dropserver works fine on the Mac.&lt;/p&gt;
&lt;p&gt;I only had to make it so the &amp;ldquo;linuxy&amp;rdquo; bits don&amp;rsquo;t show thorough on the Mac and it was ready to go. Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/4a6803a7b46f5064c18dc4e37b618a8befdfafc3&#34;&gt;4a6803a&lt;/a&gt; disables cgroups and bwrap on darwin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.14.4&#34;&gt;Dropserver 0.14.4&lt;/a&gt; 🎉&lt;/p&gt;
&lt;p&gt;The rest was mostly about docs, and me learning how to run a service on a Mac. &lt;a href=&#34;https://en.wikipedia.org/wiki/Launchd&#34;&gt;Launchd&lt;/a&gt; is quite different from &lt;a href=&#34;https://en.wikipedia.org/wiki/Systemd&#34;&gt;systemd&lt;/a&gt;. It likes to quietly do nothing that you&amp;rsquo;re asking it to do instead of printing an error.&lt;/p&gt;
&lt;p&gt;For now the &lt;a href=&#34;https://dropserver.org/docs/ds-host-mac&#34;&gt;docs&lt;/a&gt; show how to run &lt;code&gt;ds-host&lt;/code&gt; as your main user. This is of course not ideal, and it leads me to the next thing:&lt;/p&gt;
&lt;h2 id=&#34;sandboxing-on-macos&#34;&gt;Sandboxing on MacOS&lt;/h2&gt;
&lt;p&gt;I talked last month about how I am moving away from two-layer (&lt;a href=&#34;https://deno.com&#34;&gt;Deno&lt;/a&gt; + &lt;a href=&#34;https://github.com/containers/bubblewrap&#34;&gt;bubblewrap&lt;/a&gt;) sandboxing of app instances. I&amp;rsquo;m trusting Deno more as the primary sandbox and I think a sandbox around &lt;code&gt;ds-host&lt;/code&gt; and its Deno sub-processes makes more sense as the secondary sandbox.&lt;/p&gt;
&lt;p&gt;This was a good opportunity to experiment with the Mac&amp;rsquo;s sandboxing abilities.&lt;/p&gt;
&lt;p&gt;Unfortunately I didn&amp;rsquo;t get far.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://igorstechnoclub.com/sandbox-exec/&#34;&gt;&lt;code&gt;sandbox-exec&lt;/code&gt;&lt;/a&gt; should be very effective as it&amp;rsquo;s pretty low-level, but it&amp;rsquo;s not easy  to get it working. If you block everything by default there is a lot of work needed to figure out what needs to be allowed for the program to work. I didn&amp;rsquo;t have the time to go all the way with this so I&amp;rsquo;m punting.&lt;/p&gt;
&lt;p&gt;If I can&amp;rsquo;t get that to work I can at least start with an allow by default, and then restrict reading and writing to the user&amp;rsquo;s files outside of the ds-host data dir. That would protect the user&amp;rsquo;s stuff at least.&lt;/p&gt;
&lt;p&gt;Launchd also has some capabilities, like &lt;code&gt;RootDirectory&lt;/code&gt;, which is essentially &lt;code&gt;chroot&lt;/code&gt;, but I haven&amp;rsquo;t played with that, and it&amp;rsquo;s likely not the way to do things anymore.&lt;/p&gt;
&lt;p&gt;Finally it seems the way things are done now is through the &lt;a href=&#34;https://developer.apple.com/documentation/security/app-sandbox&#34;&gt;App Sandbox&lt;/a&gt;. &lt;code&gt;ds-host&lt;/code&gt; itself would call the Mac&amp;rsquo;s sandboxing features to specify how it wants to be contained. Although &lt;a href=&#34;https://stackoverflow.com/a/61880980&#34;&gt;this answer&lt;/a&gt; indicates it&amp;rsquo;s a very coarse kind of sandboxing, so less valuable (but easier to get right no doubt!)&lt;/p&gt;
&lt;p&gt;If you are knowledgeable about sandboxing things on the Mac and you want to help out, please reach out!&lt;/p&gt;
&lt;h2 id=&#34;work-on-ds-dev-for-windows&#34;&gt;Work on ds-dev for Windows&lt;/h2&gt;
&lt;p&gt;Two years ago I tried to get &lt;code&gt;ds-dev&lt;/code&gt; to work on my Windows machine. I was traveling recently with my Windows Laptop so I decided to take another stab at it.&lt;/p&gt;
&lt;p&gt;First I had to bring that branch up to speed. It was over 150 commits behind. Fun.&lt;/p&gt;
&lt;p&gt;Then I set things up so I can test the code from a Linux WSL2 instance of Debian in addition to normal Windows OS. That way as I mess around to get things to work on Windows I can verify that the tests still pass on Linux.&lt;/p&gt;
&lt;p&gt;I made some progress on the smaller more obvious fixes. Almost everything is a question of how to handle paths, really.&lt;/p&gt;
&lt;p&gt;But the real crux of the problem is centered on the Deno sandbox. The problem is that there are paths everywhere: some get passed to Deno via cli args, some are written to the import map, some are written to JS code as imports, some fetch files from Go&amp;rsquo;s virtual filesystem, some from Deno, etc&amp;hellip; In each case I&amp;rsquo;m not completely clear what format (slash type, &amp;ldquo;C:\\&amp;rdquo;??) is understood or expected.&lt;/p&gt;
&lt;p&gt;So there is a lot more work to do there, but one day I hope &lt;code&gt;ds-dev&lt;/code&gt;, and then &lt;code&gt;ds-host&lt;/code&gt; will work on Windows natively.&lt;/p&gt;
&lt;h2 id=&#34;heres-to-another-mid-month-update&#34;&gt;Here&amp;rsquo;s to Another Mid-Month Update&lt;/h2&gt;
&lt;p&gt;And that is all for October. I am quite happy with the progress I made. I have releases for hardware that is more likely to be available and familiar to people, making Dropserver more accessible. Installation process is still bad, but I&amp;rsquo;m on it.&lt;/p&gt;
&lt;p&gt;I said a month ago I&amp;rsquo;d try to write this sooner after the end of the month. Looks like I failed. Oh well.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m excited to share the &amp;ldquo;cleanup on aisle 6&amp;rdquo; type of work I&amp;rsquo;m doing in November. See you in early December! Or mid-December.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - September 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-sept-2025/</link>
      <pubDate>Tue, 14 Oct 2025 19:27:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-sept-2025/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for September 2025. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-august-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;bubblewrap-woes&#34;&gt;Bubblewrap woes&lt;/h2&gt;
&lt;p&gt;Dropserver uses &lt;a href=&#34;https://github.com/containers/bubblewrap&#34;&gt;Bubblewrap&lt;/a&gt; as a &lt;a href=&#34;https://olivierforget.net/blog/2023/dropserver-sandbox/&#34;&gt;second layer sandbox&lt;/a&gt;. &lt;code&gt;bwrap&lt;/code&gt; uses &lt;a href=&#34;https://www.man7.org/linux/man-pages/man7/namespaces.7.html&#34;&gt;Linux namespaces&lt;/a&gt; to create its sandbox, and as such things can sometimes get prickly.&lt;/p&gt;
&lt;p&gt;For some reason, on Debian 12 I can not get &lt;code&gt;ds-host&lt;/code&gt; to start a sandbox with &lt;code&gt;bwrap&lt;/code&gt; enabled when it is running from systemd. It works fine when I start it up manually, but as a systemd service, no go. I tried &lt;a href=&#34;https://social.tchncs.de/@teleclimber/115141982542092834&#34;&gt;all kinds of things&lt;/a&gt; and I just can&amp;rsquo;t get it to work. Something is different in this situation and I don&amp;rsquo;t know what and I just can&amp;rsquo;t get it to work.&lt;/p&gt;
&lt;p&gt;The folks over at Sandstorm have also &lt;a href=&#34;https://docs.sandstorm.io/en/latest/administering/install-troubleshooting/&#34;&gt;had some issues&lt;/a&gt; with Linux distros (Ok I mean Ubuntu) making it harder for some namespace features to work.&lt;/p&gt;
&lt;p&gt;There are real security issues to be fair. This &lt;a href=&#34;https://groups.google.com/g/linux.debian.bugs.dist/c/ZF9rWY3DR5w&#34;&gt;thread&lt;/a&gt; gives some idea of what&amp;rsquo;s on the maintainers&#39; minds.&lt;/p&gt;
&lt;h3 id=&#34;de-emphasizing-bubblewrap&#34;&gt;De-emphasizing Bubblewrap&lt;/h3&gt;
&lt;p&gt;For my project, I think it&amp;rsquo;s best to continue to support Bubblewrap as long as it works. However I will not recommend it so much anymore.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s harder and harder to get it to work&lt;/li&gt;
&lt;li&gt;It doesn&amp;rsquo;t offer significant additional security. Deno is fairly mature and stable and should be enough.&lt;/li&gt;
&lt;li&gt;My goal is to support platforms other than Linux, where this kind of fine-grained sandboxing doesn&amp;rsquo;t exist anyways.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;d rather focus on making sure the way I use Deno is safe rather than trying to wrestle with &lt;code&gt;bwrap&lt;/code&gt;, which is only available on one platform.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll rearrange the docs to put the &lt;code&gt;bwrap&lt;/code&gt; stuff in a separate page for those who feel they really want this.&lt;/p&gt;
&lt;h2 id=&#34;tailscale-in-the-real-world&#34;&gt;Tailscale in the Real World&lt;/h2&gt;
&lt;p&gt;I was thrilled to &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/&#34;&gt;finally ship&lt;/a&gt; &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; integration and I still think it&amp;rsquo;s transformative for people who self-host.&lt;/p&gt;
&lt;p&gt;However my experience trying to get some people hooked up with the app on their phones has been less than great. Installation is easy and quick, but for some people, it&amp;rsquo;s a legit battery drain.&lt;/p&gt;
&lt;p&gt;Nobody likes their phone losing battery faster than normal. It&amp;rsquo;s just something about the current moment in smartphone tech. Batteries last long on a good phone, but battery vampires are never welcome. So I have some people who have the Tailscale app but leave it turned off until they need it, which&amp;hellip; OK. 😔&lt;/p&gt;
&lt;p&gt;I know Tailscale has done a lot of work on battery issues for their apps, but you can still see a number of complaints in recent app reviews. I suppose there is only so much they can do yet I still hope it gets better somehow.&lt;/p&gt;
&lt;h3 id=&#34;occasionally-laggy&#34;&gt;Occasionally laggy&lt;/h3&gt;
&lt;p&gt;Once in a while, I&amp;rsquo;ll open the Leftovers app and it will sit there with the refresh spinner running. If I refresh the app it sits there trying to load.&lt;/p&gt;
&lt;p&gt;At other times, in fact most of the time, it&amp;rsquo;s blazingly fast.&lt;/p&gt;
&lt;p&gt;But when it stalls we&amp;rsquo;re talking 7 to 10 seconds of lag here. A painful wait.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m pretty sure it&amp;rsquo;s a Tailscale issue. I&amp;rsquo;ve only seen this behavior on the apps I access from Tailscale, and the logs don&amp;rsquo;t indicate a slow request processing time (I do need better request logging in ds-host though).&lt;/p&gt;
&lt;p&gt;I have a suspicion that it&amp;rsquo;s a DNS issue, but I suppose it could be anything in the process of connecting a tunnel. When I tried to observe the requests by connecting the phone to the Chrome debugger, I was unable to reproduce the issue. Weird.&lt;/p&gt;
&lt;p&gt;Also, it&amp;rsquo;s not always the case. In September I experienced the lag frequently. Now in October it seems much better? Though it still happens. Maybe TS was having some difficulty, though their status panel never showed a problem.&lt;/p&gt;
&lt;h2 id=&#34;leftovers-app-work&#34;&gt;Leftovers App Work&lt;/h2&gt;
&lt;p&gt;I improved the &lt;a href=&#34;https://leftovers.olivierforget.net/&#34;&gt;Leftovers app&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I added a ❄️Freezer❄️ section. You can now specify that items are in the freezer and set their expiry time in months instead of days. Commit &lt;a href=&#34;https://github.com/teleclimber/Leftovers/commit/21dfb724aa4a310d5825221e569c37aa178fcc84&#34;&gt;21dfb72&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The data automatically reloads every time the app visibility changes to &amp;ldquo;visible&amp;rdquo;. This helps ensure you&amp;rsquo;re always looking at the freshest (ha) food listing. Commit &lt;a href=&#34;https://github.com/teleclimber/Leftovers/commit/605d18b78c515ed3c684bd2baa16252eee157446&#34;&gt;605d18b&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I added a little spinner that shows the data loading. A tap causes the data to load again. I fiddled with CSS animations until I could get the spinner to slow down convincingly instead of abruptly stopping. Sometimes I like playing with CSS. (See commit above.)&lt;/li&gt;
&lt;li&gt;Fought a battle with &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;postcss.config.js&lt;/code&gt; and &lt;code&gt;vite.config.js&lt;/code&gt; and &lt;code&gt;yarn&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; to upgrade to Tailwind 4. I &lt;em&gt;never&lt;/em&gt; enjoy playing with these sickos. Commit &lt;a href=&#34;https://github.com/teleclimber/Leftovers/commit/41b255730817a875ce3b36bab7863b89e3d77797&#34;&gt;41b2557&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Version 0.7.0 of Leftovers is now out. The previous significant update was 18 months earlier. I enjoy the pace of development of home-cooked apps.&lt;/p&gt;
&lt;h2 id=&#34;brainstorming-better-install-experience-for-ds-host&#34;&gt;Brainstorming Better Install Experience for ds-host&lt;/h2&gt;
&lt;p&gt;I spent the rest of the month thinking about how I can improve the installation experience for &lt;code&gt;ds-host&lt;/code&gt;. As it stands it&amp;rsquo;s really pretty poor. I keep running into this myself when I want to quickly install it to test something out and I just can&amp;rsquo;t do it quickly, even though it&amp;rsquo;s my project and I&amp;rsquo;ve done it many times. 😭&lt;/p&gt;
&lt;p&gt;Dropserver is my attempt at making self-hosting more approachable to non-tech users. But right now the installation experience completely defeats the whole effort of the project. So it&amp;rsquo;s what I&amp;rsquo;m tackling next, and I intend to make it good.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s going to require a rework of the config file and a number of assumptions that are baked into the code  (I talked about domain names, &amp;ldquo;DropIDs&amp;rdquo;, and other things &lt;a href=&#34;&#34;&gt;last month&lt;/a&gt;), but it needs to be done.&lt;/p&gt;
&lt;p&gt;I think this will have to be a separate blog post though.&lt;/p&gt;
&lt;h2 id=&#34;onwards&#34;&gt;Onwards&lt;/h2&gt;
&lt;p&gt;See you next month. I&amp;rsquo;ll try not to wait til mid-month to write the progress update. I already have exciting things to write about for October!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - August 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-august-2025/</link>
      <pubDate>Sun, 14 Sep 2025 16:45:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-august-2025/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for August 2025. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This month I worked on getting an instance of &lt;code&gt;ds-host&lt;/code&gt; running in my home. Now that it&amp;rsquo;s trivially easy to &lt;a href=&#34;https://dropserver.org/docs/connect-tailnet&#34;&gt;make an appspace a Tailscale node&lt;/a&gt;, running my instance away from the public internet is the way to go.&lt;/p&gt;
&lt;p&gt;But there are caveats! And new footguns! And countless little decisions I made while developing &lt;code&gt;ds-host&lt;/code&gt; that are no longer helpful! Finding all those out, and working on solutions occupied plenty of time.&lt;/p&gt;
&lt;h2 id=&#34;domain-names-should-not-be-required&#34;&gt;Domain Names Should Not Be Required&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;ds-host&lt;/code&gt; config file asks for the domain name of the instance. Oof. What if you don&amp;rsquo;t have one? Why do you have to have one?&lt;/p&gt;
&lt;p&gt;I used to think all instances would be on the public internet, with a domain or a zone pointing to their public IP. I no longer think this way.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s perfectly reasonable, and in fact it&amp;rsquo;s probably a good approach to run &lt;code&gt;ds-host&lt;/code&gt; on a machine at home, and access it exclusively through Tailscale. This takes care of all the networking challenges in one shot while being far more secure than exposing your instance to the public internet. It&amp;rsquo;s a giant win for self-hosters.&lt;/p&gt;
&lt;p&gt;So domain names should not be a requirement. While I was pulling on that thread, I wondered about all the ways someone might want to connect to their instance. It&amp;rsquo;s quite a matrix! See &lt;a href=&#34;https://github.com/teleclimber/Dropserver/issues/142&#34;&gt;issue 142&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;dropping-dropids&#34;&gt;Dropping DropIDs&lt;/h2&gt;
&lt;p&gt;What are DropIDs? I never got around to writing that up in the docs. So here is how they came about:&lt;/p&gt;
&lt;p&gt;One of the principles of Dropserver is that you can move your service from one instance to another without undue hurdles to climb (illustrated by the &lt;code&gt;move-your-sh**.png&lt;/code&gt; icon on the &lt;a href=&#34;https://dropserver.org&#34;&gt;home page&lt;/a&gt;). Since a user on the appspace may not be a user in the new instance, appspace users have to be identified by some sort of globally unique name.&lt;/p&gt;
&lt;p&gt;Imagine for a moment that I was even more naive than I am and had used the instance&amp;rsquo;s user ID as the appspace user ID? Is user #2 in one instance the same as user #2 in a different instance? Of course not.&lt;/p&gt;
&lt;p&gt;So I cooked up DropIDs. I was fully into the &amp;ldquo;every instance will have a public domain&amp;rdquo; phase of Dropserver, so using the instance&amp;rsquo;s domain name made sense! Your DropID is your instance&amp;rsquo;s domain with a username appended as a path, so &lt;code&gt;somedomain.com/oli&lt;/code&gt; could be my DropId.&lt;/p&gt;
&lt;p&gt;With that as the user identifier in appspaces, an owner could move an appspace to a new instance and there would be no confusion as to who&amp;rsquo;s who in the list of appspace users.&lt;/p&gt;
&lt;p&gt;But wait, did I mention that DropIDs were also part of:&lt;/p&gt;
&lt;h3 id=&#34;remote-logins&#34;&gt;Remote logins&lt;/h3&gt;
&lt;p&gt;DropIDs enabled remote logins to appspaces from other instances. If an appspace is on ownerdomain.com and a user is on an instance at userdomain.com, then that user could &amp;ldquo;join&amp;rdquo; that appspace from within their instance, and log in from there by clicking on a link from within their instance (no additional password needed.)&lt;/p&gt;
&lt;p&gt;I was really keen on this &amp;ldquo;federation&amp;rdquo; feature in ds-host. I didn&amp;rsquo;t want people to have to create accounts at countless Dropserver instances to be able to participate in other people&amp;rsquo;s appspaces.&lt;/p&gt;
&lt;p&gt;I implemented all this, but I did not give this capability the dev time it deserved. And something like this takes a lot of work to get right.&lt;/p&gt;
&lt;p&gt;Now that I fully expect many instances will be hidden from the internet and have no public domain name the whole idea falls apart.&lt;/p&gt;
&lt;h3 id=&#34;use-email-instead&#34;&gt;Use email instead&lt;/h3&gt;
&lt;p&gt;I still need a unique identifier because moving appspaces around is still key.&lt;/p&gt;
&lt;p&gt;I realized that the obvious one to use is email addresses. Everybody&amp;rsquo;s got one, and they are globally unique. Everybody knows what they look like and can recognize their friend&amp;rsquo;s addresses (sometimes).&lt;/p&gt;
&lt;p&gt;The only hiccup is that &lt;code&gt;ds-host&lt;/code&gt; currently does not send mail so I&amp;rsquo;ll need to be clear that the email is for identification, not for sending.&lt;/p&gt;
&lt;h3 id=&#34;no-more-remote-logins&#34;&gt;No more remote logins?&lt;/h3&gt;
&lt;p&gt;I still think it&amp;rsquo;s important to make it as easy as possible to let other appspace users log in to an appspace. But the picture is more complicated now. Tailscale is great, but nobody I know has the Tailscale app, especially among my non-technical friends.&lt;/p&gt;
&lt;p&gt;There is more thinking to do, but anything based on public domain names I now consider DOA. So the remote login aspect will go away in a future update along with DropIDs.&lt;/p&gt;
&lt;p&gt;I do hope to bring it back someday, but it will be quite different.&lt;/p&gt;
&lt;h2 id=&#34;ds-host-at-home-new-challenges&#34;&gt;ds-host At Home: New Challenges&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://dropserver.org/docs/ds-host&#34;&gt;Installing ds-host&lt;/a&gt; is a pain. I know this and plan on improving the situation as much as possible, but more concerns came up as I went through my own install at home.&lt;/p&gt;
&lt;h3 id=&#34;backing-up&#34;&gt;Backing up&lt;/h3&gt;
&lt;p&gt;Having my own instance at home brings up some new questions: what happens if this cheap hardware I bought gives up the ghost? I have lots of data on some of my appspaces and I do not wish to lose it. (My chat-style note/journaling app has 17,679 hand typed entries as of this moment.)&lt;/p&gt;
&lt;p&gt;I had to get &lt;a href=&#34;https://www.proxmox.com/en/&#34;&gt;Proxmox&lt;/a&gt; to generate backups of the VM once per night and place them on my Synology NAS. That&amp;rsquo;s good, but &lt;code&gt;ds-host&lt;/code&gt; itself should have built-in backup capabilities. It should be able to backup itself and all its appspaces periodically. You should also be able to backup appspaces to a remote location automatically. More things to think about.&lt;/p&gt;
&lt;h3 id=&#34;monitoring&#34;&gt;Monitoring&lt;/h3&gt;
&lt;p&gt;On my older instance I installed &lt;a href=&#34;https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/&#34;&gt;Grafana and Prometheus&lt;/a&gt; in a docker compose setup to monitor the ds-host instance and its VM. It worked fine, but it&amp;rsquo;s an unreasonable lift for non-technical people. Also, it generates tons of graphs that won&amp;rsquo;t make sense to most people.&lt;/p&gt;
&lt;p&gt;This led me to wonder what could be done to give just enough visibility and what are the use cases for visibility into runtime metrics?&lt;/p&gt;
&lt;p&gt;Running Dropserver should just work. Things that just work don&amp;rsquo;t require dashboards full of graphs of low level metrics. It&amp;rsquo;s important not to carry over habits from running public SaaS apps into the world of self-hosting private apps from home. These are different things, like a Formula 1 car is different from a Honda Civic. One requires constant care and attention by engineers and the other just runs.&lt;/p&gt;
&lt;p&gt;But sometimes even the Honda needs some love, so perhaps there should be something like a &amp;ldquo;check engine light&amp;rdquo; on &lt;code&gt;ds-host&lt;/code&gt;, and a page that gives current metrics that can be shared on a forum to help with diagnosis and resolution.&lt;/p&gt;
&lt;p&gt;More thought needed there.&lt;/p&gt;
&lt;h2 id=&#34;onwards&#34;&gt;Onwards&lt;/h2&gt;
&lt;p&gt;That was long! The time spent pondering things this month will help me put my efforts in the right place in the following months.&lt;/p&gt;
&lt;p&gt;See you then!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - June and July 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/</link>
      <pubDate>Wed, 06 Aug 2025 12:22:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for June and July 2025. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-may-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In June I finally finished up the integration of &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; into Dropserver, then went on vacation. What remained of July was not terribly productive, but it was a good opportunity to think about where I should be going with this project.&lt;/p&gt;
&lt;h2 id=&#34;tailscale-integration&#34;&gt;Tailscale Integration&lt;/h2&gt;
&lt;p&gt;There were &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commits/master/?since=2025-06-01&amp;amp;until=2025-06-30&#34;&gt;21 commits in June&lt;/a&gt;. Lots of little things of course but some were the result of finally figuring out an effective UI for creating and managing a Tailscale node.&lt;/p&gt;
&lt;h3 id=&#34;tailscale-connection-ui&#34;&gt;Tailscale connection UI&lt;/h3&gt;
&lt;p&gt;I have found that the most reliable way to create a node in fewer steps is to use an &lt;a href=&#34;https://tailscale.com/kb/1085/auth-keys&#34;&gt;auth key&lt;/a&gt; generated from the Tailscale admin panel.&lt;/p&gt;
&lt;p&gt;By comparison, when using a login link, tags have to be specified (without typos) and are not applied reliably. Furthermore you usually end up interacting with the Tailscale admin UI anyways to remove key expiry for example (which should happen automatically, but once again, not reliable.)&lt;/p&gt;
&lt;p&gt;So I simplified the UI by removing the tags input line and I encourage users to create an auth key. Though if they don&amp;rsquo;t that&amp;rsquo;s fine too. Dropserver will show the login link and will detect misconfigurations (missing tags, etc&amp;hellip;) and guide the user to a fix.&lt;/p&gt;
&lt;p&gt;I also tweaked the Control URL. No more &amp;ldquo;leave blank to use Tailscale&amp;rdquo;. Now Tailscale.com is explicitly shown as the default control URL along with an affordance to &amp;ldquo;use alt control URL&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;By eliminating tags from the inputs the dialog becomes 25% simpler (3 lines instead of 4). Of those three lines, the &amp;ldquo;Hostname&amp;rdquo; line has a good default, the &amp;ldquo;Control URL&amp;rdquo; will be left untouched by most users, so all that&amp;rsquo;s left is the &amp;ldquo;Auth Key&amp;rdquo;. Not bad? See image below.&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/tailscale-connection-ui_hu1b457ca2da905da58cd7db1315c7da39_71487_717x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/tailscale-connection-ui_hu1b457ca2da905da58cd7db1315c7da39_71487_717x0_resize_box_3.png, https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/tailscale-connection-ui_hu1b457ca2da905da58cd7db1315c7da39_71487_1434x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing Dropserver&amp;#39;s Tailscale node creation UI.&#34;&gt;
&lt;p&gt;Here is what it looks like if you created a node but you are missing tags (and also do not have HTTPS turned on):&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/tailscale-fix-node-configuration_hu9cc8a13e4c7def9adfd2871e2b59f09d_135744_664x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/tailscale-fix-node-configuration_hu9cc8a13e4c7def9adfd2871e2b59f09d_135744_664x0_resize_box_3.png, https://olivierforget.net/blog/2025/dropserver-progress-june-july-2025/tailscale-fix-node-configuration_hu9cc8a13e4c7def9adfd2871e2b59f09d_135744_1328x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing Dropserver&amp;#39;s Tailscale node UI with messages indicating Tags are missing and  HTTPS is not enabled.&#34;&gt;
&lt;p&gt;Commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/fa8ebe8b75f037da1fea42df3106f21701e6185e&#34;&gt;fa8ebe8&lt;/a&gt;, &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/3f66f20044836bd2e63c9928189be66928111e87&#34;&gt;3f66f20&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/136d0d90d529aaf55939a7b187dfa8f1011513bd&#34;&gt;136d0d9&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;bug--poor-behavior-in-tsnet&#34;&gt;Bug / poor behavior in tsnet&lt;/h3&gt;
&lt;p&gt;While working on validating Control URLs I found that &lt;a href=&#34;https://tailscale.com/kb/1244/tsnet&#34;&gt;&lt;code&gt;tsnet&lt;/code&gt;&lt;/a&gt; does not error or timeout if you tell it to use a Control URL that is non-existent. I filed a &lt;a href=&#34;https://github.com/tailscale/tailscale/issues/16201&#34;&gt;bug with Tailscale&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If a user puts a typo in their control URL they will get no feedback whatsoever because of this. The UI will just sit there saying it&amp;rsquo;s waiting on a connection. Not Cool.&lt;/p&gt;
&lt;h2 id=&#34;release-finally&#34;&gt;Release (Finally)&lt;/h2&gt;
&lt;p&gt;I tagged and pushed &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.14.0&#34;&gt;v0.14.0&lt;/a&gt; on June 28. 🎉&lt;/p&gt;
&lt;p&gt;And promptly went on vacation. 😴&lt;/p&gt;
&lt;h2 id=&#34;what-next&#34;&gt;What Next?&lt;/h2&gt;
&lt;p&gt;Back from vacation I found myself not too terribly motivated to dive back into Dropserver. I usually prefer to leave with an unfinished project waiting, it makes it easier to get back into it. Also Tailscale integration took far too long, so I&amp;rsquo;m not surprised to feel the need to take some distance.&lt;/p&gt;
&lt;p&gt;After a few days hints of motivation appeared. With Tailscale done, I feel free to work on anything that could improve Dropserver. The question is what. Here are some possible directions:&lt;/p&gt;
&lt;h3 id=&#34;make-ds-easier-to-install-on-more-hosts&#34;&gt;Make DS easier to install on more hosts&lt;/h3&gt;
&lt;p&gt;This is the direction that I thought I should do while working on the Tailscale stuff. The Tailscale integration into Dropserver means you can have a usefully connected instance without doing anything like buying a domain name, opening ports, and making your network reachable by the outside world.&lt;/p&gt;
&lt;p&gt;Since Dropserver already focuses on making app installations trivially easy, the only remaining hurdle is the installation of Dropserver itself! I had originally thought that I&amp;rsquo;d offer a DS hosted service to get around this problem, but at this point I don&amp;rsquo;t think that&amp;rsquo;s the right approach. DS is about self hosting. (And I don&amp;rsquo;t want to try to run such a service!)&lt;/p&gt;
&lt;p&gt;So making ds-host as easy as possible to install, and making it installable on the computers and OS that a user has at home is key. This implies work on a number of areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rethink the &lt;a href=&#34;https://dropserver.org/docs/ds-host-config-ref&#34;&gt;config file&lt;/a&gt; to eliminate as many things that can be moved to the admin UI.&lt;/li&gt;
&lt;li&gt;Add a way to change the ds-host config without hand-editing a config file (maybe using a CLI or GUI program)&lt;/li&gt;
&lt;li&gt;Use operating system defaults for data and working directories instead of asking the admin to specify them.&lt;/li&gt;
&lt;li&gt;Find ways of packaging DS so that it can be more easily installed on Linux&lt;/li&gt;
&lt;li&gt;Make a build and maybe a package for Raspberry Pi&lt;/li&gt;
&lt;li&gt;Make a build for MacOS. &lt;code&gt;ds-host&lt;/code&gt; works fine on MacOS, I ran it on that platform throughout the development of the Tailscale integration.&lt;/li&gt;
&lt;li&gt;Continue to try to get it to run on Windows. That starts with getting a version of &lt;a href=&#34;https://dropserver.org/docs/ds-dev&#34;&gt;&lt;code&gt;ds-dev&lt;/code&gt;&lt;/a&gt; to run on Windows, then work on &lt;code&gt;ds-host&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Honestly that&amp;rsquo;s a lot and I won&amp;rsquo;t tackle all this at once. In the meantime there are other things I should look at.&lt;/p&gt;
&lt;h3 id=&#34;improve-user-management&#34;&gt;Improve user management&lt;/h3&gt;
&lt;p&gt;Tailscale integration forced some changes in how I think about users (both appspace users and users of the instance). In particular each user can have multiple ways of authenticating (username + password, tailnet ID, etc&amp;hellip;). Also, the concept of &amp;ldquo;DropID&amp;rdquo; which ties a user&amp;rsquo;s identity to a domain name no longer makes sense since &lt;code&gt;ds-host&lt;/code&gt; instances can be hidden from the public Internet thanks to Tailscale.&lt;/p&gt;
&lt;p&gt;It would be worthwhile to remove the concept of DropID from the system (though it is used in quite a few places so that has a domino effect unfortunately), and develop the &amp;ldquo;Contacts&amp;rdquo; functionality to make adding users to appspaces easier.&lt;/p&gt;
&lt;h3 id=&#34;better-backups&#34;&gt;Better backups&lt;/h3&gt;
&lt;p&gt;One project I&amp;rsquo;m definitely working on now is to move my own personal instance of &lt;code&gt;ds-host&lt;/code&gt; from a VM on the public cloud to my Proxmox instance running right here in my office. This is what Tailscale enables and I&amp;rsquo;m excited to disappear my instance from the public net.&lt;/p&gt;
&lt;p&gt;But this begs the question: what happens if my VM or its host blows up? All of a sudden I am responsible for my own backups 😓. I have 17,299 notes in my personal note taking/journaling app that runs on Dropserver so this is quite important to me!&lt;/p&gt;
&lt;p&gt;Of course I set up automated VM backups but it would be nice to have more granular backups of just the Dropserver data. It&amp;rsquo;s clear that &lt;code&gt;ds-host&lt;/code&gt; should come with the ability to generate and save backups of the instance data, or of individual appspace data, to an external source automatically.&lt;/p&gt;
&lt;h3 id=&#34;work-on-more-apps&#34;&gt;Work on more apps&lt;/h3&gt;
&lt;p&gt;When I work heavily on a capability like Tailscale integration, I don&amp;rsquo;t have any time left to improve the few existing apps or add new ones. I wouldn&amp;rsquo;t mind spending some time on this now.&lt;/p&gt;
&lt;h2 id=&#34;time-marches-on&#34;&gt;Time Marches On&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t expect to get huge amounts done in August with the kids out of school but whatever I do, I&amp;rsquo;ll try to make it a small project to avoid stretching months between releases.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - May 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-may-2025/</link>
      <pubDate>Tue, 10 Jun 2025 17:45:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-may-2025/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for May 2025. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-april-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Quick one this month because I was away on vacation for a good chunk of May.&lt;/p&gt;
&lt;h2 id=&#34;tailscale-integration&#34;&gt;Tailscale Integration&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; integration is nearly done now. I&amp;rsquo;m knocking out items on my todo list. The main thing I did this month was to experiment again with the open source alternatives to Tailscale &lt;a href=&#34;https://headscale.net&#34;&gt;Headscale&lt;/a&gt; and &lt;a href=&#34;https://jsiebens.github.io/ionscale/&#34;&gt;Ionscale&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I would really like for Dropserver to work with open alternatives to Tailscale, which is why I spent a decent amount of time trying both of them again.&lt;/p&gt;
&lt;h3 id=&#34;headscale&#34;&gt;Headscale&lt;/h3&gt;
&lt;p&gt;A major blocker with using Headscale with Dropserver is that it does not support serving over HTTPS. This means you do not get a &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts&#34;&gt;Secure Context&lt;/a&gt;, which can affect some apps. In my &lt;a href=&#34;https://leftovers.olivierforget.net/&#34;&gt;Leftovers app&lt;/a&gt;, the lack of secure context blocks use of the camera, and you can&amp;rsquo;t take pictures of the food you put in the fridge. Bummer.&lt;/p&gt;
&lt;p&gt;I had filed an &lt;a href=&#34;https://github.com/juanfont/headscale/issues/1921&#34;&gt;issue&lt;/a&gt; some time ago which resulted in a long discussion but little action (I personally do not have it in me to implement this for the Headscale project, sorry). Now, there is a new &lt;a href=&#34;https://github.com/juanfont/headscale/issues/2527&#34;&gt;issue by the maintainer&lt;/a&gt; laying out the roadmap for this feature to be implemented. So maybe Headscale will some day get HTTPS support for serve.&lt;/p&gt;
&lt;p&gt;A separate issue I ran into was that tailnet peers are &lt;a href=&#34;https://github.com/juanfont/headscale/issues/2375&#34;&gt;apparently not sent to tagged devices&lt;/a&gt;. This is a problem because Dropserver Tailnet nodes are &lt;a href=&#34;https://tailscale.com/kb/1068/tags&#34;&gt;tagged&lt;/a&gt; since they are non-user devices, and the list of peers is used to associate tailnet users to Dropserver and appspace users.&lt;/p&gt;
&lt;h3 id=&#34;ionscale&#34;&gt;Ionscale&lt;/h3&gt;
&lt;p&gt;I had to fiddle quite a bit to get Ionscale going. There are a number of issues in the docs that &lt;a href=&#34;https://github.com/jsiebens/ionscale/issues/76&#34;&gt;slowed me down&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However I did get it working (to a point). Tags were not being sent to the node which caused &lt;code&gt;ds-host&lt;/code&gt; to warn that a tag had to be applied to the node for it to work. Luckily this was &lt;a href=&#34;https://github.com/jsiebens/ionscale/issues/77&#34;&gt;resolved promptly&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I even got serve over HTTPS to work (though not before filing &lt;a href=&#34;https://github.com/jsiebens/ionscale/issues/80&#34;&gt;another issue&lt;/a&gt;). Ionscale is able to generate a certificate for your node if you provide it with a DNS nameserver and an API key.&lt;/p&gt;
&lt;p&gt;Ionscale &lt;a href=&#34;https://jsiebens.github.io/ionscale/configuration/auth-oidc/&#34;&gt;requires an OIDC provider&lt;/a&gt; to support the concept of a &amp;ldquo;user&amp;rdquo;. Wihtout that you don&amp;rsquo;t get peers at the node, and you have the same problme as with Headscale. I didn&amp;rsquo;t have it in me to sort out an OIDC situation after all the time spent on this, so I decided to move on. If someone wants to use Ionscale with Dropserver and it doesn&amp;rsquo;t work despite setting up OIDC, I hope they&amp;rsquo;ll file an issue.&lt;/p&gt;
&lt;h3 id=&#34;docs&#34;&gt;Docs&lt;/h3&gt;
&lt;p&gt;I started writing docs for connecting to Dropserver and Appspaces using Tailscale or its alternative open source clones.&lt;/p&gt;
&lt;p&gt;Good docs will be important here so I&amp;rsquo;m starting now.&lt;/p&gt;
&lt;h3 id=&#34;naming-things&#34;&gt;Naming things&lt;/h3&gt;
&lt;p&gt;I grew uncomfortable having references to &amp;ldquo;Tailscale&amp;rdquo; in the UI when there is a chance that Headscale or Ionscale is used. The term &lt;code&gt;tsnet&lt;/code&gt; which is the tailscale library has no meaning for users. I decided to change the UI to use the term &amp;ldquo;tailnet&amp;rdquo; as much as possible. I found that this term is used by both Headscale and Ionscale, and it is apparently not trademarked.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll still use Tailscale when it&amp;rsquo;s directly relevant.&lt;/p&gt;
&lt;p&gt;Finally I use it in the title of the UI box: &amp;ldquo;Tailscale Node&amp;rdquo;. If a user connects to a non-Tailscale tailnet, the title changes &amp;ldquo;Tailnet Node&amp;rdquo;. Tailscale has a lot of name recognition, and I think it will be easier for users to get what that UI offers by using the full brand name.&lt;/p&gt;
&lt;h2 id=&#34;the-ever-dwindling-todo-list&#34;&gt;The Ever Dwindling TODO List&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m at the phase of the project where the TODO list is no longer growing. In fact at this point it&amp;rsquo;s pretty short and it&amp;rsquo;s getting shorter.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not going to say what I hope to have done by the end of June. Nope. Not gonna say it.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll see you right here next month, whatever happens (or doesn&amp;rsquo;t happen).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - April 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-april-2025/</link>
      <pubDate>Wed, 07 May 2025 12:05:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-april-2025/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for April 2025. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-march-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;tailscale-integration-for-the-admin-side-of-dropserver&#34;&gt;Tailscale Integration for the Admin Side of Dropserver&lt;/h2&gt;
&lt;p&gt;Recapping where I was: I got &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; integration working pretty well for appspaces (an appspace is a running app in Dropserver, see &lt;a href=&#34;https://dropserver.org/docs/application-model&#34;&gt;here&lt;/a&gt;.) Meaning that you can access the apps that you host on Dropserver via tailnet node in addition to via the regular Internet. Now I want to give access to the admin side of &lt;a href=&#34;https://dropserver.org/docs/ds-host&#34;&gt;&lt;code&gt;ds-host&lt;/code&gt;&lt;/a&gt; via Tailscale. This is where Dropserver users go to install apps, create appspaces, and generally manage their Dropserver stuff.&lt;/p&gt;
&lt;p&gt;After completing the work of making my &lt;a href=&#34;https://tailscale.com/kb/1244/tsnet&#34;&gt;&lt;code&gt;tsnet&lt;/code&gt;&lt;/a&gt; integration code more generic (it was heavily geared towards serving appspaces) it was time to work on connecting a node for user and admin side of ds-host.&lt;/p&gt;
&lt;h3 id=&#34;setting-up-users-with-tailnet-credentials&#34;&gt;Setting up users with tailnet credentials&lt;/h3&gt;
&lt;p&gt;As with appspaces I decided that access via a tailnet node should be one of multiple ways of accessing Dropserver. A user can have tailnet credentials, and can also have a username and password should they choose to log in via a more traditional network.&lt;/p&gt;
&lt;p&gt;I had to make having an email and password optional. If a user connects via a tailnet, the authentication is taken care of, so forcing them to choose an email and pw is just an obstruction. This required some DB changes because of course the email and password columns were &lt;code&gt;NOT NULL&lt;/code&gt; and I had a unique index on email. There was also a domino effect of changes in the UI.&lt;/p&gt;
&lt;p&gt;Commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/f493857a141cc20e0f82c94533abf47f3ec32d1b&#34;&gt;f493857&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/420dcdda4bd5e42fb4ac2210c28681c744584348&#34;&gt;420dcdd&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;associating-tailnet-peers-with-ds-host-users&#34;&gt;Associating tailnet peers with ds-host users&lt;/h3&gt;
&lt;p&gt;After pondering on the possible situations that a &lt;a href=&#34;https://dropserver.org/docs/ds-host&#34;&gt;&lt;code&gt;ds-host&lt;/code&gt;&lt;/a&gt; admin may face:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They have existing users on their &lt;code&gt;ds-host&lt;/code&gt; instance, and just connected to a tailnet. They have to associate peer users from that tailnet with existing &lt;code&gt;ds-host&lt;/code&gt; users.&lt;/li&gt;
&lt;li&gt;They are connected to a tailnet and want to give access to someone new. This implies creating a new &lt;code&gt;ds-host&lt;/code&gt; user with credentials from that tailnet.&lt;/li&gt;
&lt;li&gt;They made a mistake in any of the above and have to break associations and start over&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I settled on these UI choices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When looking at tailnet settings, for each peer user of the tailnet, the admin can use a dropdown to select the ds-host user that should be associated, the last option in the dropdown is &amp;ldquo;create new user&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;When looking at a user, the admin can select which tailnet peer user to associate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In both cases, the UI respects the requirement that there is only a one-to-one relation between ds-host and tailnet users. One tailnet user can not be associated with two ds-host users, and vice versa.&lt;/p&gt;
&lt;p&gt;Commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/d629d08fbad1de9f0ec2d25638d68bbdd579fd62&#34;&gt;d629d08&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/ca99594001c81d92d9b294652f281ee78a5cbb8b&#34;&gt;ca99594&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;connecting-tsnet-to-user-and-admin-routes&#34;&gt;Connecting tsnet to user and admin routes&lt;/h3&gt;
&lt;p&gt;As mentioned above a tailnet is but one way to access your Dropserver instance. &lt;code&gt;ds-host&lt;/code&gt; has multiple servers: one for responding to requests from the Internet, and one that is on a tailnet and responds to requests from that world.&lt;/p&gt;
&lt;p&gt;Both serve routes like the user home page, and the admin pages just the same, but the authentication and authorization steps are different. Also, the &amp;ldquo;Internet&amp;rdquo; routes include the login, logout, and user registration pages, which are not reachable while accessing ds-host from a tailnet (because they make no sense there).&lt;/p&gt;
&lt;p&gt;So there are two routers, one called &lt;code&gt;FromPublic&lt;/code&gt; and the other &lt;code&gt;FromTSNet&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;FromPublic&lt;/code&gt; router can serve login/logout routes, and takes a request&amp;rsquo;s cookie to determine the authenticated user, adds the ID to the request&amp;rsquo;s context and passes control to the &amp;ldquo;user routes&amp;rdquo; router.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;FromTSNet&lt;/code&gt; router looks up the user id based on the tailnet peer&amp;rsquo;s ID, puts that in the context and passes the control onwards.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This arrangement helps me keep things decoupled and clear.&lt;/p&gt;
&lt;p&gt;Once I had it all wired up, it worked on the first shot*. I was able to access ds-host running on my iMac from my phone through a tunnel managed by Tailscale. It felt great. I feel like I&amp;rsquo;m almost there.&lt;/p&gt;
&lt;p&gt;Commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/3355234e8285e4e060114b4e34d5f54a58bad5ea&#34;&gt;3355234&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/757df0534acb7bd434312dae7f03036de3a1fcbb&#34;&gt;757df05&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;getting-close&#34;&gt;Getting close&lt;/h3&gt;
&lt;p&gt;With that functional, I turned to my todo list which is still quite long but many items are fairly quick. I started by knocking out validations, which was a bit of work because Tailscale&amp;rsquo;s naming limitations are not intuitive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Machine names: alpha numeric and dashes are allowed; must start and end with alpha or numeric.&lt;/li&gt;
&lt;li&gt;ACL tags: alpha numeric and dashes allowed, must start with alpha (not numeric!), can end in dash 🤷‍♂️&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/ab6183b0f363f832134a0df4fc922d4220ca2736&#34;&gt;ab6183b&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;bye-for-now&#34;&gt;Bye For Now&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll be unable to work for part of May, so the next progress report will be shorter.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;*: 11 months of work were necessary to get to that magical &amp;ldquo;it worked on the first shot&amp;rdquo;.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - March 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-march-2025/</link>
      <pubDate>Wed, 09 Apr 2025 12:49:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-march-2025/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for March 2025. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-february-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;dropserverorg-docs-pages-and-modern-css&#34;&gt;Dropserver.org Docs Pages and Modern CSS&lt;/h2&gt;
&lt;p&gt;I spent some time at the beginning of the month making the Docs pages of Dropserver.org easier to use. In particular I wanted to have the navigation in the sidebar instead of a separate page, this makes casually browsing the docs far more user-friendly.&lt;/p&gt;
&lt;p&gt;But this was not just an effort to improve the docs pages. I want to improve my HTML and CSS skills so I took the time to really dig into new techniques for this little project.&lt;/p&gt;
&lt;p&gt;Some years ago I got sucked into the whole Tailwind thing, but I have regrets. The &lt;code&gt;ds-host&lt;/code&gt; UI is made with Tailwind, and while it was quick to get going and have it look decent, now it feels like tweaking the look of the UI is impossible. Also I dislike having so many class names in the HTML.&lt;/p&gt;
&lt;p&gt;So part of this is exercising my atrophied HTML and CSS muscles, so that I can rebuild my Tailwind code some day.&lt;/p&gt;
&lt;p&gt;I could have just used &lt;a href=&#34;https://starlight.astro.build/&#34;&gt;Starlight&lt;/a&gt; since Dropserver.org is built with &lt;a href=&#34;https://astro.build/&#34;&gt;Astro&lt;/a&gt; but instead I reverse engineered (aka copied) their layout and learned a few things along the way.&lt;/p&gt;
&lt;p&gt;It took a bit of time, but I was able to get familiar with new (to me) CSS features like &lt;code&gt;:has()&lt;/code&gt; and &lt;code&gt;:not()&lt;/code&gt; and &lt;code&gt;clamp()&lt;/code&gt; and others.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s just the tip of the iceberg. Features like &lt;code&gt;@scope&lt;/code&gt; and &lt;code&gt;@layers&lt;/code&gt; will really help keep CSS stylesheets manageable, which is the challenge that drew me to Tailwind in the first place.&lt;/p&gt;
&lt;p&gt;See the result here: &lt;a href=&#34;https://dropserver.org/docs/&#34;&gt;Dropserver.org/docs/&lt;/a&gt;. Note the collapsible menu &lt;a href=&#34;https://social.tchncs.de/@teleclimber/114139931695838184&#34;&gt;works without JS&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&#34;tailscale-for-the-dropserver-admin-panel&#34;&gt;Tailscale For the Dropserver Admin Panel&lt;/h2&gt;
&lt;p&gt;Work continues on making the admin and user routes available via &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt;. Yes that&amp;rsquo;s right all the work I&amp;rsquo;ve done so far was focused on making &lt;code&gt;tsnet&lt;/code&gt; nodes for individual appspaces, so now I have to do similar (but different!) work to make the user&amp;rsquo;s &lt;code&gt;ds-host&lt;/code&gt; control panel accessible from yet another &lt;code&gt;tsnet&lt;/code&gt; node.&lt;/p&gt;
&lt;p&gt;In order to not repeat myself the first task is to take as much of the code I wrote for serving appspaces via &lt;code&gt;tsnet&lt;/code&gt; and make it generic enough so that it can be used to serve other things.&lt;/p&gt;
&lt;p&gt;This is progressing well. It&amp;rsquo;s the kind of work that forces one to think more clearly about the core role of each part of the code. It&amp;rsquo;s a lot of work, but the result is clearer code.&lt;/p&gt;
&lt;p&gt;Commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/aa891dd924cb6154966bf72b5b70662047997f14&#34;&gt;aa891dd&lt;/a&gt;, &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/ea6093aadb0f955fe3f1ea125ba5172bc6fa6f71&#34;&gt;ea6093a&lt;/a&gt;, and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/aafdce93a81e643ee3fb98d547356ea455c991fc&#34;&gt;aafdce9&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;thinking-about-publishing-a-generic-library-for-integrating-tsnet&#34;&gt;Thinking about publishing a generic library for integrating tsnet?&lt;/h3&gt;
&lt;p&gt;Having done so much work to figure out &lt;code&gt;tsnet&lt;/code&gt; and build out a higher level API around it I wonder if I should publish this as a library.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t have a lot of confidence in some areas of my integration with &lt;code&gt;tsnet&lt;/code&gt;, so I would like other eyes to look at it. It&amp;rsquo;s much easier for Tailscale experts to point out mistakes and offer suggestions on better ways of doing things in a standalone library than in my gigantic Dropserver codebase.&lt;/p&gt;
&lt;p&gt;Plus, some projects might adopt it and point out bugs (highly likely) and even contributes fixes (LOL I wish 😓).&lt;/p&gt;
&lt;p&gt;Unsure if I am going to do this, but I am putting it out there.&lt;/p&gt;
&lt;h2 id=&#34;keepinkeepinon&#34;&gt;Keepin&amp;rsquo;Keepin&amp;rsquo;On&lt;/h2&gt;
&lt;p&gt;Short one this time. I&amp;rsquo;d rather spend time making progress than writing about the lack of progress in a &amp;ldquo;Progress Report&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;See you next month.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - February 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-february-2025/</link>
      <pubDate>Wed, 12 Mar 2025 11:33:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-february-2025/</guid>
      <description>&lt;p&gt;This is the progress report from &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for February 2025. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-january-2025/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This month was extra-short thanks to a much-needed ski vacation, but I did manage to make some solid progress on integrating &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; into &lt;code&gt;ds-host&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;tailscale-users-as-appspace-users&#34;&gt;Tailscale Users as Appspace Users&lt;/h2&gt;
&lt;p&gt;After grinding on Vue templates, DB calls and everything in between, it&amp;rsquo;s now possible to assign multiple auth credentials to a single user. This means an appspace user can access the appspace via Tailscale, or via the public network or local network interchangeably.&lt;/p&gt;
&lt;p&gt;The UI needs some polish to say the least but the essence is there:&lt;/p&gt;
&lt;p&gt;Create a new user or assign the Tailscale identity to an existing appspace user:&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-user-associate_hub9d7c2058123e12da2a19c772c4ab978_138633_725x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-user-associate_hub9d7c2058123e12da2a19c772c4ab978_138633_725x0_resize_box_3.png, https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-user-associate_hub9d7c2058123e12da2a19c772c4ab978_138633_1450x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing a user selecting a tailscale user&#34;&gt;
&lt;p&gt;See who the peers are and the connected appspace user:&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-users_hu254ba3d84545625f829037fd76c1c5bb_79368_714x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-users_hu254ba3d84545625f829037fd76c1c5bb_79368_714x0_resize_box_3.png, https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-users_hu254ba3d84545625f829037fd76c1c5bb_79368_1428x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing users as tailscale peers associated with appspcae users.&#34;&gt;
&lt;p&gt;All this works while the Tailscale peers can change at any instant. The data is kept up-to-date on the frontend UI through a system of events inside of ds-host, and Server Sent Events to the browser (see &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-september-2024/&#34;&gt;September 2024 progress report&lt;/a&gt;). While I don&amp;rsquo;t love all-JS frontends, Vue reactivity is great for reflecting the latest state as soon as it shows up.&lt;/p&gt;
&lt;p&gt;Commit: &amp;ldquo;feat(ds-host): implement multiple auths per appspace user, including tsnetid&amp;rdquo; &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/10f47707e1cb20a9869140bdb45363de5f0cc1f2&#34;&gt;10f4770&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;identifying-tailscale-and-headscale-users&#34;&gt;Identifying Tailscale and Headscale Users&lt;/h3&gt;
&lt;p&gt;Tailscale users have a pretty solid looking ID that I understand is stable and unique. Using that to identify peers is natural, but there are a couple of gotchas.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://headscale.net/stable/&#34;&gt;Headscale&lt;/a&gt; user IDs are plain integers starting with 1. So user ids are 1, 2, 3, 4&amp;hellip; There can be many Headscale instances in the world therefore there are many Headscale users with ID 1, ID 2, etc&amp;hellip; If an admin changes / moves / rebuilds their instance, relying solely on the user ID like I do with Tailscale isn&amp;rsquo;t enough.&lt;/p&gt;
&lt;p&gt;To mitigate this I am doing two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ids in the appspace DB are stored as &lt;code&gt;&amp;lt;id&amp;gt;@&amp;lt;headscale-control-domain&amp;gt;&lt;/code&gt;. If you change to a different Headscale instance at a different domain, this will ensure that user-1 in one instance is not the same as user-1 in a different instance.&lt;/li&gt;
&lt;li&gt;I added an &lt;code&gt;extra_name&lt;/code&gt; column in the DB, which stores the email address of the Headscale user. I haven&amp;rsquo;t implemented this part yet but it should help deal with situations where a Headscale user is not who the system thinks they are.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Commit: &amp;ldquo;add extra name to appspace user auth&amp;rdquo; &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/b77fd83bdc802902da2c2b8a7dc6752e6872ce9b&#34;&gt;b77fd83&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;tags-key-expiry-and-auth-keys&#34;&gt;Tags, Key Expiry and Auth Keys&lt;/h2&gt;
&lt;p&gt;Tailscale expects non-user nodes to be &amp;ldquo;tagged&amp;rdquo; (see &lt;a href=&#34;https://tailscale.com/kb/1068/tags&#34;&gt;Tailscale docs&lt;/a&gt;.) As such appspace nodes should be tagged. This triggers the following do-list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UI to input tag when creating node&lt;/li&gt;
&lt;li&gt;read actual tags for the node&lt;/li&gt;
&lt;li&gt;disable use of appspace node if there are no tags&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the above done, I set up the UI to warn the user when the node has no tags, and point them to a remedy.&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-no-tags_huf1cf4b232a046a3d6258f8e84a653d01_90240_716x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-no-tags_huf1cf4b232a046a3d6258f8e84a653d01_90240_716x0_resize_box_3.png, https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-no-tags_huf1cf4b232a046a3d6258f8e84a653d01_90240_1432x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing a box with a warning that there are no tags.&#34;&gt;
&lt;h4 id=&#34;auth-keys&#34;&gt;Auth Keys&lt;/h4&gt;
&lt;p&gt;If you try to create an appspace Tailscale node the &lt;code&gt;ds-host&lt;/code&gt; UI will display a link to click, which takes you to Tailscale (or your Headscale instance) where you authenticate to finish creating the node. It&amp;rsquo;s convenient and requires no prior steps to complete.&lt;/p&gt;
&lt;p&gt;An alternative is to create an &lt;a href=&#34;https://tailscale.com/kb/1085/auth-keys&#34;&gt;auth key&lt;/a&gt; in Tailscale (or Headscale). Conveniently you can select tags to set on nodes created with that auth key.&lt;/p&gt;
&lt;p&gt;I added support for creating a node using an auth key. In many cases this will be a superior workflow for users, so long as they have the forethought of creating an auth key. It&amp;rsquo;s also possible to create multiple nodes with the same auth key.&lt;/p&gt;
&lt;h4 id=&#34;node-key-expiry&#34;&gt;Node key expiry&lt;/h4&gt;
&lt;p&gt;Tailscale nodes &lt;a href=&#34;https://tailscale.com/kb/1028/key-expiry&#34;&gt;expire&lt;/a&gt;, but you can disable the expiry date of the node if it&amp;rsquo;s meant to run unattended like a server. In fact, if you create a node with a tag, key expiry is disabled automatically.&lt;/p&gt;
&lt;p&gt;If in spite of the work above the appspace node is created without a tag and an expiry date is in effect, the UI points out the issue along with steps to resolve. (It&amp;rsquo;s easy to do, but &lt;a href=&#34;https://bsky.app/profile/olivierforget.net/post/3ljlptwyxfk2p&#34;&gt;if you don&amp;rsquo;t know you don&amp;rsquo;t know&lt;/a&gt;.)&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-key-expiry_hucae73020953bf3d82a8f2281cfeea3c4_100754_716x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-key-expiry_hucae73020953bf3d82a8f2281cfeea3c4_100754_716x0_resize_box_3.png, https://olivierforget.net/blog/2025/dropserver-progress-february-2025/ts-key-expiry_hucae73020953bf3d82a8f2281cfeea3c4_100754_1432x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing a box with a that key expiry is enabled and a hint to resolve.&#34;&gt;
&lt;p&gt;With the above, the user should be able to create a node and get it to usable state even if things didn&amp;rsquo;t go according to plan the first time around. &lt;code&gt;ds-host&lt;/code&gt; detects all &amp;ldquo;gotcha&amp;rdquo; situations that I can think of and points the user in the right direction to resolve. This is key to get Tailscale working for users who may not be familiar with it.&lt;/p&gt;
&lt;p&gt;Commits: &amp;ldquo;add tsnet tags input and key expiry date to status&amp;rdquo; &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/604d0e3867f4489752534057267c758e98d787eb&#34;&gt;604d0e3&lt;/a&gt; and &amp;ldquo;create tsnet node using AuthKey&amp;rdquo; &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/7f122d4b630b4905c4dd0afce4396adec214247b&#34;&gt;7f122d4&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;getting-closer&#34;&gt;Getting CLoser&lt;/h2&gt;
&lt;p&gt;It feels like Tailscale integration is finally getting closer to being done. I&amp;rsquo;m punting on a few things that are related but not critical: handling avatars, and better user management.&lt;/p&gt;
&lt;p&gt;I am now working on making the &lt;code&gt;ds-host&lt;/code&gt; admin panel accessible from Tailscale as well. Naturally it&amp;rsquo;s not nearly as simple as I would like it to be.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - January 2025</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-january-2025/</link>
      <pubDate>Wed, 12 Feb 2025 10:37:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-january-2025/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for January 2025. While the previous report was a &lt;a href=&#34;https://olivierforget.net/blog/2025/dropserver-progress-december-2024/&#34;&gt;wrap up of 2024&lt;/a&gt;, this one is a look ahead for 2025.&lt;/p&gt;
&lt;h2 id=&#34;the-battle-between-the-drive-and-the-grind&#34;&gt;The Battle Between the Drive and The Grind&lt;/h2&gt;
&lt;p&gt;A New Year&amp;rsquo;s celebration adds a new notch to a years-long project. A new year is a time to take stock of how far a project has come along, and what it still needs.&lt;/p&gt;
&lt;p&gt;Safe to say that for Dropserver I&amp;rsquo;m not beaming with confidence. There are a few things making it feel like an endless grind. Some features take forever, like &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; integration which is kicking my butt.&lt;/p&gt;
&lt;p&gt;Also, after realizing that the problem space is bigger than I had anticipated and my ideas on how to solve it shifts, I have to contemplate doing more work in a direction I hadn&amp;rsquo;t anticipated.&lt;/p&gt;
&lt;p&gt;On the other hand, there are things that drive me forwards: there is light at the end of the Tailscale tunnel, and its integration into Dropserver is key to reaching the project&amp;rsquo;s goals.&lt;/p&gt;
&lt;p&gt;This is no celebration but the current political environment in The US of A (f*** yeah?) is making self-hosting from home something many Americans may want to look into. As dark as that is, it pushes me forwards.&lt;/p&gt;
&lt;p&gt;Finally I am motivated because I have realized what I need to do to make Dropserver stand out from the crowd of self-hosting platforms: make Dropserver very to install.&lt;/p&gt;
&lt;h3 id=&#34;the-way-forward&#34;&gt;The way forward&lt;/h3&gt;
&lt;p&gt;I think the most game-changing characteristic I can bring to the table with Dropserver is to make it very easy for anybody to install. This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use a cheat code for networking (the cheat code is &amp;ldquo;Tailscale&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;make &lt;code&gt;ds-host&lt;/code&gt; installable on popular operating systems (MacOS, Windows)&lt;/li&gt;
&lt;li&gt;use GUI installers and wizards&lt;/li&gt;
&lt;li&gt;ditch the config file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many self-hosting platforms out there, but most only work on Linux. Any platform that requires Linux has to first convince the potential user that they want to mess with Linux. For &lt;a href=&#34;https://itsfoss.com/linux-market-share/&#34;&gt;many people&lt;/a&gt;, that&amp;rsquo;s a foreign country they&amp;rsquo;ve never heard about and have no intention of visiting. A real demotivator.&lt;/p&gt;
&lt;p&gt;I already build and run &lt;code&gt;ds-host&lt;/code&gt; on my Mac. Unlike platforms based on &lt;a href=&#34;https://en.wikipedia.org/wiki/Linux_namespaces&#34;&gt;Linux namespaces&lt;/a&gt; (aka containers), there is nothing about Dropserver that requires it to run on Linux. So it will be no problem to make a build for MacOS. Windows support will be harder simply because Windows is so different from Linux. But I should get to it because Windows market share is completely ridiculous if you believe &lt;a href=&#34;https://gs.statcounter.com/os-market-share/desktop/worldwide&#34;&gt;StatCounter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The next challenge will be to get rid of that &lt;a href=&#34;https://dropserver.org/docs/ds-host-config-ref&#34;&gt;config file&lt;/a&gt; somehow. Ideally the service needs to start via a GUI and live in the tray. No CLI or config file editing should ever be needed.&lt;/p&gt;
&lt;p&gt;Further challenges will be to leverage the MacOS and win32 sandboxes to good effect to provide additional protection around Deno (I currently &lt;a href=&#34;https://olivierforget.net/blog/2023/dropserver-sandbox/&#34;&gt;use bwrap&lt;/a&gt; on Linux). In addition to all that, Dropserver needs to update itself gracefully.&lt;/p&gt;
&lt;p&gt;Note that the &lt;em&gt;no-CLI&lt;/em&gt; and &lt;em&gt;no-config&lt;/em&gt; approach applies to Linux too. Despite what I said above, buying a &lt;a href=&#34;https://www.raspberrypi.com/products/raspberry-pi-500/&#34;&gt;Raspberry Pi&lt;/a&gt; with the graphical OS pre-installed is within the reach of many. I&amp;rsquo;ll be exploring a release for arm64 and techniques for making it easy to install on a Pi.&lt;/p&gt;
&lt;p&gt;These and a few other adjustments in my approach to Dropserver are where I see things going in 2025 &amp;hellip;if I can just ship Tailscale integration already! 😭&lt;/p&gt;
&lt;h2 id=&#34;tailscale-integration-work&#34;&gt;Tailscale Integration Work&lt;/h2&gt;
&lt;p&gt;The current focus of the Tailscale integration work is to merge the users who appear as peers of the appspace node into the appspace&amp;rsquo;s users.&lt;/p&gt;
&lt;p&gt;Tailscale is just one way to access an &lt;a href=&#34;https://dropserver.org/docs/application-model&#34;&gt;appspace&lt;/a&gt; on Dropserver. As such, a user might access it via Tailscale one day, and via the local network another day. Although this adds complexity, I am convinced that it is required to support multiple simultaneous ways of accessing an appspace, and not be &amp;ldquo;either-or&amp;rdquo;. This aligns with how I &lt;a href=&#34;https://olivierforget.net/blog/2025/self-hosting-third-party-services/&#34;&gt;use 3rd party services when home hosting&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As a result each appspace user can have different &amp;ldquo;identities&amp;rdquo; depending on the network used to access the appspace. I have to consider this in all aspects of authentication and user management.&lt;/p&gt;
&lt;p&gt;Then, it turns out tailnet users are&amp;hellip; different to work with. Like I&amp;rsquo;ve &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-november-2024/&#34;&gt;mentioned before&lt;/a&gt;, everything about working with &lt;a href=&#34;https://tailscale.com/kb/1244/tsnet&#34;&gt;tsnet&lt;/a&gt; is an exercise in reversing the flow of data for everything. In this case, users don&amp;rsquo;t come from my database, they come from the list of peer devices for the appspace node. This is only available when the node is connected and can change at any second. So I have to listen for changes to the peers, deduce the list of users from the devices, and then decide whether that tailnet user is a user of the appspace or not.&lt;/p&gt;
&lt;p&gt;Or rather, I have to decide how to decide if the user is an appspace user. It depends on how the tailnet is managed. If someone is carefully crafting their &lt;a href=&#34;https://tailscale.com/kb/1018/acls&#34;&gt;ACLs&lt;/a&gt; in the Tailscale UI, then any peer of the node should be authorized. But if they use set-once-and-forget ACLs that treat all appspaces the same they will use Dropserver&amp;rsquo;s UI to authorize users for individual appspaces. (Some admins may not want to mess with Tailscale ACLs on a regular basis because they are, quite frankly, user-unfriendly.)&lt;/p&gt;
&lt;p&gt;Originally I thought that &amp;ldquo;&lt;a href=&#34;https://tailscale.com/kb/1084/sharing&#34;&gt;shared&lt;/a&gt;&amp;rdquo; users would automatically become appspace users because sharing is a deliberate action by the admin, and there is no need to second-guess it. But I had reverse that. Why? Because there is a decent chance that the person is already a user of that appspace, and auto-adding would create two users for the same person. This is obviously bad and confusing.&lt;/p&gt;
&lt;p&gt;The goal in all this is to present the appspace owner with a clear view of appspace users along with their identifiers on Tailscale and elsewhere. And then give them a way to manage the Tailscale peers by turning them into new appspace users or adding their identifiers to existing users.&lt;/p&gt;
&lt;p&gt;Eventually, to make user management less manual, I will develop the &amp;ldquo;Contacts&amp;rdquo; section of Dropserver. Once a user is in the list of contacts then auto-adding becomes possible in some cases. But that&amp;rsquo;s for later. The first release of &lt;code&gt;ds-host&lt;/code&gt; with Tailscale will have a clunky UX, sorry.&lt;/p&gt;
&lt;h3 id=&#34;the-grind&#34;&gt;The grind&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;add appspace users from tsnet (unfinished) &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/bc8a63c4901942979863173a533b3c7bec4e8ca5&#34;&gt;bc8a63c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;change tsnet backendURL property name to controlURL &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/4b1ea070a6343d827f3edcafbbfad387a22a34c7&#34;&gt;4b1ea07&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;remove last_seen from appspace user and user auths &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/56532b0713217ec70529f783c77633b16bba5c3b&#34;&gt;56532b0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;refactor appspace users reactivity &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/c767b840020b296cce830284d64c6391541941d1&#34;&gt;c767b84&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;onwards&#34;&gt;Onwards&lt;/h2&gt;
&lt;p&gt;See you next month.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - Recap of 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/dropserver-progress-december-2024/</link>
      <pubDate>Wed, 08 Jan 2025 10:39:25 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/dropserver-progress-december-2024/</guid>
      <description>&lt;p&gt;Instead of going over the month of December (not much happened), here is a quick recap for the year in countdown form:&lt;/p&gt;
&lt;h2 id=&#34;four-releases&#34;&gt;Four Releases&lt;/h2&gt;
&lt;p&gt;I released four versions of Dropserver:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.0&#34;&gt;0.13.0&lt;/a&gt;: Install/update apps from URL. See &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-january-2024/&#34;&gt;January&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.1&#34;&gt;0.13.1&lt;/a&gt; brought a few bug fixes and improvements. See &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-march-2024/&#34;&gt;March progress report&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.2&#34;&gt;0.13.2&lt;/a&gt; Adds a proxy for outbound requests, and many small tweaks. See &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-may-2024/&#34;&gt;May update&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.3&#34;&gt;0.13.3&lt;/a&gt; See &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-september-2024/&#34;&gt;September progress report&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;three-main-areas-of-work&#34;&gt;Three Main Areas of Work&lt;/h2&gt;
&lt;p&gt;I worked primarily on three new things in 2024:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Outbound requests from appspaces.&lt;/strong&gt; Failed to ship (see &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-net-requests/&#34;&gt;this post&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deno 2 support.&lt;/strong&gt; Shipped but caused some &lt;a href=&#34;https://olivierforget.net/blog/2024/deno-2-and-dropserver/&#34;&gt;backwards compatibility challenges&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tailscale integration&lt;/strong&gt; (not yet finished). See progress reports for &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-april-2024/&#34;&gt;April&lt;/a&gt; and onwards.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;two-dropserver-apps&#34;&gt;Two Dropserver Apps&lt;/h2&gt;
&lt;p&gt;I worked on the two publicly available non-demo apps for Dropserver:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://leftovers.olivierforget.net&#34;&gt;Leftovers&lt;/a&gt;: small tweaks to polish the UX. This app is pretty decent now, a few quibbles aside.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://shoppinglist.olivierforget.net&#34;&gt;ShoppingList&lt;/a&gt;: I made it a PWA and improved the UX for adding items to your list quickly. This one needs more work before I am happy with it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;one-goal&#34;&gt;One Goal&lt;/h2&gt;
&lt;p&gt;I am building Dropserver in an attempt to figure out how self-hosting personal web services can be brought within reach for non-technical users, or people who don&amp;rsquo;t want to become hobbyist sysadmins.&lt;/p&gt;
&lt;p&gt;I am not where I want to be, and it seems the decks are stacked against this ever becoming a thing. But when I look at Plex, HomeAssistant, and Cloudron, I see that some formulas can lead to success.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Depending on Third Party Services When Self-Hosting</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2025/self-hosting-third-party-services/</link>
      <pubDate>Wed, 01 Jan 2025 12:27:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2025/self-hosting-third-party-services/</guid>
      <description>&lt;p&gt;In our drive to take control of our web presence by self-hosting our services from home, it seems contradictory to depend on 3rd party services to make it all work. Companies like &lt;a href=&#34;https://www.mailgun.com/&#34;&gt;Mailgun&lt;/a&gt;, &lt;a href=&#34;https://tailscale.com/&#34;&gt;Tailscale&lt;/a&gt;, &lt;a href=&#34;https://www.cloudflare.com/&#34;&gt;Cloudflare&lt;/a&gt;, &lt;a href=&#34;https://www.netlify.com/&#34;&gt;Netlify&lt;/a&gt;, &lt;a href=&#34;https://nextdns.io/&#34;&gt;NextDNS&lt;/a&gt;, &lt;a href=&#34;https://www.linode.com/&#34;&gt;Linode&lt;/a&gt;, &lt;a href=&#34;https://aws.amazon.com/&#34;&gt;AWS&lt;/a&gt;, &lt;a href=&#34;https://ngrok.com/&#34;&gt;ngrok&lt;/a&gt;, and many more offer compelling solutions to the endless challenges of self-hosting. But does using them mean we are fooling ourselves about our independence from big tech?&lt;/p&gt;
&lt;p&gt;Here is how I think of things as I decide what to use in my own home, and what I integrate into &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;questions-i-ask-myself&#34;&gt;Questions I ask myself&lt;/h2&gt;
&lt;p&gt;Naturally I ask myself if the service trustworthy and reliable, but a &amp;ldquo;yes&amp;rdquo; answer isn&amp;rsquo;t good enough. Services change, get bought, pivot and generally enshitt&amp;ndash; &lt;em&gt;No&lt;/em&gt;, it&amp;rsquo;s the first day of 2025, I won&amp;rsquo;t start the year by overusing 2024&amp;rsquo;s biggest word.&lt;/p&gt;
&lt;p&gt;In any case it&amp;rsquo;s best to assume the worst and ask questions like these:&lt;/p&gt;
&lt;h3 id=&#34;what-are-the-consequences-if-it-goes-away&#34;&gt;What are the consequences if it goes away?&lt;/h3&gt;
&lt;p&gt;If I depend on a service in my home-hosting setup, what are the consequences of the service going down, or becoming unusable? Is my instance dead? how much work to switch to something different?&lt;/p&gt;
&lt;p&gt;Is there a drop-in replacement for the service? Can I actually use the replacement &lt;em&gt;now&lt;/em&gt; or is the API different and we need to go beg maintainers of projects to support different services?&lt;/p&gt;
&lt;p&gt;Are there less convenient but workable ways of getting around the loss of the service that I can actually implement in a reasonable amount of time?&lt;/p&gt;
&lt;h3 id=&#34;how-much-of-my-data-can-the-service-harvest&#34;&gt;How much of my data can the service harvest?&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m sure the third party service says they&amp;rsquo;ll &amp;ldquo;never sell your data or use it to train LLMs&amp;rdquo; or whatever. But it&amp;rsquo;s just words. We all know how these things go. So what matters is how much of your data is actually visible to them? And are you OK with them breaking their promises with that data?&lt;/p&gt;
&lt;p&gt;An email sending service like Mailgun sees the content and the recipient address. Depending on the kind of emails you send, that may be OK. Perhaps you use it to send notifications of mundane events. On the other hand maybe you use it to send out a very personal news to friends, in which case you have to decide if it&amp;rsquo;s OK for them to have that.&lt;/p&gt;
&lt;p&gt;Another factor to consider is whether this data can be protected at all? Netlify may see every page on my website, but that website is public anyways, so it&amp;rsquo;s likely getting harvested whether I like it or not.&lt;/p&gt;
&lt;h3 id=&#34;can-the-service-hold-my-data-hostage&#34;&gt;Can the service hold my data hostage?&lt;/h3&gt;
&lt;p&gt;How much data is held exclusively by that service? If I keep a bunch of files on an S3 storage service then that service&amp;rsquo;s disappearance might have profound consequences for me. You might say &amp;ldquo;oh come on that will never happen&amp;rdquo;. Perhaps, but consider that you might lose access to your account if, say, they accuse you of being a spammer for whatever reason. Your data is as good as gone in that case.&lt;/p&gt;
&lt;p&gt;Given that one of the major reasons for self-hosting is data sovereignty, this is a big no-no. If I were to use an external storage service, I&amp;rsquo;d make sure I have copies of files in a completely independent service or a local drive.&lt;/p&gt;
&lt;p&gt;An other service that might hold critical data is newsletter sending services. They usually manage the subscriptions and hold the data for all your subscribers. Make sure that stuff can be downloaded and imported elsewhere, &lt;em&gt;and&lt;/em&gt; set up an automated recurring job that downloads that data locally.&lt;/p&gt;
&lt;p&gt;Some services will have some data that is exclusively under their control. Ask yourself if you can live without it and act accordingly.&lt;/p&gt;
&lt;h2 id=&#34;escape-hatches-for-3rd-party-services&#34;&gt;Escape hatches for 3rd party services&lt;/h2&gt;
&lt;p&gt;Given the above, what might we look for in 3rd party services for our home-hosting setup?&lt;/p&gt;
&lt;h3 id=&#34;use-generic-services&#34;&gt;Use generic services&lt;/h3&gt;
&lt;p&gt;If I have a virtual machine on DigitalOcean and I stop trusting that company, I can create the same VM on Linode. Virtual machines are not a proprietary thing. To make sure I can do this readily, I should make sure data from the machine is backed up outside of DO and that I can recreate the VM quickly using infrastructure as code.&lt;/p&gt;
&lt;p&gt;Even easier: many email sending services let you use SMTP to send through them, so with a little config change, you&amp;rsquo;ve escaped. This is good.&lt;/p&gt;
&lt;h3 id=&#34;use-services-that-have-open-source-self-hosted-versions&#34;&gt;Use services that have open source self-hosted versions&lt;/h3&gt;
&lt;p&gt;While you probably signed up for a service because it was easy and convenient, if faced with a loss self-hosting their solution is less bad than being completely stuck. It&amp;rsquo;s an escape hatch. You don&amp;rsquo;t want to use it, and with some luck you won&amp;rsquo;t have to any time soon, but you definitely don&amp;rsquo;t want to be without it.&lt;/p&gt;
&lt;h3 id=&#34;use-services-that-let-you-download-data-unattended&#34;&gt;Use services that let you download data unattended&lt;/h3&gt;
&lt;p&gt;If the service holds data that you don&amp;rsquo;t want to lose, only use it if you can reliably and automatically download your critical data in usable form.&lt;/p&gt;
&lt;h2 id=&#34;closing-thoughts&#34;&gt;Closing thoughts&lt;/h2&gt;
&lt;p&gt;Personally I find that using third party services to help me with self-hosting is a good move. Their value is well worth the cost of a small inconvenience if I have to switch.&lt;/p&gt;
&lt;p&gt;I think of commercial services as more tools in my toolbox. These tools do not displace my existing trustworthy tools, I can take advantage of them, but I have options if they become troublesome. I just make sure I don&amp;rsquo;t give my whole toolbox to a third party!&lt;/p&gt;
&lt;h3 id=&#34;different-strokes-for-different-folks&#34;&gt;Different strokes for different folks&lt;/h3&gt;
&lt;p&gt;When evaluating the questions above absolutists will end up declining to use every third party service they can, and that&amp;rsquo;s fine.&lt;/p&gt;
&lt;p&gt;My ambition with Dropserver is to (some day) bring home-hosting of personal web services to a broader audience. I&amp;rsquo;m pretty sure at this point it&amp;rsquo;s impossible without the help of third party commercial services to simplify the process. The key will be to thoughtfully integrate some services that help home-hosting without defeating the whole purpose.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - November 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-november-2024/</link>
      <pubDate>Tue, 10 Dec 2024 10:39:25 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-november-2024/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for November 2024. Here is &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-october-2024/&#34;&gt;last month&lt;/a&gt;&amp;rsquo;s report. This month was all about &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; integration. Trying to get this stuff right isn&amp;rsquo;t easy! Dig in&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;config-conundrums&#34;&gt;Config Conundrums&lt;/h2&gt;
&lt;p&gt;When I started Tailscale integration I reflexively put some configuration parameters in the &lt;code&gt;ds-host&lt;/code&gt; &lt;a href=&#34;https://dropserver.org/docs/ds-host-config-ref&#34;&gt;config file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Silly idea. First, I should not be adding things to this config file. Nobody wants to write a config file before running a new service. I should work to eliminate it not add to it.&lt;/p&gt;
&lt;p&gt;More à-propos of Tailscale, it turns out there are no configuration parameters that exist instance-wide. (Well, almost. There is one. More on that some other time.)&lt;/p&gt;
&lt;p&gt;If you speedrun through my notes from the last couple of months, it&amp;rsquo;s a continuous process of moving config values for &lt;a href=&#34;https://tailscale.com/kb/1244/tsnet&#34;&gt;&lt;code&gt;tsnet&lt;/code&gt;&lt;/a&gt; nodes away from the instance level, to have them keyed by tailnet, and finally to have them attached to an appspace ID, if not to disappear entirely.&lt;/p&gt;
&lt;p&gt;Implementing &lt;code&gt;tsnet&lt;/code&gt; is an exercise in completely reverting the flow of configuration from your config file, to have it fed to you by the state of a (running!) Tailscale node.&lt;/p&gt;
&lt;p&gt;Take HTTPS for example. For the &amp;ldquo;normal&amp;rdquo; server, whether to use HTTPS is a value in the config file that is read at &lt;code&gt;ds-host&lt;/code&gt; startup, and is used to decide whether to start a TLS server.&lt;/p&gt;
&lt;p&gt;I obviously thought there would be an equivalent config value for Tailscale nodes. Then I realized different users might use different tailnets for their nodes, so it became a per-tailnet setting. Then I realized that it shouldn&amp;rsquo;t even be a setting because you can&amp;rsquo;t even have a functioning HTTPS server on a &lt;code&gt;tsnet&lt;/code&gt; node unless the backend is set up to enabled this.&lt;/p&gt;
&lt;p&gt;By the end of November there are very few configuration values, and they are all per-appspace. The &lt;code&gt;ds-host&lt;/code&gt; config file will have nothing related to Tailscale.&lt;/p&gt;
&lt;h2 id=&#34;trying-out-ionscale&#34;&gt;Trying Out Ionscale&lt;/h2&gt;
&lt;p&gt;As I integrate Tailscale into Dropserver, I want to make sure the open-source alternative backends also work. &lt;a href=&#34;https://jsiebens.github.io/ionscale/&#34;&gt;Ionscale&lt;/a&gt; is a self-hosted alternative backplane for Tailscale. It appears to have a good number of features, but unfortunately &lt;a href=&#34;https://github.com/jsiebens/ionscale/issues/50&#34;&gt;some docs are missing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The installation docs are actually quite good. Concise, they got me to having an instance of Ionscale on a VM pretty quickly. Unfortunately, the usage docs are non-existent. It&amp;rsquo;s through trial and error that I was able to figure out how to make it work (I think).&lt;/p&gt;
&lt;p&gt;Double unfortunately, as soon as I figured out the command needed, I got a panic. Not great! I filed an &lt;a href=&#34;https://github.com/jsiebens/ionscale/issues/63&#34;&gt;issue&lt;/a&gt; but after several days of not sharing from the dev, I deleted the VM.&lt;/p&gt;
&lt;p&gt;Womp womp.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll certainly revisit Ionscale at some point in the future and hopefully have better luck, but for now I need to move on to more familiar territory.&lt;/p&gt;
&lt;h2 id=&#34;more-headscale&#34;&gt;More Headscale&lt;/h2&gt;
&lt;p&gt;I had played with &lt;a href=&#34;https://headscale.net/stable/&#34;&gt;Headscale&lt;/a&gt; already. It&amp;rsquo;s more widely used than Ionscale even though it has fewer features (see below). Also it&amp;rsquo;s the closest thing to an officially supported open source backend for Tailscale. I think the dev even works at Tailscale.&lt;/p&gt;
&lt;h3 id=&#34;one-appspace-on-tailscale-and-one-on-headscale&#34;&gt;One appspace on Tailscale and one on Headscale?&lt;/h3&gt;
&lt;p&gt;I wanted to know whether it was possible to have one node connected to the official Tailscale backplane and one connected to my own instance of Headscale. And have these nodes both connected simultaneously from one running Go program.&lt;/p&gt;
&lt;p&gt;Knowing this would inform whether the &lt;code&gt;ControlURL&lt;/code&gt; for &lt;code&gt;tsnet&lt;/code&gt; is an instance-wide setting or not. So I made some experiments&amp;hellip;&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2024/dropserver-progress-november-2024/tsnet-multiple-control-urls_hud48e583f4e5ac61aacf69008c086009c_105686_755x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2024/dropserver-progress-november-2024/tsnet-multiple-control-urls_hud48e583f4e5ac61aacf69008c086009c_105686_755x0_resize_box_3.png, https://olivierforget.net/blog/2024/dropserver-progress-november-2024/tsnet-multiple-control-urls_hud48e583f4e5ac61aacf69008c086009c_105686_1510x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing the output of a command that connects to multiple tailscale backends.&#34;&gt;
&lt;p&gt;Turns out &lt;code&gt;tsnet&lt;/code&gt; can connect to different backplanes simultaneously. That means different appspaces can be connected to different Tailscale backends (which will be great for Tailscale users who want to experiment with alternative backends) and an instance-wide config for this is unnecessarily limiting.&lt;/p&gt;
&lt;p&gt;Also &lt;em&gt;poof!&lt;/em&gt; 🪄 one less config a the instance level.&lt;/p&gt;
&lt;h3 id=&#34;headscale-https-serve-issue&#34;&gt;Headscale HTTPS serve issue&lt;/h3&gt;
&lt;p&gt;One bummer about Headscale is that it does not yet support serving over HTTPS. This means that an appspace connected to a Headscale instance is only accessible over plain HTTP. Of course, the connection is encrypted since it&amp;rsquo;s running through a WireGuard Tunnel. But if you open the link in the browser, it tells you it&amp;rsquo;s not secure.&lt;/p&gt;
&lt;p&gt;This is problematic because many advanced web features require a &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts&#34;&gt;Secure Context&lt;/a&gt; to be available. Without that, no PWA, no notifications, no camera access, etc&amp;hellip; The &lt;a href=&#34;https://leftovers.olivierforget.net/&#34;&gt;Leftovers app&lt;/a&gt; would lose a lot of usefulness without HTTPS.&lt;/p&gt;
&lt;p&gt;I opened an &lt;a href=&#34;https://github.com/juanfont/headscale/issues/1921&#34;&gt;issue&lt;/a&gt; to add this feature, unfortunately right now I don&amp;rsquo;t have the time to implement it.&lt;/p&gt;
&lt;h2 id=&#34;magicdns-tls-and-user-experience&#34;&gt;MagicDNS, TLS, and User Experience&lt;/h2&gt;
&lt;p&gt;So far in my Tailscale experiments I assumed that &lt;a href=&#34;https://tailscale.com/kb/1081/magicdns&#34;&gt;MagicDNS&lt;/a&gt; was on and &lt;a href=&#34;https://tailscale.com/kb/1153/enabling-https&#34;&gt;HTTPS enabled&lt;/a&gt;. But that&amp;rsquo;s not a given. Even if the likely outcome is that someone using Tailscale to serve Dropserver appspaces will have these features on, they may not be on at first.&lt;/p&gt;
&lt;p&gt;If a user has just signed up to Tailscale, these features are off. They may not be reading my instructions carefully (a safe assumption to make). Dropserver should connect to the tailnet with what&amp;rsquo;s available, and make clear to the user that they can get HTTPS and a URL by going in and enabling MagicDNS and TLS certs.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s more, since &lt;code&gt;tsnet&lt;/code&gt; is good about forwarding network configuration changes to the client promptly (this is inherent to how Tailscale works) Dropserver should notice these changes and act accordingly.&lt;/p&gt;
&lt;p&gt;The goal is that when a user makes changes to their Tailscale (or Headscale or Ionscale) configuration, the nodes managed by Dropserver instantly &amp;ldquo;do the right thing&amp;rdquo;. If HTTPS becomes available, then it starts &lt;code&gt;ListenTLS()&lt;/code&gt; and if it becomes unavailable it stops that listener.&lt;/p&gt;
&lt;p&gt;This means the user just needs to flip a couple of switches in the Tailscale admin UI and the &lt;code&gt;ds-host&lt;/code&gt; admin panel updates to show them the full HTTPS URL for their appspace. No interaction required. No &amp;ldquo;&amp;hellip;and then go restart your node&amp;rdquo; in the docs.&lt;/p&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/5d2114fd8a5227e11953de8b8dc1966383828bef&#34;&gt;5d2114&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next&lt;/h2&gt;
&lt;p&gt;This month I will soon finish the config side of things (for appspaces at least) and I can move on to how to handle users, which should be fun.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - October 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-october-2024/</link>
      <pubDate>Wed, 06 Nov 2024 13:06:25 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-october-2024/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for October 2024. Here is &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-september-2024/&#34;&gt;last month&lt;/a&gt;&amp;rsquo;s report.&lt;/p&gt;
&lt;h2 id=&#34;dropserver-0133-released&#34;&gt;Dropserver 0.13.3 released&lt;/h2&gt;
&lt;p&gt;As I mentioned last month I released &lt;code&gt;ds-host&lt;/code&gt; and &lt;code&gt;ds-dev&lt;/code&gt; &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.3&#34;&gt;version 0.13.3&lt;/a&gt; with support for &lt;a href=&#34;https://deno.com/blog/v2.0&#34;&gt;Deno 2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I updated to 0.13.3 on my personal instance of &lt;code&gt;ds-host&lt;/code&gt;, which happened without a hitch. I am still using Deno 1.x because I haven&amp;rsquo;t updated all my apps to work with Deno 2.&lt;/p&gt;
&lt;h2 id=&#34;update-leftovers-and-shopping-list-for-deno-2&#34;&gt;Update Leftovers and Shopping List for Deno 2&lt;/h2&gt;
&lt;p&gt;The changes to Leftovers and ShoppingList for Deno 2 were trivial in nature (though I still &lt;a href=&#34;https://olivierforget.net/blog/2024/deno-2-and-dropserver/&#34;&gt;wish there were none&lt;/a&gt;). I did have to submit a &lt;a href=&#34;https://github.com/dyedgreen/deno-sqlite/pull/266&#34;&gt;one-line PR&lt;/a&gt; for &lt;a href=&#34;https://deno.land/x/sqlite@v3.9.1&#34;&gt;deno-sqlite&lt;/a&gt; that removes a TypeScript error. The patch was merged and a new release tagged in a couple of days so I could use it right away. Nice!&lt;/p&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Leftovers/commit/ba5446a6ea1d0f86da2de019de84fefb736a9305&#34;&gt;ba5446a&lt;/a&gt; for Leftovers. Commit &lt;a href=&#34;https://github.com/teleclimber/ShoppingListDropApp/commit/51b753c6878fd6e3644c1e731d25bef4417973e7&#34;&gt;51b753c&lt;/a&gt; for ShoppingList.&lt;/p&gt;
&lt;p&gt;I packaged and published each which reminded me that an automated packaging and distribution system using GitHub Actions (or similar) would be a nice addition.&lt;/p&gt;
&lt;p&gt;Getting the new versions installed on my instance was trivial thanks to the &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-january-2024/&#34;&gt;work I did earlier on app distribution and installation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;ds-dev-screencast&#34;&gt;ds-dev Screencast&lt;/h2&gt;
&lt;p&gt;I upgraded my screen-casting setup this Summer, so it was time to record my first proper video. It walks you through some of the experience of using &lt;code&gt;ds-dev&lt;/code&gt; to develop an app for Dropserver.&lt;/p&gt;
&lt;p&gt;Have a look at it in the &lt;a href=&#34;https://dropserver.org/docs/build-dropserver-app-tutorial&#34;&gt;app development tutorial page here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I realized after publishing it and listening to it using headphones that the keyboard makes a booming sound when I type on it. I&amp;rsquo;ll try to fix that for the next one.&lt;/p&gt;
&lt;h2 id=&#34;vacation-&#34;&gt;Vacation 🏖️&lt;/h2&gt;
&lt;p&gt;I took one week (plus weekends) off this month for a family reunion. One week is short enough that when I get back to work it doesn&amp;rsquo;t feel like I have left too long, so I was able to get right back to it.&lt;/p&gt;
&lt;h2 id=&#34;back-to-tailscale-integration&#34;&gt;Back to Tailscale Integration&lt;/h2&gt;
&lt;p&gt;Last month I thought the next big task would be to capture user info from the tailnet backend and merge that with appspace users. This is definitely looming, but there are a number of other details that need to be sorted out first.&lt;/p&gt;
&lt;p&gt;I started on some basics like capturing various aspects of node status and reflecting it live on the &lt;code&gt;ds-host&lt;/code&gt; frontend. This helps me understand what is happening with the node as it goes through various states. I&amp;rsquo;ll package the UI up better later, I consider this debugging output for now.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m finding Tailscale integration to be tricky to get right because data about each node (such as its URL, ability to use HTTPS etc..) comes from the Tailscale backend, and can change at any time.&lt;/p&gt;
&lt;p&gt;Example: when creating a node, you can set a host name, like &amp;ldquo;leftovers&amp;rdquo; and the resulting URL will be &lt;a href=&#34;https://leftovers.tailxyz123.ts.net&#34;&gt;https://leftovers.tailxyz123.ts.net&lt;/a&gt;. &lt;em&gt;But!&lt;/em&gt; it might actually be &lt;code&gt;leftovers-1.tail...&lt;/code&gt; Or it might start as &amp;ldquo;leftovers&amp;rdquo;, but it can be changed at any time from the Tailscale UI. So &lt;code&gt;ds-host&lt;/code&gt; can express preference but it&amp;rsquo;s the backend that controls and can change things at any instant.&lt;/p&gt;
&lt;p&gt;This is one reason I spent time last month working on a more solid events system using Server-Sent Events and I am taking the time to build out the events that carry Tailscale data all the way to the frontend. Things can change at any second, and I don&amp;rsquo;t want users to get into confusing situations because the data they see in the Dropserver UI (like the URL of the node) is no longer correct.&lt;/p&gt;
&lt;p&gt;I am getting a handle on all of this. In fact I recorded a quick screencast to show the dynamic URL in action:&lt;/p&gt;
&lt;video controls width=&#34;80%&#34;&gt;
	&lt;source src=&#34;tailscale-hostname.mp4&#34; /&gt;
&lt;/video&gt;
&lt;p&gt;(Note the lack of booming keyboard sounds thanks to &lt;a href=&#34;https://social.tchncs.de/@teleclimber/113432671175913266&#34;&gt;this trick&lt;/a&gt;!)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be doing more of this kind of work: absorbing data from the tailnet and merging it with &lt;code&gt;ds-host&lt;/code&gt;&amp;rsquo;s view.&lt;/p&gt;
&lt;h2 id=&#34;keep-on-keepin-on&#34;&gt;Keep On Keepin&#39; On&lt;/h2&gt;
&lt;p&gt;Difficult day today in the US. But we keep going. One day at a time. See you next month.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Deno 2 and Backwards Compatibility in Dropserver</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/deno-2-and-dropserver/</link>
      <pubDate>Thu, 10 Oct 2024 11:45:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/deno-2-and-dropserver/</guid>
      <description>&lt;p&gt;Deno 2 &lt;a href=&#34;https://deno.com/blog/v2.0&#34;&gt;is here&lt;/a&gt;. My project &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt;, an application platform for your personal web services, uses Deno as its app sandbox.&lt;/p&gt;
&lt;p&gt;Deno 2&amp;rsquo;s arrival forced me to break backwards compatibility in Dropserver, which is something I really don&amp;rsquo;t like doing. Here&amp;rsquo;s an explanation of why this happened, how it chafes with my vision for Dropserver, and how I plan to avoid this in the future.&lt;/p&gt;
&lt;h2 id=&#34;deno-code-in-dropserver&#34;&gt;Deno code in Dropserver&lt;/h2&gt;
&lt;p&gt;Dropserver is written in Go, but it runs apps written in JavaScript (or Typescript) inside Deno. Dropserver injects code in the Deno sandbox to help run the app. This code ships with Dropserver to guarantee compatibility between the Go side and the Deno side.&lt;/p&gt;
&lt;p&gt;To make it easier to write apps I publish a &lt;a href=&#34;https://deno.land/x/dropserver_app&#34;&gt;&lt;code&gt;dropserver_app&lt;/code&gt;&lt;/a&gt; library that serves as a bridge between app code and the Dropserver code inside Deno. App devs import this library and call its exported members to interact with the Dropserver system, such as creating routes or fetching the authenticated user, etc&amp;hellip;&lt;/p&gt;
&lt;p&gt;To sum up Dropserver runs JavaScript in Deno:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;code that ships with the Dropserver executable&lt;/li&gt;
&lt;li&gt;code that I publish as a library in &lt;code&gt;deno.land/x/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;code written by app devs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the only code was the one that shipped with Dropserver, I would have no problems: I would patch that and ship it and tell people to upgrade. But that&amp;rsquo;s not the nature of an application platform, is it? The idea is to run other people&amp;rsquo;s code, so when things change, how do you allow old apps to keep working?&lt;/p&gt;
&lt;h2 id=&#34;what-changed-in-deno-2&#34;&gt;What changed in Deno 2&lt;/h2&gt;
&lt;p&gt;Several types of changes took place:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Typescript version changed&lt;/li&gt;
&lt;li&gt;Global space changes&lt;/li&gt;
&lt;li&gt;Deno namespace changes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See Deno&amp;rsquo;s &lt;a href=&#34;https://docs.deno.com/runtime/reference/migration_guide/&#34;&gt;migration guide&lt;/a&gt; for full details.&lt;/p&gt;
&lt;h3 id=&#34;typescript-changes&#34;&gt;TypeScript changes&lt;/h3&gt;
&lt;p&gt;Deno comes with TypeScript built-in, which means your version of TS is tied to your version of Deno. And TS makes breaking changes. In particular, in TS 5.6 &lt;code&gt;errors&lt;/code&gt; in &lt;code&gt;catch&lt;/code&gt; blocks are type &amp;ldquo;unknown&amp;rdquo; and you have to assert them before using them. So I went over my sandbox code and asserted error types. I changed this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;//...
catch(e) {
    // do somethign with error
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;hellip;to this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;//...
catch(e) {
    if( e instanceof Error) {
        // do somethign with error
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I even had to submit a &lt;a href=&#34;https://github.com/dyedgreen/deno-sqlite/pull/266&#34;&gt;tiny patch&lt;/a&gt; to the &lt;code&gt;deno-sqlite&lt;/code&gt; library because of this TypeScript change. Yawn. It&amp;rsquo;s boring menial labor, but if you don&amp;rsquo;t do it, TypeScript complains.&lt;/p&gt;
&lt;h3 id=&#34;deno-changes&#34;&gt;Deno changes&lt;/h3&gt;
&lt;p&gt;Deno removed &lt;code&gt;window&lt;/code&gt; from the global space. So all references to &lt;code&gt;window&lt;/code&gt; cause an error. This is trivial to fix: change &lt;code&gt;window.foo&lt;/code&gt; to &lt;code&gt;globalThis.foo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;They also moved many APIs from the &lt;code&gt;Deno.*&lt;/code&gt; namespace to the standard library. In all cases the change to make is trivial, but if you don&amp;rsquo;t do it, you get a fatal error.&lt;/p&gt;
&lt;p&gt;All these changes add up to a situation where I can&amp;rsquo;t expect Dropserver apps developed under Deno 1 to work in Deno 2 unchanged. And that&amp;rsquo;s a bummer.&lt;/p&gt;
&lt;h2 id=&#34;dropserver-vision&#34;&gt;Dropserver Vision&lt;/h2&gt;
&lt;p&gt;My vision with Dropserver is that an app you start using should continue to run for as long as possible. I would like a 10-year shelf life for apps, even if the developer abandons it. This is hard to pull off for many reasons, but it&amp;rsquo;s not impossible. I have been writing JavaScript for web browsers for nearly 20 years, and a lot of the code I wrote back then still works, unmodified, today.&lt;/p&gt;
&lt;p&gt;While Deno follows web standards which promise stability, they also have their own APIs which means that there are going to be changes. Given Dropserver&amp;rsquo;s deep dependence on Deno for the app runtime, that&amp;rsquo;s rough, but &lt;a href=&#34;https://olivierforget.net/blog/2020/deno-saved-project/&#34;&gt;I know how I got here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;software-changes&#34;&gt;Software changes&lt;/h3&gt;
&lt;p&gt;Note that I don&amp;rsquo;t blame Deno here. They went 4 years on 1.x. That&amp;rsquo;s pretty calm, especially for a VC funded team. If anything, I find that they are very careful with breaking changes. The changes needed are trivial to implement. By comparison, PHP breaks things every year, and &lt;a href=&#34;https://www.php.net/manual/en/migration80.incompatible.php&#34;&gt;PHP 8&lt;/a&gt; was awful to migrate to (ask me how I know!) Over in Python world, it sounds like &lt;a href=&#34;https://lwn.net/Articles/843660/&#34;&gt;Python 2 to 3 was miserable&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The reality is software changes, regardless of where its funding comes from and what guides its decision-making. So the job is to deal with the changes.&lt;/p&gt;
&lt;h3 id=&#34;vision-violation-deno-2-is-a-breaking-change-for-dropserver&#34;&gt;Vision violation: Deno 2 is a breaking change for Dropserver&lt;/h3&gt;
&lt;p&gt;I had initially hoped I could just cruise into Deno 2 with no breaking changes (meaning that no changes would be needed to old apps to run on Deno 2.) After all I make a big deal of all &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-backwards-compatibility/&#34;&gt;the layers I have in place to allow these kinds of transitions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately the changes to TypeScript mean that even if I were able to patch over all the Deno changes, any TS checking would probably raise errors in existing app code. So there is no point in trying to make this non-breaking.&lt;/p&gt;
&lt;p&gt;So does that mean my vision is unrealistic? No. But I need to make some changes to be better prepared for future changes.&lt;/p&gt;
&lt;h2 id=&#34;how-to-avoid-breaking-changes-in-a-breaking-changes-world&#34;&gt;How to avoid breaking changes in a breaking changes world&lt;/h2&gt;
&lt;p&gt;Here are some things I will do to make Dropserver more resilient to changes in Deno: (note that I use Deno 1 and 2 to illustrate the ideas, it&amp;rsquo;s obviously too late to do these things for v2!)&lt;/p&gt;
&lt;h3 id=&#34;no-typescript-checking&#34;&gt;No TypeScript checking&lt;/h3&gt;
&lt;p&gt;Right now deno runs with &lt;code&gt;--check=all&lt;/code&gt; when installing an app. The idea is to ensure that the types in use are compatible between the sandbox code (shipped with the ds executable) and the app code (written externally.) If TS raises errors, there is a good chance something went wrong somewhere, and that things will likely error out unexpectedly.&lt;/p&gt;
&lt;p&gt;On the flip side, TypeScript is prickly, never really stable and error-prone. It&amp;rsquo;s possible to get TS errors on perfectly OK code (see the &lt;code&gt;catch&lt;/code&gt; blocks above).&lt;/p&gt;
&lt;p&gt;So TS checking will be turned off. If an app misbehaves or errors out, maybe the user will be able to enable it on a one-off basis to gather errors to send to the app developer (or to me 😬).&lt;/p&gt;
&lt;h3 id=&#34;monkey-patch-old-deno-features&#34;&gt;Monkey patch old Deno features&lt;/h3&gt;
&lt;p&gt;Since Dropserver&amp;rsquo;s sandbox code runs first, before the app code, I have some freedom to monkey patch the environment that the app code will see.&lt;/p&gt;
&lt;p&gt;I could have re-added the &lt;code&gt;window&lt;/code&gt; global to the sandbox, and patched the &lt;code&gt;Deno&lt;/code&gt; namespace to implement the removed features. But this can cause problems: these were removed for a reason, and forcing them to stay could cause conflicts in the other direction.&lt;/p&gt;
&lt;p&gt;So the correct thing to do is to monkey-patch, but only if the app is designed for Deno 1. The problem is I don&amp;rsquo;t have any way to know if an app expects to run in Deno 1 or Deno 2.&lt;/p&gt;
&lt;h3 id=&#34;add-deno-version-to-app-manifest&#34;&gt;Add Deno version to app manifest&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m unsure the exact way to approach this, but the app&amp;rsquo;s manifest should probably give an indication of what runtime it definitely works with. Maybe the app packaging code could inject &lt;code&gt;&amp;quot;deno-version&amp;quot;:&amp;quot;1.46.3&amp;quot;&lt;/code&gt; to the &lt;code&gt;dropapp.json&lt;/code&gt; to represent the version of deno in use at packaging time. If that&amp;rsquo;s what&amp;rsquo;s on the system, then that&amp;rsquo;s what the app code works with, right? Then &lt;code&gt;ds-host&lt;/code&gt; can read that and determine what features it needs to monkey-patch.&lt;/p&gt;
&lt;p&gt;Or perhaps I need to have automated testing of the app as part of &lt;a href=&#34;https://dropserver.org/docs/ds-dev&#34;&gt;&lt;code&gt;ds-dev&lt;/code&gt;&lt;/a&gt;, and have a field called &lt;code&gt;tested-with&lt;/code&gt; in the manifest.&lt;/p&gt;
&lt;h3 id=&#34;let-dropserver-control-the-deno-version&#34;&gt;Let Dropserver control the Deno version&lt;/h3&gt;
&lt;p&gt;Ultimately, I think Dropserver will download its own copy of Deno and use that to run the sandbox. There are several advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simpler installation of &lt;code&gt;ds-host&lt;/code&gt;, no need to also install Deno&lt;/li&gt;
&lt;li&gt;Safer. DS could check for new versions and always run the latest release&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It could also mean having multiple versions installed. In the current case, we&amp;rsquo;d have 1.46.3, and 2.0.0. And if the app says it was built or compatible with 1.x, then use that.&lt;/p&gt;
&lt;p&gt;Then, when 1.x is no longer supported, Dropserver would fall back to monkey-patching Deno 2 so that it works like Deno 1 for the apps that need it.&lt;/p&gt;
&lt;h2 id=&#34;back-to-todays-reality&#34;&gt;Back to today&amp;rsquo;s reality&lt;/h2&gt;
&lt;p&gt;I shipped updates to &lt;a href=&#34;https://leftovers.olivierforget.net/&#34;&gt;Leftovers&lt;/a&gt; and &lt;a href=&#34;https://shoppinglist.olivierforget.net/&#34;&gt;ShoppingList&lt;/a&gt;. The user-facing changelog says this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;This release updates the code to support future software releases,
in particular it supports &amp;quot;Deno&amp;quot; version 2.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;🤢 🙈&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - September 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-september-2024/</link>
      <pubDate>Mon, 07 Oct 2024 15:15:25 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-september-2024/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for September 2024. Here is &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-july-august-2024/&#34;&gt;last month&lt;/a&gt;&amp;rsquo;s report.&lt;/p&gt;
&lt;h2 id=&#34;going-off-on-a-tangent-from-tailscale-integration&#34;&gt;Going Off On a Tangent from Tailscale Integration&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; integration is progressing. I am able to read information about the network, such as connection status, peers, etc&amp;hellip; This data is dynamic and changes when the tailnet admin shares a node with someone, or a user connects a new device, etc&amp;hellip; Some of this data has implications for the &lt;code&gt;ds-host&lt;/code&gt; appspace owner. In particular, if an appspace node is shared with someone new, that person should be considered a user of the appspace, and that should be reflected on the frontend.&lt;/p&gt;
&lt;p&gt;In 2024 you should not need to reload your interface if something changes externally. The UI the user is looking it should update dynamically to reflect the current reality. As such I am going to have to pipe some of that dynamic data from the tailnet to the frontend. This isn&amp;rsquo;t a big new thing for &lt;code&gt;ds-host&lt;/code&gt;, I already have a rudimentary event system on the backend, and I use my self-developed protocol called &amp;ldquo;Twine&amp;rdquo; that can carry these events to the frontend. But&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;twine-is-overkill-for-frontend-events&#34;&gt;Twine is overkill for frontend events&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/teleclimber/twine-protocol&#34;&gt;Twine&lt;/a&gt; is meant to offer advanced two-way communication between two running programs over a network. With Twine you can create subscriptions to a specific event and then unsubscribe. Twine is powerful, and I think I have some good ideas in there, but I&amp;rsquo;m realizing that frontends are best served with simple event streams. You don&amp;rsquo;t need powerful two-way communication for a typical frontend. Better to just get a firehose event stream.&lt;/p&gt;
&lt;p&gt;Furthermore, Twine is under-developed: there are painful design mistakes, it&amp;rsquo;s cumbersome to use and debugging issues is unpleasant. I think it could be quite good but I would need to put a lot more effort into the protocol and the implementations for it to be a nice thing to use. Right now it&amp;rsquo;s just not, and I have too much on my plate to give it the attention it needs.&lt;/p&gt;
&lt;h3 id=&#34;send-events-to-the-ds-host-fronted-using-server-sent-events&#34;&gt;Send events to the ds-host fronted using Server-Sent Events&lt;/h3&gt;
&lt;p&gt;I decided that before sending events from the tailnet to the frontend, I should make sure I&amp;rsquo;m happy with how I do this. I don&amp;rsquo;t want to write more Twine code if I know I want to eliminate Twine. I don&amp;rsquo;t want to have two systems either: one Twine-based and one &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events&#34;&gt;SSE&lt;/a&gt;-based. So I bit the bullet and decided to remove Twine from &lt;code&gt;ds-host&lt;/code&gt;, at least for frontend events. (The communications between the sandbox and &lt;code&gt;ds-host&lt;/code&gt; take place over Twine. In this case the two-way nature of it is useful. For now.)&lt;/p&gt;
&lt;p&gt;To simplify things as much as possible, I decided that there would be a single SSE endpoint that would send events for all things that the logged in user might potentially be interested in. That doesn&amp;rsquo;t mean the user will see all events. The frontend may ignore some, or simply make a change to reactive data that will update in the UI if it is currently rendered. In other cases, like if the application they just started installing has completed, they might get a toast or something. The point is the frontend doesn&amp;rsquo;t subscribe to specific events. It&amp;rsquo;s a firehose. But the number of events should be small enough that it won&amp;rsquo;t matter.&lt;/p&gt;
&lt;p&gt;Making all these changes forced me to go through all my backend event code. I refactored a number of areas. Events on the backend are more consistent now. They use the same generic base structs which have decent test coverage. I also found that some older parts of the code used events differently, so I made things more uniform throughout.&lt;/p&gt;
&lt;p&gt;Commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/84b5dc8e77f8d1a18d4541715dd3cf4c3e5928b0&#34;&gt;84b5dc8&lt;/a&gt;, &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/df43dfaf3a7126fcd39e68f301ed7b5d915aa04d&#34;&gt;df43dfa&lt;/a&gt;, &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/1a5eb34a82a0e4a568f36b38695a523ff4fb5270&#34;&gt;1a5eb34&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m amazed at how little JavaScript it takes to handle events on the frontend. I cut out a lot of code by dropping Twine. At some point I want to rebuild the frontend of &lt;code&gt;ds-host&lt;/code&gt; to be plain server-rendered HTML pages, with some JS to make the dynamic parts live, and this lean events system is a better place to start.&lt;/p&gt;
&lt;p&gt;One downside of SSEs is they take up one connection under http/1.1. But under http/2 that&amp;rsquo;s not an issue. &lt;code&gt;ds-host&lt;/code&gt; should usually be served over h2, and even if not, it&amp;rsquo;s not a very request-hungry app, so it shouldn&amp;rsquo;t matter.&lt;/p&gt;
&lt;h2 id=&#34;deno-2-drops&#34;&gt;Deno 2 Drops&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://deno.com/blog/v2.0-release-candidate&#34;&gt;Deno 2&lt;/a&gt; finally dropped! At least in release candidate form. So it was time to start testing and adapting my code to make sure everything would continue to work.&lt;/p&gt;
&lt;p&gt;I made &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/e54bfcaeaecbd796d52211da224e70a2835d9e36&#34;&gt;a number of changes to accommodate Deno 2&lt;/a&gt;. Most of the changes are minor, but existing apps need to be upgraded individually to work with Deno 2.&lt;/p&gt;
&lt;p&gt;At the very least your app code should import version &lt;code&gt;0.2.2&lt;/code&gt; of the &lt;a href=&#34;https://deno.land/x/dropserver_app&#34;&gt;&lt;code&gt;dropserver_app&lt;/code&gt;&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;My vision for Dropserver is that apps should not need much maintenance, so asking devs to make changes to support Deno 2 bugs me. But it&amp;rsquo;s not easily avoidable right now. I&amp;rsquo;ll write more about Deno 2 and how Dropserver can better handle this kind of situation in a separate post.&lt;/p&gt;
&lt;h2 id=&#34;dropserver-0133-drops&#34;&gt;Dropserver 0.13.3 Drops&lt;/h2&gt;
&lt;p&gt;On Oct 1 I tagged &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.3&#34;&gt;0.13.3&lt;/a&gt; of Dropserver which works with Deno 2 and includes the SSE changes mentioned above plus other commits that had accumulated lately.&lt;/p&gt;
&lt;p&gt;There is no downside to upgrading to Dropserver &lt;code&gt;0.13.3&lt;/code&gt;, but I&amp;rsquo;d wait to upgrade your Deno install until you are sure all your apps support Deno 2.&lt;/p&gt;
&lt;p&gt;Having said that it&amp;rsquo;s trivial to downgrade your Deno back to 1.x if things don&amp;rsquo;t work. (Trust me, I up/down-graded my Deno install a bunch of times over the last couple of weeks!)&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h2&gt;
&lt;p&gt;With the SSE work done, I&amp;rsquo;ll go back to the Tailscale integration work. The key thing is to make sense of the users from the peers list and merge them with appspace users. It&amp;rsquo;s going to be a bit messy&lt;/p&gt;
&lt;p&gt;Tune in next month for the gruesome details.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - July and August 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-july-august-2024/</link>
      <pubDate>Sun, 15 Sep 2024 12:05:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-july-august-2024/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for July and August 2024. Here is &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-june-2024/&#34;&gt;last month&lt;/a&gt;&amp;rsquo;s report.&lt;/p&gt;
&lt;p&gt;Work on &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; integration is ongoing, but before heading off on vacation I took some time to improve a Dropserver app that I use daily.&lt;/p&gt;
&lt;h2 id=&#34;work-on-the-shoppinglist-app-for-dropserver&#34;&gt;Work on the ShoppingList App for Dropserver&lt;/h2&gt;
&lt;p&gt;I finally put a bit of polish into the Shopping List app for Dropserver and released it:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://shoppinglist.olivierforget.net/&#34;&gt;https://shoppinglist.olivierforget.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My wife and I had been using an earlier version of this for well over a year now and it was finally time to make it better.&lt;/p&gt;
&lt;p&gt;When working on home-cooked apps, I like to use them without making changes for long periods of time. After so many months, it&amp;rsquo;s quite clear what needs to get worked on. When you work on your little app once per year, you make the best of that time by working on the things that really make a difference.&lt;/p&gt;
&lt;p&gt;The result is a leaner app that performs the tasks it needs to and nothing else. No time to build up bloat.&lt;/p&gt;
&lt;p&gt;Among the &lt;a href=&#34;https://github.com/teleclimber/ShoppingListDropApp/commits/main/&#34;&gt;issues I tackled&lt;/a&gt; this time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;made it a PWA (essential for an app that is used daily)&lt;/li&gt;
&lt;li&gt;improved search for items&lt;/li&gt;
&lt;li&gt;make it much easier to add an item in an ad-hoc way&lt;/li&gt;
&lt;li&gt;add selectable filter to the items list (all items, check stock items, items to buy)&lt;/li&gt;
&lt;li&gt;UI tweaks and more&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Already my wife is much happier with this version (win!). I am also pretty happy with where it&amp;rsquo;s at, but I can already see the outlines of the next things I need to add. However I won&amp;rsquo;t touch it for several months, and if I still feel the same then, I&amp;rsquo;ll go ahead and add those.&lt;/p&gt;
&lt;h2 id=&#34;tailscale-integration-in-ds-host&#34;&gt;Tailscale Integration in ds-host&lt;/h2&gt;
&lt;p&gt;As mentioned before, integrating Tailscale means changing lots of things in Dropserver. There are lots of assumptions baked into the Dropserver code that get blown apart when working with a tailnet. As such, a lot of the work of integrating tailscale is backing out of those assumptions. This is a good thing overall. The Dropserver code will be more flexible and able to adapt to new features down the line thanks to the work happening now.&lt;/p&gt;
&lt;p&gt;One specific thing that has to change is the schema of the appspace meta DB. It needs to support one appspace user signing in to the appspace using completely different identifiers (one is a tailscale ID, the other might be their Dropserver ID or email address). Since it&amp;rsquo;s the first time I change this schema I have to sort out how when and where these databases get migrated. I started work on this in &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-june-2024/&#34;&gt;June&lt;/a&gt; and finished in August (see commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/b320d6e38413e00f760a4d57f9df35b28820e704&#34;&gt;b320d6e&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/8f5ab79fa5e3414cc00447d9dd82a4d8e7dc3b54&#34;&gt;8f5ab79&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With that work done, I turned my attention to &lt;code&gt;tsnet&lt;/code&gt;, the embeddable tailscale library, and the vast array of methods and types that might deliver the information I&amp;rsquo;m looking for from the tailnet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is the appspace connected to the tailnet?&lt;/li&gt;
&lt;li&gt;is it &amp;ldquo;logged in&amp;rdquo;? Or does the user need to visit a tailscale URL to authenticate the appspace (which happens if no Auth Key is used.)&lt;/li&gt;
&lt;li&gt;who are the peers of this appspace node, and who among them can be considered users? (Meaning: who can I show in the appspace&amp;rsquo;s list of users and who gets authorized when a request arrives?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of this was not completely straightforward to sort out, but I&amp;rsquo;m happy to say I made good progress, and I&amp;rsquo;m starting to look at putting all this together in an implementation.&lt;/p&gt;
&lt;h2 id=&#34;deno-20-heating-up&#34;&gt;Deno 2.0 Heating Up&lt;/h2&gt;
&lt;p&gt;A lot of activity on some issues I subscribe to on Deno&amp;rsquo;s Github project. It appears they&amp;rsquo;re getting ready to ship Deno 2.0.&lt;/p&gt;
&lt;p&gt;My most desperately needed feature is &lt;a href=&#34;https://github.com/denoland/deno/issues/22902&#34;&gt;allow-net-fetch&lt;/a&gt; or something like it. The Deno crew looked at it and deemed it was not a breaking change, therefore it will not make it in 2.0. However they seem to say they get the use case for this? So maybe later? For now more waiting&amp;hellip;&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know if they&amp;rsquo;ll make changes to &lt;code&gt;--allow-net&lt;/code&gt; for 2.0. It would be wild if they didn&amp;rsquo;t. If ever there was a thing to change in the CLI it&amp;rsquo;s that set of permissions. See my &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-net-requests/&#34;&gt;post about allowing outgoing net requests&lt;/a&gt;. Also see &lt;a href=&#34;https://github.com/denoland/deno/issues/2705&#34;&gt;this issue&lt;/a&gt; about how the net permissions don&amp;rsquo;t distinguish between listen and dial.&lt;/p&gt;
&lt;p&gt;When the first release candidates for Deno 2.0 come out I will likely pause my work on Tailscale integration to make sure Dropserver works with Deno 2! So expect that to happen.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s no bad thing. I have a few little fixes and improvements I can ship along with 2.0 support. And tailscale integration is going to run long, so a release will be in order anyways.&lt;/p&gt;
&lt;h2 id=&#34;moving-forwards-slowly-but-surely&#34;&gt;Moving Forwards Slowly But Surely&lt;/h2&gt;
&lt;p&gt;Since I got back from my trip in early August, I can&amp;rsquo;t say I&amp;rsquo;ve been super productive. I&amp;rsquo;m actually at about 60% productivity (based on  the number of Pomodoros I complete per week) and a lot of that is spent working on non-Dropserver stuff.&lt;/p&gt;
&lt;p&gt;So things are moving slowly, but they&amp;rsquo;re moving. Hopefully I can rev things up a bit now that the kids are back in school.&lt;/p&gt;
&lt;p&gt;Til the next one..&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - June 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-june-2024/</link>
      <pubDate>Fri, 05 Jul 2024 16:38:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-june-2024/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for June 2024. Here is &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-may-2024/&#34;&gt;last month&lt;/a&gt;&amp;rsquo;s report.&lt;/p&gt;
&lt;p&gt;I started on the &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; integration, which began by getting the &lt;code&gt;tsnet&lt;/code&gt; package, which resulted in a shock.&lt;/p&gt;
&lt;h2 id=&#34;go-get-tailscalecomtsnet--&#34;&gt;Go get tailscale.com/tsnet &amp;hellip; 😲&lt;/h2&gt;
&lt;p&gt;After entering the command the machine churned for several minutes while unfurling a seemingly endless listing of dependent packages required by &lt;a href=&#34;https://pkg.go.dev/tailscale.com/tsnet&#34;&gt;tsnet&lt;/a&gt;. Yikes.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tsnet&lt;/code&gt; loads lots of dependencies from the &lt;a href=&#34;https://pkg.go.dev/tailscale.com&#34;&gt;&lt;code&gt;tailscale.com&lt;/code&gt; package&lt;/a&gt; which is expected. But these in turn load some surprising stuff. In particular, Dropserver &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/c3ded2bac136d0ae06e49c1fe2bfcc7acbaeb323#diff-33ef32bf6c23acb95f5902d7097b7a1d5128ca061167ec0716715b0b9eeaa5f6&#34;&gt;now depends&lt;/a&gt; on the &lt;a href=&#34;https://docs.aws.amazon.com/sdk-for-go/&#34;&gt;AWS SDK&lt;/a&gt; because &lt;a href=&#34;https://pkg.go.dev/tailscale.com/ipn/store&#34;&gt;tailscale.com/ipn/store&lt;/a&gt; has an option of storing stuff on S3.&lt;/p&gt;
&lt;p&gt;Having unused dependencies like that isn&amp;rsquo;t great, but I could live with it. And the reality is I&amp;rsquo;m likely going to end up depending on AWS SDK to allow pushing appspace backups to S3-compatible storage some day.&lt;/p&gt;
&lt;p&gt;But I got a shock when I compiled &lt;code&gt;ds-host&lt;/code&gt; with &lt;code&gt;tsnet&lt;/code&gt;: the built size went from 28 megs to &lt;strong&gt;47&lt;/strong&gt;! Yikes. Hello bloat. 😞&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tsnet&lt;/code&gt; creates an entire networking stack in user-space, so it&amp;rsquo;s not surprising that the build got bigger, but this is a lot. For this and other reasons, I am going to try to make it possible to build a Tailscale-free version of ds-host.&lt;/p&gt;
&lt;h2 id=&#34;integrating-tailscale-easier-said&#34;&gt;Integrating Tailscale (Easier Said&amp;hellip;)&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s easy to say I&amp;rsquo;ll integrate Tailscale into Dropserver. But there are a number of decisions to make on how this is actually going to work.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m realizing that there are likely two types of people who may want to use Dropserver via Tailscale: those who have a &lt;a href=&#34;https://tailscale.com/kb/1136/tailnet&#34;&gt;Tailnet&lt;/a&gt; in active use and those who will use Tailscale for the sole purpose of simplifying their self-hosting adventure with Dropserver.&lt;/p&gt;
&lt;p&gt;I have to consider that active Tailscale users will not allow Dropserver to do anything dubious in their Tailnet and they will likely control things themselves in the &lt;a href=&#34;https://tailscale.com/kb/1018/acls?q=acl&#34;&gt;ACL&lt;/a&gt;s. Meanwhile, users without Tailscale may not know much about ACLs and may want to minimize their interactions with the Tailscale admin panel.&lt;/p&gt;
&lt;p&gt;In either case I want to preserve the ideals of Dropserver while making Dropserver nodes &amp;ldquo;good citizens&amp;rdquo; of a Tailnet. And as always security is critical. Meeting all these goals won&amp;rsquo;t be easy.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll write a full post on the integration when I am further along, but here are some quick gotchas that I&amp;rsquo;m up against:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tailnets do not support &lt;a href=&#34;https://github.com/tailscale/tailscale/issues/11229#issuecomment-1962729863&#34;&gt;subdomains for a node&lt;/a&gt;. Woops! Subdomains are the common way of creating an address for an appspace. There is a workaround: each appspace will be its own Tailscale node.&lt;/li&gt;
&lt;li&gt;ACLs control who can access each node and are &lt;a href=&#34;https://tailscale.com/kb/1338/acl-edit&#34;&gt;edited by hand&lt;/a&gt; in a JSON file on the Tailscale website. One goal of Dropserver is to not have to hand-edit config files when hosting a new app or adding a user!&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s possible to edit the ACLs via an API, but there are no granular permissions. An API client that can edit the ACLs can make an absolute mess of your tailnet. I don&amp;rsquo;t imagine anybody that actually uses Tailscale for things other than Dropserver giving DS the keys to their tailnet. No way.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite these (and other issues) I think I see a path forward, but I&amp;rsquo;m only partway through a functioning implementation so I am not confident I&amp;rsquo;ve got it right. Stay tuned.&lt;/p&gt;
&lt;h2 id=&#34;appspace-meta-db-versioning-and-migrations&#34;&gt;Appspace Meta DB Versioning and Migrations&lt;/h2&gt;
&lt;p&gt;As mentioned in last month&amp;rsquo;s progress report integrating Tailscale means changing the Appspace Meta DB schema, where &lt;a href=&#34;https://dropserver.org/docs/application-model&#34;&gt;appspace&lt;/a&gt; users are stored. This means that for the first time I will have different schemas for the Appspace Meta DB in the wild. A backup of an appspace that is sitting in my Downloads folder will likely be at versions 0 (sans Tailscale). All currently used appspaces will have their Appspace Meta DB at version 1.&lt;/p&gt;
&lt;p&gt;I need to work through that situation while preserving the goal that Dropserver should &amp;ldquo;just work&amp;rdquo; and users should not get weird error messages or become stuck unable to use their data.&lt;/p&gt;
&lt;p&gt;To handle this Dropserver will determine the schema of any Appspace Meta DB it comes across and act accordingly. It will migrate up to the current version when appropriate. Some work alredy done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Change migration code for Appspace Meta DB. Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/8fa902afc879fc66ed1331a8292ebb32b087c7b6&#34;&gt;8fa902&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Add table to allow multiple auths in Meta DB. Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/66271e5a8e88c31aadb0f6e822f570b6eaa53ccf&#34;&gt;66271e&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next I need to work migrating all Meta DBs when the ds-host instance changes, and performing migrations when necessary when importing appspace data from backups.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll keep working on Tailscale integration!&lt;/p&gt;
&lt;p&gt;However between Summer vacation and non-Dropserver work my progress will continue to be slowed. In fact I&amp;rsquo;m going to call it now: there will be no Progress Report for July as too little will get done. I&amp;rsquo;ll be back at it in August. See you then!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - May 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-may-2024/</link>
      <pubDate>Mon, 10 Jun 2024 18:09:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-may-2024/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for May 2024. Here is &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-april-2024/&#34;&gt;last month&lt;/a&gt;&amp;rsquo;s report.&lt;/p&gt;
&lt;p&gt;May was a &amp;ldquo;Spring cleaning&amp;rdquo; month. Before launching into my next big project (&lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; integration) I want to have a clean code base, or at least clean out the obvious relics of ancient ideas that never fully blossomed.&lt;/p&gt;
&lt;p&gt;Here we go:&lt;/p&gt;
&lt;h2 id=&#34;remove-unused-appspace-db-code&#34;&gt;Remove Unused Appspace DB Code&lt;/h2&gt;
&lt;p&gt;Back in ancient times Dropserver apps could store data in a sqlite DB that was managed by Dropserver. Reads and writes went through a rather lame API from the sandbox side via a decidedly unfinished protocol. I disabled this a long time ago and recommend app devs use a &lt;a href=&#34;https://github.com/dyedgreen/deno-sqlite/&#34;&gt;WASM build of SQLite&lt;/a&gt; directly in their app.&lt;/p&gt;
&lt;p&gt;Yet there was quite a bit of code left over from this &amp;ldquo;Appspace DB&amp;rdquo; that remained to this day. &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/55cedec9c41b7581504a48c5ff201b18b360e26d&#34;&gt;No more&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Cleaning this up was important because the Appspace DB code is easily confused with the &amp;ldquo;Appspace Meta DB&amp;rdquo; which holds data about the appspace and is going to get a lot of attention when I work on Tailscale. integration (see below).&lt;/p&gt;
&lt;h2 id=&#34;rethink-backwards-compabilitlity&#34;&gt;Rethink Backwards Compabilitlity&lt;/h2&gt;
&lt;p&gt;Tailscale integration will bring new data types to the Appspace Meta DB, where users and their access types and ids are stored. This means I&amp;rsquo;ll have two versions of appspace meta DBs in the wild: the original version, and the new one with the ability to store tailscale data.&lt;/p&gt;
&lt;p&gt;This launched me down a path of rethinking how to do backwards compatibility in Dropserver. Its important to get it right, and I&amp;rsquo;m pretty sure I got it wrong, so a rethink is in order.&lt;/p&gt;
&lt;p&gt;See the post &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-backwards-compatibility/&#34;&gt;Building Backwards Compatibility into Dropserver&lt;/a&gt; for the latest thinking.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t mention the Appspace MEta DB in the post, but the implication is that there is only one version of the Meta DB understood by a given version of Dropserver.&lt;/p&gt;
&lt;p&gt;As such, the host will migrate the Meta DB of any appspace it encounters to its current version.&lt;/p&gt;
&lt;p&gt;This means that if you upgrade &lt;code&gt;ds-host&lt;/code&gt; and it supports new features and a new MetaDB schema, then all the appspaces get migrated to this schema. If you import a backup of an appspace and it needs to be migrated, that will happen too.&lt;/p&gt;
&lt;p&gt;Should you want to use an appspace that was migrated on an older &lt;code&gt;ds-host&lt;/code&gt;, then down-migration tools should be available too, possibly within &lt;code&gt;ds-host&lt;/code&gt; itself.&lt;/p&gt;
&lt;p&gt;With that in mind I was able to eliminate a lot of &lt;code&gt;v0&lt;/code&gt; code, which makes the codebase feel cleaner. I still need to write the Appspace Meta DB migration logic though.&lt;/p&gt;
&lt;h2 id=&#34;deno-config-and-import-maps&#34;&gt;Deno Config and Import maps&lt;/h2&gt;
&lt;p&gt;In addition to cleaning up the code, I have to keep an eye on the evolution of Deno to make sure I don&amp;rsquo;t fall too far behind.&lt;/p&gt;
&lt;p&gt;With the advent of &lt;a href=&#34;https://jsr.io/&#34;&gt;JSR&lt;/a&gt; I am feeling more pressure to support custom import maps for Dropserver apps. &lt;a href=&#34;https://jsr.io/docs/using-packages#adding-a-package&#34;&gt;JSR leans on import maps&lt;/a&gt; to make adding packages more convenient, and I should support that. I spent some time exploring all the ways Deno uses import maps, and looked at &lt;a href=&#34;https://html.spec.whatwg.org/multipage/webappapis.html#import-maps&#34;&gt;the spec&lt;/a&gt; carefully and ran a number of experiments.&lt;/p&gt;
&lt;p&gt;Dropserver uses import maps to prevent static access to files outside the allowed directories (see &lt;a href=&#34;https://github.com/denoland/deno/issues/6294#issuecomment-663256029&#34;&gt;this issue comment&lt;/a&gt;). Allowing custom import maps means being careful not to give the app any ability to read a file outside of its direcotry.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m happy with what I learned and I almost started implementing this but something happened that made me put it aside for now.&lt;/p&gt;
&lt;h2 id=&#34;file-descriptor-and-goroutine-leaks&#34;&gt;File Descriptor and Goroutine Leaks&lt;/h2&gt;
&lt;p&gt;My personal Dropserver instance stopped working all of a sudden. Turns out I had too many open files? This was frustrating because that is not the first time it happens and I thought I &lt;a href=&#34;https://github.com/teleclimber/Dropserver/issues/113&#34;&gt;fixed it last time&lt;/a&gt;. Evidently not.&lt;/p&gt;
&lt;p&gt;Dropserver is supposed to run for a long time without needing any attention. When it blows up like that it&amp;rsquo;s really disruptive. These kinds of headaches are why people don&amp;rsquo;t want to run their own services. It&amp;rsquo;s a pain to have to deal with them when they don&amp;rsquo;t run.&lt;/p&gt;
&lt;p&gt;My hunt for leaking file descriptors and goroutines was more thorough this time: see commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/6e0f48eb358ddd3f93e6c7972b8fe675923b0213&#34;&gt;6e0f48&lt;/a&gt;, &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/1dd6bc15a3e0d4e933a89ca3415dfa3f68d2c55c&#34;&gt;1dd6bc&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/9f442fcf6eef95fed310caa8646ba17555e40a7f&#34;&gt;9f442f&lt;/a&gt;. I might write a blog post on what I learned along the way.&lt;/p&gt;
&lt;h2 id=&#34;release-dropserver-0132&#34;&gt;Release Dropserver 0.13.2&lt;/h2&gt;
&lt;p&gt;By now I&amp;rsquo;ve accumulated a number of minor improvements and code changes, so it would be good to push that out to the world.&lt;/p&gt;
&lt;p&gt;Prior to shipping, a routine upgrade of node modules turned into a hour-long battle with my &lt;code&gt;Tailwind&lt;/code&gt; and &lt;code&gt;PostCSS&lt;/code&gt; and &lt;code&gt;package.json&lt;/code&gt; files. I swore off Tailwind a while ago, but I have yet to rewrite the Dropserver frontend using regular CSS, so I&amp;rsquo;m subject to it ruining my joie de vivre for now. (The error was &amp;ldquo;Vite CJS Node API deprecated&amp;rdquo;; see &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/7c7eff2da3ddde559699f381f0d96c5e967c71c7&#34;&gt;this commit&lt;/a&gt; for the fix.)&lt;/p&gt;
&lt;p&gt;Version &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.2&#34;&gt;0.13.2 is finally out&lt;/a&gt;, it includes a proxy for outbound requests from the sandbox that I &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-net-requests/&#34;&gt;described last month&lt;/a&gt;, the fix to goroutine and fd leaks, and a few other things.&lt;/p&gt;
&lt;h2 id=&#34;compile-ds-host-for-macos&#34;&gt;Compile ds-host for MacOS&lt;/h2&gt;
&lt;p&gt;For the Tailscale integration work I thought it might be easier if &lt;code&gt;ds-host&lt;/code&gt; was running directly on my Mac. &lt;code&gt;ds-dev&lt;/code&gt; already runs fine on the OS, so why wouldn&amp;rsquo;t &lt;code&gt;ds-host&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;One &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/e27ba997a65ec3e127d12e44a090c3f73f9cf00a&#34;&gt;little commit&lt;/a&gt; later and &lt;code&gt;ds-host&lt;/code&gt; runs on the Mac too! With the config set to just serve over localhost, I can access it via &lt;code&gt;dropid.localhost&lt;/code&gt; and appspaces are accessed at their own subdomain like &lt;code&gt;leftovers.localhost&lt;/code&gt; (Except on Safari, which doesn&amp;rsquo;t support subdomains on localhost 😠).&lt;/p&gt;
&lt;p&gt;This is encouraging. I&amp;rsquo;ll need to make some tweaks, and try to get &lt;code&gt;ds-host&lt;/code&gt; to run under the MacOS sandbox since &lt;a href=&#34;https://github.com/containers/bubblewrap&#34;&gt;Bubblewrap&lt;/a&gt; doesn&amp;rsquo;t work in this environment (On Liunx &lt;a href=&#34;https://olivierforget.net/blog/2023/dropserver-sandbox/&#34;&gt;Bubblewrap is a second layer of sandboxing in addition to Deno&lt;/a&gt;) but I can foresee a future where I offer a build of &lt;code&gt;ds-host&lt;/code&gt; for the Mac.&lt;/p&gt;
&lt;p&gt;I am so excited about this I checked the price of &lt;a href=&#34;https://www.macofalltrades.com/mac-mini/&#34;&gt;used Mac Minis&lt;/a&gt;: under $100 if you&amp;rsquo;re willing to live with 10 year old spinning disks! Might want to spend a bit more, but self-hosting Dropserver on a Mac Mini would be a great option for people who know Macs and are intimidated by Linux.&lt;/p&gt;
&lt;h1 id=&#34;onwards&#34;&gt;Onwards&lt;/h1&gt;
&lt;p&gt;I just started work on the Tailscale integration. A tailnet is a rather different environment than the global internet, and as such a number of assumptions I naively baked into the Dropserver code are going to have to be rethought. So this is going to take some time.&lt;/p&gt;
&lt;p&gt;In the meantime, I just looked at my Grafana dashboard on my personal instance and the goroutines and file descriptors lines are staying under control. Pfew!&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2024/dropserver-progress-may-2024/goroutines-flat_huf75413fd99a33676afa297bef446fa4e_47148_516x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2024/dropserver-progress-may-2024/goroutines-flat_huf75413fd99a33676afa297bef446fa4e_47148_516x0_resize_box_3.png, https://olivierforget.net/blog/2024/dropserver-progress-may-2024/goroutines-flat_huf75413fd99a33676afa297bef446fa4e_47148_1032x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot of Grafana dsahboard showing the number of goroutines over time.&#34;&gt;
&lt;p&gt;(Although I know of some situations where I still have problems, like upgrading an app causes leaks. That&amp;rsquo;s for another day!)&lt;/p&gt;
&lt;p&gt;See you next time.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Remembering My Time With Dick Rutan</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dick-rutan/</link>
      <pubDate>Mon, 03 Jun 2024 14:47:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dick-rutan/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Dick_Rutan&#34;&gt;Dick Rutan&lt;/a&gt; died earlier last month. This caused me to revisit a time in my life when I worked for him, flew with him, and shared in the misadventures of a failed project with him.&lt;/p&gt;
&lt;p&gt;I worked for Dick from the Summer of 1998 to Spring 1999 while he was on his second attempt at being the first to go around the world in a balloon non-stop and non-refueled. He was already famous for his circumnavigation of Earth in the &lt;a href=&#34;https://en.wikipedia.org/wiki/Rutan_Voyager&#34;&gt;Voyager&lt;/a&gt; in 1986. That aircraft hangs in the National Air and Space Museum in Washington DC where I grew up. I spent a lot of time in that museum in my youth and already imagined myself as an aerospace engineer, so any Rutan project was tantalizing.&lt;/p&gt;
&lt;p&gt;In 1998 I was studying engineering in Montreal. When I heard of Dick&amp;rsquo;s ballooning ambitions I traveled to &lt;a href=&#34;https://en.wikipedia.org/wiki/Mojave_Air_and_Space_Port&#34;&gt;Mojave&lt;/a&gt; to try to land a job on the project by just showing up.&lt;/p&gt;
&lt;p&gt;It worked.&lt;/p&gt;
&lt;p&gt;Here are a few vignettes from that era.&lt;/p&gt;
&lt;h2 id=&#34;dick-the-scamp&#34;&gt;Dick the scamp&lt;/h2&gt;
&lt;p&gt;Dick was due to give a talk at the &lt;a href=&#34;https://www.eaa.org/eaa-museum&#34;&gt;EAA Museum&lt;/a&gt; during &lt;a href=&#34;https://en.wikipedia.org/wiki/EAA_AirVenture_Oshkosh&#34;&gt;Airventure&lt;/a&gt; 1998 in Oshkosh, WI. I was tagging along with him. We arrived a bit late at the venue and we entered through the main doors at the back of the auditorium. The crowd was already thick and facing the stage anticipating the arrival of the aviation legend. Since they were all facing away, nobody noticed our arrival. Dick moved forwards through the mass of people. He paused behind someone and muttered &amp;ldquo;Do you think he&amp;rsquo;s even going to show up?&amp;rdquo; then moved ahead. He did this to a few people, saying things along the lines of &amp;ldquo;How long is he going to make us wait?&amp;rdquo; and &amp;ldquo;Who does this guy think he is?&amp;rdquo; all the while moving ahead as if nothing had been said.&lt;/p&gt;
&lt;p&gt;His victims were quite amused by their brush with the pilot after they figured out who was saying these things.&lt;/p&gt;
&lt;h2 id=&#34;dick-says-things&#34;&gt;Dick says things&lt;/h2&gt;
&lt;p&gt;At that same Oshkosh event he had been talking mostly about his experience flying the Voyager. That is what he was known for. I remember asking Dick if the &amp;ldquo;Balloon Project&amp;rdquo; was going to be as great as the Voyager project.&lt;/p&gt;
&lt;p&gt;He said: &amp;ldquo;It&amp;rsquo;s going to be even better.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;Balloon Project&amp;rdquo; was a failure. His first attempt ended with him &lt;a href=&#34;https://www.youtube.com/watch?v=_n3ALL3VIKE&#34;&gt;bailing out&lt;/a&gt; before his balloon &lt;a href=&#34;http://www.cnn.com/US/9801/09/balloon3/&#34;&gt;crashed and burned somewhere in the Midwest&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The second attempt was perpetually held in limbo state by lack of funds. It seemed nobody wanted to give us any money (I wonder why?). My emails to my parents are rundowns of all the ways in which we failed to unlock some much needed funds from rich people.&lt;/p&gt;
&lt;p&gt;Dick had choice words for all these people and organizations who had all the money but none of the spirit and tenacity and courage that he had in spades.&lt;/p&gt;
&lt;p&gt;But this limbo state also made my experience special. Had we gotten funding, we would have hired a bunch of people and would have gone into a pressure-cooker work environment. I had very little experience about anything at the time, so I would have been just one worker bee among others. It wouldn&amp;rsquo;t have been the same.&lt;/p&gt;
&lt;p&gt;The way things worked out the project was at best half-dead until it was fully dead. I was the only person working apart from a tiny team of long-time Rutan acolytes. I talked directly with Dick and crew chief Bruce Evans on a regular basis. Dick called on me for various things, including helping him fly his hot air balloon.&lt;/p&gt;
&lt;p&gt;The result is I got a meaningfully close look at the man, and I am grateful for it.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2024/dick-rutan/dick-me-bruce_hu3e25d4ec0a8b47916b9ad54cba254ef1_4671996_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2024/dick-rutan/dick-me-bruce_hu3e25d4ec0a8b47916b9ad54cba254ef1_4671996_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2024/dick-rutan/dick-me-bruce_hu3e25d4ec0a8b47916b9ad54cba254ef1_4671996_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;Dick Rutan, me and Bruce Evans in front the habitable high-altitude ballooning capsule I was helping to build.&#34;&gt;
&lt;p&gt;&lt;em&gt;Dick Rutan, me and Bruce Evans in front the habitable high-altitude ballooning capsule I was helping to build.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;adventure-is-the-essence-of-life&#34;&gt;Adventure is the essence of life&lt;/h2&gt;
&lt;p&gt;He wrote this on a poster of the voyager he gifted me: &amp;ldquo;Adventure is the Essence of Life.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Even after hearing many of the stories first hand, it is still striking to read his obituary in the media. His collection of adventures lived are something to behold.&lt;/p&gt;
&lt;p&gt;He could have stopped after Voyager and just talked about that on the speaking circuit for the rest of his life. But that&amp;rsquo;s not Dick.&lt;/p&gt;
&lt;p&gt;One day he was sitting in the office in the balloon hangar bemoaning the state of affairs. He must have just been rejected for funding yet again and must have really felt that his chance was slipping away.&lt;/p&gt;
&lt;p&gt;He said somberly: &amp;ldquo;I would hate it if the greatest thing I&amp;rsquo;ll ever do is behind me&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;He was over 60 at the time and already an aviation legend. But this really bugged him. He was made to go further and higher. What do you do after you get there?&lt;/p&gt;
&lt;h2 id=&#34;life-is-a-shit-sandwich&#34;&gt;&amp;ldquo;Life is a shit sandwich&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;I remember a late evening meeting with a representative of a very big company headed by a very rich guy. We were on our last gasps but had high hopes. The funds would amount to a rounding error in their books. After the main meeting, Dick spoke alone with the rep.&lt;/p&gt;
&lt;p&gt;I was poking around in the shop, heart in my stomach as I waited for the news.&lt;/p&gt;
&lt;p&gt;He emerged gloomy. Burned again.&lt;/p&gt;
&lt;p&gt;He found me and said: &amp;ldquo;Well Oliver, life is a shit sandwich and every other day you have to take a big bite.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So much for optimism. Earlier in the project he had been answering any doubt about our chances with the mantra &amp;ldquo;it&amp;rsquo;s darkest before dawn.&amp;rdquo; We were now in the &amp;ldquo;shit sandwich&amp;rdquo; phase.&lt;/p&gt;
&lt;p&gt;About a month later the &lt;a href=&#34;https://en.wikipedia.org/wiki/Breitling_Orbiter&#34;&gt;Breitling Orbiter&lt;/a&gt; completed its circumnavigation of the planet and Dick&amp;rsquo;s ballooning ambitions were forever put to rest.&lt;/p&gt;
&lt;h2 id=&#34;the-certified-flight-instructor&#34;&gt;The Certified Flight Instructor&lt;/h2&gt;
&lt;p&gt;After the project died for good Dick offered to give me flying lessons. He would get me to my first solo in a power plane (I was already a solo glider pilot). After he died I spotted a number of people on social media reminiscing about their time learning to fly from Dick.&lt;/p&gt;
&lt;p&gt;He loved to share the art of flying.&lt;/p&gt;
&lt;h2 id=&#34;this-piece-of-plastic-is-historic-or-not&#34;&gt;This piece of plastic is historic (or not)&lt;/h2&gt;
&lt;p&gt;One day towards waning days of the project he said he wanted to give me something. It was a piece of transparent plastic. &amp;ldquo;It&amp;rsquo;s from when we made the windows for the Voyager. You could go to the National Air and Space Museum, hold this up to the window of the Voyager, and it will fit perfectly.&amp;rdquo; Supposedly as they cut the pieces of plastic that made up the window, he kept a piece of discarded plastic as a keepsake.&lt;/p&gt;
&lt;p&gt;I have no idea if this piece of plastic is actually from the Voyager. Maybe he kept it for fifteen years and finally decided to part with it, or maybe Dick just felt like seeing my eyes light up for a piece of trash. I wouldn&amp;rsquo;t put it past him, the scamp that he was.&lt;/p&gt;
&lt;p&gt;That plastic may not have been from Voyager but it was definitely from Dick: full of optimism and historical aspirations but it requires one to be firmly grounded.&lt;/p&gt;
&lt;h2 id=&#34;goodbye-dick&#34;&gt;Goodbye Dick&lt;/h2&gt;
&lt;p&gt;Well Dick, you&amp;rsquo;ve taken the last bite of your shit sandwich.&lt;/p&gt;
&lt;p&gt;Thanks for letting me tag along during a tiny sliver of your incredible life. It may not have been the most glorious part of your life, but for me it was a highlight.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Building Backwards Compatibility into Dropserver</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-backwards-compatibility/</link>
      <pubDate>Mon, 20 May 2024 17:45:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-backwards-compatibility/</guid>
      <description>&lt;p&gt;An unfortunate pitfall of modern computing is to be forced to make the choice between upgrading an operating system and continuing to use a beloved old app. Forcing this on users brings out some choice words for the developers of the OS, but a system that can evolve to its full potential while running old code is hard to build.&lt;/p&gt;
&lt;p&gt;I would like for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt;, an OS of sorts, to continue to run old apps for as long as possible even as it evolves. Here is how I&amp;rsquo;m thinking through it.&lt;/p&gt;
&lt;h2 id=&#34;layers&#34;&gt;Layers&lt;/h2&gt;
&lt;p&gt;There are several layers of APIs between the application code and the core Dropserver internals. These layers provide opportunities to make backwards compatible adapters, or to hide the ugliness of aging legacy APIs. Here is the list of layers as things stand:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dropserver_app&lt;/code&gt; &lt;a href=&#34;https://deno.land/x/dropserver_app&#34;&gt;library&lt;/a&gt;. Imported by the app to interact with the Dropserver system, as &lt;a href=&#34;https://dropserver.org/docs/build-dropserver-app-tutorial&#34;&gt;shown in the tutorial&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dropserver_lib_support&lt;/code&gt; compatibility layer is a dependency of both &lt;code&gt;dropserver_app&lt;/code&gt; and &lt;code&gt;denosandboxcode&lt;/code&gt;. It&amp;rsquo;s &lt;a href=&#34;https://deno.land/x/dropserver_lib_support@v0.2.0&#34;&gt;a bunch of TypeScript types&lt;/a&gt; that ensures the layer above and the layer below can talk to each other when they are run together.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;denosandboxcode&lt;/code&gt; ships with the Dropserver host, and is therefore &lt;a href=&#34;https://github.com/teleclimber/Dropserver/tree/master/denosandboxcode&#34;&gt;part of its repo&lt;/a&gt;. It runs in the sandbox alongside the app code. It communicates with &amp;ldquo;Sandbox Services&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Sandbox Services&amp;rdquo; in Dropserver host. It listens for queries from the sandbox side and passes these on to the appropriate data model or whatever.&lt;/li&gt;
&lt;li&gt;Data models and controllers in Dropserver host. These talk to databases or other forms of storage. It&amp;rsquo;s the end of the line.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s look at how each layer help backwards-compatibility:&lt;/p&gt;
&lt;h4 id=&#34;dropserver_app&#34;&gt;dropserver_app&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;dropserver_app&lt;/code&gt; library can evolve without changing the underlying API. In other words, I can make improvements to the syntactic sugar without making any changes to the underlying APIs. As such there are no changes to be made that may cause older versions to no longer work.&lt;/p&gt;
&lt;p&gt;However making changes to this library can put app developers in an annoying spot as we&amp;rsquo;ll see below.&lt;/p&gt;
&lt;h4 id=&#34;dropserver_lib_support&#34;&gt;dropserver_lib_support&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;dropserver_lib_support&lt;/code&gt; is the compatibility layer that must remain back-compatible with itself. If I want to change anything there, I have to add a new type, or a new optional field in an existing type. I can&amp;rsquo;t delete anything, ever, if I want old apps to run. It&amp;rsquo;s going to grow over time and will include bad function names like &amp;ldquo;getUsersV3&amp;rdquo;. However, because lib_support is not used directly by the app dev, they are not subjected to this. The new versions of &lt;code&gt;dropserver_app&lt;/code&gt; will use the new APIs with nice names.&lt;/p&gt;
&lt;p&gt;Again since &lt;code&gt;dropserver_lib_support&lt;/code&gt; is hidden, it can be low level and it can be &amp;ldquo;ugly&amp;rdquo;. That&amp;rsquo;s fine, it&amp;rsquo;s hidden away. Types should be added slowly and carefully with an eye to maintaining them long term. The syntactic sugar and nice API can be left for &lt;code&gt;dropserver_app&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;denosandboxcode&#34;&gt;denosandboxcode&lt;/h4&gt;
&lt;p&gt;In &lt;code&gt;denosandboxcode&lt;/code&gt; I have the opportunity to handle old APIs by transforming them into new APIs. Remember that &lt;code&gt;denosandboxcode&lt;/code&gt; ships with Dropserver. As a result it handles the latest API (at the time of shipping). But it also has to handle all the old APIs. The best possible outcome is that old API calls can be transformed into new API calls right there in the sandbox. That way the Dropserver host does not need to ship with a &amp;ldquo;Sandbox Service&amp;rdquo; that can handle multiple versions of an API.&lt;/p&gt;
&lt;h4 id=&#34;sandbox-services&#34;&gt;Sandbox Services&lt;/h4&gt;
&lt;p&gt;It&amp;rsquo;s possible an old API can&amp;rsquo;t be coerced into a new API inside the sandbox for some reason, in which case the transformation may be able to take place at the service level. The difference between this and the sandbox is that the &amp;ldquo;Sandbox Service&amp;rdquo; runs on the host and has access to all the data about the appspace, users, etc&amp;hellip; while that information is strictly limited inside the sandbox.&lt;/p&gt;
&lt;h4 id=&#34;core-models-and-controllers&#34;&gt;Core Models and Controllers&lt;/h4&gt;
&lt;p&gt;Finally, if all else fails, there is the possibility of versioning the very core of Dropserver&amp;rsquo;s handling of app and appspace data, like the users DB, etc&amp;hellip; This manifests itself with parts of the host code named &lt;code&gt;v0AppspaceRoutes&lt;/code&gt; and &lt;code&gt;v0AppspaceUsers&lt;/code&gt; (note the &lt;code&gt;v0&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;This was actually going to be the primary way of doing things but my thinking has evolved.&lt;/p&gt;
&lt;h2 id=&#34;the-thinking-evolves&#34;&gt;The Thinking Evolves&lt;/h2&gt;
&lt;p&gt;I originally set up a good chunk of Dropserver code with these &lt;code&gt;v0&lt;/code&gt; names. I did this thinking it was the right approach, but I just removed these. Here is why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Versioning is viral&lt;/strong&gt;: when you start having versioned data structures, some other structs that depend on them may need to be versioned as well. If you display any of this data to the user, the frontend code that handles this gets versioned too, not to mention the APIs used to fetch the data. Next thing you know you&amp;rsquo;ve got more versioned code than you ever wanted to see.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;More code to maintain is bad&lt;/strong&gt;: maintaining old code paths is hard. Keep these to a minimum. You do this by eliminating the difference between an old API and the current one as early as possible. That means inside &lt;code&gt;denosandboxcode&lt;/code&gt; if at all possible. That way the core of Dropserver stays free of versioned madness.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The goal should be no changes&lt;/strong&gt; anyways. API versions imply breaking changes. Nobody wants that. So why lay the groundwork for it?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Makes small additions hard.&lt;/strong&gt; If I want to add a small feature, do I have to increment the version? That makes a big deal of every small change. I might even hesitate to make the change, holding it back until I have all the pieces that warrant a major API change. This doesn&amp;rsquo;t line up with how I&amp;rsquo;d like to work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API versions imply big releases.&lt;/strong&gt; A project like Android has API versions, and new versions coincide with new Android releases, which are announced at big flashy events every year. That&amp;rsquo;s not how I envision Dropserver. It&amp;rsquo;s a stable project. It must evolve of course, but not in that big flashy release manner that seems to be favored by companies that build planned-obsolescence into their products. By contrast, look at how &lt;a href=&#34;https://canonical.com/lxd&#34;&gt;LXD&lt;/a&gt; do it: they have a 1.0 API, and a myriad of &lt;a href=&#34;https://documentation.ubuntu.com/lxd/en/stable-5.0/api-extensions/&#34;&gt;API extensions&lt;/a&gt;. I like that better.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For all the reasons above I&amp;rsquo;ve &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commits/master/?since=2024-05-14&amp;amp;until=2024-05-16&#34;&gt;eliminated the v0 code&lt;/a&gt; wherever I could.&lt;/p&gt;
&lt;h2 id=&#34;what-about-forward-compatibility&#34;&gt;What About Forward Compatibility?&lt;/h2&gt;
&lt;p&gt;One conundrum I still have to deal with is the situation where a new version of Dropserver includes a new API for app developers, and therefore is accompanied by a new version of &lt;code&gt;dropserver_app&lt;/code&gt;. If an app developer uses the newest dropserver_app library to write a new app, does that app require the latest version of DS to run? Even if it doesn&amp;rsquo;t use the new API?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve talked about backwards compatibility where an old app can continue to run on newer Dropserver versions. But what about a brand new app running on an older instance?&lt;/p&gt;
&lt;p&gt;While I would like Dropserver instances to be updated regularly, realistically this won&amp;rsquo;t happen. Ideally a new app made with recent versions of the libraries I publish should be usable on older versions of Dropserver.&lt;/p&gt;
&lt;p&gt;The solution here I think is to not have a monolithic &lt;code&gt;dropserver_app&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;cmon-man-just-one-more-layer&#34;&gt;C&amp;rsquo;Mon Man Just One More Layer&lt;/h2&gt;
&lt;p&gt;I haven&amp;rsquo;t fully worked this out but here&amp;rsquo;s where I think things are going to go:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dropserver_app&lt;/code&gt; will become a shell of sorts, and the app dev will import other libraries, like &lt;code&gt;dropserver_users&lt;/code&gt; and &lt;code&gt;dropserver_routes&lt;/code&gt; to interact with the DS system. The objects created by these libraries are passed into &lt;code&gt;createApp()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So if an app only needs to use basic (older) route features, they can select the &lt;code&gt;dropserver_routes@^1.0.0&lt;/code&gt; and keep their app usable on old versions of Dropserver. If they need the newest features, they can use &lt;code&gt;^2.0.0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;createApp()&lt;/code&gt; can examine the objects passed in and determine the APIs that are required to run this app. This list of APIs used by the app is very handy for devX and UX reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ds-dev&lt;/code&gt; can show the app developer the minimum version of Dropserver needed to run their app (you can assume Dropserver will have a map of API -&amp;gt; minimum Dropserver version)&lt;/li&gt;
&lt;li&gt;When an app is published, that info can be embedded in the manifest and shown in the app distribution site.&lt;/li&gt;
&lt;li&gt;When installing, the user can reliably be told the version of Dropserver they need.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another advantage with this approach is that the app developer can use the latest version of the &lt;code&gt;dropserver_routes&lt;/code&gt; without being forced to use the latest version of the users API (since they are separate libraries.) This means they can adopt a new feature without being cornered into adapting unrelated parts of their code.&lt;/p&gt;
&lt;h2 id=&#34;lets-get-real&#34;&gt;Let&amp;rsquo;s Get Real&lt;/h2&gt;
&lt;p&gt;Creating a solid foundation for backwards compatibility for a platform that is not even off the ground yet is one of the more challenging aspects of Dropserver. I think it&amp;rsquo;s important though as it&amp;rsquo;s the kind of think that is hard to fix down the line.&lt;/p&gt;
&lt;p&gt;This challenge is not academic. I have a bunch of Dropserver apps in various states of development, and I currently depend on four different apps on a daily basis. I&amp;rsquo;d hate to release a new version of Dropserver that would force me to update all of these before I can upgrade my personal instance.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m sure I&amp;rsquo;ll have to make more adjustments to my approach, but I think at a fundamental level the presence of multiple layers gives a lot of opportunities to fix problems surgically instead of needing to do big rewrites.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - April 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-april-2024/</link>
      <pubDate>Sat, 11 May 2024 11:34:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-april-2024/</guid>
      <description>&lt;p&gt;This is the progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for April 2024.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-march-2024/&#34;&gt;Last month&lt;/a&gt; I said I would change how I do these. I want them shorter and more to the point. If any aspect of the work deserves a deeper technical dive it will be in a separate blog post.&lt;/p&gt;
&lt;p&gt;Here we go:&lt;/p&gt;
&lt;h2 id=&#34;outbound-fetches-get-stuffed&#34;&gt;Outbound Fetches Get Stuffed&lt;/h2&gt;
&lt;p&gt;Last month I tried to implement outgoing net requests in a safe way for the user and instance. I was unable to put something together that was flexible and powerful and safe. I ran into difficulties in a lot of places, but mostly the Deno net permissions are just not cut for this.&lt;/p&gt;
&lt;p&gt;For all the details, see my post &amp;ldquo;&lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-net-requests/&#34;&gt;Allowing Outbound Net Requests from a Dropserver App&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;My enthusiasm and optimism for Dropserver took a hit as I endured this setback. I committed the work I was doing on the &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/e78d447eccd8044112758015930c43c19d96c7ef&#34;&gt;outbound request proxy&lt;/a&gt;, and I may ship it later. But for now, my motivation to work on outgoing net requests is done.&lt;/p&gt;
&lt;p&gt;I needed to move to greener pastures, and threw myself in Tailscale&amp;rsquo;s open arms.&lt;/p&gt;
&lt;h2 id=&#34;tailscale&#34;&gt;Tailscale&lt;/h2&gt;
&lt;p&gt;I want to make Dropserver adoptable by as many people as possible. To this end I realized recently that Dropserver should be easy to install (think GUI Wizard on a popular operating system), and it should be easy to get it connected such that it can be reached and be safe. That last bit, it turns out, is a real pain.&lt;/p&gt;
&lt;p&gt;I have a blog post in the works on the challenges of serving a small personal app on the web like what Dropserver will do. In fact, I got so frustrated with this problem that I wrote a prequel so I could vent &lt;em&gt;some&lt;/em&gt; frustration before I finish the main post: &amp;ldquo;&lt;a href=&#34;https://olivierforget.net/blog/2024/surf-the-not-world-not-wide-web/&#34;&gt;I Want to Surf The Non-World Non-Wide Web&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Between domain names, DNS, TLS certs, and exposing anything to the public Internet there is no shortage of sharp edges to deal with. That is unless you summon the services of &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Tailscale lets you create a private network that you can access from any of your devices. You can also invite other Tailscale users to one or more of your services. Powerful ACLs give you &lt;a href=&#34;https://tailscale.com/blog/rbac-like-it-was-meant-to-be&#34;&gt;fine grained control over all access&lt;/a&gt;. They do all the tedious work for you: domains, TLS, etc&amp;hellip; it&amp;rsquo;s all taken care of.&lt;/p&gt;
&lt;p&gt;A prominent use case for Dropserver is hosting apps that are only used by yourself and a few other known people (like a life partner) or even just yourself. For example I use it to host my personal note-taking app, which is used by me only, but I like to access it from any device I have handy. But right now it&amp;rsquo;s exposed to the public internet, with the only thing stopping other people from reading my notes an auth system that sits at &lt;a href=&#34;https://en.wikipedia.org/wiki/OSI_model&#34;&gt;layer 7&lt;/a&gt; 😟.&lt;/p&gt;
&lt;p&gt;So the question is: what if I integrated Tailscale into Dropserver? The service is really nice, and they offer a &lt;a href=&#34;https://tailscale.com/kb/1244/tsnet&#34;&gt;library&lt;/a&gt; and &lt;a href=&#34;https://tailscale.dev/blog/tsup-tsnet&#34;&gt;encouragement&lt;/a&gt;. Could that cut down on the set-up time and increase the usefulness of a Dropserver install while also improving its security?&lt;/p&gt;
&lt;p&gt;After two weeks of playing around the answer appears to be a resounding &amp;ldquo;yes&amp;rdquo;. I&amp;rsquo;ll write a separate post specifically about this.&lt;/p&gt;
&lt;p&gt;My optimism is way up thinking about how easy it would be for someone to get a functioning yet completely private and safe way to host their private apps thanks to Tailscale 🤩.&lt;/p&gt;
&lt;h3 id=&#34;headscale-tailscales-open-source-cousin&#34;&gt;Headscale: Tailscale&amp;rsquo;s Open Source Cousin&lt;/h3&gt;
&lt;p&gt;If there is one downside to Tailscale, it&amp;rsquo;s that it&amp;rsquo;s a proprietary service run by a for-profit company which we should assume will get sold and &lt;a href=&#34;https://en.wikipedia.org/wiki/Enshittification&#34;&gt;enshittified&lt;/a&gt; at some point in the future. While we are lucky that they open-source most of their code, their control-plane is proprietary.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://headscale.net/&#34;&gt;Headscale&lt;/a&gt; is the open source self-hostable alternative, which is &lt;a href=&#34;https://github.com/tailscale/tailscale/issues/498#issuecomment-1501187146&#34;&gt;supported and encouraged by Tailscale&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ideally all Tailscale functionality that Dropserver uses would also work with a Headscale server, but that&amp;rsquo;s not going to be the case right away.&lt;/p&gt;
&lt;p&gt;Unfortunately there are some features missing in Headscale, specifically &lt;a href=&#34;https://tailscale.com/kb/1242/tailscale-serve&#34;&gt;&lt;code&gt;Serve&lt;/code&gt;&lt;/a&gt; with TLS enabled and &lt;a href=&#34;https://tailscale.com/kb/1311/tailscale-funnel&#34;&gt;Funnel&lt;/a&gt;. Since HS is written in Go I&amp;rsquo;m looking at contributing by adding the missing pieces of TLS cert generation to Headscale. See this &lt;a href=&#34;https://github.com/juanfont/headscale/issues/1921&#34;&gt;issue&lt;/a&gt;, and drop a reaction to let others know you&amp;rsquo;d like to see this happen as well, or comment if you want to help me get it built.&lt;/p&gt;
&lt;h2 id=&#34;thats-a-wrap-for-april&#34;&gt;That&amp;rsquo;s a Wrap for April&lt;/h2&gt;
&lt;p&gt;I am not able to work as many hours on Dropserver these days because of &amp;ldquo;real&amp;rdquo; work constraints. But the good news is Tailscale has given me a new boost of enthusiasm. I think it&amp;rsquo;s a brilliant service and its a shoe-in for Dropserver and I&amp;rsquo;m excited to get to work on the integration.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Allowing Outbound Net Requests from a Dropserver App</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-net-requests/</link>
      <pubDate>Wed, 08 May 2024 16:56:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-net-requests/</guid>
      <description>&lt;p&gt;With Deno 2.0 delayed again I recently tried to implement outbound net requests for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; apps using Deno v1&amp;rsquo;s permission model. I was excited to offer this new capability for Dropserver apps but unfortunately things did not go as I had hoped.&lt;/p&gt;
&lt;h2 id=&#34;problem-description&#34;&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;In the current version of Dropserver an app is unable to make a dynamic request to another host. It&amp;rsquo;s blocked by the Deno sandbox: there is no &lt;code&gt;--allow-net&lt;/code&gt; permission.&lt;/p&gt;
&lt;p&gt;(NB: Static requests are allowed by Deno. A static request is one where the URL is hard-coded into the source code files, like a typical &lt;code&gt;import * from &#39;some-url.com&#39;;&lt;/code&gt; statement. When I talk about allowing outbound net requests I mean the dynamic type.)&lt;/p&gt;
&lt;p&gt;Here are some use cases for outbound net requests:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An app needs access to a finite set of hosts, determined by the developer. Example: a dice roll app hits &lt;a href=&#34;https://random.org&#34;&gt;random.org&lt;/a&gt; for an integer.&lt;/li&gt;
&lt;li&gt;An app that needs dynamic access to hosts that are directly decided by the user. For example a RSS reader. There is a 1-1 relation between the user subscribing to a feed and the app needing access to a new host.&lt;/li&gt;
&lt;li&gt;An app that needs open ended access to the internet. For example a Fediverse server or a web crawler. One can not expect the user to approve every domain.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Regardless of which hosts are allowed and how, here are some things I want to guard against for the safety of the admin and users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP(S) only. No telneting around to see what services can be discovered.&lt;/li&gt;
&lt;li&gt;Dial only. No listening! A dropserver app can not create listeners, that&amp;rsquo;s &lt;code&gt;ds-host&lt;/code&gt;&amp;rsquo;s job. (Amazingly the Deno permissions &lt;a href=&#34;https://github.com/denoland/deno/issues/2705&#34;&gt;don&amp;rsquo;t make that distinction&lt;/a&gt;.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://owasp.org/www-community/attacks/Server_Side_Request_Forgery&#34;&gt;SSRF&lt;/a&gt; protection: no requests to the local network unless it&amp;rsquo;s explicitly allowed by the ds-host admin.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also I&amp;rsquo;d like to log all requests, with at least the name of the host contacted (see below).&lt;/p&gt;
&lt;p&gt;The most interesting apps need open-ended access to the net (3rd bullet above), so my goal was to solve that case.&lt;/p&gt;
&lt;h2 id=&#34;deno-permissions&#34;&gt;Deno Permissions&lt;/h2&gt;
&lt;p&gt;Dropserver apps run in Deno because of its sandboxing properties. See &lt;a href=&#34;https://olivierforget.net/blog/2020/deno-saved-project/&#34;&gt;this bit of history&lt;/a&gt; to know how we ended here. It&amp;rsquo;s an effective sandbox for limiting file read/write and execution access. But on the networking side, it&amp;rsquo;s far from great. Let&amp;rsquo;s look at how it works:&lt;/p&gt;
&lt;p&gt;Permissions for the network come in the form &lt;a href=&#34;https://docs.deno.com/runtime/manual/basics/permissions&#34;&gt;&lt;code&gt;--allow-net&lt;/code&gt; and &lt;code&gt;--deny-net&lt;/code&gt;&lt;/a&gt;. So far so good. However, here are the gotchas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--allow net&lt;/code&gt; permits outbound requests (dial) &lt;em&gt;and&lt;/em&gt; listen! So if you naively rant all net access because you have an app that may want to reach any host (situation three above), that app can now create listeners (servers) on any port (within operating system restrictions).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;--allow-net&lt;/code&gt; and &lt;code&gt;--deny-net&lt;/code&gt; are compared with the URL that is requested, &lt;a href=&#34;https://github.com/denoland/deno/issues/21227&#34;&gt;not the resolved IP&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These two issues open a lot of potential security problems if I open net access for Dropserver apps.&lt;/p&gt;
&lt;h3 id=&#34;good-to-know-deno-uses-reqwest&#34;&gt;Good to know: Deno uses reqwest&lt;/h3&gt;
&lt;p&gt;Deno uses &lt;a href=&#34;https://github.com/seanmonstar/reqwest&#34;&gt;&lt;code&gt;reqwest&lt;/code&gt;&lt;/a&gt; internally (&lt;a href=&#34;https://github.com/denoland/deno/issues/23516#issuecomment-2073565372&#34;&gt;for now&lt;/a&gt; at least) to make requests on behalf of the running code. This is good to know because we can assume that Deno won&amp;rsquo;t implement something that is not part of &lt;code&gt;reqwest&lt;/code&gt;. Currently there is an &lt;a href=&#34;https://github.com/seanmonstar/reqwest/issues/1515&#34;&gt;open issue&lt;/a&gt; for some sort of SSRF protection &amp;ndash; it&amp;rsquo;s been open for 3 years. So I can&amp;rsquo;t expect that to happen.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Reqwest&lt;/code&gt; now allows for a &lt;a href=&#34;https://github.com/seanmonstar/reqwest/pull/1653&#34;&gt;custom DNS resolver&lt;/a&gt; which would help with SSRF protection. Interestingly this feature was &lt;a href=&#34;https://github.com/seanmonstar/reqwest/issues/1125&#34;&gt;requested by Ry&lt;/a&gt;, the creator of Deno, so I suspect they use it internally, but so far it&amp;rsquo;s not exposed in the CLI as far as I can see.&lt;/p&gt;
&lt;h3 id=&#34;the-http_proxy&#34;&gt;The HTTP_PROXY&lt;/h3&gt;
&lt;p&gt;One feature of &lt;code&gt;reqwest&lt;/code&gt; that Deno exposes is the ability to declare a proxy for HTTP requests via environment variables like &lt;code&gt;HTTP_PROXY&lt;/code&gt;. This is a good way to route requests through a proxy that Dropserver controls to prevent any unwanted request. Proxying requests would allow me to &amp;ldquo;see&amp;rdquo; and filter to my heart&amp;rsquo;s content. I could even reuse Dropserver&amp;rsquo;s own SSRF mitigation code. It&amp;rsquo;s the ultimate solution.&lt;/p&gt;
&lt;p&gt;Unfortunately, while the proxy works as expected, it in no way prevents an app from making requests that bypass the proxy. Basically the proxy is only used for &amp;ldquo;fetch&amp;rdquo; requests. You can craft a request from low-level APIs, and I think you can even override the proxy using the fetch API.&lt;/p&gt;
&lt;p&gt;The proxy is merely a &amp;ldquo;helpful suggestion&amp;rdquo;, so not usable as a security boundary. (That&amp;rsquo;s not a knock against the proxy implementation: a proxy, by itself, is not meant to be a security boundary.)&lt;/p&gt;
&lt;h3 id=&#34;a-hail-mary---allow-net-fetch&#34;&gt;A Hail Mary: &amp;ndash;allow-net-fetch&lt;/h3&gt;
&lt;p&gt;If only Deno could block all net access except those that go through the proxy, then I&amp;rsquo;d be set. I posted a request for &lt;a href=&#34;https://github.com/denoland/deno/issues/22902&#34;&gt;&lt;code&gt;--allow-net-fetch&lt;/code&gt; permission&lt;/a&gt; in the Deno issues hoping they find it an interesting approach. Since Deno 2 is still in the works, I am hoping there is still time to slip that in, if they haven&amp;rsquo;t already done something similar.&lt;/p&gt;
&lt;h2 id=&#34;non-deno-solutions&#34;&gt;Non-Deno Solutions&lt;/h2&gt;
&lt;p&gt;I could run Deno inside a &lt;a href=&#34;https://en.wikipedia.org/wiki/Linux_namespaces&#34;&gt;Linux namespace&lt;/a&gt; that gives me full control over the network. There are a few problems with that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;this only works in Linux. This is unfortunate because I am leaning towards making Dropserver installable on Mac and Windows natively to reach the broadest possible audience.&lt;/li&gt;
&lt;li&gt;I currently use &lt;a href=&#34;https://github.com/containers/bubblewrap&#34;&gt;Bubblewrap&lt;/a&gt; to &lt;a href=&#34;https://olivierforget.net/blog/2023/dropserver-sandbox/&#34;&gt;further isolate Deno sandboxes&lt;/a&gt; when &lt;code&gt;ds-host&lt;/code&gt;runs in a Linux environment but its net namespace support is on/off. Setting up the virtual networking elements to get a functioning network is not easy. And Bubblewrap doesn&amp;rsquo;t even run in Docker, or at least &lt;a href=&#34;https://github.com/containers/bubblewrap/issues/505&#34;&gt;not easily&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So limiting an app&amp;rsquo;s net access to an acceptable degree without Deno&amp;rsquo;s help is complicated and will take a lot of my dev time, and it will only work on Linux at a time when I am eager to not limit Dropserver to Linux! So that&amp;rsquo;s a nope.&lt;/p&gt;
&lt;h2 id=&#34;report-hosts-to-user&#34;&gt;Report Hosts to User&lt;/h2&gt;
&lt;p&gt;While I am talking a lot about permissions, visibility into what hosts are being contacted and how often is an important feature for a user who is concerned about what an app is doing.&lt;/p&gt;
&lt;p&gt;There are good reasons for an app to request open-ended access to the web as we&amp;rsquo;ve seen above. But how can a user be made to feel comfortable about an app&amp;rsquo;s behavior after they&amp;rsquo;ve granted that permission? The key is to give them visibility into what the app is actually doing with that permission.&lt;/p&gt;
&lt;p&gt;If the user can see reports that point out the most contacted domains, the payload sizes, and other metrics that might reveal whether an app is behaving correctly or not.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve always felt that it was weird when a system asks me to grant some permission but then offers zero information about the usage of that permission. If it&amp;rsquo;s so important to my safety that I have to grant a permission, why are you not showing me what is done with that permission?&lt;/p&gt;
&lt;p&gt;With this in mind I worked on a logging proxy for outbound requests from the appspace sandbox.&lt;/p&gt;
&lt;h3 id=&#34;proxying-outbound-requests&#34;&gt;Proxying outbound requests&lt;/h3&gt;
&lt;p&gt;I implemented a proxy using &lt;a href=&#34;https://github.com/elazarl/goproxy&#34;&gt;goproxy&lt;/a&gt; (see &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/e78d447eccd8044112758015930c43c19d96c7ef&#34;&gt;commit e78d447&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I learned along the way that MITM&amp;rsquo;ing the connection is very computationally expensive and slows down requests significantly when there are many at a time. With no MITM the performance is OK.&lt;/p&gt;
&lt;p&gt;With no MITM the proxy only sees the host and not the full path, or the payload, but I can at least report that host X was contacted.&lt;/p&gt;
&lt;p&gt;Maybe I&amp;rsquo;ll add an option to turn on MITM for an appspace. The user might do that if they get suspicious of an app&amp;rsquo;s activity.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;After getting the proxy to workable condition I achieved 0.5 of the four requirements I laid out at the top. I only managed to log hosts and only if the app uses the Fetch API without defeating the proxy.&lt;/p&gt;
&lt;p&gt;The other requirements (HTTP-only, No listening, and SSRF protection) I am not able to pursue without better tools from Deno, or I have to make Dropserver Linux-only and dive into Linux namespaces and &lt;code&gt;veth&lt;/code&gt;s galore.&lt;/p&gt;
&lt;p&gt;What if Deno 2 doesn&amp;rsquo;t solve my issues? This would be bad, but I&amp;rsquo;m a crafty guy and I&amp;rsquo;ll figure something out.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>I Want To Surf the Not-World Not-Wide Web</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/surf-the-not-world-not-wide-web/</link>
      <pubDate>Wed, 17 Apr 2024 12:50:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/surf-the-not-world-not-wide-web/</guid>
      <description>&lt;p&gt;The World Wide Web is awesome. It&amp;rsquo;s &amp;ldquo;World-Wide&amp;rdquo;, and it&amp;rsquo;s a &amp;ldquo;Web&amp;rdquo;, meaning everybody and anybody can connect with everybody and anybody! Information is shared and everybody can read it! The WWW rocks.&lt;/p&gt;
&lt;p&gt;Well, it rocks for things that are meant to publicly available.&lt;/p&gt;
&lt;p&gt;Once you want to share information with just one or a few people things get a little weird.&lt;/p&gt;
&lt;p&gt;If you want to host your own private little island on the web for just you and a few known friends or family you find that the web is hostile to your intentions.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;But that&amp;rsquo;s not the point of the web! It&amp;rsquo;s for sharing information publicly!&amp;rdquo; True, but there are other use-cases that could benefit from the amazing tech of the web, and they are being shunned right now, and it&amp;rsquo;s unfortunate.&lt;/p&gt;
&lt;p&gt;I would like to leverage the amazing qualities of web technologies for a different use-case: private interactions. Essentially I want to use the web browser, but to browse the not-World not-Wide Web.&lt;/p&gt;
&lt;h2 id=&#34;web-browsers-are-great&#34;&gt;Web browsers are great&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Web browsers are available on any operating system. Ubiquitous.&lt;/li&gt;
&lt;li&gt;There are alternative browsers by different vendors. Choice.&lt;/li&gt;
&lt;li&gt;They&amp;rsquo;re built on standards and don&amp;rsquo;t break backwards compatibility. Longevity.&lt;/li&gt;
&lt;li&gt;Most web browsers have good security and isolation properties. Safety.&lt;/li&gt;
&lt;li&gt;I can create a well formatted readable document with just a bit of HTML and CSS. Simplicity.&lt;/li&gt;
&lt;li&gt;I can create a highly interactive application using JavaScript, if I choose to. No limits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The browser platform is incredible. But the networking protocols they work with are utterly hostile to private interactions.&lt;/p&gt;
&lt;p&gt;I have built web-apps that are private-only. One is &lt;a href=&#34;https://leftovers.olivierforget.net&#34;&gt;Leftovers&lt;/a&gt;. I also have a shopping list web-app my wife and I use. My personal note-taking app is a web-app, I am its sole user. I have ideas for others. In fact I&amp;rsquo;m building an entire &lt;a href=&#34;https://dropserver.org&#34;&gt;platform&lt;/a&gt; for supporting these use cases.&lt;/p&gt;
&lt;p&gt;But the thing I keep coming up against is the &amp;ldquo;World&amp;rdquo; &amp;ldquo;Wide&amp;rdquo; &amp;ldquo;Web&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;The problem&lt;/h2&gt;
&lt;p&gt;Here is how the web works, basically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;you enter or click on an address, like &lt;a href=&#34;http://olivierforget.net/blog/&#34;&gt;http://olivierforget.net/blog/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;that gets turned into a magic number, the IP, that looks like &lt;code&gt;50.18.142.31&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;your request is sent to the computer at that IP.&lt;/li&gt;
&lt;li&gt;that computer sends you what it deems is at that address&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Looks fine, right? Let&amp;rsquo;s look at those steps again in light of a private interaction:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;you enter or click on an address. The domain is a public record that may even contain your personal info like your physical home address.&lt;/li&gt;
&lt;li&gt;get that public IP address by contacting some 3rd party server that may or may not keep a record of the fact you looked up this address&lt;/li&gt;
&lt;li&gt;the request is sent to the other computer over the public IP network.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s only after you&amp;rsquo;ve done all this that the other computer gets a chance to ask you for your username and password to get into a private interaction.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So much of this private interaction leaves a public trace.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s like having to set up a booth on Times Square to get a hug from your grandma.&lt;/p&gt;
&lt;p&gt;It just doesn&amp;rsquo;t make any sense.&lt;/p&gt;
&lt;p&gt;It also means that to serve something privately, you have to expose the computer to the public internet, which means you&amp;rsquo;re on the receiving end of bots and other unsavory characters. Remember how the great thing about the WWW is that it allows anybody and everybody to connect? Yeah, that applies to all the state actors and script kiddies too.&lt;/p&gt;
&lt;p&gt;Setting up a computer with a public IP is like walking into a pirate bar with an &amp;ldquo;I Hate Parrots&amp;rdquo; t-shirt.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t get me wrong, again. I love the World Wide Web&amp;hellip; for &lt;em&gt;Public&lt;/em&gt; information. But for doing private, family and friends stuff it&amp;rsquo;s just the wrong architecture.&lt;/p&gt;
&lt;h2 id=&#34;what-do-i-want&#34;&gt;What do I want?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;d like to be able to leverage some of the technologies of the web, like the fantastic run-anywhere abilities of HTML+CSS+JS, but via a private network.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I don&amp;rsquo;t want to have to buy and renew a globally unique domain name just to share with a dozen people&lt;/li&gt;
&lt;li&gt;I don&amp;rsquo;t want that domain name part of the public record along with my home address (and I don&amp;rsquo;t want to pay extra to hide personal details)&lt;/li&gt;
&lt;li&gt;I should not need an external service to navigate to this domain, like a DNS server run by some company&lt;/li&gt;
&lt;li&gt;I don&amp;rsquo;t want to have to go through a third party to obtain a TLS cert that goes into the public record just to get a &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts&#34;&gt;secure context&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I don&amp;rsquo;t want the computers where I host stuff for my friends and family to have reachable public IPs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;what-does-it-look-like&#34;&gt;What does it look like?&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t know exactly. This is a gripe / wishful thinking post, not a solution post. Sorry.&lt;/p&gt;
&lt;p&gt;But I suspect it&amp;rsquo;s a bit like a &lt;a href=&#34;https://tailscale.com/&#34;&gt;Tailscale&lt;/a&gt; tailnet, but geared more towards personal interactions.&lt;/p&gt;
&lt;p&gt;Perhaps web browsers would embrace &lt;a href=&#34;https://www.wireguard.com/&#34;&gt;Wireguard&lt;/a&gt; natively and treat such connections as secure. Something like that.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;d need an alternative to the whole Public DNS thing. Maybe &lt;a href=&#34;https://www.gnunet.org/en/gns.html&#34;&gt;GNU Name system&lt;/a&gt;? But it needs to be user-friendly and browsers would have to support it.&lt;/p&gt;
&lt;p&gt;So yeah, I&amp;rsquo;m just dreaming here.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - March 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-march-2024/</link>
      <pubDate>Fri, 05 Apr 2024 12:30:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-march-2024/</guid>
      <description>&lt;p&gt;This is the monthly progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for March 2024. The previous report is &lt;a href=&#34;https://olivierforget.net/blog/2024/dropserver-progress-february-2024/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This happens to be the twelfth month for which I am publishing an update (the &lt;a href=&#34;https://olivierforget.net/blog/2023/dropserver-progress-june-2023/&#34;&gt;first progress update covered April-June 2023&lt;/a&gt;). A full year! Yay me.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also time for me to change how I write these posts. I think I&amp;rsquo;ll make them shorter and more to the point and I will dedicate complete blog posts when a topic deserves deeper examination. For example, &lt;a href=&#34;https://olivierforget.net/blog/2023/dropserver-sandbox/&#34;&gt;The State of Sandboxing in Dropserver&lt;/a&gt; is a post I keep going back to and that stands out in my list of posts, while the series of &amp;ldquo;progress updates&amp;rdquo; are just so much water under the bridge.&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m plugging away despite having less time to spend on Dropserver due to other projects. This reduction in time results in a slight decrease in time spent on the core of Dropserver, and a significant curtailing of peripheral work like experimenting with Lume and other side-quests.&lt;/p&gt;
&lt;p&gt;I started work on the next big feature of Dropserver, but before that I did some maintenance work and pushed a minor version.&lt;/p&gt;
&lt;h3 id=&#34;prepare-for-deno-20&#34;&gt;Prepare for Deno 2.0&lt;/h3&gt;
&lt;p&gt;The big 2.0 for Deno keeps getting pushed back. At this point I don&amp;rsquo;t know when it&amp;rsquo;s coming but it sounds like the previous timeframe of &amp;ldquo;April&amp;rdquo; will not happen.&lt;/p&gt;
&lt;p&gt;Dropserver uses Deno&amp;rsquo;s sandboxing features to prevent app code from doing bad things, so a big change like whatever might be coming in Deno 2 keeps me on my toes.&lt;/p&gt;
&lt;p&gt;Thankfully Deno published a &lt;a href=&#34;https://docs.deno.com/runtime/manual/advanced/migrate_deprecations&#34;&gt;guide for migrating to Deno 2&lt;/a&gt; that describes the APIs that are definitely going away in D2. I made changes to the sandbox code to use the latest server APIs and std lib (commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/283b48ebe26f32d7aff504e0d2442b637d63721c&#34;&gt;283b48&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/b603e50fc41124c61422933c633964929cb24f37&#34;&gt;b603e5&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;I am still struggling with a mistake I made long ago: I included the now deprecated &lt;code&gt;Deno.RequestEvent&lt;/code&gt; TypeScript type as part of a type in &lt;a href=&#34;https://github.com/teleclimber/dropserver_lib_support&#34;&gt;&lt;code&gt;dropserver_lib_support&lt;/code&gt;&lt;/a&gt;, which is kind of a bummer since that library is not supposed to change to preserve backwards compatibility. I may write a separate post about how that works and lessons learned there.&lt;/p&gt;
&lt;h3 id=&#34;inotify-watchers-fix&#34;&gt;Inotify watchers fix&lt;/h3&gt;
&lt;p&gt;Back in December I experienced a (thankfully rare) &lt;a href=&#34;https://social.tchncs.de/@teleclimber/111648274755121452&#34;&gt;anomaly on my personal ds-host instance&lt;/a&gt;. It turns out it was &lt;a href=&#34;https://github.com/teleclimber/Dropserver/issues/113&#34;&gt;this bug&lt;/a&gt; that was causing &lt;code&gt;ds-host&lt;/code&gt; to create and not clean up inotify watchers. I fixed it in &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/0580e5f592f6e575c2438eaa6c9b8be57fe1fc90&#34;&gt;commit 0580e5&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;(I just looked at my personal instance which has been running this fix for a few weeks, and can confirm the inotify watchers are not growing unbounded. Pfew.)&lt;/p&gt;
&lt;h3 id=&#34;release-0131&#34;&gt;Release 0.13.1&lt;/h3&gt;
&lt;p&gt;With these improvements committed, why not release a new version of Dropserver? I tagged &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.1&#34;&gt;0.13.1&lt;/a&gt; on March 13.&lt;/p&gt;
&lt;h2 id=&#34;next-feature-outgoing-net-requests&#34;&gt;Next Feature: Outgoing Net Requests&lt;/h2&gt;
&lt;p&gt;Dropserver apps are currently not allowed to make outbound network requests. This is a huge limitation that I am keen to eliminate. I could of course add a &lt;code&gt;--allow-net&lt;/code&gt; to the Deno sandbox and call it a day. But that would go against all the principles of security that I&amp;rsquo;ve established for this project.&lt;/p&gt;
&lt;p&gt;I am spending time trying to figure out how to allow network access such that it is convenient for users and developers, and such that it does not pose a security risk to the user.&lt;/p&gt;
&lt;p&gt;There is lots to consider, including how Deno does network sandboxing (&lt;a href=&#34;https://github.com/denoland/deno/issues/2705&#34;&gt;not great currently&lt;/a&gt;, maybe better in the elusive 2.0?), the kinds of things I want to protect against (&lt;a href=&#34;https://github.com/denoland/deno/issues/21227&#34;&gt;SSRF&lt;/a&gt; among others), etc&amp;hellip; I have run across gotchas everywhere and it&amp;rsquo;s making my head hurt.&lt;/p&gt;
&lt;p&gt;If I start writing about this here I won&amp;rsquo;t be able to publish this update any time soon. So it will go in a separate post some day.&lt;/p&gt;
&lt;h3 id=&#34;proxying-outgoing-requests&#34;&gt;Proxying outgoing requests&lt;/h3&gt;
&lt;p&gt;Here is something tangible I spent time on: I worked on adding an HTTP proxy in Dropserver that sits between the Deno sandbox and the outside world. The idea is that for HTTP fetches at least, I can see what the app is requesting, I can log it, I can even deny it if it doesn&amp;rsquo;t pass my SSRF filters.&lt;/p&gt;
&lt;p&gt;I learned along the way the MITMing HTTPS connections is very computationally expensive. If an app needs to download modules from deno.land/x/ its startup time increases five-fold! Without MITM I can still log the destination host and run the connection through my SSRF filter, so that&amp;rsquo;s good enough.&lt;/p&gt;
&lt;p&gt;This proxy is not a good security solution because it&amp;rsquo;s only effective if the app uses the &amp;ldquo;fetch&amp;rdquo; call, but it&amp;rsquo;s a starting point of something. While I suspect a proxy like this will play a role in a fully implemented secure outbound request solution, it&amp;rsquo;s not what it is now.&lt;/p&gt;
&lt;p&gt;Still, I may include it in a minor point release along with the ability to see fetch history, purely as an informational thing.&lt;/p&gt;
&lt;h2 id=&#34;work-on-leftovers-app&#34;&gt;Work On Leftovers App&lt;/h2&gt;
&lt;p&gt;I made some &lt;a href=&#34;https://github.com/teleclimber/Leftovers/commit/f139daa0f264f8919b2e461b1987792df303502e&#34;&gt;small&lt;/a&gt; &lt;a href=&#34;https://social.tchncs.de/@teleclimber/112164424225842776&#34;&gt;improvements&lt;/a&gt; to the &lt;a href=&#34;https://leftovers.olivierforget.net/&#34;&gt;Leftovers app&lt;/a&gt;. I use this app daily at home so its little UX paper cuts got to me all the time. Finally it&amp;rsquo;s starting to feel quite pleasant to use.&lt;/p&gt;
&lt;p&gt;A true &lt;a href=&#34;https://www.robinsloan.com/notes/home-cooked-app/&#34;&gt;home cooked app&lt;/a&gt; for home cooked meals.&lt;/p&gt;
&lt;p&gt;This was also an opportunity to run through the &lt;a href=&#34;https://dropserver.org/docs/app-packaging-distributing&#34;&gt;release + publish flow&lt;/a&gt; for a Dropserver app. It worked, but it was a bit fiddly. I may need to create a Github Action that takes care of everything for the app  developer. Push a git tag and it cuts a release and publishes an updated version of the website to GH pages. Boom done.&lt;/p&gt;
&lt;p&gt;It was also an opportunity to &lt;a href=&#34;https://social.tchncs.de/@teleclimber/112181197017228351&#34;&gt;experience the app upgrade process from the user&amp;rsquo;s point of view&lt;/a&gt;. Here again, more work needed 😔.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next&lt;/h2&gt;
&lt;p&gt;While I want to make progress on outgoing net requests, there are a few other things I should improve.&lt;/p&gt;
&lt;p&gt;In particular with &lt;a href=&#34;https://deno.com/blog/jsr_open_beta&#34;&gt;JSR out&lt;/a&gt;, and the realization that it &lt;a href=&#34;https://jsr.io/docs/with/deno&#34;&gt;uses import maps&lt;/a&gt;, I should probably support them in Dropserver apps. There are other reasons too: I&amp;rsquo;d like to support vendoring dependencies so that apps can be published with all code included, but that depends on import maps too. (And guess what? Vendoring affects outbound requests too: see the bit above about hitting deno.land/x/ through a MITM proxy!)&lt;/p&gt;
&lt;p&gt;There are many other things I could work on, and I&amp;rsquo;m not sure what I will do&amp;hellip; so see you next month!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - February 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-february-2024/</link>
      <pubDate>Mon, 11 Mar 2024 09:56:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-february-2024/</guid>
      <description>&lt;p&gt;This is the monthly progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for February 2024. The previous report is &lt;a href=&#34;../dropserver-progress-january-2024/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;This will be a short report because I spent half of this month on vacation, which limited my work. After Releasing &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.0&#34;&gt;0.13&lt;/a&gt; last month I am allowing myself some time to explore tangential projects while also chipping away at some Dropserver issues.&lt;/p&gt;
&lt;h2 id=&#34;getting-lume-to-work&#34;&gt;Getting Lume to Work&lt;/h2&gt;
&lt;p&gt;I have been trying to get &lt;a href=&#34;https://lume.land/&#34;&gt;Lume&lt;/a&gt; to work in a Dropserver app. I&amp;rsquo;d like to combine Lume, a static site generator (SSG), with a GUI frontend to make a Dropserver app that allows you to edit content in an online editor and publish it. It is meant to be a demo of the kind of app that can be built for DS. It is also a test of running a non-trivial project that was not intended to be run in Dropserver.&lt;/p&gt;
&lt;p&gt;One issue I&amp;rsquo;ve run against is that Lume is clearly meant to be used as a CLI app, and not as a library within other code, especially if given limited permissions. The other issue is that Lume leverages existing libraries from the node ecosystem via Deno&amp;rsquo;s NPM support. While the NPM libraries work, they tend to expect full disk access permissions and fail hard when they don&amp;rsquo;t have it.&lt;/p&gt;
&lt;p&gt;One such library is &lt;a href=&#34;https://browsersl.ist/&#34;&gt;Browserslist&lt;/a&gt;, which is used by &lt;a href=&#34;https://github.com/postcss/autoprefixer&#34;&gt;autoprefixer&lt;/a&gt; which is used in most projects that leverage &lt;a href=&#34;https://postcss.org/&#34;&gt;PostCSS&lt;/a&gt;. The issue is that browserslist was not designed to run in a sandboxed environment like Deno. I decided to try to fix this.&lt;/p&gt;
&lt;h3 id=&#34;browserslist-pr&#34;&gt;Browserslist PR&lt;/h3&gt;
&lt;p&gt;PostCSS and autoprefixer are so commonly used in site generation tooling that I thought it would be worthwhile to try to help it run in Deno when permissions are limited. I submitted this &lt;a href=&#34;https://github.com/browserslist/browserslist/issues/813&#34;&gt;issue&lt;/a&gt; and said I&amp;rsquo;d submit a patch.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s nice working on an existing and widely used project for a change. I spend a lot of time working on my own stuff, it feels good to get out of my shell.&lt;/p&gt;
&lt;p&gt;I added an ENV variable that limits how far up the path Browserslist goes to look for config files. Credit to the maintainer, &lt;a href=&#34;https://github.com/browserslist/browserslist/pull/819&#34;&gt;my PR&lt;/a&gt; was promptly merged (after I fixed linter errors &amp;ndash; woops!) and a new version of bl was released, which is a nice feeling.&lt;/p&gt;
&lt;p&gt;Since the Lume and autoprefixer devs are staying on top of dependencies, the current version of Lume requires the latest version of autoprefixer which requires the latest version of browserslist which includes my patch. Neat!&lt;/p&gt;
&lt;h3 id=&#34;env-vars-in-dropserver-sandbox&#34;&gt;ENV vars in Dropserver sandbox?&lt;/h3&gt;
&lt;p&gt;I changed the browserslist library to limit its file reads via an environment variable, but the Dropserver sandbox has no mechanism to let developers specify environment variables for the sandbox. I&amp;rsquo;m contemplating adding this capability. I&amp;rsquo;ll consider it seriously if I find over and over again that a library wants to be controlled via environment variables.&lt;/p&gt;
&lt;p&gt;I suspect this type of library is usually associated with CLI apps, and site generators. I do want to support site generators in Dropserver if possible. I think all the tools we build for the web that are CLI-based are a boon for technical people but leave regular users helpless.&lt;/p&gt;
&lt;p&gt;Then again this may be a bridge too far. I haven&amp;rsquo;t thought much about it, but I imagine that letting app devs specify Environment variables is a big security issue.&lt;/p&gt;
&lt;p&gt;(Note that there are other ways of preventing Browserslist from iterating up the path: put all the config files it looks for in the appspace data directory and it won&amp;rsquo;t go looking elsewhere for them. This is what I have been doing in my Dropserver Lume experiments.)&lt;/p&gt;
&lt;h3 id=&#34;make-appspace-data-directory-the-cwd&#34;&gt;Make Appspace Data Directory the CWD&lt;/h3&gt;
&lt;p&gt;Since it is a CLI app, Lume puts a lot of stock in the CWD &amp;ldquo;Current Working Directory&amp;rdquo;. When the CWD is non-existent or unreadable, Lume errors out.&lt;/p&gt;
&lt;p&gt;This one I could fix in Dropserver. I changed the sandbox code so that the appspace files dir is the CWD of the Deno sandbox. Easy peasy, and it makes it easier for app devs to interact with files in the appspace dir: they can just use relative paths instead of the helper functions that return the absolute path of the appsapce files.&lt;/p&gt;
&lt;p&gt;I did run into a weird thing that caused me to spend a few days on this: Deno is a bit inconsistent with path normalization. When symlinks are involved, or when using different capitalizations of paths in a case-insensitive filesystem, Deno will fail to recognize that two paths are the same even if they are not character-for-character the same. I filed &lt;a href=&#34;https://github.com/denoland/deno/issues/22309&#34;&gt;this issue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/cec55747bfd981d30225fbad9f419f99324f81b2&#34;&gt;cec557&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next&lt;/h2&gt;
&lt;p&gt;I will work on a few more bugs and improvements before I release Dropserver 0.13.1. Beyond that I am not sure what comes next, but this is looming:&lt;/p&gt;
&lt;h3 id=&#34;deno-20-and-outbound-requests&#34;&gt;Deno 2.0 and Outbound Requests&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m eagerly waiting for the arrival of the first public releases of Deno 2.0. Deno has been a &lt;a href=&#34;https://olivierforget.net/blog/2020/deno-saved-project/&#34;&gt;boon for the Dropserver project&lt;/a&gt;, but it&amp;rsquo;s not openly developed so I wait patiently to see what I will have to contend with when it drops.&lt;/p&gt;
&lt;p&gt;In particular, a sorely needed feature for Dropserver apps is the ability to make outbound requests. Letting an app do this opens up a number possible security issues, and Deno&amp;rsquo;s permission API plays a big role. As such, I want to see if they improve the net permissions before I do too much design work for outbound requests. See these issues for an idea of things that have been bugging me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/denoland/deno/issues/2705&#34;&gt;#2705: Current design of &amp;ndash;allow-net&lt;/a&gt; (stale-botted 😡)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/denoland/deno/issues/21227&#34;&gt;#21227: Deno should block access to local network unless explicitly permitted&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once I know what I&amp;rsquo;m dealing with, I&amp;rsquo;ll get to work enabling outbound requests from Dropserver apps.&lt;/p&gt;
&lt;p&gt;In the meantime I&amp;rsquo;ll continue experimenting with IndieWeb, ActivityPub, and RSS, with an eye towards making Dropserver apps that demonstrate what can be built on the platform.&lt;/p&gt;
&lt;p&gt;See you next time.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - January 2024</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-january-2024/</link>
      <pubDate>Fri, 02 Feb 2024 10:50:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-january-2024/</guid>
      <description>&lt;p&gt;This is the monthly progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for January 2024. The previous report is &lt;a href=&#34;../dropserver-progress-december-2023/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;Dropserver &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.13.0&#34;&gt;0.13 is out&lt;/a&gt;! 🎉 This is the release that lets Dropserver install apps from a 3rd party website. If you&amp;rsquo;ve been reading these progress reports, you know it&amp;rsquo;s been a long time coming.&lt;/p&gt;
&lt;h2 id=&#34;getting-to-a-release&#34;&gt;Getting to a Release&lt;/h2&gt;
&lt;p&gt;Before releasing I had to add a few more features and close up some unfinished work.&lt;/p&gt;
&lt;h3 id=&#34;generate-the-app-listing&#34;&gt;Generate the App Listing&lt;/h3&gt;
&lt;p&gt;The goal of the 0.13 release is that a Dropserver app should be installable (and upgradeable) just by pointing your instance to a URL. I spent most of my time in the last few months on the &lt;code&gt;ds-host&lt;/code&gt; side of this: opening package files, fetching manifests, displaying changelogs, etc&amp;hellip; But now I needed to do the other side: generating the files that can be hosted on a static file server.&lt;/p&gt;
&lt;p&gt;At the very least &lt;code&gt;ds-dev&lt;/code&gt; should be able to generate the &lt;code&gt;app-listing.json&lt;/code&gt; which is the starting point of any interaction with a URL from the &lt;code&gt;ds-host&lt;/code&gt; side. The app listing contains a list of versions and relative paths to each version&amp;rsquo;s package, icon, and changelog.&lt;/p&gt;
&lt;p&gt;This part was easy enough. Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/85b99a62d8a1518da55ad7fc89ee5cbb538f4efc&#34;&gt;85b99a&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;generate-the-website&#34;&gt;Generate the Website&lt;/h3&gt;
&lt;p&gt;What about generating an HTML page? I resisted doing this. It felt so superficial compared to the actual core functionality of 0.13. And yet, imagine this: you have an app published, and you can point people to a URL and tell them that&amp;rsquo;s how they can install your app. But visiting that URL just disgorges some useless data. Shouldn&amp;rsquo;t there be a webpage? Something that a human can consume?&lt;/p&gt;
&lt;p&gt;The more I thought about it, the more it seemed that not having some page that describes the app, its relation to Dropserver, and how to actually install it, the more the whole idea of apps from URLs would fall on its face.&lt;/p&gt;
&lt;p&gt;So I banged it out. It&amp;rsquo;s crude, it&amp;rsquo;s low-tech, but it&amp;rsquo;s there. Now when you generate an app listing you also get an HTML page. It&amp;rsquo;s self-contained but references the app icon to make it more lively. Screenshot below:&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2024/dropserver-progress-january-2024/leftovers-generated-site_hu462f74c740ac03ee79483f3aff09252f_173847_594x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2024/dropserver-progress-january-2024/leftovers-generated-site_hu462f74c740ac03ee79483f3aff09252f_173847_594x0_resize_box_3.png, https://olivierforget.net/blog/2024/dropserver-progress-january-2024/leftovers-generated-site_hu462f74c740ac03ee79483f3aff09252f_173847_1188x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing the generated website for the Leftovers app.&#34;&gt;
&lt;p&gt;All the data is sourced from the app itself so it&amp;rsquo;s missing a lengthy description and screenshots. It&amp;rsquo;s really mostly good as a minimal presence to accompany a blog post for example.&lt;/p&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/18e1e2a8768575001ae2dd14f8e8ab7418cc6f98&#34;&gt;18e1e2&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;finalize-handling-of-redirects&#34;&gt;Finalize Handling of Redirects&lt;/h3&gt;
&lt;p&gt;Up until this point I had punted on how to handle redirects from the site where the app is hosted.&lt;/p&gt;
&lt;p&gt;For the time being I don&amp;rsquo;t want the site that hosts the files to redirect to other sites. I concluded that the user is likely putting some level of trust in the site that claims to host the app files. If redirects are followed transparently, the files may actually come from a completely different host without the user knowing.&lt;/p&gt;
&lt;p&gt;For this reason I don&amp;rsquo;t allow redirects. In the case where the app has to be moved to a different host or a different address the site can return a permanent redirect. However this redirect is not followed by &lt;code&gt;ds-host&lt;/code&gt;. Instead, it presents the user with a notice of a new location for the app, and the ability to change the URL if they approve.&lt;/p&gt;
&lt;p&gt;This way the user is always aware where their app files are coming from.&lt;/p&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/14f77f5b85d77421e22b69d050ad8a9ff34d85eb&#34;&gt;14f77f&lt;/a&gt; and others.&lt;/p&gt;
&lt;h3 id=&#34;update-the-docs&#34;&gt;Update the Docs&lt;/h3&gt;
&lt;p&gt;I update the docs to describe listing and website generation and the process to move your site to a new URL:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;&#34;&gt;https://dropserver.org/docs/app-packaging-distributing&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;post-release-meandering&#34;&gt;Post-Release Meandering&lt;/h2&gt;
&lt;p&gt;After shipping 0.13 (🎉🎉) I have been feeling a bit directionless. I know there is tons more to work on but after focusing so much on one outcome, the sense of purpose feels awfully thin once the outcome is achieved.&lt;/p&gt;
&lt;p&gt;I am allowing myself a period of vagabonding through some ideas I have. In particular I don&amp;rsquo;t like how we build frontends for web-apps right now. Big messy SPAs are more trouble that they are worth. So I&amp;rsquo;m thinking about some possible ways of doing better there. I may write a bit of experimental code just to get it out of my system.&lt;/p&gt;
&lt;p&gt;This idea isn&amp;rsquo;t entirely disconnected from Dropserver: DS apps are meant to be &amp;ldquo;&lt;a href=&#34;https://www.robinsloan.com/notes/home-cooked-app/&#34;&gt;home cooked meals&lt;/a&gt;&amp;rdquo; and as such get put on a shelf for 6 months or more and revisited only occasionally. If upon revisiting the build system demands to be upgraded and then fails to do so, the app may be abandoned.&lt;/p&gt;
&lt;p&gt;I am also thinking about the &lt;a href=&#34;https://indieweb.org/&#34;&gt;IndieWeb&lt;/a&gt;, the way search engines are failing us, and how we have a lot of tech that already exists on websites (RSS, microformats) but is under-utilized and under-valued.&lt;/p&gt;
&lt;p&gt;These projects are fun to think about, but I can&amp;rsquo;t launch into anything that will take too much time away from the core of Dropserver. One thing I can do is improve the apps for Dropserver that I have built for myself, and publish them to a website. That was the whole idea of 0.13, right?&lt;/p&gt;
&lt;h2 id=&#34;leftovers-app-and-site&#34;&gt;Leftovers App and Site&lt;/h2&gt;
&lt;p&gt;I made a few improvements to the Leftovers app and released version 0.6.2. There are more small bugs I want to fix, and will do soon.&lt;/p&gt;
&lt;p&gt;First though I wanted to put Leftovers into its deserved home online:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://leftovers.olivierforget.net&#34;&gt;https://leftovers.olivierforget.net&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t want to settle for the automatically generated website. There really needs to be a description and some screenshots. I took the generated HTML and added what I felt was necessary. I link to the generated site for &lt;a href=&#34;https://leftovers.olivierforget.net/app/&#34;&gt;version details&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;other-work&#34;&gt;Other Work&lt;/h2&gt;
&lt;h4 id=&#34;indieweb&#34;&gt;IndieWeb&lt;/h4&gt;
&lt;p&gt;I added social media preview images to this site and polished some of its microformats. I have more work to do, but I&amp;rsquo;m excited to get involved with the &lt;a href=&#34;https://indieweb.org/&#34;&gt;IndieWeb&lt;/a&gt;. In particular I am thinking of ways that Dropserver can help. Some of the IndieWeb requires a server to work, which often falls on a centralized solution. I&amp;rsquo;d love to see if Dropserver can help break that pattern.&lt;/p&gt;
&lt;h4 id=&#34;ds-dev-on-windows&#34;&gt;ds-dev on Windows&lt;/h4&gt;
&lt;p&gt;I spent a bit of time working on getting &lt;code&gt;ds-dev&lt;/code&gt; to compile and run on Windows. I still want to do this but I am dialing back the time I spend on it.&lt;/p&gt;
&lt;p&gt;A version of Dropserver that is very easy to install and run on any OS is going to be a long term goal. I realized that after installing, the whole networking/domain/TLS certificates problem is such a huge hurdle for self-hosters that it&amp;rsquo;s just as important to resolve.&lt;/p&gt;
&lt;h4 id=&#34;lume-and-npm-on-dropserver&#34;&gt;Lume and npm on Dropserver&lt;/h4&gt;
&lt;p&gt;I played with &lt;a href=&#34;https://lume.land/&#34;&gt;Lume&lt;/a&gt; to see if it could eventually run as part of a Dropserver app. It won&amp;rsquo;t be easy because it depends on a lot of modules from npm, some of which &lt;a href=&#34;https://github.com/browserslist/browserslist/issues/813&#34;&gt;expect to have full read permissions on the filesystem&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I think a lot of the issues I encountered running Lume can be resolved and it will be able to run in a Dropserver app. It will take some tweaks on the Dropserver side, but this is a good test. App developers will want to make use of many npm modules, and Dropserver should accommodate this pattern.&lt;/p&gt;
&lt;p&gt;If Lume does run on Dropserver, that means you have a full fledged static site generator that can run in a Dropserver app. This opens up exciting possibilities: CMS for Lume inside a Dropserver app?&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll continue to improve the Dropserver apps I have, and publish them online. This will help people who are kicking the tires of Dropserver have something to play with. I also have ideas for more experimental &amp;ldquo;demo&amp;rdquo; apps (like a CMS+SSG as mentioned above) that give people a sense of what can be built.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll continue exploring possibilities for making Dropserver easy to install and self-host. But it will be a long road, and I realize that there is an other side to this equation: there needs to be a reason for people to install DS in the first place. That&amp;rsquo;s why I&amp;rsquo;ll also spend time on apps and demos of what&amp;rsquo;s possible.&lt;/p&gt;
&lt;p&gt;When I feel ready I&amp;rsquo;ll get to work on some bug fixes and improvements in view of a 0.13.1 release.&lt;/p&gt;
&lt;p&gt;Thanks for reading, see you next time.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - December 2023</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2024/dropserver-progress-december-2023/</link>
      <pubDate>Tue, 09 Jan 2024 14:10:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2024/dropserver-progress-december-2023/</guid>
      <description>&lt;p&gt;This is the monthly progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for December 2023. The previous report is &lt;a href=&#34;../../2023/dropserver-progress-novermber-2023/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;I made a big push to get version 0.13 out the door. While I didn&amp;rsquo;t succeed at actually cutting the release, the most challenging part is complete and I am now just adding a few more items. I also continued developing thoughts on how to take Dropserver to the next stage. I started work on getting &lt;code&gt;ds-dev&lt;/code&gt; to work on the Windows operating system.&lt;/p&gt;
&lt;h2 id=&#34;work-on-installing-app-from-url&#34;&gt;Work on Installing App from URL&lt;/h2&gt;
&lt;p&gt;Version 0.13 will make it possible to add an app to your Dropserver instance by pasting a URL. The app will be downloaded and installed, and Dropserver will periodically query that URL to determine if there are new versions of the app available. The user will see a callout when a new version is available to be installed.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ds-dev&lt;/code&gt; will generate all the necessary assets and JSON files necessary to distribute your app via a URL. All the developer needs to do is upload the generated files to a static site server.&lt;/p&gt;
&lt;p&gt;Getting all these pieces to work took some doing. In this progress report I&amp;rsquo;ll spare you the play-by-play of all the refactorings I had to do. Below are a few notable thoughts about recent work:&lt;/p&gt;
&lt;h3 id=&#34;the-app-distribution-test-site-became-a-dropserver-app&#34;&gt;The App Distribution Test Site Became a Dropserver App&lt;/h3&gt;
&lt;p&gt;Back in November I was using an entirely static site to test app distribution. I had created (by hand because the site generation code was not built) a static site that offered the necessary JSON and other files to distribute a Dropserver app. I uploaded them to Netlify and was able to test &lt;code&gt;ds-host&lt;/code&gt;&amp;rsquo;s ability to fetch a remote app by pasting that URL in the UI.&lt;/p&gt;
&lt;p&gt;However at the end of last month I got to the point where I needed to easily make changes to a published app in order to test how Dropserver displays the multitude of states it finds on the remote. For example: if I am writing the code that handles the appearance of a new app version on the distribution site, then ideally I should be able to set the distribution site to show that new version or not. That way I can repeatedly install the app, then &amp;ldquo;publish&amp;rdquo; the new version and see how &lt;code&gt;ds-host&lt;/code&gt; behaves.&lt;/p&gt;
&lt;p&gt;It is quite easy to update the site published on Netlify, but it&amp;rsquo;s still too slow and tedious for something I need to do dozens of times per day.&lt;/p&gt;
&lt;p&gt;The solution was to create a Dropserver app that could serve whatever situation I could dream up. I didn&amp;rsquo;t want to spend much time on this bit of tooling, so it only lets me select from a menu of pre-coded situations.&lt;/p&gt;
&lt;p&gt;The app is utterly basic (the main interface is an HTML form, with no styling or JS) and leverages some of Dropserver&amp;rsquo;s capabilities, like private routes for selecting the situation, and public file server route handlers for serving the JSON data files and app packages.&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2024/dropserver-progress-december-2023/ds-app-test-menu_hu3c8e4530b0749f151934ed62620525ae_54414_478x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2024/dropserver-progress-december-2023/ds-app-test-menu_hu3c8e4530b0749f151934ed62620525ae_54414_478x0_resize_box_3.png, https://olivierforget.net/blog/2024/dropserver-progress-december-2023/ds-app-test-menu_hu3c8e4530b0749f151934ed62620525ae_54414_957x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing a menu of options each with a radio button&#34;&gt;
&lt;p&gt;This worked really well. It was also a good exercise for me and for Dropserver: each time I thought of a new situation I wanted to serve, I coded it in the app, incremented the version, packaged and uploaded it to my instance, and it was live in a few seconds. This was accelerated dogfooding for app packaging, installation, and appspace migration.&lt;/p&gt;
&lt;p&gt;With the ability to switch the responses served by the app distribution site, I was ready to grind through the rest of the project.&lt;/p&gt;
&lt;h4 id=&#34;detour-into-the-future&#34;&gt;Detour into The Future&lt;/h4&gt;
&lt;p&gt;While doing the work described above it was hard to resist the temptation to create a full blown Dropserver app that serves as the app distribution site, instead of the rudimentary hard-coded thing. In the future, this is clearly how it will work: I will publish an app that you can use to publish your app.&lt;/p&gt;
&lt;p&gt;The motivator for this is that static sites can be a bit limiting. For example perhaps I&amp;rsquo;d like to get changelogs for versions 1.3.0 to 2.1.1. With a static site I&amp;rsquo;d have to do a lot of requests to get versions one-by-one, or perhaps I can load the entire app changelog which could be a lot of data. With a server handling the request, this becomes a single request that returns just what is asked.&lt;/p&gt;
&lt;p&gt;There are other reasons for the app distribution system to be Dropserver-based: it could include a support forum, reviews and comments, etc&amp;hellip;&lt;/p&gt;
&lt;p&gt;However the reason for sticking with the static site idea for now is that I think many devs will initially experiment with Dropserver locally, and may not expose their instance to the broader internet. As a result there should be a way to publish Dropserver apps without using Dropserver.&lt;/p&gt;
&lt;h3 id=&#34;the-grind&#34;&gt;The Grind&lt;/h3&gt;
&lt;p&gt;A lot of the work went into correctly reflecting the data obtained from the remote app distribution site in the the local DB and in the UI. Some examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dividing the UI flow between apps installed by uploading a package and apps installed from URL. When you add an app by uploading a package, newer versions must be obtained the same way. And vice versa, and app from a URL can only be updated when a new version is published at that URL.&lt;/li&gt;
&lt;li&gt;Lots of refactors to support re-using the same code paths for different but similar use cases, like fetching a changelog for a new app and a new version, validating manifest prior to fetching package as well as during installation, etc..&lt;/li&gt;
&lt;li&gt;Lots of head-scratching regarding error handling and reporting: the same error can be fatal for one process but informational in a different situation. This makes dividing up the code a bit tricky. I also improved how I report warnings to the user.&lt;/li&gt;
&lt;li&gt;Reflecting as much of the app to the user before they even fetch the remote package. So lots of new routes, remote fetches, and UI components to display all this as needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;windows-version-of-ds-dev&#34;&gt;Windows Version of ds-dev&lt;/h2&gt;
&lt;p&gt;Last month I decided to make Dropserver runnable on more common operating systems in an attempt to reduce the installation hurdles for self-hosters. As a first step I&amp;rsquo;m trying to get &lt;code&gt;ds-dev&lt;/code&gt; to work on Windows.&lt;/p&gt;
&lt;p&gt;So far I managed to get the test suite to run by eliminating the Linux/unix-specific code. At some point though I&amp;rsquo;ll have to figure out how get &lt;code&gt;ds-dev&lt;/code&gt; and &lt;code&gt;ds-host&lt;/code&gt; to quit nicely since &lt;a href=&#34;https://superuser.com/questions/959364/on-windows-how-can-i-gracefully-ask-a-running-program-to-terminate&#34;&gt;Windows doesn&amp;rsquo;t support &lt;code&gt;SIGTERM&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now I&amp;rsquo;m just going through the many failing tests and fixing them for Windows. I don&amp;rsquo;t know if I&amp;rsquo;ll hit any show-stoppers. I found one reason to be optimistic: &lt;a href=&#34;https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/&#34;&gt;Windows supports &lt;code&gt;AF_UNIX&lt;/code&gt; sockets&lt;/a&gt;! Dropserver communicates with its Deno sandboxes via unix sockets. Not having to re-write that is a plus!&lt;/p&gt;
&lt;h2 id=&#34;up-next&#34;&gt;Up Next&lt;/h2&gt;
&lt;p&gt;In January I&amp;rsquo;m shipping 0.13. That&amp;rsquo;s my focus. After that, we&amp;rsquo;ll see. See you on the other side!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - November 2023</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2023/dropserver-progress-novermber-2023/</link>
      <pubDate>Tue, 05 Dec 2023 19:10:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2023/dropserver-progress-novermber-2023/</guid>
      <description>&lt;p&gt;This is the monthly progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for November 2023. The previous report is &lt;a href=&#34;../dropserver-progress-october-2023&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;Although my main coding focus was getting Dropserver to install and update an application that is hosted on a third party website I got side-tracked by big thoughts on other topics. These don&amp;rsquo;t help the release tempo but are crucial for steering Dropserver in the right direction in the long term.&lt;/p&gt;
&lt;h2 id=&#34;a-light-bulb-moment&#34;&gt;A Light-Bulb Moment&lt;/h2&gt;
&lt;p&gt;I had this crazy idea: Dropserver should install and run on MS Windows and MacOS as a GUI application. It wouldn&amp;rsquo;t be terribly useful in its default configuration (localhost only), but it would allow potential users to get a taste of Dropserver. From there, configuration wizards would allow them to make their install more useful: like connecting other devices and users via a WireGuard tunnel, or leveraging 3rd party or Dropserver services for obtaining TLS certs and DNS management (think &lt;a href=&#34;https://ngrok.com/&#34;&gt;ngrok&lt;/a&gt;, &lt;a href=&#34;https://tailscale.com/&#34;&gt;Tailscale&lt;/a&gt;, &lt;a href=&#34;https://nextdns.io/&#34;&gt;NextDNS&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The big idea is that you have to go where the users are, and they are likely on a Win/Mac machine. When they get around to using a dedicated machine for Dropserver, the spare machines they have are also likely to be Windows and Mac. And if they were to buy a machine for this, they will be far more comfortable using a Mac Mini or an Intel NUC running Windows than a Linux box. That&amp;rsquo;s just the reality of it.&lt;/p&gt;
&lt;p&gt;By &lt;a href=&#34;../../2020/deno-saved-project&#34;&gt;choosing Deno&lt;/a&gt; as the sandbox for Dropserver, I effectively do not have any platform constraints. I should take full advantage of that.&lt;/p&gt;
&lt;p&gt;But it&amp;rsquo;s not just the Win/Mac thing, it&amp;rsquo;s also the idea that most people are GUI users. So instead of an &lt;a href=&#34;https://dropserver.org/docs/ds-host&#34;&gt;intimidating CLI and config file based installation&lt;/a&gt;, users should be able to run an installer then use a GUI to set things up. With that in mind I would also try to support a Linux GUI distribution for those users who made the jump to the penguin OS but would still rather avoid setting up complex configs using the command line.&lt;/p&gt;
&lt;p&gt;There are a lot of questions to answer before making this idea a reality, in particular lots of thought will have to go into making this as secure as possible. Thankfully it seems mainstream OS are getting the hint about sandboxing apps: &lt;a href=&#34;https://www.howtogeek.com/898570/this-is-how-windows-11-will-sandbox-apps-for-better-security/&#34;&gt;Windows will sandbox apps for better security&lt;/a&gt;, and &lt;a href=&#34;https://developer.apple.com/documentation/security/app_sandbox&#34;&gt;MacOS already has a Sandbox&lt;/a&gt;. These may allow me to preserve the second layer of sandboxing that I achieved &lt;a href=&#34;../dropserver-sandbox&#34;&gt;using Bubblewrap&lt;/a&gt; on Linux.&lt;/p&gt;
&lt;p&gt;A nagging feeling I&amp;rsquo;ve had with Dropserver these last months has been that it&amp;rsquo;s fine to have a platform that allows users to install web-apps easily. But if they can&amp;rsquo;t install the platform itself, what have I achieved? I think supporting mainstream OS with a GUI application is maybe a way to crack that nut. We&amp;rsquo;ll see. At least it gives me hope.&lt;/p&gt;
&lt;h2 id=&#34;frontend-thoughts&#34;&gt;Frontend Thoughts&lt;/h2&gt;
&lt;p&gt;I am spending a bit of time thinking about what tech stack I would use if I were to rebuild the &lt;code&gt;ds-host&lt;/code&gt; frontend. I am not thrilled with what I have right now (Vue 3 SPA) given that it is the control panel for a server. Why is it an SPA?&lt;/p&gt;
&lt;p&gt;SPAs are great at rendering a widget very fast, without a round trip to the server if you already have the widget data locally (like maybe the widget appeared in a list view earlier in the session). The &lt;a href=&#34;https://github.com/teleclimber/Leftovers&#34;&gt;Leftovers&lt;/a&gt; and ShoppingList Dropserver apps benefit from being locally rendered because these are the kinds of apps where any waiting time is painful for the user. But is this necessary for &lt;code&gt;ds-host&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;I originally chose Vue 3 and made it an SPA because that&amp;rsquo;s how I built the previous thing, whatever that was. It was less effort to just use the tech I knew. But now I&amp;rsquo;m seeing that it may not have been the right call. The SPA offers a good developer experience for me when I work on the components, but the data management story is poor. See below for an example.&lt;/p&gt;
&lt;p&gt;There is also lot of talk these days about web components and other more HTML-first approaches to app frontends. Maybe it&amp;rsquo;s a case of the grass is greener on the other side, but I can&amp;rsquo;t help but think about a rebuild that is more HTML-centric and simpler to maintain, not to mention more accessible and it could work without JS. The challenge is preserving the developer experience.&lt;/p&gt;
&lt;h2 id=&#34;progress-on-installing-apps-from-urls&#34;&gt;Progress on Installing Apps From URLs&lt;/h2&gt;
&lt;p&gt;Although I was able to fetch and install an app from a remote URL at the end of last month, that was hardly the end of the story. This month I implemented the storage and updating of the remote app&amp;rsquo;s info, then worked to update the frontend with this data.&lt;/p&gt;
&lt;p&gt;Note that if you don&amp;rsquo;t see any activity in the Github repo, it&amp;rsquo;s because I&amp;rsquo;m working in the &lt;a href=&#34;https://github.com/teleclimber/DropServer/tree/app-from-url&#34;&gt;&amp;ldquo;app-from-url&amp;rdquo; branch&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;db-work&#34;&gt;DB work&lt;/h4&gt;
&lt;p&gt;The DB work was fairly straightforward but lengthy. There are lots of possible situations that arise from updating data fetched remotely: any of a number of errors from various steps (fetching, validating), permanent redirects, data that has changed, data that hasn&amp;rsquo;t changed. Sorting through all that took some time, and the implementation and tests felt like a lot of work. Still it got done: &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/61489f961f63392c5449115b02a754990d7b0967&#34;&gt;commit 61489f9&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;frontend-work&#34;&gt;Frontend work&lt;/h4&gt;
&lt;p&gt;Fetching the app URL data from the DB and displaying it in the frontend was no big deal. Classic CRUD work. A challenge arose when I realized that a user may never know there is a new version of an app because of the way the frontend data model works.&lt;/p&gt;
&lt;p&gt;Simply put: the frontend loads all the apps and appspace data when a list of these is viewed, and keeps that data around between page navigation. This means that rendering an app detail page is instant. Neat. But miserable. Holding on to data means you have to update it when it changes by pushing from the backend.&lt;/p&gt;
&lt;p&gt;I started doing work to push events to the frontend: I implemented an event handler for app URL data on the backend, which ended up being my first contact with &lt;a href=&#34;https://go.dev/blog/intro-generics&#34;&gt;Go Generics&lt;/a&gt;. It took a bit of time but I found a satisfactory way of making backend events easy to implement thanks to Generics. I&amp;rsquo;ll call that a win. Commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/6e6f0dc8ba76784aee20688f868c552ddf95133e&#34;&gt;6e6f0d&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/e0e249865e44e8f184d8bdbacd3bed1d6b88bb3b&#34;&gt;e0e249&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the end I am not pushing events to the frontend. I think the whole &lt;code&gt;ds-host&lt;/code&gt; frontend is built on wrong-headed ideas given the type of data it presents. It just doesn&amp;rsquo;t need to be an SPA. So instead of adding complexity I just made it such that app URL data is reloaded when a user clicks through to a Manage App page. This solves the problem well enough and easily enough.&lt;/p&gt;
&lt;h4 id=&#34;refresh-app-url-data&#34;&gt;Refresh app URL data&lt;/h4&gt;
&lt;p&gt;In &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/0a7c31a2d8721bf8527c8858a96d0d7aab6870ec&#34;&gt;commit 0a7c31&lt;/a&gt; I tied a bunch of things together (the DB data, in particular the stashed ETag, the frontend, and the fetch code with SSRF protection) to enable one-click refresh of the remote app URL data. Whew! It&amp;rsquo;s annoying that this took so long but it&amp;rsquo;s progress.&lt;/p&gt;
&lt;p&gt;From there I shouldn&amp;rsquo;t have much trouble automatically refreshing the remote app URL data on a timer, which &lt;code&gt;ds-host&lt;/code&gt; will do about once per day.&lt;/p&gt;
&lt;h2 id=&#34;next-up&#34;&gt;Next up&lt;/h2&gt;
&lt;p&gt;Next I&amp;rsquo;ll have to make my &lt;a href=&#34;https://exquisite-klepon-d4c052.netlify.app/&#34;&gt;dummy remote app sites&lt;/a&gt; that I use to test all this stuff so that I can change the site dynamically and then fetch an update. The reason is even though I have all the pieces in place I need to implement a proper UI for when a new app version is available or other edge cases. Once I have a good UI for handling a new version of an app, I&amp;rsquo;ll make it so &lt;code&gt;ds-dev&lt;/code&gt; can generate a static site for app distribution, and then I&amp;rsquo;ll ship 0.13.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll also continue to research and develop my ideas about frontend technology and an easily-installable mainstream-OS GUI version of Dropserver.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - October 2023</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2023/dropserver-progress-october-2023/</link>
      <pubDate>Wed, 01 Nov 2023 09:07:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2023/dropserver-progress-october-2023/</guid>
      <description>&lt;p&gt;This is the monthly progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for October 2023. The previous report is &lt;a href=&#34;../dropserver-progress-september-2023&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;My focus is on getting Dropserver to install and update an application that is hosted on a third party website. Most of the work is really just thinking about what the endpoints look like on the third party site, and all the different ways a user will proceed through the steps of installing an app and create an appspace, in particular thinking about how unattended upgrades will work.&lt;/p&gt;
&lt;p&gt;I also worked on other things as they came up, which included releasing version 0.12 early.&lt;/p&gt;
&lt;h2 id=&#34;vagrant-file-for-ds-host&#34;&gt;Vagrant file for ds-host&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://mastodon.social/@ocdtrekkie&#34;&gt;Jacob Weisz&lt;/a&gt; submitted a &lt;a href=&#34;https://github.com/teleclimber/Dropserver/pull/116&#34;&gt;PR for a Vagrant file&lt;/a&gt; to help potential developers build and run &lt;code&gt;ds-host&lt;/code&gt; on their machine. I merged the PR of course but it made me wonder how &lt;a href=&#34;https://www.vagrantup.com/&#34;&gt;Vagrant&lt;/a&gt; could be leveraged to really make it easy for developers to contribute to Dropserver.&lt;/p&gt;
&lt;p&gt;Someone contributing to &lt;code&gt;ds-host&lt;/code&gt; should be able to quickly rebuild and relaunch &lt;code&gt;ds-host&lt;/code&gt; after making changes. Running &lt;code&gt;ds-dev&lt;/code&gt;, compiled from source, should be easy as well.&lt;/p&gt;
&lt;p&gt;A frontend developer should be able to launch this Vagrant machine and quickly get to a point where they are editing Vue components while enjoying the benefits of Hot Module Reloading.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll have to dive into Vagrant a bit to make all this happen. I will have to dogfood this too: I will ditch the hand built VM I currently use to run &lt;code&gt;ds-host&lt;/code&gt; and use the Vagrant development environment to do all the development of Dropserver.&lt;/p&gt;
&lt;p&gt;Anyways, thanks Jacob!&lt;/p&gt;
&lt;h2 id=&#34;bug-fix-and-012-comes-out-early&#34;&gt;Bug fix and 0.12 comes out early&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://widerweb.org/@trevorflowers&#34;&gt;Trevor Flowers&lt;/a&gt; &lt;a href=&#34;https://github.com/teleclimber/Dropserver/issues/118&#34;&gt;reported a panic in &lt;code&gt;ds-dev&lt;/code&gt;&lt;/a&gt; while working on the tutorial app. Never great to have a panic on what should be well trodden code paths of a &amp;ldquo;Hello World&amp;rdquo; app. It turns out Vim puts a file called &amp;ldquo;4913&amp;rdquo; and immediately deletes it. This caused a panic in my application code watcher loop.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a classic case of a developer putting a panic in a branch of code because they think &amp;ldquo;this can&amp;rsquo;t ever happen&amp;rdquo; and a user comes along and says &amp;ldquo;oh yeah? watch this!&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;This was quickly fixed (explanation and resolution in this &lt;a href=&#34;https://brandur.org/live-reload#vim&#34;&gt;nice blog post&lt;/a&gt;) but unfortunately I had done quite a bit of work in the main branch of Dropserver, including a proper new feature (&lt;a href=&#34;https://social.tchncs.de/@teleclimber/111064743802155075&#34;&gt;app changelogs&lt;/a&gt;) so that a patch increment (0.11.1) was inappropriate.&lt;/p&gt;
&lt;p&gt;Thus was born &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.12.0&#34;&gt;Dropserver version 0.12&lt;/a&gt;, which frankly is no bad thing.&lt;/p&gt;
&lt;p&gt;Going forwards I will be more careful not to mistreat the master branch so that I am always ready to release a patch if the need arises.&lt;/p&gt;
&lt;p&gt;Thank you Trevor for taking the time to try working with &lt;code&gt;ds-dev&lt;/code&gt; and reporting the bug.&lt;/p&gt;
&lt;h2 id=&#34;work-on-apps-from-urls&#34;&gt;Work on Apps from URLs&lt;/h2&gt;
&lt;p&gt;The early part of the month was spent figuring out how this should work. It&amp;rsquo;s not that getting an app from a URL is much harder than installing an app that was just uploaded. It&amp;rsquo;s that having an app available for installation at a URL opens up a whole new mode of operation for Dropserver:&lt;/p&gt;
&lt;p&gt;👻👻👻💀💀💀 &lt;strong&gt;UNATTENDED APP UPGRADES&lt;/strong&gt; 💀💀💀👻👻👻&lt;/p&gt;
&lt;p&gt;Boo! Scary&amp;hellip; 🫢&lt;/p&gt;
&lt;p&gt;Since the base URL returns a listing of versions for an app, Dropserver could reload the URL periodically and install new versions of the app with no user interaction. This cascades further: unattended app upgrades lead to unattended appspace data migrations. Even more scary!&lt;/p&gt;
&lt;p&gt;The big challenge with unattended app installs and data migrations is that it puts all the responsibility on the developer. It means doing things while the user is not present to be the ultimate guardian for what happens to their data. Naturally, we should never count on the end user to be the last-resort safety net. Users click &amp;ldquo;Yes&amp;rdquo; if they want the thing, so it should always be up to us to protect users as much as possible. But having a user click &amp;ldquo;yes&amp;rdquo; is a convenient cop-out for not doing everything we can to prevent a user getting into a bad situation.&lt;/p&gt;
&lt;p&gt;Since apps and appspaces will eventually be upgraded without a user present, I need to do the work make it as safe as possible. Practically speaking, here are some ways I will try to do this:&lt;/p&gt;
&lt;h4 id=&#34;granular-control&#34;&gt;Granular control&lt;/h4&gt;
&lt;p&gt;Granular control over automatic steps: user should be able to choose what they&amp;rsquo;re comfortable letting Dropserver do without them in attendance. Maybe fetching an app listing automatically is OK, and maybe installing the app unattended is fine. But migrating an appspace&amp;rsquo;s data? No way.&lt;/p&gt;
&lt;h4 id=&#34;guardrails&#34;&gt;Guardrails&lt;/h4&gt;
&lt;p&gt;A system of warnings and good default guardrails. Since the user is not present to spot something &amp;ldquo;fishy&amp;rdquo; or that &amp;ldquo;looks weird&amp;rdquo;, Dropserver has to make those determinations. Some examples: if the license changes, if the app signature changes (not implemented yet), if the fetch URL redirects to a new, different domain, etc&amp;hellip; would all cause the auto-upgrade to abort.&lt;/p&gt;
&lt;h4 id=&#34;usable-logging&#34;&gt;Usable Logging&lt;/h4&gt;
&lt;p&gt;What happened, and what was the outcome? A &amp;ldquo;log&amp;rdquo; of all operations, along with the results should be visible to the user and formatted in an easily understandable way. When operations are initiated by the user we can present the outcome of the op to them immediately and discard these results soon after. When things take place with the user absent, we have to stash all these operation results and make them available for perusal. This will not prevent problems of course, but can help the user what happened when something did go wrong.&lt;/p&gt;
&lt;h3 id=&#34;multi-step-operations&#34;&gt;Multi-step operations&lt;/h3&gt;
&lt;p&gt;In addition to all the above I want to lay the groundwork for a better UX when creating an Appspace. Currently, the user has to install an app, and then create an &lt;a href=&#34;https://dropserver.org/docs/application-model&#34;&gt;appspace&lt;/a&gt; for it. It&amp;rsquo;s really not good that these are two separate steps. In a future version I would really like for the app installation to be part of the appspace creation. The flow should be: drag an app URL into Dropserver, choose a subdomain, make a few selections for permissions if needed, and click &amp;ldquo;Create&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;This implies that the operation has to install the app and then create an appspace using the new app ID. Not a big problem but if you don&amp;rsquo;t think about it and plan it well, it&amp;rsquo;s a good way to end up with some serious spaghetti code.&lt;/p&gt;
&lt;h3 id=&#34;so-what-code-did-i-actually-write&#34;&gt;So what code did I actually &lt;strong&gt;write&lt;/strong&gt;?&lt;/h3&gt;
&lt;p&gt;After all that thinking I realized I needed to clean things up a bit in my &lt;code&gt;appgetter&lt;/code&gt; code, so I refactored some of that to allow me to proceed more easily. Git commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/b12d3c89070e51a04dea8eed806bf21156efe664&#34;&gt;b12d3c&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then finally I wrote just enough code to be able to fetch and install an app from a URL.  It&amp;rsquo;s incomplete but it&amp;rsquo;s &lt;a href=&#34;https://social.tchncs.de/@teleclimber/111291834197198022&#34;&gt;functional as far as it goes&lt;/a&gt;. Git commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/35d6ae29ee50e29f3528373b76f953a657e1c813&#34;&gt;35d6ae&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Currently I create the app website by hand. It&amp;rsquo;s utterly minimal, just enough to expose a link to a JSON and a few other files. I created bad sites too (missing manifest and package files) to check that error conditions are handled decently enough. I uploaded the sites to Netlify to allow me to test. You can &lt;a href=&#34;https://exquisite-klepon-d4c052.netlify.app/&#34;&gt;see them here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note that part of the &amp;ldquo;apps from URLs&amp;rdquo; project is to make &lt;code&gt;ds-dev&lt;/code&gt; generate a basic website capable of displaying app information to potential users as well as serve the right files to &lt;code&gt;ds-host&lt;/code&gt; for the installation process.&lt;/p&gt;
&lt;h3 id=&#34;ssrf-protection&#34;&gt;SSRF protection&lt;/h3&gt;
&lt;p&gt;In the last few days of this month I started integrating an &lt;a href=&#34;https://en.wikipedia.org/wiki/Server-side_request_forgery&#34;&gt;SSRF&lt;/a&gt; protection library to the fetch code.&lt;/p&gt;
&lt;p&gt;I settled on &lt;a href=&#34;https://github.com/daenney/ssrf&#34;&gt;Daenney&amp;rsquo;s SSRF library&lt;/a&gt;, instead of &lt;a href=&#34;https://github.com/doyensec/safeurl&#34;&gt;safeurl&lt;/a&gt;. This in spite of the fact that safeurl has 77 stars while Daenney&amp;rsquo;s has 1. I usually prefer to go with widely used libraries, so here is why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Neither is really widely used apparently, so it&amp;rsquo;s a tossup in that category anyways.&lt;/li&gt;
&lt;li&gt;Daenney&amp;rsquo;s SSRF is not a big library and I feel I understand the code well enough. I can patch it myself if need be.&lt;/li&gt;
&lt;li&gt;I didn&amp;rsquo;t like that safeurl disables IPv6 by default. It makes me less confident about the library for some reason. SSRF embraces IPv6 from the get go and from what I can tell the developer did their homework.&lt;/li&gt;
&lt;li&gt;I like that SSRF regenerates its list of default bad IP ranges from IANA sources twice a month. Neat!&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://logoi.dny.dev/2022/12/02/implementing-ssrf-protections-in-golang/&#34;&gt;blog post&lt;/a&gt; accompanying Daenney&amp;rsquo;s SSRF is informative and confidence-inspiring.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m adding &lt;code&gt;ds-host&lt;/code&gt; config fields to specify IPs (and ranges) that should be reachable by the instance despite being on a private network. Work is ongoing.&lt;/p&gt;
&lt;h2 id=&#34;work-on-leftovers-and-other-apps&#34;&gt;Work on Leftovers and other apps&lt;/h2&gt;
&lt;p&gt;While I work on Dropserver proper, I also try to spend time on the apps that I write &lt;em&gt;for&lt;/em&gt; Dropserver. One reason is that I actually use these apps daily, and they all have papercuts that I am motivated to fix.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m currently working on the &lt;a href=&#34;https://github.com/teleclimber/Leftovers&#34;&gt;Leftovers&lt;/a&gt; app. I would like it to be in good shape for when &lt;code&gt;ds-dev&lt;/code&gt; can create app distribution websites. I&amp;rsquo;ll use Leftovers as the primary example of that.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll be plowing ahead with apps from URLs. I&amp;rsquo;d like to get to the point where apps and appspaces get upgraded when a new app version is available (if user so desires, of course). But I may not be able to make app installation part of the appspace creation operation (see &amp;ldquo;Multi-Step Operations&amp;rdquo; above). I need to draw the line somewhere.&lt;/p&gt;
&lt;p&gt;By the end of November I hope to have ds-dev generate app distribution sites too. We&amp;rsquo;ll see.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - September 2023</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2023/dropserver-progress-september-2023/</link>
      <pubDate>Tue, 03 Oct 2023 09:07:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2023/dropserver-progress-september-2023/</guid>
      <description>&lt;p&gt;This is the monthly progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; for September 2023. The previous report is &lt;a href=&#34;../dropserver-progress-august-2023&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;I worked on finishing app changelogs and started working on installing apps from a URL. This is all part of &amp;ldquo;Dropserver App Packaging and Distribution&amp;rdquo; project. I also spent some time thinking about how to present Dropserver.org, how to make it more easily usable, and whether working on app distribution is the best way to spend my time now.&lt;/p&gt;
&lt;h2 id=&#34;thinking-and-questioning&#34;&gt;Thinking and Questioning&lt;/h2&gt;
&lt;p&gt;When working on a large project over a long period of time there is always a risk that going on vacation will cause a rupture in the sense of progress that may trigger a slide into apathy. Luckily I don&amp;rsquo;t feel apathy, but the break has forced me to think about where Dropserver is at and how I get it to where I would like it to be. I went down these mental quests:&lt;/p&gt;
&lt;h3 id=&#34;low-friction-dropserver-offering&#34;&gt;Low Friction Dropserver Offering&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s no secret that I&amp;rsquo;m the only person who runs a Dropserver instance, and my wife is the only non-admin user in existence. That&amp;rsquo;s fine, for now. DS still has a lot of holes, and installing and running an instance is too demanding right now. But this can&amp;rsquo;t go on forever. I need to think about how I can make it easier for people (even technical users) to try and use Dropserver.&lt;/p&gt;
&lt;p&gt;Ultimately the easiest way for someone to get on Dropserver is by signing up through a commercial hosting service. So that&amp;rsquo;s what I need to work towards. (I have known this for a long time of course, but every once in a while I have to sit and ponder every other option before returning to my starting point.)&lt;/p&gt;
&lt;p&gt;But even with that, I would still be suffering from a lack of users because of a lack of apps.&lt;/p&gt;
&lt;h3 id=&#34;re-orient-dropserverorg-website&#34;&gt;Re-Orient Dropserver.org Website&lt;/h3&gt;
&lt;p&gt;A developer &lt;a href=&#34;https://sharetron.com/@casey/111013637359605183&#34;&gt;posted a cool project&lt;/a&gt; built on &lt;a href=&#34;https://www.glitch.com&#34;&gt;Glitch&lt;/a&gt;. Since this is the kind of project I&amp;rsquo;d like to see built for Dropserver, I wondered if a developer like Casey would consider developing an app for Dropserver if they even heard about it? Looking at the Dropserver.org home page with fresh eyes, it became immediately clear it wouldn&amp;rsquo;t do the trick. It&amp;rsquo;s focused towards the end-user, who scientifically speaking can not exist in this world right now. So what&amp;rsquo;s the point of pitching them?&lt;/p&gt;
&lt;p&gt;Then, while looking around for mentions of Dropserver on various sites, I found this &lt;a href=&#34;https://www.reddit.com/r/HomeServer/comments/zb8anu/eanix_home_server_os/&#34;&gt;discussion on Reddit&lt;/a&gt; that shows that there are many home application server offerings. A &lt;a href=&#34;https://www.reddit.com/r/HomeServer/comments/zb8anu/comment/iyurrdg/&#34;&gt;comment&lt;/a&gt; by &lt;a href=&#34;https://mastodon.social/@ocdtrekkie&#34;&gt;ocdtrekkie&lt;/a&gt; spells out exactly the problem: how do you differentiate yourself? The Dropserver.org doesn&amp;rsquo;t tell a developer why they are better off developing for Dropserver. Yet developer experience is one of the differentiating factors that I want to build into Dropserver. I need to rethink the Dropserver.org site with that in mind.&lt;/p&gt;
&lt;h3 id=&#34;what-to-work-on&#34;&gt;What to Work On&lt;/h3&gt;
&lt;p&gt;The problem with spending so much time thinking is that nothing gets built, and everything comes into question. For a period I thought I might punt on installing apps from distribution URLs. I decided to carry on due to the realization that the order of things I release doesn&amp;rsquo;t matter: it all needs to get built sooner or later. The worst thing I can do given my limited resources is to stop mid-project to focus on something else because I imagine somehow it will serve DS better. This is wasteful, and I should just build the thing that I can build most effectively right now.&lt;/p&gt;
&lt;p&gt;After spending so much time on app installation and distribution, I should just knock it out and move on.&lt;/p&gt;
&lt;h2 id=&#34;some-code-progress-finally&#34;&gt;Some Code Progress, Finally&lt;/h2&gt;
&lt;h3 id=&#34;finish-work-on-changelogs&#34;&gt;Finish Work on Changelogs&lt;/h3&gt;
&lt;p&gt;I talked about changelogs in the last update. On September 13 I &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/6b161818e1ad0e02bc98117b8435aedd99a9dbcb&#34;&gt;committed the changes&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;work-on-apps-from-websites&#34;&gt;Work on Apps from Websites&lt;/h3&gt;
&lt;p&gt;The goal for Dropserver version 0.12 is that a user should be able to install an app by pasting a URL where that app can be found. Not only can the app be installed using this method, but it should be possible to fetch updates and install the latest version, and do so automatically if the user so desires.&lt;/p&gt;
&lt;p&gt;A further constraint is I want developers to be able to publish their apps as static website. Static website hosts are widely available with a generous free tier, and developers routinely host their blogs and other sites on them. The idea is that if &lt;code&gt;ds-dev&lt;/code&gt; can generate a set of files then the developer just has to upload them to their static host of choice, and the app is published.&lt;/p&gt;
&lt;p&gt;All this presents me with a number of questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is this URL? What does it look like?&lt;/li&gt;
&lt;li&gt;What data resides at that URL?&lt;/li&gt;
&lt;li&gt;What other files need to be generated?&lt;/li&gt;
&lt;li&gt;How will internationalization and localization fit into all this?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The current design calls for the URL to point to a JSON file that contains an array of versions, each with URLs to fetch the complete manifest (JSON), the package file (tar.gz), the icon file, and the changelog file (plain text).&lt;/p&gt;
&lt;h4 id=&#34;urls&#34;&gt;URLs&lt;/h4&gt;
&lt;p&gt;I would like for URLs to be clean, so a user should be able to paste olivierforget.net/leftovers/ to get the leftovers app. But that URL should serve a HTML page describing the app. I could use HTTP Headers to tell the server I want the data file, but remember I want this to be trivial to host. I don&amp;rsquo;t want the dev to fiddle with settings in their static host, which is usually required when you want to serve different content based on headers.&lt;/p&gt;
&lt;p&gt;So I am thinking of using either a &lt;code&gt;.well-known&lt;/code&gt; path like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;olivierforget.net/leftovers/.well-known/dropserver/app-listing.json
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;My fear is that the interpretation of trailing slash in the original URL will cause some problems.&lt;/p&gt;
&lt;p&gt;The other option would be to put a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag in the HTML page served that points to the data file, however it&amp;rsquo;s not clear either of these are appropriate for the task.&lt;/p&gt;
&lt;p&gt;For now user will have to paste a complete URL to the JSON file.&lt;/p&gt;
&lt;h4 id=&#34;ssrf-protection&#34;&gt;SSRF Protection&lt;/h4&gt;
&lt;p&gt;The first thing I ran into when starting to actually implement fetching that URL is the potential for &lt;a href=&#34;https://en.wikipedia.org/wiki/Server-side_request_forgery&#34;&gt;SSRF&lt;/a&gt; — Server-Side Request Forgery. Fetching apps remotely can&amp;rsquo;t be an avenue for probing your local network.&lt;/p&gt;
&lt;p&gt;While &lt;a href=&#34;https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html&#34;&gt;mitigations for SSRF&lt;/a&gt; are well understood, they present a problem for home-lab / self-hosters: the main idea of the mitigation is to prevent connections to servers that have a non-public IP. But if you are hosting at home or on a private network, well, that&amp;rsquo;s all your IPs.&lt;/p&gt;
&lt;p&gt;After &lt;a href=&#34;https://social.tchncs.de/@teleclimber/111126940558297760&#34;&gt;asking on Mastodon&lt;/a&gt; it seems the solution is to block all connections to local addresses except those white-listed by the instance admin via a config. This is probably the direction I&amp;rsquo;ll take.&lt;/p&gt;
&lt;p&gt;Here is a good post on &lt;a href=&#34;https://logoi.dny.dev/2022/12/02/implementing-ssrf-protections-in-golang/&#34;&gt;preventing SSRF attacks in Go&lt;/a&gt;, and a &lt;a href=&#34;https://github.com/daenney/ssrf&#34;&gt;library to go with it&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h2&gt;
&lt;p&gt;In October I&amp;rsquo;ll continue working on fetching apps from URLs and on the generation of the files necessary to host an app.&lt;/p&gt;
&lt;p&gt;I am still being pulled away from Dropserver by unrelated projects, so I don&amp;rsquo;t expect to be able to make leaps of progress, but at least I shouldn&amp;rsquo;t spend too much time thinking!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - August 2023</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2023/dropserver-progress-august-2023/</link>
      <pubDate>Fri, 01 Sep 2023 10:07:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2023/dropserver-progress-august-2023/</guid>
      <description>&lt;p&gt;This is the third progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt;. This one will be very short thanks to a much needed vacation during most of the month. See &lt;a href=&#34;../dropserver-progress-july-2023/&#34;&gt;last month&amp;rsquo;s report&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;After the release of version &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.11.0&#34;&gt;0.11&lt;/a&gt; I took some time for exploratory thinking. Upon my return from vacation I went to work on the &amp;ldquo;distribution&amp;rdquo; part of &amp;ldquo;app packaging and distribution&amp;rdquo;.&lt;/p&gt;
&lt;h3 id=&#34;exploratory-thinking&#34;&gt;Exploratory Thinking&lt;/h3&gt;
&lt;h4 id=&#34;i18n&#34;&gt;I18N&lt;/h4&gt;
&lt;p&gt;I collected links to tools and libraries that are used for translating apps with the goal of some day doing the work of making Dropserver localizable.&lt;/p&gt;
&lt;h4 id=&#34;tailscale&#34;&gt;Tailscale&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;https://tailscale.com/&#34;&gt;Tailscale&lt;/a&gt; has the potential to give users access to a self-hosted Dropserver instance without exposing that instance to the broader internet. I spent a bit of time trying to learn more about what it can do. I collected a few videos to watch during my vacation (I did not find the time to watch them 😑).&lt;/p&gt;
&lt;h3 id=&#34;back-to-coding&#34;&gt;Back to coding&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m back at work now writing code (sluggishly). The next release will make it possible to publish apps and Dropserver users will be able to get automated upgrades to the latest app version (opt-in of course).&lt;/p&gt;
&lt;h4 id=&#34;app-changelogs&#34;&gt;App Changelogs&lt;/h4&gt;
&lt;p&gt;I&amp;rsquo;m working on integrating release notes aka &amp;ldquo;changelogs&amp;rdquo; in packaged apps.&lt;/p&gt;
&lt;p&gt;I did a bit of research and found some &lt;a href=&#34;https://social.tchncs.de/@teleclimber/110974327197863815&#34;&gt;interesting things&lt;/a&gt; about changelogs in major platforms.&lt;/p&gt;
&lt;p&gt;I had punted on changelogs for v0.11 because I do not love the naïve approach I could take: simply include a markdown file with all release notes for shipped versions in reverse chronological order. I would like to be able to pick out the release notes for specific versions. A lot can be done to present things usefully for the user once you can pick individual version notes.&lt;/p&gt;
&lt;p&gt;Another concern is the security implication of showing markdown content created by 3rd parties in the user&amp;rsquo;s admin panel. This can not be the source of a vulnerability. To show markdown (or HTML) safely I would have to filter the content through a library like &lt;a href=&#34;https://github.com/microcosm-cc/bluemonday&#34;&gt;bluemonday&lt;/a&gt; on the server side, and display it in an iframe to gain two layers of protection against potentially malicious content. This is more work than I&amp;rsquo;d like to do right now, so I&amp;rsquo;m sticking to plain text.&lt;/p&gt;
&lt;p&gt;I decided to make plaintext file (not markdown) for changelogs, where the changelog for version x.y.z is preceded by a line consisting solely of &amp;ldquo;x.y.z&amp;rdquo;. With that, devs can easily write changelogs in a text file and the system can easily parse that file to extract the changes for a given version.&lt;/p&gt;
&lt;p&gt;Having a structured changelog format allows me to do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;warn if no changes entered for latest version (each version should include a changelog)&lt;/li&gt;
&lt;li&gt;present other metadata in listing of changes (release date, package size, API version, etc&amp;hellip;)&lt;/li&gt;
&lt;li&gt;show the changes made between the currently installed version and the version about to be installed (useful if user did not upgrade for a few versions)&lt;/li&gt;
&lt;li&gt;if upgrade includes a major rev, highlight the changes for the major release (x.0.0) which are usually lengthy and describe meaningful changes&lt;/li&gt;
&lt;li&gt;if some changes have been translated into the user&amp;rsquo;s preferred language, show these instead of the developer&amp;rsquo;s original version.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h2&gt;
&lt;p&gt;August was mostly spent not working. This Fall I will be busy with a number of non-Dropserver things but I should still be able to make good progress.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be working on app distribution and automatic upgrades which will result in release of version 0.12.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - July 2023</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2023/dropserver-progress-july-2023/</link>
      <pubDate>Tue, 01 Aug 2023 09:07:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2023/dropserver-progress-july-2023/</guid>
      <description>&lt;p&gt;This is the second progress report for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt;. This one will be modest unlike the &lt;a href=&#34;../dropserver-progress-june-2023&#34;&gt;previous epic&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;I continued to work on app packaging and managed to tag a release. To celebrate, I immediately went to work fixing some of the things that didn&amp;rsquo;t make it into the release.&lt;/p&gt;
&lt;h2 id=&#34;finishing-up-app-packaging&#34;&gt;Finishing Up App Packaging&lt;/h2&gt;
&lt;h3 id=&#34;app-name-and-description&#34;&gt;App Name and Description&lt;/h3&gt;
&lt;p&gt;I had to create validations for app name, and decide how to deal with violations. The main factor is app name length.&lt;/p&gt;
&lt;h4 id=&#34;app-name-length&#34;&gt;App name length&lt;/h4&gt;
&lt;p&gt;I had to decide how to limit application names and short descriptions that are entered by the app developer in the manifest.&lt;/p&gt;
&lt;p&gt;Every app platform I have come across limits the length of app names and other strings. Names should be limited in length because it makes it easier for users to scan when apps are displayed alongside other apps. But how does a hard limit square with the realities of responsive design? A name might be cumbersome to display on a phone screen but have lots of room to spare on a large display.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s be honest: maximum app name length is completely arbitrary. For this reason I settled on an arbitrary value, but only give a warning and not a fatal error if the name is too long. I&amp;rsquo;ll deal with exceedingly long app names using CSS.&lt;/p&gt;
&lt;h4 id=&#34;dont-be-naïve-count-graphemes&#34;&gt;Don&amp;rsquo;t be naïve: count graphemes&lt;/h4&gt;
&lt;p&gt;The naïve approach to counting the number of characters in a string is to count the length of a string. This is quite wrong unless you&amp;rsquo;re dealing strictly with ASCII characters. The answers in &lt;a href=&#34;https://stackoverflow.com/questions/12668681/how-to-get-the-number-of-characters-in-a-string&#34;&gt;this StackOverflow question&lt;/a&gt; cover a lot of ground.&lt;/p&gt;
&lt;p&gt;Thankfully I found a good &lt;a href=&#34;https://github.com/rivo/uniseg&#34;&gt;Go library that counts graphemes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/e495dad81301d3d66e629a6d7866009d224acdf9&#34;&gt;e495dad&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;remove-bad-urls-from-manifest&#34;&gt;Remove Bad URLs From Manifest&lt;/h3&gt;
&lt;p&gt;In earlier work bad URLs (like &lt;code&gt;Javascript:&lt;/code&gt;) were marked with a warning, but that meant they were still displayed in the admin frontend, which is exactly what you don&amp;rsquo;t want. Ideally the bad urls would be visible but not rendered as a clickable link.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t have the code paths to do this easily and reliably, so I do the easy thing and overwrite bad urls with an empty string.&lt;/p&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/8738eeab6dfa1ba608cf8cc58318941f7e091244&#34;&gt;8738eea&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;specify-package-base-filename&#34;&gt;Specify Package Base Filename&lt;/h3&gt;
&lt;p&gt;When you create a package file using &lt;code&gt;ds-dev&lt;/code&gt;, you now specify a base filename. So:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ds-dev -create-package=/path/to/dist/ -app=/path/to/app -pagkage-name=leftovers
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;hellip;creates &lt;code&gt;leftovers-0.1.2.tar.gz&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I thought about putting the package name in the manifest, but it doesn&amp;rsquo;t make sense. It&amp;rsquo;s not a property of the app. It has no meaning. The package could be called anything and package file names can change from version to version, the system doesn&amp;rsquo;t care. For that reason it&amp;rsquo;s an argument to the packaging tool.&lt;/p&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/0222007e5ab0dc6bb802099ad7c741cf3f38d209&#34;&gt;0222007&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;set-arbitrary-reasonable-manifest-size&#34;&gt;Set Arbitrary Reasonable Manifest Size&lt;/h3&gt;
&lt;p&gt;While limiting app name length (as well as for other strings in the manifest) is mostly a UI issue, there remains the possibility that someone will abuse the manifest with absurdly long strings, hoping to cause the system to have to deal with all that data will cause a DDOS of some sort.&lt;/p&gt;
&lt;p&gt;To prevent this I decided that manifests should only be so big. You can do anything you want, but beyond a certain size, the manifest will not be processed at all.&lt;/p&gt;
&lt;p&gt;This works because there is a lot of room between the size of a reasonably large manifest and the amount of data needed to cause problems in &lt;code&gt;ds-host&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The max size is 10kB. Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/bbbaf0c252eb2a298e34c2ab395add752abbc2c7&#34;&gt;bbbaf0c&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;validate-icon-image&#34;&gt;Validate Icon Image&lt;/h3&gt;
&lt;p&gt;I added validations for the app icon. Using a go library I check the icon size in pixels, I check that it&amp;rsquo;s square, and I warn if the icon size is too large (in kB).&lt;/p&gt;
&lt;p&gt;Along the way I learned that you can compress PNGs a &lt;em&gt;lot&lt;/em&gt; with tools like &lt;a href=&#34;https://tinypng.com/&#34;&gt;tinypng.com/&lt;/a&gt; (which are probably wrappers aroudn open source tools).&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t allow gifs for app icons, but I learned that PNGs can be animated. I don&amp;rsquo;t want app icons to move in the admin panel, so I check that the PNG is not an animation.&lt;/p&gt;
&lt;p&gt;Commit &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/8daf0f896af5e99e5d9e0b6020512586a1a7f238&#34;&gt;8daf0f8&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sometime after this something happened in the social media world: The Twitter app was rebranded to &amp;ldquo;X&amp;rdquo; and the icon changed. At least one app platform warned its users about the change:&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2023/dropserver-progress-july-2023/win-review-icon-update_hu22497dabf656186ccfe01d7cee780cea_20952_344x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2023/dropserver-progress-july-2023/win-review-icon-update_hu22497dabf656186ccfe01d7cee780cea_20952_344x0_resize_box_3.png, https://olivierforget.net/blog/2023/dropserver-progress-july-2023/win-review-icon-update_hu22497dabf656186ccfe01d7cee780cea_20952_688x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing a dialog confirming that an icon should be changed from Twitter to X&#34;&gt;
&lt;p&gt;See this &lt;a href=&#34;https://social.tchncs.de/@teleclimber/110793865736193328&#34;&gt;post on Mastodon&lt;/a&gt;. This made me realize that I would probably eventually validate that the icon has not changed significantly from version to version. This will require doing a similarity analysis between icons, luckily this &lt;a href=&#34;https://github.com/vitali-fedulov/images4&#34;&gt;go library&lt;/a&gt; might work just fine.&lt;/p&gt;
&lt;h3 id=&#34;domain-change-tool&#34;&gt;Domain Change Tool&lt;/h3&gt;
&lt;p&gt;I wanted to test all the changes I made for App Packaging against my personal &amp;ldquo;production&amp;rdquo; instance of Dropserver, but I did not want to upset this instance at all, since I rely on it. Downloading all the data from that instance and sticking it on my dev VM is easy enough, but the problem is that there a lot of places in the DB and appspace data that stores domain names.&lt;/p&gt;
&lt;p&gt;I decided to start work on a &amp;ldquo;domain change&amp;rdquo; tool in a branch (I won&amp;rsquo;t release it for a while) that would go through the DB and appspaces and change the domain name. That would allow me to take the data of any instance of &lt;code&gt;ds-host&lt;/code&gt; and change the domain names so that it can run under a different domain.&lt;/p&gt;
&lt;p&gt;This is useful for testing purposes. But it&amp;rsquo;s also handy if a user loses control of their domain and they want to reboot their instance under a different domain, for example.&lt;/p&gt;
&lt;p&gt;Work is in the &lt;a href=&#34;https://github.com/teleclimber/Dropserver/tree/change-domain-tool&#34;&gt;change-domain-tool branch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After digging through to find all the spots where a domain is written, I had a tool that did the job. It worked well to test all the changes against my &amp;ldquo;prod&amp;rdquo; data. A nice boost in confidence for this release and a useful tool already showing value.&lt;/p&gt;
&lt;h3 id=&#34;documentation&#34;&gt;Documentation&lt;/h3&gt;
&lt;p&gt;I wrote a &lt;a href=&#34;https://dropserver.org/docs/app-manifest-ref&#34;&gt;reference page for the app manifest&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I also wrote a high level overview of &lt;a href=&#34;https://dropserver.org/docs/building-dropserver-app&#34;&gt;how to build a Dropserver app&lt;/a&gt;. It is meant to give potential devs a quick view of things that are different with Dropserver app development, along with some gotchas.&lt;/p&gt;
&lt;p&gt;Finally I also added a page for &lt;a href=&#34;https://dropserver.org/docs/app-packaging-distributing&#34;&gt;packaging a Dropserver app&lt;/a&gt;. It&amp;rsquo;s a stub really for now.&lt;/p&gt;
&lt;p&gt;I found myself struggling a bit writing these docs. On one hand I want things explained. On the other, each word of docs I write needs to be maintained. Outdated docs are worse than no docs. So I have to be concise and direct, so I can stand a chance to keep it all fresh.&lt;/p&gt;
&lt;h3 id=&#34;release-v0110-&#34;&gt;Release v0.11.0 🥳🎉&lt;/h3&gt;
&lt;p&gt;Finally on July 19 I &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases/tag/v0.11.0&#34;&gt;released App Packaging&lt;/a&gt;. &lt;a href=&#34;https://social.tchncs.de/@teleclimber/110742399284484003&#34;&gt;Mastodon post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;post-release-fixes&#34;&gt;Post-Release Fixes&lt;/h2&gt;
&lt;p&gt;First thing to do after releasing is to fix and tweak the things that were missed in the release.&lt;/p&gt;
&lt;h3 id=&#34;tweak-migrations-validations&#34;&gt;Tweak Migrations Validations&lt;/h3&gt;
&lt;p&gt;In the released version of Dropserver, an app must provide migration functions in pairs (a down-migration for each up-migration). This is to encourage devs to give users a way to back out of an app upgrade that they are not happy with.&lt;/p&gt;
&lt;p&gt;Unfortunately the mere presence of a down-migration function does not guarantee that it will do its job satisfactorily. I worried that a dev faced with a fatal error because of a missing migration would simply add a stub for the down migration. This is the worst possible outcome, because the system will assume the migration took place, leading to data corruption.&lt;/p&gt;
&lt;p&gt;I decided a warning would be plenty good enough. Commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/3f19c30e28734c7295ccd1b1b56e5ce6a5d65dda&#34;&gt;3f19c30&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/502448e0f54410e189839b9f1d8dd8d2eb3258a2&#34;&gt;502448e&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;display-migrations-in-a-grid&#34;&gt;Display Migrations in a Grid&lt;/h3&gt;
&lt;p&gt;In both &lt;code&gt;ds-dev&lt;/code&gt; and &lt;code&gt;ds-host&lt;/code&gt; I wanted to show migrations that ship with an app as clearly as possible. I settled on a grid layout which I think is satisfactory.&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2023/dropserver-progress-july-2023/migrations-grid_hu5875a6d4f8aedc14249715f2a90c4936_50184_424x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2023/dropserver-progress-july-2023/migrations-grid_hu5875a6d4f8aedc14249715f2a90c4936_50184_424x0_resize_box_3.png, https://olivierforget.net/blog/2023/dropserver-progress-july-2023/migrations-grid_hu5875a6d4f8aedc14249715f2a90c4936_50184_848x0_resize_box_3.png 2x&#34;
    alt=&#34;A screenshot showing a grid to indicate which migrations are provided with an app.&#34;&gt;
&lt;p&gt;Commits &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/71bd4b17ff922cdf738894f7dadb8a1a9096431b&#34;&gt;71bd4b1&lt;/a&gt; and &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/0dc3c20535ec53fa8727a9e0aca025a76754c4a3&#34;&gt;0dc3c20&lt;/a&gt;. Yes, there is an alignment problem, &lt;a href=&#34;https://social.tchncs.de/@teleclimber/110787497035668160&#34;&gt;I know&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;ds-dev-ui-and-code&#34;&gt;ds-dev UI and Code&lt;/h3&gt;
&lt;p&gt;I changed all Vue component code to use the &lt;a href=&#34;https://vuejs.org/api/sfc-script-setup.html&#34;&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt; style&lt;/a&gt;. It&amp;rsquo;s a huge improvement in developer experience but refactoring each component is some very boring labor. This is where I wish I were a bit more adept at using AI to code because it would do quick work of this task. Oh well, it&amp;rsquo;s &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commit/91164a2fd075c642bd914d1f9f0869ec4a23f210&#34;&gt;done&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h2&gt;
&lt;p&gt;The big thing I&amp;rsquo;d like to work on next is app distribution and the ability to install and update an app automatically using just the URL at which the app is published. This is the &amp;ldquo;Distribution&amp;rdquo; part of &amp;ldquo;App Packaging and Distribution&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;But right now I&amp;rsquo;m headed for a vacation during a good chunk of the month of August so I am not going to start on that until September.&lt;/p&gt;
&lt;p&gt;See you then!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropserver Progress - April to June 2023</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2023/dropserver-progress-june-2023/</link>
      <pubDate>Fri, 07 Jul 2023 16:07:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2023/dropserver-progress-june-2023/</guid>
      <description>&lt;p&gt;I am going to try writing monthly updates on the progress of &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; development. Regardless of whether I have anything significant to share, I&amp;rsquo;ll post about the past month&amp;rsquo;s work. I&amp;rsquo;ll look at my commits and my notes (I take copious notes, arranged chronologically and in threads, but that&amp;rsquo;s the subject of a different post) and summarize what I worked on.&lt;/p&gt;
&lt;p&gt;Since this is the first such post it will cover all the work I&amp;rsquo;ve done from my last release in mid April until the end of June 2023.&lt;/p&gt;
&lt;h2 id=&#34;the-big-picture&#34;&gt;The Big Picture&lt;/h2&gt;
&lt;p&gt;I am working on application packaging. The goal is to make it easy for someone who wrote an app for Dropserver to make it available to others, and for non-technical people to make use of that app in their Dropserver instance.&lt;/p&gt;
&lt;p&gt;The current version of Dropserver allows a user to upload a &lt;em&gt;directory&lt;/em&gt; of app files. This is error prone and makes it hard to share apps around. Furthermore, the so-called &amp;ldquo;manifest&amp;rdquo; has very little useful information in it (basically just app name and version).&lt;/p&gt;
&lt;p&gt;Here is what I had to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;come up with a package format, including the manifest and the archive and compression format&lt;/li&gt;
&lt;li&gt;create the tooling that creates the package and integrate it into &lt;a href=&#34;https://dropserver.org/docs/ds-dev&#34;&gt;&lt;code&gt;ds-dev&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;adapt &lt;code&gt;ds-host&lt;/code&gt; to accept these packages and install the app&lt;/li&gt;
&lt;li&gt;update the frontend of &lt;code&gt;ds-host&lt;/code&gt; to show app package values and warnings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This has been a big project. I haven&amp;rsquo;t released a new version of Dropserver since April 10th 2023, but hopefully I should be able to release this sometime in July.&lt;/p&gt;
&lt;h2 id=&#34;details&#34;&gt;Details&lt;/h2&gt;
&lt;p&gt;Note: I am developing this in the &lt;a href=&#34;https://github.com/teleclimber/Dropserver/commits/app-package-1&#34;&gt;app-package-1 branch&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;exploratory-thoughts&#34;&gt;Exploratory thoughts&lt;/h3&gt;
&lt;p&gt;As is typical with how I work, I first had to explore the outer fringes of reasonable ideas before accepting that would I have to build is pretty straightforward and follows in line with prior art.&lt;/p&gt;
&lt;h4 id=&#34;do-i-even-need-a-manifest&#34;&gt;Do I even need a manifest?&lt;/h4&gt;
&lt;p&gt;What&amp;rsquo;s so necessary about a &amp;ldquo;manifest&amp;rdquo;? Dropserver already runs the code to get metadata about the app (such as available migrations) and perhaps putting everything in app code is the simplest thing to do for developers?&lt;/p&gt;
&lt;p&gt;Unfortunately this doesn&amp;rsquo;t work for some fields: the &lt;code&gt;entrypoint&lt;/code&gt; of the code can&amp;rsquo;t be set in code! And even if all data could be obtained by running code, Dropserver would still need a manifest format to stash that data. You do not want to run a sandbox every time you want to know something about an app. Once you have that, why not let the app dev write into it directly instead of cluttering their code?&lt;/p&gt;
&lt;h4 id=&#34;single-file-apps&#34;&gt;&amp;ldquo;Single File Apps&amp;rdquo;&lt;/h4&gt;
&lt;p&gt;Wouldn&amp;rsquo;t it be great if you could write a single TS/JS file and have it become a web-app without doing any packaging work. You could share it around as a GitHub Gist or anywhere else. (&lt;a href=&#34;https://social.tchncs.de/@teleclimber/110216573477447480&#34;&gt;Mastodon post&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;That sounds cool but the reality is that most web-based things are inherently multi-file. If you serve a frontend, even a simple one, you&amp;rsquo;ll want HTML templates and a style sheet. I realized the value of &amp;ldquo;Single-File Apps&amp;rdquo; was low and the additional complexity in Dropserver was not worth it. Instead I am focusing on making packaging easy thanks to built-in tooling in &lt;code&gt;ds-dev&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;app-distribution-site&#34;&gt;App distribution site&lt;/h4&gt;
&lt;p&gt;I don&amp;rsquo;t want Dropserver app devs and users to be beholden to a single centralized app store. It should be possible for an application developer to publish their app on a website that they control, and users should be able to install it from there. The independent and open web demands this.&lt;/p&gt;
&lt;p&gt;I had originally thought that such an application distribution website would actually be driven by a Dropserver application, but at this stage it&amp;rsquo;s better to do something simpler. An app distribution site will just be a static site hostable on any static website host.&lt;/p&gt;
&lt;p&gt;This is one idea I have not abandoned. I&amp;rsquo;m merely punting on it for a future version, but it&amp;rsquo;s still the plan.&lt;/p&gt;
&lt;h3 id=&#34;figure-out-the-manifest&#34;&gt;Figure out the manifest&lt;/h3&gt;
&lt;p&gt;Having decided I needed a manifest, I had to decide what fields would go in it, what format these fields would be, and how they would be validated. I created a &lt;a href=&#34;https://github.com/users/teleclimber/projects/5&#34;&gt;GH Project&lt;/a&gt; and an &lt;a href=&#34;fields-table.html&#34;&gt;Ethercalc table&lt;/a&gt; to work through the scenarios and possible fields. (Note that these are outdated at this point and do not reflect all my latest thinking.)&lt;/p&gt;
&lt;p&gt;I looked at manifests for &lt;a href=&#34;https://developer.android.com/guide/topics/manifest/manifest-intro&#34;&gt;Android&lt;/a&gt; (not very relevant), NPM&amp;rsquo;s &lt;a href=&#34;https://docs.npmjs.com/cli/v6/configuring-npm/package-json&#34;&gt;package.json&lt;/a&gt;, &lt;a href=&#34;https://docs.sandstorm.io/en/latest/developing/publishing-apps/&#34;&gt;Sandstorm&lt;/a&gt;, &lt;a href=&#34;https://yunohost.org/en/packaging_manifest&#34;&gt;YUNoHost&lt;/a&gt; and others for inspiration. All were informative but I found some cool ideas in YUNoHost, like pre-defined tags for &lt;a href=&#34;https://github.com/YunoHost/apps/blob/master/antifeatures.toml&#34;&gt;anti-features&lt;/a&gt; and a system for determining &lt;a href=&#34;https://yunohost.org/en/packaging_testing#application-quality-level&#34;&gt;application quality levels&lt;/a&gt;. I&amp;rsquo;m not implementing these ideas yet, but I may in the future.&lt;/p&gt;
&lt;p&gt;I had to decide on TOML versus JSON for the manifest file (&lt;a href=&#34;https://social.tchncs.de/@teleclimber/110255032974661601&#34;&gt;mastodon link&lt;/a&gt;). I decided to use JSON. TOML is lesser known and still has detractors, while JSON is nothing new for JS devs, even if it&amp;rsquo;s not ideal. Additionally, the packaging process writes its own version of the manifest, so JSON is a bit easier to work with.&lt;/p&gt;
&lt;h3 id=&#34;package-format&#34;&gt;Package format&lt;/h3&gt;
&lt;p&gt;Zip or tar.gz or something else? See this &lt;a href=&#34;https://social.tchncs.de/@teleclimber/110312970807871476&#34;&gt;Mastodon thread&lt;/a&gt;. I found tar.gz to be a better bet. It&amp;rsquo;s well supported and well understood. It&amp;rsquo;s fairly safe. No patent questions, unlike Zip.&lt;/p&gt;
&lt;p&gt;Data backups of appspaces are saved in Zip format right now. But that&amp;rsquo;s because I expect end-users to want to open these locally. There is no reason for a non-dev to manually open the archive of an app, so it&amp;rsquo;s OK if it&amp;rsquo;s in a less popular archive format.&lt;/p&gt;
&lt;h3 id=&#34;packaging-flow&#34;&gt;Packaging flow&lt;/h3&gt;
&lt;p&gt;I worked out that the app developer would write a partial manifest. Currently the only absolutely required field is the app version. They create their app package using &lt;code&gt;ds-dev -create-package&lt;/code&gt; which runs the sandbox to obtain additional data like data schema, available migration functions, and others. These get added to the manifest, and this &amp;ldquo;augmented manifest&amp;rdquo; is placed in the package instead of the dev&amp;rsquo;s original. Additionally the augmented manifest is saved locally.&lt;/p&gt;
&lt;p&gt;I do this because I want the dev to write a minimal manifest if possible, but some fields should be available without having to run a sandbox. So the augmented manifest serves as a cache for values determined at runtime.&lt;/p&gt;
&lt;h3 id=&#34;installation-flow&#34;&gt;Installation flow&lt;/h3&gt;
&lt;p&gt;A user can install an app by uploading an app package to their Dropserver account (wherever it may be). I wrote the necessary pieces to enable this flow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ds-host&lt;/code&gt; unpacks the archive carefully to prevent archive-based attacks. In particular it has an expectation of a maximum size for a package, and bails on the process as soon as it hits that maximum. The max is hard-coded right now, but it will tie in to the user disk quota mechanism when that gets written.&lt;/li&gt;
&lt;li&gt;It reads the manifest and runs the sandbox to obtain the values that are available at runtime. It validates all the values (note that it uses the values it gets from the sandbox instead of the values of the manifest where it can.)&lt;/li&gt;
&lt;li&gt;If the user commits the new app, it saves the extracted files, and it places the augmented manifest in a JSON column in the DB. It also keep the original package file.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;add-fields-to-the-manifest&#34;&gt;Add fields to the manifest&lt;/h3&gt;
&lt;p&gt;After I got rudimentary packaging and installation done, I added handling for more fields of the manifest:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;App entrypoint: This is known as &lt;code&gt;main&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;. It&amp;rsquo;s the file that the sandbox runs. It used to be hard-coded as &lt;code&gt;app.ts&lt;/code&gt;. Now it defaults to &lt;code&gt;app.ts&lt;/code&gt; and &lt;code&gt;app.js&lt;/code&gt;, or to whatever the manifest says. Here I had to be careful that it is not possible to make a path that climbs out of the app package.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;App icon: This will be shown alongside the app name in &lt;code&gt;ds-host&lt;/code&gt; UI and helps differentiate the apps. The app icon value in the manifest is a path relative to the package root to an image file. Naturally I had to take care that this would not be used to read files that are outside the package. I still have to put constraints on image size in pixels, as well as file size. Eventually expect to use something similar to &lt;a href=&#34;https://developer.android.com/distribute/google-play/resources/icon-design-specifications&#34;&gt;Android&amp;rsquo;s Icon spec&lt;/a&gt; to guide icon design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Accent color: A color that the dev chooses that complements the app icon or matches the UI of their app. This color is used to decorate a box that gives information about the app in the &lt;code&gt;ds-host&lt;/code&gt; UI. It&amp;rsquo;s never used as a background or foreground color for text so it does not affect accessibility. To make things easy for the dev any CSS color is accepted. I found a &lt;a href=&#34;github.com/mazznoer/csscolorparser&#34;&gt;CSS color parser in Go&lt;/a&gt; which made that nice and easy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Authors: An array of author objects each with name, URL and email.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;URLs: I added fields for app website, code repository and funding. Then I realized that there is such a thing as the &lt;a href=&#34;http://web.archive.org/web/20230103230046/http://crisp.tweakblogs.net/blog/313/the-useless-javascript-pseudo-protocol.html&#34;&gt;&lt;code&gt;javascript:&lt;/code&gt; protocol&lt;/a&gt;, and just displaying these URLs as links in the &lt;code&gt;ds-host&lt;/code&gt; UI could be a terrible idea. So they get validated as proper &lt;code&gt;http(s)://&lt;/code&gt; URLs. If they fail they get removed from the manifest upon app installation. I process author URLs the same.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Release date: A date in GMT that is automatically added to the manifest at package creation time. Its sole purpose is to let the user know whether the version was released recently or not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;License: I decided that the license field should preferably be an &lt;a href=&#34;https://spdx.org/licenses/&#34;&gt;SPDX&lt;/a&gt; string. If it&amp;rsquo;s not you get a warning. The reason for using SPDX is that I may want to give users a quick synopsis of the license but I can only really do that if I can correctly identify it, and SPDX is really made for that. Furthermore in the unlikely event that a license is incompatible with Dropserver, then being able to positively identify it will be useful.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ds-dev-frontend&#34;&gt;ds-dev frontend&lt;/h3&gt;
&lt;p&gt;I updated the UI of &lt;code&gt;ds-dev&lt;/code&gt;, the local dev-oriented app runner, to show all the values and warnings about the app and the manifest that a user would get if they installed the app on &lt;code&gt;ds-host&lt;/code&gt;. This should make it easy for the app dev to correct any issues before shipping.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ds-dev&lt;/code&gt; runs the same code to validate the app as &lt;code&gt;ds-host&lt;/code&gt; does when it installs the app (as does the &lt;code&gt;-create-package&lt;/code&gt; command) therefore the developer sees all the warnings the user will see (with the caveat that different versions of these programs may behave differently).&lt;/p&gt;
&lt;h3 id=&#34;app-version-model&#34;&gt;App version model&lt;/h3&gt;
&lt;p&gt;With so much metadata stashed in the manifest, I had to figure which fields were needed and in what circumstances. I don&amp;rsquo;t want to return the entire manifest every time some function needs to know something about the app version.&lt;/p&gt;
&lt;p&gt;After spinning my wheels for a while I figured that there was an internal use case that is used to run the sandbox and do other operations, and only needs values related to that (entrypoint, and a few others). Then there is the basic &amp;ldquo;UI&amp;rdquo; case, where we are presenting the app to the user and need short-description, authors, urls, icon, color, etc&amp;hellip; Finally we sometimes do need to get the entire manifest so there is a method for that.&lt;/p&gt;
&lt;p&gt;In the first two cases I make use of sqlite&amp;rsquo;s &lt;a href=&#34;https://www.sqlite.org/json1.html&#34;&gt;JSON functions&lt;/a&gt; to cherry-pick desired values from the JSON manifest (which is stored in a JSON column in the db). I am happy with this. It means I have the whole manifest available, or any subset of it that I may need.&lt;/p&gt;
&lt;h3 id=&#34;ds-host-frontend&#34;&gt;ds-host frontend&lt;/h3&gt;
&lt;p&gt;I did a lot of work on the &lt;code&gt;ds-host&lt;/code&gt; frontend. With data like icon, color, license, authors now available as metadata for the app I was able to make the display of apps more rich and interesting.&lt;/p&gt;
&lt;p&gt;See screenshots in this &lt;a href=&#34;https://social.tchncs.de/@teleclimber/110628600342105593&#34;&gt;Mastodon thread&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;punting&#34;&gt;Punting&lt;/h3&gt;
&lt;p&gt;I had to punt on a lot of things. It&amp;rsquo;s hard to do but it&amp;rsquo;s necessary to keep momentum. I&amp;rsquo;ll tackle these later:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;signatures for app packages: needs to be done right, I want to spend more time thinking about it.&lt;/li&gt;
&lt;li&gt;internationalization of manifest values: I need a Dropserver-wide strategy for I18N, which I&amp;rsquo;m thinking about but it&amp;rsquo;s not there.&lt;/li&gt;
&lt;li&gt;release notes: surprisingly tricky to do well. I could take the easy way out (one md file with all release notes), but I want to see if I can improve on the status quo here.&lt;/li&gt;
&lt;li&gt;get app from URL and auto-updating: that&amp;rsquo;s another huge chunk of work that I will do in a different release.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;looking-ahead&#34;&gt;Looking Ahead&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m at the point where I&amp;rsquo;m finishing up loose ends and doing testing. I still have a lot of docs to write but I hope to release this soon.&lt;/p&gt;
&lt;p&gt;After that I&amp;rsquo;d like to go straight to work on installing an app from a URL, and everything that comes with that, but I may have to take a step back to see if that&amp;rsquo;s really what needs to happen at that point in time.&lt;/p&gt;
&lt;p&gt;In the future I may add a number of other fields to the manifest, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;age appropriateness&lt;/li&gt;
&lt;li&gt;anti-features (like YUNoHost)&lt;/li&gt;
&lt;li&gt;features / capabilities listing (like &lt;a href=&#34;https://mastodon.social/@ocdtrekkie/110192994794926052&#34;&gt;ocdtrekkie suggested&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;package size / installed size&lt;/li&gt;
&lt;li&gt;whether additional resources are needed or if the package is self-contained&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other big ticket items that are in need of attention for Dropserver as whole:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I18N&lt;/li&gt;
&lt;li&gt;Appspace user management and instance-to-instance data sharing for users&lt;/li&gt;
&lt;li&gt;More powerful app capabilities: enable outbound requests (with permissions), support Server-Sent Events, and many more&amp;hellip;&lt;/li&gt;
&lt;li&gt;Working towards a hosted version of Dropserver&lt;/li&gt;
&lt;li&gt;And countless other stuff&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lots to do. See you next month!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The State of Sandboxing in Dropserver</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2023/dropserver-sandbox/</link>
      <pubDate>Thu, 02 Mar 2023 13:07:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2023/dropserver-sandbox/</guid>
      <description>&lt;p&gt;One of the bigger challenges of developing &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; has been to somehow make it safe to run the user&amp;rsquo;s application code. In this &lt;a href=&#34;https://olivierforget.net/blog/2020/deno-saved-project/&#34;&gt;long-ago post&lt;/a&gt; I relayed how I tried a number of different approaches, all of them being too difficult to make work until &lt;a href=&#34;https://deno.land&#34;&gt;Deno&lt;/a&gt; arrived. Naturally that was not the end of the story.&lt;/p&gt;
&lt;p&gt;But first&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;why-is-sandboxing-important-in-dropserver&#34;&gt;Why Is Sandboxing Important in Dropserver?&lt;/h3&gt;
&lt;p&gt;The goal of Dropserver is to make it possible for regular users to run server-side code of their choosing. Currently, for all internet users except for a very slim minority, touching anything &amp;ldquo;online&amp;rdquo; means interacting with a server over which they have no control. Dropserver aims to change that by giving regular people the ability to do internet things without losing all control.&lt;/p&gt;
&lt;p&gt;Dropserver users are able to upload and run &amp;ldquo;&lt;a href=&#34;https://dropserver.org/docs/application-model/&#34;&gt;apps&lt;/a&gt;&amp;rdquo;, which are basically a pile of JS code written by a well-intentioned developer. While the &amp;ldquo;app&amp;rdquo; may include a frontend that will run in the browser, the real value of Dropserver is that the app can run server-side code.&lt;/p&gt;
&lt;p&gt;An arrangement like that is rife for abuse if no guardrails are in place. That &amp;ldquo;well-intentioned&amp;rdquo; developer could actually be trying to gain control of the machine Dropserver runs on. Even if the developer is a goodie, &lt;a href=&#34;https://threatpost.com/malicious-npm-packages-web-apps/178137/&#34;&gt;compromised dependencies&lt;/a&gt; could seek to turn a nice app into a vector for an attack.&lt;/p&gt;
&lt;p&gt;As a result Dropserver treats all app code as potentially malicious and gives it as little access as possible to protect the safety of users running apps, the admin hosting the instance, and everybody else on that instance.&lt;/p&gt;
&lt;p&gt;My goal is that a Dropserver user should feel free to install apps just to kick the tires, even if they don&amp;rsquo;t know who the developer is and won&amp;rsquo;t be bothered to read through the code looking for vulnerabilities. Dropserver should feel safe. I think this is essential for the ecosystem to develop.&lt;/p&gt;
&lt;h3 id=&#34;deno-is-the-sandbox&#34;&gt;Deno is the Sandbox&lt;/h3&gt;
&lt;p&gt;Deno claims it is a secure runtime, and it&amp;rsquo;s likely fairly good at that. Through its use Dropserver can limit what an app can do, such as where on disk it can write and whether the app can make network requests.&lt;/p&gt;
&lt;p&gt;However no software is without bugs, and even in the absence of bugs our current reality is that &lt;a href=&#34;https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)&#34;&gt;Spectre&lt;/a&gt; is a vulnerability that is pervasive across all running code. (Note there are some mitigations against Spectre attacks built into Deno: for example high-precision timers are behind a flag.)&lt;/p&gt;
&lt;p&gt;In any case we should not assume Deno is and will remain airtight. For this reason a second layer of protection is essential. This is especially true since there is a good chance many Dropserver installations will not update Deno in time, and will therefore be vulnerable if any of their app code decides to take advantage of the vuln.&lt;/p&gt;
&lt;h3 id=&#34;bubblewrap-is-the-other-sandbox&#34;&gt;Bubblewrap is the Other Sandbox&lt;/h3&gt;
&lt;p&gt;Julia Evans aka &amp;ldquo;&lt;a href=&#34;https://social.jvns.ca/@b0rk&#34;&gt;B0rk&lt;/a&gt;&amp;rdquo; has a &lt;a href=&#34;https://jvns.ca/blog/2022/06/28/some-notes-on-bubblewrap/&#34;&gt;neat writeup&lt;/a&gt; where she was looking at various sandboxing tools, and found Bubblewrap. &lt;a href=&#34;https://github.com/containers/bubblewrap&#34;&gt;Bubblewrap&lt;/a&gt; basically takes the challenging work of creating Linux namespaces for your sandbox in code and makes it accessible in a convenient command line utility.&lt;/p&gt;
&lt;p&gt;Bubblewrap can set up Linux Kernel sandboxing features by specifying a few flags. It also helps make your sandbox useful by binding directories or files from the host system into the sandbox. Without Bubblewrap or another similar tool I&amp;rsquo;d be left with calling Linux system calls directly which would be more error-prone.&lt;/p&gt;
&lt;p&gt;After some playing around, I feel so much better letting bwrap do this work rather than trying to code it myself.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s interesting to note that another app platform, &lt;a href=&#34;https://sandstorm.io/&#34;&gt;Sandstorm&lt;/a&gt; (and now &lt;a href=&#34;https://github.com/zenhack/tempest&#34;&gt;Tempest&lt;/a&gt;), roll their own C code to achieve a similar goal. There has been talk of leveraging Bubblewrap, but since they&amp;rsquo;ve already done the work and they trust their C code, &lt;a href=&#34;https://github.com/containers/bubblewrap/commit/f37abd142f5e897c83a0dba7efa36b84bcf458e4&#34;&gt;they are sticking to it&lt;/a&gt;. More power to them (and more responsibility :))&lt;/p&gt;
&lt;h3 id=&#34;dropserver-010&#34;&gt;Dropserver 0.10&lt;/h3&gt;
&lt;p&gt;In Dropserver v0.10.0 I added support for wrapping Deno instances in bwrap. Here are some notes on the current implementation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deno is dynamically linked and therefore needs access to &lt;code&gt;/etc&lt;/code&gt; and some lib directories to run. Not great. I&amp;rsquo;m hoping we&amp;rsquo;ll get a statically linked version of Deno some day. This is being &lt;a href=&#34;https://github.com/denoland/deno/issues/3711&#34;&gt;talked about&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I do not have an HTTP proxy for the sandbox yet so I have to give access to &lt;code&gt;/run&lt;/code&gt; on certain systems so that it can do DNS lookups.&lt;/li&gt;
&lt;li&gt;Deno requires &lt;code&gt;/proc&lt;/code&gt; dir. With &lt;code&gt;--unshare-pid&lt;/code&gt; that&amp;rsquo;s not a big problem since the processes in &lt;code&gt;/proc&lt;/code&gt; will only be bwrap and deno.&lt;/li&gt;
&lt;li&gt;Unfortunately I am not using &lt;code&gt;--unshare-pid&lt;/code&gt; right now. It causes &lt;code&gt;bwrap&lt;/code&gt; to give me the pid of the forked &lt;code&gt;bwrap&lt;/code&gt;, not the &lt;code&gt;deno&lt;/code&gt; command that I am running. I&amp;rsquo;ll spare you the &lt;a href=&#34;https://github.com/containers/bubblewrap/issues/553&#34;&gt;details&lt;/a&gt;, but while this is something I can work around I decided it was time to ship.&lt;/li&gt;
&lt;li&gt;I realized that &lt;a href=&#34;https://deno.land/manual@v1.30.3/getting_started/setup_your_environment#environment-variables&#34;&gt;&lt;code&gt;DENO_DIR&lt;/code&gt;&lt;/a&gt;, where deno caches imported modules, etc&amp;hellip; can be a vector for abuse. It has to be read-write in the sandbox, so if someone breaks out of Deno, they can alter cached code files and therefore compromise other apps without even touching them. Yikes. For this reason each appspace gets its own &lt;code&gt;DENO_DIR&lt;/code&gt;. It slows the initial start, but after that it&amp;rsquo;s no different.&lt;/li&gt;
&lt;li&gt;Since &lt;code&gt;DENO_DIR&lt;/code&gt; is per-appspace, Deno makes many requests to the outside to obtain all the imported code the first time the appspace is run. For this reason in the current implementation the &lt;code&gt;bwrap&lt;/code&gt; sandbox must have full net access.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see there are a lot of caveats to Dropserver&amp;rsquo;s use of Bubblewrap for now. The good news is that there is a functional starting point that I can build on.&lt;/p&gt;
&lt;h3 id=&#34;roadmap&#34;&gt;Roadmap&lt;/h3&gt;
&lt;p&gt;Here is how I see Dropserver&amp;rsquo;s sandbox evolving:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If/when a statically linked or &lt;a href=&#34;https://musl.libc.org/&#34;&gt;musl&lt;/a&gt;-compatible version of Deno is available, stop binding all the libs and &lt;code&gt;/etc&lt;/code&gt; in the sandbox.&lt;/li&gt;
&lt;li&gt;A HTTP(S) proxy would make it possible to not bind the parts of the OS responsible for DNS lookups.
(Such a proxy will happen alongside the feature that allows apps make outbound http requests.)&lt;/li&gt;
&lt;li&gt;I spent some time experimenting with Linux virtual networking, such as following this &lt;a href=&#34;https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/&#34;&gt;post&lt;/a&gt;, but unfortunately I could not come up with a combination of &lt;code&gt;veth&lt;/code&gt; and whatever that did what I needed. (Some networking stuff requires privileges, which my use of bwrap does not have). However, creating a unix socket that is accessible from in and out of the sandbox is very straightforward so I expect to make the proxy accessible through that. Note that for now Deno doesn&amp;rsquo;t understand proxies as unix sockets, but that may change. Deno leverages &lt;a href=&#34;https://github.com/seanmonstar/reqwest/&#34;&gt;Reqwest&lt;/a&gt;, which is &lt;a href=&#34;https://github.com/seanmonstar/reqwest/issues/39&#34;&gt;considering this feature&lt;/a&gt;. Just have to be patient: the reward will be turning off network access entirely for the &lt;code&gt;bwrap&lt;/code&gt; sandbox.&lt;/li&gt;
&lt;li&gt;Look deeper at user namespaces. I&amp;rsquo;m using &lt;code&gt;--unshare-user-try&lt;/code&gt;, I need to look more at what happens when the user namespace does not get created.&lt;/li&gt;
&lt;li&gt;Dig deeper into Spectre to ensure I&amp;rsquo;m doing everything I can to mitigate.&lt;/li&gt;
&lt;li&gt;Seccomp. Bubblewrap has the ability to limit kernel calls via &lt;a href=&#34;https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html&#34;&gt;seccomp&lt;/a&gt;, but I have never tried that. This should make for a much tighter sandbox.&lt;/li&gt;
&lt;li&gt;There is a new set of tools that can help isolate a process called &lt;a href=&#34;https://lwn.net/Articles/859908/&#34;&gt;Landlock&lt;/a&gt;. I would look into that however I&amp;rsquo;ll probably have to wait until Bubblewrap implements it, which for now is &lt;a href=&#34;https://github.com/containers/bubblewrap/pull/519#pullrequestreview-1156361461&#34;&gt;not planned&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Explore the possibility of putting Deno installation under &lt;code&gt;ds-host&lt;/code&gt;&amp;rsquo;s control. That way it could automatically upgrade to latest patched versions as they become available.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My hope is that eventually Dropserver&amp;rsquo;s Bubblewrap sandbox will be lean and effective. Having this second layer of security around Deno makes me much more comfortable with the prospect of eventually running a Dropserver service and letting others upload and run anything they want (scary!)&lt;/p&gt;
&lt;p&gt;Note that the work of sandboxing is never done. Witness the work that Cloudflare puts into &lt;a href=&#34;https://developers.cloudflare.com/workers/learning/security-model&#34;&gt;sandboxing its Workers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sandboxing is, of course, only part of the picture, but it&amp;rsquo;s a critical part and I&amp;rsquo;m glad to be moving forward with it.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A Secret Santa App On Dropserver</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2022/secret-santa-dropserver-app/</link>
      <pubDate>Mon, 12 Dec 2022 13:07:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2022/secret-santa-dropserver-app/</guid>
      <description>&lt;p&gt;Inspired by Simon Willison&amp;rsquo;s &lt;a href=&#34;https://simonwillison.net/2022/Dec/11/over-engineering-secret-santa/&#34;&gt;post on making a Secret Santa app as a Datasette plugin&lt;/a&gt; I decided to write a minimalist Secret Santa app for Dropserver.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; is my attempt at building a platform for hosting my own personal apps. A primary objective of DS is that it should be really easy for a developer, particularly a frontend developer, to write an app that can be hosted by Dropserver.&lt;/p&gt;
&lt;p&gt;DS accomplishes this by using a JavaScript runtime (&lt;a href=&#34;https://deno.land&#34;&gt;Deno&lt;/a&gt;) and by providing many of the hard parts of backend apps baked in. This means that in a few lines of business logic, written in a language you likely know well, you can build a useful app with many of the bells and whistles of a bigger SaaS app.&lt;/p&gt;
&lt;h2 id=&#34;writing-the-app&#34;&gt;Writing the app&lt;/h2&gt;
&lt;p&gt;Anyways, let&amp;rsquo;s get going.&lt;/p&gt;
&lt;p&gt;This project builds on the Dropserver &lt;a href=&#34;https://dropserver.org/docs/build-dropserver-app-tutorial/&#34;&gt;app tutorial&lt;/a&gt;. We will use no new concepts, we will just add more business logic, more routes and more static files to serve (CSS, a font file and a &lt;code&gt;santa-hat.png&lt;/code&gt; for cuteness).&lt;/p&gt;
&lt;p&gt;Here is the &lt;a href=&#34;https://github.com/teleclimber/SecretSantaDropApp&#34;&gt;GitHub repo&lt;/a&gt; if you want to follow along.&lt;/p&gt;
&lt;h2 id=&#34;users&#34;&gt;Users&lt;/h2&gt;
&lt;p&gt;In its current incarnation Dropserver does all the user management for the app. That means the app developer does not need to code any user registration login, password storage, etc&amp;hellip; Users even have avatars, which helps make apps more friendly looking.&lt;/p&gt;
&lt;p&gt;All the app needs to do is call the &lt;code&gt;getUsers()&lt;/code&gt; method to get a list of users. Users are identified by a &amp;ldquo;proxy ID&amp;rdquo;, which is a string of alphanumeric characters that is stable and unique for each user. Personally identifying information, such as login email, is not accessible from the app.&lt;/p&gt;
&lt;p&gt;As I began writing this app I remembered that I have not yet implemented the user permission system for Dropserver apps. That means that each user is at the same level: and there is no way to distinguish an admin user from a regular user. This is something I will add in a future version of Dropserver, but for now I&amp;rsquo;ll just have to be a bit clever about when pairings can be generated.&lt;/p&gt;
&lt;p&gt;The app will detect whether Secret Santa pairings have been been made already and if the list of users in the pairings match the list of existing users for the app. If not, it will offer to generate the pairings. If a user tries to regenerate the pairings when they have already been generated and match the user list, they will get a message saying they can&amp;rsquo;t do that.&lt;/p&gt;
&lt;p&gt;Once the pairings have been generated a user signing on to their Dropserver and clicking through to the appspace will see who they are paired with, as shown below:&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2022/secret-santa-dropserver-app/screenshot_hu3024ec72a804444c355a43f7d7509929_203345_372x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2022/secret-santa-dropserver-app/screenshot_hu3024ec72a804444c355a43f7d7509929_203345_372x0_resize_box_3.png, https://olivierforget.net/blog/2022/secret-santa-dropserver-app/screenshot_hu3024ec72a804444c355a43f7d7509929_203345_744x0_resize_box_3.png 2x&#34;
    alt=&#34;Screenshot of the Secret Santa App showing one user and their Secret Santa. The Secret Santa has a santa hat on. Cute.&#34;&gt;
&lt;h2 id=&#34;generating-pairings&#34;&gt;Generating pairings&lt;/h2&gt;
&lt;p&gt;To generate the pairings, we will shuffle an array of users, then make a pair out of a user and the one preceding it in the array. This is simple and guarantees that you don&amp;rsquo;t pair a user with themselves.&lt;/p&gt;
&lt;p&gt;We write the pairs of proxy ids as a json object to a file in the appspace. (An appspace is an app instance, an address where this app can be reached, and a dedicated directory where it can write files. For more details see &lt;a href=&#34;https://dropserver.org/docs/application-model/&#34;&gt;Dropserver application model&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;While there are no routes that show all the pairings, the user who owns the appspace could download a backup and look at the json file and the user metadata to know what the pairings are. I think this is reasonable for such an app. I could encrypt each pairing like Simon did, but it means asking users to remember yet another pass code. I suspect the most likely outcome is someone not getting a gift because a user forgot their additional pass phrase.&lt;/p&gt;
&lt;h2 id=&#34;the-rest-of-the-app&#34;&gt;The rest of the app&lt;/h2&gt;
&lt;p&gt;The entire server side code fits in a single 120 line TypeScript file, including comments and blank lines.&lt;/p&gt;
&lt;p&gt;The browser side consists of plain HTML responses generated on the backend via &lt;a href=&#34;https://mustache.github.io/&#34;&gt;Mustache&lt;/a&gt; templates. Hand coded CSS is served statically along with a few image assets and a fun little Christmasy font.&lt;/p&gt;
&lt;p&gt;There is no build or packaging step for the frontend or for the Dropserver side.&lt;/p&gt;
&lt;h2 id=&#34;hosting-your-own-secret-santa-app&#34;&gt;Hosting your own Secret Santa App&lt;/h2&gt;
&lt;p&gt;If you have a Dropserver instance running, you just upload the app directory, and click through a confirmation. Then you choose an address (usually a subdomain on a domain you&amp;rsquo;ve already configured) for your appspace and start adding your users.&lt;/p&gt;
&lt;p&gt;Note: you should be running &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases&#34;&gt;ds-host&lt;/a&gt; v0.8.1 or later (I ran into a bug while writing this app and had to push a fix 😬). Documentation on running ds-host is sparse for now. For hints see the &lt;a href=&#34;https://github.com/teleclimber/Dropserver&#34;&gt;Readme&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Currently each user must have a Dropserver login to access an appspace, however it can be on any instance. In the future, users who don&amp;rsquo;t have a login will be able to access an appspace with just an email address where they will receive a secret login link.&lt;/p&gt;
&lt;h2 id=&#34;playing-with-this-app-locally&#34;&gt;Playing with this app locally&lt;/h2&gt;
&lt;p&gt;If you don&amp;rsquo;t have a Dropserver instance handy (and let&amp;rsquo;s face it, in December 2022 if your name is not Olivier Forget you probably do not) you can install &lt;a href=&#34;https://github.com/teleclimber/Dropserver/releases&#34;&gt;ds-dev&lt;/a&gt; (v0.8.1 or later) and Deno to run it on localhost. Using ds-dev you can emulate users to see the different pairings show up. Read about &lt;a href=&#34;https://dropserver.org/docs/ds-dev/&#34;&gt;how to use ds-dev here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;go-and-fork-it&#34;&gt;Go and fork it&lt;/h2&gt;
&lt;p&gt;The Secret Santa app is usable as-is, yet there is plenty of room for improvement. The good news is: there is no build step, it&amp;rsquo;s just plain HTML and CSS, so if you don&amp;rsquo;t like the background color, just fork it, open it in ds-dev, and tweak it to your liking.&lt;/p&gt;
&lt;p&gt;I wrote this app to demonstrate that Dropserver is a platform that makes building simple, almost toy-like multi-user server apps approachable. You can make something basic but useful and fun and you can host it and use it with your friends. Others who want to use it can host their own copy with just a few clicks. And if you want to change something, it will only take a couple minutes to understand the code.&lt;/p&gt;
&lt;p&gt;Happy Holidays! I hope your Secret Santa, whoever they are, and however they were selected, gets you something nice.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Has Deno Turned a Corner?</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2022/has-deno-turned-corner/</link>
      <pubDate>Fri, 21 Oct 2022 13:07:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2022/has-deno-turned-corner/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://deno.land&#34;&gt;Deno&lt;/a&gt; is &lt;a href=&#34;https://nodejs.org&#34;&gt;NodeJS&lt;/a&gt; reinvented. I like writing code for Deno, and I depend on it as a sandbox for &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; after &lt;a href=&#34;https://olivierforget.net/blog/2020/deno-saved-project/&#34;&gt;trying many other approaches&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately the JavaScript community at large does not seem to be embracing Deno as much as I am. It seems many people are simply sticking with Node for now even though Deno 1.0 has been out &lt;a href=&#34;https://deno.com/blog/v1&#34;&gt;since Spring 2020&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I &lt;a href=&#34;https://social.tchncs.de/@teleclimber/107820908483183710&#34;&gt;posted this on Mastodon last February&lt;/a&gt;: Deno&amp;rsquo;s mindshare in 2021 was in the single-digits and had only improved by one percentage point a year later. Yikes! Not a good place to be.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2022/has-deno-turned-corner/state-of-js-2020_hu3bc8bc0b0b4f6a6026357b15c80a1cc2_93380_800x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2022/has-deno-turned-corner/state-of-js-2020_hu3bc8bc0b0b4f6a6026357b15c80a1cc2_93380_800x0_resize_box_3.png, https://olivierforget.net/blog/2022/has-deno-turned-corner/state-of-js-2020_hu3bc8bc0b0b4f6a6026357b15c80a1cc2_93380_1600x0_resize_box_3.png 2x&#34;
    alt=&#34;State of JS 2020 survey results showing Deno being used regularly by 6% of developers&#34;&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2022/has-deno-turned-corner/state-of-js-2021_hu4978be9c78b7ee29d8fd6104c70dff3c_461128_800x0_resize_box_3.png&#34; 
    srcset=&#34;https://olivierforget.net/blog/2022/has-deno-turned-corner/state-of-js-2021_hu4978be9c78b7ee29d8fd6104c70dff3c_461128_800x0_resize_box_3.png, https://olivierforget.net/blog/2022/has-deno-turned-corner/state-of-js-2021_hu4978be9c78b7ee29d8fd6104c70dff3c_461128_1600x0_resize_box_3.png 2x&#34;
    alt=&#34;State of JS 2021 survey results showing Deno being used regularly by 7% of developers&#34;&gt;
&lt;p&gt;&lt;em&gt;See &lt;a href=&#34;https://2020.stateofjs.com/en-US/other-tools/#runtimes&#34;&gt;State of JS 2020 survey results&lt;/a&gt; and &lt;a href=&#34;https://2021.stateofjs.com/en-US/other-tools/#runtimes&#34;&gt;State of JS 2021 survey results&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Why would people not make the switch? I think there are two reasons:&lt;/p&gt;
&lt;p&gt;Most legacy code does not run on Deno. Deno is taking a clean sheet approach, and shunning the old Node Package Manager. It&amp;rsquo;s also all in on ESM modules, while most Node code is CommonJS. So the legacy code is (was) largely incompatible. For developers who are used to finding just about anything on NPM, looking for packages on &lt;a href=&#34;https://deno.land/x/&#34;&gt;deno.land/x/&lt;/a&gt; must be a disappointment. For developers of large projects, such as Vite&amp;rsquo;s Evan You, doing the work to support Deno was simply &lt;a href=&#34;https://github.com/vitejs/vite/issues/109#issuecomment-626275698&#34;&gt;unthinkable&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Furthermore, while Deno is an improvement over Node, it&amp;rsquo;s not revolutionary. I remember hearing Ryan Dahl (Node and Deno creator) talking about the early days of Node. He said people would just show up and write packages as they needed them, which quickly filled the void. However this time it&amp;rsquo;s different. When Node came out, it really stood out. There was nothing like it. Developer experience on most other platforms of the time was poor. So naturally developers did what developers do: they went to town and built it all.&lt;/p&gt;
&lt;p&gt;Today there are plenty of fantastic platforms and Deno is not a sufficiently revolutionary step for developers to drop everything and write the libraries that are needed. It&amp;rsquo;s easier to just stick with Node.&lt;/p&gt;
&lt;h2 id=&#34;what-is-deno-doing-about-it&#34;&gt;What is Deno doing about it?&lt;/h2&gt;
&lt;p&gt;The Deno core team seem to have realized that the ecosystem is growing slowly and that the easiest way around that is to make it possible to use NPM dependencies in Deno projects. They&amp;rsquo;ve taken &lt;a href=&#34;https://deno.land/manual@v1.26.2/node&#34;&gt;a multi-pronged approach&lt;/a&gt; to the problem: from transforming library CDNs to a compatibility mode in Deno itself. It&amp;rsquo;s a little messy but at least it&amp;rsquo;s now possible to use many of the code that assumes Node is the runtime.&lt;/p&gt;
&lt;h2 id=&#34;today-i-see-reason-for-hope&#34;&gt;Today I see reason for hope&lt;/h2&gt;
&lt;p&gt;I keep seeing hints that Deno is being embraced by the JS community. I don&amp;rsquo;t know if what I&amp;rsquo;m seeing now is the result of the NPM compatibility effort or if there is something else. It could just be that a good project that hangs around long enough eventually gets some uptake.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I saw a &lt;a href=&#34;https://twitter.com/deno_land/status/1580356550966722560&#34;&gt;tweet&lt;/a&gt; the other day showing that Deno can build a Vite project. That&amp;rsquo;s a big deal. Remember the link above to a comment by Evan You saying it was too early to support Deno? It turns out it&amp;rsquo;s the Deno devs who made most of the effort to get Vite running, but that doesn&amp;rsquo;t matter. With Vite functional in Deno, all the dependent projects are suddenly much closer to supporting Deno. Many more good things can happen.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;While researching the above, I found that &lt;a href=&#34;https://astro.build/&#34;&gt;Astro.js&lt;/a&gt;, a new better Static Site Generator with Server Side Rendering capabilities, &lt;a href=&#34;https://docs.astro.build/en/guides/deploy/deno/&#34;&gt;officially supports Deno as an SSR runtime&lt;/a&gt;. This time it looks like it&amp;rsquo;s the Astro devs who put in the effort which shows devs backing Deno with their sweat and blood (OK, maybe not blood, not yet at least). It&amp;rsquo;s one thing to say &amp;ldquo;Deno looks cool&amp;rdquo;. It&amp;rsquo;s a different matter to release official support for Deno with libraries and docs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I just learned that &lt;a href=&#34;https://supabase.com/&#34;&gt;Supabase&lt;/a&gt;, a well funded and growing alternative to Firebase, chose Deno for its &lt;a href=&#34;https://supabase.com/docs/guides/functions&#34;&gt;Edge Functions&lt;/a&gt;. Again, more developer awareness and commitment already on display from the Supabase devs. It adds to the growing list of platforms that have built-in integration with Deno, such as &lt;a href=&#34;https://api.slack.com/future/functions/custom&#34;&gt;Slack&lt;/a&gt; and &lt;a href=&#34;https://docs.netlify.com/edge-functions/overview/&#34;&gt;Netlify&lt;/a&gt;. Anybody who wants to write functions for these platforms becomes a Deno developer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of these are significant events, but to me they show a trend that will only build in the future. They make me optimistic. Will the 2022 JS survey show an uptick of Deno developers? Time will tell, but I expect it will. I think Deno is turning the corner.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Unpacking Moxie&#39;s &#34;People don’t want to run their own servers, and never will&#34;</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2022/unpacking-nobody-wants-to-run-server-home/</link>
      <pubDate>Wed, 12 Jan 2022 14:27:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2022/unpacking-nobody-wants-to-run-server-home/</guid>
      <description>&lt;p&gt;Moxie Marlinspike&amp;rsquo;s &lt;a href=&#34;https://moxie.org/2022/01/07/web3-first-impressions.html&#34;&gt;article on web3&lt;/a&gt; has resulted in huge amounts of conversation online about various aspects of the web and decentralization. One aspect that got a lot of attention, and one that I paid particular attention to given my current &lt;a href=&#34;https://Dropserver.org&#34;&gt;project&lt;/a&gt; is this statement:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;People don’t want to run their own servers, and never will.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;— &lt;a href=&#34;https://moxie.org/2022/01/07/web3-first-impressions.html&#34;&gt;Moxie Marlinspike&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I want to unpack why I think it&amp;rsquo;s very challenging to get non-technical end-users to run a home server of some sort, yet it&amp;rsquo;s not something I&amp;rsquo;d qualify as &amp;ldquo;will never happen&amp;rdquo; either. Apart from the obvious folly of declaring that some tech thing will &amp;ldquo;never happen&amp;rdquo;, it already is happening in some ways, and we can learn a lot from that.&lt;/p&gt;
&lt;p&gt;Anecdote: during the recent holiday gathering one family member treated us to festive music by streaming it from their NAS back at home in an other State. This clearly counts as hosting from home, yet our DJ was not a hobbyist sysadmin by any means.&lt;/p&gt;
&lt;p&gt;So how does this happen? People can and will run a server at home, it&amp;rsquo;s just a matter of getting the package right and creating a product that is compelling, responds to a need, and lets them get on with their lives.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s go over a few aspects of what can make home serving widely successful or not.&lt;/p&gt;
&lt;h1 id=&#34;what-are-we-serving&#34;&gt;What are we serving?&lt;/h1&gt;
&lt;p&gt;First up, what is this server for? A &amp;ldquo;server&amp;rdquo; is a generic term that could imply a myriad services and many more protocols. All these are not created equal. If you create an offering that lets people serve from home, what you choose to serve will have a big impact on how successful your users are. Here&amp;rsquo;s an incomplete list of things you might want to serve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;files&lt;/li&gt;
&lt;li&gt;eth&lt;/li&gt;
&lt;li&gt;email&lt;/li&gt;
&lt;li&gt;HTTP&lt;/li&gt;
&lt;li&gt;chat&lt;/li&gt;
&lt;li&gt;tor&lt;/li&gt;
&lt;li&gt;ipfs&lt;/li&gt;
&lt;li&gt;etc&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given the comments I&amp;rsquo;m seeing it seems some people assume that just because you mention a server, that must mean a generic machine on which any of these protocols can potentially be served. This is one way to view things, but I think it&amp;rsquo;s more useful to realize some services and protocols lend themselves better to home serving than others, and winning this battle means picking the path of least resistance instead of fighting along all paths at once.&lt;/p&gt;
&lt;p&gt;Consider email for example. There are &lt;a href=&#34;https://mailinabox.email/&#34;&gt;software packages&lt;/a&gt; that include everything you need to host your own email server at home. However a common complaint is that emails sent from such a home server have a hard time landing in Gmail&amp;rsquo;s inbox. This is due to the overwhelming amount of email spam and email providers take any opportunity to label your email spam unless they can be sure it&amp;rsquo;s not. The burden of proof is on you, the sender, and its a big burden.&lt;/p&gt;
&lt;p&gt;Compare that with HTTP: it&amp;rsquo;s much easier to successfully serve a web page. Sure, it&amp;rsquo;s possible to &lt;a href=&#34;https://gomox.medium.com/google-safe-browsing-can-kill-your-startup-7d73c474b98d&#34;&gt;trigger various browser&amp;rsquo;s safe browsing filters&lt;/a&gt;, but if you manage to avoid serving anything nefarious there is no reason for a browser to block you. All you need is an IP, a domain name, and a TLS certificate (free from Letsencrypt) and all your friends can visit your site on any browser. Unlike email the burden of proof that allows your server to participate in the larger network is low.&lt;/p&gt;
&lt;p&gt;Other protocols and services may be just as easy and possibly even easier than HTTP, but others may just lead to disappointment.&lt;/p&gt;
&lt;h1 id=&#34;hx-mdash-hosting-experience&#34;&gt;HX — &amp;ldquo;Hosting Experience&amp;rdquo;&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;d agree with Moxie if he&amp;rsquo;d written &amp;ldquo;Nobody wants to run Apache, or anything that requires hand-editing a config file.&amp;rdquo; A server intended for end-users needs to completely rethink what &amp;ldquo;running a server&amp;rdquo; means, and reconsider the relationship between the user and the software, which is entirely different than for something managed by a sysadmin.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The server needs its iPhone moment&amp;rdquo;&lt;/p&gt;
&lt;p&gt;— &lt;a href=&#34;https://twitter.com/teleclimber/status/1479896130196439042&#34;&gt;me on Twitter&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Going further, such an end-user system would need to have all the characteristics of a modern wide-release computer product:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Good defaults and secure by default.&lt;/li&gt;
&lt;li&gt;Foot-guns removed, or buried deep enough that most users will never get to them.&lt;/li&gt;
&lt;li&gt;Assume bad intentions: users can&amp;rsquo;t know if an app is safe or not, so like a smartphone, limit what apps can do using permissions or capabilities and sandboxing.&lt;/li&gt;
&lt;li&gt;Easy to set up: plug in power, plug in ethernet, visit some local web page and click through the setup wizard. 10 minutes tops.&lt;/li&gt;
&lt;li&gt;Apps are installed with one click from an app catalog (or several, this doesn&amp;rsquo;t have to become a walled garden), and just work. They can auto-update too of course.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Good IOT hardware (yes I know there are a lot of bad ones), NAS and good home routers provide this experience already (to some degree at least) so it&amp;rsquo;s entirely within the realm of the possible, it just needs to be invented and executed well.&lt;/p&gt;
&lt;h1 id=&#34;why-are-we-serving&#34;&gt;Why are we serving?&lt;/h1&gt;
&lt;p&gt;The reason a NAS can be bought at any store that sells computer electronics is not because they embody the freedom to run your own services from your home, but because they respond to a need. People buy these things because people have a lot of files, some quite large, and they need to put them somewhere. Sure they could use Dropbox but that&amp;rsquo;s slow for large videos and it limits the number of connected devices. All cloud services cap or start charging after a certain amount of data is stored, and a local NAS with a decently sized disk will store far more than that and at far greater speeds when you&amp;rsquo;re at home.&lt;/p&gt;
&lt;p&gt;Buying another electronic box and taking the time to set it up is a high bar, so the value must be there. Sadly I have no clear answer on what services could run better from home than hosted by a 3rd party. But here are some general lines of thought:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cloud-based services can get expensive. They are usually paid for monthly or yearly, so they are a constant drain on the user&amp;rsquo;s wallet. A one-time purchase of hardware can be attractive in such a case. The problem is consumers do not pay for online services that can be replicated in a home server (think Netflix, Spotify) so apart from file storage there are few options here.&lt;/li&gt;
&lt;li&gt;On the flip side free services tend to have little respect for the user&amp;rsquo;s privacy. People are uncomfortable with what big tech companies do with their data, &lt;a href=&#34;https://www.pewresearch.org/internet/2019/11/15/americans-and-privacy-concerned-confused-and-feeling-lack-of-control-over-their-personal-information/&#34;&gt;but they aren&amp;rsquo;t doing much about it&lt;/a&gt;. That could shift one day, particularly if equally convenient solutions are available.&lt;/li&gt;
&lt;li&gt;Are services ruined by the constant search for growth? Most online services are VC-backed and are expected to show skyrocketing growth. This is often achieved in manipulative ways and is fatiguing to users. Again, it&amp;rsquo;s not enough to cause many to jump ship, but it&amp;rsquo;s another &amp;ldquo;con&amp;rdquo; to leverage against 3rd party services.&lt;/li&gt;
&lt;li&gt;Does the service work reliably? It&amp;rsquo;s tough providing a service for millions, especially if it&amp;rsquo;s free. Trying to max out machine use, sometimes performance suffers. I just tried sending a tab to my laptop using the Firefox send-tab service, and the tab arrived minutes after I needed it. A little personal service on a home server, which would almost certainly be under-utilized, might have forwarded the tab in the blink of an eye.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see I offer no slam-dunks, just vague possibilities.&lt;/p&gt;
&lt;h1 id=&#34;how-to-get-people-to-self-host-at-home&#34;&gt;How to Get People to Self-Host At Home&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Find a real need. There has to be &lt;em&gt;something&lt;/em&gt; that pulls in the potential self-hoster and makes them say &amp;ldquo;Yes, this is the better way to go for me&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Serve something that can actually work given current realities. If their friends aren&amp;rsquo;t going to receive their emails, what&amp;rsquo;s the point?&lt;/li&gt;
&lt;li&gt;Make it incredibly easy and safe. The iPhone of servers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these is hard on its own, yet you have to nail all three. Good luck!&lt;/p&gt;
&lt;p&gt;This is the reason I expect most &lt;a href=&#34;https://dropserver.org&#34;&gt;Dropserver&lt;/a&gt; users to rely on a cloud service to run Dropserver Apps. Later on, if it&amp;rsquo;s realistic, there could be a DS appliance, similar to what &lt;a href=&#34;https://www.crowdsupply.com/nabu-casa/home-assistant-yellow&#34;&gt;Home Assistant is doing&lt;/a&gt;. But that&amp;rsquo;s a long ways off.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Can An &#34;App Store&#34; Be The Solution to Funding Open Source Desktop Applications?</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2021/open-source-app-store/</link>
      <pubDate>Fri, 19 Feb 2021 11:32:00 -0800</pubDate>
      
      <guid>https://olivierforget.net/blog/2021/open-source-app-store/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been thinking a lot about open source lately, and wondering if there are alternative business models that could make it sustainable. This &amp;ldquo;app store&amp;rdquo; idea is one possibility.&lt;/p&gt;
&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;I always prefer using an open source application if I can find one that meets my needs. I am uneasy spending money on closed source solutions to any of my problems.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not the money that&amp;rsquo;s the issue. With an open source application I am more confident that there is no ill-intentioned code, and I can believe that even if development stalls, a sufficiently large user base will result in the application getting patches and other needed maintenance work, so that I can continue using it.&lt;/p&gt;
&lt;p&gt;Closed source programs often use proprietary file formats to strengthen the moat they have around the market. This prevents me from moving across programs easily, and can result in loss of data in some cases. Open source projects don&amp;rsquo;t care about moats, and try to be compatible with as many formats as possible. This is a huge benefit for users.&lt;/p&gt;
&lt;p&gt;Unfortunately, the flip side of open source is that it&amp;rsquo;s often &amp;ldquo;free as in beer&amp;rdquo; too, which means there are almost no funds for sustained development. The quality and usability of the application often suffers as a result. There is only so much unpaid or barely-paid open source developers and project maintainers can do.&lt;/p&gt;
&lt;p&gt;One segment of software where open source projects can fund their development successfully is software that run on servers. In that case, offering a paid hosted version is natural and can result in a steady flow of cash for the developers. See &lt;a href=&#34;https://plausible.io/open-source-website-analytics&#34;&gt;Plausible Analytics&lt;/a&gt; and &lt;a href=&#34;https://www.taiga.io/&#34;&gt;Taiga.io&lt;/a&gt; for example.&lt;/p&gt;
&lt;p&gt;For environments where software is installed locally, such as desktop operating systems, an &amp;ldquo;application store&amp;rdquo; could provide such a system for generating funds for a project.&lt;/p&gt;
&lt;h2 id=&#34;the-idea&#34;&gt;The Idea&lt;/h2&gt;
&lt;p&gt;The idea is to create an application store to significantly increase the appeal of open source applications for end users, and collect funds in exchange for some convenience and support.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how the store might work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The store would present applications in a modern and user-oriented way.&lt;/li&gt;
&lt;li&gt;The app store would have an integrated installer, so that an application can be installed in a single click.&lt;/li&gt;
&lt;li&gt;Applications would be &amp;ldquo;sold&amp;rdquo; even though the license would remain unchanged from the original code.&lt;/li&gt;
&lt;li&gt;The store would provide some level of support to buyers as a benefit.&lt;/li&gt;
&lt;li&gt;The store would use part of the funds to promote the products in the app store.&lt;/li&gt;
&lt;li&gt;The projects would receive funds to support their continuing development.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In a nutshell, the goal is to maximize the appeal of open source software to non-technical users by focusing on user experience. By doing this, we can expand the number of users (buyers) through promotion and PR, and therefore increase the funding for the projects.&lt;/p&gt;
&lt;p&gt;By the same token, the application store would relieve the open source developers from some of the less enjoyable tasks, like providing support to end users, and self-promotion.&lt;/p&gt;
&lt;h2 id=&#34;a-virtuous-feedback-loop&#34;&gt;A Virtuous Feedback Loop&lt;/h2&gt;
&lt;p&gt;The hope with this idea is that better funded open source projects are more likely to respond to the needs of the users. This in turn brings more users and more funds, which opens the possibility of doing even more great things in FOSS.&lt;/p&gt;
&lt;p&gt;However it may not be enough to hope. It&amp;rsquo;s possible the application store would have to be selective about which applications it offers. It&amp;rsquo;s important that users perceive the store as a purveyor of quality apps. A bad experience with a few apps and the user will not bother with the store anymore, nor will they recommend it to others.&lt;/p&gt;
&lt;p&gt;Setting minimum user experience requirements puts a demand on projects, but I think it would result in a healthier open source ecosystem. Have a look at the &lt;a href=&#34;https://plausible.io/&#34;&gt;Plausible&lt;/a&gt; site and product screenshots. Does Plausible look sharp and highly usable because it is well-funded, or is it that way because the developers know they won&amp;rsquo;t make as much money if they don&amp;rsquo;t &amp;ldquo;look the part&amp;rdquo;?&lt;/p&gt;
&lt;p&gt;Like the chicken and the egg you can debate endlessly about which came first, the point is they go together. You want users to part with their money? Spend your resources so your application looks sharp, is easy to use, and doesn&amp;rsquo;t waste your user&amp;rsquo;s time.&lt;/p&gt;
&lt;p&gt;This sounds harsh but the key to accepting this demand on projects is to think of how much funds could be available to open source projects if many non-technical users turned to FOSS for their needs. This can only happen with strong UX in the store and the applications.&lt;/p&gt;
&lt;p&gt;With all of that, I can imagine a world where such an app store is well established, widely distributed among end users and large numbers of developers are working part-time or even full-time on open source applications.&lt;/p&gt;
&lt;h2 id=&#34;what-about-cheaters&#34;&gt;What About &amp;ldquo;Cheaters&amp;rdquo;?&lt;/h2&gt;
&lt;p&gt;If the application store puts a price tag on open source licensed software, what prevents someone from simply bypassing the store and downloading the source or even the binaries on their own?&lt;/p&gt;
&lt;p&gt;Nothing.&lt;/p&gt;
&lt;p&gt;First, there are no &amp;ldquo;cheaters&amp;rdquo;. If someone can&amp;rsquo;t or won&amp;rsquo;t pay, it&amp;rsquo;s absolutely within their rights to obtain the software outside the store, and that&amp;rsquo;s perfectly fine.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t think that means the idea can&amp;rsquo;t work. Remember that the key is to broaden the pool of FOSS users far outside the world of tech-savvy folks. This means many of these people may prefer to part with a few dollars than venture outside the safety of a well regarded store.&lt;/p&gt;
&lt;p&gt;It will also be critical to make the benefits of using the store meaningful and the prices reasonable enough that a sufficient number of users don&amp;rsquo;t bother to get applications outside the store. For some users, knowing they&amp;rsquo;ll get some support from the store could be enough justification.&lt;/p&gt;
&lt;h2 id=&#34;can-it-work&#34;&gt;Can it Work?&lt;/h2&gt;
&lt;p&gt;I wrote above that I could imagine this working. The truth is my imagination is a well-oiled machine that can make many improbable things come true.&lt;/p&gt;
&lt;p&gt;I do think FOSS on desktop is stuck in a local maxima, and donations are not enough to truly alter the landscape.&lt;/p&gt;
&lt;p&gt;The only way to make open source sustainable, let alone thrive, is to make it attractive to regular people, yell about it on the rooftops, and stick a price tag on it.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dark Mode: Not For Me Either</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/dark-mode-not-for-me/</link>
      <pubDate>Fri, 12 Jun 2020 18:51:07 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/dark-mode-not-for-me/</guid>
      <description>&lt;p&gt;Kev Quirk managed to get himself on the &lt;a href=&#34;https://news.ycombinator.com/item?id=23495052&#34;&gt;front page of the orange site&lt;/a&gt; for his &lt;a href=&#34;https://kevq.uk/is-dark-mode-such-a-good-idea/&#34;&gt;post on Dark Mode&lt;/a&gt;. The topic even drew 511 comments, some of which seemed to take this as a personal affront to their lifestyle choices. Now you&amp;rsquo;ve done it.&lt;/p&gt;
&lt;p&gt;Kev&amp;rsquo;s post was well researched and I learned a few things from it. Interestingly none of the reasons he cites for using light mode are reasons why I go light.&lt;/p&gt;
&lt;p&gt;Here are the my two main gripes with Dark Mode:&lt;/p&gt;
&lt;h2 id=&#34;reflections&#34;&gt;Reflections&lt;/h2&gt;
&lt;p&gt;Do you know how to make a mirror? You put a dark color behind a glass surface. Dark mode is your device trying to be a mirror, and the result is reflections galore.&lt;/p&gt;
&lt;p&gt;For a while the Guardian app had a bug that caused all articles to render in dark mode even with it disabled. This meant I couldn&amp;rsquo;t read the news outside in the morning. The strongly lit surroundings would be reflected in the article I was trying to read, forcing me to work twice as hard to follow a line of text.&lt;/p&gt;
&lt;p&gt;Painful.&lt;/p&gt;
&lt;p&gt;This bug has mercifully been fixed, and while there are still reflections on the tablet screen, it&amp;rsquo;s far less distracting than before.&lt;/p&gt;
&lt;p&gt;Even in my office I seem to always catch sight of something behind me when looking at a dark UI on my iMac. It&amp;rsquo;s distracting for no good reason.&lt;/p&gt;
&lt;p&gt;It makes me think of those fancy computers in SciFi flicks that have a transparent screen. Cool for a movie prop, but terrible UX in reality.&lt;/p&gt;
&lt;p&gt;Some will argue dark mode should be used when it&amp;rsquo;s, you know, dark. But unless you&amp;rsquo;re in a completely dark room I don&amp;rsquo;t see the point.  And if you are you should probably put the phone down and &lt;a href=&#34;https://olivierforget.net/blog/2020/dont-miss-your-sleep-train/&#34;&gt;go to sleep&lt;/a&gt; anyways. Sorry to preach.&lt;/p&gt;
&lt;h2 id=&#34;ghosts-of-readings-past&#34;&gt;Ghosts of Readings Past&lt;/h2&gt;
&lt;p&gt;There may be something wrong with my eyes but after reading light text on dark background the text lingers in my vision and dances around when I look at something else. It&amp;rsquo;s an uncomfortable feeling.&lt;/p&gt;
&lt;p&gt;A lot of text editors come with dark themes enabled by default. I tried it for a while but I just can&amp;rsquo;t stand it. Ghosts of code everywhere, I feel like I&amp;rsquo;m going crazy.&lt;/p&gt;
&lt;p&gt;I realize I may have sensitive eyes. My wife and I play dimmer wars all the time: she turns them up and I turn them down.&lt;/p&gt;
&lt;p&gt;I dim the screen on my iMac when my office gets dark. It&amp;rsquo;s very effective at reducing strain and is far less jarring than inverting of the brightness spectrum.&lt;/p&gt;
&lt;h2 id=&#34;keep-it-light&#34;&gt;Keep it Light&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t care if people like dark mode. They may be biologically predisposed to enjoy it, they may work in a cave, and I&amp;rsquo;ll give them some credit: they probably turn it off when reading in sunlight.&lt;/p&gt;
&lt;p&gt;But for me it&amp;rsquo;s light mode all the way.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was post 23 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Proprietary Services Fulfill The Open Web&#39;s Dream</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/proprietary-open-web-dreams/</link>
      <pubDate>Tue, 02 Jun 2020 20:47:07 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/proprietary-open-web-dreams/</guid>
      <description>&lt;p&gt;Last night, during the protests for #BlackLivesMatter, there was an urgent need to spread information to participants and others trying to help.&lt;/p&gt;
&lt;p&gt;In an effort to get that information out, people reached for tools that they could use quickly and effectively.&lt;/p&gt;
&lt;p&gt;One of these tools is &lt;a href=&#34;https://carrd.co&#34;&gt;Carrd&lt;/a&gt;, an online website builder that makes single-page websites or very simple multi-page sites. It is run by a solo founder-developer.&lt;/p&gt;
&lt;p&gt;Carrd is great. If you want to put a single-page or other simple website online, it gets the job done fast and well. It&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Freemium&#34;&gt;freemium&lt;/a&gt;, which means you can put something online without reaching for your credit card.&lt;/p&gt;
&lt;p&gt;When I look at the pages that were built using Carrd for the protests, like &lt;a href=&#34;https://blacklivesmatters.carrd.co/&#34;&gt;blacklivesmatters.carrd.co&lt;/a&gt; and &lt;a href=&#34;https://blmprotest.carrd.co/&#34;&gt;blmprotest.carrd.co&lt;/a&gt;, I immediately think that this is what the open web is for: the ability for anybody to create and publish content that is accessible via a URL.&lt;/p&gt;
&lt;p&gt;And yet, without the support of a service like Carrd, it&amp;rsquo;s oh so hard.&lt;/p&gt;
&lt;h1 id=&#34;the-potential-problem&#34;&gt;The Potential Problem&lt;/h1&gt;
&lt;p&gt;Protesters got lucky this time. Carrd creator &lt;a href=&#34;https://twitter.com/ajlkn&#34;&gt;AJ&lt;/a&gt; runs his service well (Billie Eilish put a link to a Carrd in her &lt;a href=&#34;https://www.instagram.com/billieeilish/&#34;&gt;Instagram bio&lt;/a&gt;, and his servers are still standing) and doesn&amp;rsquo;t seem to have any desire to stop protesters from using his service.&lt;/p&gt;
&lt;p&gt;Imagine an alternative scenario: someone builds a slick service that becomes popular at a time of crisis, except instead of the creator being on the right side of history, they are flatly in the wrong?&lt;/p&gt;
&lt;p&gt;How much power would that person have over a movement? They could delete the accounts and pages, they could redirect the visitors to pages showing completely opposite views, they could even steal the login credentials of those users and see if maybe they reuse passwords on different services.&lt;/p&gt;
&lt;p&gt;Who knows what an unscrupulous and upset service owner might do. The situation in the US for the last few years shows that saying &amp;ldquo;that will never happen&amp;rdquo; is not good enough. Some day, it will happen.&lt;/p&gt;
&lt;h1 id=&#34;the-closed-writable-web&#34;&gt;The Closed Writable Web&lt;/h1&gt;
&lt;p&gt;The web is an open technology. The communication protocols are owned by no-one, &amp;ldquo;free&amp;rdquo; to use by all. There are no licensing agreements to sign before making an HTTP request, no royalties to pay for that &lt;code&gt;&amp;lt;HTML&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;
&lt;p&gt;This openness is freedom and independence. Any web browser can load any webpage and any accessible url, regardless of who wrote, and who approves or disapproves of it.&lt;/p&gt;
&lt;p&gt;When it comes to consuming content online, we&amp;rsquo;re in a pretty good spot. In the US, &lt;a href=&#34;https://www.pewresearch.org/fact-tank/2019/04/22/some-americans-dont-use-the-internet-who-are-they/&#34;&gt;90% of the population&lt;/a&gt; can visit any site, from the largest internet properties to the smallest of independent web publishers.&lt;/p&gt;
&lt;p&gt;But when it comes to creating content, participating in the read-write web, there is one big problem: the protocols are open, but the technology is hard to use.&lt;/p&gt;
&lt;p&gt;HTML was supposed to be easy enough to write for anybody to do it. But that is 1990s thinking. There is no way someone is going to learn HTML and CSS enough to create a decent looking page by today&amp;rsquo;s standards unless they&amp;rsquo;re looking to learn the craft for hobby or professional advancement.&lt;/p&gt;
&lt;p&gt;Then there is the hosting. You can fumble your way through the maze of &lt;a href=&#34;https://aws.amazon.com/&#34;&gt;AWS&lt;/a&gt;, or their &lt;a href=&#34;https://cloud.google.com/&#34;&gt;behemoth&lt;/a&gt; &lt;a href=&#34;https://azure.microsoft.com/en-us/&#34;&gt;brethren&lt;/a&gt;, or you can reach for something lighter like &lt;a href=&#34;https://www.netlify.com/&#34;&gt;Netlify&lt;/a&gt;. However for any of these you choose, you have to learn how &lt;em&gt;they&lt;/em&gt; work and adapt your stuff to &lt;em&gt;their&lt;/em&gt; requirements.&lt;/p&gt;
&lt;p&gt;You could also stick to an open source stack, and install a Linux server on a virtual machine and secure it, but now you&amp;rsquo;ve truly lost the non-tech folks.&lt;/p&gt;
&lt;p&gt;The writable web is open for tech geeks, closed and proprietary for everyone else.&lt;/p&gt;
&lt;h1 id=&#34;some-exceptions&#34;&gt;Some Exceptions&lt;/h1&gt;
&lt;p&gt;As I was writing this I realized there were some partial exceptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WordPress is &lt;a href=&#34;https://wordpress.org/&#34;&gt;open source&lt;/a&gt; and is a de-facto standard for online publishing. You can host your own or go with a service provider. It&amp;rsquo;s also rather heavy and not friendly to very occasional users.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Mastodon_(software)&#34;&gt;Mastodon&lt;/a&gt; and other fediverse projects democratize online publishing, but there is a difference between &amp;ldquo;joining the fediverse&amp;rdquo; and just publishing something at a URL.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://dat.foundation/&#34;&gt;Dat protocol&lt;/a&gt; is a work-in-progress, but they are espousing the read/write capabilities in their &lt;a href=&#34;https://beakerbrowser.com/&#34;&gt;Beaker browser&lt;/a&gt; from the very beginning, a good sign.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of these address the need to just be able to publish something simple online with a truly small investment in time and effort by a non-technical user.&lt;/p&gt;
&lt;h1 id=&#34;a-new-standard&#34;&gt;A New Standard?&lt;/h1&gt;
&lt;p&gt;There could be a set of standards that address the need for writing and publishing websites, or at least static sites. There is a &lt;a href=&#34;https://www.w3.org/community/rww/&#34;&gt;Read/Write Web Community Group&lt;/a&gt; in the W3C, but it&amp;rsquo;s basically dead at this point.&lt;/p&gt;
&lt;p&gt;If this were revived, the focus should be on ease-of-use. The idea would be to bring static site publishing closer to how content consumption works: make it so 90% of a developed country can do it, and do it without lock-in or proprietary elements.&lt;/p&gt;
&lt;p&gt;I suspect webpage builders would become phone and desktop apps, and hosts would serve static content. The standard would be the glue between the two: the protocol that lets the builder push new HTML and CSS and other assets to the host.&lt;/p&gt;
&lt;p&gt;There would need to be a standard for DNS management since owning your domain is a key element of independence. Entering A and AAAA records and CNAMES and TXT records is not fun.&lt;/p&gt;
&lt;p&gt;Something to think about. In the meantime, visit &lt;a href=&#34;https://blacklivesmatters.carrd.co/&#34;&gt;blacklivesmatters.carrd.co&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was post 22 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>SpaceX Crew Dragon Launch and NASA&#39;s Gulfstream-IIIs</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/</link>
      <pubDate>Sat, 30 May 2020 19:41:07 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/</guid>
      <description>&lt;p&gt;I was watching news coverage before SpaceX&amp;rsquo;s launch of NASA astronauts Bob Behnken and Doug Hurley when I noticed something that took me back to the very end of my aerospace career.&lt;/p&gt;
&lt;p&gt;Astronauts usually live in Texas near NASA&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Johnson_Space_Center&#34;&gt;JSC&lt;/a&gt;, and fly to &lt;a href=&#34;https://en.wikipedia.org/wiki/Kennedy_Space_Center&#34;&gt;KSC&lt;/a&gt; (or Russia) when it&amp;rsquo;s time to launch. During the Shuttle era they would fly in &lt;a href=&#34;https://www.nasa.gov/mission_pages/shuttle/flyout/t38flyout.html&#34;&gt;T-38&lt;/a&gt;s from Texas. For this trip they took one of NASA&amp;rsquo;s Gulfstreams, though it&amp;rsquo;s unclear why. Perhaps it&amp;rsquo;s because of the pandemic, or maybe it&amp;rsquo;s because the Crew Dragon interior has been compared to that of a business jet, and you might as well fly in on something that feels like your spacecraft.&lt;/p&gt;
&lt;p&gt;The thing that jumped out at me about Bob and Doug&amp;rsquo;s ride was the hard-point under the middle of the wing. Boy did that look familiar.&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/interview-hardpoint_hu6e2995ffa8c5a663ddf26e6d59ad6bab_98945_756x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/interview-hardpoint_hu6e2995ffa8c5a663ddf26e6d59ad6bab_98945_756x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/interview-hardpoint_hu6e2995ffa8c5a663ddf26e6d59ad6bab_98945_1513x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;&lt;em&gt;Hardpoint under the wing in the blue circle. Photo by Emre Kelly, from this &lt;a href=&#34;https://www.palmbeachpost.com/news/20200521/ready-to-make-history-on-spacexs-crew-dragon-nasa-astronauts-touch-down-at-ksc&#34;&gt;article&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;rewind&#34;&gt;Rewind&lt;/h1&gt;
&lt;p&gt;Back in the mid-2000s I quit my job at &lt;a href=&#34;https://en.wikipedia.org/wiki/XCOR_Aerospace&#34;&gt;XCOR Aerospace&lt;/a&gt; in Mojave, CA and moved to Los Angeles where I worked at an aircraft engineering firm. Our specialty was aircraft modifications. We did the engineering work and supporting documentation for certifying modifications of aircraft.&lt;/p&gt;
&lt;p&gt;Our work ranged from simple mods: some rich private jet owner is upgrading the navigation avionics of their jet, so we would do the engineering work to modify the aircraft with a better external GPS antenna.&lt;/p&gt;
&lt;p&gt;Other work was more demanding. We would usually be sub-sub-contractors on these, but they involved some rather drastic modifications of large aircraft for testing purposes. We helped modify a 737 into a &lt;a href=&#34;https://en.wikipedia.org/wiki/Lockheed_Martin_CATBird&#34;&gt;F-35 avionics testbed&lt;/a&gt;, an A-3 into a &lt;a href=&#34;https://www.airliners.net/photo/Raytheon-Flight-Test-Operations/Douglas-NTA-3B-Skywarrior/1133465&#34;&gt;radar testbed&lt;/a&gt;, etc&amp;hellip;&lt;/p&gt;
&lt;h1 id=&#34;pin-the-pod-on-the-gulfstream&#34;&gt;Pin the Pod on the Gulfstream&lt;/h1&gt;
&lt;p&gt;One project involved hanging a pod underneath a Gulfstream G-III for NASA. For simple modifications a drive to the airport and a quick look at the aircraft armed with a digital camera, a ruler, and a drill was all we we needed to sort out a small antenna installation. (Yes, a drill. Sometimes you can&amp;rsquo;t know the skin thickness where you want your antenna installed, so the only solution is to drill a hole in the airframe where the antenna is going to be, and &lt;em&gt;then&lt;/em&gt; do the engineering to fix it all up.)&lt;/p&gt;
&lt;p&gt;But hanging a big pod under a the middle of the wing, which happens to be where the main fuel tank is takes a bit more work. Someone had to spend a large amount of time reclined in a low chair underneath the wing of that plane with a ruler and a notebook. That person measured and counted every line of rivets, and then re-measured again just to be sure. That person was me.&lt;/p&gt;
&lt;p&gt;It sounds like hell but I loved it. Proximity to aircraft was my favorite perk of being an aerospace engineer. So I indulged in the task, and probably measured a third time just because it was better than being in the office. I also crawled all over the tail cone to prepare for the installation of a ventral tail fin to compensate for the lost stability of the hanging pod.&lt;/p&gt;
&lt;p&gt;After all the wing measurements were done I sat at my workstation and cranked out an engineering model of the center of the wing. It was tedious work that had to be done as accurately as possible. We used the measurements of what was visible in the aircraft and cross-referenced engineering drawings to ensure that the model we were building represented as much as possible the details of the aircraft we were modifying. No drilling holes willy-nilly through the fuel tank!&lt;/p&gt;
&lt;p&gt;After building the model we&amp;rsquo;d measure stresses in the structure under virtual loads for a standard configuration, and then measure forces with the pod hanging. The difference would tell us how much reinforcements were needed, and where.&lt;/p&gt;
&lt;p&gt;Suffice it to say that aircraft was my professional obsession for a few months. It&amp;rsquo;s also the last aerospace engineering project I ever worked on and I wouldn&amp;rsquo;t see it to the end. I quit that Spring and started my own software biz.&lt;/p&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/dryden-gulfstream-pod_hubbd114c3179e264116da19ea5520a5c4_121204_577x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/dryden-gulfstream-pod_hubbd114c3179e264116da19ea5520a5c4_121204_577x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/dryden-gulfstream-pod_hubbd114c3179e264116da19ea5520a5c4_121204_1155x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;&lt;em&gt;NASA-Dryden&amp;rsquo;s G-III after the mod, with pod hanging and that big angular fin under the tail. &lt;a href=&#34;https://www.dfrc.nasa.gov/Gallery/Photo/C-20A/Medium/ED07-0042-09.jpg&#34;&gt;NASA Photo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;bob-and-dougs-excellent-ride&#34;&gt;Bob and Doug&amp;rsquo;s Excellent Ride&lt;/h1&gt;
&lt;p&gt;When I saw the hard-point under the G-III at KSC while Bob and Doug were giving their interview I thought for a while that it might be the one that I had worked on. How many G-IIIs could there be with a center hard point? It turns out there are at least two. I found out that JSC also has a G-III and it too was modified to carry a similar pod under its wing a few years after the mod I worked on.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/JSC-G-III-pod_huc10cdbefb1cff1dd93b5cb70d8dd8e7c_510423_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/JSC-G-III-pod_huc10cdbefb1cff1dd93b5cb70d8dd8e7c_510423_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/spacex-crew-dragon-nasa-gulfstream/JSC-G-III-pod_huc10cdbefb1cff1dd93b5cb70d8dd8e7c_510423_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;&lt;em&gt;JSC&amp;rsquo;s G-III with pod hanging. NASA photo from &lt;a href=&#34;https://www.nasa.gov/centers/dryden/Features/uavsar_installed_for_airmoss_study.html&#34;&gt;this page&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Apart from ferrying astronauts, this plane serves in NASA&amp;rsquo;s airborne science program. It&amp;rsquo;s similar to the Earth-observing stuff they do from space, but they do it from within the atmosphere.&lt;/p&gt;
&lt;p&gt;The pod is made by &lt;a href=&#34;https://www.jpl.nasa.gov/&#34;&gt;JPL&lt;/a&gt; and is called UAVSAR. It consists of a synthetic aperture radar that can make a very detailed map of the ground below. A complete explanation &lt;a href=&#34;https://uavsar.jpl.nasa.gov/education/what-is-uavsar.html&#34;&gt;is here&lt;/a&gt;. A big part of the instrument&amp;rsquo;s mission is to overfly natural disaster areas to learn as much as possible about the event.&lt;/p&gt;
&lt;p&gt;When carried above a disaster area by one of NASA&amp;rsquo;s modified G-IIIs, the UAVSAR pod has helped better understand &lt;a href=&#34;https://www.nasa.gov/centers/dryden/Features/baja_quake_photo.html&#34;&gt;earthquakes&lt;/a&gt;, &lt;a href=&#34;https://www.nasa.gov/topics/earth/features/slumgullion.html&#34;&gt;landslides&lt;/a&gt;, &lt;a href=&#34;https://www.nasa.gov/topics/earth/features/G-III_status_01_17_12.html&#34;&gt;volcanos&lt;/a&gt;, &lt;a href=&#34;https://disasters.nasa.gov/hurricane-florence-2018/hurricane-florence-resources-uavsar&#34;&gt;hurricane damage&lt;/a&gt;, and &lt;a href=&#34;https://www.nasa.gov/topics/earth/features/earth20121025.html&#34;&gt;oil spills&lt;/a&gt; among others. Here&amp;rsquo;s a video showing the NASA team doing the survey of the &lt;a href=&#34;https://www.youtube.com/watch?v=zOgFAcWi0go&#34;&gt;gulf oil spill&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Bob and Doug are floating in the SpaceX Crew Dragon as I write this, but the ride they took to get to the rocket shows a lesser-known but still cool and definitely important part of NASA&amp;rsquo;s mission. And I was glad to have been a tiny part of it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was post 21 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Our Web Versus Search Engines</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/search-engines-versus-web/</link>
      <pubDate>Mon, 25 May 2020 20:41:07 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/search-engines-versus-web/</guid>
      <description>&lt;p&gt;Sometimes it seems like search engines are amazing. And yes, for a lot of questions, they do get us an answer quickly.&lt;/p&gt;
&lt;p&gt;But other times search engines fail me. For example I might search for pages that talk about two topics together, and I&amp;rsquo;ll get results for a popular page about the first topic that happens to have a link to a page on the second topic in its navigation menu.&lt;/p&gt;
&lt;p&gt;For a long time Google would return pages that were written &lt;em&gt;in&lt;/em&gt; PHP for queries &lt;em&gt;about&lt;/em&gt; PHP, presumably because the URL ended in &amp;ldquo;.php&amp;rdquo; and that matched with my query: &amp;ldquo;PHP how to append an array&amp;rdquo;. Not useful, Google.&lt;/p&gt;
&lt;p&gt;They have other quirks, like just today while trying to write proper asynchronous code in TypeScript I submitted dozens of queries, one of which was &amp;ldquo;&lt;a href=&#34;https://www.google.com/search?hl=en&amp;amp;q=javascript%20emit%20occasional%20result&#34;&gt;javascript emit occasional result&lt;/a&gt;&amp;rdquo;. Not a great query but I was desperate. For some reason three of the first five results are for books about utterly unrelated topics. The first result is a book on nanoscience, another is on marine fauna. The fourth is on galaxy formations so I assume this is Google&amp;rsquo;s &lt;a href=&#34;https://knowyourmeme.com/memes/galaxy-brain&#34;&gt;galaxy brain&lt;/a&gt; search results.&lt;/p&gt;
&lt;p&gt;We all know search engines have limitations, but the bigger problems lie deeper.&lt;/p&gt;
&lt;h1 id=&#34;algorithms-are-abused&#34;&gt;Algorithms Are Abused&lt;/h1&gt;
&lt;p&gt;When the algorithm isn&amp;rsquo;t tripping over a simple query, other actors are determined to make it trip in their favor.&lt;/p&gt;
&lt;p&gt;Everyone wants to be #1 on search results. Any aspect of any algorithm will be abused to get higher in the results pages.&lt;/p&gt;
&lt;p&gt;Google is famous for inventing the &lt;a href=&#34;https://en.wikipedia.org/wiki/PageRank&#34;&gt;PageRank algorithm&lt;/a&gt;. The number of pages linking to a page is a signal for how helpful that page is, or at least how popular.&lt;/p&gt;
&lt;p&gt;But as soon as web properties figured this out, the bazaar of back-link bat-shittery began. How many times have you gotten (or sent 😲) an email asking for a link to a page? Are bots leaving random word salad comments in your forums with a few links over and over again? Thanks PageRank!&lt;/p&gt;
&lt;p&gt;Google tries to penalize abusers, and it succeeds over time. But there are always new aspects to its algorithms, and the SEO crowd is a crafty bunch so the PhDs in Mountain View are always playing catch-up.&lt;/p&gt;
&lt;p&gt;The reality today is results are littered with pages that should not be there: they tricked the algo and won.&lt;/p&gt;
&lt;p&gt;Have you ever clicked on a promising search result, read through the content, and was left with the impression you just ingested the spilled contents of a word bag related to your query? There are sentences, and they make sense, yet so little meaning or insight is revealed? The site is often nice and usable and looks like every other helpful site out there, yet lacks a true personality? The only invariant is that there are a bunch of links sprinkled throughout, all pointing to the same commercial site. Uh huh. So much HTML theater for a measly click!&lt;/p&gt;
&lt;p&gt;Thanks, search algorithms.&lt;/p&gt;
&lt;h1 id=&#34;the-algorithm-shapes-our-web&#34;&gt;The Algorithm Shapes Our Web&lt;/h1&gt;
&lt;p&gt;It&amp;rsquo;s bad enough sifting through spammy search results to get a good one. Sometimes even the good ones are compromised by a desire to increase search visitors.&lt;/p&gt;
&lt;p&gt;A few years ago Google updated its algorithm, and a bunch of people saw their search traffic drop. SEO folks figured out that pages that were a bit old but had a date on them weren&amp;rsquo;t being shown anymore. The way to recover traffic? Just &lt;a href=&#34;https://www.shoutmeloud.com/how-to-recover-from-google-panda-effect.html&#34;&gt;remove the date from your posts&lt;/a&gt;. Easy peasy!&lt;/p&gt;
&lt;p&gt;Have you ever landed on a technical blog, found the content promising but needed to know how old it was before committing to reading it? Tech moves fast, and reading a post that is many years old can be misleading. So you scroll all the way up and down to find the date, only to realize there is none on the page. &lt;a href=&#34;https://twitter.com/SaraSoueidan/status/1264945217318330369&#34;&gt;Frustration&lt;/a&gt;! The reason? It&amp;rsquo;s likely the blogger heard that removing post dates would increase their search visitors.&lt;/p&gt;
&lt;p&gt;Google has since corrected this, but not everybody is up to speed, so dates are still missing here and there. Sigh, and thanks again search algorithms.&lt;/p&gt;
&lt;h1 id=&#34;the-algorithm-shapes-our-view-of-our-web&#34;&gt;The Algorithm Shapes &lt;em&gt;Our View&lt;/em&gt; Of Our Web&lt;/h1&gt;
&lt;p&gt;Just the other day a question on the orange site ranked highly and got lots of positive feedback: &lt;a href=&#34;https://news.ycombinator.com/item?id=23202850&#34;&gt;Ask HN: Is there a search engine which excludes the world&amp;rsquo;s biggest websites?&lt;/a&gt;. It seems Google favors pages from large internet properties, and tends to leave small sites out of the results.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s clear that people (or HN users at least) feel they are missing out on part of the web. When every query is answered by one of very few search engines, we are viewing the web&amp;rsquo;s content through a filter that has its own stake holders who are not us.&lt;/p&gt;
&lt;p&gt;There is the web and there is the web we see through Google. How much are we missing?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s like having an intergalactic spaceship that can take you anywhere in the universe in the blink of an eye, but its radar can only detect large planets with the proper arrangement of keywords.&lt;/p&gt;
&lt;h1 id=&#34;we-need-something-new&#34;&gt;We Need Something New&lt;/h1&gt;
&lt;p&gt;I want a new paradigm for finding stuff online. I want something that depends less on algorithms and more on humans. I want results that make sense to me and other humans like me, even if there are fewer and it takes a bit longer. I am no longer blown away by 60,000 results in 0.000003 seconds. Blow me away with five results that are outstanding. I&amp;rsquo;ll wait.&lt;/p&gt;
&lt;p&gt;I know we can&amp;rsquo;t completely replace the might of Google, but just like I try searching on DuckDuckGo before I search on Google, I want to search on ? before I search on DDG and Google, whatever &amp;ldquo;?&amp;rdquo; is.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s search for our &amp;ldquo;?&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was post 20 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Thoughts on Sandstorm</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/thoughts-sandstorm/</link>
      <pubDate>Wed, 20 May 2020 18:41:07 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/thoughts-sandstorm/</guid>
      <description>&lt;p&gt;When I tell people about my side-project to create a server that makes it safe and easy to run your own web apps, some say I should check out &lt;a href=&#34;https://sandstorm.io/&#34;&gt;Sandstorm&lt;/a&gt;. I was a (small) backer of Sandstorm&amp;rsquo;s &lt;a href=&#34;https://www.indiegogo.com/projects/sandstorm-io-personal-cloud-platform/&#34;&gt;IndieGogo&lt;/a&gt; but I&amp;rsquo;ve been disappointed by how it worked out.&lt;/p&gt;
&lt;p&gt;I think the idea of safely and easily hosting your own server-side applications and services is important for the internet to remain free. I thought this then and I still think it now.&lt;/p&gt;
&lt;p&gt;Sandstorm is ambitious, and has a lot of good things going for it. However, development and adoption has been slow and the company behind it has &lt;a href=&#34;https://sandstorm.io/news/2017-02-06-sandstorm-returning-to-community-roots&#34;&gt;shut down&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some design choices in Sandstorm have made it harder for the platform to thrive. Here is how I see it:&lt;/p&gt;
&lt;h1 id=&#34;coerce-old-apps-into-a-new-system&#34;&gt;Coerce Old Apps Into A New System&lt;/h1&gt;
&lt;p&gt;Sandstorm&amp;rsquo;s &amp;ldquo;&lt;a href=&#34;https://sandstorm.io/how-it-works&#34;&gt;Grains&lt;/a&gt;&amp;rdquo; make it technically possible to run just about any existing application inside Sandstorm, since they are using Linux container technology. But unlike Docker, which also uses Linux containers, apps on sandstorm usually need to be modified.&lt;/p&gt;
&lt;p&gt;For example, a web-app on Sandstorm should not provide a login and user management service since the platform provides it. Since most web-apps include this as an essential part of the system, it means ripping it out or somehow bypassing it to work with Sandstorm.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s hard work going into an existing codebase to rip out one of its primary elements. Many open source web-apps are old, and old code is even harder to muck about with. Login is just one thing, Sandstorm also has its own &lt;a href=&#34;https://docs.sandstorm.io/en/latest/developing/powerbox/&#34;&gt;data sharing paradigm&lt;/a&gt; and apps have to be altered for that too.&lt;/p&gt;
&lt;p&gt;Another issue is that developers of typical standalone web-apps assume the app is started when the host starts, and runs continuously until the server needs to be rebooted. There is no reason to optimize startup time, and some apps take seconds to start. However on Sandstorm the grains are only started when the user actively summons them. The result: &lt;a href=&#34;https://github.com/sandstorm-io/sandstorm/issues/2975#issuecomment-325166256&#34;&gt;the user waits&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;not-easy-to-create-a-new-app&#34;&gt;Not Easy to Create a New App&lt;/h1&gt;
&lt;p&gt;While it&amp;rsquo;s work to modify an app to run on Sandstorm, that same container tech makes it intimidating to create an app &lt;em&gt;for&lt;/em&gt; Sandstorm in the first place. Have a look at &lt;a href=&#34;https://docs.sandstorm.io/en/latest/vagrant-spk/packaging-tutorial/&#34;&gt;this page&lt;/a&gt; that explains how do get started with a simple PHP app. Yikes! It&amp;rsquo;s Ok if you&amp;rsquo;re regular container slinger, but otherwise it seems kind of steep.&lt;/p&gt;
&lt;p&gt;Sandstorm&amp;rsquo;s approach puts it in an odd spot: while it has the advantage of being able to run almost any app thanks to its container tech, it&amp;rsquo;s a lot more work for devs to make their web-based application code run on Sandstorm than on Docker (or any other container runtime), so few have done so. But it&amp;rsquo;s also hard to create an app from scratch.&lt;/p&gt;
&lt;p&gt;So, steep hill to climb if you&amp;rsquo;re forking an app to run on Sandstorm and steep hill to climb if you&amp;rsquo;re creating one from scratch. As a result, Sandstorm&amp;rsquo;s &lt;a href=&#34;https://apps.sandstorm.io/&#34;&gt;app market&lt;/a&gt; had a very modest number of apps, most of which were a few (or many) releases behind their source, some of which were slow to start, and in my experience had a few bugs. Populating an app store for a new platform is always a hard problem, but Sandstorm&amp;rsquo;s design made it even harder.&lt;/p&gt;
&lt;h1 id=&#34;not-really-good-at-services&#34;&gt;Not Really Good At Services&lt;/h1&gt;
&lt;p&gt;This one is the kicker. Sandstorm works well with applications that you tend to sit in front of. It&amp;rsquo;s not great for situation where you regularly serve dynamic requests. See &lt;a href=&#34;https://docs.sandstorm.io/en/latest/developing/web-publishing/#why-only-static-content&#34;&gt;this page&lt;/a&gt; (the section at the bottom titled &amp;ldquo;Why only static content&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;Sandstorm also has an issue with URLs that are not clean looking, and hooking up a service to a nice sub-domain is still &lt;a href=&#34;https://news.ycombinator.com/item?id=22236975&#34;&gt;eluding the platform&lt;/a&gt;, apparently. It&amp;rsquo;s hard to feel like your service is &amp;ldquo;of the web&amp;rdquo; if it can&amp;rsquo;t simply be connected to a clean domain.&lt;/p&gt;
&lt;p&gt;To me the very essence of an online service is to serve dynamic requests. Quite possibly a lot of them, coming from many different clients at any random time with potentially different authorizations. Services should be reachable at a nice clean URL, respond quickly even if not used often, not bring the host to its knees if under some load, and take up almost no resources when not in use.&lt;/p&gt;
&lt;h1 id=&#34;the-future-of-self-hosting-web-apps&#34;&gt;The Future of Self-Hosting Web Apps&lt;/h1&gt;
&lt;p&gt;There are other pain points for Sandstorm: the user interface, the unfamiliar and complex concepts for users, etc&amp;hellip; Some of this is typical of a very ambitious project: niceties like the UI and making it simple are left for later. This &lt;a href=&#34;https://news.ycombinator.com/item?id=13582942&#34;&gt;discussion&lt;/a&gt; illustrates a few of these problems, along with a large number of comments from people who were justifiably saddened that Sandstorm was not taking off.&lt;/p&gt;
&lt;p&gt;Sandstorm is still evolving as a community project and may yet gain enough speed to take off. I certainly am not writing it off. But I think there is room for other approaches, with different trade-offs and different priorities.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was post 19 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The End of the Before-Times</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/last-before-times/</link>
      <pubDate>Mon, 18 May 2020 12:50:07 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/last-before-times/</guid>
      <description>&lt;p&gt;Amused by &lt;a href=&#34;https://www.theguardian.com/world/2020/may/18/monica-lewinsky-among-thousands-to-share-last-normal-photo&#34;&gt;this Guardian article&lt;/a&gt;, which draws from &lt;a href=&#34;https://twitter.com/RobynVinter/status/1261604559597830145&#34;&gt;this tweet&lt;/a&gt;, which is inspired by &lt;a href=&#34;https://www.bbc.com/news/uk-52622673&#34;&gt;this BBC piece&lt;/a&gt;, here is the last picture on my phone that represents normal life, or as we&amp;rsquo;ll soon know it: the before-time.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/last-before-times/j-tree-sunrise_hud2457c3ed67155c9aa670049b63c0a3f_5145761_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/last-before-times/j-tree-sunrise_hud2457c3ed67155c9aa670049b63c0a3f_5145761_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/last-before-times/j-tree-sunrise_hud2457c3ed67155c9aa670049b63c0a3f_5145761_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;This is sunrise in &lt;a href=&#34;https://en.wikipedia.org/wiki/Joshua_Tree_National_Park&#34;&gt;Joshua Tree&lt;/a&gt;, California on March 8. We had met some friends for a one-nighter camping trip. The virus was in the news a lot by then, and we greeted each other by &lt;a href=&#34;https://twitter.com/V_actually/status/1233785527788285953&#34;&gt;kicking boots&lt;/a&gt;. It was mostly for laughs though, we hugged too and the kids played together. Social distancing was not yet a thing.&lt;/p&gt;
&lt;p&gt;Soon after, we moved into our freshly remodeled new home, just squeezing by as California and LA County announced lockdown measures. We got all our stuff into the house, shut the door, and haven&amp;rsquo;t been very far since.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s another photo, this one is the sunset of the previous evening.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/last-before-times/j-tree-sunset_hu381b327997bb32b3d5c9103315cc3688_3057964_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/last-before-times/j-tree-sunset_hu381b327997bb32b3d5c9103315cc3688_3057964_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/last-before-times/j-tree-sunset_hu381b327997bb32b3d5c9103315cc3688_3057964_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;There is plenty of room to social-distance in the desert, but huddling by the campfire is better with friends. I hope we&amp;rsquo;ll get to do this again soon.&lt;/p&gt;
&lt;p&gt;PS: I&amp;rsquo;m kidding about this &amp;ldquo;before-times&amp;rdquo; stuff. I think we&amp;rsquo;ll work our way out of this. Just last week the cycling trails and beaches of Los Angeles have reopened. While we&amp;rsquo;re still social-distancing, it feels nice to get out of the house.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 18 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>100 Days Offload: Time For An Adjustment</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/100-days-offload-adjust/</link>
      <pubDate>Thu, 14 May 2020 18:41:07 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/100-days-offload-adjust/</guid>
      <description>&lt;p&gt;This is day 17 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;100DaysToOffload&lt;/a&gt; challenge for me.&lt;/p&gt;
&lt;p&gt;I have to say it&amp;rsquo;s been taxing.&lt;/p&gt;
&lt;p&gt;While I am very happy that I got this far, and I am happy with the posts I cranked out, I can tell it&amp;rsquo;s time to make an adjustment.&lt;/p&gt;
&lt;p&gt;This pace of posting is too demanding for me and my family, and it&amp;rsquo;s also limiting to some extent how much I&amp;rsquo;m getting out of the challenge.&lt;/p&gt;
&lt;h1 id=&#34;the-costs&#34;&gt;The Costs&lt;/h1&gt;
&lt;p&gt;We&amp;rsquo;re in a pandemic. Things are harder than they normally are to begin with. The kiddo isn&amp;rsquo;t going to daycare so my wife and I take turns watching over her. These moments with the little one at home are a gift, but they&amp;rsquo;re not the most restful. My wife spends more time with her than I do because my work hours are longer.&lt;/p&gt;
&lt;p&gt;In the midst of all of this I decide to do a marathon blogging challenge. Brilliant move. I&amp;rsquo;m in front of my computer even more and I go to bed late, which is &lt;a href=&#34;https://olivierforget.net/blog/2020/dont-miss-your-sleep-train/&#34;&gt;a big no-no in my book&lt;/a&gt;. When my wife suggests we should watch a movie I say no because I have to go back to the blog after dinner.&lt;/p&gt;
&lt;p&gt;This is also hurting my rule about &lt;a href=&#34;https://olivierforget.net/blog/2020/wfh-tip-good-day-off/&#34;&gt;taking a true day off at least once a week&lt;/a&gt;. If the challenge is to blog every day, I have to somehow justify time in front of my laptop on my &amp;ldquo;rest&amp;rdquo; day.&lt;/p&gt;
&lt;p&gt;Of course the rules of the challenge are that there are no rules, but I tend to latch on to trivial frameworks to accomplish things. I operate similarly when I work out: I&amp;rsquo;ll force myself to keep pedaling until I reach the top of the hill.&lt;/p&gt;
&lt;p&gt;Most evenings, after I finally shut the lid on the laptop, there has been a thought nagging in the back of my head: how long can I keep this up? I&amp;rsquo;m not even close to 100 days. It turns out I&amp;rsquo;m not alone: Kev Quirk, creator of the challenge, is also &lt;a href=&#34;https://kevq.uk/100-days-to-offload-over-saturation/&#34;&gt;feeling the costs and adjusting&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;blogger-unleashed&#34;&gt;Blogger Unleashed&lt;/h1&gt;
&lt;p&gt;I am really grateful to the challenge for getting me to publish a bunch of posts to my blog. I know it&amp;rsquo;s only been 16½ but that&amp;rsquo;s like 5.5 times more posts than when I started.&lt;/p&gt;
&lt;p&gt;The main thing this challenge has taught me so far is that I can get to the end of a post, in a complete and acceptably written way, and hit publish, and move on. In the past I would spend too much time thinking about the meaning of each post, as if somehow there was a significant meaning, and I would stall out in paralysis by analysis.&lt;/p&gt;
&lt;p&gt;Posts are just a thought man! You can amend it later with another thought. Now you&amp;rsquo;ve got two posts and you&amp;rsquo;re a blogging machine. After some time you can forget you ever posted it and there is a decent chance nobody will ever remind you (just don&amp;rsquo;t ever run for office).&lt;/p&gt;
&lt;p&gt;I am a perfectionist in my work, but I&amp;rsquo;m learning that with blogging you just have to let it go. It&amp;rsquo;s fine to publish and have it be &amp;ldquo;just OK&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;All this to say that in 16 posts I feel like I&amp;rsquo;ve unlocked that part of my blogging abilities. When I sit down to write I am much more confident that I&amp;rsquo;ll come up with something, and that publishing it will feel more good than bad.&lt;/p&gt;
&lt;p&gt;In fact I&amp;rsquo;ve been surprised by the content that has poured out of the various recesses of my mind. Some days I have had a hard time thinking of what to write. But when I decide on something, it ends up coming out in droves. It gushes out and I end up with far too much editing work.&lt;/p&gt;
&lt;p&gt;Each of these posts, even the hard ones, make me feel happy knowing they&amp;rsquo;re out there. There isn&amp;rsquo;t a single throw-away in there as far as I&amp;rsquo;m concerned (you may disagree, but this is a personal perspective). Each one was something that was on my mind, and it&amp;rsquo;s out there now. And it feels good.&lt;/p&gt;
&lt;h1 id=&#34;the-next-phase&#34;&gt;The Next Phase&lt;/h1&gt;
&lt;p&gt;I want to work on a different aspect of blogging now. Clearly I can slam a post out in a day, day after day if I want to. Check. Now I want to work on quality.&lt;/p&gt;
&lt;p&gt;I wrote earlier about how I had a &lt;a href=&#34;https://olivierforget.net/blog/2020/draft-or-not/&#34;&gt;hard time with drafts&lt;/a&gt;. Time to fix that. I want to take more time writing posts so that they go a bit deeper, are better researched and better written.&lt;/p&gt;
&lt;p&gt;Hopefully this will free up some time. By not forcing myself to publish every day I can forego the writing session if it&amp;rsquo;s more appropriate to do something else.&lt;/p&gt;
&lt;p&gt;This won&amp;rsquo;t make it easier though. I found the daily posting to be a big motivator. Without it, I&amp;rsquo;m worried I&amp;rsquo;ll spend too much time on drafts and end up with big gaps between my posts. I&amp;rsquo;m also worried that this will bring back the need to post something extra-meaningful and powerful, and failing that, to post nothing at all.&lt;/p&gt;
&lt;p&gt;But I&amp;rsquo;ll learn to overcome. That&amp;rsquo;s why it&amp;rsquo;s called a challenge.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was post 17 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Deno Saved My Side-Project</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/deno-saved-project/</link>
      <pubDate>Wed, 13 May 2020 12:15:22 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/deno-saved-project/</guid>
      <description>&lt;p&gt;My main side-project is a server that runs personal web-based applications. The idea is that web apps could be built and distributed more like the smartphone ecosystem than the current model of &amp;ldquo;everything online is a service&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll talk more about this project some other time, but for now suffice it to say that for the idea to work, a user should be able to install a web-app without putting themselves at risk.&lt;/p&gt;
&lt;p&gt;Basically, whatever code runs and however it runs, it must have very limited and controlled access to the underlying system.&lt;/p&gt;
&lt;p&gt;Examples of actions that must be controlled:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;read/write to disk&lt;/li&gt;
&lt;li&gt;outgoing web requests&lt;/li&gt;
&lt;li&gt;create network listeners (the host takes care of that)&lt;/li&gt;
&lt;li&gt;consume too much space on the disk&lt;/li&gt;
&lt;li&gt;consume too many CPU cycles&lt;/li&gt;
&lt;li&gt;consume too much memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My project has been going on for close to two years now, and a lot of that time was spent trying to figure out how I can run code with such restrictions.&lt;/p&gt;
&lt;p&gt;I want the apps to be written in a language that web developers are familiar with. Naturally this means JavaScript.&lt;/p&gt;
&lt;h1 id=&#34;vm2&#34;&gt;VM2&lt;/h1&gt;
&lt;p&gt;My first attempt was using a JS &amp;ldquo;sandbox VM&amp;rdquo; &lt;a href=&#34;https://github.com/patriksimek/vm2/&#34;&gt;thing&lt;/a&gt;. I quickly saw that this wasn&amp;rsquo;t good enough. JS is like the gunk that comes off of pine trees: once you touch it, it gets everywhere and you just can&amp;rsquo;t be sure you&amp;rsquo;ve gotten rid of it. It&amp;rsquo;s nearly impossible with current JS to isolate one part of it. There is always some weird &lt;a href=&#34;https://github.com/patriksimek/vm2/issues/178&#34;&gt;prototype&lt;/a&gt; &lt;a href=&#34;https://github.com/patriksimek/vm2/issues/138&#34;&gt;chain&lt;/a&gt; &lt;a href=&#34;https://github.com/patriksimek/vm2/issues/32&#34;&gt;trick&lt;/a&gt; that can be exploited to get out.&lt;/p&gt;
&lt;p&gt;VM2 is an impressive project, but I fear the never ending fight against JavaScript &lt;a href=&#34;https://github.com/patriksimek/vm2/issues?q=is%3Aissue+is%3Aclosed+author%3AXmiliaH&#34;&gt;escape artists&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;javascript-realms&#34;&gt;JavaScript Realms&lt;/h1&gt;
&lt;p&gt;My second hope was for &lt;a href=&#34;https://github.com/tc39/proposal-realms&#34;&gt;JS Realms&lt;/a&gt;. It addresses the above point directly: arm the language with the ability to segregate parts of itself. This seems like a good move for the JS ecosystem as a whole, and I thought the proposal was moving along nicely, but it appears stalled.&lt;/p&gt;
&lt;h1 id=&#34;containers&#34;&gt;Containers&lt;/h1&gt;
&lt;p&gt;Next, I dove into containers. If JS can&amp;rsquo;t be tamed then I&amp;rsquo;ll tame it at the OS level. Or so I thought, but this was tough. First, I am not a Linux system expert by any means. I know just enough to get by. I got hung up on &lt;a href=&#34;https://unix.stackexchange.com/questions/500987/why-would-creating-a-user-namespace-with-size-1-work-but-size-1-fail&#34;&gt;esoteric&lt;/a&gt; &lt;a href=&#34;https://bugzilla.redhat.com/show_bug.cgi?id=1361043&#34;&gt;linux&lt;/a&gt; &lt;a href=&#34;https://stackoverflow.com/questions/34783391/why-i-couldnt-use-mount-bind-proc-pid-ns-mnt-to-another-file-in-ubuntu&#34;&gt;stuff&lt;/a&gt;. Second, JS isn&amp;rsquo;t a great language for this kind of work, so I needed an upgrade. A lot of container tech is written in Go, so that&amp;rsquo;s what I landed on.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s weird that container stuff is written in Go since it&amp;rsquo;s inherently multi-threaded, which &lt;a href=&#34;https://github.com/golang/go/issues/8676&#34;&gt;causes&lt;/a&gt; &lt;a href=&#34;https://github.com/golang/go/issues/1435&#34;&gt;problems&lt;/a&gt;. But hey whatever, I still like the language (especially now that I&amp;rsquo;ve moved on from containers).&lt;/p&gt;
&lt;p&gt;Anyhoo I learned me some Go, and I am now quite dangerous with this language, and I got some custom built container orchestration &lt;a href=&#34;https://en.wikipedia.org/wiki/Rube_Goldberg_machine&#34;&gt;Rube Goldberg machine&lt;/a&gt; going.&lt;/p&gt;
&lt;p&gt;It worked, sort of. I want to be able to turn sandboxes on and off rapidly, but the latency and overhead of the system was not encouraging. I didn&amp;rsquo;t expect it to be great, but I was desperately in need of something.&lt;/p&gt;
&lt;p&gt;Along the way I learned that containers are one thing, sandboxes are another. While creating containers is easy, making a truly robust sandbox is a different level of challenge. Any little mistake in the setup of the container can leave a door wide open for an escape. Jessie Frazelle &lt;a href=&#34;https://blog.jessfraz.com/post/getting-towards-real-sandbox-containers/&#34;&gt;can do it&lt;/a&gt;, but I should probably &lt;a href=&#34;https://blog.jessfraz.com/post/containers-zones-jails-vms/&#34;&gt;not try&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;deno&#34;&gt;Deno&lt;/h1&gt;
&lt;p&gt;Sometime after I had sunk a lot of work into my container-dispatcher-axe-throwing thing I started noticing a project called &lt;a href=&#34;https://deno.land/&#34;&gt;Deno&lt;/a&gt;. It was in very early stages then, but its tagline was a promise that went straight to my heart: &amp;ldquo;A Secure Runtime For JS&amp;rdquo;. Oh baby.&lt;/p&gt;
&lt;p&gt;I decided this had to be the solution. Each app could run in its own instance of Deno with its own permissions, and &lt;a href=&#34;https://en.wikipedia.org/wiki/Cgroups&#34;&gt;cgroups&lt;/a&gt; to control resources. Startup latency is good enough for now, and I can already think of ways to make it seem faster.&lt;/p&gt;
&lt;p&gt;I created a branch and obliterated my container-juggling-circus-act code and went all-in on Deno. I figured I&amp;rsquo;d have time to write all the other parts of the system before Deno is ready (I was wrong, I&amp;rsquo;m nowhere near done).&lt;/p&gt;
&lt;h1 id=&#34;deno-and-security&#34;&gt;Deno and Security&lt;/h1&gt;
&lt;p&gt;At first I wasn&amp;rsquo;t sure how serious the devs were about the security aspect of the project. But come on, &amp;ldquo;secure&amp;rdquo; is the fourth word on their homepage after &amp;ldquo;Deno is a&amp;hellip;&amp;rdquo; so surely they&amp;rsquo;d be on it?&lt;/p&gt;
&lt;p&gt;I filed a few issues (&lt;a href=&#34;https://github.com/denoland/deno/issues/2705&#34;&gt;#2705&lt;/a&gt;, &lt;a href=&#34;https://github.com/denoland/deno/issues/2761&#34;&gt;#2761&lt;/a&gt;, &lt;a href=&#34;https://github.com/denoland/deno/issues/3401&#34;&gt;#3401&lt;/a&gt;) against early builds around security and permissions. Ryan Dahl, creator of Deno (and co-creator of Node) was receptive to my concerns, and most of my issues are now fixed. This gives me some confidence that Deno would eventually become pretty tight.&lt;/p&gt;
&lt;p&gt;Sadly I couldn&amp;rsquo;t contribute actual code because I would have to know Rust. Having learned some Go the year before my enthusiasm for learning Rust was low. Besides I&amp;rsquo;d like to become less dangerous with Go instead of super-dangerous in two languages.&lt;/p&gt;
&lt;p&gt;At this stage I wouldn&amp;rsquo;t run untrusted code in Deno, but since it&amp;rsquo;s reached 1.0 we can hope that the community will start poking at it and expose the flaws, and they&amp;rsquo;ll get fixed. The fundamentals of its design are &lt;a href=&#34;https://deno.land/manual/contributing/architecture&#34;&gt;sound&lt;/a&gt; so it&amp;rsquo;s a matter of finding and quashing bugs.&lt;/p&gt;
&lt;h1 id=&#34;thank-you-deno&#34;&gt;Thank You Deno&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m really glad Deno is here. It&amp;rsquo;s important to be able to run code that you can&amp;rsquo;t necessarily trust in an environment that limits what an attacker should do. We should have that for JS.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m also glad because my project would be dead without it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 16 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Thoughts on Hugo</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/thoughts-on-hugo/</link>
      <pubDate>Tue, 12 May 2020 09:10:21 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/thoughts-on-hugo/</guid>
      <description>&lt;p&gt;This blog is generated using &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt;. A documentation site I&amp;rsquo;m rebuilding is also made with Hugo. These two projects have given me a chance to get to know the tool, to appreciate it at times, and to curse it otherwise.&lt;/p&gt;
&lt;p&gt;Some of my complaints are inherent to static site generators, others are more specific to Hugo.&lt;/p&gt;
&lt;h1 id=&#34;your-directory-tree-is-configuration-code&#34;&gt;Your Directory Tree Is Configuration Code&lt;/h1&gt;
&lt;p&gt;In its simplest form, a static site generator takes a directory tree full of markdown files, and cranks out an identically structured directory tree full of HTML files.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s expected that the shape of your directories will affect how the generator works.&lt;/p&gt;
&lt;p&gt;Hugo has accumulated such a vast array of capabilities that the simple model described above has multiplied to the point where it&amp;rsquo;s no longer easy to know what effect a file has, or why some file does not have the effect you think it should.&lt;/p&gt;
&lt;p&gt;Have a look at the &lt;a href=&#34;https://gohugo.io/templates/lookup-order/&#34;&gt;template lookup order &amp;ldquo;help page&amp;rdquo;&lt;/a&gt;. Hugo accomplishes a lot here, with its multi-language abilities, and its taxonomies, etc&amp;hellip; But you can see from the number of examples and possible lookup places that the capabilities are paid for in complexity.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t think the filesystem is the right tool to describe the complex relations between posts and languages and templates and output formats. It&amp;rsquo;s too easy to get lost.&lt;/p&gt;
&lt;h1 id=&#34;indexmd-or-_indexmd-or-my-postmd&#34;&gt;Index.md Or _Index.md Or my-post.md&lt;/h1&gt;
&lt;p&gt;It took me a little while to understand that _index.md and index.md are not the same thing. One is used to showcase a list of posts, the other one is the post itself within a page bundle. Or something like that. I used the wrong one for a while and got no errors, but my table-of-contents didn&amp;rsquo;t seem to work. I spent a lot of time sorting that out.&lt;/p&gt;
&lt;p&gt;I ran into a number of subtle behavior gotchas like that with the tool. For instance there are different &amp;ldquo;kinds&amp;rdquo; of pages and different &amp;ldquo;types&amp;rdquo; of pages, and it affects whether a page shows up in a collection of pages among other things. (Don&amp;rsquo;t ask me to explain, I can&amp;rsquo;t.) The point is there are lots of concepts, and these concepts don&amp;rsquo;t all work intuitively, and the difference between the tool behaving one way or the other can boil down to a single underscore in a file name.&lt;/p&gt;
&lt;p&gt;I ran into another issue where I wanted to render markdown in content within a shortcode. Here again one little character makes a big difference. This {{&amp;lt; shortcode &amp;gt;}} is not the same as {{%  shortcode %}}. This behavior has changed over time, &lt;a href=&#34;https://github.com/gohugoio/hugo/issues/5900&#34;&gt;causing confusion&lt;/a&gt;, and guess what? Though I read the docs, the behavior on my site is opposite what the &lt;a href=&#34;https://gohugo.io/content-management/shortcodes/#shortcodes-without-markdown&#34;&gt;docs indicate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course it&amp;rsquo;s all my fault. Everything is &lt;a href=&#34;https://gohugo.io/documentation/&#34;&gt;documented&lt;/a&gt;. The thing is the documentation runs longer than your typical &amp;ldquo;learn a programming language&amp;rdquo; volume. I haven&amp;rsquo;t actually counted the words but it seems like there is a lot more than I should have to go through to render a blog or some docs site. The section on &amp;ldquo;Content Management&amp;rdquo; has 24 pages, each bringing in new concepts and new flags to tweak in your configuration.&lt;/p&gt;
&lt;p&gt;You might say &amp;ldquo;it&amp;rsquo;s powerful, it&amp;rsquo;s up to you to learn it&amp;rdquo;. I won&amp;rsquo;t argue it&amp;rsquo;s not powerful, but something this powerful could be more sane to use if it relied on something other than the presence of an underscore to mean something about a file. Is the file tree truly the best abstraction for the user to accomplish their goals?&lt;/p&gt;
&lt;h1 id=&#34;all-text-no-tools&#34;&gt;All Text No Tools&lt;/h1&gt;
&lt;p&gt;I understand the draw of using text files in a file tree: they can be worked on from the user&amp;rsquo;s favorite text editor, and it can all be checked into version control. Fine.&lt;/p&gt;
&lt;p&gt;The problem is the tooling for text editors is weak. If something is this complex and powerful, and intended to be seen as &amp;ldquo;code&amp;rdquo; my expectations grow accordingly: where is the live error reporting? Where is the &amp;ldquo;debugger&amp;rdquo;? Autocomplete?&lt;/p&gt;
&lt;p&gt;For instance, you can create a link to a page within your site using a &amp;ldquo;&lt;a href=&#34;https://gohugo.io/content-management/shortcodes/#ref-and-relref&#34;&gt;relref&lt;/a&gt;&amp;rdquo;. The cool thing is that the site will fail to build if you put a typo in the link. Guaranteed link correctness! I like. But the way it works is you type your stuff in your text editor, at some point hit save, then and only then your Hugo build will throw an error.&lt;/p&gt;
&lt;p&gt;Does this remind you of anything? It takes me back to engineering school in the nineties where I was learning Fortran 77 (and the new hotness Fortran 90!) Write code. Save. Run compiler. Oops error. Find error file and line. Think some. Aha! Fix. Save. Run compiler. And on and on&amp;hellip;&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know about you but I don&amp;rsquo;t work like this anymore. Whether I write Go or Typescript, I get to see my mistakes as I type them, and I get suggestions for what is actually correct. The creators of those languages provide tools to help me because they feel my pain. I&amp;rsquo;m writing cryptic text but I&amp;rsquo;m getting a lot of help. When I do things in Hugo I get almost no help.&lt;/p&gt;
&lt;p&gt;If a template doesn&amp;rsquo;t work as you expect and you want to step through it as if it were normal code, too bad. A &lt;a href=&#34;https://gohugo.io/templates/template-debugging/&#34;&gt;helpful docs page&lt;/a&gt; recommends you put &amp;ldquo;printf&amp;rdquo; statements in your template. The nineties called, they want their debugger back.&lt;/p&gt;
&lt;p&gt;Why would I not get an autocomplete when I create an internal link using relref? Shouldn&amp;rsquo;t I get a red squiggly underline if my relref has a typo? How about autocomplete when using a shortcode? (I tried installing &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=budparr.language-hugo-vscode&amp;amp;ssr=false&#34;&gt;this extension&lt;/a&gt; to my VSCode but it doesn&amp;rsquo;t seem to be doing much apart from causing an autocomplete popup for every single English word I type.)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to be able to click on any shortcode, or select any file, and have a tool tell me where it&amp;rsquo;s sourcing the templates that will be used to render it, and where the output will go.&lt;/p&gt;
&lt;p&gt;But I don&amp;rsquo;t have any of that, so when something doesn&amp;rsquo;t work quite work like I expect I end up just playing a lengthy and frustrating guessing game.&lt;/p&gt;
&lt;h1 id=&#34;disenchantment&#34;&gt;Disenchantment&lt;/h1&gt;
&lt;p&gt;I started off really wanting to like Hugo. I got into it after I realized I was going to have to put my &lt;a href=&#34;http://www.cicerone.co&#34;&gt;web content authoring tool&lt;/a&gt; on the backburner.&lt;/p&gt;
&lt;p&gt;I figured if I can&amp;rsquo;t build something great, then I should pick the best of what exists and learn to live with the things I disliked.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s been over a year now, and I just can&amp;rsquo;t find love for Hugo. I use it, it&amp;rsquo;s effective when it&amp;rsquo;s all set up correctly. But does it feel like a wonderful powerful tool? A bicycle for my content-generating mind? Hardly.&lt;/p&gt;
&lt;p&gt;There is a &lt;a href=&#34;https://vimeo.com/82301919&#34;&gt;great talk&lt;/a&gt; by &lt;a href=&#34;https://en.wikipedia.org/wiki/Alan_Kay&#34;&gt;Alan Kaye&lt;/a&gt; dubbed &amp;ldquo;Is it complex? or did we make it complicated?&amp;rdquo; that applies here.&lt;/p&gt;
&lt;p&gt;Static site generators have stepped over and beyond the bounds of what made them great: they were simple tools for simple problems. By making them do so much more they became complicated, and less effective.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;PS: I&amp;rsquo;m sorry for not including proper code snippets. Turns out if I wrap Hugo short codes in a code block, Hugo tries to interpret them as actual shortcodes. If I escape the characters with \ it renders the slashes, and if I don&amp;rsquo;t it crashes with &amp;ldquo;Null pointer dereference error&amp;rdquo;. Yay.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 15 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Laravel Temptations</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/laravel-temptations/</link>
      <pubDate>Mon, 11 May 2020 19:22:37 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/laravel-temptations/</guid>
      <description>&lt;p&gt;I need to modernize an old PHP web-app. I am facing down many hours of sifting through old messy code (written by me over many years) to figure out the essence and transform it into something more robust.&lt;/p&gt;
&lt;p&gt;This is going to be painful, and I&amp;rsquo;m looking for anything that can help ease the burden.&lt;/p&gt;
&lt;p&gt;One such helpful thing that comes up over and over in modern PHP chatter is &lt;a href=&#34;https://laravel.com/&#34;&gt;Laravel&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;laravel-in-context&#34;&gt;Laravel in Context&lt;/h1&gt;
&lt;p&gt;Laravel is a modern PHP framework. By modern I mean it was first written in 2011. For reference &lt;a href=&#34;https://en.wikipedia.org/wiki/PHP&#34;&gt;PHP&lt;/a&gt; first appeared in 1995! PHP is an old language, but it&amp;rsquo;s still &lt;a href=&#34;https://lwn.net/SubscriberLink/818973/507f4b5e09ab9870/&#34;&gt;evolving&lt;/a&gt; for the &lt;a href=&#34;https://stitcher.io/blog/php-in-2019&#34;&gt;better&lt;/a&gt;, which I find kind of endearing.&lt;/p&gt;
&lt;p&gt;I started with PHP 5 some thirteen years ago, and built everything without a framework. My code suffered from multiple personality disorder as I tried different approaches to solve the same problem.&lt;/p&gt;
&lt;p&gt;Now I need to put the whole thing into a blender, make a slurry of it and 3D-print a beauty of an application.&lt;/p&gt;
&lt;p&gt;Using Laravel would represent a deep transformation not just of code but of attitude compared to when I started.&lt;/p&gt;
&lt;h1 id=&#34;laravel-attraction&#34;&gt;Laravel Attraction&lt;/h1&gt;
&lt;p&gt;I will need to rewrite my admin and backend code to accommodate new features. I&amp;rsquo;m really not looking forward to this. Is there a way to avoid doing that? &lt;a href=&#34;https://nova.laravel.com/&#34;&gt;Laravel Nova&lt;/a&gt; caught my attention. It&amp;rsquo;s a ready-baked admin panel, apparently, and if it&amp;rsquo;s half as good as it sounds, I&amp;rsquo;m in.&lt;/p&gt;
&lt;p&gt;Nova would cost me a couple hundred bucks, but that&amp;rsquo;s peanuts compared to the pain of doing this myself.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s part of the attraction to Laravel: there are a bunch of these &amp;ldquo;add-ons&amp;rdquo;, some free some paid, and some as a service that I might leverage to remove some of my workload.&lt;/p&gt;
&lt;p&gt;Other add-ons I find interesting (all are linked from Laravel&amp;rsquo;s &lt;a href=&#34;https://laravel.com/&#34;&gt;home page&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Echo for real-time events&lt;/li&gt;
&lt;li&gt;Cashier for subscription billing (although it&amp;rsquo;s for Stripe, which I am not using. It looks like they had &lt;a href=&#34;https://laravel.com/docs/5.8/braintree&#34;&gt;Braintree support in 5.8&lt;/a&gt;?)&lt;/li&gt;
&lt;li&gt;Passport for OAuth2&lt;/li&gt;
&lt;li&gt;Scout for full-text search&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I know many other frameworks offer similar solutions in various forms, but it&amp;rsquo;s comforting to see a neatly put together set of tools and services designed to make you more productive.&lt;/p&gt;
&lt;p&gt;If Nova didn&amp;rsquo;t work out for me I could also use &lt;a href=&#34;https://backpackforlaravel.com/&#34;&gt;Backpack&lt;/a&gt;, but I like the idea of getting add-ons from the developer of the framework, it gives me hope that the add-on is seamlessly integrated with the main framework.&lt;/p&gt;
&lt;h1 id=&#34;laravel-concerns&#34;&gt;Laravel Concerns&lt;/h1&gt;
&lt;p&gt;I need to do more in-depth research on what it&amp;rsquo;s like to write an entire application using this framework. Like what it&amp;rsquo;s really like. Not a &amp;ldquo;Hello-World&amp;rdquo; type thing.&lt;/p&gt;
&lt;p&gt;In fact I&amp;rsquo;ll probably have to code an example app just to get the feel of it. And you know what that app is going to be? My admin panel (or the start of it at least). Yup, you know it. This is how I am going to slip into this framework.&lt;/p&gt;
&lt;p&gt;But seriously, I do have some concerns. My view of frameworks in general is that they make a lot of standard stuff very easy, but as soon as you get into an edge case you have to work harder to do what you need.&lt;/p&gt;
&lt;p&gt;Another concern is breaking changes. One sweet advantage of &amp;ldquo;rolling your own&amp;rdquo; anything, is that you don&amp;rsquo;t change it if you don&amp;rsquo;t need to. Frameworks, libraries, all other code written to be reused by many others change a lot over time. There is always pressure to do things better, to stay relevant, to sell the latest add-on. The result is unwanted migrations that can lead to breakage and a lot of work for no real reason.&lt;/p&gt;
&lt;h1 id=&#34;to-be-continued&#34;&gt;To Be Continued&lt;/h1&gt;
&lt;p&gt;If you&amp;rsquo;ve had experience with Laravel I&amp;rsquo;d like to hear your impressions.&lt;/p&gt;
&lt;p&gt;If I go further with the framework I&amp;rsquo;ll let you know how it goes right here.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 14 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Web Of OK People</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/web-of-ok-people/</link>
      <pubDate>Sun, 10 May 2020 19:04:27 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/web-of-ok-people/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m terribly frustrated with common social networks, and by extension the spread of misinformation and the spread of hate.&lt;/p&gt;
&lt;p&gt;This is a great time to be an a-hole, or a blowhard, or to have a desire to spread a viral idea to the world if you have no scruples.&lt;/p&gt;
&lt;p&gt;We are in the golden age of BS.&lt;/p&gt;
&lt;h1 id=&#34;social-media&#34;&gt;Social Media&lt;/h1&gt;
&lt;p&gt;Social media companies love to say they are bringing the whole world together. Zuck &lt;a href=&#34;https://www.brainyquote.com/quotes/mark_zuckerberg_453429&#34;&gt;thinks&lt;/a&gt; that the world magically gets better if more and more people can get in direct contact with each other.&lt;/p&gt;
&lt;p&gt;Unfortunately this is a naïve view of things. On social media, the things that spread are the things that trigger a quick reaction. Subtlety, nuance, and complex subjects don&amp;rsquo;t do as well.&lt;/p&gt;
&lt;p&gt;This is why a&amp;ndash;holes and blowhards thrive in this era. Anything that shocks people gets to spread. Insults, controversy, sewing division. All are much &amp;ldquo;liked&amp;rdquo; on social media.&lt;/p&gt;
&lt;p&gt;It is not a surprise that people resort to making their point as &amp;ldquo;triggering&amp;rdquo; as possible, so that it gets re-shared. This leads to oversimplification, or leaving out mitigating factors, or simply making things up.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t like any of this, so I&amp;rsquo;ve been asking myself the question: how could social media be designed such that it is much harder for jerks to be jerks.&lt;/p&gt;
&lt;h1 id=&#34;people-of-the-net&#34;&gt;People Of The Net&lt;/h1&gt;
&lt;p&gt;At a fundamental level, this shouldn&amp;rsquo;t be too hard. Most humans are cordial to each-other, and don&amp;rsquo;t start trash-talking to someone&amp;rsquo;s face for no reason.&lt;/p&gt;
&lt;p&gt;The internet is different. People who don&amp;rsquo;t know each-other get into debates about the direction of their country. This is the promise of social media: connect with anybody about meaningful things.&lt;/p&gt;
&lt;p&gt;In the physical world neighbors who know they aren&amp;rsquo;t on the same political usually prefer to just skip those conversations and instead talk about the kids soccer match, or any other matter they can talk about easily.&lt;/p&gt;
&lt;p&gt;How can we bring civility to tough discussions?&lt;/p&gt;
&lt;h1 id=&#34;basic-civility&#34;&gt;Basic Civility&lt;/h1&gt;
&lt;p&gt;It should be possible to come up with purely objective &amp;ldquo;acceptable behavior&amp;rdquo; that every participant would always have to adhere to. A code of conduct that doesn&amp;rsquo;t tell you what you can or can&amp;rsquo;t say, but one that mandates decency.&lt;/p&gt;
&lt;p&gt;Next, we need to figure out who decides whether a post or comment breaks the &amp;ldquo;acceptable behavior&amp;rdquo; rule. The typical approach is to use moderators. Personally, I don&amp;rsquo;t like this approach. Moderators are more powerful than other users, which is concentration of power which usually leads to problems.&lt;/p&gt;
&lt;p&gt;I would like an approach where every user is a moderator. This of course sets up a situation where people use moderation as a tool to abuse other users (moderation tools are &lt;strong&gt;always&lt;/strong&gt; used against users).&lt;/p&gt;
&lt;p&gt;To counter that, moderation itself should be a moderated. If a user flags a post as &amp;ldquo;offensive&amp;rdquo; when it clearly is not, that contribution could be flagged as &amp;ldquo;bad moderation&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Now of course we&amp;rsquo;re set up for an endless cascade of of users flagging flags. How does it end?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m thinking that maybe it doesn&amp;rsquo;t matter thanks to another concept:&lt;/p&gt;
&lt;h1 id=&#34;web-of-ok-people&#34;&gt;Web Of OK People&lt;/h1&gt;
&lt;p&gt;There could be a &lt;a href=&#34;https://en.wikipedia.org/wiki/Web_of_trust&#34;&gt;web-of-trust&lt;/a&gt; type of thing, but it would be a web-of-OK-people.&lt;/p&gt;
&lt;p&gt;Basically, every user would have a list of people who they consider to be &amp;ldquo;OK&amp;rdquo;, as in they are stand-up folks who aren&amp;rsquo;t going to throw feces around the room. A user would mark anybody they know, either in-person, or because you&amp;rsquo;ve witnessed their good behavior around the net for long enough to know they are stand-up folks, as OK-people.&lt;/p&gt;
&lt;p&gt;Now when there is a controversy, any flag or moderation or comment is more likely to be showed to you if they are by one of your ok-people.&lt;/p&gt;
&lt;p&gt;A score could be given to any post based on the reactions of your OK-people: if they &amp;ldquo;liked&amp;rdquo; it, the score goes up, flagged it and it goes down. If they flagged a flag, then any negative effect of that flag would be removed.&lt;/p&gt;
&lt;p&gt;Unfortunately this would mean adding hundreds or thousands of ok-people just to get some coverage of the millions of posts in an active social network. Instead the system would find who the OK-people consider OK-people themselves, and consider those as OK-people too, but with less power. Then it would go another step and another and another until it amassed for each user a large list of OK to OKish people.&lt;/p&gt;
&lt;h1 id=&#34;sane-media-not-social-madness&#34;&gt;Sane Media Not Social Madness&lt;/h1&gt;
&lt;p&gt;With a web-of-OK-people weighing moderations and flags on content, the content a user sees can be curated for them.&lt;/p&gt;
&lt;p&gt;While users of current social media can curate their feed by following good people, things get ugly when you look at replies to a post, or look at the comments section on YouTube for example (yikes!).&lt;/p&gt;
&lt;p&gt;With the web-ok-Ok-people eliminating the replies by those who don&amp;rsquo;t measure up, social media could be a decent place to be again.&lt;/p&gt;
&lt;p&gt;The community would essentially do personalized distributed censorship of unacceptable posts, and if a user thought the censorship was wrong, they could adjust who is in their list of OK-people so that it better matches their tastes.&lt;/p&gt;
&lt;p&gt;An army of bots wouldn&amp;rsquo;t get very far. A bad actor could create thousands of accounts, but with no track record (or a bad one if any) and no personal connections, most bots won&amp;rsquo;t be considered OK-people by anybody, eliminating their influence.&lt;/p&gt;
&lt;h1 id=&#34;open-questions&#34;&gt;Open Questions&lt;/h1&gt;
&lt;p&gt;Look, I don&amp;rsquo;t know if this would ever work. It might be an OK theory but a disaster in practice. I have no idea.&lt;/p&gt;
&lt;p&gt;Wikipedia experimented with &lt;a href=&#34;https://en.wikipedia.org/wiki/Wikipedia:Trust_network&#34;&gt;something like this&lt;/a&gt; at some point, but are no longer using it. I&amp;rsquo;ll need to research why.&lt;/p&gt;
&lt;p&gt;There are questions around the computational demands of such a system. It&amp;rsquo;s not clear it&amp;rsquo;s even feasible at scale.&lt;/p&gt;
&lt;p&gt;I can&amp;rsquo;t help but wonder if this would just create highly tuned filter bubbles. I think users who would want more diverse views could get that by adding OK-people who see things differently but aren&amp;rsquo;t jerks.&lt;/p&gt;
&lt;p&gt;I worry as well about onboarding new users. How does a fresh new user get anywhere on such a system if they don&amp;rsquo;t already know people? There would have to be a patronage system to help get people started.&lt;/p&gt;
&lt;p&gt;Alright, enough questions. There is bound to be a lot more to this than what I wrote, but it felt good to offload it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 13 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Google Services I&#39;m Stuck With (For Now)</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/google-services-stop-using/</link>
      <pubDate>Sat, 09 May 2020 19:04:37 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/google-services-stop-using/</guid>
      <description>&lt;p&gt;I used to merrily sign up to any new service that Google created. The company still espoused its &amp;ldquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/Don%27t_be_evil&#34;&gt;Don&amp;rsquo;t be evil&lt;/a&gt;&amp;rdquo; motto, and the concept of privacy had yet to feel like something we had taken for granted.&lt;/p&gt;
&lt;p&gt;Things are different now. We&amp;rsquo;ve become more aware of how much of our private lives are floating from server to server, trading between data brokers to make a whole bunch of people &amp;ndash; but not us &amp;ndash; rich.&lt;/p&gt;
&lt;p&gt;There is plenty of &lt;a href=&#34;https://en.wikipedia.org/wiki/Criticism_of_Google&#34;&gt;criticism of Google&lt;/a&gt; and it all affects how I feel about the company, but one of the big concerns is having all my eggs in one basket.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve already seen the company change when it is financially secure, imagine what they&amp;rsquo;ll do when things start going bad for them (every empire goes down at some point, it&amp;rsquo;s just a matter of time).&lt;/p&gt;
&lt;h1 id=&#34;de-googling&#34;&gt;De-Googling&lt;/h1&gt;
&lt;p&gt;I have a background process in the depths of my mind whose task is to cut away from Google, little by little.&lt;/p&gt;
&lt;p&gt;The process wakes up once in a while, possibly triggered by something scary I read about the &lt;a href=&#34;https://threatpost.com/google-services-track-user-movements-in-privacy-faux-pas/135078/&#34;&gt;big company and its treatment of data&lt;/a&gt;, and it takes a step to cut another thread.&lt;/p&gt;
&lt;p&gt;Here is where I made some progress:&lt;/p&gt;
&lt;h4 id=&#34;gmail&#34;&gt;Gmail&lt;/h4&gt;
&lt;p&gt;I got my own domain and a &lt;a href=&#34;https://www.fastmail.com&#34;&gt;Fastmail&lt;/a&gt; account. I haven&amp;rsquo;t killed the gmail, I figure I&amp;rsquo;ll need it as long as I have and Android phone, but I have changed my email on many services and told all of my friends to write me there.&lt;/p&gt;
&lt;h4 id=&#34;search&#34;&gt;Search&lt;/h4&gt;
&lt;p&gt;Google is first and foremost a search engine, but its results are sometimes a letdown. I think search is due for a disruption, but that&amp;rsquo;s a different post. For now I use &lt;a href=&#34;https://duckduckgo.com&#34;&gt;DuckDuckGo&lt;/a&gt; as my primary search engine, and fall back to Google when DDG fails me, as it does fairly regularly.&lt;/p&gt;
&lt;h4 id=&#34;browser&#34;&gt;Browser&lt;/h4&gt;
&lt;p&gt;I tested out &lt;a href=&#34;https://brave.com/&#34;&gt;Brave&lt;/a&gt; for a while, though I am unsure about their plans for &lt;a href=&#34;https://www.pcworld.com/article/3050923/mozilla-co-founders-ad-blocking-brave-browser-will-pay-you-bitcoin-to-see-safe-ads.html&#34;&gt;serving me ads&lt;/a&gt;. I still use it on my tablet for some reason, but all other devices have switched to FireFox.&lt;/p&gt;
&lt;p&gt;FF works well. There are a few concerns about the way they &lt;a href=&#34;https://www.ghacks.net/2017/10/06/mozilla-to-launch-firefox-cliqz-experiment-with-data-collecting/&#34;&gt;treat private data&lt;/a&gt; as well, so I&amp;rsquo;m keeping an eye on them.&lt;/p&gt;
&lt;h1 id=&#34;stuck-with-google&#34;&gt;Stuck With Google&lt;/h1&gt;
&lt;p&gt;OK those three were big ones. But this next list is depressingly long: these are the services and devices I have made no progress replacing.&lt;/p&gt;
&lt;h4 id=&#34;android&#34;&gt;Android&lt;/h4&gt;
&lt;p&gt;I could wait for Linux phones (&lt;a href=&#34;https://puri.sm/products/librem-5/pureos-mobile/&#34;&gt;Librem&lt;/a&gt;, &lt;a href=&#34;https://www.pine64.org/pinephone/&#34;&gt;Pinephone&lt;/a&gt;) to become viable, but I&amp;rsquo;m afraid that&amp;rsquo;s going to take a long time.&lt;/p&gt;
&lt;p&gt;A good camera and excellent camera software is important to me, so any off-brand thing is likely to disappoint.&lt;/p&gt;
&lt;p&gt;The only reasonable option is an iOS device, probably. Hopefully Apple continues to differentiate itself from Google by valuing privacy, and hopefully it&amp;rsquo;s genuine and not a marketing pitch. Of course we can&amp;rsquo;t really know because everything is closed with them. Urgh.&lt;/p&gt;
&lt;p&gt;I think my first move will be to replace my aging Lenovo with an iPad, despite how much &lt;a href=&#34;https://olivierforget.net/blog/2020/this-is-bicycle-for-the-mind/&#34;&gt;I love that weird thing&lt;/a&gt;. Then I&amp;rsquo;ll decide how I feel about iOS and the Apple walled garden for a phone.&lt;/p&gt;
&lt;h4 id=&#34;photos&#34;&gt;Photos&lt;/h4&gt;
&lt;p&gt;This is the other big one. Every photo I take on my Pixel goes into my &lt;a href=&#34;https://www.google.com/photos/about/&#34;&gt;Photos&lt;/a&gt;, so if I lose my phone none of the priceless memories of my growing daughter are lost. That&amp;rsquo;s huge.&lt;/p&gt;
&lt;p&gt;Apart from jumping head first in Apple&amp;rsquo;s garden-of-loveliness-with-giant-walls, I don&amp;rsquo;t know what the other options are. I&amp;rsquo;m sure there are some, I just haven&amp;rsquo;t looked yet. The background process hasn&amp;rsquo;t perked up on this one yet.&lt;/p&gt;
&lt;h4 id=&#34;maps&#34;&gt;Maps&lt;/h4&gt;
&lt;p&gt;I use Google Maps a lot. Their maps and navigation are pretty darn good. Google&amp;rsquo;s product integration here is enticing: if I get an email about a hotel reservation, that hotel gets a callout in Maps with the reservation. Now &lt;em&gt;that&lt;/em&gt;, is a good reason to read my mail.&lt;/p&gt;
&lt;p&gt;I looked for a few alternative navigation and map apps but none seemed to hold a candle to big G for that function.&lt;/p&gt;
&lt;p&gt;Again if I jump into Apple&amp;rsquo;s planters I can easily solve the maps problem, but then I&amp;rsquo;d have to ask myself: am I too deep in Apple&amp;rsquo;s mulch? Will I have to write a post like this in a few years about how I need to pole-vault my way out of their yard?&lt;/p&gt;
&lt;h4 id=&#34;chromecast&#34;&gt;Chromecast&lt;/h4&gt;
&lt;p&gt;This one is really convenient. Anything that is on any of our Android devices can instantly be played in the living room. I know there are alternatives, and among them, again, there is Apple. I think as long as I&amp;rsquo;m on Android, the Chromecast stays.&lt;/p&gt;
&lt;h4 id=&#34;play-music&#34;&gt;Play Music&lt;/h4&gt;
&lt;p&gt;I used to be on Spotify, which was OK, but I got on Play Music in large part because paying for it removes the ads from YouTube. I hate ads, and I am glad I can watch YT in the evenings and never hit an ad. This one is going to stick around for a while.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll see how much Google is able to botch their music service though. It seems to be one of their most unloved products, and I am not looking forward to the impending &lt;a href=&#34;https://www.digitaltrends.com/music/what-happens-to-google-play-music-youtube-music/&#34;&gt;migration to YouTube-Music&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;will-i-ever&#34;&gt;Will I Ever&lt;/h1&gt;
&lt;p&gt;With the list above as long as it is, and with each service a struggle of compromise, or a head-first dive into some other mega-corp&amp;rsquo;s yard, I&amp;rsquo;m not terribly optimistic about my De-Google future.&lt;/p&gt;
&lt;p&gt;For some services it doesn&amp;rsquo;t matter really: I don&amp;rsquo;t care if they know what music I listen to, and I am not going to quit YouTube as long as they have all the best content.&lt;/p&gt;
&lt;p&gt;For others, I was able to make a change by doing some research and spending the time it takes.&lt;/p&gt;
&lt;p&gt;Keep working, little background process.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 12 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Wfh Tip: Get Outdoors and Exercise</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/</link>
      <pubDate>Fri, 08 May 2020 18:59:43 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/</guid>
      <description>&lt;p&gt;Los Angeles is starting to lift its stay-at-home restrictions, and hiking and cycling trails are among the things reopening.&lt;/p&gt;
&lt;p&gt;Whew, just in the nick of time.&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t really exercised since March (I don&amp;rsquo;t count doing a few pullups as &amp;ldquo;real exercise&amp;rdquo;), and my irritability is getting bad.&lt;/p&gt;
&lt;p&gt;I need to get out and exhaust myself in some way at least once a week or I am prone to moments of anger and a general sense of angst.&lt;/p&gt;
&lt;p&gt;So if you&amp;rsquo;re at home a lot and you&amp;rsquo;re feeling a little testy, try to get out.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is the third in a series on tips for working from home. Previous posts were &lt;a href=&#34;https://olivierforget.net/blog/2020/wfh-tip-good-day-off/&#34;&gt;A Good Day Off&lt;/a&gt;, and &lt;a href=&#34;https://olivierforget.net/blog/2020/dont-miss-your-sleep-train/&#34;&gt;Don&amp;rsquo;t Miss Your Sleep Train&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;get-a-good-workout&#34;&gt;Get a Good Workout&lt;/h1&gt;
&lt;p&gt;I like a long, primarily cardio workout. It&amp;rsquo;s what I&amp;rsquo;m built for.&lt;/p&gt;
&lt;p&gt;The key is to get your body moving. When you don&amp;rsquo;t even walk to your car to get to work, you end up with an abundant supply of energy waiting to get out. Most days you can ignore it, but keep it bottled up long enough, and it may get out on its own.&lt;/p&gt;
&lt;p&gt;Apart from the positive effect this has on your mind, your body will end up fitter and healthier.&lt;/p&gt;
&lt;p&gt;After a good workout you&amp;rsquo;re likely to sleep better, and &lt;a href=&#34;https://olivierforget.net/blog/2020/dont-miss-your-sleep-train/&#34;&gt;we know that&amp;rsquo;s critical&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;get-outdoors&#34;&gt;Get Outdoors&lt;/h1&gt;
&lt;p&gt;I used to swim laps, but after becoming self-employed I heard my own voice quite enough. Putting my head underwater to guarantee airtight isolation and staring at a line of tiles with nothing else to do but contemplate the same thoughts that have nibbled at my sanity all day is a &amp;ldquo;no thanks!&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;I find gyms claustrophobic. Apart from that period when I was into racquetball, I never enjoyed being at the gym. Climbing gyms are an exception, but even then I prefer climbing outdoors.&lt;/p&gt;
&lt;p&gt;The goal here is to escape. The inside of your house is thoroughly mapped, you need to go some place where the walls are out on the horizon and the ceiling is the sky.&lt;/p&gt;
&lt;p&gt;One of the best escapes for me is mountain biking. There are a lot of trails (well, fire-roads really) that run for miles in the hills that surround LA. The uphill parts are a great workout and the downhill is thrilling.&lt;/p&gt;
&lt;p&gt;A typical weeknight ride would be 20-something miles and 2000 feet of climbing, while a weekend ride would almost double both numbers. But forget the workout, the reason I did it was because the views and the contact with nature cleaned out so many of my worries. It reset me.&lt;/p&gt;
&lt;p&gt;Maybe just look at these pictures I took on rides:&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/santa-monica-mnts-1_hub7d1b133a34971e0d7adf9ac8e3e09dc_1090080_800x0_resize_q75_box.JPG&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/santa-monica-mnts-1_hub7d1b133a34971e0d7adf9ac8e3e09dc_1090080_800x0_resize_q75_box.JPG, https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/santa-monica-mnts-1_hub7d1b133a34971e0d7adf9ac8e3e09dc_1090080_1600x0_resize_q75_box.JPG 2x&#34;
    alt=&#34;&#34;&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/santa-monica-mnts-2_hu43600a51e64997c0db2c000a0bac3e6f_293247_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/santa-monica-mnts-2_hu43600a51e64997c0db2c000a0bac3e6f_293247_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/santa-monica-mnts-2_hu43600a51e64997c0db2c000a0bac3e6f_293247_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;






&lt;img src=&#34;https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/santa-monica-mnts-3_hue9b65cebca7469736b579b767f390804_147340_789x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/santa-monica-mnts-3_hue9b65cebca7469736b579b767f390804_147340_789x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/wfh-tip-get-outdoors-exercise/santa-monica-mnts-3_hue9b65cebca7469736b579b767f390804_147340_1578x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;That last one could be used on a pamphlet about the after-life.&lt;/p&gt;
&lt;p&gt;And maybe that&amp;rsquo;s the point. To get out, to get up a hill, and to look out at a view like that is the best way to feel that whatever comes will come, and it will be fine.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 11 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>To Draft Or Not To Draft</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/draft-or-not/</link>
      <pubDate>Thu, 07 May 2020 18:53:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/draft-or-not/</guid>
      <description>&lt;p&gt;I wrote my first nine posts for &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; in one day without starting from a draft. Many bloggers leverage a well stocked drafts folder, and the really rich ones might be &lt;a href=&#34;https://fosstodon.org/@kev/104092215149061604&#34;&gt;sitting on 30&lt;/a&gt; post drafts and ideas!&lt;/p&gt;
&lt;p&gt;I also have a folder full of partially written posts, and you would think I&amp;rsquo;d leverage that to get me through this nerdy take on &lt;a href=&#34;https://www.urbandictionary.com/define.php?term=Century%20Club&#34;&gt;Century Club&lt;/a&gt;. But that&amp;rsquo;s not how I&amp;rsquo;ve been doing it.&lt;/p&gt;
&lt;p&gt;Most days I wake up not knowing what I&amp;rsquo;ll write about and wait for inspiration to strike. And then it&amp;rsquo;s a mad dash to get it fleshed out, prettied up, slimmed down, and finally published.&lt;/p&gt;
&lt;h1 id=&#34;the-idea-folder&#34;&gt;The Idea Folder&lt;/h1&gt;
&lt;p&gt;The idea folder doesn&amp;rsquo;t work for me.&lt;/p&gt;
&lt;p&gt;When I look at my pile of ideas, I don&amp;rsquo;t perceive anything like the energy I got when I wrote them down. Even though each was a good blog post in my mind back then, I no longer see them that way at a later date.&lt;/p&gt;
&lt;p&gt;The few times I tried to take an idea from the pile and make it blossom into a full post, it was an agonizing process. It seems I couldn&amp;rsquo;t rekindle with the original flame of the idea and labored to bring it back to life.&lt;/p&gt;
&lt;p&gt;The problem is that writing is inspiration, and you can write an idea down but you can&amp;rsquo;t preserve the inspiration in a notebook.&lt;/p&gt;
&lt;p&gt;Also, writing, to any degree, is a release for that moment of inspiration. Once you&amp;rsquo;ve written it down, even in part, it&amp;rsquo;s been consumed in some way.&lt;/p&gt;
&lt;h1 id=&#34;the-never-ending-draft&#34;&gt;The Never-Ending Draft&lt;/h1&gt;
&lt;p&gt;So writing ideas down doesn&amp;rsquo;t work, but what if I wrote more than an idea? What if I tried to capture the essence of the spark in imperfect written form? Then I could polish it up and publish when it&amp;rsquo;s ready. It seems that should work.&lt;/p&gt;
&lt;p&gt;When I do this, I end up in an endless series of edits.&lt;/p&gt;
&lt;p&gt;My inner perfectionist is a problem here. I know how I get when I try to do good work. It never ends. I&amp;rsquo;ll perpetually rethink the point I&amp;rsquo;m trying to make and then contemplate making this a series of posts instead of a one-off.&lt;/p&gt;
&lt;p&gt;Then I&amp;rsquo;ll second-guess myself. I&amp;rsquo;ll lose my confidence in my idea and decide it&amp;rsquo;s trash, putting it on the backburner until I feel more ready to tackle it (never).&lt;/p&gt;
&lt;p&gt;Drafts to me are like black holes: things only go in, nothing ever comes out.&lt;/p&gt;
&lt;p&gt;Even during this series of daily posts I find myself reading and re-reading, tweaking sentences and trying to make it flow better. If it weren&amp;rsquo;t for &lt;a href=&#34;https://olivierforget.net/blog/2020/dont-miss-your-sleep-train/&#34;&gt;bedtime&lt;/a&gt; and the need to write another one the next day, I&amp;rsquo;d still be on post number one when this pandemic ends.&lt;/p&gt;
&lt;h1 id=&#34;time-pressure&#34;&gt;Time Pressure&lt;/h1&gt;
&lt;p&gt;It all comes down to pressure, the need to get something out. It was my secret weapon in school. I always left essays to the last minute and knocked them out fast when I was low on time.&lt;/p&gt;
&lt;p&gt;This is why #100DaysToOffload is working well for me: I can&amp;rsquo;t get ahead, so it forces me to write under pressure and it works out for me.&lt;/p&gt;
&lt;p&gt;Each day I put my inner perfectionist in the corner, my ideas folder is out of sight, and I wait to catch a spark.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 10 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Mojave Planes From My XCOR Cubicle (Circa 2003)</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/</link>
      <pubDate>Wed, 06 May 2020 19:08:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/</guid>
      <description>&lt;p&gt;A &lt;a href=&#34;https://twitter.com/teleclimber/status/1258194501325053952&#34;&gt;tweet&lt;/a&gt; about an Antonov heavy lift aircraft at LAX reminded me that one such beast had landed in Mojave when I was working there.&lt;/p&gt;
&lt;p&gt;I set off to find pictures of the event in my old files, but we&amp;rsquo;re talking about early 2000s here, and I came up empty. It&amp;rsquo;s very possible I didn&amp;rsquo;t have a camera with me the day they let us look around the inside of the beast. It&amp;rsquo;s also possible there was a photographic record but it&amp;rsquo;s gone. I can&amp;rsquo;t find a single photo that predates 2003!&lt;/p&gt;
&lt;p&gt;I did find a cool pic that proves I&amp;rsquo;m not crazy for remembering this event on &lt;a href=&#34;https://www.jetphotos.com/photo/5762682&#34;&gt;JetPhotos&lt;/a&gt;. A couple more &lt;a href=&#34;https://www.jetphotos.com/showphotos.php?aircraft=Antonov+AN-124%3B&amp;amp;airline=all&amp;amp;country-location=all&amp;amp;photographer-group=all&amp;amp;category=all&amp;amp;keywords-type=all&amp;amp;keywords-contain=3&amp;amp;keywords=mojave&amp;amp;photo-year=2000-2009&amp;amp;genre=all&amp;amp;search-type=Advanced&amp;amp;sort-order=0&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What I did find in my old picture files was a small collection of pics I had taken from my cubicle window while employed at &lt;a href=&#34;https://en.wikipedia.org/wiki/XCOR_Aerospace&#34;&gt;XCOR Aerospace&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;an-office-with-a-view&#34;&gt;An Office With a View&lt;/h1&gt;
&lt;p&gt;Mojave is not an ordinary airport, it&amp;rsquo;s a very active civilian flight test center. Countless unique experimental aircraft have flown and &lt;a href=&#34;https://www.space.com/stratolaunch-flies-worlds-largest-plane-first-time.html&#34;&gt;continue to push the limits&lt;/a&gt; at the desert outpost. And if they&amp;rsquo;re not unique and experimental, they are often in the upper atmosphere of coolness.&lt;/p&gt;
&lt;p&gt;We had moved into the building on the flight-line during my time at the company. Prior to that, we were working out of an old shop with a trailer attached in the middle of blowing tumbleweeds, far from the runway. The move to the flight-line was like moving to the big leagues. &lt;a href=&#34;https://en.wikipedia.org/wiki/Scaled_Composites&#34;&gt;Scaled Composites&lt;/a&gt; used the building to our right, and BAE Systems&#39; &lt;a href=&#34;https://www.baesystems.com/en/article/bae-systems-delivers-its-300th-f4-flying-drone-for-us-air-force&#34;&gt;QF-4 Drones&lt;/a&gt; operation the one to our left.&lt;/p&gt;
&lt;p&gt;That is why Having a window on the flight-line was a treat. My office chair was a front-row seat to some fine aviation geekery.&lt;/p&gt;
&lt;p&gt;I got this idea for a project to take a picture of every cool thing that taxied past or parked in front of my window. And I was going to tape it all up into some sort of mosaic of flying coolness.&lt;/p&gt;
&lt;p&gt;Sadly back then I had to borrow the office&amp;rsquo;s digital camera every time I wanted to take a picture, so my output wasn&amp;rsquo;t a match for what would happen today with a smartphone camera in my pocket.&lt;/p&gt;
&lt;p&gt;Still, I got a few, and for the project to live on I post them here.&lt;/p&gt;
&lt;h1 id=&#34;mosaic-of-flying-coolness&#34;&gt;Mosaic Of Flying Coolness&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s some random helicopter cruising by. Nothing special, but I just wanted to set the scene. You&amp;rsquo;ll notice the window is old. Well, our building was very old, possibly dating back to WWII. When I said we had graduated to the big leagues, I should have said we were the scrappiest team in the big leagues.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/chopper3_hu860597d8de727f9d20c921ab455e0f00_618800_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/chopper3_hu860597d8de727f9d20c921ab455e0f00_618800_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/chopper3_hu860597d8de727f9d20c921ab455e0f00_618800_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;Next up, another mundane aircraft. There was a US Airways 737 parked outside my window for a while. Nothing special, but it was fun having a largish aircraft filling my view.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/us%20airways737-1_hu0d76859f07054f6897f1e0a73fce04e4_693301_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/us%20airways737-1_hu0d76859f07054f6897f1e0a73fce04e4_693301_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/us%20airways737-1_hu0d76859f07054f6897f1e0a73fce04e4_693301_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;Speaking of airliners, there was a DC-10 too at one point. I remember when it arrived. It taxied and parked right in front of me one evening while I was working late. After it shut down I stepped out onto the ramp and walked around it, taking in its giant size. At one point a large forklift showed up and raised a pallet up to the door behind the cockpit. I guess there was no movable stairs handy, so that&amp;rsquo;s how they got the pilots down. The two clean-cut uniformed dudes took a hesitant but brave step from the aircraft onto the pallet and the forklift let them down slowly. Welcome to Mojave boys.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/proteus%20dc10_huae6b6f5bb664a7c7ba230611247cab38_611867_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/proteus%20dc10_huae6b6f5bb664a7c7ba230611247cab38_611867_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/proteus%20dc10_huae6b6f5bb664a7c7ba230611247cab38_611867_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;In the image above, beyond the tail of the DC-10, you can spot Scaled&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Scaled_Composites_Proteus&#34;&gt;Proteus&lt;/a&gt; hanging out outside its nest, probably undergoing checks before a test flight.&lt;/p&gt;
&lt;p&gt;As far as unique aircraft go, this one fits the bill. Only one built, fully experimental, and it&amp;rsquo;s still in service 22 years later, flying experimental payloads for any customer with good money.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/proteus_huef4c9309460b150cb86ab5c482e6d32f_540299_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/proteus_huef4c9309460b150cb86ab5c482e6d32f_540299_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/proteus_huef4c9309460b150cb86ab5c482e6d32f_540299_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;I remember when it was built and rolled out. I was working inside of Scaled&amp;rsquo;s facilities as an employee from a different project that I&amp;rsquo;ll certainly blog about at some point.&lt;/p&gt;
&lt;p&gt;Anyways, I remember the Scaled crew were nice enough to invite me to the rollout, and I probably took pictures back then (1998!) But do I have them? No, no I don&amp;rsquo;t.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/white%20knight%20ss1_huc4f755cdab2b5d83cc67765f35b3b9cb_580795_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/white%20knight%20ss1_huc4f755cdab2b5d83cc67765f35b3b9cb_580795_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/white%20knight%20ss1_huc4f755cdab2b5d83cc67765f35b3b9cb_580795_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;Speaking of Scaled, here is &lt;a href=&#34;https://en.wikipedia.org/wiki/Scaled_Composites_White_Knight&#34;&gt;White Knight&lt;/a&gt;, and if you look closely that&amp;rsquo;s its buddy &lt;a href=&#34;https://en.wikipedia.org/wiki/SpaceShipOne&#34;&gt;SpaceShipOne&lt;/a&gt; tucked underneath.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a pretty lousy photo I know, but the point is that it was shot from my office chair, and what&amp;rsquo;s lousy about that? These days I see SS1 when I visit the &lt;a href=&#34;https://airandspace.si.edu/collection-objects/spaceshipone/nasm_A20050459000&#34;&gt;National Air and Space Museum in Washington DC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I admit I&amp;rsquo;m kind of amazed, 17 years later, that I didn&amp;rsquo;t bother to raise the blinds for this one. Really? Maybe the explanation is we saw Scaled&amp;rsquo;s aircraft go past our windows so many times we didn&amp;rsquo;t exactly jump out of our chairs when they did.&lt;/p&gt;
&lt;p&gt;Judging by the timestamp on the photo, this is early in captive-carry part of the WK+SS1 flight test program. Meaning the SpaceShip had not been dropped yet.&lt;/p&gt;
&lt;p&gt;That might have been &lt;a href=&#34;https://en.wikipedia.org/wiki/Peter_Siebold&#34;&gt;Pete Siebold&lt;/a&gt; flying that day. He was a regular WK pilot early in the program. Much later, he would survive a terrifying accident. He was among the nicer Scaled folks. Always pleasant to talk to, even with us scrappy underdogs.&lt;/p&gt;
&lt;p&gt;RIP Mike A, who did not survive, and was a good guy too.&lt;/p&gt;


  



&lt;img src=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/ez%20rocket_hub81bad1a8c544959a2c04cec09edddf7_659742_800x0_resize_q75_box.jpg&#34; 
    srcset=&#34;https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/ez%20rocket_hub81bad1a8c544959a2c04cec09edddf7_659742_800x0_resize_q75_box.jpg, https://olivierforget.net/blog/2020/cool-planes-from-xcor-mojave/ez%20rocket_hub81bad1a8c544959a2c04cec09edddf7_659742_1600x0_resize_q75_box.jpg 2x&#34;
    alt=&#34;&#34;&gt;
&lt;p&gt;And finally, here&amp;rsquo;s our crew working on the &lt;a href=&#34;https://en.wikipedia.org/wiki/XCOR_EZ-Rocket&#34;&gt;EZ-Rocket&lt;/a&gt;. We never flew the EZ while I was employed at XCOR. They flew it before (I still remember where I was sitting when the whole town first heard that thing fly down the runway), and they flew it and other rocket powered aircraft after I left.&lt;/p&gt;
&lt;p&gt;But just my luck, or lack of luck, somewhat characteristically of my time on various projects at Mojave, nothing great happened while I was there.&lt;/p&gt;
&lt;h1 id=&#34;what-i-have-missed&#34;&gt;What I Have Missed&lt;/h1&gt;
&lt;p&gt;That&amp;rsquo;s a pretty weak set of photos compared to all the things I clearly remember seeing.&lt;/p&gt;
&lt;p&gt;First, the obvious one: where are my F4s at? With BAE next door converting the venerable machines to target drones, there was no shortage of Phantoms going past my window. But I can&amp;rsquo;t find a picture of that right now.&lt;/p&gt;
&lt;p&gt;Then there were all the times I could not have captured the moment because it was fleeting. My friend Mike did better than me, as with this &lt;a href=&#34;http://www.mikemassee.com/gallery/v/aviationandspace/f117_flyby_in_mojave/&#34;&gt;F-117 doing a few flybys&lt;/a&gt; for example.&lt;/p&gt;
&lt;p&gt;Mike also captured that time a vintage &lt;a href=&#34;https://en.wikipedia.org/wiki/Douglas_A-1_Skyraider&#34;&gt;Douglas A-1 Skyraider&lt;/a&gt; came in for a pit stop. OK, it wasn&amp;rsquo;t exactly outside my window, I did have to walk a 100 yards or so but it was grand. Here&amp;rsquo;s a pic of me (at left) &lt;a href=&#34;http://www.mikemassee.com/gallery/v/aviationandspace/bill_anders_and_friend_in_p-51_and_skyraider/CRW_0012.jpg.html&#34;&gt;taking it all in&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Welcome to Mojave people.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 9 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>WFH Tip #2: Don&#39;t Miss Your Sleep Train</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/dont-miss-your-sleep-train/</link>
      <pubDate>Tue, 05 May 2020 14:18:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/dont-miss-your-sleep-train/</guid>
      <description>&lt;p&gt;Last night&amp;rsquo;s blog post on &lt;a href=&#34;https://olivierforget.net/blog/2020/home-automation-thoughts/&#34;&gt;Home Automation&lt;/a&gt; took a lot of work to close up. I started writing before dinner then tried to polish it off quickly after our meal and episode 1 of &lt;a href=&#34;https://www.imdb.com/title/tt6040674/&#34;&gt;Waco&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My goal was to finish quickly because I&amp;rsquo;ve learned that going to bed late, especially if I stay up in front of the computer with my mind engaged, is bad for my sleep and for the next day&amp;rsquo;s productivity.&lt;/p&gt;
&lt;p&gt;The urge to edit didn&amp;rsquo;t subside until close to 11pm, and by then the damage was done. I slept poorly, and I am a total zombie today.&lt;/p&gt;
&lt;p&gt;The bummer is I totally learned this lesson a long time ago. So here it is spelled out in blog post form.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is the second in a series on tips for working from home. The first one was &lt;a href=&#34;https://olivierforget.net/blog/2020/wfh-tip-good-day-off/&#34;&gt;A Good Day Off&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;bed-time-not-wake-up-time&#34;&gt;Bed Time Not Wake Up Time&lt;/h1&gt;
&lt;p&gt;A common refrain among recent home workers is to claim that they&amp;rsquo;ll set their alarm to an early time and that&amp;rsquo;s when they&amp;rsquo;ll get out of bed and start their day.&lt;/p&gt;
&lt;p&gt;Fine in theory, and easy to subscribe to since many normal daily job occupations revolve around dragging ourselves out of bed early enough to get there before the manager makes a point of obviously staring at his watch while you walk to your desk.&lt;/p&gt;
&lt;p&gt;However, if you don&amp;rsquo;t need to start work at a specific time, then skip the alarm clock and worry instead about the time at which you go to bed.&lt;/p&gt;
&lt;p&gt;This seems counterintuitive (&amp;ldquo;with no alarm clock I&amp;rsquo;ll spend the day in bed!&amp;quot;) but it actually works out better, at least for me.&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t used a daily alarm clock in over a decade. I naturally wake up at a reasonable time when my body is rested, which is all that matters.&lt;/p&gt;
&lt;h1 id=&#34;sleep-hours-not-work-hours&#34;&gt;Sleep Hours Not Work Hours&lt;/h1&gt;
&lt;p&gt;Sitting at home, disconnected from co-workers (if you even have co-workers) and pounding out work all day is taxing. It takes energy. Your internal drive isn&amp;rsquo;t free. Anything that can reduce your output will: headaches, fatigue, lack of exercise, too much exercise, etc&amp;hellip;&lt;/p&gt;
&lt;p&gt;Lack of sleep is very high on the list of things that cause me to have a lousy work day. Don&amp;rsquo;t get me wrong I can be slumped at my desk for a full 9 hours, but I&amp;rsquo;ll get little done if I&amp;rsquo;m not rested and ready, and what I will get done probably won&amp;rsquo;t be that great.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re self-employed all that matters is that you get the work done and the work is good. Spending hours in front of the computer being unproductive has no value.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why I focus on sleep hours and my overall wellbeing over a concern for what time I wake up. I rely on my body to tell me when it&amp;rsquo;s ready to tackle the day by waking up naturally. Most days I&amp;rsquo;m out of bed between 7:30 and 8:30.&lt;/p&gt;
&lt;p&gt;There are also days when my body needs to rest, and rest it does. I wake up late, get started late and have to be efficient to get all my work done that day. I may not even get enough work done, but it&amp;rsquo;s still a win because I am well rested and will have the energy to make up for it later in the week.&lt;/p&gt;
&lt;h1 id=&#34;shutoff-time&#34;&gt;Shutoff Time&lt;/h1&gt;
&lt;p&gt;In the early days of my career as a solo dev I had many sleepless nights. The uncertainty led to anxiety and long hours of turning over in my bed like an overcooked rotisserie chicken.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve learned to deal with the uncertainty (you just get used to it) and I&amp;rsquo;ve learned to knock myself to sleep by using what turns out to be some form of &lt;a href=&#34;https://en.wikipedia.org/wiki/Self-hypnosis&#34;&gt;self-hypnosis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But the easiest thing to learn was to get away from my computer by 10pm at the very latest. It takes over an hour for my mind to relax enough to get into a good sleep. If I am still at work past 10, I will miss my natural sleep cycle and end up having a bad night, with the usual consequences.&lt;/p&gt;
&lt;p&gt;This is the rule I broke last night trying to finish my blog post. The night was restless. This morning&amp;rsquo;s programming work was weak, labored, and not fun. I took forever dealing with email because my mind would completely stop focusing on the task at hand and wander pointlessly.&lt;/p&gt;
&lt;p&gt;A bad night&amp;rsquo;s sleep is always followed by a bad day&amp;rsquo;s work.&lt;/p&gt;
&lt;h1 id=&#34;ease-into-sleep&#34;&gt;Ease Into Sleep&lt;/h1&gt;
&lt;p&gt;After closing the laptop and putting the iMac to sleep the next step is a winddown period, which inevitably involves a screen, but that is not work related or overly mind-engaging. Social media, watching videos, movies&amp;hellip; all those are fine.&lt;/p&gt;
&lt;p&gt;After I get to bed I read a book until my eyes feel heavy. Here the idea is to &lt;a href=&#34;https://www.webmd.com/sleep-disorders/features/power-down-better-sleep#1&#34;&gt;avoid all screen time&lt;/a&gt; as I get closer to actually sleeping.&lt;/p&gt;
&lt;p&gt;The only books I read at night are novels (no self-help, deep thoughts, or programming-related stuff, or anything that could bring to the fore current news events). I like books that make me travel to distant lands and faraway times.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s an escape, a dream before I dream.&lt;/p&gt;
&lt;h1 id=&#34;good-night&#34;&gt;Good Night&lt;/h1&gt;
&lt;p&gt;Tonight I&amp;rsquo;m finishing this post before dinner, and I plan on going to bed much earlier.&lt;/p&gt;
&lt;p&gt;Tomorrow will be a better, more productive day.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 8 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Home Automation Thoughts</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/home-automation-thoughts/</link>
      <pubDate>Mon, 04 May 2020 18:55:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/home-automation-thoughts/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m intrigued by &lt;a href=&#34;https://en.wikipedia.org/wiki/Home_automation&#34;&gt;home automation&lt;/a&gt; but I haven&amp;rsquo;t taken the plunge yet. Here are some thoughts on where I stand.&lt;/p&gt;
&lt;h1 id=&#34;internet-of-&#34;&gt;Internet of 💩&lt;/h1&gt;
&lt;p&gt;I follow &lt;a href=&#34;https://twitter.com/internetofshit&#34;&gt;@internetofshit&lt;/a&gt; on twitter for a daily dish of how internet connected devices fail their users in absurd and painful (and sometimes expensive) ways.&lt;/p&gt;
&lt;p&gt;Generally speaking, devices that connect to the manufacturer&amp;rsquo;s servers are iffy. Servers go down or companies pivot or go out of business. Others may just want to push their newest offerings by sabotaging their older products. Sonos &lt;a href=&#34;https://www.theverge.com/2019/12/30/21042871/sonos-recycle-mode-trade-up-program-controversy&#34;&gt;raised eyebrows&lt;/a&gt; earlier this year for wanting to purposefully brick part of its product line.&lt;/p&gt;
&lt;p&gt;Unfortunately most off-the-shelf home automation things are basically a proprietary device that talks to the manufacturer&amp;rsquo;s servers. And if you&amp;rsquo;re lucky enough that it works and stays up for a few years, you also have to contend with what this means for your privacy.&lt;/p&gt;
&lt;h1 id=&#34;internet-of--1&#34;&gt;Internet of 🕵️‍♂️&lt;/h1&gt;
&lt;p&gt;This is the age of &lt;a href=&#34;https://www.theguardian.com/books/2019/feb/02/age-of-surveillance-capitalism-shoshana-zuboff-review&#34;&gt;surveillance capitalism&lt;/a&gt; and any device we have that is connected to some cloud server, whether it&amp;rsquo;s that manufacturer&amp;rsquo;s or something else is likely leaking data about our private lives to corporations.&lt;/p&gt;
&lt;p&gt;Most of this happens by silently shuttling bits of data gathered by the device in any way it can: microphone, camera, motion sensors, and we have only a vague notion of what gets sent, who gets it, and &lt;a href=&#34;https://www.fastcompany.com/90310803/here-are-the-data-brokers-quietly-buying-and-selling-your-personal-information&#34;&gt;where it goes&lt;/a&gt; after that.&lt;/p&gt;
&lt;p&gt;Personally this irks me and I want to have as few such devices as I can live with. The problem with most typical &lt;a href=&#34;https://en.wikipedia.org/wiki/Internet_of_things&#34;&gt;IoT&lt;/a&gt; devices is that the &amp;ldquo;I&amp;rdquo; stands for &amp;ldquo;internet&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;We have a &lt;a href=&#34;https://nest.com/&#34;&gt;Google Nest&lt;/a&gt; thermostat that was installed in the house before we bought it. I have yet to connect it to the wifi, and I may never. The idea of giving big-G still more data about me is irritating. Then again that company probably already knows the genders of our future children, so I may be overreacting, but whatever.&lt;/p&gt;
&lt;h1 id=&#34;do-i-really-want-automation&#34;&gt;Do I Really Want Automation?&lt;/h1&gt;
&lt;p&gt;I find a lot of home automation frivolous. Maybe I&amp;rsquo;m old-school, maybe I just need to experience it to change my mind, but a lot of things I see seem like more effort than they&amp;rsquo;re worth.&lt;/p&gt;
&lt;p&gt;Some people have an automatic &amp;ldquo;movie mode&amp;rdquo; that dims the lights and turns on the TV, etc&amp;hellip; That&amp;rsquo;s fancy, but does it make my life better?&lt;/p&gt;
&lt;p&gt;Add the potential for breakage of a probably brittle system and it sounds like it quickly turns into a nightmare. I imagine these systems are one bad software update from &amp;ldquo;automatically&amp;rdquo; turning the lights on in the bedroom at 3am.&lt;/p&gt;
&lt;p&gt;These are just my impression. I might be wrong. And despite all that there are some things I would like.&lt;/p&gt;
&lt;h1 id=&#34;some-home-automation-things-i-want&#34;&gt;Some Home Automation Things I Want&lt;/h1&gt;
&lt;h4 id=&#34;thermostat&#34;&gt;Thermostat&lt;/h4&gt;
&lt;p&gt;I can get up to change the temperature, but it would be nice not to have to run downstairs to do that. Even better, some &amp;ldquo;smart&amp;rdquo; thermostats let you add environment sensors in different rooms with the promise that the temperature will be ideal for the room you&amp;rsquo;re in, not the hallway downstairs where the thermostat is.&lt;/p&gt;
&lt;p&gt;Google&amp;rsquo;s Nest has one of the &lt;a href=&#34;https://www.theverge.com/2018/9/5/17820594/nest-thermostat-remote-temperature-sensors-review-price-specs&#34;&gt;dumbest ones on the market&lt;/a&gt; so I&amp;rsquo;m unlikely to burrow further into that ecosystem. Hey that&amp;rsquo;s a good thing.&lt;/p&gt;
&lt;h4 id=&#34;cameras&#34;&gt;Cameras&lt;/h4&gt;
&lt;p&gt;We need to add a few security cameras to our new home. Some for outside and some to keep an eye on the kiddo.&lt;/p&gt;
&lt;p&gt;I want to view the footage from my phone, but I don&amp;rsquo;t want this potentially private stream going far into the cyber universe outside my control. I&amp;rsquo;m bothered by all my neighbor&amp;rsquo;s Ring cameras and &lt;a href=&#34;https://arstechnica.com/tech-policy/2019/11/cops-can-keep-ring-footage-forever-share-it-with-anyone-amazon-confirms/&#34;&gt;where that footage goes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I worry about hacks too. The manufacturer&amp;rsquo;s servers and the device itself are potential avenues for &lt;a href=&#34;https://www.washingtonpost.com/technology/2018/12/20/nest-cam-baby-monitor-hacked-kidnap-threat-came-device-parents-say/&#34;&gt;problems&lt;/a&gt;. I may even want to prevent the stream from ever leaving the home network, but will the device let me?&lt;/p&gt;
&lt;h4 id=&#34;problem-detectors&#34;&gt;Problem Detectors&lt;/h4&gt;
&lt;p&gt;Yesterday morning I found a small puddle of water on the floor in the kitchen. Confused, I opened the nearest cabinet to figure out where the water was coming from. That cabinet, which happens to be under the sink, was full of water. No major damage, but it reminded me of a good use case for IoT: sensors to detect problems before they get expensive.&lt;/p&gt;
&lt;p&gt;I can imagine putting water detection sensors under all the sinks, by the water heater in the garage, and perhaps near sliding doors in case it rains. Now that would be worth it.&lt;/p&gt;
&lt;h1 id=&#34;home-automation-soup&#34;&gt;Home Automation Soup&lt;/h1&gt;
&lt;p&gt;Dejected by the surveillance capitalists I turn my nose at their offerings and dive into the DIY, open source, home automation community. I find tons of projects and there are people doing &lt;a href=&#34;https://youtu.be/eaPAhYscCZw&#34;&gt;amazing things&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is just one problem: it&amp;rsquo;s a total soup. I have no idea what&amp;rsquo;s what. The other day I saw a this tweet by &lt;a href=&#34;https://www.home-assistant.io/&#34;&gt;Home Assistant&lt;/a&gt; creator Paulus Schoutsen:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After @andreadonno showed off the pn532 working with esphome I had to try. Spend the evening and with a lot of me bugging him on Discord.. but it is working now! Also able to scan cards with the rdm6300 as that would work with my existing Magic Cards cards. &amp;ndash; &lt;a href=&#34;https://twitter.com/balloob/status/1257195162553335808&#34;&gt;@balloob&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I do not know what he&amp;rsquo;s talking about. All I know is some highly experienced HA hacker took a long time to get something to work. This does not bode well for me.&lt;/p&gt;
&lt;p&gt;I did figure out that &lt;a href=&#34;https://esphome.io/&#34;&gt;ESPHome&lt;/a&gt; refers to a software thing that helps you run things that are powered by an ESP8266 or ESP32 chip.&lt;/p&gt;
&lt;p&gt;Cool. So I know about a chip. I&amp;rsquo;m sure I&amp;rsquo;m just a few web searches away from figuring out how to have my phone notify me of a leaky faucet.&lt;/p&gt;
&lt;p&gt;Look, this is a hobby. I would love to use FOSS and open devices and assemble it all using my own ingenuity, but it will take time that I don&amp;rsquo;t have right now. (At least not for another &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;93 days&lt;/a&gt;.)&lt;/p&gt;
&lt;h1 id=&#34;living-in-a-manual-world-for-now&#34;&gt;Living In A Manual World (For Now)&lt;/h1&gt;
&lt;p&gt;Home automation will have to wait as long as I don&amp;rsquo;t want to hand more data over to various companies.&lt;/p&gt;
&lt;p&gt;I have denied my thermostat a connection to its mothership, and I get some exercise by going up and down the stairs to tweak the temperature setting on hot days.&lt;/p&gt;
&lt;p&gt;I pray my plumbing holds and I don&amp;rsquo;t forget to close a window.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s fine, for now.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 7 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>WFH Tip: A Good Day Off</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/wfh-tip-good-day-off/</link>
      <pubDate>Sun, 03 May 2020 17:08:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/wfh-tip-good-day-off/</guid>
      <description>&lt;p&gt;Today is my day off for the week.&lt;/p&gt;
&lt;p&gt;Unlike many people being at home all the time is normal for me. I&amp;rsquo;m used to it. Over the years I&amp;rsquo;ve learned techniques and patterns that make this life work well.&lt;/p&gt;
&lt;p&gt;How many years you ask?&lt;/p&gt;
&lt;p&gt;Thirteen years.&lt;/p&gt;
&lt;p&gt;In the Spring of 2007 I stepped out of my cubicle at the small aerospace engineering office that no longer employed me, and have not been back to a &amp;ldquo;place of work&amp;rdquo; since. I also haven&amp;rsquo;t had a boss since then (other than myself).&lt;/p&gt;
&lt;p&gt;Over the years I have assembled many little tips and tricks to get through the day. With &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;94 blog posts left to write&lt;/a&gt; I&amp;rsquo;ll get around to most of them.&lt;/p&gt;
&lt;h1 id=&#34;one-day-off-every-seven&#34;&gt;One Day Off Every Seven&lt;/h1&gt;
&lt;p&gt;One day out of every seven has to be a full day off. If I don&amp;rsquo;t take a true day off regularly my fatigue grows and my mood drops as the days blend into each-other. Inevitably my productivity becomes worse than if I actually stopped working.&lt;/p&gt;
&lt;p&gt;Yesterday I failed to accomplish all the work hours I set out to do for the week. Working at home with a baby doesn&amp;rsquo;t always work out the way you want. Despite that, it is more important to take today fully off than to meet my work goals.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Why didn&amp;rsquo;t you do a bit of work in the morning and then take your day off?&amp;rdquo; you might ask. Nope. That&amp;rsquo;s not how it works. During a &amp;ldquo;day off&amp;rdquo; you must&amp;hellip;&lt;/p&gt;
&lt;h4 id=&#34;do-no-work-at-all&#34;&gt;Do No Work At All&lt;/h4&gt;
&lt;p&gt;A day off has to be completely free of work, from the moment you wake up to the moment you go to sleep.&lt;/p&gt;
&lt;p&gt;Ignore emails and everything else. Try not to think about it. Unless your servers are on fire, just ignore it.&lt;/p&gt;
&lt;h4 id=&#34;do-nothing-at-all&#34;&gt;Do Nothing At All&lt;/h4&gt;
&lt;p&gt;During the day off it&amp;rsquo;s important to have time to just lounge and feel like you&amp;rsquo;re doing nothing, and be OK with that.&lt;/p&gt;
&lt;p&gt;During a work day from home, the pressure to get things done and the energy it takes to self-motivate can be draining.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why you have to have moments where you deliberately do nothing, or nothing of any value. Be fully aware of your state of unproductivity, and bask in it. It&amp;rsquo;s a good thing.&lt;/p&gt;
&lt;p&gt;I made the mistake in the past of doing something elaborate on a &amp;ldquo;day off&amp;rdquo;, like going on a day trip, or going sailing. These are tricky. It can feel very nice, but if you have to rush, or work hard planning and organizing it&amp;rsquo;s best to plan another real day off soon after.&lt;/p&gt;
&lt;h4 id=&#34;do-some-chores&#34;&gt;Do Some Chores&lt;/h4&gt;
&lt;p&gt;Yes I know I said &amp;ldquo;day off&amp;rdquo; and &amp;ldquo;do nothing&amp;rdquo;, but here&amp;rsquo;s the thing. On typical work days, there is little time to do things around the house that need doing.&lt;/p&gt;
&lt;p&gt;These end up weighing on your mind, and can distract while you&amp;rsquo;re trying to work.&lt;/p&gt;
&lt;p&gt;Doing something useful can help you feel good about yourself. It&amp;rsquo;s the flip side of doing nothing: you&amp;rsquo;ll feel good for taking something off your to-do list.&lt;/p&gt;
&lt;p&gt;A good day off is a careful balance of doing absolutely nothing part of the time, and checking some chores off your list.&lt;/p&gt;
&lt;h4 id=&#34;avoid-side-projects&#34;&gt;Avoid Side Projects&lt;/h4&gt;
&lt;p&gt;If you have side-projects, only work on the ones that are distant enough from actual work. I avoid all forms of code.&lt;/p&gt;
&lt;p&gt;I almost skipped writing my daily blog post for &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; (my 6th) but I think writing is relaxing enough, and I&amp;rsquo;m not writing about code.&lt;/p&gt;
&lt;p&gt;However, I&amp;rsquo;ll keep it short.&lt;/p&gt;
&lt;h1 id=&#34;get-more-done-next-week&#34;&gt;Get More Done Next Week&lt;/h1&gt;
&lt;p&gt;Take a day off, a real one, regularly. Take two if you can. Enjoy doing nothing, and you&amp;rsquo;ll do more next week.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>This Is a Bicycle For The Mind</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/this-is-bicycle-for-the-mind/</link>
      <pubDate>Sat, 02 May 2020 19:22:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/this-is-bicycle-for-the-mind/</guid>
      <description>&lt;p&gt;I was working on a project today and found myself struggling to keep a mental model of the architecture. The project has been growing for many months and it&amp;rsquo;s gotten a bit hairy, particularly since I am constantly rethinking how it needs to be put together.&lt;/p&gt;
&lt;p&gt;The code itself is fairly readable since Go lends itself well to that, but the high level view is not always clear in my head.&lt;/p&gt;
&lt;p&gt;Today in particular I felt the need to give my mind a diagram that shows the relation between the different systems. I reached for my favorite tools for that kind of work: the Lenovo Yoga Book and DrawExpress.&lt;/p&gt;
&lt;h1 id=&#34;the-yoga-book&#34;&gt;The Yoga Book&lt;/h1&gt;
&lt;p&gt;Look, it&amp;rsquo;s flawed, it&amp;rsquo;s weird, it&amp;rsquo;s probably not the tablet you want to own, but to me it&amp;rsquo;s the bee&amp;rsquo;s knees (I don&amp;rsquo;t know what that means, but knees bend and so does this tablet).&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://www.theverge.com/2016/10/17/13289506/lenovo-yoga-book-review&#34;&gt;Lenovo Yoga Book&lt;/a&gt; is a tablet with a full-size digitizer attached. It feels like a slightly thick and slightly heavy tablet when the digitizer is folded against the back of the screen, but unfold it and you have an extremely light and thin device.&lt;/p&gt;
&lt;p&gt;With the digitizer out the tablet becomes a magnificent drawing device. Here&amp;rsquo;s why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The digitizer surface has a texture that makes the plastic stylus feel a bit like pencil on paper. When I draw on glass surfaces, as in a normal tablet, I find the &amp;ldquo;skating on glass&amp;rdquo; feel throws my drawing off.&lt;/li&gt;
&lt;li&gt;With the digitizer to the side of the screen or below it, I always see all of my drawing. When drawing on the upper left side of a tablet (or a piece of paper!) my hand covers the rest of my drawing, and I find myself moving my hand a lot more.&lt;/li&gt;
&lt;li&gt;No need to worry about my palm registering as an input. Some tablets have great palm rejection, and for others it&amp;rsquo;s necessary to wear weird gloves when drawing on touchscreens. I can&amp;rsquo;t relate. I can smother the digitizer surface with my palm and it registers nothing.&lt;/li&gt;
&lt;li&gt;I use both hands: one to pinch-to-zoom, one to draw. Each hand is on its own half of the device, so I don&amp;rsquo;t need to move them much. It&amp;rsquo;s efficient and steady.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This tablet has plenty of flaws (have a look at the negative reviews on &lt;a href=&#34;https://www.amazon.com/Lenovo-Yoga-Book-Processor-ZA0V0035US/dp/B01MQSLK2Z/&#34;&gt;Amazon&lt;/a&gt;) but the magic of the drawing experience makes it one of my favorite devices ever.&lt;/p&gt;
&lt;p&gt;So that&amp;rsquo;s the hardware.&lt;/p&gt;
&lt;h1 id=&#34;drawexpress&#34;&gt;DrawExpress&lt;/h1&gt;
&lt;p&gt;There are all kinds of drawing apps for mobile devices. Most simply retrace the movement of your stylus or finger using a brush of some sort. If you don&amp;rsquo;t have a steady hand you end up with horrifying squiggles. Hardly helpful.&lt;/p&gt;
&lt;p&gt;I use these drawing apps too, but if I am out of practice my drawings are just painful to look at.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://drawexpress.com/&#34;&gt;DrawExpress&lt;/a&gt; is different. It&amp;rsquo;s not a drawing app so much as it is gesture recognition interface with line-and-box drawing as its output.&lt;/p&gt;
&lt;p&gt;DrawExpress doesn&amp;rsquo;t just log and retrace your trembly squiggles, instead it recognizes that what you drew looks kind of like a rectangle, so it draws a perfect rectangle for you. Trace a drunk circle that misses closing at its starting point by a mile, and it will draw a perfect one for you.&lt;/p&gt;
&lt;p&gt;If you draw a line from more-or-less one rectangle to more-or-less another one, it draws a straight line connecting the two. Draw a arrowhead at the end of the line and guess what? The line becomes an arrow. And if the line is curved but bumpy, you&amp;rsquo;ll get a smooth curve. And so on.&lt;/p&gt;
&lt;p&gt;Gestures aren&amp;rsquo;t just used for drawing, they&amp;rsquo;re for editing too. For example, tap a shape to select, then delete it by drawing an X on it.&lt;/p&gt;
&lt;p&gt;I find this amazing. Think of how pretty much everything works on a computer: you find a button, and you hit the button. The button might be drawn in the UI, or it might be the del key on your keyboard, but it&amp;rsquo;s a button and your only interaction with it is to click it, tap it, or smash it. Future humans will find this amusingly primitive.&lt;/p&gt;
&lt;p&gt;I find that when I draw an &amp;lsquo;X&amp;rsquo; to remove something I am no longer communicating through a UI that I am aware of. It&amp;rsquo;s like my hand is the UI again, but now it&amp;rsquo;s incredibly stable and capable. It can make a perfect rectangle appear, and then disappear in a snap.&lt;/p&gt;
&lt;p&gt;The video on DrawExpress&amp;rsquo;s site is broken, but it&amp;rsquo;s worth watching the one in the &lt;a href=&#34;https://play.google.com/store/apps/details?id=com.drawexpress.full&#34;&gt;Play Store&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;my-mind-went-bicycling&#34;&gt;My Mind Went Bicycling&lt;/h1&gt;
&lt;p&gt;So this afternoon I pulled out the Lenovo, went all over the house looking for the stylus (I don&amp;rsquo;t use it that often, and where do you keep a pen-like thing that doesn&amp;rsquo;t write on paper?) and sat down at my desk.&lt;/p&gt;
&lt;p&gt;With the code up on the iMac and the tablet where my keyboard normally is I set out to trace relations in my code. What object owns what? Who&amp;rsquo;s communicating with who?&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t set out to do a formal diagram like UML or any such thing (though you can do that in DE), I just wanted to turn a mental hairball into something understandable.&lt;/p&gt;
&lt;p&gt;From mental hairball, I drew squiggly ugly lines, and from those I ended up with this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;listener-services.svg&#34; alt=&#34;Diagram showing relations between boxes&#34;&gt;&lt;/p&gt;
&lt;p&gt;Looks simple doesn&amp;rsquo;t it? Yep, that&amp;rsquo;s the point.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 5 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Should I Write a New Protocol?</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/should-i-write-a-protocol/</link>
      <pubDate>Fri, 01 May 2020 14:22:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/should-i-write-a-protocol/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m finding myself in need of a protocol to communicate between two processes, and I can&amp;rsquo;t find what I want.&lt;/p&gt;
&lt;p&gt;The two processes will communicate over a &lt;a href=&#34;http://man7.org/linux/man-pages/man7/unix.7.html&#34;&gt;Unix Socket&lt;/a&gt; in a peer-to-peer fashion. This is a very straightforward situation that I thought I would be able to handle trivially.&lt;/p&gt;
&lt;p&gt;It is, of course, very easy for two processes to exchange bytes over a unix socket. The web is full of tutorials on writing various &amp;ldquo;Hello World&amp;rdquo; and echo services over unix sockets.&lt;/p&gt;
&lt;p&gt;There are also many data packaging and serialization protocols, such as the aptly named &lt;a href=&#34;https://msgpack.org/&#34;&gt;msgpack&lt;/a&gt;, or the tried and true &lt;a href=&#34;https://www.json.org/json-en.html&#34;&gt;JSON&lt;/a&gt;, and &lt;a href=&#34;https://developers.google.com/protocol-buffers/&#34;&gt;Protocol Buffers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What I found to be missing is the bits in between. On a streaming unix socket, there are no inherent message frames, or message request-response paradigms, so it&amp;rsquo;s entirely up to you to work that out.&lt;/p&gt;
&lt;p&gt;There are a few such protocols available, but most seem to be too heavy, or are less than ideal for one reason or another.&lt;/p&gt;
&lt;h1 id=&#34;what-i-am-looking-for&#34;&gt;What I Am Looking For&lt;/h1&gt;
&lt;p&gt;Here is what I would like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lean, fast, lightweight. This needs to run on low power devices.&lt;/li&gt;
&lt;li&gt;Message payloads should be binary or plain text. Not JSON. I want full flexibility to pass anything as payload, and I do not want to &lt;a href=&#34;https://stackoverflow.com/questions/1443158/binary-data-in-json-string-something-better-than-base64&#34;&gt;coerce binary data into a JSON string&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;There are multiple different services at each end of the connection, so the protocol should include metadata that identifies the service that should receive the message without decoding the payload.&lt;/li&gt;
&lt;li&gt;The protocol should pass metadata that tells the service how to handle the payload. Think of this as the function that the service has to call.&lt;/li&gt;
&lt;li&gt;Protocol should support request/response, and request/multi-response (to get rows from a DB as individual messages instead of one giant lump).&lt;/li&gt;
&lt;li&gt;All messages passed should get a response indicating whether its processing was successful or not.&lt;/li&gt;
&lt;li&gt;Support multiple simultaneous asynchronous messages.&lt;/li&gt;
&lt;li&gt;Go and Typescript implementations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While I am itching to roll my own (being in over my head yet learning something along the way is an appealing cocktail of emotions), I did look into existing solutions.&lt;/p&gt;
&lt;h1 id=&#34;existing-protocols&#34;&gt;Existing Protocols&lt;/h1&gt;
&lt;h4 id=&#34;netstringshttpsenwikipediaorgwikinetstring&#34;&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Netstring&#34;&gt;NetStrings&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;NetStrings  is the simplest of protocols. It fails to meet my needs but I absolutely love the minimalism.&lt;/p&gt;
&lt;p&gt;When I first looked into this I thought I could just use NetStrings. But once I added the need to forward payloads to different services, and to pass other metadata (including message ids) I found myself creating &amp;ldquo;Netstrings With Metadata&amp;rdquo; and it got complicated.&lt;/p&gt;
&lt;h4 id=&#34;msgpack-rpchttpsgithubcommsgpack-rpcmsgpack-rpcblobmasterspecmd&#34;&gt;&lt;a href=&#34;https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md&#34;&gt;MsgPack-RPC&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;MsgPack is appealing, so its RPC extension should be as well, right? Turns out it&amp;rsquo;s a bit underwhelming for my needs: it only supports request-response.&lt;/p&gt;
&lt;h4 id=&#34;wamphttpswamp-protoorg&#34;&gt;&lt;a href=&#34;https://wamp-proto.org/&#34;&gt;WAMP&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;WAMP is a &lt;a href=&#34;https://en.wikipedia.org/wiki/WebSocket&#34;&gt;websocket subprotocol&lt;/a&gt;, but it can be used over unix sockets as well. It looks like it is essentially what I need. The Go project that supports it is called &lt;a href=&#34;https://github.com/gammazero/nexus&#34;&gt;Nexus&lt;/a&gt;, and it looks solid if maybe more than what I need.&lt;/p&gt;
&lt;p&gt;If I fail at rolling my own this is a good candidate to rescue me.&lt;/p&gt;
&lt;h4 id=&#34;stomphttpsstompgithubio&#34;&gt;&lt;a href=&#34;https://stomp.github.io/&#34;&gt;Stomp&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;According to their home page STOMP &amp;ldquo;comes from the http school of design&amp;rdquo;, and taking a very brief look at their protocol, I do see the family resemblance. I&amp;rsquo;m looking for something that uses fewer messages. I don&amp;rsquo;t need a lot of connection stuff because I&amp;rsquo;m essentially hooking up two processes, that&amp;rsquo;s it.&lt;/p&gt;
&lt;h4 id=&#34;zero-mqhttpszeromqorg&#34;&gt;&lt;a href=&#34;https://zeromq.org/&#34;&gt;Zero-MQ&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;ØMQ is rad, and venerable, and I&amp;rsquo;ve always been interested in it but never got to use it. Looking at all it &lt;em&gt;can&lt;/em&gt; do, it seems overkill for my needs right now.&lt;/p&gt;
&lt;p&gt;I should look more at it, I just have a resistance to &amp;ldquo;everything and the kitchen sink&amp;rdquo; type of solutions to small problems.&lt;/p&gt;
&lt;h4 id=&#34;hessianhttphessiancauchocom&#34;&gt;&lt;a href=&#34;http://hessian.caucho.com/&#34;&gt;Hessian&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I came across this so I&amp;rsquo;m including it, but it looks dated. No support for Go means it&amp;rsquo;s DOA as far as I&amp;rsquo;m concerned. Moving on.&lt;/p&gt;
&lt;h4 id=&#34;beephttpbeepcoreorg&#34;&gt;&lt;a href=&#34;http://beepcore.org/&#34;&gt;BEEP&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Dated, and way too verbose (it uses a subset of XML), but I found some interesting pages about &lt;a href=&#34;http://beepcore.org/sl-beep.html&#34;&gt;protocol design&lt;/a&gt; on their site.&lt;/p&gt;
&lt;h4 id=&#34;aqmphttpswwwamqporg&#34;&gt;&lt;a href=&#34;https://www.amqp.org/&#34;&gt;AQMP&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This is an enterprise grade standard. Looks like it&amp;rsquo;s too much for what I need. The bare minimum message is already much bigger than what I have in mind.&lt;/p&gt;
&lt;h4 id=&#34;mqtthttpsmqttorg&#34;&gt;&lt;a href=&#34;https://mqtt.org/&#34;&gt;MQTT&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This caught my attention because the acronym comes up in &lt;a href=&#34;https://www.home-assistant.io/integrations/mqtt/&#34;&gt;home automation systems&lt;/a&gt;. But it&amp;rsquo;s a protocol for telemetry, so not what I&amp;rsquo;m looking for in this context.&lt;/p&gt;
&lt;h4 id=&#34;what-did-i-miss&#34;&gt;What Did I Miss?&lt;/h4&gt;
&lt;p&gt;If you know of something I should look at please ping me.&lt;/p&gt;
&lt;h1 id=&#34;what-now&#34;&gt;What Now?&lt;/h1&gt;
&lt;p&gt;I started an implementation of something that might work in Go. It&amp;rsquo;s rough and I&amp;rsquo;m not very confident about it. So I keep going back to learning more about existing protocols to see if it&amp;rsquo;s less trouble to adapt to something non-ideal than to roll my own.&lt;/p&gt;
&lt;p&gt;Expect more posts about this as I work through the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge. (Today was day 4.)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Walled Wide Web</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/walled-wide-web/</link>
      <pubDate>Thu, 30 Apr 2020 13:14:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/walled-wide-web/</guid>
      <description>&lt;p&gt;There is a situation developing on the World-Wide-Web that runs completely against its ethos.&lt;/p&gt;
&lt;p&gt;I am talking about the growing number of news websites that require that you are signed-in, and possibly a paying member to read their articles.&lt;/p&gt;
&lt;p&gt;From the web peruser&amp;rsquo;s point of view, it&amp;rsquo;s a terrible experience. You might be reading your feed on social media and decide to click on a link to read the actual article (instead of just piling on in the replies) but then, bam:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Paywall&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Instead of navigating effortlessly to an article you were interested in you just hit a wall. Your flow is disrupted. No login? No subscription? You&amp;rsquo;re out. Go back to where you came from.&lt;/p&gt;
&lt;p&gt;The problem here is not that news sites should not get paid (they should), or that I don&amp;rsquo;t want to pay (I&amp;rsquo;m willing, and I currently do for a couple outlets), it&amp;rsquo;s that putting paywalls around entire sites goes completely against the grain of the WWW.&lt;/p&gt;
&lt;h1 id=&#34;the-world-wide-web&#34;&gt;The World Wide Web&lt;/h1&gt;
&lt;p&gt;The promise of the web is that you can read a document, and in that document there are &amp;ldquo;links&amp;rdquo; to further information that expand and go deeper on whatever text was around that link.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s an incredibly powerful concept that accelerates the development of knowledge. A link can serve as a path to &amp;ldquo;more info&amp;rdquo;, or as &amp;ldquo;proof is here&amp;rdquo;, or as &amp;ldquo;you might also be interested in&amp;rdquo;, or as &amp;ldquo;here is where I got the original idea&amp;rdquo;, etc&amp;hellip;&lt;/p&gt;
&lt;p&gt;To click on a link is to effortlessly float from world to world because the mind yearns and I made the smallest of physical efforts.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s such a powerful thing that people refer to &amp;ldquo;going down the rabbit hole&amp;rdquo; when they set out to follow links and get engrossed in a topic that may or may not have been what originally &lt;a href=&#34;https://en.wikipedia.org/wiki/White_Rabbit&#34;&gt;made them curious&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In fact one of three reactions to my &lt;a href=&#34;https://olivierforget.net/blog/2020/bad-elon/&#34;&gt;post on Elon Musk&lt;/a&gt; yesterday was a &lt;a href=&#34;https://fosstodon.org/@g/104088641386426279&#34;&gt;request that I add links&lt;/a&gt; to the things I was talking about! (I wanted to but ran out of time, such is the life of a &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; blogger.)&lt;/p&gt;
&lt;p&gt;I highly recommend perusing the original &lt;a href=&#34;https://www.w3.org/History/1989/proposal.html&#34;&gt;proposal for the web&lt;/a&gt; by &lt;a href=&#34;https://en.wikipedia.org/wiki/Tim_Berners-Lee&#34;&gt;Tim Berners-Lee&lt;/a&gt;. It&amp;rsquo;s good to be reminded of the original vision for the web once in a while.&lt;/p&gt;
&lt;h1 id=&#34;the-walled-wide-web&#34;&gt;The Walled Wide Web&lt;/h1&gt;
&lt;p&gt;In these pandemic times, there is news coming out of everywhere, lots of which is important and I find myself clicking through to more news sites than usual. Unfortunately, it hardly feels like the golden age of information availability.&lt;/p&gt;
&lt;p&gt;During my morning reading time, I might need a dozen different logins to read what I clicked on. What are the odds that I have a login for some news site in Nebraska? Am I going to sit there and type in all my info to create a login just to read one article? No way.&lt;/p&gt;
&lt;p&gt;So I hit the back button, disappointed, cheated out of the information I was teased, and that much less confident I know what I need to know.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&#34;https://www.w3.org/History/1989/proposal.html&#34;&gt;original proposal for the web&lt;/a&gt; there is the idea that any page author can create a link to another page, without seeking authorization from that other page&amp;rsquo;s author. The implication here is that all pages are part of one system, and they can all cross-link without concern for boundaries.&lt;/p&gt;
&lt;p&gt;The web is meant to enable the free movement of information travelers. That&amp;rsquo;s the point. The whole point. Paywalls are like walls along borders: they keep people out, break their flow of travel.&lt;/p&gt;
&lt;h1 id=&#34;the-solution&#34;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;I don&amp;rsquo;t have one, sorry. This is a difficult problem that involves a lot more than just some opinion on what the web &amp;ldquo;is supposed to be&amp;rdquo;. News costs money to make, and that&amp;rsquo;s a huge constraint. Still, a few things are being tried:&lt;/p&gt;
&lt;h4 id=&#34;no-paywall&#34;&gt;No Paywall&lt;/h4&gt;
&lt;p&gt;The Guardian rejects paywalls and instead make a plea to those who can afford &lt;a href=&#34;https://support.theguardian.com/us/subscribe&#34;&gt;to subscribe&lt;/a&gt;. They also have some lower level app-only subscriptions. This is one of the ones I pay for.&lt;/p&gt;
&lt;h4 id=&#34;micropayments&#34;&gt;MicroPayments&lt;/h4&gt;
&lt;p&gt;The idea here would be to allow people to pay per-article in some way. It&amp;rsquo;s probably a &lt;a href=&#34;https://medium.com/@wfederman/micropayments-for-news-articles-are-a-terrible-horrible-no-good-very-bad-idea-267930d95a3a&#34;&gt;terrible idea&lt;/a&gt; (warning: Medium link).&lt;/p&gt;
&lt;h4 id=&#34;bundles&#34;&gt;Bundles&lt;/h4&gt;
&lt;p&gt;My friend Josh tweeted this today (and set me on course to write this post):&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;I end up paying for no media subscriptions because I’m always flipping through headlines and sites but would almost certainly pay $20/MO for deeper all-in-one access.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ndash; &lt;a href=&#34;https://twitter.com/joshuakrafchin/status/1255902254189522947&#34;&gt;@joshuakrafchin&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Apparently that&amp;rsquo;s what &lt;a href=&#34;https://www.apple.com/apple-news/&#34;&gt;Apple News+&lt;/a&gt; is. But now you&amp;rsquo;ve jumped into a different walled garden.&lt;/p&gt;
&lt;h1 id=&#34;keep-it-open&#34;&gt;Keep It Open&lt;/h1&gt;
&lt;p&gt;Like I said I don&amp;rsquo;t have a solution. I just know you can link to this page if you want to, and I won&amp;rsquo;t throw a paywall up at you.&lt;/p&gt;
&lt;p&gt;PS: Today is the 27th anniversary of TBL putting the &lt;a href=&#34;https://cds.cern.ch/record/1164399&#34;&gt;www in the public domain&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 3 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Bad Elon</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/bad-elon/</link>
      <pubDate>Wed, 29 Apr 2020 13:15:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/bad-elon/</guid>
      <description>&lt;p&gt;I checked Twitter briefly last night before going to sleep. Bit of a mistake. I saw something I did not like and it caused me to spend some time feeling uncomfortable as I was trying to sleep.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m talking about Elon Musk suddenly aligning fully with the &amp;ldquo;Freedom&amp;rdquo; protesters.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s backtrack a bit in case this gets read at some future date.&lt;/p&gt;
&lt;h1 id=&#34;we-are-in-a-pandemic&#34;&gt;We Are In A Pandemic&lt;/h1&gt;
&lt;p&gt;It&amp;rsquo;s 2020, we&amp;rsquo;re in the middle of a pandemic courtesy of the COVID19 virus. In the US, things aren&amp;rsquo;t going great. The US has more deaths than any country. We&amp;rsquo;re all under some degree of &amp;ldquo;stay-at-home&amp;rdquo; orders from various authorities. According to experts this is the only way to keep the number of cases low enough to not overwhelm the healthcare system until we come up with a vaccine or a cure. It could also give them time to gain enough of an understanding of the virus to know how to tame it with a less blunt hammer than &amp;ldquo;everybody stay home&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The economy is taking a huge hit, that&amp;rsquo;s undeniable, and people would like to work. I don&amp;rsquo;t envy those in charge. There are a lot of unknowns, research is hastily published with contradictory results, and consequences of getting it wrong can be dire.&lt;/p&gt;
&lt;p&gt;These are tough times, but most of the country seems to agree that we need to do the right thing to prevent deaths of those who are vulnerable: the old, those with other medical conditions, and of course healthcare workers.&lt;/p&gt;
&lt;p&gt;In the midst of this debate some people have decided that the right course of action is to flaunt all public orders, all health recommendations, and even all logic by going out onto the streets without masks, and sometimes with guns. In some cases, medical professionals have showed up to counter-protest, setting up for news photographers to capture some painful imagery: angry people, decked out to go to war, yelling at nurses and doctors.&lt;/p&gt;
&lt;p&gt;Do I need to type an argument defending the role and value of healthcare workers during a pandemic? I hope this is a low point in American culture and politics, because it&amp;rsquo;s just painful to watch.&lt;/p&gt;
&lt;p&gt;All these protesters rallied around a call for freedom. It&amp;rsquo;s usually written in caps (&amp;ldquo;FREEDOM&amp;rdquo;) because they&amp;rsquo;re yelling in anger, possibly at a nurse. They were encouraged by our Dear Leader, always the promoter of divisive causes.&lt;/p&gt;
&lt;p&gt;So that&amp;rsquo;s the context.&lt;/p&gt;
&lt;h1 id=&#34;back-to-elon&#34;&gt;Back To Elon&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m a big fan of SpaceX and Tesla. Both companies have done so much to upend their respective industries. These successes pull at my heart strings as an aerospace engineer and environmentally conscious Californian (we own a Tesla and love it). Unlike some people I can&amp;rsquo;t imagine these companies would be as successful (and in the case of SpaceX, even exist) if the man at the top was not Elon Musk.&lt;/p&gt;
&lt;p&gt;Elon gets a lot of crap for his attempts to help when the world is rallying around a cause. In most cases I think he&amp;rsquo;s genuinely trying to do good.&lt;/p&gt;
&lt;p&gt;So last night as I took a last look at Twitter I saw this gut punch of a tweet:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;a href=&#34;https://twitter.com/elonmusk/status/1255380013488189440&#34;&gt;FREE AMERICA NOW&lt;/a&gt;&amp;rdquo; &amp;ndash; @ElonMusk&lt;/p&gt;
&lt;p&gt;I imagine this wild cry into the night by a man who owns many factories has something to do with his personal finances.&lt;/p&gt;
&lt;p&gt;Most of the time I feel Ok brushing off his more unsavory tweets. I know he&amp;rsquo;s a flawed character, there is ample evidence of that. I don&amp;rsquo;t defend his BS, and I don&amp;rsquo;t make excuses. He&amp;rsquo;s a dude with lots of capabilities and plenty of flaws too. When tweets come, I know sometimes I&amp;rsquo;ll have to shake my head or sigh.&lt;/p&gt;
&lt;p&gt;This one just stings.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This was day 2 of the &lt;a href=&#34;https://100daystooffload.com/&#34;&gt;#100DaysToOffload&lt;/a&gt; challenge.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>100 Days To Offload</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2020/100-days-to-offload/</link>
      <pubDate>Tue, 28 Apr 2020 13:29:00 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2020/100-days-to-offload/</guid>
      <description>&lt;p&gt;I came across a &lt;a href=&#34;https://fosstodon.org/@mike/104062374517782929&#34;&gt;post on Mastodon&lt;/a&gt; with the hashtag &amp;ldquo;#100daysToOffload&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Having seen a lot of #100DaysOfCode posts on Twitter, I was wondering what this 
&amp;ldquo;offloading&amp;rdquo; was all about.&lt;/p&gt;
&lt;h1 id=&#34;the-challenge&#34;&gt;The Challenge&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://100daystooffload.com/&#34;&gt;100 Days To Offload&lt;/a&gt; is a challenge to post in your personal blog every day for 100 days.&lt;/p&gt;
&lt;p&gt;Hahahaha like that&amp;rsquo;s going to happen.&lt;/p&gt;
&lt;p&gt;I set up this Hugo thing over a year ago because I wanted a place to recall my experience seeing a &lt;a href=&#34;https://olivierforget.net/blog/2019/viewing-spacex-falcon-heavy-launch/&#34;&gt;SpaceX Falcon Heavy launch&lt;/a&gt;. Then guess what happened? I got &lt;a href=&#34;https://olivierforget.net/blog/2019/note-taking-apps/&#34;&gt;one more post&lt;/a&gt; published in December 2019, and it only saw the light of day after an agonizingly long series of drafts and reframings.&lt;/p&gt;
&lt;h1 id=&#34;not-doing-it-man&#34;&gt;Not Doing It Man&lt;/h1&gt;
&lt;p&gt;To think I could post every day is just hilarious, but that&amp;rsquo;s too bad. The first line in my &amp;ldquo;&lt;a href=&#34;https://olivierforget.net/blog/2019/first-post/&#34;&gt;Hello World&lt;/a&gt;&amp;rdquo; post was &amp;ldquo;I&amp;rsquo;ve been meaning to blog&amp;rdquo;. Guess what pal? You&amp;rsquo;re still meaning to.&lt;/p&gt;
&lt;p&gt;I have ideas, man. Just because my blog is blank doesn&amp;rsquo;t mean my mind is. Promise!&lt;/p&gt;
&lt;p&gt;But like heck I&amp;rsquo;m going to join a challenge to blog every day for 100 days. I can barely keep up with daily work with this pandemic. We have the kiddo at home and my work is still going 100%. Now you want me to dig even deeper and do the thing I couldn&amp;rsquo;t make myself do in the before-times?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s clear I need to be pushed if I am going to unlock a spell of writing on here, but come on.&lt;/p&gt;
&lt;p&gt;Out of curiosity I checked out some other blogs who are on the challenge&amp;rsquo;s &lt;a href=&#34;https://100daystooffload.com/blogroll.html&#34;&gt;blogroll&lt;/a&gt;, like &lt;a href=&#34;https://trivial.observer/blog/100-days-to-offload/&#34;&gt;this one&lt;/a&gt; by &lt;a href=&#34;https://sarcasm.stream/@basil&#34;&gt;@basil&lt;/a&gt;. It&amp;rsquo;s another year-old Hugo install with three posts, and an anticipation of failing this challenge after four posts.&lt;/p&gt;
&lt;p&gt;Sounds exactly like me right now. And they&amp;rsquo;re doing it.&lt;/p&gt;
&lt;h1 id=&#34;ok-im-doing-it-man&#34;&gt;OK I&amp;rsquo;m Doing It Man&lt;/h1&gt;
&lt;p&gt;I decided I am doing this. At worst I will fail in good company.&lt;/p&gt;
&lt;p&gt;See you tomorrow.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>My Personal Adventure Through Note-Taking Services, 2008 - Present</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2019/note-taking-apps/</link>
      <pubDate>Mon, 02 Dec 2019 19:04:44 -0700</pubDate>
      
      <guid>https://olivierforget.net/blog/2019/note-taking-apps/</guid>
      <description>&lt;p&gt;I love taking notes. It might be the only effective way for my brain to work. Regardless of the technology involved I always gravitate towards a blank slate of some kind and spill thoughts onto the medium.&lt;/p&gt;
&lt;p&gt;I used to buy paper notebooks and filled them with barely readable words and other scratches. There were arrows, diagrams, and strike-throughs on every page, and exclamation points inside triangles for when I really meant it. The notes were pure expressions of my thoughts.&lt;/p&gt;
&lt;p&gt;Then one day I decided the physical paper medium was too cumbersome (I had a pile eight inches high) and I switched to digital notes. I knew I would miss the free-wheeling nature of paper notes but I believed I would gain in searchability, portability, and durability.&lt;/p&gt;
&lt;p&gt;So how did that work out?&lt;/p&gt;
&lt;h1 id=&#34;luminotes-2008-2010&#34;&gt;Luminotes (2008-2010)&lt;/h1&gt;
&lt;p&gt;Once upon a time there was a web-based note-taking service called &lt;a href=&#34;https://web.archive.org/web/20091225064403/http://luminotes.com/&#34;&gt;Luminotes&lt;/a&gt;. It was brilliant. It was like a wiki but it didn&amp;rsquo;t require remembering tricky syntax to link related pages.&lt;/p&gt;
&lt;p&gt;When I was taking notes on paper I could let my hand write, I just had to think. I wanted to stay as close to that feeling in the digital realm. Any kind of syntax necessary to create a note would force me to engage my coding brain (are the brackets matched? do I need to escape this underscore?) and break my flow. In fact I valiantly resisted using &lt;a href=&#34;https://daringfireball.net/projects/markdown/&#34;&gt;markdown&lt;/a&gt;-based systems because they make me feel like I&amp;rsquo;m writing code, not notes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;media/luminotes.jpg&#34; alt=&#34;The home page of the Luminotes web service, 2007&#34;&gt;&lt;/p&gt;
&lt;p&gt;I dove in and started organizing all thoughts related to my projects in a bunch of linked notes. The &lt;a href=&#34;https://en.wikipedia.org/wiki/Wiki&#34;&gt;Wiki&lt;/a&gt; was the organizational paradigm that I could not get on paper: I could now record relations between notes in addition to the notes themselves.&lt;/p&gt;
&lt;p&gt;I made heavy use of this service and depended on it. I was a big fan, an early and dedicated user, and I exchanged a number of emails with the developer.&lt;/p&gt;
&lt;p&gt;Then one day the developer said he would no longer maintain the project. He had moved on and didn&amp;rsquo;t want to deal with the overhead of maintaining the server. He was willing to open source the code, but he would not participate in its development.&lt;/p&gt;
&lt;p&gt;To be clear I don&amp;rsquo;t blame the dev. Maintaining things is hard, and when you&amp;rsquo;re providing a service it&amp;rsquo;s even harder. Babysitting servers when your heart is no longer in the project is even more challenging, and shutting things down is be the only reasonable thing to do.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;media/luminotes-shut-down.jpg&#34; alt=&#34;Luminotes home page saying it has shut down&#34;&gt;&lt;/p&gt;
&lt;p&gt;I really wanted to keep using Luminotes in some way or another, so I created a &lt;a href=&#34;https://groups.google.com/forum/#!forum/luminotes-community&#34;&gt;Google Group&lt;/a&gt; to organize the efforts of the few Luminotes die-hards who would band together to keep the app alive through the magic of open source collaboration.&lt;/p&gt;
&lt;p&gt;We got nowhere.&lt;/p&gt;
&lt;p&gt;I never managed to install the darned thing on a development server. It was written in a language I didn&amp;rsquo;t know and depended on outdated dependencies that I failed to get installed. Others in the group had similar issues. Our meager efforts fizzled then died, the hurdles too numerous to justify staying involved.&lt;/p&gt;
&lt;p&gt;It was time to look for another note-taking application.&lt;/p&gt;
&lt;h2 id=&#34;catch-notes-2010-2013&#34;&gt;Catch Notes (2010-2013)&lt;/h2&gt;
&lt;p&gt;I settled on &lt;a href=&#34;https://www.crunchbase.com/organization/catch-com&#34;&gt;Catch Notes&lt;/a&gt; after a vain search for a wiki system that had the same ease of use as Luminotes.&lt;/p&gt;
&lt;p&gt;I examined plenty of wiki authoring tools but none of them had the same degree of &amp;ldquo;thought-free operation&amp;rdquo; as Luminotes did. I tried using some but they felt finicky and I just couldn&amp;rsquo;t write comfortably with them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;media/catch-notes.jpg&#34; alt=&#34;Catch Notes home page&#34;&gt;&lt;/p&gt;
&lt;p&gt;So Catch Notes it was. The problem with Catch Notes is that it wasn&amp;rsquo;t a wiki at all. It used a system of tags to keep notes organized. The result: after migrating my data my notes degraded from a carefully crafted personal knowledge graph to a pile of disconnected notes. I could no longer just click around from note to note to follow my thought process at the time. My painstaking work had lost a good chunk of its value.&lt;/p&gt;
&lt;p&gt;Still, I knew that would happen and accepted my fate. Over time I started thinking in terms of tags and little by little found it to be a decent way to go. I found peace with CN and tags and enjoyed productive note-taking.&lt;/p&gt;
&lt;p&gt;Then &amp;ndash; shocker &amp;ndash; Catch Notes shut down.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;media/catch-notes-dead.jpg&#34; alt=&#34;Catch Notes shut down&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;evernote-2013-2016&#34;&gt;Evernote (2013-2016)&lt;/h2&gt;
&lt;p&gt;This time I decided to go with a big established player: Evernote. I had fully adopted the tags system of Catch Notes, but unfortunately Evernote&amp;rsquo;s support for tags was flimsy. My notes lost some of their value again as they got processed through another migration.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;media/evernote.jpg&#34; alt=&#34;Evernote home page in 2013&#34;&gt;&lt;/p&gt;
&lt;p&gt;My experience with Evernote was never stellar. I was there because I felt they wouldn&amp;rsquo;t die and not because their offering was compelling to me. Their desktop app on Mac was slow and badly designed and they seemed to be developing new products in dozens of new directions while their core offering was underwhelming. Not a good place to be.&lt;/p&gt;
&lt;p&gt;Then Evernotes started showing signs of not being around forever. There was talk of financial troubles and of an exodus of users.&lt;/p&gt;
&lt;p&gt;But who would be surprised by this turn of events? This was a note-taking app that also sold socks on their website for crying out loud.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;media/evernote-socks-ffs.jpg&#34; alt=&#34;Evernote marketplace with socks for sale&#34;&gt;&lt;/p&gt;
&lt;p&gt;This time I decided not to wait until the app I used went belly-up to spread my wings and fly away.&lt;/p&gt;
&lt;h2 id=&#34;onenote-2016-present&#34;&gt;OneNote (2016-present)&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t recall exactly how I ended up in Redmond&amp;rsquo;s grip. It might have been because Satya was charming the tech world by reinventing Microsoft.&lt;/p&gt;
&lt;p&gt;Or it might have had something to do with my new Windows laptop with a touchscreen and digital pen. I got excited about taking freehand notes again, and OneNote&amp;rsquo;s tools seemed well suited for that.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;media/onenote.jpg&#34; alt=&#34;OneNote homepage today&#34;&gt;&lt;/p&gt;
&lt;p&gt;That excitement was nothing short of the tantalizing feeling that technology was catching up to fantasy. Could I get the best of both worlds? The freedom of hand-written notes with the weightlessness of the digital medium?&lt;/p&gt;
&lt;p&gt;No. The answer is no. The fantasy did not survive contact with reality. I wouldn&amp;rsquo;t take any notes by drawing with the stylus or my finger. I tried, but it didn&amp;rsquo;t work. A 15&amp;quot; laptop is very awkward to use as a tablet to draw on, and OneNote&amp;rsquo;s tools for drawing leave a lot to be desired.&lt;/p&gt;
&lt;p&gt;So I got duped by a bunch of kids apparently sketching cool mods for their fixie bikes. Can a corporation pander to me any harder than that? I should have known.&lt;/p&gt;
&lt;p&gt;So now I&amp;rsquo;m using big clunky OneNote and it&amp;rsquo;s not a party. I don&amp;rsquo;t sketch with it like I wanted, and its UI is pointlessly cumbersome. Their phone apps aren&amp;rsquo;t good, syncing takes too long and is unreliable, and their desktop Mac app always throws some sort of authentication error so I&amp;rsquo;ve given up on it. Also its search function is terrible.&lt;/p&gt;
&lt;p&gt;I desperately want to spread my wings again.&lt;/p&gt;
&lt;h2 id=&#34;where-to-now&#34;&gt;Where To Now?&lt;/h2&gt;
&lt;p&gt;There are some new players in the space and people rave about them on the socials. I read about these shiny new note-taking apps and I feel a tinge of envy and a desire to try them out. But I&amp;rsquo;ve been let down too many times. I want to do one more migration and then that&amp;rsquo;s it.&lt;/p&gt;
&lt;h3 id=&#34;open-source&#34;&gt;Open Source&lt;/h3&gt;
&lt;p&gt;Clearly I should go with something open source. Looking at my trajectory from Luminotes to OneNote, I have gravitated towards closed systems. In retrospect it&amp;rsquo;s possible much of my troubles are due to that.&lt;/p&gt;
&lt;p&gt;However remember that Luminotes was open source, and that didn&amp;rsquo;t do me any good. It&amp;rsquo;s not enough to be open, there has to be a sufficiently active community for the project to survive the departure of the original creator.&lt;/p&gt;
&lt;p&gt;Another factor is that open source note taking apps are often developer-centric, which usually means they use markdown or some other syntax, which I am not a fan of. Frankly I just haven&amp;rsquo;t found an open source note taking system that suits me.&lt;/p&gt;
&lt;p&gt;Finally there is the issue of self-hosting. I might jot something down on any of 4 devices I use regularly so I don&amp;rsquo;t want my notes to live on a single device. If there is no service available I&amp;rsquo;d have to run a server myself. This is a pain. I spend enough time dealing with servers, I really don&amp;rsquo;t view tinkering with a Linux server as a hobby. To me it&amp;rsquo;s a chore, so self-hosting comes with its own set of problems.&lt;/p&gt;
&lt;h3 id=&#34;new-note-taking-paradigm&#34;&gt;New Note Taking Paradigm?&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve greatly evolved how I take notes and how I think of my notes. I don&amp;rsquo;t think the Wiki approach works for me anymore. As the number of notes grows it becomes a lot of work to keep that graph organized.&lt;/p&gt;
&lt;p&gt;Categories don&amp;rsquo;t cut it either, they just don&amp;rsquo;t scale. And tags can scale but are too limiting. I&amp;rsquo;m rethinking the very concept of a note too.&lt;/p&gt;
&lt;p&gt;To be continued&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;PS: Thanks to the Internet Archive for making it possible to get screenshots of defunct services 10 years on! If you&amp;rsquo;re able please &lt;a href=&#34;https://archive.org/donate/&#34;&gt;donate to the Internet Archive&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What it&#39;s Like to View a SpaceX Falcon Heavy Launch</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2019/viewing-spacex-falcon-heavy-launch/</link>
      <pubDate>Sun, 14 Apr 2019 10:04:44 -0500</pubDate>
      
      <guid>https://olivierforget.net/blog/2019/viewing-spacex-falcon-heavy-launch/</guid>
      <description>&lt;p&gt;I flew to Florida to witness in person the awesome power of the &lt;a href=&#34;https://www.spacex.com/falcon-heavy&#34;&gt;Falcon Heavy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My viewing location for the launch of &lt;a href=&#34;https://en.wikipedia.org/wiki/Arabsat-6A&#34;&gt;Arabsat 6a&lt;/a&gt; was Banana Creek within the Kennedy Space Center, also known as &amp;ldquo;Feel The Heat&amp;rdquo; in KSC&amp;rsquo;s launch viewing nomenclature. It is 3.9 miles due West of the launch pad, as close as one can be for such a launch.
I do not want my recollection of this experience to become clouded with time, so here are my notes.&lt;/p&gt;
&lt;h1 id=&#34;the-ambiance&#34;&gt;The Ambiance&lt;/h1&gt;
&lt;p&gt;I traveled alone for this event and I expected to be alone most of the time. Boy was I wrong. I had many wonderful conversations with other space fans. I met a lot of people from different walks of life, and from many places further than my home in Nashville. Some I met in person after communicating on a Slack channel connected to the &lt;a href=&#34;https://www.reddit.com/r/spacex&#34;&gt;/r/spacex&lt;/a&gt; subreddit, but most were other excited space geeks who were waiting in line for a bus for the umpteenth time.&lt;/p&gt;
&lt;p&gt;Apart from the FH launch, other big space events were happening: the first photo of a black hole was revealed and &lt;a href=&#34;https://en.wikipedia.org/wiki/Beresheet&#34;&gt;Beresheet&lt;/a&gt; was scheduled to land while we were waiting for launch. We all followed the progress of the Israeli lander while sitting in the bleachers and commiserated when word of its demise came through. The bleachers are so stocked with space nerds that when I wondered what Beresheet had launched on I asked the person nearest me and got an immediate answer: it was a Falcon 9. Where else can you ask that question to anybody and get an answer?&lt;/p&gt;
&lt;p&gt;As the countdown clock ticks past milestones, the crowd begins to react more and more excitedly. At the 1 hour mark big cheers erupt. Each time the announcer mentioned even the vaguest possibility of a scrub, he would elicit boos from the crowd. We&amp;rsquo;re all passionate, excited and jittery in the bleachers. It makes for swift and audible reactions every time something happens. A puff of oxygen emanates from the rocket? Wild cheers. The announcer reminds us that they will scrub if they notice anything wrong during the last second of the countdown? Merciless booing.&lt;/p&gt;
&lt;h1 id=&#34;the-history&#34;&gt;The History&lt;/h1&gt;
&lt;p&gt;It is hard to sit across the water from pad 39A and not think about its history.&lt;/p&gt;
&lt;p&gt;Every person who walked on the moon launched from that same chunk of concrete. It&amp;rsquo;s remarkable to think that humans boarded a ship in this location and sailed across the vast expanses of space to reach another rock to call home. I noticed the moon hanging directly over 39A and the symbolism was perfect. A vast expanse of featureless sky between a rocket pad and its destination.&lt;/p&gt;
&lt;style&gt;
.history-photos  {
    display: grid;
    grid-template-columns: 50% 50%;
    grid-gap: 0.5em;
}
.history-photos P {
    margin: 0;
}
@media (max-width: 600px) {
    .history-photos {
        grid-template-columns: 100%;
    }
    .history-photos P {
        margin-bottom: 1em;
    }
}
&lt;/style&gt;
&lt;div class=&#34;history-photos&#34;&gt;
    &lt;img src=&#34;media/apollo11-history.jpg&#34; alt=&#34;A Saturn V rocket lifts off from Pad 39A&#34;&gt;
    &lt;p&gt;Apollo 11, July 16 1969. Every person who walked on the moon launched from Pad 39A. 
    *Photo credit: &lt;a href=&#34;https://www.nasa.gov/centers/kennedy/about/history/50thgallery/1969-07-16-5.html&#34;&gt;NASA&lt;/a&gt;*&lt;/p&gt;
    &lt;img src=&#34;media/space-shuttle-history.jpg&#34; alt=&#34;A Space Shuttle lifts off from Pad 39A&#34;&gt;
    &lt;p&gt;Eighty-two Space Shuttles were launched from this same pad, among them the very first and last.
    *Photo credit: &lt;a href=&#34;https://www.flickr.com/photos/nasacommons/20264606661&#34;&gt;NASA&lt;/a&gt;*&lt;/p&gt;
    &lt;img src=&#34;media/arabsat-history.jpg&#34; alt=&#34;Spacex Falcon Heavy lifts off from Pad 39A&#34;&gt;
    &lt;p&gt;What I saw: Falcon Heavy, 2019, same pad.
    *Photo credit: &lt;a href=&#34;https://www.flickr.com/photos/spacex/40628438523/&#34;&gt;SpaceX&lt;/a&gt;*&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Original idea for this sequence of photos from this &lt;a href=&#34;https://twitter.com/ChrisG_NSF/status/1116716429636788226&#34;&gt;tweet&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Soon, if all goes according to plan, US astronauts will launch into space from US soil aboard US rockets for the first time since the end of the Space Shuttle. They will do so from 39A.&lt;/p&gt;
&lt;h1 id=&#34;the-sound&#34;&gt;The Sound&lt;/h1&gt;
&lt;p&gt;This is the thing most people wonder about. Home speakers or even good headphones can&amp;rsquo;t replicate the sound in your living room, so what is it really like?&lt;/p&gt;
&lt;p&gt;It begins with silence. It takes 18 seconds for the sound to travel from the pad to your ears. When the engines are lit, an immense angry cloud jets out from the side of the launch pad signaling the beast has awakened. However there is no sound. The Heavy lifts off and climbs. Still no sound. A rocket can travel a long way in 18 seconds, and I began to feel a real disconnect between what I was seeing and what I was hearing.&lt;/p&gt;
&lt;p&gt;We had been told it was possible to see the sound waves coming across the water. I saw no such thing. My first indication of sound was this sense of deep motion in the air, the lowest deepest notes I can imagine hearing. It&amp;rsquo;s a soft, pleasant experience that soon gives way to an ever increasing roar. Finally, things sound like they are supposed to.&lt;/p&gt;
&lt;p&gt;The roar sounds just like just what it is: an immense amount of energy unleashed all at once. It builds gradually in intensity while dropping in pitch (due to the Doppler effect.) It&amp;rsquo;s a roar that you can feel in your chest, and that is why headphones can&amp;rsquo;t replicate the experience.&lt;/p&gt;
&lt;p&gt;It then begins to crackle and pop. I used to think the crackling of rockets in launch videos was due to limitations of the recording equipment. It turns out it&amp;rsquo;s the &lt;a href=&#34;https://www.quora.com/Why-did-the-space-shuttles-rockets-make-popping-sounds-as-opposed-to-a-smooth-rumbling-noise-during-liftoff/answer/Kent-Gee&#34;&gt;physics of the atmosphere&lt;/a&gt;. Imagine a loud thunderclap. Now imagine that sound in a continuous loop. You&amp;rsquo;re getting close.&lt;/p&gt;
&lt;p&gt;Then, very quickly, it becomes quiet again. The Heavy accelerates away so fast that it doesn&amp;rsquo;t take long for it to go out of earshot.&lt;/p&gt;
&lt;h1 id=&#34;the-light&#34;&gt;The Light&lt;/h1&gt;
&lt;p&gt;I was not prepared for this.&lt;/p&gt;
&lt;p&gt;Once the rocket cleared the tower and the plume was in full view, I felt like I was looking into the sun. It was so bright my eyes instinctively wanted to look away. But we had waited 6 hours for the launch to go off the day before, and 4 more hours today in addition to all the bus lines, so when that rocket finally made itself visible I was not going to look away. Too bad for my retinas, let &amp;lsquo;em burn. I am not taking my eyes off that rocket.&lt;/p&gt;
&lt;h1 id=&#34;the-great-arcs&#34;&gt;The Great Arcs&lt;/h1&gt;
&lt;p&gt;I have watched many webcasts of SpaceX launches and they are a great way of following the action and getting a taste for the excitement from home. However to see it in real life brings a new dimension to the event. It becomes less about zoomed in views and performance data, and more about the vast expanses, the palpable speeds and dizzying altitudes. We were able to see the different elements play on the vast stage that is the sky in one continuous take.&lt;/p&gt;
&lt;p&gt;I threw together a couple of graphics based on the few pics I took with my phone to show the sequence as we saw it:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;media/launch-sequence.jpg&#34; alt=&#34;Launch&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&#34;media/launch-original.jpg&#34;&gt;Full size original photo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Launch! Much excitement. Once it clears the tower the rocket plus its giant plume makes for a satisfyingly large and shockingly bright thing to look at from Banana Creek.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sound is finally getting to our ears. The rocket is accelerating and is starting to turn downrange, meaning we see less of its side and more its tailpipe. It&amp;rsquo;s an impressive sight, like a three-eyed Sauron.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Aw shoot. We launched into a perfectly clear sky, but the rocket created a contrail that grew into a cloud, hiding itself from our view. Last we saw it, it was headed straight away from us. It&amp;rsquo;s quiet in the bleachers. Surely the party&amp;rsquo;s not already over, is it?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Falcon Heavy reappears below the cloud as a wide orange triangle. Wild cheers from the crowd. It is below the cloud because it is now heading more away from us than up, like an airplane headed for the horizon. The plume has grown so much in the rarified air that we still see it as a distinct shape. It quickly gets dimmer as the rocket accelerates away from us.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Booster separation! By this point we&amp;rsquo;re really straining to see clearly, but I did see the boosters separate as two little sticks that fell off to each side. After a few more seconds we could see the two additional smoky plumes from the boost-back burn. As soon as that burn ended we lost sight of the side boosters.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;By the time the photo was taken the center core was accelerating fast away from us and about to disappear for good.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;media/landing-sequence.jpg&#34; alt=&#34;Landing&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&#34;media/landing-original.jpg&#34;&gt;Full size original photo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;ol start=&#34;7&#34;&gt;
&lt;li&gt;At 6 minutes and 11 seconds after launch the re-entry burns were going to start so we all trained our eyes to the sky, taking our best guess as to where the two boosters would appear. Somebody yelled &#34;there!&#34; and we all looked to see where that person was pointing. Two bright yellow dots were plainly visible to the right of the cloud. The reentry burns are short but they allowed us to spot the returning boosters. I was able to follow them all the way to the ground. They were mere specks at first but became more discernable as they dropped.&lt;/li&gt;
&lt;li&gt;Holy moly, these things are cooking. I remember being awed by the speed of the two objects I was looking at. Seeing them plummet from such an altitude really brings home why rocket landings are such an extraordinary feat.&lt;/li&gt;
&lt;li&gt;The landing zones are much further away from Banana Creek than the launch pad so the landing burns appear as points of light. This is too bad, but you can either be close to the launch or close to the landing. I lucked out: my spot in the bleachers allowed me to follow the boosters as they squeezed just between the &lt;a href=&#34;https://en.wikipedia.org/wiki/Vehicle_Assembly_Building&#34;&gt;VAB&lt;/a&gt; and the tan building. Fifty two seconds after the landing, a quadruple thud of sonic booms hit the crowd at Banana Creek, who were all too happy to erupt in cheers yet again.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;some-tips&#34;&gt;Some Tips&lt;/h1&gt;
&lt;p&gt;Here are a few tips for viewing a SpaceX launch and landing at Banana Creek:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Download the press kit PDF for your launch and have it ready on your phone. It spells out the exact times of all the events of the launch. Use that and the countdown clock (which counts up after the launch) to prepare to spot events as they happen. You don&amp;rsquo;t want to be looking away when boosters separate! Here is the &lt;a href=&#34;https://www.spacex.com/sites/spacex/files/arabsat-6a_press_kit.pdf&#34;&gt;Arabsat Press Kit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;To see as much of the landing(s) as possible, sit at the top of the bleachers South of the Saturn V Center. To avoid having your view obstructed by the tan building, don&amp;rsquo;t sit in the Northern most bleacher. I was at the South side of the second bleacher and saw as much as you can see from Banana Creek. Trees and other things will obscure the view as you sit further South.&lt;/li&gt;
&lt;li&gt;Ignore the livestream that they are showing on screens. It&amp;rsquo;s a distraction. It&amp;rsquo;s as much as 30 seconds behind and buffers a lot.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;so-whats-it-like&#34;&gt;So What&amp;rsquo;s it Like?&lt;/h1&gt;
&lt;p&gt;The sound, sights, the ambiance are each thrilling and together they are more than the sum of their parts. Viewing a launch live is unlike anything I&amp;rsquo;ve experienced. And like any good experience, there is no substitute. No blog post can convey the complete experience. You have to go for yourself.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The First Post</title>
      <author>Olivier Forget</author>
      <link>https://olivierforget.net/blog/2019/first-post/</link>
      <pubDate>Sat, 06 Apr 2019 10:04:44 -0500</pubDate>
      
      <guid>https://olivierforget.net/blog/2019/first-post/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been meaning to start a blog for a while now.&lt;/p&gt;
&lt;p&gt;I suppose I took so long to start because I much prefer building things than talking about building things. When I was an aerospace engineer I worked in small experimental shops that routinely produced hardware. We lived by the classic saying &amp;ldquo;Hardware talks and bullsh&amp;ndash; walks&amp;rdquo; and we had little respect for office-dwelling engineers who only produced theoretical papers.&lt;/p&gt;
&lt;p&gt;Now as a software developer I live by the same idea. As a result I rarely talk about what I&amp;rsquo;m working on. I&amp;rsquo;d rather show you when I have something usable. Unfortunately, the nature of projects is that some never reach that stage, and as a result I never talk about them.&lt;/p&gt;
&lt;h1 id=&#34;why-even-blog&#34;&gt;Why Even Blog&lt;/h1&gt;
&lt;p&gt;I want to blog about the things that I am working on and my motivations for working on them. I want to do this before projects reach releasable state if only to get it out of my system. Some projects never reach that state and they languish on my hard disk without a single publicly visible trace.&lt;/p&gt;
&lt;p&gt;I also want to relate some of my past experiences in my winding career. If only for myself so that I can come back and refresh my memory before it all evaporates.&lt;/p&gt;
&lt;h1 id=&#34;the-stack&#34;&gt;The Stack&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m generating this blog with &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;. It was a natural choice given my recent adoption of &lt;a href=&#34;https://golang.org&#34;&gt;Go&lt;/a&gt;. I moved the &lt;a href=&#34;olivierforget.net&#34;&gt;olivierforget.net&lt;/a&gt; site from AWS to &lt;a href=&#34;https://netlify.com&#34;&gt;Netlify&lt;/a&gt; to simplify deployment.&lt;/p&gt;
&lt;p&gt;I like simple readable blogs so I am modifying the &lt;a href=&#34;https://themes.gohugo.io/indigo/&#34;&gt;Indigo theme&lt;/a&gt; to my taste.&lt;/p&gt;
&lt;p&gt;Taking the leap to using an existing static site generator is an admission to myself that &lt;a href=&#34;http://cicerone.co&#34;&gt;Cicerone&lt;/a&gt; is not usable for blogging after all the work I put into it. But Hugo&amp;rsquo;s complexity reminded me — yet again — why I was developing Cicerone in the first place.&lt;/p&gt;
&lt;p&gt;Maybe I should blog about that.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>