2016年ごろの OUKITEL K10000(Android 6.0 / armv7 / 内蔵12GB + 採用済みSD約29GB)を Termux で LAN 内 Web サーバーにし、公開リポジトリの実務アプリ(駐車券記録: PHP + SQLite)まで載せた。型落ち端末の二次利用メモ。
構成
Termux は android-21 向け旧リポジトリ(packages-cf.termux.dev/apt/termux-main-21)。SSH は Termux 既定の 8022。公開鍵ログイン。Web は busybox httpd が 8080、駐車券アプリは PHP 内蔵サーバーが 4500。
LAN クライアント
│
├─ :8022 sshd (Termux OpenSSH)
├─ :8080 busybox httpd (ドキュメントルート = 外部ストレージ)
└─ :4500 php -S ($HOME/parking-ticket-app)
注意
- パスワード・秘密鍵の実値は記事に書かない。公開鍵認証にしたらパスワードログインは止める。
- Termux をスワイプで殺すと sshd / httpd / php も全部止まる。バッテリー最適化は「制限なし」寄りにする。
- 外部SD(
/storage/emulated/0)は FUSE +noexec。バイナリや PHP アプリ本体は置けない。 pkg installの行き先は常に内部$PREFIX(/data/data/com.termux/files/usr)。
1. SSH(公開鍵)
PC 側で専用 ed25519 を作り、初回だけパスワードで ~/.ssh/authorized_keys に載せる。Termux の SSH ユーザー名はログイン名と whoami(例: u0_a84)が違うことがある。両方で鍵認証できるか確認する。
# PC ~/.ssh/config 例
Host K10000
HostName 192.168.0.x
User u0_a84
Port 8022
IdentityFile ~/.ssh/id_ed25519_k10000
IdentitiesOnly yes
PreferredAuthentications publickey
2. ストレージの役割分担
MTK の共有SD(ro.mtk_shared_sdcard=1)だと、設定 → アプリ → Termux → ストレージに「SDカードに変更」が出ないことが多い。出なくても問題ない。アプリ移動非対応の Termux を無理に移すと壊れる。
- 内部
/data(約12GB): Termux 本体、$PREFIX、Python / PHP / Node、アプリコード、SQLite - 外部
/storage/emulated/0(約29GB): Download / DCIM / 公開ファイル。httpd のドキュメントルート向き
3. ファイルサーバー(8080)
追加パッケージなしで busybox httpd が使える。ルートを外部ストレージにして、トップに簡易ポータルを置く。この busybox はディレクトリ一覧が無いので、フォルダ用 index.html を生成するか、別サーバーにする。
busybox httpd -p 0.0.0.0:8080 -h /storage/emulated/0 -c ~/www-httpd.conf
IP は DHCP で変わるので、トップの二次元バーコードは静的画像にしない。開いた location.host から JS(qrcode-generator)で毎回生成する。localhost で開いたとき用に、起動スクリプトが今の wlan0 アドレスを lan.js に書く。
4. ランタイム(termux-main-21)
Android 6 でも旧リポジトリから入る。実機で起動確認済み:
- Python 3.8.0
- PHP 7.3.10(pdo_sqlite / sqlite3 付き)
- Node.js 13.0.0 + npm 6.12.0
合計およそ 200MB。内部の空きがあれば足りる。外部へはインストールできない(実行不可)。
5. 実務アプリ: 駐車券記録
対象: kuwa2005/parking-ticket-app(PHP + SQLite + Bootstrap、本来は PHP 8.3 / Docker)。Termux の PHP 7.3 でも動くが、本番コードのアロー関数 fn()(PHP 7.4+)が1箇所あるので通常の function に直す。
# アプリは $HOME へ(SD は noexec / SQLite 書き込みも内部の方が安定)
php -S 0.0.0.0:4500 -t ~/parking-ticket-app
確認例(実値の認証情報は載せない):
curl -sS http://<LAN-IP>:4500/ | grep title
curl -sS http://<LAN-IP>:4500/api.php?action=today
curl -sS -H 'Content-Type: application/json' -d '{"count":1}' \
http://<LAN-IP>:4500/api.php?action=add
8080 のトップ先頭に「駐車券」カードを追加し、ホスト名だけ差し替えて :4500 へ飛ばす。管理用パスワードはアプリ側の設定ファイルで変える(記事には書かない)。
6. 一括起動 / 自動起動
~/start-servers.sh で wake-lock + sshd + httpd + php を冪等起動。既に listen していれば触らない。--restart で強制再起動。
- Termux を開いたとき:
~/.bashrcから quiet 実行 - 電源オン自動: Termux:Boot が別途必要。入れたら
~/.termux/boot/00-start-servers.shが走る - Android 単体では Termux は起動しない
ハマりどころ
- 設定アプリに入ると Termux が殺され、8022 / 8080 が Connection refused になる。戻ったら Termux を前面に出して
sshd→bash ~/start-servers.sh。 - busybox httpd の CGI はこのビルドでは使えない。PHP は
php -Sを別ポートで。 - SD 上のファイルは
chmod +xも効かない。スクリプトは$HOMEに置く。 - scp で SD 上の既存
index.htmlを上書きできないことがある。rmしてからcp。 - game/science リポジトリの GPG 期限切れ警告は出るが、main-21 からランタイムは入る。
Android Webサーバーの限界
型落ち Android + 旧 Termux(android-21)は「LAN 内の軽い実務」までが上限。現行のフロント開発スタックや本格 RDBMS を端末上で回す用途ではない。
OS・プロセス
- Android 6 / API 23。現行 Termux(Android 7+ 前提)には上げられない。
- Termux をスワイプ・設定画面遷移で殺すと sshd / httpd / php が全部止まる。常時稼働サーバーではない。
- RAM 約 2GB(使用中すでに 0.8GB 前後)。常駐プロセスを増やすとすぐ苦しい。
- インターネット公開はしない(OS も認証も古い)。部屋・会場の LAN / テザリング専用。
ストレージ
pkgの実体は内部$PREFIX固定。外部 SD は FUSE +noexecでバイナリ実行不可。- MTK 共有 SD だと「アプリを SD に変更」ボタン自体が出ないことが多い。Termux は移動非対応。
データベース(実機で確認)
- SQLite: 動く。PHP
pdo_sqlite/ Pythonsqlite3 3.30.1。ローカルアプリはこれ一択。 - MySQL 公式サーバ: パッケージ無し。
- MariaDB 10.4: apt にあるが導入約 145MB + mysqld 常駐。この端末では非推奨。
- PostgreSQL 11.5: 導入約 20MB。余地はあるが現場アプリには過剰。
- Redis 5.0: 導入約 2.4MB。キャッシュ・順番待ち向き。
- PHP には
pdo_mysql/mysqli(クライアント)がある。サーバは別マシン、という分担は可能。
Node / フロント(実機で確認)
- apt から入る最大は Node.js 13.0.0(導入済)。LTS は 12.13。14 以降はリポジトリに無い。
- npm 6.12 自身が Node 13 非対応と警告する。
- Vite 8(8.0.0〜8.0.14):
engines.nodeは^20.19.0 || >=22.12.0。端末上のvite dev/vite buildは不可。 - Vite 3〜7 も Node 14.18+ または 18+ が必要で、同様に不可。
- React(ライブラリ)はブラウザ JS。PC でビルドした
dist/を httpd に置けば配信できる。端末上で JSX をコンパイルしない。 - esbuild の android-armv7 公式バイナリも期待できないので、古い Vite 2 でも実質ビルド不可。
実務の分け方: PHP + SQLite は端末で完結。React / Vite は PC でビルド → K10000 は静的配信。重い DB が必要なら別 PC の MariaDB に pdo_mysql でつなぐ。
チェックリスト
- 公開鍵で
ssh -p 8022できる http://<LAN-IP>:8080/にポータルと QR(動的)http://<LAN-IP>:4500/で駐車券 UI、api.php?action=todayが JSONbash ~/start-servers.shで 8022 / 8080 / 4500 が listen- Termux のバッテリー制限を緩める。必要なら Termux:Boot
- 限界を把握: SQLite は可 / MariaDB・Vite 8 は端末上不可 / React は dist 配信のみ

コメント