Skip to content

Optional Vultr golden image

For the separate Salt Master and LiteLLM dependency image templates, see Vultr infrastructure images.

client/packer/client.pkr.hcl builds a new disposable Ubuntu 24.04 LTS x64 instance using Vultr OS 2284 and vc2-4c-8gb. It never snapshots an enrolled client. Packer 1.16.0 and the official Vultr plugin 2.7.0 are pinned. The region defaults to ams. The builder plan only sizes the build: the snapshot keeps the same 25 GB client disk contract.

The builder installs Salt 3006.27, Tailscale 1.102.4, the pinned Node/uv/Oduflow artifacts, Ubuntu's Docker/containerd packages, and builds Paseo from its pinned commit. A temporary 4 GB swap file supports that build and is removed before snapshot. Building the Paseo monorepo needs several GB of scratch disk and memory; the build tree is deleted after installation, so only the installed release remains in the image. Compiling Paseo on every client instead of reusing this image is supported but slow. The package versions are recorded in /etc/oduflow/image.json; Ubuntu dependency packages still follow the signed Ubuntu repositories, so the resulting snapshot, rather than rebuilding later, is the exact reusable artifact.

Docker and containerd remain masked during the build. Their image-level units require /srv/oduflow/data to be a mount point. No databases, client settings, client data volume, application services or OCI image caches are initialized. The builder size is chosen for compiling Paseo. It is neither a client allocation nor a guarantee that the full production application workload fits on a server of any particular size.

Build

Set ODUFLOW_VULTR_API_KEY in the build process environment. The Packer variable is sensitive and the credential is not sent to shell provisioners or copied into the image. Do not put credentials in command arguments or committed Packer variable files.

mkdir -p packer/output
packer init client/packer/client.pkr.hcl
packer validate client/packer/client.pkr.hcl
packer build -var source_revision=REVIEWED_CLIENT_COMMIT client/packer/client.pkr.hcl

Use an isolated checkout of a reviewed commit for the build. The builder uploads only the repository's salt tree and removes that temporary copy afterward. Final cleanup invokes the existing salt/minion/clean-image.py refusal checks, removes Salt and Tailscale identities, cloud-init instance data, SSH host keys, temporary authorized keys, machine ID and swap; it locks the temporary root password. The plugin requests shutdown through its existing SSH connection, takes the snapshot and removes the temporary instance and Packer SSH-key record. Its shutdown helper does not verify the final provider power state; cold snapshotting is not claimed. The cleaned image must therefore be verified by a fresh clone. The snapshot is retained. Failed builds may need inspection of provider cleanup; never mistake an existing production instance for a disposable builder.

packer/output/manifest.json records the resulting snapshot ID and source revision. Snapshot descriptions begin with oduflow-image-v1 ubuntu24.04 disk25. This is a compatibility marker on the operator's Vultr account, not a cryptographic image attestation.

Select and launch

On an Oduflow plan, select Installation Source → Golden Image, enter the completed Packer snapshot ID and select a server plan with at least 25 GB local boot storage. Preparing a client freezes the snapshot ID, image contract and minimum disk size. Later edits to the plan do not alter prepared clients.

Before requesting paid infrastructure, the control plane verifies that the snapshot exists on the configured account, is complete and has the expected marker. It retains the actual snapshot metadata and credential fingerprint in the encrypted instance bundle. A changed snapshot record is rejected.

Vultr creation sends snapshot_id instead of os_id, with the same fresh cloud-init enrollment, firewall group and optional operator SSH key used for a clean installation. Instance reconciliation requires the exact returned snapshot_id, label, region, plan and firewall. A generic os_id=164 alone is insufficient proof of which image was used. Existing historical snapshot fields remain audit-only unless a newly prepared plan explicitly selects Golden Image.

On first boot, cloud-init creates the unique VPN/minion identity. Salt mounts the newly verified client data volume and writes actual client configuration. Only then does it unmask Docker/containerd and their socket. Application package receipts let the existing installer reuse the already installed versions. Production and LLM keys are supplied separately through encrypted pillar.

Validation and official references

Packer init, formatting, full configuration validation and shell syntax checks pass. Tests cover the small clean builder, service masking, first-boot ordering, snapshot metadata, creation payload and exact-image reconciliation. Runtime snapshot creation and clone/enrollment checks are separate deployment evidence.