<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[CMR Lab]]></title><description><![CDATA[A practical engineering journal exploring home labs, networking, virtualization and cybersecurity through real experiments, troubleshooting and lessons learned.]]></description><link>https://cmrlab.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6acc2c62a8662b5ce37f8451/8b000963-fdad-40e5-babd-18b638c3f300.png</url><title>CMR Lab</title><link>https://cmrlab.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 16 Oct 2026 15:35:23 GMT</lastBuildDate><atom:link href="https://cmrlab.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[I Wanted a Dashboard. I Ended Up With Five Containers.]]></title><description><![CDATA[I wanted a webpage with links to my home lab services.
That was the idea.
Somewhere I could open Proxmox, UniFi and whatever else I eventually deployed without having to remember a collection of IP ad]]></description><link>https://cmrlab.hashnode.dev/i-wanted-a-dashboard-i-ended-up-with-five-containers</link><guid isPermaLink="true">https://cmrlab.hashnode.dev/i-wanted-a-dashboard-i-ended-up-with-five-containers</guid><category><![CDATA[Docker]]></category><category><![CDATA[Homelab]]></category><category><![CDATA[self hosting]]></category><category><![CDATA[proxmox]]></category><category><![CDATA[troubleshooting]]></category><dc:creator><![CDATA[Charles Rattan]]></dc:creator><pubDate>Fri, 16 Oct 2026 00:08:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6acc2c62a8662b5ce37f8451/4727e7c3-1488-4650-9356-29def37a5421.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I wanted a webpage with links to my home lab services.</p>
<p>That was the idea.</p>
<p>Somewhere I could open Proxmox, UniFi and whatever else I eventually deployed without having to remember a collection of IP addresses and port numbers.</p>
<p>Nothing particularly elaborate.</p>
<p>By the end of 7 June 2026, I had another Ubuntu virtual machine, Docker Engine, Portainer, Homepage, Uptime Kuma, Vaultwarden and Nginx Proxy Manager.</p>
<p>I also had a few problems that hadn't been resolved.</p>
<p>It was becoming apparent that <strong>installing services was going to be considerably easier than organizing them properly.</strong></p>
<h2>Another VM seemed reasonable</h2>
<p>I'd only just finished establishing the first two virtual machines on my newly installed Proxmox server.</p>
<p><code>ubuntu-mgmt-01</code> was intended for infrastructure management, while <code>unifi-controller-01</code> had taken over responsibility for the UniFi Network Application.</p>
<p>The separation made sense to me.</p>
<p>I didn't want to repeat the arrangement I'd had with my old MacBook, where applications accumulated on the same machine simply because there was somewhere to install them.</p>
<p>So rather than installing Docker on the Proxmox host itself, or mixing general applications into one of the existing VMs, I created a third.</p>
<p><strong>VM120 —</strong> <code>docker-services-01</code></p>
<p>This would become the home for containerized applications that supported the lab and, potentially, services I might actually use around the house.</p>
<p>I was still getting comfortable with virtualization, and Docker introduced another layer of abstraction.</p>
<p>A physical machine could host virtual machines. Those virtual machines could each run their own operating systems. And one of those operating systems could host multiple applications in containers.</p>
<p>I understood the concept.</p>
<p>Getting accustomed to working with those layers was another matter.</p>
<h2>The first permission problem</h2>
<p>Docker's installation wasn't particularly troublesome.</p>
<p>Working with it initially was.</p>
<p>One of the first issues came from attempting to add the wrong Linux username to the Docker group. The account referenced in the command didn't actually exist on the VM.</p>
<p>Once that was corrected, I encountered another problem: <strong>permission denied when attempting to communicate with the Docker daemon.</strong></p>
<p>It was a straightforward permissions and session issue, eventually resolved by correcting group membership and ensuring the session recognized the change.</p>
<p>But it was an early reminder that I needed to pay attention to the environment I was actually working in.</p>
<p>A command copied from a guide, or adapted from another machine, isn't necessarily appropriate for the system in front of you.</p>
<p>Even something as basic as a username matters.</p>
<p>There's also a security consideration here that became more apparent as I continued learning: membership in the Docker group provides powerful access to the host.</p>
<p>Convenience and privilege aren't entirely separate concerns.</p>
<p>With Docker functioning, I could finally get to the applications I wanted to run.</p>
<h2>Portainer: a window into the containers</h2>
<p>The first useful addition was <strong>Portainer Community Edition</strong>.</p>
<p>I wanted a graphical way to see what was running and manage containers without relying exclusively on commands.</p>
<p>Not because I wanted to avoid the command line, but because I was still learning how Docker organized containers, images, volumes and networks.</p>
<p>Portainer gave me a way to explore those relationships visually.</p>
<p>It was useful almost immediately.</p>
<p>But Portainer wasn't the dashboard I originally had in mind.</p>
<p>It provided a view of the container environment. I wanted a convenient starting page for the entire lab, including services that weren't running in Docker.</p>
<p>For that, I settled on <strong>Homepage</strong>.</p>
<h2>A homepage that didn't want visitors</h2>
<p>Homepage was intended to bring the environment together.</p>
<p>Proxmox, UniFi, Portainer, monitoring tools and other services could be presented as a single collection of links.</p>
<p>I liked the simplicity of the idea.</p>
<p>Rather than opening bookmarks or remembering addresses, I'd have one page that reflected what was available in the lab.</p>
<p>Except that getting the page to load correctly wasn't quite as straightforward as I'd expected.</p>
<p>Homepage was running, but requests using the address I was accessing it through were being rejected by its host validation.</p>
<p>I initially attempted to resolve the problem through the application's YAML configuration.</p>
<p>That didn't work.</p>
<p>After examining the container logs, the solution became clearer. The application expected the permitted hosts to be supplied through an environment variable:</p>
<p><code>HOMEPAGE_ALLOWED_HOSTS</code></p>
<p>I recreated the container with the appropriate configuration, and the dashboard became accessible.</p>
<p>This wasn't a particularly complicated problem once the correct configuration mechanism was understood.</p>
<p>But it was a useful introduction to something I'd encounter repeatedly with containerized applications.</p>
<p><strong>An application can be running perfectly well inside a container while still being inaccessible or incorrectly configured from the user's perspective.</strong></p>
<p>Docker had done its job by starting the process.</p>
<p>That didn't mean I'd finished mine.</p>
<h2>Seeing whether things were actually available</h2>
<p>Once the dashboard was working, another question arose.</p>
<p>What happens when one of those services stops responding?</p>
<p>A dashboard with links is useful, but clicking each one to see whether it works isn't much of a monitoring strategy.</p>
<p>So I deployed <strong>Uptime Kuma</strong>.</p>
<p>I began adding availability checks for Homepage, Portainer, Proxmox and UniFi.</p>
<p>At a glance, I could now see whether the selected service endpoints were responding.</p>
<p>It was satisfying to have a central dashboard and some basic visibility into availability.</p>
<p>But there was a distinction I would come to appreciate more as the lab evolved.</p>
<p>A successful availability check doesn't necessarily mean an application is healthy in every meaningful sense.</p>
<p>A web interface might respond while an important background function has failed. A container might be running while its application is unable to connect to a dependency.</p>
<p>And an application might appear perfectly healthy until someone actually tries to use it.</p>
<p><strong>'Online' is a useful observation. It isn't a complete assessment.</strong></p>
<p>Uptime Kuma gave me a starting point, not a complete monitoring solution.</p>
<p>That distinction would become increasingly important as the number of services grew.</p>
<h2>Vaultwarden raised a different question</h2>
<p>One of the applications I was interested in running was <strong>Vaultwarden</strong>, a self-hosted implementation compatible with Bitwarden clients.</p>
<p>This wasn't just another dashboard or experimental utility.</p>
<p>A password manager would potentially hold information I genuinely depended on.</p>
<p>And that changed how I needed to approach the deployment.</p>
<p>The container installed and reported a healthy state.</p>
<p>But that wasn't the same as being ready for use.</p>
<p>Vaultwarden required a secure browser context for important functionality, which meant I needed to resolve HTTPS properly before treating the deployment as suitable for real credentials.</p>
<p>I had an application that appeared to be operational, but I wasn't prepared to consider that a successful production deployment.</p>
<p>That was a useful boundary to establish.</p>
<p>I'd been treating most of the lab as an environment where I could install something, break it, rebuild it and move on.</p>
<p><strong>That approach isn't quite so comfortable when the application is intended to protect passwords.</strong></p>
<p>For the moment, Vaultwarden remained installed but not ready for that responsibility.</p>
<p>It would take more work on certificates and internal service access before I was comfortable moving forward.</p>
<h2>Making addresses easier didn't make networking simpler</h2>
<p>Another problem was beginning to emerge.</p>
<p>Every new service came with another address or port number to remember.</p>
<p>I wanted to type a recognizable name into the browser and arrive at the correct application.</p>
<p>So I introduced <strong>Nginx Proxy Manager</strong>.</p>
<p>The idea was to have a reverse proxy accept requests for different internal service names and direct them to the appropriate applications.</p>
<p>It was a sensible direction, but I was still missing part of the foundation.</p>
<p>I hadn't established proper internal DNS.</p>
<p>Instead, I began with temporary entries in my Windows hosts file to associate the names I wanted to use with the appropriate local address.</p>
<p>For testing, that worked.</p>
<p>But it wasn't a particularly elegant solution.</p>
<p>Those names existed because I had manually configured them on one computer. They weren't automatically available to every device in the household.</p>
<p>And not everything worked neatly through the proxy either.</p>
<p>Portainer, for example, remained accessible directly, but getting its reverse-proxy arrangement working correctly proved troublesome.</p>
<p>I had a collection of components that individually made sense:</p>
<ul>
<li><p><strong>Homepage</strong> provided navigation.</p>
</li>
<li><p><strong>Portainer</strong> provided container administration.</p>
</li>
<li><p><strong>Uptime Kuma</strong> checked service availability.</p>
</li>
<li><p><strong>Nginx Proxy Manager</strong> provided a route towards simpler service access.</p>
</li>
<li><p><strong>Vaultwarden</strong> offered a potentially useful password-management service, once HTTPS was properly addressed.</p>
</li>
</ul>
<p>What I didn't yet have was a fully coherent way to manage how those services were deployed, accessed, secured and recovered.</p>
<p>And I was starting to recognize the difference.</p>
<h2>Five containers, several unfinished conversations</h2>
<p>By this point, the lab was beginning to look rather impressive from the dashboard.</p>
<p>There were services to click, containers to inspect and status checks reporting results.</p>
<p>But the list of unresolved considerations was growing alongside the list of working applications.</p>
<p>What happened to application data if I removed a container?</p>
<p>How would I rebuild the environment without manually repeating every deployment?</p>
<p>What would happen after a Proxmox host failure?</p>
<p>Could I restore the applications, their settings and their data rather than simply reinstall the software?</p>
<p>How would I make internal names work consistently across different devices?</p>
<p>And how would I distinguish applications that were safe to experiment with from those I might eventually rely on?</p>
<p>These weren't necessarily questions I'd fully answered on 7 June.</p>
<p>They were the sorts of questions the environment was beginning to force me to confront.</p>
<p>I was enjoying building things, but I was also beginning to see how easily a lab could become another collection of loosely connected services.</p>
<p>Just with better-looking dashboards.</p>
<h2>Moving beyond individual commands</h2>
<p>The original Docker applications had been deployed using individual <code>docker run</code> commands.</p>
<p>That worked for getting started.</p>
<p>But it wasn't how I wanted to manage an expanding set of services indefinitely.</p>
<p>By 10 June, I had begun consolidating the Docker deployments using <strong>Docker Compose</strong>.</p>
<p>Instead of relying on a collection of individual commands, Compose provided a way to describe application deployments through configuration files.</p>
<p>That made the environment easier to understand and gave me a more repeatable basis for managing it.</p>
<p>Around the same time, I also began establishing more deliberate backup arrangements, including backups of the Docker VM and an archive of its application data and configuration.</p>
<p>There was still plenty to learn about restoration, and creating a backup isn't the same as proving that it can be restored successfully.</p>
<p>But the thinking was beginning to change.</p>
<p>The objective was no longer simply to get another application running.</p>
<p>It was becoming important to understand how that application fitted into the wider environment and what would be required to keep it operational.</p>
<h2>I may have been moving a little too quickly</h2>
<p>Looking back, I can appreciate how much I tried to accomplish in a relatively short period.</p>
<p>Within days of recovering an old Dell computer and installing Proxmox, I'd started building a virtualized network-management environment, a container platform, application dashboards, monitoring and the foundations of internal service discovery.</p>
<p>Each step had a reasonable explanation.</p>
<p>But collectively, I was introducing a fair amount of complexity before all the underlying arrangements had been properly established.</p>
<p>I don't necessarily regret that.</p>
<p>Part of the purpose of CMR Lab is to experiment, encounter problems and learn how different technologies fit together.</p>
<p>But there's a difference between experimentation and allowing an unfinished experiment to become something the household depends on.</p>
<p>That distinction would matter more as I began introducing services intended for everyday use.</p>
<p>For now, the Docker platform was operational, but not particularly mature.</p>
<p>The next challenge was to make service access more consistent, establish proper internal DNS and address HTTPS rather than continuing to work around those missing pieces.</p>
<p>And somewhere in all of that, I still wanted the original thing I'd asked for.</p>
<p><em>A simple webpage with links to my services.</em></p>
<hr />
<p><em>This article is part of the CMR Lab engineering journal. Supporting architecture, implementation decisions and historical technical records are available in the</em> <a href="https://github.com/charlesrattan/cmr-lab-2026"><em>CMR Lab GitHub repository</em></a><em>.</em></p>
]]></content:encoded></item><item><title><![CDATA[Getting Proxmox Running Was the Easy Part]]></title><description><![CDATA[MongoDB had a rather unhelpful message for me.
status=4/ILL (Illegal Instruction)
That was it. The service would attempt to start and immediately fail.
I'd only just finished putting together my first]]></description><link>https://cmrlab.hashnode.dev/getting-proxmox-running-was-the-easy-part</link><guid isPermaLink="true">https://cmrlab.hashnode.dev/getting-proxmox-running-was-the-easy-part</guid><category><![CDATA[Homelab]]></category><category><![CDATA[proxmox]]></category><category><![CDATA[virtualization]]></category><category><![CDATA[unifi]]></category><category><![CDATA[troubleshooting]]></category><dc:creator><![CDATA[Charles Rattan]]></dc:creator><pubDate>Tue, 13 Oct 2026 16:02:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6acc2c62a8662b5ce37f8451/b0965eb3-1b4d-4ee2-a0fb-3e7aff8cbcb3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>MongoDB had a rather unhelpful message for me.</p>
<p><code>status=4/ILL (Illegal Instruction)</code></p>
<p>That was it. The service would attempt to start and immediately fail.</p>
<p>I'd only just finished putting together my first Proxmox server, and one of the applications I wanted to run was already refusing to cooperate.</p>
<p>The interesting part was that the processor wasn't actually incapable of running the software. <strong>The problem was what the virtual machine thought the processor could do.</strong></p>
<p>But I'm getting ahead of myself.</p>
<h2>The first proper server</h2>
<p>By 6 June 2026, the Dell OptiPlex 7010 I'd recovered was ready for its new role.</p>
<p>It had an Intel Core i7-3770, 20 GB of DDR3 memory, a 500 GB SSD and a 1 TB hard drive. Not exactly a modern server, but certainly enough to explore virtualisation and begin separating some of the services that had accumulated on my old Ubuntu MacBook.</p>
<p>I installed <strong>Proxmox VE 9.2.2</strong> on the SSD.</p>
<p>The installation itself was fairly uneventful.</p>
<p>Once the web interface was accessible, I configured the no-subscription repositories, installed the available updates and rebooted to confirm everything returned as expected.</p>
<p>I also configured the BIOS to recover automatically after a power failure and prepared the machine to operate without a monitor or keyboard.</p>
<p>These weren't particularly exciting steps, but I wanted the basics right before depending on the machine for anything useful.</p>
<p>The secondary hard drive was brought into the storage configuration, and I was finally ready to create the first virtual machine.</p>
<h2>Giving things their own place</h2>
<p>The first VM was deliberately uncomplicated.</p>
<p>I created <code>ubuntu-mgmt-01</code>, assigned it two virtual CPUs, 4 GB of RAM and a 50 GB disk, then installed Ubuntu Server.</p>
<p>The idea was to have a dedicated management environment for infrastructure utilities and, eventually, automation.</p>
<p>It wasn't particularly difficult to get running. Ubuntu installed, networking worked, SSH was available and the QEMU Guest Agent was installed so Proxmox could better communicate with the guest.</p>
<p>I also created a snapshot of the fresh installation.</p>
<p>That last step felt like one of the immediate benefits of virtualisation.</p>
<p>I could experiment with software and configurations without necessarily having to rebuild an entire physical machine if something went badly wrong.</p>
<p>Of course, <strong>snapshots aren't backups</strong>, and I would eventually need to think much more seriously about recovery. But for the purpose of experimenting with a fresh operating system, it was a useful capability.</p>
<p>With the first VM running, the next question was what service to migrate.</p>
<p><em>UniFi seemed an obvious candidate.</em></p>
<h2>One access point, too many possible controllers</h2>
<p>My home network included a UniFi AC Pro access point.</p>
<p>It was working, but its management arrangement wasn't particularly satisfactory.</p>
<p>I had an older UniFi Cloud Key Gen1 that I'd managed to recover, reset and update. There was also a UniFi Network Controller running on my main Windows machine.</p>
<p>The Cloud Key was an option, but its age and limited upgrade path made me question whether it was the right place to continue investing time.</p>
<p>And I didn't particularly want the main PC responsible for managing the wireless network.</p>
<p>That was precisely the kind of arrangement I was trying to move away from.</p>
<p>So I decided to give UniFi its own VM.</p>
<p><code>unifi-controller-01</code> became VM110, running Ubuntu Server 24.04 with resources assigned specifically for the UniFi Network Application.</p>
<p>I liked the idea of this separation.</p>
<ul>
<li><p><strong>VM100 —</strong> <code>ubuntu-mgmt-01</code><strong>:</strong> General infrastructure management</p>
</li>
<li><p><strong>VM110 —</strong> <code>unifi-controller-01</code><strong>:</strong> UniFi network administration</p>
</li>
</ul>
<p>Each would have a clear responsibility.</p>
<p>At least, that was the intention.</p>
<h2>Apparently, the processor couldn't follow instructions</h2>
<p>Installing UniFi required a few supporting components, including Java and MongoDB.</p>
<p><strong>MongoDB was where things stopped progressing.</strong></p>
<p>The service failed with an <em>illegal instruction</em> error.</p>
<p>Initially, that suggested some sort of incompatibility with the processor. The OptiPlex was built around an ageing third-generation Intel Core i7, so it wasn't unreasonable to question whether its instruction set was sufficient.</p>
<p>But the processor supported <strong>AVX</strong>, which was relevant to the MongoDB version I was attempting to run.</p>
<p>The issue turned out to be how Proxmox was presenting the CPU to the virtual machine.</p>
<p>VM110 had been configured using the <code>x86-64-v2-AES</code> virtual CPU model.</p>
<p>That provided a standardized set of processor capabilities, but it did not expose the AVX instructions MongoDB needed.</p>
<p>In effect, <strong>the physical processor could support the software, but the virtual machine couldn't see the necessary capability.</strong></p>
<p>I changed the VM's CPU type from <code>x86-64-v2-AES</code> to <code>host</code>.</p>
<p>MongoDB started successfully.</p>
<p>It was one of those problems that made considerably more sense after it had been resolved.</p>
<p>The error message wasn't necessarily misleading. The software really was encountering an instruction it couldn't execute in its presented environment.</p>
<p>What I'd initially considered a possible hardware limitation was actually a virtualization configuration issue.</p>
<p>I also came away with a better appreciation for why virtual CPU models matter.</p>
<p>Presenting a standardized CPU can be useful when moving virtual machines between hosts with different processors. Exposing the host's capabilities can offer better compatibility with certain workloads, but introduces its own portability considerations.</p>
<p>In my case, with a single Proxmox host at the time, changing to <code>host</code> was a reasonable decision.</p>
<p>More importantly, <strong>I understood why the change worked.</strong></p>
<h2>The application worked. The access point was another matter.</h2>
<p>With MongoDB running, the UniFi Network Application installed successfully and its management interface became accessible.</p>
<p>That was encouraging.</p>
<p>The remaining task was to move the access point away from the controller on my Windows machine.</p>
<p>I'd already been dealing with a peculiar behaviour before the migration.</p>
<p>The access point would continue broadcasting Wi-Fi and supporting connected devices, but periodically disappear from the controller. Issuing a new <code>set-inform</code> command would restore its visibility.</p>
<p>I remember questioning why this seemed to happen almost every night.</p>
<p>The distinction was important. <strong>The wireless access point wasn't necessarily failing as a wireless device. Its communication with the controller was the part behaving unexpectedly.</strong></p>
<p>Moving controller management onto a dedicated VM offered a cleaner arrangement, although it wasn't proof that the recurring behaviour would disappear.</p>
<p>I evaluated the existing controller backup and began preparing the new environment, including recreating the wireless network settings.</p>
<p>The access point initially appeared in the new controller, but the migration wasn't straightforward.</p>
<p>At one point, it required a reset.</p>
<p>I connected to the device and issued:</p>
<p><code>mca-cli-op set-default</code></p>
<p>That command reset the access point to its default state and closed the SSH connection, as expected.</p>
<p>What happened afterward was less convenient.</p>
<p>The access point was still visible on the local network. I could ping it, and the Linksys router showed it as a connected device.</p>
<p>Its LED was solid white.</p>
<p>But it wasn't appearing in the new UniFi controller, and the usual management connections weren't responding.</p>
<p>This was another useful distinction.</p>
<p>A successful ping told me the device was reachable at the network layer. It didn't tell me whether its management services were ready or whether it had established communication with the correct controller.</p>
<p>It was frustrating because the device was clearly there, but the application intended to manage it couldn't see it.</p>
<p>Eventually, I completed the migration and the AC Pro was successfully adopted into VM110.</p>
<p>The original controller on the Windows machine could finally be retired.</p>
<p>I enabled automatic startup for the management and UniFi virtual machines so they would return after the Proxmox host restarted.</p>
<p>The original objective had been achieved: <strong>the wireless controller now had a dedicated home on the virtualization platform.</strong></p>
<h2>Two problems, two different lessons</h2>
<p>Looking back, the MongoDB and access point problems were quite different.</p>
<p>With MongoDB, I had a service that wouldn't run because the virtualisation layer was hiding a processor capability. The application logs pointed towards an instruction problem, and understanding the relationship between the guest CPU model and physical hardware led to a specific, successful correction.</p>
<p>With the access point, basic network connectivity wasn't enough to establish that controller communication was working.</p>
<p><strong>A responding device and a manageable device aren't necessarily the same thing.</strong></p>
<p>Both experiences reinforced something I wanted CMR Lab to help me develop: the discipline to separate what I've observed from what I've assumed.</p>
<ul>
<li><p><strong>An error message is evidence</strong>, but it still needs interpretation.</p>
</li>
<li><p><strong>A successful ping is evidence</strong>, but it only answers a particular question.</p>
</li>
<li><p><strong>A configuration change that makes something work</strong> doesn't automatically establish every detail of the original cause.</p>
</li>
</ul>
<h2>By the end of the weekend</h2>
<p>In a relatively short period, an ageing Dell OptiPlex had become an operational Proxmox server with separate virtual machines for management and wireless network administration.</p>
<p>There had already been a hardware recovery exercise, some storage configuration, a virtual CPU compatibility problem and an access point migration that was more awkward than I'd anticipated.</p>
<p>But the important thing was that the environment was beginning to make sense.</p>
<p>Instead of having services distributed across whichever machines happened to be available, I was beginning to assign responsibilities deliberately.</p>
<p>I also had a much better understanding of the systems supporting those services.</p>
<p>The next step was to build a separate Docker environment for the applications I actually wanted to run.</p>
<p>That would introduce another collection of decisions about containers, service access, storage, reverse proxies and which things should remain experiments rather than become dependencies.</p>
<p>For the moment, though, the first two virtual machines were doing their jobs.</p>
<p><em>And I'd already learned more than I expected from getting them there.</em></p>
<hr />
<p><em>This article is part of the CMR Lab engineering journal. Supporting architecture, implementation decisions and historical technical records are available in the</em> <a href="https://github.com/charlesrattan/cmr-lab-2026"><em>CMR Lab GitHub repository</em></a><em>.</em></p>
]]></content:encoded></item><item><title><![CDATA[Starting Over Without Starting From Scratch]]></title><description><![CDATA[There comes a point when you look at something you've been building for years and wonder whether it would be easier to tear it all down and start again.
That was more or less where I found myself at t]]></description><link>https://cmrlab.hashnode.dev/starting-over-without-starting-from-scratch</link><guid isPermaLink="true">https://cmrlab.hashnode.dev/starting-over-without-starting-from-scratch</guid><category><![CDATA[Homelab]]></category><category><![CDATA[proxmox]]></category><category><![CDATA[self hosting]]></category><category><![CDATA[networking]]></category><category><![CDATA[#learning-in-public]]></category><dc:creator><![CDATA[Charles Rattan]]></dc:creator><pubDate>Mon, 12 Oct 2026 01:39:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6acc2c62a8662b5ce37f8451/901ffd3f-61d2-437e-b2a8-909a19de97e4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There comes a point when you look at something you've been building for years and wonder whether it would be easier to tear it all down and start again.</p>
<p>That was more or less where I found myself at the beginning of June 2026.</p>
<p>I had what I loosely considered a home lab. There was an ageing MacBook running Ubuntu Server, a collection of networking equipment, some Raspberry Pis and several computers that had either been repurposed or were waiting to be useful again.</p>
<p>Things worked. Mostly.</p>
<p>I had Jellyfin running, Cockpit for management, experiments with Ollama and a few other services that had accumulated over time.</p>
<p>But the environment wasn't particularly organized. Some things had been configured because I needed them at the time. Others existed because I wanted to experiment with something new.</p>
<p>I could make things work, but I couldn't necessarily claim that the environment had been designed with any real intention.</p>
<p>And increasingly, that bothered me.</p>
<h2>A collection of experiments isn't necessarily a lab</h2>
<p>I enjoy working with technology. Much of what I've learned throughout my career has come from working through problems, experimenting and figuring things out.</p>
<p>That curiosity doesn't switch off when I leave work.</p>
<p>Over time, the equipment I had available became an opportunity to explore things I might not ordinarily get to experiment with in a professional environment.</p>
<p>My old MacBook Pro, for example, had become an Ubuntu server. It wasn't particularly powerful: a dual-core Intel i5, 8 GB of memory and a modest SSD, supplemented by an external media drive.</p>
<p>It was also connected over Wi-Fi.</p>
<p>For a few services and occasional experiments, it was useful. But I was beginning to ask more of it than I had originally intended.</p>
<p>I wanted to explore virtualization, better network management, centralized DNS, automation, monitoring and eventually cybersecurity experimentation.</p>
<p>I also wanted documentation that was more meaningful than a collection of screenshots and notes I might struggle to find six months later.</p>
<p>The problem wasn't necessarily the equipment.</p>
<p>It was the absence of a coherent plan.</p>
<h2>The temptation to start from scratch</h2>
<p>My initial thought was to scrap the existing arrangement and rebuild everything.</p>
<p>New naming conventions. A better physical network. Clearly defined services. Proper documentation. A virtualization platform rather than another collection of applications running directly on whatever computer happened to be available.</p>
<p>I even started thinking about what new hardware might make the most sense.</p>
<p>But before committing to purchases, I decided to examine what I already had.</p>
<p>There were Dell OptiPlex machines, Lenovo laptops, two Raspberry Pis, a UniFi access point, a Cloud Key, a UniFi Security Gateway and various switches.</p>
<p>Some were operational. Some hadn't been used in a while. Others weren't even powering on properly.</p>
<p>And that became the first real exercise.</p>
<p><strong>Instead of designing around what I wanted to buy, I would design around what I could actually make work.</strong></p>
<h2>The Dell OptiPlex that wasn't quite dead</h2>
<p>One of the available systems was a Dell OptiPlex 7010 Small Form Factor.</p>
<p>It had seen better days.</p>
<p>When I began examining it on 3 June, it wasn't a functioning server candidate. I was dealing with an amber power indicator, diagnostic beeps and uncertainty about the condition of its components.</p>
<p>As it turned out, the machine initially had no memory installed.</p>
<p>After fitting a spare DDR3 module, I managed to get into the BIOS. The machine recognised the RAM and I could begin investigating the processor, storage and other components.</p>
<p>That was encouraging.</p>
<p>I had several old OptiPlex machines available, which meant I could recover parts rather than immediately purchasing replacements.</p>
<p>By 5 June, the system had come together.</p>
<p>It had an Intel Core i7-3770 processor, 20 GB of DDR3 memory, a 500 GB SSD and a 1 TB hard drive.</p>
<p>There was still a problem with one of the memory slots, but I had a working machine with enough resources to begin experimenting with virtualization.</p>
<p>It wasn't new, powerful or particularly elegant.</p>
<p>But it could do the job.</p>
<p>And there was something satisfying about that.</p>
<p>I had gone from investigating why an old computer wouldn't start to preparing it as the foundation of a completely rebuilt environment.</p>
<h2>Sometimes the biggest improvement is a cable</h2>
<p>There was another issue I needed to address before moving forward.</p>
<p>The internet connection entered the house downstairs. A CAT6 connection already ran to the Linksys router in the upstairs living room, where some of the networking equipment was located.</p>
<p>My lab equipment, however, was in a bedroom.</p>
<p>Rather than running another cable, I had been relying on Wi-Fi for convenience.</p>
<p>That was fine for ordinary use, but it wasn't how I wanted to operate a server hosting several persistent virtual machines and network services.</p>
<p>So I ran and terminated a CAT6 cable between the living-room networking equipment and the bedroom.</p>
<p>I tested the connection, brought a switch online and connected the main workstation and the newly recovered OptiPlex.</p>
<p>Nothing particularly sophisticated happened.</p>
<p>But suddenly I had a much more dependable physical foundation for the work ahead.</p>
<p>It also reminded me of something that is easy to overlook when you're excited about virtual machines, automation and security tools.</p>
<p>Sometimes the most important improvement is getting the basics right.</p>
<h2>Getting serious about documentation</h2>
<p>Around the same time, I began organising the project on GitHub.</p>
<p>This was another learning exercise in itself.</p>
<p>I'd worked with code and development tools before, but I hadn't developed a particularly disciplined approach to version control.</p>
<p>I was familiar with the problem of accumulating files called something along the lines of <em>v1.0</em>, <em>v1.2</em>, <em>final</em> and <em>really final</em>.</p>
<p>I didn't want my lab documentation to become another version of that.</p>
<p>So I began with a single repository and Markdown documents for the equipment inventory, architecture, decisions, roadmap and development history.</p>
<p>At first, even that felt a little excessive. I found myself creating files and wondering whether I was spending more time organising the project than actually building it.</p>
<p>That was a useful early lesson too.</p>
<p>Documentation needs a purpose.</p>
<p>I didn't need to manufacture an impressive-looking collection of documents. I needed enough structure to explain what existed, why I made decisions and what happened when something changed.</p>
<p>The documentation would evolve alongside the environment.</p>
<h2>The first real milestone</h2>
<p>By 6 June, the recovered OptiPlex was ready to become the first Proxmox server.</p>
<p>This marked the point where CMR Lab began transitioning from a collection of individual systems into something more deliberate.</p>
<p>The original MacBook had served its purpose, but it was no longer the right foundation for what I wanted to accomplish.</p>
<p>With Proxmox, I could begin separating responsibilities: management utilities, network administration and application hosting could each have their own environments.</p>
<p>At least, that was the plan.</p>
<p>I would soon discover that installing a virtualisation platform was only the beginning. Processor compatibility, storage configuration, application dependencies and networking would all introduce their own challenges.</p>
<p>Some of those problems would turn out to be considerably more interesting than the installations themselves.</p>
<h2>Why I'm documenting this journey</h2>
<p>CMR Lab isn't an attempt to build the most powerful home lab or collect the largest number of running services.</p>
<p>It's an opportunity to understand technology more deeply through practical experience.</p>
<p>I want to be able to explain not only what I've deployed, but why it was necessary, what alternatives I considered, what problems I encountered and how I determined whether something actually worked.</p>
<p>There will be mistakes, decisions I'll reconsider and experiments that don't go according to plan.</p>
<p>I'm not particularly interested in editing those parts out.</p>
<p>They're often where the learning happens.</p>
<p>And if documenting those experiences helps someone else approach a similar problem with a little more understanding, that's worthwhile too.</p>
<p>For now, the first milestone was relatively simple.</p>
<p>I had taken an unreliable collection of equipment, recovered an old computer, improved the physical network and established a foundation for the next stage.</p>
<p>I hadn't really started from scratch.</p>
<p>I'd started by understanding what I already had.</p>
<hr />
<p><em>CMR Lab's technical architecture, decisions and supporting records are available in the</em> <a href="https://github.com/charlesrattan/cmr-lab-2026"><em>GitHub repository</em></a><em>.</em></p>
]]></content:encoded></item></channel></rss>