Establish clean homelab infrastructure baseline
lint / yaml (push) Has been cancelled
lint / ansible (push) Has been cancelled
lint / terraform (push) Has been cancelled

Reorganize the brownfield repository, remove retired and generated artifacts, harden ignore rules, and record the GitOps/IaC redesign.
This commit is contained in:
2026-09-09 16:47:20 +00:00
commit 88a02ababa
418 changed files with 50579 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Load every *.json in this folder into Grafana as a sidecar dashboard ConfigMap.
# The Grafana chart's dashboard sidecar (sidecar.dashboards.enabled) watches for
# ConfigMaps labeled grafana_dashboard=1 in the monitoring namespace and imports them.
# Idempotent — re-run after adding/updating a dashboard JSON.
#
# The VictoriaMetrics board uses a `$ds` datasource variable that resolves to the
# default datasource (VictoriaMetrics), so no per-panel rewiring is needed.
set -euo pipefail
cd "$(dirname "$0")"
NS=monitoring
for f in *.json; do
[ -e "$f" ] || continue
name="grafana-dashboard-$(basename "$f" .json)"
echo "applying $name from $f"
kubectl create configmap "$name" \
--namespace "$NS" \
--from-file="$f" \
--dry-run=client -o yaml \
| kubectl label --local -f - grafana_dashboard=1 --dry-run=client -o yaml \
| kubectl apply -f -
done
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Deploy Grafana. Create the OIDC client secret first (see oidc-secret.yaml header),
# then install the chart. Requires the metrics/logs/traces backends to exist so the
# provisioned datasources resolve.
set -euo pipefail
# 1) OIDC client secret (edit oidc-secret.yaml, or create it imperatively — preferred).
kubectl apply -f oidc-secret.yaml
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update grafana
# Pin --version after the first install (helm search repo grafana/grafana --versions).
helm upgrade --install grafana grafana/grafana \
--namespace monitoring \
--values values.yaml \
--wait
# The tailnet FQDN, once the tailscale operator assigns it:
# kubectl -n monitoring get ingress grafana -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
# Break-glass admin password:
# kubectl -n monitoring get secret grafana -o jsonpath='{.data.admin-password}' | base64 -d
@@ -0,0 +1,18 @@
# Plaintext OIDC client secret Grafana presents to Authelia. Authelia stores only the
# pbkdf2-sha512 HASH of this same value (see authelia/values.yaml grafana client).
#
# Generate a matching pair:
# authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72
# Put the "Random Password" (plaintext) below; put the "Digest" (hash) in Authelia.
#
# Do NOT commit the real secret. Create it out-of-band instead, e.g.:
# kubectl -n monitoring create secret generic grafana-oidc \
# --from-literal=client_secret='<plaintext>'
apiVersion: v1
kind: Secret
metadata:
name: grafana-oidc
namespace: monitoring
type: Opaque
stringData:
client_secret: "REPLACE_ME_WITH_PLAINTEXT_OIDC_SECRET"
@@ -0,0 +1,98 @@
# Grafana — single pane over metrics (VictoriaMetrics), logs (VictoriaLogs) and
# traces (VictoriaTraces via Jaeger API). Exposed privately on the tailnet
# (grafana.tail7e769.ts.net) and authenticated via Authelia OIDC. Local admin is
# break-glass only.
#
# Chart: grafana/grafana (repo: https://grafana.github.io/helm-charts)
# --- VictoriaLogs needs its Grafana datasource plugin ---
plugins:
- victoriametrics-logs-datasource
# --- Dashboard sidecar: auto-loads any ConfigMap labeled grafana_dashboard=1 in the
# namespace. Migrated boards live in ./dashboards and are applied by ./dashboards/apply.sh ---
sidecar:
dashboards:
enabled: true
label: grafana_dashboard
labelValue: "1"
folderAnnotation: grafana_folder
provider:
foldersFromFilesStructure: true
# --- Provisioned datasources ---
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: VictoriaMetrics
type: prometheus
access: proxy
url: http://vmsingle-main.monitoring.svc:8428
isDefault: true
jsonData:
prometheusType: Prometheus
- name: VictoriaLogs
type: victoriametrics-logs-datasource
access: proxy
url: http://vlsingle-main.monitoring.svc:9428
- name: VictoriaTraces
type: jaeger
access: proxy
# VictoriaTraces (VTSingle CR) exposes a Jaeger-compatible query API under /select/jaeger.
url: http://vtsingle-main.monitoring.svc:10428/select/jaeger
# --- Persistence on OpenEBS ZFS ---
persistence:
enabled: true
storageClassName: localpv-zfs-ceph
size: 5Gi
# --- Private exposure via the Tailscale ingress (like seaweedfs-admin) ---
# The tailscale operator provisions grafana.<tailnet>.ts.net and a TLS cert.
ingress:
enabled: true
ingressClassName: tailscale
hosts:
- grafana
tls:
- hosts:
- grafana
# --- OIDC via Authelia (AD groups -> Grafana roles) ---
# client_secret is injected from the grafana-oidc Secret (see oidc-secret.yaml),
# which overrides any value in grafana.ini.
envValueFrom:
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET:
secretKeyRef:
name: grafana-oidc
key: client_secret
grafana.ini:
server:
root_url: "https://grafana.tail7e769.ts.net" # must match the tailnet FQDN + Authelia redirect_uri
auth:
# Keep the local admin login available as break-glass; don't force OIDC-only.
disable_login_form: false
oauth_auto_login: false
auth.generic_oauth:
enabled: true
name: Authelia
client_id: grafana
scopes: "openid profile email groups"
auth_url: "https://auth.ddupan.top/api/oidc/authorization"
token_url: "https://auth.ddupan.top/api/oidc/token"
api_url: "https://auth.ddupan.top/api/oidc/userinfo"
login_attribute_path: preferred_username
name_attribute_path: name
email_attribute_path: email
groups_attribute_path: groups
# AD "Enterprise Admins" -> full Grafana server admin; "Domain Admins" -> org Admin;
# everyone else who can authenticate -> Viewer. Tune group names to taste.
role_attribute_path: "contains(groups[*], 'Enterprise Admins') && 'GrafanaAdmin' || contains(groups[*], 'Domain Admins') && 'Admin' || 'Viewer'"
allow_assign_grafana_admin: true
role_attribute_strict: false
use_pkce: true
# Dashboards are loaded by the sidecar (above) from ConfigMaps created by
# ./dashboards/apply.sh. Drop more JSON into ./dashboards and re-run that script.