Compare commits
No commits in common. "22645f139a0fbacb7ec2c13086bc8092c459d36d" and "01a6688900103bb42c741d1c121ad2e8c0a16db0" have entirely different histories.
22645f139a
...
01a6688900
4 changed files with 0 additions and 104 deletions
|
|
@ -10,10 +10,5 @@ DATA_DIR=/Volumes/Data/printhive
|
||||||
# or a network share.
|
# or a network share.
|
||||||
PGDATA_DIR=/Volumes/Data/printhive/pgdata
|
PGDATA_DIR=/Volumes/Data/printhive/pgdata
|
||||||
|
|
||||||
# Where tools/backup.sh writes (default ./backups) and how many days of
|
|
||||||
# database dumps it keeps (default 14). Best on a different disk from DATA_DIR.
|
|
||||||
BACKUP_DIR=/Volumes/Data/printhive-backups
|
|
||||||
KEEP_DAYS=14
|
|
||||||
|
|
||||||
# Thingiverse import — get a free app token at https://www.thingiverse.com/developers
|
# Thingiverse import — get a free app token at https://www.thingiverse.com/developers
|
||||||
THINGIVERSE_TOKEN=
|
THINGIVERSE_TOKEN=
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -11,4 +11,3 @@ tools/venv/
|
||||||
__pycache__/
|
__pycache__/
|
||||||
extracted/
|
extracted/
|
||||||
models/
|
models/
|
||||||
backups/
|
|
||||||
|
|
|
||||||
28
README.md
28
README.md
|
|
@ -77,34 +77,6 @@ files live on one of those.
|
||||||
A backup needs the database (or a `pg_dump`) and `uploads`; the other three rebuild themselves. Everything else in
|
A backup needs the database (or a `pg_dump`) and `uploads`; the other three rebuild themselves. Everything else in
|
||||||
the container is replaced on each update, so nothing outside these folders is kept.
|
the container is replaced on each update, so nothing outside these folders is kept.
|
||||||
|
|
||||||
### Backups
|
|
||||||
|
|
||||||
`tools/backup.sh` takes a dated dump of the database and mirrors the model files, leaving Printhive running:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./tools/backup.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
It writes to `./backups` unless `BACKUP_DIR` says otherwise: `backups/db/printhive-YYYY-MM-DD.dump` (kept for
|
|
||||||
`KEEP_DAYS`, 14 by default) and `backups/uploads`, an rsync mirror of the files — matching what's there now,
|
|
||||||
deletions included, rather than a history. Thumbnails, previews and extracted archives are skipped, as they rebuild.
|
|
||||||
Each dump is read back with `pg_restore -l` before it replaces the day's file, so a failed run leaves the older
|
|
||||||
backups alone and exits non-zero.
|
|
||||||
|
|
||||||
Nightly, at 3:30am — `crontab -e`, with the path to your own copy:
|
|
||||||
|
|
||||||
```
|
|
||||||
30 3 * * * cd /path/to/printhive && ./tools/backup.sh >> backups/backup.log 2>&1
|
|
||||||
```
|
|
||||||
|
|
||||||
Docker has to be running for it to work, and the backups are best kept on a different disk from `DATA_DIR`.
|
|
||||||
|
|
||||||
To restore the database into a running stack:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose exec -T db pg_restore -U printhive -d printhive --clean --if-exists < backups/db/printhive-2026-01-01.dump
|
|
||||||
```
|
|
||||||
|
|
||||||
Upgrading from a version that used Docker named volumes: stop the stack, run `tools/volumes-to-folders.sh` to copy the
|
Upgrading from a version that used Docker named volumes: stop the stack, run `tools/volumes-to-folders.sh` to copy the
|
||||||
data across, then start it again. The script only copies — the old volumes stay until you remove them yourself.
|
data across, then start it again. The script only copies — the old volumes stay until you remove them yourself.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# Nightly backup: a dated dump of the database, and a mirror of the model files.
|
|
||||||
#
|
|
||||||
# Run it from anywhere — it finds the folder holding docker-compose.yml itself.
|
|
||||||
# Printhive keeps running throughout; pg_dump takes a consistent snapshot.
|
|
||||||
#
|
|
||||||
# ./tools/backup.sh
|
|
||||||
#
|
|
||||||
# Settings (in .env beside docker-compose.yml, or the environment):
|
|
||||||
# BACKUP_DIR where backups go (default: ./backups)
|
|
||||||
# DATA_DIR where the data lives (default: ./data)
|
|
||||||
# KEEP_DAYS dumps to keep, in days (default: 14)
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
cd "$(dirname "$0")/.."
|
|
||||||
|
|
||||||
setting() { # name, fallback
|
|
||||||
local from_env="${!1:-}"
|
|
||||||
if [ -n "$from_env" ]; then echo "$from_env"; return; fi
|
|
||||||
if [ -f .env ]; then
|
|
||||||
local line
|
|
||||||
line="$(grep -E "^$1=" .env | tail -1 | cut -d= -f2-)"
|
|
||||||
if [ -n "$line" ]; then echo "$line"; return; fi
|
|
||||||
fi
|
|
||||||
echo "$2"
|
|
||||||
}
|
|
||||||
|
|
||||||
BACKUP_DIR="$(setting BACKUP_DIR ./backups)"
|
|
||||||
DATA_DIR="$(setting DATA_DIR ./data)"
|
|
||||||
KEEP_DAYS="$(setting KEEP_DAYS 14)"
|
|
||||||
stamp="$(date +%Y-%m-%d)"
|
|
||||||
|
|
||||||
mkdir -p "$BACKUP_DIR/db"
|
|
||||||
|
|
||||||
# --- the database -----------------------------------------------------------
|
|
||||||
# Written to a .part file first, so an interrupted run never leaves behind
|
|
||||||
# something that looks like a good backup.
|
|
||||||
dump="$BACKUP_DIR/db/printhive-$stamp.dump"
|
|
||||||
|
|
||||||
# Dumped inside the container and read back there — a dump that can't be listed
|
|
||||||
# is no backup at all, and pg_restore can only list a real file, not a pipe.
|
|
||||||
if ! docker compose exec -T db sh -c \
|
|
||||||
'pg_dump -U printhive -Fc printhive > /tmp/printhive.dump && pg_restore -l /tmp/printhive.dump > /dev/null'; then
|
|
||||||
echo "$(date '+%F %T') FAILED: couldn’t dump the database — keeping the old backups" >&2
|
|
||||||
docker compose exec -T db rm -f /tmp/printhive.dump || true
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
docker compose exec -T db cat /tmp/printhive.dump > "$dump.part"
|
|
||||||
docker compose exec -T db rm -f /tmp/printhive.dump || true
|
|
||||||
|
|
||||||
if [ ! -s "$dump.part" ]; then
|
|
||||||
echo "$(date '+%F %T') FAILED: the dump came out empty — keeping the old backups" >&2
|
|
||||||
rm -f "$dump.part"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
mv "$dump.part" "$dump"
|
|
||||||
echo "$(date '+%F %T') database → $dump ($(du -h "$dump" | cut -f1))"
|
|
||||||
|
|
||||||
# Older dumps go, so the folder doesn't grow for ever.
|
|
||||||
find "$BACKUP_DIR/db" -name 'printhive-*.dump' -type f -mtime "+$KEEP_DAYS" -delete
|
|
||||||
|
|
||||||
# --- the model files --------------------------------------------------------
|
|
||||||
# A mirror, not a history: it matches what's there now, deletions included.
|
|
||||||
# Thumbnails, previews and extracted archives are left out — they rebuild.
|
|
||||||
if [ ! -d "$DATA_DIR/uploads" ]; then
|
|
||||||
echo "$(date '+%F %T') FAILED: no $DATA_DIR/uploads — is the disk mounted?" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
rsync -a --delete "$DATA_DIR/uploads/" "$BACKUP_DIR/uploads/"
|
|
||||||
echo "$(date '+%F %T') files → $BACKUP_DIR/uploads ($(du -sh "$BACKUP_DIR/uploads" | cut -f1))"
|
|
||||||
Loading…
Reference in a new issue