GREEN PACKAGE SKILL · K3S · FLUX · HETZNER

k3s

Provision one secured Hetzner K3s node, bootstrap Flux, and reconcile a public Git repository without exposing the Kubernetes API.

  • Single node
  • K3s + Flux
  • Private API
  • GitOps

#Introduction

This skill creates one Hetzner VPS, attaches a restrictive cloud firewall, installs exact K3s and Flux releases, and points Flux at a public Git repository. The package owns infrastructure and bootstrap; GitOps owns applications.

Safe first stepsbuild renders local files and create --dry-run prints the workflow without contacting providers. Review both before approving a real operation.

#Quick start

npx skills add getcolors/k3s
cp .agents/skills/package-k3s-green/green ./green
./green build
./green create --dry-run
# after approval:
./green create
./green kubectl get nodes

#Workflow architecture

create/build  start ─ k3s-compute ─┬─ k3s-ansible-local
                                      └─ k3s-ansible-remote

delete        start ─ k3s-ansible-cleanup ─ k3s-compute

The compute stage reuses ONCE’s Hetzner server template and adds a package-owned firewall. Package-specific stage names isolate state.

#Desired state

AreaRequired choices
ProvidersHetzner compute; no-infra or Cloudflare DNS; local, S3, or R2 backend
GitOpsPublic HTTPS repository, optional branch and path
VersionsExact k3s-version and flux-version
HetznerName, Ubuntu image, server type, location, existing SSH key
SafetyUnique profile and compute-prevent-destroy: true

See the configuration reference.

#Networking and access

The attached default-deny firewall admits ICMP and TCP 22, 80, and 443. TCP 6443 is deliberately absent. The launcher’s kubectl verb runs sudo k3s kubectl over the managed SSH alias, so no kubeconfig is copied locally.

#Flux, DNS, and TLS

Flux watches branch main and path ./k8s by default. With Cloudflare enabled, create streams the API token into Kubernetes Secrets for ExternalDNS and cert-manager. The public repository contains only Secret references, never token values.

#Command reference

CommandEffect
./green buildValidate and render
./green create --dry-runPrint the DAG
./green createProvision and reconcile
./green kubectl …Run remote kubectl over SSH
./green deleteGuarded VPS and boot-disk destruction

#State and output

.colors/<profile>/
├── k3s-compute/
├── k3s-ansible-local/
└── k3s-ansible-remote/

Remote state is <profile>/k3s-compute.tfstate. Generated files may contain addresses but contain no kubeconfig or provider token.

#Credentials and safety

Keep the API privateDo not add port 6443 to the public firewall. Use the remote kubectl adapter.
  • COLORS_PAR_HCLOUD_TOKEN provisions compute.
  • Cloudflare and R2 use their corresponding COLORS_PAR_* variables.
  • Never export COLORS_PAR_PROFILE.
  • Keep the destroy guard committed as true.

#Troubleshooting

Flux is not applying changes

Inspect GitRepository and Kustomization readiness with the remote kubectl command, then verify the configured branch and path.

HTTPS is pending

Check ExternalDNS, cert-manager, the token Secret references, and the public DNS zone independently.