Адаптивный пересказ поста my server is a phone now (seg6.space). Текст и диаграммы здесь мои; за первоисточником и деталями — по ссылке. Это чужой личный проект — я лишь пересказываю его опыт.

Идея звучит как шутка: взять старый смартфон из ящика и сделать из него домашний сервер вместо оплачиваемого VPS. Но если присмотреться, телефон — это неплохой мини-сервер: несколько ARM-ядер, гигабайты памяти, флеш-накопитель, Wi-Fi, а главное — встроенная батарея, то есть бесплатный UPS. Ниже — как это довели до рабочего состояния, включая пару тупиковых поворотов (они полезнее, чем гладкая инструкция).

Зачем

Личная инфраструктура автора жила на дешёвом VPS: remote-браузер, финтрекер, screen-share, пара мелких web-приложений. Работало, но платить не хотелось — особенно за выделенный CPU, который нужен браузеру под нагрузкой. Покупать отдельную машину тоже не тянуло (память сейчас дорогая). А в ящике лежал уже оплаченный телефон с 8 ARM-ядрами, 8 ГБ RAM, 128 ГБ флеша, Wi-Fi 6 и 5G. Железо явно простаивало.

Плохая идея №1: снести Android

Первый, «чистый» вариант — прошить нормальный Linux (у телефона есть порт postmarketOS). На бумаге всё зелёное, на деле — сломаны Wi-Fi, Bluetooth, аппаратное ускорение и половина того, что делает телефон полезным как сервер. Итог: сплэш-экран, потом чёрный экран — ни сервера, ни телефона. Восстановление стоковой прошивки превратилось в отдельный квест (утилита требовала Windows, USB-passthrough, драйверы MediaTek, soft-brick и почти-кирпич).

Вывод, который стоит запомнить до того, как повторять: у Android уже есть рабочие драйверы на всё это железо — Wi-Fi, питание, батарею, GPU, модем. Выбрасывать их ради «привычного» Linux — плохая сделка. Телефону не нужно становиться обычной Linux-машиной. Нужно, чтобы он надёжно запускал Linux-приложения, пока Android продолжает делать свою низкоуровневую работу.

Termux как хост-система

Второй заход: оставить сток-Android, а хостом сделать Termux . Termux даёт OpenSSH, runit, Caddy, Cloudflared, пакетный менеджер и достаточно юниксового окружения. Termux:Boot поднимает супервизор и SSH после ребута, а Tailscale даёт телефону стабильный приватный адрес — и с любой машины в своей сети можно просто:

BASH
ssh cmf
Нажмите, чтобы развернуть и увидеть больше

Важный нюанс: Termux — не виртуальная машина. Его процессы работают прямо на ядре Android, но userspace на Bionic достаточно отличается от Debian, чтобы обычные Linux-образы просто так в нём не завелись. Это ограничение обернулось плюсом: Termux остаётся маленьким «control plane» хоста, а каждое приложение приносит свою Linux-файловую систему.

Отдельная боль — управление питанием. Для телефона оно отличное, для «сервера» — вредное: Android агрессивно усыпляет фон. Поэтому в host-профиль (применяется через Ansible) входят: persistent wake lock, отключение idle-режимов, вывод Termux / Termux:Boot / Tailscale из-под фоновых ограничений, запрет засыпания Wi-Fi и Tailscale как always-on VPN.

Важнее любой отдельной настройки — цепочка восстановления, чтобы телефон переживал ребут без участия человека:

Цепочка автозапуска и два слоя: Android+Termux как хост, rooted Linux residents как приложения

Порядок такой: Android загрузился → always-on VPN поднял Tailscale → Termux:Boot стартовал runitrunit поднял все сервисы → health-check проверил локальный и публичный путь. Ни systemd, ни обычного Docker-демона здесь нет — и не нужно притворяться, что они есть. Это Linux-ядро с дееспособным userland, и этого достаточно.

Плохая идея №2 (наполовину): proot, потом chroot

Приложения уже собраны как OCI-образы под ARM64. Запустить их под Debian помог proot-distro: PRoot в userspace перехватывает файловые и процессные вызовы и заставляет обычный Termux-процесс думать, будто он внутри Debian-rootfs. Это не граница контейнера (общие ядро, сеть и UID), но как слой совместимости — прекрасно: не нужен ни root, ни специальное ядро.

Обычные web-сервисы так и поехали: у каждого — своя проверенная rootfs, loopback-порт и runit-сервис, а Caddy в Termux роутит hostname на нужный порт. Исключением стал latency-чувствительный браузерный workload: старт процессов, открытие библиотек, обход путей, чтение профилей — всё это шло через userspace-трансляцию PRoot. CPU был, но браузер не мог до него эффективно дотянуться.

Решение — не заменить Android, а получить нативные syscalls: телефон рутанули, чтобы смонтировать ту же Debian-ФС по-нормальному и войти в неё настоящим chroot. Жизненным циклом по-прежнему владеет runit из Termux, конфиг — из того же места, данные — в хранилище Termux; workload просто дошёл до ядра Android напрямую. Разница в отзывчивости оказалась заметной, и после этого мелкие сервисы тоже перевели на chroot.

Схема установки: рабочая станция резолвит ARM64-образ в точный digest и экспортирует его ФС; Ansible проверяет и ставит на телефон; маленький root-helper создаёт приватный mount namespace, биндит нужные пути, входит через chroot, сбрасывает привилегии и запускает штатный entrypoint образа. Ни Docker, ни компилятор на телефоне не нужны.

Отдельная поучительная неудача: попытка пробросить графику Debian на GPU Mali через VirGL/Vulkan дала «галочки» аппаратного композитинга — вместе с битыми страницами и худшей производительностью. Скучный софтварный рендер оказался быстрее. Иногда правильный ответ — не гнаться за ускорением.

Инфраструктура, а не свалка из истории команд

Чтобы это не был «питомец», собранный из команд, которые забудешь через неделю, весь хост загнали в Ansible-managed state: версии, определения сервисов, роуты, настройки питания, секреты и health-check — в одном приватном репозитории.

Поток деплоя примерно такой:

PLAINTEXT
релиз / OCI-образ
  → digest/checksum, зафиксированный в Git
  → Ansible по SSH
  → версионированные файлы на телефоне
  → атомарный симлинк current
  → runit-сервис
  → локальный health-check
  → публичный edge-check
Нажмите, чтобы развернуть и увидеть больше

Релизы прибиты по digest/checksum и ставятся в версионированные каталоги за атомарным симлинком current. Провал контрольной суммы или health-check останавливает деплой; откат — вернуть pin и применить заново. Данные приложений лежат отдельно от релизов. После маленького ручного bootstrap (поставить три Android-приложения, рутануть, дать Termux root, авторизовать SSH) остальным владеет репозиторий:

BASH
make phone
make phone-status
make phone-edge-check
Нажмите, чтобы развернуть и увидеть больше

Повторный прогон не трогает неизменившиеся файлы и не перезапускает здоровые сервисы. И — что ценно — если этот телефон умрёт, другой rootable ARM64-телефон приводится к тому же состоянию без реконструкции истории команд.

Секреты на телефоне не хранятся вовсе: они зашифрованы Ansible Vault в репозитории, а пароль от Vault добывается подписью фиксированного challenge через 1Password SSH-agent — приватный ключ остаётся в 1Password, телефон к нему доступа не имеет. При деплое на телефон попадают только нужные runtime-значения.

Как трафик доходит до телефона

Домашний интернет не даёт статики «как на VPS», выставлять SSH и случайные порты через роутер не хочется, а ещё телефон должен оставаться телефоном: отключил, унёс, подключил к другому Wi-Fi — сервер работает.

Трафик доходит до телефона через исходящие соединения: Cloudflare Tunnel для web, Tailscale для администрирования, WebSocket-обёртка для Surf

Стоит ли так делать?

Честно — это скорее увлекательный хак, чем «правильный» сервер, и относиться к нему стоит соответственно:

За:

Против:

Если нужен предсказуемый прод — берите VPS или мини-ПК. Но как способ не выбрасывать хорошее железо, разобраться в Android/Termux/Linux-userspace и получить портативный сервер с батарейкой — затея на удивление рабочая. Главное — не выкидывать то, что и так уже работает (драйверы Android), в погоне за «более правильным» устройством.

Авторские права

Автор: Vasiliy Fakunin

Ссылка: https://notes.melancholic.tech/posts/phone-as-server/

Лицензия: CC BY-NC-SA 4.0

Использование материалов блога разрешается при условии: указания авторства/источника, некоммерческого использования и сохранения лицензии.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша