encryption

Automated encrypted incremental backups with restic to a Synology mount

Synology

The Synology devices are easy to setup but the backup applications are not that great. In addition, Synology does not offer SSH key based authentication for non-privileged accounts out of the box. After each upgrade the SSH key setup might be gone and it always feels like a hack.

The following text describes how to setup painless, automated, encrypted, incremental backups via CIFS using Restic. The script makes use of passwords stored in the gnome keyring and thus can mount a CIFS aka Samba share without having to store the Synology user password in the /etc/fstab file or in the clear in a local file.

Restic

To quote the restic web site

restic is a program that does backups right. The design goals are: Easy: Doing backups should be a frictionless process, otherwise you are tempted to skip it. Restic should be easy to configure and use, so that in the unlikely event of a data loss you can just restore it. Likewise, restoring data should not be complicated. Fast: Backing up your data with restic should only be limited by your network or hard disk bandwidth so that you can backup your files every day. Nobody does backups if it takes too much time. Restoring backups should only transfer data that is needed for the files that are to be restored, so that this process is also fast. Verifiable: Much more important than backup is restore, so restic enables you to easily verify that all data can be restored. Secure: Restic uses cryptography to guarantee confidentiality and integrity of your data. The location where the backup data is stored is assumed to be an untrusted environment (e.g. a shared space where others like system administrators are able to access your backups). Restic is built to secure your data against such attackers, by encrypting it with AES-256 in counter mode and authenticating it using Poly1305-AES. Efficient: With the growth of data, additional snapshots should only take the storage of the actual increment. Even more, duplicate data should be de-duplicated before it is actually written to the storage backend to save precious backup space. Free: restic is free software and licensed under the BSD 2-Clause License and actively developed on GitHub.

The pre-requisits

We need the following things beforewe can start the backup:

  • A Synology user account
  • Restic installed on the local machine
  • The username and password stored in the Gnome keyring using the secret-tool
  • An initialized restic repository
  • The repository password stored in the Gnome key ring

The prerequisits are rather easy to setup. We need to add the username and password once to the Gnome keyring. We can use a label and some attributes. The attributes are used for finding the username and password again in the key ring.

secret-tool store --label="Synology username" synology username

Our user should also be able to mount the remote folder. One wayt to achieve this is by allowing the user to use sudo without a password for the mount and unmount command. This can be done by adding the following line to the sudoers file:

stefan ALL=(ALL) NOPASSWD: /usr/bin/mount, /usr/bin/umount, /usr/bin/mkdir, /usr/bin/chown

The restic commands are pretty self explainatory.

restic -r ${SYNOLOGY_BACKUP_PATH} backup \
      ~/git \
      ~/.aliases \
      ~/.zshrc \
      ~/.bashrc \
      ~/.vimrc \
      ~/.ssh

In order to be mindfiul about the used storage, we will prune snapshots after a while.

 # Prune older snapshots but keep 2 pe day, 7 days and 4 weeks
    restic -r ${SYNOLOGY_BACKUP_PATH} \
      forget \
      --prune \
      --keep-hourly 2 \
      --keep-daily 7 \
      --keep-weekly 4

The automation part is done by a classic cron job which runs for instance every 4 hours.

The prerequisits are described in the comments of the script below.

The backup script

The following script will backup the folders and files listed in the backup command.

#!/usr/bin/env bash
# exit when any command fails
set -e

# The following script assumes that you initialized the directory $SYNOLOGY_BACKUP_PATH
# on the Synology as a new restic repository:
# restic -r ${SYNOLOGY_BACKUP_PATH} init
# Make sure to add the username and the password first to the key ring
# secret-tool store --label="Synology username" synology username
# secret-tool store --label="Synology password" synology password
# Also add the restic password to the keyring
# secret-tool store --label="Restic password" restic password
# Add the mount and umount command without sudo password
# by using sudo visudo and add this line (adapt username)
# sproell ALL=(ALL) NOPASSWD: /usr/bin/mount, /usr/bin/umount, /usr/bin/mkdir, /usr/bin/chown
# Add a cron job which runs every 4 hours (for example)
# MAILTO="stefan.proell@cropster.com"
# 0 */4 * * * DISPLAY=:0 /home/sproell/scripts/automatic-restic-backup.sh

NAS_IP=192.168.1.10

BACKUP_MOUNT_TARGET=/media/${USER}/cropster-synology-backup
SYNOLOGY_PATH=/home
SYNOLOGY_BACKUP_PATH="${BACKUP_MOUNT_TARGET}/2020-restic-backups"
LOCAL_USER_ID=$( id -u )
LOCAL_GROUP_ID=$( id -g )

isPathMounted() { findmnt -rno TARGET "$1" >/dev/null;} 

runResticBackup()
{
  # Store the repository password in the environment variable
  RESTIC_PASSWORD=$( secret-tool lookup restic password )
  export RESTIC_PASSWORD

  # Check of the remote directory exists, otherwise create it
  [ -d ${SYNOLOGY_BACKUP_PATH} ] ||  ( \
    sudo mkdir ${SYNOLOGY_BACKUP_PATH};\
    sudo chown -R ${LOCAL_USER_ID}:${LOCAL_GROUP_ID} \
    ${SYNOLOGY_BACKUP_PATH})

  restic -r ${SYNOLOGY_BACKUP_PATH} snapshots
  restic -r ${SYNOLOGY_BACKUP_PATH} backup \
    ~/git \
    ~/.aliases \
    ~/.zshrc \
    ~/.bashrc \
    ~/.vimrc \
    ~/.ssh
  # Prune older snapshots but keep 2 pe day, 7 days and 4 weeks
  restic -r ${SYNOLOGY_BACKUP_PATH} \
    forget \
    --prune \
    --keep-hourly 2 \
    --keep-daily 7 \
    --keep-weekly 4
  sudo umount ${BACKUP_MOUNT_TARGET}
  unset RESTIC_PASSWORD
  unset SYNO_PASS
}

echo "Current date: $( date )"
# Can I ping the nas?
echo "Pinging the NAS 10 times"
ping -c 10 $NAS_IP > /dev/null && echo "up... proceeding" || ( echo "NAS down.";exit 1)


# Get username and password from key chain
SYNO_USER=$( secret-tool lookup synology username )
SYNO_PASS=$( secret-tool lookup synology password )

if isPathMounted "${BACKUP_MOUNT_TARGET}";
  then 
    echo "${BACKUP_MOUNT_TARGET} is mounted"   
    
   else 
   # Check if the directory exists locally, otherwise create it
    [ -d ${BACKUP_MOUNT_TARGET} ] ||  sudo mkdir ${BACKUP_MOUNT_TARGET}
    sudo mount -t cifs \
      -o username=${SYNO_USER},password="${SYNO_PASS}",vers=2.0,uid=${LOCAL_USER_ID},gid=${LOCAL_GROUP_ID},noauto,user \
      "//192.168.1.10${SYNOLOGY_PATH}/" \
      "${BACKUP_MOUNT_TARGET}"
fi

runResticBackup

if isPathMounted "${BACKUP_MOUNT_TARGET}";
  then
    sudo umount ${BACKUP_MOUNT_TARGET}
fi

A MySQL 5.7 Cluster Based on Ubuntu 16.04 LTS – Part 2

In a recent article, I described how to setup a basic MySQL Cluster with two data nodes and a combined SQL and management node. In this article, I am going to highlight a hew more things and we are going to adapt the cluster a little bit.

Using Hostnames

For making our lives easier, we can use hostnames which are easier to remember than IP addresses. Hostnames can be specified for each VM in the file /etc/hosts. For each request to the hostname, the operating system will lookup the corresponding IP address. We need to change this file on all three nodes to the following example:

Encrypt a USB Drive (or any other partition) Using LUKS

Did you ever want to feel like secret agent or do you really need to transport and exchange sensitive data? Encrypting your data is not much effort and can be used to protect a pen drive or any partition and the data on it from unauthorized access. In the following example you see how to create an encrypted partition on a disk. Note two things: If you accidentally encrypt the wrong partition, the data is lost. For ever. So be careful when entering the commands below. Secondly, the method shown below only protects the data at rest. As soon as you decrypt and mount the device, the data can be read from everyone else if you do not use correct permissions.

Preparation

Prepare a mount point for your data and change ownership.

# Create a mount point
sudo mkdir /media/cryptoUSB
# Set permissions for the owner
sudo chown stefan:stefan /media/cryptoUSB

Create an Encrypted Device

Encrypt the device with LUKS. Note that all data on the partition will be overwritten during this process.

# Create encrypted device 
sudo cryptsetup --verify-passphrase luksFormat /dev/sdX -c aes -s 256 -h sha256

# From the man page:
       --cipher, -c 
              Set the cipher specification string.
       --key-size, -s 
              Sets  key  size in bits. The argument has to be a multiple of 8.
              The possible key-sizes are limited by the cipher and mode used.
       --verify-passphrase, -y
              When interactively asking for a passphrase, ask for it twice and
              complain  if  both  inputs do not match.
       --hash, -h 
              Specifies the passphrase hash for open (for  plain  and  loopaes
              device types).

# Open the Device
sudo cryptsetup luksOpen /dev/sdX cryptoUSB
# Create a file system (ext3)
sudo mkfs -t ext3 -m 1 -O dir_index,filetype,sparse_super /dev/mapper/cryptoUSB
# Add a label
sudo tune2fs -L Crypto-USB /dev/mapper/cryptoUSB
# Close the devicesudo cryptsetup luksClose cryptoUSB

Usage

The usage is pretty simple. With a GUI you will be prompted for decrypting the device. At the command line, use the following commads to open and decrypt the device.

# Open the Device
sudo cryptsetup luksOpen /dev/sdcX cryptoUSB
# Mount it
sudo mount /dev/mapper/cryptoUSB /media/cryptoUSB

When you are finished with your secret work, unmount and close the device properly.

sudo umount /media/cryptoUSB 
sudo cryptsetup luksClose cryptoUSB