Podplane vmconfig is a minimal configuration system for the Podplane Kubernetes distribution & PaaS, designed for Debian-based Linux VMs, written in Bash.
The published packages vary the VM configuration based on the desired VM "kind":
-
kndcreates a Kubernetes Data Plane / Worker node, which runs kubelet, containerd, and supporting services. -
knccreates a Kubernetes Control Plane node, which is essentially a base ofknd+ adds netsy (as an etcd alternative), kube-apiserver, kube-scheduler, kube-controller-manager, etc. -
nstcreates an Nstance Server VM. -
natcreates a dedicated NAT VM.
The VM cloud-init user-data script is responsible for downloading and verifying all dependencies required for its nominated VM kind, and invoking the vmconfig package's install.sh then configure.sh entrypoints.
The full list of dependencies per VM kind, OS, and architecture is published as a vmconfig-manifest.json manifest inside each vmconfig tarball.
VMs are responsible for:
- Placing all dependencies into
/opt/podplane/artifacts/using the<key>.<ext>naming convention (e.g.vmconfig.tar.gz,containerd.tar.gz,fluent-bit.deb,kubelet,runc) - Extracting
/opt/podplane/artifacts/vmconfig.tar.gzto/(paths inside the tarball are relative to the system root, so this also lands/opt/podplane/share/vmconfig-manifest.json) - Invoking
/opt/podplane/bin/install.sh(verifies + installs artifacts, can be used for preparing machine images) - (Optional) Writing any vmconfig runtime settings/environment variables to
/opt/podplane/etc/user-data.env - (Optional) Writing any sensitive bootstrap files required by individual services (e.g.
/opt/nstance-agent/identity/nonce.jwt) - (Optional,
knc) Writing VM-lifecycle-owned production tunnel static Pod manifests under/etc/kubernetes/manifestsand root-only mounted files under/opt/podplane/tunnel/files - Invoking
/opt/podplane/bin/configure.sh(idempotent per-boot configuration) - Invoking
/opt/podplane/bin/restart.sh(idempotent per-boot service (re)start)
Note that the outcome of 1, 2, & 3 can be bundled into a machine image (e.g. an AMI on AWS).
Kubelet watches /etc/kubernetes/manifests for static Pods on knd, knc, and nst VMs. On nst, the Nstance tunnel command constructs fixed hardened manifests from configured digest-pinned images, arguments, and protected file mounts. Deployment configuration owns production tunnel manifests on knc VMs.
The VM kind (knd, knc, nst, or nat) is read from vmconfig.kind in /opt/podplane/share/vmconfig-manifest.json (and after install, from /opt/podplane/share/vmconfig-installed.json). Kubernetes node manifests always include the active connection counters; configuration enables them only when NSTANCE_EBPF_PORTS contains production listener ports.
docs/dependencies.md records each VM kind's artifact sources and bundled dependency chains. Regenerate it with make dependencies; Debian package edges are checked against signed repository metadata.
install.sh, configure.sh, and restart.sh are designed to be idempotent. They handle checking all dependencies, installing them, configuring the system, and (re)starting services as needed.
Runtime settings that can be updated after bootstrap are defined by the stable /opt/podplane/share/defaults/mutable.env contract.
All dev workflows are defined in the Makefile - run make help for the full list, but key workflows include:
-
update-trust: Refreshes
trust/*.asc: GPG keys used to verify upstream apt repositories. Committed to the repo so every dependency manifest update run anchors to an auditable copy. -
update-manifests: Refreshes
manifests/<kind>.<os-name>.<arch>.jsondependency manifests (e.g.manifests/knd.debian-13.amd64.json): one manifest per kind, OS, and arch listing every dependency's URL, version, and content hash/digest. Each entry is resolved through a verified chain (see Dependency Trust below). Incremental - delete an entry or the whole file to scope the refresh. -
test-install: Runs a container-based smoke test for the
install.shandpermissions.shscripts.
The test-install is helpful but limited - every other script under templates should be developed/tested using the Podplane CLI local VM feature. Note that:
-
There is a "live reload" utility per VM kind, which:
- watches for file changes
- uses the Podplane CLI
local synccommand to rsync them to the local VM
-
vmconfig development VMs use a local development vmconfig manifest:
- run
podplane deps download --vmconfig manifests/<kind>.<os-name>.<arch>.jsonso the CLI caches the local manifest (for 7 days) - the checked-in dev manifest has an unreleased
vmconfigdependency stub, so local VM user-data downloads the non-vmconfig dependencies without downloading/extracting a published vmconfig package - sync the locally built
dist/<kind>/tree into the VM withpodplane local sync, then re-run user-data or invoke/opt/podplane/bin/install.sh,/opt/podplane/bin/configure.sh, and/opt/podplane/bin/restart.shmanually as needed - this keeps the developer in control of when synced local/uncommitted vmconfig changes are installed, configured, and restarted
- run
Per-source verification chain used by update-manifests:
-
Debian apt:
gpgverifiesInReleaseagainsttrust/debian-archive.asc-> SHA256 ofPackages->.debdigest. -
Fluent Bit apt: same flow as Debian apt, except using
trust/fluentbit.asc. -
Kubernetes binaries (dl.k8s.io):
.sha256sidecar and per-binary cosign keyless -
containerd tarballs:
.sha256sumsidecar and the release-wide sigstore bundle*-attestation.intoto.jsonl(GitHub Actions OIDC) -
runc, registry, cri-tools, cni-plugins, Debian OS image: TLS + sidecar checksum only - their available signing layouts are not currently verified by the manifest updater
Learn more about Podplane at the official project website: podplane.dev
For more information about vmconfig specifically, please read the documentation at: podplane.dev/docs/vmconfig
Podplane is licensed under the Apache License, Version 2.0. Copyright The Podplane Authors.
See the LICENSE file for details.