tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1572Shell 203Rust 109Markdown 993728 Definiciones

⎇ f33df351cfd0c70b5909b01d1f0ff4105adf9010 scripts/respaldo-gitea.sh Shell · 65 líneas · 3.4 KB Historia crudo

la caja tiene HORA, LATIDO y ROTACIÓN — y el respaldo del gitea dejó de ser a mano 0a7afebe9 · Sergio ·

1#!/bin/sh
2# respaldo-gitea.sh — el respaldo PERIÓDICO del gitea: la sqlite y los repos.
3#
4# ── POR QUÉ EXISTE (SDD 28 §6.15) ───────────────────────────────────────────────────────────────
5# `respaldo-storagebox.sh` respalda el STORE de artefactos, que es lo reconstruible. **Los datos del
6# gitea —44 repos, 26 de ellos sin copia en ningún otro lado— no los cubría nadie**, y estuvieron en
7# UNA sola copia hasta el 2026-09-14, cuando se hizo a mano. Un respaldo que depende de que alguien
8# se acuerde es un respaldo que no existe: esto es lo mismo, con `crond` disparándolo.
9#
10# ── LAS DOS PARTES, Y POR QUÉ LA SQLITE NO SE COPIA A LO BRUTO ──────────────────────────────────
11# Un `cp` de una sqlite viva puede quedar a medias de una transacción y el fichero resultante abre
12# —parece bueno— y le faltan las últimas escrituras. `.backup` del propio sqlite3 toma una copia
13# CONSISTENTE con el servidor corriendo (1,5 s medidos sobre los 2 G de gioser). Los repos en cambio
14# son ficheros que git sólo AÑADE, así que `rsync -aH` alcanza.
15#
16# ⚠ Al Storage Box se entra por el PUERTO 23: el 22 da un SFTP restringido y contesta
17# `Permission denied (publickey,password)` teniendo la clave buena — se lee como «no tengo acceso».
18#
19# Uso:  respaldo-gitea.sh            (desde la caja que sirve el gitea)
20#       DRY=1 respaldo-gitea.sh      (dice qué haría y no sube nada)
21set -eu
22
23GITEA_DATA="${GITEA_DATA:-/var/lib/gitea}"
24GITEA_ETC="${GITEA_ETC:-/etc/gitea}"
25SB_USER="${SB_USER:-u647150}"
26SB_HOST="${SB_HOST:-u647150.your-storagebox.de}"
27SB_PORT="${SB_PORT:-23}"
28KEY="${KEY:-/root/.ssh/github5}"
29DESTINO="${DESTINO:-gitea}"
30TMP="${TMP:-/work/respaldo-gitea}"
31
32log() { echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*"; }
33
34[ -d "$GITEA_DATA" ] || { log "no existe $GITEA_DATA — ¿esta caja sirve el gitea?"; exit 78; }
35command -v sqlite3 >/dev/null || { log "falta sqlite3: la DB se copiaría a lo bruto y eso NO es consistente"; exit 78; }
36[ -f "$KEY" ] || { log "falta la clave $KEY — sin ella no hay Storage Box"; exit 78; }
37
38mkdir -p "$TMP"
39DB="$GITEA_DATA/gitea.db"
40if [ -f "$DB" ]; then
41	log "snapshot consistente de la sqlite…"
42	rm -f "$TMP/gitea.db"
43	sqlite3 "$DB" ".backup '$TMP/gitea.db'"
44	# Un `.backup` que deja un fichero de 0 bytes es el modo de fallo que más engaña: sube, ocupa
45	# lugar y no restaura nada (`CLAUDE.md` regla 3).
46	[ -s "$TMP/gitea.db" ] || { log "el snapshot salió VACÍO — no se sube nada"; exit 1; }
47	log "  $(du -h "$TMP/gitea.db" | cut -f1)"
48else
49	log "no hay $DB (¿DB_TYPE distinto de sqlite3?) — sigo con los repos"
50fi
51
52SSH_CMD="ssh -4 -p $SB_PORT -i $KEY -o StrictHostKeyChecking=accept-new -o ServerAliveInterval=30"
53RS="rsync -aH --partial -e '$SSH_CMD'"
54[ "${DRY:-0}" = "1" ] && RS="$RS --dry-run" && log "DRY=1: no se sube nada"
55
56log "subiendo repos y config…"
57eval rsync -aH --partial -e "'$SSH_CMD'" ${DRY:+--dry-run} \
58	--exclude 'gitea.db' --exclude 'gitea.db-wal' --exclude 'gitea.db-shm' \
59	"$GITEA_DATA/" "$SB_USER@$SB_HOST:$DESTINO/data/"
60eval rsync -aH --partial -e "'$SSH_CMD'" ${DRY:+--dry-run} \
61	"$GITEA_ETC/" "$SB_USER@$SB_HOST:$DESTINO/etc/"
62[ -s "$TMP/gitea.db" ] && eval rsync -aH --partial -e "'$SSH_CMD'" ${DRY:+--dry-run} \
63	"$TMP/gitea.db" "$SB_USER@$SB_HOST:$DESTINO/gitea.db"
64
65log "listo."