A small and practical Bash backup script for Linux VPS servers.
It creates a date-stamped ZIP archive of /var/www/html, uploads the archive to MEGA through rclone, sends a status report to Discord, and removes the temporary ZIP file after the upload attempt.
Built for simple, scheduled website backups without a database, framework, or extra application layer.
- 📦 ZIP backup of
/var/www/html - 📅 Date-based backup filenames
- ☁️ MEGA upload via rclone
- 🔔 Discord webhook notifications
- 🧹 Automatic temporary-file cleanup
- ⏰ Easy
cronscheduling - 🐚 Pure Bash — simple and easy to customize
/var/www/html
│
▼
ZIP archive
│
▼
rclone
│
▼
MEGA
│
└──────► Discord status report
Temporary ZIP ──► deleted
Example for 2026-09-28:
/tmp/html_backup_2026-09-28.zip
The current script uploads it to:
mega:/VeePass/html_backup_2026-09-28.zip
Recommended for Debian/Ubuntu VPS servers:
- Bash
zipcurlrclone- A configured MEGA remote in rclone
- A Discord webhook URL
The current script backs up:
/var/www/html
sudo apt update
sudo apt install zip curl -yInstall rclone:
curl https://rclone.org/install.sh | sudo bashVerify:
rclone version
zip -v
curl --versionStart the rclone configuration wizard:
rclone configCreate a remote for your MEGA account.
The current script expects the remote to be named:
mega
Test it:
rclone lsd mega:If you use another remote name, change the DEST variable in main.sh.
Edit the script:
nano main.shMain settings:
DATE=$(date +%F)
SRC="/var/www/html"
ZIP_FILE="/tmp/html_backup_$DATE.zip"
DEST="mega:/VeePass/html_backup_$DATE.zip"
WEBHOOK_URL=""For example:
SRC="/var/www/example.com"For example:
DEST="mega:/backups/html_backup_$DATE.zip"Set your webhook:
WEBHOOK_URL="https://discord.com/api/webhooks/..."Do not commit a real webhook URL to GitHub.
Make the script executable:
chmod +x main.shRun it manually:
./main.shThe script then:
- Creates the ZIP archive.
- Attempts to upload it to MEGA.
- Sends a Discord report containing the ZIP and upload status.
- Removes the temporary ZIP file.
Edit your crontab:
crontab -eRun the backup every day at 03:00:
0 3 * * * /path/to/mega-backup-upload/main.sh >> /var/log/mega-backup.log 2>&1Example:
0 3 * * * /opt/mega-backup-upload/main.sh >> /var/log/mega-backup.log 2>&1Check the active cron jobs:
crontab -lFiles are named using the server date:
html_backup_YYYY-MM-DD.zip
Example:
html_backup_2026-09-28.zip
html_backup_2026-09-29.zip
html_backup_2026-09-30.zip
The script can contain access credentials or URLs for external services, so protect the configuration.
- Never publish your Discord webhook URL.
- Never commit sensitive rclone configuration files.
- Use appropriate file permissions on the script and configuration.
- Prefer a dedicated backup account or remote when practical.
- Make sure the user running the script can read the source directory.
A leaked Discord webhook should be treated as compromised and replaced.
rclone lsd mega:ls -lah /var/www/htmlzip -r /tmp/test-backup.zip /var/www/htmlcurl -H "Content-Type: application/json" \
-X POST \
-d '{"content":"MEGA backup test"}' \
"YOUR_WEBHOOK_URL"rclone ls mega:/VeePassThis repository intentionally keeps the backup process simple.
The current main.sh reports the ZIP and upload steps separately. If ZIP creation fails, the script still proceeds to the upload command and then sends the resulting status messages.
For production environments, you may want to add:
set -euo pipefail- stop-on-failure logic
- backup retention/rotation
- checksum or integrity verification
- restore testing
- configurable environment variables
- more detailed logging
- failure-specific notifications
These improvements are outside the scope of the current minimal script.
mega-backup-upload/
├── main.sh
├── README.md
└── LICENSE
| File | Purpose |
|---|---|
main.sh |
Creates, uploads and cleans up the backup |
README.md |
Project documentation |
LICENSE |
MIT License |
This project is licensed under the MIT License.
See LICENSE for the full license text.
Sina Hosseini
GitHub: @sinahinson
Simple backups · Remote storage · Discord alerts