v4 #1

Merged
yamen merged 19 commits from v4 into main 2026-04-26 00:38:14 +02:00
Showing only changes of commit fa6f4976c3 - Show all commits

110
scripts/backup-db.sh Executable file
View File

@@ -0,0 +1,110 @@
#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# Encoach / Odoo 19 — full database backup
#
# Produces an Odoo-format .zip backup that can be restored on the live VPS via
# /web/database/manager (the "Restore Database" button) or via the matching
# /web/database/restore HTTP endpoint.
#
# The zip layout matches what Odoo writes itself:
#
# <db>.zip
# ├── dump.sql # plain-text pg_dump (--no-owner --format=p)
# ├── manifest.json # Odoo metadata: db, version, modules
# └── filestore/ # contents of <data_dir>/filestore/<db>/
#
# We do this manually (instead of POST /web/database/backup) because Odoo's
# subprocess PATH on this host doesn't always contain pg_dump 18, which makes
# the HTTP endpoint return "Command pg_dump not found".
#
# Usage:
# ./scripts/backup-db.sh # backs up encoach_v2 → ./backups/
# DB=mydb OUT_DIR=/tmp ./scripts/backup-db.sh
#
# The output filename is encoach_v2_YYYYMMDD_HHMMSS.zip (UTC-local clock).
# -----------------------------------------------------------------------------
set -euo pipefail
PGBIN="${PGBIN:-/Users/yamenahmad/micromamba/envs/odoo19/bin}"
DB="${DB:-encoach_v2}"
DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-5432}"
DB_USER="${DB_USER:-yamenahmad}"
DATA_DIR="${DATA_DIR:-/tmp/odoo-data}"
OUT_DIR="${OUT_DIR:-$(cd "$(dirname "$0")/.." && pwd)/backups}"
if [[ ! -x "$PGBIN/pg_dump" ]]; then
echo "ERROR: pg_dump not found at $PGBIN/pg_dump" >&2
exit 1
fi
mkdir -p "$OUT_DIR"
TS=$(date +%Y%m%d_%H%M%S)
OUT="$OUT_DIR/${DB}_${TS}.zip"
WORK=$(mktemp -d -t encoach_backup_XXXXXX)
trap 'rm -rf "$WORK"' EXIT
echo "[1/4] pg_dump ${DB} -> ${WORK}/dump.sql"
"$PGBIN/pg_dump" \
--host="$DB_HOST" --port="$DB_PORT" --username="$DB_USER" \
--no-owner --no-privileges --format=p \
--dbname="$DB" \
> "$WORK/dump.sql"
DUMP_BYTES=$(wc -c < "$WORK/dump.sql" | tr -d ' ')
echo " dump.sql = $((DUMP_BYTES / 1024)) KB"
echo "[2/4] copy filestore -> ${WORK}/filestore/"
if [[ -d "$DATA_DIR/filestore/$DB" ]]; then
mkdir -p "$WORK/filestore"
# cp -R preserves symlinks/timestamps; the leading /. copies *contents*
cp -R "$DATA_DIR/filestore/$DB/." "$WORK/filestore/"
FS_BYTES=$(du -sk "$WORK/filestore" | awk '{print $1}')
echo " filestore = $((FS_BYTES / 1024)) MB"
else
echo " WARN: no filestore at $DATA_DIR/filestore/$DB (continuing without it)"
fi
echo "[3/4] write manifest.json"
PG_VERSION=$("$PGBIN/psql" -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB" -At -c "SHOW server_version;")
ODOO_VERSION=$("$PGBIN/psql" -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB" -At -c "SELECT latest_version FROM ir_module_module WHERE name='base';")
MAJOR=$(echo "$ODOO_VERSION" | cut -d. -f1-2)
# Build modules JSON object: {"name": "version", ...} for installed modules.
MODULES_JSON=$("$PGBIN/psql" -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB" -At -c \
"SELECT json_object_agg(name, latest_version) FROM ir_module_module WHERE state='installed';")
cat > "$WORK/manifest.json" <<EOF
{
"odoo_dump": "1",
"db_name": "${DB}",
"version": "${MAJOR}",
"version_info": [${MAJOR%%.*}, ${MAJOR#*.}, 0, "final", 0, ""],
"major_version": "${MAJOR}",
"pg_version": "${PG_VERSION}",
"modules": ${MODULES_JSON}
}
EOF
echo " odoo=${MAJOR} pg=${PG_VERSION} modules=$(echo "$MODULES_JSON" | tr ',' '\n' | wc -l | tr -d ' ')"
echo "[4/4] zip -> ${OUT}"
( cd "$WORK" && zip -qr "$OUT" dump.sql manifest.json filestore 2>/dev/null || \
zip -qr "$OUT" dump.sql manifest.json )
OUT_BYTES=$(wc -c < "$OUT" | tr -d ' ')
echo
echo "OK: $OUT"
echo " size = $((OUT_BYTES / 1024 / 1024)) MB"
echo
echo "Restore on live VPS:"
echo " 1) Open https://<vps>/web/database/manager"
echo " 2) Click 'Restore Database', enter the master password,"
echo " pick this .zip, set the destination DB name (e.g. encoach_v2),"
echo " and submit."
echo
echo "Or via curl:"
echo " curl -F 'master_pwd=<MASTER>' -F 'name=encoach_v2' -F 'copy=true' \\"
echo " -F 'backup_file=@${OUT}' https://<vps>/web/database/restore"