Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ jobs:
name: YAML lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- run: pip install yamllint --quiet
- run: yamllint -c .yamllint.yml .

secrets:
name: Secrets detection
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install gitleaks
Expand All @@ -38,7 +38,7 @@ jobs:
name: Kubernetes manifest validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Install kubeconform
run: |
Expand All @@ -58,7 +58,7 @@ jobs:
name: Helm lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Install Helm
uses: azure/setup-helm@v4
Expand Down Expand Up @@ -98,7 +98,7 @@ jobs:
name: API deprecation check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Read target Kubernetes version
id: k8s
Expand Down Expand Up @@ -130,9 +130,9 @@ jobs:
name: Markdown lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "20"
node-version: "24"
- run: npm install -g markdownlint-cli2
- run: markdownlint-cli2 "**/*.md" "#node_modules"
41 changes: 41 additions & 0 deletions .github/workflows/talos-image-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Update Talos image

on:
repository_dispatch:
types: [talos-image-update]

jobs:
update:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- uses: actions/checkout@v6

- name: Update omni/talos-image.yaml
env:
TALOS_VERSION: ${{ github.event.client_payload.talos_version }}
run: |
sed -i "s|^talos_version:.*|talos_version: ${TALOS_VERSION}|" omni/talos-image.yaml
sed -i "s|^updated_at:.*|updated_at: \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"|" omni/talos-image.yaml

- name: Open pull request
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TALOS_VERSION: ${{ github.event.client_payload.talos_version }}
run: |
BRANCH="talos-image-update/${TALOS_VERSION}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b "${BRANCH}"
git add omni/talos-image.yaml
git diff --cached --quiet && echo "No changes" && exit 0
git commit -m "chore: update Talos installer image to ${TALOS_VERSION}"
git push origin "${BRANCH}"
gh pr create \
--title "chore: update Talos installer image to ${TALOS_VERSION}" \
--body "Auto-generated by talos-images build workflow." \
--base main \
--head "${BRANCH}"
1 change: 1 addition & 0 deletions .markdownlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MD013: false # line-length: URLs and long paths make this impractical
8 changes: 0 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ repos:
hooks:
- id: gitleaks

- repo: https://github.com/yannh/kubeconform
rev: v0.6.7
hooks:
- id: kubeconform
args:
- -strict
- -ignore-missing-schemas
- -summary

- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.44.0
Expand Down
6 changes: 5 additions & 1 deletion omni/cluster-templates/talos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ name: oci-talos
labels:
environment: oci
kubernetes:
# Not touched by the talos-images upgrade workflow — bump deliberately, one
# minor at a time. Talos 1.13.x supports k8s 1.31–1.36 (SupportedKubernetesVersions=6
# counting back from its 1.36.2 default), so this is valid as-is.
version: v1.32.3
talos:
version: v1.12.5
# Keep in step with installImage in omni/machine-classes/*.yaml.
version: v1.13.5
patches:
- file: ../patches/cni-none.yaml
- file: ../patches/disable-kube-proxy.yaml
Expand Down
2 changes: 1 addition & 1 deletion omni/machine-classes/control-plane.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ metadata:
id: oci-cp

spec:
installImage: ghcr.io/syscode-labs/talos-images/installer:v1.9.0
installImage: ghcr.io/syscode-labs/talos-images/installer:v1.13.5
matchLabels:
# Applied manually in Omni UI after OCI nodes connect via SideroLink.
# omnictl machine set-labels <machine-id> role=oci-cp
Expand Down
2 changes: 1 addition & 1 deletion omni/machine-classes/worker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ metadata:
id: oci-worker

spec:
installImage: ghcr.io/syscode-labs/talos-images/installer:v1.9.0
installImage: ghcr.io/syscode-labs/talos-images/installer:v1.13.5
matchLabels:
# Applied manually in Omni UI after OCI nodes connect via SideroLink.
# omnictl machine set-labels <machine-id> role=oci-worker
Expand Down
75 changes: 67 additions & 8 deletions omni/scripts/generate-manifests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ set -euo pipefail
CILIUM_VERSION="${CILIUM_VERSION:-1.17.2}"
ARGOCD_VERSION="${ARGOCD_VERSION:-v2.14.4}"

# Argo topology selector.
# hub : omit in-cluster Argo — a central hub Argo (on the Omni VM k8s) manages
# this cluster as a spoke (default for this homelab).
# in-cluster : bootstrap Argo CD + root App-of-Apps inside this cluster.
# Cilium is always in-cluster (it is the CNI).
ARGO_MODE="${ARGO_MODE:-hub}"
case "$ARGO_MODE" in
in-cluster|hub) ;;
*) echo "ARGO_MODE must be 'in-cluster' or 'hub', got '${ARGO_MODE}'" >&2; exit 1 ;;
esac

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PATCH_FILE="${SCRIPT_DIR}/../patches/inline-manifests.yaml"
TMPDIR=$(mktemp -d)
Expand All @@ -29,30 +40,37 @@ helm template cilium cilium/cilium \
--set hubble.ui.enabled=true \
> "${TMPDIR}/cilium.yaml"

echo "==> Downloading Argo CD ${ARGOCD_VERSION}..."
curl -sL "https://raw.githubusercontent.com/argoproj/argo-cd/${ARGOCD_VERSION}/manifests/install.yaml" \
> "${TMPDIR}/argocd.yaml"
if [ "$ARGO_MODE" = "in-cluster" ]; then
echo "==> Downloading Argo CD ${ARGOCD_VERSION}..."
curl -sL "https://raw.githubusercontent.com/argoproj/argo-cd/${ARGOCD_VERSION}/manifests/install.yaml" \
> "${TMPDIR}/argocd.yaml"
ARGOCD_CONTENT=$(sed 's/^/ /' "${TMPDIR}/argocd.yaml")
fi

CILIUM_CONTENT=$(sed 's/^/ /' "${TMPDIR}/cilium.yaml")
ARGOCD_CONTENT=$(sed 's/^/ /' "${TMPDIR}/argocd.yaml")

echo "==> Writing ${PATCH_FILE}..."
echo "==> Writing ${PATCH_FILE} (ARGO_MODE=${ARGO_MODE})..."
cat > "${PATCH_FILE}" <<EOF
# Talos inline manifests applied during cluster bootstrap by the first control plane node.
# These run before any workload scheduler is up, so they must be self-contained YAML.
#
# REGENERATE after Cilium/Argo CD version bumps:
# mise run oci:generate-manifests
# mise run oci:generate-manifests # central hub Argo (default)
# ARGO_MODE=in-cluster mise run oci:generate-manifests # in-cluster Argo + App-of-Apps
#
# ARGO_MODE: ${ARGO_MODE}
# Cilium: ${CILIUM_VERSION} — kubeProxyReplacement=true, KubePrism (localhost:7445)
# Argo CD: ${ARGOCD_VERSION} — raw install manifest + root App-of-Apps

cluster:
inlineManifests:
- name: cilium
contents: |
# cilium v${CILIUM_VERSION} — generated $(date -u +%Y-%m-%d)
${CILIUM_CONTENT}
EOF

if [ "$ARGO_MODE" = "in-cluster" ]; then
cat >> "${PATCH_FILE}" <<EOF

- name: argocd
contents: |
Expand Down Expand Up @@ -80,5 +98,46 @@ ${ARGOCD_CONTENT}
prune: true
selfHeal: true
EOF
else
cat >> "${PATCH_FILE}" <<'EOF'

# ARGO_MODE=hub — no in-cluster Argo. A central hub Argo (on the Omni VM k8s) manages
# this cluster as a spoke. This block ships the ServiceAccount the hub authenticates as,
# so the token exists from first boot. Registration (read token → sops → commit) is the
# single manual step, documented once in:
# syscode-ai-internal-plans/projects/imp/docs/plans/2026-07-11-argo-hub-spoke-registration-runbook.md
- name: argocd-manager
contents: |
apiVersion: v1
kind: ServiceAccount
metadata:
name: argocd-manager
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argocd-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: argocd-manager
namespace: kube-system
---
# Non-expiring legacy SA token (auto-token Secrets removed in k8s 1.24). Deliberate:
# a bound short-lived token can't be pre-committed for GitOps registration.
apiVersion: v1
kind: Secret
metadata:
name: argocd-manager-token
namespace: kube-system
annotations:
kubernetes.io/service-account.name: argocd-manager
type: kubernetes.io/service-account-token
EOF
fi

echo "==> Done. Commit omni/patches/inline-manifests.yaml."
echo "==> Done (ARGO_MODE=${ARGO_MODE}). Commit omni/patches/inline-manifests.yaml."
10 changes: 5 additions & 5 deletions omni/talos-image.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Auto-updated by talos-images workflow — do not edit manually
talos_version: v1.9.0
kubernetes_version: v1.32.3
schematic_id: ""
oci_image_ocid: ""
updated_at: ""
talos_version: v1.13.5
kubernetes_version: v1.36.2
schematic_id: 4a0d65c669d46663f377e7161e50cfd570c401f26fd9e7bda34a0216b6f1922b
oci_image_ocid: ocid1.image.oc1.uk-london-1.aaaaaaaadheaqve6ikpx5nqn637zmaudgq6dt67tnv7z2t7dnju5tyu6l2ta
updated_at: 2026-07-05T05:59:40Z
Loading