The Millhouse Group Blog
Software Development in the 21st Century
Saturday, 28 March 2026
Home-lab design (2026 edition) part 2 - Inside the NUC
Following on from last-month's look at the [physical boxes that make up my home "lab"](https://blog.themillhousegroup.com/2026/02/home-lab-design-pt1-physical-boxes.html) in 2026, there's only one box that actually deserves any deeper inspection; the Intel NUC5PGYH, an incredibly-lucky hard-rubbish find from a few years back that, after sourcing a suitable 19V (i.e. laptop) power supply, de-Windows-ing, and most recently, a RAM doubling (at the princely cost of $25) to 8Gb, has proven itself to be an ideal platform for various x86-based experimentation.
Up until last month, the NUC has been running Debian Bookworm, keeping up my long-standing tradition of using Debian-based Linux for my home servers. The primary applications running on this box before 2026 were [_Home Assistant_](https://www.home-assistant.io/) via the [packaged-up `haos.qcow2` virtual machine image](https://www.home-assistant.io/installation/linux/#install-home-assistant-operating-system), the excellent [_OctoPrint_](https://octoprint.org/) for [3D printer](https://blog.themillhousegroup.com/search/label/3dprinting) monitoring, the [_BrickSync_](https://bricksync.net/) inventory-management software that keeps multiple [online LEGO parts stores](https://blog.themillhousegroup.com/2024/06/home-cooked-and-delicious.html) in sync, and various self-written node.js-based webapps that aren't suitable for public hosting on the otherwise-brilliant (and free) [Netlify](https://www.netlify.com/) platform.
HAOS runs as a VM, which was fairly easy to get going following the instructions as linked above, and pretty-much looks after itself. OctoPrint, being a "proper" solution, runs properly as a system service; the latter apps I'd run fairly erratically using `screen` sessions. Finally, after a particularly annoying festival of `screen`-cursing and port-interfering, I'd had enough. The SvelteKit apps I prefer these days are [fairly trivial to Dockerise](https://khromov.se/dockerizing-your-sveltekit-applications-a-practical-guide/), and I've spent enough time with Docker in my work life to appreciate the true segregation and repeatability that it brings - "cattle, not pets". And thus so began a new phase - transforming the NUC into a more-appropriate host for these "workloads".
### Moving it all over
After carefully tidying up the home directory of the Debian installation (which featured the usual assortment of scripts, Github clones and random downloaded files), it was time to say goodbye. My new OS for the NUC is [Proxmox VE](https://www.proxmox.com/en/products/proxmox-virtual-environment/overview), which is still Debian-based underneath, so I guess my run continues. I liked the idea of completely installing from scratch, and having the absolute thinnest layer possible between the VM workloads and the bare metal. It certainly shows in Proxmox's boot time, which is extremely impressive; no starting desktops or initializing sound systems here - just straight down to business!
The conceptual layout of the VMs inside Proxmox is also refreshingly simple:
```mermaid
architecture-beta
group prox(affinity:server)[Proxmox VE]
service ahaos(affcircle:c-house-blue)[HAOS 100] in prox
service zdocker(affcircle:c-nas-blue)[Docker 101] in prox
```
That's it. _Everything_ that's not Home Assistant will be run as a Docker container inside VM 101.
Moving the `HAOS` image (that I'd backed up over to my NAS, simply by stopping the VM and copying the `haos.qcow2` file) was easy, courtesy of this excellent [step-by-step guide](https://forum.proxmox.com/threads/guide-install-home-assistant-os-in-a-vm.143251/). With `haos.qcow2` safely copied into your Proxmox `local` storage, you can install it like this in the main Shell:
```
root@nuc:/home# qm importdisk 100 /var/lib/vz/import/haos.qcow2 local-lvm
importing disk '/var/lib/vz/import/haos.qcow2' to VM 100 ...
Logical volume "vm-100-disk-1" created.
Logical volume pve/vm-100-disk-1 changed.
transferred 0.0 B of 32.0 GiB (0.00%)
transferred 327.7 MiB of 32.0 GiB (1.00%)
transferred 655.4 MiB of 32.0 GiB (2.00%)
...
```
Now for *Docker*, there are many opinions about the best way to run it, but I like an easy life, so another VM is my choice. I already had a `docker.qcow2` image, which runs a super-slim _Alpine Linux_ host OS, [just enough to host Docker](https://wiki.alpinelinux.org/wiki/Docker), so we do it all again. Exactly the same. Cattle, not pets ;-)
```
root@nuc:~# qm importdisk 101 /var/lib/vz/import/docker.qcow2 local-lvm
importing disk '/var/lib/vz/import/docker.qcow2' to VM 101 ...
Logical volume "vm-101-disk-1" created.
Logical volume pve/vm-101-disk-1 changed.
transferred 0.0 B of 32.0 GiB (0.00%)
transferred 331.0 MiB of 32.0 GiB (1.01%)
transferred 665.2 MiB of 32.0 GiB (2.03%)
transferred 996.1 MiB of 32.0 GiB (3.04%)
transferred 1.3 GiB of 32.0 GiB (4.06%)
```
### Final touches (USB device mapping)
I have a couple of USB devices that hang off the NUC, and Proxmox VE has actually substantially improved my quality-of-life with its device-ID-specific mapping which means even if a device is power-cycled (as happens all the time with the 3D printer; it's too noisy to leave on) it still remains consistently available to the consuming applications. Under Debian, such a device would appear as a new `bus:device` pair every time, causing havoc.
#### Mapping the Sonoff Zigbee dongle through to the `haos` VM:
#### Mapping the 3D printer through to the `docker` VM:
Labels:
3dprinting,
alpine,
containerization,
debian,
docker,
haos,
homeassistant,
homeautomation,
markdown-enabled,
nuc,
octoprint,
proxmox,
proxmoxve,
qcow2,
svelte,
sveltekit,
usb
Saturday, 21 February 2026
Home-lab design (2026 edition) part 1 - Physical Boxes
Any long-time readers of this blog will probably be sick of my Mermaid [network diagrams](https://blog.themillhousegroup.com/2025/07/mikrotik-automation.html), but hey, these posts are as much for me to document my own trials and tribulations as they are for you, so ... let's do another one!
```mermaid
architecture-beta
service internet(affinity:cloud)
group home(affinity:house)[Home]
service ispr(affcircle:c-firewall-green) [ISP Router] in home
service gbe(affcircle:c-router-green)[Mikrotik] in home
service pi(affcircle:c-server-blue)[Pi] in home
service nuc(affcircle:c-server-blue)[NUC] in home
service nas(affcircle:c-nas-blue)[NAS] in home
internet:B --> T:ispr
ispr:B --> T:gbe
gbe:B -- T:pi
gbe:L -- R:nas
gbe:R -- L:nuc
```
Dead simple.
The __NAS__, a __Synology DS209__, has been faithfully just doing its thing for 15(!) years now and aside from occasional, painless, disk size increments, just keeps keeping on.
And after last year's introduction of the [__Mikrotik RouterBoard RB2011__](https://blog.themillhousegroup.com/2025/01/upgrading-to-mikrotik-routerboard.html) router for [DHCP](https://blog.themillhousegroup.com/2025/03/upgrading-to-mikrotik-routerboard.html) and [DNS](https://blog.themillhousegroup.com/2025/04/upgrading-to-mikrotik-routerboard.html), the __Raspberry Pi 4B__ has been freed up for more Pi-suitable tasks (light web serving, streaming, home automation tasks).
Which leaves the __Intel NUC__, specifically a `NUC5PGYH` - a lucky roadside hard-waste find that has proven invaluable as a super-compact, super-efficient x86 server. This is the core of my "self-hosting" plan for 2026.
Saturday, 3 January 2026
2026 - Off we go again
Happy New Year!
After some refreshing time off I'm looking to refresh my "home lab" with some self-hosted projects, so this is likely to be a big focus of this year's posts.
Of course, as much as possible I'm still [doing](https://blog.themillhousegroup.com/2023/09/frenzyjs-saga-of-flood-fill.html) [projects](https://blog.themillhousegroup.com/2022/06/introducing-cardle.html) "out in the open" and hosting them on [Netlify](https://www.netlify.com), whose [SvelteKit](https://svelte.dev/docs/kit/introduction) [integration](https://svelte.dev/docs/kit/adapter-netlify) is still the smoothest and easiest way to get a modern, public-facing website that I've found.
But for situations where full public access isn't appropriate, I've been experimenting with [Dockerization of Svelte apps](https://khromov.se/dockerizing-your-sveltekit-applications-a-practical-guide/) and self-hosted Docker and I'm liking what I'm seeing.
More to come.
Tuesday, 30 December 2025
2023 Kia EV6 GT-Line RWD
After several experiments and test drives, copious amounts of internet research and the fortuitous introduction of a Novated Lease scheme at my employer, earlier this month I took delivery of a two-year old, heavily depreciated *Kia EV6*.
For me, this car manages to tiptoe along a perilous path between Mr Musk's vehicles (with their [flawed dependence on the centre screen](https://blog.themillhousegroup.com/2024/03/tesla-model-3-2022-standard-range-rwd.html)) and the influx of Chinese vehicles (which in my experience ride like wheelbarrows) - a well-built, good-to-drive vehicle that has (roughly) the dimensions I favour with a decent range.
The novated lease (ex-tax) brought the cost of the car down to close to 50% of its original sticker, and all the registration, insurance, servicing and consumables (electricity and tyres) all get paid from my pre-tax salary so it works out very nicely as a package deal.
Having owned and driven it now for a couple of weeks (including a couple of decent road trips) here are my takeaways:
*Pros*
- Locally-tuned suspension rides really well
- RWD dynamics disguise the (significant) weight
- Real-world 450km road-trip range
- Generally excellent cabin
- Screen in front of driver
*Cons*
- HVAC/Media soft-keys always in wrong mode
- Boot/trunk space could be bigger
- Lack of Kia Connect in AU
The cons probably warrant more explanation;
the *HVAC/Media soft keys* are a halfway-house that means you don't always need to be interacting with the main central touchscreen à la Tesla - this is good, but the fact that they are not actual buttons and each one has a dual function (depending on the "position" of the master switch) can cause annoyance.
For some reason, Kia Motors Australia have decided that the EV6 isn't supported by the Kia Connect app. That means no fancy seat pre-heating but also basics like seeing the battery charge level is simply impossible on Australia. Crazy, right?
That said, it's an excellent car, and hopefully some future software/firmware updates will fix most of the cons.
Labels:
electriccars,
ev,
ev6,
green,
kia,
markdown-enabled,
polestar,
tesla
Sunday, 30 November 2025
Home Assistant and Zigbee
After my Google Home Mini [devices started "dying"](https://blog.themillhousegroup.com/2024/10/google-home-minis-1st-gen-bricked.html) (aka getting remotely bricked) I was looking around for something less vendor-tied to perform the same tasks and found the [Home Assistant Voice Preview](https://www.home-assistant.io/voice-pe/) which I have taken the plunge on. More on that later.
And so I had to jump to the Home Assistant world from OpenHAB.
Oh wow. This has been such a nice change. Everything about setting the thing up (I'm running a `hass` VM image on my `NUC5PGYH` NUC) was trouble-free, it runs well and when the time came to add a sprinkling of Zigbee, it was *so* easy I actually audibly gasped.
I plugged in one of these Sonoff USB Zigbee gateways:
... went into my VM console and granted USB passthrough to the relevant (cryptically-named) device (points off to Sonoff here - couldn't you have changed the USB device name and vendor to something a little bit more ... obvious?)
And by the time I'd logged into the Home Assistant page, it had already discovered the gateway!
Pairing with the multiple (cheap!) Zigbee temperature/humidity sensors was stupidly-simple and they've been rock-solid for weeks now. Much better than the wifi-based ones I've tried in the past.
Niiiice.
Sunday, 26 October 2025
shellcommand | shellcommand | pbcopy aliases FTW
This is such a simple yet powerful thing. I was writing up a slightly-tedious process at work that required using various command-line tools (like `kubectl`) to access a secret being used in a Kubernetes pod. The secret could then be copy-pasted into a web UI that needed access using the same credentials.
That's when it hit me: the whole thing can be done as a one-liner that finishes with ` | pbcopy` to paste the output into the clipboard, and then aliased in your shell startup (e.g. `~/.zprofile` on the Mac); e.g.:
```
alias getdbpass="kubectl get secret db_secrets-collection -n namespace -o json | jq --raw-output '\''.data | map_values(@base64d) | .PASSWORD'\'' | pbcopy'
```
Now you just type `getdbpass` when you need to get in, flip to your browser, and Cmd-V. And you can always check/remind yourself what it does with `alias` on the command line. You can build up an awesome collection of these. saving time and typos - give it a try!
Sunday, 28 September 2025
The fascinating intersection of SVG and Svelte
## The context
I'm working on a new top-secret web project that had some interesting graphical requirements:
- Tileable images that scale to fit the entire device viewport
- Support rotation in 4 steps (N,S,E,W)
- Support overlaying
- Support filling in distinct steps
- Support theming; i.e. be able to draw the images using (at least) a "light" and "dark" variant
Pretty steep requirements, and once I realised the final two requirements were non-optional, PNGs just weren't going to cut it; the sheer number of permutations would be prohibitive.
## Evangelising Svelte - Svangelising?
[Svelte](https://svelte.dev/) is definitely my "current squeeze" when it comes to building web front-ends; it's minimal, seems to avoid React's primary footguns and with [SvelteKit](https://svelte.dev/docs/kit/introduction), makes development of full-stack apps an absolute breeze. It truly feels like standing on the shoulders of giants when using these powerful tools!
Svelte has an extremely interesting property in that due to the way that `.svelte` files are laid out, i.e.:
```
```
... you can drop an *SVG file* into a Svelte project, change its extension to `.svelte` and it **Just Works** - it's a Svelte file that just happens to not have any `script` or `style`.
## SVelteGraphics Version 1
Given that an SVG "is just" (or perhaps [`satisfies` the definition of](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#the-satisfies-operator)) a Svelte component, that means we can give it props, right?
`FillableThing.svelte`:
```
```
Which we can use like this:
`Caller.svelte`:
```
```
... although this is arguably not particularly useful; being able to set `filled` is nice, but we really want dynamic control over *which* SVG we're actually rendering in the first place.
## Snippet Like It's Hot
Further messing-around with the possibilities inherent in this finally led me to this "shape", that uses a [Svelte snippet](https://svelte.dev/docs/svelte/snippet):
`FillableThingSnippet.svelte`
```
{#snippet thingSnippet(filled: boolean)}
{/snippet}
```
So what I've ended up with is the "guts" of the original SVG (that had the two paths `main` and `inner`) inside a Svelte `snippet` that I can put anywhere in my Svelte app, and call with:
`Caller.svelte`
```
{@render thingSnippet(true)}
```
and as long as I've got my themed CSS variables (e.g. `--theme-color` and `--theme-fill-color`) defined, I've got fillable, themable SVG content.
## Bonus: The MDN SVG Tutorial
MDN has a [fantastic tutorial](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorials/SVG_from_scratch) that introduces the components of SVGs one-by-one, and I'm really interested in exploring programmatic manipulations of these. Stay tuned!
Subscribe to:
Comments (Atom)







