From a92442fa6bb54c1eedf035194d337bde83ead7a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BE=D0=BB=D0=B3=D0=B8=D0=B9=20=D0=90=D1=80=D1=82?=
 =?UTF-8?q?=D1=91=D0=BC?= <artem@da2001.ru>
Date: Tue, 9 Aug 2022 17:07:20 +0300
Subject: [PATCH] add rpi_backup

---
 rpi_backup.md | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 236 insertions(+)
 create mode 100644 rpi_backup.md

diff --git a/rpi_backup.md b/rpi_backup.md
new file mode 100644
index 0000000..1fe251a
--- /dev/null
+++ b/rpi_backup.md
@@ -0,0 +1,236 @@
+# Описание процесса создания резервной копии Raspberry Pi 4
+
+Существует множество способов создания резервных копий системы, среди которых - использование специализированного ПО, самописные скрипты, которые выполняют копирование/архивирование выбранных директорий, ручное копирование, создание образов дисков и разделов и т.д.
+
+Создать резервную копию мало, необходимо также быть уверенным в том, что в случае необходимости, с ранее созданной резервной копии можно восстановиться. Ведь в процессе создания резервной копии, исходные данные могут изменяться - происходит чтение/запись, таким образом, есть вероятность, что в резервную копию попадут не консистентные данные и восстановиться с такой резервной копии будет невозможно. Чтобы избежать подобных проблем, необходимо исключить возможность изменения исходных данных в процессе создания резервных копий. Например, при создании образа системы, необходимо, чтобы раздел, резервную копию которого будем выполнять, не был смонтирован. Этого легко добиться, если это не загрузочный раздел.
+
+Но как быть, если нужно создать резервную копию (образ) загрузочного раздела или всего диска? - Необходимо выполнить загрузку с какого-нибудь live-cd и средствами этого самого live-cd создать образ системы. С Raspberry Pi 4 ситуация немного проще, достаточно извлечь SD-карту, создать её образ и сохрать этот образ в надёжном месте. Всё это ручная работа, которая требует времени.
+
+## Один из способов автоматизации создания образа системы Raspberry Pi 4 описан ниже.
+
+Raspberry Pi 4, 400 и Compute Module 4 используют EEPROM для загрузки системы. Все остальные модели Raspberry Pi используют bootcode.bin файл, расположенный в загрузочной файловой системе.
+
+Если не углубляться в детали ([BOOT ORDER](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#BOOT_ORDER)), EEPROM позволяет выполнять загрузку c SD карты, USB, сети. Такую возможность добавили в одном из обновлений, необходимо убедиться, что используется последняя версия EEPROM.
+
+Таким образом, выполнить создание образа SD-карты RPI можно если:
+
+- записать образ системы на USB накопитель, подойдёт Raspberry Pi OS lite (<https://www.raspberrypi.com/software/operating-systems/>);
+- переключить EEPROM в режим загрузки с USB;
+- выполнить загрузку с USB;
+- создать образ SD-карты и передать его в надёжное сетевое хранилище;
+- вернуть EEPROM в режим загрузки с SD-карты;
+- перезагрузить RPI.
+
+Ничего сложного, осталось найти способ автоматического переключения способов загрузки в EEPROM. И такой способо существует - утилита `rpi-eeprom-config`
+
+Нам достаточно двух ключей:
+
+-a, --apply
+-o, --out
+
+сохранить текущие настройки загрузчика во внешний файл
+
+```bash
+pi@sdboot:~ $ sudo rpi-eeprom-config -o ~/eeprom.conf
+```
+
+применить конфигурацию загрузчика из файла
+
+```bash
+pi@sdboot:~ $ sudo rpi-eeprom-config -a ~/eeprom.conf
+```
+
+Осталось окончательно сформировать архитектуру нашего решения по созданию образа.
+
+**На системе с SD**
+
+1. Необходимо создать конфигурационный файл EEPROM, который установит загрузку на USB
+
+```bash
+pi@sdboot:~ $ cat usb_eeprom.conf 
+[all]
+BOOT_UART=0
+WAKE_ON_GPIO=1
+POWER_OFF_ON_HALT=0
+BOOT_ORDER=0xf4
+```
+
+2. Создать скрипт, который будет выполнять обновление конфигурации EEPROM
+
+```bash
+#!/bin/bash
+
+###################################################################################################
+
+# Скрипт выполняет обновление конфигурации EEPROM Raspberry PI для загрузки с USB.
+# В директории с этим скриптом должен находится конфигурационный файл EEPROM - $eeprom_conf
+
+# Для корректной работы скрипта, EEPROM RPI должен поддерживать режим переключения загрузки SD<=>USB.
+
+###################################################################################################
+
+# Убедиться, что запуск происходит от root
+if [ "$EUID" -ne 0 ]
+  then echo "Скрипт необходимо запускать от администратора"
+  exit
+fi
+
+# Необходимо убедиться, что в папке присутствует конфиг EEPROM для изменения порядка загрузки
+eeprom_conf="usb_eeprom.conf"
+
+if [ ! -e "./$eeprom_conf" ]; then
+    echo Файл настроек EEPROM $eeprom_conf не найден > log 2>&1
+    exit
+fi
+
+# Необходимо переключить EEPROM на загрузку с USB
+rpi-eeprom-config -a ./$eeprom_conf
+
+# Перезагрузка
+reboot
+```
+
+3. Выполнить настройку запуска скрипта по расписанию.
+
+*т.к. обновление конфигурации EEPROM необходимо выполнять с привилегиями root, настраивать расписание нужно также пользователя root, чтобы скрипт запускался с повышенными привилегиями.*
+
+```bash
+pi@sdboot:~ $ sudo crontab -e
+```
+
+например, для запуска скрипта каждую среду в 2 часа ночи, необходимо добавить строку
+
+```bash
+0 2 * * 3 /opt/scripts/rpi_usb_boot.sh
+```
+
+**На системе с USB**
+
+4. Обеспечить подключение к хранилищу по SSH на основе ключа
+
+```bash
+pi@usbboot:~ $ ssh-keygen
+pi@usbboot:~ $ ssh-copy-id user@nas
+```
+
+5. Создать конфигурационный файл EEPROM, который вернёт загрузку на SD
+
+```bash
+pi@usbboot:~ $ cat sd_eeprom.conf 
+[all]
+BOOT_UART=0
+WAKE_ON_GPIO=1
+POWER_OFF_ON_HALT=0
+BOOT_ORDER=0xf1
+```
+
+6. Подготовить основной скрипт, который выполнит создание образа SD-карты и передаст его по SSH в сетевое хранилище
+
+```bash
+#!/bin/bash
+
+###################################################################################################
+
+# Скрипт создаёт образ SD-карты Raspberry PI и отправляет его на удалённый сервер по SSH,
+# при этом на удалённом сервере происходит сжатие образа для экономии места.
+# Сжатие происходит на удалённом сервере, чтобы минимизировать операции записи на Flash память,
+# с которой произведена загрузка RPI.
+# После создания образа, происходит обновление конфигурации EEPROM Raspberry PI для загрузки с SD карты.
+# В директории с этим скриптом должен находится конфигурационный файл EEPROM - $eeprom_conf
+
+# Для корректной работы скрипта, EEPROM RPI должен поддерживать режим переключения загрузки SD<=>USB.
+
+###################################################################################################
+
+# Убедиться, что запуск происходит от root
+if [ "$EUID" -ne 0 ]
+  then echo "Скрипт необходимо запускать от администратора"
+  exit
+fi
+
+# Удалённый сервер. Необходимо предварительно обеспечить доступ по ключам - ssh-keygen && ssh-sopy-id
+server=user@nas
+
+# Путь сохранения на удалённом сервре
+remote_path=/mnt/disk2/Backup/rpi
+
+# Необходимо убедиться, что в папке присутствует конфиг EEPROM для изменения порядка загрузки
+eeprom_conf="sd_eeprom.conf"
+
+if [ ! -e "./$eeprom_conf" ]; then
+    ssh $server "echo Файл настроек EEPROM $eeprom_conf не найден" > $remote_path/lastlog 2>&1
+    exit
+fi
+
+# Имя образа
+name=$(date +%Y-%m-%d)_rpi_image.img.gz
+
+# Имя диска, над которым будем работать. SD в RPI называется mmcblk0
+disk=/dev/mmcblk0
+
+# запишем в переменную последний сектор последнего раздела диска
+last_sector=$(fdisk -l -o end $disk | tail -1)
+
+# Считаем, что размер сектора составляет 512 Байт, тогда необходимо сохранить ($last_sector+1)*512 Байт.
+# Или ($last_sector+1)*512/1024/1024 Мб.
+count=$(($(($last_sector+1))*512/1024/1024))
+
+# Команда создания образа
+dd if=$disk bs=1M count=$count conv=noerror,sync | ssh $server "gzip -c  > $remote_path/$name 2>> $remote_path/lastlog" && \
+ssh $server "echo `date +"%A, %d %B %Y"` - Образ создан успешно >> $remote_path/log" || \
+ssh $server "echo `date +"%A, %d %B %Y"` - При создании образа произошла ошибка >> $remote_path/log"
+
+# Необходимо хранить только последние 20 строк в файле log
+echo "$(tail -20 log)" > log
+
+# Необходимо хранить только последние 3 резервные копии
+count_copies=3
+find . -type f -name "*_rpi_image.img.gz" -printf "%T@ %p\n" | sort -n | cut -d' ' -f 2- | tail -n +$(($count_copies+1)) | xargs rm -f --
+
+# Необходимо переключить EEPROM на загрузку с SD карты
+rpi-eeprom-config -a ./$eeprom_conf
+
+# Перезагрузка
+reboot
+```
+
+7. Обеспечить выполнение скрипта при загрузке с USB. Рассмотрим 3 способа.
+
+7.1. /etc/rc.d/rc.local
+
+Для выполнения пользовательского скрипта при загрузке, достаточно указать к нему полный путь в файле `/etc/rc.d/rc.local`. Затем необходимо добавить права на выполнение
+
+```bash
+pi@usbboot:~ $ chmod +x /etc/rc.d/rc.local
+```
+
+7.2. crontab
+
+Добавить задание в crontab с параметром `@reboot`
+
+```bash
+@reboot /opt/scripts/rpi_backup.sh
+```
+
+7.3. Systemd unit
+
+Для этого вам нужно создать скрипт запуска systemd и поместить его в каталог `/etc/systemd/system/`.
+
+```bash
+pi@usbboot:~ $ vim /etc/systemd/system/rpi_backup.service
+```
+
+```bash
+pi@usbboot:~ $ cat /etc/systemd/system/rpi_backup.service
+[Unit]
+Description=Run a Backup Script at Startup
+After=default.target
+
+[Service]
+ExecStart=/opt/scripts/rpi_backup.sh
+
+[Install]
+WantedBy=default.target
+```
+
+***