Делаем сервер из Android-телефона
Некоторое время назад мне пришла в голову интересная идея — превратить свои старые телефоны (их скопилось немало за десять лет) в серверы, в качестве альтернативы покупке Raspberry Pi.
На то было несколько причин: во-первых, у телефонов есть батарея, что для сервера практически бесплатный мини-UPS, во-вторых, внутренняя память смартфона (UFS) работает быстрее и надёжнее, чем SD-карта. В-третьих, у телефонов имеется экран, по которому можно отслеживать состояние сервера.
Ну и в-четвёртых, мне просто было жаль их выбрасывать. Консьюмеризм в наше время предписывает каждый год-два покупать новые смартфоны, производители блокируют возможности железа, которые им невыгодны, прекращают поддержку старых моделей, оставляя людей беспомощными. Миллионы смартфонов отправляются на свалку истории каждый год, хотя каждый из них это мощный компьютер.
TL;DR: в этом посте будут разобраны вопросы установки PostmarketOS на смартфон,
поднятия на нём в качестве примера Docker и веб-приложения в нём.
Сразу хочу оговориться — я понимаю, что есть типовые решения, например Termux или UserLAnd, и спектр поддерживаемых устройств у них шире. Но все они работают как надстройки над основной системой, Android, и подвержены её ограничениям, таким как агрессивное сокращение энергопотребления или перенос задач на LITTLE-ядра при выключении экрана. Будущее Termux, например, вообще неясно из-за всё более жёстких гаек безопасности в Android 11. UserLAnd, помимо этого, работает через PRoot, который при всей своей пользе ощутимо замедляет процессы с большим количеством системных вызовов. В этой статье мы разбираем именно создание сервера на железе без Android.
Часть первая. Прошивка
Проект PostmarketOS был создан именно ради этой цели — сохранение вычислительных устройств после прекращения их поддержки производителями. Список поддерживаемых устройств можно найти здесь.
Для установки требуется телефон с разблокированным загрузчиком. В качестве примера буду использовать OnePlus One из-за простоты разлочки со стороны производителя. Для каждого производителя список шагов разный, ниже привожу обобщённые действия для смартфона 2018-2021 года выпуска:
$ sudo apt install adb fastboot
$ # подключаем телефон к USB
$ adb devices
$ # должен показать устройство в статусе unauthorized
Далее авторизуем подключение на самом телефоне
$ adb devices
$ # теперь должен показать нормальный статус "device"
$ adb reboot bootloader
$ # смартфон перезагружается в режим fastboot
$ # команда может отличаться от oem unlock, уточняйте шаги для вашего производителя
$ fastboot oem unlock
$ # теперь должен показать дисклеймер и уточнить намерения, подтверждаем...
После разблокировки телефон сбросит данные снова перезагрузится в Android, перезапустите его в режим fastboot комбинацией клавиш или повторите релевантные для этого шаги 3 и 4.
Если разблокировка прошла успешно, далее можно следовать стандартной процедуре установки PmOS:
$ sudo apt install python3-pip git
$ python3 -m pip install --user pmbootstrap
$ export PATH="$HOME/.local/bin:$PATH"
$ pmbootstrap init
На этом этапе pmbootstrap
запросит пароль и задаст довольно много вопросов о том, как сконфигурировать систему и целевое устройство. Итоговый результат будет записан в ~/.config/pmbootstrap.cfg
.
Пару слов по поводу разных конфигураций. Здесь есть несколько важных пунктов — ядро mainline
или downstream
, графическая среда mate
, weston
и т.д., канал обновлений edge
или stable
. Интуиция при выборе значений должна быть такой:
- Если планируете пользоваться графикой, ставьте пароль из цифр. Некоторые графические среды поддерживают только цифровую клавиатуру на экране ввода пин-кода.
- Выбирайте
edge
в качестве канала обновлений. PostmarketOS разрабатывается быстро, и много опакеченного ПО ещё долго не будет вstable
. - Выбирайте ядро
downstream
если хотите максимум работающей "из коробки" второстепенной периферии после установки. Выбирайте ядроmainline
если вам нужен OpenGL/OpenCL и современные возможности ядра, такие как контейнеризация и cgroups. - Выбирайте графическую систему
phosh
,sway
илиplasma-mobile
если у ваc ядроmainline
и имеется графическое ускорение. В противном случае остановитесь наmate
илиxfce4
. Внимательно смотрите страницу вики для вашего устройства.
[pmbootstrap]
aports = /home/kanedias/.local/var/pmbootstrap/cache_git/pmaports
ccache_size = 5G
is_default_channel = False
device = oneplus-bacon
extra_packages = rsync,vim,networkmanager,bluez
hostname = lab-of-maker
build_pkgs_on_install = True
jobs = 17
kernel = mainline
keymap =
locale = en_US.UTF-8
nonfree_firmware = True
nonfree_userland = False
ssh_keys = True
timezone = Europe/Moscow
ui = sway
ui_extras = False
user = kanedias
work = /home/kanedias/.local/var/pmbootstrap
boot_size = 128
extra_space = 0
sudo_timer = False
Затем с помощью pmbootstrap install
сразу же начинаем сборку образа целевой системы. После сборки её предлагается установить самому, так как механизм установки варьируется от модели к модели. Пример того, как это делается стандартно, и как вышло у меня, ниже.
$ # прошиваем основную систему, библиотеки, модули ядра
$ pmbootstrap flasher flash_rootfs
$ # прошиваем ядро и initramfs
$ # можно использовать pmbootstrap flasher boot для проверки загрузки перед этим
$ pmbootstrap flasher flash_kernel
Есть хорошие шансы, что всё сработает как надо с первого раза. К сожалению, загрузчики и реализацию fastboot каждый производитель телефонов пишет по-своему, отчего попытки установки превращаются в смерть от тысячи иголок. В моём случае fastboot наотрез отказывался прошивать образы такого размера. Пришлось воспользоваться сторонним recovery, чтобы продвинуться дальше:
$ # собираем образ для установки напрямую на устройстве через TWRP
$ pmbootstrap install --android-recovery-zip
$ # скачиваем TWRP для нужного устройства, см. https://twrp.me/Devices/
$ fastboot boot twrp-3.5.2_9-0-bacon.img
$ # на экране телефона выбираем Advanced -> ADB Sideload -> Start sideload
$ pmbootstrap flasher --method=adb sideload
После завершения процесса sideload жмём "Reboot to system". Должен пойти процесс загрузки ядра и далее самой PostmarketOS.
Часть вторая. Настройка PostmarketOS
По сути своей, PostmarketOS построена на основе дистрибутива Linux под названием Alpine. Это позволяет создать работающую систему минимального размера, что для большого количества старых устройств с ограниченной внутренней памятью критично.
Однако, есть и подводные камни. О них ниже:
- Alpine построен на основе лаконичного libc под названием Musl. Плохая новость тут в том, что большинство других дистрибутивов работает на основе glibc, что означает невозможность установки ПО простым переносом бинарников с Raspbian или Ubuntu ARM, как позволяет, например, Golang или Rust.
- Система инициализации в дистрибутиве — OpenRC. Если вы знакомы с Gentoo, это для вас не будет озарением, но OpenRC куда ближе к прародителю sysvinit, чем к общепринятому в индустрии systemd. Имейте в виду.
- Для уменьшения размера используется Busybox, поэтому команды
grep
/sed
/find
и т.д. имеют ограниченный набор опций по умолчанию. Устанавливайте их GNU-версии и стандартный Bash-шелл отдельно, чтобы получить полный набор.
Итак, после загрузки телефона с PostmarketOS нам необходимо каким-то образом с ним взаимодействовать. Если вы ставили оболочку Phosh или Plasma Mobile, скорее всего вы сможете это сделать напрямую с тачскрина телефона. Если по каким-то причинам графический интерфейс не сработал, подключайте телефон к компьютеру USB-кабелем, PostmarketOS автоматически создаст дополнительную сеть:
После чего к телефону можно будет подключиться с именем и паролем пользователя, который вы указывали при pmbootstrap install
:
$ ssh [email protected]
[email protected] password:
$ sudo cat /etc/os-release | head -3
PRETTY_NAME="postmarketOS edge"
NAME="postmarketOS"
VERSION_ID="edge"
Если вы видите эти строчки — значит PostmarketOS установлена верно. В противном случае попробуйте посмотреть секцию Troubleshooting для вашего устройства на вики PmOS, измените конфигурацию для pmbootstrap install
или спросите мейнтейнеров в IRC или Matrix чате (все три пункта ваш покорный слуга в итоге и сделал).
Настройка сети
Если не получилось настроить WiFi сеть через графическую оболочку, ниже пример как сделать это через консоль. Предварительно подключите телефон к USB-интерфейсу вашего ПК.
Выполните на ПК:
# разрешаем интерфейсам, подключённым по USB, ходить в интернет через нас
$ sudo sysctl net.ipv4.ip_forward=1
$ sudo iptables -P FORWARD ACCEPT
$ sudo iptables -A POSTROUTING -t nat -j MASQUERADE -s 172.16.42.0/24
Выполните на телефоне:
$ # делаем наш подключённый по USB ПК основным сетевым шлюзом для телефона
$ sudo route add default gw 172.16.42.2
$ echo nameserver 1.1.1.1 | sudo tee /etc/resolv.conf
$ # теперь у нас есть интернет на телефоне, правда пока только через USB-кабель
Далее, снова на телефоне:
$ # обычно если ip link show показывает беспроводной интерфейс, этого достаточно
$ # если нет, убедитесь, что firmware-пакеты для вашего устройства установлены
$ sudo apk add networkmanager
$ sudo rc-update add networkmanager
$ sudo /etc/init.d/networkmanager start
$ nmtui
$ # далее подключаемся к WiFi через интерфейс NM
Настройка Bluetooth
Если на вики указана поддержка bluetooth, пробуем так:
$ sudo apk add bluez
$ sudo rc-update add bluetooth
$ sudo /etc/init.d/bluetooth start
$ # далее подключаемся к мыши/клавиатуре/наушникам (должно быть в режиме pairing)
$ bluetoothctl
Agent registered
[CHG] Controller 00:00:00:00:5A:AD Pairable: yes
[bluetooth]$ power on
Changing power on succeeded
[CHG] Controller 00:00:00:00:5A:AD Powered: yes
[bluetooth]$ scan on
Discovery started
[CHG] Controller 00:00:00:00:5A:AD Discovering: yes
[NEW] Device D6:3B:32:01:3D:DD TEST-DEVICE
[bluetooth]$ pair D6:3B:32:01:3D:DD
Attempting to pair with D6:3B:32:01:3D:DD
[CHG] Device D6:3B:32:01:3D:DD Connected: yes
Если всё прошло как надо, на графическом интерфейсе увидите мышку и/или пропадёт экранная клавиатура.
Настройка диска
PostmarketOS как правило устанавливает себя в раздел system
, то место, где Андроид обычно хранит системные библиотеки, настройки и приложения. Размер этого раздела ограничен, и для каталогов /home
или /var/lib/docker
имеет смысл выбрать раздел побольше. На Андроиде это, как правило, userdata
:
$ ls -lh /dev/disk/by-partlabel/ | grep userdata
lrwxrwxrwx 1 root root 16 May 5 1970 userdata -> ../../mmcblk0p28
$ sudo mkfs.ext4 /dev/mmcblk0p28
$ sudo mkdir -p /var/lib/docker
$ sudo mount /dev/mmcblk0p28 /var/lib/docker
Готово, теперь будущий докер не съест всё системное место за секунды.
Настройка Docker
Здесь должен был быть большой раздел про пересборку ядра и быстрый экскурс в pmbootstrap kconfig
Благодаря недавним изменениям в конфигурации ядра PostmarketOS, докер и другие системы контейнеризации должны работать из коробки на любом устройстве, достаточно установить (apk add docker
) и запустить (/etc/init.d/docker start
) сервис.
На PostmarketOS действует рудиментарный фаервол в виде правил nftables
, сперва разрешаем трафик с интерфейса WiFi. Создайте файл /etc/nftables.d/52_wlan_inet.nft
с таким содержимым:
table inet filter {
chain input {
iifname "wlan*" accept comment "Allow incoming network traffic from WLAN"
}
chain forward {
iifname "wlan*" accept comment "Allow outgoing network traffic from WLAN through us"
ct state {established, related} counter accept comment "accept established connections"
}
}
Затем выполняем:
$ # сперва перезагружаем фаервол
$ /etc/init.d/nftables restart
* Caching service dependencies ... [ ok ]
* Stopping firewall ... [ ok ]
* Loading nftables state and starting firewall ... [ ok ]
$ # запускаем сервис, для примера возьмём персональное облако NextCloud
$ docker run --rm -d -p 80:80 nextcloud
Далее на локальном компьютере открываем http://<ip-адрес-телефона>
и смотрим, что получилось:
Часть третья. Заключение
Какие выводы я сделал, проведя такой опыт переноса своих сервисов на телефон? Самое главное — делайте это только убедившись, что точно хотите окунуться в неизвестное и сможете потратить на это 2-4 дня, а может и больше. Сильно поможет, если устройство хорошо поддерживается сообществом, ну и конечно если идеи свободного ПО и переиспользования вам близки :)
В моём случае оказалось, что таким устройством, как у меня, никто из разработчиков не обладает, и пришлось добавлять драйверы производителя, поддержку батареи и её зарядки в ядре и следить за обновлениями, чтобы изменения не потерялись. Тем не менее, после настройки телефон работает как полноценный сервер NextCloud, синхронизируя календарь, файлы и задачи, и потребляя при этом всего 2.5 Вт энергии.
Я выкладываю эту инструкцию в надежде, что она окажется полезной, но не предоставляю никаких гарантий работоспособности результата. Если вы столкнулись с проблемами, пишите в комментарии или в Matrix-каналы разработчиков PostmarketOS, будем разбираться.