<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/default.xsl"?>
<fr:tree xmlns:fr="http://www.forester-notes.org" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xml="http://www.w3.org/XML/1998/namespace" root="false" base-url="/">
  <fr:frontmatter>
    <fr:authors>
      <fr:author>
        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
      </fr:author>
    </fr:authors>
    <fr:date>
      <fr:year>2026</fr:year>
      <fr:month>4</fr:month>
      <fr:day>18</fr:day>
    </fr:date>
    <fr:uri>https://patrick.sirref.org/self-host-music/</fr:uri>
    <fr:display-uri>self-host-music</fr:display-uri>
    <fr:route>/self-host-music/</fr:route>
    <fr:title text="Landlocked Eio › Self-hosting Music "><fr:link href="/weekly-2026-w16/" title="Landlocked Eio" uri="https://patrick.sirref.org/weekly-2026-w16/" display-uri="weekly-2026-w16" type="local">Landlocked Eio</fr:link> › Self-hosting Music </fr:title>
  </fr:frontmatter>
  <fr:mainmatter>
    <html:p>After my friend, <fr:link href="https://gretathompson.com/" type="external">Greta</fr:link>, sent me some articles about music streaming services and their exploitation of artists, I decided enough was enough and setup <fr:link href="https://www.navidrome.org/" type="external">navidrome</fr:link>. It is compatible with <fr:link href="https://www.subsonic.org/pages/api.jsp" type="external">Subsonic</fr:link> and so far I'm very pleased to be streaming my own music to my devices. I am using <fr:link href="https://substreamer.org/" type="external">substreamer</fr:link> on iOS. On my laptop, I tried out <fr:link href="https://github.com/rossberg/camp" type="external">Andreas Rossberg's Camp</fr:link></html:p>
    <html:blockquote>
      <html:p>What you got here is an old-school music player heavily inspired by good old <![CDATA[Winamp [1], with a focus on decent music library and playlist handling.]]></html:p>
    </html:blockquote>
    <html:p>I took <fr:link href="/anilmadhavapeddy/" title="Anil Madhavapeddy" uri="https://patrick.sirref.org/anilmadhavapeddy/" display-uri="anilmadhavapeddy" type="local">Anil's</fr:link> <fr:link href="https://github.com/avsm/oi" type="external">OCaml Installer</fr:link> tool for a spin with great success... after a few mishaps mostly related to system dependencies.</html:p>
    <html:pre><![CDATA[$ nix-shell -p pkg-config gcc pulseaudio miniaudio libxi libxrandr libxinerama libffi mesa libxcursor libGL 
$ oi-linux-x86_64 run --with=https://github.com/patricoferris/camp#nix -- camp]]></html:pre>
    <html:p>The fixes in my fork of Camp are just to install the assets using <html:code>dune</html:code> and also statically provide the <html:code>-lpulse</html:code> flag (which should probably be dynamically picked up). Otherwise, raylib or miniaudio selects the <html:code>Null</html:code> playback device. Roll-on <fr:link href="https://ryan.freumh.org/papers/2026-package-calculus.html" type="external">cross-ecosystem package management</fr:link>.</html:p>
    <html:img src="/bafkrmifuphhk6ys7hpaqm2jaad6qr7253nevf6ddu4bh7d5tjyasp35kum.png" />
  </fr:mainmatter>
  <fr:backmatter>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="References">References</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Context">Context</fr:title>
      </fr:frontmatter>
      <fr:mainmatter>
        <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors>
              <fr:author>
                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
              </fr:author>
            </fr:authors>
            <fr:date>
              <fr:year>2026</fr:year>
              <fr:month>4</fr:month>
              <fr:day>18</fr:day>
            </fr:date>
            <fr:uri>https://patrick.sirref.org/weekly-2026-w16/</fr:uri>
            <fr:display-uri>weekly-2026-w16</fr:display-uri>
            <fr:route>/weekly-2026-w16/</fr:route>
            <fr:title text="Landlocked Eio">Landlocked Eio</fr:title>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>I spent the start of last week wrapping up the "local" CI I mentioned <fr:link href="/weekly-2026-w15/" title="Moving away from Github" uri="https://patrick.sirref.org/weekly-2026-w15/" display-uri="weekly-2026-w15" type="local">the previous week</fr:link>. Unfortunately it was mostly a packaging nightmare, followed by missing features in <html:code>ocaml-ci-local</html:code>. It would be great to have a richer CLI tool for running tests on a directory of git repositories, but unfortunately most of the existing tooling has prioritised the Github/Gitlab etc. APIs.</html:p>
            <html:p>After coming across <fr:link href="https://minimal.dev/" type="external">minimal</fr:link> during the week, I took it as an opportunity to learn a little more about Linux's <fr:link href="https://lwn.net/Articles/859908/" type="external">Landlock</fr:link> mechanism.</html:p>
            <fr:tree show-metadata="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2026</fr:year>
                  <fr:month>4</fr:month>
                  <fr:day>18</fr:day>
                </fr:date>
                <fr:title text="Landlocked Eio">Landlocked Eio</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p><fr:link href="https://lwn.net/Articles/859908/" type="external">Landlock</fr:link> is a sandboxing mechanism that has existed in the Linux kernel since 5.13. It allows unprivileged processes a means to restrict their ambient rights (e.g. creating a file or opening a network connection). These rights are ambient in the <fr:link href="https://en.wikipedia.org/wiki/Ambient_authority" type="external">ambient authority</fr:link> sense, i.e., any process can attempt to perform an action without needing access to any particular capability to do so.</html:p>
                <html:p>Ambient systems are often contrasted with capability-based ones. In terms of operating systems, this is most commonly illustrated with <fr:link href="/miller2003capability/" title="Capability myths demolished" uri="https://patrick.sirref.org/miller2003capability/" display-uri="miller2003capability" type="local">access-control-lists-as-columns and capabilities-as-rows in an access matrix</fr:link>.</html:p>
                <html:p><fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio</fr:link> is a capability-based library in OCaml -- resources are provided at the start of the application and can be passed around wherever they are needed. The design is covered in <fr:link href="/talex5/" title="Thomas Leonard" uri="https://patrick.sirref.org/talex5/" display-uri="talex5" type="local">Thomas Leonard</fr:link>'s <fr:link href="https://roscidus.com/blog/blog/2023/04/26/lambda-capabilities/" type="external">lambda capabilities blog post</fr:link>. Unfortunately, any application (willingly or via a third-party library) may ambiently access OS resources. In OCaml, this may be by using the standard library functions (e.g. <html:code>Sys.readdir</html:code>), things from the <html:code>Unix</html:code> module, a C FFI function or by spawning a subprocess.</html:p>
                <html:p>I had a go at "landlocking" Eio applications last week after stumbling across <fr:link href="https://minimal.dev/" type="external">minimal's</fr:link> <fr:link href="github.com/gominimal/hakoniwa" type="external">hakoniwa</fr:link> library for process isolation (which is very reminiscent of <fr:link href="/void-processes/" title="Vpnkit, Void Processes, LSP Servers › Void Processes " uri="https://patrick.sirref.org/void-processes/" display-uri="void-processes" type="local">void processes</fr:link>).</html:p>
                <html:pre class="hilite">
                  <html:code>
                    <html:span class="ocaml-keyword-other">module</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Landlock</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio_linux</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Landlock</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword-other">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">/</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Path</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">/</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">run_eio</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">file</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">traceln</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">Writing to file</html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Path</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">save</html:span>
                    <html:span class="ocaml-source"> ~</html:span>
                    <html:span class="ocaml-source">create</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-constant-language-polymorphic-variant">`Exclusive</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-numeric-octal-integer">0o644</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">file</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">hello, world!</html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">traceln</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">Reading file: </html:span>
                    <html:span class="ocaml-constant-character-printf"><![CDATA[%s]]></html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Path</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">load</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">file</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Path</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">unlink</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">file</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">bad_program</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">In_channel</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">with_open_bin</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">/etc/passwd</html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">In_channel</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">input_all</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-operator">|&gt;</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">traceln</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">/etc/passwd: </html:span>
                    <html:span class="ocaml-constant-character-printf"><![CDATA[%s]]></html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword-other">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio_linux</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">run</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">@@</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">fun</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">env</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Path</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">with_open_dir</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Stdenv</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">cwd</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">env</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">/</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">.</html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">@@</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">fun</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">dir</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">parent_fd</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> 
</html:span>
                    <html:span class="ocaml-source">    </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio_unix</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Resource</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">fd_opt</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source">fst</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">dir</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">|&gt;</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Option</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">get</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-other">in</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">file</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">dir</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">/</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">hello.txt</html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">in</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">rules</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">    </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Landlock</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Rule</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">      </html:span>
                    <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">        </html:span>
                    <html:span class="ocaml-source">path_beneath</html:span>
                    <html:span class="ocaml-source"> ~</html:span>
                    <html:span class="ocaml-source">parent_fd</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">          ~</html:span>
                    <html:span class="ocaml-source">flags</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Flags</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Fs</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">            </html:span>
                    <html:span class="ocaml-source">write_file</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">+</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">read_file</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">+</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">make_reg</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">+</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">remove_file</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">           </html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">      </html:span>
                    <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-other">in</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-other">match</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Landlock</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">enter</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">rules</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">with</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-other">|</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Ok</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">      </html:span>
                    <html:span class="ocaml-source">run_eio</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">file</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">      </html:span>
                    <html:span class="ocaml-source">bad_program</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-other">|</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Error</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-polymorphic-variant">`Not_supported</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">traceln</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">Landlock not supported!</html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-source">
</html:span>
                  </html:code>
                </html:pre>
                <html:p>Running this program (with the necessary privileges) prints the following.</html:p>
                <html:pre><![CDATA[+Writing to file
+Reading file: hello, world!
Fatal error: exception Sys_error("/etc/passwd: Permission denied")]]></html:pre>
                <html:p>Eio already has a similar function for the BSDs using <fr:link href="https://github.com/ocaml-multicore/eio#filesystem-access" type="external">capsicum</fr:link>. In capsicum, <fr:link href="https://man.freebsd.org/cgi/man.cgi?query=cap_enter" type="external">processes enter a capability mode</fr:link>:</html:p>
                <html:blockquote>
                  <html:p><html:code>cap_enter()</html:code> places the current process into capability mode, a mode of execution in which processes may	only issue system calls	operating on file descriptors or reading limited global system state.</html:p>
                </html:blockquote>
                <html:p>This plays nicely with <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio</fr:link>'s capabilities. Within the scope of <html:code>Eio.Path.with_open_dir</html:code>, the directory will remain usable after entering "cap" mode. This is not the case with landlock unless you add a specific <html:code>path_beneath</html:code> rule to the ruleset (like in the example above). However, you could imagine plumbing the necessary information throughout the <html:code>Eio_linux</html:code> backend for it to build a set of rules that can be applied at any given moment in order to mimic the capsicum semantics.</html:p>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2026</fr:year>
                  <fr:month>4</fr:month>
                  <fr:day>18</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/self-host-music/</fr:uri>
                <fr:display-uri>self-host-music</fr:display-uri>
                <fr:route>/self-host-music/</fr:route>
                <fr:title text="Self-hosting Music ">Self-hosting Music </fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>After my friend, <fr:link href="https://gretathompson.com/" type="external">Greta</fr:link>, sent me some articles about music streaming services and their exploitation of artists, I decided enough was enough and setup <fr:link href="https://www.navidrome.org/" type="external">navidrome</fr:link>. It is compatible with <fr:link href="https://www.subsonic.org/pages/api.jsp" type="external">Subsonic</fr:link> and so far I'm very pleased to be streaming my own music to my devices. I am using <fr:link href="https://substreamer.org/" type="external">substreamer</fr:link> on iOS. On my laptop, I tried out <fr:link href="https://github.com/rossberg/camp" type="external">Andreas Rossberg's Camp</fr:link></html:p>
                <html:blockquote>
                  <html:p>What you got here is an old-school music player heavily inspired by good old <![CDATA[Winamp [1], with a focus on decent music library and playlist handling.]]></html:p>
                </html:blockquote>
                <html:p>I took <fr:link href="/anilmadhavapeddy/" title="Anil Madhavapeddy" uri="https://patrick.sirref.org/anilmadhavapeddy/" display-uri="anilmadhavapeddy" type="local">Anil's</fr:link> <fr:link href="https://github.com/avsm/oi" type="external">OCaml Installer</fr:link> tool for a spin with great success... after a few mishaps mostly related to system dependencies.</html:p>
                <html:pre><![CDATA[$ nix-shell -p pkg-config gcc pulseaudio miniaudio libxi libxrandr libxinerama libffi mesa libxcursor libGL 
$ oi-linux-x86_64 run --with=https://github.com/patricoferris/camp#nix -- camp]]></html:pre>
                <html:p>The fixes in my fork of Camp are just to install the assets using <html:code>dune</html:code> and also statically provide the <html:code>-lpulse</html:code> flag (which should probably be dynamically picked up). Otherwise, raylib or miniaudio selects the <html:code>Null</html:code> playback device. Roll-on <fr:link href="https://ryan.freumh.org/papers/2026-package-calculus.html" type="external">cross-ecosystem package management</fr:link>.</html:p>
                <html:img src="/bafkrmifuphhk6ys7hpaqm2jaad6qr7253nevf6ddu4bh7d5tjyasp35kum.png" />
              </fr:mainmatter>
            </fr:tree>
          </fr:mainmatter>
        </fr:tree>
      </fr:mainmatter>
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Backlinks">Backlinks</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Related">Related</fr:title>
      </fr:frontmatter>
      <fr:mainmatter>
        <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors />
            <fr:uri>https://patrick.sirref.org/anilmadhavapeddy/</fr:uri>
            <fr:display-uri>anilmadhavapeddy</fr:display-uri>
            <fr:route>/anilmadhavapeddy/</fr:route>
            <fr:title text="Anil Madhavapeddy">Anil Madhavapeddy</fr:title>
            <fr:taxon>person</fr:taxon>
            <fr:meta name="external">https://anil.recoil.org</fr:meta>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>Professor of Planetary Computing at <fr:link href="/ucam/" title="University of Cambridge" uri="https://patrick.sirref.org/ucam/" display-uri="ucam" type="local">University of Cambridge</fr:link>.</html:p>
          </fr:mainmatter>
        </fr:tree>
      </fr:mainmatter>
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Contributions">Contributions</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
  </fr:backmatter>
</fr:tree>
