# Account Backups

> Back up a whole hosting account — files, databases, domains, mailboxes — on demand or on a schedule, and restore it onto this server or another one.

Source: https://www.corepanel.net/docs/backups/
Last updated: 2026-09-03
Part of the CorePanel documentation — https://www.corepanel.net/docs

---

A CorePanel backup captures a **whole account**: its home directory, its databases, its
domains and subdomains, its FTP accounts, its mailboxes and its mail routing, plus
the account's own
identity and limits. The result is a single `.tar` archive that can rebuild the account
from scratch.

It is, deliberately, the inverse of the [cPanel importer](https://www.corepanel.net/docs/cpanel-import): the same
idea of a self-describing archive, in the other direction.

## What is inside an archive

| Resource | Captured |
|---|---|
| **Home directory** | Every file the account owns, with ownership and permissions |
| **MySQL** | Each database, dumped, plus its users and their grants |
| **Domains** | Primary, aliases and addon domains, with their document roots, serving modes, canonical host and [web optimizations](https://www.corepanel.net/docs/docs/web/optimizations/) |
| **Subdomains** | With their document roots, serving modes and their own web optimizations |
| **Mailboxes** | Accounts and their mail |
| **Mail routing** | Every [forwarder](https://www.corepanel.net/docs/email/mailboxes#forwarders), the domain catch-all and the whole-domain redirect |
| **FTP accounts** | |
| **[Applications](https://www.corepanel.net/docs/applications/)** | Each application's settings, its environment variables, its data volume and the release it was running |
| **The account itself** | uid/gid, home path, PHP version, package reference and every limit |

A `manifest.json` at the root of the archive indexes all of it, so an archive can be
inspected — and a restore planned — without unpacking it first.

> **What a restore will not put back**
>
> **Paid optimizations are not applied on an edition that does not include them.** Restoring
> an account that used minification or the page cache onto a Personal server brings back
> everything else and reports what it left out — the free optimizations still come back
> exactly as they were. The same happens to the page cache of an alias domain, which cannot
> be cached at all. (See also [Passwords after a restore](#passwords-after-a-restore).)
## Taking a backup

**Backups → Create backup**, pick the account, and the job starts in the background. The
job list shows progress and, when it finishes, a per-resource report of what was captured
and what was not.

From the CLI:

```bash
corepanel account backup <username>
```

Archives are written to `/var/lib/corepanel/backups` on the server.

> **The job is asynchronous**
>
> Starting a backup returns immediately with a job you can poll. A large account takes a
> while — the home directory tarball and the database dumps are the slow parts — and the
> job survives you closing the panel.
## Backups your customers take

On **Business**, a hosting account can take a backup of itself from the
[client panel](https://www.corepanel.net/docs/client-panel#backups-are-readable-always-writable-only-if-you-say-so).
It is **off until you turn it on**, in Server → Settings → *Client panel*, because the
archive lands on the panel's disk rather than inside the account's quota.

What it does to this page: those jobs appear in the list like any other, marked as the
customer's own. They follow rules of their own, and the reason for each is the same one —
the disk they fill is yours, not theirs:

| | Yours (manual) | Yours (scheduled) | The customer's |
|---|---|---|---|
| Kept until | You delete it | Your retention policy | The customer's next backup but two |
| How often | Whenever you like | Your schedule | Once an hour at most, one at a time |
| Remote destination | Yes | Yes | No — always local |

The rotation is the part worth knowing before you switch it on: a customer's **two most
recent** archives survive, and a third pushes the oldest out. It bounds what your disk can
be asked to hold to roughly twice the size of the accounts whose owners use the button —
and it never touches an archive of yours, whichever way you took it.

Downloading is not governed by that switch. A customer can always download any finished
backup of their own account, including the ones your schedule produced: the archive is a
copy of their own data.

## Scheduled backups

The **Schedules** tab defines recurring backups.

| Field | Notes |
|---|---|
| **Name** | How the schedule appears in the list |
| **Scope** | A single **account**, or **all** accounts on the server |
| **Frequency** | `daily` (02:00), `weekly` (Sundays 02:00), `monthly` (1st, 02:00), or a custom five-field cron expression |
| **Retention — keep** | Maximum number of archives to keep. `0` = no limit |
| **Retention — days** | Delete archives older than N days. `0` = no limit |
| **Enabled** | A disabled schedule stays defined but does not fire |

A server-wide schedule runs a bounded number of accounts at a time rather than starting
one job per account at once — a full backup is a heavy `mysqldump` plus a large tarball,
and firing hundreds in parallel would take the server down.

**Run now** executes a schedule immediately, which is the right way to verify one before
trusting it.

## Remote destinations

By default an archive stays on the same disk as the server it protects — which is exactly
the failure a backup exists to survive. A **destination** is where CorePanel copies the
finished archive: S3-compatible object storage, or any SSH server over SFTP.

The **Destinations** tab of the Backups view manages them.

| Driver | Works with |
|---|---|
| **S3-compatible** | AWS S3, MinIO, Cloudflare R2, Backblaze B2, Wasabi, and Google Cloud Storage through its S3 endpoint |
| **SFTP** | Any SSH server with a directory you can write to |

Adding one asks for the settings the driver needs — bucket and endpoint, or host and
remote path — plus its credentials. Two fields are worth understanding:

- **Path-style addressing** (S3) puts the bucket in the URL path instead of the hostname.
  MinIO and most self-hosted gateways need it; AWS does not. Getting it wrong is the usual
  cause of a destination that connects but cannot find the bucket.
- **Host key** (SFTP) pins the server's identity. Left empty, CorePanel adopts the key it
  sees on the first successful connection and verifies every later one against it.

### Editing a destination

**Edit** changes a destination's settings in place — a corrected bucket, a new prefix, or
rotated credentials. Leave the credential fields empty and the stored ones are kept, so
fixing a typo in the endpoint never costs you the keys. The driver itself cannot change:
S3 and SFTP are different destinations, not two settings of one.

Editing rather than replacing matters more than it looks. Backup jobs remember which
destination they were pushed to by **id**, so deleting a destination and creating an
identical one leaves every archive already stored there orphaned: retention can no longer
find it, and those files stay in the bucket — billed — until someone removes them by hand.
Rotating S3 keys is an edit, not a re-creation.

### Always test a destination

**Test connection** uploads a small probe object, lists it and deletes it again. That is
deliberately more than a login check: a destination can accept a connection and still
reject writes, and you do not want to discover that on the night you need the backup. The
result is stored, so the list shows the last known state of every destination.

Once a destination exists, **Create backup** and every schedule can point at it. A
schedule's retention then prunes the remote copies too, not just the local ones.

> **The local copy is kept**
>
> Pushing to a destination does not remove the archive from the server. If the destination
> is unreachable the job comes back **partial**, with the reason in its report, and the
> local archive is still there — a failed upload never costs you the backup.
Remote destinations require **CorePanel Pro or Business**. Listing, disabling and deleting
a destination — and restoring an archive back from one — work on every edition, so a
lapsed licence never leaves you unable to reach your own backups.

## Restoring

**Restore** takes an archive and rebuilds the account: system user (with its original
uid/gid and home path), files, databases and users, domains, subdomains, mailboxes,
mail routing and FTP accounts.

Two options shape the run:

| Option | Effect |
|---|---|
| **Dry run** | Reports everything the restore would do, and every conflict it would hit, without writing anything |
| **On conflict** | `abort` (default) stops at the first collision; `skip` restores everything that does not collide and reports the rest |

Always dry-run a restore onto a server that already hosts things. A domain name is unique
across the whole server, so an existing domain is the most common collision.

### WordPress after a restore

A restore ends by scanning the rebuilt account for WordPress installations, so its sites
are back in [WordPress](https://www.corepanel.net/docs/wordpress) — not just back on disk — when the job finishes.
The archive carries the sites' files and databases but no catalog of its own, which is why
the scan runs rather than being restored from the archive.

The report's **wordpress** line says how many installations were cataloged. If it reads
*skipped*, the scan could not run: the sites themselves are unaffected and
`corepanel wp scan <account>` lists them.

### Mail routing after a restore

Forwarders, the catch-all and the whole-domain redirect are recreated **after** the
mailboxes, in the order they were originally created. Both halves of that matter: a
forwarder that [keeps a copy in its own mailbox](https://www.corepanel.net/docs/email/mailboxes#keeping-a-copy-in-the-mailbox)
needs that mailbox to be back first, and a forwarder is checked against the ones already
present, so replaying the sequence that built the routing is what rebuilds it.

A route that cannot be recreated is **reported and skipped**, never fatal — the restore
has already brought back the account by then. There are two realistic reasons: its domain
did not restore (the domain step says why), or a forwarder that delivers into its own
mailbox found that mailbox suspended, which is the one state the panel does not let you
create either.

Archives taken before CorePanel captured mail routing carry none, and restore without it.

### Passwords after a restore

The account's password — for the panel and for FTP — is **preserved** when the archive
carries a recoverable hash, so the customer's credentials keep working. When it does not,
the account is restored with a random password and the report says a reset is required.

A mailbox or FTP login that was **closed** when the backup ran comes back closed. Its
password is restored with it, so reopening the login later gives the owner back the one
they already had — but the restore never reopens it for you, because a login somebody
disabled is not something to hand back by surprise on the day of an incident. Backups
taken before CorePanel recorded this restore every login active, as they always did.

MySQL users are recreated with their original credentials where the hash can be
recovered. A user whose password cannot be recovered is **skipped and reported** rather
than recreated with a random password — recreating it would silently break the
application that connects with it.

### Partial restores

A failure in one resource does not abort the whole run: it downgrades the job to
**partial** and is recorded in the report. You get an account that mostly came back plus
an explicit list of what did not, instead of an all-or-nothing failure.

## Restoring a deleted account

Backup archives are **not** deleted when an account is deleted. That is the point of a
backup: it must outlive what it describes. Restoring a deleted account is the ordinary
restore flow, with no collisions to worry about.

## Moving an account to another server

The archive is self-contained, so rebuilding an account elsewhere is just a restore on the
other machine. The account's uid/gid, home path and limits come from the archive, and its
hosting package is re-mapped by name if the ID differs on the target.

If both servers share a destination, nothing has to be copied by hand: add the same
destination on the new server, list what is stored there, and restore the archive you
want.

```bash
corepanel backup-destination add offsite --type s3 --endpoint ... --bucket ...
corepanel backup-destination archives offsite
corepanel account restore --dest offsite --remote-key cpbackup-pxdemo-20260802T031500Z-j42.tar --wait
```

Otherwise, copy the `.tar` across and restore it as a local file.

The DNS zone is **regenerated by the new server**, so its records point at the new machine
rather than the old one. What is not automatic is the delegation: the domain keeps
resolving to the old server until its nameservers or records are changed.

A few things do not travel in the archive today, and are worth planning for: custom DNS
records beyond the managed zone, mail forwarders, TLS certificates (Let's Encrypt reissues
them once DNS points at the new server) and application data under
`/var/opt/userapps`.

## Where archives live

Backups are written to `/var/lib/corepanel/backups` on the server itself, unencrypted, and
copied to a [destination](#remote-destinations) when one is configured. Two consequences
worth planning around:

- **Get a copy off the server.** A backup on the same disk as the account does not survive
  the failure it is there to protect against. A destination is the built-in answer; a
  `rsync` or `rclone` [cron job](https://www.corepanel.net/docs/accounts/cron-jobs) is the manual one.
- **Treat archives as sensitive, wherever they land.** An archive contains the account's
  files, its databases, its mail and the password hashes of its mailboxes and database
  users. On a destination that means a private bucket and credentials scoped to it — a
  bucket that is readable by the world publishes all of that.

## Backups vs restore points

| | Account backup | [WordPress restore point](https://www.corepanel.net/docs/wordpress/managing#restore-points) |
|---|---|---|
| Scope | The whole account | One WordPress instance |
| Contents | Files, databases, domains, mail, FTP | That instance's document root and database |
| History | Governed by retention | Three per instance |
| Survives account deletion | Yes | No |
| Purpose | Disaster recovery, migration | An undo button for an update |

Use restore points around risky updates. Use backups for everything else.
