Home Lab from First Principle
I find the first principles in math quite fascinating… its the answer to the most important question, “chicken or the egg”??
So I find myself with a bare, but typical ‘home network’, an ISP router and some personal devices on the network. Then I added a pihole for DHCP and DNS. I needed some compute and was inspired by TiniMiniMicro (its about the price of raspberry pies, at the scalping prices, which noone should pay..)
So.. how does one bootstrap a cluster? I have not decided (or rather, ‘learnt’) how to properly arrange my homelab, would like to go back and adjust early decisions as I learn how wrong I am today. Or when add more ‘things’ to the lab.. What is the ‘first principle’ for my cluster, how can I bootstrap a computer without any other computer?
MAAS sounds ideal… but.. its certainly not ‘small’. I need to bootstrap my lab, and MAAS wants postgress, user management.. way too much for home use.
Then I stumbled on How to configure a Raspberry Pi as a PXE boot server That is much closer to what I need! pihole already has installed dnsmasq, so its even ‘less work’! (as-if 😂)
So after some tinkering, yes, I can remote-boot a machine (what a backdoor… lets ignore that… need to get pfsense probably). YES!! Still. Problem. ubuntu install is not completely ‘headless’. This is however an old problem. The solution.. keeps changing. Here is the best post I found on the subject.
Now I have all the pieces, how to glue that all together. Just need
- a
pxelinux.cfg
anduser-data
per machine - some static content (ubuntu iso,
vmlinuz
,initrd
,system.efi
…) - tftp and http fileserver to serve the above content
- dnsmasq to direct boot sequence to above http/tftp server dnsmasq has a tftp server, http fileserver is a python one-liner, but.. copy-paste duplication of files is ‘blasphemy’!!
‘Luckily’, I spent several years working with go text/template
(i.e. {{.Varname}}
syntax, it shows in a lot of tools). Go also has a file server.. and.. yes, there is an implementation of tftp! https://github.com/pin/tftp. So.. we can implement a bootstrap server in go!!!
Few hours later:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
serve:
host: <raspberry pihole hostname>
http: 8080
tftp: 69
datadir: /static
inventory:
12:34:56:78:9A:B3: firefly1
12:34:56:78:9A:BB: firefly2
12:34:56:78:9A:BE: firefly3
12:34:56:78:9A:B5: firefly4
12:34:56:78:9A:B7: firefly5
passwordhash: # `apt-get install whois && mkpasswd <password>`
bootmenu: |
DEFAULT install
LABEL install
KERNEL http://{{.Server}}:{{.HttpPort}}/static/efi64/vmlinuz
INITRD http://{{.Server}}:{{.HttpPort}}/static/efi64/initrd
APPEND root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://{{.Server}}:{{.HttpPort}}/static/ubuntu-22.04.1-live-server-amd64.iso autoinstall ds=nocloud-net;s=http://{{.Server}}:{{.HttpPort}}/autoinstall/{{.Hostname}}/ cloud-config-url=/dev/null
cloudinit: |
#cloud-config
autoinstall:
updates: security
version: 1
reporting:
hook:
type: webhook
endpoint: http://{{.Server}}:{{.HttpPort}}/cloudlog/{{.Hostname}}
apt:
disable_components: []
geoip: true
preserve_sources_list: false
primary:
- arches:
- amd64
- i386
uri: http://{{.Server}}:3142/ubuntu
- arches:
- default
uri: http://{{.Server}}:3142/ubuntu
drivers:
install: false
identity:
hostname: {{.Hostname}}
password: {{.PasswordHash}}
realname: vpaprots
username: vpaprots
kernel:
package: linux-generic
...
Added an apt-cacher-ng
on the pi (probably not a good solution long-term..) and call-home log reporting to the golang server. Then realized that I need to send WakeOnLine packets, added that too.. Since have a webserver, hooked WOL up to a GET request.. And for good measure, I thought it might be nice to see what part of the install we are on, which can be gleaned from what files have been requested so far! (First time using websockets.. and accidentally stumbled on bootstrap.js
.. so many pieces!!)
And.. voila.. (and I need to find how to make better gifs 😅)
Full code at @vpaprots/pxeserver.