ov-foundation/skills/k3s-server/SKILL.md
k3s control-plane (server) node with ServiceLB, Traefik v2, and local-path-provisioner enabled by default. Publishes kubeconfig back to the operator via layer artifacts and registers a ClusterProfile on first boot.
npx skillsauth add overthinkos/overthink-plugins k3s-serverInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Property | Value |
|----------|-------|
| Install files | layer.yml, tasks:, service:, artifacts:, secret_requires: |
| Depends on | /ov-foundation:k3s |
| Service | k3s.service (system scope, enabled) |
K3S_CLUSTER_TOKEN from the credential store (secret_requires:)./etc/rancher/k3s/config.yaml with:
token: — the pre-shared cluster tokenwrite-kubeconfig-mode: "0644" — so the operator can scp the kubeconfig backtls-san: — ${K3S_SERVER_HOSTNAME} (or hostname -n fallback)disable: [] — explicitly empty, so ServiceLB, Traefik v2, and
local-path-provisioner all install as default k3s addons./etc/systemd/system/k3s.service running k3s server./etc/rancher/k3s/k3s.yaml back to
the operator via the new artifacts: layer-schema feature. The
retrieved file lands at ~/.cache/ov/clusters/<deploy_name>/kubeconfig.yaml
with 127.0.0.1 rewritten to ${K3S_SERVER_HOSTNAME} so the operator
can kubectl the cluster from their machine.K3sPostProvision hook (Go, runs after artifact retrieval)
merges the kubeconfig into ~/.kube/config under context
<deploy_name> and writes a matching ClusterProfile to
~/.config/ov/clusters/<deploy_name>.yaml with ingress.class=traefik
and storage.class_default=local-path.K3S_CLUSTER_TOKEN auto-generates on first deploy. The resolver
(ov/layer_secrets.go — ensureLayerSecret) detects the missing
secret_requires: entry, generates a 32-byte hex token via
generateAndStoreSecret, and persists it to the active credential
backend (keyring / kdbx / config-file fallback). Every subsequent
k3s-server and k3s-agent deploy reads the same persisted value —
zero operator setup, server and agents automatically share the token.
Override with a specific value (uncommon — only when reproducing a specific cluster identity, e.g., disaster recovery):
ov secrets set ov/secret/K3S_CLUSTER_TOKEN $(openssl rand -hex 32)
Retrieve the auto-generated token (for debugging or out-of-band agent join):
ov secrets get ov/secret K3S_CLUSTER_TOKEN
# overthink.yml
vm:
k3s-srv:
source: { kind: cloud_image, url: "…" }
disposable: true
ram: 4G
cpus: 2
deployments:
images:
"vm:k3s-srv":
target: vm
vm_source: k3s-srv
add_layers: [k3s-server]
env:
- K3S_SERVER_HOSTNAME=k3s-srv.lan # optional but recommended
ov vm create k3s-srv
ov deploy add vm:k3s-srv
# → kubeconfig auto-retrieved + ClusterProfile written
kubectl --context k3s-srv get nodes
ov eval k8s addons --cluster k3s-srv
Build-scope:
/etc/rancher/k3s/config.yaml exists, mode 0600./etc/systemd/system/k3s.service exists.Deploy-scope (using the new ov eval k8s verb — see /ov-advanced:eval-k8s):
k8s: wait-nodes — at least 1 node Ready.k8s: ingressclass — traefik present.k8s: storageclass — local-path present.k8s: addons — Traefik + ServiceLB + local-path-provisioner all Ready./ov-foundation:k3s — Base layer installing the k3s binary (required dep)/ov-foundation:k3s-agent — Worker nodes joining this server/ov-coder:kubernetes-layer — kubectl/helm on the operator side (not needed in the cluster)/ov-advanced:eval-k8s — The test verb used by this layer's deploy-scope checkstools
Use when authoring or modifying a charly PLUGIN — a candy with a `plugin:` block that contributes Providers (verbs/kinds/deploy-targets/steps/builders/commands), its own CUE schema, builtin (compiled-in) or external (out-of-tree git repo). Covers the unified Provider model, the per-plugin CUE-schema contract (single source → Go params for dev + schema-over-Describe RPC for runtime), the SDK, and the loader.
tools
The CUE data-validation / configuration CLI (cue), pinned to v0.16.1. Use when working with the cue candy, installing the cue binary into a box or onto a target:local dev host, or running the offline schema-vendoring pipeline that feeds charly's egress validation.
tools
CUE EGRESS validation — validating (and, where it adds value, generating) the config files charly WRITES to a system BEFORE the bytes hit disk. MUST be invoked before working on charly/egress.go, the vendored schemas under candy/plugin-egress/egress-schemas/vendor/, the ValidateEgress / registerVendoredEgressKind path, the offline `task cue:vendor` pipeline, or adding an egress schema for any written artifact (cloud-init, k8s manifests, traefik routes, runtime config, install ledger, systemd/quadlet units, ssh_config, libvirt XML).
tools
Kubernetes cluster-probe declarative check verb — the `kube:` check verb (nodes, pods, ingress, storage class, addon health, apply/delete, and arbitrary resource GETs) served out-of-process by the candy/plugin-kube plugin (vendored client-go; no external kubectl required).