Backup and restore¶
A recoverable Okatana deployment consists of more than SQL. Preserve the database, private/public file stores, encryption key and environment, and the application version that understands the schema.
Backup inventory¶
| Component | Why it matters |
|---|---|
| SQL database | users, memberships, tickets, documents, history, sessions/cache/queues, integration metadata |
storage/app/private |
ticket and comment attachment contents |
storage/app/public |
avatars and inline editor images |
APP_KEY |
decryption of TOTP and webhook secrets; session/application encryption |
| environment/secrets | database/mail/OAuth configuration and operational policy |
| release identifier/image | code compatible with the migrated schema and queued jobs |
| optional built docs/assets | reproducible from source, but helpful for exact release artifact continuity |
Logs and framework cache are operationally useful but not the primary domain backup. Database session/cache/job tables have different retention needs from domain data; include them in full snapshots but decide whether to restore stale runtime state.
Consistency boundary¶
Database rows reference files. A backup taken while uploads/imports are active can capture one side without the other.
For the simplest consistent backup:
- Enter a maintenance/quiesced period or stop write traffic.
- Stop queue workers so they do not mutate delivery/job/notification state.
- Take a consistent database snapshot/dump.
- Snapshot both storage roots immediately in the same window.
- Capture configuration/key metadata and release version.
- Resume service.
At scale, use storage/database snapshot mechanisms with documented point-in-time coordination. Okatana does not implement a cross-database/filesystem snapshot transaction.
Database-specific approach¶
SQLite¶
Stop all writers or use SQLite’s supported online backup mechanism. Copying the database file while web/queue processes write can produce an inconsistent backup, especially when journal files are involved.
Record the absolute DB_DATABASE path and file permissions. In Docker the default file is /data/database.sqlite in okatana_data.
MySQL¶
Use a transactionally consistent mysqldump or managed snapshot suitable for InnoDB, including triggers. Verify that the dump contains both audit-protection triggers. Store database/server version and character-set information.
PostgreSQL¶
Use pg_dump/managed snapshot and preserve schema objects including the audit trigger function and triggers. For point-in-time recovery, retain the required WAL/base-backup chain under your PostgreSQL operations policy.
Storage backup¶
Preserve file bytes, relative paths, permissions where relevant, and a manifest/checksum. The database stores attachment disk/path and avatar/editor-image paths. Restoring into a different root is fine only when Laravel disk configuration maps those same logical relative paths.
Do not rely only on public/storage: it is normally a symlink. Back up storage/app/public itself.
Protect the backup¶
Backups contain personal data, rich content, attachment contents, audit IP/user-agent data, and integration metadata. Encrypt backups, restrict access, record retrieval, apply retention, and securely delete expired copies according to policy.
Store APP_KEY securely but ensure it can be restored during a disaster. A database/storage backup without the key cannot recover encrypted TOTP/webhook values.
Restore runbook¶
Perform restore into an isolated network first:
- Provision the same application release and compatible runtime/database version.
- Restore
APP_KEYand environment without exposing secrets in shell history/logs. - Restore the database, including triggers.
- Restore
storage/app/privateandstorage/app/publicto configured disks. - Set writable ownership for Laravel.
- Clear/rebuild configuration, route, and view caches.
- Decide whether to retain restored
jobs,failed_jobs, sessions, cache, and pending webhook deliveries. Replaying stale jobs can duplicate effects; make this an explicit recovery decision. - Run
php artisan migrate:status; apply only migrations appropriate to the restored release/target release. - Start web without queue and perform read-only validation.
- Start queue only after reviewing pending jobs/external effects.
Restore validation¶
-
/up, SPA assets, MkDocs, and Scalar load. - A known account can sign in and decrypt/use TOTP state.
- Organization/project counts and membership are correct.
- A known private attachment downloads and inline image renders.
- A document PDF with a local image renders.
- Audit triggers reject update/delete.
- Ticket deep links and revision history resolve.
- API credential behavior matches planned secret handling.
- Webhook secret can sign a controlled test event.
- Queue/mail behavior is enabled only after review.
- A fresh export completes.
Portable exports versus backups¶
okatana.export.v1 is valuable for logical transfer, selective recovery, and cross-installation migration. It regenerates identifiers, may invite missing users, sanitizes content, omits some oversized/missing assets, and creates imported-history metadata. It is therefore not a transparent full-system restore.
Use both when appropriate:
- database/storage snapshots for exact disaster recovery;
- organization/project exports for portability and human-auditable logical recovery;
- timeline exports for preserving/reporting event history.
Test recovery regularly¶
A backup is unproven until restored. Schedule restore drills, record recovery time/data point objectives, validate content and encrypted fields, and fix automation after every failure. Include both database and file loss scenarios.