Automated My Homelab with the Bat Stack (Bootc, Ansible, Terraform/OpenTofu)

Klohier1 pts0 comments

I've Automated My Homelab with the BAT Stack (Bootc, Ansible, Terraform/OpenTofu) After playing around with my homelab creating services and self hosting anything I can think of, I came to the realization that manually managing these services was taking a lot of time.<br>Services only got updated whenever they notified me and I got to it. While my documentation stayed up to date as I made major changes, I found myself forgetting to note down any ad hoc change I made to the system. This led to a drift between my documentation and the actual state of my servers. I had no trust that I would be able to rebuild my homelab if I had to. The BAT stack is a combination of Bootc, Ansible and Terraform/OpenTofu. This stack allows me to manage my homelab entirely with infrastructure as code tools, making it easier to maintain, scale, automate, and recover.

What is BootC?

Bootc helps you to make containerized operating system images the same way you would make a container image with Docker or Podman. Instead of having to maintain different systems with different configurations, I can maintain one base image that all my systems are based on.

FROM quay.io/fedora/fedora-bootc:44<br>RUN dnf install -y dnf5-plugins && \<br>dnf config-manager addrepo --from-repofile=https://pkgs.tailscale.com/stable/fedora/tailscale.repo && \<br>dnf install -y \<br>bash-completion \<br>chrony \<br>cloud-init \<br>firewalld \<br>git \<br>jq \<br>qemu-guest-agent \<br>tailscale \<br>vim \<br>vim-enhanced \<br>yq && \<br>dnf clean all<br># CIS hardening<br>RUN dnf install -y openscap-scanner scap-security-guide && \<br>oscap xccdf eval --remediate \<br>--profile xccdf_org.ssgproject.content_profile_standard \<br>/usr/share/xml/scap/ssg/content/ssg-fedora-ds.xml ; \<br>dnf remove -y openscap-scanner scap-security-guide && \<br>dnf clean all<br># Crypto policy<br>RUN update-crypto-policies --set DEFAULT<br># SELinux kernel args<br>RUN mkdir -p /usr/lib/bootc/kargs.d<br>COPY kargs.d/01-selinux.toml /usr/lib/bootc/kargs.d/01-selinux.toml<br># SELinux lockdown service<br>COPY selinux/selinux-lockdown.service /usr/lib/systemd/system/selinux-lockdown.service<br># Enable services<br>RUN systemctl enable \<br>chronyd.service \<br>firewalld.service \<br>qemu-guest-agent.service \<br>selinux-lockdown.service \<br>tailscaled.service

RUN bootc container lint

In my homelab, this made maintaining the system easier as there was now only one source of truth that every system in my lab was running. I learned about hardening systems using openscap and SELinux then incorporated that into the base image so that all my systems were hardened by default. The base image also includes qemu-guest-agent and cloud-init so that I can manage the systems through proxmox. The very last service I added was tailscale so that I could connect to my homelab remotely. The benefit with bootc is that when I make an update to the container file and push it to the registry, all my VMs are able to update to the new image with built in rollback support if needed. Bootc gives me the same image based operating system but does not configure the applications running on top of it. This is where Ansible comes in.

What is Ansible?

Ansible helps you configure your servers using code. In my setup I have playbooks that configure the entire server stack by setting up caddy and using dynamic inventories with proxmox. This allows all my playbooks to be updated with what's currently running on the server. When I set up a new VM and run the playbook, caddy automatically creates a domain name so that I don't have to use the IP address directly. Incorporated with Ansible Automation Platform I am able to have the playbooks on a schedule, have credentials stored securely in one central location, and be injected into the playbooks when needed.

Ansible Automation Platform dashboard showing the playbooks I have setup

I fell down the rabbit hole of Ansible and found that I could use it as well to setup the entire network for my homelab. Using my ubiquiti unifi controller, I was able to use Ansible to configure my VLANs and firewall rules to segment my homelab, iot devices, and guest devices from each other. This was huge as it allowed me to have my network configuration version controlled. The beauty of Ansible are the collections that are available to make it easy to integrate with other systems. Once I had a repeatable operating system and a way to configure it, I needed a way to provision the VMs. This is where Terraform/OpenTofu comes in.

What is Terraform/OpenTofu?

Terraform/OpenTofu helps you create and manage your infrastructure using code. I chose OpenTofu in my lab as it is a community driven fork of Terraform and is open source. It maintains compatibility with Terraform modules and providers. For proxmox, I used the bpg provider because it was being actively maintained and recently updated.

To avoid duplicating configuration, I created a reusable VM module. Each virtual machine only specifies the values that differ, such as its name, CPU, memory, disk size, and IP address, while the module handles...

bootc ansible homelab selinux service terraform

Related Articles