The fleet at a glance¶
This page is the place to start if the tools in this guide are new to you. It shows what you are building, which tool does which job, and how a host goes from nothing to running services. Nothing here is a step. Read it once, then follow the running order.
Each tool has a primer in Tools, and each recurring term is in the glossary. The build pages link to both where a tool or a term first appears, so you can read them as you meet them.
What you are building¶
A fleet is a group of virtual machines that are built the same way and managed together. This one runs on a Proxmox host, and every VM in it is a Docker host: a small Linux machine whose job is to run containers.
Each VM has one purpose, and its name says which. The two digits leave room for a second of the same kind.
| Host | Runs | Why the fleet needs it |
|---|---|---|
| km01 | Komodo | Deploys the containers on every host, itself included |
| ci01 | Semaphore, the monitoring stack, notifications, and the mail relay | Starts every build, and stores every host's metrics and logs |
| id01 | Authentik | One sign-in in front of every web interface |
| pk01 | step-ca | The fleet's own certificate authority |
| tf01 | The Traefik hub | One place that knows every published route |
| bh01 | The DMZ edge | The only way in from the internet, through a tunnel it opens outward |
| mx01 | Stalwart | Mailboxes. Optional |
| ap01 | Your own applications | The worked example of adding a host |
The internal network, the Servers VLAN, holds everything that should never face the internet. The DMZ is a second network for the two hosts that do. Each is a VLAN of its own, 7 and 8 in these pages, and your router's firewall decides what may pass between the two.
The fleet builds neither network. You set both up on your own router and switch before the build. See The network and DNS the fleet expects for what they need, and for how the fleet's hostnames resolve.
Background: why one VM for each job
Everything could run on one large VM. The fleet splits it up for three reasons.
A failure stays small. A full disk or a bad upgrade on one VM takes out one service, and the others keep running.
Each VM can be rebuilt on its own. A host is wiped and installed again in one run, and it finds its data on a disk the rebuild leaves alone. See Rebuilding a VM.
The network can tell the hosts apart. A firewall rule can let bh01 reach tf01 and nothing else, which is not possible when both are containers on one machine.
Which tool does which job¶
No single tool builds a host. Each one does the part it is good at and hands over to the next.
| Job | Tool | Its instructions live in |
|---|---|---|
| Create the VM in Proxmox | OpenTofu | The fleet-opentofu repo, and opentofu/prod.tfvars in the private repo |
| Install and configure the operating system | NixOS | The fleet-nixos repo, and nixos/ in the private repo |
| Define the containers | Docker Compose | The fleet-stacks repo |
| Deploy the containers and keep them as defined | Komodo | komodo/ in the private repo |
| Run those three in order, for the hosts you name | Ansible | The fleet-ansible repo, and hosts.yml in the private repo |
| Give the run a permanent home, with its secrets and its history | Semaphore | Semaphore's own database on ci01 |
| Keep secrets in git without exposing them | sops with age | secrets/ in the private repo |
Four of the repos are public and hold no fact about your fleet. Everything that makes the fleet yours, which hosts exist, their addresses, their secrets, is in the private repo. See The private repo.
Once a host is up, a second set of tools serves what runs on it.
| Job | Tool |
|---|---|
| Route a hostname to the right container, with TLS | Traefik |
| Ask for a sign-in before a web interface loads | Authentik |
| Collect metrics and logs, and raise alerts | VictoriaMetrics |
| Issue certificates inside the fleet | step-ca |
| Hold mailboxes | Stalwart |
Two more stacks are defined in fleet-stacks, and no host in this guide runs them: CrowdSec, which bans addresses that behave like attackers, and Technitium, a DNS server. Each has a primer for the day you add it.
How a host is built¶
You describe a host in the private repo: a few lines of inventory saying what it is called and which stacks it runs, and a few lines saying how big its VM is. Then you start one run and name the host. The diagram shows what the run does with that description.
flowchart TD
you[You: describe the host, start the run] --> control[Control node runs site.yml]
control -->|1. create a blank VM| tofu[OpenTofu]
tofu --> proxmox[Proxmox]
proxmox -->|the VM boots the installer ISO| host[The new host]
control -->|2. wait for SSH| host
control -->|3. install NixOS, deploy the configuration| host
control -->|4. sync this host's Stacks| komodo[Komodo Core on km01]
host -->|Periphery dials out| komodo
komodo -->|deploy the Stacks| host
The control node is whatever machine the run starts from: a shell on your own machine for the first two hosts, and Semaphore from then on. It does all the work. The new host is told what to become and never has to be logged in to.
Running the same host again is safe. Each stage looks at what exists and changes only what differs from the description, so a second run of a finished host does nothing. See How a host is built for each stage.
Background: why describe a host instead of setting it up by hand
A host set up by hand is the sum of every command anyone ever ran on it, and nobody has the full list. Building a second one like it, or the same one again after a failure, means remembering.
A described host is built from files. The files are in git, so every change has an author, a date, and a reason, and the host can be built again from them at any time. A change is made in the files and applied by a run, never typed into the host, which is why the pages keep sending you back to the private repo.
This approach goes by the names infrastructure as code and declarative configuration. OpenTofu, NixOS, Compose, and Komodo's Resource Sync each apply it to one layer.
Why the first two hosts are different¶
Komodo deploys every stack and Semaphore starts every run, and each is itself a stack on a host, so neither can build the host it lives on. A shell on your own machine builds km01 and ci01, and then hands over to Semaphore. That stretch of the guide is the foundation. See The problem it solves for the full reason.
The same problem shows up one more time. A finished host expects a sign-in from id01, a telemetry store on ci01, and the hub on tf01, and the first hosts are built before those exist. They start in bootstrap mode, which leaves those three out, and the whole fleet leaves the mode together in one procedure.
What to read next¶
| To | Read |
|---|---|
| Start building | The running order |
| Prepare your router and your DNS | The network and DNS the fleet expects |
| Understand the run before starting it | How a host is built |
| Learn a tool before you meet it | Tools |
| Look up a term | Glossary |