Automated WordPress file + database backups for shared hosting with configurable compression, retention cleanup, error notifications, and optional PHP trigger execution; can be automated with a cronjob.
Developed for shared hosting, tested on all-inkl and IONOS.
Key characteristic This tool runs fully server-side and independently from WordPress internals. It does not require a WordPress plugin, theme integration, or admin access. It also works on shared hosting without SSH by using the PHP trigger.
- Clone the repository (or upload the project files) and open the project folder.
- Create
scripts/.env-wordpress-backupfromscripts/env-wordpress-backup.example.- Ensure file permissions allow writing the file during setup, then set it to 600 for secure read/write access by the owner only.
- Edit
scripts/.env-wordpress-backupand set at least:WP_FOLDERBACKUP_FOLDERCOMPRESSION_METHOD- email settings (
SMTP_*,EMAIL_FROM,EMAIL_TO) if notifications are required
- Run one test backup and check log output.
- With SSH: run
scripts/wordpress-backup.sh. - Without SSH: execute
trigger/wordpress-backup.phpvia URL. - In both cases, verify the result in
backup.log.
- With SSH: run
- Review Trigger Security before exposing the trigger via URL.
- Automate via cron (shell cron if SSH is available, otherwise URL cron via trigger).
This tool is not part of the WordPress installation. Deploy it in a separate directory on the server and point WP_FOLDER at your WordPress root.
/home/user/www (account home, example)
├── wordpress-website/ ← WP_FOLDER (WordPress installation)
│ ├── wp-config.php
│ ├── wp-content/
│ └── ...
├── wordpress-backup-shell-script/ ← this repository (separate location)
│ ├── scripts/
│ │ ├── wordpress-backup.sh
│ │ └── .env-wordpress-backup
│ └── trigger/
│ └── wordpress-backup.php
└── wordpress-backups/ ← BACKUP_FOLDER
Use a separate cron URL or subdomain for trigger/ (not the WordPress site URL).
Supported via COMPRESSION_METHOD:
none:files.tar+database.sqlgzip:files.tar.gz+database.sql.gzzip:files.zip+database.sql.zipbzip2:files.tar.bz2+database.sql.bz2
Notes:
- For
zipDB backups, the internal SQL filename keeps a timestamp. - Missing/invalid method or missing tool stops the script with an error.
Main variables in scripts/.env-wordpress-backup:
WP_FOLDER: absolute path to WordPress installBACKUP_FOLDER: absolute path where backups are storedMAX_BACKUPS: number of backup folders to keepCOMPRESSION_METHOD:none,gzip,zip,bzip2USE_NICE_FOR_TAR: applynicefor tar-based methodsUSE_NO_TABLESPACES: include--no-tablespacesfor shared-hosting compatibilityEXCLUDES: space-separated paths to exclude from file archiveSEND_EMAIL_ON_ERROR:1or0SMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASSEMAIL_FROM,EMAIL_TO,EMAIL_SUBJECT_DEFAULT
Security note:
.env-wordpress-backupcontains credentials. Keep permissions at600.
trigger/wordpress-backup.php is useful when SSH execution is not available.
Config options in the file:
$shellScriptPath: default../scripts/wordpress-backup.sh$executionMode:sync: waits for completion (works well on all-inkl)background: starts detached process (recommended on IONOS for large backups)
$debugMode:false(default): minimal HTTP outputtrue: verbose HTTP output for troubleshooting
By default, the trigger returns minimal HTTP messages only. Full diagnostics are written to BACKUP_FOLDER/backup.log.
Static .htaccess IP allowlists for shared-hosting cronjobs are unreliable because cronjob source IPs can change.
Current policy:
- keep trigger exposure minimal
- keep
$debugMode = falsein production (minimal HTTP responses only) - use
backup.logfor diagnostics, not the HTTP response body - monitor access via logs
- do not treat static IP allowlists as primary protection
TODO:
- implement a stable trigger authentication mechanism that does not rely on fixed source IPs
- document the final approach in this README
- No DB backup generated
- Check DB values parsed from
wp-config.php - Check
backup.log+mysqldumperror output
- Check DB values parsed from
- Compression errors
- Validate
COMPRESSION_METHOD - Ensure required tools are available (
tar,gzip,zip,bzip2)
- Validate
- Mail not sent
- Verify
SMTP_*values - Confirm
curlorsendmailavailability
- Verify
- Permission errors
- Ensure read/write access to
WP_FOLDERandBACKUP_FOLDER - Keep
.env-wordpress-backupat permissions600 - Never expose
scripts/via web URL
- Ensure read/write access to
- Backups too large
- Use
EXCLUDESfor cache/temporary folders
- Use
- Timeouts on shared hosting
- Set
$executionMode = 'background'in the PHP trigger - Consider
COMPRESSION_METHOD=noneandUSE_NICE_FOR_TAR=1
- Set
- Trigger returns only
Errorwith no details- Check
BACKUP_FOLDER/backup.logfor the full error log - If you need more detail in the HTTP response (e.g. without log access), set
$debugMode = trueintrigger/wordpress-backup.phptemporarily - Set
$debugModeback tofalsewhen done (required for production/cron)
- Check
MIT License.