DX-13: both shell scripts ran bare 'docker compose', which has no config
file to find in the layout docs/self-hosting.md tells people to use (only
docker-compose.selfhost.yml is downloaded) — they now fall back to it, while
a source checkout keeps resolving docker-compose.yml as before. The two
PowerShell scripts moved the dump through the PS pipeline, which corrupts
binary on 5.1 and cannot express -Encoding Byte at all on 7 ('Byte' is not a
supported encoding name), so they simply failed there; they now write inside
the container and 'docker compose cp' it across. backup.sh also wrote its
output straight into backups/, leaving a truncated file that looks like a
real backup when pg_dump fails — it writes a .part and promotes on success.
Both restores report a non-zero pg_restore rather than printing 'Restored'
over it. Docs now state that a backup is the dump PLUS .env: without
TOKEN_ENCRYPTION_KEY every encrypted secret in the restored database is
unreadable, which the old one-line 'back up the volume' never said.
DX-14: 'latest' moves with every release and migrations run on every boot,
so self-hosters had no way to choose when they move and no way back. Docs
gain IMAGE_TAG pinning, a rollback recipe (image-only vs schema-bearing) and
the migration-failed-at-boot case; CHANGELOG.md is generated from
releaseNotes.ts so the file cannot drift from what the app shows, and
'siftlode release' refuses on a stale one rather than regenerating it into
the clean tree it just demanded.
Verified: dump + restore round-trip on both platforms against localdev into
a scratch database (8 users, 262822 videos, schema 0082_invite_lang), and
IMAGE_TAG=0.80.0 resolves on both services in 'compose config'.
40 lines
1.7 KiB
Bash
40 lines
1.7 KiB
Bash
#!/bin/sh
|
|
# Dumps the Siftlode Postgres database to backups/siftlode-<timestamp>.dump (custom format).
|
|
# Run from the project root: ./scripts/backup.sh
|
|
#
|
|
# A dump is only HALF a backup. The other half is your `.env` — it holds TOKEN_ENCRYPTION_KEY,
|
|
# without which every encrypted value in the restored database (Google credentials, SMTP password,
|
|
# Plex token, stored refresh tokens) is unreadable. See docs/self-hosting.md § Backups.
|
|
set -e
|
|
|
|
# `docker compose` finds docker-compose.yml on its own and honours $COMPOSE_FILE. The documented
|
|
# self-host layout (docs/self-hosting.md § Get the files) has NEITHER — just the selfhost file — so
|
|
# without this the command below failed there with "no configuration file provided".
|
|
if [ -z "${COMPOSE_FILE:-}" ] && [ ! -f docker-compose.yml ] && [ -f docker-compose.selfhost.yml ]; then
|
|
COMPOSE_FILE=docker-compose.selfhost.yml
|
|
export COMPOSE_FILE
|
|
fi
|
|
|
|
USER_NAME="${POSTGRES_USER:-siftlode}"
|
|
DB_NAME="${POSTGRES_DB:-siftlode}"
|
|
mkdir -p backups
|
|
TS=$(date +%Y%m%d-%H%M%S)
|
|
OUT="backups/siftlode-$TS.dump"
|
|
|
|
# Write to a temp name and only promote it on success: a failed pg_dump would otherwise leave a
|
|
# truncated (often 0-byte) file sitting in backups/ that looks exactly like a real backup.
|
|
TMP="$OUT.part"
|
|
if ! docker compose exec -T db pg_dump -U "$USER_NAME" -Fc "$DB_NAME" > "$TMP"; then
|
|
rm -f "$TMP"
|
|
echo "BACKUP FAILED — pg_dump returned an error; no file was written." >&2
|
|
exit 1
|
|
fi
|
|
if [ ! -s "$TMP" ]; then
|
|
rm -f "$TMP"
|
|
echo "BACKUP FAILED — pg_dump produced an empty file; no backup was written." >&2
|
|
exit 1
|
|
fi
|
|
mv "$TMP" "$OUT"
|
|
echo "Wrote $OUT"
|
|
echo "Remember: back up your .env too (TOKEN_ENCRYPTION_KEY) — this dump alone cannot be fully restored."
|