237 lines
6.3 KiB
Bash
237 lines
6.3 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ============================================================
|
|
# Phase 6 — Grafana + Prometheus Deployment on PD
|
|
# Run this script on PlausibleDeniability as root or with sudo
|
|
# ============================================================
|
|
|
|
echo "=== Phase 6: Grafana + Prometheus ==="
|
|
echo ""
|
|
|
|
# ---- 1. Scaffold directories ----
|
|
echo "[1/6] Scaffolding directories..."
|
|
|
|
mkdir -p /mnt/docker-ssd/docker/compose/monitoring/provisioning/datasources
|
|
mkdir -p /mnt/docker-ssd/docker/compose/monitoring/provisioning/dashboards
|
|
|
|
mkdir -p /mnt/tank/docker/appdata/prometheus
|
|
chown 65534:65534 /mnt/tank/docker/appdata/prometheus
|
|
|
|
mkdir -p /mnt/tank/docker/appdata/grafana
|
|
chown 472:472 /mnt/tank/docker/appdata/grafana
|
|
|
|
echo " Done."
|
|
|
|
# ---- 2. Write docker-compose.yaml ----
|
|
echo "[2/6] Writing docker-compose.yaml..."
|
|
|
|
cat > /mnt/docker-ssd/docker/compose/monitoring/docker-compose.yaml << 'COMPOSE'
|
|
name: monitoring
|
|
|
|
services:
|
|
prometheus:
|
|
image: prom/prometheus:v3.4.0
|
|
container_name: prometheus
|
|
restart: unless-stopped
|
|
ports:
|
|
- "9090:9090"
|
|
command:
|
|
- '--config.file=/etc/prometheus/prometheus.yml'
|
|
- '--storage.tsdb.path=/prometheus'
|
|
- '--storage.tsdb.retention.time=90d'
|
|
- '--web.enable-lifecycle'
|
|
volumes:
|
|
- /mnt/tank/docker/appdata/prometheus:/prometheus
|
|
- /mnt/docker-ssd/docker/compose/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
|
networks:
|
|
- default
|
|
|
|
grafana:
|
|
image: grafana/grafana:13.0.1
|
|
container_name: grafana
|
|
restart: unless-stopped
|
|
ports:
|
|
- "3000:3000"
|
|
environment:
|
|
TZ: ${TZ}
|
|
GF_SECURITY_ADMIN_USER: ${GF_ADMIN_USER}
|
|
GF_SECURITY_ADMIN_PASSWORD: ${GF_ADMIN_PASS}
|
|
GF_SERVER_ROOT_URL: https://${GF_HOST}/
|
|
volumes:
|
|
- /mnt/tank/docker/appdata/grafana:/var/lib/grafana
|
|
- /mnt/docker-ssd/docker/compose/monitoring/provisioning:/etc/grafana/provisioning:ro
|
|
networks:
|
|
- pangolin
|
|
- default
|
|
|
|
node-exporter:
|
|
image: prom/node-exporter:v1.9.0
|
|
container_name: node-exporter
|
|
restart: unless-stopped
|
|
ports:
|
|
- "9100:9100"
|
|
command:
|
|
- '--path.procfs=/host/proc'
|
|
- '--path.sysfs=/host/sys'
|
|
- '--path.rootfs=/rootfs'
|
|
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
|
|
volumes:
|
|
- /proc:/host/proc:ro
|
|
- /sys:/host/sys:ro
|
|
- /:/rootfs:ro
|
|
networks:
|
|
- default
|
|
|
|
networks:
|
|
pangolin:
|
|
external: true
|
|
COMPOSE
|
|
|
|
echo " Done."
|
|
|
|
# ---- 3. Write prometheus.yml ----
|
|
echo "[3/6] Writing prometheus.yml..."
|
|
|
|
cat > /mnt/docker-ssd/docker/compose/monitoring/prometheus.yml << 'PROMCFG'
|
|
global:
|
|
scrape_interval: 15s
|
|
evaluation_interval: 15s
|
|
|
|
scrape_configs:
|
|
# ------- PlausibleDeniability (local) -------
|
|
- job_name: 'pd-node'
|
|
static_configs:
|
|
- targets: ['node-exporter:9100']
|
|
labels:
|
|
host: 'plausible-deniability'
|
|
|
|
- job_name: 'pd-netdata'
|
|
metrics_path: /api/v1/allmetrics
|
|
params:
|
|
format: [prometheus]
|
|
static_configs:
|
|
- targets: ['10.5.1.6:19999']
|
|
labels:
|
|
host: 'plausible-deniability'
|
|
|
|
# ------- Serenity -------
|
|
- job_name: 'serenity-netdata'
|
|
metrics_path: /api/v1/allmetrics
|
|
params:
|
|
format: [prometheus]
|
|
static_configs:
|
|
- targets: ['10.5.1.5:19999']
|
|
labels:
|
|
host: 'serenity'
|
|
|
|
# ------- N.O.M.A.D. -------
|
|
# Uncomment when Netdata or node-exporter is available on N.O.M.A.D.
|
|
# - job_name: 'nomad-netdata'
|
|
# metrics_path: /api/v1/allmetrics
|
|
# params:
|
|
# format: [prometheus]
|
|
# static_configs:
|
|
# - targets: ['10.5.1.16:19999']
|
|
# labels:
|
|
# host: 'nomad'
|
|
PROMCFG
|
|
|
|
echo " Done."
|
|
|
|
# ---- 4. Write Grafana provisioning ----
|
|
echo "[4/6] Writing Grafana provisioning configs..."
|
|
|
|
cat > /mnt/docker-ssd/docker/compose/monitoring/provisioning/datasources/prometheus.yml << 'DATASRC'
|
|
apiVersion: 1
|
|
|
|
datasources:
|
|
- name: Prometheus
|
|
type: prometheus
|
|
access: proxy
|
|
url: http://prometheus:9090
|
|
isDefault: true
|
|
editable: true
|
|
DATASRC
|
|
|
|
cat > /mnt/docker-ssd/docker/compose/monitoring/provisioning/dashboards/dashboards.yml << 'DASHCFG'
|
|
apiVersion: 1
|
|
|
|
providers:
|
|
- name: 'default'
|
|
orgId: 1
|
|
folder: ''
|
|
type: file
|
|
disableDeletion: false
|
|
editable: true
|
|
options:
|
|
path: /var/lib/grafana/dashboards
|
|
foldersFromFilesStructure: false
|
|
DASHCFG
|
|
|
|
echo " Done."
|
|
|
|
# ---- 5. Generate .env ----
|
|
echo "[5/6] Generating .env..."
|
|
|
|
GF_PASS=$(openssl rand -hex 16)
|
|
|
|
cat > /mnt/docker-ssd/docker/compose/monitoring/.env << ENV
|
|
TZ=America/New_York
|
|
|
|
# Grafana
|
|
GF_ADMIN_USER=admin
|
|
GF_ADMIN_PASS=${GF_PASS}
|
|
GF_HOST=grafana.paccoco.com
|
|
ENV
|
|
|
|
echo " Done."
|
|
echo ""
|
|
echo " Grafana admin password: ${GF_PASS}"
|
|
echo " (saved in /mnt/docker-ssd/docker/compose/monitoring/.env)"
|
|
echo ""
|
|
|
|
# ---- 6. Validate and deploy ----
|
|
echo "[6/6] Validating and deploying..."
|
|
|
|
cd /mnt/docker-ssd/docker/compose/monitoring
|
|
docker compose --env-file .env config > /dev/null 2>&1
|
|
echo " Compose config valid."
|
|
|
|
docker compose --env-file .env up -d
|
|
echo ""
|
|
echo "=== Deployment complete ==="
|
|
echo ""
|
|
echo "Waiting 10 seconds for containers to start..."
|
|
sleep 10
|
|
|
|
# ---- Post-deploy checks ----
|
|
echo ""
|
|
echo "=== Post-Deploy Verification ==="
|
|
echo ""
|
|
|
|
echo "--- Container status ---"
|
|
docker ps --filter name=prometheus --filter name=grafana --filter name=node-exporter --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|
echo ""
|
|
|
|
echo "--- Prometheus targets ---"
|
|
curl -s http://10.5.1.6:9090/api/v1/targets 2>/dev/null | python3 -m json.tool 2>/dev/null | head -30 || echo "Prometheus not yet responding (may need a moment)"
|
|
echo ""
|
|
|
|
echo "--- Grafana health ---"
|
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://10.5.1.6:3000/ 2>/dev/null || echo "000")
|
|
echo "Grafana HTTP status: ${HTTP_CODE}"
|
|
echo ""
|
|
|
|
echo "--- Node exporter ---"
|
|
curl -s http://10.5.1.6:9100/metrics 2>/dev/null | head -5 || echo "Node exporter not yet responding"
|
|
echo ""
|
|
|
|
echo "=== All done! ==="
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " 1. Add Pangolin resource: grafana.paccoco.com -> http://grafana:3000"
|
|
echo " 2. Log in at https://grafana.paccoco.com with admin / ${GF_PASS}"
|
|
echo " 3. Import dashboards: Node Exporter Full (ID 1860), Docker Stats (ID 893)"
|
|
echo " 4. Set up Grafana -> n8n alert webhook at https://n8n.paccoco.com/webhook/grafana-alert"
|