diff --git a/bootstrap/inventory/prod/group_vars/k8s_cluster/k8s-cluster.yml b/bootstrap/inventory/prod/group_vars/k8s_cluster/k8s-cluster.yml index e116d17..90d5bfc 100644 --- a/bootstrap/inventory/prod/group_vars/k8s_cluster/k8s-cluster.yml +++ b/bootstrap/inventory/prod/group_vars/k8s_cluster/k8s-cluster.yml @@ -122,6 +122,9 @@ kube_proxy_mode: iptables # Moritz: changed to iptables for tegra #kube_proxy_mode: ipvs +# Expose kube-proxy metrics on all interfaces so Prometheus can scrape port 10249 +kube_proxy_metrics_bind_address: "0.0.0.0:10249" + # configure arp_ignore and arp_announce to avoid answering ARP queries from kube-ipvs0 interface # must be set to true for MetalLB to work kube_proxy_strict_arp: false diff --git a/k8s/README.md b/k8s/README.md index 0ba2a42..c14e2e6 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -121,19 +121,24 @@ Backup tool. See chart [README](https://github.com/vmware-tanzu/helm-charts/blob ```sh helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts helm repo update -helm upgrade --install --create-namespace --namespace velero -f ./velero/velero.secret.yaml velero vmware-tanzu/velero --version 5.3.0 -kubectl create secret generic rclone-config --from-file=./velero/rclone.secret -kubectl apply -f velero/dropbox_sync.yml -# # +# Apply CRDs first (required on upgrades across major versions) +helm show crds vmware-tanzu/velero --version 12.1.0 | kubectl apply -f - +helm upgrade --install --create-namespace --namespace velero -f ./velero/velero.secret.yaml velero vmware-tanzu/velero --version 12.1.0 +# Secrets for rclone (minio + gdrive) +kubectl create secret generic rclone-config --from-file=./velero/rclone.secret -n velero +kubectl create secret generic gdrive-sa-key --from-file=gdrive_sa.json.secret=./velero/gdrive_sa.json.secret -n velero +# Deploy GDrive sync cronjob +kubectl apply -f velero/gdrive_sync.yml +# Teardown helm delete velero -n velero kubectl delete ns velero ``` -A manual backup may be created executing the following command. **Note: Keep backuped namespaces in sync with config from helm chart!!!** +A manual backup may be created executing the following command. **Note: Keep backed-up namespaces in sync with config from helm chart!!!** ```sh DATE=$( date +%Y%m%d ) -velero backup create $DATE --include-namespaces datalab,development,nextcloud,tt-rss,mailu --wait +velero backup create $DATE --include-namespaces coder,home-assistant,n8n,influxdb --wait ``` ## coder diff --git a/k8s/cert-manager/production-issuer.yaml b/k8s/cert-manager/production-issuer.yaml index b9acefc..025f6c6 100644 --- a/k8s/cert-manager/production-issuer.yaml +++ b/k8s/cert-manager/production-issuer.yaml @@ -18,4 +18,4 @@ spec: solvers: - http01: ingress: - class: nginx + ingressClassName: traefik diff --git a/k8s/cert-manager/staging-issuer.yaml b/k8s/cert-manager/staging-issuer.yaml index 51f74ed..0367166 100644 --- a/k8s/cert-manager/staging-issuer.yaml +++ b/k8s/cert-manager/staging-issuer.yaml @@ -18,4 +18,4 @@ spec: solvers: - http01: ingress: - class: nginx + ingressClassName: traefik diff --git a/k8s/home-assistant/home-assistant.secret.yaml b/k8s/home-assistant/home-assistant.secret.yaml index 8bdb03e..55b86d7 100644 Binary files a/k8s/home-assistant/home-assistant.secret.yaml and b/k8s/home-assistant/home-assistant.secret.yaml differ diff --git a/k8s/home-assistant/tmp_long_lived_token.secret.yml b/k8s/home-assistant/tmp_long_lived_token.secret.yml new file mode 100644 index 0000000..36ec8b1 --- /dev/null +++ b/k8s/home-assistant/tmp_long_lived_token.secret.yml @@ -0,0 +1,2 @@ +# this token has been generated to enable AI to access HASS +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2NDMyZTI1MDIzZjU0ZmFiYTU3OTc0ODYyMzg3M2ExZSIsImlhdCI6MTc4MjczMTY4NiwiZXhwIjoyMDk4MDkxNjg2fQ.u8kFHoYL2kdhVenfe3BiWcNkN_en3yn91MRGSVJvbmw diff --git a/k8s/mailu/backup.secret.yml b/k8s/mailu/backup.secret.yml deleted file mode 100644 index 529f7ac..0000000 --- a/k8s/mailu/backup.secret.yml +++ /dev/null @@ -1,45 +0,0 @@ -# kind: ConfigMap -# metadata: -# creationTimestamp: null -# name: rclone-dropbox-config -# namespace: mailu -# apiVersion: v1 -# data: -# rclone.conf: | -# [dropbox] -# type = dropbox -# token = {"access_token":"17hvEArIh3cAAAAAAAGTXUfwkGdz8EC_rDcEseLmSRltQoUz_AVceuUewx0sGMQ1","token_type":"bearer","expiry":"0001-01-01T00:00:00Z"} -# --- -# apiVersion: batch/v1beta1 -# kind: CronJob -# metadata: -# name: backup-mailu -# namespace: mailu -# spec: -# schedule: "30 4 * * *" -# jobTemplate: -# spec: -# template: -# spec: -# containers: -# - name: backup-mailu -# image: iptizer/swiss -# volumeMounts: -# - name: rclone-dropbox-config -# mountPath: /rclone.conf -# subPath: "rclone.conf" -# - mountPath: /data/ -# name: data -# command: -# - "/bin/bash" -# - "-c" -# args: -# - "cd / && tar zcvf - /data/ | /usr/bin/rclone --config /rclone.conf -v rcat dropbox:server_backup/$( /bin/expr $( date +%m ) % 3 )_$( /bin/expr $( date +%j ) % 3 )_mailu.tar.gz" -# volumes: -# - name: rclone-dropbox-config -# configMap: -# name: rclone-dropbox-config -# - name: data -# persistentVolumeClaim: -# claimName: mailu-storage -# restartPolicy: Never diff --git a/k8s/mailu/mailu.secret.yml b/k8s/mailu/mailu.secret.yml deleted file mode 100644 index df15970..0000000 --- a/k8s/mailu/mailu.secret.yml +++ /dev/null @@ -1,82 +0,0 @@ -# DO NOT USE MASTER!!!! -#mailuVersion: master -# DO NOT USE MASTER!!! - -hostnames: - - mail.moritzgraf.de -domain: moritzgraf.de -secretKey: fa5faeD9aegietaesahbiequ5Pe9au -subnet: 10.233.0.0/16 - -ingress: - annotations: - kubernetes.io/ingress.class: nginx - -clamav: - enabled: false -front: - resources: - requests: - memory: 10Mi - cpu: 10m - limits: - memory: 200Mi - cpu: 200m -admin: - resources: - requests: - memory: 20Mi - cpu: 50m - limits: - memory: 500Mi - cpu: 500m - -dovecot: - resources: - requests: - memory: 50Mi - cpu: 10m - limits: - memory: 500Mi - cpu: 500m -postfix: - resources: - requests: - memory: 1Gi - cpu: 10m - limits: - memory: 2Gi - cpu: 500m - -redis: - resources: - requests: - memory: 20Mi - cpu: 10m - limits: - memory: 300Mi - cpu: 200m -roundcube: - enabled: true - logLevel: INFO - resources: - requests: - memory: 10Mi - cpu: 10m - limits: - memory: 200Mi - cpu: 200m -rspamd: - resources: - requests: - memory: 10Mi - cpu: 10m - limits: - memory: 2000Mi - cpu: 600m -certmanager: - issuerType: ClusterIssuer - issuerName: "letsencrypt-prod" - apiVersion: cert-manager.io/v1 -persistence: - storageClass: openebs-hostpath \ No newline at end of file diff --git a/k8s/mailu/restore.yaml b/k8s/mailu/restore.yaml deleted file mode 100644 index c2b4e37..0000000 --- a/k8s/mailu/restore.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - creationTimestamp: null - labels: - run: restore - name: restore -spec: - containers: - - image: iptizer/swiss - name: restore - resources: {} - volumeMounts: - - mountPath: /data/ - name: data - command: - - "sleep" - - "3600" - dnsPolicy: ClusterFirst - restartPolicy: Never - volumes: - - name: data - persistentVolumeClaim: - claimName: mailu-storage -status: {} diff --git a/k8s/minio/minio.secret.yaml b/k8s/minio/minio.secret.yaml index e11e6a0..ebcb113 100644 Binary files a/k8s/minio/minio.secret.yaml and b/k8s/minio/minio.secret.yaml differ diff --git a/k8s/monitoring/AGENTS.md b/k8s/monitoring/AGENTS.md new file mode 100644 index 0000000..c3c4983 --- /dev/null +++ b/k8s/monitoring/AGENTS.md @@ -0,0 +1,164 @@ +# AGENTS.md — Monitoring Folder Guide for AI Agents + +## Overview + +This folder manages the **kube-prometheus-stack** deployment and **Grafana dashboards as code** for the `haumdaucher` Kubernetes cluster. The monitoring stack runs in the `monitoring` namespace. + +## Folder Structure + +``` +monitoring/ +├── AGENTS.md ← You are here +├── README.md ← Human-oriented deployment guide +├── DASHBOARD_CREATION.md ← How to create/update dashboards (read this!) +├── prometheus-operator.secret.yml ← Helm values for kube-prometheus-stack +├── alertmanagerconfig.secret.yaml ← Alertmanager config (Telegram alerts) +├── servicemonitor.secret.yml ← ServiceMonitor examples (commented out) +├── tankerkoenig.yml ← Tankerkoenig fuel price exporter +├── dashboards/ ← Grafana dashboards as ConfigMaps +│ ├── grafana-dashboard-home-climate.yaml +│ ├── grafana-dashboard-energy-monitor.yaml +│ ├── grafana-dashboard-heating-gas.yaml +│ └── grafana-dashboard-outdoor-weather.yaml +└── scripts/ ← Discovery & helper scripts + ├── discover-influxdb.sh ← Query InfluxDB schema + └── discover-home-assistant.sh ← Query Home Assistant entities +``` + +## Key Infrastructure Context + +### Namespaces & Services + +| Namespace | Service | Purpose | +|-----------|---------|---------| +| `monitoring` | kube-prometheus-stack | Prometheus, Alertmanager, Grafana | +| `influxdb` | InfluxDB2 | Time-series storage for Home Assistant sensor data | +| `home-assistant` | Home Assistant | Smart home hub, writes sensor data to InfluxDB | + +### Data Flow + +``` +Home Assistant sensors → InfluxDB (bucket: default, org: influxdata) + ↓ + Grafana (Flux queries via datasource) +``` + +### Grafana Datasources + +| Name | UID | Type | URL | +|------|-----|------|-----| +| InfluxDB Home Assistant | `P2AB959DC95E5519F` | influxdb (Flux) | `http://influxdb-influxdb2.influxdb.svc.cluster.local:80` | +| InfluxDB Home Assistant InfluxQL | `P86455D1023ECC470` | influxdb (InfluxQL) | same | +| Prometheus | `prometheus` | prometheus | internal | + +> **⚠️ IMPORTANT**: The datasource UIDs above are the **current** values. If the Grafana deployment is recreated, these UIDs will change. Always re-discover UIDs via `kubectl -n monitoring exec deploy/prometheus-operator-grafana -c grafana -- curl -s -u "admin:" http://localhost:3000/api/datasources` before creating new dashboards. + +### Grafana Admin Credentials + +- URL: `https://grafana.haumdaucher.de` +- User: `admin` +- Password: stored in `prometheus-operator.secret.yml` under `grafana.adminPassword` + +### Home Assistant API + +- URL: `https://hass.moritzgraf.de` +- Token: stored in `../home-assistant/tmp_long_lived_token.secret.yml` + +### InfluxDB API + +- Internal URL: `http://influxdb-influxdb2.influxdb.svc.cluster.local:80` +- Org: `influxdata` +- Bucket: `default` +- Token: stored in `prometheus-operator.secret.yml` under `grafana.additionalDataSources[0].secureJsonData.token` + +## Dashboard Architecture + +Dashboards are managed as **Kubernetes ConfigMaps** with the label `grafana_dashboard: "1"`. The kube-prometheus-stack's **Grafana Dashboard Sidecar** (`grafana-sc-dashboard` container) watches for these ConfigMaps and auto-loads them into Grafana. + +### Key Design Decisions + +1. **One file per dashboard** — Each ConfigMap YAML contains the dashboard JSON embedded directly in `data`. No separate JSON files (avoids duplication). +2. **Strict GitOps** — Dashboards are `editable: false` in Grafana UI. All changes must be made to the YAML files and re-applied. +3. **Namespace-scoped** — Sidecar only watches the `monitoring` namespace (`searchNamespace: monitoring`). +4. **Folder annotation** — Use `grafana_dashboard_folder` annotation to organize dashboards in Grafana folders. + +### ConfigMap Template + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboard- + namespace: monitoring + labels: + grafana_dashboard: "1" + annotations: + grafana_dashboard_folder: "🏠 Home" +data: + .json: | + { + "uid": "", + "title": "", + ... + } +``` + +## InfluxDB Data Schema + +Home Assistant writes sensor data to InfluxDB with this structure: + +- **Measurement name** = unit of measurement (e.g., `°C`, `%`, `W`, `kWh`, `m³`, `hPa`, `km/h`, `mm/h`) +- **Fields**: `value` (numeric), plus metadata fields (`friendly_name_str`, `device_class_str`, `id_str`, etc.) +- **Tags**: `entity_id` (e.g., `home_wohnzimmer_temperature` — **NOTE: no `sensor.` prefix!**), `domain` (e.g., `sensor`) + +### Flux Query Pattern (MUST follow this exactly) + +**Exact match on entity_id:** +```flux +from(bucket: "default") + |> range(start: v.timeRangeStart, stop: v.timeRangeStop) + |> filter(fn: (r) => r["_measurement"] == "°C") + |> filter(fn: (r) => r["_field"] == "value") + |> filter(fn: (r) => r.entity_id == "home_wandthermostat_bad_temperature") + |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) + |> yield(name: "mean") +``` + +**Regex match on entity_id** (use `=~` operator with `/pattern/`): +```flux +from(bucket: "default") + |> range(start: v.timeRangeStart, stop: v.timeRangeStop) + |> filter(fn: (r) => r["_measurement"] == "°C") + |> filter(fn: (r) => r["_field"] == "value") + |> filter(fn: (r) => r.entity_id =~ /^home_/) + |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) + |> yield(name: "mean") +``` + +**Critical rules:** +- Always use bracket notation: `r["_measurement"]`, `r["_field"]` (fields starting with `_`) +- Always use dynamic time: `range(start: v.timeRangeStart, stop: v.timeRangeStop)` and `aggregateWindow(every: v.windowPeriod, ...)` +- Always end with `|> yield(name: "mean")` +- **entity_id in InfluxDB does NOT have the `sensor.` prefix** — use `home_wohnzimmer_temperature`, NOT `sensor.home_wohnzimmer_temperature` +- For "current value" stat panels, use `range(start: -15m)` with `last()` instead of aggregateWindow +- Regex operator is `=~` with `/pattern/` syntax (e.g., `=~ /^home_/` matches all entities starting with `home_`) + +## Common Pitfalls (Lessons Learned) + +1. **Entity IDs have no `sensor.` prefix in InfluxDB** — HA stores domain separately. Use `home_wohnzimmer_temperature`, not `sensor.home_wohnzimmer_temperature`. This is the #1 cause of "no data". +2. **Dashboard JSON must NOT be wrapped in `"dashboard"` key** — Grafana file provisioning expects top-level properties (`uid`, `title`, `panels`, etc.). The `"dashboard"` wrapper is only used in the HTTP API. +3. **Datasource reference must use actual UID** — Discover via `kubectl exec` + Grafana API. Current UID: `P2AB959DC95E5519F`. +4. **Don't add `uid` to helm datasource config** — Adding `uid` to existing datasources in `additionalDataSources` causes Grafana provisioning to fail with "data source not found". Let UIDs be auto-generated. +5. **Always use bracket notation for `_measurement` and `_field`** — Use `r["_measurement"]` and `r["_field"]`, not dot notation. Fields starting with underscore may not resolve with dot notation in Flux. +6. **Always use Grafana time variables** — Never hardcode `range(start: -24h)` or `aggregateWindow(every: 5m)`. Always use `v.timeRangeStart`, `v.timeRangeStop`, `v.windowPeriod`. +7. **Always add `yield(name: "mean")`** — Required for Grafana to properly parse Flux results. +8. **InfluxDB has multiple fields per measurement** — Always filter `r["_field"] == "value"` to get numeric data. +9. **Sidecar container name is `grafana-sc-dashboard`** (singular), not `grafana-sc-dashboards`. +10. **Use Wandthermostat entities for temperature/humidity** — Query HA to filter by device type. Wandthermostat entities have `wandthermostat` or `thermostat` in their entity_id. + +## Related Files Outside This Folder + +- `../home-assistant/home-assistant.secret.yaml` — HA helm values (InfluxDB integration config) +- `../home-assistant/tmp_long_lived_token.secret.yml` — HA API token for discovery +- `../influxdb/influxdb2.secret.yml` — InfluxDB helm values +- `../../kochbuch/plans/grafana-dashboards-as-code.md` — Original architecture plan \ No newline at end of file diff --git a/k8s/monitoring/DASHBOARD_CREATION.md b/k8s/monitoring/DASHBOARD_CREATION.md new file mode 100644 index 0000000..4377b33 --- /dev/null +++ b/k8s/monitoring/DASHBOARD_CREATION.md @@ -0,0 +1,326 @@ +# DASHBOARD_CREATION.md — How to Create & Update Grafana Dashboards + +> **Linked from**: [AGENTS.md](AGENTS.md) + +This document captures the exact process used to create the Grafana dashboards in this folder, including all pitfalls encountered and lessons learned. Use this as a reference when creating new dashboards or updating existing ones. + +--- + +## Step-by-Step Dashboard Creation Process + +### Step 1: Discovery — Find Available Metrics + +Before creating any dashboard, discover what data actually exists: + +#### 1a. Query Home Assistant for Entity Metadata + +```bash +# Get all entities with their friendly names, units, and device classes +curl -s -H "Authorization: Bearer " \ + https://hass.moritzgraf.de/api/states | \ + jq '[.[] | select(.attributes.unit_of_measurement != null) | { + entity_id, + unit: .attributes.unit_of_measurement, + friendly_name: (.attributes.friendly_name // ""), + device_class: (.attributes.device_class // "") + }] | group_by(.unit)' +``` + +Or use the helper script: `./scripts/discover-home-assistant.sh` + +#### 1b. Query InfluxDB for Measurements and Schema + +```bash +# Port-forward to InfluxDB (no ingress configured) +kubectl -n influxdb port-forward svc/influxdb-influxdb2 8086:80 + +# List measurements with data in last 6 months +curl -s "http://localhost:8086/api/v2/query?org=influxdata" \ + -H "Authorization: Token " \ + -H "Content-Type: application/vnd.flux" \ + -d 'from(bucket: "default") + |> range(start: -6mo) + |> keep(columns: ["_measurement"]) + |> distinct() + |> sort()' + +# For a specific measurement, get fields and tags +curl -s "http://localhost:8086/api/v2/query?org=influxdata" \ + -H "Authorization: Token " \ + -H "Content-Type: application/vnd.flux" \ + -d 'import "influxdata/influxdb/schema" + schema.measurementFieldKeys(bucket: "default", measurement: "°C")' +``` + +Or use: `./scripts/discover-influxdb.sh` + +#### 1c. Verify Data Exists + +Always test a sample query before building dashboards: + +```bash +curl -s "http://localhost:8086/api/v2/query?org=influxdata" \ + -H "Authorization: Token " \ + -H "Content-Type: application/vnd.flux" \ + -d 'from(bucket: "default") + |> range(start: -1h) + |> filter(fn: (r) => r._measurement == "°C" and r._field == "value") + |> limit(n: 5)' +``` + +### Step 2: Discover Grafana Datasource UIDs + +Datasource UIDs change when Grafana is redeployed. Always discover the current UIDs: + +```bash +kubectl -n monitoring exec deploy/prometheus-operator-grafana -c grafana -- \ + curl -s -u "admin:" \ + http://localhost:3000/api/datasources | \ + jq '.[] | {name, uid, type}' +``` + +The Grafana admin password is in [`prometheus-operator.secret.yml`](prometheus-operator.secret.yml) under `grafana.adminPassword`. + +### Step 3: Select the Right Entities + +**Important**: Not all sensors of the same type are equal. For example: +- Use **Wandthermostat** (wall thermostat) entities for temperature/humidity, not raw sensor entities. Wandthermostats provide more reliable, calibrated readings. +- Query Home Assistant to filter by entity name pattern or device type. + +```bash +# Find all Wandthermostat temperature sensors +curl -s -H "Authorization: Bearer " \ + https://hass.moritzgraf.de/api/states | \ + jq '[.[] | select(.attributes.unit_of_measurement == "°C" and + (.entity_id | test("wandthermostat|thermostat"; "i")))]' +``` + +### Step 4: Create the Dashboard ConfigMap YAML + +Create a new file in `dashboards/` following this template: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboard- + namespace: monitoring + labels: + grafana_dashboard: "1" + annotations: + grafana_dashboard_folder: "🏠 Home" +data: + .json: | + { + "uid": "", + "title": "", + "tags": ["home", "", "auto-generated"], + "timezone": "browser", + "schemaVersion": 39, + "version": 1, + "refresh": "5m", + "editable": false, + "graphTooltip": 1, + "time": { "from": "now-24h", "to": "now" }, + "panels": [ ... ] + } +``` + +#### Critical JSON Structure Rules + +**✅ CORRECT** (top-level properties, no wrapper): +```json +{ + "uid": "my-dashboard", + "title": "My Dashboard", + "panels": [...] +} +``` + +**❌ WRONG** (wrapped in "dashboard" key — causes "Dashboard title cannot be empty"): +```json +{ + "dashboard": { + "uid": "my-dashboard", + "title": "My Dashboard", + "panels": [...] + } +} +``` + +The `"dashboard"` wrapper is **only** used in the Grafana HTTP API (`/api/dashboards/db`). For file-based provisioning via the sidecar, properties must be at the top level. + +#### Datasource Reference + +**✅ CORRECT** (by actual UID): +```json +"datasource": { "type": "influxdb", "uid": "P2AB959DC95E5519F" } +``` + +**❌ WRONG** (by name — won't resolve): +```json +"datasource": { "type": "influxdb", "uid": "InfluxDB Home Assistant" } +``` + +#### Flux Query Template + +**Exact match on entity_id:** +```flux +from(bucket: "default") + |> range(start: v.timeRangeStart, stop: v.timeRangeStop) + |> filter(fn: (r) => r["_measurement"] == "" and r["_field"] == "value") + |> filter(fn: (r) => r.entity_id == "") + |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) + |> yield(name: "mean") +``` + +**Regex match on entity_id** (for panels showing multiple entities matching a pattern): +```flux +from(bucket: "default") + |> range(start: v.timeRangeStart, stop: v.timeRangeStop) + |> filter(fn: (r) => r["_measurement"] == "" and r["_field"] == "value") + |> filter(fn: (r) => r.entity_id =~ /^home_/) + |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) + |> yield(name: "mean") +``` + +**Current value** (for stat panels showing last reading): +```flux +from(bucket: "default") + |> range(start: -15m) + |> filter(fn: (r) => r["_measurement"] == "" and r["_field"] == "value") + |> filter(fn: (r) => r.entity_id == "") + |> last() + |> yield(name: "mean") +``` + +**Key points**: +- Use bracket notation `r["_measurement"]`, `r["_field"]` for fields starting with underscore. +- **entity_id in InfluxDB has NO `sensor.` prefix** — HA stores domain in a separate `domain` tag. Use `home_wohnzimmer_temperature`, not `sensor.home_wohnzimmer_temperature`. +- Always use `v.timeRangeStart`, `v.timeRangeStop`, `v.windowPeriod` — never hardcode time values. +- Always end with `|> yield(name: "mean")` — required for Grafana to parse Flux results. +- Use regex `=~ /pattern/` for multi-entity panels (e.g., `=~ /^home_/` matches all home entities). +- Always filter `r["_field"] == "value"` — InfluxDB stores metadata strings in other fields. + +### Step 5: Deploy + +```bash +# Apply all dashboards +kubectl apply -f dashboards/ + +# Apply a single dashboard +kubectl apply -f dashboards/grafana-dashboard-.yaml +``` + +### Step 6: Verify + +```bash +# Check ConfigMaps are labeled correctly +kubectl get configmaps -n monitoring -l grafana_dashboard=1 + +# Check sidecar logs (container name is grafana-sc-dashboard, singular!) +kubectl -n monitoring logs -l "app.kubernetes.io/name=grafana" \ + -c grafana-sc-dashboard --tail=20 + +# Check Grafana main logs for errors +kubectl -n monitoring logs -l "app.kubernetes.io/name=grafana" \ + -c grafana --tail=30 | grep -i "error\|failed" +``` + +--- + +## Update Process (Modifying an Existing Dashboard) + +1. Edit the YAML file in `dashboards/` +2. Increment the `version` field in the dashboard JSON +3. Run `kubectl apply -f dashboards/grafana-dashboard-.yaml` +4. The sidecar will detect the change and reload within ~60 seconds +5. Verify in Grafana UI + +**Never edit dashboards in the Grafana UI** — they are `editable: false`. All changes must go through the YAML files. + +--- + +## Removing a Dashboard + +```bash +kubectl delete configmap -n monitoring grafana-dashboard- +``` + +The sidecar will remove it from Grafana within ~60 seconds. + +--- + +## Pitfalls Encountered in This Conversation + +### Pitfall 1: Entity IDs lack `sensor.` prefix in InfluxDB +**Problem**: Used `sensor.home_wohnzimmer_temperature` in queries — no data appeared. Home Assistant stores the domain (`sensor`) in a separate `domain` tag, not in `entity_id`. +**Fix**: Use `home_wohnzimmer_temperature` (without prefix). Always query InfluxDB directly to verify entity_id format before building queries. + +### Pitfall 2: Hardcoded time ranges +**Problem**: Used `range(start: -24h)` and `aggregateWindow(every: 5m)` — dashboard time picker had no effect, data not loaded properly. +**Fix**: Always use `v.timeRangeStart`, `v.timeRangeStop`, `v.windowPeriod`. These Grafana variables adapt to the dashboard time picker. + +### Pitfall 3: Missing `yield()` +**Problem**: Flux queries missing `yield(name: "mean")` — Grafana couldn't parse results. +**Fix**: Always end Flux queries with `|> yield(name: "mean")`. + +### Pitfall 4: Dot notation for underscore fields +**Problem**: Used `r._measurement` and `r._field` — Flux may not resolve fields starting with `_` via dot notation. +**Fix**: Use bracket notation: `r["_measurement"]`, `r["_field"]`. + +### Pitfall 5: Datasource UID vs Name +**Problem**: Used datasource name as UID (`"uid": "InfluxDB Home Assistant"`). Dashboards loaded but showed "no data". +**Fix**: Discover actual UID via `kubectl exec` + Grafana API. Current: `P2AB959DC95E5519F`. + +### Pitfall 6: `"dashboard"` JSON Wrapper +**Problem**: Dashboard JSON wrapped in `{"dashboard": {...}}`. Grafana showed "Dashboard title cannot be empty". +**Fix**: Top-level properties only. The `"dashboard"` wrapper is for HTTP API, not file provisioning. + +### Pitfall 7: Adding `uid` to Helm Datasource Config +**Problem**: Added `uid: influxdb-ha-flux` to helm values — Grafana pod crashed. +**Fix**: Let Grafana auto-generate UIDs. Never add `uid` to existing datasources. + +### Pitfall 8: Multi-entity panels using `or` in filter +**Problem**: Used `filter(fn: (r) => r.entity_id == "A" or r.entity_id == "B")` — Flux `or` inside a single filter call doesn't reliably work. +**Fix**: Use regex: `filter(fn: (r) => r.entity_id =~ /^home_/)` for matching multiple entities. + +### Pitfall 9: Wrong Sensor Selection +**Problem**: Used raw temperature sensors instead of Wandthermostat sensors. +**Fix**: Query HA to filter entities with `wandthermostat` or `thermostat` in entity_id. + +### Pitfall 10: Sidecar Container Name +**Problem**: `kubectl logs -c grafana-sc-dashboards` (plural). +**Fix**: Container name is `grafana-sc-dashboard` (singular). + +--- + +## Dashboard Design Guidelines + +1. **Use semantic thresholds with colors**: Blue=cold, green=comfort, orange=warm, red=hot for temperature; reverse for grid import (green=low, red=high). +2. **Use Stat panels with sparklines** for current values — they show the 24h mini-trend. +3. **Use BarGauge for day comparisons** (today vs yesterday vs avg). +4. **Use Gauge for ranged values** (battery SoC 0-100%, cloud cover 0-100%). +5. **Color-code panel backgrounds** with `"colorMode": "background"` for at-a-glance status. +6. **Set `"editable": false`** for strict GitOps. +7. **Use emoji in dashboard and panel titles** for visual appeal (🏠 ⚡ 🔥 🌡️ 💧). +8. **Add `"auto-generated"` tag** to distinguish from manually created dashboards. +9. **Include calcs in legend** (`mean`, `max`, `min`, `lastNotNull`) for quick statistics. +10. **Use `"spanNulls": true`** in timeseries to handle gaps in sensor data. + +--- + +## InfluxDB Measurement Reference + +| Measurement | Unit | Typical Entities | +|-------------|------|------------------| +| `°C` | celsius | Wandthermostat temperatures, outdoor temp, battery temp | +| `%` | percent | Humidity, battery levels, heating valve position, cloud cover | +| `W` | watt | Solar production, self-consumption, grid import/export, house consumption | +| `kWh` | kilowatt-hour | Daily energy totals (production, consumption, import, export) | +| `m³` | cubic meter | Gas volume counter | +| `m³/h` | cubic meter/hour | Current gas flow rate | +| `hPa` | hectopascal | Barometric pressure | +| `km/h` | kilometer/hour | Wind speed | +| `mm/h` | millimeter/hour | Precipitation rate | +| `EUR` | euro | Gas cost, electricity cost | diff --git a/k8s/monitoring/README.md b/k8s/monitoring/README.md new file mode 100644 index 0000000..c46e1ec --- /dev/null +++ b/k8s/monitoring/README.md @@ -0,0 +1,90 @@ +# Grafana Dashboards as Code + +This directory contains Grafana dashboards managed as Kubernetes ConfigMaps. Dashboards are automatically loaded into Grafana via the dashboard sidecar. + +## Architecture + +``` +dashboards/*.yaml (ConfigMap with embedded JSON) + │ + │ kubectl apply + ▼ +Kubernetes ConfigMap (label: grafana_dashboard=1) + │ + │ Sidecar watches for ConfigMaps + ▼ +Grafana Dashboard (read-only, GitOps managed) +``` + +## Quick Deploy + +```bash +# Apply all dashboards +kubectl apply -f dashboards/ + +# Apply a single dashboard +kubectl apply -f dashboards/grafana-dashboard-home-climate.yaml +``` + +## Verify + +```bash +# Check ConfigMaps are created and labeled correctly +kubectl get configmaps -n monitoring -l grafana_dashboard=1 + +# Check sidecar logs to confirm dashboards were loaded +kubectl logs -n monitoring deployment/kube-prometheus-stack-grafana -c grafana-sc-dashboards --tail=50 + +# List dashboards via Grafana API +kubectl -n monitoring exec deploy/kube-prometheus-stack-grafana -- \ + curl -s -u admin:$(kubectl -n monitoring get secret kube-prometheus-stack-grafana -o jsonpath='{.data.admin-password}' | base64 -d) \ + http://localhost:3000/api/search?type=dash-db | jq '.[].title' +``` + +## Discovery + +Before generating new dashboards, discover what metrics are available: + +```bash +# Discover InfluxDB measurements, fields, and tags +./scripts/discover-influxdb.sh + +# Discover Home Assistant entities and their metadata +./scripts/discover-home-assistant.sh +``` + +## Dashboard Structure + +Each dashboard is a single YAML file containing a Kubernetes ConfigMap with the dashboard JSON embedded: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboard- + namespace: monitoring + labels: + grafana_dashboard: "1" + annotations: + grafana_dashboard_folder: "" +data: + .json: | + { + "dashboard": { ... } + } +``` + +## Adding a New Dashboard + +1. Run discovery scripts to understand available metrics +2. Create a new ConfigMap YAML in `dashboards/` +3. Apply: `kubectl apply -f dashboards/grafana-dashboard-.yaml` +4. Verify the dashboard appears in Grafana at https://grafana.haumdaucher.de + +## Removing a Dashboard + +```bash +kubectl delete configmap -n monitoring grafana-dashboard- +``` + +The sidecar will automatically remove the dashboard from Grafana within ~60 seconds. \ No newline at end of file diff --git a/k8s/monitoring/alertmanagerconfig.secret.yaml b/k8s/monitoring/alertmanagerconfig.secret.yaml index afd5890..df713f4 100644 Binary files a/k8s/monitoring/alertmanagerconfig.secret.yaml and b/k8s/monitoring/alertmanagerconfig.secret.yaml differ diff --git a/k8s/monitoring/dashboards/grafana-dashboard-energy-monitor.yaml b/k8s/monitoring/dashboards/grafana-dashboard-energy-monitor.yaml new file mode 100644 index 0000000..8d13aaf --- /dev/null +++ b/k8s/monitoring/dashboards/grafana-dashboard-energy-monitor.yaml @@ -0,0 +1,92 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboard-energy-monitor + namespace: monitoring + labels: + grafana_dashboard: '1' + annotations: + grafana_dashboard_folder: 🏠 Home +data: + energy-monitor.json: '{"uid": "energy-monitor", "title": "⚡ Energy Monitor", "tags": ["home", "energy", "solar", "power", "auto-generated"], "timezone": "browser", "schemaVersion": 39, "version": 1, "refresh": + "5m", "editable": false, "graphTooltip": 1, "time": {"from": "now-24h", "to": "now"}, "panels": [{"title": "⚡ Live Power", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 0}, "collapsed": false}, + {"title": "☀️ Solar", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 0, "y": 1}, "fieldConfig": {"defaults": {"unit": "watt", "decimals": + 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#555", "value": null}, {"color": "#FFD700", "value": 100}, {"color": "#73BF69", "value": 500}, {"color": "#37872D", "value": 2000}]}, "color": + {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: + \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"W\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_systemleistung\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "🏠 Self-Use", "type": "stat", "datasource": {"type": "influxdb", + "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 4, "y": 1}, "fieldConfig": {"defaults": {"unit": "watt", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#555", "value": + null}, {"color": "#73BF69", "value": 100}, {"color": "#FFD700", "value": 1000}, {"color": "#FF7383", "value": 3000}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": + "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> + filter(fn: (r) => r[\"_measurement\"] == \"W\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_eigene_leistung\")\n |> aggregateWindow(every: v.windowPeriod, + fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "🔌 Grid Import", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, + "gridPos": {"h": 4, "w": 4, "x": 8, "y": 1}, "fieldConfig": {"defaults": {"unit": "watt", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#73BF69", "value": null}, {"color": "#FFD700", + "value": 500}, {"color": "#FF7383", "value": 2000}, {"color": "#C4162A", "value": 5000}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": + "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) + => r[\"_measurement\"] == \"W\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_bezugsleistung\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: + false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "↗️ Grid Export", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, + "w": 4, "x": 12, "y": 1}, "fieldConfig": {"defaults": {"unit": "watt", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#555", "value": null}, {"color": "#5794F2", "value": 100}, + {"color": "#1F60C4", "value": 500}, {"color": "#3274D9", "value": 2000}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": + {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] + == \"W\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_einspeiseleistung\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> + yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "🔋 Battery SoC", "type": "gauge", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": + 16, "y": 1}, "fieldConfig": {"defaults": {"unit": "percent", "decimals": 0, "min": 0, "max": 100, "thresholds": {"mode": "absolute", "steps": [{"color": "#C4162A", "value": null}, {"color": "#FF7383", + "value": 20}, {"color": "#FFD700", "value": 40}, {"color": "#73BF69", "value": 60}]}, "color": {"mode": "thresholds"}}}, "options": {"reduceOptions": {"values": false, "calcs": ["lastNotNull"]}, "orientation": + "auto", "showThresholdLabels": true, "showThresholdMarkers": true}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: -15m)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and + r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"ladeaufstellung_soc\")\n |> last()\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "🏡 Total House", "type": + "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 20, "y": 1}, "fieldConfig": {"defaults": {"unit": "watt", "decimals": 0, "thresholds": {"mode": + "absolute", "steps": [{"color": "#555", "value": null}, {"color": "#73BF69", "value": 200}, {"color": "#FFD700", "value": 1000}, {"color": "#FF7383", "value": 3000}, {"color": "#C4162A", "value": 5000}]}, + "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": + "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"W\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id + == \"home_strommesserat_currentpowerconsumption\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": + "📈 Power Flow", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 5}, "collapsed": false}, {"title": "Power Timeline", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, + "gridPos": {"h": 10, "w": 24, "x": 0, "y": 6}, "fieldConfig": {"defaults": {"unit": "watt", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": + {"id": "byName", "options": "Solar"}, "properties": [{"id": "color", "value": {"fixedColor": "#FFD700", "mode": "fixed"}}, {"id": "custom.fillOpacity", "value": 15}]}, {"matcher": {"id": "byName", "options": + "Self-Use"}, "properties": [{"id": "color", "value": {"fixedColor": "#73BF69", "mode": "fixed"}}]}, {"matcher": {"id": "byName", "options": "Grid Import"}, "properties": [{"id": "color", "value": {"fixedColor": + "#FF7383", "mode": "fixed"}}]}, {"matcher": {"id": "byName", "options": "Grid Export"}, "properties": [{"id": "color", "value": {"fixedColor": "#5794F2", "mode": "fixed"}}, {"id": "custom.lineStyle", + "value": {"fill": "dash", "dash": [8, 4]}}]}, {"matcher": {"id": "byName", "options": "Local Load"}, "properties": [{"id": "color", "value": {"fixedColor": "#C4162A", "mode": "fixed"}}]}]}, "options": + {"legend": {"displayMode": "table", "placement": "bottom", "calcs": ["max", "mean", "lastNotNull"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "SOLAR", "query": "from(bucket: + \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"W\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_systemleistung\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"source\", value: \"Solar\")", "resultFormat": "time_series"}, {"refId": "SELF", "query": + "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"W\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id + == \"garten_bzp3n7g1b0_eigene_leistung\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"source\", value: \"Self-Use\")", "resultFormat": + "time_series"}, {"refId": "IMPORT", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"W\" and r[\"_field\"] + == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_bezugsleistung\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> + set(key: \"source\", value: \"Grid Import\")", "resultFormat": "time_series"}, {"refId": "EXPORT", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> + filter(fn: (r) => r[\"_measurement\"] == \"W\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_einspeiseleistung\")\n |> aggregateWindow(every: v.windowPeriod, + fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"source\", value: \"Grid Export\")", "resultFormat": "time_series"}, {"refId": "LOAD", "query": "from(bucket: \"default\")\n |> + range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"W\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_lokale_lastleistung\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"source\", value: \"Local Load\")", "resultFormat": "time_series"}]}, {"title": "📊 Energy + Summary (Today)", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 16}, "collapsed": false}, {"title": "☀️ Solar Produced", "type": "bargauge", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, + "gridPos": {"h": 4, "w": 6, "x": 0, "y": 17}, "fieldConfig": {"defaults": {"unit": "kwatth", "decimals": 1, "min": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#555", "value": null}, {"color": + "#FFD700", "value": 5}, {"color": "#73BF69", "value": 15}, {"color": "#37872D", "value": 30}]}, "color": {"mode": "thresholds"}}}, "options": {"reduceOptions": {"values": false, "calcs": ["lastNotNull"]}, + "orientation": "horizontal", "displayMode": "basic", "showUnfilled": true}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: -15m)\n |> filter(fn: (r) => r[\"_measurement\"] == \"kWh\" + and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_systemerzeugung_heute\")\n |> last()\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": + "🏠 Self-Consumed", "type": "bargauge", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 6, "x": 6, "y": 17}, "fieldConfig": {"defaults": {"unit": "kwatth", "decimals": + 1, "min": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#555", "value": null}, {"color": "#73BF69", "value": 5}, {"color": "#FFD700", "value": 15}, {"color": "#FF7383", "value": 30}]}, + "color": {"mode": "thresholds"}}}, "options": {"reduceOptions": {"values": false, "calcs": ["lastNotNull"]}, "orientation": "horizontal", "displayMode": "basic", "showUnfilled": true}, "targets": [{"query": + "from(bucket: \"default\")\n |> range(start: -15m)\n |> filter(fn: (r) => r[\"_measurement\"] == \"kWh\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_eigenverbrauch_heute\")\n |> + last()\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "🔌 Grid Imported", "type": "bargauge", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": + 4, "w": 6, "x": 12, "y": 17}, "fieldConfig": {"defaults": {"unit": "kwatth", "decimals": 1, "min": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#73BF69", "value": null}, {"color": "#FFD700", + "value": 2}, {"color": "#FF7383", "value": 10}, {"color": "#C4162A", "value": 20}]}, "color": {"mode": "thresholds"}}}, "options": {"reduceOptions": {"values": false, "calcs": ["lastNotNull"]}, "orientation": + "horizontal", "displayMode": "basic", "showUnfilled": true}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: -15m)\n |> filter(fn: (r) => r[\"_measurement\"] == \"kWh\" and r[\"_field\"] + == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_netzbezug_heute\")\n |> last()\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "↗️ Grid Exported", + "type": "bargauge", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 6, "x": 18, "y": 17}, "fieldConfig": {"defaults": {"unit": "kwatth", "decimals": 1, "min": + 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#555", "value": null}, {"color": "#5794F2", "value": 2}, {"color": "#1F60C4", "value": 10}, {"color": "#3274D9", "value": 20}]}, "color": {"mode": + "thresholds"}}}, "options": {"reduceOptions": {"values": false, "calcs": ["lastNotNull"]}, "orientation": "horizontal", "displayMode": "basic", "showUnfilled": true}, "targets": [{"query": "from(bucket: + \"default\")\n |> range(start: -15m)\n |> filter(fn: (r) => r[\"_measurement\"] == \"kWh\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"export_ins_netz_heute\")\n |> last()\n |> + yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "📈 Energy Trend", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 21}, "collapsed": false}, {"title": "Daily Energy", "type": + "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 10, "w": 24, "x": 0, "y": 22}, "fieldConfig": {"defaults": {"unit": "kwatth", "custom": {"lineWidth": 2, + "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": {"id": "byName", "options": "Solar"}, "properties": [{"id": "color", "value": {"fixedColor": "#FFD700", "mode": + "fixed"}}]}, {"matcher": {"id": "byName", "options": "Self-Use"}, "properties": [{"id": "color", "value": {"fixedColor": "#73BF69", "mode": "fixed"}}]}, {"matcher": {"id": "byName", "options": "Grid + Import"}, "properties": [{"id": "color", "value": {"fixedColor": "#FF7383", "mode": "fixed"}}]}, {"matcher": {"id": "byName", "options": "Grid Export"}, "properties": [{"id": "color", "value": {"fixedColor": + "#5794F2", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": "table", "placement": "bottom", "calcs": ["sum", "mean"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": + "SOLAR", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"kWh\" and r[\"_field\"] == \"value\")\n |> + filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_systemerzeugung_heute\")\n |> aggregateWindow(every: 1d, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"type\", value: + \"Solar\")", "resultFormat": "time_series"}, {"refId": "SELF", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] + == \"kWh\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_eigenverbrauch_heute\")\n |> aggregateWindow(every: 1d, fn: mean, createEmpty: false)\n |> yield(name: + \"mean\") |> set(key: \"type\", value: \"Self-Use\")", "resultFormat": "time_series"}, {"refId": "IMPORT", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> + filter(fn: (r) => r[\"_measurement\"] == \"kWh\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"garten_bzp3n7g1b0_netzbezug_heute\")\n |> aggregateWindow(every: 1d, fn: mean, + createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"type\", value: \"Grid Import\")", "resultFormat": "time_series"}, {"refId": "EXPORT", "query": "from(bucket: \"default\")\n |> range(start: + v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"kWh\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"export_ins_netz_heute\")\n |> + aggregateWindow(every: 1d, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"type\", value: \"Grid Export\")", "resultFormat": "time_series"}]}]}' diff --git a/k8s/monitoring/dashboards/grafana-dashboard-heating-gas.yaml b/k8s/monitoring/dashboards/grafana-dashboard-heating-gas.yaml new file mode 100644 index 0000000..4ce7a9f --- /dev/null +++ b/k8s/monitoring/dashboards/grafana-dashboard-heating-gas.yaml @@ -0,0 +1,62 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboard-heating-gas + namespace: monitoring + labels: + grafana_dashboard: '1' + annotations: + grafana_dashboard_folder: 🏠 Home +data: + heating-gas.json: '{"uid": "heating-gas", "title": "🔥 Heating & Gas", "tags": ["home", "heating", "gas", "auto-generated"], "timezone": "browser", "schemaVersion": 39, "version": 1, "refresh": "5m", "editable": + false, "graphTooltip": 1, "time": {"from": "now-24h", "to": "now"}, "panels": [{"title": "⛽ Gas Overview", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 0}, "collapsed": false}, {"title": + "Current Gas Flow", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 6, "x": 0, "y": 1}, "fieldConfig": {"defaults": {"unit": "cms", "decimals": + 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#73BF69", "value": null}, {"color": "#FFD700", "value": 0.5}, {"color": "#FF7383", "value": 1.5}, {"color": "#C4162A", "value": 3}]}, "color": + {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: + \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"m³/h\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == + \"home_gaszahler_currentgasflow\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Total Gas Volume", + "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 6, "x": 6, "y": 1}, "fieldConfig": {"defaults": {"unit": "cms", "decimals": 0, "thresholds": + {"mode": "absolute", "steps": [{"color": "#73BF69", "value": null}, {"color": "#FFD700", "value": 500}, {"color": "#FF7383", "value": 1000}, {"color": "#C4162A", "value": 2000}]}, "color": {"mode": + "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> + range(start: -15m)\n |> filter(fn: (r) => r[\"_measurement\"] == \"m³\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_gaszahler_gasvolume\")\n |> last()\n |> yield(name: + \"mean\")", "resultFormat": "time_series"}]}, {"title": "Gas Cost (EUR)", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 6, "x": 12, "y": 1}, + "fieldConfig": {"defaults": {"unit": "currencyEUR", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#73BF69", "value": null}, {"color": "#FFD700", "value": 200}, {"color": "#FF7383", + "value": 500}, {"color": "#C4162A", "value": 1000}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, + "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: -15m)\n |> filter(fn: (r) => r[\"_measurement\"] == \"EUR\" and r[\"_field\"] == \"value\")\n |> filter(fn: + (r) => r.entity_id == \"home_gaszahler_gasvolume_cost\")\n |> last()\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Electricity Cost (EUR)", "type": "stat", "datasource": + {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 6, "x": 18, "y": 1}, "fieldConfig": {"defaults": {"unit": "currencyEUR", "decimals": 0, "thresholds": {"mode": "absolute", + "steps": [{"color": "#73BF69", "value": null}, {"color": "#FFD700", "value": 100}, {"color": "#FF7383", "value": 300}, {"color": "#C4162A", "value": 500}]}, "color": {"mode": "thresholds"}}}, "options": + {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: + -15m)\n |> filter(fn: (r) => r[\"_measurement\"] == \"EUR\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_strommesserat_energy_counter_usage_high_tariff_cost\")\n |> + last()\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "📈 Gas Consumption Trend", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 5}, "collapsed": false}, {"title": + "Gas Flow", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 8, "w": 16, "x": 0, "y": 6}, "fieldConfig": {"defaults": {"unit": "cms", "custom": + {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": {"id": "byName", "options": "Gas Flow"}, "properties": [{"id": "color", "value": {"fixedColor": + "#FF7383", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": "table", "placement": "bottom", "calcs": ["max", "mean"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": + "FLOW", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"m³/h\" and r[\"_field\"] == \"value\")\n |> + filter(fn: (r) => r.entity_id == \"home_gaszahler_currentgasflow\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"metric\", value: + \"Gas Flow\")", "resultFormat": "time_series"}]}, {"title": "Gas Volume", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 8, "w": 8, "x": 16, "y": + 6}, "fieldConfig": {"defaults": {"unit": "cms", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": {"id": "byName", "options": "Gas Volume"}, + "properties": [{"id": "color", "value": {"fixedColor": "#C4162A", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": "table", "placement": "bottom", "calcs": ["mean", "lastNotNull"]}, "tooltip": + {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "VOL", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] + == \"m³\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_gaszahler_gasvolume\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: + \"mean\") |> set(key: \"metric\", value: \"Gas Volume\")", "resultFormat": "time_series"}]}, {"title": "🏠 Heating Activity", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 14}, "collapsed": + false}, {"title": "Heating Valve Position", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 10, "w": 24, "x": 0, "y": 15}, "fieldConfig": {"defaults": + {"unit": "percent", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": {"id": "byName", "options": "Wohnzimmer"}, "properties": [{"id": + "color", "value": {"fixedColor": "#FF7383", "mode": "fixed"}}]}, {"matcher": {"id": "byName", "options": "Wohnzimmer #2"}, "properties": [{"id": "color", "value": {"fixedColor": "#FF9830", "mode": "fixed"}}]}, + {"matcher": {"id": "byName", "options": "Arbeitszimmer"}, "properties": [{"id": "color", "value": {"fixedColor": "#5794F2", "mode": "fixed"}}]}, {"matcher": {"id": "byName", "options": "Schlafzimmer"}, + "properties": [{"id": "color", "value": {"fixedColor": "#8F3BB8", "mode": "fixed"}}]}, {"matcher": {"id": "byName", "options": "Küche"}, "properties": [{"id": "color", "value": {"fixedColor": "#73BF69", + "mode": "fixed"}}]}, {"matcher": {"id": "byName", "options": "Bad"}, "properties": [{"id": "color", "value": {"fixedColor": "#1F60C4", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": "table", + "placement": "bottom", "calcs": ["mean", "lastNotNull"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "Wo", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, + stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wohnzimmer_heating\")\n |> aggregateWindow(every: + v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")\n |> set(key: \"room\", value: \"Wohnzimmer\")", "resultFormat": "time_series"}, {"refId": "Wo", "query": "from(bucket: \"default\")\n |> + range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wohnzimmer_2_heating\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")\n |> set(key: \"room\", value: \"Wohnzimmer #2\")", "resultFormat": "time_series"}, {"refId": "Ar", + "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: + (r) => r.entity_id == \"home_arbeitszimmer_heating\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")\n |> set(key: \"room\", value: \"Arbeitszimmer\")", + "resultFormat": "time_series"}, {"refId": "Sc", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and + r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_schlafzimmer_og_heating\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")\n |> + set(key: \"room\", value: \"Schlafzimmer\")", "resultFormat": "time_series"}, {"refId": "Kü", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: + (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_kuche_vorne_heating\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: + false)\n |> yield(name: \"mean\")\n |> set(key: \"room\", value: \"Küche\")", "resultFormat": "time_series"}, {"refId": "Ba", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, + stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_badezimmer_thermostat_heating\")\n |> aggregateWindow(every: + v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")\n |> set(key: \"room\", value: \"Bad\")", "resultFormat": "time_series"}]}]}' diff --git a/k8s/monitoring/dashboards/grafana-dashboard-home-climate.yaml b/k8s/monitoring/dashboards/grafana-dashboard-home-climate.yaml new file mode 100644 index 0000000..71703c6 --- /dev/null +++ b/k8s/monitoring/dashboards/grafana-dashboard-home-climate.yaml @@ -0,0 +1,98 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboard-home-climate + namespace: monitoring + labels: + grafana_dashboard: '1' + annotations: + grafana_dashboard_folder: 🏠 Home +data: + home-climate.json: '{"uid": "home-climate", "title": "🏠 Home Climate", "tags": ["home", "climate", "temperature", "humidity", "auto-generated"], "timezone": "browser", "schemaVersion": 39, "version": + 1, "refresh": "5m", "editable": false, "graphTooltip": 1, "time": {"from": "now-24h", "to": "now"}, "panels": [{"title": "🌡️ Current Temperatures", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, + "y": 0}, "collapsed": false}, {"title": "Wohnzimmer", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 0, "y": 1}, "fieldConfig": {"defaults": + {"unit": "celsius", "decimals": 1, "thresholds": {"mode": "absolute", "steps": [{"color": "blue", "value": null}, {"color": "green", "value": 18}, {"color": "orange", "value": 22}, {"color": "red", + "value": 26}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": + [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: + (r) => r.entity_id == \"home_wall_mounted_thermostat_pro_temperature\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, + {"title": "Wohnzimmer #2", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 4, "y": 1}, "fieldConfig": {"defaults": {"unit": "celsius", + "decimals": 1, "thresholds": {"mode": "absolute", "steps": [{"color": "blue", "value": null}, {"color": "green", "value": 18}, {"color": "orange", "value": 22}, {"color": "red", "value": 26}]}, "color": + {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: + \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == + \"home_wohnzimmer_2_thermostat_temperature\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Arbeitszimmer", + "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 8, "y": 1}, "fieldConfig": {"defaults": {"unit": "celsius", "decimals": 1, "thresholds": + {"mode": "absolute", "steps": [{"color": "blue", "value": null}, {"color": "green", "value": 18}, {"color": "orange", "value": 22}, {"color": "red", "value": 26}]}, "color": {"mode": "thresholds"}}}, + "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> + range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_arbeitszimmer_thermostat_temperature\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Küche", "type": "stat", "datasource": {"type": "influxdb", + "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 12, "y": 1}, "fieldConfig": {"defaults": {"unit": "celsius", "decimals": 1, "thresholds": {"mode": "absolute", "steps": [{"color": "blue", + "value": null}, {"color": "green", "value": 18}, {"color": "orange", "value": 22}, {"color": "red", "value": 26}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", + "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> + filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_kuche_wandthermostat_temperature\")\n |> aggregateWindow(every: v.windowPeriod, + fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Bad", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": + {"h": 4, "w": 4, "x": 16, "y": 1}, "fieldConfig": {"defaults": {"unit": "celsius", "decimals": 1, "thresholds": {"mode": "absolute", "steps": [{"color": "blue", "value": null}, {"color": "green", "value": + 18}, {"color": "orange", "value": 22}, {"color": "red", "value": 26}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": + {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] + == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wandthermostat_bad_temperature\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> + yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "📈 Temperature Trends", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 5}, "collapsed": false}, {"title": "All Rooms Temperature", + "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 10, "w": 16, "x": 0, "y": 6}, "fieldConfig": {"defaults": {"unit": "celsius", "custom": {"lineWidth": + 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}}, "options": {"legend": {"displayMode": "table", "placement": "bottom", "calcs": ["mean", "lastNotNull", "min", "max"]}, "tooltip": {"mode": + "multi", "sort": "desc"}}, "targets": [{"refId": "Wo", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == + \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wall_mounted_thermostat_pro_temperature\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> + set(key: \"room\", value: \"Wohnzimmer\")\n |> yield(name: \"mean\")", "resultFormat": "time_series"}, {"refId": "Wo2", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: + v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wohnzimmer_2_thermostat_temperature\")\n |> aggregateWindow(every: + v.windowPeriod, fn: mean, createEmpty: false)\n |> set(key: \"room\", value: \"Wohnzimmer #2\")\n |> yield(name: \"mean\")", "resultFormat": "time_series"}, {"refId": "Ar", "query": "from(bucket: + \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == + \"home_arbeitszimmer_thermostat_temperature\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> set(key: \"room\", value: \"Arbeitszimmer\")\n |> yield(name: \"mean\")", + "resultFormat": "time_series"}, {"refId": "Kü", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"°C\" + and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_kuche_wandthermostat_temperature\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> set(key: \"room\", value: \"Küche\")\n |> yield(name: + \"mean\")", "resultFormat": "time_series"}, {"refId": "Ba", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> + filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wandthermostat_bad_temperature\")\n |> aggregateWindow(every: v.windowPeriod, + fn: mean, createEmpty: false)\n |> set(key: \"room\", value: \"Bad\")\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Indoor vs Outdoor", "type": "timeseries", "datasource": + {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 10, "w": 8, "x": 16, "y": 6}, "fieldConfig": {"defaults": {"unit": "celsius", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": + true, "showPoints": "never"}}, "overrides": [{"matcher": {"id": "byName", "options": "Outdoor"}, "properties": [{"id": "color", "value": {"fixedColor": "light-blue", "mode": "fixed"}}, {"id": "custom.lineStyle", + "value": {"fill": "dash", "dash": [10, 5]}}]}, {"matcher": {"id": "byName", "options": "Indoor Avg"}, "properties": [{"id": "color", "value": {"fixedColor": "orange", "mode": "fixed"}}]}]}, "options": + {"legend": {"displayMode": "table", "placement": "bottom", "calcs": ["mean", "lastNotNull"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "OUT", "query": "from(bucket: \"default\")\n |> + range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_temperatur\")\n |> + aggregateWindow(every: 1h, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")\n |> set(key: \"location\", value: \"Outdoor\")", "resultFormat": "time_series"}, {"refId": "IN", "query": "from(bucket: + \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id =~ + /^home_/)\n |> aggregateWindow(every: 1h, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")\n |> group()\n |> mean()\n |> set(key: \"location\", value: \"Indoor Avg\")", "resultFormat": + "time_series"}]}, {"title": "💧 Humidity", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 16}, "collapsed": false}, {"title": "Wohnzimmer", "type": "stat", "datasource": {"type": "influxdb", + "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 0, "y": 17}, "fieldConfig": {"defaults": {"unit": "percent", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "red", + "value": null}, {"color": "orange", "value": 30}, {"color": "green", "value": 40}, {"color": "orange", "value": 60}, {"color": "red", "value": 70}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": + "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, + stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wall_mounted_thermostat_pro_humidity\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Arbeitszimmer", "type": "stat", "datasource": {"type": + "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 4, "y": 17}, "fieldConfig": {"defaults": {"unit": "percent", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": + "red", "value": null}, {"color": "orange", "value": 30}, {"color": "green", "value": 40}, {"color": "orange", "value": 60}, {"color": "red", "value": 70}]}, "color": {"mode": "thresholds"}}}, "options": + {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: + v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_arbeitszimmer_thermostat_humidity\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Wohnzimmer #2", "type": "stat", "datasource": {"type": + "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 8, "y": 17}, "fieldConfig": {"defaults": {"unit": "percent", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": + "red", "value": null}, {"color": "orange", "value": 30}, {"color": "green", "value": 40}, {"color": "orange", "value": 60}, {"color": "red", "value": 70}]}, "color": {"mode": "thresholds"}}}, "options": + {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: + v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wohnzimmer_2_thermostat_humidity\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Bad", "type": "stat", "datasource": {"type": "influxdb", + "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 12, "y": 17}, "fieldConfig": {"defaults": {"unit": "percent", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "red", + "value": null}, {"color": "orange", "value": 30}, {"color": "green", "value": 40}, {"color": "orange", "value": 60}, {"color": "red", "value": 70}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": + "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, + stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wandthermostat_bad_humidity\")\n |> aggregateWindow(every: + v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Küche", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, + "gridPos": {"h": 4, "w": 4, "x": 16, "y": 17}, "fieldConfig": {"defaults": {"unit": "percent", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "red", "value": null}, {"color": + "orange", "value": 30}, {"color": "green", "value": 40}, {"color": "orange", "value": 60}, {"color": "red", "value": 70}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": + "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> + filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_kuche_wandthermostat_humidity\")\n |> aggregateWindow(every: v.windowPeriod, + fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "Humidity Trends", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, + "gridPos": {"h": 8, "w": 24, "x": 0, "y": 20}, "fieldConfig": {"defaults": {"unit": "percent", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}}, "options": {"legend": + {"displayMode": "table", "placement": "bottom", "calcs": ["mean", "lastNotNull"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "Wo", "query": "from(bucket: \"default\")\n |> + range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wall_mounted_thermostat_pro_humidity\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> set(key: \"room\", value: \"Wohnzimmer\")\n |> yield(name: \"mean\")", "resultFormat": "time_series"}, {"refId": "Ar", "query": + "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id + == \"home_arbeitszimmer_thermostat_humidity\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> set(key: \"room\", value: \"Arbeitszimmer\")\n |> yield(name: \"mean\")", + "resultFormat": "time_series"}, {"refId": "Wo2", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and + r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wohnzimmer_2_thermostat_humidity\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> set(key: \"room\", value: \"Wohnzimmer #2\")\n |> yield(name: + \"mean\")", "resultFormat": "time_series"}, {"refId": "Ba", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> + filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_wandthermostat_bad_humidity\")\n |> aggregateWindow(every: v.windowPeriod, + fn: mean, createEmpty: false)\n |> set(key: \"room\", value: \"Bad\")\n |> yield(name: \"mean\")", "resultFormat": "time_series"}, {"refId": "Kü", "query": "from(bucket: \"default\")\n |> range(start: + v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"home_kuche_wandthermostat_humidity\")\n |> + aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> set(key: \"room\", value: \"Küche\")\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}]}' diff --git a/k8s/monitoring/dashboards/grafana-dashboard-outdoor-weather.yaml b/k8s/monitoring/dashboards/grafana-dashboard-outdoor-weather.yaml new file mode 100644 index 0000000..1fa264f --- /dev/null +++ b/k8s/monitoring/dashboards/grafana-dashboard-outdoor-weather.yaml @@ -0,0 +1,75 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboard-outdoor-weather + namespace: monitoring + labels: + grafana_dashboard: '1' + annotations: + grafana_dashboard_folder: 🏠 Home +data: + outdoor-weather.json: '{"uid": "outdoor-weather", "title": "🌡️ Outdoor & Weather", "tags": ["home", "weather", "outdoor", "auto-generated"], "timezone": "browser", "schemaVersion": 39, "version": 1, "refresh": + "5m", "editable": false, "graphTooltip": 1, "time": {"from": "now-24h", "to": "now"}, "panels": [{"title": "🌤️ Current Conditions", "type": "row", "gridPos": {"h": 1, "w": 24, "x": 0, "y": 0}, "collapsed": + false}, {"title": "🌡️ Temperature", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 0, "y": 1}, "fieldConfig": {"defaults": {"unit": + "celsius", "decimals": 1, "thresholds": {"mode": "absolute", "steps": [{"color": "#5794F2", "value": null}, {"color": "#73BF69", "value": 0}, {"color": "#FFD700", "value": 15}, {"color": "#FF7383", + "value": 25}, {"color": "#C4162A", "value": 30}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, + "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"°C\" and r[\"_field\"] + == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_temperatur\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": + "time_series"}]}, {"title": "💧 Humidity", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 4, "y": 1}, "fieldConfig": {"defaults": {"unit": + "percent", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#FF7383", "value": null}, {"color": "#FFD700", "value": 30}, {"color": "#73BF69", "value": 40}, {"color": "#FFD700", + "value": 70}, {"color": "#5794F2", "value": 90}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, + "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] + == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_luftfeuchtigkeit\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "resultFormat": "time_series"}]}, {"title": "🔵 Pressure", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 8, "y": 1}, "fieldConfig": + {"defaults": {"unit": "pressurehpa", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#FF7383", "value": null}, {"color": "#FFD700", "value": 990}, {"color": "#73BF69", "value": + 1010}, {"color": "#FFD700", "value": 1030}, {"color": "#FF7383", "value": 1040}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", + "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] + == \"hPa\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_druck\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: + \"mean\")", "resultFormat": "time_series"}]}, {"title": "💨 Wind", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 12, "y": 1}, "fieldConfig": + {"defaults": {"unit": "velocitykmh", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#73BF69", "value": null}, {"color": "#FFD700", "value": 20}, {"color": "#FF7383", "value": + 40}, {"color": "#C4162A", "value": 60}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": + ["lastNotNull"]}}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"km/h\" and r[\"_field\"] + == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_windgeschwindigkeit\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "resultFormat": "time_series"}]}, {"title": "🌧️ Rain", "type": "stat", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 16, "y": 1}, "fieldConfig": {"defaults": + {"unit": "mm/h", "decimals": 0, "thresholds": {"mode": "absolute", "steps": [{"color": "#73BF69", "value": null}, {"color": "#5794F2", "value": 0.1}, {"color": "#1F60C4", "value": 1}, {"color": "#3274D9", + "value": 5}]}, "color": {"mode": "thresholds"}}}, "options": {"graphMode": "area", "colorMode": "background", "textMode": "auto", "reduceOptions": {"values": false, "calcs": ["lastNotNull"]}}, "targets": + [{"query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"mm/h\" and r[\"_field\"] == \"value\")\n |> filter(fn: + (r) => r.entity_id == \"regensburg_regensburg_niederschlag\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, + {"title": "☁️ Cloud Cover", "type": "gauge", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 4, "w": 4, "x": 20, "y": 1}, "fieldConfig": {"defaults": {"unit": "percent", + "decimals": 0, "min": 0, "max": 100, "thresholds": {"mode": "absolute", "steps": [{"color": "#5794F2", "value": null}, {"color": "#73BF69", "value": 20}, {"color": "#FFD700", "value": 50}, {"color": + "#808080", "value": 80}]}, "color": {"mode": "thresholds"}}}, "options": {"reduceOptions": {"values": false, "calcs": ["lastNotNull"]}, "orientation": "auto", "showThresholdLabels": true, "showThresholdMarkers": + true}, "targets": [{"query": "from(bucket: \"default\")\n |> range(start: -15m)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id + == \"regensburg_regensburg_bewolkungsgrad\")\n |> last()\n |> yield(name: \"mean\")", "resultFormat": "time_series"}]}, {"title": "📈 Temperature & Humidity Trend", "type": "row", "gridPos": {"h": + 1, "w": 24, "x": 0, "y": 5}, "collapsed": false}, {"title": "Temperature", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 8, "w": 12, "x": 0, + "y": 6}, "fieldConfig": {"defaults": {"unit": "celsius", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": {"id": "byName", "options": + "Temperature"}, "properties": [{"id": "color", "value": {"fixedColor": "#FF7383", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": "table", "placement": "bottom", "calcs": ["min", "max", + "mean"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "T", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) + => r[\"_measurement\"] == \"°C\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_temperatur\")\n |> aggregateWindow(every: 30m, fn: mean, createEmpty: + false)\n |> yield(name: \"mean\") |> set(key: \"metric\", value: \"Temperature\")", "resultFormat": "time_series"}]}, {"title": "Humidity", "type": "timeseries", "datasource": {"type": "influxdb", + "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 8, "w": 12, "x": 12, "y": 6}, "fieldConfig": {"defaults": {"unit": "percent", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": + "never"}}, "overrides": [{"matcher": {"id": "byName", "options": "Humidity"}, "properties": [{"id": "color", "value": {"fixedColor": "#5794F2", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": + "table", "placement": "bottom", "calcs": ["min", "max", "mean"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "H", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, + stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_luftfeuchtigkeit\")\n |> aggregateWindow(every: + 30m, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"metric\", value: \"Humidity\")", "resultFormat": "time_series"}]}, {"title": "📊 Pressure & Wind", "type": "row", "gridPos": + {"h": 1, "w": 24, "x": 0, "y": 14}, "collapsed": false}, {"title": "Pressure", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 8, "w": 12, "x": + 0, "y": 15}, "fieldConfig": {"defaults": {"unit": "pressurehpa", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": {"id": "byName", "options": + "Pressure"}, "properties": [{"id": "color", "value": {"fixedColor": "#8F3BB8", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": "table", "placement": "bottom", "calcs": ["min", "max", "mean"]}, + "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "P", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] + == \"hPa\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_druck\")\n |> aggregateWindow(every: 30m, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> + set(key: \"metric\", value: \"Pressure\")", "resultFormat": "time_series"}]}, {"title": "Wind Speed", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": + {"h": 8, "w": 12, "x": 12, "y": 15}, "fieldConfig": {"defaults": {"unit": "velocitykmh", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": + {"id": "byName", "options": "Wind"}, "properties": [{"id": "color", "value": {"fixedColor": "#5794F2", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": "table", "placement": "bottom", "calcs": + ["max", "mean"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "W", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: + (r) => r[\"_measurement\"] == \"km/h\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_windgeschwindigkeit\")\n |> aggregateWindow(every: 30m, fn: mean, + createEmpty: false)\n |> yield(name: \"mean\") |> set(key: \"metric\", value: \"Wind\")", "resultFormat": "time_series"}]}, {"title": "🌧️ Precipitation & Cloud", "type": "row", "gridPos": {"h": 1, + "w": 24, "x": 0, "y": 23}, "collapsed": false}, {"title": "Rain", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": 8, "w": 12, "x": 0, "y": 24}, + "fieldConfig": {"defaults": {"unit": "mm/h", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": {"id": "byName", "options": "Rain"}, "properties": + [{"id": "color", "value": {"fixedColor": "#3274D9", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": "table", "placement": "bottom", "calcs": ["mean", "lastNotNull"]}, "tooltip": {"mode": + "multi", "sort": "desc"}}, "targets": [{"refId": "R", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"mm/h\" + and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_niederschlag\")\n |> aggregateWindow(every: 30m, fn: mean, createEmpty: false)\n |> yield(name: \"mean\") |> + set(key: \"metric\", value: \"Rain\")", "resultFormat": "time_series"}]}, {"title": "Cloud Cover", "type": "timeseries", "datasource": {"type": "influxdb", "uid": "P2AB959DC95E5519F"}, "gridPos": {"h": + 8, "w": 12, "x": 12, "y": 24}, "fieldConfig": {"defaults": {"unit": "percent", "custom": {"lineWidth": 2, "fillOpacity": 5, "spanNulls": true, "showPoints": "never"}}, "overrides": [{"matcher": {"id": + "byName", "options": "Cloud Cover"}, "properties": [{"id": "color", "value": {"fixedColor": "#808080", "mode": "fixed"}}]}]}, "options": {"legend": {"displayMode": "table", "placement": "bottom", "calcs": + ["mean"]}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [{"refId": "C", "query": "from(bucket: \"default\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: + (r) => r[\"_measurement\"] == \"%\" and r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r.entity_id == \"regensburg_regensburg_bewolkungsgrad\")\n |> aggregateWindow(every: 30m, fn: mean, createEmpty: + false)\n |> yield(name: \"mean\") |> set(key: \"metric\", value: \"Cloud Cover\")", "resultFormat": "time_series"}]}]}' diff --git a/k8s/monitoring/prometheus-operator.secret.yml b/k8s/monitoring/prometheus-operator.secret.yml index e5ac5d4..ddfe33b 100644 --- a/k8s/monitoring/prometheus-operator.secret.yml +++ b/k8s/monitoring/prometheus-operator.secret.yml @@ -7,12 +7,11 @@ kubeControllerManager: serviceMonitor: https: true insecureSkipVerify: true -# proxy not working, svc not exposed by port kubeProxy: service: targetPort: 10249 serviceMonitor: - https: true + https: false insecureSkipVerify: true ################## @@ -61,6 +60,7 @@ prometheus: storage: 50Gi ingress: enabled: true + ingressClassName: traefik hosts: - prometheus.haumdaucher.de tls: @@ -68,7 +68,7 @@ prometheus: - "prometheus.haumdaucher.de" secretName: prometheus-haumdaucher-de annotations: - kubernetes.io/ingress.class: "nginx" + kubernetes.io/ingress.class: "traefik" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" cert-manager.io/cluster-issuer: "letsencrypt-prod" # see https://kubernetes.github.io/ingress-nginx/examples/auth/basic/ @@ -89,6 +89,7 @@ alertmanager: enabled: true ingress: enabled: true + ingressClassName: traefik hosts: - alertmanager.haumdaucher.de tls: @@ -96,7 +97,7 @@ alertmanager: - "alertmanager.haumdaucher.de" secretName: alertmanager-haumdaucher-de annotations: - kubernetes.io/ingress.class: "nginx" + kubernetes.io/ingress.class: "traefik" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" cert-manager.io/cluster-issuer: "letsencrypt-prod" # see https://kubernetes.github.io/ingress-nginx/examples/auth/basic/ @@ -126,8 +127,31 @@ grafana: imageRenderer: enabled: true adminPassword: kohkohh5sah1Do3ize2x + additionalDataSources: + - name: InfluxDB Home Assistant + type: influxdb + access: proxy + url: http://influxdb-influxdb2.influxdb.svc.cluster.local:80 + jsonData: + version: Flux + organization: influxdata + defaultBucket: default + httpMode: POST + secureJsonData: + token: enaiY9yaiWi6ahv0phoph3FaiphoGh + - name: InfluxDB Home Assistant InfluxQL + type: influxdb + access: proxy + url: http://influxdb-influxdb2.influxdb.svc.cluster.local:80 + jsonData: + dbName: default + httpHeaderName1: 'Authorization' + httpMode: POST + secureJsonData: + httpHeaderValue1: 'Token enaiY9yaiWi6ahv0phoph3FaiphoGh' ingress: enabled: true + ingressClassName: traefik hosts: - grafana.haumdaucher.de tls: @@ -135,7 +159,7 @@ grafana: - "grafana.haumdaucher.de" secretName: grafana-haumdaucher-de annotations: - kubernetes.io/ingress.class: "nginx" + kubernetes.io/ingress.class: "traefik" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" cert-manager.io/cluster-issuer: "letsencrypt-prod" env: @@ -149,4 +173,22 @@ grafana: # interval_day: "MMM YYYY" # interval_month: "YYYY-MM" # interval_year: "YYYY" + sidecar: + dashboards: + enabled: true + label: grafana_dashboard + labelValue: "1" + searchNamespace: monitoring + folder: /tmp/dashboards + defaultFolderName: null + provider: + name: sidecarProvider + orgId: 1 + folder: "" + type: file + disableDeletion: false + editable: false + allowUiUpdates: false + options: + path: /tmp/dashboards diff --git a/k8s/monitoring/scripts/discover-home-assistant.sh b/k8s/monitoring/scripts/discover-home-assistant.sh new file mode 100755 index 0000000..a48fbd0 --- /dev/null +++ b/k8s/monitoring/scripts/discover-home-assistant.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# discover-home-assistant.sh — Query Home Assistant REST API for entity metadata +# Usage: ./discover-home-assistant.sh +# Requires: curl, jq + +set -euo pipefail + +HA_URL="https://hass.moritzgraf.de" +HA_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2NDMyZTI1MDIzZjU0ZmFiYTU3OTc0ODYyMzg3M2ExZSIsImlhdCI6MTc4MjczMTY4NiwiZXhwIjoyMDk4MDkxNjg2fQ.u8kFHoYL2kdhVenfe3BiWcNkN_en3yn91MRGSVJvbmw" + +echo "=== Home Assistant Entity Discovery ===" +echo "URL: $HA_URL" +echo "" + +# Get all entities +echo "→ Fetching all entities..." +ENTITIES=$(curl -s -H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/states") + +if [ -z "$ENTITIES" ] || echo "$ENTITIES" | jq -e '. == null' >/dev/null 2>&1; then + echo "ERROR: Failed to fetch entities. Check token and connectivity." + exit 1 +fi + +echo "" +echo "=== Entity Summary ===" +echo "$ENTITIES" | jq -r ' + [.[] | { + entity_id, + state, + friendly_name: (.attributes.friendly_name // ""), + unit: (.attributes.unit_of_measurement // ""), + device_class: (.attributes.device_class // ""), + domain: (.entity_id | split(".")[0]) + }] + | sort_by(.domain, .entity_id) + | .[] + | "\(.entity_id) | state=\(.state) | name=\(.friendly_name) | unit=\(.unit) | class=\(.device_class) | domain=\(.domain)" +' + +echo "" +echo "=== Domains (entity types) ===" +echo "$ENTITIES" | jq -r '[.[].entity_id | split(".")[0]] | unique | .[]' + +echo "" +echo "=== Entities with unit_of_measurement (likely sensor data in InfluxDB) ===" +echo "$ENTITIES" | jq -r ' + [.[] | select(.attributes.unit_of_measurement != null) | { + entity_id, + unit: .attributes.unit_of_measurement, + friendly_name: (.attributes.friendly_name // ""), + device_class: (.attributes.device_class // "") + }] + | sort_by(.unit, .entity_id) + | .[] + | "\(.entity_id) | \(.unit) | \(.device_class) | \(.friendly_name)" +' + +echo "" +echo "=== Device classes ===" +echo "$ENTITIES" | jq -r '[.[].attributes.device_class | select(. != null)] | unique | .[]' + +echo "" +echo "=== Discovery complete ===" \ No newline at end of file diff --git a/k8s/monitoring/scripts/discover-influxdb.sh b/k8s/monitoring/scripts/discover-influxdb.sh new file mode 100755 index 0000000..c85272f --- /dev/null +++ b/k8s/monitoring/scripts/discover-influxdb.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# discover-influxdb.sh — Query InfluxDB to discover measurements, fields, and tags +# Usage: ./discover-influxdb.sh [namespace] +# Requires: kubectl, curl, jq + +set -euo pipefail + +NAMESPACE="${1:-influxdb}" +INFLUXDB_TOKEN="enaiY9yaiWi6ahv0phoph3FaiphoGh" +INFLUXDB_ORG="influxdata" +INFLUXDB_BUCKET="default" +LOCAL_PORT="8086" + +echo "=== InfluxDB Discovery ===" +echo "Namespace: $NAMESPACE" +echo "" + +# Start port-forward in background +echo "→ Starting port-forward to influxdb-influxdb2..." +kubectl -n "$NAMESPACE" port-forward "svc/influxdb-influxdb2" "$LOCAL_PORT:80" &>/dev/null & +PF_PID=$! +sleep 2 + +# Ensure cleanup on exit +cleanup() { + kill "$PF_PID" 2>/dev/null || true +} +trap cleanup EXIT + +API="http://localhost:$LOCAL_PORT/api/v2/query?org=$INFLUXDB_ORG" +AUTH="Authorization: Token $INFLUXDB_TOKEN" +CT="Content-Type: application/vnd.flux" + +echo "" +echo "=== Measurements (tables) in bucket '$INFLUXDB_BUCKET' ===" +curl -s "$API" -H "$AUTH" -H "$CT" \ + -d "import \"influxdata/influxdb/schema\" + schema.measurements(bucket: \"$INFLUXDB_BUCKET\")" \ + | jq -r '.[] | ._value' 2>/dev/null || echo "(no results or parse error)" + +echo "" +echo "=== Measurements with data in last 6 months ===" +curl -s "$API" -H "$AUTH" -H "$CT" \ + -d "from(bucket: \"$INFLUXDB_BUCKET\") + |> range(start: -6mo) + |> keep(columns: [\"_measurement\"]) + |> distinct() + |> sort()" \ + | jq -r '.[] | ._value' 2>/dev/null || echo "(no results or parse error)" + +echo "" +echo "=== For each measurement: fields, tags, and sample count ===" + +# Get measurements +MEASUREMENTS=$(curl -s "$API" -H "$AUTH" -H "$CT" \ + -d "import \"influxdata/influxdb/schema\" + schema.measurements(bucket: \"$INFLUXDB_BUCKET\")" \ + | jq -r '.[] | ._value' 2>/dev/null) + +for m in $MEASUREMENTS; do + echo "" + echo "--- Measurement: $m ---" + + # Fields + echo " Fields:" + curl -s "$API" -H "$AUTH" -H "$CT" \ + -d "import \"influxdata/influxdb/schema\" + schema.measurementFieldKeys(bucket: \"$INFLUXDB_BUCKET\", measurement: \"$m\")" \ + | jq -r '.[] | " - \(._value)"' 2>/dev/null || echo " (none)" + + # Tags + echo " Tags:" + curl -s "$API" -H "$AUTH" -H "$CT" \ + -d "import \"influxdata/influxdb/schema\" + schema.measurementTagKeys(bucket: \"$INFLUXDB_BUCKET\", measurement: \"$m\")" \ + | jq -r '.[] | " - \(._value)"' 2>/dev/null || echo " (none)" + + # Tag values for entity_id (most common tag in HA data) + echo " entity_id values (sample):" + curl -s "$API" -H "$AUTH" -H "$CT" \ + -d "import \"influxdata/influxdb/schema\" + schema.tagValues(bucket: \"$INFLUXDB_BUCKET\", tag: \"entity_id\") + |> filter(fn: (r) => r._measurement == \"$m\") + |> limit(n: 20)" \ + | jq -r '.[] | " - \(._value)"' 2>/dev/null || echo " (none)" + + # Sample count in last 6 months + echo " Data points (last 6 months):" + curl -s "$API" -H "$AUTH" -H "$CT" \ + -d "from(bucket: \"$INFLUXDB_BUCKET\") + |> range(start: -6mo) + |> filter(fn: (r) => r._measurement == \"$m\") + |> count()" \ + | jq -r '.[] | " - \(._value)"' 2>/dev/null || echo " (none)" +done + +echo "" +echo "=== Discovery complete ===" \ No newline at end of file diff --git a/k8s/tt-rss/tt-rss-mariadb.secret.yml b/k8s/tt-rss/tt-rss-mariadb.secret.yml deleted file mode 100644 index 1a17a9b..0000000 --- a/k8s/tt-rss/tt-rss-mariadb.secret.yml +++ /dev/null @@ -1,10 +0,0 @@ -rootUser: - password: cah6eepai1Saepho8tho - forcePassword: true -db: - name: tt-rss - user: tt-rss - password: AhS5cai7oph3ahN4Aile - forcePassword: true -replication: - enabled: false \ No newline at end of file diff --git a/k8s/tt-rss/tt-rss-phpmyadmin.yml b/k8s/tt-rss/tt-rss-phpmyadmin.yml deleted file mode 100644 index d6f6823..0000000 --- a/k8s/tt-rss/tt-rss-phpmyadmin.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -db: - host: tt-rss-mariadb -ingress: - enabled: true - hosts: - - path: "/" - tls: true - name: "tt-rss.phpmyadmin.haumdaucher.de" - tlsSecret: "tt-rss-phpmyadmin-haumdaucher-de" - annotations: - cert-manager.io/cluster-issuer: "letsencrypt-prod" - nginx.ingress.kubernetes.io/proxy-body-size: "0" \ No newline at end of file diff --git a/k8s/tt-rss/tt-rss.helm.secret.yml b/k8s/tt-rss/tt-rss.helm.secret.yml deleted file mode 100644 index c6c3fcd..0000000 --- a/k8s/tt-rss/tt-rss.helm.secret.yml +++ /dev/null @@ -1,32 +0,0 @@ -env: - # -- External URL you use to connect to the RSS (the one you enter in your browser) - TTRSS_SELF_URL_PATH: "tt-rss.moritzgraf.de" - # -- Postgres database hostname - # @default -- internal postgresql URL - TTRSS_DB_HOST: "tt-rss-mariadb" - # -- Postgres database port. - TTRSS_DB_PORT: "3306" - # -- Postgres database user name - # @default -- postgresql.postgresqlUsername value - TTRSS_DB_USER: "tt-rss" - # -- Postgres database password - # @default -- postgresql.postgresqlPassword value - TTRSS_DB_PASS: "AhS5cai7oph3ahN4Aile" - # -- Postgres database password - # @default -- postgresql.postgresqlDatabase value - TTRSS_DB_NAME: "tt-rss" - -ingress: - main: - enabled: true - annotations: - kubernetes.io/ingress.class: "nginx" - nginx.ingress.kubernetes.io/force-ssl-redirect: "true" - cert-manager.io/cluster-issuer: "letsencrypt-prod" - tls: - - hosts: - - "tt-rss.moritzgraf.de" - secretName: tt-rss-moritzgraf-de -postgresql: - enabled: false - \ No newline at end of file diff --git a/k8s/tt-rss/tt-rss.secret.yaml b/k8s/tt-rss/tt-rss.secret.yaml deleted file mode 100644 index 040e154..0000000 Binary files a/k8s/tt-rss/tt-rss.secret.yaml and /dev/null differ diff --git a/k8s/velero/dropbox_sync.yml b/k8s/velero/dropbox_sync.yml deleted file mode 100644 index b4fae60..0000000 --- a/k8s/velero/dropbox_sync.yml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: batch/v1 -kind: CronJob -metadata: - name: dropbox-sync - namespace: velero -spec: - schedule: "0 5 * * *" - jobTemplate: - spec: - template: - spec: - serviceAccountName: default - containers: - - name: dopybox-sync - image: iptizer/swiss - volumeMounts: - - name: rclone-config - mountPath: /rclone.secret - subPath: "rclone.secret" - command: - - "devbox" - - "run" - args: - - "rclone --config /rclone.secret -v copy minio:backup/ dropbox:server_backup/velero/" - volumes: - - name: rclone-config - secret: - secretName: rclone-config - restartPolicy: Never \ No newline at end of file diff --git a/k8s/velero/gdrive_sa.json.secret b/k8s/velero/gdrive_sa.json.secret new file mode 100755 index 0000000..2fa38ee Binary files /dev/null and b/k8s/velero/gdrive_sa.json.secret differ diff --git a/k8s/velero/gdrive_sync.yml b/k8s/velero/gdrive_sync.yml new file mode 100644 index 0000000..4a076bb --- /dev/null +++ b/k8s/velero/gdrive_sync.yml @@ -0,0 +1,39 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: gdrive-sync + namespace: velero +spec: + schedule: "0 5 * * *" + jobTemplate: + spec: + template: + spec: + serviceAccountName: default + containers: + - name: gdrive-sync + image: rclone/rclone:latest + volumeMounts: + - name: rclone-config + mountPath: /rclone.secret + subPath: "rclone.secret" + - name: gdrive-sa-key + mountPath: /gdrive_sa.json.secret + subPath: "gdrive_sa.json.secret" + command: + - "rclone" + args: + - "--config" + - "/rclone.secret" + - "-v" + - "sync" + - "minio:backup/" + - "gdrivemoritz:" + volumes: + - name: rclone-config + secret: + secretName: rclone-config + - name: gdrive-sa-key + secret: + secretName: gdrive-sa-key + restartPolicy: Never diff --git a/k8s/velero/gdrive_sync_manual_job.yml b/k8s/velero/gdrive_sync_manual_job.yml new file mode 100644 index 0000000..6afa7ff --- /dev/null +++ b/k8s/velero/gdrive_sync_manual_job.yml @@ -0,0 +1,36 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: gdrive-sync-manual + namespace: velero +spec: + template: + spec: + serviceAccountName: default + containers: + - name: gdrive-sync + image: rclone/rclone:latest + volumeMounts: + - name: rclone-config + mountPath: /rclone.secret + subPath: "rclone.secret" + - name: gdrive-sa-key + mountPath: /gdrive_sa.json.secret + subPath: "gdrive_sa.json.secret" + command: + - "rclone" + args: + - "--config" + - "/rclone.secret" + - "-v" + - "sync" + - "minio:backup/" + - "gdrivemoritz:" + volumes: + - name: rclone-config + secret: + secretName: rclone-config + - name: gdrive-sa-key + secret: + secretName: gdrive-sa-key + restartPolicy: Never diff --git a/k8s/velero/rclone.secret b/k8s/velero/rclone.secret index c0dad08..15596ec 100644 Binary files a/k8s/velero/rclone.secret and b/k8s/velero/rclone.secret differ diff --git a/k8s/velero/values_12.1.0_default.yaml b/k8s/velero/values_12.1.0_default.yaml new file mode 100644 index 0000000..cea4b7f --- /dev/null +++ b/k8s/velero/values_12.1.0_default.yaml @@ -0,0 +1,828 @@ +## +## Configuration settings related to Velero installation namespace +## + +# Labels settings in namespace +namespace: + labels: {} + # Enforce Pod Security Standards with Namespace Labels + # https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/ + # pod-security.kubernetes.io/enforce: privileged + # pod-security.kubernetes.io/enforce-version: latest + # pod-security.kubernetes.io/audit: privileged + # pod-security.kubernetes.io/audit-version: latest + # pod-security.kubernetes.io/warn: privileged + # pod-security.kubernetes.io/warn-version: latest + +## +## End of namespace-related settings. +## + + +## +## Configuration settings that directly affect the Velero deployment YAML. +## + +# Details of the container image to use in the Velero deployment & daemonset (if +# enabling node-agent). Required. +image: + repository: docker.io/velero/velero + tag: v1.18.1 + # Digest value example: sha256:73266e6bd7e2fe3f65fb20677d36c4a8df76d417d9ba76bd9932e0d983a776ec. + # If used, it will take precedence over the image.tag. + # digest: + pullPolicy: IfNotPresent + # One or more secrets to be used when pulling images + imagePullSecrets: [] + # - registrySecretName + +nameOverride: "" +fullnameOverride: "" + +# Annotations to add to the Velero deployment's. Optional. +# +# If you are using reloader use the following annotation with your VELERO_SECRET_NAME +annotations: {} +# secret.reloader.stakater.com/reload: "" + +# Annotations to add to secret +secretAnnotations: {} + +# Labels to add to the Velero deployment's. Optional. +labels: {} + +# Annotations to add to the Velero deployment's pod template. Optional. +# +# If using kube2iam or kiam, use the following annotation with your AWS_ACCOUNT_ID +# and VELERO_ROLE_NAME filled in: +podAnnotations: {} + # iam.amazonaws.com/role: "arn:aws:iam:::role/" + +# Additional pod labels for Velero deployment's template. Optional +# ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +podLabels: {} + +# Number of old history to retain to allow rollback (If not set, default Kubernetes value is set to 10) +# revisionHistoryLimit: 1 + +# Resource requests/limits to specify for the Velero deployment. +# https://velero.io/docs/v1.6/customize-installation/#customize-resource-requests-and-limits +resources: {} + # requests: + # cpu: 500m + # memory: 128Mi + # limits: + # cpu: 1000m + # memory: 512Mi + +# Container resize policy for the Velero deployment. +# See: https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/ +resizePolicy: [] + # - resourceName: cpu + # restartPolicy: NotRequired + # - resourceName: memory + # restartPolicy: RestartContainer + +# Configure hostAliases for Velero deployment. Optional +# For more information, check: https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ +hostAliases: [] + # - ip: "127.0.0.1" + # hostnames: + # - "foo.local" + # - "bar.local" + +# Resource requests/limits to specify for the upgradeCRDs job pod. Need to be adjusted by user accordingly. +upgradeJobResources: {} +# requests: +# cpu: 50m +# memory: 128Mi +# limits: +# cpu: 100m +# memory: 256Mi +upgradeCRDsJob: + # Extra volumes for the Upgrade CRDs Job. Optional. + extraVolumes: [] + # Extra volumeMounts for the Upgrade CRDs Job. Optional. + extraVolumeMounts: [] + # Additional values to be used as environment variables. Optional. + extraEnvVars: [] + # Simple value + # - name: SIMPLE_VAR + # value: "simple-value" + + # FieldRef example + # - name: MY_POD_LABEL + # valueFrom: + # fieldRef: + # fieldPath: metadata.labels['my_label'] + + # Configure if API credential for Service Account is automounted. + automountServiceAccountToken: true + # Configure the shell cmd in case you are using custom image + # shellCmd: /tmp/sh + # updateCmd: /velero install --crds-only --dry-run -o yaml | /tmp/kubectl apply -f - + +# Configure the dnsPolicy of the Velero deployment +# See: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy +dnsPolicy: ClusterFirst + +# Init containers to add to the Velero deployment's pod spec. At least one plugin provider image is required. +# If the value is a string then it is evaluated as a template. +initContainers: + # - name: velero-plugin-for-aws + # image: velero/velero-plugin-for-aws:v1.13.1 + # imagePullPolicy: IfNotPresent + # volumeMounts: + # - mountPath: /target + # name: plugins + +# SecurityContext to use for the Velero deployment. Optional. +# Set fsGroup for `AWS IAM Roles for Service Accounts` +# see more informations at: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html +podSecurityContext: {} + # fsGroup: 1337 + +# Container Level Security Context for the 'velero' container of the Velero deployment. Optional. +# See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +containerSecurityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: ["ALL"] + # add: [] + # readOnlyRootFilesystem: true + +# Container Lifecycle Hooks to use for the Velero deployment. Optional. +lifecycle: {} + +# Pod priority class name to use for the Velero deployment. Optional. +priorityClassName: "" + +# Pod runtime class name to use for the Velero deployment. Optional. +runtimeClassName: "" + +# The number of seconds to allow for graceful termination of the pod. Optional. +terminationGracePeriodSeconds: 3600 + +# Liveness probe of the pod +livenessProbe: + httpGet: + path: /metrics + port: http-monitoring + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 30 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + +# Readiness probe of the pod +readinessProbe: + httpGet: + path: /metrics + port: http-monitoring + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 30 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + +# Tolerations to use for the Velero deployment. Optional. +tolerations: [] + +# Affinity to use for the Velero deployment. Optional. +affinity: {} + +# Node selector to use for the Velero deployment. Optional. +nodeSelector: {} + +# DNS configuration to use for the Velero deployment. Optional. +dnsConfig: {} + +# Pod Disruption Budget for the Velero deployment. Optional. +# Velero runs a single replica with a Recreate strategy by default, so this is +# disabled by default. Enable it when running Velero with multiple replicas. +podDisruptionBudget: + enabled: false + # minAvailable and maxUnavailable are mutually exclusive; set only one. + minAvailable: 1 + maxUnavailable: "" + # See https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + # unhealthyPodEvictionPolicy: IfHealthyBudget + annotations: {} + labels: {} + +# Extra volumes for the Velero deployment. Optional. +extraVolumes: [] + +# Extra volumeMounts for the Velero deployment. Optional. +extraVolumeMounts: [] + +# Extra K8s manifests to deploy +extraObjects: [] + # - apiVersion: secrets-store.csi.x-k8s.io/v1 + # kind: SecretProviderClass + # metadata: + # name: velero-secrets-store + # spec: + # provider: aws + # parameters: + # objects: | + # - objectName: "velero" + # objectType: "secretsmanager" + # jmesPath: + # - path: "access_key" + # objectAlias: "access_key" + # - path: "secret_key" + # objectAlias: "secret_key" + # secretObjects: + # - data: + # - key: access_key + # objectName: client-id + # - key: client-secret + # objectName: client-secret + # secretName: velero-secrets-store + # type: Opaque + +# Settings for Velero's prometheus metrics. Enabled by default. +metrics: + enabled: true + scrapeInterval: 30s + scrapeTimeout: 10s + + # service metdata if metrics are enabled + service: + annotations: {} + type: ClusterIP + labels: {} + nodePort: null + + # External/Internal traffic policy setting (Cluster, Local) + # https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-policies + externalTrafficPolicy: "" + internalTrafficPolicy: "" + + # the IP family policy for the metrics Service to be able to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). + ipFamilyPolicy: "" + # a list of IP families for the metrics Service that should be supported, in the order in which they should be applied to ClusterIP. Can be "IPv4" and/or "IPv6". + ipFamilies: [] + + # Pod annotations for Prometheus + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8085" + prometheus.io/path: "/metrics" + + serviceMonitor: + autodetect: true + enabled: false + annotations: {} + additionalLabels: {} + + # metrics.serviceMonitor.metricRelabelings Specify Metric Relabelings to add to the scrape endpoint + # ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + # metricRelabelings: [] + # metrics.serviceMonitor.relabelings [array] Prometheus relabeling rules + # relabelings: [] + # ServiceMonitor namespace. Default to Velero namespace. + # namespace: + # ServiceMonitor connection scheme. Defaults to HTTP. + # scheme: "" + # ServiceMonitor connection tlsConfig. Defaults to {}. + # tlsConfig: {} + nodeAgentPodMonitor: + autodetect: true + enabled: false + annotations: {} + additionalLabels: {} + # metrics.nodeAgentPodMonitor.metricRelabelings Specify Metric Relabelings to add to the scrape endpoint + # ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + # metricRelabelings: [] + # metrics.nodeAgentPodMonitor.relabelings [array] Prometheus relabeling rules + # relabelings: [] + # PodMonitor namespace. Default to Velero namespace. + # namespace: + # PodMonitor connection scheme. Defaults to HTTP. + # scheme: "" + # PodMonitor connection tlsConfig. Defaults to {}. + # tlsConfig: {} + + prometheusRule: + autodetect: true + enabled: false + # Additional labels to add to deployed PrometheusRule + additionalLabels: {} + # PrometheusRule namespace. Defaults to Velero namespace. + # namespace: "" + # Rules to be deployed + spec: [] + # - alert: VeleroBackupFailed + # annotations: + # message: Velero backup {{ $labels.schedule }} has failed + # expr: |- + # velero_backup_last_status{schedule!=""} != 1 + # for: 15m + # labels: + # severity: warning + # - alert: VeleroBackupFailing + # annotations: + # message: Velero backup {{ $labels.schedule }} has been failing for the last 12h + # expr: |- + # velero_backup_last_status{schedule!=""} != 1 + # for: 12h + # labels: + # severity: critical + # - alert: VeleroNoNewBackup + # annotations: + # message: Velero backup {{ $labels.schedule }} has not run successfully in the last 25h + # expr: |- + # ( + # (time() - velero_backup_last_successful_timestamp{schedule!=""}) >bool (25 * 3600) + # or + # absent(velero_backup_last_successful_timestamp{schedule!=""}) + # ) == 1 + # for: 1h + # labels: + # severity: critical + # - alert: VeleroBackupPartialFailures + # annotations: + # message: Velero backup {{ $labels.schedule }} has {{ $value | humanizePercentage }} partialy failed backups + # expr: |- + # rate(velero_backup_partial_failure_total{schedule!=""}[25m]) + # / rate(velero_backup_attempt_total{schedule!=""}[25m]) > 0.5 + # for: 15m + # labels: + # severity: warning + +kubectl: + image: + repository: registry.k8s.io/kubectl + # Digest value example: sha256:c7bf8cf6e79f474fda2623a7b98572a1b909c4d912b05062b444ffe79883fdbe. + # If used, it will take precedence over the kubectl.image.tag. + # digest: + # kubectl image tag. If used, it will take precedence over the cluster Kubernetes version. + # tag: v1.34.5 + # Container Level Security Context for the 'kubectl' container of the crd jobs. Optional. + # See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + containerSecurityContext: {} + # Resource requests/limits to specify for the upgrade/cleanup job. Optional + resources: {} + # Annotations to set for the upgrade/cleanup job. Optional. + annotations: {} + # Labels to set for the upgrade/cleanup job. Optional. + labels: {} + # Extra volumes for the upgrade/cleanup job. Optional. + extraVolumes: [] + # Extra volumeMounts for the upgrade/cleanup job. Optional. + extraVolumeMounts: [] + +# This job upgrades the CRDs. +upgradeCRDs: true + +# This job is meant primarily for cleaning up CRDs on CI systems. +# Using this on production systems, especially those that have multiple releases of Velero, will be destructive. +cleanUpCRDs: false + +## +## End of deployment-related settings. +## + + +## +## Parameters for the `default` BackupStorageLocation and VolumeSnapshotLocation, +## and additional server settings. +## +configuration: + # Parameters for the BackupStorageLocation(s). Configure multiple by adding other element(s) to the backupStorageLocation slice. + # See https://velero.io/docs/v1.6/api-types/backupstoragelocation/ + backupStorageLocation: + # name is the name of the backup storage location where backups should be stored. If a name is not provided, + # a backup storage location will be created with the name "default". Optional. + - name: + # provider is the name for the backup storage location provider. + provider: "" + # bucket is the name of the bucket to store backups in. Required. + bucket: "" + # caCert defines a base64 encoded CA bundle to use when verifying TLS connections to the provider. Optional. + caCert: + # prefix is the directory under which all Velero data should be stored within the bucket. Optional. + prefix: + # default indicates this location is the default backup storage location. Optional. + default: false + # validationFrequency defines how frequently Velero should validate the object storage. Optional. + validationFrequency: + # backupSyncPeriod defines how frequently Velero should synchronize backups in object storage. Optional. + backupSyncPeriod: + # accessMode determines if velero can write to this backup storage location. Optional. + # default to ReadWrite, ReadOnly is used during migrations and restores. + accessMode: ReadWrite + credential: + # name of the secret used by this backupStorageLocation. + name: + # name of key that contains the secret data to be used. + key: + # Additional provider-specific configuration. See link above + # for details of required/optional fields for your provider. + config: {} + # region: + # s3ForcePathStyle: + # s3Url: + # kmsKeyId: + # resourceGroup: + # The ID of the subscription containing the storage account, if different from the cluster’s subscription. (Azure only) + # subscriptionId: + # storageAccount: + # publicUrl: + # Name of the GCP service account to use for this backup storage location. Specify the + # service account here if you want to use workload identity instead of providing the key file.(GCP only) + # serviceAccount: + # Option to skip certificate validation or not if insecureSkipTLSVerify is set to be true, the client side should set the + # flag. For Velero client Command like velero backup describe, velero backup logs needs to add the flag --insecure-skip-tls-verify + # insecureSkipTLSVerify: + + # annotations allows adding arbitrary annotations to this BackupStorageLocation resource. Optional. + annotations: {} + + # Parameters for the VolumeSnapshotLocation(s). Configure multiple by adding other element(s) to the volumeSnapshotLocation slice. + # See https://velero.io/docs/v1.6/api-types/volumesnapshotlocation/ + volumeSnapshotLocation: + # name is the name of the volume snapshot location where snapshots are being taken. If a name is not provided, + # a volume snapshot location will be created with the name "default". Optional. + - name: + # provider is the name for the volume snapshot provider. + provider: "" + credential: + # name of the secret used by this volumeSnapshotLocation. + name: + # name of key that contains the secret data to be used. + key: + # Additional provider-specific configuration. See link above + # for details of required/optional fields for your provider. + config: {} + # region: + # apiTimeout: + # resourceGroup: + # The ID of the subscription where volume snapshots should be stored, if different from the cluster’s subscription. If specified, also requires `configuration.volumeSnapshotLocation.config.resourceGroup`to be set. (Azure only) + # subscriptionId: + # incremental: + # snapshotLocation: + # project: + + # annotations allows adding arbitrary annotations to this VolumeSnapshotLocation resource. Optional. + annotations: {} + + # These are server-level settings passed as CLI flags to the `velero server` command. Velero + # uses default values if they're not passed in, so they only need to be explicitly specified + # here if using a non-default value. The `velero server` default values are shown in the + # comments below. + # -------------------- + # `velero server` default: kopia + uploaderType: + # `velero server` default: 1m + backupSyncPeriod: + # `velero server` default: 4h + fsBackupTimeout: + # `velero server` default: 30 + clientBurst: + # `velero server` default: 500 + clientPageSize: + # `velero server` default: 20.0 + clientQPS: + # Name of the default backup storage location. Default: default + defaultBackupStorageLocation: + # The default duration any single item operation can take before timing out, especially important for large volume schedules. Default 4h + defaultItemOperationTimeout: + # How long to wait by default before backups can be garbage collected. Default: 72h + defaultBackupTTL: + # Name of the default volume snapshot location. + defaultVolumeSnapshotLocations: + # `velero server` default: empty + disableControllers: + # `velero server` default: false + disableInformerCache: false + # `velero server` default: 1h + garbageCollectionFrequency: + # `velero server` default: 1 + itemBlockWorkerCount: + # Set log-format for Velero pod. Default: text. Other option: json. + logFormat: + # Set log-level for Velero pod. Default: info. Other options: debug, warning, error, fatal, panic. + logLevel: + # The address to expose prometheus metrics. Default: :8085 + metricsAddress: + # Directory containing Velero plugins. Default: /plugins + pluginDir: + # The address to expose the pprof profiler. Default: localhost:6060 + profilerAddress: + # `velero server` default: false + restoreOnlyMode: + # `velero server` default: customresourcedefinitions,namespaces,storageclasses,volumesnapshotclass.snapshot.storage.k8s.io,volumesnapshotcontents.snapshot.storage.k8s.io,volumesnapshots.snapshot.storage.k8s.io,persistentvolumes,persistentvolumeclaims,secrets,configmaps,serviceaccounts,limitranges,pods,replicasets.apps,clusterclasses.cluster.x-k8s.io,clusters.cluster.x-k8s.io,clusterresourcesets.addons.cluster.x-k8s.io + restoreResourcePriorities: + # `velero server` default: 1m + storeValidationFrequency: + # How long to wait on persistent volumes and namespaces to terminate during a restore before timing out. Default: 10m + terminatingResourceTimeout: + # Bool flag to configure Velero server to move data by default for all snapshots supporting data movement. Default: false + defaultSnapshotMoveData: + # Comma separated list of velero feature flags. default: empty + # features: EnableCSI + features: + # Configures the timeout for provisioning the volume created from the CSI snapshot. Default: 30m + dataMoverPrepareTimeout: + # Resource requests/limits to specify for the repository-maintenance job. Optional. + # https://velero.io/docs/v1.14/repository-maintenance/#resource-limitation + repositoryMaintenanceJob: + # Per-repository resource settings ConfigMap + # This ConfigMap allows specifying different settings for different repositories + # See: https://velero.io/docs/main/repository-maintenance/ + repositoryConfigData: + # Name of the ConfigMap to create. If not provided, will use "velero-repo-maintenance" + name: "velero-repo-maintenance" + # Global configuration applied to all repositories + # This configuration is used when no specific repository configuration is found + # global: + # podResources: + # cpuRequest: "100m" + # cpuLimit: "200m" + # memoryRequest: "100Mi" + # memoryLimit: "200Mi" + # keepLatestMaintenanceJobs: 1 + # loadAffinity: + # - nodeSelector: + # matchExpressions: + # - key: "cloud.google.com/machine-family" + # operator: "In" + # values: ["e2"] + # - nodeSelector: + # matchExpressions: + # - key: "topology.kubernetes.io/zone" + # operator: "In" + # values: ["us-central1-a", "us-central1-b", "us-central1-c"] + # priorityClassName: "low-priority" # Note: priorityClassName is only supported in global configuration + global: + keepLatestMaintenanceJobs: 3 + # Repository-specific configurations + # Repository keys are formed as: "{namespace}-{storageLocation}-{repositoryType}" + # For example: "default-default-kopia" or "prod-s3-backup-kopia" + # Note: priorityClassName is NOT supported in repository-specific configurations + # repositories: + # "kibishii-default-kopia": + # podResources: + # cpuRequest: "200m" + # cpuLimit: "400m" + # memoryRequest: "200Mi" + # memoryLimit: "400Mi" + # keepLatestMaintenanceJobs: 2 + repositories: {} + # `velero server` default: velero + namespace: + # additional command-line arguments that will be passed to the `velero server` + # e.g.: extraArgs: ["--foo=bar"] + extraArgs: [] + + # Additional values to be used as environment variables. Optional. + extraEnvVars: [] + # Simple value + # - name: SIMPLE_VAR + # value: "simple-value" + + # FieldRef example + # - name: MY_POD_LABEL + # valueFrom: + # fieldRef: + # fieldPath: metadata.labels['my_label'] + + # Set true for backup all pod volumes without having to apply annotation on the pod when used file system backup Default: false. + defaultVolumesToFsBackup: + + # How often repository maintain is run for repositories by default. + defaultRepoMaintainFrequency: + +## +## End of backup/snapshot location settings. +## + + +## +## Settings for additional Velero resources. +## + +rbac: + # Whether to create the Velero role and role binding to give all permissions to the namespace to Velero. + create: true + # Whether to create the cluster role binding to give administrator permissions to Velero + clusterAdministrator: true + # Name of the ClusterRole. + clusterAdministratorName: cluster-admin + +# Information about the Kubernetes service account Velero uses. +serviceAccount: + server: + create: true + name: + annotations: + labels: + imagePullSecrets: [] + # - registrySecretName + # Configure if API credential for Service Account is automounted. + automountServiceAccountToken: true + +# Info about the secret to be used by the Velero deployment, which +# should contain credentials for the cloud provider IAM account you've +# set up for Velero. +credentials: + # Whether a secret should be used. Set to false if, for examples: + # - using kube2iam or kiam to provide AWS IAM credentials instead of providing the key file. (AWS only) + # - using workload identity instead of providing the key file. (Azure/GCP only) + useSecret: true + # Name of the secret to create if `useSecret` is true and `existingSecret` is empty + name: + # Name of a pre-existing secret (if any) in the Velero namespace + # that should be used to get IAM account credentials. Optional. + existingSecret: + # Data to be stored in the Velero secret, if `useSecret` is true and `existingSecret` is empty. + # As of the current Velero release, Velero only uses one secret key/value at a time. + # The key must be named `cloud`, and the value corresponds to the entire content of your IAM credentials file. + # Note that the format will be different for different providers, please check their documentation. + # Here is a list of documentation for plugins maintained by the Velero team: + # [AWS] https://github.com/vmware-tanzu/velero-plugin-for-aws/blob/main/README.md + # [GCP] https://github.com/vmware-tanzu/velero-plugin-for-gcp/blob/main/README.md + # [Azure] https://github.com/vmware-tanzu/velero-plugin-for-microsoft-azure/blob/main/README.md + secretContents: {} + # cloud: | + # [default] + # aws_access_key_id= + # aws_secret_access_key= + # additional key/value pairs to be used as environment variables such as "DIGITALOCEAN_TOKEN: ". Values will be stored in the secret. + extraEnvVars: {} + # Name of a pre-existing secret (if any) in the Velero namespace + # that will be used to load environment variables into velero and node-agent. + # Secret should be in format - https://kubernetes.io/docs/concepts/configuration/secret/#use-case-as-container-environment-variables + extraSecretRef: "" + +# Whether to create backupstoragelocation crd, if false => do not create a default backup location +backupsEnabled: true +# Whether to create volumesnapshotlocation crd, if false => disable snapshot feature +snapshotsEnabled: true + +# Whether to deploy the node-agent daemonset. +deployNodeAgent: false + +nodeAgent: + # Disables Host Path volumes for node-agent. + disableHostPath: false + podVolumePath: /var/lib/kubelet/pods + pluginVolumePath: /var/lib/kubelet/plugins + # Pod priority class name to use for the node-agent daemonset. Optional. + priorityClassName: "" + # Pod runtime class name to use for the node-agent daemonset. Optional. + runtimeClassName: "" + # Resource requests/limits to specify for the node-agent daemonset deployment. Optional. + # https://velero.io/docs/v1.6/customize-installation/#customize-resource-requests-and-limits + resources: {} + # requests: + # cpu: 500m + # memory: 512Mi + # limits: + # cpu: 1000m + # memory: 1024Mi + # Container resize policy for the node-agent daemonset. + # See: https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/ + resizePolicy: [] + # - resourceName: cpu + # restartPolicy: NotRequired + # - resourceName: memory + # restartPolicy: RestartContainer + + # Tolerations to use for the node-agent daemonset. Optional. + tolerations: [] + + # Annotations to set for the node-agent daemonset. Optional. + annotations: {} + + # labels to set for the node-agent daemonset. Optional. + labels: {} + + # Additional pod labels for the node-agent daemonset. Optional + # ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + podLabels: {} + + # will map /scratch to emptyDir. Set to false and specify your own volume + # via extraVolumes and extraVolumeMounts that maps to /scratch + # if you don't want to use emptyDir. + useScratchEmptyDir: true + + # Extra volumes for the node-agent daemonset. Optional. + extraVolumes: [] + + # Extra volumeMounts for the node-agent daemonset. Optional. + extraVolumeMounts: [] + + # Additional values to be used as environment variables for node-agent daemonset. Optional. + extraEnvVars: [] + # Simple key/value + # - name: SIMPLE_VAR + # value: "simple-value" + + # FieldRef example + # - name: MY_POD_LABEL + # valueFrom: + # fieldRef: + # fieldPath: metadata.labels['my_label'] + + # Additional command-line arguments that will be passed to the node-agent. Optional. + # e.g.: extraArgs: ["--foo=bar"] + extraArgs: [] + + # Configure the dnsPolicy of the node-agent daemonset + # See: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy + dnsPolicy: ClusterFirst + + # Configure hostAliases for node-agent daemonset. Optional + # For more information, check: https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ + hostAliases: [] + # - ip: "127.0.0.1" + # hostnames: + # - "foo.local" + # - "bar.local" + + # SecurityContext to use for the Velero deployment. Optional. + # Set fsGroup for `AWS IAM Roles for Service Accounts` + # see more informations at: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html + podSecurityContext: + runAsUser: 0 + # fsGroup: 1337 + + # Container Level Security Context for the 'node-agent' container of the node-agent daemonset. Optional. + # See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + containerSecurityContext: {} + + # Container Lifecycle Hooks to use for the node-agent daemonset. Optional. + lifecycle: {} + + # Node selector to use for the node-agent daemonset. Optional. + nodeSelector: {} + + # Affinity to use with node-agent daemonset. Optional. + affinity: {} + + # DNS configuration to use for the node-agent daemonset. Optional. + dnsConfig: {} + + # Update strategy to use for the node-agent daemonset. Optional. + updateStrategy: {} + +# Backup schedules to create. +# Eg: +# schedules: +# mybackup: +# disabled: false +# labels: +# myenv: foo +# annotations: +# myenv: foo +# schedule: "0 0 * * *" +# useOwnerReferencesInBackup: false +# paused: false +# skipImmediately: false +# template: +# ttl: "240h" +# storageLocation: default +# includedNamespaces: +# - foo +# # See: https://velero.io/docs/v1.14/resource-filtering/#excludes +# excludedNamespaceScopedResources: +# - persistentVolumeClaims +# excludedClusterScopedResources: +# - persistentVolumes +schedules: {} + +# Velero ConfigMaps. +# Eg: +# configMaps: + # See: https://velero.io/docs/v1.11/file-system-backup/ +# fs-restore-action-config: +# labels: +# velero.io/plugin-config: "" +# velero.io/pod-volume-restore: RestoreItemAction +# data: +# image: velero/velero:v1.17.1 +# cpuRequest: 200m +# memRequest: 128Mi +# cpuLimit: 200m +# memLimit: 128Mi +# secCtx: | +# capabilities: +# drop: +# - ALL +# add: [] +# allowPrivilegeEscalation: false +# readOnlyRootFilesystem: true +# runAsUser: 1001 +# runAsGroup: 999 +configMaps: {} + +## +## End of additional Velero resource settings. +## + diff --git a/k8s/velero/velero.secret.yaml b/k8s/velero/velero.secret.yaml index 1a479f4..4943736 100644 Binary files a/k8s/velero/velero.secret.yaml and b/k8s/velero/velero.secret.yaml differ diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl index 6e9d8a5..010d1ed 100644 --- a/terraform/.terraform.lock.hcl +++ b/terraform/.terraform.lock.hcl @@ -1,4 +1,4 @@ -# This file is maintained automatically by "tofu init". +# This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. provider "registry.opentofu.org/ovh/ovh" { @@ -21,3 +21,84 @@ provider "registry.opentofu.org/ovh/ovh" { "zh:f953ef37e4a1b3cac22f851c3269e7376704018ffa642b4768869cc227ffccc9", ] } + +provider "registry.terraform.io/hashicorp/google" { + version = "5.45.2" + constraints = "~> 5.0" + hashes = [ + "h1:y2hf6zus1eKA5vpAfoyYkNBKDBQTVqmx4OVh3iRBaRo=", + "zh:0d09c8f20b556305192cdbe0efa6d333ceebba963a8ba91f9f1714b5a20c4b7a", + "zh:117143fc91be407874568df416b938a6896f94cb873f26bba279cedab646a804", + "zh:16ccf77d18dd2c5ef9c0625f9cf546ebdf3213c0a452f432204c69feed55081e", + "zh:3e555cf22a570a4bd247964671f421ed7517970cd9765ceb46f335edc2c6f392", + "zh:688bd5b05a75124da7ae6e885b2b92bd29f4261808b2b78bd5f51f525c1052ca", + "zh:6db3ef37a05010d82900bfffb3261c59a0c247e0692049cb3eb8c2ef16c9d7bf", + "zh:70316fde75f6a15d72749f66d994ccbdde5f5ed4311b6d06b99850f698c9bbf9", + "zh:84b8e583771a4f2bd514e519d98ed7fd28dce5efe0634e973170e1cfb5556fb4", + "zh:9d4b8ef0a9b6677935c604d94495042e68ff5489932cfd1ec41052e094a279d3", + "zh:a2089dd9bd825c107b148dd12d6b286f71aa37dfd4ca9c35157f2dcba7bc19d8", + "zh:f03d795c0fd9721e59839255ee7ba7414173017dc530b4ce566daf3802a0d6dd", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.9.0" + constraints = "~> 2.0" + hashes = [ + "h1:oF4vw1rikPMqQtMMBoUjc/pERp50DlWwO+C2I6/sNI8=", + "zh:0baa4566cf77f1ff52f4293d1c8536202dd23edc197c3196413a28343c3ac3a0", + "zh:16b5559c3c07088ddad11a9bb9e9c0799999363c2958e9a5be2bcbbf2cd9ca64", + "zh:197c79015a10d1cce904a8ea722cbc750c42aeae2da53f44a6a0751d9fd1aa90", + "zh:29d0b03e5343a80677ebfeb2e2c31cbe4b1f65e736e53417454a4277fec2544c", + "zh:4896bfa6cf1d2fd562b47ef2e87f47862ae92a04f8ad5d764380f0c6653473b8", + "zh:531f8529cbca49f681883e57761a05a8398afaef6d1ab0d205d26bf12f4428e8", + "zh:6aaf5011d83161c86d2bfb80c0923ec934e578288758da2f37acb7aec129004b", + "zh:7430275253d3d3c40aa6179e0ec0d63212874dbbc06c5a51b9d07ec590f9756c", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:be17dc611e95e26cdf6cad79dfccf1064f0e32032a2efeb939a9bbe7fb1cbfe9", + "zh:f0e3b0aa644202e1d79d2000dca91f6019425da71e9800fa23f27e51c034f195", + "zh:f62bae4519e4ead49182ddc8afe8cf61e2a4c3ba3973b0fbba967736a2696aa3", + "zh:fcafa360a5b0b96244f26f4e3a6d642b716a376557142c2442ff2fb12d11da18", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.9.0" + hashes = [ + "h1:o0s5Mk9NXMP60nlheO1r0LsDGGratFb3oL0t7bD2QnM=", + "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1", + "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea", + "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f", + "zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0", + "zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61", + "zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc", + "zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e", + "zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef", + "zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b", + "zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257", + "zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04", + ] +} + +provider "registry.terraform.io/ovh/ovh" { + version = "2.15.0" + hashes = [ + "h1:Y6pQdKjn1OR4wNlxRpy+nI7Dvap/bKzFb68fynMxTmI=", + "zh:22d361f99caa70b07532fce13208fce8b84072cf83eaf6ddfcd9096df88b57ea", + "zh:497f88936649d3c352fdb639ba5ebdabfec8ec7a59d67bf619013e3afbbaefb4", + "zh:62e49208e2950daf366b396694dc7de5bba31a8b7a10aac7c021f2c78fd64f70", + "zh:97e06f7494706df30c136f4809314d92a25129738cf080e22c5c9e47ec70c4cf", + "zh:be23cf1ecb2eb76c60dad72eb4f9d005c6184cae6e2cf9f13b0462030133644c", + "zh:bf60c1af6db5ca51ff4372fee8e64a21462134d281ae9cb3968ca5b209338c4b", + "zh:c9e5ad5c063249786595c5b6c3f59791bd21f5157ff0572a4ed2d52ca8141c50", + "zh:d2bf2603741df6fc29a88384f7026fb8b0e982b8a270796e672037d287b41e83", + "zh:d944de8032fc01d8488087755bf7fb813e7b8c259e23a7b68ed654905ad19b56", + "zh:dcf2a7620abac38e9d8f0a88f2a79de0fddd917ba0facba1108f6581eb1b7f6f", + "zh:e7c7905954f69f0d5b6cf9bd87572101924e128aa33311856dbbfedd711361d2", + "zh:f6a9977d744ed879a0b3c28a5a800b6a1f49aabe8d71e87ca1d02fe6a77a31ba", + "zh:fd0e48de826df04e18489d33b0ff35bd776cb6e7704188f67dad66cbb041e5af", + ] +} diff --git a/terraform/gcp_backups.tf b/terraform/gcp_backups.tf new file mode 100644 index 0000000..9520705 --- /dev/null +++ b/terraform/gcp_backups.tf @@ -0,0 +1,56 @@ +variable "gcp_project_id" { + type = string + description = "The GCP Project ID where the Service Account should be created. If empty, a new project named 'velero-backup-xxxx' will be created." + default = "" +} + +resource "random_id" "project_suffix" { + byte_length = 4 +} + +resource "google_project" "backup_project" { + count = var.gcp_project_id == "" ? 1 : 0 + name = "velero-backup" + project_id = "velero-backup-${random_id.project_suffix.hex}" +} + +locals { + project_id = var.gcp_project_id == "" ? google_project.backup_project[0].project_id : var.gcp_project_id +} + +resource "google_project_service" "drive_api" { + project = local.project_id + service = "drive.googleapis.com" + disable_on_destroy = false +} + +resource "google_project_organization_policy" "allow_key_creation" { + project = local.project_id + constraint = "iam.disableServiceAccountKeyCreation" + + boolean_policy { + enforced = false + } +} + +resource "google_service_account" "velero_backup_sa" { + project = local.project_id + account_id = "velero-backup-sa" + display_name = "Velero GDrive Backup Service Account" + depends_on = [google_project_service.drive_api] +} + +resource "google_service_account_key" "velero_backup_sa_key" { + service_account_id = google_service_account.velero_backup_sa.name + depends_on = [google_project_organization_policy.allow_key_creation] +} + +resource "local_file" "gdrive_sa_key_file" { + content = base64decode(google_service_account_key.velero_backup_sa_key.private_key) + filename = "${path.module}/../k8s/velero/gdrive_sa.json.secret" +} + +output "velero_backup_sa_email" { + value = google_service_account.velero_backup_sa.email + description = "The email address of the Google Cloud Service Account. Share your Google Drive backup folder with this email address and grant it Editor access." +} diff --git a/terraform/terraform.tfstate b/terraform/terraform.tfstate index f241311..4adab42 100644 --- a/terraform/terraform.tfstate +++ b/terraform/terraform.tfstate @@ -1 +1,1807 @@ -{"version":4,"terraform_version":"1.9.0","serial":208,"lineage":"8aff5d23-05f6-10eb-0ae6-1084c787677e","outputs":{},"resources":[{"mode":"managed","type":"ovh_domain_zone_record","name":"ameliegraf_de_first","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159023749","subdomain":"","target":"151.101.128.119","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"ameliegraf_de_second","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159023747","subdomain":"","target":"151.101.192.119","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_google_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370186587","subdomain":"google._domainkey","target":"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxkPdqXqsRT9NMioibnQJ1MmOX4Yzp/pwpJAIEGawsVLwZCkkhZEH5SyT4CSVz3AS6/XG2Qgx/a2hYctkzXSXllBhFDvixie6oXCOsjqyfr7R5s4LaKb399djFFl/GC7gSV+PUAW6sI02vJPfmn8BaVRAkrH0OrcjX3LSaTS5RRR9QGNCx0JreM+ho2Mcp8VbZCwnCMu42IjilR1d+kQX+2x0+r6mO0eJfP2QKOVpRnBXgv/FT+8jE+dmusf8MFoXxKuX6QjUh5TBH2J9W5NHUiBB4eC2DTrceuO1bM8ycmaGS95e1BmYXMcwfJknhjIgK85jESA8uDa38PIrN/b7WwIDAQAB","ttl":3600,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_google_grabengasse7_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370190173","subdomain":"google._domainkey","target":"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxR/e/Bc6/6Rfhos0ZQoVsq4HV8wkOdnOgkyubzvnepRDm/ARCws/CTvg9azJGFafsOsft1JZRAypj8mMovnDBjnW3mclVCyHQO34VLm13Et8ySX3GeJwwJQKx52PHsCQT1eEeEF3IjckS9wDiCkgdty9NEqpdF76N62nj6j8WY0czNxrYT0ivyiKQ6reB/mOeTiqPHiSHuB3ANxebwy5/wLilHSH320T9C+TDqcZ/Q6VTrUFpXIMjccEg93ZPaIu++FMTWZAe1pX6IWMuBXt5xRLLTamTzDUIOfwhvMxVee+d9mqwvIOc6J6ZiBhhCZpSVjiVLI5NcfNICQU4kjakwIDAQAB","ttl":3600,"zone":"grabengasse7.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_google_graf_fam_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370190174","subdomain":"google._domainkey","target":"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqT7j2pdU/dKDp7392+67cqI54QSwQsYrbdJa0aOH94m5gcXa3B2CZvuN2iKt6mO2mUtzWUbwKcNVL0p9yVW6nHpCMNefUS3NfZ8KQfl+lVsaYZXzYZwuTy2ZMvaBZpftIQjclfChFrOtMvBOTpdu8SBJT8hXnqkOYvtuHPBG+qDsFvsV+N4jjHtYbMPMnD2w7GeYciFWzp3bM9FbYIgdzyD+jzIYkaJlph4cMJBMoOredJhK+T2F95uvsvUk43QNU6KujLTFL6F/wNM/zSmH+5hYBAgAMG3QAguhicATJHV6bxd2oM1aLWNjZt90xBkTmMMzvtLjcGGpkgNuxa35WwIDAQAB","ttl":3600,"zone":"graf-fam.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_google_haumdaucher_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365220662","subdomain":"google._domainkey","target":"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4al3nYNZLlUBn0dcxqui5q48jjk4YvB2d2VNLfr864YdCm+3WqO6fc8Yx7sO4jKiX+OpMXnOc2RZazCCpcdCofJwTZxT+H0u2h4uyveEHq8UYqQZ66aAFLt3N1HYMT6+uFJZpKpSkFgqLagkQoW/cQHguJuu7Xjmt09fLTsBunjfJkKfUcjcyNlpnnAcVuo/TT7DKNzjB436yB1pf8QHxykUkV/lfz1/IzfRV//hR3H5pSNn4kR9qT9HqrTGgaZkPmStjoV2i2Dih4d3jO9FF1VDUNDm7W7739yiQhRZ5yelj5TaWGeRxWv+xM3YpVGqJzWI9oCuSpR2QaVKaOMQwIDAQAB","ttl":3600,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_google_krassescheisse_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370190171","subdomain":"google._domainkey","target":"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp9dLGkWdBZ0YyjBdRVTf26Fo+lVag1dfHHpO4N+oFLg0xV1gRJFcSGjteHUoKbrJxgesAwSmBYsaWAZB0RCI4wbAZKgb++6NX2Tk5gxkKys9pmc3ufGhCsjQkiiNepUkgalJRU7WAsWWolHXqn69D2DkXx9fPekdwaDeJwdtozoGacdbj46Ef1btGo48CJKk5rjh39c7BDNMmYEXXMztBIK2K80Y5WrLJZFxkvEKBrEB4pVoPDa3xEYcR0olLdDwB2SOEX6HSQ2xXkNB3KxbyIiHJTSJsNxquozTzfiWoqly/AdQLCU9j3jtqP88ne61NciQcxGdvOcQ0yUtFoydOwIDAQAB","ttl":3600,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_google_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365220661","subdomain":"google._domainkey","target":"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz4hYXxdgHDaNwqiUrHa4S9vbqLx/iV2avvgwwPqa5+2aOef109Ap8U7OfgFQQgwRVXx5XWbkKL69as3sdzuVA+8A8fRKbprugZEFoL9gyoTxPQveKO2s+1CsP0fUIx1c7aemfgn6mrfC0Ep17D70Y9YcQQWgiNHGHlgQDE1z6ncfUquHdipcmd0wEIAmjdNDBoqf3b1SRz5xaayKIeAsf/f2AFB1IeYwvLEaOC/mQDZWsry86RwjAfKvxbw0zAQaxSLFOho+kuxL2YUPbT55mZaB9Bi1G4VemzZUGuqXoq8xPzFOO/wxNi6Pei0Vs9wLwFahtuxriin4EVYOkjF4uwIDAQAB","ttl":3600,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370186586","subdomain":"_dmarc","target":"v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_grabengasse7_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370190169","subdomain":"_dmarc","target":"v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de","ttl":60,"zone":"grabengasse7.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_graf_fam_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370190167","subdomain":"_dmarc","target":"v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de","ttl":60,"zone":"graf-fam.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_haumdaucher_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365220116","subdomain":"_dmarc","target":"v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_krassescheisse_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370190166","subdomain":"_dmarc","target":"v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365220117","subdomain":"_dmarc","target":"v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370186584","subdomain":"","target":"google-site-verification=LwCbVqOp4c200QYrEEX1m4lIebOzxl5eBb2IkHbrSVA","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_grabengasse7_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370189154","subdomain":"","target":"google-site-verification=zwmmYhET0gyCJr_An22btaOVcpsE_nR2b1St0y4jn1A","ttl":60,"zone":"grabengasse7.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_graf_fam_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370188597","subdomain":"","target":"google-site-verification=DcG0tKp5YXxCRvw_Ekxa-3gbzdkZvxXUVkPs8aq9yQ4","ttl":60,"zone":"graf-fam.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_krassescheisse_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370188972","subdomain":"","target":"google-site-verification=SHFDcMegmOoh9syhj7_xBH9dLQxA2NMnh_zvg4Ma0CM","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365216140","subdomain":"","target":"google-site-verification=YwUd-Bmbq1-lA7uYGcowsLEMczqx1odndFZq_Nk3nvM","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"haumdaucher_domain","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5106871420","subdomain":"","target":"136.243.23.215","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"haumdaucher_mx_record","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5365107576","subdomain":"","target":"1 SMTP.GOOGLE.COM.","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"haumdaucher_wildcard_domain","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5112336220","subdomain":"*","target":"136.243.23.215","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"kochen_haumdaucher","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5205826663","subdomain":"kochen","target":"haumdaucher-datalab.github.io.","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"krassescheisse_subdomains","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"index_key":"alertmanager","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532212","subdomain":"alertmanager","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"auth","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532224","subdomain":"auth","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"chat","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532214","subdomain":"chat","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"cloud","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532215","subdomain":"cloud","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"code","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532228","subdomain":"code","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"grafana","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532218","subdomain":"grafana","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"hub","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532223","subdomain":"hub","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"imap","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532227","subdomain":"imap","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"jaeger","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532222","subdomain":"jaeger","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"kc","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113533002","subdomain":"kc","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"ldap","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532229","subdomain":"ldap","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"monitoring","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532226","subdomain":"monitoring","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"mqtt","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532213","subdomain":"mqtt","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"phpmyadmin","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532217","subdomain":"phpmyadmin","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"phppgadmin","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532231","subdomain":"phppgadmin","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"pop3","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532225","subdomain":"pop3","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"prometheus","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532230","subdomain":"prometheus","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"rstudio","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532221","subdomain":"rstudio","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"smtp","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532216","subdomain":"smtp","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"webapp","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113533005","subdomain":"webapp","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"www","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5122534663","subdomain":"www","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"moritzgraf_subdomains","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"index_key":"alertmanager","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870451","subdomain":"alertmanager","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"auth","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870439","subdomain":"auth","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"chat","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870446","subdomain":"chat","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"cloud","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870454","subdomain":"cloud","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"code","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870455","subdomain":"code","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"grafana","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870443","subdomain":"grafana","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"hub","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870438","subdomain":"hub","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"imap","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870448","subdomain":"imap","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"jaeger","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870437","subdomain":"jaeger","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"kc","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113533004","subdomain":"kc","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"ldap","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870449","subdomain":"ldap","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"monitoring","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870447","subdomain":"monitoring","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"mqtt","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870444","subdomain":"mqtt","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"phpmyadmin","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870440","subdomain":"phpmyadmin","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"phppgadmin","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870452","subdomain":"phppgadmin","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"pop3","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870453","subdomain":"pop3","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"prometheus","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870456","subdomain":"prometheus","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"rstudio","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870442","subdomain":"rstudio","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"smtp","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870450","subdomain":"smtp","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"webapp","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113533003","subdomain":"webapp","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"www","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870435","subdomain":"www","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"moritzgraf_subdomains_k8s","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"index_key":"corona","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113233478","subdomain":"corona","target":"haumdaucher.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"corona-api","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113233479","subdomain":"corona-api","target":"haumdaucher.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"git","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5116593521","subdomain":"git","target":"haumdaucher.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"tt-rss","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113719565","subdomain":"tt-rss","target":"haumdaucher.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"moritzgraf_wildcard_domain","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159040750","subdomain":"*","target":"136.243.23.215","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5370186585","subdomain":"","target":"1 smtp.google.com.","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_grabengasse7_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5370189178","subdomain":"","target":"1 smtp.google.com.","ttl":60,"zone":"grabengasse7.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_graf_fam_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5370188840","subdomain":"","target":"1 smtp.google.com.","ttl":60,"zone":"graf-fam.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_krassescheisse_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5370188995","subdomain":"","target":"1 smtp.google.com.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5365216454","subdomain":"","target":"1 SMTP.GOOGLE.COM.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"one","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5114515103","subdomain":"one","target":"136.243.23.215","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"spf_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370186583","subdomain":"","target":"v=spf1 include:_spf.google.com ~all","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"spf_grabengasse7_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370190168","subdomain":"","target":"v=spf1 include:_spf.google.com ~all","ttl":60,"zone":"grabengasse7.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"spf_graf_fam_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370190172","subdomain":"","target":"v=spf1 include:_spf.google.com ~all","ttl":60,"zone":"graf-fam.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"spf_haumdaucher_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365219216","subdomain":"","target":"v=spf1 include:_spf.google.com ~all","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"spf_krassescheisse_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370190170","subdomain":"","target":"v=spf1 include:_spf.google.com ~all","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"spf_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365219217","subdomain":"","target":"v=spf1 include:_spf.google.com ~all","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"wildcard_ameliegraf_de_first","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159023750","subdomain":"*","target":"151.101.128.119","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"wildcard_ameliegraf_de_second","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159023748","subdomain":"*","target":"151.101.192.119","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]}],"check_results":null} +{ + "version": 4, + "terraform_version": "1.14.3", + "serial": 221, + "lineage": "8aff5d23-05f6-10eb-0ae6-1084c787677e", + "outputs": { + "velero_backup_sa_email": { + "value": "velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "type": "string" + } + }, + "resources": [ + { + "mode": "managed", + "type": "google_project", + "name": "backup_project", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "index_key": 0, + "schema_version": 1, + "attributes": { + "auto_create_network": true, + "billing_account": null, + "deletion_policy": "DELETE", + "effective_labels": {}, + "folder_id": "", + "id": "projects/velero-backup-dc8c8f74", + "labels": {}, + "name": "velero-backup", + "number": "408632269830", + "org_id": "267822720032", + "project_id": "velero-backup-dc8c8f74", + "skip_delete": null, + "terraform_labels": {}, + "timeouts": null + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwLCJyZWFkIjo2MDAwMDAwMDAwMDAsInVwZGF0ZSI6NjAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIxIn0=", + "dependencies": [ + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_organization_policy", + "name": "allow_key_creation", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "boolean_policy": [ + { + "enforced": false + } + ], + "constraint": "constraints/iam.disableServiceAccountKeyCreation", + "etag": "CK28j9IGEKii/f4B", + "id": "velero-backup-dc8c8f74:iam.disableServiceAccountKeyCreation", + "list_policy": [], + "project": "velero-backup-dc8c8f74", + "restore_policy": [], + "timeouts": null, + "update_time": "2026-06-30T15:18:05.534729Z", + "version": 0 + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoyNDAwMDAwMDAwMDAsImRlbGV0ZSI6MjQwMDAwMDAwMDAwLCJyZWFkIjoyNDAwMDAwMDAwMDAsInVwZGF0ZSI6MjQwMDAwMDAwMDAwfX0=", + "dependencies": [ + "google_project.backup_project", + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_service", + "name": "drive_api", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "disable_dependent_services": null, + "disable_on_destroy": false, + "id": "velero-backup-dc8c8f74/drive.googleapis.com", + "project": "velero-backup-dc8c8f74", + "service": "drive.googleapis.com", + "timeouts": null + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=", + "dependencies": [ + "google_project.backup_project", + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_service_account", + "name": "velero_backup_sa", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "account_id": "velero-backup-sa", + "create_ignore_already_exists": null, + "description": "", + "disabled": false, + "display_name": "Velero GDrive Backup Service Account", + "email": "velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "id": "projects/velero-backup-dc8c8f74/serviceAccounts/velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "member": "serviceAccount:velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "name": "projects/velero-backup-dc8c8f74/serviceAccounts/velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "project": "velero-backup-dc8c8f74", + "timeouts": null, + "unique_id": "110772617250427578026" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjozMDAwMDAwMDAwMDB9fQ==", + "dependencies": [ + "google_project.backup_project", + "google_project_service.drive_api", + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_service_account_key", + "name": "velero_backup_sa_key", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "projects/velero-backup-dc8c8f74/serviceAccounts/velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com/keys/069aa702ed55bb6d3c325a45535ee51bc87de092", + "keepers": null, + "key_algorithm": "KEY_ALG_RSA_2048", + "name": "projects/velero-backup-dc8c8f74/serviceAccounts/velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com/keys/069aa702ed55bb6d3c325a45535ee51bc87de092", + "private_key": "ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAidmVsZXJvLWJhY2t1cC1kYzhjOGY3NCIsCiAgInByaXZhdGVfa2V5X2lkIjogIjA2OWFhNzAyZWQ1NWJiNmQzYzMyNWE0NTUzNWVlNTFiYzg3ZGUwOTIiLAogICJwcml2YXRlX2tleSI6ICItLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS1cbk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRRGtacWNsaXV2MWVSQk9cblVIN2twTER0RzEwd3VnMHptaE8wMTlDSFBMNVhGYkR2aW9LWlliTVZKV25XY29CUFJEZmNXQS9NTVhOeXJPSUdcbkdpWndMVFkyek5pdGRGQ3BweVY3ZTR1Zjk1ak9HREdwWkZGZ1hNSEc5RndFb3RNQlJQNTVTNnVMU3lXbW1idE5cbkdDRkoxV0h0a2plREp1SUpsb0xlL1BFV2NhR0FWcjE1VlBSNGQwMlRVZEFZcHJJZGJuRm90MnJ4U1RHS2IzZktcbi9PRm41SkdoeURyejR3Nkg1ME1ZWVQvVFI4ZWVSVTZoRHlsWVpja1FJK0dKcWp6eCtXMVZyY2dKdUs0MTN5bzhcbmY3RnBlRGpQZldGS2NGdHZNUk5SemtTRzd2VS9EbnUxQ0IxQUhYWEp0SE5HaGJXV2s2K0NPZ2tzTUV4UldFOFNcbmt4cEUxMjc1QWdNQkFBRUNnZ0VBR0FzaVgxWmZmb2pQQ1o5NXJESVdHZSsrZ0ttbFNDQlpJTGx6VHprNnhFb1pcblJTNHNqMTcwamk1UkZPMGF5cjFnc0FacEsxS3RWNDRSZ1JqeG9POXhmSlZWM2ZTWHBUUmVRc0IvczBoS1FxL1RcblVvU24rRi9yV2psUkVuL2RmSTI1eUNVS0d2Qy9OdW1LQ1JTWU5JQ00vWWhkNWFXTE4vMHJLN1F1NFBEM1VsNGNcblRFU2o2QVFUbzlycGJPc0ZzRmF3QkJhSnJ4eUhQOS80aWhINGxJbW1CM3crOEFQRDhkbmdsRCtYaDJHVEpPc0lcbklXWlZ3KzgrdEUrV3JDL2dyUE9hUW9UdW9nNVA2QVFzTzMrM1RCRGlqOXRxUWpHMHlWaThXa1FUWm1NYkNmYlpcbm10Q29GUTRrRUwwSURqclEwWFF3Z2h5OW5vU1djaUdRdEcwaFhtWVdIUUtCZ1FEMGROVExYNmVFV2x6M0xCK3Jcbmc0VjZxdXBHVmxyN3EzbCtGS2U1eUgxVkJ0OGdMWHJmU2lMNUlLTmRoTTc1bkFDcUN1dmI4dmpYbUhmRFlhcFJcbklNY29FYWJKUjVGVENjZzJQSW4xWGlvQWgySFNJTGdPTUxaeHg4WG5lL0lJYm1MYTNQMjFnUkx5TXFTWnl3aFJcbndLb1hzRklrMEF3akloVUJSa3FOak5YT3R3S0JnUUR2TDd0ODVaclk2OVAxMWlLcW1abGt4WCsvSVl2VHE5dEhcbnZ4SW5IeFJSclVTckplVFQ3NFBiQTMrTmhMZmQ2TTVyTkF3YXZFRlJxak55YnlaeGNmaE5ScnFmcDNCWXY0TWNcblBGOHBvUE5iNmU1dTI0QUM2c2lrQm5rYlBEOUJtZ1FrNGVhLzJUcnZGOUdxaUZWakZWMW5wT0xSZ0FRUWw5M2Ncbkk5eVRrRnYvendLQmdHVkNlOTdlZVpxR2Y5blhDaXRXcUpUZWRYcTdUS2JSS2R0REhSTUU3SDJyQWdQbk11MkpcblhTRkxGc0NuUWNEOWtQemUxMEpkekJ3cVNQbkMyL1VOR2RJTU5jVk1ndk1kcXpSa01WVlZNeHJTK1g4OEZHRzBcblplNk5yUG10U3QyWk5CT3ExT0U1WFNxOE5aaUxGS0FncVpSMGNpSlRsNk41KzY5eWVYRlc5RDNUQW9HQUVUY2hcblNuc0lLeWJHS2NLUTJqQ1Yvcy9NUXdoNkZQRWdwa2hWV1NWK2crWnhzOVBWWlgrdXdOdSttWVA4NitidXZINlJcbmhIY2FTSE4wb243bmlIRElpMTlVM1ZyaTFqQnFrbVN5QU1BSjVBcXhVNTlPMW1icHJBeWZPTnVjUGUrRTd0YW5cbmtoVmpqWVBzWGxiVHRuNzZLeFNPRXNBaENzU3pmajNDaVloeFpyY0NnWUF3cG45ME84MmZwZE9FVUo1bnNpbElcbktjVEI2dU1XTW5XbWN0cEpEQ05iVlRVNWk0SmxYd0wzaGkzdCtjZENjWk4vMHJKU0lXT3psT29lYWg0MGw1MUhcbkpQclZ0M2lhSmdQanVJMVFHYjhyc3JPNnpMNDRvb0pHWHo1U2sxRi9NOXBnY2dKWlR3akpXV3VpN1pET0VPUzJcblVLN3NwNGJaU0dXZE1iOUY5SUxKcWc9PVxuLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLVxuIiwKICAiY2xpZW50X2VtYWlsIjogInZlbGVyby1iYWNrdXAtc2FAdmVsZXJvLWJhY2t1cC1kYzhjOGY3NC5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsCiAgImNsaWVudF9pZCI6ICIxMTA3NzI2MTcyNTA0Mjc1NzgwMjYiLAogICJhdXRoX3VyaSI6ICJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9vYXV0aDIvYXV0aCIsCiAgInRva2VuX3VyaSI6ICJodHRwczovL29hdXRoMi5nb29nbGVhcGlzLmNvbS90b2tlbiIsCiAgImF1dGhfcHJvdmlkZXJfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9vYXV0aDIvdjEvY2VydHMiLAogICJjbGllbnRfeDUwOV9jZXJ0X3VybCI6ICJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9yb2JvdC92MS9tZXRhZGF0YS94NTA5L3ZlbGVyby1iYWNrdXAtc2ElNDB2ZWxlcm8tYmFja3VwLWRjOGM4Zjc0LmlhbS5nc2VydmljZWFjY291bnQuY29tIiwKICAidW5pdmVyc2VfZG9tYWluIjogImdvb2dsZWFwaXMuY29tIgp9Cg==", + "private_key_type": "TYPE_GOOGLE_CREDENTIALS_FILE", + "public_key": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvRENDQWVTZ0F3SUJBZ0lJWWRxRUo0cmJOMzB3RFFZSktvWklodmNOQVFFRkJRQXdJREVlTUJ3R0ExVUUKQXd3Vk1URXdOemN5TmpFM01qVXdOREkzTlRjNE1ESTJNQ0FYRFRJMk1EWXpNREUzTURZeU9Gb1lEems1T1RreApNak14TWpNMU9UVTVXakFnTVI0d0hBWURWUVFEREJVeE1UQTNOekkyTVRjeU5UQTBNamMxTnpnd01qWXdnZ0VpCk1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRGtacWNsaXV2MWVSQk9VSDdrcExEdEcxMHcKdWcwem1oTzAxOUNIUEw1WEZiRHZpb0taWWJNVkpXbldjb0JQUkRmY1dBL01NWE55ck9JR0dpWndMVFkyek5pdApkRkNwcHlWN2U0dWY5NWpPR0RHcFpGRmdYTUhHOUZ3RW90TUJSUDU1UzZ1TFN5V21tYnROR0NGSjFXSHRramVECkp1SUpsb0xlL1BFV2NhR0FWcjE1VlBSNGQwMlRVZEFZcHJJZGJuRm90MnJ4U1RHS2IzZksvT0ZuNUpHaHlEcnoKNHc2SDUwTVlZVC9UUjhlZVJVNmhEeWxZWmNrUUkrR0pxanp4K1cxVnJjZ0p1SzQxM3lvOGY3RnBlRGpQZldGSwpjRnR2TVJOUnprU0c3dlUvRG51MUNCMUFIWFhKdEhOR2hiV1drNitDT2drc01FeFJXRThTa3hwRTEyNzVBZ01CCkFBR2pPREEyTUF3R0ExVWRFd0VCL3dRQ01BQXdEZ1lEVlIwUEFRSC9CQVFEQWdlQU1CWUdBMVVkSlFFQi93UU0KTUFvR0NDc0dBUVVGQndNQ01BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRREsrZG8yUElZcitSUnUrVDFXdzU3agpNV1U4bC9ZWmlZYjZHVHdSSTl5aGVUZ0JMd0ZxbS9Hckw4RHFhSHd1eXlHcCtIZHIzRENqRDZLQmd3ZFE1WFdRCmxCNlN5dExOVmJGKzRKN1lick1zbWJvSWg4RDRaUDZMQjNNTDM0dmc2eHg1Mmt5QU9JeDg0S1Z3TXh6RjJBaXYKUFZWQkxwWGtBcE53WlJnMy9uYWZnMVl1VW0xWXBqQVpaVDdrLzRZVGJPL0dmS0ZNLzlDT0M5OENidFNUUjJoVgpLZFlHK3hWek52VjYvTGdtUjFoRXF2Q2xKOG00Y3RzdTk4dURleGNDZ21TaXc3Z3Mzc240cDBhNE90OWdtTFh3Ckxva3dPMnFBdGhBN3YvU0ZaQ050Y2p6VGRha1did1YyeWU5QldGcWNpZExEbnk5cFpwd0w4STRHNTZ2MW1LbVIKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=", + "public_key_data": null, + "public_key_type": "TYPE_X509_PEM_FILE", + "service_account_id": "projects/velero-backup-dc8c8f74/serviceAccounts/velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "valid_after": "2026-06-30T17:06:28Z", + "valid_before": "9999-12-31T23:59:59Z" + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "private_key" + } + ] + ], + "identity_schema_version": 0, + "private": "bnVsbA==", + "dependencies": [ + "google_project.backup_project", + "google_project_organization_policy.allow_key_creation", + "google_project_service.drive_api", + "google_service_account.velero_backup_sa", + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "local_file", + "name": "gdrive_sa_key_file", + "provider": "provider[\"registry.terraform.io/hashicorp/local\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "content": "{\n \"type\": \"service_account\",\n \"project_id\": \"velero-backup-dc8c8f74\",\n \"private_key_id\": \"069aa702ed55bb6d3c325a45535ee51bc87de092\",\n \"private_key\": \"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDkZqcliuv1eRBO\\nUH7kpLDtG10wug0zmhO019CHPL5XFbDvioKZYbMVJWnWcoBPRDfcWA/MMXNyrOIG\\nGiZwLTY2zNitdFCppyV7e4uf95jOGDGpZFFgXMHG9FwEotMBRP55S6uLSyWmmbtN\\nGCFJ1WHtkjeDJuIJloLe/PEWcaGAVr15VPR4d02TUdAYprIdbnFot2rxSTGKb3fK\\n/OFn5JGhyDrz4w6H50MYYT/TR8eeRU6hDylYZckQI+GJqjzx+W1VrcgJuK413yo8\\nf7FpeDjPfWFKcFtvMRNRzkSG7vU/Dnu1CB1AHXXJtHNGhbWWk6+COgksMExRWE8S\\nkxpE1275AgMBAAECggEAGAsiX1ZffojPCZ95rDIWGe++gKmlSCBZILlzTzk6xEoZ\\nRS4sj170ji5RFO0ayr1gsAZpK1KtV44RgRjxoO9xfJVV3fSXpTReQsB/s0hKQq/T\\nUoSn+F/rWjlREn/dfI25yCUKGvC/NumKCRSYNICM/Yhd5aWLN/0rK7Qu4PD3Ul4c\\nTESj6AQTo9rpbOsFsFawBBaJrxyHP9/4ihH4lImmB3w+8APD8dnglD+Xh2GTJOsI\\nIWZVw+8+tE+WrC/grPOaQoTuog5P6AQsO3+3TBDij9tqQjG0yVi8WkQTZmMbCfbZ\\nmtCoFQ4kEL0IDjrQ0XQwghy9noSWciGQtG0hXmYWHQKBgQD0dNTLX6eEWlz3LB+r\\ng4V6qupGVlr7q3l+FKe5yH1VBt8gLXrfSiL5IKNdhM75nACqCuvb8vjXmHfDYapR\\nIMcoEabJR5FTCcg2PIn1XioAh2HSILgOMLZxx8Xne/IIbmLa3P21gRLyMqSZywhR\\nwKoXsFIk0AwjIhUBRkqNjNXOtwKBgQDvL7t85ZrY69P11iKqmZlkxX+/IYvTq9tH\\nvxInHxRRrUSrJeTT74PbA3+NhLfd6M5rNAwavEFRqjNybyZxcfhNRrqfp3BYv4Mc\\nPF8poPNb6e5u24AC6sikBnkbPD9BmgQk4ea/2TrvF9GqiFVjFV1npOLRgAQQl93c\\nI9yTkFv/zwKBgGVCe97eeZqGf9nXCitWqJTedXq7TKbRKdtDHRME7H2rAgPnMu2J\\nXSFLFsCnQcD9kPze10JdzBwqSPnC2/UNGdIMNcVMgvMdqzRkMVVVMxrS+X88FGG0\\nZe6NrPmtSt2ZNBOq1OE5XSq8NZiLFKAgqZR0ciJTl6N5+69yeXFW9D3TAoGAETch\\nSnsIKybGKcKQ2jCV/s/MQwh6FPEgpkhVWSV+g+Zxs9PVZX+uwNu+mYP86+buvH6R\\nhHcaSHN0on7niHDIi19U3Vri1jBqkmSyAMAJ5AqxU59O1mbprAyfONucPe+E7tan\\nkhVjjYPsXlbTtn76KxSOEsAhCsSzfj3CiYhxZrcCgYAwpn90O82fpdOEUJ5nsilI\\nKcTB6uMWMnWmctpJDCNbVTU5i4JlXwL3hi3t+cdCcZN/0rJSIWOzlOoeah40l51H\\nJPrVt3iaJgPjuI1QGb8rsrO6zL44ooJGXz5Sk1F/M9pgcgJZTwjJWWui7ZDOEOS2\\nUK7sp4bZSGWdMb9F9ILJqg==\\n-----END PRIVATE KEY-----\\n\",\n \"client_email\": \"velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com\",\n \"client_id\": \"110772617250427578026\",\n \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n \"token_uri\": \"https://oauth2.googleapis.com/token\",\n \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/velero-backup-sa%40velero-backup-dc8c8f74.iam.gserviceaccount.com\",\n \"universe_domain\": \"googleapis.com\"\n}\n", + "content_base64": null, + "content_base64sha256": "gjWa6Ybyx03eN9NFF61rxtnJA7qU2cVs8DYq88edE2w=", + "content_base64sha512": "SQ6O7L8ylOgmpJI65GXpYW4u4Ken/WmdvKHYdFzSyzvTY5I73F+LWKTqKJqhCjNNAzN6heHtm9J0u6KU056nhQ==", + "content_md5": "7754550fa246ffcc9a01ec63e85191ac", + "content_sha1": "a78f85be2f699453aeb2dec074c940b397108b9b", + "content_sha256": "82359ae986f2c74dde37d34517ad6bc6d9c903ba94d9c56cf0362af3c79d136c", + "content_sha512": "490e8eecbf3294e826a4923ae465e9616e2ee0a7a7fd699dbca1d8745cd2cb3bd363923bdc5f8b58a4ea289aa10a334d03337a85e1ed9bd274bba294d39ea785", + "directory_permission": "0777", + "file_permission": "0777", + "filename": "./../k8s/velero/gdrive_sa.json.secret", + "id": "a78f85be2f699453aeb2dec074c940b397108b9b", + "sensitive_content": null, + "source": null + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "content" + } + ], + [ + { + "type": "get_attr", + "value": "sensitive_content" + } + ] + ], + "identity_schema_version": 0, + "dependencies": [ + "google_project.backup_project", + "google_project_organization_policy.allow_key_creation", + "google_project_service.drive_api", + "google_service_account.velero_backup_sa", + "google_service_account_key.velero_backup_sa_key", + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "ameliegraf_de_first", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159023749", + "subdomain": "", + "target": "151.101.128.119", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "ameliegraf_de_second", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159023747", + "subdomain": "", + "target": "151.101.192.119", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370186587", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxkPdqXqsRT9NMioibnQJ1MmOX4Yzp/pwpJAIEGawsVLwZCkkhZEH5SyT4CSVz3AS6/XG2Qgx/a2hYctkzXSXllBhFDvixie6oXCOsjqyfr7R5s4LaKb399djFFl/GC7gSV+PUAW6sI02vJPfmn8BaVRAkrH0OrcjX3LSaTS5RRR9QGNCx0JreM+ho2Mcp8VbZCwnCMu42IjilR1d+kQX+2x0+r6mO0eJfP2QKOVpRnBXgv/FT+8jE+dmusf8MFoXxKuX6QjUh5TBH2J9W5NHUiBB4eC2DTrceuO1bM8ycmaGS95e1BmYXMcwfJknhjIgK85jESA8uDa38PIrN/b7WwIDAQAB", + "ttl": 3600, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190173", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxR/e/Bc6/6Rfhos0ZQoVsq4HV8wkOdnOgkyubzvnepRDm/ARCws/CTvg9azJGFafsOsft1JZRAypj8mMovnDBjnW3mclVCyHQO34VLm13Et8ySX3GeJwwJQKx52PHsCQT1eEeEF3IjckS9wDiCkgdty9NEqpdF76N62nj6j8WY0czNxrYT0ivyiKQ6reB/mOeTiqPHiSHuB3ANxebwy5/wLilHSH320T9C+TDqcZ/Q6VTrUFpXIMjccEg93ZPaIu++FMTWZAe1pX6IWMuBXt5xRLLTamTzDUIOfwhvMxVee+d9mqwvIOc6J6ZiBhhCZpSVjiVLI5NcfNICQU4kjakwIDAQAB", + "ttl": 3600, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190174", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqT7j2pdU/dKDp7392+67cqI54QSwQsYrbdJa0aOH94m5gcXa3B2CZvuN2iKt6mO2mUtzWUbwKcNVL0p9yVW6nHpCMNefUS3NfZ8KQfl+lVsaYZXzYZwuTy2ZMvaBZpftIQjclfChFrOtMvBOTpdu8SBJT8hXnqkOYvtuHPBG+qDsFvsV+N4jjHtYbMPMnD2w7GeYciFWzp3bM9FbYIgdzyD+jzIYkaJlph4cMJBMoOredJhK+T2F95uvsvUk43QNU6KujLTFL6F/wNM/zSmH+5hYBAgAMG3QAguhicATJHV6bxd2oM1aLWNjZt90xBkTmMMzvtLjcGGpkgNuxa35WwIDAQAB", + "ttl": 3600, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_haumdaucher_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365220662", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4al3nYNZLlUBn0dcxqui5q48jjk4YvB2d2VNLfr864YdCm+3WqO6fc8Yx7sO4jKiX+OpMXnOc2RZazCCpcdCofJwTZxT+H0u2h4uyveEHq8UYqQZ66aAFLt3N1HYMT6+uFJZpKpSkFgqLagkQoW/cQHguJuu7Xjmt09fLTsBunjfJkKfUcjcyNlpnnAcVuo/TT7DKNzjB436yB1pf8QHxykUkV/lfz1/IzfRV//hR3H5pSNn4kR9qT9HqrTGgaZkPmStjoV2i2Dih4d3jO9FF1VDUNDm7W7739yiQhRZ5yelj5TaWGeRxWv+xM3YpVGqJzWI9oCuSpR2QaVKaOMQwIDAQAB", + "ttl": 3600, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190171", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp9dLGkWdBZ0YyjBdRVTf26Fo+lVag1dfHHpO4N+oFLg0xV1gRJFcSGjteHUoKbrJxgesAwSmBYsaWAZB0RCI4wbAZKgb++6NX2Tk5gxkKys9pmc3ufGhCsjQkiiNepUkgalJRU7WAsWWolHXqn69D2DkXx9fPekdwaDeJwdtozoGacdbj46Ef1btGo48CJKk5rjh39c7BDNMmYEXXMztBIK2K80Y5WrLJZFxkvEKBrEB4pVoPDa3xEYcR0olLdDwB2SOEX6HSQ2xXkNB3KxbyIiHJTSJsNxquozTzfiWoqly/AdQLCU9j3jtqP88ne61NciQcxGdvOcQ0yUtFoydOwIDAQAB", + "ttl": 3600, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365220661", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz4hYXxdgHDaNwqiUrHa4S9vbqLx/iV2avvgwwPqa5+2aOef109Ap8U7OfgFQQgwRVXx5XWbkKL69as3sdzuVA+8A8fRKbprugZEFoL9gyoTxPQveKO2s+1CsP0fUIx1c7aemfgn6mrfC0Ep17D70Y9YcQQWgiNHGHlgQDE1z6ncfUquHdipcmd0wEIAmjdNDBoqf3b1SRz5xaayKIeAsf/f2AFB1IeYwvLEaOC/mQDZWsry86RwjAfKvxbw0zAQaxSLFOho+kuxL2YUPbT55mZaB9Bi1G4VemzZUGuqXoq8xPzFOO/wxNi6Pei0Vs9wLwFahtuxriin4EVYOkjF4uwIDAQAB", + "ttl": 3600, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370186586", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190169", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190167", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_haumdaucher_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365220116", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190166", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365220117", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370186584", + "subdomain": "", + "target": "google-site-verification=LwCbVqOp4c200QYrEEX1m4lIebOzxl5eBb2IkHbrSVA", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370189154", + "subdomain": "", + "target": "google-site-verification=zwmmYhET0gyCJr_An22btaOVcpsE_nR2b1St0y4jn1A", + "ttl": 60, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370188597", + "subdomain": "", + "target": "google-site-verification=DcG0tKp5YXxCRvw_Ekxa-3gbzdkZvxXUVkPs8aq9yQ4", + "ttl": 60, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370188972", + "subdomain": "", + "target": "google-site-verification=SHFDcMegmOoh9syhj7_xBH9dLQxA2NMnh_zvg4Ma0CM", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365216140", + "subdomain": "", + "target": "google-site-verification=YwUd-Bmbq1-lA7uYGcowsLEMczqx1odndFZq_Nk3nvM", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "haumdaucher_domain", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5106871420", + "subdomain": "", + "target": "136.243.23.215", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "haumdaucher_mx_record", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5365107576", + "subdomain": "", + "target": "1 SMTP.GOOGLE.COM.", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "haumdaucher_wildcard_domain", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5112336220", + "subdomain": "*", + "target": "136.243.23.215", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "kochen_haumdaucher", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5205826663", + "subdomain": "kochen", + "target": "haumdaucher-datalab.github.io.", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "krassescheisse_subdomains", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "index_key": "alertmanager", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532212", + "subdomain": "alertmanager", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "auth", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532224", + "subdomain": "auth", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "chat", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532214", + "subdomain": "chat", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "cloud", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532215", + "subdomain": "cloud", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "code", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532228", + "subdomain": "code", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "grafana", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532218", + "subdomain": "grafana", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "hub", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532223", + "subdomain": "hub", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "imap", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532227", + "subdomain": "imap", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "jaeger", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532222", + "subdomain": "jaeger", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "kc", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113533002", + "subdomain": "kc", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "ldap", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532229", + "subdomain": "ldap", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "monitoring", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532226", + "subdomain": "monitoring", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "mqtt", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532213", + "subdomain": "mqtt", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "phpmyadmin", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532217", + "subdomain": "phpmyadmin", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "phppgadmin", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532231", + "subdomain": "phppgadmin", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "pop3", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532225", + "subdomain": "pop3", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "prometheus", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532230", + "subdomain": "prometheus", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "rstudio", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532221", + "subdomain": "rstudio", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "smtp", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532216", + "subdomain": "smtp", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "webapp", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113533005", + "subdomain": "webapp", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "www", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5122534663", + "subdomain": "www", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "moritzgraf_subdomains", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "index_key": "alertmanager", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870451", + "subdomain": "alertmanager", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "auth", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870439", + "subdomain": "auth", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "chat", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870446", + "subdomain": "chat", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "cloud", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870454", + "subdomain": "cloud", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "code", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870455", + "subdomain": "code", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "grafana", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870443", + "subdomain": "grafana", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "hub", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870438", + "subdomain": "hub", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "imap", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870448", + "subdomain": "imap", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "jaeger", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870437", + "subdomain": "jaeger", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "kc", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113533004", + "subdomain": "kc", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "ldap", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870449", + "subdomain": "ldap", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "monitoring", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870447", + "subdomain": "monitoring", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "mqtt", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870444", + "subdomain": "mqtt", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "phpmyadmin", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870440", + "subdomain": "phpmyadmin", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "phppgadmin", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870452", + "subdomain": "phppgadmin", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "pop3", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870453", + "subdomain": "pop3", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "prometheus", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870456", + "subdomain": "prometheus", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "rstudio", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870442", + "subdomain": "rstudio", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "smtp", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870450", + "subdomain": "smtp", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "webapp", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113533003", + "subdomain": "webapp", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "www", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870435", + "subdomain": "www", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "moritzgraf_subdomains_k8s", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "index_key": "corona", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113233478", + "subdomain": "corona", + "target": "haumdaucher.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "corona-api", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113233479", + "subdomain": "corona-api", + "target": "haumdaucher.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "git", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5116593521", + "subdomain": "git", + "target": "haumdaucher.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "tt-rss", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113719565", + "subdomain": "tt-rss", + "target": "haumdaucher.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "moritzgraf_wildcard_domain", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159040750", + "subdomain": "*", + "target": "136.243.23.215", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5370186585", + "subdomain": "", + "target": "1 smtp.google.com.", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5370189178", + "subdomain": "", + "target": "1 smtp.google.com.", + "ttl": 60, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5370188840", + "subdomain": "", + "target": "1 smtp.google.com.", + "ttl": 60, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5370188995", + "subdomain": "", + "target": "1 smtp.google.com.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5365216454", + "subdomain": "", + "target": "1 SMTP.GOOGLE.COM.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "one", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5114515103", + "subdomain": "one", + "target": "136.243.23.215", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370186583", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190168", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190172", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_haumdaucher_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365219216", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190170", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365219217", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "wildcard_ameliegraf_de_first", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159023750", + "subdomain": "*", + "target": "151.101.128.119", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "wildcard_ameliegraf_de_second", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159023748", + "subdomain": "*", + "target": "151.101.192.119", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "random_id", + "name": "project_suffix", + "provider": "provider[\"registry.terraform.io/hashicorp/random\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "b64_std": "3IyPdA==", + "b64_url": "3IyPdA", + "byte_length": 4, + "dec": "3700199284", + "hex": "dc8c8f74", + "id": "3IyPdA", + "keepers": null, + "prefix": null + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + } + ], + "check_results": null +} diff --git a/terraform/terraform.tfstate.backup b/terraform/terraform.tfstate.backup index 2f1f141..bd9333c 100644 --- a/terraform/terraform.tfstate.backup +++ b/terraform/terraform.tfstate.backup @@ -1 +1,1715 @@ -{"version":4,"terraform_version":"1.9.0","serial":207,"lineage":"8aff5d23-05f6-10eb-0ae6-1084c787677e","outputs":{},"resources":[{"mode":"managed","type":"ovh_domain_zone_record","name":"ameliegraf_de_first","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159023749","subdomain":"","target":"151.101.128.119","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"ameliegraf_de_second","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159023747","subdomain":"","target":"151.101.192.119","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_google_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370186587","subdomain":"google._domainkey","target":"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxkPdqXqsRT9NMioibnQJ1MmOX4Yzp/pwpJAIEGawsVLwZCkkhZEH5SyT4CSVz3AS6/XG2Qgx/a2hYctkzXSXllBhFDvixie6oXCOsjqyfr7R5s4LaKb399djFFl/GC7gSV+PUAW6sI02vJPfmn8BaVRAkrH0OrcjX3LSaTS5RRR9QGNCx0JreM+ho2Mcp8VbZCwnCMu42IjilR1d+kQX+2x0+r6mO0eJfP2QKOVpRnBXgv/FT+8jE+dmusf8MFoXxKuX6QjUh5TBH2J9W5NHUiBB4eC2DTrceuO1bM8ycmaGS95e1BmYXMcwfJknhjIgK85jESA8uDa38PIrN/b7WwIDAQAB","ttl":3600,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_google_haumdaucher_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365220662","subdomain":"google._domainkey","target":"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4al3nYNZLlUBn0dcxqui5q48jjk4YvB2d2VNLfr864YdCm+3WqO6fc8Yx7sO4jKiX+OpMXnOc2RZazCCpcdCofJwTZxT+H0u2h4uyveEHq8UYqQZ66aAFLt3N1HYMT6+uFJZpKpSkFgqLagkQoW/cQHguJuu7Xjmt09fLTsBunjfJkKfUcjcyNlpnnAcVuo/TT7DKNzjB436yB1pf8QHxykUkV/lfz1/IzfRV//hR3H5pSNn4kR9qT9HqrTGgaZkPmStjoV2i2Dih4d3jO9FF1VDUNDm7W7739yiQhRZ5yelj5TaWGeRxWv+xM3YpVGqJzWI9oCuSpR2QaVKaOMQwIDAQAB","ttl":3600,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_google_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365220661","subdomain":"google._domainkey","target":"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz4hYXxdgHDaNwqiUrHa4S9vbqLx/iV2avvgwwPqa5+2aOef109Ap8U7OfgFQQgwRVXx5XWbkKL69as3sdzuVA+8A8fRKbprugZEFoL9gyoTxPQveKO2s+1CsP0fUIx1c7aemfgn6mrfC0Ep17D70Y9YcQQWgiNHGHlgQDE1z6ncfUquHdipcmd0wEIAmjdNDBoqf3b1SRz5xaayKIeAsf/f2AFB1IeYwvLEaOC/mQDZWsry86RwjAfKvxbw0zAQaxSLFOho+kuxL2YUPbT55mZaB9Bi1G4VemzZUGuqXoq8xPzFOO/wxNi6Pei0Vs9wLwFahtuxriin4EVYOkjF4uwIDAQAB","ttl":3600,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dkim_record","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"index_key":"krassescheisse.de","schema_version":0,"attributes":{"fieldtype":"TXT","id":"5106871427","subdomain":"dkim._domainkey","target":"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhnjYV76s63M4zVRTjVf5Z/fTO6Rq3o4DXg62FCgAxQOYB9ANXeBvUPokT+p5SgjGC8HwBYIzzwCTCS6sqHsy8NfnHU1xFH5NcY4LqTopVX//eYpPF+bTwarDVu/lcCxiX4cN84U1yL8lqf0sOJ7ubGlSeZ/SfM/Ppj7Wkh/kBOQIDAQAB","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"moritzgraf.de","schema_version":0,"attributes":{"fieldtype":"TXT","id":"5106871412","subdomain":"dkim._domainkey","target":"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhnjYV76s63M4zVRTjVf5Z/fTO6Rq3o4DXg62FCgAxQOYB9ANXeBvUPokT+p5SgjGC8HwBYIzzwCTCS6sqHsy8NfnHU1xFH5NcY4LqTopVX//eYpPF+bTwarDVu/lcCxiX4cN84U1yL8lqf0sOJ7ubGlSeZ/SfM/Ppj7Wkh/kBOQIDAQAB","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370186586","subdomain":"_dmarc","target":"v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_haumdaucher_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365220116","subdomain":"_dmarc","target":"v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365220117","subdomain":"_dmarc","target":"v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"dmarc_record","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"index_key":"krassescheisse.de","schema_version":0,"attributes":{"fieldtype":"TXT","id":"5106871409","subdomain":"_dmarc","target":"v=DMARC1; p=reject; rua=none; ruf=mailto:admin@moritzgraf.de; adkim=s; aspf=s","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"moritzgraf.de","schema_version":0,"attributes":{"fieldtype":"TXT","id":"5106871410","subdomain":"_dmarc","target":"v=DMARC1; p=reject; rua=none; ruf=mailto:admin@moritzgraf.de; adkim=s; aspf=s","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370186584","subdomain":"","target":"google-site-verification=LwCbVqOp4c200QYrEEX1m4lIebOzxl5eBb2IkHbrSVA","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_grabengasse7_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370189154","subdomain":"","target":"google-site-verification=zwmmYhET0gyCJr_An22btaOVcpsE_nR2b1St0y4jn1A","ttl":60,"zone":"grabengasse7.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_graf_fam_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370188597","subdomain":"","target":"google-site-verification=DcG0tKp5YXxCRvw_Ekxa-3gbzdkZvxXUVkPs8aq9yQ4","ttl":60,"zone":"graf-fam.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_krassescheisse_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370188972","subdomain":"","target":"google-site-verification=SHFDcMegmOoh9syhj7_xBH9dLQxA2NMnh_zvg4Ma0CM","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"google_domain_verification_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365216140","subdomain":"","target":"google-site-verification=YwUd-Bmbq1-lA7uYGcowsLEMczqx1odndFZq_Nk3nvM","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"haumdaucher_domain","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5106871420","subdomain":"","target":"136.243.23.215","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"haumdaucher_mx_record","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5365107576","subdomain":"","target":"1 SMTP.GOOGLE.COM.","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"haumdaucher_wildcard_domain","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5112336220","subdomain":"*","target":"136.243.23.215","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"kochen_haumdaucher","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5205826663","subdomain":"kochen","target":"haumdaucher-datalab.github.io.","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"krassescheisse_subdomains","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"index_key":"alertmanager","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532212","subdomain":"alertmanager","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"auth","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532224","subdomain":"auth","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"chat","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532214","subdomain":"chat","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"cloud","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532215","subdomain":"cloud","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"code","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532228","subdomain":"code","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"grafana","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532218","subdomain":"grafana","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"hub","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532223","subdomain":"hub","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"imap","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532227","subdomain":"imap","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"jaeger","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532222","subdomain":"jaeger","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"kc","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113533002","subdomain":"kc","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"ldap","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532229","subdomain":"ldap","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"monitoring","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532226","subdomain":"monitoring","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"mqtt","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532213","subdomain":"mqtt","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"phpmyadmin","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532217","subdomain":"phpmyadmin","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"phppgadmin","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532231","subdomain":"phppgadmin","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"pop3","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532225","subdomain":"pop3","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"prometheus","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532230","subdomain":"prometheus","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"rstudio","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532221","subdomain":"rstudio","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"smtp","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113532216","subdomain":"smtp","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"webapp","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113533005","subdomain":"webapp","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"www","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5122534663","subdomain":"www","target":"krassescheisse.de.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mail_moritzgraf","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5106870709","subdomain":"mail","target":"136.243.23.215","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"moritzgraf","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5118726203","subdomain":"","target":"136.243.23.215","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"moritzgraf_subdomains","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"index_key":"alertmanager","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870451","subdomain":"alertmanager","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"auth","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870439","subdomain":"auth","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"chat","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870446","subdomain":"chat","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"cloud","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870454","subdomain":"cloud","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"code","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870455","subdomain":"code","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"grafana","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870443","subdomain":"grafana","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"hub","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870438","subdomain":"hub","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"imap","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870448","subdomain":"imap","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"jaeger","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870437","subdomain":"jaeger","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"kc","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113533004","subdomain":"kc","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"ldap","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870449","subdomain":"ldap","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"monitoring","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870447","subdomain":"monitoring","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"mqtt","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870444","subdomain":"mqtt","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"phpmyadmin","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870440","subdomain":"phpmyadmin","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"phppgadmin","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870452","subdomain":"phppgadmin","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"pop3","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870453","subdomain":"pop3","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"prometheus","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870456","subdomain":"prometheus","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"rstudio","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870442","subdomain":"rstudio","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"smtp","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870450","subdomain":"smtp","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"webapp","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113533003","subdomain":"webapp","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"www","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5106870435","subdomain":"www","target":"moritzgraf.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"moritzgraf_subdomains_k8s","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"index_key":"corona","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113233478","subdomain":"corona","target":"haumdaucher.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"corona-api","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113233479","subdomain":"corona-api","target":"haumdaucher.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"git","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5116593521","subdomain":"git","target":"haumdaucher.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="},{"index_key":"tt-rss","schema_version":0,"attributes":{"fieldtype":"CNAME","id":"5113719565","subdomain":"tt-rss","target":"haumdaucher.de.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"moritzgraf_wildcard_domain","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159040750","subdomain":"*","target":"136.243.23.215","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5370186585","subdomain":"","target":"1 smtp.google.com.","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_grabengasse7_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5370189178","subdomain":"","target":"1 smtp.google.com.","ttl":60,"zone":"grabengasse7.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_graf_fam_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5370188840","subdomain":"","target":"1 smtp.google.com.","ttl":60,"zone":"graf-fam.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_krassescheisse_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5370188995","subdomain":"","target":"1 smtp.google.com.","ttl":60,"zone":"krassescheisse.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"mx_record_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"MX","id":"5365216454","subdomain":"","target":"1 SMTP.GOOGLE.COM.","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"one","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5114515103","subdomain":"one","target":"136.243.23.215","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"spf_ameliegraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5370186583","subdomain":"","target":"v=spf1 include:_spf.google.com ~all","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"spf_haumdaucher_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365219216","subdomain":"","target":"v=spf1 include:_spf.google.com ~all","ttl":60,"zone":"haumdaucher.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"spf_moritzgraf_de","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"TXT","id":"5365219217","subdomain":"","target":"v=spf1 include:_spf.google.com ~all","ttl":60,"zone":"moritzgraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"wildcard_ameliegraf_de_first","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159023750","subdomain":"*","target":"151.101.128.119","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"mode":"managed","type":"ovh_domain_zone_record","name":"wildcard_ameliegraf_de_second","provider":"provider[\"registry.opentofu.org/ovh/ovh\"]","instances":[{"schema_version":0,"attributes":{"fieldtype":"A","id":"5159023748","subdomain":"*","target":"151.101.192.119","ttl":60,"zone":"ameliegraf.de"},"sensitive_attributes":[],"private":"bnVsbA=="}]}],"check_results":null} +{ + "version": 4, + "terraform_version": "1.14.3", + "serial": 218, + "lineage": "8aff5d23-05f6-10eb-0ae6-1084c787677e", + "outputs": { + "velero_backup_sa_email": { + "value": "velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "type": "string" + } + }, + "resources": [ + { + "mode": "managed", + "type": "google_project", + "name": "backup_project", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "index_key": 0, + "schema_version": 1, + "attributes": { + "auto_create_network": true, + "billing_account": null, + "deletion_policy": "DELETE", + "effective_labels": {}, + "folder_id": "", + "id": "projects/velero-backup-dc8c8f74", + "labels": {}, + "name": "velero-backup", + "number": "408632269830", + "org_id": "267822720032", + "project_id": "velero-backup-dc8c8f74", + "skip_delete": null, + "terraform_labels": {}, + "timeouts": null + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwLCJyZWFkIjo2MDAwMDAwMDAwMDAsInVwZGF0ZSI6NjAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIxIn0=", + "dependencies": [ + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_organization_policy", + "name": "allow_key_creation", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "boolean_policy": [ + { + "enforced": false + } + ], + "constraint": "constraints/iam.disableServiceAccountKeyCreation", + "etag": "CK28j9IGEKii/f4B", + "id": "velero-backup-dc8c8f74:iam.disableServiceAccountKeyCreation", + "list_policy": [], + "project": "velero-backup-dc8c8f74", + "restore_policy": [], + "timeouts": null, + "update_time": "2026-06-30T15:18:05.534729Z", + "version": 0 + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoyNDAwMDAwMDAwMDAsImRlbGV0ZSI6MjQwMDAwMDAwMDAwLCJyZWFkIjoyNDAwMDAwMDAwMDAsInVwZGF0ZSI6MjQwMDAwMDAwMDAwfX0=", + "dependencies": [ + "google_project.backup_project", + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_service", + "name": "drive_api", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "disable_dependent_services": null, + "disable_on_destroy": false, + "id": "velero-backup-dc8c8f74/drive.googleapis.com", + "project": "velero-backup-dc8c8f74", + "service": "drive.googleapis.com", + "timeouts": null + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=", + "dependencies": [ + "google_project.backup_project", + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_service_account", + "name": "velero_backup_sa", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "account_id": "velero-backup-sa", + "create_ignore_already_exists": null, + "description": "", + "disabled": false, + "display_name": "Velero GDrive Backup Service Account", + "email": "velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "id": "projects/velero-backup-dc8c8f74/serviceAccounts/velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "member": "serviceAccount:velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "name": "projects/velero-backup-dc8c8f74/serviceAccounts/velero-backup-sa@velero-backup-dc8c8f74.iam.gserviceaccount.com", + "project": "velero-backup-dc8c8f74", + "timeouts": null, + "unique_id": "110772617250427578026" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjozMDAwMDAwMDAwMDB9fQ==", + "dependencies": [ + "google_project.backup_project", + "google_project_service.drive_api", + "random_id.project_suffix" + ] + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "ameliegraf_de_first", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159023749", + "subdomain": "", + "target": "151.101.128.119", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "ameliegraf_de_second", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159023747", + "subdomain": "", + "target": "151.101.192.119", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370186587", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxkPdqXqsRT9NMioibnQJ1MmOX4Yzp/pwpJAIEGawsVLwZCkkhZEH5SyT4CSVz3AS6/XG2Qgx/a2hYctkzXSXllBhFDvixie6oXCOsjqyfr7R5s4LaKb399djFFl/GC7gSV+PUAW6sI02vJPfmn8BaVRAkrH0OrcjX3LSaTS5RRR9QGNCx0JreM+ho2Mcp8VbZCwnCMu42IjilR1d+kQX+2x0+r6mO0eJfP2QKOVpRnBXgv/FT+8jE+dmusf8MFoXxKuX6QjUh5TBH2J9W5NHUiBB4eC2DTrceuO1bM8ycmaGS95e1BmYXMcwfJknhjIgK85jESA8uDa38PIrN/b7WwIDAQAB", + "ttl": 3600, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190173", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxR/e/Bc6/6Rfhos0ZQoVsq4HV8wkOdnOgkyubzvnepRDm/ARCws/CTvg9azJGFafsOsft1JZRAypj8mMovnDBjnW3mclVCyHQO34VLm13Et8ySX3GeJwwJQKx52PHsCQT1eEeEF3IjckS9wDiCkgdty9NEqpdF76N62nj6j8WY0czNxrYT0ivyiKQ6reB/mOeTiqPHiSHuB3ANxebwy5/wLilHSH320T9C+TDqcZ/Q6VTrUFpXIMjccEg93ZPaIu++FMTWZAe1pX6IWMuBXt5xRLLTamTzDUIOfwhvMxVee+d9mqwvIOc6J6ZiBhhCZpSVjiVLI5NcfNICQU4kjakwIDAQAB", + "ttl": 3600, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190174", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqT7j2pdU/dKDp7392+67cqI54QSwQsYrbdJa0aOH94m5gcXa3B2CZvuN2iKt6mO2mUtzWUbwKcNVL0p9yVW6nHpCMNefUS3NfZ8KQfl+lVsaYZXzYZwuTy2ZMvaBZpftIQjclfChFrOtMvBOTpdu8SBJT8hXnqkOYvtuHPBG+qDsFvsV+N4jjHtYbMPMnD2w7GeYciFWzp3bM9FbYIgdzyD+jzIYkaJlph4cMJBMoOredJhK+T2F95uvsvUk43QNU6KujLTFL6F/wNM/zSmH+5hYBAgAMG3QAguhicATJHV6bxd2oM1aLWNjZt90xBkTmMMzvtLjcGGpkgNuxa35WwIDAQAB", + "ttl": 3600, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_haumdaucher_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365220662", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4al3nYNZLlUBn0dcxqui5q48jjk4YvB2d2VNLfr864YdCm+3WqO6fc8Yx7sO4jKiX+OpMXnOc2RZazCCpcdCofJwTZxT+H0u2h4uyveEHq8UYqQZ66aAFLt3N1HYMT6+uFJZpKpSkFgqLagkQoW/cQHguJuu7Xjmt09fLTsBunjfJkKfUcjcyNlpnnAcVuo/TT7DKNzjB436yB1pf8QHxykUkV/lfz1/IzfRV//hR3H5pSNn4kR9qT9HqrTGgaZkPmStjoV2i2Dih4d3jO9FF1VDUNDm7W7739yiQhRZ5yelj5TaWGeRxWv+xM3YpVGqJzWI9oCuSpR2QaVKaOMQwIDAQAB", + "ttl": 3600, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190171", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp9dLGkWdBZ0YyjBdRVTf26Fo+lVag1dfHHpO4N+oFLg0xV1gRJFcSGjteHUoKbrJxgesAwSmBYsaWAZB0RCI4wbAZKgb++6NX2Tk5gxkKys9pmc3ufGhCsjQkiiNepUkgalJRU7WAsWWolHXqn69D2DkXx9fPekdwaDeJwdtozoGacdbj46Ef1btGo48CJKk5rjh39c7BDNMmYEXXMztBIK2K80Y5WrLJZFxkvEKBrEB4pVoPDa3xEYcR0olLdDwB2SOEX6HSQ2xXkNB3KxbyIiHJTSJsNxquozTzfiWoqly/AdQLCU9j3jtqP88ne61NciQcxGdvOcQ0yUtFoydOwIDAQAB", + "ttl": 3600, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dkim_google_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365220661", + "subdomain": "google._domainkey", + "target": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz4hYXxdgHDaNwqiUrHa4S9vbqLx/iV2avvgwwPqa5+2aOef109Ap8U7OfgFQQgwRVXx5XWbkKL69as3sdzuVA+8A8fRKbprugZEFoL9gyoTxPQveKO2s+1CsP0fUIx1c7aemfgn6mrfC0Ep17D70Y9YcQQWgiNHGHlgQDE1z6ncfUquHdipcmd0wEIAmjdNDBoqf3b1SRz5xaayKIeAsf/f2AFB1IeYwvLEaOC/mQDZWsry86RwjAfKvxbw0zAQaxSLFOho+kuxL2YUPbT55mZaB9Bi1G4VemzZUGuqXoq8xPzFOO/wxNi6Pei0Vs9wLwFahtuxriin4EVYOkjF4uwIDAQAB", + "ttl": 3600, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370186586", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190169", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190167", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_haumdaucher_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365220116", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190166", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "dmarc_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365220117", + "subdomain": "_dmarc", + "target": "v=DMARC1; p=none; rua=mailto:custom-admin@haumdaucher.de; ruf=mailto:custom-admin@haumdaucher.de", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370186584", + "subdomain": "", + "target": "google-site-verification=LwCbVqOp4c200QYrEEX1m4lIebOzxl5eBb2IkHbrSVA", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370189154", + "subdomain": "", + "target": "google-site-verification=zwmmYhET0gyCJr_An22btaOVcpsE_nR2b1St0y4jn1A", + "ttl": 60, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370188597", + "subdomain": "", + "target": "google-site-verification=DcG0tKp5YXxCRvw_Ekxa-3gbzdkZvxXUVkPs8aq9yQ4", + "ttl": 60, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370188972", + "subdomain": "", + "target": "google-site-verification=SHFDcMegmOoh9syhj7_xBH9dLQxA2NMnh_zvg4Ma0CM", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "google_domain_verification_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365216140", + "subdomain": "", + "target": "google-site-verification=YwUd-Bmbq1-lA7uYGcowsLEMczqx1odndFZq_Nk3nvM", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "haumdaucher_domain", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5106871420", + "subdomain": "", + "target": "136.243.23.215", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "haumdaucher_mx_record", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5365107576", + "subdomain": "", + "target": "1 SMTP.GOOGLE.COM.", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "haumdaucher_wildcard_domain", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5112336220", + "subdomain": "*", + "target": "136.243.23.215", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "kochen_haumdaucher", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5205826663", + "subdomain": "kochen", + "target": "haumdaucher-datalab.github.io.", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "krassescheisse_subdomains", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "index_key": "alertmanager", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532212", + "subdomain": "alertmanager", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "auth", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532224", + "subdomain": "auth", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "chat", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532214", + "subdomain": "chat", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "cloud", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532215", + "subdomain": "cloud", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "code", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532228", + "subdomain": "code", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "grafana", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532218", + "subdomain": "grafana", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "hub", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532223", + "subdomain": "hub", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "imap", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532227", + "subdomain": "imap", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "jaeger", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532222", + "subdomain": "jaeger", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "kc", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113533002", + "subdomain": "kc", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "ldap", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532229", + "subdomain": "ldap", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "monitoring", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532226", + "subdomain": "monitoring", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "mqtt", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532213", + "subdomain": "mqtt", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "phpmyadmin", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532217", + "subdomain": "phpmyadmin", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "phppgadmin", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532231", + "subdomain": "phppgadmin", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "pop3", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532225", + "subdomain": "pop3", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "prometheus", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532230", + "subdomain": "prometheus", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "rstudio", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532221", + "subdomain": "rstudio", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "smtp", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113532216", + "subdomain": "smtp", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "webapp", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113533005", + "subdomain": "webapp", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "www", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5122534663", + "subdomain": "www", + "target": "krassescheisse.de.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "moritzgraf_subdomains", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "index_key": "alertmanager", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870451", + "subdomain": "alertmanager", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "auth", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870439", + "subdomain": "auth", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "chat", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870446", + "subdomain": "chat", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "cloud", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870454", + "subdomain": "cloud", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "code", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870455", + "subdomain": "code", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "grafana", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870443", + "subdomain": "grafana", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "hub", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870438", + "subdomain": "hub", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "imap", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870448", + "subdomain": "imap", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "jaeger", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870437", + "subdomain": "jaeger", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "kc", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113533004", + "subdomain": "kc", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "ldap", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870449", + "subdomain": "ldap", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "monitoring", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870447", + "subdomain": "monitoring", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "mqtt", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870444", + "subdomain": "mqtt", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "phpmyadmin", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870440", + "subdomain": "phpmyadmin", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "phppgadmin", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870452", + "subdomain": "phppgadmin", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "pop3", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870453", + "subdomain": "pop3", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "prometheus", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870456", + "subdomain": "prometheus", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "rstudio", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870442", + "subdomain": "rstudio", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "smtp", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870450", + "subdomain": "smtp", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "webapp", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113533003", + "subdomain": "webapp", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "www", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5106870435", + "subdomain": "www", + "target": "moritzgraf.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "moritzgraf_subdomains_k8s", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "index_key": "corona", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113233478", + "subdomain": "corona", + "target": "haumdaucher.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "corona-api", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113233479", + "subdomain": "corona-api", + "target": "haumdaucher.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "git", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5116593521", + "subdomain": "git", + "target": "haumdaucher.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + }, + { + "index_key": "tt-rss", + "schema_version": 0, + "attributes": { + "fieldtype": "CNAME", + "id": "5113719565", + "subdomain": "tt-rss", + "target": "haumdaucher.de.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "moritzgraf_wildcard_domain", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159040750", + "subdomain": "*", + "target": "136.243.23.215", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5370186585", + "subdomain": "", + "target": "1 smtp.google.com.", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5370189178", + "subdomain": "", + "target": "1 smtp.google.com.", + "ttl": 60, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5370188840", + "subdomain": "", + "target": "1 smtp.google.com.", + "ttl": 60, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5370188995", + "subdomain": "", + "target": "1 smtp.google.com.", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "mx_record_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "MX", + "id": "5365216454", + "subdomain": "", + "target": "1 SMTP.GOOGLE.COM.", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "one", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5114515103", + "subdomain": "one", + "target": "136.243.23.215", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_ameliegraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370186583", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_grabengasse7_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190168", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "grabengasse7.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_graf_fam_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190172", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "graf-fam.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_haumdaucher_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365219216", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "haumdaucher.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_krassescheisse_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5370190170", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "krassescheisse.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "spf_moritzgraf_de", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "TXT", + "id": "5365219217", + "subdomain": "", + "target": "v=spf1 include:_spf.google.com ~all", + "ttl": 60, + "zone": "moritzgraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "wildcard_ameliegraf_de_first", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159023750", + "subdomain": "*", + "target": "151.101.128.119", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "ovh_domain_zone_record", + "name": "wildcard_ameliegraf_de_second", + "provider": "provider[\"registry.terraform.io/ovh/ovh\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "fieldtype": "A", + "id": "5159023748", + "subdomain": "*", + "target": "151.101.192.119", + "ttl": 60, + "zone": "ameliegraf.de" + }, + "sensitive_attributes": [], + "identity_schema_version": 0, + "private": "bnVsbA==" + } + ] + }, + { + "mode": "managed", + "type": "random_id", + "name": "project_suffix", + "provider": "provider[\"registry.terraform.io/hashicorp/random\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "b64_std": "3IyPdA==", + "b64_url": "3IyPdA", + "byte_length": 4, + "dec": "3700199284", + "hex": "dc8c8f74", + "id": "3IyPdA", + "keepers": null, + "prefix": null + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + } + ], + "check_results": null +} diff --git a/terraform/versions.tf b/terraform/versions.tf index c76c1c8..b98aaa1 100644 --- a/terraform/versions.tf +++ b/terraform/versions.tf @@ -3,6 +3,14 @@ terraform { ovh = { source = "ovh/ovh" } + google = { + source = "hashicorp/google" + version = "~> 5.0" + } + local = { + source = "hashicorp/local" + version = "~> 2.0" + } } required_version = ">= 0.13" }