Backup & Restore
Kuploy can back up and restore the whole instance — its own database and configuration, which hold every organization on this deployment. This is an operator-level disaster-recovery tool, separate from any per-app database backups your developers configure.
Everything here lives under Settings → Maintenance and is available to instance admins only.
This is an operator tool, so on Kuploy Cloud it lives under Platform Admin → Maintenance and is restricted to platform admins — the people who run the deployment. Regular organization owners and admins (tenants) can't reach it: it acts on the shared platform database that holds every organization, never a single tenant's data. Everything below applies identically; only the location (Platform Admin → Maintenance instead of Settings → Maintenance) differs.
An instance backup captures everything — all organizations, users, projects and settings. Restoring one rolls the whole instance back to that point in time, not a single organization. Treat it accordingly.
Prerequisites
- You must be signed in as an instance admin (the first user created on a fresh instance is an admin).
- At least one S3 destination (a bucket kuploy can upload backups to). If you don't have one yet, follow Configure an AWS S3 bucket below.
Configure an AWS S3 bucket
You only need to do this once. These steps use Amazon S3; any S3-compatible provider (Cloudflare R2, Wasabi, MinIO, DigitalOcean Spaces, …) works the same way — only the Endpoint differs.
1. Create the bucket
- In the top-right Region selector of the AWS console, pick the region the
bucket should live in, e.g. US East (Ohio)
us-east-2. Note the region code — you'll need it below. (The Create bucket form shows this region under General configuration; it isn't a separate field there.) - Open S3 → Buckets → Create bucket.
- Bucket type — leave General purpose.
- Bucket namespace — leave Global namespace (the default).
- Bucket name — a globally-unique name, e.g.
my-kuploy-backups. - Object Ownership — leave ACLs disabled (recommended).
- Block Public Access — keep Block all public access ticked; backups must stay private.
- Bucket Versioning — optionally set to Enable so an overwritten or deleted backup object can still be recovered.
- Leave the remaining defaults (encryption, tags) and click Create bucket.
2. Create a scoped IAM policy
Give kuploy access to only this bucket. In IAM → Policies → Create policy,
switch to the JSON editor and paste (replace my-kuploy-backups with your bucket
name):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "KuployBackupsBucket",
"Effect": "Allow",
"Action": ["s3:ListBucket", "s3:GetBucketLocation"],
"Resource": "arn:aws:s3:::my-kuploy-backups"
},
{
"Sid": "KuployBackupsObjects",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::my-kuploy-backups/*"
}
]
}
Name it e.g. kuploy-backups and create it.
3. Create the IAM user
- In IAM → Users → Create user, name it e.g.
kuploy-backups, and leave Provide user access to the AWS Management Console unchecked. - On Set permissions, choose Attach policies directly, search for
kuploy-backups, tick it, and finish creating the user.
Creating the user does not generate an access key — that's a separate step below.
4. Create an access key
- Open the user (IAM → Users →
kuploy-backups) → Security credentials tab → Create access key. - For Use case, choose Application running outside AWS → Next.
- Skip the optional description tag → Create access key.
- On Retrieve access keys, copy the Access key ID and Secret access key now — the secret is shown only once (or Download .csv).
5. Add the destination in kuploy
Go to Settings → S3 Destinations → Add Destination and fill in:
| Field | Value |
|---|---|
| Name | A label you choose, e.g. AWS backups |
| Provider | Amazon Web Services (AWS) S3 |
| Access Key Id | The Access key ID from step 4 |
| Secret Access Key | The Secret access key from step 4 |
| Bucket | Your bucket name, e.g. my-kuploy-backups |
| Region | Your bucket's region, e.g. us-east-2 |
| Endpoint | https://s3.<region>.amazonaws.com, e.g. https://s3.us-east-2.amazonaws.com |
Open the bucket in S3 → Buckets → my-kuploy-backups → Properties → Bucket
overview: it shows the AWS Region (e.g. us-east-2) and the bucket ARN
(arn:aws:s3:::my-kuploy-backups). The Bucket field above is just the name,
and the Endpoint is https://s3. + that region + .amazonaws.com.
Click Test connection to confirm the credentials, then Create.
Back up the instance
- Go to Settings → Maintenance → Backups → Create Backup.
- Pick your Destination, a Schedule (cron) and an optional Prefix (a folder inside the bucket).
- Keep the latest — optionally cap how many backups are retained; older ones are pruned automatically. Leave it empty to keep every backup (no pruning — the default).
- Save. Use the Run (▶) action on a backup to take one immediately, or let the schedule run it. The checklist icon on a backup lists its recent runs (status + logs).
Each backup is a single archive in your bucket containing the instance database and its configuration files.
Restore
Restore is reached from Settings → Maintenance → Backups → Restore Backup. Pick the destination and the backup file, then choose where to restore to.
Restore to a new database (recommended)
Restores the backup's database into a separate, empty database you provide — the running instance's database and filesystem are never touched. Use it to validate a backup, stand up a clone, or migrate to fresh infrastructure. It's safe and ungated because nothing on the live instance changes.
-
Prepare an empty target database on your Postgres server. It must already exist (the restore populates it) and should be empty:
CREATE DATABASE kuploy_restore; -
In Restore Backup, choose your Destination and the backup file (
instance-backup-<timestamp>.zip). -
Under Restore to, select New / external database.
-
In Target database URL, enter the connection string of that empty database, e.g.
postgresql://user:password@host:5432/kuploy_restore. -
Click Restore and watch the log until "Restore completed successfully!" (you'll also get a success toast).
-
Verify the copy by connecting to the target and checking your data landed:
SELECT name FROM organization;
SELECT name FROM project; -
To actually run on the restored copy, point a fresh kuploy instance at that database (its
DATABASE_URL). On first boot it re-applies any newer migrations (see the note below).
The restore log may end with pg_restore reported ignored, non-fatal errors.
That's normal when the backup was taken with a newer Postgres than the target
(e.g. a SET transaction_timeout the older server doesn't recognise) — the
restore still completes. Use matching Postgres major versions if you want a
clean log.
In-place restore (destructive)
Overwrites the running instance's own database and configuration, rolling every organization back to the backup. Use only for genuine disaster recovery.
Because it's irreversible, kuploy requires you to type the instance name to confirm, and it automatically takes a fresh pre-restore backup first so you can recover the current state if needed.
Restoring a whole-database backup also resets the instance's schema to that backup's version. On the next start, kuploy re-applies its forward migrations to catch the schema back up. Let migrations finish converging before trusting the instance, and consider running Clean Redis afterward to drop cache and sessions that reference the pre-restore state.
Restore history
Every restore is recorded and listed under Settings → Maintenance → Restore history, newest first — its status (running / done / error), whether it was in-place or restore-to-new, the backup file and destination, when it ran, and any error. Use it as an audit trail of what was restored and whether it succeeded.
Other maintenance actions
- Reload Server — restarts the web server process. The panel is briefly unavailable while it comes back up.
- Clean Redis — flushes the instance's Redis, clearing cached state and sessions for every organization on it. Requires a typed confirmation. Users stay signed up but will need to sign in again.