Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

🛸 Fleet-Control: Homelab Infrastructure

This repository is the central nervous system for my homelab and laptop provisioning. It manages the lifecycle of Proxmox VMs through a "Define once, Deploy anywhere" workflow.


📂 Repository Architecture

.
├── terraform/                
│   ├── brownfunk/            # Hardware definition for the main cluster
│   │   ├── main.tf
│   │   └── variables.tf
│   ├── myNewNode/            # Sandbox/Secondary node definitions
│   └── [Go to Terraform Docs](./terraform/README.md)
│
├── ansible/                  
│   ├── inventory/            # Host definitions
│   │   ├── brownfunk.ini     # Generated by TF (Main fleet)
│   │   └── myNewNode.ini     # Generated by TF (Experimental nodes)
│   ├── collections/          # Local Ansible modules (Git ignored)
│   ├── tasks/                # Reusable logic (Docker, LUKS, etc.)
│   └── [Go to Ansible Docs](./ansible/README.md)
│
├── terraform.tfvars          # Global Secrets & API Keys (Git ignored)
└── .gitignore                # Protects state, inventory, and secreto

🐳 Docker stacks live in fleet-compose

Terraform creates the VMs, Ansible prepares them, and the docker compose stacks come from a separate repo: lbesnard/fleet-compose (machines/<project>-<vm_type>/docker-compose, secrets encrypted with its own vault key).

VM (terraform = ansible host = stack name) what runs there
brownfunk-nas / beefunk-nas samba, rsync-server, scrutiny (next to the disks)
brownfunk-media / beefunk-media traefik, pihole, wireguard, the arr stack, nextcloud... everything else; also the Tailscale subnet router
jellyfin (LXC) Jellyfin; traefik on the media VM routes to it (traefik/dynamic_tls.yml)

How it fits together (setup_homelabs.yml):

  1. NAS play: tasks/storage_setup.yml unlocks/mounts the passthrough disks at /media/<name>, tasks/nfs_server_nas.yml exports the folders of storage_map[project_dir], then fleet-compose is synced and docker compose up runs.
  2. Media play: tasks/nfs_client_media.yml mounts every storage_map key at /mnt/nfs/<key>, pihole's local DNS (05-lan.conf) is generated, fleet-compose is synced and compose is started.
  3. Sync (tasks/fleet_compose_sync.yml): the VM clones fleet-compose and runs its install.sh --machine <project>-<type>, which decrypts the secrets and fetches vendored repos. The fleet-compose vault password is stored encrypted in this repo (vars/vault.yml: fleet_compose_vault_pass) and written to ~/.config/fleet-compose/vault-pass on the VM; nothing to export:
ansible-playbook -i inventories/beefunk.ini setup_homelabs.yml --ask-vault-pass

(Fleet-Control's own vault, vars/vault.yml and vars/paths.yml, has a different password from fleet-compose's.)

There is no -net VM: pihole, traefik, wireguard and the Tailscale subnet router all run on the media VM. The traefik routes to the Jellyfin LXC and to the NAS (scrutiny) are tracked in fleet-compose/machines/<project>-media/docker-compose/traefik/dynamic_tls.yml, not generated.

Where the storage config lives (Ansible vault)

  • vars/vault.yml -> disk_configs.<project>.<by-id path>: name, parent_path (/media), fstype, optional luks_password. Nested per project because two docks can report the same /dev/disk/by-id string. Every passthrough disk in terraform/<project>/variables.tf must have an entry; the sanity play checks it before doing anything. A disk may be partitioned or LUKS/ext4/xfs on the whole disk, both are detected.
  • vars/paths.yml -> storage_map.<project>.<key>: folders on the NAS that are exported over NFS and mounted on the media VM at /mnt/nfs/<key>. The *_PATH variables of the fleet-compose <project>-media/.env are /mnt/nfs/<key>/...; those of <project>-nas/.env are the real /media/<disk>/... paths. When you add a folder to a compose file, add its key here.

🔁 Changing an IP address

IPs are hard-coded in several places (terraform vm_fleet/lxc_fleet, the generated inventory, docs, and in fleet-compose: .env, pihole 02-custom.conf, traefik/dynamic_tls.yml, prometheus/alloy targets...). One script finds and changes them in both repos:

scripts/change-ip.sh --list                          # every IP found, with counts and files
scripts/change-ip.sh 192.168.1.202 192.168.1.50      # dry run: shows each changed line
scripts/change-ip.sh 192.168.1.202 192.168.1.50 --apply

It works for any address (VM/LXC, Tailscale, gateway, subnet), matches whole addresses only, skips the legacy single-host stacks unless --legacy, edits the plaintext secrets and re-encrypts them (./fleet encrypt), and never commits. After --apply: terraform apply for a VM/LXC address, then review/commit/push both repos. The fleet-compose checkout is ../fleet-compose (or --compose DIR / $FLEET_COMPOSE_DIR).


🚀 Quick Start

1. Provision Hardware

Navigate to the specific node folder in Terraform. Applying this will trigger the provider to build the VM and use the .tftpl to write the .ini file into the Ansible inventory folder.

cd terraform/brownfunk
terraform init
terraform apply

2. Prepare Ansible Environment

Ensure the local collections are installed into the project (required once, or whenever requirements.yml changes).

cd ../../ansible
ansible-galaxy collection install -r requirements.yml -p ./collections

3. Run Configuration

Execute the playbook against the specific inventory generated in step 1.

ansible-playbook -i inventory/brownfunk.ini setup_homelabs.yml --ask-vault-pass # or --vault-password-file ansible/.vault_pass

🛠️ Management Commands

Proxmox (Terraform)

Command Result
terraform plan Check what hardware changes are pending
terraform refresh Sync local state with actual Proxmox status
terraform apply -compact-warnings Clean output during VM creation

Configuration (Ansible)

Command Result
ansible-inventory -i inventory/brownfunk.ini --list Debug the generated host groups
ansible-playbook ... --limit "brownfunk-nas*" Only run tasks on the NAS node

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages