ReviewOS

stacks/ts-cloud

On-demand/dashboard DB backups accumulate forever (no retention in DB_BACKUP_DIR)

#199
Closed glennmichael123 opened this 4 days ago ·
4 days ago

Summary

backupDatabase() / buildBackupScript() write a timestamped gzipped dump to /var/backups/ts-cloud/databases/<name>-<stamp>.sql.gz on every call, but nothing ever prunes that directory. buildListBackupsScript() only lists it. So each dashboard "Backup" action (POST /api/databases/backup) or ts-cloud db:backup call leaves a full dump on the box indefinitely, with no cap and no off-box copy.

Verified against @stacksjs/ts-cloud@0.16.15; same code in the current feat/host-cleanup-timer source.

Where

packages/ts-cloud/src/deploy/dashboard-database.ts:

  • DB_BACKUP_DIR = '/var/backups/ts-cloud/databases'
  • buildBackupScript() dumps ${name}-$STAMP.sql.gz and never trims the dir
  • buildListBackupsScript() is ls -1t ${dir}/*.sql.gz | head -50 | sed … (list only, no delete)
  • backupDatabase() calls the above and is wired to the dashboard handler

Impact

For a large database this slowly fills the disk. The scheduled path (drivers/shared/backups.ts) correctly applies retention: { count, maxAge } via ts-backups; this on-demand path has no retention at all, so it is an unbounded local-accumulation vector. (Context: we recently had to hand-clean a shared box where a full database's dumps had grown to ~100G; a dashboard backup button with no cap has the same shape, just manually triggered.)

Suggested fix

After a successful dump, keep the newest N per database and/or delete older than M days, mirroring ComputeBackupConfig.retentionCount / retentionDays that the scheduled path already honours. Or route on-demand dumps through ts-backups so dump + retention + off-box upload are consistent across both paths.

Sign in to comment on this issue.