Skip to content

Instantly share code, notes, and snippets.

@simontegelid
Last active September 7, 2023 08:50
Show Gist options
  • Save simontegelid/5fbaa8478327b4f12ec26bed74ae314a to your computer and use it in GitHub Desktop.
Save simontegelid/5fbaa8478327b4f12ec26bed74ae314a to your computer and use it in GitHub Desktop.
A guide for setting up a Raspberry PI Zero W as a backup server, pulling files over SSH with rsync to an external USB HDD on schedule.

Setup SD card

Download Raspberry Pi OS Lite at https://www.raspberrypi.org/software/operating-systems/ and write it to SD card

wget https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2020-12-04/2020-12-02-raspios-buster-armhf-lite.zip
unzip 2020-12-02-raspios-buster-armhf-lite.zip
sudo dd bs=4M if=2020-12-02-raspios-buster-armhf-lite.img of=/dev/sdX status=progress conv=fsync

If you have no monitor available; enable ssh directly from here "SSH can be enabled by placing a file named ssh, without any extension, onto the boot partition of the SD card". More info at https://www.raspberrypi.org/documentation/remote-access/ssh/

Also, enable wifi by creating a wpa_supplicant.conf and placing it in the same spot as the ssh file above. See below for contents. More info at https://www.raspberrypi.org/documentation/configuration/wireless/headless.md

While at it, you might want to change the /etc/hostname to something else than "raspberrypi" in the rootfs mount.

Setup the Raspberry PI

Rename default user and change its password

Login with pi/raspberry and enable root password

sudo passwd root

If you're already on SSH, you need to enable root access over SSH now. Add PermitRootLogin yes to /etc/ssh/sshd_config. Do not forget to remove it when done.

then logout from pi user:

logout

Now, login as root with its new password rename user "pi" to "newname" and change home dir name:

usermod -l newname -m -d /home/newname pi
groupmod -n newname pi

Then logout from root

logout

Change the password(!)

passwd

Confirm that the newuser still has sudo rights

sudo echo "Great success!"

Lock root account again:

sudo passwd -l root

If you enabled root access over SSH, this is the time to remove it from /etc/ssh/sshd_config.

Setup remote access

If you enabled ssh and wifi with the boot partition thing before booting, then skip this section.

Enable ssh

sudo systemctl enable ssh
sudo systemctl start ssh

Enable wifi connection

sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

Contents of /etc/wpa_supplicant/wpa_supplicant.conf:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=SE # https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements

network={
	ssid="SSID"
	psk="PASSWORD"
}

Create SSH keypair

To enable SSH access to the devices you will pull files from, you will need a SSH keypair.

ssh-keygen -t id25519

Append the public key ~/.ssh/id_ed25519.pub to .ssh/authorized_keys on the devices you want to backup from.

Setup external backup disk

Plug in an USB HDD and create a mount point, eg.:

sudo mkdir /mnt/extdisk

Get the UUID of the disk:

ls -l /dev/disk/by-uuid

Automount the disk

sudo nano /etc/fstab

Append something like to the end of /etc/fstab: UUID=251ee046-ee3d-4008-b41b-58f5c3726a32 /mnt/extdisk ext4 noexec,rw,user,errors=remount-ro 0 2

Mount the disk with

sudo mount -a

Schedule backup script

Download backup.sh and make it executable

wget https://gist.github.com/simontegelid/5fbaa8478327b4f12ec26bed74ae314a/raw/ec916a42d6649c834fd1273635896bf24d9265e5/backup.sh
chmod +x backup.sh

Modify(!!!) backup.sh and run it manually to verify that it does what you want. There are as many backup scripts as there are people on earth, so you'll want to modify yours too.

When you are satisfied, schedule it with cron

crontab -e

To run at midnight every day, append this line:

  0 0  *   *   *     /path/to/backup.sh

Let the USB drive sleep when inactive

Download setup-hd-idle.sh and make it executable

wget https://gist.github.com/simontegelid/5fbaa8478327b4f12ec26bed74ae314a/raw/ec916a42d6649c834fd1273635896bf24d9265e5/setup-hd-idle.sh
chmod +x setup-hd-idle.sh
./setup-hd-idle.sh
#!/bin/bash
# Backup script heavily influenced by
# http://www.mikerubel.org/computers/rsync_snapshots/#Incremental However, it
# is not deleting anything, just creating a new snapshot on each execution. The
# magic relies in the --link-dest flag to rsync which creates hard links to the
# folder of the last backup run and then synchronizes only the differences.
set -e
set -x
BACKUP_MNT=/mnt/extdisk # Mount point of your external disk
BACKUP_ROOT=${BACKUP_MNT}/backup
BACKUP_SOURCES=(
"user@hostcomputer.local:Documents"
"user@hostcomputer.local:Pictures"
)
if grep -qs "${BACKUP_MNT} " /proc/mounts; then
echo "${BACKUP_MNT} mounted"
else
echo "${BACKUP_MNT} seems not mounted. Abort"
exit 1
fi
PREV_FILE=${BACKUP_ROOT}/latest.txt
NOW_STAMP=`date +"%F_%H-%M-%S"`
EXCLUDE_LIST=${BACKUP_ROOT}/rsync-exclude.txt
# For first time use; create files and dirs if not present:
if [ ! -d ${BACKUP_ROOT} ]; then
mkdir -p ${BACKUP_ROOT}
fi
touch ${EXCLUDE_LIST}
TARGET_DIR_BASE=${BACKUP_ROOT}/backup
NOW_TARGET_DIR=${TARGET_DIR_BASE}-${NOW_STAMP}
LOG_FILE=${NOW_TARGET_DIR}.log
if [ ! -e ${PREV_FILE} ]; then
echo "First run. Create dummy folder for --link-dest"
mkdir -p ${BACKUP_ROOT}/delete-me
PREV_TARGET_DIR=${BACKUP_ROOT}/delete-me
else
PREV_TARGET_DIR=${TARGET_DIR_BASE}-`cat ${PREV_FILE}`
fi
if [ ! -d "${PREV_TARGET_DIR}" ]; then
echo "${PREV_TARGET_DIR} does not exist. Abort"
exit 1
fi
if [ -d "${NOW_TARGET_DIR}" ]; then
echo "${NOW_TARGET_DIR} already exists. Abort"
exit 1
fi
rsync -avhR \
--partial \
--progress \
--delete \
--stats \
--log-file=${LOG_FILE} \
--exclude-from ${EXCLUDE_LIST} \
--link-dest="${PREV_TARGET_DIR}" \
-e 'ssh' ${BACKUP_SOURCES[@]} "${NOW_TARGET_DIR}"
echo ${NOW_STAMP} > ${PREV_FILE}
cp ${LOG_FILE} ~/last-backup.log
df -h ${BACKUP_ROOT} >> ~/last-backup.log
if [ -d "${BACKUP_ROOT}/delete-me" ]; then
echo "Clean up after first run"
rmdir ${BACKUP_ROOT}/delete-me
else
#!/bin/bash
set -e
set -x
HD_IDLE_VERSION=hd-idle-1.05
sudo apt-get update
sudo apt-get install -y debhelper
cd
mkdir -p hd-idle-install
cd hd-idle-install
wget http://sourceforge.net/projects/hd-idle/files/${HD_IDLE_VERSION}.tgz
tar -xvf ${HD_IDLE_VERSION}.tgz
cd hd-idle
dpkg-buildpackage -rfakeroot || true # dpkg-buildpackage might fail due to failed signing. Ignore that.
sudo dpkg -i ../hd-idle_*.deb
sudo apt-get remove debhelper -y
sudo apt-get autoremove -y
sudo apt-get clean -y
sudo rm -rf /var/lib/apt/lists/*
cd
rm -rf hd-idle-install
sudo sed -i 's/START_HD_IDLE=false/START_HD_IDLE=true/g' /etc/default/hd-idle
sudo systemctl restart hd-idle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment