Notes from a small homelab
Write-ups of the server chores I end up solving twice, so the third time takes five minutes. Short, practical, probably wrong in places.
- Upgrading Node under pm2 without the surprises
When upgrading Node.js with nvm under pm2, pin
nvm alias defaultto a major version, update the saved PATH in ~/.pm2/dump.pm2 for fork-mode apps, regenerate the pm2 systemd unit with the new node binary, and checkreadlink /proc/PID/exebefore uninstalling the old version. - Snipping Tool stuck on a busy cursor: a recycled PID
If Win+Shift+S shows only a busy cursor and SnippingTool.exe processes pile up, run
taskkill /f /im SnippingTool.exe. The hang comes from the Windows App SDK AppInstance code treating a recycled PID as alive and leaving a mutex owned. - Windows CPU % under-counts partial load
Windows time-based CPU % (Task Manager, GetThreadTimes, PDH % Processor Time) under-reported a partially loaded 8-core/16-thread desktop CPU by up to about 45% compared with QueryThreadCycleTime. To judge a CPU bottleneck, use GPU utilization or PresentMon GPU Busy instead.
- Certbot renewals that reload nginx on their own
Certificates from
certbot certonlyrenew, but nginx keeps serving the old one until reloaded. Put an executable script in /etc/letsencrypt/renewal-hooks/deploy/ that runsnginx -t && systemctl reload nginx, and test it withcertbot renew --dry-run --run-deploy-hooks. - An old monitor that forgets to listen
An old DVI monitor that stays black after boot or after a long signal gap can be woken by switching its input over DDC/CI (VCP 0x60) to VGA and back to DVI with NirSoft ControlMyMonitor, run from a scheduled task at logon.
- PowerShell 5.1 traps that only show up in the admin run
Windows PowerShell 5.1 pitfalls: BOM-less UTF-8 scripts are read as ANSI, a failed [xml] cast does not stop the script, $null becomes an empty string in .NET calls, unary-comma returns break pipelines, variable names are case-insensitive, and native exit codes must be checked.
- Restic to a second disk, the boring way
Run restic backups from a systemd service and timer (OnCalendar, RandomizedDelaySec, Persistent=true) with
restic forget --pruneretention, credentials in an EnvironmentFile, and a monthly test restore. - Bad RAM, one shared DLL, and badmemorylist
Random Windows blue screens with no WHEA errors came from one bad chip on non-ECC DDR4. Identical ILLEGAL_INSTRUCTION crashes in one shared DLL across processes pointed to a bad physical page, MemTest86 confirmed it, and
bcdedit /set {badmemory} badmemorylistfenced the pages off. - The editor update that deletes the editor
Cursor and other VS Code-based editors on Windows can delete themselves during an update when a stdio MCP server still runs the editor's bundled node.exe. Recover by moving the staged build out of the
_folder, and kill those processes before updating. - Folders called "cache" aren't always cache
Folders named cache or depots inside an app's data directory can hold the installed build: deleting C:\ProgramData\LGHUB\depots broke Logitech G HUB. Check the app's manifests before deleting, and prefer the app's own cleanup.
- Measure your DNS resolvers before picking one
Public DNS resolver speed depends on your ISP's routing. Benchmark 1.1.1.1, 8.8.8.8 and 9.9.9.9 from your own network with dig and random uncached names, and compare median and worst-case latency.