<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="/rss.xls"?>
<rss version="2.0"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:dcterms="http://purl.org/dc/terms/"
     xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Open source software and nice hardware</title>
<link>http://box.matto.nl/index.html</link>
<atom:link href="http://box.matto.nl/index.xml" rel="self" type="application/rss+xml"/>
<description>Open source software and nice hardware</description>
<generator>A Common Lisp thingy</generator>
<pubDate>Wed, 11 Mar 2026 16:41:56 +0100</pubDate>
<item>
<title>Deploy a Matrix server using Conduit and Cinny on FreeBSD in the homelab</title>
<link>https://box.matto.nl/deploy-a-matrix-server-using-conduit-and-cinny-on-freebsd-in-the-homelab.html</link>
<guid isPermaLink="false">https://box.matto.nl/deploy-a-matrix-server-using-conduit-and-cinny-on-freebsd-in-the-homelab.html</guid>
<pubDate>Wed, 11 Mar 2026 01:00:00 +0100</pubDate>
<dcterms:modified>2026-03-11T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="deploy_a_matrix_server_using_conduit_and_cinny_on_freebsd_in_the_homelab">Deploy a Matrix server using Conduit and Cinny on FreeBSD in the homelab</h1>

<p>Here is a small post about deploying a Matrix server in the homelab.</p>

<p>The goal is a Matrix server running on a FreeBSD jail that can be
used from the web browser on your desktop.</p>

<p>It is a quick-and-dirty configuration, to get you started.</p>

<p>This setup is for testing purposes. The server will not be exposed
to the internet and it will not federate with the Matrix network.</p>

<p>The setup contains three parts:</p>

<ul>
<li>the Conduit Matrix server</li>
<li>the Cinny web Matrix client</li>
<li>NGINX as reverse proxy</li>
</ul>

<h2 id="domain_names">Domain names</h2>

<p>First, create in your local DNS server two subdomain names, one for
Conduit and one for Cinny, f.e., <code>matrix.example.com</code> and
<code>cinny.example.com</code>, both pointing to the ip-address of the jail.</p>

<h2 id="certificates">Certificates</h2>

<p>Create certificates for the two domains.</p>

<p>If you haven't setup a local CA, do that first, for example using
<a href="https://github.com/FiloSottile/mkcert" >mkcert</a>.</p>

<p>Place the certificate files in <code>/etc/ssl/certs/</code> in the jail.</p>

<h2 id="conduit">Conduit</h2>

<p><a href="https://conduit.rs/" >Conduit</a> advertises itself as a simple, fast and reliable matrix server.</p>

<p>It is available as a FreeBSD package.</p>

<p>Copy the file <code>/usr/local/etc/conduit.toml.sample</code> to <code>/usr/local/etc/conduit.toml</code>
and edit this file:</p>

<h4 id="servername">Servername</h4>

<p>This is the subdomain of your Conduitserver.</p>

<p><code>servername = &quot;matrix.example.com&quot;</code></p>

<h4 id="registration_token">Registration token</h4>

<p>New users can register with this token.</p>

<p><code>registration_token = &quot;very-secret&quot;</code></p>

<h4 id="allow_federation">Allow federation</h4>

<p>We won't expose our server to the internet. Federation will not be required and we will not allow it.</p>

<p><code>allow_federation = false</code></p>

<h2 id="cinny">Cinny</h2>

<p><a href="https://cinny.in/" >Cinny</a> is yet another Matrix client. It runs as a web application.
You access it with your web browser.</p>

<p>It is available as a FreeBSD package.</p>

<p>The package manager installs Cinny in <code>/usr/local/www/cinny</code>.</p>

<p>In this directory, copy the file <code>config.json.example</code> to <code>config.json</code> and edit it:</p>

<h4 id="homeserverlist">homeserverList</h4>

<p>Delete all entries in the homeserverList and insert the subdomain of your Conduit server.</p>

<pre><code>&quot;homeserverList&quot;: [
  &quot;matrix.example.com&quot;
],
</code></pre>

<h4 id="featuredcommunities">featuredCommunities</h4>

<p>Probably you can delete a lot here. I only cleaned the list &quot;servers&quot;:</p>

<pre><code>&quot;servers&quot;: [&quot;matrix.example.com&quot;]
</code></pre>

<h2 id="nginx">NGINX</h2>

<p><a href="https://nginx.org/en/" >NGINX</a> is a very great web server.</p>

<p>It is available as a FreeBSD package.</p>

<p>Here we use it as a reverse proxy.</p>

<p>In the file <code>/usr/local/etc/nginx/nginx.conf</code> add two blocks for the
virtual servers:</p>

<pre><code>server {
    listen *:443 ssl;
    server_name matrix.example.com;
    client_max_body_size 1G;
    ssl_certificate /etc/ssl/certs/matrix.example.com.crt;
    ssl_certificate_key /etc/ssl/certs/matrix.example.com.key;
    location / {
       proxy_pass http://127.0.0.1:6167;
    }
}

server {
    listen *:443 ssl;
    server_name cinny.example.com;
    client_max_body_size 1G;
    ssl_certificate /etc/ssl/certs/cindy.example.com.crt;
    ssl_certificate_key /etc/ssl/certs/cindy.example.com.key;
    location / {
       root /usr/local/www/cinny;
       index index.html;
    }
}
</code></pre>

<h2 id="allow_the_daemons_to_run">Allow the daemons to run</h2>

<p>In <code>/etc/rc.conf</code> add two lines to allow the daemons to run.</p>

<pre><code>conduit_enable=&quot;YES&quot;
nginx_enable=&quot;YES&quot;
</code></pre>

<p>Start or restart the Conduit and the NGINX daemons.</p>

<h2 id="create_a_few_accounts">Create a few accounts</h2>

<p>Open <code>cinny.example.com</code> in your web browser.</p>

<p>Register as new account. Choose your server (matrix.example.com),
and provide a user name and a password. Insert the registration
token from the Conduit configuration (above this is mentioned as
&quot;very-secret&quot;) in the field below the two password fields.</p>

<p>Repeat, to get a few accounts to play with.</p>

<p>Have fun playing with Matrix in you homelab!</p>
]]></description>
</item>
<item>
<title>Books of February 2026</title>
<link>https://box.matto.nl/books-of-february-2026.html</link>
<guid isPermaLink="false">https://box.matto.nl/books-of-february-2026.html</guid>
<pubDate>Sun, 01 Mar 2026 01:00:00 +0100</pubDate>
<dcterms:modified>2026-03-01T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="books_of_february_2026">Books of February 2026</h1>

<p>Below are the two books that I finished this month. I started a
third one, but didn't like and decided not to finish it.</p>

<h2 id="non-fiction">Non-fiction</h2>

<h3 id="the_beak_of_the_finch:_a_story_of_evolution_in_our_time_by_jonathan_weiner_(1994)">The Beak of the Finch: A Story of Evolution in Our Time by Jonathan Weiner (1994)</h3>

<ul>
<li>332 pages</li>
<li>5 stars</li>
</ul>

<p>A book about scientific research aimed at better understanding
natural selection, sexual selection, and evolution.</p>

<p>Much of the book is about two biologists, Peter and Rosemary Grant,
doing a decades long research of finches on a small vulcanic island
in the Galapagos. Also some other evolutionairy biological research
is discussed. The book explains how natural selection and evolution
can indeed be seen in action, contrairy the old idea that evolution
moves too slow to witness.</p>

<p>I learned from it that in nature there is always competition and that
in hard times, like when food is extra scarce, the selection pressure
increases and evolution accelerates.</p>

<p>A very interesting book, easy to read and understand.</p>

<h2 id="fiction">Fiction</h2>

<h3 id="a_maze_of_death_by__philip_k._dick_(1970)">A Maze of Death by  Philip K. Dick (1970)</h3>

<ul>
<li>216 pages</li>
<li>5 stars</li>
</ul>

<p>Science fiction story of a very small group of people colonizing
the planet Delmak-O. They arrived in so-called &quot;nosers&quot;, which are
one-way space ships. The story develops when bad things starting to
happen. This is, as often with works from this writer, a rather short
book.</p>

<p>It is a good story. with enough tension and surprises to keep you
engaged. Recommended!</p>
]]></description>
</item>
<item>
<title>Translate Texinfo files using po4a</title>
<link>https://box.matto.nl/translate-texinfo-files-using-po4a.html</link>
<guid isPermaLink="false">https://box.matto.nl/translate-texinfo-files-using-po4a.html</guid>
<pubDate>Tue, 17 Feb 2026 01:00:00 +0100</pubDate>
<dcterms:modified>2026-02-17T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="translate_texinfo_files_using_po4a">Translate Texinfo files using po4a</h1>

<h2 id="texinfo">Texinfo</h2>

<p><a href="https://www.gnu.org/software/texinfo/manual/texinfo/html_node/index.html" >Texinfo</a> is a
brilliant hypertext system that predates HTML. You access it with <code>info</code>, which
is a text mode application. The content consists of a number of nodes. 
Each node is an information element. You access the nodes through menus,
hyperlinks, and indices. Also you can &quot;walk&quot; through a info file with
keys like <code>[</code> and <code>]</code>. See <code>info info</code>.</p>

<p>Leveraging the power of TeX, Texinfo files can be used to produce
gorgeous looking PDF files, like the GNU books. Compared to
generating PDF files from LaTeX, generating PDF files from Texinfo
is incredible fast.</p>

<h2 id="po4a">po4a</h2>

<p>The <a href="https://www.po4a.org/index.php.en" >po4a (PO for anything)</a>
eases documentation translations and their maintenance.</p>

<p>This is what this website says:</p>

<blockquote>
It extracts the translatable material from the original document,
and places it into a PO file that is adapted to the translation
process. Once this PO file is updated by the translator, po4a
re-injects the translation into the structure of the original
document to generate a translated document.
</blockquote>

<p>po4a supports several documentation formats, including Texinfo.</p>

<h2 id="workflow">Workflow</h2>

<p>In general, the workflow is something like this:</p>

<ul>
<li>Create a PO-file from the orginal Texinfo file.</li>
<li>Add the translations to the PO-file.</li>
<li>Generate a translated Texinfo file.</li>
<li>Use the translated Texinfo file like any other Texinfo file, e.g., create an Info file and a PDF with it.</li>
</ul>

<p>When the original Texinfo file changes:</p>

<ul>
<li>Update the PO-file.</li>
<li>Add or change translations where needed.</li>
<li>Generate a new translated Texinfo file.</li>
</ul>

<h2 id="store_the_original_texinfo_file">Store the original Texinfo file</h2>

<p>In order for the update of the PO-file to work, you'll need both the
original Texinfo file as well as the new version of the Texinfo file.
It is therefor important to keep a copy of the original Texinfo file.</p>

<p>In the examples below, two versions of the Texinfo file are mentioned:</p>

<ul>
<li><code>testinfo-v1.texi</code>: this represents the original file to be translated.</li>
<li><code>testinfo-v2.texi</code>: this represents a new version of the file to be translated.</li>
</ul>

<h2 id="create_a_po-file">Create a PO-file</h2>

<p>To create the PO-file from the original Texinfo file, using the following command.</p>

<pre><code>po4a-updatepo \
--format texinfo \
--master testinfo-v1.texi \
--po testinfo.po
</code></pre>

<p>Replace <code>testinfo-v1.texi</code> with the name of the original Texinfo file.</p>

<p>Replace <code>testinfo.po</code> with the desired name of the PO-file.</p>

<h2 id="translating_the_po-file">Translating the PO-file</h2>

<p>The PO-file contains a lot of strings and paragraphs to be translated.</p>

<h3 id="translating_strings">Translating strings</h3>

<p>The entry for a string in the PO-file is something like this:</p>

<pre><code>#. type: menuentry
#: testinfo-v2.texi:30
msgid &quot;Fundamental stuff&quot;
msgstr &quot;&quot;
</code></pre>

<p>The first line containing the type differs for the roles of the string in the Texinfo document.</p>

<ul>
<li>The line starting with <code>msgid</code> is a line to be translated.</li>
<li>The line starting with <code>msgstr</code> is where the translation must be paced.</li>
</ul>

<h3 id="translating_paragraphs">Translating paragraphs</h3>

<p>The entry for a paragraph looks something likes this:</p>

<pre><code>#. type: Plain text
#: testinfo.texi:24
msgid &quot;&quot;
&quot;In this chapter I define the concepts that will be used throughout the rest &quot;
&quot;of the document.  Moreover, measures of efficiencies as well as bounds of &quot;
&quot;complexity will be introduced.&quot;
msgstr &quot;&quot;
</code></pre>

<p>The translation of the paragraph must be placed right below the line starting
with <code>msgstr</code>:</p>

<pre><code>#. type: Plain text
#: testinfo.texi:24
msgid &quot;&quot;
&quot;In this chapter I define the concepts that will be used throughout the rest &quot;
&quot;of the document.  Moreover, measures of efficiencies as well as bounds of &quot;
&quot;complexity will be introduced.&quot;
msgstr &quot;&quot;
&quot;In dit hoofdstuk definieer ik de concepten die gebruikt worden in de rest &quot;
&quot; ... &quot;
</code></pre>

<p>The lines in the translated paragraph start with a double quote (<code>&quot;</code>) and
end with a space and a double quote.</p>

<p>The last line of the translated paragraph ends with a double quote without a
space, just like the last line of the paragraph in the original language.</p>

<p>(Example text copied from <a href="https://linuxgazette.net/issue76/spiel.html" >Writing Documentation, Part IV: Texinfo</a> on Linux Gazette.)</p>

<h3 id="texinfo_commands_in_paragraphs">Texinfo commands in paragraphs</h3>

<p>Texinfo commands require special formatting of the lines.</p>

<p>For this, we make use of the <code>\n</code> formatting in the strings and paragraphs:</p>

<p>String example:</p>

<pre><code>#. type: smallexample
#: testinfo.texi:1421
#, no-wrap
msgid &quot;Original line to be translated\n&quot;
msgstr &quot;Translated line\n&quot;
</code></pre>

<p>Sometimes po4a has recognized the Texinfo command and treated as such,
which can be seen at the type of the PO-element, as here above.</p>

<p>Other times the Texinfo command appears inside a paragraphs to be translated.
Here we make uses of careful <code>\n</code> formatting in the translated paragraph:</p>

<pre><code>&quot; ... &quot;
&quot;Some text inside the paragraph\n&quot;
&quot;@ifnottex \n@xref{Some-ref}.\n@end ifnottex\n&quot;
&quot;@iftex \n@xref{Some-other-ref}. \n@end iftex\n&quot;
&quot;Some other text inside the paragraph. &quot;
&quot; ... &quot;
</code></pre>

<p>Not: the <code>\n</code> is directly followed by a double quote, without a space before
the double quote.</p>

<h2 id="update_a_po-file">Update a PO-file</h2>

<p>When later the original Texinfo file gets an update, we have to reflect those 
changes in our translated file.</p>

<p>Here's how to update the PO-file. Note the use of the name of the new
version of the Texinfo file (<code>testinfo-v2.texi</code>) and the name of original
file the PO-file was created with (<code>testinfo-v1.texi</code>).</p>

<pre><code>po4a-updatepo \
  --format texinfo \
  --master testinfo-v2.texi \
  --previous testinfo-v1.texi \
  --po testinfo.po
</code></pre>

<p>The PO-file in the command above is the same file we created in the first
step and has been filled with our translations.</p>

<h2 id="how_to_recognize_changes_in_the_updated_po-file">How to recognize changes in the updated PO-file</h2>

<p>After running the <code>po4a-updatepo</code> command, the PO-file with our translations
is changed. <code>po4a</code> has merged the changes into it.</p>

<p>This means we must go through the PO-file again, to add or change translations.
Below follows how to recognize new text, deleted text and changed text.</p>

<h3 id="new_text">New text</h3>

<p>New lines and paragraphs can be recognized by an empty <code>msgstr</code>. Example:</p>

<pre><code>msgid &quot;Very new chapter&quot;
msgstr &quot;&quot;
</code></pre>

<h3 id="deleted_text">Deleted text</h3>

<p>Deleted text can be recognized by a pound char (<code>#</code>) at the start of the <code>msgid</code> and  <code>msgstr</code> lines. Example:</p>

<pre><code>#~ msgid &quot;This line will be deleted in the next version.&quot;
#~ msgstr &quot;Deze regel wordt in de volgende versie verwijderd.&quot;
</code></pre>

<h3 id="changed_lines">Changed lines</h3>

<p>Changed lines are preceded by a line with <code>#| msgid</code> at the start. Example:</p>

<pre><code>#| msgid &quot;This line will be changed in the next version.&quot;
msgid &quot;This line is now changed in this version.&quot;
msgstr &quot;Deze regel wordt in de nieuwe vesie gewijzigd.&quot;
</code></pre>

<ul>
<li>The line starting with <code>#| msgid</code> is the line as it was in the previous version of the Texinfo file.</li>
<li>The line starting with <code>msgid</code> is the line as it is in the new version of the Texinfo file.</li>
<li>The <code>msgstr</code> contains the previous translation, is no longer valid and must be changed into a translation of the new text.</li>
</ul>

<h2 id="create_translated_texinfo_file">Create translated texinfo file</h2>

<pre><code>po4a-translate \
  --format texinfo \
  --master testinfo-v2.texi \
  --po testinfo.po \
  --localized testinfo-nl.texi
</code></pre>

<p>Here, the input file <code>testinfo-v2.texi</code> is used as an example. The
output file is <code>testinfo-nl.texi</code>, the Texinfo file that is generated
using the PO-file and the Texinfo file it was created from.</p>

<p>For convenience, create a Makefile for this:</p>

<pre><code>testinfo-nl.texi:   testinfo.po
    po4a-translate \
      --format texinfo \
      --master testinfo-v2.texi \
      --po testinfo.po \
      --localized testinfo-nl.texi
</code></pre>

<p>When only a part of the translation has been done, po4a will refuse
to generate the Texinfo output file. This can be configured by using
the switch <code>-k</code>, e.g., <code>-k 30</code> to generate an output file
when at least 30% of the translation has been done. The default is
80%.</p>

<h2 id="generate_a_pdf_file_from_the_texinfo_file_with_the_translation">Generate a PDF file from the texinfo file with the translation</h2>

<pre><code>makeinfo --pdf testinfo-nl.texi
</code></pre>

<p>To add this to the Makefile, you could do something like this:</p>

<pre><code>testinfo-nl.pdf:    testinfo-nl.texi testinfo.po
    makeinfo --pdf testinfo-nl.texi

testinfo-nl.texi:   testinfo-nl.po
    po4a-translate \
     --format texinfo \
     --master testinfo.texi \
     --po testinfo.po \
     --localized testinfo-nl.texi
</code></pre>

<p>When there are some non fatal errors, the <code>makeinfo</code> command can be extended
with the switch <code>---force</code> to generate an output file even when
there are errors.</p>

<h2 id="editing_po-files_with_emacs">Editing PO-files with Emacs</h2>

<p>Here follow some tips for working in Emacs.</p>

<h3 id="spell_check">Spell check</h3>

<p>When working on the PO file and inserting translations, the file will
contain text in two languages, the original language and the language
we are translating to.</p>

<p>An easy way to spellcheck a single entry is by
marking it as a region and run <code>M-x flyspell-region</code>.</p>

<p>First, set the dictionary to be used with <code>M-x ispell-change-dictionary</code>.</p>

<h3 id="flyspell-mode">Flyspell-mode</h3>

<p><code>Flyspell-mode</code> checks your spelling while you type. Just enable it
--after having changed to the right dictionary-- with: ````</p>

<pre><code>M-x flyspell-mode
</code></pre>

<h3 id="curly_braces">Curly braces</h3>

<p>Texinfo uses a lot of curly braces. Make live easier and enable
<code>electric-pair-mode</code>:</p>

<pre><code>M-x electric-pair-mode
</code></pre>

<p>This will let Emacs insert the closing curly brace for you.</p>

<h3 id=".dir-locals.el"><code>.dir-locals.el</code></h3>

<p>Set several options automagically with a file named
<code>.dir-locals.el</code> in your directory, for example:</p>

<pre><code>((nil . ((ispell-local-dictionary . &quot;nl&quot;)
     (abbrev-mode . t)
     (eval . (flyspell-mode))
     (eval . (electric-pair-mode))
     (eval . (company-mode)))))
</code></pre>

<p>Where <code>nl</code> is the Dutch dictionary.</p>

<h3 id="view_local_info_file_in_info-mode">View local info file in <code>Info-mode</code></h3>

<p>To open in a local info file in <code>info-mode</code>, use <code>C-u C-h i</code>.</p>

<h3 id="working_with_paragraphs">Working with paragraphs</h3>

<p>For me, this works convenient:</p>

<ul>
<li>First, write the paragraph with the translation just as normal text.</li>
<li>Next, when needed, correct the paragraph using <code>fill-paragraph</code>, normally with <code>M-q</code>.</li>
<li>Third, surround each line with double quotes, with a space before the double at the end of the line.</li>
<li>Make sure the last line just ends with a double quote, not a space and double quote.</li>
</ul>

<p>Some small Elisp functions can help:</p>

<pre><code>(defun my/quote-region ()
  &quot;Surround each line in the region with quotes.&quot;
  (interactive)
  (save-excursion
    (save-restriction
      (narrow-to-region (region-beginning) (region-end))
      (goto-char (point-min))
      (replace-regexp &quot;^&quot; &quot;\&quot;&quot;)
      (goto-char (point-min))
      (replace-regexp &quot;$&quot; &quot; \&quot;&quot;))))

(defun my/unquote-region ()
  &quot;Remove quotes around the lines in the region.&quot;
  (interactive)
  (save-excursion
    (save-restriction
      (narrow-to-region (region-beginning) (region-end))
      (goto-char (point-min))
      (replace-regexp &quot;^\&quot;&quot; &quot;&quot;)
      (goto-char (point-min))
      (replace-regexp &quot;\&quot;$&quot; &quot;&quot;))))

(defun my/unquote-region-and-fill-paragraph ()
  &quot;Remove quotes around the lines in the region and fill-paragraph&quot;
  (interactive)
  (save-excursion
    (save-restriction
      (narrow-to-region (region-beginning) (region-end))
      (goto-char (point-min))
      (replace-regexp &quot;^\&quot;&quot; &quot;&quot;)
      (goto-char (point-min))
      (replace-regexp &quot;\&quot;$&quot; &quot;&quot;)
      (goto-char (point-min))
      (fill-paragraph))))

Example key bindings:
(define-key global-map (kbd &quot;C-c n q&quot;) #'my/quote-region)
(define-key global-map (kbd &quot;C-c n Q&quot;) #'my/unquote-region)
(define-key global-map (kbd &quot;C-c n m&quot;) #'my/unquote-region-and-fill-paragraph)
</code></pre>

<p>The function <code>my/quote-region</code> can be improved: it leaves a space before the double quote on the last line.</p>
]]></description>
</item>
<item>
<title>Books of January 2026</title>
<link>https://box.matto.nl/books-of-january-2026.html</link>
<guid isPermaLink="false">https://box.matto.nl/books-of-january-2026.html</guid>
<pubDate>Wed, 04 Feb 2026 01:00:00 +0100</pubDate>
<dcterms:modified>2026-02-04T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="books_of_january_2026">Books of January 2026</h1>

<p>I started this year with re-reading &quot;Pattern Recognition&quot;. This is
the first book that I re-read within a year.</p>

<p>Because I really enjoyed this book, I followed it with the other
two books of the Blue Ant trilogy.</p>

<h2 id="non_fiction">Non fiction</h2>

<h3 id="ends_of_the_earth:_journeys_to_the_polar_regions_in_search_of_life,_the_cosmos,_and_our_future_by_neil_shubin_(2025)">Ends of the Earth: Journeys to the Polar Regions in Search of Life, the Cosmos, and Our Future by Neil Shubin (2025)</h3>

<ul>
<li>288 pages</li>
<li>5 stars</li>
</ul>

<p>A book about Antarctic and Arctic expeditions, science, and history.</p>

<p>The book opens with the author, at the time still a student, experiences his first polar expedition.
It is the start of a career with 30 years of science and many more polar expeditions.</p>

<p>The book tells about survival on the poles and the life of
scientists working in extreme environments, and couples that with
historic events. Well written, this book explains how the poles
influences our weather and climate, and all life on earth, and the
dangers of the current climate crisis. It is easy to read, never
boring.</p>

<p>Absolutely recommended reading.</p>

<h2 id="fiction">Fiction</h2>

<h3 id="pattern_recognition_by_william_gibson_(2003)">Pattern Recognition by William Gibson (2003)</h3>

<ul>
<li>368 pages</li>
<li>5 stars</li>
</ul>

<p>A great and captivating story that develops at a good pace.
Real and easy to identify with protagonist. Lovely written, with
many great sentences, great descriptions of the surroundings, and
of the characters. A real and highly recommended page-turner.</p>

<p>Re-read this book. Gibson creates wonderful sentences and I expect to have
missed several in the first read, being captivated by the story development.
I like Cayse, the protagonist and her way of thinking.
This book is definitely becoming a kind of comfort read for me.</p>

<h3 id="spook_country_by_william_gibson_(2007)">Spook Country by William Gibson (2007)</h3>

<ul>
<li>371 pages</li>
<li>5 stars</li>
</ul>

<p>Second book in the Blue Ant trilogy. Like the first book, &quot;Pattern
Recognition&quot;, this is not a science fiction story. Although I felt less
connection with the three protagonists, I got quickly immersed into the story.
Again the book is wonderful written, good plot, and a page-turner.</p>

<h3 id="zero_history_by__william_gibson_(2010)">Zero History by  William Gibson (2010)</h3>

<ul>
<li>416 pages</li>
<li>5 stars</li>
</ul>

<p>Third book in the Blue Ant trilogy. Again not a science fiction book.
And again a story around the fashion world. I got quickly immersed into the story.
Another page turner, wonderful written. I enjoyed this one more then the second
book from the trilogy.</p>

<p>These are all three great books, Pattern Recognition is the best, followed by
ero History, and Spook Country on third.</p>
]]></description>
</item>
<item>
<title>A collection of internet evergreens</title>
<link>https://box.matto.nl/a-collection-of-internet-evergreens.html</link>
<guid isPermaLink="false">https://box.matto.nl/a-collection-of-internet-evergreens.html</guid>
<pubDate>Tue, 03 Feb 2026 01:00:00 +0100</pubDate>
<dcterms:modified>2026-02-03T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="a_collection_of_internet_evergreens">A collection of internet evergreens</h1>

<p>I started a new web page, to publish a collection of awesome and
inspiring web pages that are worth reading.</p>

<p>Currently the collection is modest, I hope to build over time.</p>

<p>Find this <a href="/internet-evergreens.html" >collection of evergreens here</a>.</p>
]]></description>
</item>
<item>
<title>denote-review</title>
<link>https://box.matto.nl/denotereview.html</link>
<guid isPermaLink="false">https://box.matto.nl/denotereview.html</guid>
<pubDate>Tue, 27 Jan 2026 01:00:00 +0100</pubDate>
<dcterms:modified>2026-01-27T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="denote-review">denote-review</h1>

<p>Implement a simple review process for denote notes with 
<a href="https://codeberg.org/mattof/denote-review" >denote-review</a></p>

<h2 id="how_an_emacs_package_came_into_existence">How an Emacs package came into existence</h2>

<h3 id="systems_in_use">Systems in use</h3>

<p>Over time I have grown into using several different note systems 
next to each other, like taking notes in <a href="/tag/awkiawki.html" >awkiawki wiki</a> 
and in <a href="https://protesilaos.com/emacs/denote" >denote</a>.</p>

<p>Both were a succession of earlier systems:</p>

<ul>
<li>My notes in awkiawki once started as notes in <a href="https://vimwiki.github.io/" >vimwiki</a>.</li>
<li>My notes in denote once started as notes in <a href="https://jblevins.org/projects/deft/" >Deft for Emacs</a>.</li>
</ul>

<h3 id="obtf">OBTF</h3>

<p>Thinking about the best way forward I experimented with different options.</p>

<p>Moving towards an OBTF --One Big Text File-- looked promising. I
explored org mode options like org refile. To get familiarized I set
up some exercises, configured an org capture for an OBTF and started using
it.</p>

<p>After getting some hands on experience, I came to the conclusion
that I prefer a lot of small note files above one big one.</p>

<h3 id="migrated_awkiawki">Migrated awkiawki</h3>

<p>I decided to migrate the awkiawki notes to denote and wrote a small
Guile Scheme script to convert the wiki formatted notes into denote
formatted notes (in org mode). Links between wiki-notes became links
between denote notes.</p>

<p>After the migration I ended up with over 1,300 notes in denote.</p>

<h3 id="need_for_a_reviewing_process">Need for a reviewing process</h3>

<p>All notes are created equal, but some are more equal than others.</p>

<p>It was clear that I needed a system to review the collection of
notes, get rid of notes that addressed the same topic or were
outdated, and which notes are underdeveloped. Knowing myself, this
would result in a early death without a systematic approach.</p>

<p>I started thinking about a simple set up, that would not get in your
way and wouldn't affect being &quot;in the flow&quot; when working with notes.</p>

<h2 id="denote_notes">Denote notes</h2>

<p>Notes are unstructured data by default, but denote notes start with
some structured data, called &quot;frontmatter&quot;. It contains metadata
like the title, keywords (think: tags), an identifier and the
creation date of a note.</p>

<p>This seemed the best place for a small addition.
I thought about setting a deadline for each note, before which it had
to be reviewed, but that opens another rabbit hole and I decided against it.</p>

<p>I ended up with creating a small system that added an extra field to
the frontmatter, a line that stated the last review date, and a
method to select some notes and order these by that review date.</p>

<p>I build this and brought it under the attention of Protesilaos
Stavrou, the creator of denote, also known as &quot;Prot&quot;. Denote
supports different kind of formatting of the frontmatter,
markdown-toml, markdown-yaml, plain text, and org mode. I had build
my system for my own needs, and it just supported org-mode.</p>

<p>Prot nudged me into making the system more general, by adding
support for the other formats. This turned out less complicated than
I had originally envisioned and the system grew into a usable Emacs
package. I submitted the package for inclusion in GNU ELPA. Philip
Kaludercic and Stefan Monnier helped me improved the code, and the
rest is history.</p>

<h2 id="usage">Usage</h2>

<p>denote-review adds an extra line to the frontmatter. Here's an example
of the frontmatter of an org-mode formatted denote note:</p>

<p><img src="/i/denote-review-frontmatter.png" alt="screenshot of denote-frontmatter" /></p>

<p>The function <code>denote-review-set-date</code> adds the reviewdate to the frontmatter,
or updates it to the current date.</p>

<p>For convenience, bind this to a keychord, for example:</p>

<pre><code>(define-key global-map (kbd &quot;C-c n x&quot;) #'denote-review-set-date)
</code></pre>

<p>To get started, select a number of notes in Dired and bulk-insert the
frontmatter into these notes, see below.</p>

<p>After extending the frontmatter of several notes with a review data it 
becomes useful to list them, using the command:</p>

<pre><code> M-x denote-review-display-list
</code></pre>

<p>This command prompts for a denote-directory when needed (when there is more
than one denote-directory in your Emacs configuration, or when you have
set up several directories using <code>denote-silo</code>). Select a directory
using completion.</p>

<p>Next, the command prompts for a keyword to narrow the list to. Choose a
keyword or just hit RET (the enter key) for all notes.</p>

<p>This creates a tabulated list with for each note the review date and the
file name:</p>

<p><img src="/i/denote-review-tabulated-view.png" alt="screenshot of tabulated list with notes" /></p>

<p>Only notes that contain the reviewdate frontmatter are displayed, notes without
a review date are ignored.</p>

<p>The notes are sorted by review date. Click on one of the column headers to
order by the contents of that column or to reverse the sort order.
Using the key <code>S</code> (uppercase, so shift-s) performs the same actions.</p>

<p>Select a line by moving point up or down in this list. With a single key press,
perform one of the following commands:</p>
<table >
<thead>
<tr><th>
Key</th><th>
Action</th></tr>
</thead>
<tbody>
<tr><td>
RET</td><td>
Open and edit the note in another window.</td></tr>
<tr><td>
e</td><td>
Open and edit the note.</td></tr>
<tr><td>
o</td><td>
Open the note in read only mode in another window.</td></tr>
<tr><td>
r</td><td>
Open a random note from the list in another window.</td></tr>
<tr><td>
g</td><td>
Update (refresh) the tabulated list.</td></tr>
<tr><td>
q</td><td>
Close the tabulated list.</td></tr>
</tbody>
</table>

<p>The tabulated list mode comes with a number of build-in commands, like
<code>p</code> and <code>n</code> to move to the previous or next line,
<code>SPC</code> and <code>DEL</code> (space bar and backspace key) to scroll down or up.</p>

<p>The general idea is that you from time to time set up a review sessions:</p>

<ul>
<li>select a number of notes, f.e., notes with a specific keyword</li>
<li>go through the list and review notes, for each note edit where needed</li>
<li>update the reviewdate of reviewed notes</li>
</ul>

<p>Slowly moving to the situation where all notes have a recent review date.</p>

<p><em>Note: The filenames in the screenshots above are based on headers in the README from Protesilaos Stavrou, see <a href="https://protesilaos.com/emacs/denote" >protesilaos.com/emacs/denote</a></em></p>

<h3 id="bulk-insert_the_review_date">Bulk-insert the review date</h3>

<p>Open a denote-directory in Dired and mark one or more notes with <code>m</code>.</p>

<p>Unmark a marked note with <code>u</code>.</p>

<p>To bulk-insert the review date there are two options:</p>

<h4 id="the_original_creation_date_as_review_date">The original creation date as review date</h4>

<p>Issue the command</p>

<pre><code>M-x denote-review-set-date-dired-marked-files
</code></pre>

<p>This will insert a frontmatter line with the review date derived
from the date encoded in the first chars of the filename.</p>

<h4 id="the_current_date_as_review_date">The current date as review date</h4>

<p>Enter the Universal Argument <code>C-u</code></p>

<p>Issue the command</p>

<pre><code>M-x denote-review-set-date-dired-marked-files.
</code></pre>

<p>This will insert a frontmatter line with the current date a review date.</p>

<h4 id="select_multiple_notes_in_dired">Select multiple notes in Dired</h4>

<p>Like Prot has written in his denote manual, it is easy to select and
mark a number of notes in Dired using a regexp.</p>

<p>For example, to select and mark all notes with the keyword &quot;foo&quot;:</p>

<ul>
<li>press <code>%m</code></li>
<li>enter <code>_foo RET</code></li>
</ul>

<p>To reverse the selection (all notes that don't have the keyword &quot;foo&quot;):</p>

<ul>
<li>press <code>%m</code></li>
<li>enter <code>_foo RET</code></li>
<li>press <code>t</code> (toggle)</li>
</ul>

<p>Happy note taking!</p>
]]></description>
</item>
<item>
<title>Best of the Gutenberg books I read in 2025</title>
<link>https://box.matto.nl/best-of-the-gutenberg-books-i-read-in-2025.html</link>
<guid isPermaLink="false">https://box.matto.nl/best-of-the-gutenberg-books-i-read-in-2025.html</guid>
<pubDate>Thu, 01 Jan 2026 01:00:00 +0100</pubDate>
<dcterms:modified>2026-01-01T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="best_of_the_gutenberg_books_i_read_in_2025">Best of the Gutenberg books I read in 2025</h1>

<p><a href="https://www.gutenberg.org/" >Project Gutenberg</a> is a fantastic
treasure trove filled to the brim with over 75,000 books.</p>

<p>In 2025 I read several books and short stories that are now in the
public domain. Here are the most noteworthy.</p>

<h2 id="books">Books</h2>

<h3 id="little_fuzzy_by_h._beam_piper_(1962)">Little Fuzzy by H. Beam Piper (1962)</h3>

<p>252 pages</p>

<p>Short science fiction novel about a planet in deep space which is
being mined for &quot;sunstones&quot;. The discovery of a small humanoid
furry race set of a chain of events. This book breathes US
culture, but is non the less a lovely read.</p>

<p><a href="https://www.gutenberg.org/ebooks/18137" >Gutenberg book 18137</a></p>

<h3 id="ziska_-_the_problem_of_a_wicked_soul_by_marie_corelli_(1898)">Ziska - The Problem of a Wicked Soul by Marie Corelli (1898)</h3>

<p>206 pages</p>

<p>A Gothic novel set in Egypt. A group of English tourists visits
Cairo when the mysterious &quot;Princess Zika&quot; appears. Two friends
fall in love with her. A spooky story about love and revenge.</p>

<p><a href="https://www.gutenberg.org/ebooks/5079" >Gutenberg book 5079</a></p>

<h2 id="short_stories">Short stories</h2>

<h3 id="let's_get_together_by_isaac_asimov_(1957)">Let's Get Together by Isaac Asimov (1957)</h3>

<p>18 pages</p>

<p>Short story set in a world where the Cold War has endured for a century.</p>

<p><a href="https://www.gutenberg.org/ebooks/68377" >Gutenberg book 68377</a></p>

<h3 id="the_black_kiss_by__robert_bloch,_henry_kuttner_(1937)">The Black Kiss by  Robert Bloch, Henry Kuttner (1937)</h3>

<p>20 pages</p>

<p>A horror short story. I almost never read horror stories, this one I enjoyed.</p>

<p><a href="https://www.gutenberg.org/ebooks/76435" >Gutenberg book 76435</a></p>
]]></description>
</item>
<item>
<title>Added a blogroll like in the old days</title>
<link>https://box.matto.nl/added-a-blogroll-like-in-the-old-days.html</link>
<guid isPermaLink="false">https://box.matto.nl/added-a-blogroll-like-in-the-old-days.html</guid>
<pubDate>Wed, 31 Dec 2025 01:00:00 +0100</pubDate>
<dcterms:modified>2025-12-31T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="added_a_blogroll_like_in_the_old_days">Added a blogroll like in the old days</h1>

<p>In the heyday of blogs, many blogs published a blogroll, often is
a side bar.</p>

<p>This was a list with which showed a selection of links other blogs.
It showed the blogs that had recently been updated.</p>

<p>I created a blogroll that does the same.</p>

<h2 id="selection_of_links">Selection of links</h2>

<p>A script looks every night at the personal websites and blogs listed
on my <a href="links.html" >links</a> page. When a change in their RSS-feed is
detected, the website or blog is listed in the
<a href="blogroll.html" >blogroll</a>.</p>
]]></description>
</item>
<item>
<title>New category in the links</title>
<link>https://box.matto.nl/new-category-in-the-links.html</link>
<guid isPermaLink="false">https://box.matto.nl/new-category-in-the-links.html</guid>
<pubDate>Tue, 23 Dec 2025 01:00:00 +0100</pubDate>
<dcterms:modified>2025-12-23T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="new_category_in_the_links">New category in the links</h1>

<p>The demise of the search engines and the embrace of untrustworthy,
useless AI-generated results, optimistically referred to as
&quot;AI-powered&quot; are upon us.</p>

<p>The web is turning into a web for profit. Individual websites and
blogs, that make up the smol web, are almost impossible to find.</p>

<p>Some websites are trying to do something about this, by either
creating some kind of feed aggregator, or create a search engine
that targets small websites, often based on the parsing of
RSS feeds.</p>

<h2 id="new_category:_feed_aggregators">New category: Feed aggregators</h2>

<p>In my <a href="/links.html" >links</a> I have now added a new category,
&quot;Feed aggregator&quot; for this.</p>

<p>Currently there are only a few entries in it, but I hope to
grow this list over time.</p>

<p>Let's take back the web!</p>
]]></description>
</item>
<item>
<title>Joined the Generation Lissa! webring</title>
<link>https://box.matto.nl/joined-the-generation-lissa!-webring.html</link>
<guid isPermaLink="false">https://box.matto.nl/joined-the-generation-lissa!-webring.html</guid>
<pubDate>Mon, 24 Nov 2025 01:00:00 +0100</pubDate>
<dcterms:modified>2025-11-24T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="joined_the_generation_lissa!_webring">Joined the Generation Lissa! webring</h1>

<p>The <i>Generation Lissa!</i> webring is for people who learned how
to build their own personal websites with code between the years of
1996 and 2005, and still run a personal space on the Internet.</p>

<p><a href="https://genlissa.baccyflap.com/" >More about the webring</a></p>

<h2 id="webrings_help_to_keep_the_web_alive">Webrings help to keep the web alive</h2>

<p>Small hand-cafted, non commercial websites are almost impossible to
discover.</p>

<p>The web gets demolished by the demise of the search engines and the
embrace of untrustworthy, useless AI-generated results,
optimistically referred to as &quot;AI-powered&quot;.</p>

<p>Search engines prioritize large domains with commercial content. The
web is swamped with &quot;SEO-optimized&quot; content and AI-generated slob.</p>

<p>Personal blogs, art pages, and other hand-crafted websites
practically never turn up in search results.</p>

<p>The best way to fight this, is to restore the <i>wanderability</i> of
the early web: Create links between websites and make following
these links fun.</p>

<h2 id="embrace_webrings">Embrace webrings</h2>

<p>The blogosphere made the web a place of personal expression. The
current craze is massive delivery of shallow, meaningless content.</p>

<p>Webrings bring back the joy of surfing. They encourage you to
explore, and frequently lead you to unexpected discoveries. The
visitors drift through a community instead of being funneled by
billionaire’s dark algorithms.</p>

<h2 id="the_open_web_needs_you">The open web needs you</h2>

<p>Website creators require motivation and inspiration. Without
visitors, homemade websites may go neglected.</p>

<ul>
<li>If you have a website, join a webring. Or maybe more than one.</li>
<li>When visiting a website, follow the webring links, and see what
  happens.</li>
</ul>
]]></description>
</item>
<item>
<title>Prosody XMPP server in the home lab</title>
<link>https://box.matto.nl/prosody-xmpp-server-in-the-home-lab.html</link>
<guid isPermaLink="false">https://box.matto.nl/prosody-xmpp-server-in-the-home-lab.html</guid>
<pubDate>Sun, 23 Nov 2025 01:00:00 +0100</pubDate>
<dcterms:modified>2025-11-23T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="prosody_xmpp_server_in_the_home_lab">Prosody XMPP server in the home lab</h1>

<h2 id="local_xmpp_server_on_a_raspberry_pi_zero_2_w">Local XMPP server on a Raspberry Pi Zero 2 W</h2>

<p>This is an article about a local server only, not reachable from the internet.</p>

<p>The differences with a XMPP server that is connected to the internet
and does federation with other XMPP servers is in the
infrastructure: TLS-certificates from an official CA, and official
DNS records. When providing a XMPP server on the internet, security
and privacy protection are very important.</p>

<h2 id="light_weight_server">Light weight server</h2>

<p><a href="https://prosody.im/" >Prosody</a> is a light weight, easy to administrate
XMPP server. I had it running
<a href="https://box.matto.nl/beaglebone-black-still-going-strong.html" >for years on a BeagleBone Black</a>.</p>

<p>Due to circumstances I had to move that XMPP server to a location outside of our
home network.</p>

<p>I still wanted a local XMPP server just for testing purposes and set up a
Prosody server on a small <a href="https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/" >Raspberry Pi Zero 2 W</a>
running <a href="https://www.raspberrypi.com/software/operating-systems/" >Raspberry Pi OS Lite</a>.</p>

<p>This page describes the use of a Raspberry Pi as server, but it is not
limited to that platform. Prosody is available for all the open
source operating systems.</p>

<p>The use of a local only XMPP server, not federated and not reachable
from the internet is of course limited. It can be used for test purposes,
local machine-to-machine communication, and it is fun!</p>

<p>The main objective is a server with the following capabilities:</p>

<ul>
<li>support for <a href="https://xmpp.org/extensions/xep-0384.html" >OMEMO encryption</a></li>
<li>support for <a href="https://xmpp.org/extensions/xep-0045.html" >Multi-User Chat</a></li>
<li>support for <a href="https://xmpp.org/extensions/xep-0363.html" >HTTP File Upload</a></li>
</ul>

<h2 id="requirements">Requirements</h2>

<h3 id="dns">DNS</h3>

<p>Three subdomains are needed:</p>

<ul>
<li>a subdomain for the XMPP server</li>
<li>a subdomain for the Multi-User Chat</li>
<li>a subdomain for the HTTP-File-Upload</li>
</ul>

<p>All three subdomains can point to the same IP address,  the address of the Raspberry Pi.
Set it up for both the ipv4 and the ipv6 address. (Maybe only ipv6 works too, I
have not tested that.)</p>

<p>The best solution is to set up a local DNS server in your local network.</p>

<p>If you don't have a local DNS server in your home lab, stop now and set one
up first. It won't take much effort and is great for now and in the future.
There a several open source servers available.</p>

<p><a href="https://en.wikipedia.org/wiki/Unbound_(DNS_server)" >Unbound</a> is a good
DNS server, easy to set up, also for reverse look-ups.</p>

<h3 id="certificates">Certificates</h3>

<p>Each of the three subdomains needs a TLS certificate. In your home
lab there is of course no need for certificates from an official CA.</p>

<p>The best solution is to set up a local CA.</p>

<p>When you run a local CA, you yourself can issue signed certificates for all
the subdomains in your home lab.</p>

<p><a href="https://github.com/FiloSottile/mkcert" >Mkcert</a> is an easy way to
set up a CA and issue certificates. It can also be done from the command
line with openssl.</p>

<p>Create and sign certificates for the three subdomains. Six files in
total, two for each subdomain. Place the certificate files in
<code>/etc/prosody/certs/</code> or in <code>/usr/local/etc/prosody/certs/</code>,
depending on your operating system.</p>

<h2 id="install_and_configure_prosody">Install and configure Prosody</h2>

<p>Just use the package manager to install Prosody. It is available as package on most systems.</p>

<p>The location of the configuration files and work directory depends
on your operating system. The configuration file
<code>prosody.cfg.lua</code> will most likely be in <code>/etc/prosody</code> or
in <code>/usr/local/etc/prosody</code>. </p>

<p>On the Raspberry Pi, the work directory is in <code>/var/lib/</code>.</p>

<p>Here is a complete configuration, for use in a home lab.</p>

<pre><code>admins = { }
modules_enabled = {
        &quot;disco&quot;; -- Service discovery
        &quot;roster&quot;; -- Allow users to have a roster.
        &quot;saslauth&quot;; -- Authentication for clients and servers.
        &quot;tls&quot;; -- Add support for secure TLS on c2s/s2s connections
        &quot;blocklist&quot;; -- Allow users to block communications with other users
        &quot;bookmarks&quot;; -- Synchronise the list of open rooms between clients
        &quot;carbons&quot;; -- Keep multiple online clients in sync
        &quot;dialback&quot;; -- Support for verifying remote servers using DNS
        &quot;limits&quot;; -- Enable bandwidth limiting for XMPP connections
        &quot;pep&quot;; -- Allow users to store public and private data in their account
        &quot;private&quot;; -- Legacy account storage mechanism (XEP-0049)
        &quot;smacks&quot;; -- Stream management and resumption (XEP-0198)
        &quot;vcard4&quot;; -- User profiles (stored in PEP)
        &quot;vcard_legacy&quot;; -- Conversion between legacy vCard and PEP Avatar, vcard
        &quot;csi_simple&quot;; -- Simple but effective traffic optimizations for mobile devices
        &quot;invites&quot;; -- Create and manage invites
        &quot;invites_adhoc&quot;; -- Allow admins/users to create invitations via their client
        &quot;invites_register&quot;; -- Allows invited users to create accounts
        &quot;ping&quot;; -- Replies to XMPP pings with pongs
        &quot;register&quot;; -- Allow users to register on this server using a client and change passwords
        &quot;time&quot;; -- Let others know the time here on this server
        &quot;uptime&quot;; -- Report how long server has been running
        &quot;version&quot;; -- Replies to server version requests
        &quot;mam&quot;; -- Store recent messages to allow multi-device synchronization
        &quot;admin_adhoc&quot;; -- Allows administration via an XMPP client that supports ad-hoc commands
        &quot;admin_shell&quot;; -- Allow secure administration via 'prosodyctl shell'
        &quot;posix&quot;; -- POSIX functionality, sends server to background, enables syslog, etc.
        &quot;groups&quot;; -- Shared roster support
        &quot;http&quot;;    -- Allow Prosody modules to expose various services over HTTP
        &quot;http_file_share&quot;; -- Let users share files via HTTP
}
pidfile = &quot;/run/prosody/prosody.pid&quot;;
c2s_require_encryption = true
s2s_secure_auth = true
limits = {
    c2s = {
        rate = &quot;10kb/s&quot;;
    };
    s2sin = {
        rate = &quot;30kb/s&quot;;
    };
}
authentication = &quot;internal_hashed&quot;
archive_expires_after = &quot;1w&quot; -- Remove archived messages after 1 week
log = {
    debug = &quot;/var/log/prosody/prosody.log&quot;;
    error = &quot;/var/log/prosody/prosody.err&quot;;
    { levels = { &quot;error&quot; }; to = &quot;syslog&quot;;  };
}
certificates = &quot;certs&quot;
VirtualHost &quot;xmpp.your-domain.home&quot;
    disco_items = {
        { &quot;upload.your-domain.home&quot;, &quot;file sharing service&quot; },
        { &quot;muc.your-domain.home&quot;,  &quot;chat room service&quot; },
    }
    ssl = {
        key = &quot;/etc/prosody/certs/xmpp.your-domain.home.key&quot;;
        certificate = &quot;/etc/prosody/certs/xmpp.your-domain.home.crt&quot;;
    }
    Component &quot;upload.your-domain.home&quot; &quot;http_file_share&quot;
        http_file_share_expire_after = 86400*28 -- 28 days
        http_file_share_size_limit = 128*1024*1024+16 -- 128 MB
    Component &quot;muc.your-domain.home&quot; &quot;muc&quot; name = &quot;chat room service&quot;
        modules_enabled = { &quot;muc&quot;, &quot;muc_mam&quot;, &quot;vcard_muc&quot;,&quot;pastebin&quot; }
        restrict_room_creation = false
</code></pre>

<p>Here we use three domains:</p>

<ul>
<li>xmpp.your-domain.home</li>
<li>muc.your-domain.home</li>
<li>upload.your-domain.home</li>
</ul>

<p>Replace <code>your-domain.home</code> with the domain used in your home lab.</p>

<p>Make sure the line with the pidfile fits your operating system.</p>

<p>You can choose any name for the subdomains <code>xmpp</code>, <code>muc</code>, and
<code>upload</code>. Be sure the names are the same as set up in the DNS server.</p>

<p>Make sure that the element <code>disco_items</code> comes before the Component-sections
in your config. The order is important.</p>

<p>In this example, the logging is configured at the <code>debug</code> level.
When everything is running smoothly, you can replace that with <code>info</code>.</p>

<p>Check your settings with <code>prosodyctl check</code>.</p>

<h2 id="start_the_service">Start the service</h2>

<p>Depending on your system you need to give some commands to get the
server running.</p>

<p>Firstly, enable the server with <code>systemctl enable prosody</code> on systems
with systemd, or f.e., add a line to <code>/etc/rc.conf</code> or
<code>/etc/rc.conf.local</code>.</p>

<p>Next, start the server with <code>systemctl start prosody</code> or
<code>/etc/rc.d/prosody start</code> or <code>/usr/local/etc/rc.d/prosody start</code>.</p>

<p>Check the service with <code>prosodyctl status</code> and check the log files.</p>

<h2 id="add_a_user">Add a user</h2>

<p>Add a user, in this example &quot;alice&quot;, with:</p>

<p><code>prosodyctl adduser alice@xmpp.your-domain.home</code></p>

<p>This will prompt for a password and for a confirmation of the password.</p>

<h2 id="prepare_for_testing">Prepare for testing</h2>

<p>Make sure the certificates are trusted on your desktop machine.</p>

<p>Install a <a href="https://xmpp.org/software/?category=clients" >XMPP client</a>.
Make sure it is <a href="https://omemo.top/" >ready for OMEMO</a> and test that you
can log in.</p>

<p>Have fun!</p>
]]></description>
</item>
<item>
<title>VNC on a OpenBSD virtual machine</title>
<link>https://box.matto.nl/vnc-on-a-openbsd-virtual-machine.html</link>
<guid isPermaLink="false">https://box.matto.nl/vnc-on-a-openbsd-virtual-machine.html</guid>
<pubDate>Sun, 09 Nov 2025 01:00:00 +0100</pubDate>
<dcterms:modified>2025-11-09T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="vnc_on_a_openbsd_virtual_machine">VNC on a OpenBSD virtual machine</h1>

<p>OpenBSD comes with the vmm(4) hypervisor and vmd(8) daemon.
It is easy to create and install an OpenBSD virtual machine 
on an OpenBSD workstation. For more information, see the
<a href="https://www.openbsd.org/faq/faq16.html" >Virtualization page in the OpenBSD FAQ</a>.</p>

<p>Running one or more OpenBSD virtual machines on your OpenBSD
laptop is great for testing purposes.</p>

<h2 id="vnc_to_local_vm">VNC to local vm</h2>

<p>A graphical desktop can be useful when testing or trying out
stuff. Here we are going to set up VNC on a virtual machine
that gives us an XDM login window. </p>

<p>The virtual machine we used is running OpenBSD 7.8.</p>

<p><img src="/i/vm1-vnc.png" alt="XDM login over VNC on a OpenBSD vm" />
<p class="center">XDM login over VNC on a OpenBSD vm</p></p>

<h2 id="install_tigervnc">Install TigerVNC</h2>

<p>We need to install Tiger VNC on the VM for this. </p>

<pre><code>doas pkg_add tigervnc
</code></pre>

<h2 id="create_a_vnc_passwordfile">Create a VNC passwordfile</h2>

<p>We are going to need a password file on the VM for the VNC connection.</p>

<pre><code>doas vncpasswd /etc/X11/xenodm/VNCpwd
</code></pre>

<p>Here, <code>/etc/X11/xenodm/VNCpwd</code> is the file name for the file
we are going to create. Choose a path and file name to your liking.</p>

<p>The command vncpasswd will ask for a password and a confirmation of it.</p>

<p>Optionally you can also add a second password, for a read-only VNC session.
We skipped this.</p>

<h2 id="edit_xenodm-config">Edit xenodm-config</h2>

<p>On the VM, edit the file <code>/etc/X11/xenodm/xenodm-config</code>.
At the bottom, add a line:</p>

<pre><code>DisplayManager._1.authorize: false
</code></pre>

<h2 id="edit_xservers">Edit Xservers</h2>

<p>Edit the file <code>/etc/X11/xenodm/Xservers</code>.</p>

<p>At the bottom, comment out the line:</p>

<pre><code>:0 local /usr/X11R6/bin/X :0 vt05
</code></pre>

<p>And add a line:</p>

<pre><code>:1 local /usr/local/bin/Xvnc :1 -geometry 1024x768 -depth 16 -desktop vm1 -Passwordfile /etc/X11/xenodm/VNCpwd
</code></pre>

<p>Make sure the path and file name of the password file correspondent with
the password file you just created.</p>

<h2 id="enable_and_start_xenodm">Enable and start xenodm</h2>

<p>On the VM, enable and start xenodm.</p>

<pre><code>doas rcctl enable xenodm
doas rcctl start xenodm
</code></pre>

<p>Or, if xenodm is already running, restart the service.</p>

<h2 id="connect_with_vncviewwer">Connect with vncviewwer</h2>

<p>To get vncviewer on your laptop, install tigervnc.</p>

<pre><code>doas pkg_add tigervnc
</code></pre>

<p>Now, connect to the VNC server on the VM:</p>

<pre><code>vncviewer 100.64.1.3:1
</code></pre>

<p>Replace <code>100.64.1.3</code> with the ip address of your VM.</p>

<h2 id="optionally_encrypt_traffic">Optionally encrypt traffic</h2>

<p>Remember that the VNC protocol transports your data unecrypted.
This is insecure.</p>

<p>We use this setup only for testing purposes, only for local
VM's on our laptop, without any sensitive data..</p>

<p>To protect your data from eavesdropping, encrypt the connection, f.e.,
with an SSH-tunnel.</p>

<p>Virtual machines are very useful. Creating and installing an
OpenBSD virtual machine on an OpenBSD laptop is easy.</p>

<p>Have fun!</p>
]]></description>
</item>
<item>
<title>Install 9front in vm-bhyve on FreeBSD</title>
<link>https://box.matto.nl/install-9front-in-vmbhyve-on-freebsd.html</link>
<guid isPermaLink="false">https://box.matto.nl/install-9front-in-vmbhyve-on-freebsd.html</guid>
<pubDate>Thu, 30 Oct 2025 01:00:00 +0100</pubDate>
<dcterms:modified>2025-10-30T01:00:00.000000+01:00</dcterms:modified>
<description> <![CDATA[
<h1 id="install_9front_in_vm-bhyve_on_freebsd">Install 9front in vm-bhyve on FreeBSD</h1>

<h2 id="9front">9front</h2>

<p><a href="https://fqa.9front.org/fqa1.html#1.1" >9front</a> (or plan9front)
is a fork of the Plan 9 from Bell Labs operating system.</p>

<p><img src="/i/9front-netsurf.png" alt="9front with Netsurf" />
<p class="center">9front with Mothra and Netsurf</p></p>

<h2 id="vm-bhyve">vm-bhyve</h2>

<p>FreeBSD vm-bhyve is a great tool to create, install and manage virtual machines.</p>

<p>vm-bhyve is designed to work with ZFS, which makes it very easy to
create new vm's, and make ZFS snapshots of those.</p>

<p>Virtual machines can either run with or without a graphical desktop.
For machines running without a graphical desktop we use SSH.</p>

<p>The FreeBSD bhyve hypervisor provides VNC access to the virtual
machines that boot with UEFI. Expose the VNC port to the network to
allow for remote management.</p>

<h2 id="9front_on_bhyve_using_vm-bhyve">9front on bhyve using vm-bhyve</h2>

<p>This is how I got 9front installed and booting after the
install.</p>

<p>I have exactly zero experience with 9front or plan9. so maybe
there are better ways.</p>

<h2 id="download_install_iso">Download install iso</h2>

<p>An install iso can be downloaded from
<a href="https://9front.org/releases/" >9front.org</a>.</p>

<p>I downloaded  <code>9front-11321.amd64.iso</code>.</p>

<h2 id="installation">Installation</h2>

<p>We don't use the normal way to install an operating system on a VM
with vm-bhyve (<code>vm install vm-name iso-name</code>). This is because
vm-bhyve removes the CD-ROM from the VM at the first reboot after
this command.</p>

<p>We follow a slightly different way:</p>

<h3 id="create_a_new_virtual_machine:">Create a new virtual machine:</h3>

<pre><code>vm create -t dragonfly 9frontvm
</code></pre>

<p>We choose the dragonfly template because is comes with UEFI and VNC support.</p>

<h3 id="add_lines_for_the_cd-rom">Add lines for the CD-ROM</h3>

<p>Add the following lines to the configuration of the VM (the file <code>/bhyve/9frontvm/9frontvm.conf</code>):</p>

<pre><code>disk1_type=&quot;ahci-cd&quot;
disk1_dev=&quot;custom&quot;
disk1_name=&quot;/bhyve/.iso/9front-11321.amd64.iso&quot;
</code></pre>

<h3 id="start_the_installation:">Start the installation:</h3>

<p><code>vm start 9frontvm</code></p>

<p>Now open your VNC viewer to the VM.</p>

<p>From here you can follow 
<a href="https://fqa.9front.org/fqa4.html#4.3" >the installation guide</a>.
The installation window doesn't show a cursor. just trust that
you are indeed typing at the prompt.</p>

<p>Just accept the default values.</p>

<ul>
<li>At the bootargs just hit Enter.</li>
<li>After selecting <code>1024x768x16</code> for the <code>vgasize</code> (just hit Enter)
  I had to select <code>vga</code> as monitor.</li>
</ul>

<p>After accepting the default for the mouse port a graphical
desktop is started.</p>

<p>In the terminal, issue the command <code>inst/start</code>.</p>

<p>Again, accept the default values.</p>

<ul>
<li>Disk to partition: <code>sdE0</code>.</li>
<li>Install mbr or gpt: <code>gpt</code>.</li>
<li>Use esp as 9fat: <code>yes</code>.</li>
</ul>

<p>At the configuration of the network I did choose <code>manual</code>.
This gives the option to enter ip address, netmask, gateway and DNS.</p>

<ul>
<li>Distribution disk: <code>/dev/sdF0/data</code>.</li>
</ul>

<p>The list with options for the timezone for Europe is smaller than usual.</p>

<p>Time Zone: <code>CET</code>.</p>

<p>After the reboot, use the bootargs <code>local!/dev/sdE0/fscache</code>.</p>

<h2 id="prepare_for_easy_boot">Prepare for easy boot</h2>

<p>Next, we are going to edit <code>9plan.ini</code> in the 9front terminal.</p>

<pre><code>9fs esp
cd /n/esp
ed plan9.ini
</code></pre>

<p>There are more options beside <code>ed</code> to edit the file, f.e., use the <code>acme</code> editor.</p>

<p>Change the bootargs line to:</p>

<pre><code>nobootprompt=local!/dev/sdE0/fscache
</code></pre>

<p>And add a line:</p>

<pre><code>user=glenda
</code></pre>

<p>Save the changes, and check with <code>cat plan9.ini</code>.</p>

<p>If all is well, reboot (see below).</p>

<p>Now it will boot without the need to hit Enter and it will directly
go into Rio (the graphical desktop).</p>

<h2 id="shutdown">Shutdown</h2>

<p>Shut down the virtual machine by issuing the command <code>fshalt</code> in
a 9front terminal, or use <code>fshalt -r</code> to reboot..</p>

<h2 id="desktop_resolution">Desktop resolution</h2>

<p>As 1024x768 is quite cramped, I changed the resolution to 1200x720.</p>

<p>First, I changed the line in plan9.ini:</p>

<pre><code>vgasize=1200x720x16
</code></pre>

<p>Next, I added a line to the configuration of the VM:</p>

<pre><code>graphics_res=&quot;1200x720&quot;
</code></pre>

<h2 id="remote_access_using_drawterm">Remote access using drawterm</h2>

<p>VNC on bhyve is not the best experience. The mouse often requires some persuation to
before reachting the edges of the frame, and it is not fast.</p>

<p>Drawterm solves this all.</p>

<p>I followed <a href="https://gist.github.com/99z/1ff7c64f700a18e4025aa3c36ae78df0" >this turorial</a> to
allow for remote access using drawterm.</p>

<p>To get the latest version, get drawterm from <a href="https://drawterm.9front.org" >drawterm.9front.org</a>.</p>

<h2 id="resources">Resources</h2>

<ul>
<li><a href="https://wiki.9front.org/freebsd-bhyve" >wiki.9front.org/freebsd-bhyve</a></li>
<li><a href="https://pspodcasting.net/dan/blog/2019/plan9_desktop.html" >Plan 9 desktop guide</a></li>
<li><a href="https://luksamuk.codes/posts/plan9-setup-rpi.html" >Setting up 9front an a Raspberry Pi</a> with useful information, not only for Raspberry Pi.</li>
</ul>

<h2 id="thanks">Thanks</h2>

<p>Thanks to <a href="http://triapul.cz/" >Tom</a> for the provided help, inspiration and useful links!</p>

<p>Have fun with 9front!</p>

<h2 id="updates">Updates</h2>

<ul>
<li>2025-01-01: added section on remote access with drawterm.</li>
</ul>
]]></description>
</item>
<item>
<title>Adventures with OS X Mavericks in 2025</title>
<link>https://box.matto.nl/adventures-with-os-x-mavericks-in-2025.html</link>
<guid isPermaLink="false">https://box.matto.nl/adventures-with-os-x-mavericks-in-2025.html</guid>
<pubDate>Fri, 03 Oct 2025 02:00:00 +0200</pubDate>
<dcterms:modified>2025-10-03T02:00:00.000000+02:00</dcterms:modified>
<description> <![CDATA[
<h1 id="adventures_with_os_x_mavericks_in_2025">Adventures with OS X Mavericks in 2025</h1>

<h2 id="running_os_x_mavericks_on_an_old_mid_2013_macbook_air">Running OS X Mavericks on an old mid 2013 MacBook Air</h2>

<h3 id="specs_of_the_macbook_air">Specs of the Macbook Air</h3>

<ul>
<li>1.3 GHz Intel Core i5</li>
<li>4 Gb 1600 MHz DDR memory</li>
<li>Intel HD Graphincs 5000</li>
<li>13 inch TFT LED 1440x900 display</li>
<li>128 GB SSD</li>
</ul>

<p>Apart from the Apple keyboard layout, the keyboard is fine.</p>

<p>The glass trackpad (without buttons) is quite large.
Unfortunately, Apple keyboards don't come with a
<a href="https://en.wikipedia.org/wiki/Pointing_stick" >TrackPoint</a> like ThinkPads do, but the
glass trackpad will do fine.</p>

<h2 id="os_x_mavericks">OS X Mavericks</h2>

<p>Sometime ago I did a factory reset on this old MacBook. This
installs the default operating system, which is OS X Mavericks. The
old MacBook Air works fine with it. The laptop doesn't feel old,
everything is snappy and the display is a joy to look at.</p>

<p>I decided not to upgrade to a newer version of OS X, or replace it
with Linux or one of the BSDs. I like the look and feel of OS X
Mavericks, it doesn't require an iCloud account to run, and it is
completely different from my daily drivers: ThinkPads running
FreeBSD with the ratpoison window manager, and FreeBSD with the
Emacs X Window Manager &quot;EXWM&quot;.</p>

<p>Of course running an old system has it challenges.</p>

<p>Here follows some information about the software I installed, and other stuff.</p>

<h2 id="macports">MacPorts</h2>

<p>It's hardly believable, <a href="https://www.macports.org/" >MacPorts</a> is available for OS X Mavericks!</p>

<p>Using MacPorts I installed the following packages:</p>

<ul>
<li>Emacs 30.2 under X11</li>
<li>GnuPG 2.4.8</li>
<li>Hunspell</li>
<li>Links</li>
<li>Lynx</li>
<li>OpenSSH</li>
<li>OpenSSL</li>
<li>RCS</li>
<li>Tmux</li>
<li>Xorg</li>
</ul>

<p>See also my page <a href="https://box.matto.nl/spellcheck-in-emacs-on-os-x-mavericks-with-macports.html" >Spellcheck in Emacs on OS X Mavericks with MacPorts</a>.</p>

<h2 id="firefox">Firefox</h2>

<p>Using Firefox Dinasty I installed Firefox 144.0b5, with the help of and the
links from the <a href="https://mavericksforever.com/" >Mavericks Forever</a> website.</p>

<p>This installs Firefox together with the tools to open websites that require a
modern TLS encrypted connection.</p>

<h2 id="software_from_the_macintosh_garden_and_the_macintosh_repository">Software from the Macintosh Garden and the Macintosh Repository</h2>

<p>The <a href="https://macintoshgarden.org/" >Macintosh Garden</a> and
the <a href="https://www.macintoshrepository.org/" >Macintosh Repository</a>
are brilliant sources of software for older MacOS and Mac OS X systems.</p>

<p>Using these sources I installed:</p>

<p>Version 3.2.15 of <a href="https://netnewswire.com/" >NetNewsWire</a>, a graphical
RSS feed reader.</p>

<p>Version 2.0 β5 of  [<a href="https://en.wikipedia.org/wiki/Notational_Velocity" >Notational
Velocity</a>. See my
<a href="/notational-velocity-on-os-x-mavericks.html" >page on Notational Velocity</a>.</p>

<p><a href="https://en.wikipedia.org/wiki/Pages_(word_processor)" >Pages</a> 5.2.2.</p>

<h2 id="karabiner">Karabiner</h2>

<p>Karabiner remaps Apple keyboard keys.</p>

<p>I installed version 10.22 using this web-archive link:
<a href="https://web.archive.org/web/20190809131630/https://pqrs.org/osx/karabiner/files/Karabiner-10.22.0.dmg" >https://web.archive.org/web/20190809131630/https://pqrs.org/osx/karabiner/files/Karabiner-10.22.0.dmg</a></p>

<p>Switching the Fn-key and the left Control-key is a real game-changer, it makes
using the MacBook much easier.</p>

<p>BTW: To use Option as Alt-key in the Apple's Terminal application
(part of OS X Mavericks), check the option &quot;Use Option as Meta key&quot;
in the preferences.</p>

<h2 id="itunes">iTunes</h2>

<p>OS X Mavericks comes with iTunes 12.6. I prefer the look and feel of the older iTunes that comes
with OS X 10.3.9.</p>

<p>However, iTunes 12.6 is still usable. It doesn't try to convert your mp3 files to another format
and it doens't require iCloud. This version of iTunes is still a very usefule tool to organise
your mp3 files into an &quot;Artist / Album / Tracks&quot; directory structure.</p>

<h2 id="vnc_client">VNC client</h2>

<p>OS X Mavericks also comes with a VNC client, which is called &quot;Screen Sharing&quot;.
This works fine, and is useful to manage virtual machines running a graphical user interface.</p>

<p>See my page
<a href="/manage-remote-vmbhyve-guests-with-os-x-mavericks-vnc-client.html" >Manage remote vm-bhyve guests with OS X Mavericks VNC client</a>.</p>

<h2 id="resources">Resources</h2>

<p>Useful resources:</p>

<ul>
<li><a href="https://mavericksforever.com/" >Mavericks Forever</a></li>
<li>The blogpost
<a href="https://minutestomidnight.co.uk/blog/getting-ready-for-the-winter-part-1/" >Getting Ready for the Winter. Part 1, Switching Technology</a></li>
<li>The <a href="https://macintoshgarden.org/" >Macintosh Garden</a></li>
<li>The <a href="https://www.macintoshrepository.org/" >Macintosh Repository</a></li>
</ul>

<h2 id="kudos">Kudos</h2>

<p>Originally my idea was to have some fun with this old laptop and be done with it.
Thanks you, <a href="https://82mhz.net/" >Andreas</a> for the inspiration go further and turn this system with OS X Mavericks into a
really usable machine, and providing me useful pointers!</p>
]]></description>
</item>
<item>
<title>Notational Velocity on OS X Mavericks</title>
<link>https://box.matto.nl/notational-velocity-on-os-x-mavericks.html</link>
<guid isPermaLink="false">https://box.matto.nl/notational-velocity-on-os-x-mavericks.html</guid>
<pubDate>Mon, 29 Sep 2025 02:00:00 +0200</pubDate>
<dcterms:modified>2025-09-29T02:00:00.000000+02:00</dcterms:modified>
<description> <![CDATA[
<h1 id="notational_velocity_on_os_x_mavericks">Notational Velocity on OS X Mavericks</h1>

<p>The <a href="https://82mhz.net/posts/2025/09/linkdump-no-74/" >Linkdump No 74</a>
on <a href="https://82mhz.net/" >82MHz</a> had a nice introduction to the
blogpost
<a href="https://minutestomidnight.co.uk/blog/getting-ready-for-the-winter-part-1/" >Getting Ready for the Winter. Part 1, Switching Technology</a> on the
blog <a href="https://minutestomidnight.co.uk/" >Minutes To Midnight</a> by
Simone Silvestroni.</p>

<p>In this great blogpost Simone describes several reasons to
switch to
<a href="https://en.wikipedia.org/wiki/OS_X_Mavericks" >OS X Mavericks</a>
and writes about favorite software recently installed on it.</p>

<p>Simone also points to <a href="https://mavericksforever.com/" >Mavericks Forever</a>,
a wonderful website with a lot of useful tips and links for
running OS X Mavericks in 2025.</p>

<p>I sometimes play with an old MacBook Air from 2013, running OS X Mavericks.</p>

<p>Inspired by Simone's post, I went to
<a href="https://macintoshgarden.org/" >Macintosh Garden</a> and
to <a href="https://www.macintoshrepository.org/" >Macintosh Repository</a>
to find some additional software that I might like.</p>

<h2 id="notational_velocity">Notational Velocity</h2>

<p>I stumbled upon the old version 2.0 β5 of
<a href="https://en.wikipedia.org/wiki/Notational_Velocity" >Notational Velocity</a>.</p>

<p><img src="/ftx/nv-version.png" alt="Screenshot of version window" /></p>

<p>I have never used Notational Velocity, but I remember that several
years ago a lot of people posting about being disappointed that they
no longer could run it after upgrading their OS X.</p>

<p>In the past I have used <a href="https://github.com/jrblevin/deft" >Deft for Emacs</a>, 
an Emacs mode for quickly browsing, filtering, and editing
directories of plain text notes. According to the developer, Deft is
inspired by Notational Velocity.</p>

<p><img src="/ftx/notational-velocity.png" alt="Screenshot of Notational Velocity" /></p>

<p>Notational Velocity can be used without a mouse, completely keyboard-driven.</p>

<p>Just start typing the title of a note. During typing Notational Velocity
performs a incremental search for notes. It searches both in the title
as well as in the body of the notes.</p>

<ul>
<li>To create a new note, just type the title, followed by the Enter-key.</li>
<li>Otherwise, select a note from the list with search results using the
  up and down keys, or the mouse, and activate with the Enter-key.</li>
<li>Changes are automatically saved, there is no save-button.</li>
<li>To create a link to another note, just type the title within double square brackets.
  Follow a link with Command-Enter or by a mouse click.</li>
</ul>

<p>Notational Velocity comes with four notes pre-installed, in one of
them you'll find a list of useful key bindings.</p>

<p>Some useful settings:</p>

<ul>
<li>In Preferences: Store and read notes as plain text files (under &quot;storage&quot;) will create text files.
  This way you can always use them with some other piece of software.</li>
<li>In View: Switch to vertical layout.  This will give a two column layout, the left column shows the search results/list of notes, and the right column the body of the active note.</li>
</ul>

<p>Notational Velocity does what it says on the tin: it is fast and efficient to use. It is not
Emacs, but just like Emacs it can be used completely keyboard driven.</p>
]]></description>
</item>
<item>
<title>Spellcheck in Emacs on OS X Mavericks with MacPorts</title>
<link>https://box.matto.nl/spellcheck-in-emacs-on-os-x-mavericks-with-macports.html</link>
<guid isPermaLink="false">https://box.matto.nl/spellcheck-in-emacs-on-os-x-mavericks-with-macports.html</guid>
<pubDate>Mon, 01 Sep 2025 02:00:00 +0200</pubDate>
<dcterms:modified>2025-09-01T02:00:00.000000+02:00</dcterms:modified>
<description> <![CDATA[
<h1 id="spellcheck_in_emacs_on_os_x_mavericks_with_macports">Spellcheck in Emacs on OS X Mavericks with MacPorts</h1>

<p><a href="https://www.macports.org" >The MacPorts Project</a> provides thousands
of ports that greatly simplify the task of compiling and installing
open-source software on a Mac. It is easy to install MacPorts.</p>

<p>Once MacPorts is installed, it only takes a few commands to install
and upgrade software (&quot;ports&quot;).</p>

<p>MacPorts support many different versions of OS X and MacOS.</p>

<p>Some time ago I installed MacPorts on an old MacBook Air from
2013, running OS X 10.9.5, also known as Mavericks. This results
in an old laptop running an old operating system running modern
software.</p>

<h2 id="gnu_emacs_from_macports">GNU Emacs from MacPorts</h2>

<p>Using MacPorts I installed GNU Emacs, it installed version 30.1,
which takes quite some time because it needs toe compile software
from source code.</p>

<p>Yesterday I upgraded MacPorts and the installed software, which
again resulted in a lot of compile time, and now it runs Emacs 30.2.</p>

<h2 id="emacs_on_an_old_macbook_air">Emacs on an old MacBook Air</h2>

<p>Emacs runs of course fine on an old MacBook Air.</p>

<p>Unfortunately, on this MacBook the function Fn-key and the Ctrl key
can not be exchanged. There is only the option to turn the Caps lock
key as Control key. It is best to drop the habit of using the 
left Control key and only use the Caps lock key for this.</p>

<p><img src="ftx/mavericks-emacs302.png" alt="Screenshot of Emacs 30.2 on OS X Mavericks" />
<p class="center">Screenshot of Emacs 30.2 in X11 on OS X Mavericks</p></p>

<h2 id="spellcheck_on_emacs">Spellcheck on Emacs</h2>

<p>The Flyspell package takes care of spellchecking, but it needs
additional software.</p>

<p>sudo port install hunspell hunspell-dict-nl_NL hunspell-en_US</p>

<p>Next, we need to tell Emacs how to use hunspell and set a default
language.</p>

<p>Request the location of the dictionaries with <code>hunspell -D</code> and
add these to the Emacs init file.</p>

<pre><code>(setenv &quot;DICPATH&quot; &quot;/opt/local/share/hunspell/&quot;)
(setenv &quot;LANG&quot; &quot;en_US.UTF8&quot;)
(setq ispell-program-name &quot;hunspell&quot;)
      (eval-after-load &quot;ispell&quot;
        '(progn (defun ispell-get-coding-system () 'utf-8)))
</code></pre>

<p>Restart Emacs or evaluate the init file.</p>

<h2 id="check_spelling_with_flyspell">Check spelling with Flyspell</h2>

<ul>
<li><code>M-x flyspell-buffer</code> checks the spelling of the current buffer.</li>
<li><code>M-x flyspell-mode</code> enables Flyspell.</li>
<li><code>M-$$</code> check spelling of word-at-point.</li>
<li><code>C-.</code> or <code>ESC TAB</code> auto-corrects the word-at-point.</li>
</ul>

<p>For many more options, see 
<a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Spelling.html" >the friendly manual</a>.</p>
]]></description>
</item>
<item>
<title>Quickly transpose sentences and paragraphs using key bindings in Emacs</title>
<link>https://box.matto.nl/quickly-transpose-sentences-and-paragraphs-using-key-bindings-in-emacs.html</link>
<guid isPermaLink="false">https://box.matto.nl/quickly-transpose-sentences-and-paragraphs-using-key-bindings-in-emacs.html</guid>
<pubDate>Thu, 28 Aug 2025 02:00:00 +0200</pubDate>
<dcterms:modified>2025-08-28T02:00:00.000000+02:00</dcterms:modified>
<description> <![CDATA[
<h1 id="quickly_transpose_sentences_and_paragraphs_using_key_bindings_in_emacs">Quickly transpose sentences and paragraphs using key bindings in Emacs</h1>

<p>Emacs has several fantastic functions that offer you superpowers
when it comes to text editing.</p>

<p>Not all of these functions come with default key bindings.</p>

<p>To make editing prose more efficient, I added a few key bindings for
transposing sentences and paragraphs.</p>

<h2 id="transpose_sentences">Transpose sentences</h2>

<p>The Emacs function transpose-sentences works great and is very
useful when editing prose. By default it has no key bound to it.</p>

<p>First we need to make sure Emacs understands that sentences ends
with a single space:</p>

<pre><code>(setopt sentence-end-double-space nil)
</code></pre>

<p>In a <a href="https://idiomdrottning.org/paredit" >brilliant post</a> Sandra
explains that in Emacs, key bindings can be different for lowercase
and for uppercase chars.</p>

<p>We can utilize this method to construct an easy-to-remember key
binding for <code>transpose-sentences</code>:</p>

<pre><code>(global-set-key (kbd &quot;C-S-t&quot;) #'transpose-chars)
(global-set-key (kbd &quot;C-t&quot;) #'transpose-sentences)
</code></pre>

<p>The default key binding for <code>transpose-chars</code> is <code>C-t</code>.
I don't use that function very often, this config moves that to
<code>C-S-t</code>, making room for binding transpose-sentences to
<code>C-t</code>.</p>

<p>If you frequently use the <code>transpose-chars</code> function, it is
perhaps better to turn the two around, <code>C-t</code> to transpose chars,
and <code>C-S-t</code> to transpose sentences.</p>

<h2 id="transpose_paragraphs">Transpose paragraphs</h2>

<p>Unfortunately, we can't use this method to load M-t and M-S-t with
different key bindings.</p>

<p>Looking for a key binding that may be used within and outside org
mode, I came to <code>C-c M-t</code>:</p>

<pre><code>(global-set-key (kbd &quot;C-c M-t&quot;) #'transpose-paragraphs)
(define-key org-mode-map (kbd &quot;C-c M-t&quot;) #'transpose-paragraphs)
</code></pre>

<p>It is a little awkward to type <code>C-c M-t</code>, but it nevertheless
works faster than <code>M-x transpose-paragraphs</code>.</p>
]]></description>
</item>
<item>
<title>Moving the feed from index.rss to index.xml</title>
<link>https://box.matto.nl/moving-the-feed-from-indexrss-to-indexxml.html</link>
<guid isPermaLink="false">https://box.matto.nl/moving-the-feed-from-indexrss-to-indexxml.html</guid>
<pubDate>Tue, 19 Aug 2025 02:00:00 +0200</pubDate>
<dcterms:modified>2025-08-19T02:00:00.000000+02:00</dcterms:modified>
<description> <![CDATA[
<h1 id="moving_the_feed_from_index.rss_to_index.xml">Moving the feed from index.rss to index.xml</h1>

<p>After reading <a href="https://wok.oblomov.eu/tecnologia/google-killing-open-web/" >Google is killing the open web</a>
I started to style my <a href="/index.xml" >RSS feed</a> using XSLT.</p>

<p>Unfortunately, web browsers won't open a file with the extension &quot;rss&quot;, but
just offer to download it. Therefor I have to rename my RSS feed.</p>

<p>Old name: index.rss</p>

<p>New name: index.xml</p>

<p>The complete URL is:</p>

<pre><code>http://box.matto.nl/index.xml
</code></pre>

<p>or</p>

<pre><code>https://box.matto.nl/index.xml
</code></pre>

<p>For some time the RSS feed will be available on both the old and the new URL.</p>

<p>Please replace the old URL <code>http://box.matto.nl/index.rss</code> with the new
URL <code>http://box.matto.nl/index.xml</code> in your RSS feed reader.</p>
]]></description>
</item>
<item>
<title>Manage remote vm-bhyve guests with OS X Mavericks VNC client</title>
<link>https://box.matto.nl/manage-remote-vmbhyve-guests-with-os-x-mavericks-vnc-client.html</link>
<guid isPermaLink="false">https://box.matto.nl/manage-remote-vmbhyve-guests-with-os-x-mavericks-vnc-client.html</guid>
<pubDate>Sun, 17 Aug 2025 02:00:00 +0200</pubDate>
<dcterms:modified>2025-08-17T02:00:00.000000+02:00</dcterms:modified>
<description> <![CDATA[
<h1 id="manage_remote_vm-bhyve_guests_with_os_x_mavericks_vnc_client">Manage remote vm-bhyve guests with OS X Mavericks VNC client</h1>

<p>FreeBSD vm-bhyve is a great tool to create, install and manage
virtual machines.</p>

<p>vm-bhyve is designed to work with ZFS, which makes it very easy to
create new vm's, and make ZFS snapshots of those.</p>

<p>Virtual machines can either run with or without a graphical
desktop. For machines running without a graphical desktop we
use SSH.</p>

<p>The FreeBSD bhyve hypervisor provides VNC access to the virtual
machines that boot with UEFI. Expose the VNC port to the network
to allow for remote management.</p>

<p><img src="/ftx/mavericks-vnc.png" alt="Screenshot of the Screen Sharing application with a VNC connection to a Debian virtual machine running on the bhyve hypervisor" />
<p class="center">The Screen Sharing application with a VNC connection to a Debian virtual machine running on the bhyve hypervisor</p></p>

<h2 id="vnc_access_with_vm-bhyve">VNC access with vm-bhyve</h2>

<p>We add some lines to the template to allow for remote VNC access:</p>

<pre><code>loader=&quot;uefi&quot;
graphics=&quot;yes&quot;
graphics_res=&quot;1024x760&quot;
graphics_listen=&quot;192.168.123.4&quot;
vnc_password=&quot;secret&quot;
</code></pre>

<ul>
<li>The first line sets UEFI as boot method.</li>
<li>Choose a fitting resolution and use that in the &quot;graphics_res&quot; line,</li>
<li>Set the listen address to allow remote access to the ip address of the bhyve server.</li>
<li>Set a password for connecting to the virtual machine from a VNC client.</li>
</ul>

<p>Start the virtual machine. The default VNC port is 5900. When another
virtual machine is started, port 5901 will be assigned to it, and so on.</p>

<h2 id="os_x_mavericks_vnc_client">OS X Mavericks VNC client</h2>

<p>There is no need to install additional software, OS X Mavericks has
a build-in VNC client.</p>

<p>Open the Finder, choose &quot;Go -&gt; Connect to server&quot; in the menu and
enter &quot;vnc://192.168.123.4:5900&quot; (where &quot;192.168.123.4&quot; is the
ip address of the bhyve server). This prompts for the password
(&quot;secret&quot; in our example above).</p>

<p>The &quot;Screen sharing&quot; application opens with a VNC connection to
the bhyve client.</p>
]]></description>
</item>
<item>
<title>Joined the netizen club webring</title>
<link>https://box.matto.nl/joined-the-netizen-club-webring.html</link>
<guid isPermaLink="false">https://box.matto.nl/joined-the-netizen-club-webring.html</guid>
<pubDate>Tue, 29 Jul 2025 02:00:00 +0200</pubDate>
<dcterms:modified>2025-07-29T02:00:00.000000+02:00</dcterms:modified>
<description> <![CDATA[
<h1 id="joined_the_netizen_club_webring">Joined the netizen club webring</h1>

<p>The netizen club maintains a webring focused on websites that are
able to be viewed in older computers.</p>

<p><a href="http://netizen.club/webring.php" >More about the webring</a>.</p>

<h2 id="the_web_has_become_non-inclusive">The web has become non-inclusive</h2>

<p>Sadly, the web has become mostly inaccessible for old computers.</p>

<p>Websites are often only accessible using encryption. Old
computers lack modern ciphers which makes it impossible to
connect to those websites.</p>

<p><a href="https://en.wikipedia.org/wiki/HTML" >Hypertext Markup Language (HTML)</a> is 
the standard markup language for documents designed to be displayed in a
web browser. Unfortunately, most websites make extensive use of programming
techniques like the use of 
<a href="https://en.wikipedia.org/wiki/JavaScript" >JavaScript</a>, not only making the 
pages slow to load, but also not suitable for older web browsers. Another
disadvantage is that these techniques result in web pages not suitable for
the tools used by visual impaired people.</p>

<h2 id="it_doesn't_have_to_be_like_this">It doesn't have to be like this</h2>

<p>Very often the real content of a web page is dwarfed in comparison
with the total web page's &quot;weight&quot;. To publish a piece of text,
there is often no real reason to use of tools like JavaScript, aside
from loading web pages with surveillance advertising and other
privacy invading solutions.</p>

<p>The netizen club webring helps to find websites that are accessible
for old computers. Let's keep the web open!</p>
]]></description>
</item>
</channel>
</rss>