remove SOPS pipeline, deploy ESO + Vault DB/K8s engines
Vault is now the sole source of truth for secrets. SOPS pipeline removed entirely — auth via `vault login -method=oidc`. Part A: SOPS removal - vault/main.tf: delete 990 lines (93 vars + 43 KV write resources), add self-read data source for OIDC creds from secret/vault - terragrunt.hcl: remove SOPS var loading, vault_root_token, check_secrets hook - scripts/tg: remove SOPS decryption, keep -auto-approve logic - .woodpecker/default.yml: replace SOPS with Vault K8s auth via curl - Delete secrets.sops.json, .sops.yaml Part B: External Secrets Operator - New stack stacks/external-secrets/ with Helm chart + 2 ClusterSecretStores (vault-kv for KV v2, vault-database for DB engine) Part C: Database secrets engine (in vault/main.tf) - MySQL + PostgreSQL connections with static role rotation (24h) - 6 MySQL roles (speedtest, wrongmove, codimd, nextcloud, shlink, grafana) - 6 PostgreSQL roles (trading, health, linkwarden, affine, woodpecker, claude_memory) Part D: Kubernetes secrets engine (in vault/main.tf) - RBAC for Vault SA to manage K8s tokens - Roles: dashboard-admin, ci-deployer, openclaw, local-admin - New scripts/vault-kubeconfig helper for dynamic kubeconfig K8s auth method with scoped policies for CI, ESO, OpenClaw, Woodpecker sync.
This commit is contained in:
parent
d17a6e2fd3
commit
3aba29e7a3
25 changed files with 680 additions and 1357 deletions
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
## Instructions
|
||||
- **"remember X"**: Use `memory-tool store "content" --category facts --tags "tag1,tag2"` (via exec) for persistent cross-session memory. Also update this file + `AGENTS.md` (if shared knowledge), commit with `[ci skip]`. To recall: `memory-tool recall "query"`. To list: `memory-tool list`. To delete: `memory-tool delete <id>`. The native `memory_search` and `memory_get` tools are also available for searching indexed memory files. For **storing** new memories, always use the `memory-tool` CLI via exec.
|
||||
- **Apply with SOPS**: Use `scripts/tg` wrapper instead of raw `terragrunt` — auto-decrypts secrets
|
||||
- **Apply**: Authenticate via `vault login -method=oidc`, then use `scripts/tg` or `terragrunt` directly. `scripts/tg` adds `-auto-approve` for `--non-interactive` applies.
|
||||
- **New services need CI/CD** (Woodpecker) and **monitoring** (Prometheus/Uptime Kuma)
|
||||
- **New service**: Use `setup-project` skill for full workflow
|
||||
- **Ingress**: `ingress_factory` module. Auth: `protected = true`. Anti-AI: on by default.
|
||||
|
|
@ -19,13 +19,20 @@
|
|||
- **Node memory changes**: When changing VM memory on any k8s node, update kubelet `systemReserved`, `kubeReserved`, and eviction thresholds accordingly. Config: `/var/lib/kubelet/config.yaml`. Template: `stacks/infra/main.tf`. Current values: systemReserved=512Mi, kubeReserved=512Mi, evictionHard=500Mi, evictionSoft=1Gi.
|
||||
- **Sealed Secrets**: User-managed secrets go in `sealed-*.yaml` files in the stack directory. Stacks pick them up via `kubernetes_manifest` + `fileset(path.module, "sealed-*.yaml")`. See AGENTS.md for full workflow.
|
||||
|
||||
## Secrets Management — Vault KV
|
||||
- **All secrets migrated from SOPS to Vault KV v2** (2026-03-15). 43 stacks read from `data "vault_kv_secret_v2" "secrets"` at `secret/<stack-name>`.
|
||||
- **Vault stack** (`stacks/vault/main.tf`) is the bridge: reads secrets from SOPS `-var-file`, writes them to Vault KV via 43 `vault_kv_secret_v2` resources.
|
||||
- **Bootstrap secrets stay in SOPS permanently**: `vault_root_token`, `vault_authentik_client_id`, `vault_authentik_client_secret`.
|
||||
- **Platform cannot depend on vault** (circular — vault depends on platform). Apply order: vault first, then platform.
|
||||
## Secrets Management — Vault KV (SOPS removed)
|
||||
- **Vault is the sole source of truth** for secrets. SOPS pipeline has been removed entirely.
|
||||
- **Auth**: `vault login -method=oidc` (Authentik SSO) → `~/.vault-token` → read by Vault TF provider.
|
||||
- **Vault stack self-reads**: `data "vault_kv_secret_v2" "vault"` reads its own OIDC creds from `secret/vault`.
|
||||
- **Consuming stacks** read from `data "vault_kv_secret_v2" "secrets"` at `secret/<stack-name>`.
|
||||
- **External Secrets Operator (ESO)**: `stacks/external-secrets/` syncs Vault KV → K8s Secrets via `ClusterSecretStore`.
|
||||
- **Database rotation**: Vault database secrets engine rotates app DB passwords every 24h (MySQL + PostgreSQL static roles).
|
||||
- **K8s credentials**: Vault K8s secrets engine issues short-lived tokens for dashboard, CI, OpenClaw, local admin.
|
||||
- **CI/CD (Woodpecker)**: Authenticates via K8s service account JWT → Vault K8s auth method.
|
||||
- **Platform cannot depend on vault** (circular). Apply order: vault first, then platform.
|
||||
- **Complex types** (maps/lists like `homepage_credentials`, `k8s_users`) stored as JSON strings in KV, decoded with `jsondecode()` in consuming stack `locals` blocks.
|
||||
- **New stacks**: Add a `vault_kv_secret_v2` resource in vault/main.tf, then use `data "vault_kv_secret_v2" "secrets"` + `dependency "vault"` in the new stack.
|
||||
- **New stacks**: Add secret in Vault UI/CLI at `secret/<stack-name>`, then use `data "vault_kv_secret_v2" "secrets"` in the stack.
|
||||
- **Backup CronJob**: `vault-raft-backup` uses manually-created `vault-root-token` K8s Secret (independent of automation).
|
||||
- **Bootstrap (fresh cluster)**: See vault/main.tf comments — comment out data source + OIDC, deploy Helm, init+unseal, populate `secret/vault`, uncomment, re-apply.
|
||||
|
||||
## Resource Management Patterns
|
||||
- **CPU**: All CPU limits removed cluster-wide (CFS throttling). Only set CPU requests based on actual usage.
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
# SOPS configuration — defines who can decrypt which files
|
||||
# age public keys only (safe to commit)
|
||||
creation_rules:
|
||||
- path_regex: ^secrets\.sops\.json$
|
||||
age: >-
|
||||
age1z64h9t3acsm2rr74pz7j4846kwj5tutx9sk78jqv46y8fln4vs2sy920ce,
|
||||
age1hrafaswdslw4u63scxp8u5ye4tf8h0xjah0v85w280phy06m0vespz2u0n
|
||||
|
|
@ -18,12 +18,13 @@ steps:
|
|||
- |
|
||||
curl -k https://10.0.20.100:6443/api/v1/namespaces/woodpecker/configmaps/git-crypt-key -H "Authorization:Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" | jq -r .data.key | base64 -d > /tmp/key
|
||||
- "git-crypt unlock /tmp/key && rm /tmp/key"
|
||||
# SOPS: download to workspace (shared across steps), decrypt secrets
|
||||
- "wget -qO ./sops https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64 && chmod +x ./sops"
|
||||
- "echo \"$SOPS_AGE_KEY\" > /tmp/age.key && SOPS_AGE_KEY_FILE=/tmp/age.key ./sops -d secrets.sops.json > secrets.auto.tfvars.json && rm -f /tmp/age.key"
|
||||
environment:
|
||||
SOPS_AGE_KEY:
|
||||
from_secret: sops_age_key
|
||||
# Vault: authenticate via K8s service account JWT
|
||||
- |
|
||||
SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
|
||||
VAULT_TOKEN=$(curl -s -X POST http://vault-active.vault.svc.cluster.local:8200/v1/auth/kubernetes/login \
|
||||
-d "{\"role\":\"ci\",\"jwt\":\"$SA_TOKEN\"}" | jq -r .auth.client_token)
|
||||
echo "export VAULT_TOKEN=$VAULT_TOKEN" > .vault-env
|
||||
echo "export VAULT_ADDR=http://vault-active.vault.svc.cluster.local:8200" >> .vault-env
|
||||
|
||||
- name: terragrunt-apply
|
||||
image: alpine
|
||||
|
|
@ -35,13 +36,15 @@ steps:
|
|||
# Install Terragrunt
|
||||
- "wget -qO /usr/local/bin/terragrunt https://github.com/gruntwork-io/terragrunt/releases/download/v0.99.4/terragrunt_linux_amd64"
|
||||
- "chmod 755 /usr/local/bin/terragrunt"
|
||||
# Source Vault token
|
||||
- "source .vault-env"
|
||||
# Apply platform stack (core infrastructure services)
|
||||
- "cd stacks/platform && terragrunt apply --non-interactive -auto-approve"
|
||||
|
||||
- name: cleanup-and-push
|
||||
image: alpine
|
||||
commands:
|
||||
- "rm -f secrets.auto.tfvars.json secrets.auto.tfvars.json.*"
|
||||
- "rm -f .vault-env"
|
||||
- "apk update && apk add openssh-client git git-crypt"
|
||||
- "mkdir -p ~/.ssh && ssh-keyscan -H github.com >> ~/.ssh/known_hosts"
|
||||
- "chmod 400 secrets/deploy_key"
|
||||
|
|
|
|||
BIN
config.tfvars
BIN
config.tfvars
Binary file not shown.
18
scripts/tg
18
scripts/tg
|
|
@ -1,24 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
# scripts/tg — wrapper: decrypt secrets then run terragrunt
|
||||
# scripts/tg — wrapper: inject -auto-approve for non-interactive apply
|
||||
# Usage: scripts/tg apply --non-interactive
|
||||
# scripts/tg run --all -- plan
|
||||
# Auth: `vault login -method=oidc` (token at ~/.vault-token)
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
SOPS_FILE="$REPO_ROOT/secrets.sops.json"
|
||||
OUT_FILE="$REPO_ROOT/secrets.auto.tfvars.json"
|
||||
|
||||
# Decrypt if needed (skips if already decrypted and up-to-date)
|
||||
if [ -f "$SOPS_FILE" ]; then
|
||||
if [ ! -f "$OUT_FILE" ] || [ "$SOPS_FILE" -nt "$OUT_FILE" ]; then
|
||||
TEMP=$(mktemp "$OUT_FILE.XXXXXX")
|
||||
trap "rm -f '$TEMP'" EXIT
|
||||
sops -d "$SOPS_FILE" > "$TEMP"
|
||||
mv "$TEMP" "$OUT_FILE"
|
||||
echo "Decrypted secrets.sops.json → secrets.auto.tfvars.json"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If running apply with --non-interactive, add -auto-approve for Terraform
|
||||
args=("$@")
|
||||
has_apply=false
|
||||
|
|
|
|||
10
scripts/vault-kubeconfig
Executable file
10
scripts/vault-kubeconfig
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
# Generate a short-lived kubeconfig from Vault K8s secrets engine.
|
||||
# Requires: vault login -method=oidc (or VAULT_TOKEN set)
|
||||
set -euo pipefail
|
||||
|
||||
TOKEN=$(vault write -format=json kubernetes/creds/local-admin kubernetes_namespace=default | jq -r .data.service_account_token)
|
||||
kubectl config set-credentials vault-admin --token="$TOKEN"
|
||||
kubectl config set-context vault --cluster=kubernetes --user=vault-admin
|
||||
kubectl config use-context vault
|
||||
echo "Kubeconfig set with 1h token"
|
||||
File diff suppressed because one or more lines are too long
20
stacks/actualbudget/.terraform.lock.hcl
generated
20
stacks/actualbudget/.terraform.lock.hcl
generated
|
|
@ -57,3 +57,23 @@ provider "registry.terraform.io/hashicorp/random" {
|
|||
"zh:f49fd62aa8c5525a5c17abd51e27ca5e213881d58882fd42fec4a545b53c9699",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/vault" {
|
||||
version = "4.8.0"
|
||||
constraints = "~> 4.0"
|
||||
hashes = [
|
||||
"h1:GPfhH6dr1LY0foPBDYv9bEGifx7eSwYqFcEAOWOUxLk=",
|
||||
"zh:269ab13433f67684012ae7e15876532b0312f5d0d2002a9cf9febb1279ce5ea6",
|
||||
"zh:4babc95bf0c40eb85005db1dc2ca403c46be4a71dd3e409db3711a56f7a5ca0e",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:86e27c1c625ecc24446a11eeffc3ac319b36c2b4e51251db8579256a0dbcf136",
|
||||
"zh:a32f31da94824009e26b077374440b52098aecb93c92ff55dc3d31dd37c4ea25",
|
||||
"zh:be0a18c6c0425518bab4fbffd82078b82036a88503b5d76064de551c9f646cbf",
|
||||
"zh:be5a77fdfd36863ebeec79cd12b1d13322ffad6821d157a0b279789fa06b5937",
|
||||
"zh:be8317d142a3caad74c7d936039ae27076a1b2b8312ef5208e2871a5f525977c",
|
||||
"zh:c94a84895a3d9954b80e983eed4603330a5cdbbd8eef5b3c99278c2d1402ef3c",
|
||||
"zh:de1fb712784dd8415f011ca5346a34f87fab6046c730557615247e511dbc7d98",
|
||||
"zh:e3eafae7da550f86cae395d6660b2a0e93ec8d2b0e0e5ef982ec762e961fc952",
|
||||
"zh:ff35fb1ab6add288f0f368981e56f780b50405accd1937131cba1137999c8d83",
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,22 @@
|
|||
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
|
||||
terraform {
|
||||
required_providers {
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "kube_config_path" {
|
||||
type = string
|
||||
default = "~/.kube/config"
|
||||
}
|
||||
|
||||
variable "vault_root_token" {
|
||||
type = string
|
||||
default = "~/.kube/config"
|
||||
sensitive = true
|
||||
default = ""
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
|
|
@ -14,3 +28,9 @@ provider "helm" {
|
|||
config_path = var.kube_config_path
|
||||
}
|
||||
}
|
||||
|
||||
provider "vault" {
|
||||
address = "https://vault.viktorbarzin.me"
|
||||
token = var.vault_root_token
|
||||
skip_child_token = true
|
||||
}
|
||||
|
|
|
|||
80
stacks/external-secrets/main.tf
Normal file
80
stacks/external-secrets/main.tf
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
resource "kubernetes_namespace" "external_secrets" {
|
||||
metadata {
|
||||
name = "external-secrets"
|
||||
labels = {
|
||||
tier = local.tiers.cluster
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "helm_release" "external_secrets" {
|
||||
name = "external-secrets"
|
||||
namespace = kubernetes_namespace.external_secrets.metadata[0].name
|
||||
repository = "https://charts.external-secrets.io"
|
||||
chart = "external-secrets"
|
||||
version = "0.12.1"
|
||||
|
||||
values = [yamlencode({
|
||||
installCRDs = true
|
||||
})]
|
||||
}
|
||||
|
||||
# --- ClusterSecretStore for Vault KV v2 ---
|
||||
|
||||
resource "kubernetes_manifest" "css_vault_kv" {
|
||||
manifest = {
|
||||
apiVersion = "external-secrets.io/v1beta1"
|
||||
kind = "ClusterSecretStore"
|
||||
metadata = { name = "vault-kv" }
|
||||
spec = {
|
||||
provider = {
|
||||
vault = {
|
||||
server = "http://vault-active.vault.svc.cluster.local:8200"
|
||||
path = "secret"
|
||||
version = "v2"
|
||||
auth = {
|
||||
kubernetes = {
|
||||
mountPath = "kubernetes"
|
||||
role = "eso"
|
||||
serviceAccountRef = {
|
||||
name = "external-secrets"
|
||||
namespace = "external-secrets"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
depends_on = [helm_release.external_secrets]
|
||||
}
|
||||
|
||||
# --- ClusterSecretStore for Vault Database Engine ---
|
||||
|
||||
resource "kubernetes_manifest" "css_vault_db" {
|
||||
manifest = {
|
||||
apiVersion = "external-secrets.io/v1beta1"
|
||||
kind = "ClusterSecretStore"
|
||||
metadata = { name = "vault-database" }
|
||||
spec = {
|
||||
provider = {
|
||||
vault = {
|
||||
server = "http://vault-active.vault.svc.cluster.local:8200"
|
||||
path = "database"
|
||||
version = "v1"
|
||||
auth = {
|
||||
kubernetes = {
|
||||
mountPath = "kubernetes"
|
||||
role = "eso"
|
||||
serviceAccountRef = {
|
||||
name = "external-secrets"
|
||||
namespace = "external-secrets"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
depends_on = [helm_release.external_secrets]
|
||||
}
|
||||
8
stacks/external-secrets/terragrunt.hcl
Normal file
8
stacks/external-secrets/terragrunt.hcl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
include "root" {
|
||||
path = find_in_parent_folders()
|
||||
}
|
||||
|
||||
dependency "vault" {
|
||||
config_path = "../vault"
|
||||
skip_outputs = true
|
||||
}
|
||||
10
stacks/external-secrets/tiers.tf
Normal file
10
stacks/external-secrets/tiers.tf
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
|
||||
locals {
|
||||
tiers = {
|
||||
core = "0-core"
|
||||
cluster = "1-cluster"
|
||||
gpu = "2-gpu"
|
||||
edge = "3-edge"
|
||||
aux = "4-aux"
|
||||
}
|
||||
}
|
||||
20
stacks/freedify/.terraform.lock.hcl
generated
20
stacks/freedify/.terraform.lock.hcl
generated
|
|
@ -38,3 +38,23 @@ provider "registry.terraform.io/hashicorp/kubernetes" {
|
|||
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/vault" {
|
||||
version = "4.8.0"
|
||||
constraints = "~> 4.0"
|
||||
hashes = [
|
||||
"h1:GPfhH6dr1LY0foPBDYv9bEGifx7eSwYqFcEAOWOUxLk=",
|
||||
"zh:269ab13433f67684012ae7e15876532b0312f5d0d2002a9cf9febb1279ce5ea6",
|
||||
"zh:4babc95bf0c40eb85005db1dc2ca403c46be4a71dd3e409db3711a56f7a5ca0e",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:86e27c1c625ecc24446a11eeffc3ac319b36c2b4e51251db8579256a0dbcf136",
|
||||
"zh:a32f31da94824009e26b077374440b52098aecb93c92ff55dc3d31dd37c4ea25",
|
||||
"zh:be0a18c6c0425518bab4fbffd82078b82036a88503b5d76064de551c9f646cbf",
|
||||
"zh:be5a77fdfd36863ebeec79cd12b1d13322ffad6821d157a0b279789fa06b5937",
|
||||
"zh:be8317d142a3caad74c7d936039ae27076a1b2b8312ef5208e2871a5f525977c",
|
||||
"zh:c94a84895a3d9954b80e983eed4603330a5cdbbd8eef5b3c99278c2d1402ef3c",
|
||||
"zh:de1fb712784dd8415f011ca5346a34f87fab6046c730557615247e511dbc7d98",
|
||||
"zh:e3eafae7da550f86cae395d6660b2a0e93ec8d2b0e0e5ef982ec762e961fc952",
|
||||
"zh:ff35fb1ab6add288f0f368981e56f780b50405accd1937131cba1137999c8d83",
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,22 @@
|
|||
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
|
||||
terraform {
|
||||
required_providers {
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "kube_config_path" {
|
||||
type = string
|
||||
default = "~/.kube/config"
|
||||
}
|
||||
|
||||
variable "vault_root_token" {
|
||||
type = string
|
||||
default = "~/.kube/config"
|
||||
sensitive = true
|
||||
default = ""
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
|
|
@ -14,3 +28,9 @@ provider "helm" {
|
|||
config_path = var.kube_config_path
|
||||
}
|
||||
}
|
||||
|
||||
provider "vault" {
|
||||
address = "https://vault.viktorbarzin.me"
|
||||
token = var.vault_root_token
|
||||
skip_child_token = true
|
||||
}
|
||||
|
|
|
|||
20
stacks/linkwarden/.terraform.lock.hcl
generated
20
stacks/linkwarden/.terraform.lock.hcl
generated
|
|
@ -57,3 +57,23 @@ provider "registry.terraform.io/hashicorp/random" {
|
|||
"zh:f49fd62aa8c5525a5c17abd51e27ca5e213881d58882fd42fec4a545b53c9699",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/vault" {
|
||||
version = "4.8.0"
|
||||
constraints = "~> 4.0"
|
||||
hashes = [
|
||||
"h1:GPfhH6dr1LY0foPBDYv9bEGifx7eSwYqFcEAOWOUxLk=",
|
||||
"zh:269ab13433f67684012ae7e15876532b0312f5d0d2002a9cf9febb1279ce5ea6",
|
||||
"zh:4babc95bf0c40eb85005db1dc2ca403c46be4a71dd3e409db3711a56f7a5ca0e",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:86e27c1c625ecc24446a11eeffc3ac319b36c2b4e51251db8579256a0dbcf136",
|
||||
"zh:a32f31da94824009e26b077374440b52098aecb93c92ff55dc3d31dd37c4ea25",
|
||||
"zh:be0a18c6c0425518bab4fbffd82078b82036a88503b5d76064de551c9f646cbf",
|
||||
"zh:be5a77fdfd36863ebeec79cd12b1d13322ffad6821d157a0b279789fa06b5937",
|
||||
"zh:be8317d142a3caad74c7d936039ae27076a1b2b8312ef5208e2871a5f525977c",
|
||||
"zh:c94a84895a3d9954b80e983eed4603330a5cdbbd8eef5b3c99278c2d1402ef3c",
|
||||
"zh:de1fb712784dd8415f011ca5346a34f87fab6046c730557615247e511dbc7d98",
|
||||
"zh:e3eafae7da550f86cae395d6660b2a0e93ec8d2b0e0e5ef982ec762e961fc952",
|
||||
"zh:ff35fb1ab6add288f0f368981e56f780b50405accd1937131cba1137999c8d83",
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,24 @@
|
|||
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
|
||||
terraform {
|
||||
required_providers {
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "kube_config_path" {
|
||||
type = string
|
||||
default = "~/.kube/config"
|
||||
}
|
||||
|
||||
variable "vault_root_token" {
|
||||
type = string
|
||||
sensitive = true
|
||||
default = ""
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
config_path = var.kube_config_path
|
||||
}
|
||||
|
|
@ -13,3 +28,9 @@ provider "helm" {
|
|||
config_path = var.kube_config_path
|
||||
}
|
||||
}
|
||||
|
||||
provider "vault" {
|
||||
address = "https://vault.viktorbarzin.me"
|
||||
token = var.vault_root_token
|
||||
skip_child_token = true
|
||||
}
|
||||
|
|
|
|||
20
stacks/nextcloud/.terraform.lock.hcl
generated
20
stacks/nextcloud/.terraform.lock.hcl
generated
|
|
@ -38,3 +38,23 @@ provider "registry.terraform.io/hashicorp/kubernetes" {
|
|||
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/vault" {
|
||||
version = "4.8.0"
|
||||
constraints = "~> 4.0"
|
||||
hashes = [
|
||||
"h1:GPfhH6dr1LY0foPBDYv9bEGifx7eSwYqFcEAOWOUxLk=",
|
||||
"zh:269ab13433f67684012ae7e15876532b0312f5d0d2002a9cf9febb1279ce5ea6",
|
||||
"zh:4babc95bf0c40eb85005db1dc2ca403c46be4a71dd3e409db3711a56f7a5ca0e",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:86e27c1c625ecc24446a11eeffc3ac319b36c2b4e51251db8579256a0dbcf136",
|
||||
"zh:a32f31da94824009e26b077374440b52098aecb93c92ff55dc3d31dd37c4ea25",
|
||||
"zh:be0a18c6c0425518bab4fbffd82078b82036a88503b5d76064de551c9f646cbf",
|
||||
"zh:be5a77fdfd36863ebeec79cd12b1d13322ffad6821d157a0b279789fa06b5937",
|
||||
"zh:be8317d142a3caad74c7d936039ae27076a1b2b8312ef5208e2871a5f525977c",
|
||||
"zh:c94a84895a3d9954b80e983eed4603330a5cdbbd8eef5b3c99278c2d1402ef3c",
|
||||
"zh:de1fb712784dd8415f011ca5346a34f87fab6046c730557615247e511dbc7d98",
|
||||
"zh:e3eafae7da550f86cae395d6660b2a0e93ec8d2b0e0e5ef982ec762e961fc952",
|
||||
"zh:ff35fb1ab6add288f0f368981e56f780b50405accd1937131cba1137999c8d83",
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,22 @@
|
|||
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
|
||||
terraform {
|
||||
required_providers {
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "kube_config_path" {
|
||||
type = string
|
||||
default = "~/.kube/config"
|
||||
}
|
||||
|
||||
variable "vault_root_token" {
|
||||
type = string
|
||||
sensitive = true
|
||||
default = ""
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
|
|
@ -14,3 +28,9 @@ provider "helm" {
|
|||
config_path = var.kube_config_path
|
||||
}
|
||||
}
|
||||
|
||||
provider "vault" {
|
||||
address = "https://vault.viktorbarzin.me"
|
||||
token = var.vault_root_token
|
||||
skip_child_token = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,6 @@ variable "kube_config_path" {
|
|||
default = "~/.kube/config"
|
||||
}
|
||||
|
||||
variable "vault_root_token" {
|
||||
type = string
|
||||
sensitive = true
|
||||
default = ""
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
config_path = var.kube_config_path
|
||||
}
|
||||
|
|
@ -31,6 +25,5 @@ provider "helm" {
|
|||
|
||||
provider "vault" {
|
||||
address = "https://vault.viktorbarzin.me"
|
||||
token = var.vault_root_token
|
||||
skip_child_token = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
|
||||
terraform {
|
||||
backend "local" {
|
||||
path = "/woodpecker/src/github.com/ViktorBarzin/infra/state/stacks/platform/terraform.tfstate"
|
||||
path = "/Users/viktorbarzin/code/infra/state/stacks/platform/terraform.tfstate"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
stacks/servarr/.terraform.lock.hcl
generated
20
stacks/servarr/.terraform.lock.hcl
generated
|
|
@ -57,3 +57,23 @@ provider "registry.terraform.io/hashicorp/random" {
|
|||
"zh:f49fd62aa8c5525a5c17abd51e27ca5e213881d58882fd42fec4a545b53c9699",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/vault" {
|
||||
version = "4.8.0"
|
||||
constraints = "~> 4.0"
|
||||
hashes = [
|
||||
"h1:GPfhH6dr1LY0foPBDYv9bEGifx7eSwYqFcEAOWOUxLk=",
|
||||
"zh:269ab13433f67684012ae7e15876532b0312f5d0d2002a9cf9febb1279ce5ea6",
|
||||
"zh:4babc95bf0c40eb85005db1dc2ca403c46be4a71dd3e409db3711a56f7a5ca0e",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:86e27c1c625ecc24446a11eeffc3ac319b36c2b4e51251db8579256a0dbcf136",
|
||||
"zh:a32f31da94824009e26b077374440b52098aecb93c92ff55dc3d31dd37c4ea25",
|
||||
"zh:be0a18c6c0425518bab4fbffd82078b82036a88503b5d76064de551c9f646cbf",
|
||||
"zh:be5a77fdfd36863ebeec79cd12b1d13322ffad6821d157a0b279789fa06b5937",
|
||||
"zh:be8317d142a3caad74c7d936039ae27076a1b2b8312ef5208e2871a5f525977c",
|
||||
"zh:c94a84895a3d9954b80e983eed4603330a5cdbbd8eef5b3c99278c2d1402ef3c",
|
||||
"zh:de1fb712784dd8415f011ca5346a34f87fab6046c730557615247e511dbc7d98",
|
||||
"zh:e3eafae7da550f86cae395d6660b2a0e93ec8d2b0e0e5ef982ec762e961fc952",
|
||||
"zh:ff35fb1ab6add288f0f368981e56f780b50405accd1937131cba1137999c8d83",
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,22 @@
|
|||
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
|
||||
terraform {
|
||||
required_providers {
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "kube_config_path" {
|
||||
type = string
|
||||
default = "~/.kube/config"
|
||||
}
|
||||
|
||||
variable "vault_root_token" {
|
||||
type = string
|
||||
sensitive = true
|
||||
default = ""
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
|
|
@ -14,3 +28,9 @@ provider "helm" {
|
|||
config_path = var.kube_config_path
|
||||
}
|
||||
}
|
||||
|
||||
provider "vault" {
|
||||
address = "https://vault.viktorbarzin.me"
|
||||
token = var.vault_root_token
|
||||
skip_child_token = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,6 @@ variable "kube_config_path" {
|
|||
default = "~/.kube/config"
|
||||
}
|
||||
|
||||
variable "vault_root_token" {
|
||||
type = string
|
||||
sensitive = true
|
||||
default = ""
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
config_path = var.kube_config_path
|
||||
}
|
||||
|
|
@ -31,6 +25,5 @@ provider "helm" {
|
|||
|
||||
provider "vault" {
|
||||
address = "https://vault.viktorbarzin.me"
|
||||
token = var.vault_root_token
|
||||
skip_child_token = true
|
||||
}
|
||||
|
|
|
|||
1303
stacks/vault/main.tf
1303
stacks/vault/main.tf
File diff suppressed because it is too large
Load diff
|
|
@ -13,9 +13,8 @@ remote_state {
|
|||
}
|
||||
}
|
||||
|
||||
# Load config.tfvars (plaintext) + secrets.auto.tfvars.json (SOPS-decrypted).
|
||||
# Run `scripts/tg` instead of raw `terragrunt` — it decrypts secrets first.
|
||||
# Falls back to terraform.tfvars if it exists (migration compatibility).
|
||||
# Load config.tfvars (plaintext) + terraform.tfvars (git-crypt encrypted, migration).
|
||||
# Secrets come from Vault KV — authenticate via `vault login -method=oidc`.
|
||||
terraform {
|
||||
extra_arguments "common_vars" {
|
||||
commands = get_terraform_commands_that_need_vars()
|
||||
|
|
@ -23,8 +22,7 @@ terraform {
|
|||
"${get_repo_root()}/config.tfvars"
|
||||
]
|
||||
optional_var_files = [
|
||||
"${get_repo_root()}/terraform.tfvars",
|
||||
"${get_repo_root()}/secrets.auto.tfvars.json"
|
||||
"${get_repo_root()}/terraform.tfvars"
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -34,12 +32,6 @@ terraform {
|
|||
"-var", "kube_config_path=${get_repo_root()}/config"
|
||||
]
|
||||
}
|
||||
|
||||
# Safety: fail if neither secrets source exists
|
||||
before_hook "check_secrets" {
|
||||
commands = ["apply", "plan", "destroy"]
|
||||
execute = ["sh", "-c", "test -f ${get_repo_root()}/secrets.auto.tfvars.json || test -f ${get_repo_root()}/terraform.tfvars || (echo 'ERROR: No secrets file found. Run scripts/tg instead of terragrunt directly.' && exit 1)"]
|
||||
}
|
||||
}
|
||||
|
||||
# Generate kubernetes + helm providers for K8s stacks.
|
||||
|
|
@ -62,12 +54,6 @@ variable "kube_config_path" {
|
|||
default = "~/.kube/config"
|
||||
}
|
||||
|
||||
variable "vault_root_token" {
|
||||
type = string
|
||||
sensitive = true
|
||||
default = ""
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
config_path = var.kube_config_path
|
||||
}
|
||||
|
|
@ -80,7 +66,6 @@ provider "helm" {
|
|||
|
||||
provider "vault" {
|
||||
address = "https://vault.viktorbarzin.me"
|
||||
token = var.vault_root_token
|
||||
skip_child_token = true
|
||||
}
|
||||
EOF
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue