orbotodocs
Admin guideOperations

Backups

Scheduled backup jobs, external S3 destinations, content scopes, and exactly how full and project restores work.

Backup jobs and runs

What a backup contains

A full backup is a single archive: a manifest, every database table as line-delimited JSON, and a copy of every stored file (attachments, avatars). Derived data - search vectors, AI embeddings, cached translations - is deliberately excluded and regenerated after a restore instead of shipped in the archive, which keeps archives smaller and portable even across different AI providers (a restore doesn't assume the target has the same embedding model as the source).

Creating a scheduled backup job

The new backup job form

Go to Admin -> Backup -> New job. Fill in:

  • Name - your own label, shown in the job list and on every run it produces.
  • Scope - Full (the whole workspace) or Project (pick one project from the dropdown that appears).
  • Schedule - a cron expression, with four quick presets (every day at 03:00, every Sunday at 02:00, first of the month at 04:00, every hour) you can click instead of typing cron syntax by hand. Leave it blank if you only want to trigger this job manually.
  • Timezone override - optional; leave blank to run on the workspace's own timezone (Admin -> System settings), or pick a different IANA zone for just this job.
  • Retention (days) - how long completed runs from this job are kept before automatic cleanup.
  • Destination - Internal storage (default) or External S3 bucket (see below).
  • Contents - what the job actually captures (see the table below).

Save, and the job appears in the list with a green dot (active). Click Run now on any job at any time - before a risky upgrade, before a bulk import - without waiting for its schedule.

Destination: external S3 bucket

Any S3-compatible service works: AWS S3, Cloudflare R2, Backblaze B2, MinIO, Hetzner Object Storage. Selecting External S3 bucket reveals: endpoint (leave empty for AWS), region, bucket name, an optional path prefix, access key, and secret. Click Test connection before saving - it verifies the credentials actually work against that exact bucket, catching a typo'd region or a permissions gap before your first scheduled run fails at 3am. The secret is encrypted at rest and never returned by the API; the edit form always shows it masked, and leaving it blank on save keeps whatever is already stored - only typing a new value replaces it.

Content scope

ScopeWhat it producesBest for
Database + filesThe classic combined ZIP archive - every table as NDJSON plus every storage object together. Restorable as-is through the setup wizard or the Admin import button.Your primary, restorable backup
Database onlyThe same ZIP, without storage objects - small and fast.Frequent schedules (hourly/daily), paired with a Files-only job
Files only (S3 mirror)No archive at all - external destinations only. Every owned storage object (attachments, avatars) is mirrored to <prefix>/storage/<key> in your bucket, incrementally by key + size. Nothing is ever deleted remotely, even if the object is later removed locally.Cheap, frequent offsite copies of large attachment histories

A common offsite pattern is two jobs pointed at the same bucket: a daily "Database only" job plus a daily "Files only" mirror job. The mirror only transfers what's new or changed since last time, so daily runs stay cheap even once the attachment history is large.

Managed jobs

On a hosted (Coolify-managed / cloud) instance, jobs the control plane created for your plan show a Managed badge in the job list. You can still Run now on a managed job, but pause, edit, and delete are hidden for it - those stay under the platform's control.

Manual full export

The Full backup now button (top of the Backup page) downloads a complete workspace archive immediately, completely outside any schedule. Use it right before a version upgrade or any change you'd want a rollback point for.

Compliance exports

Admins holding the DSGVO-export permission additionally see two buttons here: a DSGVO Art. 15 export (a person's own personal-data export, for a data-subject request) and a BSI-C5 compliance PDF. These are distinct from the audit-trail evidence exports - see Audit and compliance for those.

Run history

Every run - scheduled or manual - lands in Recent runs, with its status (success / failed / running, with a spinner while in flight), size, and start time. A run triggered by a job shows that job's name; a manual full export shows as Manual. Each completed run offers Download (grabs the archive) and Delete (removes just that run's stored archive and history row - a simple confirm, since the run itself carries no live data, only its own history entry).

Restoring

There are two genuinely different restore paths, and picking the right one matters:

Full restore (whole workspace)

The reliable, always-works path is the first-run setup wizard: on a brand-new instance, the wizard's first screen offers Fresh setup, Restore from a backup, or Import from a remote instance. Pick Restore from a backup, upload the archive, and enter the setup token (a one-time value printed in the server's boot log, or set via the SETUP_TOKEN environment variable - required so an unauthenticated first-run screen can't be used to overwrite a running instance by anyone who finds the URL). Click Start restore; you'll see a live progress view (table-by-table row counts, then storage objects), and a completion screen with the total rows and tables restored. Sign in afterward with the credentials from the backup - not a new account.

You can also trigger a full restore directly from Admin -> Backup -> Import on an already-running instance: upload the archive, and orboto inspects it first (read-only) showing its kind, export date, orboto version, total rows, and a per-table breakdown, before asking you to type WIPE-AND-RESTORE to confirm. Be aware this path is guarded by a fresh-instance safety check on the server side - it's built for restoring onto an effectively-empty instance, and attempting it from an already-populated, logged-in admin session can be refused by that guard. If you hit that, use the setup-wizard path above instead, against a genuinely fresh instance.

After any full restore, AI embeddings are automatically re-queued and rebuild in the background - AI-dependent search features stay empty until that finishes (or until you configure an AI provider, if none was set on the source workspace).

Project restore (one project)

Use Admin -> Backup -> Import with a project-scope archive (one created by a "Project" backup job, not a full one) - this path works on any running instance, with no fresh-instance requirement. After inspecting the archive, you pick:

  • Import as a new project - creates a brand-new project from the archive; the default and safest choice.
  • Overwrite an existing project - pick a target project from a searchable list, then type OVERWRITE to confirm. This wipes that project's current rows and replaces them with the archive's content while preserving the project's existing UUID (so anything referencing that project by ID, like a webhook subscription, keeps working afterward).

Restoring from an S3-mirrored destination

An archive sitting in your own S3 bucket restores exactly like a locally downloaded one - download it and feed it into whichever restore path above matches its scope. A "Database only" archive plus its paired "Files only" mirror restore together: import the database archive first through one of the paths above, then copy the mirrored objects from <prefix>/storage/ in your bucket into the instance's storage under those exact same keys - the keys under that prefix ARE the original storage keys, by design, so this is a straight copy, not a remap.

Cloud workspaces are additionally backed up by the platform automatically, independent of anything configured here; the admin backup area still lets you export your own archives at any time for your own copy.

Troubleshooting

  • "WIPE-AND-RESTORE" full-restore fails on Admin -> Backup's Import button - expected on an already-populated instance; the fresh-instance guard is load-bearing safety, not a bug to work around. Use the first-run setup wizard against a genuinely fresh instance instead.
  • S3 destination "Test connection" fails - check the endpoint has no trailing slash, the region matches the bucket's actual region (some providers reject a mismatched region even when the endpoint itself is correct), and the access key has both write and list permissions on that specific bucket.
  • A mirror run reports failed objects - the whole run is marked failed (and alerts like any failed backup job) if even one object couldn't be transferred; check the bucket's own access logs or storage quota before simply re-running it.
  • Retention isn't shrinking your bucket's usage - retentionDays only governs the instance's own internal storage cleanup. Objects living in your own external bucket are yours to manage - set a lifecycle rule on the bucket itself if you want them expired.
  • Search / AI features stay empty right after a restore - expected immediately after any restore; embeddings regenerate in the background. If it's been a while with no visible progress, check Admin -> AI settings for the re-embed status, or confirm an AI provider is actually configured on the restored instance.
  • Setup-wizard restore rejects the setup token - it must match either the value printed in the server's boot log at startup or the SETUP_TOKEN environment variable if one was set; a stale value copied from an earlier boot won't work after a restart regenerated it.

On this page