gif gif

The interesting corner

gif gif

Automating backups to an external node with qvalet, rsync and cron

Introduction

I have quite some services running on Ymir, and I want to back them up automatically to my backup VM that's running in RAID5, so I can be sure my data is secure and I'll be protected against data loss (except when my apartment burns down, but we will hope that won't happen (ㆆ _ ㆆ)). Sending the actual data is a perfect job for rsync, and automating it is what cron is best for.

The only kind-of challenge with this is: my backups VM is always off. I only turn it on when I want to write a backup to it. So I needed a way to programatically turn it on and off before and after performing a backup. Luckily, you can turn VMs on and off with the qm start and qm shutdown commands proxmox offers.

However, I didn't really know about a good way to send commands from one node to the other. After some searching, I came across qvalet. It's a pretty small program that runs on a node and can receive HTTP commands from which it can execute other commands. This is perfect for my use case.

Setting up qvalet

I set up qvalet to run on my proxmox host, and it listens on two endpoints: startbackup and stopbackup. each endpoint just calls a script to perform the necessary action: start_backup.sh to start and stop_backup.sh to stop the VM. The whole config.yaml looks like this:

          
debug: false
port: <your port>
listeners:
  /startbackup:
    command: bash
    args:
      - -c
      - "cd /root/qvalet; ./start_backup.sh"
    return: output

  /stopbackup:
    command: bash
    args:
      - -c
      - "cd /root/qvalet; ./stop_backup.sh"
    return: output
          
        

The endpoints can then be called by curling the host, port and endpoint: curl http://localhost:port/startbackup.

To make sure the VM is not shut off by one process while still receiving a backup from the other, I added a little counter that gets updated every time the start and stop endpoints get called, and this counter is written to the backups_amount file. The start_backup.sh file looks like this:

          
#!/bin/bash

value=$(<backups_amount)
newvalue=$((value+1))
if [[ $newvalue -lt 1 ]]
then
        newvalue=1
fi
echo "Amount of running backups: $newvalue"
echo $newvalue > backups_amount
qm start vm-id
qm list | grep vm-id | awk '{print $3}'
          
        

the stop_backup.sh file looks like this:

          
#!/bin/bash

value=$(<backups_amount)
newvalue=$((value-1))

if [[ $newvalue -lt 0 ]]
then
        newvalue=0
fi

echo $newvalue > backups_amount
if [[ $newvalue -gt 0 ]]
then
        echo "A backup is still running"
else
        echo "Stopping VM"
        qm shutdown vm-id
        qm list | grep vm-id | awk '{print $3}'
fi
          
        

You can replace the vm-id with the ID of the VM you want to start/stop.