The dev profile runs a complete Zomg deployment inside a local KVM VM. It is the fastest way to prove the full deploy path without touching GCP: a Linux host provisions a VM at 192.168.86.2, installs k3s, deploys Zomg, builds the bases required by the dev profile, and runs the same verification suite used for development.

Requirements

  • A Linux host/container with readable and writable /dev/kvm.
  • An x86_64 Linux host. This local VM flow downloads the Ubuntu amd64 cloud image and starts it with qemu-system-x86_64; arm64/aarch64 hosts are not supported by the KVM dev path yet.
  • Either a privileged root container, or a user with /dev/kvm access and passwordless sudo. The setup uses sudo only for package install, /usr/local/bin, TAP/bridge networking, and iptables.
  • At least 40 GB RAM for comfortable first-run verification. The inner VM defaults to 12 GB via ZOMG_KVM_RAM.
  • SSH access to clone this repository.
  • git, openssh-client, ca-certificates, just, and a shell. The setup target installs the remaining dev dependencies when they are missing.

Fresh install

Clone the repository and run the maintained entrypoint:
sudo apt-get update
sudo apt-get install -y ca-certificates git just openssh-client
git clone git@github.com:loopwork/forkr.git
cd zomg
just from-scratch --profile dev
just from-scratch --profile dev performs the full local workflow:
  1. Installs KVM/dev dependencies when needed.
  2. Provisions the VM with TAP, bridge, and NAT networking.
  3. Runs Ansible against the VM.
  4. Builds or imports the bases required by the dev profile.
  5. Runs scripts/verify.py against the dev target.
Use --skip-verify only when you want to stop after deployment:
just from-scratch --profile dev --skip-verify
ZOMG_PROFILE=dev just verify
Use --skip-web when a fresh core control-plane deployment is enough for the change you are proving. It skips the dashboard and apex site image builds while still provisioning k3s, TLS, API, agentd, SSH gateway, observability, required bases, and verification:
just from-scratch --profile dev --skip-web
The default just from-scratch --profile dev remains the full local setup and deploys https://dash.192.168.86.2.sslip.io/. The dev profile requires box-base for the normal verification suite. Heavier derived bases such as dev-base and gha-runner-base are built by the workflows that need them, such as GitHub runner deployment, instead of every local dev bootstrap. Base builds are reused automatically across local dev runs. The cache is keyed by the required base chain and base build inputs under ${ZOMG_CACHE_DIR:-$HOME/.cache/zomg}/dev-bases/; a fresh VM restores a matching tarball before base-build.sh verifies the target-side helper binaries. When the bases are already present but the helper binaries are missing, the script installs only the CLI/helper archive and skips base-context packaging. Set ZOMG_DEV_BASE_CACHE=0 when you intentionally need to avoid the automatic cache. just from-scratch --profile dev also accepts these cache controls:
FlagEffect
--bases <list>Override the profile’s required bases for this run. Use comma-separated names, for example --bases box-base,dev-base.
--force-base-buildRebuild bases instead of seeding from an available cache, then refresh the cache.
--seed-base-cacheImport bases from the configured cache tarball before build/deploy.
--save-base-cacheSave the built bases to the configured cache tarball.
--require-base-cacheRequire the cache tarball and fail instead of building missing bases.
Override the exact cache tarball path with ZOMG_DEV_BASE_CACHE_TAR. For the dev profile, the Mintlify docs export used by the apex site is cached automatically by content hash under ${ZOMG_CACHE_DIR:-$HOME/.cache/zomg}/docs-export. Set ZOMG_DOCS_EXPORT_CACHE=0 when you intentionally need to force a fresh Mintlify export without changing docs inputs. The dev deploy also caches locally built control-plane and web image archives by deploy hash under ${ZOMG_CACHE_DIR:-$HOME/.cache/zomg}/dev-images. Fresh VMs load a matching archive instead of rebuilding the same image. BuildKit is installed in the dev VM only when an image cache miss needs a rebuild. Set ZOMG_DEV_IMAGE_CACHE=0 to force image rebuilds, or ZOMG_DEV_IMAGE_CACHE_DIR to put the archives somewhere else.

Inspect the VM

The VM uses a generated SSH key under kvm/boxes-kvm/:
ssh -i kvm/boxes-kvm/id_ed25519 ubuntu@192.168.86.2
Always pass the dev kubeconfig explicitly:
KUBECONFIG=~/.kube/boxes-dev kubectl get nodes
KUBECONFIG=~/.kube/boxes-dev kubectl get pods -A
Core URLs use sslip.io:
curl -k -H 'Authorization: Bearer test' https://api.192.168.86.2.sslip.io/healthz
curl -k -H 'Authorization: Bearer test' https://dash.192.168.86.2.sslip.io/

Reuse during development

For normal iteration after a successful first run, use targeted deploys and the CI-prep target:
ZOMG_PROFILE=dev just deploy-api
ZOMG_PROFILE=dev just deploy-web
ZOMG_PROFILE=dev just deploy-observability
ZOMG_PROFILE=dev just dev-ci-prepare
ZOMG_PROFILE=dev just verify
just dev-ci-prepare --profile dev reuses an existing dev VM when it is running and reachable. Use --full-bootstrap to force a fresh VM path, and --rebuild-bases when base-related changes need a new cache. Targeted app deploys do not reconcile k3s-managed platform services or TLS secrets. Use the narrow deploy that matches the boundary you are changing:
TargetReconciles
just deploy-k3sTraefik, CoreDNS, cert-manager, and other k3s-managed platform tasks.
just deploy-tlsTLS secrets for the selected profile.
just deployFull reconciliation: CLI install, k3s/TLS, API, agentd, SSH gateway, observability, dashboard, and docs.
Run the local quality gate before sending changes:
just check

Prove first-run behavior in a disposable box

Use a fresh disposable Linux box when you need to verify the repository works from a clean environment. Create the outer box with at least 40 GB RAM, inject Git credentials, then run:
cd /work
git clone git@github.com:loopwork/forkr.git
cd zomg
git switch <branch>
sudo apt-get update
sudo apt-get install -y ca-certificates git just openssh-client
just from-scratch --profile dev
If the first run fails, fix the maintained just target or the scripts it calls. Do not bypass the flow with ad hoc script execution; the goal is a clone that can run the documented command end to end.