Back Up and Restore WordPress Site on Linux Server without A Plugin

In a previous tutorial, I showed you how to install WordPress on Linux server. In this article, I will show you how to back up your WordPress site and restore it without a plugin. I assume that you have access to your Linux VPS (virtual private server) or dedicated server via SSH and know some basic Linux commands. If you have a shared hosting plan, then I’m sorry that this article is not for you.

Back Up WordPress without a plugin

So you probably know that you shouldn’t install too many plugins on your WordPress site because that will slow down your site. Good news to those of you who host WordPress on virtual private server or dedicated server. You can use Linux and MySQL command to automate your WordPress backup process so you can remove your WordPress backup plugin. Best of all, this backup method is free of charge!

To back up a WordPress site, we have to back up the database and all the files under your webroot directory. First I will explain how to back up the database.

Backing up WordPress Database

The following command applies to both MySQL database and MariaDB database. For those of you who don’t know, MariaDB is a drop-in replacement of MySQL. That means 99% percent of the commands of MariaDB is the same as those of MySQL. And I highly recommend you migrate to MariaDB if you are using MySQL as your database server.

You can check whether you are using MariaDB or MySQL by executing the following command at the shell prompt:

mysql --version

Sample output:

mysql Ver 15.1 Distrib 10.3.22-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2

As you can see, I’m using MariaDB. Another method to detect whether you have MySQL or MariaDB is to log in to your database server using the MySQL client.

sudo mysql -u root

After logging in, you will see a welcome message:

Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 102
Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1-log Ubuntu 19.10

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

You can see that I’m using MariaDB Server version 10.3.22. If you use MySQL database then the server version will be something like:

8.0.7-MySQL Community Server (GPL)

Now you know what database server you are using, let’s do the backup.

After you log into the database server using the sudo mysql -u root -p command, execute the following command to show all the databases you have on your server. Don’t leave out the semicolon.

show databases;

Sample outputs:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| wordpress          |
+--------------------+

Normally you have four databases. Every MySQL/MariaDB Server includes infomation_schema, mysql, performance_schema databases. The last one is the database for your WordPress Site, which is the only database you need to back up. Enter the exit command to exit your database server.

exit;

Now we use the mysqldump utility to back up the wordpress database.

sudo mysqldump -u root wordpress > wordpress.sql

The above command will back up the wordpress database to a file named wordpress.sql under the current working directory. You can change the backup file name to your liking such as mysite.sql. If you encounter the following error:

mysqldump: Error: Binlogging on server not active

Then you need to enable binary logging by editing your /etc/mysql/my.cnf or /etc/my.cnf config file depending on your Linux distribution.

sudo nano /etc/mysql/my.cnf

or

sudo nano /etc/my.cnf

Put the following text under the [mysqld] section.

log-bin=mysql-bin

Like this:

[mysqld]
 user = mysql
 pid-file = /var/run/mysqld/mysqld.pid
 socket = /var/run/mysqld/mysqld.sock
 port = 3306
 basedir = /usr
 datadir = /var/lib/mysql
 tmpdir = /tmp
 lc-messages-dir = /usr/share/mysql
 skip-external-locking
 log-bin=mysql-bin
 #

Save and close the file. Then restart your database server

sudo systemctl restart mysql

or

sudo systemctl restart mariadb

Now use the above mysqldump command to back up all your WordPress database to a .sql file.

You can also zip the backup file so it won’t take up too much space.

sudo mysqldump -u root wordpress | gzip > wordpress.sql.gz

Backing Up WordPress Files under Webroot

Your WordPress program files, theme files, plugins files and uploaded pictures are all in webroot directory. Your webroot directory could be /var/www/html/ or /usr/share/nginx/html/ or something like that depending on your web server configurations.

For backing up these WordPress files we will use a command-line utility called tar, short of tap archive. Enter the following command at your shell prompt.

sudo tar -cpvzf filename.tar.gz /var/www/html/

The above command has 5 options, where:

  • -c means creating an archive file.
  • -p means preserving permissions of the files that are archived.
  • -v: show verbose information.
  • -z means compressing the archive file using gzip.
  • -f stands for file.

filename.tar.gz is the archive file name and /var/www/html/ means all the files and directories under the webroot directory will be archived and compressed. Your webroot directory may be different so check your web server configuration.

Restoring WordPress Database and Files on the Same Server

Now you know how to back up your WordPress database and files, but it’s useless if you don’t know how to restore them.

Restoring WordPress database

Let’s say your WordPress site has been hacked via a vulnerability in a plugin. If you have a backup of the database, you can easily restore the original state. Enter the following command to import previously backed up database to MySQL/MariaDB database server.

sudo mysql -u root wordpress < wordpress.sql

After that, you can log into your database server and see if all your databases are imported.

Restoring WordPress Files

First, extract the tarball

tar -xzvf filename.tar.gz

Then copy WordPress files to webroot directory. I assume that your web root directory is /var/www/html/.

sudo cp var/www/html/* /var/www/html/ -R

Email Backup Files to Your Inbox

If you want to email your database backup file and WordPress backup file to your inbox, then follow the steps below.

First, install heirloom mailx. Heirloom mailx is a fantastic mail user agent (email client). It supports attachment and can send emails using external SMTP servers such as Gmail. We’re going to send our database backup file and WordPress backup files as attachments using Gmail as the SMTP server.

Installing Heirloom Mailx

On CentOS/RHEL server, execute the following command:

sudo yum install -y mailx

On Fedora server:

sudo dnf install -y mailx

On Debian/Ubuntu server:

sudo apt-get install -y heirloom-mailx

That’s it!

Setting Gmail as External SMTP Server to Relay Emails

Edit mailrc file. On CentOS/RHEL/Fedora server:

sudo vi /etc/mail.rc

on Debian/Ubuntu Server

vi ~/.mail.rc

Put the following text into the file.

set smtp-use-starttls
set ssl-verify=ignore
set smtp=smtp://smtp.gmail.com:587
set smtp-auth=login
set smtp-auth-user=user-account@gmail.com
set smtp-auth-password=user-password
set from="user-account@gmail.com(Your_Name)"

Replace the green texts with your Gmail account credentials. Save and close the file. Now We can now send emails using the mail command like this:

echo "website backed up" | mail -v -a backup.sql -a filename.tar.gz -s "wordpress backed up" [email protected]

The text following echo is the mail content that will be piped into mail command.

  • -v stands for verbose, it will display your connection status with Gmail.
  • -a stands for attachment. you can use multiple -a options to add muptilple attachments to your email.
  • -s means subject.
  • The last argument is the recipient email address, such as [email protected] By the way, you can send email to yourself. That means the From address and To address can be the same. Also you can add multiple recipient email addresses.

CentOS/RHEL/Fedora server needs to add an extra line to mail.rc file. First, download these three files to your server, put it in your home’s .certs directory. If you are using firefox on desktop Linux, then you can also find these files under ~/.mozilla/firefox/<arbitrary-letters>.default directory.

Then add the following line to /etc/mail.rc file.

set nss-config-dir=/home/<username>/.certs/

Save and close the file. Now you can send emails using Gmail as Relay.

Getting Around Gmail’s Attachment File Size Limitation

Gmail limits the sender’s total attachment file size to 25M, although a Gmail account can receive an attachment of 34M. Your database may not get larger very soon, however, WordPress files tends to get larger very quickly.  If your archive file is larger than 25M, you may want to split your archive file into multiple parts and email them one by one.

Splitting the File

For this purpose, we’re going to use the split command. Its syntax is as follows:

split -b 5M -d filename.tar.gz <prefix>

The above command means to split filename.tar.gz into 5 Megabytes size of the file. You can change 5M to something lower that is lower than 25M. <prefix> is the name that will be prepended to the split files.

For example, if I execute the following command:

split -b 5M -d linuxbabe.tar.gz wordpress

I will get the following files.

-rw-rw-r-- 1 user user 15M Nov 21 01:57 linuxbabe.tar.gz
-rw-rw-r-- 1 user user 5.0M Nov 21 13:46 wordpress00
-rw-rw-r-- 1 user user 5.0M Nov 21 13:46 wordpress01
-rw-rw-r-- 1 user user 4.5M Nov 21 13:46 wordpress02

The linuxbabe.tar.gz file is split into three files.  Let’s say your archive file is 40 Megabytes of size. You can use the following command:

split -b 25M -d filename.tar.gz wordpress

to get a file of 25M and another file of 15M. Now you can send those two files to your Gmail account. But you have to use mail command twice to send each of the files, you can’t send both of them as an attachment at once.

How to Join Them Together

When you restore your website you have to join those split files together. We can use the cat command to accomplish this.

cat wordpress00 wordpress01 > wordpress.tar.gz

Automating the process

Yes! You can automate the above processes. Who doesn’t love automation?We will install cron and use it to schedule backup task. Install it with the following commands:

For Debian/Ubuntu server:

sudo apt-get install cron

For CentOS/RHEL:

sudo yum install crontabs

For Fedora server:

sudo dnf install crontabs

If you use systemd, then you need to start it after install.

sudo systemd start crond

Enable start on system boot:

sudo systemd enable crond

Scheduling Backup Task

Enter the following command in terminal:

crontab -e

This will open up the cron table in which we will add tasks. For example, if we want to backup database at 4 am every day, then put the following text into it.

0 4 * * * mysqldump -u root -pyourpassword --all-databases --master-data | gzip > backup.sql.gz

0 4 * * * means every day at 4:00. Replace the green text with your database root password.

Next we will backup out WordPress files in webroot. Add the following text in the next line.

5 4 * * * tar -cpzf filename.tar.gz /var/www/html/

If your web root is not /var/www/html/ but something else like /usr/share/nginx/html, then change it. So we backup wordpress file at 4:05 every day. Then we need to send them as attachements to our email address.

10 4 * * *  echo "website backed up" | mail -a backup.sql.gz -a filename.tar.gz -s "wordpress backed up" [email protected]

The above command will send our database backup and file backup at 4:10 every day. I separate the three tasks in 5 minute interval. If you want them to happen right after the previous one, then you can do the following.

0 4 * * * mysqldump -u root -pyourpassword --all-databases --master-data | gzip > backup.sql.gz && tar -cpzf filename.tar.gz /var/www/html/ && echo "website backed up" | mail -a backup.sql.gz -a filename.tar.gz -s "wordpress backed up" [email protected]

The double ampersand (&&) means executing the next command when the previous command has successfully completed. So you don’t have to wait 5 minute. But this format will make your crontab file a little messy.

If you want to delete the database backup and file backup after it’s been emailed to save space on your server, you can add

15 4 * * * rm backup.sql.gz filename.tar.gz

or just append the rm command using &&.

If you want your cron job to run every hour, you can do:

0 * * * *

or once every two hours

0 */2 * * *

Move Your WordPress Site to a New Server

If the restore process is on your original server, then you are done. Your WordPress site is now running properly as before. But if you transfer your site from your original server to another server, follow the instructions below.

  • First, you need to install LAMP stack or LEMP stack on the new server.
  • Then, you should copy your Apache or Nginx virtual host file and SSL certificate file to the new server. Be sure to test the virtual host file and reload your web server.
  • Next, copy the WordPress files to the new server under the webroot directory.
  • After that, you need to create an empty database in MySQL/MariaDB on the new server, which is described below.

Open the default WordPress configuration file under webroot directory.

sudo nano /var/www/html/wp-config.php

This will open up your wp-config.php file and in that file, you can find the database user you created when you first installed WordPress and the user’s password like the following:

/** The name of the database for WordPress */
 define('DB_NAME', 'database-name');
/** MySQL database username */
 define('DB_USER', 'database-username');
/** MySQL database password */
 define('DB_PASSWORD', 'user-password');

Now log into the database server using the following command:

sudo mysql -u root

Create the database.

create database database-name;

Grant all privileges of WordPress database to the user:

grant all privileges on database-name.* to database-username@localhost identified by 'user-password';

Flush database privileges.

flush privileges;

Exit database server.

exit;

Now copy the backed up SQL file to the new server and restore the database.

sudo mysql -u root wordpress < wordpress.sql

You have successfully transferred your WordPress site to the new server. Change your DNS record and you should see your WordPress site running properly!

Things to Look Out Before Deleting a VPS

I normally do the following things before deleting a VPS that I don’t need anymore. They help me to prevent deleting important software or data without migration.

  • List Let’s Encrypt TLS certificates on the VPS with sudo certbot certificates.
  • List running services on the VPS with sudo netstat -lnptu.
  • Check disk usage with sudo ncdu /. Yes, you need to install the ncdu utility: sudo apt install ncdu.
  • Check if there’s any Cron jobs on the VPS with sudo crontab -l.
  • Check the home directory to see if I have some files there.

Wrapping Up

Congrats! You just backed up your WordPress site using Linux commands and The best part is you can automate the backup process and you don’t have to buy WordPress backup plugin. In addition, your WordPress site will load faster because you just eliminated a plugin from your site.

Rate this tutorial
[Total: 5 Average: 4.8]

One Response to “Back Up and Restore WordPress Site on Linux Server without A Plugin

  • Đỗ Anh Tú
    2 years ago

    Great article, but I think you should have some update.

    Add few more lines into file `/etc/mysql/mysql.conf.d/mysqld.cnf` like this:

    server-id=master-01
    log-bin=mysql-bin
    binlog-format = ‘ROW’

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.


The maximum upload file size: 2 MB.
You can upload: image.