Review on #927: the git -C /root/source/ prefix let config and push
through; rm /root/Notes/wiki/ matched path traversal. Allowed git forms
are now log/show/diff/status/rev-parse/ls-files per repo (both the ~ and
/root spelling), config is denied for those forms too, rm is denied and
notes are deleted through the vault's wiki-delete.sh, which validates the
slug. Verified headless: log allowed, config denied, push not allowed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The pass that verifies notes against sources, repos and the live cluster
and edits them still ran on the workstation timer, with no TypeSafe key,
no cost record, and no run on days the machine was off. It joins the
nightly pipeline after the audit: full clones of homelab and homeassistant
under ~/source, read-only kubectl via the ci-diagnostics token, its own
permission scope, JSON output so the report and total_cost_usd land in
the step log. push-notes also commits the rotation state and pushes the
agent's own snapshot commits.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every night with an empty queue started a full claude run that read the
directory and stopped, paying the agent's startup context and a model
pick for nothing (runs 10362, 10583).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The audit agent had no executable path in CI (Bash limited to the two
retrieval tools), wrote itself scripts it could not run and reported one
of seven checks (runs 10262, 10362). The checks are mechanical, so
notes/bin/wiki_audit.py does them without a model. push-notes adds only
wiki/, raw/ and output/, so scratch files in the checkout root are no
longer committed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The project moved to Codeberg; GitHub is a read-only mirror and the old
chart index at k8s-gateway.github.io returns 404, so the HelmRelease has
had no artifact. The chart is now published as an OCI artifact in the
project's own Codeberg registry (oci://codeberg.org/k8s-gateway/charts/
k8s-gateway), alongside the image.
OCIRepository + chartRef as for spegel and mariadb-operator; semver
range unchanged. Chart 3.7.2 -> 3.7.3, image moves to
codeberg.org/k8s-gateway/k8s_gateway:1.8.3. The rendered Corefile is
identical to the live one.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
NETWORK-traffic-classes.md described table 48 and rules 980/981/990/991,
which #857 replaced with one table (47) decided by longest prefix, and
listed management as not started. Rewritten to the live state: five
classes, table 47 contents owned by bird, node IP and etcd on node0, the
etcd leave-and-rejoin procedure, and the mixed-state hazard hit during
the node IP move. The bird DaemonSet comment still named table 48.
Closes#576
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Records the live state after moving all three nodes:
- site-homelab.yaml: kubelet nodeIP.validSubnets fd02:46::/64 and
10.2.46.0/24 (was 10.2.40.0/24 and the legacy fd40::/64).
- cluster.yaml: etcd advertisedSubnets 10.2.46.0/24.
- mgmt0 comments: VLAN 40 is world-to-node only now.
Applied per node (k8s-3, k8s-2, k8s-1): drain, stage the config (delete
the old lists, set the new ones, one staged patch call), etcd
forfeit-leadership and leave, reboot. Each node rejoined etcd with its
VLAN 46 peer URL; EPHEMERAL was not wiped.
Refs #576
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Pod-sourced traffic is routed from table 47. Once the node IP moves to
VLAN 46 (step 3), pods reach node addresses there: the kubernetes
ClusterIP (socket LB rewrites it to the apiserver's advertise address),
hostNetwork pod IPs, and replies to kubelet probes. Without the attached
node0 route in table 47 those flows take the default to the UDM and every
in-cluster API client breaks. Taking it from the interface, like the
other attached networks, keeps the table in one owner.
Refs #576
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- node0: VLANConfig on the uplink trunk, VLAN 46, static fd02:46::1x/64
and 10.2.46.1x/24, accept_ra 0. Closed like pod0. Unused until the node
IP moves there (step 3).
- cluster.etcd.advertisedSubnets pinned to 10.2.40.0/24 so a reboot
cannot pick a node0 address: Talos never updates an existing member's
peer URLs.
Applied live with talosctl patch --mode=no-reboot, k8s-3 first. Node IPs
unchanged, etcd 3/3 healthy, node0 reachable node to node over v6 and v4.
Refs #576
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Nothing selects cni.renner.uno/cilium-uninstall or
cni.renner.uno/multus-sole-writer since stage B (#915, #916). Removed
live from all three nodes with a $patch: delete strategic merge patch
(--mode=no-reboot); Talos dropped them from the Kubernetes nodes and
left the other labels in place.
Closes#832
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
cni.confPath: /etc/cni/net.d/multus mounts that host directory as the
agent's /host/etc/cni/net.d, so write-cni-conf-when-ready (unchanged,
.../05-cilium.conflist) lands in /etc/cni/net.d/multus/05-cilium.conflist,
the file the per-node CiliumNodeConfigs already produced on all three
nodes. The agent finds it unchanged and does not rewrite it.
updateStrategy maxUnavailable: 1 (chart default 2) so the roll takes one
node's datapath at a time.
bootstrap.sh renders the chart from these values, so a cold rebuild
lands directly in this layout.
Refs #832
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
All three nodes run the sole-writer layout. Converge the Multus side and
drop the per-node Cilium overrides:
- kube-multus-ds-subdir becomes the only Multus DaemonSet, no node
affinity; kube-multus-ds (0 pods) and its ConfigMap are pruned.
- /etc/cni/net.d/multus is mounted DirectoryOrCreate so Multus waits for
the Cilium conflist instead of exiting on a missing directory.
- CiliumNodeConfigs removed. They only act when a cilium pod is created;
stage B2 moves the same path into the HelmRelease (cni.confPath) and
rolls the agents.
Refs #832
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
k8s-1 carries cni.renner.uno/cilium-uninstall and
cni.renner.uno/multus-sole-writer, applied live with talosctl patch.
Verified on the node: /etc/cni/net.d holds only 00-multus.conf at the
top level, and after a reboot with immediate uncordon the OSD came up
with net1 (10.99.0.1) and no restarts. All three nodes are converted.
Refs #832
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Deployment tolerated every NoSchedule taint (operator: Exists, no
key), including node.kubernetes.io/unschedulable. During the #832 node
reboots its ReplicaSet kept placing replacement pods on the cordoned,
shutting-down node; the kubelet rejected each with NodeShutdown, about
200 failed pods per reboot. Tolerate only the control-plane taint the
comment names.
Refs #832
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
k8s-2 carries cni.renner.uno/cilium-uninstall and
cni.renner.uno/multus-sole-writer, applied live with talosctl patch.
Verified on the node: /etc/cni/net.d holds only 00-multus.conf at the
top level, and after a reboot with immediate uncordon the OSD came up
with net1 (10.99.0.2) and no restarts.
Refs #832
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
k8s-3 carries cni.renner.uno/cilium-uninstall and
cni.renner.uno/multus-sole-writer, applied live with talosctl patch.
Verified on the node: /etc/cni/net.d holds only 00-multus.conf at the
top level, Cilium writes multus/05-cilium.conflist, and after a reboot
with immediate uncordon the OSD came up with net1 (10.99.0.3) and no
restarts.
Refs #832
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Nothing changes until a node is labelled:
- post-crds/cilium-nodeconfig.yaml: CiliumNodeConfig cni-uninstall
(label cni.renner.uno/cilium-uninstall) arms the agent's preStop
conflist cleanup; multus-sole-writer (label
cni.renner.uno/multus-sole-writer) moves write-cni-conf-when-ready to
/host/etc/cni/net.d/multus/05-cilium.conflist, a subdirectory libcni
does not read.
- multus/multus-subdir.yaml: kube-multus-ds-subdir with
multusAutoconfigDir /host/etc/cni/net.d/multus, scheduled only on
labelled nodes; kube-multus-ds gets the inverse affinity.
The kube-multus-ds template change rolls Multus node by node once on
merge.
Refs #832
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- kubernetes/infrastructure/netbird-proxy-services -> netbird-service-sync:
SA, ClusterRole(Binding) and Deployment renamed, in namespace
netbird-service-sync, image gitea_admin/netbird-service-sync pinned to
the master build digest, BAO_ROLE=netbird-service-sync.
- Old policy doc netbird-proxy-services.hcl removed; Traefik comment
follows the name.
The infrastructure KS owns both old and new objects, so prune and apply
happen in one pass. OpenBao policy and role netbird-service-sync are
already written.
Closes#876
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Additive; the running controller is untouched:
- ci/images/netbird-proxy-services -> ci/images/netbird-service-sync,
build step and image name renamed, so the merge builds
gitea_admin/netbird-service-sync.
- Namespace netbird-service-sync with a baseline policy: probes in;
out only to kube-dns, kube-apiserver, OpenBao :8200 and world :443
(NetBird management API).
- openbao-ns admits netbird-service-sync on :8200, like wiki-index.
- policies/netbird-service-sync.hcl documents the new policy and role
(applied by hand, as before).
Refs #876
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Gitea runs in the gitea namespace since #906. Remove what only served it
in apps:
- openbao rotator egress (flux-git, review-bot): apps/gitea target.
- ai-ns wiki-index ingress: apps/gitea source.
- apps default-deny egress to wiki-index :8080 (gitea's webhook; now in
gitea-ns.yaml).
- Velero schedule comments.
Refs #878
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- kubernetes/apps/gitea: every object in namespace gitea; applied by a
new gitea Flux Kustomization (clusters/homelab/gitea.yaml) instead of
apps. gitea-allow-metrics-scrape dropped: the gitea-ns baseline
already admits monitoring.
- Rotators (flux-git, review-bot) and the Prometheus gitea job use
gitea.gitea.svc.
- bootstrap.sh waits for the gitea KS.
Data: data-gitea-0 is not copied. The PV (reclaimPolicy Retain) is
rebound to a PVC gitea/data-gitea-0 pre-created with volumeName, which
the new StatefulSet adopts. gitea-tls is pre-issued in the gitea
namespace so HTTPS has no certificate gap.
Refs #878
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Additive only, nothing moves yet:
- Namespace gitea, declared in infrastructure like woodpecker.
- network-policies/gitea-ns.yaml: baseline (same-ns, monitoring, host,
ICMP; egress to traefik, kube-dns, wiki-index, world) and
gitea-allow-traefik for :3000 and :2222.
- openbao rotator egress (flux-git, review-bot) and wiki-index ingress
also admit gitea in the gitea namespace; the apps entries stay until
stage 3.
- Velero schedule gitea-daily (07:45) so data-gitea-0 stays backed up
after the move; apps-daily comment updated (Woodpecker left apps).
Refs #878
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
decide required every consumer to pin the same ci-claude tag and aborted
otherwise (pipeline 10497: [2.1.250 2.1.278]), which needed a hand fix
before the latest version could roll out. Record all distinct tags, bump
whenever any is off latest, and rewrite every version-pinned tag to the
new one with a validated x.y.z version.
Merging this is itself a push touching the pipeline file, so the refresh
runs, builds the latest image, and opens the bump PR.
Refs #889
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Pipeline 10186 failed in bump-pr with 'url contains a newline in its
username component': ci_claude_bump_bot_token carries a trailing newline,
so the push URL (and the PR API auth header) broke. Strip CR/LF once at
the top of the step and fail fast if the token ends up empty. This makes
the step independent of how the secret value was written.
Closes#889
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>