Files
homelab/scripts/import-cluster-access.sh
claude-botandClaude Opus 5 a4b659c965
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful
feat(tooling): Hetzner throwaway site and rebuild-harness hardening
None of this is reconciled by Flux — bootstrap.sh, the vmtest Job and
the Talos hcloud patches are operator tooling, applied only when a
rebuild test runs. Zero effect on the live cluster from merging.

New: an hcloudtest phase that provisions three cpx42 servers with
private cluster/storage networks, a this-host-only firewall and one raw
OSD volume per node, then hands over to the ordinary talos phase through
the same four variables vmtest uses. Servers carrying the test label are
adopted and rebuilt from the Talos snapshot instead of recreated —
capacity, not cleanliness, is the scarce resource. Network ranges and
volume sizes are derived from what the cluster itself declares (the site
patch and the machine patches), never stated a second time.
hcloudclean deletes everything by label.

The vmtest Job clones from the GitHub mirror instead of in-cluster
Gitea: a rebuild rehearsal cannot depend on the thing whose loss it
rehearses, and a run died on resolving gitea.renner.uno before the
first VM booted.

bootstrap.sh hardening from a week of rehearsals: the OpenBao unseal
loops until the StatefulSet converges instead of unsealing whichever
pods existed at one instant, require_secrets takes a subset, secrets can
be streamed into a waiting run, retries around talosctl bootstrap and
server placement, and node waits print progress and refuse an expected
count of zero.

import-cluster-access.sh keeps its default AWS profile but stops
overriding one the caller already chose.

Known boundary, documented in site-hcloud.yaml: from master the hcloud
site validates provisioning through cluster-Ready; the SAN path needs
the follow-up rollout PR that renames the storage NIC by role.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-06 20:47:45 +02:00

54 lines
2.2 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Import SOPS-encrypted talosconfig and kubeconfig from Hetzner Object Storage
# (s3://renner-uno-k8s-secrets/cluster-access/) into local ~/.talos/config and
# ~/.kube/config.
#
# Requires aws-cli + sops on the workstation, and Hetzner Object Storage
# credentials reachable either via env (AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY)
# or via an aws-cli profile passed in AWS_PROFILE (the "secrets" profile must
# hold the Hetzner Object Storage keypair).
ENDPOINT="https://fsn1.your-objectstorage.com"
BUCKET="renner-uno-k8s-secrets"
PREFIX="cluster-access"
# Overridable, which the unconditional `export AWS_PROFILE="secrets"` was not.
# The default is unchanged and deliberately so: "secrets" resolves to working
# credentials and this script has always used it. Both "secrets" and "hetzner"
# exist in ~/.aws/credentials on the workstation.
#
# The defect is only the assignment. Forcing the value defeated the env-based
# path this file's own header offers, and it also overrode a caller who had
# already selected a profile — which is how a 403 from HeadObject can appear
# while the credentials the caller intended were perfectly good. That error
# reads as a bucket permissions problem and sends you looking in the wrong
# place.
export AWS_PROFILE="${AWS_PROFILE:-secrets}"
command -v aws >/dev/null || { echo "aws-cli not found"; exit 1; }
command -v sops >/dev/null || { echo "sops not found"; exit 1; }
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
echo "Fetching access files from $ENDPOINT/$BUCKET/$PREFIX/ ..."
AWS_DEFAULT_REGION=fsn1 aws --endpoint-url "$ENDPOINT" \
s3 cp "s3://$BUCKET/$PREFIX/talosconfig.sops" "$TMPDIR/talosconfig.sops"
AWS_DEFAULT_REGION=fsn1 aws --endpoint-url "$ENDPOINT" \
s3 cp "s3://$BUCKET/$PREFIX/kubeconfig.sops" "$TMPDIR/kubeconfig.sops"
mkdir -p ~/.talos ~/.kube
sops -d --input-type binary --output-type binary "$TMPDIR/talosconfig.sops" > ~/.talos/config
chmod 600 ~/.talos/config
sops -d --input-type binary --output-type binary "$TMPDIR/kubeconfig.sops" > ~/.kube/config
chmod 600 ~/.kube/config
echo "Imported:"
echo " ~/.talos/config"
echo " ~/.kube/config"
kubectl get nodes 2>&1 | head -5