<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Software - Category - log - Nicholas Ward</title><link>https://log.nicholas.uuard.com/categories/software/</link><description>Software - Category - log - Nicholas Ward</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>nicholaspward@outlook.com (Nicholas Ward)</managingEditor><webMaster>nicholaspward@outlook.com (Nicholas Ward)</webMaster><lastBuildDate>Mon, 03 Aug 2026 10:00:00 -0500</lastBuildDate><atom:link href="https://log.nicholas.uuard.com/categories/software/" rel="self" type="application/rss+xml"/><item><title>☎️ Local Voice Agent</title><link>https://log.nicholas.uuard.com/posts/2026-08-03-local-voice-agent/</link><pubDate>Mon, 03 Aug 2026 10:00:00 -0500</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/2026-08-03-local-voice-agent/</guid><description><![CDATA[<p>In a <a href="/posts/2026-03-01-voip/" rel="">previous post</a>, I built a small telephone system with FreePBX and a low-cost SIP carrier, BulkVS. This gave me a real phone number, extensions, softphones, a ring group, and voicemail. This would serve as the perfect entry point for a self-hosted voice agent.</p>
<p>I have configured the system such that when my phone number is dialed, a voice describes a telephone menu where the caller can dial a selection:</p>]]></description></item><item><title>🏗️ Home Ops Upgrades</title><link>https://log.nicholas.uuard.com/posts/2026-07-07-home-ops/</link><pubDate>Tue, 07 Jul 2026 10:00:00 -0500</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/2026-07-07-home-ops/</guid><description><![CDATA[<p>As the number of self-hosted services I use regularly has grown, managing them by hand began to feel wrong, and occasionally annoying and tedious. It ends now!</p>






<figure>
  <a
    class="lightgallery"
    href="https://files.web-log.uuard.com/2026-07-07-home-ops/images/portainer-container-dashboard.png"
    data-thumbnail="https://files.web-log.uuard.com/2026-07-07-home-ops/images/portainer-container-dashboard.png"
    data-sub-html="Container dashboard - many apps">
    
  </a>

  
    <figcaption>Container dashboard - many apps</figcaption>
  
</figure>

<p>In the beginning, my workflow was pretty sloppy since much of the deployment/management depended on me remembering to restart a container or update a version, manually copy a secret here and there. Things like this. Totally maintainable, sustainable with some effort, but it is not <em>the way</em>. And to some degree these manual interventions will always be necessary, but it will serve me well to reduce them and automate them away as much as reasonable to help these apps live far into the future with little fuss. Many of these apps have proven their usefulness to me over many years, so I have begun to take their management more seriously, slowly taking steps toward git-ops patterns and best practices. Before: scattered <code>.env</code> files. Flat directory of compose files. No documentation. Manually copying secrets by hand. Manually rebuilding host dependencies by hand. Now: a single command issued by a single click of a button (maybe I am overstating the simplicity here&hellip;nevertheless) will handle mostly everything I care about. Host setup, Compose projects, rendered secrets, state directories, validation, and deployment are all described in one place. Easy!</p>]]></description></item><item><title>☎️ VoIP</title><link>https://log.nicholas.uuard.com/posts/2026-03-01-voip/</link><pubDate>Sun, 01 Mar 2026 08:00:00 +0000</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/2026-03-01-voip/</guid><description>&lt;p>I pay my share of the family phone plan ($15/mo), and in return I get unlimited texts, 1000 minutes of calls, and 1 GB of data. This is already extraordinarily cheap, but for how little I use the service I think I can do better, at least in terms of raw cost of owning a phone number on which I can make and receive voice calls. I can get the cost down to pennies a month, depending on how much time I spend in a phone call.&lt;/p></description></item><item><title>🔀 Router Build</title><link>https://log.nicholas.uuard.com/posts/router-build/</link><pubDate>Wed, 27 Aug 2025 18:30:00 -0500</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/router-build/</guid><description><![CDATA[<p>My router (<strong>Netgear R6400v2</strong>) lacks many of the features I would like to use and become familiar with:</p>
<ul>
<li>VLANs</li>
<li>Advanced routing, firewall</li>
<li>Monitoring, logging, alerts</li>
<li>etc.</li>
</ul>
<p><strong>I need a new router.</strong></p>
<p>I have a few options from here:</p>
<ol>
<li>
<p>❌ <strong>Write custom firmware to existing router</strong> (<em>DD-WRT, OpenWRT, Tomato, etc.</em>)</p>
<ul>
<li>➕ Fun</li>
<li>➕ Free</li>
<li>➖ Too much jank</li>
</ul>
</li>
<li>
<p>❌ <strong>Buy new hardware</strong></p>
<ul>
<li>➕ Very easy setup</li>
<li>➖ Boring</li>
<li>💲 Could require expensive/high-end router hardware</li>
</ul>
</li>
<li>
<p>✅ <strong>Repurpose existing hardware</strong></p>]]></description></item><item><title>🧭 Centralized, Secure Reverse Proxy at the edge</title><link>https://log.nicholas.uuard.com/posts/edge-reverse-proxy/</link><pubDate>Wed, 06 Aug 2025 08:00:00 -0500</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/edge-reverse-proxy/</guid><description><![CDATA[<p>In a <a href="/posts/infrastructure-overhaul/" rel="">previous post </a> I recorded the state of my network at the time, which included no centralized reverse proxy. There was no need. I accessed my services <strong>locally</strong> and each of the service host ran its own reverse proxy on its own IP. I show this configuration in the diagram below.</p>
<p><strong>✅ Multiple Reverse Proxies (LOCAL ONLY)</strong></p>
<pre class="mermaid">
  graph TD

subgraph lan[🏠LAN]
    client[🧑‍💻Client]
    subgraph hostA[&#34;🖥️Docker Host&#34;]
        reverseproxyA[&#34;🚪Reverse Proxy&#34;]
        serviceAA[&#34;🧠LLM&#34;]
    end
    subgraph hostB[&#34;🖥️Kubernetes Host&#34;]
        reverseproxyB[&#34;🚪Reverse Proxy&#34;]
        serviceBA[&#34;🖼️Photos&#34;]
        serviceBB[&#34;📝Blog&#34;]
    end
end

client --&gt;|192.168.1.10:443|reverseproxyA
client --&gt;|192.168.1.11:443|reverseproxyB

reverseproxyA --&gt;|llm.domain.com|serviceAA
reverseproxyB --&gt;|photos.domain.com|serviceBA
reverseproxyB --&gt;|blog.domain.com|serviceBB
</pre>

<p>However, now I would like to access certain services from beyond my local network, and not just for myself. I want them to be accessible to all web users, otherwise I would simply set up a client-to-site VPN and be done. I want them to be accessible over HTTPS.</p>]]></description></item><item><title>🗿 Photogrammetry - Tongan Wood Carving</title><link>https://log.nicholas.uuard.com/posts/photogrammetry/</link><pubDate>Wed, 02 Jul 2025 20:00:00 -0500</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/photogrammetry/</guid><description>&lt;p>I was gifted a beautiful yet somewhat haunting, grimacing figure, carved of wood, which I am told was gifted to one of my great uncles by the king of Tonga himself. I do know quite what to do with this object besides to proudly display it on a small table by the front door of my apartment. But what if I lost it? What if it just vanished? As its new caretaker, I figured it would be prudent to digitally preserve this artifact. After all, if I take seriously the &lt;a href="#-god-figure" rel="">dubious claimed provenance&lt;/a> of the item, I am dealing with the once-property of a king!&lt;/p></description></item><item><title>🔨 Infrastructure Overhaul</title><link>https://log.nicholas.uuard.com/posts/infrastructure-overhaul/</link><pubDate>Fri, 27 Jun 2025 19:00:00 -0500</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/infrastructure-overhaul/</guid><description><![CDATA[<p>This overhaul of my infrastructure is mostly about <strong>separating concerns</strong>. The two main concerns being separated are: <strong>storage</strong> and <strong>services</strong>. Mainly, I am moving all of the containers off my storage server and onto their own machine. They call this <strong>storage-service decoupling</strong>. There are also some improvements I will make along the way.</p>
<h2 id="-problems">⚠️ Problems</h2>
<p>There are a couple main problems with current configuration that I will need to address:</p>]]></description></item><item><title>📈 Server Monitoring with Grafana</title><link>https://log.nicholas.uuard.com/posts/server-monitor/</link><pubDate>Fri, 16 May 2025 08:00:00 -0500</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/server-monitor/</guid><description><![CDATA[<p>In this post I will develop a server monitoring dashboard that will show me the status of my server at a glance. The goal here is to replicate the functionality of a simple command-line &ldquo;real-time&rdquo; system information monitor e.g. <code>top</code>, <code>htop</code>, etc. via a web interface.</p>






<figure>
  <a
    class="lightgallery"
    href="https://files.web-log.uuard.com/server-monitor/images/btop.png"
    data-thumbnail="https://files.web-log.uuard.com/server-monitor/images/btop.png"
    data-sub-html="Btop UI">
    
  </a>

  
    <figcaption>Btop UI</figcaption>
  
</figure>

<ul>
<li>A <strong>web-based</strong> monitoring dashboard, as opposed to e.g. <code>htop</code>, will be useful to me because it will allow me to access this dashboard from virtually any OS, anywhere at any time. No more <code>ssh</code>-ing into my machine and running all manner of monitoring-related commands.</li>
<li>The web interface will also make integrating with other web-based dashboards trivial, which is something I plan to do later so that I can show my server stats alongside things like calendars, reminders, etc. in a master dashboard.</li>
<li>The tools I plan to use will allow me to configure alerts that will notify me if certain metrics go beyond threshold values, e.g. disk space, CPU utilization &gt; 90%, etc.</li>
</ul>
<h2 id="project-scope">Project Scope</h2>
<p>There are a few pieces of information I want immediately visible when I visit my dashboard:</p>]]></description></item><item><title>▶️ Gitea Actions &amp; Kubernetes</title><link>https://log.nicholas.uuard.com/posts/gitea-actions-kubernetes/</link><pubDate>Thu, 08 May 2025 12:50:00 -0500</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/gitea-actions-kubernetes/</guid><description><![CDATA[<p>I currently use <strong>Jenkins</strong> to automate the build and deployment of my <a href="https://nicholas.uuard.com" target="_blank" rel="noopener noreffer ">personal website</a> and my <a href="https://log.nicholas.uuard.com" target="_blank" rel="noopener noreffer ">blog site</a>. I will experiment with a <strong>Gitea Actions</strong> workflow to see if I can accomplish the same thing in Gitea.</p>
<p>This process should be familiar to me since the workflow I configure in this post will more or less mirror the behavior of my Jenkins setup: an independent service (e.g., Jenkins agent, Gitea runner) executes steps defined in a repo configuration file (e.g., <code>Jenkinsfile</code>, <code>demo.yml</code>).</p>]]></description></item><item><title>🥣 Formulation - Nutrition Calculator</title><link>https://log.nicholas.uuard.com/posts/formulation-web-app-ii/</link><pubDate>Tue, 15 Apr 2025 12:45:00 -0500</pubDate><author>nicholas</author><guid>https://log.nicholas.uuard.com/posts/formulation-web-app-ii/</guid><description><![CDATA[<p><strong>View the git repository <a href="https://git.uuard.com/nicholas/formulation" target="_blank" rel="noopener noreffer ">here</a></strong></p>
<p>In a <a href="/posts/formulation-web-app-i/" rel="">previous post</a> I added multi-user support to a web app I built with Microsoft&rsquo;s Blazor framework in C#, which I named <strong>Formulation</strong>. In this post I review a fully-working version of the project.</p>



<figure class="video">
<video controls preload="metadata" width="100%"  autoplay="true" loop="true">
<source src="https://files.web-log.uuard.com/formulation-web-app-II/videos/formulation-demo-3x.mp4" >
</video>
</figure>
<h3 id="problem">Problem</h3>
<p>The problem is in my previous approach to estimating nutrition, which was to prepare many units of a single type of food item with known nutrition, e.g. frozen burritos. I knew that if I ate one whole <code>&lt;food&gt;</code> I would have consumed <code>&lt;nutrition&gt;</code>. This works, but it is not flexible: I must eat the whole <code>&lt;food&gt;</code> item, and only eat <code>&lt;food&gt;</code> items, or else be pained to calculate things manually.</p>]]></description></item></channel></rss>