Przejdź do polskiej wersji tego wpisu / Go to polish version of this post
In my previous posts, I described how to install the YunoHost environment and how to run the first application – WriteFreely instance on it. The next natural step that any reasonable admin would take is to create a system that will first create backups of the running infrastructure and secondly secure those backups in case the server on which it is all running suddenly decides it’s a good time to cause problems.
To begin with, let’s define some working names for the two machines that I will be using in this post:
- YunoHost server – the machine on which YunoHost is installed and whose backup we will create,
- backup server – any other Linux machine, it can be a computer, a home server, or a VPS, on which we will store the created backups.
Tasks to be performed on YunoHost server
Let’s start by connecting to the YunoHost server via SSH. Now we will create a recurring task that will automatically perform two backups a day. One of them will be created at 5:00 and the other at 15:00. The backup task must be executed with root privileges, so first we need to switch to the root user.
sudo suWe will be asked to provide the password for our YunoHost administrator account. We open the Cron task table, or rather create it, because if it has not been used before, it does not exist by default:
crontab -eA short configurator will appear, in which we need to specify which text editor we want to use. The default for me is nano, so I choose option 1. /bin/nano, which means I press 1 and ENTER. Our table will be opened, at the beginning of which there will be a fairly long comment. We can completely delete this text or simply skip it and go to the end of the file. The crontab table works in such a way that one task is one line, which consists of a formula defining the frequency of execution and the command, program or path to the script that is to be executed. The interval formula notation consists of five parts, in order – minute, hour, day of the month, month, day of the week. A very helpful tool here is the Crontab Guru website. For our task, the command in the Cron task table should look like this:
0 5,15 * * * yunohost backup createThis notation means that the yunohost backup create command (built-in command in YunoHost for calling backup creation) will be executed at minute 0, hours 5 and 15, every day, every month, regardless of the day of the week. To exit the editor nano and close the table as usual (ctrl+x, y, ENTER).
It is very important to have synchronized time zones on both servers, so for safety, let’s set the appropriate time zone for Poland:
timedatectl set-timezone Europe/WarsawIn addition, after each change in the Cron task table, remember to rebuild the process and thus implement the changes:
service cron reloadOn the YunoHost server, we still need to enable login using SSH keys, because without it, it will be difficult for us to connect to the backups from the server level. I described how to do this here.
That’s all we need to do here. It’s time to move on to the machine that will be our space for storing created backups.
Tasks to perform on the backup server
Now let’s switch to the backup server. First of all, let’s also set the appropriate time zone for Poland here:
timedatectl set-timezone Europe/WarsawNow let’s configure the SSH connection to the server with YunoHost. To do this, in the /home/$USER/.ssh/ folder, create a file named yunohost and paste the SSH private key to the YunoHost server into it:
nano /home/$USER/.ssh/yunohostSave the file and exit it. Let’s give it the appropriate permissions:
chmod 600 /home/$USER/.ssh/yunohostLet’s add this private key to our keychain:
ssh-add /home/$USER/.ssh/yunohostFrom this point on, we should be able to connect via SSH to the YunoHost server from the backup server, so let’s test it with the following command formatted to your needs:
ssh <admin_username>@<yunohost_server_ip>
If we did everything correctly, we should not be prompted for a password and should be able to access the YunoHost server shell without any problems. Let’s terminate the SSH connection and return back to the backup server using the following command:
exitTo download backup copies from a YunoHost server and transfer them to a backup server, we will use the scp tool, whose name stands for Secure Copy. It allows for simple and secure data transfer between servers. The scp syntax for our use case is as follows:
scp <admin_name>@<yunohost_server_ip>:<what_to_copy> <where_to_copy>
We now know how to acquire files from one server and transfer them to another. The next step is to consider the strategy for doing so. Let us remind ourselves that a backup task is scheduled to run on the YunoHost server every day at 5:00 AM and 3:00 PM. Creating a backup takes less than a minute, but as our YunoHost environment grows, this time may increase. Therefore, for safety, let us assume that we will download the backup copy one hour after it is made, i.e., at 6:00 AM and 4:00 PM.
We now need to understand how YunoHost manages backup copies. The creators have provided a ready-made command for creating backups from the terminal:
yunohost backup createThis command must be executed with administrator privileges, either directly as the root user or preceded by the sudo phrase. This command syntax will use the default settings of this tool, so a backup of everything (system configuration, user data, applications, etc.) will be created and saved in the folder:
/home/yunohost.backup/archives/The name under which the backup will be saved has the following format:
<year><month><day>–<hour><minute><second>.tar
So, if the backup is created on July 8, 2023 at 12:34:56, its name will be 20230708-123456.tar. Why am I focusing on this so much? It is important in the context of how we will determine which file should be downloaded, which backup is the latest and should be retrieved to occupy the space next to the backups already downloaded to the backup server. Note that by making two copies a day, I will have two files every day, part of the name before the hyphen will be the same because it is the date. Therefore, they can only be distinguished by the second part of the name (after the hyphen), that is, based on the creation time. Note that I intentionally make two copies, the first one at 5:00, so after the hyphen in the name, it will have 0 (zero), and the second one at 15:00, so after the hyphen in the name, it will have 1 (one). In this way, the backup named 20230708-0* is a morning copy made on July 8, 2023, and the backup named 20230708-1* is an afternoon copy. The use of the * sign in Bash means that the remaining part of the name can be anything.
Now that we have everything planned out, let’s get to work. Let’s start by creating a place (folder) on the backup server where we will store downloaded backup copies.
mkdir /home/$USER/yunohost_backupsNow, let’s open (or create if it does not yet exist) the Cron task table on this server:
crontab -eTo add these two lines at the end of an open text file:
0 6 * * * scp admin@AAA.BBB.CCC.DDD:/home/yunohost.backup/archives/$(date +"%Y%m%d")-0* /home/$USER/yunohost_backups/ 0 16 * * * scp admin@AAA.BBB.CCC.DDD:/home/yunohost.backup/archives/$(date +"%Y%m%d")-1* /home/$USER/yunohost_backups/Just remember to replace the phrase admin with your YunoHost administrator’s username and the phrase AAA.BBB.CCC.DDD with your YunoHost server’s IP address. Save the file and exit it. The above two lines do almost the same thing but run at two different times (every day at 6:00 and 16:00). In both cases, scp connects to the YunoHost server, finds the file whose name starts with today’s date, followed by a hyphen and in the case of the first line (running at 6:00) followed by 0* (zero and any other characters), and in the case of the second line (running at 16:00) followed by 1* (one and any other characters). At the end of each line, there is also an indication of the path to the backup folder on the server.
Just like before, after modifying the Cron tasks, we need to reload the service:
service cron reloadAs usual, sometimes things don’t work…
In my case, as a server for backups, I chose Mikrus and encountered an interesting problem. After some time, Mikrus completely forgets my private key to the server with YunoHost. And as if that wasn’t enough, when I tried to add it again with the ssh-add command, I received the following message:
Could not open a connection to your authentication agent.This is a known problem when trying to use ssh-add when ssh-agent is not working as a process. It turns out that the ssh-agent process is being killed for some reason by my server… Is this an unsolvable problem? Of course not! However, some modifications to the actions I presented are necessary.
First of all, I need to write two scripts that will replace those two tasks from the Cron table. These scripts will:
- Started the ssh-agent,
- Added my private key to the Yunohost server keychain,
- Executed the command to copy the backup file using scp as it was done previously.
First, we create the first script that will run cyclically at 6:00:
nano /home/$USER/yunohost_backup1.shLet’s paste the following content into it (remember to modify the phrases admin and AAA.BBB.CCC.DDD accordingly):
#!/bin/bash eval "$(ssh-agent)" ssh-add /home/$USER/.ssh/yunohost scp admin@AAA.BBB.CCC.DDD:/home/yunohost.backup/archives/$(date +"%Y%m%d")-0* /home/$USER/yunohost_backups/Then, we create the second script:
nano /home/$USER/yunohost_backup2.shLet’s paste the following content into it (remember to modify the phrases admin and AAA.BBB.CCC.DDD accordingly):
#!/bin/bash eval "$(ssh-agent)" ssh-add /home/$USER/.ssh/yunohost scp admin@AAA.BBB.CCC.DDD:/home/yunohost.backup/archives/$(date +"%Y%m%d")-1* /home/$USER/yunohost_backups/Now we need to make both scripts executable (give them permission to execute):
sudo chmod +x /home/$USER/yunohost_backup1.sh /home/$USER/yunohost_backup2.shFinally, we need to modify the Cron task table:
crontab -eInstead of the previously set two lines, we paste the following:
0 6 * * * /home/$USER/yunohost_backup1.sh 0 16 * * * /home/$USER/yunohost_backup2.shThis modified way of operation solves the problem with ssh-agent.
Alternative Solutions
It must be admitted that the solution presented by me is not the most sophisticated one. However, it shows that there are many ways to achieve the same effect. If someone is looking for a different solution, YunoHost in its documentation mentions three applications that can be used: BorgBackup, Restic, and Archivist. I tried to use the latter, but it seems to be currently broken and simply not working… Among other things, that’s why I decided to set everything up from scratch, without relying on external applications. However, I recommend reading the YunoHost documentation and deciding for yourself which option seems best for you.