Declarative Configuration
KSail uses declarative YAML configuration files for reproducible cluster setup. This page describes ksail.yaml — the project-level configuration file that defines your cluster’s desired state.
What is ksail.yaml?
Section titled “What is ksail.yaml?”Each KSail project includes a ksail.yaml file describing cluster distribution, networking, components, and workload configuration. Run ksail cluster init to generate it — commit to version control to share with your team.
Environment Variable Expansion
Section titled “Environment Variable Expansion”KSail supports environment variable expansion in all string configuration values using the ${VAR_NAME} syntax for secure credentials, environment-specific paths, and dynamic values.
Syntax
Section titled “Syntax”Basic syntax: ${VARIABLE_NAME} — Reference an environment variable. If not set, expands to an empty string and logs a warning.
Default value syntax: ${VARIABLE_NAME:-default} — Use a default value if the variable is not set. No warning is logged when using defaults.
spec: editor: "${EDITOR:-vim}" cluster: connection: kubeconfig: "${HOME}/.kube/config" context: "${KUBE_CONTEXT:-kind-kind}" distributionConfig: "${CONFIG_DIR:-configs}/kind.yaml" localRegistry: registry: "${REGISTRY:-localhost:5000}" vanilla: mirrorsDir: "${MIRRORS_DIR:-mirrors}" talos: config: "${TALOS_CONFIG_PATH:-~/.talos/config}" provider: hetzner: sshKeyName: "${HCLOUD_SSH_KEY}" workload: sourceDirectory: "${WORKLOAD_DIR:-k8s}" chat: model: "${CHAT_MODEL:-gpt-4o}"Expansion Behavior
Section titled “Expansion Behavior”| Syntax | Variable Set | Variable Not Set |
|---|---|---|
${VAR} | Uses value | Empty string + warning |
${VAR:-default} | Uses value | Uses default (no warning) |
${VAR:-} | Uses value | Empty string (no warning) |
Environment variables are expanded in all string fields of ksail.yaml, distribution configs (kind.yaml, k3d.yaml), and Talos patch files (talos/cluster/, talos/control-planes/, talos/workers/):
# kind.yaml - Environment variables are expanded before parsingkind: ClusterapiVersion: kind.x-k8s.io/v1alpha4containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry.mirrors."${REGISTRY:-localhost:5000}"] endpoint = ["http://${REGISTRY:-localhost:5000}"]# talos/cluster/registry.yaml - Environment variables are expandedmachine: registries: mirrors: docker.io: endpoints: - http://${REGISTRY:-localhost:5000}Example: Credentials
Section titled “Example: Credentials”spec: cluster: localRegistry: registry: "${REGISTRY_USER}:${REGISTRY_PASS}@${REGISTRY_HOST:-ghcr.io}/myorg/myrepo"export REGISTRY_USER="github-user"export REGISTRY_PASS="ghp_secrettoken123"ksail cluster createExample: Multi-Environment Setup
Section titled “Example: Multi-Environment Setup”spec: cluster: connection: context: "${CLUSTER_NAME:-kind-kind}" distributionConfig: "${ENV:-dev}/kind.yaml" workload: sourceDirectory: "${ENV:-dev}/k8s"# Development (using defaults)ksail cluster create
# Production (override with environment variables)export ENV="prod"export CLUSTER_NAME="prod-cluster"ksail cluster createMinimal Example
Section titled “Minimal Example”# yaml-language-server: $schema=https://raw.githubusercontent.com/devantler-tech/ksail/main/schemas/ksail-config.schema.jsonapiVersion: ksail.io/v1alpha1kind: Clusterspec: cluster: distribution: Vanilla distributionConfig: kind.yamlThis minimal configuration creates a Vanilla cluster (implemented with Kind) using defaults for all other settings.
Complete Example
Section titled “Complete Example”# yaml-language-server: $schema=https://raw.githubusercontent.com/devantler-tech/ksail/main/schemas/ksail-config.schema.jsonapiVersion: ksail.io/v1alpha1kind: Clusterspec: editor: code --wait cluster: distribution: Vanilla distributionConfig: kind.yaml connection: kubeconfig: ~/.kube/config context: kind-kind timeout: 5m cni: Cilium csi: Default metricsServer: Enabled certManager: Enabled policyEngine: Kyverno localRegistry: registry: localhost:5050 gitOpsEngine: Flux workload: sourceDirectory: k8s validateOnPush: trueConfiguration Reference
Section titled “Configuration Reference”Top-Level Fields
Section titled “Top-Level Fields”| Field | Type | Required | Description |
|---|---|---|---|
apiVersion | string | Yes | Must be ksail.io/v1alpha1 |
kind | string | Yes | Must be Cluster |
spec | object | Yes | Cluster and workload specification (see below) |
The spec field is a Spec object that defines editor, cluster, and workload configuration.
| Field | Type | Default | Description |
|---|---|---|---|
editor | string | – | Editor command for interactive workflows (e.g. code —wait) |
cluster | ClusterSpec | – | |
provider | ProviderSpec | – | |
workload | WorkloadSpec | – | |
chat | ChatSpec | – |
spec.editor
Section titled “spec.editor”Editor command for interactive workflows (e.g., code --wait, vim). Falls back to SOPS_EDITOR, KUBE_EDITOR, EDITOR, VISUAL, or system defaults.
spec.cluster (ClusterSpec)
Section titled “spec.cluster (ClusterSpec)”| Field | Type | Default | Description |
|---|---|---|---|
distributionConfig | string | – | |
connection | Connection | – | |
distribution | enum | – | |
provider | enum | – | |
cni | enum | – | |
csi | enum | – | |
cdi | enum | – | |
metricsServer | enum | – | |
loadBalancer | enum | – | |
certManager | enum | – | |
policyEngine | enum | – | |
localRegistry | LocalRegistry | – | |
gitOpsEngine | enum | – | |
sops | SOPS | – | |
importImages | string | – | Path to tar archive with container images to import after cluster creation but before component installation |
vanilla | OptionsVanilla | – | |
talos | OptionsTalos | – |
distribution
Section titled “distribution”See Distributions for detailed information.
Vanilla(default) – Standard upstream Kubernetes via KindK3s– Lightweight Kubernetes via K3dTalos– Talos Linux in Docker containers or Hetzner Cloud serversVCluster– Virtual clusters via vCluster
provider
Section titled “provider”See Providers for more details.
Docker(default) – Run nodes as Docker containers (local development)Hetzner– Run nodes on Hetzner Cloud servers (requiresHCLOUD_TOKEN)Omni– Manage Talos cluster nodes through Sidero Omni
distributionConfig
Section titled “distributionConfig”Path to the distribution-specific configuration file or directory. This tells KSail where to find settings like node counts, port mappings, and distribution-specific features.
Default values by distribution:
Vanilla→kind.yamlK3s→k3d.yamlTalos→talos/(directory)
See Distribution Configuration below for details on each format.
connection (Connection)
Section titled “connection (Connection)”| Field | Type | Default | Description |
|---|---|---|---|
kubeconfig | string | ~/.kube/config | Path to kubeconfig file |
context | string | (derived) | Kubeconfig context name |
timeout | duration | – | Timeout for cluster operations |
Context defaults by distribution:
Vanilla→kind-kindK3s→k3d-k3d-defaultTalos(Docker/Hetzner) →admin@talos-defaultTalos(Omni) → the context name generated by Omni (e.g.,devantler-prod)
When using Talos with Omni, Omni generates the context name; set spec.cluster.connection.context to that generated name.
Timeout format: Go duration string (e.g., 30s, 5m, 1h)
See CNI for more details.
Default(default) – Uses the distribution’s built-in CNI (kindnetdfor Vanilla,flannelfor K3s)Cilium– Installs Cilium for advanced networking and observabilityCalico– Installs Calico for network policies
See CSI for more details.
Default(default) – Uses the distribution × provider’s default behavior:- K3s: includes local-path-provisioner
- Vanilla/Talos × Docker: no CSI
- Talos × Hetzner: includes Hetzner CSI driver
Enabled– Explicitly installs CSI driver (local-path-provisioner for local clusters, Hetzner CSI for Talos × Hetzner)Disabled– Disables CSI installation (for K3s, this disables the default local-storage)
metricsServer
Section titled “metricsServer”Whether to install metrics-server for resource metrics.
Default(default) – Uses distribution’s default behavior (K3s includes metrics-server; Vanilla and Talos do not)Enabled– Install metrics-serverDisabled– Skip installation
When metrics-server is enabled on Vanilla or Talos, KSail automatically:
- Configures kubelet certificate rotation (
serverTLSBootstrap: true) - Installs kubelet-csr-approver to approve certificate requests
- Deploys metrics-server with secure TLS communication
certManager
Section titled “certManager”Whether to install cert-manager for TLS certificate management.
Enabled– Install cert-managerDisabled(default) – Skip installation
policyEngine
Section titled “policyEngine”Policy engine to install for enforcing security, compliance, and best practices. See Policy Engines for details.
None(default) – No policy engineKyverno– Install KyvernoGatekeeper– Install OPA Gatekeeper
localRegistry
Section titled “localRegistry”Registry configuration for GitOps workflows. Supports local Docker registries or external registries with authentication.
Format: [user:pass@]host[:port][/path]
Examples:
localhost:5050– Local Docker registryghcr.io/myorg/myrepo– GitHub Container Registry${USER}:${PASS}@ghcr.io:443/myorg– With credentials from environment variables
gitOpsEngine
Section titled “gitOpsEngine”GitOps engine for continuous deployment. See GitOps. When set to Flux or ArgoCD, KSail scaffolds a GitOps CR into your source directory.
None(default) – No GitOps engineFlux– Install Flux CD and scaffold FluxInstance CRArgoCD– Install Argo CD and scaffold Application CR
Distribution and Tool Options
Section titled “Distribution and Tool Options”Advanced configuration options are direct fields under spec.cluster. See Schema Support for the complete structure.
Talos options (spec.cluster.talos):
controlPlanes– Number of control-plane nodes (default:1)workers– Number of worker nodes (default:0)config– Path to talosconfig file (default:~/.talos/config)iso– Cloud provider ISO/image ID for Talos Linux (default:122630for x86; use122629for ARM)
Hetzner options (spec.provider.hetzner):
controlPlaneServerType– Server type for control-plane nodes (default:cx23)workerServerType– Server type for worker nodes (default:cx23)location– Datacenter location:fsn1,nbg1,hel1(default:fsn1)networkName– Private network name (default:<cluster>-network)networkCidr– Network CIDR block (default:10.0.0.0/16)sshKeyName– SSH key name for server access (optional)tokenEnvVar– Environment variable for API token (default:HCLOUD_TOKEN)
Vanilla options (spec.cluster.vanilla):
mirrorsDir– Directory for containerd host mirror configuration
spec.workload (WorkloadSpec)
Section titled “spec.workload (WorkloadSpec)”| Field | Type | Default | Description |
|---|---|---|---|
sourceDirectory | string | k8s | Path to the directory containing Kubernetes manifests. Used as the default path by validate, watch, and push when no explicit path argument is given. |
validateOnPush | boolean | false | Validate manifests against schemas before pushing (validation disabled by default) |
tag | string | dev | OCI artifact tag used for workload push and GitOps reconciliation (Flux OCIRepository and ArgoCD Application). Push priority: CLI oci:// ref > this field > registry-embedded tag > dev. Reconciliation priority: this field > registry-embedded tag > dev |
kustomizationFile | string | – | Path to the kustomization directory relative to sourceDirectory. When set, Flux Sync.Path is configured to this path so Flux uses the specified kustomization as the entry point instead of requiring a root kustomization.yaml. |
spec.chat (ChatSpec)
Section titled “spec.chat (ChatSpec)”| Field | Type | Default | Description |
|---|---|---|---|
model | string | – | Chat model (empty or ‘auto’ for API default) |
reasoningEffort | string | – | Reasoning effort level for chat responses (low, medium, or high) |
Distribution Configuration
Section titled “Distribution Configuration”KSail references distribution-specific configuration files to customize cluster behavior. The path to these files is set via spec.cluster.distributionConfig.
Vanilla (implemented with Kind) Configuration
Section titled “Vanilla (implemented with Kind) Configuration”Default: kind.yaml
See Kind Configuration for the full schema.
Example:
kind: ClusterapiVersion: kind.x-k8s.io/v1alpha4nodes: - role: control-plane extraPortMappings: - containerPort: 30000 hostPort: 30000K3s (implemented with K3d) Configuration
Section titled “K3s (implemented with K3d) Configuration”Default: k3d.yaml
See K3d Configuration for the full schema.
Example:
apiVersion: k3d.io/v1alpha5kind: Simpleservers: 1agents: 2ports: - port: 8080:80 nodeFilters: - loadbalancerTalos Configuration
Section titled “Talos Configuration”Default: talos/ directory
Talos uses a directory structure for Talos machine configuration patches. Place YAML patch files in talos/cluster/ (all nodes), talos/control-planes/, or talos/workers/:
# talos/cluster/kubelet.yaml (applies to all nodes)machine: kubelet: extraArgs: max-pods: "250"See Talos Configuration Reference for patch syntax. Use spec.cluster.talos to configure node counts:
spec: cluster: distribution: Talos distributionConfig: talos talos: controlPlanes: 3 workers: 2Port Mappings (Docker Provider)
Section titled “Port Mappings (Docker Provider)”On macOS, Docker runs in a Linux VM, so MetalLB virtual IPs are not accessible from the host. Use extraPortMappings to expose container ports directly:
spec: cluster: distribution: Talos talos: extraPortMappings: - containerPort: 80 hostPort: 8080 protocol: TCP - containerPort: 443 hostPort: 8443 protocol: TCPAccess services at http://localhost:8080. Ports are exposed on the first control-plane node; in multi-control-plane clusters, extraPortMappings apply only to that node.
Schema Support
Section titled “Schema Support”KSail provides a JSON Schema for IDE validation and autocompletion. Reference it at the top of your ksail.yaml:
# yaml-language-server: $schema=https://raw.githubusercontent.com/devantler-tech/ksail/main/schemas/ksail-config.schema.jsonapiVersion: ksail.io/v1alpha1kind: Clusterspec: # ...IDEs with YAML language support (e.g., VS Code + Red Hat YAML extension) provide field autocompletion, inline docs, validation, and enum suggestions.