Updates to sms

This commit is contained in:
bunker-admin 2026-02-27 08:36:21 -07:00
parent 9e51aac570
commit 621042806a
7 changed files with 619 additions and 62 deletions

View File

@ -19,6 +19,23 @@ import type {
const { Text, Paragraph } = Typography;
/** A single terminal command line with copy button */
function CmdLine({ cmd, comment }: { cmd: string; comment?: string }) {
return (
<div style={{ marginBottom: 6 }}>
{comment && <Text type="secondary" style={{ fontSize: 12 }}># {comment}</Text>}
{comment && <br />}
<Text
code
copyable={{ text: cmd, tooltips: ['Copy', 'Copied!'] }}
style={{ fontSize: 13, wordBreak: 'break-all' }}
>
{cmd}
</Text>
</div>
);
}
export default function SmsSetupPage() {
const { setPageHeader } = useOutletContext<AppOutletContext>();
const { message } = App.useApp();
@ -283,29 +300,71 @@ export default function SmsSetupPage() {
{/* Step 0: Phone Preparation */}
{currentStep === 0 && (
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
{/* Part 1: Install Apps */}
<Alert
type="info"
type="error"
showIcon
icon={<AndroidOutlined />}
message="Prepare Your Android Phone"
message="Step 1 — Install Apps on Android"
description={
<div>
<Paragraph>Follow these steps on your Android phone:</Paragraph>
<ol style={{ marginLeft: 20, lineHeight: 2.2 }}>
<li>Install <Text strong>Termux</Text> from F-Droid (not Play Store)</li>
<li>Install <Text strong>Termux:API</Text> from F-Droid</li>
<li>In Termux, run: <Text code copyable>pkg install python && pip install flask</Text></li>
<li>Grant SMS permissions when prompted</li>
<li>Install <Text strong>Tailscale</Text> from Play Store (optional, for stable IP)</li>
<Paragraph>
<Text strong style={{ fontSize: 14 }}>
Both Termux and Termux:API MUST be installed from F-Droid not the Play Store.
</Text>
<br />
<Text type="secondary">
The Play Store version of Termux is abandoned and incompatible with the API plugin.
If you have Termux from the Play Store, uninstall it first and reinstall from F-Droid.
</Text>
</Paragraph>
<ol style={{ marginLeft: 20, lineHeight: 2.4 }}>
<li>
<Text strong>Termux</Text> terminal emulator for Android
<br /><Text type="secondary">Install from <Text strong>F-Droid</Text> (f-droid.org). If already installed from Play Store, uninstall it first.</Text>
</li>
<li>
<Text strong>Termux:API</Text> gives Termux access to SMS, contacts, battery, GPS
<br /><Text type="secondary">Also from <Text strong>F-Droid</Text>. Both apps must come from the same source or SMS commands won't work.</Text>
</li>
<li>
<Text strong>Tailscale</Text> VPN mesh for stable IP addressing (recommended)
<br /><Text type="secondary">Install from Play Store. Creates a persistent 100.x.x.x IP so the server can always reach your phone.</Text>
</li>
</ol>
</div>
}
/>
<Divider>API Key</Divider>
{/* Part 2: Termux Setup */}
<Alert
type="info"
showIcon
icon={<ApiOutlined />}
message="Step 2 — Set Up Termux"
description={
<div>
<Paragraph>Open Termux on the phone and run each command (tap the copy icon):</Paragraph>
<div style={{ background: 'rgba(0,0,0,0.1)', padding: 12, borderRadius: 6 }}>
<CmdLine comment="Update packages and install dependencies" cmd="pkg update && pkg install python git termux-api openssh -y" />
<CmdLine comment="Install Flask (the SMS server framework)" cmd="pip install flask" />
<CmdLine comment="Clone the SMS server from Gitea" cmd="git clone https://gitea.bnkops.com/admin/campaign_connector.git ~/sms-server" />
<CmdLine comment="Grant SMS permission (tap Allow when prompted)" cmd="termux-sms-list" />
<CmdLine comment="Grant Contacts permission (tap Allow when prompted)" cmd="termux-contact-list" />
</div>
<Paragraph type="secondary" style={{ marginTop: 8, marginBottom: 0 }}>
Tap <Text strong>Allow</Text> when Android asks for SMS and Contacts permissions.
If you miss the prompt, go to Android Settings Apps Termux:API Permissions.
</Paragraph>
</div>
}
/>
{/* Part 3: API Key */}
<Divider>Step 3 Generate & Set API Key</Divider>
<Paragraph>
Generate an API key that both the server and phone will use for authentication.
You'll paste this key into the phone's Termux environment.
Generate a shared secret key. Both the server and phone use this to authenticate API requests.
Click the button below, then paste the key into Termux.
</Paragraph>
<Space>
@ -352,15 +411,64 @@ export default function SmsSetupPage() {
</pre>
)}
<Paragraph style={{ marginTop: 12, marginBottom: 0 }}>
On the phone in Termux, set this as <Text code>SMS_API_SECRET</Text> environment variable
before starting the SMS server.
<Divider style={{ margin: '12px 0' }} />
<Paragraph strong>Now run these in Termux on the phone:</Paragraph>
<div style={{ background: 'rgba(0,0,0,0.1)', padding: 12, borderRadius: 6 }}>
<CmdLine comment="Set the API key for this session" cmd={`export SMS_API_SECRET='${generatedKey}'`} />
<CmdLine comment="Save permanently so it persists across restarts" cmd={`echo 'export SMS_API_SECRET="${generatedKey}"' >> ~/.bashrc`} />
</div>
</div>
}
/>
)}
{/* Part 4: Start the server */}
{generatedKey && (
<Alert
type="info"
showIcon
icon={<RocketOutlined />}
message="Step 4 — Start the SMS Server"
description={
<div>
<Paragraph>With the API key set, start the Flask server:</Paragraph>
<div style={{ background: 'rgba(0,0,0,0.1)', padding: 12, borderRadius: 6 }}>
<CmdLine comment="Create logs dir and start the SMS API server" cmd="mkdir -p ~/logs && cd ~/sms-server/android && python termux-sms-api-server.py" />
</div>
<Paragraph style={{ marginTop: 8 }}>
You should see output like: <Text code>Termux SMS API Server Starting</Text> with the device IP and port 5001.
</Paragraph>
<Divider style={{ margin: '12px 0' }} />
<Paragraph strong>To keep it running permanently:</Paragraph>
<div style={{ background: 'rgba(0,0,0,0.1)', padding: 12, borderRadius: 6 }}>
<CmdLine comment="Run the watchdog (auto-restarts server if it crashes)" cmd="nohup bash ~/sms-server/android/sms-watchdog.sh >> ~/logs/sms-watchdog.log 2>&1 &" />
</div>
<Paragraph type="secondary" style={{ marginTop: 8, marginBottom: 0 }}>
For auto-start on phone reboot, install <Text strong>Termux:Boot</Text> from F-Droid.
Also disable battery optimization: Android Settings Apps Termux Battery Unrestricted.
</Paragraph>
</div>
}
/>
)}
{/* Access methods info */}
<Alert
type="warning"
showIcon
message="Ways to Access the Phone"
description={
<div>
<Paragraph style={{ marginBottom: 4 }}>You can run these commands on the phone via:</Paragraph>
<ul style={{ marginLeft: 20, lineHeight: 2 }}>
<li><Text strong>Directly on phone</Text> open the Termux app and type commands</li>
<li><Text strong>SSH</Text> run <Text code>sshd</Text> in Termux, then <Text code>ssh -p 8022 phone-ip</Text> from your computer</li>
<li><Text strong>scrcpy</Text> mirror the phone screen to your computer via USB or WiFi</li>
</ul>
</div>
}
/>
<div style={{ marginTop: 16, display: 'flex', justifyContent: 'flex-end' }}>
<Button type="primary" onClick={() => setCurrentStep(1)}>
Next: Connect to Phone

View File

@ -9,10 +9,12 @@ class SmsDeviceMonitorService {
start() {
if (this.interval) return;
// Initial check
this.check().catch((err) => {
logger.warn('Initial SMS device check failed:', err instanceof Error ? err.message : err);
});
// Delay initial check by 15s to stagger with response sync (avoids concurrent Termux API calls)
setTimeout(() => {
this.check().catch((err) => {
logger.warn('Initial SMS device check failed:', err instanceof Error ? err.message : err);
});
}, 15_000);
this.interval = setInterval(() => {
this.check().catch((err) => {
@ -20,7 +22,7 @@ class SmsDeviceMonitorService {
});
}, env.SMS_DEVICE_MONITOR_INTERVAL_MS);
logger.info(`SMS device monitor started (interval: ${env.SMS_DEVICE_MONITOR_INTERVAL_MS}ms)`);
logger.info(`SMS device monitor started (interval: ${env.SMS_DEVICE_MONITOR_INTERVAL_MS}ms, initial delay: 15s)`);
}
stop() {

View File

@ -222,7 +222,11 @@ class TermuxClient {
if (!this.enabled) return null;
try {
return await this.request<TermuxBatteryStatus>('GET', '/api/device/battery');
// Flask endpoint returns { battery: { percentage, status, ... }, success: true }
const data = await this.request<{ battery?: TermuxBatteryStatus } & Partial<TermuxBatteryStatus>>(
'GET', '/api/device/battery',
);
return data.battery || data as unknown as TermuxBatteryStatus;
} catch (err) {
logger.warn('Termux getBattery failed:', err instanceof Error ? err.message : err);
return null;

1
campaign_connector Submodule

@ -0,0 +1 @@
Subproject commit 30c2cfeba55a886b45878331c48346472d05e75a

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -28,7 +28,7 @@
"assets/images/social/docs/admin/broadcast/email-templates.png": "6b121b89ef5cea5b36f39032e3a50e9364e30bb3",
"assets/images/social/docs/admin/broadcast/index.png": "68d98e1866ae03ecde866e5f55aa6282cd44f941",
"assets/images/social/docs/admin/broadcast/newsletter.png": "31997f46a4f4a14ca1a688e9f54ff0c1f3552a78",
"assets/images/social/docs/admin/broadcast/sms.png": "d331316eb6ebe63adf9c1f7ba61f73ecc51b6ced",
"assets/images/social/docs/admin/broadcast/sms.png": "82ab0ac704e93728f657d899c7373cd3078385d3",
"assets/images/social/docs/admin/dashboard.png": "8ea5f8248da65c60385ffcd06c32aebe2cf96717",
"assets/images/social/docs/admin/index.png": "5b118844de3687d26a701228b5e71762becf524c",
"assets/images/social/docs/admin/map/areas.png": "8bdf057cd91548b6bd037a7bcc6890ebe226f85a",

View File

@ -1,64 +1,506 @@
---
title: SMS Campaigns
description: Text message outreach via a Termux Android bridge with contact management and response tracking.
description: Complete guide to setting up the Termux Android SMS bridge for text message outreach, contact management, and response tracking.
icon: material/message-text
---
# SMS Campaigns
Text message outreach via a Termux Android bridge. Enable with `ENABLE_SMS=true`.
Text message outreach via a Termux Android bridge. Uses a real Android phone to send and receive SMS — no third-party SMS gateway or Twilio account needed.
Enable with `ENABLE_SMS=true` or via the setup wizard.
---
## Architecture Overview
The SMS system uses a three-tier architecture where your server communicates with a lightweight Python Flask API running on an Android phone:
```mermaid
graph LR
A[Admin Dashboard<br/>Campaign UI] -->|API calls| B[Express API<br/>BullMQ Queue]
B -->|HTTP + API Key| C[Android Phone<br/>Flask on Termux]
C -->|termux-sms-send| D[Android SMS]
D -->|Carrier Network| E[Recipients]
E -->|Reply SMS| D
D -->|termux-sms-list| C
C -->|HTTP response| B
```
**Why this approach?**
- **No SaaS dependency** — your phone is the SMS gateway, no Twilio/MessageBird/etc.
- **Real phone number** — recipients see a real number, not a short code
- **Two-way messaging** — incoming replies sync automatically
- **Low cost** — just your phone plan's SMS allowance
- **Full control** — FOSS stack end-to-end
---
## Prerequisites
Before starting setup, you'll need:
| Item | Details |
|------|---------|
| **Android phone** | Any Android 7+ device with an active SIM card and SMS plan |
| **Termux** | Terminal emulator — install from **F-Droid** (not Play Store) |
| **Termux:API** | Termux plugin for SMS/contacts/battery — install from **F-Droid** |
| **Tailscale** (recommended) | VPN mesh for stable IP — install from Play Store |
| **Network access** | Phone must be reachable from the server (Tailscale, LAN, or port forwarding) |
!!! danger "Both Apps MUST Come from F-Droid"
The Play Store version of Termux is **abandoned and incompatible** with the API plugin. If you install Termux from the Play Store and Termux:API from F-Droid (or vice versa), SMS commands will fail with:
> Termux:API is not yet available on Google Play
**Fix:** Uninstall both apps, then reinstall **both** from [F-Droid](https://f-droid.org). They must come from the same source because Android verifies matching app signatures for inter-process communication.
---
## Phone Setup Guide
### Step 1: Install Apps
On your Android phone:
1. **Install F-Droid** — download from [f-droid.org](https://f-droid.org) if you don't have it
2. **Install Termux** — search in F-Droid and install
3. **Install Termux:API** — search in F-Droid and install
4. **Install Tailscale** (recommended) — from Play Store, create account, connect to your tailnet
### Step 2: Set Up Termux
Open the Termux app on your phone and run:
```bash
# Update package repository and install dependencies
pkg update && pkg install python git termux-api openssh -y
# Install the Flask web framework (used by the SMS server)
pip install flask
```
!!! note "termux-api package"
The `termux-api` package provides the command-line tools (`termux-sms-send`, `termux-sms-list`, etc.) that bridge to the Termux:API Android app. You need **both** the F-Droid app and this Termux package installed.
### Step 3: Clone the SMS Server
The SMS server code is hosted on your Gitea instance. Clone it directly to the phone:
```bash
# Clone the campaign connector repository
git clone https://gitea.bnkops.com/admin/campaign_connector.git ~/sms-server
```
!!! tip "Alternative: Copy just the server file"
If git isn't available or you prefer minimal setup, you only need one file:
```bash
mkdir -p ~/sms-server/android
# Copy termux-sms-api-server.py from your server to the phone
# via SSH, USB transfer, or paste the contents directly
```
### Step 4: Grant Permissions
Termux:API needs Android permissions to access SMS, contacts, and other features:
```bash
# These commands will trigger Android permission prompts
# Tap "Allow" when prompted
termux-sms-list # Triggers SMS permission
termux-contact-list # Triggers Contacts permission
termux-battery-status # Usually auto-granted
```
If you missed a prompt, go to **Android Settings → Apps → Termux:API → Permissions** and enable SMS and Contacts manually.
### Step 5: Set the API Key
Go to the admin dashboard SMS Setup page (`/app/sms/setup`) and click **Generate API Key**. Copy the generated key, then set it in Termux:
```bash
# Replace YOUR_KEY_HERE with the key from the setup wizard
export SMS_API_SECRET='YOUR_KEY_HERE'
# Save it permanently so it survives restarts
echo 'export SMS_API_SECRET="YOUR_KEY_HERE"' >> ~/.bashrc
```
### Step 6: Start the Server
```bash
cd ~/sms-server/android
python termux-sms-api-server.py
```
You should see output like:
```
🚀 Termux SMS API Server Starting
📱 Device IP: 100.64.0.5
🌐 API Base URL: http://100.64.0.5:5001
🔗 Health Check: http://100.64.0.5:5001/health
📞 SMS Endpoint: http://100.64.0.5:5001/api/sms/send
```
Note the **Device IP** — you'll need it for the connection wizard.
### Step 7: Run Persistently
By default, the server dies if you close Termux or restart the phone. Here's how to make it survive:
#### A. Prevent Android from Killing Termux
This is **required** regardless of which method you use below:
1. Open **Android Settings → Apps → Termux → Battery** → set to **Unrestricted**
2. Lock Termux in the recent apps view (long-press the app card → Lock/Pin)
3. Samsung phones: also add Termux to **Settings → Device Care → Battery → Never Sleeping Apps**
#### B. Install Termux:Boot (auto-start on reboot)
Install [Termux:Boot](https://f-droid.org/packages/com.termux.boot/) from F-Droid (must be same source as Termux), then open it once to register with Android.
```bash
# Create the boot scripts directory
mkdir -p ~/.termux/boot
# Create the auto-start script
cat > ~/.termux/boot/start-sms-server << 'EOF'
#!/data/data/com.termux/files/usr/bin/sh
termux-wake-lock
export SMS_API_SECRET="YOUR_KEY_HERE"
mkdir -p ~/logs
nohup python ~/sms-server/android/termux-sms-api-server.py >> ~/logs/sms-api.log 2>&1 &
EOF
chmod +x ~/.termux/boot/start-sms-server
```
!!! warning "Replace YOUR_KEY_HERE"
Edit the script and replace `YOUR_KEY_HERE` with your actual API key. Or if you've already saved it in `~/.bashrc`, replace the export line with `source ~/.bashrc`.
#### C. Watchdog (auto-restart on crash)
The repo includes a watchdog script that monitors the server and restarts it if it crashes:
```bash
# Run the watchdog (it starts the server automatically)
cd ~/sms-server/android
bash sms-watchdog.sh
```
The watchdog:
- Acquires a wake lock (`termux-wake-lock`) to prevent Android from sleeping
- Checks the server health every 30 seconds
- Automatically restarts the server if it's unresponsive
- Logs everything to `~/logs/sms-api.log`
For maximum reliability, use the watchdog as your boot script:
```bash
cat > ~/.termux/boot/start-sms-server << 'EOF'
#!/data/data/com.termux/files/usr/bin/sh
source ~/.bashrc
nohup bash ~/sms-server/android/sms-watchdog.sh >> ~/logs/sms-watchdog.log 2>&1 &
EOF
chmod +x ~/.termux/boot/start-sms-server
```
#### D. Quick Background (simplest)
If you just want to background the server without persistence:
```bash
# Start in background
termux-wake-lock
nohup python ~/sms-server/android/termux-sms-api-server.py >> ~/logs/sms-api.log 2>&1 &
# Check if it's running
curl http://127.0.0.1:5001/health
# View logs
tail -f ~/logs/sms-api.log
# Stop the server
pkill -f termux-sms-api-server.py
```
---
## Accessing the Phone
There are several ways to run commands on the phone:
### Direct (on phone)
Simply open the Termux app and type commands. Best for initial setup.
### SSH (remote access)
Start the SSH server in Termux, then connect from your computer:
```bash
# On the phone (first time only):
pkg install openssh
passwd # Set a password
sshd # Start SSH server on port 8022
# From your computer:
ssh -p 8022 your-phone-ip
# Or with Tailscale:
ssh -p 8022 100.x.x.x
```
### scrcpy (screen mirror)
Mirror the phone screen to your computer — great for setup:
```bash
# Install scrcpy on your computer (Ubuntu)
sudo apt install scrcpy
# Connect via USB
scrcpy
# Or wireless (phone must be on same network)
scrcpy --tcpip=phone-ip:5555
```
---
## Setup Wizard
The admin panel provides a guided three-step wizard at `/app/sms/setup`:
### Step 1: Prepare Phone
Walks you through installing apps, cloning the server, setting the API key, and starting the Flask server. Generates a shared API key that both the server and phone use for authentication.
### Step 2: Connect
Choose how to find your phone's IP address:
=== "Tailscale Auto-Discovery (Recommended)"
1. Enter your Tailscale API key (`tskey-api-...`)
2. Click **Discover Devices**
3. The wizard queries the Tailscale API and lists all devices on your tailnet
4. Select your Android phone — the URL auto-fills with its stable `100.x.x.x` IP
!!! info "Getting a Tailscale API Key"
Go to [Tailscale Admin Console](https://login.tailscale.com/admin/settings/keys) → Settings → Keys → Generate auth key or API access token.
=== "Manual URL Entry"
Enter the phone's URL directly:
- **With Tailscale:** `http://100.x.x.x:5001` (stable IP, works across networks)
- **On same LAN:** `http://192.168.x.x:5001` (changes if phone reconnects)
- **Via port forward:** `http://your-public-ip:5001` (requires router config)
### Step 3: Test & Save
1. Click **Test Connection** — the wizard calls the phone's `/health` endpoint
2. On success, you'll see device uptime and message count
3. Click **Save Configuration** — stores the URL and key encrypted in the database
4. The `enableSms` feature flag is automatically enabled
---
## How It Works
1. **Configure the bridge** — set `TERMUX_API_URL` and `TERMUX_API_KEY` to connect to an Android device running Termux with the SMS plugin
2. **Create contact lists** — import contacts or build lists from existing supporters
3. **Write a campaign** — compose a message template with variable substitution (name, location, etc.)
4. **Launch the campaign** — messages are queued via BullMQ and sent serially through the device
5. **Monitor responses** — incoming replies are synced and classified by keyword
### Sending Messages
1. Admin creates an SMS campaign with a message template and contact list
2. Campaign is started → messages are queued in **BullMQ** (one at a time, serial delivery)
3. For each message, the Express API calls `POST /api/sms/send` on the phone
4. The Flask server on the phone executes `termux-sms-send` to send via Android's native SMS
5. A notification appears on the phone for each sent message
6. Results are tracked in the database (success/failure per recipient)
### Receiving Responses
A background service (`sms-response-sync.service.ts`) polls the phone's inbox at a configurable interval:
1. Calls `GET /api/sms/inbox?since=<last_sync_timestamp>` on the phone
2. The Flask server runs `termux-sms-list` to get new messages
3. Incoming messages are matched to contacts and classified by keyword
4. Threaded conversations are maintained per contact
### Device Monitoring
A background service (`sms-device-monitor.service.ts`) checks phone health periodically:
- Battery level, charging status, temperature
- Server uptime and total messages sent
- Connection status (available/unreachable)
- Results displayed on the SMS Dashboard
---
## Key Features
- **Contact lists** — import, tag, and segment contacts for targeted outreach
- **Message templates** — reusable templates with variable placeholders
- **BullMQ queue** — serial delivery with configurable delays between messages (`SMS_DELAY_BETWEEN_MS`)
- **Response sync** — incoming SMS replies synced and classified automatically (`SMS_RESPONSE_SYNC_INTERVAL_MS`)
- **Device monitoring** — health checks and status reporting for the connected Android device (`SMS_DEVICE_MONITOR_INTERVAL_MS`)
- **Message templates** — reusable templates with `{name}` variable placeholders
- **BullMQ queue** — serial delivery with configurable delays between messages
- **Response sync** — incoming SMS replies synced and classified automatically
- **Device monitoring**battery, uptime, and connectivity reported in real-time
- **Conversation view** — threaded message history per contact
- **Retry logic** — configurable retry attempts for failed deliveries (`SMS_MAX_RETRIES`)
---
## Setup Wizard
The SMS Setup page (`/app/sms/setup`) provides a guided three-step wizard for connecting your Android phone:
### Step 1: Prepare Phone
Install Termux and Termux:API from F-Droid on the Android device, then generate a shared API key from the admin panel. The key is used for mutual authentication between the server and the phone.
### Step 2: Connect
Choose one of two connection methods:
- **Tailscale Auto-Discovery (recommended)** -- enter your Tailscale API key and the wizard automatically discovers devices on your tailnet, highlights Android devices, and pre-fills the stable IP address
- **Manual URL Entry** -- enter the Termux API server URL directly (typically `http://100.x.x.x:5001` when using Tailscale)
### Step 3: Test and Save
Run a live connection test against the phone to verify the URL and API key are correct. The test displays device health info (uptime, messages sent). Once the test passes, save the configuration to enable SMS features platform-wide.
The wizard stores credentials encrypted in the database and updates the `enableSms` feature flag automatically.
- **Retry logic** — configurable retry attempts for failed deliveries
---
## Admin Routes
- `/app/sms/setup` -- guided setup wizard with Tailscale auto-discovery
- `/app/sms` -- SMS dashboard with campaign overview and device status
- `/app/sms/contacts` -- manage contact lists and entries
- `/app/sms/campaigns` -- create and monitor SMS campaigns
- `/app/sms/conversations` -- view threaded conversations with contacts
| Route | Description |
|-------|-------------|
| `/app/sms/setup` | Guided setup wizard with Tailscale auto-discovery |
| `/app/sms` | SMS dashboard — campaign overview and device status |
| `/app/sms/contacts` | Manage contact lists and entries |
| `/app/sms/campaigns` | Create and monitor SMS campaigns |
| `/app/sms/conversations` | View threaded conversations with contacts |
---
## Configuration
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `ENABLE_SMS` | `false` | Feature flag (also set via setup wizard) |
| `TERMUX_API_URL` | — | Phone URL, e.g. `http://100.x.x.x:5001` |
| `TERMUX_API_KEY` | — | Shared API key for authentication |
| `SMS_DELAY_BETWEEN_MS` | `1000` | Delay between messages in a campaign (ms) |
| `SMS_MAX_RETRIES` | `3` | Retry attempts for failed sends |
| `SMS_RESPONSE_SYNC_INTERVAL_MS` | `10000` | How often to check for incoming replies (ms) |
| `SMS_DEVICE_MONITOR_INTERVAL_MS` | `30000` | How often to check device health (ms) |
| `TAILSCALE_API_KEY` | — | Tailscale API key for auto-discovery |
| `TAILSCALE_TAILNET` | — | Tailscale tailnet name (optional) |
!!! note
When you use the setup wizard, configuration is stored in the database and takes priority over environment variables. You don't need to set env vars if you use the wizard.
### Phone-Side Configuration
On the phone, only one environment variable is needed:
```bash
export SMS_API_SECRET='your-64-char-hex-key'
```
The Flask server also accepts `TERMUX_API_KEY` as an alias for backwards compatibility.
---
## Phone API Endpoints
The Flask server running on the phone exposes these endpoints on port 5001:
| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| `GET` | `/health` | No | Server status, uptime, messages sent |
| `GET` | `/` | No | Web dashboard with endpoint documentation |
| `POST` | `/api/sms/send` | Yes | Send an SMS message |
| `POST` | `/api/sms/send-reply` | Yes | Send a reply with conversation tracking |
| `GET` | `/api/sms/inbox` | No | Get incoming messages (with `since` filter) |
| `GET` | `/api/sms/list` | No | List messages with pagination |
| `GET` | `/api/sms/history` | No | Get SMS history for a phone number |
| `GET` | `/api/device/battery` | No | Battery level, health, temperature |
| `GET` | `/api/device/location` | No | GPS coordinates (requires permission) |
| `GET` | `/api/device/info` | No | Device info + battery + uptime |
| `GET` | `/api/contacts/list` | No | Phone address book (with search) |
| `POST` | `/api/campaign/notify` | No | Push notification to device |
Authentication uses the `X-API-Key` header with the shared secret.
---
## Troubleshooting
### Phone can't be reached
**Symptoms:** Test connection fails, "Connection refused" or timeout.
**Checks:**
1. **Is the Flask server running?** Check Termux — you should see the startup banner
2. **Is the IP correct?** Run `ifconfig` in Termux to find the current IP
3. **Are they on the same network?** If not using Tailscale, both must be on the same LAN
4. **Is Tailscale connected?** Check the Tailscale app on the phone — it should show "Connected"
5. **Firewall?** Android rarely blocks incoming connections on Termux, but check if any firewall app is installed
```bash
# Quick test from your server
curl http://PHONE_IP:5001/health
```
### "Authentication required" errors
**Symptoms:** API calls return 401 with "Authentication required".
**Fix:** The API key on the phone doesn't match the one in the admin panel.
```bash
# On the phone, check the current key
echo $SMS_API_SECRET
# If it doesn't match, update it
export SMS_API_SECRET='correct-key-from-admin-panel'
echo 'export SMS_API_SECRET="correct-key-from-admin-panel"' >> ~/.bashrc
# Restart the server
pkill -f termux-sms-api-server.py
cd ~/sms-server/android && python termux-sms-api-server.py
```
### SMS not sending
**Symptoms:** Server responds successfully but messages don't arrive.
**Checks:**
1. **SMS permissions granted?** Go to Android Settings → Apps → Termux:API → Permissions → SMS
2. **Active SIM card?** The phone needs a working SIM with SMS capability
3. **Message too long?** Maximum 1600 characters per message
4. **Rate limited?** Minimum 1 second between messages (carrier may enforce longer delays)
### Termux keeps getting killed
**Symptoms:** Server stops after some time, especially when phone screen is off.
**Fix:** Disable battery optimization for Termux:
1. Android Settings → Apps → Termux → Battery → **Unrestricted**
2. Lock Termux in recent apps (long-press app card → Lock)
3. Some phones: Settings → Battery → Battery Optimization → find Termux → Don't Optimize
4. Samsung: Settings → Device Care → Battery → App Power Management → add Termux to "Never sleeping apps"
### Server won't start — "Missing SMS_API_SECRET"
**Symptoms:** Server exits immediately with a security error.
**Fix:** Set the API key environment variable:
```bash
# Generate a new key if you don't have one
python -c "import secrets; print(secrets.token_hex(32))"
# Set it
export SMS_API_SECRET='your-generated-key'
echo 'export SMS_API_SECRET="your-key"' >> ~/.bashrc
```
### Updating the SMS server
To pull the latest version of the server code:
```bash
cd ~/sms-server
git pull
# Restart the server
pkill -f termux-sms-api-server.py
cd android && python termux-sms-api-server.py
```