mirror of
https://github.com/BaaRai/ARTEX.git
synced 2026-11-13 19:50:54 +08:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c8359fdb1 | ||
|
|
e2d7eecb61 |
+1
-1
@@ -57,4 +57,4 @@ Thumbs.db
|
||||
# bench benchmark related (local artifacts, not committed)
|
||||
/bench/
|
||||
/Dockerfile.bench
|
||||
/Dockerfile.bench.v2
|
||||
/Dockerfile.bench.v2backups/
|
||||
|
||||
@@ -148,6 +148,29 @@ ARTEX_TARGETS=linux/amd64,windows/amd64 ./build.sh --release
|
||||
|
||||
---
|
||||
|
||||
## Backups
|
||||
|
||||
`scripts/backup.sh` dumps the Postgres database (and optionally the data
|
||||
directory) with timestamped output and rotation:
|
||||
|
||||
```bash
|
||||
scripts/backup.sh --with-data # db dump + data/ archive, keep 14
|
||||
scripts/backup.sh --keep 7 # db only, keep 7
|
||||
```
|
||||
|
||||
Restore a dump into a running stack:
|
||||
|
||||
```bash
|
||||
gunzip -c backups/artex-db-<timestamp>.sql.gz | docker compose exec -T postgres \
|
||||
psql -U "$POSTGRES_USER" -d "$POSTGRES_DB"
|
||||
```
|
||||
|
||||
Daily cron example (03:20, operator crontab):
|
||||
|
||||
```
|
||||
20 3 * * * cd /path/to/ARTEX && scripts/backup.sh --with-data >> backups/backup.log 2>&1
|
||||
```
|
||||
|
||||
## Updating and upgrading
|
||||
|
||||
> Upgrading only swaps the program and never touches data: the Postgres volume `pgdata`, `./data` (jwt.key / SQLite, etc.), and `./skills` are all preserved. **No manual database migration is needed**: `artex` idempotently re-runs `schema.sql` on every start (with `ADD COLUMN` / `CREATE INDEX IF NOT EXISTS`), i.e. "restart equals migrate". It is still recommended to back up `./data` and the database before upgrading.
|
||||
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
# Backup the ARTEX database (and optionally the data directory) with rotation.
|
||||
#
|
||||
# Usage:
|
||||
# scripts/backup.sh [--with-data] [--keep N] [--output-dir DIR]
|
||||
#
|
||||
# --with-data also archive the bind-mounted data/ directory (worker
|
||||
# artifacts, evidence, skills state) as a tar.gz
|
||||
# --keep N number of db dumps to keep (default 14; data archives rotate
|
||||
# to the same count)
|
||||
# --output-dir where to write (default backups/, relative to the repo root)
|
||||
#
|
||||
# The database dump runs inside the postgres compose service, so no psql client
|
||||
# is needed on the host. Restore:
|
||||
# gunzip -c backups/artex-db-<ts>.sql.gz | docker compose exec -T postgres \
|
||||
# psql -U "$POSTGRES_USER" -d "$POSTGRES_DB"
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
usage() { sed -n '2,15p' "$0" | sed 's/^# \?//'; }
|
||||
|
||||
KEEP=14
|
||||
OUTPUT_DIR="backups"
|
||||
WITH_DATA=0
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--keep) KEEP="${2:?}"; shift 2 ;;
|
||||
--output-dir) OUTPUT_DIR="${2:?}"; shift 2 ;;
|
||||
--with-data) WITH_DATA=1; shift ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) echo "unknown option: $1" >&2; usage >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
case "$KEEP" in (*[!0-9]*|'') echo "--keep must be a positive integer" >&2; exit 2 ;; esac
|
||||
|
||||
# Compose reads .env for credentials; source it for the dump command too.
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
. ./.env
|
||||
set +a
|
||||
fi
|
||||
PGUSER_NAME="${POSTGRES_USER:-artex}"
|
||||
PGDATABASE_NAME="${POSTGRES_DB:-artex}"
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
TS=$(date -u +%Y%m%dT%H%M%SZ)
|
||||
DB_OUT="$OUTPUT_DIR/artex-db-$TS.sql.gz"
|
||||
if [ -e "$DB_OUT" ]; then
|
||||
echo "refusing to overwrite $DB_OUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker compose exec -T postgres pg_dump -U "$PGUSER_NAME" "$PGDATABASE_NAME" | gzip > "$DB_OUT"; then
|
||||
rm -f "$DB_OUT"
|
||||
echo "pg_dump failed (is the stack running?)" >&2
|
||||
exit 1
|
||||
fi
|
||||
gzip -t "$DB_OUT"
|
||||
echo "wrote $DB_OUT ($(du -h "$DB_OUT" | cut -f1))"
|
||||
|
||||
if [ "$WITH_DATA" -eq 1 ]; then
|
||||
DATA_OUT="$OUTPUT_DIR/artex-data-$TS.tar.gz"
|
||||
# data/ contains files written by the container (root); unreadable ones make
|
||||
# tar exit 2. Fail loudly rather than ship a partial archive.
|
||||
if ! tar -czf "$DATA_OUT" data 2>"$OUTPUT_DIR/.tar.err"; then
|
||||
rm -f "$DATA_OUT"
|
||||
echo "data archive failed (run as root so container-written files are readable):" >&2
|
||||
head -5 "$OUTPUT_DIR/.tar.err" >&2
|
||||
rm -f "$OUTPUT_DIR/.tar.err"
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$OUTPUT_DIR/.tar.err"
|
||||
echo "wrote $DATA_OUT ($(du -h "$DATA_OUT" | cut -f1))"
|
||||
fi
|
||||
|
||||
prune() {
|
||||
ls -1t "$OUTPUT_DIR"/$1 2>/dev/null | tail -n +$((KEEP + 1)) | while IFS= read -r old; do
|
||||
echo "pruning $old"
|
||||
rm -f "$old"
|
||||
done
|
||||
}
|
||||
prune 'artex-db-*.sql.gz'
|
||||
[ "$WITH_DATA" -eq 1 ] && prune 'artex-data-*.tar.gz'
|
||||
echo "backup complete ($KEEP newest kept)"
|
||||
Reference in New Issue
Block a user