From 21bb3036affbd8acaa65b24874666e3349d82005 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Thu, 19 Mar 2026 20:23:59 +0000 Subject: [PATCH] state(dbaas): update encrypted state --- config.tfvars | Bin 9860 -> 9875 bytes stacks/actualbudget/providers.tf | 7 - stacks/audiobookshelf/providers.tf | 7 - stacks/audiobookshelf/terragrunt.hcl | 4 - stacks/calibre/providers.tf | 7 - stacks/calibre/terragrunt.hcl | 4 - stacks/changedetection/providers.tf | 7 - stacks/changedetection/terragrunt.hcl | 4 - stacks/coturn/providers.tf | 7 - stacks/dbaas/modules/dbaas/main.tf | 14 +- stacks/echo/providers.tf | 7 - stacks/freedify/providers.tf | 7 - stacks/freshrss/providers.tf | 7 - stacks/freshrss/terragrunt.hcl | 4 - stacks/frigate/providers.tf | 7 - stacks/infra/.terraform.lock.hcl | 19 +++ stacks/navidrome/providers.tf | 7 - stacks/navidrome/terragrunt.hcl | 4 - stacks/novelapp/providers.tf | 7 - stacks/ntfy/providers.tf | 7 - stacks/openclaw/main.tf | 160 ++++++++++++++++++ stacks/owntracks/providers.tf | 7 - stacks/platform/.terraform.lock.hcl | 44 ----- stacks/platform/backend.tf | 2 +- stacks/platform/modules/crowdsec/values.yaml | 3 + .../modules/infra-maintenance/main.tf | 4 +- .../modules/kyverno/security-policies.tf | 91 ++++++++++ .../monitoring/prometheus_chart_values.tpl | 84 +++++++++ stacks/platform/modules/redis/main.tf | 7 +- stacks/privatebin/providers.tf | 7 - stacks/servarr/providers.tf | 7 - stacks/url/main.tf | 3 + stacks/vault/main.tf | 4 +- stacks/ytdlp/providers.tf | 7 - 34 files changed, 381 insertions(+), 186 deletions(-) diff --git a/config.tfvars b/config.tfvars index ce173138580eefaa6b426e69d6fcb3b2f445825d..804ef7b8029985093982ff226602c906006f54cc 100644 GIT binary patch literal 9875 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 /backup/dump_$now.sql + mysqldump --all-databases -u root --host mysql.dbaas.svc.cluster.local > /backup/dump_$now.sql # Rotate - delete last log file cd /backup @@ -1068,7 +1076,7 @@ resource "kubernetes_cron_job_v1" "postgresql-backup" { # Rotate - delete last log file cd /backup - find . -name "dump_*.sql" -type f -mtime +7 -delete # 7 day retention of backups + find . -name "dump_*.sql" -type f -mtime +14 -delete # 14 day retention of backups echo Done EOT ] diff --git a/stacks/echo/providers.tf b/stacks/echo/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/echo/providers.tf +++ b/stacks/echo/providers.tf @@ -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 } diff --git a/stacks/freedify/providers.tf b/stacks/freedify/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/freedify/providers.tf +++ b/stacks/freedify/providers.tf @@ -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 } diff --git a/stacks/freshrss/providers.tf b/stacks/freshrss/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/freshrss/providers.tf +++ b/stacks/freshrss/providers.tf @@ -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 } diff --git a/stacks/freshrss/terragrunt.hcl b/stacks/freshrss/terragrunt.hcl index f4c920ab..7aa411a2 100644 --- a/stacks/freshrss/terragrunt.hcl +++ b/stacks/freshrss/terragrunt.hcl @@ -7,7 +7,3 @@ dependency "platform" { skip_outputs = true } -dependency "vault" { - config_path = "../vault" - skip_outputs = true -} diff --git a/stacks/frigate/providers.tf b/stacks/frigate/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/frigate/providers.tf +++ b/stacks/frigate/providers.tf @@ -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 } diff --git a/stacks/infra/.terraform.lock.hcl b/stacks/infra/.terraform.lock.hcl index 28fba95b..44e446dc 100644 --- a/stacks/infra/.terraform.lock.hcl +++ b/stacks/infra/.terraform.lock.hcl @@ -20,6 +20,25 @@ provider "registry.terraform.io/hashicorp/null" { ] } +provider "registry.terraform.io/hashicorp/vault" { + version = "5.8.0" + hashes = [ + "h1:gk1cR+x1D+TEz05MKWmpp0p06+Trob5cN0eYU1vZGJs=", + "zh:18e79b42c8c155a5c541a45d54a6ccdeab23c404c239acdeed336a17cbfc2fd4", + "zh:241f50d1ea40030578034b4440e41676f1c9b5e8a2be5cd3afdb6e387914e0bf", + "zh:3c25da9ca98df3ae13fd08aa32a94ae4d15959cbb7165044b5f411d16317dfa1", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:85a2cf2e47fe7eab5c81ad5051668c09dcdfd6b6318420f42b91ea179dee8eb0", + "zh:861d09d5ab848704cea3bf6c6765288e60938634bf54ed3c29dd2d9a9dc8f7c9", + "zh:9822fc41def7ef6f9ffe6ef8d6aaf5014870961d12f5050b60997fa0c12699e1", + "zh:9b63003071d47299bd2cb85af0a7d9b33329a8152a5ed06cdd3ba46e839f0c43", + "zh:c3ce51f4ab24ac788a0a3eeb0ec16c04f38b74ad9997f86d4dca384ab1472a5a", + "zh:c53702a1e829226c63baac15af2f727a8979e00384e220862c8047fd2fcf6b38", + "zh:e68cebb3c78f0fed01a3e15ac54f09b4276418d7b7d12811bcc79568e58dcfc1", + "zh:f8d97c753305077ddcbd9e60780c5b06b173de2127943b9590d7e8decda4bd7a", + ] +} + provider "registry.terraform.io/telmate/proxmox" { version = "3.0.2-rc07" constraints = "3.0.2-rc07" diff --git a/stacks/navidrome/providers.tf b/stacks/navidrome/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/navidrome/providers.tf +++ b/stacks/navidrome/providers.tf @@ -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 } diff --git a/stacks/navidrome/terragrunt.hcl b/stacks/navidrome/terragrunt.hcl index f4c920ab..7aa411a2 100644 --- a/stacks/navidrome/terragrunt.hcl +++ b/stacks/navidrome/terragrunt.hcl @@ -7,7 +7,3 @@ dependency "platform" { skip_outputs = true } -dependency "vault" { - config_path = "../vault" - skip_outputs = true -} diff --git a/stacks/novelapp/providers.tf b/stacks/novelapp/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/novelapp/providers.tf +++ b/stacks/novelapp/providers.tf @@ -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 } diff --git a/stacks/ntfy/providers.tf b/stacks/ntfy/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/ntfy/providers.tf +++ b/stacks/ntfy/providers.tf @@ -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 } diff --git a/stacks/openclaw/main.tf b/stacks/openclaw/main.tf index 9f1f019d..362505a2 100644 --- a/stacks/openclaw/main.tf +++ b/stacks/openclaw/main.tf @@ -992,3 +992,163 @@ resource "kubernetes_cron_job_v1" "task_processor" { } } } + +# --- OpenLobster: Multi-user Telegram AI assistant (trial) --- + +module "nfs_openlobster_data" { + source = "../../modules/kubernetes/nfs_volume" + name = "openlobster-data" + namespace = kubernetes_namespace.openclaw.metadata[0].name + nfs_server = var.nfs_server + nfs_path = "/mnt/main/openclaw/openlobster-data" +} + +resource "random_password" "openlobster_graphql_token" { + length = 32 + special = false +} + +resource "kubernetes_deployment" "openlobster" { + metadata { + name = "openlobster" + namespace = kubernetes_namespace.openclaw.metadata[0].name + labels = { + app = "openlobster" + tier = local.tiers.aux + } + } + spec { + strategy { + type = "Recreate" + } + replicas = 0 + selector { + match_labels = { + app = "openlobster" + } + } + template { + metadata { + labels = { + app = "openlobster" + } + } + spec { + # node4 has corrupted containerd content store — avoid it + affinity { + node_affinity { + required_during_scheduling_ignored_during_execution { + node_selector_term { + match_expressions { + key = "kubernetes.io/hostname" + operator = "NotIn" + values = ["k8s-node4"] + } + } + } + } + } + container { + name = "openlobster" + image = "ghcr.io/neirth/openlobster/openlobster:latest" + port { + container_port = 8080 + } + env { + name = "OPENLOBSTER_GRAPHQL_AUTH_TOKEN" + value = random_password.openlobster_graphql_token.result + } + env { + name = "OPENLOBSTER_PROVIDERS_ANTHROPIC_API_KEY" + value_from { + secret_key_ref { + name = "openclaw-secrets" + key = "anthropic_api_key" + } + } + } + env { + name = "OPENLOBSTER_PROVIDERS_ANTHROPIC_MODEL" + value = "claude-sonnet-4-20250514" + } + env { + name = "OPENLOBSTER_CHANNELS_TELEGRAM_TOKEN" + value_from { + secret_key_ref { + name = "openclaw-secrets" + key = "telegram_bot_token" + } + } + } + env { + name = "OPENLOBSTER_DATABASE_DRIVER" + value = "sqlite" + } + env { + name = "OPENLOBSTER_DATABASE_DSN" + value = "/app/data/openlobster.db" + } + env { + name = "OPENLOBSTER_AGENT_NAME" + value = "Lobster" + } + env { + name = "OPENLOBSTER_MEMORY_BACKEND" + value = "file" + } + volume_mount { + name = "openlobster-data" + mount_path = "/app/data" + } + resources { + requests = { + cpu = "10m" + memory = "64Mi" + } + limits = { + memory = "256Mi" + } + } + } + volume { + name = "openlobster-data" + persistent_volume_claim { + claim_name = module.nfs_openlobster_data.claim_name + } + } + } + } + } + lifecycle { + ignore_changes = [spec[0].template[0].spec[0].dns_config] + } +} + +resource "kubernetes_service" "openlobster" { + metadata { + name = "openlobster" + namespace = kubernetes_namespace.openclaw.metadata[0].name + labels = { + app = "openlobster" + } + } + spec { + selector = { + app = "openlobster" + } + port { + port = 80 + target_port = 8080 + } + } +} + +module "openlobster_ingress" { + source = "../../modules/kubernetes/ingress_factory" + namespace = kubernetes_namespace.openclaw.metadata[0].name + name = "openlobster" + tls_secret_name = var.tls_secret_name + host = "openlobster" + port = 80 + protected = true +} diff --git a/stacks/owntracks/providers.tf b/stacks/owntracks/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/owntracks/providers.tf +++ b/stacks/owntracks/providers.tf @@ -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 } diff --git a/stacks/platform/.terraform.lock.hcl b/stacks/platform/.terraform.lock.hcl index 9bb9232c..eca3dfe9 100644 --- a/stacks/platform/.terraform.lock.hcl +++ b/stacks/platform/.terraform.lock.hcl @@ -1,30 +1,6 @@ # This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. -provider "registry.terraform.io/cloudflare/cloudflare" { - version = "4.52.5" - constraints = "~> 4.0" - hashes = [ - "h1:+rfzF+16ZcWZWnTyW/p1HHTzYbPKX8Zt2nIFtR/+f+E=", - "h1:18bXaaOSq8MWKuMxo/4y7EB7/i7G90y5QsKHZRmkoDo=", - "zh:1a3400cb38863b2585968d1876706bcfc67a148e1318a1d325c6c7704adc999b", - "zh:4c5062cb9e9da1676f06ae92b8370186d98976cc4c7030d3cd76df12af54282a", - "zh:52110f493b5f0587ef77a1cfd1a67001fd4c617b14c6502d732ab47352bdc2f7", - "zh:5aa536f9eaeb43823aaf2aa80e7d39b25ef2b383405ed034aa16a28b446a9238", - "zh:5cc39459a1c6be8a918f17054e4fbba573825ed5597dcada588fe99614d98a5b", - "zh:629ae6a7ba298815131da826474d199312d21cec53a4d5ded4fa56a692e6f072", - "zh:719cc7c75dc1d3eb30c22ff5102a017996d9788b948078c7e1c5b3446aeca661", - "zh:8698635a3ca04383c1e93b21d6963346bdae54d27177a48e4b1435b7f731731c", - "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", - "zh:8a9993f1dcadf1dd6ca43b23348abe374605d29945a2fafc07fb3457644e6a54", - "zh:b1b9a1e6bcc24d5863a664a411d2dc906373ae7a2399d2d65548ce7377057852", - "zh:b270184cdeec277218e84b94cb136fead753da717f9b9dc378e51907f3f00bb0", - "zh:dff2bc10071210181726ce270f954995fe42c696e61e2e8f874021fed02521e5", - "zh:e8e87b40b6a87dc097b0fdc20d3f725cec0d82abc9cc3755c1f89f8f6e8b0036", - "zh:ee964a6573d399a5dd22ce328fb38ca1207797a02248f14b2e4913ee390e7803", - ] -} - provider "registry.terraform.io/hashicorp/helm" { version = "3.1.1" hashes = [ @@ -65,26 +41,6 @@ provider "registry.terraform.io/hashicorp/kubernetes" { ] } -provider "registry.terraform.io/hashicorp/null" { - version = "3.2.4" - hashes = [ - "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", - "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", - "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", - "zh:7b9c7b16f118fbc2b05a983817b8ce2f86df125857966ad356353baf4bff5c0a", - "zh:85e33ab43e0e1726e5f97a874b8e24820b6565ff8076523cc2922ba671492991", - "zh:9d32ac3619cfc93eb3c4f423492a8e0f79db05fec58e449dee9b2d5873d5f69f", - "zh:9e15c3c9dd8e0d1e3731841d44c34571b6c97f5b95e8296a45318b94e5287a6e", - "zh:b4c2ab35d1b7696c30b64bf2c0f3a62329107bd1a9121ce70683dec58af19615", - "zh:c43723e8cc65bcdf5e0c92581dcbbdcbdcf18b8d2037406a5f2033b1e22de442", - "zh:ceb5495d9c31bfb299d246ab333f08c7fb0d67a4f82681fbf47f2a21c3e11ab5", - "zh:e171026b3659305c558d9804062762d168f50ba02b88b231d20ec99578a6233f", - "zh:ed0fe2acdb61330b01841fa790be00ec6beaac91d41f311fb8254f74eb6a711f", - ] -} - provider "registry.terraform.io/hashicorp/vault" { version = "4.8.0" constraints = "~> 4.0" diff --git a/stacks/platform/backend.tf b/stacks/platform/backend.tf index 6d424f69..f9db2d0d 100644 --- a/stacks/platform/backend.tf +++ b/stacks/platform/backend.tf @@ -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" } } diff --git a/stacks/platform/modules/crowdsec/values.yaml b/stacks/platform/modules/crowdsec/values.yaml index fcfbb3af..fc491ac4 100644 --- a/stacks/platform/modules/crowdsec/values.yaml +++ b/stacks/platform/modules/crowdsec/values.yaml @@ -49,6 +49,9 @@ agent: - name: whitelist configMap: name: crowdsec-whitelist +podAnnotations: + dependency.kyverno.io/wait-for: "mysql.dbaas:3306" + lapi: resources: requests: diff --git a/stacks/platform/modules/infra-maintenance/main.tf b/stacks/platform/modules/infra-maintenance/main.tf index abf50453..d69a8f14 100644 --- a/stacks/platform/modules/infra-maintenance/main.tf +++ b/stacks/platform/modules/infra-maintenance/main.tf @@ -101,8 +101,8 @@ resource "kubernetes_cron_job_v1" "backup-etcd" { container { name = "backup-etcd" image = "registry.k8s.io/etcd:3.5.21-0" - command = ["etcdctl"] - args = ["--endpoints=https://127.0.0.1:2379", "--cacert=/etc/kubernetes/pki/etcd/ca.crt", "--cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt", "--key=/etc/kubernetes/pki/etcd/healthcheck-client.key", "snapshot", "save", "/backup/etcd-snapshot-latest.db"] + command = ["/bin/sh", "-c"] + args = ["ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key snapshot save /backup/etcd-snapshot-$(date +%Y%m%d-%H%M%S).db"] env { name = "ETCDCTL_API" value = "3" diff --git a/stacks/platform/modules/kyverno/security-policies.tf b/stacks/platform/modules/kyverno/security-policies.tf index 1f1c83a8..00bcf3a6 100644 --- a/stacks/platform/modules/kyverno/security-policies.tf +++ b/stacks/platform/modules/kyverno/security-policies.tf @@ -160,6 +160,97 @@ resource "kubernetes_manifest" "policy_restrict_capabilities" { depends_on = [helm_release.kyverno] } +# ============================================================================= +# Image Pull Policy Governance +# ============================================================================= +# Mutate imagePullPolicy to IfNotPresent for all containers with pinned tags +# (non-:latest). This prevents pods from getting stuck in ImagePullBackOff +# when the pull-through cache at 10.0.20.10 has transient failures. +# For :latest or untagged images, set to Always so stale images don't persist. + +resource "kubernetes_manifest" "policy_set_image_pull_policy" { + manifest = { + apiVersion = "kyverno.io/v1" + kind = "ClusterPolicy" + metadata = { + name = "set-image-pull-policy" + annotations = { + "policies.kyverno.io/title" = "Set Image Pull Policy" + "policies.kyverno.io/category" = "Best Practices" + "policies.kyverno.io/severity" = "medium" + "policies.kyverno.io/description" = "Set imagePullPolicy to IfNotPresent for pinned tags and Always for :latest to prevent ImagePullBackOff from transient cache failures." + } + } + spec = { + background = false + rules = [ + { + name = "set-ifnotpresent-for-pinned-tags" + match = { + any = [{ + resources = { + kinds = ["Pod"] + } + }] + } + mutate = { + foreach = [{ + list = "request.object.spec.containers" + preconditions = { + all = [{ + key = "{{ ends_with(element.image, ':latest') || !contains(element.image, ':') }}" + operator = "Equals" + value = false + }] + } + patchStrategicMerge = { + spec = { + containers = [{ + name = "{{ element.name }}" + imagePullPolicy = "IfNotPresent" + }] + } + } + }] + } + }, + { + name = "set-always-for-latest" + match = { + any = [{ + resources = { + kinds = ["Pod"] + } + }] + } + mutate = { + foreach = [{ + list = "request.object.spec.containers" + preconditions = { + all = [{ + key = "{{ ends_with(element.image, ':latest') || !contains(element.image, ':') }}" + operator = "Equals" + value = true + }] + } + patchStrategicMerge = { + spec = { + containers = [{ + name = "{{ element.name }}" + imagePullPolicy = "Always" + }] + } + } + }] + } + } + ] + } + } + + depends_on = [helm_release.kyverno] +} + resource "kubernetes_manifest" "policy_require_trusted_registries" { manifest = { apiVersion = "kyverno.io/v1" diff --git a/stacks/platform/modules/monitoring/prometheus_chart_values.tpl b/stacks/platform/modules/monitoring/prometheus_chart_values.tpl index c4d5070b..970d943e 100755 --- a/stacks/platform/modules/monitoring/prometheus_chart_values.tpl +++ b/stacks/platform/modules/monitoring/prometheus_chart_values.tpl @@ -500,6 +500,90 @@ serverFiles: severity: critical annotations: summary: "etcd backup CronJob has never completed successfully" + - alert: PostgreSQLBackupStale + expr: (time() - kube_cronjob_status_last_successful_time{cronjob="postgresql-backup", namespace="dbaas"}) > 129600 + for: 30m + labels: + severity: critical + annotations: + summary: "PostgreSQL backup is {{ $value | humanizeDuration }} old (threshold: 36h)" + - alert: PostgreSQLBackupNeverSucceeded + expr: kube_cronjob_status_last_successful_time{cronjob="postgresql-backup", namespace="dbaas"} == 0 + for: 1h + labels: + severity: critical + annotations: + summary: "PostgreSQL backup CronJob has never completed successfully" + - alert: MySQLBackupStale + expr: (time() - kube_cronjob_status_last_successful_time{cronjob="mysql-backup", namespace="dbaas"}) > 129600 + for: 30m + labels: + severity: critical + annotations: + summary: "MySQL backup is {{ $value | humanizeDuration }} old (threshold: 36h)" + - alert: MySQLBackupNeverSucceeded + expr: kube_cronjob_status_last_successful_time{cronjob="mysql-backup", namespace="dbaas"} == 0 + for: 1h + labels: + severity: critical + annotations: + summary: "MySQL backup CronJob has never completed successfully" + - alert: VaultBackupStale + expr: (time() - kube_cronjob_status_last_successful_time{cronjob="vault-raft-backup", namespace="vault"}) > 129600 + for: 30m + labels: + severity: critical + annotations: + summary: "Vault backup is {{ $value | humanizeDuration }} old (threshold: 36h)" + - alert: VaultBackupNeverSucceeded + expr: kube_cronjob_status_last_successful_time{cronjob="vault-raft-backup", namespace="vault"} == 0 + for: 1h + labels: + severity: critical + annotations: + summary: "Vault backup CronJob has never completed successfully" + - alert: VaultwardenBackupStale + expr: (time() - kube_cronjob_status_last_successful_time{cronjob="vaultwarden-backup", namespace="vaultwarden"}) > 129600 + for: 30m + labels: + severity: critical + annotations: + summary: "Vaultwarden backup is {{ $value | humanizeDuration }} old (threshold: 36h)" + - alert: VaultwardenBackupNeverSucceeded + expr: kube_cronjob_status_last_successful_time{cronjob="vaultwarden-backup", namespace="vaultwarden"} == 0 + for: 1h + labels: + severity: critical + annotations: + summary: "Vaultwarden backup CronJob has never completed successfully" + - alert: RedisBackupStale + expr: (time() - kube_cronjob_status_last_successful_time{cronjob="redis-backup", namespace="redis"}) > 14400 + for: 30m + labels: + severity: critical + annotations: + summary: "Redis backup is {{ $value | humanizeDuration }} old (threshold: 4h)" + - alert: RedisBackupNeverSucceeded + expr: kube_cronjob_status_last_successful_time{cronjob="redis-backup", namespace="redis"} == 0 + for: 1h + labels: + severity: critical + annotations: + summary: "Redis backup CronJob has never completed successfully" + - alert: CSIDriverCrashLoop + expr: kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff", namespace=~"nfs-csi|iscsi-csi"} > 0 + for: 10m + labels: + severity: critical + annotations: + summary: "CSI driver CrashLoopBackOff in {{ $labels.namespace }}/{{ $labels.pod }} — storage-layer failure risk" + - alert: BackupCronJobFailed + expr: kube_job_status_failed{job_name=~".*backup.*"} > 0 + for: 15m + labels: + severity: warning + annotations: + summary: "Backup job failed: {{ $labels.namespace }}/{{ $labels.job_name }}" - alert: NewTailscaleClient expr: irate(headscale_machine_registrations_total{action="reauth"}[5m]) > 0 for: 5m diff --git a/stacks/platform/modules/redis/main.tf b/stacks/platform/modules/redis/main.tf index 5f5c5966..1a89deea 100644 --- a/stacks/platform/modules/redis/main.tf +++ b/stacks/platform/modules/redis/main.tf @@ -283,12 +283,15 @@ resource "kubernetes_cron_job_v1" "redis-backup" { image = "redis:7-alpine" command = ["/bin/sh", "-c", <<-EOT set -eux + TIMESTAMP=$(date +%Y%m%d-%H%M) # Trigger a fresh RDB save on the master redis-cli -h redis.redis BGSAVE sleep 5 # Copy the RDB via redis-cli --rdb - redis-cli -h redis.redis --rdb /backup/dump.rdb - echo "Backup complete: $(ls -lh /backup/dump.rdb)" + redis-cli -h redis.redis --rdb /backup/redis-$TIMESTAMP.rdb + # Rotate — 7-day retention + find /backup -name 'redis-*.rdb' -type f -mtime +7 -delete + echo "Backup complete: redis-$TIMESTAMP.rdb" EOT ] volume_mount { diff --git a/stacks/privatebin/providers.tf b/stacks/privatebin/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/privatebin/providers.tf +++ b/stacks/privatebin/providers.tf @@ -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 } diff --git a/stacks/servarr/providers.tf b/stacks/servarr/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/servarr/providers.tf +++ b/stacks/servarr/providers.tf @@ -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 } diff --git a/stacks/url/main.tf b/stacks/url/main.tf index d39d07a8..9dba0b24 100644 --- a/stacks/url/main.tf +++ b/stacks/url/main.tf @@ -170,6 +170,9 @@ resource "kubernetes_deployment" "shlink" { labels = { run = "shlink" } + annotations = { + "dependency.kyverno.io/wait-for" = "mysql.dbaas:3306" + } } spec { container { diff --git a/stacks/vault/main.tf b/stacks/vault/main.tf index 8959be73..8d527e52 100644 --- a/stacks/vault/main.tf +++ b/stacks/vault/main.tf @@ -163,8 +163,8 @@ resource "vault_jwt_auth_backend_role" "default" { backend = vault_jwt_auth_backend.oidc.path role_name = "default" token_policies = ["default"] - token_ttl = 3600 - token_max_ttl = 86400 + token_ttl = 604800 + token_max_ttl = 604800 user_claim = "email" groups_claim = "groups" role_type = "oidc" diff --git a/stacks/ytdlp/providers.tf b/stacks/ytdlp/providers.tf index f4845cc8..860c9eba 100644 --- a/stacks/ytdlp/providers.tf +++ b/stacks/ytdlp/providers.tf @@ -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 }