Infrastructure as code (IaC) configuration for my homelab setup.
Currently hosted on a Dell XPS 9370 with a SONOFF Zigbee Dongle-P adapter. Mostly managed with Pulumi, via the Kubernetes provider.
Automatically deployed via GitHub CI.
Add a block to appDefinitions.ts
.
- Install Node.js
- Install Pulumi CLI
- Get access keys to domdomegg AWS account
- Create
~/.aws/config
with the contents:[default] region = eu-west-1
- Create
~/.aws/credentials
file with the contents:[default] aws_access_key_id = <ACCESS_KEY_ID_FOR_DOMDOMEGG_ACCOUNT> aws_secret_access_key = <ACCESS_KEY_ID_FOR_DOMDOMEGG_ACCOUNT>
- Run
pulumi login s3://domdomegg-pulumi-backend/homelab
- See step in manual setup notes below to get kubeconfig
- Deploy with
npm run deploy:prod
To get a kubernetes cluster that you can run this all on, we install Ubuntu server + k3s. Full instructions:
- Download the Ubuntu Server
.iso
- Install Ventoy onto a USB stick, and copy over Ubuntu Server
- Run the Ubuntu Server installer via Ventoy, and during installation choose:
- Connect to internet
- Enable OpenSSH server
- Only allow connecting via SSH keys
- Can use the GitHub keys temporarily, we'll replace them in a second
- (recommended) SSH in to the machine remotely - generally easier to copy and paste the next bits from a machine with easy access to these instructions. The following instructions assume you've created an SSH config entry called
xps
to connect, i.e. you can dossh xps
. - Replace SSH keys with the key you want to use. Adam: for
id_ed25519_xps
:echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC6fJP2IaW0o1y3xT2SwwNjT8zC3V4CpNCGYYVEY3eVv" > ~/.ssh/authorized_keys
- Enable sudo without password
In the file, change the %sudo line to:
sudo visudo
(Why: Avoids needing to manage a separate sudo password. Also see this security discussion)%sudo ALL=(ALL:ALL) NOPASSWD: ALL
- Harden security by setting password to random value, and then locking it to disable its use, then disabling getty.
NB: this will make the device only accessible via SSH
echo $USER:$(openssl rand -base64 24) | chpasswd sudo passwd -l $USER sudo systemctl mask getty@.service
- Expand the storage space to the whole disk (by default only 100GB is used)
sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
- Set the display to blank after 30s of inactivity, by editing
/etc/default/grub
to set:then apply the changes to the configuration file with:GRUB_CMDLINE_LINUX_DEFAULT="consoleblank=30"
sudo update-grub
- (for laptops) Make closing the lid not put it to sleep, by editing
/etc/systemd/logind.conf
to add:
HandleLidSwitch=ignore
LidSwitchIgnoreInhibited=no
Then restart systemd with:
sudo service systemd-logind restart
-
Install k3s Create /etc/systemd/system/shutdown-k3s.service:
# From https://github.com/k3s-io/k3s/issues/2400#issuecomment-1312621468 [Unit] Description=Kill containerd-shims on shutdown DefaultDependencies=false Before=shutdown.target umount.target [Service] ExecStart=/usr/local/bin/k3s-killall.sh Type=oneshot [Install] WantedBy=shutdown.target
Run:
curl -sfL https://get.k3s.io | sh -s - --disable=traefik --cluster-cidr=fd7d:4ce0:5b35:1::/64,10.42.0.0/16 --service-cidr=fd7d:4ce0:5b35:2::/112,10.43.0.0/16 --flannel-ipv6-masq sudo systemctl enable shutdown-k3s.service
Cluster CIDR range can be generated with https://unique-local-ipv6.com/ (replace
fd7d:4ce0:5b35
with the part you've generated here). We disable traefik because we use ingress-nginx instead. -
Set up Bluetooth for Home Assistant (see official docs). In short on my device it was:
sudo apt install -y bluez # nb: may not be necessary after Ubuntu 23.10 # https://www.phoronix.com/news/Ubuntu-23.10-Dbus-Broker-Plan sudo apt install dbus-broker -y sudo systemctl stop dbus sudo systemctl disable dbus sudo systemctl start dbus-broker sudo systemctl enable dbus-broker
-
Get the kubeconfig.
On the external system you want to get the config, run:
# NB: this will overwrite ~/.kube/config mkdir -p ~/.kube && ssh -t xps 'sudo cat /etc/rancher/k3s/k3s.yaml | sed "s/\[::1]/\[$(ip route get 2606:4700:4700::1111 | awk '\''{print $11}'\'')]/g"' > ~/.kube/config
This will substitute in the IP the system uses to reach the internet as the address to connect with kubectl. Adjust if necessary.
These commands will work provided you've followed the steps above to set up the server.
- SSH into the server:
ssh xps
- Run an ad-hoc shell inside the k8s cluster (so you can ping or wget cluster ips etc.):
kubectl run -i --tty --rm --restart=Never debug-shell --image=busybox -- /bin/sh