<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://blog.beardhatcode.be/feed.xml" rel="self" type="application/atom+xml"/><link href="https://blog.beardhatcode.be/" rel="alternate" type="text/html"/><updated>2025-12-03T16:49:59+00:00</updated><id>https://blog.beardhatcode.be/feed.xml</id><title type="html">Beard Hat Code</title><subtitle>A buffer overflow of all the things that go on under my hat while I&apos;m coding... </subtitle><entry><title type="html">Code Formatting Overhaul: A Git Mid-Project Guide</title><link href="https://blog.beardhatcode.be/2023/12/rebase-forgotten-formatter.html" rel="alternate" type="text/html" title="Code Formatting Overhaul: A Git Mid-Project Guide"/><published>2023-12-08T15:44:43+00:00</published><updated>2023-12-08T15:44:43+00:00</updated><id>https://blog.beardhatcode.be/2023/12/rebase-forgotten-formatter</id><content type="html" xml:base="https://blog.beardhatcode.be/2023/12/rebase-forgotten-formatter.html"><![CDATA[<p>Code formatters play a crucial role in maintaining a consistent coding style across a project. When collaborating in a team, code formatters ensure a uniform “look” for your code, irrespective of the author. This enhances readability and, even more significant, results in smaller <code class="language-plaintext highlighter-rouge">diff</code>s in pull requests. To achieve this, all contributors must adhere to the same formatter (with the same configuration). Ideally, a specification of how to format is stored within the project’s Git repository, and is automatically checked on every commit.</p> <p>But what if you realize there’s no formatter set up for a project after it has already started? In this blog post, I’ll share my steps for addressing this issue, particularly for repositories where all branches are frequently rebased.</p> <h2 id="step-0-prioritize-pr-merges">Step 0. Prioritize PR Merges</h2> <p>Given that applying a formatter will likely impact almost all files and potentially lead to merge conflicts, it’s advisable to merge pull requests before proceeding with the formatter implementation. This will minimize your (or your colleague’s) workload in later steps.</p> <h2 id="step-1-introduce-the-formatter-config">Step 1. Introduce the Formatter Config</h2> <p>We begin by adding the files containing your formatters’ config (like <code class="language-plaintext highlighter-rouge">.editorconfig</code>, <code class="language-plaintext highlighter-rouge">.clang-format</code>, etc.). Place a script in the root your repository – say, <code class="language-plaintext highlighter-rouge">format_all.sh</code> – that applies the formatter to all files. Your script might look something like this:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh</span>
<span class="c"># Script to format all the files in this repo in place.</span>
<span class="c"># Your script will likely use a different formatter.</span>
<span class="c"># This one uses find to find all c++ related files and then executes</span>
<span class="c">#   clang-format -i {file}</span>
<span class="c"># on each of them.</span>


find <span class="nb">.</span> <span class="nt">-regex</span> <span class="s1">'.*\.\(cpp\|hpp\|cc\|cxx\|c\|h\)'</span> <span class="nt">-exec</span> clang-format <span class="nt">-i</span> <span class="o">{}</span> <span class="se">\;</span>
</code></pre></div></div> <p><strong>Don’t execute the formatter just yet!</strong> Add and commit the script and the formatter config files. Next, tag that commit for future reference (we’ll need it in step 3).</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Add ONLY the formatting files</span>
git add .editorconfig .clang-format format_all.sh
git commit <span class="nt">-m</span> <span class="s2">"clean: introduce formatter configuration"</span>
git tag tmp/fmt-add-config <span class="c"># for future reference</span>
</code></pre></div></div> <h3 id="step-2-apply-the-formatter-and-commit">Step 2: Apply the Formatter and Commit</h3> <p>In the root of your repository, run the <code class="language-plaintext highlighter-rouge">format_all.sh</code> script and commit the results.</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./format_all.sh
git add <span class="nt">--all</span>
git commit <span class="nt">-m</span> <span class="s2">"clean: format all the files"</span>
git tag tmp/fmt-applied
</code></pre></div></div> <h2 id="step-3-fix-all-the-branches">Step 3. Fix all the branches</h2> <p>For each branch that couldn’t be merged earlier, follow these steps.</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git rebase tmp/fmt-add-config
git filter-branch <span class="nt">-f</span> <span class="nt">--tree-filter</span> ./format_all.sh <span class="nt">--</span> tmp/fmt-add-config~..HEAD
git rebase <span class="nt">--empty</span><span class="o">=</span>drop tmp/fmt-applied
git push <span class="nt">--force-with-lease</span>
</code></pre></div></div> <p>I’ll break down these steps below.</p> <h3 id="step-31-rebase-on-the-commit-adding-the-formatter">Step 3.1 Rebase on the commit adding the formatter.</h3> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git rebase tmp/fmt-add-config
</code></pre></div></div> <p>This makes the code in this branch as close as possible to the code you applied the formatter on (step 2). Additionally, this branch now also contains the formatter config and <code class="language-plaintext highlighter-rouge">format_all.sh</code> script.</p> <p>It may be possible that you have some rebase conflicts here, but these are not related to applying the formatter. If you hit one of these, fix the conflict, <code class="language-plaintext highlighter-rouge">git add</code> the conflicting file and <code class="language-plaintext highlighter-rouge">git rebase --continue</code>.</p> <h3 id="step-32-apply-the-formatter-on-all-the-commits-of-this-branch">Step 3.2: Apply the formatter on all the commits of this branch</h3> <p>Now, we will format all the files, to do this, we will use the wonderful <code class="language-plaintext highlighter-rouge">git filter-branch</code>, a program that edits the contents of the files at each commit.</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git filter-branch <span class="nt">-f</span> <span class="se">\</span>
  <span class="nt">--tree-filter</span> ./format_all.sh <span class="se">\</span>
  <span class="nt">--</span> <span class="se">\</span>
  tmp/fmt-add-config~..HEAD
</code></pre></div></div> <p>Filter branch will check out every commit between the one where we added the formatter config and where we are now (HEAD). At each commit it executes the <code class="language-plaintext highlighter-rouge">./format_all.sh</code> script, which replaces all the file in the commit with their formatted counterparts.</p> <p>Our current “tree filtered” branch, and the formatted main branch now only differ at those places where there were actually changes made.</p> <p>The attentive reader may have noticed that this branch does not have our “format all the things” commit. However, on this branch the commit that introduced the formatter config has been rewritten to also include the formatting. In the next step we will paste these two histories together.</p> <h3 id="step-33-rebase-on-the-formatted-main-branch">Step 3.3: Rebase on the formatted main branch</h3> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git rebase <span class="nt">--empty</span><span class="o">=</span>drop tmp/fmt-applied
</code></pre></div></div> <p>Git will now apply our changes onto the commit that formatted all the files. In doing so, it will notice that the changes in the first commit of this branch are the same as the ones in the last commit of the main branch. It will skip this commit with the message:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dropping SOME SHA ... -- patch contents already upstream
</code></pre></div></div> <h1 id="step-4-push-the-changes-with-gentle-force">Step 4: Push the changes (with gentle force)</h1> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push <span class="nt">--force-with-lease</span>
</code></pre></div></div> <p>As we have changed all the commits in this branch we cannot simply push. That would lead to the push being rejected with “failed to push some refs”. So instead we push with force and lease lock. The <code class="language-plaintext highlighter-rouge">--force-with-lease</code> differs from the simple <code class="language-plaintext highlighter-rouge">--force</code> in that it checks that the stuff you are forcefully pushing is only replacing commits you know of. If someone else pushed a commit since you last pushed, the push <code class="language-plaintext highlighter-rouge">--force-with-lease</code> will fail (which is what you should want).</p>]]></content><author><name></name></author><category term="git"/><category term="git"/><category term="linux"/><summary type="html"><![CDATA[Ever found yourself knee-deep in a project, only to realize that no formatter was set up for it? Fear not! In this blog post, I'll guide you through the steps to introduce a formatter to an ongoing project.]]></summary></entry><entry><title type="html">Automatically do `pass git push` after every commit</title><link href="https://blog.beardhatcode.be/2021/05/pass-auto-push.html" rel="alternate" type="text/html" title="Automatically do `pass git push` after every commit"/><published>2021-05-14T17:51:37+00:00</published><updated>2021-05-14T17:51:37+00:00</updated><id>https://blog.beardhatcode.be/2021/05/pass-auto-push</id><content type="html" xml:base="https://blog.beardhatcode.be/2021/05/pass-auto-push.html"><![CDATA[<p>Sometimes, it is interesting to automatically push after every commit. In this blogpost, I’ll show you how to accomplish this with a post-commit hook in git. We’ll also look at <code class="language-plaintext highlighter-rouge">git -C</code> and two interesting environment variables: <code class="language-plaintext highlighter-rouge">GIT_DIR</code> and <code class="language-plaintext highlighter-rouge">GIT_WORK_TREE</code> . We will use my favourite password manager, password-store, as context for the examples.</p> <p><a href="http://www.zx2c4.com/projects/password-store/" rel="noopener noreferrer" target="_blank">Password-store</a> is an application that uses PGP to keep your passwords (and other data) secure. You enter your secret data into a text file which <code class="language-plaintext highlighter-rouge">pass</code> then encrypts with your public PGP key and stores in a folder. You can also set up this folder as a git repository. If you do so <code class="language-plaintext highlighter-rouge">pass</code> will create a commit in for every change you make. By using <code class="language-plaintext highlighter-rouge">pass git push</code> you can then push your changes to other devices.</p> <p>To automagically call <code class="language-plaintext highlighter-rouge">pass git push</code> after every commit we can create a <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks" rel="noopener noreferrer" target="_blank"><code class="language-plaintext highlighter-rouge">post-commit</code> hook</a> to trigger an action at the right moment. Because pass makes a commit for every change, this means that we can call a program after every edit.</p> <p>To do this, create a file <code class="language-plaintext highlighter-rouge">.git/hooks/post-commit</code> in your password store and set its content to:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh</span>
<span class="nb">set</span> <span class="nt">-x</span>
git pull <span class="nt">--rebase</span> <span class="c"># get edits by other devices</span>
git push          <span class="c"># send the latest commit</span>
</code></pre></div></div> <p>We use <code class="language-plaintext highlighter-rouge">git</code> here, instead of <code class="language-plaintext highlighter-rouge">pass git</code>, because hooks always execute in the root of the password store repository. To make it more likely that the hook succeeds, we pull in remote changes first. Thanks to the <code class="language-plaintext highlighter-rouge">set -x</code> we ensure that no push will occur if the pull failed.</p> <h2 id="use-git--c-to-set-a-working-directory">Use <code class="language-plaintext highlighter-rouge">git -C</code> to set a working directory</h2> <p>Existing <code class="language-plaintext highlighter-rouge">pass</code> users may have noticed that <code class="language-plaintext highlighter-rouge">pass git</code> acts like git in the password store, even when working elsewhere in the filesystem. How can <code class="language-plaintext highlighter-rouge">pass git</code> do that? Well, it can first <code class="language-plaintext highlighter-rouge">cd</code> into that directory and then execute the git actions. So basically:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> <span class="s2">"/path/to/folder/"</span>
git <span class="nv">$@</span>
</code></pre></div></div> <p>We can also accomplish the same with <code class="language-plaintext highlighter-rouge">git -C</code>, like how <code class="language-plaintext highlighter-rouge">pass</code> does it internally. The following is equivalent<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> to the previous block of code:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git <span class="nt">-C</span> <span class="s2">"/path/to/folder/"</span> <span class="nv">$@</span>
</code></pre></div></div> <h2 id="bonus-git_dir-and-git_work_tree">Bonus: <code class="language-plaintext highlighter-rouge">GIT_DIR</code> and <code class="language-plaintext highlighter-rouge">GIT_WORK_TREE</code></h2> <p>We can also combine the <code class="language-plaintext highlighter-rouge">GIT_WORK_TREE</code> and <code class="language-plaintext highlighter-rouge">GIT_DIR</code> environment variables to achieve the same result:</p> <ul> <li><code class="language-plaintext highlighter-rouge">GIT_DIR</code> specifies the location of the <code class="language-plaintext highlighter-rouge">.git</code> directory of the repository want to interact with</li> <li><code class="language-plaintext highlighter-rouge">GIT_WORK_TREE</code> contains the path to the root of the repository (that is not bare)</li> </ul> <p>So, the following command stages <code class="language-plaintext highlighter-rouge">/path/to/folder/file</code> in the git repository in <code class="language-plaintext highlighter-rouge">/path/to/folder</code> no mater where we are in the filesystem.</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">GIT_DIR</span><span class="o">=</span><span class="s2">"/path/to/folder/.git"</span> <span class="nv">GIT_WORK_TREE</span><span class="o">=</span><span class="s2">"/path/to/folder"</span> git add file
</code></pre></div></div> <p>If we only want to inspect the history, <code class="language-plaintext highlighter-rouge">GIT_DIR</code> will suffice. As an example, the following will act like <code class="language-plaintext highlighter-rouge">git log</code> executed in <code class="language-plaintext highlighter-rouge">/path/to/folder/</code>:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">GIT_DIR</span><span class="o">=</span><span class="s2">"/path/to/folder/.git"</span> git log
</code></pre></div></div> <p>Although these environment variables look cool, they are also non-trivial. If you want to carry out more than one action on a repository, and don’t need stuff from other places it might be best to just <code class="language-plaintext highlighter-rouge">cd</code> into the right directory or use <code class="language-plaintext highlighter-rouge">git -C</code>. Combining these environment variables with <code class="language-plaintext highlighter-rouge">-C</code> can lead to unexpected results as the environment variables <code class="language-plaintext highlighter-rouge">GIT_DIR</code> and <code class="language-plaintext highlighter-rouge">GIT_WORK_TREE</code> will be interpreted relative to the path given to <code class="language-plaintext highlighter-rouge">-C</code>. If you are using git in a script that may be used in bizarre environments, you should clear these environment variables like <code class="language-plaintext highlighter-rouge">pass</code> does:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">unset </span>GIT_DIR GIT_WORK_TREE GIT_NAMESPACE GIT_INDEX_FILE GIT_INDEX_VERSION GIT_OBJECT_DIRECTORY GIT_COMMON_DIR
</code></pre></div></div> <h2 id="final-notes">Final notes</h2> <p>The approach laid out here to push changes does not poll the remote repository for incoming changes. I personally do not need that, because I can just <code class="language-plaintext highlighter-rouge">pass git pull</code> whenever a login fails. I almost always have internet when trying to log in to places, and thanks to the post-commit hook, the latest passwords are always in the remote.</p> <h2 id="sources">Sources</h2> <ul> <li>The source code of <a href="https://git.zx2c4.com/password-store/tree/src/password-store.sh" rel="noopener noreferrer" target="_blank">pass</a></li> <li>A chapter in the gitbook on <a href="https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables" rel="noopener noreferrer" target="_blank">Git’s Environment Variables</a></li> <li>manual page on <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks" rel="noopener noreferrer" target="_blank">githooks</a> (also <code class="language-plaintext highlighter-rouge">man githooks</code>)</li> </ul> <div class="footnotes" role="doc-endnotes"> <ol> <li id="fn:1"> <p>Almost, after executing this, your current working directory remains the same. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> </ol> </div>]]></content><author><name></name></author><category term="Git"/><category term="git"/><category term="password"/><summary type="html"><![CDATA[Sometimes, it is interesting to automatically push after every commit. In this blogpost, I’ll show you how to accomplish this with a post-commit hook in git. We’ll also look at git -C and two interesting environment variables: GIT_DIR and GIT_WORK_TREE . We will use my favourite password manager, password-store, as context for the examples.]]></summary></entry><entry><title type="html">Backing up a ZFS pool to a Raspberry Pi with syncoid</title><link href="https://blog.beardhatcode.be/2021/05/raspberry-pi-zfs-replication.html" rel="alternate" type="text/html" title="Backing up a ZFS pool to a Raspberry Pi with syncoid"/><published>2021-05-14T17:51:37+00:00</published><updated>2021-05-14T17:51:37+00:00</updated><id>https://blog.beardhatcode.be/2021/05/raspberry-pi-zfs-replication</id><content type="html" xml:base="https://blog.beardhatcode.be/2021/05/raspberry-pi-zfs-replication.html"><![CDATA[<p>Recently the NAS at my parents home broke, and I needed a quick alternative to take off-site backups of a server. Since that NAS was only there for me when I was younger, and I couldn’t visit them to replace it, I opted to upgrade the Pi4 that was still there doing nothing to a ZFS replication device. I prepared an SD card with <a href="https://ubuntu.com/download/raspberry-pi" rel="noopener noreferrer" target="_blank">Ubuntu server for the Raspberry Pi</a> and told my parents to replace the SD card in the Pi. Then I logged in and installed it remotely.</p> <h2 id="step-1-setting-up-zfs">Step 1: Setting up ZFS</h2> <p>First, we’ll need to get the ZFS tools installed:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>zfsutils-linux
</code></pre></div></div> <p>Then, we make a pool called <code class="language-plaintext highlighter-rouge">rpool</code> representing the whole vdev, and we add a dataset named <code class="language-plaintext highlighter-rouge">rpool/backup</code> that used lz4 compression. The command below is for a single disk. If you have multiple disks, you may want to make a mirror vdev (like I will probably do after Covid-19). Lookup what configuration will work best for you. There is a more <a href="https://ubuntu.com/tutorials/setup-zfs-storage-pool" rel="noopener noreferrer" target="_blank">elaborate tutorial on how to set up a ZFS pool</a> on the ubuntu website.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo zpool create -f -o ashift=12 -O  acltype=posixacl -O xattr=sa rpool "$DISK_ID"
sudo zfs create rpool/backup
sudo zfs set compression=lz4 rpool/backup
</code></pre></div></div> <h2 id="step-2-put-the-pis-ssh-key-on-the-remote-server">Step 2: Put the Pi’s SSH key on the remote server</h2> <p>We will pull in snapshots over SSH. To this end, we add the SSH key of the root user on the pi to the root user’s authorized keys file on the remote server.</p> <p>Note that we do not do it the other way around, we want our backup server to reach out to the remote server and pull in snapshots. We do not want the remote server to push snapshots to the pi, because if this server gets compromised it should not have access the backup server (to wipe it).</p> <p>It is advised to <strong>always pull from the backup server</strong>, and ensure that you harden the backup server’s security: only accessible over VPN, the bare minimum of running services, ….</p> <h2 id="step-3-install-syncoid">Step 3: Install Syncoid</h2> <p>To pull in snapshots from the remote machine, we will use Syncoid. This is a tool bundled with the policy-driven ZFS snapshot management package <a href="https://github.com/jimsalterjrs/sanoid/" rel="noopener noreferrer" target="_blank">Sanoid</a>. To install it, use:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>sanoid
</code></pre></div></div> <p>Syncoid facilitates incremental replication of ZFS datasets.</p> <h3 id="example-with-one-dataset">Example with one dataset</h3> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#             ___________ source ___________   _______target ______</span>
<span class="nb">sudo </span>syncoid root@remote:rpool/data/mydataset rpool/backup/mydataset
</code></pre></div></div> <ol> <li>The above snippet creates a snapshot named “syncoid_ubuntu_YYYY-MM-DD-HH:MM:SS” for <code class="language-plaintext highlighter-rouge">rpool/data/mydataset</code> on the remote server.</li> <li>Rolls back <code class="language-plaintext highlighter-rouge">rpool/backup/mydataset</code> to the latest common snapshot between the target and the source.</li> <li>Incrementally receives that “syncoid_ubuntu_YYYY-MM-DD-HH:MM:SS” snapshot and all earlier snapshots to our target <code class="language-plaintext highlighter-rouge">rpool/backup/mydataset</code> dataset (the pi4).</li> <li>Removes older “syncoid_ubuntu_YYYY-MM-DD-HH:MM:SS”-like snapshots on both the source and the target (keeping the latest one).</li> </ol> <h3 id="working-with-multiple-datasets-recursively">Working with multiple datasets recursively</h3> <p>We want Syncoid to incrementally receive all the snapshots for all datasets under <code class="language-plaintext highlighter-rouge">/rpool/data</code> on the remote machine to <code class="language-plaintext highlighter-rouge">/rpool/data</code> on the pi. To do this we use:</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>syncoid <span class="nt">-R</span> <span class="nt">--skip-parent</span> <span class="nt">--no-rollback</span> root@remote:rpool/data rpool/backup
</code></pre></div></div> <p>Let’s go over the flags:</p> <ul> <li><code class="language-plaintext highlighter-rouge">-R</code> indicates that we want to recursively visit all datasets under <code class="language-plaintext highlighter-rouge">root@remote:rpool/data</code></li> <li><code class="language-plaintext highlighter-rouge">--skip-parent</code> ensures that we do not receive <code class="language-plaintext highlighter-rouge">root@remote:rpool/data</code> itself (I don’t have anything in there)</li> <li><code class="language-plaintext highlighter-rouge">--no-rollback</code> prevents Syncoid from rolling back snapshots on the target machine (the pi).</li> </ul> <p>The <code class="language-plaintext highlighter-rouge">--no-rollback</code> flag ensures that Syncoid does not delete snapshots but only adds them. If you mess with the snapshots on your remote machine (e.g. by doing a rollback), ZFS receive will not be able to receive the latest snapshot. Syncoid will continue with the other datasets and then exit with exit code 2. To still get the changes regardless, you can remove this flag, then Syncoid will look for the latest common snapshot, and it will roll back target to that snapshot and then do the receive.</p> <p>Because this is a backup system, we do not want to roll back in case an adversary rolls back the ZFS filesystem on our server.</p> <h2 id="step-4-automate-and-monitor">Step 4: Automate and monitor</h2> <p>To not forget to run Syncoid, we will use a SystemD timer. As a general rule you should <strong>ensure that you monitor your automated backups actively</strong>, If you don’t and something silently goes wrong, you will not notice it until it is too late. Have your monitoring service constantly check the freshness of your backups (active). Do not only rely on the backup server to send you mail when something went wrong (passive monitoring).</p> <p>Create a file <code class="language-plaintext highlighter-rouge">/opt/syncoid-pull/syncoid-pull</code> owned by root and only writeable and executable by root that calls syncoid and sends off metrics for monitoring:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
<span class="nb">set</span> <span class="nt">-xeuo</span> pipefail <span class="c"># failfast and be verbose</span>

syncoid <span class="nt">-R</span> <span class="nt">--skip-parent</span> <span class="nt">--no-rollback</span> <span class="nt">--debug</span> root@remote:rpool/data rpool/backup

zfs list <span class="nt">-Hpo</span> creation,name,used <span class="nt">-t</span> snapshot <span class="nt">-r</span> rpool/backup <span class="nt">-s</span> creation |<span class="se">\</span>
    <span class="nb">sed</span> <span class="s1">'s:\t\([^@]*\)@:\t\1\t:'</span> |<span class="se">\</span>
    column <span class="nt">-J</span> <span class="nt">--table-columns</span> creation,dataset,name,size <span class="nt">-s</span> <span class="s1">$'</span><span class="se">\t</span><span class="s1">'</span> <span class="nt">--table-name</span> <span class="s1">'snapshots'</span> |<span class="se">\</span>
    ssh  root@remote <span class="s1">'cat &gt; /var/www/status/backups.json'</span>
</code></pre></div></div> <p>The last command in this file sends a JSON of snapshots to a file on the remote machine to be monitored. Replace the last line with something that interacts with your monitoring system.</p> <p>Automate a call to the script above during the off-peak hour with these SystemD unit and timer files:</p> <p><code class="language-plaintext highlighter-rouge">/etc/systemd/system/syncoid-pull.service</code>:</p> <div class="language-systemd highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">[Unit]</span>
<span class="nt">Description</span><span class="p">=</span>syncoid pull
<span class="nt">Requires</span><span class="p">=</span>local-fs.target
<span class="nt">After</span><span class="p">=</span>local-fs.target

<span class="k">[Service]</span>
<span class="nt">Type</span><span class="p">=</span>oneshot
<span class="nt">ExecStart</span><span class="p">=</span>/opt/syncoid-pull/syncoid-pull
<span class="nt">WorkingDirectory</span><span class="p">=</span>/opt/syncoid-pull/
</code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">/etc/systemd/system/syncoid-pull.timer</code>:</p> <div class="language-systemd highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">[Unit]</span>
<span class="nt">Description</span><span class="p">=</span>syncoid pull every night

<span class="k">[Timer]</span>
<span class="nt">OnCalendar</span><span class="p">=</span>04:37:41
<span class="nt">Persistent</span><span class="p">=</span>true

<span class="k">[Install]</span>
<span class="nt">WantedBy</span><span class="p">=</span>timers.target
</code></pre></div></div> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>systemctl <span class="nb">enable </span>syncoid-pull.timer <span class="o">&amp;&amp;</span> <span class="nb">sudo </span>systemctl start syncoid-pull.timer
</code></pre></div></div> <h2 id="extra-delete-old-snapshots">Extra: Delete old snapshots</h2> <p>To preserve some space on the pi, I want to remove snapshots older than 2 months automatically. To do this, I added the equivalent of the following snippet to my <code class="language-plaintext highlighter-rouge">syncoid-pull</code> script.</p> <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">now</span><span class="o">=</span><span class="si">$(</span><span class="nb">date</span> +%s<span class="si">)</span>
zfs list <span class="nt">-Hpo</span> creation,name <span class="nt">-t</span> snapshot <span class="nt">-r</span> rpool/backup <span class="se">\</span>
    | <span class="nb">grep</span> <span class="s1">$'</span><span class="se">\t</span><span class="s1">''rpool/backup/[^@]*@zfs-auto-snap_'</span> <span class="se">\</span>
    | <span class="nb">tac</span> <span class="se">\</span>
    | <span class="k">while </span><span class="nb">read</span> <span class="nt">-r</span> creation snapshot<span class="p">;</span> <span class="k">do
        if</span> <span class="o">((</span> <span class="o">(</span> <span class="nv">$now</span> - <span class="nv">$creation</span> <span class="o">)</span> <span class="o">&gt;</span> 60 <span class="k">*</span> 60 <span class="k">*</span> 24 <span class="k">*</span> 30 <span class="k">*</span> 2 <span class="o">))</span><span class="p">;</span> <span class="k">then
            </span>zfs destroy <span class="nv">$snapshot</span><span class="p">;</span>
        <span class="k">fi</span><span class="p">;</span>
      <span class="k">done</span>
</code></pre></div></div> <p>It finds all snapshots in <code class="language-plaintext highlighter-rouge">rpool/backup</code> and deletes them once they reach teh age of two months. The <code class="language-plaintext highlighter-rouge">tac</code> reverses the list which makes it faster. This action should be performed before sending the list of snapshots to monitoring.</p> <h2 id="other-tips-and-tricks">Other tips and tricks</h2> <ul> <li>Attach a M.2 SATA SSD to USB 3.0 External SSD enclosure to your pi.</li> <li>Do regular ZFS scrubs (<code class="language-plaintext highlighter-rouge">zpool scrub rpool</code>) to check the health of your pool and send the health status to monitoring.</li> <li>Use logcheck to send mails to you when a service fails.</li> <li>Don’t boot your Pi from the SD card</li> </ul>]]></content><author><name></name></author><category term="Backup"/><category term="zfs"/><summary type="html"><![CDATA[How to quickly make a ZFS replication server from a Raspberry Pi using syncoid. We show how syncoid can simplify `zfs send` and `receive` to a Raspberry Pi running Ubuntu.]]></summary></entry><entry><title type="html">Declarative NixOS containers</title><link href="https://blog.beardhatcode.be/2020/12/Declarative-Nixos-Containers.html" rel="alternate" type="text/html" title="Declarative NixOS containers"/><published>2020-12-28T08:29:25+00:00</published><updated>2020-12-28T08:29:25+00:00</updated><id>https://blog.beardhatcode.be/2020/12/Declarative-Nixos-Containers</id><content type="html" xml:base="https://blog.beardhatcode.be/2020/12/Declarative-Nixos-Containers.html"><![CDATA[<p>NixOS’ containers allow you to run separate lightweight NixOS instances on the same machine. This can be interesting if you want to deploy multiple services on the same host that each need a custom OS configuration. NixOS’ containers do <em>not</em> provide full security out of the box (just like docker). They do give you a separate chroot, but a privileged user (root) in a container can escape the container and become root on the host system. With that disclaimer out of the way (we have some solutions at the bottom of this post), let’s look at an example.</p> <p>Suppose we wanted to make a container called <code class="language-plaintext highlighter-rouge">wasabi</code> that hosts a simple HTTPD server. The configuration would look something like this:</p> <div class="language-nix highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="nv">containers</span><span class="o">.</span><span class="nv">wasabi</span> <span class="o">=</span> <span class="p">{</span>
    <span class="nv">ephemeral</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
    <span class="nv">autoStart</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
    <span class="nv">config</span> <span class="o">=</span> <span class="p">{</span> <span class="nv">config</span><span class="p">,</span> <span class="nv">pkgs</span><span class="p">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
        <span class="nv">services</span><span class="o">.</span><span class="nv">httpd</span><span class="o">.</span><span class="nv">enable</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
        <span class="nv">services</span><span class="o">.</span><span class="nv">httpd</span><span class="o">.</span><span class="nv">adminAddr</span> <span class="o">=</span> <span class="s2">"foo@example.org"</span><span class="p">;</span>
        <span class="nv">networking</span><span class="o">.</span><span class="nv">firewall</span><span class="o">.</span><span class="nv">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="p">];</span>
    <span class="p">};</span>
  <span class="p">};</span>
</code></pre></div></div> <p>After a <code class="language-plaintext highlighter-rouge">nixos-rebuild switch</code>, we will see that a new service is started <code class="language-plaintext highlighter-rouge">container@wasabi</code>. If we <code class="language-plaintext highlighter-rouge">curl localhost</code> then we will see that it works:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ curl 'http://localhost'
&lt;html&gt;&lt;body&gt;&lt;h1&gt;It works!&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;

$ systemctl status container@wasabi
● container@wasabi.service - Container 'wasabi'
     Loaded: loaded (/nix/store/...-unit-container-wasabi.service/container@wasabi.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2020-12-24 14:22:49 UTC; 1h 15min ago
</code></pre></div></div> <p>The container punched a hole through the firewall of the host and allowed us to access the hosted content, even from other computers than our own. But how can we see the status of the HTTPD daemon? Running <code class="language-plaintext highlighter-rouge">systemctl status httpd</code> on our server will show us nothing.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ systemctl status httpd
Unit httpd.service could not be found.
</code></pre></div></div> <h2 id="logging-in-to-the-container">Logging in to the container</h2> <p>To see the HTTPD service, we need to log into the container with:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nixos-container root-login wasabi
</code></pre></div></div> <p>Once in there, we see that the HTTPD service is indeed running:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[root@wasabi:~]# systemctl status httpd
● httpd.service - Apache HTTPD
     Loaded: loaded (/nix/store/...-unit-httpd.service/httpd.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2020-12-24 14:22:49 UTC; 12min ago
     ...
</code></pre></div></div> <p>We can also find the server logs in <code class="language-plaintext highlighter-rouge">/var/logs/httpd</code> directory in the container.</p> <h2 id="to-preserve-state-or-not-to-preserve-state">To preserve state or not to preserve state</h2> <p>By default, nix-containers are stateful, files you modify while logged in to your container will persist over restarts and updates of the container. Just like your document folder that remains untouched by <code class="language-plaintext highlighter-rouge">nixos-rebuid</code>. Files managed by nix cannot be modified as they are symlinked from the read only <code class="language-plaintext highlighter-rouge">/nix/store</code> shared by host and container. So don’t store secrets in the store if you don’t trust the container fully.</p> <p>We can also ensure that a container starts “fresh” every time it is updated or reloaded. To do this we set <code class="language-plaintext highlighter-rouge">containers.wasabi.ephemeral = true</code>. My general recommendation for configuration management is that you want as less state in your containers as possible. This ensures that you can <code class="language-plaintext highlighter-rouge">nix-rebuild</code> on another host and still have everything working.</p> <h2 id="mounts">Mounts</h2> <p>But sometimes there is important state you want to keep: uploaded files, database contents and so on. How can we manage those? You can preserve data in a mount. For this example, let’s imagine that we want to preserve our HTTPD logs. To do this, we use the <code class="language-plaintext highlighter-rouge">containers.&lt;name&gt;.bindMounts</code> option:</p> <div class="language-nix highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="nv">containers</span><span class="o">.</span><span class="nv">wasabi</span><span class="o">.</span><span class="nv">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
      <span class="s2">"/var/log/httpd"</span> <span class="o">=</span> <span class="p">{</span>
        <span class="nv">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/wasabiData/"</span><span class="p">;</span>
        <span class="nv">isReadOnly</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
      <span class="p">};</span>
    <span class="p">};</span>
</code></pre></div></div> <p>The configuration above specifies that <code class="language-plaintext highlighter-rouge">/var/log/httpd</code> in the container should be linked to <code class="language-plaintext highlighter-rouge">/mnt/wasabiData</code> on the host (machine running the containers). For this to work the folders should exist and for HTTPD to have write privileges on the folder in the container we should declare the folders as follows, with <code class="language-plaintext highlighter-rouge">systemd.tmpfiles</code> (it’s a bad name, I know). In the config of the container (the body of the function in <code class="language-plaintext highlighter-rouge">containers.wasabi.config</code>), we must ensure that the <code class="language-plaintext highlighter-rouge">/var/log/httpd</code> directory is a directory (<code class="language-plaintext highlighter-rouge">d</code>) and that it is owned by user <code class="language-plaintext highlighter-rouge">wwwrun</code> (first one) and the group <code class="language-plaintext highlighter-rouge">wwwrun</code> (second one). The user and group must be set differently depending on the needs of your system, if you don’t set the user and group properly, HTTPD will not be allowed to write to the folder. The easiest way to find out what user and group you need is to log into the container before you set up the mount and find out the permissions with <code class="language-plaintext highlighter-rouge">ls -l</code> in the parent directory.</p> <div class="language-nix highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">containers</span><span class="o">.</span><span class="nv">wasabi</span> <span class="o">=</span> <span class="p">{</span>
    <span class="o">...</span>
    <span class="nv">config</span> <span class="o">=</span> <span class="p">{</span> <span class="nv">config</span><span class="p">,</span> <span class="nv">pkgs</span><span class="p">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
       <span class="nv">systemd</span><span class="o">.</span><span class="nv">tmpfiles</span><span class="o">.</span><span class="nv">rules</span> <span class="o">=</span> <span class="p">[</span>
        <span class="s2">"d /var/log/httpd 700 wwwrun wwwrun -"</span>
       <span class="p">];</span>
       <span class="o">...</span>
    <span class="p">};</span>
<span class="p">}</span>
</code></pre></div></div> <p>We must also ensure that <code class="language-plaintext highlighter-rouge">/mnt/wasabiData/</code> exists on the host. Do <em>not</em> use <code class="language-plaintext highlighter-rouge">tempfiles</code> to achieve this, as this can cause confusing problems when you redeploy the system without modification to the container. In that case, the tempfiles on the host get executed, changing the permissions of the mounted directory in a way that may conflict with the configuration inside your container (your container will suddenly lose access to the data).</p> <p>Data stored in mounted folders will be preserved even if the container is set to be ephemeral.</p> <h2 id="networking-and-port-forwarding">Networking and port forwarding</h2> <p>By default, declarative nix containers can use the network of the host. They can initiate connections to anywhere and listen on any port.</p> <p><strong>If you want to do any kind of port forwarding or reverse proxies you must set <em>all</em> of the following properties on your container</strong></p> <div class="language-nix highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="nv">containers</span><span class="o">.</span><span class="nv">wasabi</span> <span class="o">=</span> <span class="p">{</span>
    <span class="nv">privateNetwork</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
    <span class="nv">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.2"</span>
    <span class="nv">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
  <span class="p">}</span>
</code></pre></div></div> <p>You may adjust the IP addresses to your liking. By setting <code class="language-plaintext highlighter-rouge">privateNetwork</code> to true, the containers network is decoupled from the hosts network. It gets its own virtual interface <code class="language-plaintext highlighter-rouge">ve-wasabi</code>. The container can not directly listen on ports on the host, and it cannot initiate connections to the outside world. The only connections it can have is to the host.</p> <h3 id="give-internet-access">Give internet access</h3> <p>To allow our container to initiate connections to the public internet we need to set up <a href="https://en.wikipedia.org/wiki/Network_address_translation" rel="noopener noreferrer" target="_blank">network address translation (NAT)</a>. This will allow our containers to open non-privileged ports (&gt; 1024) on the host to send and receive packets to the outside world. To do this, add the following to the <em>host</em> config. (with <code class="language-plaintext highlighter-rouge">eth0</code> the name of your real network interface)</p> <div class="language-nix highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="nv">networking</span><span class="o">.</span><span class="nv">nat</span><span class="o">.</span><span class="nv">enable</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
  <span class="nv">networking</span><span class="o">.</span><span class="nv">nat</span><span class="o">.</span><span class="nv">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"ve-wasabi"</span> <span class="p">];</span>
  <span class="nv">networking</span><span class="o">.</span><span class="nv">nat</span><span class="o">.</span><span class="nv">externalInterface</span> <span class="o">=</span> <span class="s2">"eth0"</span><span class="p">;</span>
</code></pre></div></div> <p>You can add the names of all containers with <code class="language-plaintext highlighter-rouge">privateNetwork</code> set to true that need internet access. To allow access to the internet to all your containers with a private network you can set <code class="language-plaintext highlighter-rouge">networking.nat.internalInterfaces = [ "ve-*" ];</code></p> <p>Note: This only if the container needs to connect remote servers (like databases), it is not needed to reply to incoming traffic coming form, for example a reverse proxy service on the host.</p> <h3 id="reverse-proxies">Reverse proxies</h3> <p>Before you start remapping ports, it might be interesting to realize that this is not necessary for all applications. Consider that our host is a service that host various HTTP based services in the containers <code class="language-plaintext highlighter-rouge">wasabi</code>, <code class="language-plaintext highlighter-rouge">sambal</code> and <code class="language-plaintext highlighter-rouge">tabasco</code>. With IP addresses <code class="language-plaintext highlighter-rouge">192.168.100.11</code>, <code class="language-plaintext highlighter-rouge">192.168.100.22</code> and <code class="language-plaintext highlighter-rouge">192.168.100.33</code>. We can use a nginx instance with <a href="https://letsencrypt.org/" rel="noopener noreferrer" target="_blank">Let’s Encrypt</a> certificates that allows us to dispatch incoming requests to the right container.</p> <div class="language-nix highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="nv">security</span><span class="o">.</span><span class="nv">acme</span><span class="o">.</span><span class="nv">acceptTerms</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
  <span class="nv">security</span><span class="o">.</span><span class="nv">acme</span><span class="o">.</span><span class="nv">email</span> <span class="o">=</span> <span class="s2">"letsencrypt@example.com"</span><span class="p">;</span>
  <span class="nv">services</span><span class="o">.</span><span class="nv">nginx</span> <span class="o">=</span> <span class="p">{</span>
    <span class="nv">enable</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
    <span class="nv">recommendedProxySettings</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
    <span class="nv">recommendedTlsSettings</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
    <span class="nv">virtualHosts</span> <span class="o">=</span> <span class="p">{</span>
      <span class="s2">"wasabi.example.com"</span> <span class="o">=</span> <span class="p">{</span>
        <span class="nv">enableACME</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
        <span class="nv">forceSSL</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
        <span class="nv">locations</span><span class="o">.</span><span class="s2">"/"</span><span class="o">.</span><span class="nv">proxyPass</span> <span class="o">=</span> <span class="s2">"http://192.168.100.11:80"</span><span class="p">;</span>
      <span class="p">};</span>
      <span class="s2">"samabal.example.com"</span> <span class="o">=</span> <span class="p">{</span>
        <span class="nv">enableACME</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
        <span class="nv">forceSSL</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
        <span class="nv">locations</span><span class="o">.</span><span class="s2">"/"</span><span class="o">.</span><span class="nv">proxyPass</span> <span class="o">=</span> <span class="s2">"http://192.168.100.22:80"</span><span class="p">;</span>
      <span class="p">};</span>
      <span class="s2">"tabasco.example.com"</span> <span class="o">=</span> <span class="p">{</span>
        <span class="nv">enableACME</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
        <span class="nv">forceSSL</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
        <span class="nv">locations</span><span class="o">.</span><span class="s2">"/"</span><span class="o">.</span><span class="nv">proxyPass</span> <span class="o">=</span> <span class="s2">"http://192.168.100.33:80"</span><span class="p">;</span>
      <span class="p">};</span>
    <span class="p">};</span>
  <span class="p">};</span>
</code></pre></div></div> <p>Tip: you might want to put the IP addresses in variables.</p> <h3 id="real-port-forwarding">Real Port Forwarding</h3> <p>If you only have one HTTP host or if the solution above does not work for you, you can use real port forwarding. The example below forwards port 22 on the container to port 2222 on the host, and forwards port 80 on the container to 8080 on the host. The ports should be opened by both the container’s firewall and the hosts’ firewall.</p> <div class="language-nix highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="nv">containers</span><span class="o">.</span><span class="nv">wasabi</span><span class="o">.</span><span class="nv">forwardPorts</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">{</span>
      <span class="nv">containerPort</span> <span class="o">=</span> <span class="mi">22</span><span class="p">;</span>
      <span class="nv">hostPort</span> <span class="o">=</span> <span class="mi">2222</span><span class="p">;</span>
      <span class="nv">protocol</span> <span class="o">=</span> <span class="s2">"tcp"</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">{</span>
      <span class="nv">containerPort</span> <span class="o">=</span> <span class="mi">80</span><span class="p">;</span>
      <span class="nv">hostPort</span> <span class="o">=</span> <span class="mi">8080</span><span class="p">;</span>
      <span class="nv">protocol</span> <span class="o">=</span> <span class="s2">"tcp"</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">];</span>
</code></pre></div></div> <p>Notes:</p> <ul> <li>Unfortunately, IPv6 forwarding is not supported (<a href="https://github.com/systemd/systemd/issues/6106" rel="noopener noreferrer" target="_blank">issue</a>) yet.</li> <li>The loopback interface is explicitly excluded when forwarding ports. This means that we cannot <code class="language-plaintext highlighter-rouge">curl localhost:8080</code> on the host but other devices on the network can <code class="language-plaintext highlighter-rouge">curl myIP:8080</code>.</li> </ul> <h2 id="underpinnings">Underpinnings</h2> <p>NixOS containers are based on <strong>systemd-nspawn</strong>, a fancy chroot in the systemd-container program.</p> <p>If you run into trouble, it might be interesting to check out the man pages of the project <a href="https://manpages.ubuntu.com/manpages/latest/en/man1/systemd-nspawn.1.html" rel="noopener noreferrer" target="_blank">systemd-nspawn (1)</a> and <a href="https://manpages.ubuntu.com/manpages/latest/en/man5/systemd.nspawn.5.html" rel="noopener noreferrer" target="_blank">systemd-nspawn (5)</a> and ofcourse the <a href="https://wiki.archlinux.org/index.php/Systemd-nspawn" rel="noopener noreferrer" target="_blank">systemd-nspawn</a> page on ArchWiki.</p> <h2 id="security">Security</h2> <p>A quick online search for “systemd-nspawn security” will tell you that it is “not secure”. By default, NixOS containers are “privileged containers”, these are containers where the user id zero inside the container has the same meaning outside the container. With some tricks, the root user inside the container can escape the container. (This issue also affects docker and the likes).</p> <p>There are two ways around this: 1) don’t run vulnerable programs in your container as root, 2) make the container unprivileged. Option 1) will probably work for you, but if not, I’ll briefly show you what option 2) entails.</p> <h3 id="unprivileged-containers">Unprivileged containers</h3> <p>Luckily there is a dim ray of hope: We can drop the privileges of a container to a non-privileged user with nspawn’s <code class="language-plaintext highlighter-rouge">-U</code> option (set <code class="language-plaintext highlighter-rouge">containers.wasabi.extraFlags = [ "-U" ];</code>). This option ensures that the root user inside the container does not have UID <code class="language-plaintext highlighter-rouge">0</code> outside the container but rather something like <code class="language-plaintext highlighter-rouge">1815543862</code>. This works, but there are a lot of downsides to this regarding communication with the host and the outside world:</p> <ul> <li>You cannot listen on ports below 1024 in the container, not even as root (but we can easily tell httpd to listen on 8080)</li> <li><code class="language-plaintext highlighter-rouge">bindMounts</code> break because there is no way to change the permissions of the mount to the right thing, because root in the container is not allowed to alter the permissions.</li> <li><code class="language-plaintext highlighter-rouge">nixos-container root-login</code> is not compatible with these kinds of permissions</li> </ul> <p>But if you are OK with that, you should be fine.</p> <p><em>Note:</em> if you find a nice way to fix some of these problems, let me know, or even better open a PR adding a <code class="language-plaintext highlighter-rouge">privileged</code> option to the containers in <a href="https://github.com/NixOS/nixpkgs" rel="noopener noreferrer" target="_blank">nixpkgs</a>.</p> <h3 id="stripping-capabilities">Stripping capabilities</h3> <p>Another way to reduce the capabilities of a container is by using <code class="language-plaintext highlighter-rouge">containers.wasabi.dropCapabilities</code> to remove some capabilities assigned to the container by default. A list of capabilities can be found in the <a href="https://manpages.ubuntu.com/manpages/latest/en/man7/capabilities.7.html" rel="noopener noreferrer" target="_blank">capabilities (7) manpage</a>, the capabilities assigned by default can be found in the “security options” section of the <a href="https://manpages.ubuntu.com/manpages/latest/en/man1/systemd-nspawn.1.html" rel="noopener noreferrer" target="_blank">systemd-nspawn (1) </a>. This section also holds more tricks to be added with <code class="language-plaintext highlighter-rouge">containers.wasabi.extraFlags</code>.</p> <h2 id="sources">Sources</h2> <ul> <li><a href="https://people.kernel.org/brauner/runtimes-and-the-curse-of-the-privileged-container" rel="noopener noreferrer" target="_blank">Runtimes And the Curse of the Privileged Container by Christian Brauner, June 18, 2019</a>: An excellent read on container security</li> <li><a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/nixos-containers.nix" rel="noopener noreferrer" target="_blank">The NixOS containers module implementaion</a></li> <li><a href="https://wiki.archlinux.org/index.php/Systemd-nspawn" rel="noopener noreferrer" target="_blank">systemd-nspawn on ArchWiki</a></li> <li>A lot of manpages</li> </ul>]]></content><author><name></name></author><category term="linux"/><category term="NixOS"/><category term="provisioning"/><summary type="html"><![CDATA[Everything you need to know about declarative containers in NixOS with a simple example to demonstrate logging in, mounting volumes and forwarding ports.]]></summary></entry><entry><title type="html">A reMarkable self healing reverse shell</title><link href="https://blog.beardhatcode.be/2020/12/A-reMarkable-reverse-shell.html" rel="alternate" type="text/html" title="A reMarkable self healing reverse shell"/><published>2020-12-24T11:19:31+00:00</published><updated>2020-12-24T11:19:31+00:00</updated><id>https://blog.beardhatcode.be/2020/12/A-reMarkable-reverse-shell</id><content type="html" xml:base="https://blog.beardhatcode.be/2020/12/A-reMarkable-reverse-shell.html"><![CDATA[<p>You might have seen the <a href="https://blog.stigok.com/2018/04/22/self-healing-reverse-ssh-systemd-service.html" rel="noopener noreferrer" target="_blank">self healing reverse SSH setup with systemd</a> that helps you get easy SSH access to devices that are behind complicated NAT systems (or in the hands on non-technical people you support). This can also come in quite handy when you have a <a href="https://en.wikipedia.org/wiki/ReMarkable" rel="noopener noreferrer" target="_blank">reMarkable tablet</a>. Since you can SSH into it with root access, we can also map our SSH port onto another server. The systemd unit is shown below:</p> <div class="language-systemd highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">[Unit]</span>
<span class="nt">Description</span><span class="p">=</span>Reverse SSH connection
<span class="nt">After</span><span class="p">=</span>network.target

<span class="k">[Service]</span>
<span class="nt">Type</span><span class="p">=</span>simple
<span class="nt">ExecStart</span><span class="p">=</span>/usr/bin/ssh -i /home/root/.ssh/id_rsa -g -N -T -o "ExitOnForwardFailure yes" -R 22221:localhost:22  hole@YOURSERVER.TLD
<span class="nt">Restart</span><span class="p">=</span>always
<span class="nt">RestartSec</span><span class="p">=</span>30s

<span class="k">[Install]</span>
<span class="nt">WantedBy</span><span class="p">=</span>default.target
</code></pre></div></div> <p>Let’s pull that apart. The Unit part described when the unit should be run and its description. We need a network connection to SSH, so we run after we have that.</p> <p>But the interesting part is the <code class="language-plaintext highlighter-rouge">[Service]</code>, it diverges lightly from the version in the article I stole the idea from, this is because the SSH server on the remarkable is not OpenSSH but <a href="https://matt.ucc.asn.au/dropbear/dropbear.html" rel="noopener noreferrer" target="_blank">Dropbear</a>. This SSH server is much smaller, ideal for embedded devices but it also has fewer functionalities: no <code class="language-plaintext highlighter-rouge">ServerAliveInterval</code> and no extra verbose mode. The argument we give tho ssh are:</p> <ul> <li><code class="language-plaintext highlighter-rouge">-i /home/root/.ssh/id_rsa</code> specifying the identity file the reMarkable uses to identify itself to the remote server,</li> <li><code class="language-plaintext highlighter-rouge">-g</code> permits the server the reMarkable is connecting to initiate connections back to the reMarkable,</li> <li><code class="language-plaintext highlighter-rouge">-N -T</code> do not run a remote command and don’t even allocate a pseudo terminal (we don’t need that),</li> <li><code class="language-plaintext highlighter-rouge">-o "ExitOnForwardFailure yes"</code> adds an option to the ssh connection to fail and exit if it was not able to establish the port forward.</li> <li><code class="language-plaintext highlighter-rouge">-R 22221:localhost:22</code> does the magic connecting port 22221 on the remote machine with port 22 on the reMarkable.</li> <li><code class="language-plaintext highlighter-rouge">hole@YOURSERVER.TLD</code> the final argument specifies what host and username to connect to, here we connect to <code class="language-plaintext highlighter-rouge">YOURSERVER.TLD</code> as user <code class="language-plaintext highlighter-rouge">hole</code>.</li> </ul> <h2 id="making-this-secure">Making this secure</h2> <p>An important security principle is that of the minimal privilege, the remarkable should only be allowed to open a specific port on our server and nothing else. To do this we will put restrictions on the what is allowed with the reMarkable provides.</p> <h3 id="creating-a-ssh-key-on-the-remarkable">Creating a SSH key on the reMarkable</h3> <p>Before we can set restrictions on a key, we need to create it. Because there is no openSSH on the reMarkable but dropbear, we need to use its key generator to make a key in <code class="language-plaintext highlighter-rouge">/home/root/.ssh/id_rsa</code>. The second line prints the public part of the key.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dropbearkey <span class="nt">-f</span> ./.ssh/id_rsa <span class="nt">-t</span> rsa <span class="nt">-s</span> 2048
dropbearkey <span class="nt">-f</span> ./.ssh/id_rsa <span class="nt">-y</span>
</code></pre></div></div> <h3 id="making-a-dedicated-hole-user-for-port-forwarding-on-the-server">Making a dedicated <code class="language-plaintext highlighter-rouge">hole</code> user for port forwarding on the server</h3> <p>The remarkable only needs to open a port, and it should not be able to authenticate as one of the actual users on the server. So we create a hole user on the server that will only be used to manage forwarded ports. This user should be created as a system user without a login shell, but with a home directory:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>useradd <span class="nt">--system</span> <span class="nt">--create-home</span> <span class="nt">--shell</span> /usr/bin/nologin hole
</code></pre></div></div> <p>Now in the home directory of this user <code class="language-plaintext highlighter-rouge">/home/hole</code> we will need to make an autorised keys file <code class="language-plaintext highlighter-rouge">/home/perforation/.ssh/authorized_keys</code> with the following contents:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>restrict,port-forwarding,permitopen="localhost:22221" ssh-rsa BCDAD5PscK...WgTp root@reMarkable
</code></pre></div></div> <p>Where <code class="language-plaintext highlighter-rouge">BCDAD5PscK...WgTp</code> is replaced with the public key of remarkable. This file ensures that any connection authenticating with the given key will only be able to use portforwarding to listen on port 22221.</p> <h2 id="making-it-convenient">Making it convenient</h2> <p>With all this set up we can connect to our remarkable with a jump host. To make this more simple we can add this to our ssh config (<code class="language-plaintext highlighter-rouge">~/.ssh/config</code>).</p> <div class="language-ssh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Host</span> remarkableTun
    <span class="k">Hostname</span> localhost
    <span class="k">ProxyJump</span> jumphost
    <span class="k">Port</span> <span class="m">22221</span>
    <span class="k">User</span> root

<span class="k">Host</span> jumphost
    <span class="k">Hostname</span> YOURSERVER.TLD
    <span class="k">User</span> user
</code></pre></div></div> <p>This configuration allows us to connect to the reMarkable with:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh remarkableTun
</code></pre></div></div> <h2 id="extra-tips-and-tricks">Extra tips and tricks</h2> <h3 id="getting-the-correct-ip">Getting the correct IP</h3> <p>Sending files to the remarkable can be slow over this SSH tunnel certainly if the server is not on the same network. We can use the following command to find out programmatically what IP address is assigned to the reMarkable. Then we can connect to it directly over the local network. Of course, this does not work if the remarkable is on a different network or a network that drops ssh packets on the local network.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh remarkableTun <span class="nt">--</span> /sbin/ip addr | <span class="nb">awk</span> <span class="nt">-F</span> <span class="s1">' '</span> <span class="s1">'$1 == "inet" &amp;&amp; $7 == "wlan0" { print $2 }'</span>
</code></pre></div></div> <h3 id="alternative-ports">Alternative ports</h3> <p>If f your ssh server does not run on port <code class="language-plaintext highlighter-rouge">22</code> add <code class="language-plaintext highlighter-rouge">-p PORTNUMBER</code> to the end of the <code class="language-plaintext highlighter-rouge">ExecStart</code></p> <h3 id="the-execstart-command-to-use-when-on-openssh">The <code class="language-plaintext highlighter-rouge">ExecStart</code> command to use when on OpenSSH</h3> <p>I just put this here for archival purposes if <a href="https://blog.stigok.com/2018/04/22/self-healing-reverse-ssh-systemd-service.html" rel="noopener noreferrer" target="_blank">site I learned this from</a> goes down.</p> <div class="language-systemd highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">ExecStart</span><span class="p">=</span>/usr/bin/ssh -vvv -g -N -T -o "ServerAliveInterval 10" -o "ExitOnForwardFailure yes" -R 22221:localhost:22  hole@YOURSERVER.TLD
</code></pre></div></div>]]></content><author><name></name></author><category term="linux"/><category term="shell"/><category term="reMarkable"/><category term="reMarkable"/><category term="ssh"/><summary type="html"><![CDATA[You might have seen the self healing reverse SSH setup with systemd that helps you get easy SSH access to devices that are behind complicated NAT systems (or in the hands on non-technical people you support). This can also come in quite handy when you have a reMarkable tablet. Since you can SSH into it with root access, we can also map our SSH port onto another server. The systemd unit is shown below:]]></summary></entry><entry><title type="html">Better hunk headers for markdown in `git`</title><link href="https://blog.beardhatcode.be/2020/03/markdown-git-hunk-header.html" rel="alternate" type="text/html" title="Better hunk headers for markdown in `git`"/><published>2020-03-06T17:14:00+00:00</published><updated>2020-03-06T17:14:00+00:00</updated><id>https://blog.beardhatcode.be/2020/03/markdown-git-hunk-header</id><content type="html" xml:base="https://blog.beardhatcode.be/2020/03/markdown-git-hunk-header.html"><![CDATA[<p>When you make many changes throughout a file, <code class="language-plaintext highlighter-rouge">git</code> will group them in, so called, “hunks”. Typically, the changes of a single hunk will all occur within a single function. For C-like files git is intelligent enough to add a line at the top of the hunk (after <code class="language-plaintext highlighter-rouge">@@...@@</code>) that shows you the name of the function. It finds out the name of the function with a regex defined for the type of the edited file. There are many predefined regexes (even for LaTeX) in git. Unfortunately there is no predefined regex for markdown files.</p> <p>Luckily, you can define your own regexes to be placed at the top of a “hunk” by defining a <code class="language-plaintext highlighter-rouge">xfuncname</code> for the file type. The code snippet below show you how you can make likes starting with <code class="language-plaintext highlighter-rouge">#</code> (headers in markdown) become the header of the hunk, if the file is of type “md” for diffing according to git.</p> <div class="language-config highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[<span class="n">diff</span> <span class="s2">"md"</span>]
    <span class="n">xfuncname</span>=<span class="s2">"^#.*"</span>
</code></pre></div></div> <p>You can put this in your <code class="language-plaintext highlighter-rouge">~/.gitconfig</code> if you want it defined in all your repos, or you can specify it for one repo only in <code class="language-plaintext highlighter-rouge">$repo/.git/config</code>.</p> <p>To let git know that files ending in <code class="language-plaintext highlighter-rouge">.md</code> are of diffing type “md” the following line should be added to your <code class="language-plaintext highlighter-rouge">$repo/.gitattributes</code>. If you don’t want to share this setting, put it in <code class="language-plaintext highlighter-rouge">$repo/.git/info/attributes</code>. Put it in <code class="language-plaintext highlighter-rouge">$XDG_CONFIG_HOME/git/attributes</code> (probably <code class="language-plaintext highlighter-rouge">~/.config/git/attributes</code>) if you want it in all your repos.</p> <div class="language-config highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*.<span class="n">md</span>  <span class="n">diff</span>=<span class="n">md</span>
</code></pre></div></div> <p>Learn more about this in the <a href="https://git-scm.com/docs/gitattributes#_defining_a_custom_hunk_header" rel="noopener noreferrer" target="_blank">gitattribute documentation page (<code class="language-plaintext highlighter-rouge">man gitattributes</code>)</a>.</p> <h2 id="example-result">Example result</h2> <p>What was</p> <div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
<span class="p">@@ -274,7 +231,7 @@</span> this is some example prose text not much interesting here
<span class="p">except this line git shows you for context, but where is it located? Well,`git`
</span><span class="gi">+shows the name of the section after the `@@`, because it understands markdown.
</span><span class="gd">-does not understand how markdown works, so it's not very helpfull.
</span></code></pre></div></div> <p>now becomes:</p> <div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
<span class="p">@@ -274,7 +231,7 @@</span> ## Getting `git` to understand markdown
<span class="p">except this line git shows you for context, but where is it located? Well,`git`
</span><span class="gi">+shows the name of the section after the `@@`, because it understands markdown.
</span><span class="gd">-does not understand how markdown works, so it's not very helpfull.
</span></code></pre></div></div> <h2 id="bonus">Bonus</h2> <p>Want to see the whole function/section that was edited using git? Use <code class="language-plaintext highlighter-rouge">git diff --function-context</code> or more cryptic:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git diff -W
</code></pre></div></div>]]></content><author><name></name></author><category term="linux"/><category term="shell"/><category term="git"/><category term="markdown"/><category term="pandoc"/><category term="man"/><category term="tricks"/><summary type="html"><![CDATA[When you make many changes throughout a file, git will group them in, so called, “hunks”. Typically, the changes of a single hunk will all occur within a single function. For C-like files git is intelligent enough to add a line at the top of the hunk (after @@...@@) that shows you the name of the function. It finds out the name of the function with a regex defined for the type of the edited file. There are many predefined regexes (even for LaTeX) in git. Unfortunately there is no predefined regex for markdown files.]]></summary></entry><entry><title type="html">Reading markdown like a `man`</title><link href="https://blog.beardhatcode.be/2020/01/reading-markdown-like-a-man.html" rel="alternate" type="text/html" title="Reading markdown like a `man`"/><published>2020-01-13T20:33:08+00:00</published><updated>2020-01-13T20:33:08+00:00</updated><id>https://blog.beardhatcode.be/2020/01/reading-markdown-like-a-man</id><content type="html" xml:base="https://blog.beardhatcode.be/2020/01/reading-markdown-like-a-man.html"><![CDATA[<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh</span>
<span class="nv">file</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">1</span><span class="k">:-</span><span class="nv">README</span><span class="p">.md</span><span class="k">}</span><span class="s2">"</span><span class="p">;</span>

<span class="k">if</span> <span class="o">[</span> <span class="nt">-f</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
  </span>pandoc <span class="nt">-s</span> <span class="nt">-M</span> <span class="nv">header</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span><span class="nb">basename</span> <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span> <span class="nt">-f</span> gfm <span class="nt">-t</span> man <span class="s2">"</span><span class="nv">$file</span><span class="s2">"</span> | man <span class="nt">-l</span> -
<span class="k">else
  </span><span class="nb">echo</span> <span class="s2">"File could not be found."</span>
<span class="k">fi</span>
</code></pre></div></div> <p data-download="filename">The code above transforms a markdown file into a <a href="https://en.wikipedia.org/wiki/Man_page" rel="noopener noreferrer" target="_blank">manpage</a> for easy reading in the terminal. Although markdown in itself is already readable in its pure raw format, this makes it even nicer.</p> <p>As you can see <a href="https://pandoc.org/" rel="noopener noreferrer" target="_blank">Pandoc</a> is doing all the work here, it is the tool converting the markdown into a manpage. Let’s go over the basic flags we gave it:</p> <ul> <li><code class="language-plaintext highlighter-rouge">-s</code> asks for a “standalone” document,</li> <li><code class="language-plaintext highlighter-rouge">-f gfm</code> tells Pandoc we want to convert from Github flavoured markdown (gfm) and</li> <li><code class="language-plaintext highlighter-rouge">-t man</code> indicated that we want to get out a manpage.</li> </ul> <p>There is one flag we did not discuss yet: <code class="language-plaintext highlighter-rouge">-M header=...</code>. This flag sets the value of the <a href="https://pandoc.org/MANUAL.html#option--metadata" rel="noopener noreferrer" target="_blank">metadata field</a> <code class="language-plaintext highlighter-rouge">header</code> to the filename of the file we are looking at. If we look at <a href="https://github.com/jgm/pandoc-templates/blob/master/default.man" rel="noopener noreferrer" target="_blank">Pandocs default template for manpages</a>, we see that the metadata field <code class="language-plaintext highlighter-rouge">$header</code> is used in the line starting with <code class="language-plaintext highlighter-rouge">.TH</code>.</p> <div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mf">.</span><span class="no">TH</span> <span class="s2">"</span><span class="nv">$title</span><span class="s2">/nowrap$"</span> <span class="s2">"</span><span class="nv">$section</span><span class="s2">/nowrap$"</span> <span class="s2">"</span><span class="nv">$date</span><span class="s2">/nowrap$"</span> <span class="s2">"</span><span class="nv">$footer</span><span class="s2">/nowrap$"</span> <span class="s2">"</span><span class="nv">$header</span><span class="s2">/nowrap$"</span>
</code></pre></div></div> <p>From the man page about the format of manpages (<code class="language-plaintext highlighter-rouge">man man-pages 7</code>) we learn that <code class="language-plaintext highlighter-rouge">.TH</code> can indeed take 5 arguments, namely:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.TH title section date source manual
</code></pre></div></div> <p>By setting the headers we are in fact setting the name of the manual shown. This name is shown at the top centre of the manpage. For the curious, the following diagram shows where the other arguments end up.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>title(section)       manual      title(section)

                      ...

source               date        title(section)
</code></pre></div></div> <p>To complete the description of our script:</p> <ul> <li>To make <code class="language-plaintext highlighter-rouge">man</code> read from standard input we use the “local file” <code class="language-plaintext highlighter-rouge">-l</code> flag (see <code class="language-plaintext highlighter-rouge">man man</code>).</li> <li>To by default read <code class="language-plaintext highlighter-rouge">README.md</code> we use <code class="language-plaintext highlighter-rouge">${var:-default}</code> to set a default value if <code class="language-plaintext highlighter-rouge">$var</code> is not set.</li> <li>We use <code class="language-plaintext highlighter-rouge">if [ -f "$file" ]</code> to check if the file is a regular file before we try converting.</li> </ul> <p><em>Tip</em>: save this script as <code class="language-plaintext highlighter-rouge">mdread</code> in your <code class="language-plaintext highlighter-rouge">$PATH</code> and read markdown files with <code class="language-plaintext highlighter-rouge">mdread</code> in your terminal.</p> <p>This is how the output looks:</p> <pre style="font-family:'Fira Code',monospace;font-size:.5em;width:max-content;max-width: 100%;margin: 0 auto;color:#657b83;background-color:#fdf6e3;white-space: nowrap;padding:0;"><span style="color:#657b83;background-color:#fdf6e3;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iso, a val and a ref can be subtyped to a box or tag, but a val cannot become a ref
</span><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nor can a ref become a val, finally a box can become a tag]
<br />
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Apart &nbsp;from &nbsp;using generic functions, you can also use subtyping to just throw away
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;your capabilities:
<br />
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val myRefCar = consume myIsoCar
<br />
<br /><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">Receiver</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">reference</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">capabilities</span><span style="color:#657b83;background-color:#fdf6e3;">
</span><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reference capabilities are checked when you are trying to access the value &nbsp;or &nbsp;the
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fields &nbsp;of &nbsp;a variable. &nbsp;If you have an iso variable you can read any of its iso or
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val fields. &nbsp;All other types of fields are read as a tag.
<br />
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;At first, that seems odd, you might be wondering "If I have an iso why can't I read
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;its &nbsp;ref &nbsp;field?" &nbsp;The &nbsp;reason is that an iso must maintain the property that it is
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isolated and that there is thus no other alias that can read or write to that memo‐
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ry. &nbsp;This includes its fields. &nbsp;If you were able to make an alias to one on the ref
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fields of an iso variable, you could still read from and write to the internals &nbsp;of
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the &nbsp;iso &nbsp;trough &nbsp;the alias of this ref field even if you passed the iso to another
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;actor. &nbsp;The same holds for trn and box fields. &nbsp;val Fields are &nbsp;fine &nbsp;because &nbsp;they
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;are immutable, and they are always safe to read.
<br />
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The following table summarizes the restrictions. &nbsp;The row indicates your capability
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;on an object, the column specifies the capability the &nbsp;object &nbsp;itself &nbsp;has &nbsp;on &nbsp;the
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filed you are trying to access. &nbsp;Because you can't read fields form a tag, that row
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;only contains "n/a".
<br />
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;▷ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iso field &nbsp;&nbsp;trn field &nbsp;&nbsp;ref field &nbsp;&nbsp;val field &nbsp;&nbsp;box field &nbsp;&nbsp;tag field
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;───────────────────────────────────────────────────────────────────────────────────
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">iso</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">origin</span><span style="color:#657b83;background-color:#fdf6e3;"> &nbsp;&nbsp;iso &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag
</span><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">trn</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">origin</span><span style="color:#657b83;background-color:#fdf6e3;"> &nbsp;&nbsp;iso &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trn &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;box &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;box &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag
</span><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">ref</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">origin</span><span style="color:#657b83;background-color:#fdf6e3;"> &nbsp;&nbsp;iso &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trn &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ref &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;box &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag
</span><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">val</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">origin</span><span style="color:#657b83;background-color:#fdf6e3;"> &nbsp;&nbsp;val &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag
</span><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">box</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">origin</span><span style="color:#657b83;background-color:#fdf6e3;"> &nbsp;&nbsp;tag &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;box &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;box &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;box &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tag
</span>
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">tag</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">origin</span><span style="color:#657b83;background-color:#fdf6e3;"> &nbsp;&nbsp;n/a &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n/a &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n/a &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n/a &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n/a &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n/a
</span><br />
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;When you are calling a method on an object, the &nbsp;restrictions &nbsp;from &nbsp;the &nbsp;call-site
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;still need to hold. &nbsp;You can't call the method setRefField(...) on an iso variable.
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;For this reason functions are annotated with a <span style="font-decoration:underline;color:#657b83;background-color:#fdf6e3;">receiver</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-decoration:underline;color:#657b83;background-color:#fdf6e3;">reference</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-decoration:underline;color:#657b83;background-color:#fdf6e3;">capability</span><span style="color:#657b83;background-color:#fdf6e3;">. &nbsp;&nbsp;You
</span><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;can &nbsp;only &nbsp;call &nbsp;a &nbsp;method that is compatible with your capabilities on the object.
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The default receiver reference capability of a method is box.
<br />
<br /><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">Refcap</span><span style="color:#657b83;background-color:#fdf6e3;"> </span><span style="font-weight:bold;color:#586e75;background-color:#fdf6e3;">recap</span><span style="color:#657b83;background-color:#fdf6e3;">
</span><br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reference capabilities guard the amount of references there are to a certain &nbsp;piece
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of memory.
<br />
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A &nbsp;variable is a pointer to an object. &nbsp;Or to be more precise a variable references
<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a capability. &nbsp;When creating a variable, you need to assign a reference &nbsp;capability
<br /><span style="color:#fdf6e3;background-color:#657b83;"> Manual page (stdin) line 293 (press h for help or q to quit)</span></pre>]]></content><author><name></name></author><category term="linux"/><category term="shell"/><category term="markdown"/><category term="pandoc"/><category term="man"/><category term="tricks"/><summary type="html"><![CDATA[A command line tool to read Markdown files in the Linux manual reader.]]></summary></entry><entry><title type="html">Pony capabilities</title><link href="https://blog.beardhatcode.be/2018/10/pony-capabilities.html" rel="alternate" type="text/html" title="Pony capabilities"/><published>2018-10-16T10:43:53+00:00</published><updated>2018-10-16T10:43:53+00:00</updated><id>https://blog.beardhatcode.be/2018/10/pony-capabilities</id><content type="html" xml:base="https://blog.beardhatcode.be/2018/10/pony-capabilities.html"><![CDATA[<style scoped="">dl{counter-reset:item1}dt:before{counter-increment:item1;content:counter(item1) ". "}dt{font-weight:bold}dd{margin-left:2em}table{padding:1em;margin:1em auto;border-collapse:collapse}td,th{border:1px solid #eee;padding:.5em;text-align:center}</style> <p><a href="http://ponylang.io/" rel="noopener noreferrer" target="_blank">Pony</a> is a programming language that allows concurrent programming using actors. The language features an intelligent type system that prevents data-races trough a system called “capabilities”. In this blog post I will attempt to explain them.</p> <p>Let’s start with the definition of a capability in pony:</p> <blockquote> <p>A capability is an unforgeable token that</p> <ol> <li>designates an object and</li> <li>gives the program the authority to perform a specific set of actions on that object.</li> </ol> </blockquote> <p>In other words with a capability you can do <em>anything</em> with the object. You can think of the capability as being the object itself.</p> <p>So how do capabilities help us with concurrency problems? Well, they don’t, at least not on their own. The thing that makes capabilities useful is limiting how they are used. In Pony, the type system limits on how you can use these unforgeable tokens. When working with <a href="https://en.wikipedia.org/wiki/Actor_model" rel="noopener noreferrer" target="_blank">actor based concurrency</a>, these limitations allow us to make some useful guarantees.</p> <h1 id="references">References</h1> <p>The objects that are created in pony are stored in a space that is accessible by all actors. An actor can only change an object trough a reference to the objects’ capability. When an object is created, a reference to the capability of the newly created object is returned.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">val</span> <span class="n">a</span> <span class="o">:</span> <span class="nc">Object</span> <span class="o">=</span> <span class="nc">Object</span><span class="p">.</span><span class="n">create</span><span class="p">()</span>
</code></pre></div></div> <p>After executing the above, <code class="language-plaintext highlighter-rouge">a</code> holds a <em>reference</em> to the newly created object. In pony references allow the holder one of the following functionalities:</p> <ul> <li><code class="language-plaintext highlighter-rouge">M</code>: If the reference points to an actor, the reference can be used to send messages to it</li> <li><code class="language-plaintext highlighter-rouge">RM</code>: The referenced object can be read, and messages can be sent</li> <li><code class="language-plaintext highlighter-rouge">RWM</code>: The referenced object can be read form, written to, and messages can be sent</li> </ul> <h1 id="aliases">Aliases</h1> <p>Let’s look at what happens if we clone a reference:</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">val</span> <span class="n">b</span> <span class="o">:</span> <span class="nc">Object</span> <span class="o">=</span> <span class="n">a</span>
</code></pre></div></div> <p>Now <code class="language-plaintext highlighter-rouge">b</code> references the same object that <code class="language-plaintext highlighter-rouge">a</code> was pointing to. We say that <code class="language-plaintext highlighter-rouge">a</code> and <code class="language-plaintext highlighter-rouge">b</code> are <em>aliases</em>, they reference the same object. Aliases can cause problems during parallel computation. Race conditions can occur when aliases live on different actors. Consider the following example:</p> <blockquote> <p>Actors <code class="language-plaintext highlighter-rouge">A</code> and <code class="language-plaintext highlighter-rouge">B</code> are counting the number of ponies on a farm. Both actors work on a different field, and increment a counter each time a pony is found. The example below shows what happens when both actors find a pony at the same moment, and increment the count by looking at what the current value of the counter is, adding one and storing it. The result is wrong.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>actor A           a,b          actor B
   |               0            |
a' = a (0)         0         b' = b (0)            Both read 0 as counter value
   |               1          b = b' + 1 (2)       B overwrites content with 1
 a = a' + 1        1            |                  A overwrites content with 1
   |               1            |                  The count is 1 (not 2)
</code></pre></div> </div> </blockquote> <h2 id="when-aliases-are-created">When aliases are created</h2> <p>Apart from doing, <code class="language-plaintext highlighter-rouge">b = a</code>, aliases are also created for every parameter in a function call, and for the <code class="language-plaintext highlighter-rouge">this</code> in every method call.</p> <p>So,</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">object</span><span class="p">.</span><span class="n">f</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">,</span><span class="n">c</span><span class="p">)</span>
</code></pre></div></div> <p>Creates an alias for <code class="language-plaintext highlighter-rouge">object</code>, <code class="language-plaintext highlighter-rouge">a</code>, <code class="language-plaintext highlighter-rouge">b</code> and <code class="language-plaintext highlighter-rouge">c</code>.</p> <h2 id="managing-aliases">Managing aliases</h2> <p>As we will see, ponies type system strongly relies on counting the number of aliases of a certain kind. For this reason it will come in handy to be able to move a capability over to another variable, without aliasing it. There are two ways to move a capability.</p> <ol> <li> <p><em>Destructive read</em>: In pony the result of value of the expression <code class="language-plaintext highlighter-rouge">a = b</code> is the old value of <code class="language-plaintext highlighter-rouge">a</code>. By doing the following, the number of aliases to the location <code class="language-plaintext highlighter-rouge">b</code> points to in the beginning remains unchanged.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="n">b</span> <span class="o">=</span> <span class="p">...</span>
</code></pre></div> </div> <p><code class="language-plaintext highlighter-rouge">a</code> now refers to what <code class="language-plaintext highlighter-rouge">b</code> used to refer to, and <code class="language-plaintext highlighter-rouge">b</code> refers to whatever the result of <code class="language-plaintext highlighter-rouge">...</code> is.</p> </li> <li> <p><em>Consuming</em> the variable: This takes the value out of the variable you gave it. The given variable is now empty (think of it as <code class="language-plaintext highlighter-rouge">null</code>). The type checker will prevent you form using a consumed variable.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">consume</span> <span class="n">b</span>
</code></pre></div> </div> <p>This is effectively the same as the following destructive read (which is not valid pony code):</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>b = null
</code></pre></div> </div> </li> </ol> <h1 id="reference-capabilities">Reference capabilities</h1> <h2 id="tag">Tag</h2> <p>To avoid concurrency problems, we could simply say that it is forbidden to read or write trough a reference. This is what the <code class="language-plaintext highlighter-rouge">tag</code> reference capability does. You are allowed to make as many aliases of a tag as you like, you can store them and you can compare two <code class="language-plaintext highlighter-rouge">tag</code> variables for identity.</p> <p>Aliases of a <code class="language-plaintext highlighter-rouge">tag</code> can safely live on different actors as they cannot be read form or written to. The only thing you can do is send messages to it (if is an actor). These messages will then be handled sequentially by the actor in the order in which they arrived.</p> <p><img src="/img/181016/drawing-tag.svg" alt="A tag" class="center"/></p> <h2 id="value">Value</h2> <p>In some cases you really only need to read the referred information. The only way that we can safely read data at the same location form multiple actors, is when we know the data is immutable. The main principle is:</p> <blockquote> <p>If I can read, no other actor can write.</p> </blockquote> <p>The <code class="language-plaintext highlighter-rouge">val</code> reference capability guarantees something even stronger, that <em>no</em> actor has write permissions. A <code class="language-plaintext highlighter-rouge">val</code> can only be used to read or to send messages, never to write.</p> <p>There may also exist <code class="language-plaintext highlighter-rouge">tag</code> (or <code class="language-plaintext highlighter-rouge">box</code>) aliases of a val, but that’s fine because they too don’t allow writing.</p> <p><img src="/img/181016/drawing-val.svg" alt="A val" class="center"/></p> <h2 id="isolate">Isolate</h2> <p>So, now that we know how to read safely, we want to write safely. Mutable data must reside on one actor (thread). There must not be a reference through witch data can be read by another actor. This is where the <code class="language-plaintext highlighter-rouge">iso</code> reference capability comes in. It stands for “Isolate”. An <code class="language-plaintext highlighter-rouge">iso</code> variable must not have any other alias (of any kind) to it, or to an internal part of it. It is isolated, only accessible form the outermost layer and exactly once.</p> <p><img src="/img/181016/drawing-iso.svg" alt="A val" class="center"/></p> <p>Let’s look at an example.</p> <p>If you have a <code class="language-plaintext highlighter-rouge">Car iso</code> reference capability that is stored in <code class="language-plaintext highlighter-rouge">car</code>, you cannot do the following:</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">weels</span> <span class="o">:</span> <span class="nc">Wheels</span> <span class="kd">iso</span> <span class="o">=</span> <span class="n">car</span><span class="p">.</span><span class="n">wheels</span>      <span class="err">#</span> <span class="nc">Won</span><span class="p">'</span><span class="n">t</span> <span class="n">work</span>
</code></pre></div></div> <p>Because if you could, there would be two aliases to the memory location of <code class="language-plaintext highlighter-rouge">car.wheels</code> (<code class="language-plaintext highlighter-rouge">wheels</code> and <code class="language-plaintext highlighter-rouge">car.wheels</code>).</p> <p>The benefit of these strong restrictions is that you know there is exactly one reference a piece of memory referred to by an <code class="language-plaintext highlighter-rouge">iso</code>. There are no aliases. if you give up your local alias you can pass it on to another actor. As you remember, giving up an alias can be done with <code class="language-plaintext highlighter-rouge">consume</code>. <code class="language-plaintext highlighter-rouge">consume car</code> is of type <code class="language-plaintext highlighter-rouge">Car iso^</code> , here the <code class="language-plaintext highlighter-rouge">^</code> modifier on the type indicates that there is no reference to the value. The reference is ephemeral (short-lived, it has no alias). When there is no alias it is safe to send it to another actor using a <code class="language-plaintext highlighter-rouge">give_automobile(Car iso car)</code> behaviour.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>otherActor.give_automobile(consume car)
</code></pre></div></div> <p>Now only <code class="language-plaintext highlighter-rouge">otherActor</code> has access to the car in memory. The original owner is no longer allowed to use <code class="language-plaintext highlighter-rouge">car</code> by the type checker.</p> <p>This is cool, by using an <code class="language-plaintext highlighter-rouge">iso</code> we ensure that there is only one reference to that piece of memory. No aliases are allowed. But an <code class="language-plaintext highlighter-rouge">iso</code> is very restrictive. As you recall form the previous section, it is very easy to create aliases. Using an <code class="language-plaintext highlighter-rouge">iso</code> as a argument to a function will not work without consuming the alias. If we don’t plan on sharing a reference, an <code class="language-plaintext highlighter-rouge">iso</code> is far to restrictive. This is where the <code class="language-plaintext highlighter-rouge">ref</code> reference capability comes in.</p> <h2 id="reference">Reference</h2> <p>The <code class="language-plaintext highlighter-rouge">ref</code> reference capability is the most permissive read-write capability. It permits as many aliases as you like as long as all the aliases with read and/or write capabilities are on the same actor. There may still be <code class="language-plaintext highlighter-rouge">tag</code> (no read, nor write) aliases on other actors. The principle is:</p> <blockquote> <p>If I can write, no other actor can read.</p> </blockquote> <p><img src="/img/181016/drawing-ref.svg" alt="A ref" class="center"/></p> <p>A reference with the <code class="language-plaintext highlighter-rouge">ref</code> reference capability is like the variables you are used to from for example Java. The only thing you can’t do with it is send it to an other actor. That is, a <code class="language-plaintext highlighter-rouge">ref</code> reference capability is not sendable. The sendable reference capabilities are <code class="language-plaintext highlighter-rouge">iso</code>, <code class="language-plaintext highlighter-rouge">val</code> and <code class="language-plaintext highlighter-rouge">tag</code> .</p> <h2 id="transition-and-box">Transition and box</h2> <p>A more flexible variant of the <code class="language-plaintext highlighter-rouge">iso</code> that allows reading and writing is the <code class="language-plaintext highlighter-rouge">trn</code> (transition). This reference capability is designed to create a read-only variable (a <code class="language-plaintext highlighter-rouge">val</code>). As opposed to the <code class="language-plaintext highlighter-rouge">iso</code> a <code class="language-plaintext highlighter-rouge">trn</code> may have read aliases. But these aliases must remain on the same actor. In other words, these aliases must not be sendable. Luckily the type system of pony has a reference capability that is just that: <code class="language-plaintext highlighter-rouge">box</code>.</p> <p><img src="/img/181016/drawing-box-trn.svg" alt="A val" class="center"/></p> <h2 id="summary">Summary</h2> <p>The following “<em>deny matrix</em>” summarizes the aliases that are forbidden for each of the reference capabilities. RW means read and write access, W means write access. The upper right corner is empty because it is not possible to deny more on your actor (local) than on other actors (global). On the diagonal, we find the sendable reference capabilities, they have the same restrictions local and globally.</p> <table class="tableHideEmpty" style="text-align:center; width:100%;"> <tbody><tr> <th></th> <th></th> <th colspan="3">other global aliases</th> </tr> <tr> <th></th> <th></th> <th>no RW</th> <th>no W</th> <th>all</th> </tr> <tr> <th rowspan="3">other<br/>local<br/>aliases</th> <th>no RW</th> <td><em>iso</em></td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <th>no W</th> <td>trn</td> <td><em><em>val</em></em></td><td>&nbsp;</td></tr><tr> <th>all</th> <td>ref</td> <td>box</td> <td><em><em>tag</em></em></td></tr><tr style="color: grey;"> <td>&nbsp;</td> <td>&nbsp;</td> <td>mutable</td> <td>immutable</td> <td>opaque</td> </tr></tbody></table> <h1 id="syntax">Syntax</h1> <p>So how do you assign a reference capability to a variable? Well, you add the name of the reference capability to the end of the type name:</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">val</span> <span class="n">myCar</span> <span class="o">:</span> <span class="nc">Car</span> <span class="kd">iso</span> <span class="o">=</span> <span class="p">...;</span>
<span class="kd">val</span> <span class="n">sharedPicture</span><span class="o">:</span> <span class="nc">Picture</span> <span class="kd">val</span> <span class="o">=</span> <span class="p">...;</span>
</code></pre></div></div> <p>Here <code class="language-plaintext highlighter-rouge">myCar</code> is an <code class="language-plaintext highlighter-rouge">iso</code> reference to a <code class="language-plaintext highlighter-rouge">Car</code> and <code class="language-plaintext highlighter-rouge">sharedPicture</code> is a <code class="language-plaintext highlighter-rouge">val</code> reference to a <code class="language-plaintext highlighter-rouge">Picture</code>.</p> <h2 id="default-capabilities">Default capabilities</h2> <p>Often the default reference capability of an object can be derived from the “meaning” of the class. Therefore, when you define a class you can specify a default reference capability:</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">class</span> <span class="kd">val</span> <span class="nc">Picture</span><span class="o">:</span>
  <span class="p">...</span>
</code></pre></div></div> <p>And then just use:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>val sharedPicture: Picture = ...;
</code></pre></div></div> <h2 id="capabilities-of-methods">Capabilities of methods</h2> <p>In a method you can make use of <code class="language-plaintext highlighter-rouge">this</code>, which refers to the current instance of the class. Remember that calling a method, an alias is created for <code class="language-plaintext highlighter-rouge">this</code>. By default, the reference capability for this is <code class="language-plaintext highlighter-rouge">ref</code>, but you can change it by adding a reference capability to your function definition:</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">class</span> <span class="kd">iso</span> <span class="nc">Car</span><span class="o">:</span>
  <span class="kr">fun</span> <span class="kd">ref</span> <span class="n">doIt</span><span class="p">()</span> <span class="o">=&gt;</span> <span class="p">...</span>
  <span class="kr">fun</span> <span class="kd">val</span> <span class="n">doThat</span><span class="p">()</span> <span class="o">=&gt;</span> <span class="p">...</span>

</code></pre></div></div> <h1 id="recovering-capabilities">Recovering capabilities</h1> <h2 id="recover-lifting-your-capabilities">Recover: Lifting your capabilities</h2> <p>You might have a <code class="language-plaintext highlighter-rouge">ref</code> and know that there is only one reference to it. You want to turn your <code class="language-plaintext highlighter-rouge">ref</code> into an <code class="language-plaintext highlighter-rouge">iso</code>. The type checker would not let you undertake this, unless you can prove everything is fine. The <code class="language-plaintext highlighter-rouge">recover</code>-expression is a mechanism to provide such a proof. Form within a recover expression you can access all sendable variables form the enclosing lexical scope (<code class="language-plaintext highlighter-rouge">iso</code>, <code class="language-plaintext highlighter-rouge">val</code> and <code class="language-plaintext highlighter-rouge">tag</code>). You can do complex things with it and get out an <code class="language-plaintext highlighter-rouge">iso</code> if your expression evaluated to any mutable reference capability.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>val thing : Thing iso = recover
  ... complex stuff ...
  aRefThing
end
</code></pre></div></div> <p>If your expression evaluates to an immutable, you can get out a <code class="language-plaintext highlighter-rouge">val</code>. And tags stay tags.</p> <p>So you can recover an</p> <ul> <li><code class="language-plaintext highlighter-rouge">iso</code> form <code class="language-plaintext highlighter-rouge">{iso,trn,ref}</code> (preserve mutability)</li> <li><code class="language-plaintext highlighter-rouge">val</code> form <code class="language-plaintext highlighter-rouge">{val,box}</code> (preseve immutability)</li> <li><code class="language-plaintext highlighter-rouge">tag</code> form <code class="language-plaintext highlighter-rouge">{tag}</code> (preserve opacity)</li> </ul> <h2 id="receiver-recovery">Receiver recovery</h2> <p>When you call a method, there is an alias to <code class="language-plaintext highlighter-rouge">this</code>. As a consequence, we should not be able to call non-<code class="language-plaintext highlighter-rouge">tag</code> functions on an <code class="language-plaintext highlighter-rouge">iso</code>. Unless we use what we just learned and write the following:</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">var</span> <span class="n">obj</span> <span class="o">:</span> <span class="nc">Object</span> <span class="kd">iso</span><span class="o">=</span> <span class="nc">Object</span>
<span class="kr">var</span> <span class="n">returnValue</span> <span class="o">:</span> <span class="nc">String</span> <span class="kd">val</span><span class="o">=</span> <span class="s">""</span>
<span class="n">obj</span> <span class="o">=</span> <span class="kr">recover</span>
        <span class="kd">val</span> <span class="n">refObj</span> <span class="o">:</span> <span class="nc">Object</span> <span class="kd">ref</span> <span class="o">=</span> <span class="kr">consume</span> <span class="n">obj</span>
        <span class="n">returnValue</span> <span class="o">=</span> <span class="n">refObj</span><span class="p">.</span><span class="n">toString</span><span class="p">()</span>
        <span class="n">refObj</span>
      <span class="kr">end</span>
</code></pre></div></div> <p>We consume our <code class="language-plaintext highlighter-rouge">iso</code> and make it into a <code class="language-plaintext highlighter-rouge">ref</code>, do what we want to do and recover our original object with the <code class="language-plaintext highlighter-rouge">iso</code> reference capability. Luckily we don’t need to do this as pony will do this for us automatically in a process called <em>Automatic receiver recovery</em>.</p> <h1 id="subtyping">Subtyping</h1> <p>There is a hierarchy to reference capabilities. If a function expects a <code class="language-plaintext highlighter-rouge">ref</code> you can give it an <code class="language-plaintext highlighter-rouge">iso</code> or a <code class="language-plaintext highlighter-rouge">trn</code> (if you consume it), after all you have write permissions. A <code class="language-plaintext highlighter-rouge">box</code> may have at most one writeable alias, a <code class="language-plaintext highlighter-rouge">val</code> may have none, therefore a function that expects a <code class="language-plaintext highlighter-rouge">box</code> will happily accept a <code class="language-plaintext highlighter-rouge">val</code>.</p> <p><img src="/img/181016-capabilities-subtyping.svg" alt="You can subtype an iso to anything, a trn can become anything except an iso, a val and a ref can be subtyped to a box or tag, but a val cannot become a ref nor can a ref become a val, finally a box can become a tag"/></p> <p>Apart from using generic functions, you can also use subtyping to just throw away your capabilities:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>val myRefCar = consume myIsoCar
</code></pre></div></div> <h1 id="receiver-reference-capabilities">Receiver reference capabilities</h1> <p>Reference capabilities are checked when you are trying to access the value or the fields of a variable. If you have an <code class="language-plaintext highlighter-rouge">iso</code> variable you can read any of its <code class="language-plaintext highlighter-rouge">iso</code> or <code class="language-plaintext highlighter-rouge">val</code> fields. All other types of fields are read as a <code class="language-plaintext highlighter-rouge">tag</code>.</p> <p>At first, that seems odd, you might be wondering “If I have an <code class="language-plaintext highlighter-rouge">iso</code> why can’t I read its <code class="language-plaintext highlighter-rouge">ref</code> field?” The reason is that an iso must maintain the property that it is isolated and that there is thus no other alias that can read or write to that memory. This includes its fields. If you were able to make an alias to one on the <code class="language-plaintext highlighter-rouge">ref</code> fields of an <code class="language-plaintext highlighter-rouge">iso</code> variable, you could still read from and write to the internals of the <code class="language-plaintext highlighter-rouge">iso</code> trough the alias of this <code class="language-plaintext highlighter-rouge">ref</code> field even if you passed the <code class="language-plaintext highlighter-rouge">iso</code> to another actor. The same holds for <code class="language-plaintext highlighter-rouge">trn</code> and <code class="language-plaintext highlighter-rouge">box</code> fields. <code class="language-plaintext highlighter-rouge">val</code> Fields are fine because they are immutable, and they are always safe to read.</p> <p>The following table summarizes the restrictions. The row indicates your capability on an object, the column specifies the capability the object itself has on the filed you are trying to access. Because you can’t read fields form a tag, that row only contains “n/a”.</p> <table> <thead> <tr> <th>▷</th> <th>iso field</th> <th>trn field</th> <th>ref field</th> <th>val field</th> <th>box field</th> <th>tag field</th> </tr> </thead> <tbody> <tr> <td><strong>iso origin</strong></td> <td>iso</td> <td>tag</td> <td>tag</td> <td>val</td> <td>tag</td> <td>tag</td> </tr> <tr> <td><strong>trn origin</strong></td> <td>iso</td> <td>trn</td> <td>box</td> <td>val</td> <td>box</td> <td>tag</td> </tr> <tr> <td><strong>ref origin</strong></td> <td>iso</td> <td>trn</td> <td>ref</td> <td>val</td> <td>box</td> <td>tag</td> </tr> <tr> <td><strong>val origin</strong></td> <td>val</td> <td>val</td> <td>val</td> <td>val</td> <td>val</td> <td>tag</td> </tr> <tr> <td><strong>box origin</strong></td> <td>tag</td> <td>box</td> <td>box</td> <td>val</td> <td>box</td> <td>tag</td> </tr> <tr> <td><strong>tag origin</strong></td> <td>n/a</td> <td>n/a</td> <td>n/a</td> <td>n/a</td> <td>n/a</td> <td>n/a</td> </tr> </tbody> </table> <p>When you are calling a method on an object, the restrictions from the call-site still need to hold. You can’t call the method <code class="language-plaintext highlighter-rouge">setRefField(...)</code> on an <code class="language-plaintext highlighter-rouge">iso</code> variable. For this reason functions are annotated with a <em>receiver reference capability</em>. You can only call a method that is compatible with your capabilities on the object. The default receiver reference capability of a method is <code class="language-plaintext highlighter-rouge">box</code>.</p> <h1 id="refcap-recap">Refcap recap</h1> <p>Reference capabilities guard the amount of references there are to a certain piece of memory.</p> <p>A variable is a pointer to an object. Or to be more precise a variable references a capability. When creating a variable, you need to assign a reference capability to it. One of <code class="language-plaintext highlighter-rouge">iso</code>, <code class="language-plaintext highlighter-rouge">trn</code>, <code class="language-plaintext highlighter-rouge">var</code>, <code class="language-plaintext highlighter-rouge">ref</code>, <code class="language-plaintext highlighter-rouge">box</code> or <code class="language-plaintext highlighter-rouge">tag</code>. The reference capability you choose is your promise to the compiler that states how you will use this variable. The pony compiler will strictly uphold you to your promise.</p> <p>In the following overview R means read rights, RW means read and write rights.</p> <p><code class="language-plaintext highlighter-rouge">iso</code> = <em>Isolate</em>. (RW, no aliased, can be passed) : If you have an <code class="language-plaintext highlighter-rouge">iso</code> variable, this means that you are certain that there is no other alias to that piece of memory with read (or write) access. It is safe to read, and write to this variable. You can pass an <code class="language-plaintext highlighter-rouge">iso</code> to another actor if you also pass the ownership by using <code class="language-plaintext highlighter-rouge">consume</code>.</p> <p><code class="language-plaintext highlighter-rouge">trn</code> = <em>Transition</em>. (RW, may have R aliases, cannot be passed) : A <code class="language-plaintext highlighter-rouge">trn</code> variable is designed to create a read only variable. Having one allows you to make edits to its contents and allows you to create read only variants of it (<code class="language-plaintext highlighter-rouge">box</code>es). These read-only variants can’t be passed to other actors but may come in handy when constructing your read only data. For example when you are creating a <code class="language-plaintext highlighter-rouge">val</code> data structure with cyclic references.</p> <p><code class="language-plaintext highlighter-rouge">box</code> = <em>Box</em>. (R, may have R and RW aliases, cannot be passed) : This box should be thought of as transparent with a slot for messages. You can read its (internal public) data but you cannot alter its state trough function calls. You can still send messages to it if it is an actor</p> <p><code class="language-plaintext highlighter-rouge">ref</code> = <em>Reference</em> (RW, may have RW aliases, cannot be passed). : A <code class="language-plaintext highlighter-rouge">ref</code> variable is your default reference capability. It states that you can modify the data the variable is pointing and that there may be other aliases with the same RW capability.</p> <p><code class="language-plaintext highlighter-rouge">val</code> = <em>Value</em>. (R, can have R aliases, can be passed) : A <code class="language-plaintext highlighter-rouge">val</code> reference to data implies that all references to that data are read-only. You can safely use the data without worrying about concurrency problems.</p> <p><code class="language-plaintext highlighter-rouge">tag</code> = <em>Tag</em>. (only allows sending of messages, can be passed) : A <code class="language-plaintext highlighter-rouge">tag</code> variable references a place in memory that has no guarantees. The only thing you can do is send a message to it. Since it a <code class="language-plaintext highlighter-rouge">tag</code> does not allow changing the internals directly it can be passed without problem.</p>]]></content><author><name></name></author><category term="programming-languages"/><category term="programming-languages"/><category term="ponylang"/><category term="concurrency"/><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Dining ponies</title><link href="https://blog.beardhatcode.be/2018/10/dining-ponies.html" rel="alternate" type="text/html" title="Dining ponies"/><published>2018-10-15T19:20:25+00:00</published><updated>2018-10-15T19:20:25+00:00</updated><id>https://blog.beardhatcode.be/2018/10/dining-ponies</id><content type="html" xml:base="https://blog.beardhatcode.be/2018/10/dining-ponies.html"><![CDATA[<p>In this blog post we implement a version of dining philosophers problem in Pony. <a href="https://en.wikipedia.org/wiki/Dining_philosophers_problem" rel="noopener noreferrer" target="_blank">Wikipedia</a> states the problem as follows:</p> <blockquote> <p>Five silent philosophers sit at a round table with bowls of spaghetti. Forks are placed between each pair of adjacent philosophers.</p> <p>Each philosopher must alternately think and eat. However, a philosopher can only eat spaghetti when they have both left and right forks. Each fork can be held by only one philosopher and so a philosopher can use the fork only if it is not being used by another philosopher. After an individual philosopher finishes eating, they need to put down both forks so that the forks become available to others. A philosopher can take the fork on their right or the one on their left as they become available, but cannot start eating before getting both forks.</p> <p>Eating is not limited by the remaining amounts of spaghetti or stomach space; an infinite supply and an infinite demand are assumed.</p> <p>The problem is how to design a discipline of behaviour (a concurrent algorithm) such that no philosopher will starve; i.e., each can forever continue to alternate between eating and thinking, assuming that no philosopher can know when others may want to eat or think.</p> </blockquote> <p>You can find the file with the pony implementation on my <a href="https://github.com/beardhatcode/savina-implementations/blob/master/pony/11_philosophers/main.pony" rel="noopener noreferrer" target="_blank">GitHub</a></p> <h1 id="actors-based-solution">Actors based solution</h1> <p>Since Pony is an actors-based programming language, we take on this problem in the default actor way.</p> <p>When a philosopher wants to start eating, they request both sticks form the table (which is also and actor). Eating can only commence once both sticks are acquired. If the philosopher fails to acquire a stick, they go on to think a bit longer and try again later.</p> <h2 id="main">Main</h2> <p>The main of the program creates a table with 5 sticks and 5 philosophers.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">actor</span> <span class="nc">Main</span>
  <span class="kr">new</span> <span class="n">create</span><span class="p">(</span><span class="n">env</span><span class="o">:</span> <span class="nc">Env</span><span class="p">)</span> <span class="o">=&gt;</span>
    <span class="kr">let</span> <span class="n">number</span>  <span class="o">=</span> <span class="nc">USize</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
    <span class="n">env</span><span class="p">.</span><span class="n">out</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Let's eat!"</span><span class="p">)</span>
    <span class="kr">let</span> <span class="n">table</span> <span class="o">=</span> <span class="nc">Table</span><span class="p">(</span><span class="n">number</span><span class="p">)</span>
    <span class="kr">for</span> <span class="n">i</span> <span class="kr">in</span> <span class="nc">Range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">number</span><span class="p">)</span> <span class="kr">do</span>
      <span class="nc">Philosopher</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="n">env</span><span class="p">,</span> <span class="n">table</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">number</span><span class="p">)()</span>
    <span class="kr">end</span>
</code></pre></div></div> <h2 id="stick-class">Stick class</h2> <p>We represent a stick using a class that has a default reference capability of <code class="language-plaintext highlighter-rouge">iso</code>. This means that there may be at most one actor in possession of a stick.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">class</span> <span class="kd">iso</span> <span class="nc">Stick</span>
  <span class="kr">let</span> <span class="nc">_id</span><span class="o">:</span><span class="nc">USize</span> <span class="kd">val</span>

  <span class="kr">new</span> <span class="kd">iso</span> <span class="n">create</span><span class="p">(</span><span class="n">id</span><span class="p">'</span><span class="o">:</span><span class="nc">USize</span><span class="p">)</span><span class="o">=&gt;</span> <span class="nc">_id</span> <span class="o">=</span> <span class="n">id</span><span class="p">'</span>
  <span class="kr">fun</span> <span class="kd">box</span> <span class="n">id</span><span class="p">()</span><span class="o">:</span><span class="nc">USize</span> <span class="o">=&gt;</span> <span class="nc">_id</span>
  <span class="kr">fun</span> <span class="kd">box</span> <span class="n">eq</span><span class="p">(</span><span class="n">that</span><span class="o">:</span> <span class="nc">Stick</span> <span class="kd">box</span><span class="p">)</span><span class="o">:</span> <span class="nc">Bool</span> <span class="o">=&gt;</span> <span class="kr">this</span><span class="p">.</span><span class="nc">_id</span> <span class="o">==</span> <span class="n">that</span><span class="p">.</span><span class="nc">_id</span>
</code></pre></div></div> <h2 id="table-actor">Table actor</h2> <p>A table actor gets a <code class="language-plaintext highlighter-rouge">USize</code> as argument to its constructor. This indicates the number of sticks and seats. An array is made of optional sticks (that is <code class="language-plaintext highlighter-rouge">None</code> or <code class="language-plaintext highlighter-rouge">Stick iso</code>).</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">actor</span> <span class="nc">Table</span>
  <span class="kr">let</span> <span class="nc">_sticks</span><span class="o">:</span> <span class="nc">Array</span><span class="p">[(</span><span class="nc">Stick</span><span class="o">|</span><span class="nc">None</span><span class="p">)]</span> <span class="kd">ref</span>

  <span class="kr">new</span> <span class="n">create</span><span class="p">(</span><span class="n">num</span><span class="o">:</span> <span class="nc">USize</span><span class="p">)</span> <span class="o">=&gt;</span>
    <span class="nc">_sticks</span> <span class="o">=</span> <span class="nc">Array</span><span class="p">[(</span><span class="nc">Stick</span><span class="o">|</span><span class="nc">None</span><span class="p">)]()</span>
    <span class="kr">for</span> <span class="n">i</span> <span class="kr">in</span> <span class="nc">Range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">num</span><span class="p">)</span> <span class="kr">do</span>
      <span class="nc">_sticks</span><span class="p">.</span><span class="n">push</span><span class="p">(</span> <span class="nc">Stick</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="p">)</span>
    <span class="kr">end</span>
</code></pre></div></div> <p>There are two messages the table actor accepts: <code class="language-plaintext highlighter-rouge">takeStick</code> and <code class="language-plaintext highlighter-rouge">realeaseStick</code>. They are both implemented as a behaviour in Pony. These behaviours are different from the notion of behaviours in other actor based languages in which they are used as a synchronisation mechanism.</p> <p>For the first behaviour, we get a request for a certain stick and who to give it to. Because the sticks in our array are <code class="language-plaintext highlighter-rouge">iso</code> we cannot just take a stick with <code class="language-plaintext highlighter-rouge">_sticks(num)</code> and send it back to the philosopher as this would create a new alias. To solve this we perform a destructive read, using <code class="language-plaintext highlighter-rouge">update</code>. The return type of <code class="language-plaintext highlighter-rouge">Array.update</code> is a <code class="language-plaintext highlighter-rouge">(Stick iso|None)^</code>. This is an ephemeral type, which means that there are no aliases to the returned value. We are allowed to send it back to the philosopher.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="kr">be</span> <span class="n">takeStick</span><span class="p">(</span><span class="n">num</span><span class="o">:</span> <span class="nc">USize</span><span class="p">,</span> <span class="n">who</span><span class="o">:</span><span class="nc">Philosopher</span><span class="p">)</span><span class="o">=&gt;</span>
    <span class="kr">try</span>  <span class="n">who</span><span class="p">.</span><span class="n">stick</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="nc">_sticks</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">num</span><span class="p">,</span><span class="nc">None</span><span class="p">)</span><span class="o">?</span><span class="p">)</span>
    <span class="kr">else</span> <span class="n">who</span><span class="p">.</span><span class="n">stick</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="nc">None</span><span class="p">)</span>
    <span class="kr">end</span>
</code></pre></div></div> <p>When a stick is returned, it is sent with a <code class="language-plaintext highlighter-rouge">realeaseStick</code> call. We take that stick and use match to verify if we got a stick. Take not of how we use <code class="language-plaintext highlighter-rouge">consume</code> in the match. By doing this we do not create an extra alias to the stick. Our initial <code class="language-plaintext highlighter-rouge">stick</code> is consumed and placed in <code class="language-plaintext highlighter-rouge">s</code>. Since <code class="language-plaintext highlighter-rouge">s</code> is an <code class="language-plaintext highlighter-rouge">iso</code> we can call the <code class="language-plaintext highlighter-rouge">box</code> method <code class="language-plaintext highlighter-rouge">s.id()</code> to get the id of the stick such that we can put it back in the array at the right place. To place the stick in the array we need to consume the stick <code class="language-plaintext highlighter-rouge">s</code> again.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="kr">be</span> <span class="n">realeaseStick</span><span class="p">(</span><span class="n">stick</span><span class="o">:</span><span class="p">(</span><span class="nc">Stick</span> <span class="kd">iso</span> <span class="o">|</span> <span class="nc">None</span><span class="p">))</span> <span class="o">=&gt;</span>
    <span class="kr">try</span> <span class="kr">match</span> <span class="p">(</span><span class="kr">consume</span> <span class="n">stick</span><span class="p">)</span>
        <span class="o">|</span> <span class="kr">let</span> <span class="n">s</span><span class="o">:</span><span class="nc">Stick</span> <span class="kd">iso</span> <span class="o">=&gt;</span> <span class="nc">_sticks</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">id</span><span class="p">(),</span><span class="kr">consume</span> <span class="n">s</span><span class="p">)</span><span class="o">?</span>
    <span class="kr">end</span> <span class="kr">end</span>
</code></pre></div></div> <h2 id="philosopher-actor">Philosopher actor</h2> <p>The philosopher is the most complicated actor.</p> <p>To create one we save the number of the philosopher and the required sticks in instance variables. We also set the <code class="language-plaintext highlighter-rouge">_sticksPending</code> tuple to <code class="language-plaintext highlighter-rouge">(false,false)</code>. This tuple keeps track of which sticks we have requested but haven’t received or been denied. We also keep a <code class="language-plaintext highlighter-rouge">Rand</code> in the actor to generate random sleep times.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">actor</span> <span class="nc">Philosopher</span>
   <span class="p">...</span>

  <span class="kr">new</span> <span class="n">create</span><span class="p">(</span><span class="n">number</span><span class="p">'</span><span class="o">:</span> <span class="nc">USize</span><span class="p">,</span> <span class="n">env</span><span class="o">:</span> <span class="nc">Env</span><span class="p">,</span> <span class="n">table</span><span class="o">:</span> <span class="nc">Table</span> <span class="kd">tag</span><span class="p">,</span> <span class="n">left_stick</span><span class="o">:</span><span class="nc">USize</span><span class="p">,</span> <span class="n">right_stick</span><span class="o">:</span><span class="nc">USize</span><span class="p">)</span> <span class="o">=&gt;</span>
    <span class="n">number</span> <span class="o">=</span> <span class="n">number</span><span class="p">'</span>
    <span class="nc">_sticks</span> <span class="o">=</span> <span class="p">(</span><span class="n">left_stick</span><span class="p">,</span><span class="n">right_stick</span><span class="p">)</span>
    <span class="nc">_sticksOwn1</span> <span class="o">=</span> <span class="nc">None</span>
    <span class="nc">_sticksOwn2</span> <span class="o">=</span> <span class="nc">None</span>
    <span class="nc">_sticksPending</span> <span class="o">=</span> <span class="p">(</span><span class="no">false</span><span class="p">,</span><span class="no">false</span><span class="p">)</span>
    <span class="nc">_table</span> <span class="o">=</span> <span class="n">table</span>
    <span class="nc">_env</span> <span class="o">=</span> <span class="n">env</span>
    <span class="n">rand</span> <span class="o">=</span> <span class="nc">Rand</span><span class="p">(</span><span class="mi">133742</span> <span class="o">+</span> <span class="p">(</span><span class="n">number</span><span class="p">'.</span><span class="n">u64</span><span class="p">()))</span>
</code></pre></div></div> <p>The <code class="language-plaintext highlighter-rouge">apply</code> behaviour, which is called at the start of the program, waits a random amount of time and requests sticks.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="kr">be</span> <span class="n">apply</span><span class="p">()</span> <span class="o">=&gt;</span>
    <span class="kr">let</span> <span class="n">l</span><span class="o">:</span><span class="nc">Philosopher</span> <span class="kd">tag</span> <span class="o">=</span> <span class="kr">this</span>
    <span class="nc">_env</span><span class="p">.</span><span class="n">out</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"@THINK "</span> <span class="o">+</span> <span class="n">number</span><span class="p">.</span><span class="n">string</span><span class="p">())</span>
    <span class="kr">this</span><span class="p">.</span><span class="n">doDelayed</span><span class="p">(</span><span class="err">{</span><span class="p">(</span><span class="n">l</span><span class="o">:</span><span class="nc">Philosopher</span> <span class="kd">tag</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="n">l</span><span class="p">.</span><span class="n">requestSticks</span><span class="p">();</span> <span class="nc">None</span> <span class="err">}</span><span class="p">)</span>
</code></pre></div></div> <p>This is carried out by simply sending a <code class="language-plaintext highlighter-rouge">takeStick</code> request to the table. After asking sticks we must wait for a <code class="language-plaintext highlighter-rouge">stick</code> message as response from the table. To keep track of which sticks we do not have an answer for we set <code class="language-plaintext highlighter-rouge">_sticksPending</code> to <code class="language-plaintext highlighter-rouge">true</code> for both sticks.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="kr">be</span> <span class="n">requestSticks</span><span class="p">()</span><span class="o">=&gt;</span>
    <span class="nc">_env</span><span class="p">.</span><span class="n">out</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Request sticks "</span> <span class="o">+</span> <span class="n">number</span><span class="p">.</span><span class="n">string</span><span class="p">())</span>
    <span class="nc">_sticksPending</span> <span class="o">=</span> <span class="p">(</span><span class="no">true</span><span class="p">,</span><span class="no">true</span><span class="p">)</span>
    <span class="nc">_table</span><span class="p">.</span><span class="n">takeStick</span><span class="p">(</span><span class="nc">_sticks</span><span class="p">.</span><span class="nc">_1</span><span class="p">,</span><span class="kr">this</span><span class="p">)</span>
    <span class="nc">_table</span><span class="p">.</span><span class="n">takeStick</span><span class="p">(</span><span class="nc">_sticks</span><span class="p">.</span><span class="nc">_2</span><span class="p">,</span><span class="kr">this</span><span class="p">)</span>
</code></pre></div></div> <p>When <code class="language-plaintext highlighter-rouge">stick</code> messages arrive, we store the <code class="language-plaintext highlighter-rouge">Stick</code> or <code class="language-plaintext highlighter-rouge">None</code> in <code class="language-plaintext highlighter-rouge">_sticksOwn1</code> and <code class="language-plaintext highlighter-rouge">_sticksOwn2</code>. We update <code class="language-plaintext highlighter-rouge">_sticksPending</code>. If have got a response for all sticks, we validate that we have both sticks. If one of the sticks is missing, we return all sticks we have. In the fortunate case that we have both sticks, we eat.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="kr">be</span> <span class="n">stick</span><span class="p">(</span><span class="n">num</span><span class="o">:</span><span class="nc">USize</span><span class="p">,</span> <span class="n">s</span><span class="o">:</span> <span class="p">(</span><span class="nc">Stick</span><span class="o">|</span><span class="nc">None</span><span class="p">))</span> <span class="o">=&gt;</span>
    <span class="kr">match</span> <span class="p">(</span><span class="kr">consume</span> <span class="n">s</span><span class="p">)</span>
    <span class="o">|</span> <span class="kr">let</span> <span class="n">x</span><span class="o">:</span><span class="nc">Stick</span> <span class="o">=&gt;</span>
        <span class="kr">if</span>     <span class="n">x</span><span class="p">.</span><span class="n">id</span><span class="p">()</span> <span class="o">==</span> <span class="nc">_sticks</span><span class="p">.</span><span class="nc">_1</span> <span class="kr">then</span> <span class="nc">_sticksOwn1</span> <span class="o">=</span> <span class="kr">consume</span> <span class="n">x</span>
        <span class="kr">elseif</span> <span class="n">x</span><span class="p">.</span><span class="n">id</span><span class="p">()</span> <span class="o">==</span> <span class="nc">_sticks</span><span class="p">.</span><span class="nc">_2</span> <span class="kr">then</span> <span class="nc">_sticksOwn2</span> <span class="o">=</span> <span class="kr">consume</span> <span class="n">x</span>
        <span class="kr">end</span>
    <span class="kr">end</span>

    <span class="nc">_sticksPending</span> <span class="o">=</span> <span class="p">(</span>
      <span class="kr">if</span> <span class="n">num</span> <span class="o">==</span> <span class="nc">_sticks</span><span class="p">.</span><span class="nc">_1</span> <span class="kr">then</span> <span class="no">false</span> <span class="kr">else</span> <span class="nc">_sticksPending</span><span class="p">.</span><span class="nc">_1</span> <span class="kr">end</span><span class="p">,</span>
      <span class="kr">if</span> <span class="n">num</span> <span class="o">==</span> <span class="nc">_sticks</span><span class="p">.</span><span class="nc">_2</span> <span class="kr">then</span> <span class="no">false</span> <span class="kr">else</span> <span class="nc">_sticksPending</span><span class="p">.</span><span class="nc">_2</span> <span class="kr">end</span>
    <span class="p">)</span>

    <span class="kr">if</span> <span class="p">((</span><span class="nc">_sticksPending</span><span class="p">.</span><span class="nc">_1</span><span class="p">)</span> <span class="n">or</span> <span class="p">(</span><span class="nc">_sticksPending</span><span class="p">.</span><span class="nc">_2</span><span class="p">))</span> <span class="kr">then</span> <span class="kr">return</span> <span class="kr">end</span>

    <span class="c1">// Check if none of the sticks are None</span>
    <span class="kr">recover</span>
      <span class="kr">match</span> <span class="nc">_sticksOwn1</span>
      <span class="o">|</span> <span class="nc">None</span> <span class="o">=&gt;</span> <span class="kr">this</span><span class="p">.</span><span class="n">returnSticks</span><span class="p">()</span>
      <span class="kr">else</span>
        <span class="kr">match</span> <span class="nc">_sticksOwn2</span>
        <span class="o">|</span> <span class="nc">None</span> <span class="o">=&gt;</span> <span class="kr">this</span><span class="p">.</span><span class="n">returnSticks</span><span class="p">()</span>
        <span class="kr">else</span>
          <span class="n">eat</span><span class="p">()</span> <span class="c1">// We have both sticks</span>
        <span class="kr">end</span>
      <span class="kr">end</span>
    <span class="kr">end</span>
</code></pre></div></div> <p>Eating is simple. We print that we are eating and return the sticks after some time.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="kr">fun</span> <span class="kd">ref</span> <span class="n">eat</span><span class="p">()</span> <span class="o">=&gt;</span>
    <span class="n">state</span> <span class="o">=</span> <span class="nc">Eating</span>
    <span class="nc">_env</span><span class="p">.</span><span class="n">out</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"@EATING "</span> <span class="o">+</span> <span class="n">number</span><span class="p">.</span><span class="n">string</span><span class="p">())</span>
    <span class="kr">this</span><span class="p">.</span><span class="n">doDelayed</span><span class="p">(</span><span class="err">{</span><span class="p">(</span><span class="n">l</span><span class="o">:</span><span class="nc">Philosopher</span> <span class="kd">tag</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="n">l</span><span class="p">.</span><span class="n">returnSticks</span><span class="p">();</span> <span class="nc">None</span> <span class="err">}</span> <span class="kd">iso</span><span class="p">)</span>
</code></pre></div></div> <p>When the sticks are returned we set our state to <code class="language-plaintext highlighter-rouge">Thinking</code> and send back the sticks to the table. Since we mustn’t create aliases to our <code class="language-plaintext highlighter-rouge">Sticks</code>, we first use a destructive read to get the <code class="language-plaintext highlighter-rouge">iso</code> in a local variable we can consume. Once the sticks are sent, we can go back to our <code class="language-plaintext highlighter-rouge">apply()</code>.</p> <div class="language-pony highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="kr">be</span> <span class="n">returnSticks</span><span class="p">()</span> <span class="o">=&gt;</span>
    <span class="nc">_env</span><span class="p">.</span><span class="n">out</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Return sticks "</span><span class="o">+</span><span class="n">number</span><span class="p">.</span><span class="n">string</span><span class="p">())</span>
    <span class="n">state</span> <span class="o">=</span> <span class="nc">Thinking</span>
    <span class="kr">let</span> <span class="n">s1</span> <span class="o">=</span> <span class="nc">_sticksOwn1</span> <span class="o">=</span> <span class="nc">None</span><span class="p">;</span> <span class="nc">_table</span><span class="p">.</span><span class="n">realeaseStick</span><span class="p">(</span><span class="kr">consume</span> <span class="n">s1</span><span class="p">)</span>
    <span class="kr">let</span> <span class="n">s2</span> <span class="o">=</span> <span class="nc">_sticksOwn2</span> <span class="o">=</span> <span class="nc">None</span><span class="p">;</span> <span class="nc">_table</span><span class="p">.</span><span class="n">realeaseStick</span><span class="p">(</span><span class="kr">consume</span> <span class="n">s2</span><span class="p">)</span>
    <span class="kr">this</span><span class="p">()</span>
</code></pre></div></div>]]></content><author><name></name></author><category term="programming-languages"/><category term="programming-languages"/><category term="ponylang"/><category term="concurrency"/><summary type="html"><![CDATA[In this blog post we implement a version of dining philosophers problem in Pony. Wikipedia states the problem as follows:]]></summary></entry><entry><title type="html">`mysqlimport` form pipe</title><link href="https://blog.beardhatcode.be/2018/04/mysqlimport.html" rel="alternate" type="text/html" title="`mysqlimport` form pipe"/><published>2018-04-14T15:57:49+00:00</published><updated>2018-04-14T15:57:49+00:00</updated><id>https://blog.beardhatcode.be/2018/04/mysqlimport</id><content type="html" xml:base="https://blog.beardhatcode.be/2018/04/mysqlimport.html"><![CDATA[<p>Contrary to what you would expect, <a href="https://dev.mysql.com/doc/refman/5.7/en/mysqlimport.html" rel="noopener noreferrer" target="_blank"><code class="language-plaintext highlighter-rouge">mysqlimport</code></a> does not allow importing TSV’s from standard in. This in an issue if you want to load a <code class="language-plaintext highlighter-rouge">gzip</code>ped into a database table. The following script works around this shortcoming:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>zcat file.tsv.gz | <span class="se">\</span>
    mysql <span class="s2">"</span><span class="nv">$databasename</span><span class="s2">"</span> <span class="nt">-e</span> <span class="s2">"LOAD DATA LOCAL INFILE '/dev/stdin' INTO TABLE </span><span class="nv">$tablename</span><span class="s2">"</span>
</code></pre></div></div> <h2 id="showing-warnings">Showing warnings,</h2> <p>Another functionality that <a href="https://dev.mysql.com/doc/refman/5.7/en/mysqlimport.html" rel="noopener noreferrer" target="_blank"><code class="language-plaintext highlighter-rouge">mysqlimport</code></a> is missing is reporting warning in full. If warnings occur during loading you get is “1337 warnings”, which does not help you pinpoint the problem. To work around this issue, you can append <code class="language-plaintext highlighter-rouge">SHOW WARNINGS</code> at the end of the command (after a <code class="language-plaintext highlighter-rouge">;</code>).</p> <h2 id="loading-in-binary-data">Loading in binary data</h2> <p>There is no support for loading in binary data, but there is a simple workaround. If your TSV contains a column with binary data as hex the following will work.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>zcat file.tsv.gz | <span class="se">\</span>
    mysql <span class="s2">"</span><span class="nv">$databasename</span><span class="s2">"</span> <span class="nt">-e</span> <span class="s2">"
            LOAD DATA LOCAL INFILE '/dev/stdin'
            INTO TABLE targettable (col1, col2, @hex3, col4)
            SET col3 = UNHEX(@hex3);
            SHOW WARNINGS;"</span>
</code></pre></div></div> <p>Rather than being loaded into the table, the third column will be placed in a variable that is later used to set the value of the third column.</p> <p>Reminder: The following command transforms data to a hex.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>... | xxd <span class="nt">-p</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span>
</code></pre></div></div> <h2 id="storing-a-compressed-column">Storing a compressed column</h2> <p>Instead of using <code class="language-plaintext highlighter-rouge">UNHEX</code>, all kinds of operations can be done. A nice example is <code class="language-plaintext highlighter-rouge">COMPRESS</code>. Using a similar piece of code, you can compress data form your TSV with gzip.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>zcat file.tsv.gz | <span class="se">\</span>
    mysql <span class="s2">"</span><span class="nv">$databasename</span><span class="s2">"</span> <span class="nt">-e</span> <span class="s2">"
            LOAD DATA LOCAL INFILE '/dev/stdin'
            INTO TABLE targettable (col1, col2, @large3, col4)
            SET col3 = COMPRESS(@large3);
            SHOW WARNINGS;"</span>
</code></pre></div></div> <p>Want to compress binary data? Combine the last 2: <code class="language-plaintext highlighter-rouge">COMPRESS(UNHEX(…))</code>.</p> <p><strong>Sources</strong></p> <p>This solution was inspired by the stackoverflow post “<a href="https://stackoverflow.com/a/38922801/831645" rel="noopener noreferrer" target="_blank">MySQL import from stdin</a>”. The best answer unfortunately did not have the majority of the up-votes at the time of writing this.</p>]]></content><author><name></name></author><category term="linux"/><category term="database"/><category term="linux"/><category term="MySQL"/><summary type="html"><![CDATA[Loading data form a pipe into a MySQL database can be done with `... | mysql db -e "LOAD DATA LOCAL INFILE '/dev/stdin' INTO TABLE tbl"`]]></summary></entry></feed>