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 the cluster and workload configuration. Run ksail cluster init to generate this file, which can be committed to version control and shared with your team.
The configuration file uses the ksail.io/v1alpha1 API version and follows the Cluster kind schema. It defines:
- Cluster settings: distribution, networking, components
- Connection details: kubeconfig path, context, timeouts
- Workload configuration: manifest directory, validation preferences
- Editor preferences: for interactive workflows
Environment Variable Expansion
Section titled “Environment Variable Expansion”KSail supports environment variable expansion in all string configuration values using the ${VAR_NAME} syntax. This enables:
- Secure credential management: Keep sensitive values out of version control
- Environment-specific configuration: Use different values per environment (dev/staging/prod)
- Dynamic path resolution: Reference user-specific or system-specific paths
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}" 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:
- ksail.yaml — All supported string fields (see below)
- Distribution configs —
kind.yaml,k3d.yamlfile contents - Talos patches — All YAML patch files in
talos/cluster/,talos/control-planes/,talos/workers/
This means you can use ${VAR} syntax inside your Kind, K3d, or Talos configuration files too:
# 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}Supported Fields
Section titled “Supported Fields”Environment variable expansion works in these string fields:
General:
spec.editor- Editor commandspec.cluster.connection.kubeconfig- Kubeconfig pathspec.cluster.connection.context- Kubernetes context namespec.cluster.distributionConfig- Distribution config pathspec.cluster.localRegistry.registry- Registry specification (including credentials)spec.workload.sourceDirectory- Workload manifest directoryspec.chat.model- Chat model name
Distribution-specific:
spec.cluster.vanilla.mirrorsDir- Mirror configuration directoryspec.cluster.talos.config- Talos configuration path
Provider-specific:
spec.cluster.hetzner.sshKeyName- SSH key namespec.cluster.hetzner.networkName- Network namespec.cluster.hetzner.placementGroup- Placement group name
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 createExample: Distribution Config with Variables
Section titled “Example: Distribution Config with Variables”Environment variables also work inside distribution configuration files:
kind: ClusterapiVersion: kind.x-k8s.io/v1alpha4nodes: - role: control-plane extraPortMappings: - containerPort: ${INGRESS_PORT:-80} hostPort: ${HOST_PORT:-8080}containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry.mirrors."${MIRROR_REGISTRY:-docker.io}"] endpoint = ["http://${REGISTRY:-localhost:5000}"]machine: registries: mirrors: docker.io: endpoints: - http://${REGISTRY:-localhost:5000}Minimal 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 | – | |
workload | WorkloadSpec | – | |
chat | ChatSpec | – |
spec.editor
Section titled “spec.editor”Editor command used by KSail for interactive workflows like ksail cipher edit or ksail workload edit.
Examples: code --wait, vim, nano
If not specified, KSail falls back to standard editor environment variables (SOPS_EDITOR, KUBE_EDITOR, EDITOR, VISUAL) or system defaults (vim, nano, vi).
spec.cluster (ClusterSpec)
Section titled “spec.cluster (ClusterSpec)”| Field | Type | Default | Description |
|---|---|---|---|
distributionConfig | string | – | |
connection | Connection | – | |
distribution | enum | – | |
provider | enum | – | |
cni | enum | – | |
csi | enum | – | |
metricsServer | enum | – | |
loadBalancer | enum | – | |
certManager | enum | – | |
policyEngine | enum | – | |
localRegistry | LocalRegistry | – | |
gitOpsEngine | enum | – | |
importImages | string | – | Path to tar archive with container images to import after cluster creation but before component installation |
vanilla | OptionsVanilla | – | |
talos | OptionsTalos | – | |
hetzner | OptionsHetzner | – | |
omni | OptionsOmni | – |
distribution
Section titled “distribution”Valid values:
Vanilla(default)K3sTalosVCluster
See Distributions for detailed information about each distribution.
Vanilla– Standard upstream Kubernetes (implemented with Kind)K3s– Lightweight Kubernetes (implemented with K3d)Talos– Talos Linux in Docker containers or Hetzner Cloud servers
provider
Section titled “provider”Valid values:
Docker(default)HetznerOmni
See Providers for more details.
Docker– Run nodes as Docker containers (local development)Hetzner– Run nodes on Hetzner Cloud servers (requiresHCLOUD_TOKEN)
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→admin@talos-default
Timeout format: Go duration string (e.g., 30s, 5m, 1h)
Valid values:
Default(default)CiliumCalico
See CNI for more details.
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
Valid values:
Default(default)EnabledDisabled
See CSI for more details.
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”Valid values:
Default(default)EnabledDisabled
Whether to install metrics-server for resource metrics.
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”Valid values:
EnabledDisabled(default)
Whether to install cert-manager for TLS certificate management.
policyEngine
Section titled “policyEngine”Valid values:
None(default)KyvernoGatekeeper
Policy engine to install for enforcing security, compliance, and best practices. See Policy Engines for more details about Kyverno and 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”Valid values:
None(default)FluxArgoCD
GitOps engine to install for continuous deployment workflows. See GitOps for more details about Flux and ArgoCD. When set to Flux or ArgoCD, KSail scaffolds a GitOps CR (FluxInstance or ArgoCD Application) into your source directory.
None– 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)
Hetzner options (spec.cluster.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 | |
validateOnPush | boolean | – |
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
The Vanilla distribution is configured via a YAML file following the Kind configuration schema. This allows you to customize:
- Node images and versions
- Extra port mappings
- Extra mounts
- Networking settings
Documentation: Kind Configuration
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
The K3s distribution is configured via a YAML file following the K3d configuration schema. This allows you to customize:
- Server and agent counts
- Port mappings
- Volume mounts
- Registry configurations
Documentation: K3d Configuration
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. Each directory contains YAML patch files that modify the Talos machine configuration.
Documentation: Talos Configuration Reference
Directory structure and examples:
machine: kubelet: extraArgs: max-pods: "250"machine: kubelet: extraArgs: feature-gates: "EphemeralContainers=true"machine: sysctls: net.core.somaxconn: "65535"Use spec.cluster.talos to configure node counts:
spec: cluster: distribution: Talos distributionConfig: talos talos: controlPlanes: 3 workers: 2Schema 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 (like VS Code with the Red Hat YAML extension) will provide:
- Field autocompletion
- Inline documentation
- Validation errors for invalid values
- Enum suggestions for fields like
distribution,cni, etc.