The PocketServer Journey

A log of problems we hit, how we debugged them, and what we fixed. A phone running as a 24/7 headless server is uncharted territory.

Problems & Fixes

FIX 30-Minute Service Restart Loop

Problem: The boot script was re-triggered every 30 minutes, running pm disable-user on 109 packages each time. This hammered Android's PackageManager, froze the UI, killed WiFi overnight, and eventually caused the phone to hang completely (touch unresponsive, ADB unreachable).

Root Cause: Android's init.rc defined the boot service with boot-wrapper.sh, which called the boot script then sleep 1800 (30 min). When sleep ended, init restarted the service, creating an infinite 30-minute loop.

Fix: Changed boot-wrapper.sh to call boot-auto.sh directly (not backgrounded). boot-auto.sh now ends with a health monitor loop that never exits, so init never restarts it.

PERF CPU Governor: performance to schedutil

Problem: All 8 CPU cores were locked at max frequency 24/7, generating excessive heat and draining battery even when idle.

Fix: Switched CPU governor from performance to schedutil. The CPU now scales dynamically — low frequency when idle, full speed when Ollama processes a query. Same peak performance, fraction of the heat.

FEAT Health Monitor with Auto-Reboot

Problem: When services died, the watchdog and cron (both inside the chroot) also died. Nothing could bring them back without a manual reboot.

Fix: Added an Android-side health monitor (outside the chroot) that checks supervisord every 2 minutes. If dead for 3 consecutive checks (6 min), it tries to restart services. If that fails, it reboots the phone automatically.

PERF Aggressive Android Debloat

Problem: ~50 unnecessary Android services running (Play Store, Gboard, Bluetooth, dialer, carrier apps, etc.) consuming over 3 GB RAM.

Fix: Disabled 150+ packages via pm disable-user. Freed ~3 GB RAM. Added GMS background restriction. Disabled Google Play Services entirely.

FIX Persistent Logging

Problem: When the phone crashed/rebooted, all diagnostic logs were lost (kernel dmesg and logcat clear on reboot).

Fix: Added persistent health log at /sdcard/server-health.log that records memory, swap, CPU load, and process count every 5 minutes. Also logs service restarts and auto-reboots. Survives phone reboots.

FIX Magisk Module Removed

Problem: The Magisk module at /data/adb/modules/android-server/service.sh was never the actual boot mechanism. Boot was triggered by init.rc directly. The Magisk module was a no-op causing confusion during debugging.

Fix: Removed the Magisk module and uninstalled the Magisk app. Boot is handled entirely by init.rcboot-wrapper.shboot-auto.sh.

Architecture (Current)

Phone Boot
  |
  v
init.rc (on sys.boot_completed=1)
  |
  v
boot-wrapper.sh (never exits)
  |
  v
boot-auto.sh
  |-- System tweaks (schedutil, swappiness 60, screen off 5min)
  |-- Debloat 150+ packages
  |-- WiFi reconnect
  |-- Swap enable (8GB ZRAM + 8GB file)
  |-- Chroot mount (/data/local/linux/rootfs)
  |-- Start services (sshd, cron, supervisord, tailscale)
  |-- Health monitor loop (runs forever)
        |-- Check supervisord every 2 min
        |-- Try restart if dead
        |-- Auto-reboot after 3 failures (6 min)

Inside chroot (Supervisor manages):
  |-- ollama (port 11434)
  |-- ollama-chat (port 5000) + Tailscale Funnel
  |-- scheduler (APScheduler)
  |-- watchdog (restarts sshd, tailscale, cron, supervisor)
        

Key Files

/system/etc/init/android-server.rcinit.rc service definition
/data/local/linux/boot-wrapper.shThin wrapper (never exits)
/data/local/linux/boot-auto.shMain boot logic + health monitor
/data/local/linux/boot.logBoot log (per-boot)
/sdcard/server-health.logPersistent health log (survives reboots)
/data/local/linux/rootfs/Ubuntu 22.04 chroot
/opt/server/ollama-chat/server.pyFlask app (this UI)