Documentation menu

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

FieldDefault
vm.name"klimax"
vm.cpus4
vm.memory"10GiB"
vm.disk"40GiB"
network.kindBridgeCIDR"172.30.0.0/16"
network.disablePortMirroringtrue
kind.nodeVersion"v1.35.0"
kind.metalLBVersion"v0.16.1"
kind.autoMergeKubeconfigtrue
kind.autoRemoveKubeconfigtrue
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