Files
kubesolo-os/docs/cloud-init.md
Adolfo Delorenzo d900fa920e feat: add cloud-init Go parser (Phase 2)
Implement a lightweight cloud-init system for first-boot configuration:
- Go parser for YAML config (hostname, network, KubeSolo settings)
- Static/DHCP network modes with DNS override
- KubeSolo extra flags and API server SAN configuration
- Portainer Edge Agent and air-gapped deployment support
- New init stage 45-cloud-init.sh runs before network/hostname stages
- Stages 50/60 skip gracefully when cloud-init has already applied
- Build script compiles static Linux/amd64 binary (~2.7 MB)
- 17 unit tests covering parsing, validation, and example files
- Full documentation at docs/cloud-init.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 10:39:05 -06:00

4.1 KiB

KubeSolo OS — Cloud-Init Configuration

KubeSolo OS uses a lightweight cloud-init system to configure the node on first boot. The configuration is a YAML file placed on the data partition before the first boot.

Configuration File Location

The cloud-init config is loaded from (in priority order):

  1. Path specified by kubesolo.cloudinit=<path> boot parameter
  2. /mnt/data/etc-kubesolo/cloud-init.yaml (default)

Boot Sequence Integration

Cloud-init runs as init stage 45, before network (stage 50) and hostname (stage 60). When cloud-init applies successfully, stages 50 and 60 detect this and skip their default behavior.

Stage 20: Mount persistent storage
Stage 30: Load kernel modules
Stage 40: Apply sysctl
Stage 45: Cloud-init (parse YAML, apply hostname + network + KubeSolo config)  <--
Stage 50: Network fallback (skipped if cloud-init handled it)
Stage 60: Hostname fallback (skipped if cloud-init handled it)
Stage 70: Clock sync
Stage 80: Containerd prerequisites
Stage 90: Start KubeSolo

YAML Schema

# Hostname for the node
hostname: kubesolo-node

# Network configuration
network:
  mode: dhcp | static        # Default: dhcp
  interface: eth0             # Optional: auto-detected if omitted
  address: 192.168.1.100/24   # Required for static mode (CIDR notation)
  gateway: 192.168.1.1        # Required for static mode
  dns:                        # Optional: DNS nameservers
    - 8.8.8.8
    - 1.1.1.1

# KubeSolo settings
kubesolo:
  extra-flags: "--disable traefik"   # Extra CLI flags for KubeSolo binary
  local-storage: true                # Enable local-path provisioner (default: true)
  apiserver-extra-sans:              # Extra SANs for API server certificate
    - node.example.com
    - 10.0.0.50

# NTP servers (optional)
ntp:
  servers:
    - pool.ntp.org

# Air-gapped deployment (optional)
airgap:
  import-images: true          # Import container images from data partition
  images-dir: /mnt/data/images # Directory containing .tar image files

# Portainer Edge Agent (optional)
portainer:
  edge-agent:
    enabled: true
    edge-id: "your-edge-id"
    edge-key: "your-edge-key"
    portainer-url: "https://portainer.example.com"

Network Modes

DHCP (Default)

network:
  mode: dhcp

Uses BusyBox udhcpc on the first non-virtual interface. Optionally override DNS:

network:
  mode: dhcp
  dns:
    - 10.0.0.1

Static IP

network:
  mode: static
  interface: eth0
  address: 192.168.1.100/24
  gateway: 192.168.1.1
  dns:
    - 8.8.8.8
    - 8.8.4.4

Both address (CIDR) and gateway are required for static mode.

Persistence

After applying, cloud-init saves its configuration to the data partition:

File Purpose
/mnt/data/network/interfaces.sh Shell script to restore network config on next boot
/mnt/data/etc-kubesolo/hostname Saved hostname
/etc/kubesolo/extra-flags KubeSolo CLI flags
/etc/kubesolo/config.yaml KubeSolo configuration

On subsequent boots, stage 50 (network) sources the saved interfaces.sh directly, skipping cloud-init parsing entirely. This is faster and doesn't require the cloud-init binary.

CLI Usage

The cloud-init binary supports three commands:

# Apply configuration (run during boot by stage 45)
kubesolo-cloudinit apply /path/to/cloud-init.yaml

# Validate a config file
kubesolo-cloudinit validate /path/to/cloud-init.yaml

# Dump parsed config as JSON (for debugging)
kubesolo-cloudinit dump /path/to/cloud-init.yaml

Examples

See cloud-init/examples/ for complete configuration examples:

  • dhcp.yaml — DHCP with defaults
  • static-ip.yaml — Static IP configuration
  • portainer-edge.yaml — Portainer Edge Agent integration
  • airgapped.yaml — Air-gapped deployment with pre-loaded images

Building

The cloud-init binary is built as part of the normal build process:

# Build just the cloud-init binary
make build-cloudinit

# Run cloud-init unit tests
make test-cloudinit

# Full build (includes cloud-init)
make iso

The binary is compiled as a static Linux/amd64 binary (CGO_ENABLED=0) and is approximately 2.7 MB.