Как стать автором
Обновить

Удалённая переустановка Raspberry Pi OS по ssh

Уровень сложностиСредний
Время на прочтение4 мин
Количество просмотров7.8K

На habr'е уже была публикация про удаленную переустановку Linux по ssh. Воистину, так гланды ещё никто не удалял… Я подивился находчивости и целеустремлённости автора, и искренне пожелал себе, чтобы материал никогда не пригодился на практике.

Но внезапно мне понадобилось переустановить Raspberry Pi OS на microSD-карте, установленной в Raspberry Pi 4. При этом доставать microSD-карту очень не хотелось, дело в том, что плата Raspberry Pi установлена внутрь корпуса, который не позволяет достать microSD-карту без разборки.

Памятуя, что это не единственная моя плата Raspberry Pi и это не последний раз, когда придётся полностью переустанавливать Raspberry Pi OS, я решил, что лучше полчаса потерять, потом за пять минут обновить.

Сразу оговорюсь, что приведённая ниже инструкция не универсальна. Я буду рассматривать очень простой случай:

  • есть небольшая локальная сеть IPv4 с DHCP-сервером и выходом в Интернет;

  • имеется плата Raspberry Pi (далее rpi), подключённая к локальной сети по Ethernet, на которой уже установлена и функционирует Raspberry Pi OS не слишком старой версии;

  • в локальной сети есть компьютер (далее host), с которого мы можем подключаться к rpi по ssh (на host установлены wget, openssh-client и xz);

  • rpi может получать IP-адрес по DHCP; мы умеем найти rpi в локальной сети (хотя бы по MAC-адресу).

Вот стартовав в таких тепличных условиях, попробуем полностью обновить содержимое microSD-карты в rpi, перезагрузиться и снова подключиться к rpi по ssh.

Не нагуглив готового решения для Raspberry Pi OS, я обратился к посту Удаленная переустановка Linux по ssh без доступа к консоли. Ключевым моментом изложенной там методики является возможность на ходу логически "отключить" накопитель, с которого работает "старая" ОС, а затем уже переподключить его, но так, что "старая" ОС будет его считать другим накопителем и не будет противиться его полной перезаписи.
Увы, то, что дозволено делать со SCSI-диском не дозволено делать с microSD-картой, по крайней мере мне подобные возможности найти не удалось.

Я рассмотрел другие возможности:

  • порвать с /dev/mmcblk0 при помощи pivot_root;

  • перезагрузиться, так, чтобы совсем не задействовать /dev/mmcblk0 для /: использовать nfsroot или nbd для rootfs.

Эти решения сопряжены с дополнительными хлопотами, которых хотелось бы избежать.

И почти готовое решение нашлось: Alpine Linux.

Alpine Linux это дистрибутив, который требует очень скромных ресурсов накопителя и ОЗУ так, что оказывается возможным, загрузившись с microSD-карты, развернуть корневую файловую систему только в ОЗУ.

Будем действовать так:

  • загрузим на rpi Alpine Linux в специальной конфигурации, в которой производится автоматическая настройка сетевого интерфейса Ethernet по DHCP и обеспечивается запуск ssh-сервера с беспарольным доступом;

  • из Alpine Linux запишем на microSD-карту базовый образ Raspberry Pi OS и проведём его минимальную настройку;

  • перезагрузимся в Raspberry Pi OS.

Развёртывание Alpine Linux

Подключаемся по ssh к root@rpi, где работает Raspberry Pi OS, и развёртываем там Alpine Linux.

Для Raspberry Pi OS microSD-карта размечается так, что карте создаётся два раздела:

  • /dev/mmcblk0p1 --- небольшой раздел с файловой системой FAT, где находятся загрузчик и всё, что надо для запуска ядра ОС;

  • /dev/mmcblk0p2 --- раздел с файловой системой EXT4; этот раздел содержит корневую файловую систему ОС.

NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
mmcblk0     179:0    0 59.7G  0 disk
├─mmcblk0p1 179:1    0  512M  0 part /boot/firmware
└─mmcblk0p2 179:2    0 59.2G  0 part /

ВНИМАНИЕ! Не забудьте сохранить ценные данные с microSD-карты, если таковые там есть, через несколько минут они отправятся в страну вечной охоты!

Будем развёртывать Alpine в разделе загрузчика, то есть в /boot/firmware:

root@raspberrypi:~# cd /boot/firmware/
root@raspberrypi:/boot/firmware# wget -O - https://dl-cdn.alpinelinux.org/alpine/v3.18/releases/aarch64/alpine-rpi-3.18.5-aarch64.tar.gz | tar fxz -
root@raspberrypi:/boot/firmware# wget https://raw.githubusercontent.com/macmpi/alpine-linux-headless-bootstrap/f35a86687534306895ea147953730f56af4cff37/headless.apkovl.tar.gz

Скачанный файл headless.apkovl.tar.gz как раз и обеспечивает настройку сетевого интерфейса rpi при старте и запуск ssh-сервера. Подробности тут.

Итак, microSD-карта настроена так, что при следующей загрузке на rpi запустится Alpine Linux.

Перезагружаемся:

root@raspberrypi:/boot/firmware# reboot

Развёртывание и настройка Raspberry Pi OS

Немного подождём и попробуем подключиться к rpi с работающим Alpine Linux по ssh.

Это можно сделать так:

host$ ssh -x -o userknownhostsfile=/dev/null -o stricthostkeychecking=no root@rpi

Дополнительные опции нужны, чтобы клиент ssh не смущался новому, неведомому серверу, жить которому только несколько минут.

Чтобы не набирать такую длинную команду несколько раз, закинем её в переменную:

host$ RPISSH="ssh -o userknownhostsfile=/dev/null -o stricthostkeychecking=no root@rpi"

Освобождаем mmcblk0:

host$ $RPISSH umount /.modloop/
host$ $RPISSH umount /media/mmcblk0p1/

Теперь можно накатывать образ Raspberry Pi OS. Чтобы не возиться с установкой на Alpine Linux xz-utils, будем запускать xz на host:

host$ wget -O - https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-12-06/2023-12-05-raspios-bookworm-arm64-lite.img.xz | xz -cd | $RPISSH dd bs=8M of=/dev/mmcblk0

С некоторых пор нельзя просто так взять и подключиться к Raspberry Pi OS по ssh, см. https://www.raspberrypi.com/news/raspberry-pi-bullseye-update-april-2022/, необходима небольшая начальная настройка.

Начнём с того, что разрешим запуск ssh-сервера при старте:

host$ $RPISSH mount /dev/mmcblk0p1 /mnt
host$ $RPISSH "echo > /mnt/ssh"

Опционально можно включить использование последовательного порта в качестве консоли:

host$ $RPISSH "echo enable_uart=1 >> /mnt/config.txt"

Работы с разделом загрузчика завершены, этот раздел можно отключить:

host$ $RPISSH umount /mnt

В современной Raspberry Pi OS по умолчанию ни пользователю root, ни пользователю pi нельзя подключиться по ssh. Поэтому подложим пользователю root готовый открытый ключ, чтобы в дальнейшем можно было подключиться к root@rpi без пароля:

host$ $RPISSH mount /dev/mmcblk0p2 /mnt
host$ $RPISSH "cat > /mnt/root/.ssh/authorized_keys" < ~/.ssh/id_rsa.pub
host$ $RPISSH umount /mnt

Подробнее про ключи openssh можно почитать тут.

Перезагрузимся в Raspberry Pi OS:

host$ $RPISSH reboot

Подождём не более пары минут и voilà:

host$ $RPISSH uname -a
...
Linux raspberrypi 6.1.0-rpi7-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.63-1+rpt1 (2023-11-24) aarch64 GNU/Linux

Эпилог

Инструкция несколько раз проверена на Raspberry Pi 4 Model B. Для других плат понадобятся внести незначительные корректировки, но, полагаю, вдумчивый читатель догадается где надо заменить aarch64/arm64 на armhf.

Теги:
Хабы:
Всего голосов 19: ↑19 и ↓0+19
Комментарии1

Публикации

Истории

Работа

Ближайшие события

15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань