Bootstrap

Google Nexus 5: Nura (postmarketOS) без графики — домашний сервер с Docker и экранной оболочкой

Google Nexus 5: Nura (postmarketOS) без графики — домашний сервер с Docker и экранной оболочкой

Что получится

Nexus 5 2013 года превращается в маленький сервер: Linux без графического интерфейса, Docker, вход по SSH-ключу, Wi-Fi. Вместо пустой строки login: на экране — табло состояния, htop, консоль и меню, которыми можно управлять кнопками громкости и касаниями. Телефон можно отдать человеку без ПК: в меню есть подключение к новой сети Wi-Fi.

Nura — новое название postmarketOS. Команды и инструменты (pmbootstrap, pmaports) остались прежними.

Табло состояния

ПараметрЗначение
МодельLG Google Nexus 5 (D820/D821), кодовое имя hammerhead
SoCQualcomm Snapdragon 800 (msm8974), 4 ядра Krait, armv7 (32 бита)
Память2 ГБ (около 1,88 ГБ доступно системе)
НакопительeMMC 16/32 ГБ
Wi-FiBroadcom BCM4339 по SDIO (драйвер brcmfmac)
Порт Nuralg-hammerhead, категория testing, ядро linux-postmarketos-qcom-msm8974 (общее с OnePlus One)

Ядро на момент установки (ноябрь 2026): 6.16.12. Без графики система занимает около 300 МБ памяти, образ — 1,5 ГБ.

Похожая статья про OnePlus One (тот же процессор msm8974, первая версия экранной оболочки): OnePlus One: Ubuntu Touch → Nura.

Что нужно

  • Nexus 5 с разблокированным загрузчиком (fastboot oem unlock, стирает данные). Желательно TWRP в разделе recovery: он пригодится, если что-то пойдёт не так.
  • ПК с Linux, кабель micro-USB. У старых Nexus 5 часто разболтано гнездо: если телефон не определяется, переподключите кабель.
  • pmbootstrap 3.11 или новее. В Debian пакет устарел (3.1.0), поэтому берём из git:

☯

Terminal:

⌕

≡

✕
git clone https://gitlab.postmarketos.org/postmarketOS/pmbootstrap.git ~/src/pmbootstrap
alias pmbootstrap="python3 ~/src/pmbootstrap/pmbootstrap.py"
pmbootstrap --version          # 3.12.1 на момент написания
pmbootstrap pull               # обновить pmaports

Если на ПК уже есть настройки pmbootstrap для другого телефона, сохраните копию ~/.config/pmbootstrap_v3.cfg.

Если на телефоне уже стоял postmarketOS: частые проблемы

Мой Nexus 5 уже работал на postmarketOS, но не видел Wi-Fi. Причины пригодятся всем, кто обновляет старую установку.

Нет Wi-Fi после обновления. Интерфейса wlan0 нет, хотя чип виден в dmesg (mmc1: new ultra high speed SDR104 SDIO card). uname -r показывает одно ядро, а в /lib/modules лежат модули другого, поэтому modprobe brcmfmac не находит модуль. Причина: после apk upgrade новый /boot/boot.img не записался в раздел boot. В порте lg-hammerhead нет настройки flash_kernel_on_update, так что без lk2nd ядро само не обновляется. Исправление вручную (с резервной копией):

☯

Terminal:

⌕

≡

✕
sudo dd if=/dev/disk/by-partlabel/boot of=~/boot-backup.img bs=1M conv=fsync
sudo dd if=/boot/boot.img of=/dev/disk/by-partlabel/boot bs=1M conv=fsync
sudo reboot

Как сделать, чтобы это происходило автоматически, — в разделе «Ядро при обновлениях».

lk2nd на этом экземпляре не заработал. pmbootstrap предлагает поставить вторичный загрузчик lk2nd. У меня lk2nd 20.0 уходил в режим зарядки (загрузчик LG передаёт androidboot.mode=charger), а при следующей перезагрузке зависал на заставке. Откатился через TWRP: adb push резервной копии раздела boot и dd обратно. Поэтому дальше ядро пишется прямо в раздел boot, загрузкой управляет штатный загрузчик LG.

Сохранить файлы старой системы через TWRP. Если система не грузится, но TWRP работает, rootfs postmarketOS можно смонтировать прямо в TWRP: он лежит во втором разделе внутри userdata. Так я забрал профиль Wi-Fi, чтобы не вводить пароль заново:

☯

Terminal:

⌕

≡

✕
adb shell 'fdisk -l /dev/block/mmcblk0p28'      # userdata: внутри p1 (boot) и p2 (rootfs), смотрим начальный сектор p2
adb shell 'mkdir -p /tmp/oldroot; L=$(losetup -f); losetup -o $((651264*512)) -r $L /dev/block/mmcblk0p28 && mount -t ext4 -o ro $L /tmp/oldroot'
adb shell 'ls /tmp/oldroot/etc/NetworkManager/system-connections/'
adb pull "/tmp/oldroot/etc/NetworkManager/system-connections/<сеть>.nmconnection" backup/
adb shell 'umount /tmp/oldroot; losetup -d /dev/block/loop0'

Число 651264 — начальный сектор p2 из вывода fdisk, у вас может отличаться. В файлах .nmconnection пароль Wi-Fi хранится открытым текстом: держите их с правами 600.

pmbootstrap init

☯

Terminal:

⌕

≡

✕
pmbootstrap init

Ответы:

  • Vendor / device: lg / hammerhead.
  • Username: ваш пользователь.
  • UI: console («Console environment, with no graphical/touch UI»).
  • Service manager: по умолчанию systemd.
  • Extra packages: docker,docker-cli-compose,nano,htop.
  • Locale ru_RU, hostname, например, nexus5.
  • Copy SSH keys to device: да — тогда сразу будет вход по ключу.

Init может подставить часовой пояс ПК или виртуальной машины. Проверьте и при необходимости поправьте:

☯

Terminal:

⌕

≡

✕
pmbootstrap config timezone Europe/Moscow

Сборка образа

☯

Terminal:

⌕

≡

✕
pmbootstrap install --password <PIN>

Пароль должен быть цифровым: он же PIN. После первого входа его можно сменить командой passwd. Все пакеты для armv7 готовые, компиляции нет, сборка заняла около 11 минут.

Результат — ~/.local/var/pmbootstrap/chroot_native/home/pmos/rootfs/lg-hammerhead.img, 1,5 ГБ. С console UI образ почти вдвое меньше, чем с Phosh.

В конце pmbootstrap предложит flash_lk2nd. Его я пропустил (см. выше).

Прошивка

Переведите телефон в fastboot: с выключенного — кнопки VOL− и POWER, из TWRP — adb reboot bootloader. Проверка:

☯

Terminal:

⌕

≡

✕
fastboot getvar product            # hammerhead
fastboot oem device-info           # Device unlocked: true

Сначала очистите userdata. Это главный совет статьи, ниже объясню почему:

☯

Terminal:

⌕

≡

✕
fastboot erase userdata

Затем rootfs и ядро:

☯

Terminal:

⌕

≡

✕
pmbootstrap flasher flash_rootfs --partition userdata
pmbootstrap flasher flash_kernel
fastboot reboot

Запись rootfs идёт около 4 минут. Предупреждение config-postmarketos-qcom-msm8974.armv7 isn't configured properly (category:hardening) при flash_kernel некритично.

Первая загрузка: «root partition not found»

Я сначала прошил без fastboot erase userdata и получил: USB-сеть есть (ping 172.16.42.1 отвечает), а SSH закрыт. Зато открыт telnet (порт 23) — это отладочная оболочка initramfs. На экране и в /pmOS_init.log:

☯

Terminal:

⌕

≡

✕
Mount subpartitions of /dev/mmcblk0p28
Primary GPT is invalid, using alternate GPT.
ERROR: failed to mount subpartitions!   /  root partition not found!

Лог можно прочитать с ПК без интерактивного telnet:

☯

Terminal:

⌕

≡

✕
{ sleep 1; echo 'tail -30 /pmOS_init.log'; sleep 3; } | nc 172.16.42.1 23

Причина. Старая система лежала в userdata с таблицей разделов GPT. Резервная копия GPT хранится в последних секторах раздела. Новый образ (1,5 ГБ, таблица msdos) намного короче раздела (12,8 ГБ), поэтому хвост с резервной GPT остался. Ядро видит «испорченный основной GPT», берёт резервную, старую таблицу, и разделы оказываются не там, где их записал pmbootstrap.

Проверка: в последнем секторе раздела сигнатура EFI PART:

☯

Terminal:

⌕

≡

✕
N=$(cat /sys/class/block/mmcblk0p28/size)
dd if=/dev/mmcblk0p28 bs=512 skip=$((N-1)) count=1 | head -c 8

Исправление прямо в отладочной оболочке — затереть хвост раздела:

☯

Terminal:

⌕

≡

✕
N=$(cat /sys/class/block/mmcblk0p28/size)
dd if=/dev/zero of=/dev/mmcblk0p28 bs=512 seek=$((N-64)) count=64 conv=fsync
L=$(losetup --show -Pf /dev/mmcblk0p28); blkid ${L}p1 ${L}p2; losetup -d $L
#   p1: LABEL="pmOS_boot"   p2: LABEL="pmOS_root"   — теперь правильно
reboot -f

Чтобы не попасть в эту ловушку, перед flash_rootfs на устройство, где раньше был postmarketOS, Ubuntu Touch или любая система с GPT внутри userdata, выполняйте fastboot erase userdata.

Первая настройка

Через минуту после загрузки поднимается SSH по USB-сети:

☯

Terminal:

⌕

≡

✕
ssh <пользователь>@172.16.42.1

Если на этом же адресе раньше был другой телефон, ssh предупредит о смене ключа хоста. Чтобы не удалять старый ключ, дайте новому телефону отдельное имя: ssh -o HostKeyAlias=nexus5 <пользователь>@172.16.42.1. Если ssh-copy-id падает с Too many authentication failures, добавьте -o PubkeyAuthentication=no. Вход под root по SSH запрещён.

Корневой раздел. Initramfs растягивает раздел до конца userdata, но файловая система у меня осталась прежнего размера (957 МБ, занято 87%). Проверьте df -h / и при необходимости:

☯

Terminal:

⌕

≡

✕
sudo resize2fs /dev/loop0p2
df -h /                          # 11.9G, занято 7%

Wi-Fi. Либо сохранённый профиль:

☯

Terminal:

⌕

≡

✕
sudo install -m 600 -o root -g root <сеть>.nmconnection /etc/NetworkManager/system-connections/
sudo nmcli con reload && sudo nmcli -w 40 con up "<сеть>"

либо новая сеть: sudo nmcli device wifi connect "<сеть>" password "<пароль>". Работает только 2,4 ГГц: в прошивке нет файла brcmfmac4339-sdio.clm_blob, драйвер предупреждает об ограниченном наборе каналов.

Время. Часов реального времени у телефона нет, после загрузки дата может быть неверной:

☯

Terminal:

⌕

≡

✕
sudo timedatectl set-ntp true

Docker:

☯

Terminal:

⌕

≡

✕
sudo systemctl enable --now docker
sudo addgroup <пользователь> docker
docker run --rm hello-world

Docker 29, драйвер хранения overlayfs, cgroup v2 — всё работает из коробки.

Репозиторий пакетов. Если apk update пишет про репозиторий Nura 1 unavailable, провайдер обрывает загрузку с mirror.nura.eco. Пакеты Alpine при этом ставятся нормально. Обход — стороннее зеркало, как в статье про OnePlus One.

Ядро при обновлениях

Чтобы новое ядро после apk upgrade само попадало в раздел boot (без lk2nd), включите flash_kernel_on_update локально. boot-deploy читает /etc/deviceinfo после настроек пакета устройства, поэтому пакет трогать не нужно:

☯

Terminal:

⌕

≡

✕
sudo tee /etc/deviceinfo <<'X'
# Локальные настройки поверх /usr/share/deviceinfo/deviceinfo
deviceinfo_flash_kernel_on_update="true"
X
sudo mkinitfs            # то же, что при обновлении ядра
#   ==> Flashing boot image
#   Flashing boot.img to 'boot'

Перед этим сохраните копию раздела boot (dd выше). Проверка, что записалось:

☯

Terminal:

⌕

≡

✕
S=$(stat -c %s /boot/boot.img); head -c $S /dev/disk/by-partlabel/boot | md5sum; md5sum /boot/boot.img

Перезагрузка по SSH: sudo systemd-run --on-active=3 systemctl reboot. Вариант (sleep 2; reboot) & не работает — фоновый процесс умирает вместе с сессией.

Экранная оболочка nura-server-shell

Без графики на экране висит только nexus5 login:. Я написал для таких телефонов небольшую оболочку и выложил её на GitHub: nura-server-shell, лицензия GPL-3.0-or-later. Она работает на Nexus 5 и OnePlus One.

Установка одной командой (ключ --headless дополнительно отключает графический вход, если он был):

☯

Terminal:

⌕

≡

✕
wget -qO- https://raw.githubusercontent.com/ramanzes/nura-server-shell/main/install.sh | sudo sh -s -- --headless

Повторный запуск той же команды — обновление. Удаление: sudo ./uninstall.sh из клона репозитория, --restore-gui вернёт графику.

Что появляется на экране:

  • Табло на tty1: время, аптайм, Wi-Fi и уровень сигнала, IP, доступность шлюза и интернета, USB-сеть, контейнеры Docker, батарея, температура и загрузка CPU, память. Экран гаснет через минуту.
  • Светодиод показывает состояние: зелёная вспышка раз в 5 секунд — всё в порядке.
  • htop, консоль с экранной клавиатурой и меню.

Меню

ДействиеЧто делает
VOL+ / VOL−яркость (в htop — прокрутка, в меню — выбор пункта)
VOL+ и VOL− вместетабло ⇄ htop
VOL− дважды в htopпоказать / спрятать экранную клавиатуру
VOL− дваждыконсоль ⇄ табло
VOL+ дваждыменю ⇄ табло (и отмена ввода пароля Wi-Fi)
касание пункта менювыполнить
POWER коротковключить погасший экран
POWER 5 секундперезагрузка

В меню: подключить к Wi-Fi, перезапустить контейнеры, переподключить Wi-Fi, перезагрузить, выключить. Опасные действия — с подтверждением.

Подключение к новой сети Wi-Fi без ПК

  1. VOL+ дважды → «Подключить к Wi-Fi».
  2. Через 5–10 секунд — список до 6 сетей по силе сигнала: #/##/### — сигнал, * — текущая, + — сохранённая, open — без пароля.
  3. Касание сети. Сохранённая или открытая подключается сразу. Для новой защищённой сети открывается экран ввода пароля с экранной клавиатурой. Пароль виден при вводе, чтобы было проще не ошибиться. Пустой пароль или VOL+ дважды — отмена.
  4. В меню выводится результат: «Подключено» с IP и сигналом или текст ошибки. Профиль с неверным паролем удаляется.

Выбор сети

Ввод пароля

htop с клавиатурой

В htop VOL− дважды показывает экранную клавиатуру, htop ужимается по высоте. Функциональных клавиш на экранной клавиатуре нет, поэтому строка F1Help … F10Quit внизу htop нажимается касанием. Работают k (завершить процесс), / (поиск), t (дерево), P/M/T (сортировка), F7/F8 (приоритет), q (выход на табло). В портрете htop использует шрифт 12×24 (90 колонок), чтобы строка F1…F10 помещалась целиком.

htop

htop с клавиатурой

Поворот экрана на msm8974 недоступен. В меню есть пункт «Ориентация htop/консоли», но ядро msm8974 собрано без CONFIG_FRAMEBUFFER_CONSOLE_ROTATION: запись в /sys/class/graphics/fbcon/rotate проходит без ошибки и ничего не меняет. На Nexus 5 и OnePlus One оболочка честно пишет «Ядро не умеет поворачивать консоль». На устройствах с другим ядром (например, sdm660) поворот работает.

Итог

ЧтоРезультат
Загрузка до SSHоколо 1 минуты
Память без нагрузки~300 МБ из 1,88 ГБ
Свободно на диске~11 ГБ (из 16)
Wi-Fi2,4 ГГц
Dockerработает
Обновление ядраавтоматически, через flash_kernel_on_update

Для 32-битного телефона 2013 года это вполне рабочий маленький сервер: Docker-контейнеры, SSH, туннель наружу. При этом встроенный аккумулятор работает как ИБП, а экран показывает состояние без подключения к ПК.

Ссылки

Копирование материалов разрешается только с указанием автора Роман Александрович Сахно и индексируемой прямой ссылкой на сайт (http://itdid.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/sahroman.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/sahroman.

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как настроить свой компьютер

  2. Текстовая ссылка:

    Она выглядит вот так: Как настроить свой компьютер

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.