Update ISO installer tiers and backend deployment
This commit is contained in:
1 parent
79784a6743
commit
56668f7bdc
38 files changed
+7206
-175
No files matched your search
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
# Nexus One AI backup/restore helper.
|
||||
#
|
||||
# Usage:
|
||||
# sudo bash scripts/cezen-backup.sh backup
|
||||
# sudo bash scripts/cezen-backup.sh list
|
||||
# sudo bash scripts/cezen-backup.sh restore /opt/cezen/backups/cezen-backup-YYYYmmdd-HHMMSS.zip
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ACTION="${1:-backup}"
|
||||
TARGET="${2:-}"
|
||||
DATA_DIR="${CEZEN_DATA:-/opt/cezen/data}"
|
||||
BACKUP_DIR="${CEZEN_BACKUP_DIR:-/opt/cezen/backups}"
|
||||
|
||||
python3 - "$ACTION" "$TARGET" "$DATA_DIR" "$BACKUP_DIR" <<'PY'
|
||||
import json
|
||||
import shutil
|
||||
import sys
|
||||
import zipfile
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
action, target, data_dir, backup_dir = sys.argv[1:5]
|
||||
data_dir = Path(data_dir)
|
||||
backup_dir = Path(backup_dir)
|
||||
backup_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def now_tag():
|
||||
return datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
|
||||
|
||||
def iso_now():
|
||||
return datetime.now(timezone.utc).isoformat()
|
||||
|
||||
def write_backup(dest):
|
||||
manifest = {
|
||||
"schema": "cezen.backup_manifest.v1",
|
||||
"created_at": iso_now(),
|
||||
"data_dir": str(data_dir),
|
||||
"source": "cezen-backup.sh",
|
||||
}
|
||||
with zipfile.ZipFile(dest, "w", compression=zipfile.ZIP_DEFLATED) as zf:
|
||||
zf.writestr("manifest.json", json.dumps(manifest, indent=2))
|
||||
if data_dir.exists():
|
||||
for path in data_dir.rglob("*"):
|
||||
if path.is_file():
|
||||
zf.write(path, path.relative_to(data_dir).as_posix())
|
||||
|
||||
def restore(src):
|
||||
src = Path(src)
|
||||
if not src.exists():
|
||||
raise SystemExit(f"Backup not found: {src}")
|
||||
safety = backup_dir / f"pre-restore-{now_tag()}.zip"
|
||||
write_backup(safety)
|
||||
root = data_dir.resolve()
|
||||
with zipfile.ZipFile(src, "r") as zf:
|
||||
for member in zf.infolist():
|
||||
if member.filename == "manifest.json" or member.is_dir():
|
||||
continue
|
||||
target_path = (data_dir / member.filename).resolve()
|
||||
if root not in target_path.parents and target_path != root:
|
||||
raise SystemExit(f"Unsafe archive path: {member.filename}")
|
||||
target_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with zf.open(member) as source, open(target_path, "wb") as out:
|
||||
shutil.copyfileobj(source, out)
|
||||
print(json.dumps({"ok": True, "restored": str(src), "pre_restore_snapshot": str(safety)}, indent=2))
|
||||
|
||||
if action == "backup":
|
||||
dest = backup_dir / f"cezen-backup-{now_tag()}.zip"
|
||||
write_backup(dest)
|
||||
print(json.dumps({"ok": True, "backup": str(dest)}, indent=2))
|
||||
elif action == "list":
|
||||
rows = []
|
||||
for path in sorted(backup_dir.glob("cezen-backup-*.zip"), key=lambda p: p.stat().st_mtime, reverse=True):
|
||||
rows.append({"name": path.name, "path": str(path), "size_bytes": path.stat().st_size})
|
||||
print(json.dumps({"backup_dir": str(backup_dir), "backups": rows}, indent=2))
|
||||
elif action == "restore":
|
||||
if not target:
|
||||
raise SystemExit("Usage: cezen-backup.sh restore /path/to/backup.zip")
|
||||
restore(target)
|
||||
else:
|
||||
raise SystemExit("Usage: cezen-backup.sh backup|list|restore [backup.zip]")
|
||||
PY
|
||||
Reference in new issue
Block a user