Configuration
klimax reads a single YAML file. Defaults are sensible enough that most people never touch it — but every knob, from VM size to the bridge CIDR to registry mirrors, lives here.
The config file
The default path is ~/.klimax/config.yaml. Open it in your
$EDITOR with:
$ klimax config edit
Or point any command at a specific file:
$ klimax up -c config.yaml
The quickest way to start is from the shipped
config.example.yaml — it documents every field inline.
Full reference
The full annotated example, with every field and its default:
# ── VM ──
vm:
name: "klimax" # Lima instance name; Docker socket at ~/.<name>.docker.sock
cpus: 4 # default: 4
memory: "10GiB" # default
disk: "40GiB" # default
# rosetta: false # transparent amd64 containers (Apple Silicon); needs softwareupdate --install-rosetta
# ── Networking ──
network:
kindBridgeCIDR: "172.30.0.0/16" # routed macOS → VM lima0, no SNAT (default)
# disablePortMirroring: true # default true → kubeconfigs use the lima0 IP; set false to force 127.0.0.1; VM-level (needs destroy && up)
# ── Kind (applied to every cluster create) ──
kind:
nodeVersion: "v1.35.0" # kindest/node tag — matched to the bundled kind CLI; overriding warns
metalLBVersion: "v0.16.1" # MetalLB version (default)
customDnsResolvers: # CoreDNS forwarding rules
- domain: "runlocal.dev"
# resolvers: ["8.8.8.8", "8.8.4.4"] # default when omitted
# - domain: "corp.internal"
# resolvers: ["10.0.0.53"]
# autoMergeKubeconfig: true # merge new context into ~/.kube/config (default: true)
# autoRemoveKubeconfig: true # remove context on deletion (default: true)
# ── Registries ──
registries:
# cacheStorage: "host" # "host" (default) survives klimax destroy; "guest" wiped on destroy
mirrors: # name must NOT be a hostname (no '.' or ':') — it would shadow the upstream
- name: "registry-dockerio"
port: 5030
remoteURL: "https://registry-1.docker.io"
# username / password # optional, to avoid Docker Hub rate limits
- name: "registry-quayio"
port: 5010
remoteURL: "https://quay.io"
- name: "registry-gcrio"
port: 5020
remoteURL: "https://gcr.io"
- name: "registry-us-docker-pkgdev"
port: 5040
remoteURL: "https://us-docker.pkg.dev"
- name: "registry-us-central1-docker-pkgdev"
port: 5050
remoteURL: "https://us-central1-docker.pkg.dev"
Defaults
| Field | Default |
|---|---|
vm.name | "klimax" |
vm.cpus | 4 |
vm.memory | "10GiB" |
vm.disk | "40GiB" |
network.kindBridgeCIDR | "172.30.0.0/16" |
network.disablePortMirroring | true |
kind.nodeVersion | "v1.35.0" |
kind.metalLBVersion | "v0.16.1" |
kind.autoMergeKubeconfig | true |
kind.autoRemoveKubeconfig | true |
registries.cacheStorage | "host" |
| DNS resolvers (when omitted) | ["8.8.8.8", "8.8.4.4"] |
Cluster lifecycle is managed only through klimax cluster
subcommands — there is no list of clusters in the config file.
Per-cluster subnets, ports and MetalLB pools are derived automatically
from each cluster's slot number.
Several settings above (vm.*, the bridge CIDR,
network.disablePortMirroring) are VM-level —
they only take effect on a fresh VM. Apply a change by re-creating it:
klimax destroy && klimax up. The same is true after a
klimax upgrade: destroy and re-create the VM so the new
binary re-provisions it.
See also
- Networking & L3 routing — how the bridge CIDR becomes routable.
- Registry mirrors — the pull-through caches and how to add your own.
- CLI reference — every command and flag.