151 lines
5.0 KiB
Markdown
151 lines
5.0 KiB
Markdown
# Backup de dashboards de Grafana
|
|
|
|
Este servidor corre Grafana en `http://localhost:3000` (puerto expuesto: 3000).
|
|
El backup se hace vía la API HTTP de Grafana (no toca los volúmenes/DB de Docker
|
|
directamente), exportando cada dashboard como JSON.
|
|
|
|
## Archivos involucrados
|
|
|
|
| Ruta | Qué es |
|
|
|----------------------------------------------------------------|-------------------------------------------|
|
|
| `/opt/server/scripts/backup-grafana-dashboards.sh` | Script de backup (root:root, permisos 700 porque contiene la contraseña de Grafana) |
|
|
| `/opt/server/backups/grafana_dashboards/` | Carpeta con los `.tar.gz` generados |
|
|
|
|
**No está agregado a crontab** (a diferencia de `backup-jenkins-home.sh`). Se
|
|
ejecuta manualmente con `sudo` cuando se necesite.
|
|
|
|
## Cómo correr el backup manualmente
|
|
|
|
```bash
|
|
sudo /opt/server/scripts/backup-grafana-dashboards.sh
|
|
```
|
|
|
|
Esto genera `/opt/server/backups/grafana_dashboards/grafana_dashboards_YYYYMMDD.tar.gz`
|
|
y conserva solo los últimos 4 backups (los más viejos se borran automáticamente,
|
|
`KEEP=4` dentro del script).
|
|
|
|
### Convención de nombres dentro del tar.gz
|
|
|
|
Cada dashboard se guarda como:
|
|
|
|
```
|
|
<título_sanitizado>__<uid>.json
|
|
```
|
|
|
|
Ejemplo:
|
|
|
|
```
|
|
Monitoreo__adpjcx6.json
|
|
Node_Exporter_Full__rYdddlPWk.json
|
|
Node_Exporter_Full_completo__rYdddlPWk3.json
|
|
MySQL_Overview__MQWgroiiz.json
|
|
```
|
|
|
|
El título se sanitiza (solo `A-Za-z0-9`, resto reemplazado por `_`), y el `uid`
|
|
real de Grafana queda al final por si dos títulos sanitizados coinciden.
|
|
|
|
### Ver contenido de un backup sin extraerlo
|
|
|
|
```bash
|
|
sudo tar tzf /opt/server/backups/grafana_dashboards/grafana_dashboards_<fecha>.tar.gz
|
|
```
|
|
|
|
## Cómo restaurar un dashboard
|
|
|
|
Cada archivo `.json` dentro del tar tiene esta forma (respuesta cruda de la API
|
|
`GET /api/dashboards/uid/{uid}`):
|
|
|
|
```json
|
|
{
|
|
"meta": { ... },
|
|
"dashboard": { ... } <- esto es lo que Grafana necesita para importar
|
|
}
|
|
```
|
|
|
|
**IMPORTANTE:** para importar, Grafana necesita únicamente el contenido del
|
|
campo `dashboard`, sin el wrapper `meta`. Si se sube/pega el JSON completo
|
|
(`meta` + `dashboard`) da el error:
|
|
|
|
```
|
|
Invalid or unknown dashboard schema
|
|
```
|
|
|
|
### Opción A — Restaurar vía API (rápido, scripteable)
|
|
|
|
```bash
|
|
sudo bash -c '
|
|
LATEST=$(ls -1t /opt/server/backups/grafana_dashboards/grafana_dashboards_*.tar.gz | head -1)
|
|
mkdir -p /tmp/restore
|
|
tar xzf "$LATEST" -C /tmp/restore ./<archivo>.json
|
|
|
|
jq "{dashboard: (.dashboard + {id: null}), overwrite: true}" \
|
|
/tmp/restore/<archivo>.json > /tmp/restore/payload.json
|
|
|
|
curl -sf -X POST -H "Content-Type: application/json" \
|
|
-u admin:<password_de_grafana> \
|
|
http://localhost:3000/api/dashboards/db \
|
|
-d @/tmp/restore/payload.json
|
|
'
|
|
```
|
|
|
|
Notas:
|
|
- `id: null` — el `id` interno viejo puede no existir más (ej. si se borró el
|
|
dashboard); ponerlo en `null` hace que Grafana cree uno nuevo.
|
|
- El `uid` se mantiene igual, así el dashboard vuelve con la misma URL que tenía.
|
|
- `overwrite: true` evita el error 412 si el uid ya existiera.
|
|
- Respuesta esperada: `{"status":"success", "uid": "...", "url": "...", ...}`.
|
|
- Limpiar `/tmp/restore` después (`sudo rm -rf /tmp/restore`).
|
|
|
|
### Opción B — Restaurar a mano desde la UI
|
|
|
|
1. Extraer solo el campo `dashboard` (sin el wrapper `meta`):
|
|
|
|
```bash
|
|
sudo bash -c '
|
|
LATEST=$(ls -1t /opt/server/backups/grafana_dashboards/grafana_dashboards_*.tar.gz | head -1)
|
|
mkdir -p /tmp/restore
|
|
tar xzf "$LATEST" -C /tmp/restore ./<archivo>.json
|
|
jq ".dashboard" /tmp/restore/<archivo>.json > /tmp/restore/import.json
|
|
'
|
|
```
|
|
|
|
2. Bajar `/tmp/restore/import.json` a tu equipo si vas a subirlo como archivo
|
|
(`scp jenkins-srv:/tmp/restore/import.json .`), o simplemente abrirlo con
|
|
`cat`/editor para copiar el contenido.
|
|
|
|
3. En la UI de Grafana (`http://172.19.13.204:3000`):
|
|
**Dashboards → New → Import → Upload JSON file** (o pegar el contenido en
|
|
"Import via panel json").
|
|
|
|
4. Confirmar el nombre/folder propuesto y click **Import**.
|
|
|
|
5. Si Grafana avisa que el `uid` ya existe, ofrece la opción de sobrescribir
|
|
en el mismo diálogo.
|
|
|
|
6. Limpiar `/tmp/restore` cuando termines.
|
|
|
|
## Encontrar rápido el uid/título de un dashboard sin extraer todo el tar
|
|
|
|
```bash
|
|
for f in $(tar tzf <backup>.tar.gz | grep '\.json$'); do
|
|
echo -n "$f -> "
|
|
tar xzOf <backup>.tar.gz "$f" | jq -r '.dashboard.title'
|
|
done
|
|
```
|
|
|
|
(Con la convención de nombres actual esto ya no es necesario para uso normal,
|
|
pero sirve como referencia si en algún momento se cambia el formato del script.)
|
|
|
|
## Credenciales
|
|
|
|
El script usa el usuario admin de Grafana (`admin`) y su contraseña, embebidas
|
|
en `/opt/server/scripts/backup-grafana-dashboards.sh`. Por eso el script tiene
|
|
permisos `700` (solo root puede leerlo/ejecutarlo), a diferencia de otros
|
|
scripts en `/opt/server/scripts/` que son `755`.
|
|
|
|
## Probado el (2026-08-05)
|
|
|
|
Ciclo completo validado: crear dashboard de prueba → backup → borrar dashboard
|
|
→ restaurar (API y manual) → verificar que el contenido vuelve idéntico. Ambos
|
|
métodos de restauración funcionan.
|