Add steps for restoring backups
This commit is contained in:
parent
e2ec962f01
commit
16ba4192a0
1 changed files with 121 additions and 5 deletions
126
README.md
126
README.md
|
|
@ -1,6 +1,22 @@
|
||||||
# Raspberry Pi IaC
|
# Raspberry Pi IaC
|
||||||
Contains the Infrastructure as Code files which are used for provisioning my in house Raspberry Pi.
|
Contains the Infrastructure as Code files which are used for provisioning my in house Raspberry Pi.
|
||||||
|
|
||||||
|
- [Raspberry Pi IaC](#raspberry-pi-iac)
|
||||||
|
- [Prerequisites](#prerequisites)
|
||||||
|
- [Ansible control node prerequisites](#ansible-control-node-prerequisites)
|
||||||
|
- [Environment prerequisites](#environment-prerequisites)
|
||||||
|
- [Raspberry Pi preparation](#raspberry-pi-preparation)
|
||||||
|
- [Provisioning](#provisioning)
|
||||||
|
- [Overview of installed software](#overview-of-installed-software)
|
||||||
|
- [SSH with ZSH](#ssh-with-zsh)
|
||||||
|
- [Other](#other)
|
||||||
|
- [Reinstalling the Pi](#reinstalling-the-pi)
|
||||||
|
- [The external Kingston drive](#the-external-kingston-drive)
|
||||||
|
- [Debugging users other than the main user](#debugging-users-other-than-the-main-user)
|
||||||
|
- [Manually restoring a backup](#manually-restoring-a-backup)
|
||||||
|
- [Restoring the database content](#restoring-the-database-content)
|
||||||
|
- [Restoring docker backups](#restoring-docker-backups)
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
The files within this repository should be run on a computer with Ansible installed which is only supported on MacOS and Linux systems. For Windows it can be run within a WSL distro (see [this guide](https://code.visualstudio.com/docs/remote/wsl-tutorial) on how to set this up, make sure the repository is checked out on the WSL distribution itself).
|
The files within this repository should be run on a computer with Ansible installed which is only supported on MacOS and Linux systems. For Windows it can be run within a WSL distro (see [this guide](https://code.visualstudio.com/docs/remote/wsl-tutorial) on how to set this up, make sure the repository is checked out on the WSL distribution itself).
|
||||||
|
|
||||||
|
|
@ -29,17 +45,17 @@ The Raspberry Pi IaC code contained within this repository provisions the Raspbe
|
||||||
1. [A prepared Raspberry Pi]((#raspberry-pi-preperation)).
|
1. [A prepared Raspberry Pi]((#raspberry-pi-preperation)).
|
||||||
3. [Cloudflare](https://dash.cloudflare.com/login) should be setup for managing the domain records of *kleinendorst.info*.
|
3. [Cloudflare](https://dash.cloudflare.com/login) should be setup for managing the domain records of *kleinendorst.info*.
|
||||||
|
|
||||||
### Raspberry Pi preperation
|
### Raspberry Pi preparation
|
||||||
The Raspberry Pi should be installed and running with reachable SSH from the network.
|
The Raspberry Pi should be installed and running with reachable SSH from the network.
|
||||||
|
|
||||||
1. Setup its MicroSD card using the Raspberry Pi Imager ([download](https://www.raspberrypi.com/software/)). For **CHOOSE OS** select the : **Raspberry Pi OS (other)** > **Raspberry Pi OS Lite (64-bit)** option.
|
1. Setup its MicroSD card using the Raspberry Pi Imager ([download](https://www.raspberrypi.com/software/)). For **CHOOSE OS** select the : **Raspberry Pi OS (other)** > **Raspberry Pi OS Lite (64-bit)** option.
|
||||||
2. When asked: **Would you like to apply OS customisation settings?** select **EDIT SETTINGS**. Select and fill in the following settings:
|
2. When asked: **Would you like to apply OS customization settings?** select **EDIT SETTINGS**. Select and fill in the following settings:
|
||||||
1. **Set username and password**
|
1. **Set username and password**
|
||||||
2. **Set locale settings**
|
2. **Set locale settings**
|
||||||
3. **Enable SSH** > **Allow public-key authentication only** and enter your computer's public key.
|
3. **Enable SSH** > **Allow public-key authentication only** and enter your computer's public key.
|
||||||
4. Disable **Eject media when finished** (probably not really important but I heard it could prevent problems on Windows).
|
4. Disable **Eject media when finished** (probably not really important but I heard it could prevent problems on Windows).
|
||||||
3. Start the Raspberry Pi with an ethernet cable attached.
|
3. Start the Raspberry Pi with an ethernet cable attached.
|
||||||
4. Find the assigned IP of the Raspberry Pi in the [router](http://asusrouter.com/) and configure DHCP to statically asign this address to the Raspberry Pi.
|
4. Find the assigned IP of the Raspberry Pi in the [router](http://asusrouter.com/) and configure DHCP to statically assign this address to the Raspberry Pi.
|
||||||
5. Add the new Raspberry Pi to the *hosts* file using the internal IP if it isn't there already.
|
5. Add the new Raspberry Pi to the *hosts* file using the internal IP if it isn't there already.
|
||||||
6. Test if the Raspberry Pi is correctly configured by opening an SSH session to it (using its IP address).
|
6. Test if the Raspberry Pi is correctly configured by opening an SSH session to it (using its IP address).
|
||||||
|
|
||||||
|
|
@ -52,14 +68,14 @@ ansible-playbook playbook.yml
|
||||||
|
|
||||||
## Overview of installed software
|
## Overview of installed software
|
||||||
### SSH with ZSH
|
### SSH with ZSH
|
||||||
It's possible to connect to the Raspberry Pi from the internal network via either its FQDN or IP address **using a public key only** setup as part of [the Raspberry Pi preperation](#raspberry-pi-preperation).
|
It's possible to connect to the Raspberry Pi from the internal network via either its FQDN or IP address **using a public key only** setup as part of [the Raspberry Pi preparation](#raspberry-pi-preparation).
|
||||||
When logged in the user will be prompted with the **zsh** configured with **[Oh My Zsh](https://ohmyz.sh)** and **[Starhip](https://starship.rs) prompts**.
|
When logged in the user will be prompted with the **zsh** configured with **[Oh My Zsh](https://ohmyz.sh)** and **[Starhip](https://starship.rs) prompts**.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Other
|
## Other
|
||||||
### Reinstalling the Pi
|
### Reinstalling the Pi
|
||||||
It can be handy to reinstall the Pi. First shutdown the pi by running `sudo shutdown` from SSH. Next take out the memory card and follow all steps in [Raspberry Pi preperation](#raspberry-pi-preperation).
|
It can be handy to reinstall the Pi. First shutdown the pi by running `sudo shutdown` from SSH. Next take out the memory card and follow all steps in [Raspberry Pi preparation](#raspberry-pi-preparation).
|
||||||
For the next step remove the current *known_hosts* entry with: `ssh-keygen -R '192.168.50.27'` for all PCs that had SSH access to the Pi.
|
For the next step remove the current *known_hosts* entry with: `ssh-keygen -R '192.168.50.27'` for all PCs that had SSH access to the Pi.
|
||||||
|
|
||||||
### The external Kingston drive
|
### The external Kingston drive
|
||||||
|
|
@ -80,3 +96,103 @@ sudo login
|
||||||
This is verified to be working:
|
This is verified to be working:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
### Manually restoring a backup
|
||||||
|
The `backups` role will install scripting which automatically backs up specific files and uploads it to an external service called
|
||||||
|
[BorgBase](https://www.borgbase.com). This section describes manually restoring such a backup after cleanly reinstalling the Pi from scratch.
|
||||||
|
|
||||||
|
First what's needed is a reference to the Borg repo URL and passphrase. They can be found in the vault file located at: `roles/backups/vars/main/vault.yml`.
|
||||||
|
Read out the values using the `ansible-vault` binary. Log into the Raspberry Pi, change to root and fill the `BORG_REPO` and `BORG_PASSPHRASE` variables:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -i
|
||||||
|
export BORG_REPO='...'
|
||||||
|
export BORG_PASSPHRASE='...'
|
||||||
|
```
|
||||||
|
|
||||||
|
The `backups` role generates a new SSH key pair when run. Since we're assuming in this section a new install took place we'll have to upload the newly
|
||||||
|
generated public key into BorgBase. The correct key is stored in the `root` user's home folder, view it with `cat ~/.ssh/id_ssh_rsa.pub` and upload it
|
||||||
|
to [BorgBase](https://www.borgbase.com). Make sure to also remove any old keys and add it to the repository with "full access".
|
||||||
|
|
||||||
|
It should now be possible to view backups contained within the borg repo by running: `borg list`. Now run the following commands (replacing `[ARCHIVE_NAME]`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir /bulk/backup_work_dir
|
||||||
|
cd /bulk/backup_work_dir/
|
||||||
|
|
||||||
|
borg extract '::[ARCHIVE_NAME]' ./docker_volumes ./postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
The files are now unpacked in this directory, make sure to clean up this directory after use.
|
||||||
|
|
||||||
|
#### Restoring the database content
|
||||||
|
In order to restore the database backups: first log into the PostgreSQL database's REPL shell with the credentials
|
||||||
|
of the `postgres` user found in the role's vault (if required). Now run the following commands (substituting `[DBNAME]`):
|
||||||
|
|
||||||
|
First:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -ti postgres-postgres-1 psql --user postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
Then:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE DATABASE [DBNAME];
|
||||||
|
CREATE USER [DBNAME] WITH PASSWORD '...';
|
||||||
|
GRANT ALL PRIVILEGES ON DATABASE [DBNAME] TO [DBNAME] WITH GRANT OPTION;
|
||||||
|
ALTER DATABASE [DBNAME] OWNER TO [DBNAME];
|
||||||
|
```
|
||||||
|
|
||||||
|
Now that the user exists, exit from the `psql` REPL shell and perform the following actions:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy a database backup into the container
|
||||||
|
docker cp ./postgres/[DBNAME].sql postgres-postgres-1:/dump.sql
|
||||||
|
|
||||||
|
# Load the data into the database
|
||||||
|
docker exec -ti postgres-postgres-1 psql --username '[DBNAME]' --dbname '[DBNAME]' --file '/dump.sql'
|
||||||
|
|
||||||
|
# Remove the dump file from the container
|
||||||
|
docker exec postgres-postgres-1 rm /dump.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Restoring docker backups
|
||||||
|
The backups service stores a configuration file at: `/etc/borg_backup_script/backup_configuration.yaml` which
|
||||||
|
contains an overview of backups. We can use it with a script to loop over the available backups and restore them
|
||||||
|
(in a similar way to how the backup script itself creates the backups). This script assumes that we want to restore
|
||||||
|
all backups, change where necessary.
|
||||||
|
|
||||||
|
Copy this script to the local folder (still assuming this is the folder which contains the `docker_volumes` and `postgres` directories):
|
||||||
|
|
||||||
|
> **Note**: This assumes that the containers are already running. They will be stopped by the script. The script also assumes that
|
||||||
|
> these directories already exist.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# Copied and altered from backup_script.sh:
|
||||||
|
configurationFileLocation='/etc/borg_backup_script/backup_configuration.yaml'
|
||||||
|
nrOfConfigurations="$(yq '.docker_volume_backups | length' <"$configurationFileLocation")"
|
||||||
|
|
||||||
|
for ((i = 0 ; i < "$nrOfConfigurations" ; i++)); do
|
||||||
|
dockerConfiguration="$(yq ".docker_volume_backups[$i]" <"$configurationFileLocation")"
|
||||||
|
containerName="$(echo "$dockerConfiguration" | jq -r '.container_name')"
|
||||||
|
volumeName="$(echo "$dockerConfiguration" | jq -r '.volume_name')"
|
||||||
|
|
||||||
|
specificVolumeBackupPath="./docker_volumes/$volumeName"
|
||||||
|
|
||||||
|
echo "Backup up Docker volume: $volumeName from running container: $containerName..."
|
||||||
|
|
||||||
|
echo "Stopping container: $containerName..."
|
||||||
|
docker stop "$containerName"
|
||||||
|
|
||||||
|
echo "Starting new container which copies over files..."
|
||||||
|
start=$SECONDS
|
||||||
|
docker run --rm -v "$specificVolumeBackupPath:/source" -v "$volumeName:/target" --entrypoint "ash" \
|
||||||
|
alpine -c "rm -rf /target/*; cp -rf /source/* /target/"
|
||||||
|
|
||||||
|
elapsedSeconds=$(( SECONDS - start ))
|
||||||
|
echo "Copying succeeded (in $elapsedSeconds seconds), restarting container..."
|
||||||
|
docker start "$containerName"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue