<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://dofahy.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://dofahy.github.io/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-09-14T07:01:32+00:00</updated><id>https://dofahy.github.io/feed.xml</id><title type="html">Donal Fahy</title><subtitle>Donal Fahy is an IT consultant based in Ireland specialising in cybersecurity, software, networking and infrastructure.</subtitle><entry><title type="html">Dell Latitude 7450 Fan Cycling on Kubuntu</title><link href="https://dofahy.github.io/2026/09/05/post9.html" rel="alternate" type="text/html" title="Dell Latitude 7450 Fan Cycling on Kubuntu" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-14T07:00:41+00:00</updated><id>https://dofahy.github.io/2026/09/05/post9</id><content type="html" xml:base="https://dofahy.github.io/2026/09/05/post9.html"><![CDATA[<p>I recently ran into an extremely annoying problem with a Dell Latitude 7450 running Kubuntu: the laptop would repeatedly blast its fan at roughly 3000 RPM or more, even though the machine was doing almost nothing.</p>

<p>The laptop was sitting on a stand with the internal display off and an external 1920×1080 monitor running at 60 Hz. CPU utilization was very low, temperatures were around 40°C, and yet the fan would repeatedly do this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Fan OFF
    ↓
10–20 seconds
    ↓
Fan ~3000+ RPM
    ↓
about 1 minute
    ↓
Fan OFF
    ↓
repeat
</code></pre></div></div>

<p>The noise was much worse than the workload warranted.</p>

<p>The eventual solution was surprisingly simple:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>KDE Power Profile: power-saver
Intel EPP:          power
Turbo:              still enabled
Dell BIOS:          Quiet
Fan at idle:        0 RPM
</code></pre></div></div>

<p>The important part is that <strong>Turbo remained enabled</strong>. I did not have to sacrifice the CPU’s ability to boost when actually needed.</p>

<p>This post documents the diagnostics because they may also be useful to other Dell/Linux users who are experiencing apparently irrational fan behaviour.</p>

<h2 id="the-hardware-and-software">The hardware and software</h2>

<p>The system is:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Dell Latitude 7450
Intel® Core™ Ultra 5 125H (18 MB cache, 14 cores, 18 threads, 1.2 GHz to 3.0 GHz P-Core, 28W)
16 GB RAM
Intel Iris Xe
Kubuntu 26.04 LTS
KDE Plasma 6.6.6
Wayland
Kernel 7.0.0-31-generic
BIOS 1.32.0
</code></pre></div></div>

<p>The BIOS thermal mode was initially set to Optimized, with Turbo enabled. I also tested Dell’s Quiet thermal mode.</p>

<p>Neither Optimized nor Quiet stopped the fan cycling.</p>

<h2 id="the-first-useful-discovery-the-temperatures-were-not-actually-high">The first useful discovery: the temperatures were not actually high</h2>

<p>The initial <code class="language-plaintext highlighter-rouge">sensors</code> output looked approximately like this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CPU package:  40–41°C
CPU cores:    roughly 37–41°C
NVMe:         ~33°C
Wi-Fi:        ~28–29°C
Ambient:      ~30–31°C
Fan:          0 RPM or ~3300 RPM
</code></pre></div></div>

<p>When the fan was running at more than 3000 RPM, the CPU was still only around 41°C.</p>

<p>That immediately suggested that this was not a conventional situation where the CPU was getting hot and the fan was sensibly responding.</p>

<p>The fan was being extremely aggressive relative to the temperature.</p>

<h2 id="the-fan-appeared-to-have-a-hard-threshold">The fan appeared to have a hard threshold</h2>

<p>The pattern became clearer after watching the temperatures while the fan cycled.</p>

<p>With the normal Balanced power profile, the behaviour was essentially:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~39°C → fan off

~40–41°C → fan jumps to ~3000+ RPM

temperature falls

fan switches off

~20 seconds later the CPU reaches ~40–41°C again

fan jumps back on
</code></pre></div></div>

<p>So this looked very much like a threshold or hysteresis problem.</p>

<p>The striking part was how narrow the operating range was. The machine was spending its time crossing a very small temperature boundary and repeatedly triggering a relatively high fan state.</p>

<p>Changing the Dell BIOS thermal mode to Quiet did not eliminate the behaviour.</p>

<h2 id="was-linux-fan-control-software-responsible">Was Linux fan-control software responsible?</h2>

<p>The next step was to find out whether something in Linux was explicitly controlling the fan.</p>

<p>There was no <code class="language-plaintext highlighter-rouge">fancontrol</code>, <code class="language-plaintext highlighter-rouge">i8kmon</code>, or NBFC process running.</p>

<p>The only obvious thermal daemon was:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>thermald
</code></pre></div></div>

<p>I stopped it:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>systemctl stop thermald
</code></pre></div></div>

<p>The fan behaviour did not change.</p>

<p>That ruled out <code class="language-plaintext highlighter-rouge">thermald</code> as the source of the problem, at least in this configuration.</p>

<h2 id="the-dell-smm-interface-was-interesting">The Dell SMM interface was interesting</h2>

<p>Linux exposed this device:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dell_smm-virtual-0
</code></pre></div></div>

<p>with values such as:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fan1:   3343 RPM
pwm1:   64% MANUAL CONTROL
</code></pre></div></div>

<p>and, when the fan was off:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fan1:   0 RPM
pwm1:   0% MANUAL CONTROL
</code></pre></div></div>

<p>The Dell SMM hwmon driver documentation is worth reading here because its behaviour is <strong>not the same as a normal PC PWM controller</strong>.</p>

<p>The Linux driver supports Dell-specific fan states and can expose the fan through the Linux thermal framework. Its documentation also explains that Dell’s SMM interface is reverse-engineered and warns that some undocumented SMM commands can have severe side effects.
That is an important lesson: don’t assume that:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo </span>0 <span class="o">&gt;</span> pwm1
</code></pre></div></div>

<p>means the same thing on a Dell laptop that it means on a normal PWM-controlled fan.</p>

<p>In this case, trying to write:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo </span>0 | <span class="nb">sudo tee</span> /sys/class/hwmon/hwmon6/pwm1
</code></pre></div></div>

<p>did not solve anything. The value simply returned to the previous Dell SMM state.</p>

<p>Likewise, the interface reported:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pwm1_enable = 1
</code></pre></div></div>

<p>but attempting the commonly documented:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo </span>2 | <span class="nb">sudo tee</span> /sys/class/hwmon/hwmon6/pwm1_enable
</code></pre></div></div>

<p>returned:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Invalid argument
</code></pre></div></div>

<p>This was a useful warning not to keep guessing at Dell SMM control values.</p>

<h2 id="the-decisive-test-remove-the-dell-smm-hwmon-module">The decisive test: remove the Dell SMM hwmon module</h2>

<p>The Dell SMM hwmon module was loaded:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dell_smm_hwmon
</code></pre></div></div>

<p>I temporarily removed it:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>modprobe <span class="nt">-r</span> dell_smm_hwmon
</code></pre></div></div>

<p>The fan <strong>continued cycling</strong>.</p>

<p>That was an important result.</p>

<p>It meant that the noisy fan behaviour was not simply caused by the Linux <code class="language-plaintext highlighter-rouge">dell_smm_hwmon</code> driver continuously commanding the fan.</p>

<p>After unloading the module, the Dell DDV sensor still reported the fan:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dell_ddv-virtual-0

CPU Fan: 3236 RPM
</code></pre></div></div>

<p>and later:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CPU Fan: 0 RPM
</code></pre></div></div>

<p>and later again:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CPU Fan: 2224 RPM
</code></pre></div></div>

<p>So the underlying Dell firmware/embedded-controller behaviour was still present.</p>

<p>I then restored the module with:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>modprobe dell_smm_hwmon
</code></pre></div></div>

<h2 id="the-breakthrough-intel-epp--power-saver">The breakthrough: Intel EPP / Power Saver</h2>

<p>The machine was using Intel’s <code class="language-plaintext highlighter-rouge">intel_pstate</code> driver:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>active
</code></pre></div></div>

<p>and Turbo was enabled:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>no_turbo = 0
</code></pre></div></div>

<p>The CPU exposed these Energy Performance Preference choices:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>default
performance
balance_performance
balance_power
power
</code></pre></div></div>

<p>The Linux <code class="language-plaintext highlighter-rouge">intel_pstate</code> documentation explains that, on systems using hardware-managed P-states, the Energy Performance Preference is a hint to the CPU’s internal performance-selection logic. Higher energy-saving preference biases the CPU toward efficiency rather than maximum performance.</p>

<p>I changed the KDE power profile to:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>power-saver
</code></pre></div></div>

<p>This resulted in the CPU policies reporting:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>energy_performance_preference = power
</code></pre></div></div>

<p>while:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>intel_pstate = active
no_turbo = 0
</code></pre></div></div>

<p>In other words:</p>

<p><strong>Turbo was still allowed.</strong></p>

<p>The important difference was how aggressively the CPU behaved during light workloads.</p>

<h2 id="and-the-fan-stopped-cycling">And the fan stopped cycling</h2>

<p>This was the result that finally solved the problem.</p>

<p>Under the previous Balanced configuration, the machine repeatedly crossed the fan trigger:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>39°C → 40–41°C → fan
</code></pre></div></div>

<p>Under Power Saver, the laptop could sit at:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CPU:     43°C
Fan:      0 RPM
</code></pre></div></div>

<p>and later:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CPU:     47°C
Fan:      0 RPM
</code></pre></div></div>

<p>That is the crucial observation.</p>

<p>The fan was not simply turning on because the CPU reached 40°C.</p>

<p>The CPU could reach 47°C and the fan could remain completely off.</p>

<p>The change was the processor’s power/performance behaviour, not simply a lower temperature.</p>

<p>This strongly suggests that the Balanced profile was allowing short performance/power excursions that interacted badly with the Dell firmware’s fan-control behaviour. Those excursions were enough to repeatedly trigger the noisy fan state.</p>

<p>With the stronger energy-saving preference, the CPU stopped bouncing through whatever condition was causing the firmware to engage the fan.</p>

<h2 id="my-final-configuration">My final configuration</h2>

<p>For this particular Latitude 7450, the configuration that eliminated the noise was:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Dell BIOS thermal mode:   Quiet
Kubuntu power profile:    power-saver
intel_pstate:             active
Intel EPP:                power
Turbo:                    enabled
</code></pre></div></div>

<p>The laptop can still boost when needed because Turbo is not disabled.</p>

<p>This is therefore very different from simply putting the CPU into a permanently low-performance mode.</p>

<p>The goal is not:</p>

<blockquote>
  <p>Never let the CPU run fast.</p>
</blockquote>

<p>The goal is:</p>

<blockquote>
  <p>Don’t let trivial desktop activity repeatedly trigger an unnecessarily aggressive fan state.</p>
</blockquote>

<h2 id="what-other-latitude-7450-owners-should-check">What other Latitude 7450 owners should check</h2>

<p>If a Latitude 7450 is exhibiting similar behaviour under Linux, I would start with temperature and power-management diagnostics rather than immediately trying to override the fan.</p>

<p>Check the thermal readings:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sensors
</code></pre></div></div>

<p>Look specifically at:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Package id 0
CPU Fan
NVMe
Dell SMM temperatures
</code></pre></div></div>

<p>Check whether <code class="language-plaintext highlighter-rouge">thermald</code> is running:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl status thermald
</code></pre></div></div>

<p>Check the Intel P-state driver:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> /sys/devices/system/cpu/intel_pstate/status
</code></pre></div></div>

<p>Check whether Turbo is disabled:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> /sys/devices/system/cpu/intel_pstate/no_turbo
</code></pre></div></div>

<p>Check the available Intel energy/performance preferences:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> /sys/devices/system/cpu/cpufreq/policy<span class="k">*</span>/energy_performance_available_preferences
</code></pre></div></div>

<p>Check the current setting:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> /sys/devices/system/cpu/cpufreq/policy<span class="k">*</span>/energy_performance_preference
</code></pre></div></div>

<p>On my machine, the available options included:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>default performance balance_performance balance_power power
</code></pre></div></div>

<p>and setting the KDE profile to Power Saver resulted in:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>power
</code></pre></div></div>

<p>across the CPU policies.</p>

<p>The Linux kernel documentation specifically recommends keeping energy/performance hints consistent across CPUs when possible, because tasks can migrate between CPUs.</p>

<h2 id="a-possible-middle-ground">A possible middle ground</h2>

<p>Full Power Saver may not be necessary for everyone.</p>

<p>On my 7450, the CPU supports:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>balance_power
</code></pre></div></div>

<p>as well as:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>power
</code></pre></div></div>

<p>That suggests a useful experiment for somebody who wants more responsiveness than full Power Saver but still wants to avoid triggering the fan.</p>

<p>For a temporary test:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>f <span class="k">in</span> /sys/devices/system/cpu/cpufreq/policy<span class="k">*</span>/energy_performance_preference<span class="p">;</span> <span class="k">do
    </span><span class="nb">echo </span>balance_power | <span class="nb">sudo tee</span> <span class="s2">"</span><span class="nv">$f</span><span class="s2">"</span> <span class="o">&gt;</span>/dev/null
<span class="k">done</span>
</code></pre></div></div>

<p>Then watch the fan over several minutes.</p>

<p>If the fan remains quiet, <code class="language-plaintext highlighter-rouge">balance_power</code> may provide a better performance/noise compromise.</p>

<p>If the fan starts the old cycle again, <code class="language-plaintext highlighter-rouge">power</code> is the more reliable setting for this particular machine.</p>

<p>I would treat this as a per-machine experiment rather than a universal rule.</p>

<h2 id="dont-blindly-experiment-with-dell-smm-commands">Don’t blindly experiment with Dell SMM commands</h2>

<p>This deserves emphasis.</p>

<p>Linux’s Dell SMM documentation states that the SMM interface was reverse-engineered because Dell does not publish the necessary documentation. It also explicitly warns that some automatic-fan-control commands can have severe side effects on machines that do not support them.</p>

<p>The documentation also describes two different mechanisms for returning fan control to the BIOS, depending on the machine. A <code class="language-plaintext highlighter-rouge">pwm1_enable=2</code> solution therefore cannot simply be assumed to work on every Dell.</p>

<p>In my case, the attempted <code class="language-plaintext highlighter-rouge">pwm1_enable=2</code> write was rejected, so I stopped experimenting with undocumented SMM fan states.</p>

<p>That was the right decision.</p>

<h2 id="bios-updates-still-matter">BIOS updates still matter</h2>

<p>Dell’s own troubleshooting documentation recommends checking the system BIOS when investigating fan noise or thermal problems.</p>

<p>My 7450 was already running BIOS <strong>1.32.0</strong>, so this was not a case of simply needing an old BIOS to be updated.</p>

<p>Dell continues to publish BIOS updates for the Latitude 7450, so owners experiencing different symptoms should still check Dell’s current support page before assuming the firmware behaviour is fixed or identical to another machine.</p>

<h2 id="conclusion">Conclusion</h2>

<p>The important finding from this investigation was not a magical fan command.</p>

<p>It was discovering that the fan problem was strongly coupled to <strong>CPU power/performance behaviour</strong> rather than simply CPU temperature.</p>

<p>On my Latitude 7450:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Balanced + Quiet
    ↓
CPU repeatedly crosses a narrow operating point
    ↓
fan repeatedly jumps to ~3000+ RPM
    ↓
noise
</code></pre></div></div>

<p>Changing to:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Power Saver
Intel EPP = power
Turbo still enabled
</code></pre></div></div>

<p>produced:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CPU can reach ~47°C
    ↓
fan remains at 0 RPM
    ↓
silence
</code></pre></div></div>

<p>For anyone with a Dell laptop running Kubuntu, this is therefore worth trying before resorting to aggressive fan-control hacks.</p>

<p>The practical lesson is:</p>

<p><strong>When a Dell laptop’s fan is cycling on and off at low temperatures, look at the CPU’s Energy Performance Preference and power profile, not just CPU utilization and temperature.</strong></p>

<p>On this Latitude 7450, putting Intel’s EPP into its <code class="language-plaintext highlighter-rouge">power</code> setting solved the problem without disabling Turbo.</p>]]></content><author><name>Donal Fahy</name></author><category term="vpn" /><category term="business" /><category term="network" /><summary type="html"><![CDATA[Dell Latitude 7450 Fan Cycling on Kubuntu]]></summary></entry><entry><title type="html">Lessons learned from trying to create a VPN provider business</title><link href="https://dofahy.github.io/2026/09/04/post8.html" rel="alternate" type="text/html" title="Lessons learned from trying to create a VPN provider business" /><published>2026-09-04T00:00:00+00:00</published><updated>2026-09-14T07:00:41+00:00</updated><id>https://dofahy.github.io/2026/09/04/post8</id><content type="html" xml:base="https://dofahy.github.io/2026/09/04/post8.html"><![CDATA[<p>When I started IrishVPN, I had two objectives.</p>

<p>The first was: build a VPN service that I would actually want to use.</p>

<p>The second was: find out how many people will purchase it.</p>

<p>Rather than simply deploying a VPN server on a rented VPS and calling it a day, I wanted to understand what was involved in operating an Internet-facing service from end to end. That meant networking, routing, isolation, access control, hardening, monitoring, key management, and, importantly, thinking about what would happen when something went wrong. Also, doing it all on a budget of about €10 (the price of a domain).</p>

<p>I also thought I might turn it into a small business.</p>

<p>That part did not exactly go according to plan.</p>

<p>The service has attracted very few customers. In practice, I get less than one customer per month on average. Technically, however, I have been very happy with the result. In some respects I prefer using my own VPN to several of the large commercial VPN providers I have tried.</p>

<p>That contrast taught me something useful: building a good security product and building a successful security business are two very different problems.</p>

<h2 id="the-technical-problem-was-the-part-i-enjoyed">The technical problem was the part I enjoyed</h2>

<p>The most interesting part of the project was never the website or the payment system. It was designing the infrastructure.</p>

<p>Running a VPN means deliberately putting a service on the edge of a network and allowing untrusted devices to connect to it. That creates an obvious security problem if the VPN infrastructure is allowed to interact freely with the rest of the network.</p>

<p>I therefore treated the VPN environment as a separate trust domain rather than simply another machine on my home LAN.</p>

<p>The architecture uses Layer-3 separation and multiple security controls to keep the VPN service isolated from my normal devices and management environment. The goal was straightforward: if the VPN host were compromised, compromising the VPN should not automatically mean compromising everything else in the house.</p>

<p>That sounds obvious, but implementing it properly forces you to think about details that are easy to ignore in a lab environment.</p>

<p>What networks can communicate with each other?</p>

<p>Which routes should exist?</p>

<p>What happens if a firewall rule is accidentally too permissive?</p>

<p>How is administration performed without unnecessarily exposing management interfaces?</p>

<p>What happens when a component is compromised?</p>

<p>Which systems should trust VPN traffic, and which should treat it as untrusted traffic?</p>

<p>Those questions became more interesting once there were real external users connecting to the service.</p>

<p>A security architecture is much easier to design when the only traffic comes from you. The moment strangers are using it, assumptions have to become explicit.</p>

<h2 id="a-vpn-provider-is-also-an-interesting-threat-modeling-exercise">A VPN provider is also an interesting threat-modeling exercise</h2>

<p>A VPN service sits in an unusual position.</p>

<p>Clients connect to it because they want to trust it with their traffic. At the same time, from the perspective of the infrastructure, those clients are effectively untrusted Internet users.</p>

<p>That creates an interesting boundary.</p>

<p>I had to think not only about protecting the VPN from the Internet, but also about protecting the rest of my infrastructure from the VPN.</p>

<p>This led me towards a principle that has become increasingly important in my thinking about security:</p>

<p><strong>Do not grant trust simply because two systems happen to be on the same physical network.</strong></p>

<p>The physical location of a device tells you very little about what it should be allowed to access.</p>

<p>The project gave me a practical environment in which to apply that principle. Segmentation, routing restrictions, firewall policy, administrative isolation, service hardening and access controls were no longer abstract concepts from a security course. They were things I had to make work on a system that was actually exposed to the Internet.</p>

<h2 id="the-hardest-problem-wasnt-technical">The hardest problem wasn’t technical</h2>

<p>The technical side was satisfying.</p>

<p>The business side was much harder.</p>

<p>Consumers already have a huge number of VPN providers to choose from. Many are backed by large companies, have substantial advertising budgets, and are household names within the VPN market.</p>

<p>A small independent service has an obvious disadvantage: trust.</p>

<p>When someone sees a VPN provider they have never heard of, the first question is not necessarily “how good is the encryption?”</p>

<p>It is often:</p>

<p><strong>Why should I trust you?</strong></p>

<p>That is a difficult question for a small provider to answer.</p>

<p>People are being asked to route their Internet traffic through infrastructure they do not control and operated by a company they have never heard of. The fact that the underlying technology is sound does not automatically make the product trustworthy.</p>

<p>I learned that technical credibility and consumer trust are separate things.</p>

<p>A technically competent service can still struggle to acquire customers because customers cannot easily evaluate the competence behind it.</p>

<h2 id="competing-with-free-vpn-providers">Competing with “free” VPN providers</h2>

<p>When consumers feel they are getting the same service for free, there is obviously a challenge to convince them otherwise.</p>

<p>There are countless free and extremely cheap VPN services available. Some users will happily choose one despite legitimate concerns about how those services make money.</p>

<p>From a purely technical perspective, this can be frustrating.</p>

<p>You can spend considerable time designing a carefully isolated and hardened system and discover that your potential customer would rather use a free application they downloaded five minutes ago.</p>

<p>But that is not really a technical problem.</p>

<p>It is a product problem.</p>

<p>Users are not purchasing a firewall architecture. They are purchasing an outcome, and they need to believe that the provider behind that outcome is trustworthy.</p>

<p>That means branding, reputation, transparency, support, convenience and perceived legitimacy can matter just as much as the underlying infrastructure.</p>

<h2 id="building-a-service-taught-me-more-than-building-a-lab">Building a service taught me more than building a lab</h2>

<p>One of the most valuable parts of the project was that it was not purely theoretical.</p>

<p>There is a difference between completing a security exercise and operating an exposed service.</p>

<p>A lab can be reset.</p>

<p>A production system has consequences.</p>

<p>Once other people depend on a service, relatively mundane questions become security questions.</p>

<p>How quickly do you patch it?</p>

<p>What happens if an update breaks something?</p>

<p>How do you recover?</p>

<p>What information do you log?</p>

<p>How much information should you log?</p>

<p>How do you protect administrative access?</p>

<p>What happens if credentials are compromised?</p>

<p>How do you notice unusual behaviour?</p>

<p>What is the blast radius of a compromised component?</p>

<p>What assumptions are you making about the environment that might turn out to be wrong?</p>

<p>These are the kinds of questions that make infrastructure security interesting to me.</p>

<h2 id="the-business-failed-the-project-didnt">The business failed. The project didn’t.</h2>

<p>From a commercial perspective, Irish-VPN has not become much of a business.</p>

<p>The number of customers is tiny, and I have no illusion that I have somehow disrupted the commercial VPN industry.</p>

<p>But that does not mean I consider the project unsuccessful.</p>

<p>The business experiment answered one question fairly clearly: there is not enough demand for my particular service in its current form to justify treating it as a serious commercial operation.</p>

<p>The engineering experiment answered a different question, and that one was much more successful.</p>

<p>I built and operated an Internet-facing VPN service on my own infrastructure. I designed a segmented network around it, considered the trust boundaries involved, hardened the systems, and exposed the service to real external users.</p>

<p>That experience is considerably more interesting to me than the number of subscriptions.</p>

<h2 id="what-i-would-do-differently">What I would do differently</h2>

<p>If I were starting again, I would separate the engineering objective from the business objective much earlier.</p>

<p>The engineering project is worth doing even if nobody buys it.</p>

<p>The business requires an entirely different set of capabilities: distribution, branding, customer acquisition, support, payment infrastructure, compliance, reputation and trust.</p>

<p>Those are not extensions of the technical problem. They are different problems.</p>

<p>I would also be much more explicit about what the project actually is.</p>

<p>There is a temptation with a project like this to make it look like a conventional VPN company. But that can obscure the most interesting part.</p>

<p>This is, fundamentally, a personal security and infrastructure engineering project that happens to provide VPN connectivity to a small number of other people.</p>

<p>I think that is a more honest description, and ultimately a more interesting one.</p>

<h2 id="the-biggest-lesson">The biggest lesson</h2>

<p>The biggest lesson from Irish-VPN is that good engineering does not automatically produce a good business.</p>

<p>That sounds obvious, but building something yourself makes the distinction much clearer.</p>

<p>I can control the architecture.</p>

<p>I can control the network design.</p>

<p>I can control the security controls.</p>

<p>I can control the software and infrastructure that I operate.</p>

<p>I cannot control whether people trust an unknown provider, whether they recognise the brand, or whether there is enough demand for the service to become commercially viable.</p>

<p>For me, that makes the project valuable even if it never becomes a significant business.</p>

<p>I set out to build a VPN provider.</p>

<p>What I actually built was a practical exercise in network security, infrastructure engineering and operating a service in the real world.</p>

<p>That was probably the more useful outcome.</p>]]></content><author><name>Donal Fahy</name></author><category term="vpn" /><category term="business" /><category term="network" /><summary type="html"><![CDATA[Lessons learned from trying to create a VPN provider business]]></summary></entry><entry><title type="html">Linux Firmware Security with fwupdmgr</title><link href="https://dofahy.github.io/2026/08/20/post7.html" rel="alternate" type="text/html" title="Linux Firmware Security with fwupdmgr" /><published>2026-08-20T00:00:00+00:00</published><updated>2026-09-14T07:00:41+00:00</updated><id>https://dofahy.github.io/2026/08/20/post7</id><content type="html" xml:base="https://dofahy.github.io/2026/08/20/post7.html"><![CDATA[<p>What is fwupdmgr? It is the Firmware Update Manager application found on Linux systems.
Firmware security is easy to ignore because most Linux security tooling starts above the firmware layer. Often admins will routinely check packages, services, kernel configuration, firewall rules and file permissions, while the firmware underneath all of it is treated as something that simply works.</p>

<p>That is the gap that <code class="language-plaintext highlighter-rouge">fwupd</code> and its Host Security ID (HSI) reporting are trying to address.</p>

<p>The Firmware Security page in the KDE kinfocenter program provides a useful way to turn a fairly technical set of firmware and kernel checks into something that can be understood and acted upon. Underneath the graphical presentation is the same security model exposed by <code class="language-plaintext highlighter-rouge">fwupdmgr security</code>, where fwupd evaluates a collection of host security attributes and assigns an HSI level plus, when appropriate, a runtime suffix. The HSI specification is intended to provide an end-user-verifiable view of platform firmware security. (<a href="https://bugs.kde.org/describecomponents.cgi?product=kinfocenter" title="Information Center (software and hardware details)">kinfocenter</a>)</p>

<p>On a client system, the initial assessment looked like this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HSI-4
✔ SMAP:                          Enabled
✘ Encrypted RAM:                 Disabled

Runtime Suffix -!
✔ CET OS Support:               Supported
✔ fwupd plug-ins:                Untainted
✔ UEFI db:                       Not found
✘ Linux kernel lockdown:         Disabled
✘ Linux swap:                    Unencrypted
✘ Linux kernel:                  Tainted
✘ UEFI secure boot:              Disabled

This system has HSI runtime issues.
 » https://fwupd.github.io/hsi.html#hsi-runtime-suffix

Host Security Events
  2026-08-07 20:25:49:  ✔ BIOS rollback protection changed: Disabled → Enabled
  2026-08-07 20:25:49:  ✔ Suspend-to-idle changed: Disabled → Enabled
  2026-05-30 08:49:20:  ✘ Suspend-to-idle changed: Enabled → Disabled
  2026-05-17 17:10:50:  ✔ TPM v2.0 changed: Not found → Found
  2026-04-03 18:38:18:  ✘ Kernel is tainted
</code></pre></div></div>

<p>The HSI number represents the core firmware security level. The runtime suffix represents security conditions that can change while the operating system is running. fwupd explicitly separates those two concepts: the core HSI level does not change simply because the OS configuration changes, but the runtime suffix can. (<a href="https://fwupd.github.io/libfwupdplugin/hsi.html" title="FwupdPlugin – 1.0: Host Security ID Specification">Fwupd</a>)</p>

<h2 id="what-hsi-4-means">What HSI-4 means</h2>

<p>fwupd defines HSI-4 as its “Secure State”. At this level the platform has a robust collection of firmware protections, including hardware-assisted encryption and execution protections where the platform supports them.</p>

<p>In the client’s case, the HSI-4 result was accompanied by:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>✘ Encrypted RAM: Disabled
</code></pre></div></div>

<p>The fwupd HSI specification describes DRAM memory encryption as using technologies such as Intel TME or AMD SME to protect data on the external memory bus. Where supported, this can reduce the risk of an attacker extracting memory contents through physical access to the memory subsystem. fwupd considers successful detection and activation of the feature a requirement for HSI-4 on systems where the test applies. (<a href="https://fwupd.github.io/libfwupdplugin/hsi.html" title="FwupdPlugin – 1.0: Host Security ID Specification">Fwupd</a>)</p>

<p>The client’s system reported:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Runtime Suffix -!
</code></pre></div></div>

<p>The exclamation mark means that fwupd detected a runtime security issue. The current HSI specification lists several conditions that can produce it, including Secure Boot being disabled, an untrusted or tainted kernel, kernel lockdown being disabled, unencrypted swap, and modified fwupd plug-ins. (<a href="https://fwupd.github.io/libfwupdplugin/linux-lockdown-README.html" title="FwupdPlugin – 1.0: Plugin: Linux Kernel Lockdown">Fwupd</a>)</p>

<p>That makes the runtime section particularly valuable for Linux administrators because it connects firmware security with the configuration of the currently running operating system.</p>

<p>In other words, a machine can have reasonably strong firmware protections and still have a weaker runtime security posture.</p>

<h2 id="how-i-reviewed-the-findings">How I reviewed the findings</h2>

<p>For the kernel taint state, I checked the kernel’s exported taint value:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> /proc/sys/kernel/tainted
</code></pre></div></div>

<p>and then looked at the kernel log for the reason:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dmesg | <span class="nb">grep</span> <span class="nt">-i</span> taint
dmesg | <span class="nb">grep</span> <span class="nt">-Ei</span> <span class="s1">'module|firmware|unsigned|taint'</span>
</code></pre></div></div>

<p>The issue was then identified as the integrated webcam driver.
It was signed when secure boot was enabled. After secure was disabled on the system, the driver was untrusted:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Kubuntu 26
   │
   ├── Secure Boot originally enabled
   │       └── MOK "dof-7340 Secure Boot Module Signature key"
   │
   ├── Secure Boot subsequently disabled
   │
   └── IPU6 DKMS installed
           │
           └── ov02c10.ko
                   │
                   ├── out-of-tree → O taint
                   └── signature not being trusted/required → E taint
</code></pre></div></div>

<p>For swap, I checked what was active:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>swapon <span class="nt">--show</span>
<span class="nb">cat</span> /proc/swaps
</code></pre></div></div>

<p>The fwupd Linux Swap plugin checks the currently available swap partitions and files and records whether they are encrypted. (<a href="https://fwupd.github.io/libfwupdplugin/linux-swap-README.html" title="FwupdPlugin – 1.0: Plugin: Linux Swap">Fwupd</a>)</p>

<p>In this case the system used “swap to file” and as the filesystem was unencrypted this was expected.</p>

<p>A dedicated swap partition used for hibernation functionality would also be flagged here if unencrypted.</p>

<p>Kernel lockdown was connected to the trusted boot configuration and was addressed as part of restoring Secure Boot.</p>

<p>The missing UEFI db result had to be interpreted in the context of the Secure Boot configuration.</p>

<p>Encrypted RAM was enabled in the BIOS.</p>

<h2 id="the-host-security-event-history-is-useful-too">The host security event history is useful too</h2>

<p>The event history gave a useful timeline.</p>

<p>It is more useful than a single snapshot because firmware security is not static.</p>

<p>For example, the TPM state changed from “Not found” to “Found”, BIOS rollback protection changed, and the suspend mode changed over time. That makes the history a primitive audit trail for platform-security configuration.</p>

<h2 id="conclusion">Conclusion</h2>

<p>The value of the Firmware Security page is that it provides a starting point for investigating the security of the machine beneath the operating system.
It provides firmware details that are normally buried in UEFI setup menus: rollback protection, Secure Boot, TPM state, memory protections, SPI protections, recovery and platform trust.
It also shows normal Linux runtime state: kernel lockdown, kernel taint, swap encryption and the trustworthiness of fwupd itself. These features make it a useful addition to a system security audit and to fix issues that are relevant to your threat model.</p>]]></content><author><name>Donal Fahy</name></author><category term="linux" /><category term="firmware" /><category term="fwupdmgr" /><summary type="html"><![CDATA[Linux Firmware Security with fwupdmgr]]></summary></entry><entry><title type="html">Revolut, Cash and the Limits of Digital Banking</title><link href="https://dofahy.github.io/2026/08/12/post6.html" rel="alternate" type="text/html" title="Revolut, Cash and the Limits of Digital Banking" /><published>2026-08-12T00:00:00+00:00</published><updated>2026-09-14T07:00:41+00:00</updated><id>https://dofahy.github.io/2026/08/12/post6</id><content type="html" xml:base="https://dofahy.github.io/2026/08/12/post6.html"><![CDATA[<p><i>This article was generated using GPT 5.6 Luna with reasoning enabled. I tried roughly 20 attempts at adjusting the prompt and requesting the model to evaluate and review it’s own output. Even then the article below is repetitive and omits a lot of content related to cash deposits and digital banking. I was left thinking I should have just taken the time to write it myself.</i></p>

<p>Revolut has stopped accepting cash deposits in Ireland, the UK and several other European markets. The Irish service was operating through Paysafe by March 2024: Revolut’s terms from 22 March 2024 set limits for Paysafe cash top-ups in Ireland of €1,000 per transaction, €2,250 per month and €10,000 per year. Revolut charged 2.5% for the service. The UK service was also provided through Paysafe and was publicly launched in 2024. Revolut withdrew the Irish service on 26 January 2026 and the UK service on 13 February. (<a href="https://cdn.revolut.com/terms_and_conditions/pdf/limits_for_paysafe_cash_top_ups_2f096f40_1.0.0_1711019320_en.pdf?utm_source=chatgpt.com" title="Limits for Paysafe cash top-ups">Revolut</a>)</p>

<p>The timing is notable. Revolut had invested in a way of bringing physical cash into a predominantly digital banking model, using Paysafe rather than building branches. The customer deposited cash through the Paysafe network and the resulting transaction was credited to the Revolut account. In the UK, Revolut said 71% of surveyed customers had deposited cash with another financial institution during the previous year and 34% wanted to do so monthly. (<a href="https://ir.paysafe.com/financial-info-and-filings/sec-filings/content/0000950170-24-125922/0000950170-24-125922.pdf?utm_source=chatgpt.com" title="6-K - 11/13/2024 - Paysafe Ltd">Paysafe Ltd</a>)</p>

<p>Revolut has not explained why it withdrew the service. The obvious possibilities are operational cost, reliance on an external cash network, compliance requirements, fraud controls and relatively low demand compared with electronic funding. None is confirmed by Revolut, but all are relevant to the decision.</p>

<p>The AML question is not whether a cash deposit can be traced. It can. Paysafe provides a transaction record, and Revolut can associate the deposit with the customer’s account and monitor subsequent activity. The limitation is earlier in the chain. A transfer from another bank normally identifies the originating institution and account; a cash deposit records the deposit itself but does not necessarily tell Revolut how the customer originally obtained the notes. That distinction is relevant when a bank assesses whether activity is consistent with the customer’s profile and whether a transaction warrants further investigation.</p>

<p>The operational burden is more tangible. Revolut’s cash service depended on Paysafe and a retail network outside Revolut’s own infrastructure. The bank had to integrate the service into its account, payments, reconciliation and risk systems while relying on another company to handle the physical transaction. Removing the service removes those requirements. Revolut’s current Irish help page now lists bank transfer, debit card, Apple Pay and Google Pay as the remaining funding methods. (<a href="https://help.revolut.com/en-IE/help/adding-money/cash-deposits/?utm_source=chatgpt.com" title="How to make cash deposits | Revolut Ireland">Revolut</a>)</p>

<p>That does not make digital funding intrinsically safer. It changes the fraud environment. Account takeover, stolen credentials, social engineering, authorised-payment fraud and mule accounts can all operate without cash. Electronic transactions simply provide a larger body of structured data for automated monitoring and fraud detection.</p>

<p>The regulatory framework adds another consideration. EU financial institutions are subject to the Digital Operational Resilience Act, which places requirements on ICT risk and third-party risk. For a service delivered through an external payment provider, the relevant issue is not merely whether the provider can process transactions, but whether the bank can manage the resilience, security and regulatory risks associated with that dependency.</p>

<p>Revolut’s decision is therefore not evidence that cash is incompatible with fintech. Other digital financial services still support it. Chime, for example, operates without a conventional branch network but allows cash deposits through a large US retail network. N26 operates CASH26 in selected European markets, allowing customers to deposit and withdraw cash through participating retailers. The technological model is available; the providers have simply made different commercial and operational choices.</p>

<p>Those choices also have to be understood in jurisdictional terms. “Digital bank” is not a single legal category. Revolut’s Irish banking service is provided by Revolut Bank UAB through its Irish branch, while US fintechs such as Chime operate through partner banks. Banking licences, deposit protection, AML obligations, payment regulation, data protection and operational-resilience requirements therefore vary according to the entity and jurisdiction involved.</p>

<p>Cash makes those differences visible, but the same principle applies to almost every feature of a fintech account. What appears to the customer as one application may sit on top of several regulated entities, payment systems and third-party providers. Whether a provider accepts cash is one expression of the choices made about that underlying infrastructure.</p>

<p>Revolut has now chosen a narrower model in the affected markets. Customers can move money in electronically, but anyone holding physical cash may need another provider to convert it into electronic funds first.</p>

<p>The interesting part is not that Revolut has “gone digital”. It was digital before. The interesting part is that it tried supporting cash through a third-party network, operated the service for a relatively short period, and then removed it. That makes the decision a useful case study in fintech architecture: which parts of traditional banking a digital provider is prepared to reproduce, which it is prepared to outsource, and which it ultimately decides are not worth carrying.</p>]]></content><author><name>Donal Fahy</name></author><category term="fintech" /><category term="banking" /><summary type="html"><![CDATA[Revolut has discontinued accepting cash deposits]]></summary></entry><entry><title type="html">CSA CISO Community Initial Post-Mortem on OpenAI Model Breach</title><link href="https://dofahy.github.io/2026/08/05/post5.html" rel="alternate" type="text/html" title="CSA CISO Community Initial Post-Mortem on OpenAI Model Breach" /><published>2026-08-05T00:00:00+00:00</published><updated>2026-09-14T07:00:41+00:00</updated><id>https://dofahy.github.io/2026/08/05/post5</id><content type="html" xml:base="https://dofahy.github.io/2026/08/05/post5.html"><![CDATA[<p>This report on the Hugging Face breach by an OpenAI model gives an accurate account of what actually happened and contains expert guidance on how to navigate this emerging threat.
It provides key insights for CISOs looking for a defence strategy and what to do if their agents attack another company’s systems.</p>

<p><a href="/assets/pdfs/openai-hugging-face-initial-incident-report.pdf" target="_blank">Download the full report (PDF)</a></p>

<p>The latest version of this report can be found on the CSA site:<br />
https://cloudsecurityalliance.org/artifacts/hugging-face-ciso-post-mortem</p>]]></content><author><name>Donal Fahy</name></author><category term="CISO" /><category term="AI" /><category term="response" /><summary type="html"><![CDATA[CSA CISO Community Initial Post-Mortem on OpenAI Model Breach]]></summary></entry><entry><title type="html">Replace Your Sky or Vodafone Router</title><link href="https://dofahy.github.io/2026/07/27/post4.html" rel="alternate" type="text/html" title="Replace Your Sky or Vodafone Router" /><published>2026-07-27T00:00:00+00:00</published><updated>2026-09-14T07:00:41+00:00</updated><id>https://dofahy.github.io/2026/07/27/post4</id><content type="html" xml:base="https://dofahy.github.io/2026/07/27/post4.html"><![CDATA[<p>If your home has full-fibre broadband and a small fibre termination box on the wall with an Ethernet port, you can usually connect a suitable third-party router directly to it.</p>

<p>This lets you replace the ISP-supplied Sky Hub or Vodafone router with your own hardware for better Wi-Fi, stronger controls, VPN features, or more capable networking.</p>

<p>This guide applies to <strong>Sky Ireland</strong> and <strong>Vodafone Ireland</strong> full-fibre services where the fibre enters an ONT (Optical Network Terminal) and the ONT provides Ethernet to the ISP router.</p>

<h2 id="before-you-start">Before You Start</h2>

<p>Look for the wall-mounted unit where the fibre cable terminates. It is normally called an <strong>ONT</strong> and will have a fibre input and one or more Ethernet ports. The existing Sky or Vodafone router should be connected from that ONT’s Ethernet port to its WAN/Internet port.</p>

<p>Your replacement router must support:</p>

<ul>
  <li>PPPoE WAN connections</li>
  <li>802.1Q VLAN tagging on its WAN interface</li>
  <li>A gigabit Ethernet WAN port, or 2.5GbE if your broadband package exceeds 1Gbps</li>
</ul>

<p>Keep the ISP router somewhere safe. If you need technical support for a line problem, Sky or Vodafone may ask you to reconnect their supplied device while they test the service.</p>

<h2 id="physical-connection">Physical Connection</h2>

<ol>
  <li>Disconnect the Ethernet cable running from the ONT to the ISP router.</li>
  <li>Connect that cable to the <strong>WAN</strong> or <strong>Internet</strong> port on your own router.</li>
  <li>Open your router’s administration interface.</li>
  <li>Configure the WAN connection using the relevant ISP settings below.</li>
  <li>Save the configuration and allow a few minutes for the PPPoE session to establish.</li>
</ol>

<p>Do <strong>not</strong> disconnect or reset the fibre cable or ONT. The only cable you normally need to move is the Ethernet cable between the ONT and router.</p>

<h2 id="sky-ireland-configuration">Sky Ireland Configuration</h2>

<p>For Sky Ireland fibre, set the WAN connection to PPPoE and add VLAN ID 10.</p>

<table>
  <thead>
    <tr>
      <th>Setting</th>
      <th>Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Connection type</td>
      <td>PPPoE</td>
    </tr>
    <tr>
      <td>Username</td>
      <td><code class="language-plaintext highlighter-rouge">anything@skydsl</code></td>
    </tr>
    <tr>
      <td>Password</td>
      <td><code class="language-plaintext highlighter-rouge">anything</code></td>
    </tr>
    <tr>
      <td>WAN VLAN ID</td>
      <td><code class="language-plaintext highlighter-rouge">10</code></td>
    </tr>
    <tr>
      <td>MTU</td>
      <td><code class="language-plaintext highlighter-rouge">1492</code> initially</td>
    </tr>
    <tr>
      <td>DNS</td>
      <td>Automatic, or your preferred DNS provider</td>
    </tr>
  </tbody>
</table>

<p>Sky’s authentication is commonly reported to accept placeholder PPPoE credentials, while VLAN 10 is the important network setting.</p>

<p>After saving the configuration, the router should obtain a public IP address and show its WAN connection as active.</p>

<h2 id="vodafone-ireland-configuration">Vodafone Ireland Configuration</h2>

<p>Vodafone Ireland full fibre also uses PPPoE and WAN VLAN 10, but it uses fixed published PPPoE credentials.</p>

<table>
  <thead>
    <tr>
      <th>Setting</th>
      <th>Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Connection type</td>
      <td>PPPoE</td>
    </tr>
    <tr>
      <td>Username</td>
      <td><code class="language-plaintext highlighter-rouge">vodafone@vodafone.ie</code></td>
    </tr>
    <tr>
      <td>Password</td>
      <td><code class="language-plaintext highlighter-rouge">broadband</code></td>
    </tr>
    <tr>
      <td>WAN VLAN ID</td>
      <td><code class="language-plaintext highlighter-rouge">10</code></td>
    </tr>
    <tr>
      <td>MTU</td>
      <td><code class="language-plaintext highlighter-rouge">1492</code> initially</td>
    </tr>
    <tr>
      <td>DNS</td>
      <td>Automatic, or your preferred DNS provider</td>
    </tr>
  </tbody>
</table>

<p>The same physical arrangement applies: ONT Ethernet directly to your router’s WAN port.</p>

<p>You may encounter old Vodafone documentation referring to VPI and VCI values. Those relate to older DSL services over a telephone line and do not apply when you have an Ethernet connection from a fibre ONT.</p>

<h2 id="why-pppoe-is-used">Why PPPoE Is Used</h2>

<p>PPPoE—Point-to-Point Protocol over Ethernet—is an older but still common ISP access method. It creates an authenticated connection between your router and the provider’s network.</p>

<p>It does not make fibre broadband inherently less reliable. Connection stability depends far more on the fibre/ONT, ISP network, router firmware, power supply, and correct WAN configuration than on PPPoE itself.</p>

<p>PPPoE has a small framing overhead. Traditionally, this means an MTU of 1492 rather than the standard Ethernet MTU of 1500. In normal use, that difference is negligible for streaming, video calls, browsing, online gaming, and downloads.</p>

<h2 id="performance-considerations">Performance Considerations</h2>

<p>The main consideration is whether the router can process PPPoE at your line speed. PPPoE can require more router CPU work than a plain DHCP WAN connection, particularly at very high speeds.</p>

<p>For broadband packages up to around 1Gbps, a modern mid-range or high-performance router should normally be suitable. For multi-gigabit services, verify the manufacturer’s stated PPPoE throughput rather than relying only on its Ethernet port speed or Wi-Fi rating.</p>

<p>After installation, run a wired speed test and check the router’s CPU load. If speeds reach your subscribed rate without sustained high CPU use, the router is handling PPPoE correctly.</p>

<h2 id="troubleshooting">Troubleshooting</h2>

<p>If the connection does not come up, start with the basics:</p>

<ul>
  <li>Confirm the ONT Ethernet cable is in your router’s dedicated WAN port, not a LAN port.</li>
  <li>Confirm PPPoE—not DHCP or static IP—is selected.</li>
  <li>Confirm WAN VLAN ID is set to 10.</li>
  <li>Re-enter the username and password carefully.</li>
  <li>Set the MTU to 1492.</li>
  <li>Power-cycle the ONT and router: turn off both, wait about a minute, power on the ONT first, wait for it to settle, then power on the router.</li>
  <li>Check whether the router has received a WAN IP address and whether the PPPoE log reports authentication or VLAN errors.</li>
</ul>

<p>If you need to raise a fault with Sky or Vodafone, reconnect the original ISP router first. This makes it easier for support to verify whether the issue is with the broadband line or your own equipment.</p>

<h2 id="final-notes">Final Notes</h2>

<p>Replacing an ISP router does not change the underlying broadband service. The ONT remains the fibre endpoint, while your own router takes over the routing, Wi-Fi, firewall, and local-network duties.</p>

<h2 id="appendix-other-irish-providers-and-personal-routers">Appendix: Other Irish Providers and Personal Routers</h2>

<p>Your ability to replace an ISP router depends on the <strong>access technology</strong>, not only the retail brand.</p>

<p>If your service has a fibre ONT with an Ethernet port, a personal router can often connect directly to the ONT using the provider’s required WAN method, VLAN tag, and—where needed—PPPoE credentials. On cable, DSL, fixed-wireless, and mobile services, the ISP device may also perform a modem or radio function and may need to remain in place.</p>

<blockquote>
  <p><strong>Important:</strong> The configurations below are common reported settings, not a substitute for ISP support. Providers can use different settings across OpenEir, SIRO, NBI, legacy services, static-IP products, and newer packages. Keep the original router so that you can reconnect it for fault diagnosis.</p>
</blockquote>

<h3 id="virgin-media-ireland-a-different-model">Virgin Media Ireland: A Different Model</h3>

<p>Virgin Media differs from most OpenEir, SIRO and NBI fibre services. On its cable network, the Virgin Hub is not merely a Wi-Fi router: it also acts as the cable modem that connects and authenticates to Virgin’s network.</p>

<p>You would normally <strong>keep the Virgin Hub</strong>, enable <strong>Modem Mode</strong>, and connect your own router to it by Ethernet. Configure the personal router’s WAN as <strong>DHCP / Automatic IP</strong>—not PPPoE.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Virgin cable connection
        |
Virgin Hub in Modem Mode
        |
Ethernet
        |
Your router WAN port
        |
Your home network
</code></pre></div></div>

<p>In this arrangement, your router still controls your home network, including Wi-Fi, firewall rules, DNS, VPN, DHCP reservations, port forwarding, and local-network features. The Virgin Hub remains only as the network termination modem.</p>

<h3 id="other-providers">Other Providers</h3>

<table>
  <thead>
    <tr>
      <th>Provider</th>
      <th>Usual access network</th>
      <th style="text-align: right">Can a personal router connect directly to the ONT?</th>
      <th>Typical WAN configuration</th>
      <th>Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>eir</strong></td>
      <td>OpenEir FTTH</td>
      <td style="text-align: right">Usually yes</td>
      <td>DHCP/IPoE; VLAN 10 may be required</td>
      <td>DHCP/IPoE is generally preferable where available. PPPoE may be required for some static-IP or legacy configurations. If you use eir home phone/VoIP, keep the supplied router unless eir provides separate SIP details.</td>
    </tr>
    <tr>
      <td><strong>Digiweb</strong></td>
      <td>OpenEir, SIRO, NBI</td>
      <td style="text-align: right">Usually yes</td>
      <td>PPPoE; commonly VLAN 10</td>
      <td>Reported OpenEir credentials: <code class="language-plaintext highlighter-rouge">digiweb@nga.digiweb.ie</code> / <code class="language-plaintext highlighter-rouge">digiweb</code>. Reported SIRO credentials: <code class="language-plaintext highlighter-rouge">digiweb@siro.digiweb.ie</code> / <code class="language-plaintext highlighter-rouge">digiweb</code>. Confirm the correct details with Digiweb.</td>
    </tr>
    <tr>
      <td><strong>Pure Telecom</strong></td>
      <td>OpenEir, SIRO, NBI</td>
      <td style="text-align: right">Usually yes</td>
      <td>PPPoE or DHCP/IPoE; commonly VLAN 10</td>
      <td>Reported PPPoE credentials: <code class="language-plaintext highlighter-rouge">puretelecom@puretel.ie</code> / <code class="language-plaintext highlighter-rouge">broadband1</code>. Some installations may use DHCP/IPoE instead. Confirm with Pure Telecom.</td>
    </tr>
    <tr>
      <td><strong>Blacknight</strong></td>
      <td>Usually OpenEir; availability varies</td>
      <td style="text-align: right">Usually yes, on FTTH</td>
      <td>PPPoE; reported VLAN 15</td>
      <td>Reported credentials: <code class="language-plaintext highlighter-rouge">broadband@bk.network</code> / <code class="language-plaintext highlighter-rouge">broadband</code>. The reported VLAN is <strong>15</strong>, not the commonly seen VLAN 10, so do not copy settings from another provider. Confirm with Blacknight.</td>
    </tr>
    <tr>
      <td><strong>Fastcom</strong></td>
      <td>OpenEir, SIRO and/or NBI, depending on product</td>
      <td style="text-align: right">Often possible on FTTH</td>
      <td>Provider-specific</td>
      <td>Request the WAN type, VLAN ID and any PPPoE credentials from Fastcom before replacing its router.</td>
    </tr>
    <tr>
      <td><strong>Rural WiFi</strong></td>
      <td>FTTH and fixed-wireless products</td>
      <td style="text-align: right">Depends on product</td>
      <td>PPPoE, DHCP/IPoE or ISP CPE</td>
      <td>On FTTH with an Ethernet ONT, direct use may be possible. On fixed wireless, the outdoor radio/CPE must remain because it is part of the access connection.</td>
    </tr>
    <tr>
      <td><strong>Imagine</strong></td>
      <td>Fixed wireless / 4G / 5G</td>
      <td style="text-align: right">No, not in the fibre-ONT sense</td>
      <td>DHCP behind ISP CPE</td>
      <td>The installed outdoor/indoor radio equipment normally remains. Connect your router behind it, using bridge mode or IP passthrough if offered. Otherwise, use DMZ or accept double NAT.</td>
    </tr>
    <tr>
      <td><strong>Three Broadband</strong></td>
      <td>4G / 5G mobile</td>
      <td style="text-align: right">No ONT to replace</td>
      <td>SIM/APN connection</td>
      <td>A compatible unlocked 4G/5G router may work with the supplied SIM, subject to service terms and APN requirements. This is not PPPoE or fibre.</td>
    </tr>
    <tr>
      <td><strong>GoMo, 48, Clear Mobile</strong></td>
      <td>Mobile services</td>
      <td style="text-align: right">No ONT to replace</td>
      <td>SIM/APN connection</td>
      <td>These are mobile services rather than conventional fixed-fibre providers. A suitable unlocked SIM router may be possible, subject to plan and network restrictions.</td>
    </tr>
  </tbody>
</table>

<h3 id="choosing-the-right-wan-mode">Choosing the Right WAN Mode</h3>

<p>Use the WAN method specified by your retail ISP—not the method used by another provider on the same fibre network.</p>

<table>
  <thead>
    <tr>
      <th>WAN mode</th>
      <th>When it is normally used</th>
      <th>Router settings to expect</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>PPPoE</strong></td>
      <td>Common with many Irish fibre resellers</td>
      <td>PPPoE username, password, usually MTU 1492, and possibly a WAN VLAN</td>
    </tr>
    <tr>
      <td><strong>DHCP / IPoE</strong></td>
      <td>Used by some fibre services, including many standard eir setups</td>
      <td>Automatic/DHCP IP address; may still need a WAN VLAN</td>
    </tr>
    <tr>
      <td><strong>DHCP Option 61</strong></td>
      <td>Used by some provider and network combinations</td>
      <td>DHCP with a client identifier; router support varies</td>
    </tr>
    <tr>
      <td><strong>Bridge / Modem Mode</strong></td>
      <td>Cable, some DSL, and certain wireless gateways</td>
      <td>ISP modem/CPE stays connected; personal router receives its WAN address by DHCP</td>
    </tr>
    <tr>
      <td><strong>Double NAT / DMZ</strong></td>
      <td>When bridge mode is unavailable</td>
      <td>Personal router sits behind the ISP router; use DMZ to the personal router where possible</td>
    </tr>
  </tbody>
</table>

<h3 id="why-the-underlying-network-matters">Why the Underlying Network Matters</h3>

<p>Ireland’s main fixed broadband networks are:</p>

<ul>
  <li><strong>OpenEir:</strong> a wholesale fibre and copper network used by eir and many retail providers.</li>
  <li><strong>SIRO:</strong> a wholesale fibre-to-the-premises network used by multiple providers.</li>
  <li><strong>NBI:</strong> the National Broadband Ireland rural fibre network, sold through approved retail providers.</li>
  <li><strong>Virgin Media:</strong> primarily a separate cable network, where the supplied hub normally remains as the modem.</li>
</ul>

<p>The same provider can use different connection methods depending on whether your address is served by OpenEir, SIRO, NBI, cable, or an older DSL product. This is why another customer’s settings may not work at your address.</p>

<h3 id="before-replacing-an-isp-router">Before Replacing an ISP Router</h3>

<p>Ask the ISP these questions before disconnecting its equipment:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1. Is my service full fibre with an Ethernet ONT, cable, DSL, fixed wireless, or mobile?
2. Can I connect my own router directly to the ONT?
3. Is the WAN method PPPoE, DHCP/IPoE, DHCP Option 61, or another method?
4. Is a WAN VLAN required? If so, what VLAN ID and priority should I use?
5. If PPPoE is required, what username and password should I use?
6. Does the supplied router provide phone/VoIP service that requires it to remain connected?
7. Will support require the ISP router to be reconnected during fault testing?
</code></pre></div></div>

<h3 id="general-troubleshooting">General Troubleshooting</h3>

<p>If a direct ONT connection does not work, check the following before assuming the service is faulty:</p>

<ul>
  <li>The Ethernet cable from the ONT is connected to the router’s <strong>WAN/Internet</strong> port.</li>
  <li>The correct WAN mode is selected: PPPoE, DHCP/IPoE, or another provider-specified method.</li>
  <li>The required WAN VLAN has been configured.</li>
  <li>PPPoE credentials have been entered exactly.</li>
  <li>The PPPoE MTU is set to <strong>1492</strong> unless the provider specifies otherwise.</li>
  <li>The ONT has been allowed to fully start before powering on the router.</li>
  <li>The original ISP router has been tested again before contacting support.</li>
</ul>

<p>A direct connection can be technically possible even if a provider does not officially troubleshoot third-party equipment. For any fault report, reconnecting the ISP-supplied router first makes it easier to separate an issue with the fibre service from an issue with personal router configuration.</p>]]></content><author><name>Donal Fahy</name></author><category term="router" /><category term="Ireland" /><category term="ISP" /><summary type="html"><![CDATA[How to use your own router with internet providers in Ireland]]></summary></entry><entry><title type="html">Firmware mod CN to US - GL.iNet Beryl 7</title><link href="https://dofahy.github.io/2026/06/11/post3.html" rel="alternate" type="text/html" title="Firmware mod CN to US - GL.iNet Beryl 7" /><published>2026-06-11T00:00:00+00:00</published><updated>2026-09-14T07:00:41+00:00</updated><id>https://dofahy.github.io/2026/06/11/post3</id><content type="html" xml:base="https://dofahy.github.io/2026/06/11/post3.html"><![CDATA[<p>The GL-MT3600BE router is available in CN and global markets.
The CN version is about half the price, but has certain features blocked.
For example, the VPN features are blocked on the CN version.
These can be unblocked by modifying the firmware.</p>

<p>(11/06/2026, Amazon UK €135 vs 淘寶 TaoBao €55)</p>

<p>If done correctly the process does not take long.
The device will be functionally the exact same as the global version.
There is a small risk of damaging the device from user error during this process.</p>

<h2 id="steps-to-modify-and-write-firmware">Steps to modify and write firmware</h2>

<p>The process involves connecting to the router over ssh, making a bin of the factory mtd,
copying this back to your laptop, make the modification, copy the modified bin back to
the router and then write it to the mtd. After a reboot, configuration that relies on this
marker will read US instead of CN.</p>

<p>To begin, in a web browser navigate to the router page http://192.168.8.1
Login and in the Security &gt; Admin Access, enable ssh.
Open terminal or powershell and continue:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh root@192.168.8.1
  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M

root@GL-MT3600BE:~#

cat /proc/mtd
Identify the partition named "Factory",
on this device it was mtd3

copy the content of mtd3 to a bin file
dd if=/dev/mtd3 of=/tmp/factory.bin
8192+0 records in
8192+0 records out

transfer file to laptop
use the compatible -O flag as router does not have sftp
ash: /usr/libexec/sftp-server: not found
or install openssh sftp

scp -O root@192.168.8.1:/tmp/factory.bin .
md5sum factory.bin
9352af94d1ec6fd012b22a3259fc5a8e

now search for the marker we want to modify
grep -oba 'CN' factory.bin

The output was 16520,
search around that value to confirm it is the correct marker

xxd -s 16496 -l 48 factory.bin
00004080: ffff ffff ffff ffff 434E ffff ffff ffff  ........CN......

xxd -s 23199 -l 48 factory.bin
This was unrelated data that happened to contain CN

make a backup
cp factory.bin factory.bin.orig

modify CN to US:
printf 'US' | dd of=factory.bin bs=1 seek=16520 conv=notrunc

Confirm write success:
xxd -s 16512 -l 16 factory.bin
00004080: ffff ffff ffff ffff 5553 ffff ffff ffff  ........US......

md5sum factory.bin
ad406453d33fa680c7f7343b357ba49e

Copy the modified image back to the router.
scp -O factory.bin root@192.168.8.1:/tmp/

ssh into the router and write the image
mtd write /tmp/factory.bin Factory

Reboot and the router is now in US (global) mode.
</code></pre></div></div>

<h2 id="enabling-unlocked-features">Enabling unlocked features</h2>

<p>With the router now in global mode, a flash of the router image will enable all features.
Download it from the GL.iNet site, grab the latest beta or stable image.
Flash whichever one you prefer by going to:</p>

<p>System &gt; Upgrade &gt; Firmware Local Upgrade</p>

<p>After the flash all router functionality is working.</p>

<p>You may also wish to go to the openwrt page and download the latest supported image.
As of writing GL.iNet ships images with openwrt version 21.
The latest supported openwrt version for the beryl7 is 25.
The process to flash is the same.
I recommend doing this as version 21 is EOL.
It does mean that GL.iNets UI will be replaced by openwrts LuCI.</p>

<h2 id="links">Links</h2>

<p>When buying a router, check that it is compatible with OpenWrt to keep it updated and secure.
https://toh.openwrt.org/?view=normal
https://openwrt.org/toh/gl.inet/gl-mt3600be</p>

<p>Merge of 25.12 is pending for MediaTek chip GL-MT3600BE (as of 11/06/2026)
https://github.com/openwrt/openwrt/pull/23368
Going to wait for release instead of compiling OpenWrt with the patch applied.</p>

<h2 id="background-info-on-router-design">Background info on router design</h2>

<p>The GL-MT3600BE device follows a standard modern embedded router architecture based on a MediaTek SoC paired with large capacity NAND flash.
The persistent storage is not treated as a single filesystem like a PC disk.
Instead it is a structured flash layout exposed through the Linux MTD subsystem.
The underlying storage is SPI-NAND flash 512mb, much larger than earlier router generations that used 4–16 MB SPI NOR flash.</p>

<p>At the lowest level, the flash chip is divided into MTD partitions defined by the bootloader and device tree.
These partitions represent fixed functional regions rather than flexible filesystems.
These include bootloader stages (BL2, FIP, U-Boot), a factory/ calibration region, and a large firmware region.
The factory partition is used to store immutable data like MAC addresses, wireless calibration values, and regulatory identifiers.
This avoids duplicating data inside firmware images and allows it to persist across firmware upgrades.</p>

<p>The main firmware area is implemented using UBI (Unsorted Block Images), which is a flash translation layer designed for NAND.
NAND flash requires block erasure and has bad-block management, so raw filesystems are not suitable.
UBI abstracts these details and allows logical volumes to be created on top of the raw flash partition.
Inside the UBI, OpenWrt creates two logical volumes: a read-only squashfs root filesystem and a writeable data volume.</p>

<p>The read-only portion, often mounted as /rom, contains the compressed base system image.
This is the actual OpenWrt firmware image provided by the vendor or build system.
It includes the kernel, base utilities, init system, and default configuration templates.
This image is immutable at runtime and is effectively what would be considered the “factory firmware” in traditional embedded systems.
The writeable overlay filesystem is mounted on /overlay using overlayfs, which merges changes on top of the read-only base system.
This design allows package installation, configuration changes, and system modifications without altering the underlying firmware image.</p>

<p>This layered filesystem approach is common for OpenWrt devices and many Linux embedded systems.
It differs from simpler router designs where firmware is a single squashfs partition with minimal or no overlay separation.
In more constrained legacy devices, updates often replaced the entire flash region or used dual partition A/B schemes.
UBI based OpenWrt systems provide greater flexibility, wear levelling, and resilience against power loss during writes.</p>]]></content><author><name>Donal Fahy</name></author><category term="router" /><summary type="html"><![CDATA[Flashing a Beryl 7 with modified firmware]]></summary></entry><entry><title type="html">AI Defense Matrix</title><link href="https://dofahy.github.io/2026/06/09/post2.html" rel="alternate" type="text/html" title="AI Defense Matrix" /><published>2026-06-09T00:00:00+00:00</published><updated>2026-09-14T07:00:41+00:00</updated><id>https://dofahy.github.io/2026/06/09/post2</id><content type="html" xml:base="https://dofahy.github.io/2026/06/09/post2.html"><![CDATA[<h1 id="ai-defense-matrix">AI Defense Matrix</h1>

<p>The AI Defense Matrix is a structured framework for defending AI systems. Each row is an AI-specific asset class. Columns are NIST CSF 2.0 functions. Cells show the AI-specific control category, objective, or representative tooling for each intersection.</p>

<table>
  <thead>
    <tr>
      <th>Asset Class</th>
      <th>Govern</th>
      <th>Identify</th>
      <th>Protect</th>
      <th>Detect</th>
      <th>Respond</th>
      <th>Recover</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><em><strong>AI-Workload Platforms</strong></em></td>
      <td>AI-platform standards</td>
      <td>AI security posture management</td>
      <td>AI-workload hardening; model-loading supply-chain verification</td>
      <td>AI-workload runtime detection</td>
      <td>Generic container IR</td>
      <td>Generic platform restore</td>
    </tr>
    <tr>
      <td><em><strong>AI Orchestration Tools</strong></em></td>
      <td>AI application governance</td>
      <td>AIBOM for applications; agent-framework discovery</td>
      <td>System-prompt hardening; plugin allowlisting</td>
      <td>Prompt-injection testing; agent anomaly detection</td>
      <td>Agent runtime IR; plugin disable</td>
      <td>Framework config; prompt rollback</td>
    </tr>
    <tr>
      <td><em><strong>AI-Generated Code</strong></em></td>
      <td>AI coding standards, code-review policy, license; provenance policy</td>
      <td>AI-code provenance; origin tracking</td>
      <td>AI-aware SAST</td>
      <td>Hallucinated dependency; insecure-pattern detection</td>
      <td>PR block; revert of AI-generated commits</td>
      <td>Code rewrite; replacement of flagged artifacts</td>
    </tr>
    <tr>
      <td><em><strong>AI Gateways and Routers</strong></em></td>
      <td>AI egress policy; approved-service registry</td>
      <td>AI traffic discovery</td>
      <td>AI gateways for egress; MCP gateways for tool gating</td>
      <td>Anomalous AI traffic; RAG-leakage egress detection</td>
      <td>AI traffic blocking; shadow AI takedown</td>
      <td>Generic network failover</td>
    </tr>
    <tr>
      <td><em><strong>AI Model</strong></em></td>
      <td>Model selection; provider evaluation</td>
      <td>Model inventory; AIBOM</td>
      <td>Model firewalls; weight protection</td>
      <td>Model drift; integrity monitoring</td>
      <td>Model rollback; provider coordination for consumed models</td>
      <td>Model version restore; provider re-selection</td>
    </tr>
    <tr>
      <td><em><strong>Training Data</strong></em></td>
      <td>Dataset provenance; licensing policy</td>
      <td>Dataset inventory; lineage</td>
      <td>Data access control</td>
      <td>Poisoning; backdoor detection</td>
      <td>Dataset quarantine; retraining trigger</td>
      <td>Dataset restore from golden copies; model retraining</td>
    </tr>
    <tr>
      <td><em><strong>Runtime AI Data</strong></em></td>
      <td>Prompt; RAG policy, memory-retention governance, interaction-history policy</td>
      <td>RAG source; LLM-oversharing inventory</td>
      <td>Prompt-injection defence, RAG sanitization, memory-poisoning defence, AI-content DLP</td>
      <td>Prompt anomaly, jailbreak attempts, RAG leakage, memory tampering</td>
      <td>Session termination; RAG source isolation</td>
      <td>Vector DB restore; re-indexing</td>
    </tr>
    <tr>
      <td><em><strong>AI Agent Identities</strong></em></td>
      <td>AI agent identity policy, authorization standards, OAuth for agents</td>
      <td>AI agent; non-human principal inventory</td>
      <td>Agent OAuth; capability scoping, short-lived credentials</td>
      <td>Agent behavioural monitoring; runtime authorization drift</td>
      <td>Credential revocation, agent quarantine, session termination</td>
      <td>Agent identity re-provisioning</td>
    </tr>
  </tbody>
</table>

<hr />

<p><strong>Source:</strong> https://aidefensematrix.com</p>]]></content><author><name>Donal Fahy</name></author><category term="cyber" /><category term="matrix" /><category term="AI" /><summary type="html"><![CDATA[AI Defense Matrix]]></summary></entry><entry><title type="html">Notes April to June 2026</title><link href="https://dofahy.github.io/2026/06/01/post1.html" rel="alternate" type="text/html" title="Notes April to June 2026" /><published>2026-06-01T00:00:00+00:00</published><updated>2026-09-14T07:00:41+00:00</updated><id>https://dofahy.github.io/2026/06/01/post1</id><content type="html" xml:base="https://dofahy.github.io/2026/06/01/post1.html"><![CDATA[<h2 id="trying-nim">trying nim</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>published my first nim program, more to follow
    https://github.com/dofahy/nim-explore

getting kate setup for nim
    enabled plugins
    nimble install nimlsp
    nimble install nph
        run formatting in cli
    kate defaults to python indentation for nim
        change to none
        settings &gt; editing &gt; indentation - set none and untick auto detect

    formatting in kate
        create external tool
        Name: Format Nim
        Exec: nph
        Args: %{Document:FileName}

        create shortcut for tool
        ctrl+alt+f

add markdown preview to kate
    sudo apt install markdownpart

bencode (bee-encode)
    the encoding use by torrent files as part of bittorrent spec
    https://en.wikipedia.org/wiki/Bencode

    integers, byte strings, lists and dictionaries
    a couple drawbacks:
        not human-readable encoding format. values often contain binary data,
        so decoding by hand may be error prone. a hex editor or bencode editor is needed.
        does not store any metadata about the size of list or dictionary,
        requiring all elements to be read sequentially. not be suitable for
        large data where random access is required.

nim - parsing bencode
    create nim-bencode, a library to encode/decode bencode torrent files

pushed code for nim-bencode
    can create more tests and improve bencode.nim to be closer to spec
    encoding and decoding are not robust

pushed code for nim-dmidecode
    nim c main.nim
    sudo dmidecode &gt; dmi.txt
    ./main dmi.txt

    output
    Physical Memory Array =&gt; 6
    End Of Table =&gt; 0
    System Information =&gt; 8
    Processor Information =&gt; 22
    System Boot Information =&gt; 1
    Memory Array Mapped Address =&gt; 5
    Chassis Information =&gt; 15
    Memory Device =&gt; 21
    BIOS Information =&gt; 10

pushed code for nim-linkschecker
    a simple http utility using sequential or async

installed markdown preview for kate
    https://apps.kde.org/markdownpart/

viewing debian iputils package
    https://salsa.debian.org/debian/iputils/-/tree/master/ping?ref_type=heads

came across sourcehut, a lightweight alternative to github
    https://sourcehut.org/
    https://news.ycombinator.com/item?id=33607098

nim has a robust config file parser module parsecfg
    https://nim-lang.org/docs/parsecfg.html
    https://github.com/nim-lang/Nim/blob/devel/lib/pure/parsecfg.nim

created a smaller version that works on an ini file taken from wiki's ini article
    https://en.wikipedia.org/wiki/INI_file

    pushed code for nim-configparser

pushed code for nim-urlshort
    a simple url shortener
curl -X POST http://localhost:5000/short -H "Content-Type: application/json" -d '{"url":"example.com"}'
    {"id":"tzjgq"}
</code></pre></div></div>

<h2 id="irishvpn-dev">irishvpn dev</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>installed mailpit
    sudo sh &lt; &lt;(curl -sL https://raw.githubusercontent.com/axllent/mailpit/develop/install.sh)

installed stripe-cli
    https://github.com/stripe/stripe-cli/releases

    stripe login
    if using gpg signing
        gpg --full-generate-key
    auth is good for 90 days

setup mariadb-10.11.16

used sdkman to get java 21

installed latest nvm and node
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash

fixed bug in temp password generation
    code did not guarantee at least one letter, number and special

</code></pre></div></div>

<h2 id="regulations-api">regulations api</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>installed latest postgresql
/postgresql-18.3/bin/initdb -D ~/databases/data/pg18.3-casino-reg-ie --encoding=UTF8 --locale=en_IE.UTF-8

pushed code for regulations app
    working example for basic post and get
    can refactor main.py to fill in the be

added helpers to the casino regulations api
    commit checks
    test coverage
    ruff - linting and formatting

coverage in README is static
    can make it dynamic (later)
    codecov.io

need to use --no-verify until the imports are sorted

need to use underscores for python and postgres
    dashes cause issues but they are only needed for
        the apps name and cmd line starting
            everywhere else in code should be underscores

desktop froze twice - gpu gtx 1070 issue - driver (nvidia 580.126.09) or wayland
    audio was still playing
    alt+prt screen+b to force reboot
    see if it goes away with x11
        sudo apt install plasma-session-x11

added logging, can switch to json format when needed
    toggle sqlalchemy

</code></pre></div></div>

<h2 id="network-changes-and-kate-support">network changes and kate support</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>made network changes
    removed ISP device. it is not needed
    set owned device to PPPoE
        vodafone@vodafone.ie
        broadband
    set vlan 10
    speeds tests are similar but stability has noticeably improved

added additional support in kate
    https://github.com/python-lsp/python-lsp-server
    pip install python-lsp-server

    https://github.com/redhat-developer/yaml-language-server
    npm install -g yaml-language-server
    yaml-language-server --version =&gt; 1.22.0

    https://github.com/artempyanykh/marksman
        mv marksman-linux-x64 ~/.local/bin/marksman
        chmod +x ~/.local/bin/marksman
        echo 'export PATH="$HOME/.local/bin:$PATH"' &gt;&gt; ~/.bashrc
        source ~/.bashrc
        marksman --version =&gt; release 2026-02-08

Also, Tools &gt; Spelling &gt; Auto spell check
</code></pre></div></div>

<h2 id="matrix-protocol-and-sqlalchemy">matrix protocol and sqlalchemy</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>matrix protocol
    https://en.wikipedia.org/wiki/Matrix_(protocol)
    A communications protocol that can bridge instant messaging apps into a single app.
    The messaging app developed by the matrix team is called Element.

gerrit - free web-based team code collaboration tool.

renamed app to regulate-ie
    created github action for a production ci workflow
    may use poetry
    can install with pipx

reading docs for version 2
    https://docs.sqlalchemy.org/en/20/tutorial/dbapi_transactions.html

</code></pre></div></div>

<h2 id="pip-fortune-and-rogue">pip, fortune and rogue</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Went with pip-tools instead of poetry
    note on poetry setup:
        sudo apt install pipx
        pipx install poetry
        pipx upgrade poetry
        poetry completions bash &gt;&gt; ~/.bash_completion
        generate a project -&gt; poetry init

sudo apt install fortunes
pipx install cowsay -&gt; v6.1 original is 1999 perl program
(https://github.com/VaasuDevanS/cowsay-python)
cowsay -t "$(fortune)" -c "tux"

    pip-tools -&gt; https://pypi.org/project/pip-tools/
    can install it in project venv or using pipx
    pip install pip-tools
    pip-compile --version
        pip-compile, version 7.5.3
    pip-compile -o requirements.txt pyproject.toml --strip-extras
    pip-compile --extra dev -o requirements-dev.txt pyproject.toml --strip-extras

1980 text game
    https://en.wikipedia.org/wiki/Rogue_(video_game)
    https://en.wikipedia.org/wiki/Roguelike

</code></pre></div></div>

<h2 id="openwrt-router">openwrt router</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>firmware version: OpenWrt 21.02
kernel version: 5.4.238

OpenWrt - Linux operating system targeting embedded devices
    https://openwrt.org/

LuCI - OpenWrt Configuration Interface
    https://github.com/openwrt/luci/wiki/

ddns config
    https://openwrt.org/docs/guide-user/services/ddns/client

to configure ddns
    from router home page go to LuCI
    click System &gt; software
    update list
    filter for ddns
    install  ddns-scripts and luci-app-ddns
    optional wget-ssl and ca-certificates, or curl and ca-bundle for SSL
    ddns-scripts-noip ddns-scripts-cloudflare
    full reload page
    go to services &gt; ddns
    delete defaults
    add new connections
    ca cert path -&gt; /etc/ssl/certs
    for cloudflare the username is Bearer and pw is api key
    logs are auto truncated

create backup of current config
    system &gt; backup &gt; generate archive

setup ssh key only from lan
    use vpn to lan

ash
    https://en.wikipedia.org/wiki/Almquist_shell

opkg
    https://openwrt.org/docs/guide-user/additional-software/opkg

created layer 3 segmentation
    the web server is on its own network
    it can be accessed from the management network
    the firewall restricts it to reject input and forward
    custom input for dhcp and dns
    port forwarding setup
</code></pre></div></div>

<h2 id="updating-dependencies-and-depracted-code">updating dependencies and depracted code</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mvn dependency:tree
mvn versions:display-dependency-updates

in addition to stable release this also shows candidate, milestone, snapshot, beta, alpha versions
only go with stable or milestone for production

This is too heavy but could run it as part of CI
https://dependency-check.github.io/DependencyCheck/dependency-check-maven/index.html

pom.xml updated with
    org.springframework.boot
    version 3.5.13

    jsonwebtoken
    https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api
    latest 0.13.0

    stripe 32.0.0
        reverted to 30 as major version upgrade introduced breaking changes in
        how objects are deserialized or how the Session object is constructed.

updating jjwt depracted code
    https://github.com/jwtk/jjwt#installation
    https://javadoc.io/doc/io.jsonwebtoken/jjwt-api/latest/io/jsonwebtoken/package-summary.html

    the JwtService class now has cleaner and more readable code.
    added issuer validation
    The "iss" (issuer) claim identifies the principal that issued the
    JWT.  The processing of this claim is generally application specific.
    The "iss" value is a case-sensitive string containing a StringOrURI
    value.  Use of this claim is OPTIONAL.
    https://www.rfc-editor.org/rfc/rfc7519.html#section-4.1.1

</code></pre></div></div>

<h2 id="netbeans-and-dependency-artifacts">netbeans and dependency artifacts</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>netbeans has an option to auto download the source and javadoc for dependencies.
however this can cause slow startup times.

better to use maven
mvn dependency:sources
mvn dependency:resolve -Dclassifier=javadoc

they are needed for IDE features like code navigation, refactoring, and doc lookup.

</code></pre></div></div>

<h2 id="network-tester-and-kvm">network tester and KVM</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>network tester
    Bufferbloat and Internet Speed Test
    https://www.waveform.com/tools/bufferbloat

shopping list
    Remote KVM
        https://www.gl-inet.com/campaign/kvm/

kde tips
    can copy the clock in plasma to get a timestamp, useful for jekyll date requirements.

</code></pre></div></div>

<h2 id="setting-up-local-build-system">setting up local build system</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setting up a local build system
    https://about.gitea.com/
    https://github.com/go-gitea/gitea

    can set up so that i push to it and github
        it will run tests and local repo
        github will just store private for remote access and as backup

    it's also called a forge
        https://en.wikipedia.org/wiki/Forge_(software)

setting up a forgejo system

    using a pi 5 as a prototype
    writing iac instructions as project progresses

    using:
        podman
        cockpit, cockipit-podman
        forgejo, forgejo-runner
        postgres
        caddy

    the container files specify config to run as systemd services
        systemd manages lifecycle/restarts
        podman exec for entering and running commands inside
        folders on the host persist and provide access to pod data
        like
            mkdir -p /srv/forge/data/caddy/{config,data,site}

    creating a rootful version first then try rootless.
</code></pre></div></div>

<h2 id="caddy">caddy</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://en.wikipedia.org/wiki/Caddy_(web_server)
setup involved making a container, creating a Caddyfile and copying the cert to client
devices then importing the authority cert in browser.
result is i can navigate to forge.home.arpa with no browser warnings.

</code></pre></div></div>

<h2 id="pi-eeprom">pi EEPROM</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://en.wikipedia.org/wiki/EEPROM
electrically erasable programmable read-only memory is a type of non-volatile memory.
It is used in computers, usually integrated in microcontrollers such as smart cards
and remote keyless systems, or as a separate chip device, to store relatively small
amounts of data by allowing individual bytes to be erased and reprogrammed.

Raspberry Pi EEPROM stores critical bootloader firmware on Pi 4/5 models, non-volatilely
maintaining data without power.
https://github.com/raspberrypi/rpi-eeprom

sudo rpi-eeprom-update -a

</code></pre></div></div>

<h2 id="ubuntu-2604">ubuntu 26.04</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>steps to update
    logout
    ctrl+alt+f3
    sudo systemctl stop sddm
    cp .config backup-config
    rm -r .config
    sudo do-release-upgrade
        follow prompts
    reboot
        restore any config
        clean up any startup services
    systemd-analyze blame
    sudo systemctl disable NetworkManager-wait-online.service
    sudo systemctl disable qemu-kvm.service

    add to nextcloud service
    [Service]
    ExecStartPre=/bin/sleep 5
    systemctl --user daemon-reload
    systemctl --user restart com.nextcloud.desktopclient.nextcloud.servic
</code></pre></div></div>

<h2 id="github-pages">Github Pages</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>getting familiar with github pages
https://docs.github.com/en/pages

read up on creative commons license
https://creativecommons.org/licenses/


installed a fedora 43 vm with kde
    going to use this for trying nim code

    sudo dnf group install c-development development-tools
    curl https://nim-lang.org/choosenim/init.sh -sSf | sh

    (optional) sudo dnf install --nogpgcheck --repofrompath '
    terra,https://repos.fyralabs.com/terra$releasever' terra-release

    sudo dnf install file-devel
    nim c -r main.nim

opentofu - an open source alternative to terraform (which was open source until 2023)
    https://github.com/opentofu/opentofu
    iac templates for azure
    https://github.com/infra-at-scale/organization-template

setup scrcpy
    https://github.com/genymobile/scrcpy
</code></pre></div></div>]]></content><author><name>Donal Fahy</name></author><category term="notes" /><summary type="html"><![CDATA[A collection of notes from early April to start of June 2026]]></summary></entry></feed>