commit 2bd7fb534aed4f615bac034a5a0289107c666617
parent 59a29b8d8150d7ede97280582d74ff7e38489a02
Author: MTRNord <MTRNord@users.noreply.github.com>
Date: Sun, 7 Dec 2025 21:08:10 +0100
meow?
Signed-off-by: MTRNord <MTRNord@users.noreply.github.com>
Diffstat:
4 files changed, 483 insertions(+), 8 deletions(-)
diff --git a/.github/renovate.json b/.github/renovate.json
@@ -1,11 +1,130 @@
{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "extends": [
+ "config:base",
+ ":dependencyDashboard",
+ ":semanticCommits",
+ ":separateMultipleMinorReleases"
+ ],
"prConcurrentLimit": 4,
"prHourlyLimit": 5,
- "semanticCommits": "enabled",
- "enabledManagers": [
- "github-actions",
- "helm-values",
- "helmv3",
- "flux"
- ]
+ "suppressNotifications": ["prIgnoreNotification"],
+ "rebaseWhen": "conflicted",
+ "enabledManagers": ["github-actions", "helm-values", "helmv3", "flux"],
+ "flux": {
+ "fileMatch": [
+ "(^|/)clusters/.+\\.ya?ml$",
+ "(^|/)infrastructure_talos/.+\\.ya?ml$",
+ "(^|/)apps/.+\\.ya?ml$"
+ ]
+ },
+ "helm-values": {
+ "fileMatch": [
+ "(^|/)apps/.+/values\\.ya?ml$",
+ "(^|/)infrastructure_talos/.+/values\\.ya?ml$"
+ ]
+ },
+ "kubernetes": {
+ "fileMatch": [
+ "(^|/)clusters/.+\\.ya?ml$",
+ "(^|/)infrastructure_talos/.+\\.ya?ml$",
+ "(^|/)apps/.+\\.ya?ml$"
+ ]
+ },
+ "packageRules": [
+ {
+ "description": "Auto-merge patch updates",
+ "matchUpdateTypes": ["patch"],
+ "matchCurrentVersion": "!/^0/",
+ "automerge": true,
+ "automergeType": "pr",
+ "platformAutomerge": true
+ },
+ {
+ "description": "Auto-merge minor updates for non-breaking changes",
+ "matchUpdateTypes": ["minor"],
+ "matchCurrentVersion": "!/^0/",
+ "automerge": false,
+ "groupName": "minor-updates"
+ },
+ {
+ "description": "Group Flux component updates",
+ "matchDatasources": ["docker", "github-releases"],
+ "matchPackagePatterns": ["^fluxcd/"],
+ "groupName": "flux-components",
+ "automerge": false
+ },
+ {
+ "description": "Group cert-manager updates",
+ "matchDatasources": ["docker", "helm"],
+ "matchPackagePatterns": ["cert-manager"],
+ "groupName": "cert-manager",
+ "automerge": false
+ },
+ {
+ "description": "Group monitoring stack updates",
+ "matchDatasources": ["docker", "helm"],
+ "matchPackagePatterns": [
+ "prometheus",
+ "grafana",
+ "alertmanager",
+ "kube-state-metrics",
+ "node-exporter"
+ ],
+ "groupName": "monitoring-stack",
+ "automerge": false
+ },
+ {
+ "description": "Group security updates and auto-merge",
+ "matchDatasources": ["docker"],
+ "matchUpdateTypes": ["patch"],
+ "vulnerabilityAlerts": {
+ "enabled": true
+ },
+ "groupName": "security-updates",
+ "automerge": true,
+ "schedule": ["at any time"]
+ },
+ {
+ "description": "Pin GitHub Actions digests",
+ "matchManagers": ["github-actions"],
+ "pinDigests": true
+ },
+ {
+ "description": "Group GitHub Actions updates",
+ "matchManagers": ["github-actions"],
+ "groupName": "github-actions",
+ "automerge": true,
+ "automergeType": "pr"
+ },
+ {
+ "description": "Separate major updates",
+ "matchUpdateTypes": ["major"],
+ "automerge": false,
+ "labels": ["type/major-update"]
+ },
+ {
+ "description": "Label minor updates",
+ "matchUpdateTypes": ["minor"],
+ "labels": ["type/minor-update"]
+ },
+ {
+ "description": "Label patch updates",
+ "matchUpdateTypes": ["patch"],
+ "labels": ["type/patch-update"]
+ }
+ ],
+ "regexManagers": [
+ {
+ "description": "Update _VERSION variables in shell scripts",
+ "fileMatch": ["\\.sh$"],
+ "matchStrings": [
+ "datasource=(?<datasource>\\S+) depName=(?<depName>\\S+)( versioning=(?<versioning>\\S+))?\n.*?_VERSION=\"(?<currentValue>.*)\""
+ ]
+ }
+ ],
+ "vulnerabilityAlerts": {
+ "enabled": true,
+ "labels": ["security", "type/security-update"]
+ }
}
diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml
@@ -0,0 +1,51 @@
+---
+name: Renovate
+
+on:
+ schedule:
+ # Run every day at 2:00 AM UTC
+ - cron: '0 2 * * *'
+ workflow_dispatch:
+ inputs:
+ logLevel:
+ description: 'Log level'
+ required: false
+ default: 'info'
+ type: choice
+ options:
+ - info
+ - debug
+ - trace
+ dryRun:
+ description: 'Dry run'
+ required: false
+ default: 'false'
+ type: choice
+ options:
+ - 'true'
+ - 'false'
+
+permissions:
+ contents: write
+ pull-requests: write
+ issues: write
+
+jobs:
+ renovate:
+ name: Renovate Dependencies
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Self-hosted Renovate
+ uses: renovatebot/github-action@v40.1.12
+ with:
+ configurationFile: .github/renovate.json
+ token: ${{ secrets.RENOVATE_TOKEN || secrets.GITHUB_TOKEN }}
+ env:
+ LOG_LEVEL: ${{ inputs.logLevel || 'info' }}
+ RENOVATE_DRY_RUN: ${{ inputs.dryRun || 'false' }}
+ RENOVATE_AUTODISCOVER: 'false'
+ RENOVATE_BASE_BRANCHES: 'main'
+ RENOVATE_GIT_AUTHOR: 'Renovate Bot <bot@renovateapp.com>'
diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml
@@ -0,0 +1,191 @@
+---
+name: Validate GitOps Manifests
+
+on:
+ pull_request:
+ branches: ["*"]
+ paths:
+ - "apps/**"
+ - "clusters/**"
+ - "infrastructure_talos/**"
+ - "scripts/validate.sh"
+ push:
+ branches: ["main"]
+ paths:
+ - "apps/**"
+ - "clusters/**"
+ - "infrastructure_talos/**"
+ - "scripts/validate.sh"
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ validate-manifests:
+ name: Validate Kubernetes Manifests
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Flux CLI
+ uses: fluxcd/flux2/action@main
+
+ - name: Setup tools
+ run: |
+ # Install yq
+ sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
+ sudo chmod +x /usr/local/bin/yq
+
+ # Install kustomize
+ curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
+ sudo mv kustomize /usr/local/bin/
+
+ # Install kubeconform
+ curl -LO https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz
+ tar xzf kubeconform-linux-amd64.tar.gz
+ sudo mv kubeconform /usr/local/bin/
+
+ # Verify installations
+ yq --version
+ kustomize version
+ kubeconform -v
+
+ - name: Run validation script
+ run: |
+ chmod +x scripts/validate.sh
+ ./scripts/validate.sh
+
+ - name: Validate Flux sources
+ run: |
+ flux check --pre
+
+ security-scan:
+ name: Security Scanning
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ security-events: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Run gitleaks
+ uses: gitleaks/gitleaks-action@v2
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Setup tools for manifest extraction
+ run: |
+ # Install yq
+ sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
+ sudo chmod +x /usr/local/bin/yq
+
+ # Install kustomize
+ curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
+ sudo mv kustomize /usr/local/bin/
+
+ - name: Extract container images
+ id: extract-images
+ run: |
+ set +e
+ mkdir -p /tmp/manifests
+
+ # Build all kustomizations and extract images
+ find . -type f -name 'kustomization.yaml' | while read -r file; do
+ dir=$(dirname "$file")
+ echo "Building $dir"
+ kustomize build "$dir" --load-restrictor=LoadRestrictionsNone > /tmp/manifests/$(echo "$dir" | tr '/' '_').yaml 2>/dev/null || true
+ done
+
+ # Extract unique images
+ cat /tmp/manifests/*.yaml | yq eval 'select(.spec.template.spec.containers != null) | .spec.template.spec.containers[].image' - 2>/dev/null | sort -u > /tmp/images.txt || true
+ cat /tmp/manifests/*.yaml | yq eval 'select(.spec.template.spec.initContainers != null) | .spec.template.spec.initContainers[].image' - 2>/dev/null | sort -u >> /tmp/images.txt || true
+
+ # Extract images from HelmRelease values
+ find . -type f -name '*.yaml' -exec grep -l "kind: HelmRelease" {} \; | while read -r file; do
+ yq eval '.spec.values | .. | select(. == "*image*" or . == "*repository*") | select(type == "!!str")' "$file" 2>/dev/null || true
+ done >> /tmp/images.txt || true
+
+ sort -u /tmp/images.txt > /tmp/images_final.txt
+
+ echo "Found images:"
+ cat /tmp/images_final.txt
+
+ - name: Run Trivy vulnerability scanner
+ uses: aquasecurity/trivy-action@master
+ with:
+ scan-type: 'config'
+ scan-ref: '.'
+ format: 'sarif'
+ output: 'trivy-results.sarif'
+ severity: 'CRITICAL,HIGH'
+
+ - name: Upload Trivy results to GitHub Security
+ uses: github/codeql-action/upload-sarif@v3
+ if: always()
+ with:
+ sarif_file: 'trivy-results.sarif'
+
+ kubeaudit:
+ name: Kubernetes Security Audit
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup tools
+ run: |
+ # Install kustomize
+ curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
+ sudo mv kustomize /usr/local/bin/
+
+ # Install kubeaudit
+ curl -LO https://github.com/Shopify/kubeaudit/releases/latest/download/kubeaudit_linux_amd64.tar.gz
+ tar xzf kubeaudit_linux_amd64.tar.gz
+ sudo mv kubeaudit /usr/local/bin/
+
+ - name: Run kubeaudit
+ continue-on-error: true
+ run: |
+ mkdir -p /tmp/manifests
+
+ # Build all kustomizations
+ find . -type f -name 'kustomization.yaml' | while read -r file; do
+ dir=$(dirname "$file")
+ echo "Building $dir"
+ kustomize build "$dir" --load-restrictor=LoadRestrictionsNone > /tmp/manifests/$(echo "$dir" | tr '/' '_').yaml 2>/dev/null || true
+ done
+
+ # Run kubeaudit on each manifest
+ for manifest in /tmp/manifests/*.yaml; do
+ echo "Auditing $manifest"
+ if [ -f kubeaudit-config.yml ]; then
+ kubeaudit all -f "$manifest" --minseverity warning -c kubeaudit-config.yml || true
+ else
+ kubeaudit all -f "$manifest" --minseverity warning || true
+ fi
+ done
+
+ lint:
+ name: Lint YAML Files
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: YAML Lint
+ uses: ibiqlik/action-yamllint@v3
+ with:
+ config_data: |
+ extends: default
+ rules:
+ line-length:
+ max: 120
+ level: warning
+ document-start: disable
+ truthy:
+ check-keys: false
diff --git a/README.md b/README.md
@@ -1 +1,115 @@
-TODO: Rewrite this file
+# Talos Kubernetes GitOps Repository
+
+GitOps configuration for Kubernetes on [Talos Linux](https://www.talos.dev/) using [Flux CD](https://fluxcd.io/).
+
+## Stack
+
+- **OS**: Talos Linux
+- **GitOps**: Flux CD
+- **Secrets**: SOPS + age
+- **CNI**: Cilium
+- **Updates**: Renovate
+
+## Structure
+
+```
+├── clusters/talos_cluster/ # Flux bootstrap
+├── infrastructure_talos/ # Controllers, monitoring
+├── apps/ # Applications
+└── .github/workflows/ # CI (validation, renovate)
+```
+
+## Quick Start
+
+```bash
+# Bootstrap Talos
+talosctl gen config my-cluster https://CONTROL_PLANE_IP:6443
+talosctl apply-config --insecure --nodes CONTROL_PLANE_IP --file controlplane.yaml
+talosctl bootstrap --nodes CONTROL_PLANE_IP
+talosctl kubeconfig --nodes CONTROL_PLANE_IP
+
+# Install Flux
+flux check --pre
+kubectl apply -k clusters/talos_cluster/flux-system
+
+# Setup SOPS (generate NEW key, never use the one in repo!)
+age-keygen -o age.key
+kubectl create secret generic sops-age --namespace=flux-system --from-file=age.agekey=age.key
+# Update .sops.yaml with your public key, store age.key securely
+
+# Deploy
+flux reconcile kustomization flux-system --with-source
+```
+
+## Secrets
+
+```bash
+# Encrypt
+sops --encrypt --encrypted-regex '^(data|stringData)$' secret.yaml > secret.enc.yaml
+
+# Edit
+sops secret.enc.yaml
+```
+
+**Never commit:** `age.key`, `age.agekey`, decrypted secrets
+
+## Common Tasks
+
+```bash
+# Deploy changes
+git commit -am "update" && git push
+
+# Force reconcile
+flux reconcile kustomization flux-system --with-source
+
+# Check status
+flux get all -A
+flux logs --level=error
+
+# Rollback
+git revert COMMIT && git push
+```
+
+## CI/CD
+
+- **validate.yaml**: Validates manifests, runs security scans (gitleaks, trivy, kubeaudit)
+- **renovate.yaml**: Automated dependency updates (daily 2 AM UTC)
+
+Run locally: `./scripts/validate.sh`
+
+## Troubleshooting
+
+```bash
+# Flux
+flux check
+flux logs --all-namespaces
+
+# SOPS
+kubectl get secret sops-age -n flux-system
+
+# Apps
+kubectl describe pod POD -n NAMESPACE
+kubectl logs POD -n NAMESPACE
+
+# Talos
+talosctl health --nodes NODE_IP
+talosctl logs -n NODE_IP
+```
+
+## Security Notes
+
+**Critical**: The `age.agekey` in this repo is exposed and must be rotated immediately.
+
+Remove sensitive files: `age.agekey`, `gerrit_key*`, `*.log`, `audit.txt`, `bak_*`
+
+Apply security policies:
+
+- Pod Security Standards (restricted mode)
+- LimitRanges for resource defaults
+- ResourceQuotas for namespace limits
+- NetworkPolicies (default-deny)
+
+## Resources
+
+- [Flux Docs](https://fluxcd.io/docs/)
+- [Talos Docs](https://www.talos.dev/docs/)