...

How to Back Up a Website on a VPS: Files, Database, Schedule, and Recovery

Martin Klein

Reading time 1 minute

A website backup on a VPS is not just a single archive in the /backup folder. A proper backup strategy answers five questions: what to back up, where to store it, how often to run backups, how long to keep them, and how to verify recovery.

For a small website, the minimum backup set usually includes:

  • Website files;
  • The database;
  • uploads and user files;
  • Application configuration files;
  • Web server configuration files;
  • cron jobs;
  • SSL certificates or instructions for restoring them;
  • a separate copy outside the primary VPS.

For WordPress, an archive of the files alone is not enough. You need at least two components: the WordPress files and a MySQL dump of the database. The files contain themes, plugins, uploads, and the site code. The database contains posts, pages, users, settings, WooCommerce orders, and most of the dynamic content.

Storing a backup only on the same VPS is risky. If the server is deleted, the disk fails, the account is blocked, or an attacker gains access to the system, local backups may disappear along with the website. A practical setup therefore usually combines a local copy for fast recovery with remote storage for emergencies.

A VPS snapshot is useful, but it is not a replacement for a regular backup. A snapshot is good for quickly rolling back the entire server after a failed update, but it is not always convenient for restoring a single database, one uploads directory, or a specific version of the website, and it is not intended for long-term storage.

For convenience, here is a table:

What to back upHow oftenWhy
DatabaseDailyTo preserve posts, pages, users, orders, and settings
Website filesOnce a week or after major changesTo restore the code, themes, plugins, and project structure
UploadsSeparately, depending on how often they changeTo avoid losing images, documents, and user files
VPS snapshotBefore updates and important maintenanceTo quickly roll back the entire server
Remote copyAfter each important backupTo avoid losing backups together with the VPS
Restore testingRegularlyTo make sure the backup can actually be restored

You can configure the schedule with cron: for example, create a MySQL dump every day, archive the required directories, and send a copy to object storage or a separate backup server. It is better for the backup server to pull the backup rather than having the main server push it there.

The main mistake is assuming that a backup exists before an incident occurs. The archive may turn out to be empty, the database may fail to restore, file permissions may be broken, or the backup script may have stopped working a month ago.

That is why a backup should be considered usable only after recovery has been tested. At least once every six months, you should restore the website from a backup on a test domain or in a temporary environment and check whether the site opens, the database connects, images are visible, and forms, orders, and the admin panel work.

If the archive contains personal data, orders, email addresses, documents, or user files, the backup must be protected: restrict access, encrypt archives, and do not store them in public website directories.

A good backup strategy does not make a website invulnerable, but it turns an incident from a disaster into a manageable task: restore the files, import the database, check the configuration, and bring the website back online.

What a backup strategy should include

A backup strategy is not just a command that creates an archive. It is a clear plan for restoring a website after an error, a compromise, deleted files, a disk failure, or a failed update.

For a small website, the strategy should answer five questions: what exactly to back up, where to store the copies, how often to create them, how long to keep older versions, and how to verify that restoration actually works.

What to Back Up

First, you need to back up everything required to restore the site to working order. For a static site, this may be just the files. For WordPress, an online store, a forum, or a user account area, you also need the database.

The minimum set usually includes:

  • Site files;
  • The database;
  • Uploaded images and documents;
  • Application configuration files;
  • Web server configuration files;
  • cron jobs;
  • Important .env files;
  • Instructions for restoring SSL certificates;
  • A list of installed services and versions.

For WordPress, it is especially important not to forget the database. The files contain themes, plugins, uploads, and the WordPress core. But posts, pages, users, settings, comments, WooCommerce orders, and much of the plugin data are stored in the database.

If you create only a file archive, the site may technically load after a failure, but without its content, settings, or orders. That is why the files and the database should be backed up together as two parts of a single backup.

Once it is clear exactly what needs to be backed up, the next question is where these copies will be stored. The storage location determines whether the backups will survive a real failure.

Where to Store Backups

The simplest option is to store backups on the same VPS. This is convenient for quick recovery: the archive is close at hand, it does not need to be downloaded from external storage, and you can quickly retrieve an individual file or import the database.

However, this option should not be considered full protection. If the VPS is deleted, the disk fails, the account is blocked, or an attacker gains access to the server, local backups may disappear along with the website.

That is why it is better to use multiple storage tiers:

Where to storeBest suited forLimitation
On the same VPSQuickly restoring a file or databaseDoes not help if the server is lost
On a separate backup serverStoring copies separately from the websiteAccess and storage space must be secured
In object storageKeeping remote copies with rotationAccess settings and retention policies are required
As a VPS snapshotQuickly rolling back the entire serverNot always convenient for restoring a single file or a single database

For a small website, a practical setup might look like this: a short-retention local backup on the VPS for quick recovery, plus a separate remote copy in object storage or on a backup server.

Ideally, one of the backup storage locations should be with another provider, or even in a local office, in case of a large-scale outage.

If backups contain personal data, orders, email addresses, or user documents, the archives must be protected: restrict access, do not store them in the website’s public directory, and encrypt them if necessary.

After choosing a storage location, you need to define the backup frequency. One website may change once a month, while another processes orders every day, so their backup schedules should not be the same.

How Often to Create Backups

Backup frequency depends on how often the data changes. The more often new posts, orders, users, comments, or uploaded files appear on the site, the more frequently backups should be created.

For a small WordPress site, you can use the following basic schedule as a starting point:

What to back upFrequency
DatabaseEvery day
Site filesOnce a week
UploadsDaily or several times a week
Configuration filesAfter changes
VPS snapshotBefore updates and major maintenance work

If the site is a blog where new content is published infrequently, a daily database backup and a weekly file backup are usually sufficient. If it is an online store, the database should be backed up more often because it contains orders, customers, payment statuses, and WooCommerce settings.

Before updating WordPress, a theme, plugins, PHP, the database, or the web server, it is best to create a separate manual backup. This backup is not a replacement for the scheduled backups; it is an additional restore point before a risky operation.

To assess backup frequency properly, you need to consider the RPO (Recovery Point Objective): in practical terms, how much data, measured by time, can be permanently lost. Based on this, the frequency may need to be increased, or the entire backup strategy may need to be redesigned.

But frequency is only half of the strategy. If you keep every backup indefinitely, storage space will run out quickly. If you keep only the most recent backup, you may overwrite a good backup after a failure has already occurred.

How Long to Keep Backups

The backup retention period should account for two scenarios. The first is when an incident is detected immediately and you need to restore yesterday’s version. The second is when the problem occurred some time ago but was noticed only days or weeks later.

For example, a site could be hacked today, but the malicious code might not be discovered until a week later. If only the most recent copy is retained, it may already contain infected files. Or important data that was deleted long ago may suddenly be needed again.

For a small website, you can use a simple rotation policy:

  • Daily copies — keep for 7–14 days;
  • Weekly copies — keep for 4–8 weeks;
  • Monthly copies — keep for 3–6 months;
  • Separate backups before major changes — keep until verification is complete.

This approach is not universal, but it is better than a single backup-latest.tar.gz archive that is constantly overwritten.

For sites that process orders, personal data, and legally significant information, the retention period should be chosen more carefully. It is important to consider not only ease of recovery, but also requirements for data protection, access, and deletion of outdated copies.

Once the schedule and retention period have been defined, the key question remains: can the site actually be restored from these archives?

How to Test a Restore

A backup cannot be considered usable until the restore process has been tested. An archive may be created without errors but still be missing the database, uploads, required configuration files, or the correct access permissions.

It is best to test a restore not on the production site, but in a test environment: a temporary domain, a subdomain, a separate directory, or a separate VPS.

A minimal restore test looks like this:

  1. Extract the site files.
  2. Create a new database.
  3. Import the SQL dump.
  4. Check the database connection configuration.
  5. Configure permissions for files and directories.
  6. Open the site in a browser.
  7. Check the admin area, forms, images, and key pages.

For WordPress, you should also check whether posts and pages open, media files are visible, permalinks work, plugins still work, and the theme loads correctly.

For an online store, it is important to test the catalog, cart, checkout, emails, order statuses, and the user’s account area.

You do not need to test recovery every day. However, it should be done regularly and always after any change to the backup setup: a new script, new storage, a database change, a site migration, or an infrastructure update.

Only a restore shows whether a site has a real backup. Until recovery has been tested at least once, all you have is the hope that the archive will help someday.

What to back up on a website

After covering the overall backup strategy, you need to examine what the website itself consists of. A common mistake among many VPS owners is that they save only the folder with the files and assume that this is enough.

For a simple static website, this approach can sometimes work. But for WordPress, an online store, a forum, a user account area, or any other dynamic project, a website consists of several parts: files, the database, user uploads, configuration files, and scheduled tasks.

Website Files

Website files are the code, templates, themes, plugins, static assets, and project structure. They are usually located in a directory such as: /var/www/example.com/ or in another folder used by the control panel, framework, or specific VPS configuration.

For WordPress, a file backup typically includes:

  • The WordPress core;
  • Themes;
  • Plugins;
  • The wp-content directory;
  • Custom code changes;
  • .htaccess files, if Apache is used;
  • Additional scripts and static files.

A file archive helps restore the site’s appearance, plugins, custom code, and project structure. However, by itself it does not restore posts, pages, users, orders, or settings if that data is stored in the database.

Therefore, after backing up the files, you must move on to the database. For a dynamic website, this is not an add-on; it is the second half of the backup.

Database

The database stores the dynamic part of the site. In WordPress, this includes posts, pages, users, comments, settings, menus, WooCommerce orders, payment statuses, and data from many plugins.

If you back up only the files but lose the database, the site may technically still open, but it will be missing its main content.

For MySQL or MariaDB, this is usually done with an SQL dump: mysqldump -u db_user -p database_name > database_name.sql

For automated backups, the command is usually used in a script where database access is read from a protected configuration file or environment variables. The password should not be left in plaintext in public files or in the command history.

For multiple databases, you can create separate dumps or a single backup of all databases if that is justified: mysqldump –all-databases > all-databases.sql

However, to restore a specific site, it is more convenient to have a separate dump of the required database. This reduces the risk of accidentally affecting other projects on the same VPS.

Together, the files and database are enough to restore most of the site. However, a VPS also has configuration files without which the site may fail to start even if you have the archive and the SQL dump.

Web server and application configuration files

Configuration files define how the site starts, where traffic is routed, which PHP version is used, how the application connects to the database, and which environment variables are required for operation.

For the web server, these may be Nginx or Apache configuration files:

/etc/nginx/sites-available/example.com

/etc/nginx/nginx.conf

/etc/apache2/sites-available/example.com.conf

For the application, these may include:

  • .env;
  • wp-config.php;
  • Framework configuration files;
  • Database connection settings;
  • Cache parameters;
  • API keys;
  • Queue settings;
  • Email and SMTP settings.

These files must be backed up carefully. They often contain passwords, tokens, secret keys, and credentials for external services. For this reason, archives containing configuration files must not be stored in the site’s public directory or made available through a direct link.

If configuration files are lost, the site may be partially restored but still fail to start: the database exists and the files are present, but the database connection, domain, rewrite rules, PHP-FPM, or environment variables are misconfigured.

After configuration files, it is important to review user files separately. These files often take up the most space and change more frequently than the site code.

Uploads and User Files

Uploads are images, documents, attachments, avatars, media files, and other data that users or administrators add through the site.

In WordPress, the main uploads directory is usually located here: /var/www/example.com/wp-content/uploads/

For an online store, this directory may contain product images, downloadable files, documents, receipts, instructions, user attachments, and other important materials.

Uploads should be treated separately from the site code. Theme and plugin code may change infrequently, while uploaded files can change every day. As a result, they may require a different backup schedule.

For example, WordPress files can be archived once a week, while uploads can be backed up daily or several times a week if the site is updated frequently.

Size is also important. The uploads directory can take up tens of gigabytes, and if you create a full archive every time, backups will quickly fill the disk. In such cases, it is worth using incremental copies, synchronization to remote storage, or a separate retention policy.

Once files, the database, configuration files, and uploads are covered, a few small but important infrastructure elements remain: SSL and cron jobs.

SSL Certificates and Cron Jobs

SSL certificates do not always need to be backed up like regular files. If Let’s Encrypt is used, the certificate can usually be reissued easily. However, it is important to preserve or document the recovery procedure: the domain, web server, certbot, configuration file paths, and reissue commands.

If the certificates are commercial, custom, or issued manually, they need to be stored more carefully: together with the private keys, certificate chains, and installation instructions.

The paths may look like this:

/etc/letsencrypt/

/etc/ssl/

However, private keys should only be archived in a protected form. If such an archive falls into the wrong hands, an attacker could use the key to undermine trust in the site.

Cron jobs are also often overlooked. Backups, cache cleanup, mailings, parsers, updates, product imports, sitemap generation, and other background tasks may all be run through cron.

You can view the current user’s crontab with: crontab -l

System cron jobs may be located in:

/etc/crontab

/etc/cron.d/

/etc/cron.daily/

/etc/cron.weekly/

If a site is restored without its cron jobs, it may load, but some processes will stop working: notifications may not be sent, products may not be updated, temporary files may not be cleaned up, or backups may not run.

Ultimately, a complete site backup is more than just an archive of /var/www. Recovery requires files, the database, uploads, configuration files, important system settings, SSL instructions, and cron jobs. The better the backup contents are documented, the fewer surprises there will be during the restore.

Practical example: WordPress on a VPS

WordPress on a VPS is a good example of a typical small website: it has files, a database, uploaded images, plugins, themes, configuration files, and periodic changes.

For a site like this, it is better to build a good backup from several parts rather than as one large archive. This makes it easier to restore a specific component instead of the entire server: the database, uploads, a theme, a plugin, or the state of the VPS before an update.

Backing Up WordPress Files

WordPress files are usually located in the site directory. For example: /var/www/example.com/

Before creating a backup, it is useful to create a separate directory for archives: mkdir -p /backup/example.com

You can then create an archive of the site files: tar -czf /backup/example.com/site-files-$(date +%F).tar.gz /var/www/example.com

This archive will preserve the site structure, themes, plugins, WordPress core, the .htaccess file if Apache is used, and other project files.

However, in WordPress, most of the content is not stored in files. Therefore, the site directory archive should be supplemented with a database backup.

MySQL database dump

The WordPress database stores posts, pages, users, comments, settings, menus, WooCommerce orders, and data from many plugins.

For MySQL or MariaDB, you can create a database dump: mysqldump -u db_user -p wordpress_db > /backup/example.com/wordpress-db-$(date +%F).sql

You can then compress the SQL file: gzip /backup/example.com/wordpress-db-$(date +%F).sql

In practice, the database name, username, and password are taken from wp-config.php:

define( ‘DB_NAME’, ‘wordpress_db’ );

define( ‘DB_USER’, ‘db_user’ );

define( ‘DB_PASSWORD’, ‘db_password’ );

define( ‘DB_HOST’, ‘localhost’ );

Do not leave the database password in plain text in scripts, public directories, or command history. For automation, it is better to use a protected configuration file with restricted permissions or a separate database user with the required privileges.

The site files and database dump already provide a basis for restoring WordPress. However, for an active site, you should consider the uploads directory separately: this directory often changes more frequently than themes and plugins.

Separate uploads archive

In WordPress, the uploads directory is usually located here: /var/www/example.com/wp-content/uploads/

It contains images, documents, media files, product files, attachments, and other materials uploaded through the admin area or by users.

If the site is updated frequently, it is useful to back up uploads separately:

tar -czf /backup/example.com/uploads-$(date +%F).tar.gz /var/www/example.com/wp-content/uploads

This approach is useful for two reasons.

First, uploads can take up a lot of space. It is not always practical to archive the entire WordPress installation every day if only the media files and database are actually changing.

Second, a separate uploads archive makes partial recovery easier. For example, if images go missing after a migration, you do not need to restore the entire site — just restore the uploads directory.

For large sites, it is better to consider syncing uploads to remote storage instead of creating a full uploads archive every time. But for a small WordPress site, a separate archive often remains the most straightforward option.

Files, the database, and uploads help restore the site itself. A VPS snapshot is needed for a different scenario: quickly rolling back the entire server.

VPS Snapshot

A VPS snapshot is a provider-level capture of the server’s state. It may include the disk, operating system, installed packages, configuration files, website files, and the database exactly as they were when the snapshot was created.

A snapshot is especially useful before high-risk operations:

  • Upgrading PHP;
  • Upgrading the database;
  • Bulk-updating WordPress plugins;
  • Changing Nginx or Apache configuration files;
  • Migrating a website;
  • Changing the control panel;
  • Major server maintenance.

If the website stops loading after an update, a snapshot lets you quickly roll back the entire VPS to its previous state.

However, a snapshot should not be treated as the only backup. It has limitations: it depends on the provider, may be stored within the same infrastructure, is not always practical for restoring a single file or a single database, may affect the performance of the entire VPS, and does not replace an off-site copy.

For this reason, a snapshot is best used as an additional layer of protection, not as the primary backup strategy.

After local archives and snapshots, the most important question remains: what happens if the primary VPS is lost entirely. This requires a copy outside the server itself.

Copying to remote storage

A remote copy protects against scenarios where the primary VPS is unavailable, deleted, compromised, or damaged. If all backups were stored only on that server, there would be nothing to restore from.

For remote storage, you can use:

  • Object storage;
  • A separate backup server;
  • SFTP storage;
  • Cloud storage;
  • Another VPS used only for backups.

The basic approach is simple: the backup is created locally and then copied off the primary server.

For example, if you use a separate backup server, you can send the copy using rsync: rsync -avz /backup/example.com/ [email protected]:/backups/example.com/

Or using scp:

scp /backup/example.com/site-files-$(date +%F).tar.gz [email protected]:/backups/example.com/

It is important to make sure that synchronization works only in one direction: if the VPS is compromised, an attacker could use the scripts and credentials to delete the backups. An alternative is to configure the scripts in a similar way on the backup server, so that it connects on its own and pulls the archives.

For object storage, provider CLI tools or S3-compatible clients are usually used. In this case, it is important to configure access permissions so that backups are not public, use credentials with write-only permissions (not delete permissions), and configure rotation using S3 tools.

If the archives contain personal data, orders, email addresses, documents, or user files, encryption should be used before uploading them to remote storage.

A practical setup for WordPress on a VPS looks like this: site files are archived separately, the database is saved via a MySQL dump, uploads can be placed in a separate archive, a snapshot is created before important work, and the finished copies are sent to remote storage. This setup is not the most complex, but it addresses the main risks for a small website.

How to Configure a Backup Schedule with cron

Once you know exactly what needs to be backed up, the next step is automation. A manual backup before major changes is useful, but it is no substitute for a schedule: on ordinary days, a site owner can easily forget to make a copy.

On a VPS, cron is commonly used for recurring tasks. You can use it to run backup scripts every day, once a week, or on another schedule.

It is important not to bundle everything into a single opaque command. It is better to separate the tasks: the database, files, deleting old archives, and checking logs should each be handled separately.

Daily database backup

The database changes more often than anything else. In WordPress, it stores posts, pages, users, settings, comments, WooCommerce orders, and plugin data. For this reason, the database is typically backed up daily, and even more frequently for active online stores.

A simple script for a daily database dump might look like this:

#!/bin/bash

BACKUP_DIR="/backup/example.com/db"

DATE=$(date +%F)

DB_NAME="wordpress_db"

DB_USER="db_user"

mkdir -p "$BACKUP_DIR"

mysqldump -u "$DB_USER" -p "$DB_NAME" | gzip > "$BACKUP_DIR/db-$DATE.sql.gz"

This example illustrates the general approach, but in a production script, it is better not to enter the password manually or store it in plain text. A safer option is to use a separate MySQL configuration file with restricted permissions, or another secure authentication method.

For example, you can put the credentials in a file that is accessible only to the intended user and use it in the script:

mysqldump –defaults-extra-file=/root/.my.cnf wordpress_db | gzip > /backup/example.com/db/db-$(date +%F).sql.gz

After that, you can add the task to cron:

crontab -e

Example of running it every day at 03:10:

10 3 * * * /usr/local/bin/backup-db.sh >> /var/log/site-backup.log 2>&1

The database is the most sensitive part of a dynamic website, but SQL dumps alone are not enough. WordPress files, themes, plugins, and uploads should also be included in the schedule.

Weekly File Backup

Website files usually change less frequently than the database. Themes, plugins, code, and the project structure are not updated every day, so a weekly archive is often enough for a small site.

Example script for WordPress files:

#!/bin/bash

BACKUP_DIR="/backup/example.com/files"

DATE=$(date +%F)

SITE_DIR="/var/www/example.com"

mkdir -p "$BACKUP_DIR"

tar -czf "$BACKUP_DIR/site-files-$DATE.tar.gz" "$SITE_DIR"

If the uploads directory changes frequently and takes up a lot of space, it can be backed up separately from the other files. For example, back up the site code once a week, and uploads daily or several times a week.

To run it weekly via cron, you can use the following entry:

30 3 * * 0 /usr/local/bin/backup-files.sh >> /var/log/site-backup.log 2>&1

Here, the script runs on Sundays at 03:30. It is best to choose a time when the site is less active so that the load from archiving does not interfere with users.

Before major updates to WordPress, PHP, the database, the theme, or plugins, it is best to create an additional manual backup. The schedule provides regular protection, but it does not eliminate the need for a rollback point before risky changes.

Once the database and files are saved regularly, a new problem quickly appears: archives take up more and more space. That is why rotation is needed.

Rotating old archives

Rotation deletes old backups according to defined rules so that archives do not fill up the disk. Without rotation, backups can themselves cause an outage: the site may stop working because the VPS runs out of space.

The simplest option is to delete daily backups older than a specified period:

find /backup/example.com/db -type f -name "*.sql.gz" -mtime +14 -delete

This command deletes SQL archives older than 14 days.

For file archives, you can use a different retention period, for example 30 days:

find /backup/example.com/files -type f -name "*.tar.gz" -mtime +30 -delete

However, deleting everything with a single rule is not always convenient. It is better to define a retention policy in advance:

Backup typeExample retention period
Daily database backups7–14 days
Weekly file backups4–8 weeks
Monthly archives3–6 months
Backup before a major updateUntil verification is complete

Rotation can be added as a separate cron job:

0 4 * * * /usr/local/bin/rotate-backups.sh >> /var/log/site-backup.log 2>&1

It is important not to delete old copies until the new copy has been successfully created and uploaded to remote storage. Otherwise, you may be left without an up-to-date backup. For this reason, it is best to add a check for the latest backup file to the rotation script, or to create a single backup script that deletes old copies only after a successful run.

Automation should not only create and delete archives. You also need to know whether the backup completed successfully. Logs are needed for that.

Checking backup logs

Cron runs tasks automatically, but by itself it does not guarantee that a backup was created successfully. The script may have exited with an error, the database may have been unavailable, the disk may have filled up, or the remote storage may have failed to accept the file.

For this reason, it is best to write script output to a log:

10 3 * * * /usr/local/bin/backup-db.sh >> /var/log/site-backup.log 2>&1

30 3 * * 0 /usr/local/bin/backup-files.sh >> /var/log/site-backup.log 2>&1

0 4 * * * /usr/local/bin/rotate-backups.sh >> /var/log/site-backup.log 2>&1

Review the log periodically:

tail -n 100 /var/log/site-backup.log

It is also useful to check the size of recent archives:

ls -lh /backup/example.com/db/

ls -lh /backup/example.com/files/

If yesterday’s database dump was 300 MB and today’s is suddenly 2 KB, that is a reason to stop and inspect the script. Strictly speaking, the file was created, but it may not contain a complete backup.

For a more reliable setup, you can add notifications: send a message by email, to Slack, or to a monitoring system when an error occurs. The key is not to discover that a backup is broken only after an incident.

Scheduling with cron takes care of regularity, but it does not address storage. Local archives are convenient, but real protection is achieved only when copies are moved outside the primary VPS.

Where to Store Backups

Where backups are stored is just as important as the backup archive itself. If a backup is stored alongside the website and depends on the same server, it may disappear along with it.

A good storage strategy should account for several scenarios: accidental file deletion, a website failure after an update, a VPS outage, loss of server access, and local disk corruption.

On the same VPS

A local backup on the same VPS is convenient for quick restores. For example, if you accidentally delete a file, break a WordPress theme, or need to roll the database back to its state from yesterday, the archive is close at hand and can be used quickly.

This option is suitable for short-term storage:

  • Recent SQL dumps;
  • Recent file archives;
  • Copies created before updates;
  • Temporary backups before changing configuration files.

However, a local backup does not protect against a serious incident. If the server is deleted, the disk fails, the account is suspended, or an attacker gains root access, the backups may be lost along with the website.

Another issue is disk space. If you store archives on the same VPS without rotation, they can fill up the disk and cause the website to fail.

Therefore, local copies are best used as a fast recovery layer, not as the only storage location.

On a separate backup server

A separate backup server protects against the loss of the primary VPS. This can be another VPS, a dedicated server, network storage, or a separate machine to which the primary server sends archives.

This option is useful when you need more control: you can configure rsync, SFTP, SSH keys, separate access permissions, rotation, and your own directory structure.

Example of sending backups via rsync:

rsync -avz /backup/example.com/ [email protected]:/backups/example.com/

The backup server should not be just “another folder with full access.” It is better to use a separate user, restricted permissions, and keys that allow writing backups but do not grant unnecessary access to the primary server.

It is also important to monitor free space, transfer logs, and the retention period for old archives. If the backup server fills up, new copies may stop being saved, and the site owner may only discover this after an incident.

A separate server provides control, but it requires maintenance. If you want to reduce administrative overhead, object storage is often more convenient.

In object storage

Object storage is suitable for storing archives remotely: SQL dumps, website files, uploads, and encrypted copies. This format is convenient because the storage is separate from the VPS and is usually well suited for automated file uploads.

In object storage, you can configure:

  • A separate bucket for backups;
  • Restricted access keys;
  • Lifecycle rules for deleting old copies;
  • Versioning;
  • Storage in another region;
  • An access policy without public read access.

The main rule is that a bucket containing backups must not be public. Archives may contain personal data, orders, email addresses, configuration files, user documents, and other sensitive data.

If backups contain this type of data, they should be encrypted before being sent to object storage. That way, even if access settings are misconfigured, the archive will not be stored in plaintext.

Object storage is well suited for disaster recovery, but it is not always convenient for instantly rolling back an entire server. VPS snapshots are often used for that purpose.

Using a VPS snapshot

A VPS snapshot is a provider-level snapshot of the server’s state. It is useful when you need to quickly roll back the entire server after a failed update, configuration change, or major migration.

A snapshot is especially appropriate before actions that may affect the entire system:

  • Updating PHP;
  • Updating the database;
  • Changing the OS version;
  • Configuring the control panel;
  • Migrating the site;
  • Bulk updating WordPress, the theme, and plugins;
  • Changing Nginx, Apache, or PHP-FPM configuration.

However, a snapshot does not replace regular backups. It depends on the provider, may be stored in the same infrastructure, and is not always convenient when you need to restore only a single database, one uploads directory, or an individual file.

Another consideration is data consistency. If a snapshot is taken while the database is being actively written to, the application state may not be ideal. For important projects, it is better to combine snapshots with regular database dumps and file backups.

A snapshot is a good tool for quick rollback, but a complete backup strategy should not rely on a single storage option.

Why it’s better to combine several options

A reliable backup strategy usually combines several storage tiers. Each option addresses a specific risk, but no single option solves every problem at once.

For a small website, you can use the following setup:

Where to store itWhy
On the same VPSTo quickly restore a file or database, or roll back after a minor error
On a separate backup serverTo keep copies separate from the primary server
In object storageTo keep remote archives with rotation and long-term retention
In a VPS snapshotTo quickly roll back the entire server after a failed update

A practical minimum is a local copy on the VPS plus a remote copy outside it. For a more thorough setup, you can add a snapshot before important work and use object storage for long-term retention.

The biggest mistake is keeping the only backup in the same place as the website. That kind of archive helps only with minor issues, but it will not save you if the VPS is lost.

It is better to think about storage by asking: “What happens if the primary server disappears right now?” If the answer is “The backups disappear too,” the setup needs to be changed.

How to Verify a Restore

A backup cannot be considered usable simply because the archive was created without errors. The real test begins during the restore process: the database must import successfully, the files must extract correctly, permissions must remain intact, and the website must open in a browser.

It is best not to test a restore on the production site. A test environment is safer: a separate VPS, a temporary domain, a subdomain, a local machine, or an isolated directory. This lets you verify the archives safely without putting the live project at risk.

Restoring the database in a test environment

For a dynamic website, the database is one of the key components of recovery. If the SQL dump is corrupted, incomplete, or taken from the wrong database, the site may load with errors or lose some of its content.

In the test environment, create a new database:

mysql -u root -p -e "CREATE DATABASE restore_test DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

Then import the dump:

gunzip < /backup/example.com/db/db-2026-01-15.sql.gz | mysql -u root -p restore_test

If the dump is not compressed, the command is simpler:

mysql -u root -p restore_test < /backup/example.com/db/db-2026-01-15.sql

After the import, verify that the tables are actually present:

mysql -u root -p -e &quot;SHOW TABLES FROM restore_test;&quot;

For WordPress, it is also important to make sure the database contains tables with the expected prefix, such as wp_posts, wp_options, wp_users, and wp_postmeta.

If the database has been restored without errors, you can proceed to the site files. Without them, the database alone will not provide a working WordPress site, online store, or application.

Checking files and uploads

Extract the site files into a test directory, not over the production project. For example:

mkdir -p /var/www/restore-test

tar -xzf /backup/example.com/files/site-files-2026-01-15.tar.gz -C /var/www/restore-test

After extraction, verify that the structure looks as expected. For WordPress, it should contain files and directories such as:

wp-admin/

wp-content/

wp-includes/

wp-config.php

index.php

Check uploads separately. In WordPress, this directory is usually located here:

/wp-content/uploads/

If uploads are not restored, the site may load, but images, documents, product files, and media files will be missing. For an online store, this can mean empty product pages, broken instructions, missing attachments, or unavailable digital products.

You should also check the size of the restored files. If the uploads archive is supposed to be several gigabytes, but extraction results in an almost empty folder, the backup was incomplete or the restore was performed incorrectly.

Once the database and files have been restored, the site may still fail to load because of permissions. The next step is therefore to check file ownership and permissions.

Checking access permissions

After a restore, files may end up owned by the wrong user. For example, the archive may have been extracted as root, while the web server runs as www-data. As a result, the site may open with errors, fail to load images, fail to update plugins, or be unable to write to the cache.

You can check file ownership as follows:

ls -la /var/www/restore-test

For a typical Nginx/Apache setup with PHP-FPM, the owner is often set to the web server user or to a dedicated site user. For example:

chown -R www-data:www-data /var/www/restore-test

Permissions also need to be set carefully. For WordPress, the following is often used as a guideline:

find /var/www/restore-test -type d -exec chmod 755 {} \;

find /var/www/restore-test -type f -exec chmod 644 {} \;

However, this is not a universal rule for every project. Some applications require specific permissions for cache directories, uploads, storage, logs, or temporary files.

Pay special attention to configuration files that contain secrets: .env, wp-config.php, files with API keys, and database credentials. They must not be publicly accessible and must not have overly broad permissions.

After checking permissions, you can launch the site on a test domain or temporary address and verify that it works as a fully functional project.

Checking the site after a restore

The final restore check is not just about opening the home page. The home page may load from cache, while issues may appear in the admin area, forms, cart, images, or database connection.

For WordPress, check the following:

  • Whether the home page opens;
  • Whether internal pages work;
  • Whether the admin area opens;
  • Whether images from the uploads directory are visible;
  • Whether permalinks work;
  • Whether the required plugins are active;
  • Whether the theme is loaded correctly;
  • Whether there are any PHP errors in the logs.

For an online store, the check should be broader:

  • Whether the catalog opens;
  • Whether product pages work;
  • Whether a product can be added to the cart;
  • Whether checkout can be completed;
  • Whether an order is created in the admin area;
  • Whether emails are sent to the customer and the administrator;
  • Whether payment and delivery statuses are saved;
  • Whether the customer account area works.

It is also worth checking the web server configuration, database connection, cron jobs, and background processes. The site may open in a browser but fail to run scheduled tasks: clearing the cache, importing products, generating the sitemap, sending notifications, or creating new backups.

After a test restore, it is useful to record the result: which backup was restored, how long the process took, which commands were used, and what issues occurred. This turns restoration from a one-off improvisation into a clear procedure.

If a restore has never been tested, the backup remains an assumption. Only a backup from which the site has already been successfully restored, at least in a test environment, can be considered a working backup.

Common Website Backup Mistakes

Most backup problems do not occur during setup, but during an incident. While the site is running, it may seem like archives are being created somewhere and that this is enough. But during recovery, you may discover that the copy was stored in the wrong location, the database was not backed up, the archive is corrupted, or the script stopped running long ago.

That is why it is better to review mistakes in your backup strategy in advance. They are common, but they are exactly what often turns a minor failure into a complete loss of the website.

Keeping backups only on the same VPS

A local backup on the same VPS is convenient, but it should not be the only backup. It helps when you need to quickly restore a deleted file, roll back the database to the previous day’s state, or recover after a failed update.

The problem is that a local copy depends on the same server as the website. If the VPS is deleted, the disk fails, the account is blocked, or an attacker gains access to the system, the backups may disappear along with the main project.

Another risk is running out of disk space. If archives are stored on the same server without rotation, they can consume all available space. As a result, the website may become unstable, the database may stop writing data, and new backups will not be created.

A better approach is to use local copies only as a fast recovery layer. The primary disaster recovery backup should be stored outside the VPS: on a separate backup server, in object storage, or in another protected storage location.

Even if a backup is stored in the right place, that does not necessarily mean you can restore from it. The next common mistake is never testing the restore process.

Not testing restores

A backup without a tested restore is not a guarantee; it is an assumption. An archive may look fine, take up a lot of space, and be created on schedule, but still turn out to be useless when you try to restore it.

The issues can vary:

  • The SQL dump was created from the wrong database;
  • The file archive does not include uploads;
  • The file is corrupted;
  • The backup was interrupted because there was not enough space;
  • The script did not log errors;
  • The database cannot be imported because of encoding or version issues;
  • Access permissions break after the restore;
  • The archive does not contain the required configuration files.

It is best to test restores in a test environment: a separate VPS, a temporary domain, a subdomain, or a local machine. You need to do more than simply unpack the archive; you need to make sure the site loads, the database connection works, images are displayed, forms work, and the admin panel is accessible.

For WordPress, you should check pages, posts, media files, plugins, permalinks, and admin login. For an online store, check the catalog, cart, checkout, emails, and user account area.

Restore testing shows which parts of the backup actually work and which exist only on paper. This stage very often reveals that only the files were being saved, not the database.

Backing up files only, without the database

For a dynamic website, a file archive is not a complete backup. WordPress, WooCommerce, forums, user accounts, and many CMS platforms store core information in the database.

Files contain themes, plugins, code, images, templates, and static assets. The database contains posts, pages, users, comments, settings, orders, payment statuses, menus, and plugin data.

If you save only the files, after a failure you may be able to restore the site’s shell, but not its content.

For WordPress, a minimal backup should include:

  • An archive of the site files;
  • An SQL dump of the database;
  • The uploads directory;
  • Configuration files such as wp-config.php;
  • Information about the PHP version, database, and web server.

The database is especially critical for online stores. Losing the SQL dump can mean losing orders, customers, payment statuses, and purchase history.

Therefore, files and the database should be backed up together, but not necessarily at the same frequency. The database can be backed up daily, while files can be backed up once a week or after major changes.

When a backup includes the database, uploads, and configuration files, another question arises: how the archives themselves are protected. If they contain personal data, storing them in plaintext is risky.

Not encrypting archives containing personal data

Backups often contain more sensitive data than it may seem. They may include email addresses, phone numbers, orders, delivery addresses, documents, user files, API keys, database passwords, and application configuration files.

If such an archive is stored unencrypted, its leakage can be more dangerous than ordinary access to the public part of the website. This is especially true if the backup is sent to remote storage, stored on a third-party server, or transferred between systems.

Minimum security measures:

  • Do not store archives in the website’s public directory;
  • Restrict access permissions to the backup folder;
  • Use separate keys for backup storage;
  • Encrypt archives containing personal data;
  • Do not transfer backups over unsecured channels;
  • Delete outdated copies according to the retention policy.

For example, archives should not be stored in a directory such as:

/var/www/example.com/backup/

If this folder accidentally becomes accessible from a browser, the backup can be downloaded directly.

For sensitive data, it is better to encrypt archives before sending them to remote storage. That way, even if access settings are misconfigured, the archive will not be fully exposed.

However, protecting archives does not solve another problem: backups can be stored properly, yet no one may notice that they stopped being created long ago.

Discovering a broken backup only after a failure

One of the most frustrating situations is discovering a backup problem during recovery. For example, the site is already down, and the latest archives are empty, outdated, corrupted, or have not been created at all in the past two months.

This often happens when there is no monitoring or log review. The script may have stopped working after a MySQL update, a password change, a change to the site path, a full disk, or moving the project to another directory.

The cron job may still be in place, but the backup is not being created.

To avoid discovering this too late, you should check:

  • The date of the last successful backup;
  • The size of recent archives;
  • The script logs;
  • Available disk space;
  • Successful upload to remote storage;
  • Errors during the database dump;
  • Periodic restores in a test environment.

It is useful to add error notifications via email, Slack, or a monitoring system. Even a simple “backup was not created” message is better than silence until an incident occurs.

Ultimately, a good backup strategy should not only create archives, but also confirm that they were created, are not empty, were sent to the correct location, and are restored at least periodically. Without this, backups remain a weak point rather than protection for the site.

Conclusion

A website backup on a VPS is not a one-time command or an archive that happens to be stored somewhere on the server. It is a strategy: what to back up, where to send the copies, how often to create them, how long to retain them, and how to test recovery.

For a small website, the minimum you need to back up is the files, the database, uploads, configuration files, important cron jobs, and SSL recovery instructions. For WordPress, it is especially important to remember that files and the database are different parts of the site. Themes, plugins, and media are stored in the files, while posts, pages, users, settings, and WooCommerce orders are stored in the database.

Storing backups only on the same VPS is risky. A local archive can help you quickly restore a file or database, but it will not help if the server is deleted, the disk is damaged, or access to the VPS is lost. For this reason, a working setup should include remote storage: a separate backup server, object storage, or another independent option.

A VPS snapshot is useful for a quick rollback before updates and major changes, but it does not replace regular backups. To restore an individual database, uploads directory, or specific website version, it is more convenient to have separate archives and an SQL dump.

The main measure of backup quality is not the fact that an archive was created, but a successful restore. If recovery has never been tested, you cannot be sure that the archive will help after a failure. At least periodically, you should restore the site from a backup in a test environment and check the database, files, uploads, permissions, admin area, forms, and key workflows.

A good backup strategy turns a failure from a disaster into a clear sequence of actions: retrieve the required copy, restore the database, unpack the files, check the configuration, fix permissions, and bring the site back online.

FAQ

How often should you back up a website on a VPS?

The frequency depends on how often the data changes. For a small WordPress site, a daily database backup and a weekly file backup are usually sufficient.

For an online store, it is better to back up the database more often because it contains orders, customers, payment statuses, and WooCommerce settings. Before updating WordPress, PHP, the database, the theme, plugins, or web server configuration, you should create a separate manual backup.

Is a VPS snapshot enough to protect a website?

No. A VPS snapshot is useful, but it should not be your only backup. It is well suited for quickly rolling back the entire server after a failed update or configuration change.

However, a snapshot depends on the provider and is not always convenient if you need to restore a single database, a single uploads directory, or an individual file. For this reason, it is better to combine snapshots with regular file archives, SQL database dumps, and a copy in remote storage.

What should you always back up in WordPress?

For WordPress, you need to back up the site files and the database. The files include the WordPress core, themes, plugins, wp-content, uploads, and custom modifications. The database stores posts, pages, users, comments, settings, menus, plugin data, and WooCommerce orders.

You should also save wp-config.php, web server configuration files, cron jobs, and information about the versions of PHP, MySQL/MariaDB, and key extensions.

Can backups be stored on the same VPS?

Yes, but only as an additional fast recovery layer. A local copy is useful when you need to quickly restore a deleted file or roll back the database to the previous day.

However, backups should not be stored only on the same VPS. If the server is deleted, the disk fails, or an attacker gains access to the system, the local archives may disappear along with the website.

How can you tell whether a backup actually works?

A backup should be considered usable only after a restore test. You need to take the archive, bring up the site in a test environment, import the database, extract the files, and check uploads, access permissions, configuration files, and how the site works in a browser.

For WordPress, check the homepage, internal pages, admin area, media files, permalinks, and plugins. For an online store, check the catalog, cart, checkout, emails, and customer account area.

Should website backups be encrypted?

If backups contain personal data, orders, email addresses, documents, user files, API keys, or database passwords, it is best to encrypt the archives.

This is especially important when sending them to remote storage or to a separate backup server. Even if storage access is configured incorrectly, an encrypted archive reduces the risk of a data leak.

Which is worse: not making backups or not testing recovery?

Both are dangerous. But an untested backup creates a false sense of security. A site owner may believe everything is protected, only to discover after an incident that the archive is empty, the database cannot be imported, or the uploads were not saved.

That is why a backup strategy should include not only creating copies, but also checking logs, monitoring archive size, sending backups to remote storage, and regularly testing restore procedures.

Sources

1. WordPress Developer Resources — Backing Up Your Database

2. WordPress Developer Resources — Backing Up Your WordPress Files

3. MySQL Documentation — mysqldump: A Database Backup Program

4. Ubuntu Manpages — cron

Subscribe to our newsletter and receive articles and news

    Check out our other materials