b23ef64ee1
Generate a fresh ed25519 key pair at rebuild time, inject the public key into the Proxmox answer file, use the private key for cluster join over SSH, then remove the key from both the remote host and the database. This eliminates the need to manage static SSH keys in config/secrets. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
120 lines
3.7 KiB
Markdown
120 lines
3.7 KiB
Markdown
# Provisioning
|
|
|
|
Central control plane for a Proxmox homelab cluster. Handles PXE booting bare metal, unattended Proxmox installation, cluster join, and host lifecycle management.
|
|
|
|
## What it does
|
|
|
|
1. Operator registers a host (MAC address + server type)
|
|
2. Operator triggers "rebuild with Proxmox"
|
|
3. Host PXE boots → dnsmasq responds → iPXE chain-loads the Proxmox installer
|
|
4. Installer fetches a per-host answer file (TOML) from Provisioning
|
|
5. Proxmox installs unattended → post-install webhook fires
|
|
6. Host reboots → first-boot script phones home with IP + hardware ID
|
|
7. Provisioning SSHes into the new host → `pvecm add` joins the cluster
|
|
8. Host registered in Infrastructure → marked ready
|
|
|
|
Admin dashboard shows real-time progress via SSE.
|
|
|
|
## Deploy
|
|
|
|
### Prerequisites
|
|
|
|
- Docker + Docker Compose on the target host
|
|
- Host must be on the same network as the bare-metal nodes (for PXE/DHCP)
|
|
- SSH key pair for root access to new Proxmox nodes
|
|
- Registry access to `gitea.thewrightserver.net`
|
|
|
|
### Setup
|
|
|
|
```bash
|
|
mkdir -p /opt/provisioning/keys
|
|
cd /opt/provisioning
|
|
|
|
# Log in to the container registry
|
|
docker login gitea.thewrightserver.net
|
|
|
|
# Pull the compose file
|
|
curl -sO https://gitea.thewrightserver.net/josh/Provisioning/raw/branch/main/docker-compose.yml
|
|
|
|
# Pull example configs
|
|
curl -s https://gitea.thewrightserver.net/josh/Provisioning/raw/branch/main/deploy/provisioning.example.yaml -o provisioning.yaml
|
|
curl -s https://gitea.thewrightserver.net/josh/Provisioning/raw/branch/main/deploy/server-types.example.yaml -o server-types.yaml
|
|
|
|
# Copy your SSH key pair
|
|
cp /path/to/id_ed25519 ./keys/
|
|
```
|
|
|
|
### Configure
|
|
|
|
Edit `provisioning.yaml`:
|
|
|
|
- `server.public_url` — LAN-reachable URL (e.g. `http://192.168.1.100:8080`)
|
|
- `pxe.interface` — NIC name on the host (e.g. `eth0`, `enp2s0`)
|
|
- `pxe.subnet` — LAN CIDR for proxy-DHCP
|
|
- `proxmox.existing_node` — IP of any current cluster member
|
|
- `proxmox.join_fingerprint` — from `pvecm status` on an existing node
|
|
- `credentials.root_password_hash` — `mkpasswd -m sha-512`
|
|
- `infrastructure.base_url` — URL of the Infrastructure service
|
|
- `infrastructure.server_type_map` — maps local type keys to Infrastructure IDs
|
|
|
|
Edit `server-types.yaml` with your actual hardware types.
|
|
|
|
### Run
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
Dashboard at `http://<host>:8080`.
|
|
|
|
### Update
|
|
|
|
```bash
|
|
docker compose pull
|
|
docker compose up -d
|
|
```
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# Run tests
|
|
go test ./...
|
|
|
|
# Run locally (PXE disabled)
|
|
cp deploy/provisioning.example.yaml provisioning.yaml
|
|
cp deploy/server-types.example.yaml server-types.yaml
|
|
# Edit provisioning.yaml: set pxe.enabled=false, infrastructure.base_url=""
|
|
go run ./cmd/provisioning -config provisioning.yaml
|
|
|
|
# Build binary
|
|
make build
|
|
|
|
# Build Docker image locally
|
|
make docker
|
|
```
|
|
|
|
## Architecture
|
|
|
|
```
|
|
cmd/provisioning/ Entry point, wiring, shutdown
|
|
internal/
|
|
config/ YAML config + hot-reloaded server types
|
|
db/ SQLite (WAL, embedded migrations)
|
|
model/ Domain types
|
|
store/ Hand-written SQL (hosts, operations, locks, images)
|
|
statemachine/ Table-driven host state machine
|
|
events/ SSE fan-out hub
|
|
pxe/ dnsmasq supervisor, iPXE scripts, answer files
|
|
orchestrator/ Lifecycle driver (state transitions, cluster join)
|
|
infra/ Infrastructure API client
|
|
api/ HTTP handlers (JSON API + dashboard)
|
|
httpserver/ chi router assembly
|
|
web/ Embedded static assets (CSS, JS)
|
|
```
|
|
|
|
## CI/CD
|
|
|
|
Gitea Actions workflow (`.gitea/workflows/build.yml`):
|
|
- Runs `go test` and `go vet` on every push to main
|
|
- Builds Docker image and pushes to `gitea.thewrightserver.net/josh/provisioning:latest`
|