<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:wfw="http://wellformedweb.org/CommentAPI/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:atom="http://www.w3.org/2005/Atom"
 xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
 xmlns:georss="http://www.georss.org/georss"
 xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
 xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<atom:link href="/blog/rss.xml" rel="self" type="application/rss+xml" />
<title>Neo's Blog</title>
<link>/blog</link>
<description><![CDATA[Ramblings about Emacs, self-hosting and everything FOSS]]></description>
<language>en</language>
<lastBuildDate>Thu, 07 May 2026 20:25:31 -0700</lastBuildDate>
<generator>Emacs 30.2 org-publish-rss.el 0.8</generator>
<item>
<title>Creating a universal chat server with Nix and Prosody</title>
<link>/blog/xmpp_activitypub_nix.html</link>
<pubDate>Thu, 07 May 2026 20:02:43 -0700</pubDate>
<guid>/blog/xmpp_activitypub_nix.html</guid>
<description>
<![CDATA[<div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#org27dccf6">Intro</a></li>
<li><a href="#org173ed47">Stack</a></li>
<li><a href="#org7b111f0">Why XMPP</a></li>
<li><a href="#org4f367bb">XMPP Pain Points</a></li>
<li><a href="#org711f183">Initial Setup</a></li>
<li><a href="#orgc7725ad">DNS Setup</a></li>
</ul>
</div>
</div>
<p>
Work in progress post
</p>
<div id="outline-container-org27dccf6" class="outline-2">
<h2 id="org27dccf6">Intro</h2>
<div class="outline-text-2" id="text-org27dccf6">
<p>
I'm working on creating a decentralized identity
</p>
</div>
</div>
<div id="outline-container-org173ed47" class="outline-2">
<h2 id="org173ed47">Stack</h2>
<div class="outline-text-2" id="text-org173ed47">
<ul class="org-ul">
<li>nix</li>
<li>hertnzer</li>
<li>prosody</li>
</ul>
</div>
</div>
<div id="outline-container-org7b111f0" class="outline-2">
<h2 id="org7b111f0">Why XMPP</h2>
<div class="outline-text-2" id="text-org7b111f0">
<p>
I wanted something that is easy to self host and extend as needed. XMPP is a very old and well documented format so I have confidence it will be around for a long time, even if it might never get extremely popular.
It's also fairly light, After using it for months my database is a 520kb sqlite file, prosody itself is idling at 90mb (which seems relatively high tbh), the IRC gateway is using 30mb and the matrix gateway is idling at 3mb
</p>

<p>
I considered Matrix but the setup seemed rather involved. <a href="https://github.com/timokoesters/conduit">Conduit</a> looks promising though
</p>
</div>
</div>
<div id="outline-container-org4f367bb" class="outline-2">
<h2 id="org4f367bb">XMPP Pain Points</h2>
<div class="outline-text-2" id="text-org4f367bb">
<p>
The clients suck. The best I've been able to find is Gajim for my PC and Monal for my phone.
</p>
</div>
</div>
<div id="outline-container-org711f183" class="outline-2">
<h2 id="org711f183">Initial Setup</h2>
<div class="outline-text-2" id="text-org711f183">
<p>
I use <a href="https://nixos.org/">https://nixos.org/</a> as much package manager on every platform. The amount of packages included makes experimenting with services really easy so I wanted to use a nixOS install as my
</p>

<p>
I went with a 2gb VPS on Hetzner and it's been working flawlessly.
</p>

<p>
To set up a basic nix OS follow the instructions <a href="https://nix-community.github.io/nixos-anywhere/quickstart.html">here</a>
I didn't change much other than adjusting the file sizes, but just for reference:
</p>

<div class="org-src-container">
<pre class="src src-nix" id="org834f8d3">{
<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">inputs.nixpkgs.url</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"github:NixOS/nixpkgs/nixpkgs-unstable"</span>;
<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">inputs.disko.url</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"github:nix-community/disko"</span>;
<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">inputs.disko.inputs.nixpkgs.follows</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"nixpkgs"</span>;
<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">inputs.deploy-rs.url</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"github:serokell/deploy-rs"</span>;
<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">inputs.agenix.url</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"github:ryantm/agenix"</span>;

<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">outputs</span><span style="color: #61647a;"> </span>=
<span style="color: #61647a;">    </span>{
<span style="color: #61647a;">      </span>self,
<span style="color: #61647a;">      </span>nixpkgs,
<span style="color: #61647a;">      </span>disko,
<span style="color: #61647a;">      </span>deploy-rs,
<span style="color: #61647a;">      </span>agenix,
<span style="color: #61647a;">    </span>}:
<span style="color: #61647a;">    </span>{
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">nixosConfigurations.hetzner-cloud</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>nixpkgs.lib.nixosSystem<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">        </span><span style="color: #4ae2f0;">system</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"x86_64-linux"</span>;
<span style="color: #61647a;">        </span><span style="color: #4ae2f0;">modules</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>[
<span style="color: #61647a;">          </span>disko.nixosModules.disko
<span style="color: #61647a;">          </span><span style="color: #b6a0ff;">./configuration.nix</span>
<span style="color: #61647a;">          </span><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">Using</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">agenix</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">for</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">secrets</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">management
</span><span style="color: #61647a;">          </span>agenix.nixosModules.default
<span style="color: #61647a;">          </span><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">Basic</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">reverse</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">proxy</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">and</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">SSL</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">Configuration
</span><span style="color: #61647a;">          </span><span style="color: #b6a0ff;">./nginx.nix</span>
<span style="color: #61647a;">          </span><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">Prosody</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">Config
</span><span style="color: #61647a;">          </span><span style="color: #b6a0ff;">./xmpp.nix</span>
<span style="color: #61647a;">          </span><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">Spoilers</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">for</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">a</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">future</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">article?
</span><span style="color: #61647a;">          </span><span style="color: #b6a0ff;">./gotosocial.nix</span>
<span style="color: #61647a;">        </span>];
<span style="color: #61647a;">      </span>};

<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">deploy.nodes.hertzner-cloud</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">        </span><span style="color: #4ae2f0;">hostname</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"public</span><span style="color: #61647a;"> </span><span style="color: #2fafff;">IP"</span>;
<span style="color: #61647a;">        </span><span style="color: #4ae2f0;">profiles.system</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">          </span><span style="color: #4ae2f0;">user</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"root"</span>;
<span style="color: #61647a;">          </span><span style="color: #4ae2f0;">sshUser</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"root"</span>;
<span style="color: #61647a;">          </span><span style="color: #4ae2f0;">path</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>deploy-rs.lib.x86_64-linux.activate.nixos<span style="color: #61647a;"> </span>self.nixosConfigurations.hetzner-cloud;
<span style="color: #61647a;">        </span>};
<span style="color: #61647a;">      </span>};
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">checks</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>builtins.mapAttrs<span style="color: #61647a;"> </span>(system:<span style="color: #61647a;"> </span>deployLib:<span style="color: #61647a;"> </span>deployLib.deployChecks<span style="color: #61647a;"> </span>self.deploy)<span style="color: #61647a;"> </span>deploy-rs.lib;
<span style="color: #61647a;">    </span>};
<span style="color: #000000; background-color: #d0d040;">}</span>
</pre>
</div>

<div class="org-src-container">
<pre class="src src-nix" id="orgc1c6458"><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">Example</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">to</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">create</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">a</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">bios</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">compatible</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">gpt</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">partition
</span>{<span style="color: #61647a;"> </span>lib,<span style="color: #61647a;"> </span>...<span style="color: #61647a;"> </span>}:
{
<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">disko.devices</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">    </span><span style="color: #4ae2f0;">disk.disk1</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">device</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>lib.mkDefault<span style="color: #61647a;"> </span><span style="color: #2fafff;">"/dev/sda"</span>;
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">type</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"disk"</span>;
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">content</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">        </span><span style="color: #4ae2f0;">type</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"gpt"</span>;
<span style="color: #61647a;">        </span><span style="color: #4ae2f0;">partitions</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">          </span><span style="color: #4ae2f0;">boot</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">name</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"boot"</span>;
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">size</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"1M"</span>;
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">type</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"EF02"</span>;
<span style="color: #61647a;">          </span>};
<span style="color: #61647a;">          </span><span style="color: #4ae2f0;">esp</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">name</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"ESP"</span>;
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">size</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"500M"</span>;
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">type</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"EF00"</span>;
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">content</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">              </span><span style="color: #4ae2f0;">type</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"filesystem"</span>;
<span style="color: #61647a;">              </span><span style="color: #4ae2f0;">format</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"vfat"</span>;
<span style="color: #61647a;">              </span><span style="color: #4ae2f0;">mountpoint</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"/boot"</span>;
<span style="color: #61647a;">            </span>};
<span style="color: #61647a;">          </span>};
<span style="color: #61647a;">          </span><span style="color: #4ae2f0;">root</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">name</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"root"</span>;
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">size</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"100%"</span>;
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">content</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">              </span><span style="color: #4ae2f0;">type</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"lvm_pv"</span>;
<span style="color: #61647a;">              </span><span style="color: #4ae2f0;">vg</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"pool"</span>;
<span style="color: #61647a;">            </span>};
<span style="color: #61647a;">          </span>};
<span style="color: #61647a;">        </span>};
<span style="color: #61647a;">      </span>};
<span style="color: #61647a;">    </span>};
<span style="color: #61647a;">    </span><span style="color: #4ae2f0;">lvm_vg</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">pool</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">        </span><span style="color: #4ae2f0;">type</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"lvm_vg"</span>;
<span style="color: #61647a;">        </span><span style="color: #4ae2f0;">lvs</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">          </span><span style="color: #4ae2f0;">root</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">size</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"100%FREE"</span>;
<span style="color: #61647a;">            </span><span style="color: #4ae2f0;">content</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">              </span><span style="color: #4ae2f0;">type</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"filesystem"</span>;
<span style="color: #61647a;">              </span><span style="color: #4ae2f0;">format</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"ext4"</span>;
<span style="color: #61647a;">              </span><span style="color: #4ae2f0;">mountpoint</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"/"</span>;
<span style="color: #61647a;">              </span><span style="color: #4ae2f0;">mountOptions</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>[
<span style="color: #61647a;">                </span><span style="color: #2fafff;">"defaults"</span>
<span style="color: #61647a;">              </span>];
<span style="color: #61647a;">            </span>};
<span style="color: #61647a;">          </span>};
<span style="color: #61647a;">        </span>};
<span style="color: #61647a;">      </span>};
<span style="color: #61647a;">    </span>};
<span style="color: #61647a;">  </span>};
<span style="color: #000000; background-color: #d0d040;">}</span>
</pre>
</div>

<div class="org-src-container">
<pre class="src src-nix" id="orgcec421f">{
<span style="color: #61647a;">  </span>modulesPath,
<span style="color: #61647a;">  </span>lib,
<span style="color: #61647a;">  </span>pkgs,
<span style="color: #61647a;">  </span>...
}@args:
{
<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">imports</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>[
<span style="color: #61647a;">    </span>(modulesPath<span style="color: #61647a;"> </span>+<span style="color: #61647a;"> </span><span style="color: #2fafff;">"/installer/scan/not-detected.nix"</span>)
<span style="color: #61647a;">    </span>(modulesPath<span style="color: #61647a;"> </span>+<span style="color: #61647a;"> </span><span style="color: #2fafff;">"/profiles/qemu-guest.nix"</span>)
<span style="color: #61647a;">    </span><span style="color: #b6a0ff;">./disk-config.nix</span>
<span style="color: #61647a;">  </span>];
<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">boot.loader.grub</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">    </span><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">no</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">need</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">to</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">set</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">devices,</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">disko</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">will</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">add</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">all</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">devices</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">that</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">have</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">a</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">EF02</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">partition</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">to</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">the</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">list</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">already
</span><span style="color: #61647a;">    </span><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">devices</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">=</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">[</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">];
</span><span style="color: #61647a;">    </span><span style="color: #4ae2f0;">efiSupport</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">true</span>;
<span style="color: #61647a;">    </span><span style="color: #4ae2f0;">efiInstallAsRemovable</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">true</span>;
<span style="color: #61647a;">  </span>};

<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">services.openssh</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">    </span><span style="color: #4ae2f0;">enable</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">true</span>;
<span style="color: #61647a;">    </span><span style="color: #4ae2f0;">settings</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">PasswordAuthentication</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">false</span>;
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">KbdInteractiveAuthentication</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">false</span>;
<span style="color: #61647a;">    </span>};
<span style="color: #61647a;">  </span>};

<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">services.fail2ban</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">    </span><span style="color: #4ae2f0;">enable</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">true</span>;
<span style="color: #61647a;">    </span><span style="color: #4ae2f0;">bantime-increment.enable</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">true</span>;
<span style="color: #61647a;">    </span><span style="color: #4ae2f0;">jails</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>{
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">nginx-http-auth.settings.enabled</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">true</span>;
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">nginx-botsearch.settings.enabled</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">true</span>;
<span style="color: #61647a;">      </span><span style="color: #4ae2f0;">nginx-bad-request.settings.enabled</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">true</span>;
<span style="color: #61647a;">    </span>};
<span style="color: #61647a;">  </span>};

<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">environment.systemPackages</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">map</span><span style="color: #61647a;"> </span>lib.lowPrio<span style="color: #61647a;"> </span>[
<span style="color: #61647a;">    </span><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">Manual</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">plugins</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">todo
</span><span style="color: #61647a;">    </span>pkgs.mercurial
<span style="color: #61647a;">    </span>pkgs.curl
<span style="color: #61647a;">    </span>pkgs.gitMinimal
<span style="color: #61647a;">    </span>pkgs.openssl
<span style="color: #61647a;">    </span>pkgs.dig
<span style="color: #61647a;">  </span>];

<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">time.timeZone</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"UTC"</span>;

<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">users.users.root.openssh.authorizedKeys.keys</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span>[
<span style="color: #61647a;">    </span><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">change</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">this</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">to</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">your</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">ssh</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">key
</span><span style="color: #61647a;">    </span><span style="color: #2fafff;">"MY</span><span style="color: #61647a;"> </span><span style="color: #2fafff;">KEY"</span>
<span style="color: #61647a;">  </span>]
<span style="color: #61647a;">  </span>++<span style="color: #61647a;"> </span>(args.extraPublicKeys<span style="color: #61647a;"> </span><span style="color: #79a8ff;">or</span><span style="color: #61647a;"> </span>[<span style="color: #61647a;"> </span>]);<span style="color: #61647a;"> </span><span style="color: #ef8386;">#</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">this</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">is</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">used</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">for</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">unit-testing</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">this</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">module</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">and</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">can</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">be</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">removed</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">if</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">not</span><span style="color: #61647a;"> </span><span style="color: #ef8386;">needed
</span>
<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">system.stateVersion</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #2fafff;">"24.05"</span>;

<span style="color: #61647a;">  </span><span style="color: #4ae2f0;">virtualisation.containers.enable</span><span style="color: #61647a;"> </span>=<span style="color: #61647a;"> </span><span style="color: #feacd0;">true</span>;

<span style="color: #000000; background-color: #d0d040;">}</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-orgc7725ad" class="outline-2">
<h2 id="orgc7725ad">DNS Setup</h2>
<div class="outline-text-2" id="text-orgc7725ad">
<p>
Prosody requires you to configure several DNS records: an A record
</p>

<p>
The documentation <a href="https://prosody.im/doc/dns">here</a> is fairly comprehensive
</p>

<p>
⚠️ I used namecheap for my domain which has proven itself to be quite annoying. One gotcha is the SRV Record GUI does not accurately show the values you type in, for example, typing in the host as _xmpp-server._tcp.conference.im will only show <code>_xmpp-server._tcp</code> in the UI
</p>

<p>
You can check if the values are set correctly through the following URL (replace example.com with your domain). I just used trial and error with manual dig calls until I got what I wanted
</p>

<p>
<a href="https://ap.www.namecheap.com/Domains/dns/GetAdvancedDnsInfo?domainName=example.com&amp;fillTransferInfo=false">https://ap.www.namecheap.com/Domains/dns/GetAdvancedDnsInfo?domainName=example.com&amp;fillTransferInfo=false</a>
</p>

<p>
In the future Id like to move to a declarative setup with terraform as I did not anticipate just how many records Id have to make
</p>

<p>
For my setup Ive made records pointing to the top level domain as well as CNAME records for each one of the components I use, in my case
</p>

<ul class="org-ul">
<li>biboumi.example.com (IRC Gateway)</li>
<li>matridge.example.com (Matrix Gateway)</li>
<li>conference.example.com (Group XMPP Chats)</li>
<li>turn.example.com (Turn/Stun)</li>
<li>upload.example.com (File sharing through XMPP)</li>
</ul>
</div>
</div>
]]>
</description></item>
<item>
<title>Using XQuery to wrangle JSON</title>
<link>/blog/xpath_json.html</link>
<pubDate>Thu, 07 May 2026 19:49:25 -0700</pubDate>
<guid>/blog/xpath_json.html</guid>
<description>
<![CDATA[<div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#intro"><span class="todo TODO">TODO</span> Intro</a></li>
<li><a href="#json">JSON</a>
<ul>
<li><a href="#jq">JQ</a></li>
<li><a href="#JMESPath">JMESPath</a></li>
<li><a href="#kubectl">Kubectl JSONPath</a></li>
</ul>
</li>
<li><a href="#xml">XML</a>
<ul>
<li><a href="#xidel">Xidel</a></li>
<li><a href="#basex">BaseX</a></li>
<li><a href="#xee">Xee</a></li>
</ul>
</li>
<li><a href="#xee">Jee</a></li>
</ul>
</div>
</div>
<p>
Work in progress post
</p>
<div id="outline-container-intro" class="outline-2">
<h2 id="intro"><span class="todo TODO">TODO</span> Intro</h2>
<div class="outline-text-2" id="text-intro">
<p>
At my work during the day to day I spend an unreasonable amount of time parsing and modifying large blobs of JSON (or, well usually it's YAML 🤮)
</p>

<p>
Because of that I try to make sure I use the right tool for the job, which is usually JQ. But as someone who's often intrigued by "obsolete" technologies I was always envious of the XML stack, the XPaths the XQueries the XLSTs&#x2026;
</p>
</div>
</div>
<div id="outline-container-json" class="outline-2">
<h2 id="json">JSON</h2>
<div class="outline-text-2" id="text-json">
</div>
<div id="outline-container-jq" class="outline-3">
<h3 id="jq">JQ</h3>
<div class="outline-text-3" id="text-jq">
<p>
JQ is the lingua franca of dealing with json. I don't really have any issues with it but, personally, I struggle a lot with the syntax outside of the very basics. One thing I find particularly ugly is dealing with complicated keys, eg <code>jq '.["Key With Space Or Something IDK"]'</code>
</p>
</div>
</div>
<div id="outline-container-JMESPath" class="outline-3">
<h3 id="JMESPath">JMESPath</h3>
<div class="outline-text-3" id="text-JMESPath">
<p>
Mainly seen in AWS CLI I actually quite like JMESPath
</p>
</div>
</div>
<div id="outline-container-kubectl" class="outline-3">
<h3 id="kubectl">Kubectl JSONPath</h3>
<div class="outline-text-3" id="text-kubectl">
<p>
Kubectl supports JSONPath
</p>
</div>
</div>
</div>
<div id="outline-container-xml" class="outline-2">
<h2 id="xml">XML</h2>
<div class="outline-text-2" id="text-xml">
</div>
<div id="outline-container-xidel" class="outline-3">
<h3 id="xidel">Xidel</h3>
<div class="outline-text-3" id="text-xidel">
<p>
Xidel is by far the easiest to use XQuery tool I've seen. My main issue with it is that the errors are really hard to understand
</p>
</div>
</div>
<div id="outline-container-basex" class="outline-3">
<h3 id="basex">BaseX</h3>
<div class="outline-text-3" id="text-basex">
<p>
BaseX standard library seems to be by far the most comprehensive out of all the XML tools I've seen, but I wasn't able to pass JSON to it directly, requiring a manual json:doc call
</p>
</div>
</div>
<div id="outline-container-xee" class="outline-3">
<h3 id="xee">Xee</h3>
<div class="outline-text-3" id="text-xee">
<p>
Xee is the new ✨Rust✨ XPath engine and CLI
</p>

<p>
Currently <code>xee xpath</code> expects a well-formed XML document as the input, which makes it unusable for us
</p>
</div>
</div>
</div>
<div id="outline-container-xee" class="outline-2">
<h2 id="xee">Jee</h2>
<div class="outline-text-2" id="text-xee">
<p>
Jee 
</p>
</div>
</div>
]]>
</description></item>
</channel>
</rss>
