Push Tracker
ria-ran--sim-drop/plan/09-android.md
A ashkan@beigi.net 8672b0de6b Add Phase-1 eSIM provisioning implementation
Full working closed-loop eSIM provisioning stack (spec in claude.md / plan/):
Flask API, SQLite subscriber store, credential/profile generator, Open5GS
and free5gc core adapters, captive portal, operational scripts, systemd
units, network configs, and a 44-test suite.

Profile generation currently returns a mock JSON profile; real SGP.22
generation via pySim is the planned Phase-2 upgrade.

Fixes two bugs found while getting the suite green:
- generate_imsi hardcoded a 10-digit MSIN, producing 16-digit IMSIs for a
  3-digit MNC; MSIN length is now 15 - len(mcc) - len(mnc).
- check_rate_limit compared timestamps as strings across mismatched formats
  (SQLite CURRENT_TIMESTAMP vs Python isoformat); both sides now normalized
  via SQLite datetime() so the window check is chronologically correct.

Add .gitignore for venv, caches, runtime config.yaml, and databases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 05:56:31 +00:00

4.6 KiB

Unit 09 — Android / Termux Deployment

Goal

Automated setup script and instructions for running the provisioning stack on Android via Termux (no root required for basic operation).

Files

  • android/README.md
  • android/termux_setup.sh

Constraints & Differences from Raspberry Pi

Feature Raspberry Pi Android (Termux)
WiFi AP hostapd (full control) Android Settings hotspot (limited)
DNS hijacking dnsmasq full control Limited without root
Port 80 Direct Need port >1024 or root; use 8080
Captive portal trigger iptables redirect Relies on OS captive portal detection
Systemd Yes No — use Termux boot scripts

android/termux_setup.sh

#!/data/data/com.termux/files/usr/bin/bash
set -euo pipefail

echo "=== eSIM Provisioning Server — Termux Setup ==="

# Update Termux packages
pkg update -y && pkg upgrade -y

# Install core dependencies
pkg install -y python python-pip nginx

# Install Python dependencies
pip install flask cryptography pymongo pyyaml requests

# Create directory structure
INSTALL_DIR="$HOME/esim-provisioning"
mkdir -p "$INSTALL_DIR"/{server/core_adapters,portal/{css,js,assets},scripts,tests,data}

# Copy server code (assumes script run from repo root)
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cp -r "$SCRIPT_DIR/server" "$INSTALL_DIR/"
cp -r "$SCRIPT_DIR/portal" "$INSTALL_DIR/"
cp -r "$SCRIPT_DIR/scripts" "$INSTALL_DIR/"
cp "$SCRIPT_DIR/config.yaml.example" "$INSTALL_DIR/config.yaml"

# Configure for Android (port 8080, data path in home)
sed -i 's|port: 5000|port: 8080|' "$INSTALL_DIR/config.yaml"
sed -i "s|/opt/esim-provisioning/data|$INSTALL_DIR/data|" "$INSTALL_DIR/config.yaml"

# Configure nginx for Android (port 8080 as reverse proxy target)
cat > "$PREFIX/etc/nginx/nginx.conf" << 'EOF'
worker_processes 1;
events { worker_connections 64; }
http {
    server {
        listen 8080 default_server;
        server_name _;
        location /activate {
            alias /data/data/com.termux/files/home/esim-provisioning/portal/;
            index index.html;
        }
        location /css/ { alias /data/data/com.termux/files/home/esim-provisioning/portal/css/; }
        location /js/ { alias /data/data/com.termux/files/home/esim-provisioning/portal/js/; }
        location /api/ { proxy_pass http://127.0.0.1:5000; }
        location / { return 302 http://192.168.43.1:8080/activate; }
    }
}
EOF

# Initialize database
cd "$INSTALL_DIR"
CONFIG_PATH=config.yaml python scripts/init_db.py

# Create start script
cat > "$INSTALL_DIR/start.sh" << 'STARTEOF'
#!/data/data/com.termux/files/usr/bin/bash
cd ~/esim-provisioning
echo "Starting eSIM provisioning server..."
nginx
CONFIG_PATH=config.yaml python -m server.app &
echo "Server started. Access at http://192.168.43.1:8080/activate"
echo "To stop: pkill nginx && pkill python"
STARTEOF
chmod +x "$INSTALL_DIR/start.sh"

# Termux:Boot integration (auto-start on reboot)
mkdir -p "$HOME/.termux/boot"
cp "$INSTALL_DIR/start.sh" "$HOME/.termux/boot/esim-provisioning.sh"

echo ""
echo "=== Setup Complete ==="
echo ""
echo "Next steps:"
echo "1. Enable WiFi Hotspot in Android Settings"
echo "   - SSID: Emergency-5G (or any name)"
echo "   - No password"
echo "2. Run: ~/esim-provisioning/start.sh"
echo "3. Users connect to hotspot and visit http://192.168.43.1:8080/activate"
echo ""
echo "Note: Install Termux:Boot app for auto-start on reboot"

android/README.md

Prerequisites

  • Android 9+
  • Termux app (from F-Droid, NOT Play Store)
  • Optional: Termux:Boot (for auto-start)
  • 5G-capable device with pre-provisioned SIM for gNB backhaul

Installation

# In Termux:
cd /path/to/esim-provisioning
bash android/termux_setup.sh

Starting the Server

~/esim-provisioning/start.sh

WiFi Hotspot Setup

  1. Android Settings → Network → Hotspot
  2. Set name to Emergency-5G (optional, any name works)
  3. Remove password (open network)
  4. Enable hotspot

Captive Portal Limitation

Android's captive portal detection requires DNS manipulation. Without root, clients must navigate manually to http://192.168.43.1:8080/activate. With root + Termux, dnsmasq can be used for full DNS hijacking.

Known Android Hotspot IPs

  • Most Android: 192.168.43.1
  • Samsung: 192.168.0.1 or 192.168.43.1
  • Pixel: 192.168.43.1

Update config.yaml and nginx config with your device's hotspot IP.


Verification

# On Android in Termux:
~/esim-provisioning/start.sh
curl http://127.0.0.1:5000/api/status
curl http://127.0.0.1:8080/activate  # through nginx