I was tired of my SD cards corrupting on my Raspberry Pis and rebuilding the system from an old, out-of-date backup image, so here is a homemade backup strategy for my backup images.
Each machine has a user called backupper
and each backupper user has the ability to copy disk images to each other's /backupper/backups
directory. The computers do the exact same thing to each other, but the opposite.
backupper@computer_tina
creates an encrypted, compressed disk image of itself and securely sends the file tobackupper@computer_okie:/home/backupper/backups/computer_tina
backupper@computer_okie
creates an encrypted, compressed disk image of itself and securely sends the file tobackupper@computer_tina:/home/backupper/backups/computer_okie
My head hurts and my eyes are cross.
If you want, you can use borg backup to send the images to a remote borg repository. You could use borg to back up your files, too, but I like to have a Raspberry Pi image lying around with all my configurations saved so I don't have to go through that pain when the card corrupts or I want to try something new on another machine. With this strategy, you can backup your images and use a borg repos to backup the directory with those images.
Do each of these commands in both machines. There might be some cd
s and such missing in some places (sorry!), so do your best to fill in the gaps. It's easiest to do the same command, step-by-step, together, in each machine, as you go. Just open two terminals and copy/paste. I wrote these commands down so I won't forget them, but decided to share. Let me know if you get stuck and maybe I can help.
Create a backupper
user with a home directory:
sudo useradd -m backupper
Give backupper a password:
sudo passwd backupper
Login with backupper and cd
into backupper's home directory
su backupper
cd ~/backupper/
Try and use sudo with backupper. You should get a permission denied error.
sudo less /etc/shadow
Create a directory for your backups:
cd backupper && mkdir backups/self && mkdir backups/$remote_host
touch .backup.sh
This should create a a directory at /backupper/backups/self
and /backupper/backups/$remote_host
.
/backupper/backups/$remote_host
is where the images from your other computer friend will live. ~/self
can be where you save the local machine's image, if you want. You can name these directories whatever you want or even hide them somewhere, just change the names in the script — we'll come back and add code to .backup.sh
later.
Gotta swap public keys between the two backupper users. This part is kinda tricky, so pay attention to what you're doing. Digital Ocean has some good information if you get stuck here.
An important thing to know: you need to be logged into to both backupper users when you create the keys so that the correct users are owners of the ~/.ssh
code. I learned this the hard way.
You should still be logged into your backupper users. Create keys with each backupper user:
ssh-keygen -t rsa
Print the public key for backupper@local and copy it to your clipboard:
cd backupper/.ssh
cat id_rsa.pub
Add the public key to backupper@$remote_host:
echo "$key_from_clipboard" > authorized_keys
Make sure the keys match for either set of keys. Compare the authorized keys in the remote host:
# remote host
cat authorized_keys
# client -- should match the remote host's authorized keys
cat id_rsa.pub
backupper needs to be added to the sshusers
group:
sudo usermod -a -G sshusers backupper
Restart ssh service:
sudo systemctl reload sshd.service
If you want to really lock down, you can limit what a ssh public key can do or access.
Logout of backupper with exit
. cd
into the backupper/backups
directory.
With the superuser, only give the script owner (backupper) read and execute permissions:
sudo chmod 0500 .backup.sh
Confirm that the backupper user can't write to the script. Other users can't read the script. A superuser can read, write, and execute.
Edit the sudo file with a superuser:
sudo visudo
Add these lines to the file:
# blacklist everything
backupper ALL=(ALL) !ALL
# whitelist only what you need
backupper ALL=NOPASSWD: /bin/dd
Add this code to backupper/backups/.backup.sh
. It's not much code and you can probably take it to a better place if you tried.
local_backup_path=/home/backupper/backups/self
local_backup_target=$local_backup_path/$HOSTNAME.$(date +%d%m%Y).img.gz
remote_backup_target=backupper@$remote_backup_host:~/backups/$HOSTNAME
# backup
sudo dd if=/dev/mmcblk0 conv=sync,noerror status=progress | openssl aes-192-cbc -salt -e -pass "pass:password" | gzip -9 -c > $local_backup_target
# copy to remote hosts
scp $local_backup_target $remote_backup_target
# delete your local image, if you want.
# you should also figure out a way so that
# the remote host isn't full of your images
rm $local_backup_target
Make sure you're logged in as a backupper user to run it:
./backups/backup.sh
Watch the status of the dd
command:
watch -n 10 ls -alh
This can take a long time. You should have a backup in your remote host eventually. For initial testing, you might want to halt this process and then comment out line with the dd
command, so you can test the scp
. If your ssh
is properly configured, then this should work, but you might have some headaches here.
Let me know how I can improve this, particularly the script that does the image backup. And if anybody actually knows how to use linux like a sysadmin would professionally, please let me know ways in which this could be improved or go wrong or if I'm doing anything counterintutively.
If you have any issues, good luck. Your pain points might be ssh
, backupper
's user permissions, copying the image with dd
, scp
, etc. Pick a part each piece and figure out what is and is not working, then figure out why that part is not working.
I'm a linux noob, especially with users and permissions, so here are some bash ingredients that I kept nearby while working on this.
list all users
less /etc/passwd
delete user
sudo userdel backupper
see user's groups
groups
ssh config
sudo nano /etc/ssh/sshd_config
ssh logs
tail -n 500 /var/log/auth.log | grep 'sshd'
- You're gonna need to delete old backups somehow
- Limit what an SSH user can do within the
backupper
user
- [similar to what i'm doing](https://www.it-react.com/index.php/2020/02/02/backup-your-raspberry-pi-remotely/
- a different approach and something to try next time
- where most of the code came from
- Auto Pi Backup
- some linux user basic commands
- https://unix.stackexchange.com/questions/107541/add-ssh-user-with-minimum-rights-for-backup
- scp privilege escalation
- https://www.digitalocean.com/docs/droplets/resources/troubleshooting-ssh/authentication/#fixing-key-permissions-and-ownership
create this script to run in the backup directory