<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>dKade's notes</title><link>https://dkade.com/</link><description>Recent content on dKade's notes</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>dkade@dkade.com (Daniel Loureiro)</managingEditor><webMaster>dkade@dkade.com (Daniel Loureiro)</webMaster><lastBuildDate>Tue, 11 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://dkade.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Running Wiki.js in a FreeBSD 15.1 Jail</title><link>https://dkade.com/posts/wikijs_freebsd_jail/</link><pubDate>Tue, 11 Aug 2026 00:00:00 +0000</pubDate><author>dkade@dkade.com (Daniel Loureiro)</author><guid>https://dkade.com/posts/wikijs_freebsd_jail/</guid><description>Installing Wiki.js 2.5.314 on FreeBSD 15.1 with SQLite and Node.js 24, including rebuilding the Linux sqlite3 native module</description><content:encoded><![CDATA[<p>Wiki.js works well inside a FreeBSD jail, but there is one important catch: the official Wiki.js release ships a prebuilt Linux <code>sqlite3</code> native module. On FreeBSD this needs to be rebuilt locally before Wiki.js will start.</p>
<p>This post covers a simple Wiki.js 2.5.314 installation on FreeBSD 15.1 using SQLite, Node.js 24, and a native <code>rc.d</code> service.</p>
<h2 id="setup">Setup</h2>
<p>The jail is a normal FreeBSD 15.1-RELEASE jail with its own IP on the LAN.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">FreeBSD 15.1-RELEASE Host
</span></span><span class="line"><span class="cl">│
</span></span><span class="line"><span class="cl">└── wiki jail
</span></span><span class="line"><span class="cl">    └── Wiki.js :3000
</span></span></code></pre></div><p>No Docker or Linux emulation is needed. Wiki.js itself runs natively under FreeBSD Node.js.</p>
<h2 id="installing-wikijs">Installing Wiki.js</h2>
<p>I created a small bootstrap script which handles the whole installation.</p>
<p>Inside the jail as root:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">fetch https://codeberg.org/dkade/BSD/raw/branch/main/FreeBSD/wikijs/install-wikijs-freebsd-15.1.sh
</span></span><span class="line"><span class="cl">chmod +x install-wikijs-freebsd-15.1.sh
</span></span><span class="line"><span class="cl">./install-wikijs-freebsd-15.1.sh
</span></span></code></pre></div><p>The script installs:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">node24
</span></span><span class="line"><span class="cl">npm-node24
</span></span><span class="line"><span class="cl">python311
</span></span><span class="line"><span class="cl">gmake
</span></span><span class="line"><span class="cl">pkgconf
</span></span><span class="line"><span class="cl">sqlite3
</span></span><span class="line"><span class="cl">ca_root_nss
</span></span></code></pre></div><p>It then downloads Wiki.js 2.5.314 and extracts it under:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">/usr/local/wikijs
</span></span></code></pre></div><p>A dedicated <code>wikijs</code> user is created to run the service instead of running Wiki.js as root.</p>
<h2 id="the-sqlite-freebsd-gotcha">The SQLite FreeBSD gotcha</h2>
<p>The official Wiki.js release includes its <code>node_modules</code>, including a prebuilt <code>sqlite3</code> native module.</p>
<p>Trying to start it directly on FreeBSD results in errors such as:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Shared object &#34;libc.musl-x86_64.so.1&#34; not found,
</span></span><span class="line"><span class="cl">required by &#34;node_sqlite3.node&#34;
</span></span></code></pre></div><p>Running <code>ldd</code> makes the problem obvious:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">ldd /usr/local/wikijs/node_modules/sqlite3/build/Release/node_sqlite3.node
</span></span></code></pre></div><p>returns:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">not a FreeBSD ELF shared object
</span></span></code></pre></div><p>The bundled module is a Linux/musl binary, so it cannot be used natively on FreeBSD.</p>
<p>The solution is to rebuild only the SQLite native module:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="nb">cd</span> /usr/local/wikijs
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">rm -rf node_modules/sqlite3/build
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">env <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="nv">npm_config_python</span><span class="o">=</span>/usr/local/bin/python3.11 <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="nv">npm_config_build_from_source</span><span class="o">=</span><span class="nb">true</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="nv">MAKE</span><span class="o">=</span>gmake <span class="se">\
</span></span></span><span class="line"><span class="cl">  npm rebuild sqlite3
</span></span></code></pre></div><p>Python 3.11 is used because the version of <code>node-gyp</code> bundled with Wiki.js 2.5.x still depends on Python&rsquo;s old <code>distutils</code> module, which was removed in Python 3.12.</p>
<p>After the rebuild:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">file node_modules/sqlite3/build/Release/node_sqlite3.node
</span></span></code></pre></div><p>should identify it as a FreeBSD ELF shared object.</p>
<p>Test it directly:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">node -e <span class="s2">&#34;const s=require(&#39;sqlite3&#39;); console.log(s.VERSION); console.log(&#39;sqlite3 OK&#39;)&#34;</span>
</span></span></code></pre></div><h2 id="configuration">Configuration</h2>
<p>Wiki.js uses:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">/usr/local/wikijs/config.yml
</span></span></code></pre></div><p>For a simple SQLite setup:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">3000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">db</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">sqlite</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="l">/usr/local/wikijs/data/wiki.db</span><span class="w">
</span></span></span></code></pre></div><p>Make sure the database directory is writable by the Wiki.js user:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">mkdir -p /usr/local/wikijs/data
</span></span><span class="line"><span class="cl">chown -R wikijs:wikijs /usr/local/wikijs
</span></span></code></pre></div><h2 id="freebsd-rcd-service">FreeBSD rc.d service</h2>
<p>The installer creates:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">/usr/local/etc/rc.d/wikijs
</span></span></code></pre></div><p>Wiki.js is started using FreeBSD&rsquo;s <code>daemon(8)</code> and Node.js:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">/usr/local/bin/node /usr/local/wikijs/server
</span></span></code></pre></div><p>The service is enabled with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sysrc <span class="nv">wikijs_enable</span><span class="o">=</span>YES
</span></span></code></pre></div><p>Start it:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">service wikijs start
</span></span></code></pre></div><p>Check the status:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">service wikijs status
</span></span></code></pre></div><p>Restart it:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">service wikijs restart
</span></span></code></pre></div><p>Logs are written to:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">/var/log/wikijs.log
</span></span></code></pre></div><p>so they can be followed with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">tail -f /var/log/wikijs.log
</span></span></code></pre></div><p>Once running, Wiki.js is available at:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">http://&lt;jail-ip&gt;:3000
</span></span></code></pre></div><p>The first connection opens the Wiki.js setup wizard.</p>
<h2 id="upgrading">Upgrading</h2>
<p>Before upgrading, take a ZFS snapshot or at least back up:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">/usr/local/wikijs/config.yml
</span></span><span class="line"><span class="cl">/usr/local/wikijs/data/
</span></span></code></pre></div><p>After replacing the Wiki.js application files with a newer release, rebuild the SQLite module again:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="nb">cd</span> /usr/local/wikijs
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">env <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="nv">npm_config_python</span><span class="o">=</span>/usr/local/bin/python3.11 <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="nv">npm_config_build_from_source</span><span class="o">=</span><span class="nb">true</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="nv">MAKE</span><span class="o">=</span>gmake <span class="se">\
</span></span></span><span class="line"><span class="cl">  npm rebuild sqlite3
</span></span></code></pre></div><p>Then restart Wiki.js:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">service wikijs restart
</span></span></code></pre></div><p>Avoid blindly running:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">npm update
</span></span></code></pre></div><p>or:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">npm audit fix --force
</span></span></code></pre></div><p>inside the Wiki.js application tree. Wiki.js ships with a specific dependency set and changing package versions independently can break the application.</p>
<h2 id="gotchas">Gotchas</h2>
<ul>
<li><strong>SQLite native module:</strong> the bundled <code>node_sqlite3.node</code> is Linux/musl and must be rebuilt for FreeBSD.</li>
<li><strong>Python version:</strong> use Python 3.11 when rebuilding with the older bundled <code>node-gyp</code>.</li>
<li><strong>Node.js:</strong> Wiki.js 2.5.314 runs correctly with the FreeBSD <code>node24</code> package.</li>
<li><strong>Do not copy old <code>node_modules</code>:</strong> when upgrading, use a clean Wiki.js release tree and preserve only your configuration and database.</li>
<li><strong>rc.d PID tracking:</strong> when using <code>daemon(8)</code>, set <code>procname</code> to <code>/usr/local/bin/node</code> so <code>service wikijs status</code> correctly detects the running process.</li>
</ul>
<h2 id="summary">Summary</h2>
<p>Wiki.js runs cleanly inside a FreeBSD 15.1 jail without Docker or Linux emulation.</p>
<p>The only non-obvious part is rebuilding the bundled SQLite native module for FreeBSD. Once that is done, Wiki.js behaves like any other native FreeBSD service: a dedicated user, an <code>rc.d</code> script, automatic startup, and straightforward ZFS snapshots for backups and upgrades.</p>
<p>The bootstrap script automates the complete process from a fresh jail.</p>
]]></content:encoded></item><item><title>Running HomeAssistant Core in FreeBSD Jails with BastilleBSD</title><link>https://dkade.com/posts/homeassistant_freebsd_jail/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><author>dkade@dkade.com (Daniel Loureiro)</author><guid>https://dkade.com/posts/homeassistant_freebsd_jail/</guid><description>A complete guide to running HomeAssistant Core in a VNET FreeBSD jail managed with BastilleBSD, with separate jails for Mosquitto MQTT and Zigbee2MQTT with USB passthrough</description><content:encoded><![CDATA[<p>I run HomeAssistant Core on FreeBSD inside a jail managed with BastilleBSD — no Docker, no VM, just a lightweight VNET jail with its own IP on the LAN. This post covers the full setup: three jails, a bootstrap script, USB passthrough for Zigbee, and WiFi devices on the same subnet.</p>
<h2 id="architecture">Architecture</h2>
<pre tabindex="0"><code>FreeBSD 15.1-RELEASE Host
│
├── homeassistant (192.168.2.50)  — HA Core :8123
├── mosquitto    (192.168.2.52)  — MQTT broker :1883
└── zigbee2mqtt  (192.168.2.51)  — Zigbee2MQTT, Sonoff USB passthrough
</code></pre><p>All three jails are VNET on the same <code>/24</code> subnet. HA Core talks to Mosquitto over MQTT, Zigbee2MQTT publishes device states to Mosquitto, and HA subscribes. Shelly devices connect directly over WiFi and are auto-discovered by HA on the LAN.</p>
<h2 id="why-jails">Why jails?</h2>
<ul>
<li>Native FreeBSD — no Docker overlay, no Linux emulation</li>
<li>VNET gives each jail a real IP on the LAN — devices discover HA directly</li>
<li>ZFS snapshots for quick rollbacks before upgrades</li>
<li>Each service in its own jail — clean isolation, restart one without affecting others</li>
</ul>
<h2 id="creating-the-jails">Creating the jails</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bastille create -V homeassistant 15.1-RELEASE 192.168.2.50/24 vtnet0
</span></span><span class="line"><span class="cl">bastille create -V mosquitto 15.1-RELEASE 192.168.2.52/24 vtnet0
</span></span><span class="line"><span class="cl">bastille create -V zigbee2mqtt 15.1-RELEASE 192.168.2.51/24 vtnet0
</span></span></code></pre></div><p>The <code>-V</code> flag gives each jail a VNET interface with its own IP and routing table — they live on the same broadcast domain as the host.</p>
<h2 id="homeassistant-jail">HomeAssistant jail</h2>
<p>A bootstrap script handles the full setup:</p>
<ul>
<li><strong>Repository</strong>: <a href="https://codeberg.org/dkade/BSD/src/branch/main/FreeBSD/install_ha_freebsd.sh">codeberg.org/dkade/BSD</a></li>
<li><strong>Method</strong>: Python 3.14 virtual environment under <code>/usr/local/etc/homeassistant/venv</code></li>
<li><strong>User</strong>: dedicated <code>hass</code> system user</li>
<li><strong>Service</strong>: FreeBSD rc.d script using <code>daemon -u hass</code></li>
<li><strong>Enable</strong>: <code>sysrc homeassistant_enable=YES</code></li>
</ul>
<p>What the script does:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Inside the jail as root</span>
</span></span><span class="line"><span class="cl">fetch https://codeberg.org/dkade/BSD/raw/branch/main/FreeBSD/install_ha_freebsd.sh
</span></span><span class="line"><span class="cl">sh install_ha_freebsd.sh
</span></span></code></pre></div><p>It installs system packages (<code>python314</code>, <code>gcc12</code>, <code>rust</code>, <code>dbus</code>, <code>libffi</code>, <code>openssl</code>, etc.), creates a venv, and installs <code>homeassistant</code> along with <code>numpy</code>, <code>zlib_ng</code>, and <code>isal</code> for performance. The rc.d script starts HA as the <code>hass</code> user and listens on port 8123.</p>
<p>After first boot, complete the onboarding at <code>http://192.168.2.50:8123</code>.</p>
<h2 id="mosquitto-jail">Mosquitto jail</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bastille console mosquitto
</span></span><span class="line"><span class="cl">pkg install mosquitto
</span></span><span class="line"><span class="cl">sysrc <span class="nv">mosquitto_enable</span><span class="o">=</span>YES
</span></span><span class="line"><span class="cl">service mosquitto start
</span></span></code></pre></div><p>No authentication is needed on a local subnet — configure <code>listener 1883 192.168.2.52</code> in <code>/usr/local/etc/mosquitto/mosquitto.conf</code> to bind to the jail IP.</p>
<h2 id="zigbee2mqtt-jail">Zigbee2MQTT jail</h2>
<p>This jail needs access to the Sonoff Zigbee coordinator plugged into the host.</p>
<h3 id="usb-passthrough-with-devfs">USB passthrough with devfs</h3>
<p>On the <strong>host</strong> (<code>/etc/devfs.rules</code>):</p>
<pre tabindex="0"><code>[bastille_usb=101]
add path &#39;usbctl&#39; mode 0660
add path &#39;usb/*&#39; mode 0660
add path &#39;ugen*&#39; mode 0660
add path &#39;cuaU*&#39; mode 0660
add path &#39;ttyU*&#39; mode 0660
</code></pre><p>Set the rule in <code>/usr/local/bastille/jails/zigbee2mqtt/jail.conf</code>:</p>
<pre tabindex="0"><code>devfs_ruleset = &#34;bastille_usb&#34;;
</code></pre><p>Then find the Sonoff device:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># On the host</span>
</span></span><span class="line"><span class="cl">ls /dev/cuaU*
</span></span><span class="line"><span class="cl"><span class="c1"># /dev/cuaU0 &lt;- this is the Sonoff</span>
</span></span></code></pre></div><p>Restart the jail and you should see the device inside:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bastille restart zigbee2mqtt
</span></span><span class="line"><span class="cl">bastille console zigbee2mqtt
</span></span><span class="line"><span class="cl">ls /dev/cuaU*
</span></span></code></pre></div><h3 id="installing-and-configuring">Installing and configuring</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bastille console zigbee2mqtt
</span></span><span class="line"><span class="cl">pkg install node npm mosquitto-libs
</span></span><span class="line"><span class="cl">npm install -g zigbee2mqtt
</span></span></code></pre></div><p>Create <code>/usr/local/etc/zigbee2mqtt/configuration.yaml</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">mqtt</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">server</span><span class="p">:</span><span class="w"> </span><span class="l">mqtt://192.168.2.52:1883</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">serial</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l">/dev/cuaU0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">frontend</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">8080</span><span class="w">
</span></span></span></code></pre></div><p>rc.d script at <code>/usr/local/etc/rc.d/zigbee2mqtt</code> to start via <code>daemon</code>, then <code>sysrc zigbee2mqtt_enable=YES &amp;&amp; service zigbee2mqtt start</code>.</p>
<h2 id="device-integration">Device integration</h2>
<ul>
<li><strong>Shelly</strong> (WiFi): connect them to your WiFi. HA auto-discovers them via the LAN once the Shelly integration is added in the UI.</li>
<li><strong>Zigbee</strong> (Sonoff sensors, bulbs, etc.): pair through the Zigbee2MQTT frontend (<code>http://192.168.2.51:8080</code>). HA receives device states via MQTT auto-discovery.</li>
</ul>
<h2 id="upgrading">Upgrading</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># HA Core</span>
</span></span><span class="line"><span class="cl">bastille console homeassistant
</span></span><span class="line"><span class="cl">service homeassistant stop
</span></span><span class="line"><span class="cl">su -l hass -c <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="s1">&#39;HOME=/usr/local/etc/homeassistant PIP_CACHE_DIR=/tmp/pip-cache \
</span></span></span><span class="line"><span class="cl"><span class="s1">   /usr/local/etc/homeassistant/venv/bin/pip install --upgrade homeassistant&#39;</span>
</span></span><span class="line"><span class="cl">service homeassistant start
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># zigbee2mqtt</span>
</span></span><span class="line"><span class="cl">bastille console zigbee2mqtt
</span></span><span class="line"><span class="cl">service zigbee2mqtt stop
</span></span><span class="line"><span class="cl">npm update -g zigbee2mqtt
</span></span><span class="line"><span class="cl">service zigbee2mqtt start
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># mosquitto</span>
</span></span><span class="line"><span class="cl">bastille console mosquitto
</span></span><span class="line"><span class="cl">pkg upgrade mosquitto
</span></span><span class="line"><span class="cl">service mosquitto restart
</span></span></code></pre></div><h2 id="gotchas">Gotchas</h2>
<ul>
<li><strong>Python compilation</strong>: HA Core compiles C and Rust extensions during <code>pip install</code>. Make sure <code>gcc12</code>, <code>rust</code>, <code>libffi</code>, and <code>openssl</code> are installed in the jail before installing HA.</li>
<li><strong>dbus</strong>: HA Core expects D-Bus to be running (<code>service dbus start</code>). The rc.d script has <code>REQUIRE: dbus</code>, so dbus starts first.</li>
<li><strong>USB devfs</strong>: The devfs ruleset must be applied <em>before</em> the jail starts. Double-check the ruleset number matches in both <code>/etc/devfs.rules</code> and the jail config.</li>
<li><strong>VNET routing</strong>: If jails can&rsquo;t reach the internet for <code>pkg install</code>, check that <code>gateway_enable=&quot;YES&quot;</code> is set on the host and NAT/pf is configured for the VNET subnet.</li>
<li><strong>Persistent pip cache</strong>: The script sets <code>PIP_CACHE_DIR=/tmp/pip-cache</code> so you don&rsquo;t re-download wheels on every upgrade.</li>
</ul>
<h2 id="summary">Summary</h2>
<p>Three FreeBSD jails managed with BastilleBSD running HA Core, Mosquitto, and Zigbee2MQTT — each with its own IP, rc.d service, and clean isolation. The bootstrap script at <code>codeberg.org/dkade/BSD</code> automates the HA jail from scratch, and the rest is just standard FreeBSD package management.</p>
<hr>
<p><em>Disclaimer: I use AI as a productivity tool. For a senior engineer, AI is incredibly powerful as one can focus on the solution design and conceptualization and leave the boring part that is implementation to the AI.</em></p>
]]></content:encoded></item><item><title>Tips and lessons learnt by using AWS FMS and WAFv2</title><link>https://dkade.com/posts/aws_tips_waf_fms/</link><pubDate>Thu, 11 Mar 2021 00:00:00 +0000</pubDate><author>dkade@dkade.com (Daniel Loureiro)</author><guid>https://dkade.com/posts/aws_tips_waf_fms/</guid><description>&lt;ul&gt;
&lt;li&gt;Properly plan for your WAF logs, this will be the hardest part;&lt;/li&gt;
&lt;li&gt;Logs are activated per WebACL so each account needs to have a properly configured Kinesis Data Firehose. It is possible to enable the logs from FMS&lt;/li&gt;
&lt;li&gt;When creating Cloudformation stack make sure you make resources dependent on another or WAF will quickly rate limit Cloudformation and your stack will fail&lt;/li&gt;
&lt;li&gt;Use JSON in Cloudformation if you have accounts starting with 0. PyYAML has a &lt;a href="https://github.com/yaml/pyyaml/issues/98"&gt;bug&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Instead of Cloudformation you can use Terraform (when I started building the solution this wasn&amp;rsquo;t possible)&lt;/li&gt;
&lt;li&gt;Before activating an account on a FMS Policy, make sure that account has AWS Config enabled&lt;/li&gt;
&lt;li&gt;Use AWS Managed rules as they are created with standards in mind for example protecting from &lt;a href="https://owasp.org/www-project-top-ten/"&gt;OWASP Top 10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS WAF uses web ACL capacity units and you are limited to 1500, you can request increase but it&amp;rsquo;s not simple, so plan accordingly because if you need to change the WCU capacity of a Rule group you have to create a new one and delete the old one&lt;/li&gt;
&lt;li&gt;Rate limit rules can ONLY be added to WebACLs and are related to that WebACL. There is no option at the moment to add them to FMS, we are working with AWS to change this;&lt;/li&gt;
&lt;/ul&gt;</description><content:encoded><![CDATA[<ul>
<li>Properly plan for your WAF logs, this will be the hardest part;</li>
<li>Logs are activated per WebACL so each account needs to have a properly configured Kinesis Data Firehose. It is possible to enable the logs from FMS</li>
<li>When creating Cloudformation stack make sure you make resources dependent on another or WAF will quickly rate limit Cloudformation and your stack will fail</li>
<li>Use JSON in Cloudformation if you have accounts starting with 0. PyYAML has a <a href="https://github.com/yaml/pyyaml/issues/98">bug</a></li>
<li>Instead of Cloudformation you can use Terraform (when I started building the solution this wasn&rsquo;t possible)</li>
<li>Before activating an account on a FMS Policy, make sure that account has AWS Config enabled</li>
<li>Use AWS Managed rules as they are created with standards in mind for example protecting from <a href="https://owasp.org/www-project-top-ten/">OWASP Top 10</a></li>
<li>AWS WAF uses web ACL capacity units and you are limited to 1500, you can request increase but it&rsquo;s not simple, so plan accordingly because if you need to change the WCU capacity of a Rule group you have to create a new one and delete the old one</li>
<li>Rate limit rules can ONLY be added to WebACLs and are related to that WebACL. There is no option at the moment to add them to FMS, we are working with AWS to change this;</li>
</ul>
]]></content:encoded></item><item><title>How OLX Europe Fights Millions of Bots with AWS</title><link>https://dkade.com/posts/olx_aws_post_/</link><pubDate>Mon, 08 Mar 2021 00:00:00 +0000</pubDate><author>dkade@dkade.com (Daniel Loureiro)</author><guid>https://dkade.com/posts/olx_aws_post_/</guid><description>&lt;p&gt;My latest work done in OLX was featured by AWS on their own blog! I&amp;rsquo;m really happy with it. I talk about using AWS Firewall Manager + WAFv2 and in house tools to fight attacks. A big kudos to &lt;a href="https://www.linkedin.com/in/gabrielsoltz/"&gt;Gabril Soltz&lt;/a&gt; for his amazing work with the WAFBot.&lt;/p&gt;
&lt;p&gt;Read more at -&amp;gt; &lt;a href="https://aws.amazon.com/blogs/architecture/field-notes-how-olx-europe-fights-millions-of-bots-with-aws/"&gt;https://aws.amazon.com/blogs/architecture/field-notes-how-olx-europe-fights-millions-of-bots-with-aws/&lt;/a&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p>My latest work done in OLX was featured by AWS on their own blog! I&rsquo;m really happy with it. I talk about using AWS Firewall Manager + WAFv2 and in house tools to fight attacks.  A big kudos to <a href="https://www.linkedin.com/in/gabrielsoltz/">Gabril Soltz</a> for his amazing work with the WAFBot.</p>
<p>Read more at -&gt; <a href="https://aws.amazon.com/blogs/architecture/field-notes-how-olx-europe-fights-millions-of-bots-with-aws/">https://aws.amazon.com/blogs/architecture/field-notes-how-olx-europe-fights-millions-of-bots-with-aws/</a></p>
]]></content:encoded></item></channel></rss>