Backup and Recovery
PlantPulse Studio handles complete state through one backup script and one recovery script.
All commands run from the installation directory (/opt/kopens/plantpulse-studio-docker).
What gets backed up
A single backup file (dist/backup-<date>.tar.gz) contains all of the following.
| Target | Contents |
|---|---|
| Full PostgreSQL dump | User accounts · conversation history · watchers · alarm read status · skills · deployment history · audit logs |
Workspace (workspaces/) | Actual source code per project · chat attachments |
Build artifacts (builds/) | Each version of deployed apps (needed for rollback) |
State directory (state/) | settings.json (configuration) · audit and usage logs · custom templates · branding logos |
PostgreSQL's data directory itself is excluded from the archive — it is replaced by an SQL dump.
The archive contains entire workspaces for all users, and if migrated from a previous
installation, settings.json may contain leftover API keys.
- The script creates the backup file with
600(owner read-only) and thedist/directory with700. - Preserve these permissions when moving to external media or other servers.
(Use permission-preserving options like
scp -p,rsync -a,tar -p) - If exporting outside the organization, separate encryption is recommended.
Run backup
cd /opt/kopens/plantpulse-studio-docker
bash bin/backup.sh
▶ PostgreSQL 덤프
▶ 파일 상태 아카이브(postgres 데이터 제외 — 덤프로 대체)
-rw------- 1 root root 78M ... dist/backup-20260728-031501.tar.gz
✅ 백업 완료 (보존 14개)
- Output:
dist/backup-<YYYYMMDD-HHMMSS>.tar.gz - Retention policy: Only the latest 14 backups are kept; older files are deleted automatically (adjust with
BACKUP_KEEP). - If using bundled PostgreSQL, the stack must be running to dump the database.
BACKUP_KEEP=30 bash bin/backup.sh # 이번 실행부터 30개 보존
Run bash bin/backup.sh once before image upgrades or major configuration changes.
Set up automatic backup (recommended)
Install a cron job to run backup daily at 03:30. Requires root privileges.
sudo bash bin/install-backup-cron.sh
[backup-cron] 설치 완료 — 스케줄: '30 3 * * *', 보존 14개, 로그: dist/backup.log
To change the time or retention count,
sudo BACKUP_CRON="0 4 * * *" BACKUP_KEEP=30 bash bin/install-backup-cron.sh
To remove it,
sudo bash bin/install-backup-cron.sh remove
Check operation status in the logs.
tail -50 /opt/kopens/plantpulse-studio-docker/dist/backup.log
ls -lh /opt/kopens/plantpulse-studio-docker/dist/backup-*.tar.gz
Recommended maintenance schedule
| Interval | Task |
|---|---|
| Daily | Automatic backup (cron) — keep 14 days |
| Weekly | Copy the latest backup to another server or media (preserve permissions) |
| Monthly | Check dist/ size and available disk space |
| Quarterly | DRYRUN=1 recovery drill — see below |
| Before upgrade | One manual backup |
Even if backup files accumulate daily, you cannot know if they actually recover until you try. Run a quarterly drill. It is non-destructive, so it is safe to run during operations.
Recovery drill (non-destructive)
Checks archive structure and database reachability only; changes nothing.
DRYRUN=1 bash bin/restore.sh # 최신 백업 대상
DRYRUN=1 bash bin/restore.sh dist/backup-20260712-191858.tar.gz
▶ 아카이브 검증
ppstudio.sql 12M · files.tar.gz 66M
▶ DRYRUN — DB 도달성만 확인
✅ DB 도달 OK
✅ DRYRUN 통과 — 실제 복구는 DRYRUN 없이 실행
Run recovery
It overwrites the current database contents and entire data directory to the backup point in time. Projects, conversations, and deployments created after recovery will be lost.
cd /opt/kopens/plantpulse-studio-docker
bash bin/restore.sh # 최신 백업으로 복구
bash bin/restore.sh dist/backup-20260712-191858.tar.gz # 특정 시점으로 복구
You must enter restore at the confirmation prompt to proceed.
⚠ 현재 DB 와 /var/lib/pp-studio 파일 상태를 이 백업으로 덮어씁니다: dist/backup-...
계속하려면 'restore' 를 입력하세요:
The script performs the following steps:
- Validate archive structure (confirm dump and file archive exist)
- Automatically backup current file state to
dist/pre-restore-<date>.tar.gz - Stop the stack
- Restore data directory → restore database
- Start the stack → health check
To run without a prompt inside an automation script,
FORCE=1 bash bin/restore.sh dist/backup-20260712-191858.tar.gz
Health check fails after recovery
bash bin/logs.sh # 서버 로그 확인
bash bin/status.sh
To revert, recover again from the backup created in step 2. Note that the backup contains file state only (database is not included).
bash bin/restore.sh dist/pre-restore-20260728-104233.tar.gz
Migrate to another server
- Install the stack on the new server with the same version (installation or air-gapped installation).
- Copy
.envfrom the existing server to the new server (preserve permissions600). - Copy the backup archive to
dist/on the new server (preserve permissions600). - Run recovery.
cd /opt/kopens/plantpulse-studio-docker
DRYRUN=1 bash bin/restore.sh dist/backup-20260728-031501.tar.gz # 먼저 리허설
bash bin/restore.sh dist/backup-20260728-031501.tar.gz
If the access address changes after migration, all users must log out and log back in once — login cookies are host-specific at issue time, so leaving them unchanged causes 401 errors on data requests. See Domain and reverse proxy for details.
Disk management
Backups include entire workspaces and build artifacts, so they grow as projects increase.
du -sh /opt/kopens/plantpulse-studio-docker/dist
du -sh /var/lib/pp-studio/*
df -h /var/lib/pp-studio
- To reduce the retention count, reinstall cron with
BACKUP_KEEPvalue. - Older versions of deployed apps are kept to a maximum of 10 per project by default, with excess cleaned up automatically (the currently deployed version is always retained).
Related documentation
- Installation · Air-gapped installation
- Secret management — principles for keeping keys out of backups
- Troubleshooting