Skip to content

Latest commit

 

History

History
160 lines (122 loc) · 20.4 KB

README.ru.md

File metadata and controls

160 lines (122 loc) · 20.4 KB

pi-builder

[English version]

pi-builder - это удобный и расширяемый инструмент для сборки образов Arch Linux ARM для Raspberry Pi с использованием Docker.


Проблема

Обычно для сборки операционок разработчики дистрибутивов используют набор шелл-скриптов. У каждого дистрибутива они, как правило, свои. С их помощью создается чрут с нужными пакетами, правятся конфиги, добавляются пользователи и выполняются иные операции. Таким образом обеспечивается необходимый минимум для успешной загрузки, работы и дальнейшей кастомизации оси руками конечного пользователя.

Однако если вы создаете какой-то собственный продукт на основе одноплатного компьютера (маленький роутер, IP-камеру или систему управления умным домом, что угодно), то скорее всего вам захочется каким-нибудь способом задокументировать все изменения, которые вы внесли в свежеустановленную операционную систему, и обеспечить себе возможность повторить эти настройки, не боясь забыть о каком-нибудь важном действии, типа настройки sysctl.

Типичное решение в данном случае - написать большой и страшный скрипт, выполняющий все необходимые действия либо над развернутым на разработческой машине корнем, либо прямо на устройстве. При использовании chroot и binfmt_misc, а так же при необходимости сохранения промежуточных стадий сборки сложность подобных скриптов сразу возрастает на порядок. А со временем они становятся абсолютно неподдерживаемыми.


Что предлагает pi-builder?

По сути, это новый подход к сборке целевой операционной системы для встраиваемых устройств. Он позволяет собирать образ так, как если бы это была не система для реальной железки, а обычный докер-контейнер. Сборка системы описывается стандартным синтаксисом докерфайлов и выполняется в докере прямо на машине разработчика. Получившийся образ можно экспортировать на SD-карту и загрузить на Raspberry Pi.


Что это дает?

  • Документирование и повторяемость сборок. Докерфайлы - это практически готовая документация к последовательности действий, необходимых для настройки всей вашей системы.
  • Простота. Ну серьезно, что может быть проще, чем написать докерфайл?
  • Скорость и кеширование сборок. Сборка целевой системы может состоять из сотен сложных и долго выполняющихся команд. С помощью докера и его кешей вы можете не выполнять все эти команды каждый раз при сборке новой системы; сборка будет начинаться только с изменившихся команд, а результаты предыдущих будут браться из кеша.
  • Тестирование на реальном окружении. Если вы разрабатываете какой-то софт, который должен работать на Raspberry Pi, совершенно логично тестировать его в том же окружении, в котором он будет работать на реальной железке - это избавит от многих потенциальных проблем.

Как это работает?

Разработчики Arch Linux ARM (да и других систем) предоставляют для своих осей архивы с минимальными корневыми ФС, которые можно развернуть на флешке и загрузиться с них. И поскольку это обычные корни, из них также можно сделать собственный базовый образ для докера с помощю механизма FROM scratch. Однако этот образ будет содержать исполняемые файлы и библиотеки с архитектурой ARM, и если ваша машина работает под другой архитектурой (скажем, x86_64), то ни одна команда внутри этого образа у вас не запустится.

Для того, чтобы иметь возможность исполнять файлы с другой архитектурой, ядро Linux имеет специальный механизм binfmt_misc, который позволяет установить кастомный интерпретатор для архитектуры, отличной от системной. Таким образом, можно настроить binfmt_misc для запуска ARM-бинарников с помощью эмулятора (в нашем случае - qemu-arm-static для x86_64). Pi-builder содержит небольшой скрипт, настраивающий в хост-системе binfmt_misc, чтобы иметь возможность запускать исполняемые файлы на ARM.

Сборка операционной системы в терминологии pi-builder делится на последовательные стейжи, представляющие какой-либо отдельный аспект настройки оси. Например, стейж ro включает в себя Dockerfile.part с необходимыми инструкциями, чтобы сделать на системе read-only корень, и конфиги для этого. Другой пример - стейж watchdog, включающий все необходимое для настройки вачдога с оптимальными параметрами на Raspberry Pi.

Полный список стейжей, идущих в комплекте с pi-builder, можно посмотреть тут или в списке ниже. При сборке системы вы сами решаете, какие стейжи вам нужны, и просто включаете их в вашу конфигурацию. По сути, стейжи - это кусочки докерфайла которые при сборке склеиваются в указанной последовательности в один большой докерфайл и содержат все инструкции, которые будут выполнены на собираемой системе. Вы можете сами создать собственные стейжи по аналогии с имеющимися.

Последовательность сборки выглядит так:

  1. pi-builder скачивает статически скомпилированный qemu-arm-static от Debian и настраивает binfmt_misc глобально на вашей машине.
  2. Далее скачивается образ Arch Linux ARM и заряжется в докер в качестве базового образа.
  3. Производится сборка конейнера с необходимыми стейжами - установка пакетов, настройка конфигов, чистка и так далее.
  4. В получившемся контейнере можно запустить оболочку с помощью docker run (или make shell), чтобы проверить, все ли в порядке.
  5. С помощью утилиты docker-extract, входящей в состав pi-builder, контейнер извлекается из внутреннего хранилища докера и помещается в каталог, как обыкновенная развернутая корневая ФС.
  6. Готовую ФС можно скопировать на SD-карту и загрузить с нее Raspberry Pi.

Как этим пользоваться?

Для сборки системы с помощью pi-builder вам понадобится свежий докер с возможностью запуска контейнера в привелегированном режиме (он требуется вспомогательному образу для установки binfmt_misc, форматирования SD-карты и некоторых других операций).

Вся работа с pi-builder выполняется с помощью главного Makefile в корне репозитория. В его начале перечислены параметры, доступные для переопределения, которое можно выполнить, создав файл config.mk с новыми значениями. Дефолтные значения таковы:

# Пространство имен для промежуточных образов, просто назовите как нравится
PROJECT ?= common

# Целевая платформа Raspberry Pi
BOARD ?= rpi

# Список необходимых стейжей, об этом подробнее ниже
STAGES ?= __init__ os pikvm-repo watchdog no-bluetooth no-audit ro ssh-keygen __cleanup__

# Имя хоста для получившейся системы
HOSTNAME ?= pi

# Локаль будущей системы (UTF-8)
LOCALE ?= en_US

# Таймзона будущей системы
TIMEZONE ?= Europe/Moscow

# Путь к карте памяти
CARD ?= /dev/mmcblk0

Самые важные параметры - это BOARD, определяющий, под какую плату нужно собрать систему, STAGES, указывающий, какие стейжи необходимо включить и CARD, содержащий путь к устройству SD-карты. Вы можете переопределить их, передав новые значание вместе с вызовом make, или создав файл config.mk с новыми значениями.

Стейж __init__ всегда должен идти первым: он содержит инициализирующие инструкции для создания базового образа системы (FROM scratch). Далее идут стейжи для "обживания" системы - установки полезных пакетов, настройки вачдога, приведения системы к ридонли, настройки ключей SSH для рута и очистки от временных файлов.

Вы можете создать собственные стейжи и включить их в сборку наравне с комплектными. Для этого просто заведите каталог для вашего стейжа в папке stages и разместите в нем файл Dockerfile.part по аналогии с любым другим стейжем. Как вариант, можно сделать так, как это устроено в проекте Pi-KVM (для которого, собственно, pi-builder и был разработан).


Комплектные стейжи

  • __init__ - главный стейж, формирующий базовый образ на основе корневой ФС Arch Linux ARM. Он ВСЕГДА должен идти первым в списке STAGES.
  • os - просто ставит некоторые пакеты и настраивает систему, чтобы в ней было несколько более комфортно жить. Просто посмотрите его содержимое.
  • ro - превращает систему в ридонли-ось. В таком режиме Raspberry Pi можно просто выключать из розетки без предварительной подготовки, не боясь повредить файловоую систему. Для того, чтобы временно включить систему на запись (например, для обновления), используйте команду rw; после всех изменений выполните команду ro для обратного перемонтирования в ридонли.
  • pikvm-repo - добавляет ключ и репозиторий проекта Pi-KVM. Нужно для вачдога, содержит другие дополнительные пакеты. Подключать не обязательно.
  • watchdog - настраивает аппаратный вачдог.
  • no-bluetooth - отключает блютуз и восстанавливает работоспособность UART0/ttyAMA0 на 14 и 15 пинах GPIO.
  • no-audit - отключает ядерный аудит.
  • ssh-root - удаляет пользователя alarm, блокирует пароль root и добавляет в его ~/.ssh/authorized_keys ключи из каталога stages/ssh-root/pubkeys. По умолчанию там лежат ключи разработчика pi-builder, так что обязательно их замените. Кроме того, этот стейж блокирует возможность логина через UART. Если вам требуется эта возможность, напишите свой собственный стейж с аналогичными функциями.
  • ssh-keygen - генерирует хостовые SSH-ключи. На этом стейже ВСЕГДА будет происходить пересборка системы. В обычной ситуации ручная генерация ключей не требуется, но если система загружается в ридонли, у SSH нет возможности сгенерировать ключи самостоятельно даже при первой загрузке.
  • __cleanup__ - удаляет всякий мусор во временных папках, оставшийся от сборки.

Ограничения


Некоторые файлы, такие как /etc/host и /etc/hostname, автоматически заполняются докером и все изменения, вносимые в них из докерфайла, будут потеряны. В случае с именем хоста в Makefile добавлен специальный костыль, которые записывает имя хоста в экспортируемую систему, или назначает это имя при запуске make run. Так что если вам потребуется изменить что-нибудь в подобных файлах, то придется дописать это аналогичным образом в Makefile.


TL;DR

Как собрать систему под Raspberry Pi 3 и поставить ее на SD-карту:

$ git clone https://github.com/pikvm/pi-builder
$ cd pi-builder
$ make rpi3
$ make install

Как собрать систему со своим списком стейжей:

$ make os BOARD=rpi3 STAGES="__init__ os __cleanup__"

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

$ make

===== Available commands  =====
    make                # Print this help
    rpi|rpi2|rpi3|rpi4|zero|zerow|zero2w  # Build Arch-ARM rootfs with pre-defined config
    make shell          # Run Arch-ARM shell
    make binfmt         # Before build
    make scan           # Find all RPi devices in the local network
    make clean          # Remove the generated rootfs
    make format         # Format /dev/mmcblk0 to /dev/mmcblk0p1 (vfat), /dev/mmcblk0p2 (ext4)
    make install        # Install rootfs to partitions on /dev/mmcblk0

===== Running configuration =====
    PROJECT = common
    BOARD   = rpi
    STAGES  = __init__ os watchdog no-bluetooth ro ssh-keygen __cleanup__

    BUILD_OPTS =
    HOSTNAME   = pi
    LOCALE     = en_US
    TIMEZONE   = Europe/Moscow
    REPO_URL   = http://mirror.yandex.ru/archlinux-arm

    CARD = /dev/mmcblk0

    QEMU_PREFIX =
    QEMU_RM     = 1
  • Важно: проверьте в Makefile путь к SD-карте в переменнjq CARD и отключите автомонтирование, чтобы свежеотформатированная карта памяти не прицепилась к вашей системе, и скрипт установки не зафейлился.
  • Очень важно: положите в каталог stages/ssh-root/pubkeys свой SSH-ключ, иначе не сможете потом залогиниться в систему, или не используйте стейж ssh-root.
  • Еще более важно: прочитайте весь этот README целиком, чтобы понимать, что и зачем вы все-таки делаете.

Лицензия

Copyright (C) 2018 by Maxim Devaev [email protected]

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.