- **Username:** `[unique_username]` — created in OTS web UI (Settings → Users)
- **Password:** `[user_password]` — set in OTS web UI
#### MQTT Settings
- **Topic:** `opentakserver`
- **Encryption Enabled:** ❌ **DISABLED** — **CRITICAL:** OTS cannot decode PSK-encrypted MQTT payloads. The LoRa RF hop between radios is still PSK-encrypted regardless of this setting. This toggle only controls whether the radio re-encrypts before publishing to MQTT. TLS on port 8883 provides wire security instead.
- **JSON Output:** ❌ **DISABLED** — OTS expects protobuf format, not JSON. Leave this off.
- **Proxy to Client:** ❌ **DISABLED** — required per OTS docs; enabling this causes presence/LWT issues with gateway operation
- **Uplink Enabled:** ✅ **REQUIRED** — configured per-channel when scanning QR code from OTS web UI
- **Position Precision:** Any — full precision is sent to private server regardless of this setting
**Important:** "Map Publish" only affects the public Meshtastic map. Position data still flows to custom MQTT servers (ots.k7zvx.com) with full precision when disabled.
### User Setup Process
1.**Create OTS user account:**
```bash
# Via OTS Web UI
https://ots.k7zvx.com → Settings → Users → Create User
# Set username (e.g., "matt", "jeepnjonny")
# Set password
```
2.**Configure Meshtastic radio** with connection settings above
3.**Test connection:**
- Send a text message from the radio
- Message should appear in iTAK/ATAK within seconds (will appear in triplicate due to mesh retry logic)
4.**Verify position data:**
- Position updates send based on mesh broadcast interval (typically 15-30 minutes)
- Node should appear as contact on TAK map with accurate location
**Symptom:** OTS logs show `UnicodeEncodeError` related to emojis
**Fix:** Remove emojis from Meshtastic node name (long name and short name). PostgreSQL database cannot handle emojis with current encoding.
**Example error:**
```
UnicodeEncodeError: 'ascii' codec can't encode character '\U0001f3f4' in position 0
```
### Known Behaviors
#### Triplicate Messages
**Behavior:** Each text message appears 3 times in iTAK
**Reason:** Meshtastic retry logic sends messages 3 times for reliability over mesh network. OTS forwards all copies.
**Impact:** Normal behavior, ensures messages get through despite poor mesh coverage. Not configurable without modifying OTS source.
#### Position Update Frequency
**Mesh vs MQTT:** Meshtastic has separate intervals:
- **Mesh broadcasts:** Position sent to local mesh (15-30 min typical)
- **MQTT publishing:** Position sent to MQTT server (can be same or different)
Radio may show position locally more often than it publishes to MQTT server. Configure "MQTT Position Interval" separately from mesh broadcast interval.
#### Map Publish vs Custom MQTT
**Map Publish:** Controls publishing to public Meshtastic map (map.meshtastic.org)
- Has 1-hour minimum interval due to privacy concerns
- Shows degraded precision on public map
**Custom MQTT (OTS):** Unaffected by map publish settings
- Receives full precision position data
- Updates at configured mesh/MQTT interval
- Completely private — only visible to your TAK clients
Disabling "Map Publish" does NOT affect position data sent to custom MQTT servers like OTS.
### Active Gateways
| Node ID | Callsign | Owner | Channel | Status |
|---------|----------|-------|---------|--------|
| !f861851e | Meshtastic 851e | matt | LFtrackers | Active |
### Port Summary
| Port | Service | Bind Address | External Access | Purpose |
**Problem:** Canonical's GeoDNS is broken for Filer Telephone ISP (Idaho). All DNS servers (local, Google, Cloudflare) returned only UK mirror IPs (91.189.x.x range) which had severe packet loss and timeouts.
**Root Cause:**
- Your ISP has poor peering with Canonical's UK infrastructure
- GeoDNS should return US mirrors but only returned UK for this region
- 30-50% packet loss between ISP and Canonical's network
**Fix Applied:**
```bash
# Changed /etc/apt/sources.list to use Oregon mirror
sed -i "s|http://archive.ubuntu.com/ubuntu|http://mirrors.kernel.org/ubuntu|g" /etc/apt/sources.list
# Results:
# - Before: Timeouts (10+ seconds)
# - After: 11 MB/s download speed
```
**Testing:**
- archive.ubuntu.com: TIMEOUT
- mirrors.kernel.org: 0.16s response time
- mirror.arizona.edu: 0.31s response time
### 2. PostgreSQL Driver Compatibility
**Problem:** OpenTAKServer installer uses psycopg3 by default, which has a compatibility bug with SQLAlchemy's PostgreSQL version detection. This causes the service to crash-loop with:
```
TypeError: cannot use a string pattern on a bytes-like object
```
**Fix Applied:**
```bash
# Install psycopg2-binary (stable driver)
pip install psycopg2-binary
# Update connection string in /home/zvx/ots/config.yml
# Changed: postgresql+psycopg://
# To: postgresql+psycopg2://
```
**Impact:** Without this fix, the backend API doesn't run and login fails silently.
---
## Troubleshooting
### Service Won't Start
```bash
# Check service status
systemctl status opentakserver
# Check logs for errors
tail -50 /home/zvx/ots/logs/opentakserver.log
# Common issues:
# 1. Database connection errors → check PostgreSQL is running
# 2. Port conflicts → check nginx/other services
# 3. psycopg errors → ensure psycopg2-binary is installed
```
### Login Fails
```bash
# Verify backend API is running
systemctl status opentakserver
# Check if service is crash-looping
journalctl -u opentakserver -f
# Test local API access
curl -I http://localhost:8080
curl -I https://localhost:443
```
### Slow Package Updates
```bash
# Verify using fast mirror
grep "URIs:" /etc/apt/sources.list
# Should show: http://mirrors.kernel.org/ubuntu
# If not, run:
sed -i "s|http://archive.ubuntu.com/ubuntu|http://mirrors.kernel.org/ubuntu|g" /etc/apt/sources.list
Previous attempts to install OpenTAKServer via Docker encountered persistent authentication issues. The native installation method worked successfully.
- Using mirrors.kernel.org for all Ubuntu-based containers
- Setting up a local apt-cacher-ng if this becomes widespread
- Monitoring ISP routing changes
### Tailscale Not Involved
Initial suspicion was that Tailscale exit nodes or DNS were causing the mirror issues. Testing confirmed this was false - the issue persists even with local DNS and no Tailscale routing.