<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>derlocke.net</title>
  <link>https://derlocke.net/</link>
  <description>Linux desktop, privacy and the Kiwi ecosystem: notes and release news from derlocke.</description>
  <language>en</language>
  <atom:link href="https://derlocke.net/feed.xml" rel="self" type="application/rss+xml"/>
  <lastBuildDate>Sun, 18 Oct 2026 04:30:15 GMT</lastBuildDate>
  <item>
    <title>kiwi-updater: Apps From Git Catalogs on Silverblue and Bluefin</title>
    <link>https://derlocke.net/posts/kiwi-updater/</link>
    <guid isPermaLink="true">https://derlocke.net/posts/kiwi-updater/</guid>
    <pubDate>Sun, 04 Oct 2026 00:00:00 GMT</pubDate>
    <category>kiwi</category>
    <category>linux</category>
    <category>silverblue</category>
    <category>open-source</category>
    <description>Meet kiwi-updater — install and update open-source apps straight from git catalogs on immutable Fedora desktops. No accounts, no store, no vendor.</description>
    <content:encoded><![CDATA[<p>Time for a fresh start on this blog. Most of what used to live here is history; what I actually spend my evenings on now is the <strong>Kiwi</strong> ecosystem, and it starts with one tool: <strong>kiwi-updater</strong>.</p>
<!--more--><h2 id="the-problem">The problem</h2>
<p>On Fedora Silverblue or Bluefin, <code>/usr</code> is immutable. That&#39;s great — until you want a small tool that isn&#39;t a Flatpak and isn&#39;t worth layering a package (and rebooting) for. A CLI helper, a GNOME extension, a firewall daemon with a settings app… you end up with a pile of <code>git clone &amp;&amp; ./install.sh</code> and nothing that keeps it updated.</p>
<h2 id="the-idea">The idea</h2>
<p><strong>An app is just a git repo</strong> with two files in its root: a <code>kiwi.manifest</code> describing it and an <code>install.sh</code> that installs it. <strong>A catalog is just a git repo</strong> with a list of app URLs. <code>kiwi</code> reads the catalogs, clones an app, checks out its latest release tag, runs the installer — and then keeps it updated in the background, itself included.</p>
<p>No accounts, no store, no vendor. A catalog is something you can read, fork and send a pull request to.</p>
<h2 id="getting-started">Getting started</h2>
<pre data-lang="bash"><code class="hljs language-bash"><span class="hljs-comment"># recommended on a desktop: user scope + root-owned system scope, one password prompt</span>
curl -fsSL https://raw.githubusercontent.com/derlocke-ng/kiwi-updater/main/get-kiwi.sh | bash -s -- --with-system

kiwi catalog add https://github.com/derlocke-ng/kiwi-catalog.git
kiwi list
kiwi install kiwi-killswitch</code></pre>
<p>Don&#39;t want anything outside your home directory? Drop <code>--with-system</code>: the minimal install is 100 % <code>~/.local</code>, no root, no password, ever. That covers every app that is only files in your home. Prefer clicking? <strong>Kiwi Apps</strong> shows up in your app grid: search, filter and inspect everything in your catalogs.</p>
<h2 id="apps-with-a-root-half">Apps with a root half</h2>
<p>Some apps are a binary in <code>~/.local/bin</code>. Others — like <a href="https://derlocke.net/projects.html#kiwi-killswitch">kiwi-killswitch</a> — are a root firewall daemon <em>and</em> a desktop app <em>and</em> a GNOME extension. The manifest simply says so:</p>
<pre data-lang="ini"><code class="hljs language-ini"><span class="hljs-attr">COMPONENTS</span>=daemon cli gui gnome-extension
<span class="hljs-attr">SCOPES</span>=user system
<span class="hljs-attr">ROOT_REASON</span>=installs a root firewall daemon, its D-Bus policy and two systemd units</code></pre>
<p><code>kiwi</code> installs each half where it belongs: user parts in <code>~/.local</code>, system parts cloned as root into <code>/var/lib</code>, because <strong>root must never execute a file the user can write</strong>. Before it asks for your password, it tells you what the password is <em>for</em> — that&#39;s the <code>ROOT_REASON</code> line. Updating a system app afterwards needs no password at all: a single polkit-gated helper only updates apps the administrator already installed.</p>
<h2 id="you-decide-what-runs">You decide what runs</h2>
<p>Installing an app runs its <code>install.sh</code>, as root if it has a system half. Catalogs are curated, not audited, so kiwi gives you the tools to look first:</p>
<pre data-lang="bash"><code class="hljs language-bash">kiwi info --installer &lt;app&gt;  <span class="hljs-comment"># the exact script an install would run</span>
kiwi diff &lt;app&gt;              <span class="hljs-comment"># what an update would change, installer included</span>
kiwi pin &lt;app&gt; v1.2.0        <span class="hljs-comment"># stay on a version until you say otherwise</span>
kiwi install &lt;app&gt; --dry-run <span class="hljs-comment"># show what would happen, do nothing</span>
kiwi doctor                  <span class="hljs-comment"># stale locks, version skew, broken lists, timers</span></code></pre>
<p>Releases are git tags shaped like <code>v1.2.3</code>, so a pre-release or a scratch tag is never picked up by accident.</p>
<h2 id="what-s-in-the-catalog">What&#39;s in the catalog</h2>
<div class="table-wrap"><table>
<thead>
<tr>
<th>App</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td><strong>kiwi-updater</strong></td>
<td>keeps itself current, too</td>
</tr>
<tr>
<td><strong><a href="https://derlocke.net/projects.html#kiwi-killswitch">kiwi-killswitch</a></strong></td>
<td>fail-closed VPN kill switch for GNOME — one VPN, no leaks, no password prompts</td>
</tr>
<tr>
<td><strong><a href="https://derlocke.net/projects.html#ensconce">ensconce</a></strong></td>
<td>turns a fresh Bluefin-DX install into your workstation, from plain list files</td>
</tr>
<tr>
<td><strong><a href="https://derlocke.net/projects.html#kiwi-cli-tools-desktop">kiwi-cli-tools-desktop</a></strong></td>
<td><code>pweb</code>, <code>select-server</code>, <code>tethering</code></td>
</tr>
</tbody></table></div>
<p>Building something open source that works without an account, a subscription or a tracker? Add a <code>kiwi.manifest</code> and an <code>install.sh</code>, tag a release and send a PR to <a href="https://github.com/derlocke-ng/kiwi-catalog">kiwi-catalog</a>.</p>
<h2 id="where-it-stands">Where it stands</h2>
<p>kiwi-updater is at <strong>1.7.2</strong>. Three full audits went into the 1.x releases, and the <a href="https://github.com/derlocke-ng/kiwi-updater/blob/main/CHANGELOG.md">changelog</a> documents what each one found and fixed. Still on the roadmap: a registry of trusted catalogs, and signature verification of release tags.</p>
<p>Everything is GPL-3.0-or-later and on <a href="https://github.com/derlocke-ng/kiwi-updater">GitHub</a>. Issues, ideas and catalog PRs are very welcome. 🥝</p>
]]></content:encoded>
  </item>
  <item>
    <title>Getting Started with Linux</title>
    <link>https://derlocke.net/posts/linux-getting-started/</link>
    <guid isPermaLink="true">https://derlocke.net/posts/linux-getting-started/</guid>
    <pubDate>Thu, 01 Jan 2026 00:00:00 GMT</pubDate>
    <category>linux</category>
    <category>tutorial</category>
    <description>So you want to try Linux? Good choice. Here&apos;s my no-bullshit guide to getting started.</description>
    <content:encoded><![CDATA[<p>So you want to try Linux? Good choice. Here&#39;s my no-bullshit guide to getting started.</p>
<h2 id="choosing-a-distro">Choosing a Distro</h2>
<p>Don&#39;t overthink it. Here&#39;s my recommendation:</p>
<ul>
<li><strong>Complete beginner?</strong> → Linux Mint or Ubuntu</li>
<li><strong>Want to learn?</strong> → Fedora or openSUSE</li>
<li><strong>Already comfortable?</strong> → Arch, Debian, or whatever you want</li>
</ul>
<h2 id="first-steps-after-install">First Steps After Install</h2>
<pre data-lang="bash"><code class="hljs language-bash"><span class="hljs-comment"># Update everything first</span>
<span class="hljs-built_in">sudo</span> apt update &amp;&amp; <span class="hljs-built_in">sudo</span> apt upgrade -y  <span class="hljs-comment"># Debian/Ubuntu</span>
<span class="hljs-built_in">sudo</span> dnf upgrade -y                      <span class="hljs-comment"># Fedora</span>
<span class="hljs-built_in">sudo</span> pacman -Syu                         <span class="hljs-comment"># Arch</span>

<span class="hljs-comment"># Install essential tools</span>
<span class="hljs-built_in">sudo</span> apt install git curl vim htop neofetch</code></pre>
<h2 id="learn-the-terminal">Learn the Terminal</h2>
<p>The terminal is your friend. Start with these:</p>
<div class="table-wrap"><table>
<thead>
<tr>
<th>Command</th>
<th>What it does</th>
</tr>
</thead>
<tbody><tr>
<td><code>ls -la</code></td>
<td>List files with details</td>
</tr>
<tr>
<td><code>cd</code></td>
<td>Change directory</td>
</tr>
<tr>
<td><code>pwd</code></td>
<td>Print working directory</td>
</tr>
<tr>
<td><code>cat</code></td>
<td>Display file contents</td>
</tr>
<tr>
<td><code>grep</code></td>
<td>Search text patterns</td>
</tr>
<tr>
<td><code>man</code></td>
<td>Read the manual</td>
</tr>
</tbody></table></div>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://wiki.archlinux.org/">ArchWiki</a> — Best documentation, works for any distro</li>
<li><a href="https://linuxjourney.com/">Linux Journey</a> — Interactive learning</li>
<li><code>/r/linux4noobs</code> — Friendly community</li>
</ul>
<blockquote>
<p>&quot;The best way to learn Linux is to break things and fix them.&quot; — Every sysadmin ever</p>
</blockquote>
<p>More tutorials coming soon. Happy hacking! 🐧</p>
]]></content:encoded>
  </item>
  <item>
    <title>Setting Up a Home Server with Proxmox</title>
    <link>https://derlocke.net/posts/homelab-proxmox/</link>
    <guid isPermaLink="true">https://derlocke.net/posts/homelab-proxmox/</guid>
    <pubDate>Thu, 20 Nov 2025 00:00:00 GMT</pubDate>
    <category>homelab</category>
    <category>linux</category>
    <category>tutorial</category>
    <description>Time to talk about one of my favorite topics: homelabbing. Today we&apos;re setting up Proxmox VE as the foundation for all your self-hosted services.</description>
    <content:encoded><![CDATA[<p>Time to talk about one of my favorite topics: homelabbing. Today we&#39;re setting up Proxmox VE as the foundation for all your self-hosted services.</p>
<h2 id="why-proxmox">Why Proxmox?</h2>
<ul>
<li>Free and open source</li>
<li>Type 1 hypervisor (runs on bare metal)</li>
<li>Supports VMs and LXC containers</li>
<li>Web-based management</li>
<li>Great community</li>
</ul>
<h2 id="hardware-requirements">Hardware Requirements</h2>
<p>You don&#39;t need fancy hardware. I started with:</p>
<pre><code class="hljs">- Old Dell Optiplex (i5-4590)
- 32GB RAM (upgraded from 8GB)
- 256GB SSD for OS
- 2TB HDD for storage</code></pre>
<p>Any x86_64 machine with VT-x/AMD-V support works.</p>
<h2 id="installation">Installation</h2>
<ol>
<li>Download ISO from <a href="https://proxmox.com">proxmox.com</a></li>
<li>Flash to USB with <code>dd</code> or Balena Etcher</li>
<li>Boot and follow the installer</li>
<li>Access web UI at <code>https://your-ip:8006</code></li>
</ol>
<pre data-lang="bash"><code class="hljs language-bash"><span class="hljs-comment"># After install, fix the enterprise repo nag</span>
<span class="hljs-comment"># Edit /etc/apt/sources.list.d/pve-enterprise.list</span>
<span class="hljs-comment"># Comment out the enterprise repo, add:</span>
deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription</code></pre>
<h2 id="my-current-vms-containers">My Current VMs/Containers</h2>
<div class="table-wrap"><table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Purpose</th>
</tr>
</thead>
<tbody><tr>
<td>docker-host</td>
<td>LXC</td>
<td>Runs all my containers</td>
</tr>
<tr>
<td>pihole</td>
<td>LXC</td>
<td>DNS + Ad blocking</td>
</tr>
<tr>
<td>nginx-proxy</td>
<td>LXC</td>
<td>Reverse proxy</td>
</tr>
<tr>
<td>wireguard</td>
<td>LXC</td>
<td>VPN server</td>
</tr>
<tr>
<td>truenas</td>
<td>VM</td>
<td>NAS + storage</td>
</tr>
</tbody></table></div>
<h2 id="tips">Tips</h2>
<ul>
<li><strong>Backups:</strong> Use Proxmox Backup Server or simple vzdump</li>
<li><strong>Networking:</strong> Set up a bridge, consider VLANs</li>
<li><strong>Storage:</strong> ZFS is great if you have the RAM</li>
<li><strong>Templates:</strong> Create LXC templates for quick deployments</li>
</ul>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://pve.proxmox.com/wiki/">Proxmox Wiki</a></li>
<li><a href="https://reddit.com/r/homelab">r/homelab</a></li>
<li><a href="https://youtube.com/@TechnoTim">Techno Tim on YouTube</a></li>
</ul>
<p>Happy homelabbing! 🖥️</p>
]]></content:encoded>
  </item>
  <item>
    <title>Life Update: Why I Started This Blog</title>
    <link>https://derlocke.net/posts/personal-why-this-blog/</link>
    <guid isPermaLink="true">https://derlocke.net/posts/personal-why-this-blog/</guid>
    <pubDate>Sun, 05 Oct 2025 00:00:00 GMT</pubDate>
    <category>personal</category>
    <description>Life&apos;s been... interesting. Without going into too much detail, the past few years have been rough. Health issues, job changes, the usual chaos that comes with existing in this…</description>
    <content:encoded><![CDATA[<p>Alright, time for something personal.</p>
<h2 id="the-background">The Background</h2>
<p>Life&#39;s been... interesting. Without going into too much detail, the past few years have been rough. Health issues, job changes, the usual chaos that comes with existing in this world.</p>
<p>But here&#39;s the thing — through it all, a few things kept me sane:</p>
<ol>
<li><strong>Tinkering with tech</strong> — Nothing clears my head like debugging a server at 2 AM</li>
<li><strong>Growing plants</strong> — There&#39;s something meditative about watching things grow</li>
<li><strong>Writing</strong> — Even if nobody reads it, getting thoughts out helps</li>
</ol>
<h2 id="why-this-blog">Why This Blog?</h2>
<p>I&#39;ve consumed so much free knowledge from random blogs and forums over the years. Time to give back.</p>
<p>Plus, I needed a project. Something to focus on that isn&#39;t doom-scrolling or worrying about things I can&#39;t control.</p>
<h2 id="what-to-expect">What to Expect</h2>
<ul>
<li>Tutorials when I figure something out</li>
<li>Rants when things don&#39;t work</li>
<li>Personal updates occasionally</li>
<li>No schedule, no pressure</li>
</ul>
<h2 id="a-note-on-shitty-life">A Note on &quot;Shitty Life&quot;</h2>
<p>Yeah, I mentioned that in the blog description. Life can be hard. Mental health is a real thing. If you&#39;re struggling, you&#39;re not alone.</p>
<p>I&#39;m not here to give advice I&#39;m not qualified to give. But I will say: find your thing. Whether it&#39;s tech, gardening, gaming, whatever — having something to focus on helps.</p>
<hr>
<p>Anyway, that&#39;s enough feelings for one post. Back to technical stuff next time.</p>
<p>Stay safe out there. 🤙</p>
]]></content:encoded>
  </item>
  <item>
    <title>Self-Hosting a WireGuard VPN</title>
    <link>https://derlocke.net/posts/networking-wireguard/</link>
    <guid isPermaLink="true">https://derlocke.net/posts/networking-wireguard/</guid>
    <pubDate>Mon, 15 Sep 2025 00:00:00 GMT</pubDate>
    <category>networking</category>
    <category>homelab</category>
    <category>tutorial</category>
    <description>Want secure remote access to your home network? WireGuard is fast, simple, and modern. Here&apos;s how to set it up.</description>
    <content:encoded><![CDATA[<p>Want secure remote access to your home network? WireGuard is fast, simple, and modern. Here&#39;s how to set it up.</p>
<h2 id="why-wireguard">Why WireGuard?</h2>
<ul>
<li><strong>Fast</strong> — Much better performance than OpenVPN</li>
<li><strong>Simple</strong> — Minimal codebase, easy to audit</li>
<li><strong>Modern crypto</strong> — ChaCha20, Curve25519, etc.</li>
<li><strong>Cross-platform</strong> — Linux, Windows, macOS, iOS, Android</li>
</ul>
<h2 id="server-setup-debian-ubuntu">Server Setup (Debian/Ubuntu)</h2>
<pre data-lang="bash"><code class="hljs language-bash"><span class="hljs-comment"># Install WireGuard</span>
<span class="hljs-built_in">sudo</span> apt install wireguard

<span class="hljs-comment"># Generate keys</span>
wg genkey | <span class="hljs-built_in">tee</span> /etc/wireguard/privatekey | wg pubkey &gt; /etc/wireguard/publickey
<span class="hljs-built_in">chmod</span> 600 /etc/wireguard/privatekey

<span class="hljs-comment"># Create config</span>
<span class="hljs-built_in">sudo</span> nano /etc/wireguard/wg0.conf</code></pre>
<h3 id="server-config-etc-wireguard-wg0-conf">Server Config (<code>/etc/wireguard/wg0.conf</code>)</h3>
<pre data-lang="ini"><code class="hljs language-ini"><span class="hljs-section">[Interface]</span>
<span class="hljs-attr">PrivateKey</span> = &lt;server-private-key&gt;
<span class="hljs-attr">Address</span> = <span class="hljs-number">10.0</span>.<span class="hljs-number">0.1</span>/<span class="hljs-number">24</span>
<span class="hljs-attr">ListenPort</span> = <span class="hljs-number">51820</span>
<span class="hljs-attr">PostUp</span> = iptables -A FORWARD -i wg0 -j ACCEPT<span class="hljs-comment">; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE</span>
<span class="hljs-attr">PostDown</span> = iptables -D FORWARD -i wg0 -j ACCEPT<span class="hljs-comment">; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE</span>

<span class="hljs-section">[Peer]</span>
<span class="hljs-comment"># Client 1</span>
<span class="hljs-attr">PublicKey</span> = &lt;client-public-key&gt;
<span class="hljs-attr">AllowedIPs</span> = <span class="hljs-number">10.0</span>.<span class="hljs-number">0.2</span>/<span class="hljs-number">32</span></code></pre>
<h3 id="enable-ip-forwarding">Enable IP Forwarding</h3>
<pre data-lang="bash"><code class="hljs language-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;net.ipv4.ip_forward=1&quot;</span> | <span class="hljs-built_in">sudo</span> <span class="hljs-built_in">tee</span> -a /etc/sysctl.conf
<span class="hljs-built_in">sudo</span> sysctl -p</code></pre>
<h3 id="start-wireguard">Start WireGuard</h3>
<pre data-lang="bash"><code class="hljs language-bash"><span class="hljs-built_in">sudo</span> systemctl <span class="hljs-built_in">enable</span> wg-quick@wg0
<span class="hljs-built_in">sudo</span> systemctl start wg-quick@wg0</code></pre>
<h2 id="client-config">Client Config</h2>
<pre data-lang="ini"><code class="hljs language-ini"><span class="hljs-section">[Interface]</span>
<span class="hljs-attr">PrivateKey</span> = &lt;client-private-key&gt;
<span class="hljs-attr">Address</span> = <span class="hljs-number">10.0</span>.<span class="hljs-number">0.2</span>/<span class="hljs-number">24</span>
<span class="hljs-attr">DNS</span> = <span class="hljs-number">10.0</span>.<span class="hljs-number">0.1</span>  <span class="hljs-comment"># Use your Pi-hole!</span>

<span class="hljs-section">[Peer]</span>
<span class="hljs-attr">PublicKey</span> = &lt;server-public-key&gt;
<span class="hljs-attr">Endpoint</span> = your-domain.com:<span class="hljs-number">51820</span>
<span class="hljs-attr">AllowedIPs</span> = <span class="hljs-number">0.0</span>.<span class="hljs-number">0.0</span>/<span class="hljs-number">0</span>  <span class="hljs-comment"># Route all traffic through VPN</span>
<span class="hljs-attr">PersistentKeepalive</span> = <span class="hljs-number">25</span></code></pre>
<h2 id="tips">Tips</h2>
<ul>
<li><strong>Port forwarding:</strong> Open UDP 51820 on your router</li>
<li><strong>Dynamic DNS:</strong> Use DuckDNS or similar if you don&#39;t have a static IP</li>
<li><strong>Multiple devices:</strong> Just add more [Peer] sections</li>
</ul>
<h2 id="my-setup">My Setup</h2>
<p>I run WireGuard in an LXC container on Proxmox. Works perfectly. I can access my home network from anywhere, securely.</p>
<p>On a Silverblue or Bluefin laptop, pair the client side with <a href="https://derlocke.net/projects.html#kiwi-killswitch">kiwi-killswitch</a>: a fail-closed firewall that only lets traffic out through your WireGuard tunnel, so nothing leaks when the VPN drops.</p>
<hr>
<p>Questions? Hit me up. Stay secure! 🔐</p>
]]></content:encoded>
  </item>
</channel>
</rss>
