Custom Backup Script: Weekly Backups with Monthly Retention

Custom Backup Script: Weekly Backups with Monthly Retention

I’m sharing a custom backup script I use for my HestiaCP server. It creates weekly backups (4 per month) and automatically keeps only the most recent backup from previous months, helping save disk space while maintaining a good backup history.

Features:

  • Creates organized backups in date-structured directories (e.g., /backup/12 DEC 2025/)
  • Maintains symlinks in /backup/ for HestiaCP panel compatibility
  • Symlinks are essential - they allow HestiaCP to update backup counters correctly and enable users to download, restore, and delete backups from the panel, even though backups are organized in monthly folders
  • Automatically cleans orphaned backups
  • Optional: Keep only 1 backup per user from previous months (configurable)
  • HTML email notifications with full backup summary
  • Detailed logging for each backup session
  • Database integrity checks before backup
  • Robust cleanup of temporary files and incomplete backups

Installation:

  1. Create the script file:

    nano /usr/local/hestia/bin/v-backup-users-custom
    
  2. Paste the script content (I’ll provide it below)

  3. Set proper permissions:

    chmod 755 /usr/local/hestia/bin/v-backup-users-custom
    
  4. In HestiaCP Admin Panel:

    • Go to SettingsBackups
    • Ensure “Local backup” is enabled
    • Go to Cron Jobs
    • Find the existing backup cron job: 00 01 * * 0 sudo /usr/local/hestia/bin/v-backup-users
    • Change it to: 00 01 * * 0 sudo /usr/local/hestia/bin/v-backup-users-custom
    • Adjust the time as needed (current example: Sunday at 1:00 AM)

Configuration Options:

At the top of the script, you can customize:

# Auto-detect admin user with ROLE='admin' (leave empty)
ADMIN_USER_OVERRIDE=""

# Use CONTACT email from admin user (leave empty)
# Or set manually: ADMIN_EMAIL_OVERRIDE="[email protected]"
ADMIN_EMAIL_OVERRIDE=""

# Keep only 1 backup per user from previous months (TRUE/FALSE)
# When TRUE: Keeps only the most recent backup from previous months
# When FALSE: Keeps all backups (default HestiaCP behavior)
KEEP_ONLY_ONE_OLD_BACKUP="FALSE"

How it works:

  1. Runs weekly (or as configured in cron)
  2. Creates backups in organized folders: /backup/DD MMM YYYY/username/
  3. Maintains symlinks in /backup/ for panel compatibility
    • These symlinks are crucial - they allow HestiaCP to:
      • Update backup counters (U_BACKUPS) correctly
      • Display backups in the user panel
      • Enable download, restore, and delete functions
      • All functions work normally despite backups being organized in monthly folders
  4. If KEEP_ONLY_ONE_OLD_BACKUP="TRUE", automatically removes old backups from previous months, keeping only the latest one per user
  5. Sends HTML email summary with backup status
  6. Logs everything for troubleshooting

User Panel Compatibility:

Even though backups are stored in organized monthly folders, all HestiaCP panel functions work perfectly:

  • Users can see their backups in the panel
  • Download backups directly
  • Restore backups with one click
  • Delete backups from the panel
  • Backup counters are updated correctly

This is possible because the script maintains symlinks in the /backup/ directory that point to the actual backup files in the organized folders.

Remote Backup Support:

You can customize this script to work with remote backups (FTP, SFTP, B2, Rclone) by modifying the backup functions. The script is based on HestiaCP’s original v-backup-user logic but with enhanced organization and cleanup features.

**Script:
**

Notes:

  • This script replaces the standard v-backup-users for scheduled backups
  • You can still run manual backups using the original command
  • All backups remain compatible with HestiaCP’s restore functions
  • The script includes error handling and cleanup for interrupted backups
  • Symlinks ensure full panel functionality while maintaining organized storage

Feedback and improvements welcome

3 Likes

I have already custom for daily,weakly,monthly creating username_daily etc and replacing the old one! Good job and thanks for sharing! I can provide also the scripts if someone need.

1 Like

It’s not a bad option, although I prefer not to modify how Hestia performs its backups.

It’s not much more complicated to create a bash script that handles backup cleanup.

For this, the bash script should read and edit the files in:
/usr/local/hestia/data/users
and delete the backups. It works very well.

I have the logic set up to maintain 7 daily backups + 3 weekly backups + 2 monthly backups, and I haven’t had any problems.

The difference is that by following my implementation you get a highly configurable script with a tenth the weight of your code.

Just sharing something i been using for years on vesta. :love_you_gesture:

Thanks for sharing!

@Blats and @Antonio if you have something that you think is better and are willing to share: please do :slight_smile:

I don’t use GitHub, and it’s not something so special that it needs to be shared.

in the file:
/usr/local/hestia/data/users/USER_XX/backup.conf
You have the complete list of all backups for each account.

and in:
/usr/local/hestia/data/users/USER_XX/user.conf
You have the stored backup counter U_BACKUPS=‘’

You just need to go through each user’s list, determine which backups you want to delete (by age), and update the backup counter (user.conf) and their backup list (backup.conf).

You can create your own backup schedule—daily, weekly, monthly, annual, whatever you want.
You don’t need to use anyone else’s.

An easy, simple, and extremely useful solution if you don’t have a minimum of knowledge of BASH is to use this data to ask your preferred AI; I assure you it will give you an easy and simple script to understand.

The amount of code you will need is well below 5kb, including extensive comments.

IMPORTANT:
The difference with this idea is that it’s not actually a backup program, it’s a backup deletion program.

pd
Furthermore, my backup cleaning script is tailored to my needs and I handle external backups, so I add an extra layer that is unnecessary for most people.

1 Like

That’s essentially what my script does.

It looks large because I included a more elaborate email template.

Also, instead of using v-backup-users, I copied its contents directly into my script. I could call it externally, and the script would be much smaller.

I haven’t read your script, nor have I criticized it.

I got the impression that your script replaces Hestia’s scheduled backup with your own.

Is that correct?
And that’s precisely the point I don’t touch.

When I create a hosting plan, I add 20 backups and let HestiaCP perform its backups at the scheduled time each day.

And my script simply performs cleanup… Depending on the configuration variables, it will allow X daily backups, X weekly backups, X monthly backups…

And I think that’s the only difference.

  • Your script is a backup script.

  • My script is a simple cleanup script.

These are two perfect ideas.

Yup, I know :grin:

Just saying that it is using v-backup-user as base.

The code just looks big. :grimacing: