Files
cirrus/talos
traberphandClaude Opus 5.5 3d3ddc98e9 initial commit: cirrus edge (Talos + sish)
- talos/: generated base config (gitignored) + patches for control-plane
  scheduling, unprivileged ports and the ingress firewall
- kubernetes/: sish base and cirrus-dev overlay, applied with kubectl
- READMEs incl. production rollout plan

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 12:16:27 +02:00
..

Talos: cirrus edge node

Single-node Talos control plane that runs only sish. Talos and Kubernetes are managed by hand with talosctl/kubectl (no Flux).

File
controlplane.yaml Base config, unmodified output of talosctl gen config (gitignored, contains the cluster PKI)
worker.yaml Generated worker config, unused on a single node (gitignored)
talosconfig Admin client config for talosctl (gitignored)
patches/*.yaml Every change to the base config
export TALOSCONFIG=talos/talosconfig   # run from the repo root
N="-n 10.20.5.130 -e 10.20.5.130"

Base config + patches

The base file is never edited by hand; all changes live in patches/. The node's config is therefore always controlplane.yaml + patches/*.yaml, which keeps changes reviewable and lets a newly generated base (new node, new Talos defaults) get the same changes by reapplying the patches. talosctl patch mc merges a patch into the node's live config; it does not touch the local files.

Patch Purpose
control-plane-scheduling.yaml Drops the control-plane NoSchedule taint so sish can run on the only node
unprivileged-ports.yaml ip_unprivileged_port_start=22: sish (non-root, hostNetwork) binds :22/:80/:443
firewall.yaml Ingress firewall, default block (see below)

Apply a single patch (dry run first; use --mode try for anything that can lock you out, it reverts automatically unless re-applied):

talosctl $N patch mc --patch @talos/patches/<patch>.yaml --mode no-reboot --dry-run
talosctl $N patch mc --patch @talos/patches/<patch>.yaml --mode no-reboot

Check that the node matches the files (expect No changes.):

talosctl machineconfig patch talos/controlplane.yaml \
  $(for p in talos/patches/*.yaml; do printf -- '--patch @%s ' "$p"; done) |
  talosctl $N apply-config --file /dev/stdin --dry-run

Firewall

Default action block. Loopback and replies to outgoing connections are always allowed.

Open Source
22, 80, 443, 2222, 20000-20099 tcp anyone sish (2222 = connector SSH, rest = forwards)
6443, 50000 tcp anyone Kubernetes API, Talos API (both client-cert authenticated)
53 udp/tcp pod network 10.244.0.0/16 CoreDNS forwards to the Talos host DNS

Closed: flannel VXLAN 4789/udp, etcd 2379-2383, kubelet 10250, kube-proxy 10256, trustd 50001 (open it to the node network only when a second node joins).

The sish ports must match port-bind-range in kubernetes/base/sish/config.yml. To add a raw TCP port outside 20000-20099, change both files together.

New node

talosctl gen config <cluster-name> https://<node-ip>:6443 --install-disk <disk> -o talos/
talosctl machineconfig patch talos/controlplane.yaml \
  $(for p in talos/patches/*.yaml; do printf -- '--patch @%s ' "$p"; done) |
  talosctl apply-config --insecure -n <node-ip> --file /dev/stdin
talosctl --talosconfig talos/talosconfig config endpoint <node-ip>
talosctl --talosconfig talos/talosconfig -n <node-ip> bootstrap
talosctl --talosconfig talos/talosconfig -n <node-ip> kubeconfig

Back up controlplane.yaml and talosconfig outside this folder: they are the only copy of the cluster PKI and admin credentials.