Host Inventory for a (not-) Homelab
I don't really consider myself as running a proper "homelab." For starters, I own neither a proper network rack nor any rackable gear, and I see that as a prerequisite for calling your setup a "homelab." Nonetheless, I have a lot of physical and virtual machines to keep track of.
A thing I find useful sometimes is to be able to print a list of all my hosts. This ought to be simple enough, but what source of truth should I use? For hobby projects, any documentation is sure to fall out of date quickly.
The obvious solution, following a best practice that applies equally in programming or updating an electrical panel: documentation should be as near as possible to the implementation — unified, if possible.
For me, this means using my ~/.ssh/config
as the source of truth. This file necessarily gets updated as I add or update machines, it supports comments, and it's checked into version control for sharing across all my machines. Perfect.
The following shell alias parses hosts out from ~/.ssh/config
and print them to the terminal:
alias hosts-list='{ grep "^#\?Host " ~/.ssh/config | grep -v "Host \*" | sed "s/^Host //" | sed "s/^#Host /!/" ; }'
Output from the command looks like this:
burr burr.cdzombak.net #cloud #linux #deb
azul azul.cdzombak.net #cloud #linux #deb
wt wt.cdzombak.net #cloud #linux #deb
jetstream jetstream.tailnet-003a.ts.net #home #linux #deb
curie curie.tailnet-003a.ts.net #home #macos
opportunity opportunity.tailnet-003a.ts.net #home #macos
surroundings surroundings.tailnet-003a.ts.net #home #linux #deb #tiny #rpi
pidns pidns.tailnet-003a.ts.net #home #linux #deb #tiny #armbian
altdns altdns.tailnet-003a.ts.net #home #linux #deb #vm
pikvm pikvm.tailnet-003a.ts.net #home #linux #tiny #ro
jetkvm jetkvm.tailnet-003a.ts.net #home #linux #tiny #ro
pi400.dzhome #home #linux #deb #tiny #rpi
workshop-pi workshop-pi.tailnet-003a.ts.net #home #linux #deb #tiny #rpi #ro
mediactrpi mediactrpi.dzhome #home #linux #deb #tiny #rpi
rad2 rad2.dzhome #home #linux #deb #tiny #rpi #ro
labrackpwrmon labrackpwrmon.dzhome #home #linux #deb #tiny #rpi #ro
gamedeskpwrmon gamedeskpwrmon.dzhome #home #linux #deb #tiny #rpi #ro
mediactrpwrmon mediactrpwrmon.dzhome #home #linux #deb #tiny #rpi #ro
officebtns officebtns.dzhome #home #linux #deb #tiny #rpi
!planck (Windows laptop) #windows
!wilbur (Windows game desktop) #windows
There are a few special features here.
Tags: Many hosts have a sequence of tags after them that describe properties of the hosts (e.g. #deb
means the system uses Debian-style package management). The relevant Host
line in ~/.ssh/config
looks like:
Host mediactrpwrmon mediactrpwrmon.dzhome #home #linux #deb #tiny #rpi #ro
This allows me to grep
for just the hosts I'm interested in when performing a specific task. For example, if I want to apply a new Pi Reliability best practice to all my machines that use SD cards for storage, I can run hosts-list | grep '#tiny'
for a list of the relevant machines.
Placeholders: Some hosts — most notably Windows machines — do not naturally show up in my SSH config. For these hosts, I've set a convention where I add an entry to !/.ssh/config
like:
#Host wilbur (Windows game desktop) #windows
These entries are just comments as far as SSH is concerned, but hosts-list
will parse them and include them in the list, prefixed by !
.
Finally, I use a second alias that generates a Markdown-formatted "todo list" of hosts. This can be copied into e.g. Bear or processed into Things (using a Shortcut out of scope for this post) for project management/task tracking:
alias hosts-list-md='{ grep "^#\?Host " ~/.ssh/config | grep -v "Host \*" | sed "s/^Host /- [ ] /" | sed "s/^#Host /- [ ] !/" ; }'
Use and output of this command typically looks like this (in this example, finding all hosts that use a read-only root filesystem):
$ hosts-list-md | grep '#ro'
- [ ] pikvm pikvm.tailnet-003a.ts.net #home #linux #tiny #ro
- [ ] jetkvm jetkvm.tailnet-003a.ts.net #home #linux #tiny #ro
- [ ] workshop-pi workshop-pi.tailnet-003a.ts.net #home #linux #deb #tiny #rpi #ro
- [ ] rad2 rad2.dzhome #home #linux #deb #tiny #rpi #ro
- [ ] labrackpwrmon labrackpwrmon.dzhome #home #linux #deb #tiny #rpi #ro
- [ ] gamedeskpwrmon gamedeskpwrmon.dzhome #home #linux #deb #tiny #rpi #ro
- [ ] mediactrpwrmon mediactrpwrmon.dzhome #home #linux #deb #tiny #rpi #ro