Keep your backups safe off-site by pushing each finished archive to one or more destinations — SFTP, FTP/FTPS, Amazon S3 (and Wasabi, B2, MinIO), Google Drive, or a Local folder. All uploaders are pure PHP with no SDK dependencies, and retention prunes remote copies right alongside the local one.
Destinations (formerly “Remote Storage”)
Remote and local targets are now unified as Destinations. A profile can push each finished archive to one or more destinations, managed per profile in the profile's Destinations panel. Each destination is stored as one row (with its settings as JSON) in #__mokonyxbackup_remotes. A local destination type stores the archive in a folder on this server — it is now just another destination alongside the remote ones (see below).
| Backend | Features |
|---|---|
| SFTP | SSH-key, encrypted-key (passphrase), or password auth (paste or upload a key file), configurable port and remote path |
| FTP/FTPS | Passive mode, SSL, recursive dir creation, size verification |
| Google Drive | OAuth2 refresh tokens, placeholder-able subfolder path, resumable chunked upload, no SDK |
| Amazon S3 | AWS Signature V4, multipart upload, placeholder-able path prefix, custom endpoints |
| Local | A folder on this server — this IS the local copy of the archive (see below) |
SFTP, S3 and Google Drive appear in the Add/Edit modal's Type selector; FTP is a fully supported backend used by existing/imported destinations. All uploaders are pure PHP with cURL — no SDK dependencies.
SFTP Authentication
An SFTP destination supports three auth types: an unencrypted SSH key, an encrypted SSH key (with a passphrase), and a password. Password and encrypted-key auth are performed via the server's sshpass utility — the secret is passed to the SSH process through an environment variable, never on the command line. If sshpass isn't installed on the server, those two modes report a clear, actionable error; switch the destination to an unencrypted key or install sshpass.
Google Drive Subfolder Path
A Google Drive destination has an optional Subfolder Path field (for example [HOST]/[YEAR]). Drive addresses folders by opaque ID rather than by path, so each / segment of the resolved path is found or created by name under the configured Drive folder ID (or your Drive root), and the deepest folder parents the uploaded file. The value is placeholder-resolved before use, and retention deletes target the same resolved folder (a missing subfolder is treated as “nothing to delete”). Uploads stream in 5 MB chunks from a temp file (so peak memory doesn't scale with chunk size) and each chunk is retried with exponential backoff on a transient failure (transport error, 429, or 5xx). The field carries the same clickable Insert: placeholder legend as the local backup-directory field.
S3-Compatible Services
- AWS S3:
https://s3.amazonaws.com - Wasabi:
https://s3.wasabisys.com - Backblaze B2:
https://s3.us-west-001.backblazeb2.com - MinIO: your server URL
The S3 Path Prefix is run through the placeholder resolver ([HOST], [SITE_NAME], date tokens, and so on) for both upload and retention delete, so a value like [HOST]/backups produces a real object-key prefix rather than a folder literally named [HOST]. Multipart uploads use parts of at least 5 MB. The S3 path field shows the same clickable Insert: placeholder legend as the local backup-directory field.
Per-Destination Restore Script
Each destination chooses how — and whether — a restore script travels with the archive it receives, via a Restore script dropdown with three modes:
- None — the archive is delivered as-is, with no restore script.
- Inside the archive — the destination receives a copy of the archive with
restore.phpwrapped in. The already-compressed archive is stored (not re-compressed), so wrapping is fast. - Outside as a sidecar — a standalone
restore.phpis placed beside the archive at the destination, as a separate file.
Because the mode is chosen per destination, you can (for example) push a plain archive to cheap bulk storage while keeping a self-restoring copy on an SFTP box.
The Local Copy Is a Local Destination
The old Keep local copy profile option has been removed. Instead, a local destination IS the local copy. If the profile has an enabled local destination, the archive is kept on this server; if it has none, the local archive is deleted after the remote uploads finish (and, as a safeguard, whenever any upload fails). To keep a copy on the server, add a Local destination pointing at the folder you want the archive to live in. A per-destination Keep Local Copy toggle lets you keep the single working archive when any enabled destination requests it. Local-destination paths resolve [HOME]/[HOST] and the other placeholders (no more literal [HOME]/[HOST] folders), and a local destination that points at the archive's own folder is handled gracefully rather than erroring. Out of the box the default backup directory now sits above the web root, so it is never web-accessible.
Per-Destination Results
Each backup record shows a per-destination result for every destination the profile targeted — a Delivered or Failed status alongside the destination's type and path. If one remote fails while others succeed, you see exactly which one failed and where each copy landed, rather than a single all-or-nothing status for the whole backup.
Remote Retention Pruning
RetentionManager is the single retention authority and prunes remote copies as well as the local one. When a record is pruned by age or count it deletes the DB row, unlinks the local archive and its log, and deletes the archive from every currently enabled remote destination for that profile. Remote deletion is idempotent and best-effort — a failure is logged but never blocks local pruning. The shared standalone restore.php is intentionally never pruned from remotes.