Military-Grade TAK Server Aggregator
OmniTAK is a high-performance, memory-safe TAK (Team Awareness Kit) server aggregator written in Rust. It connects to multiple TAK servers simultaneously, aggregates CoT (Cursor on Target) messages, and provides a unified API for managing tactical data.
- Multi-Protocol Support: TCP, UDP, TLS, WebSocket
- High Performance: Handle 10,000+ concurrent connections with <1ms latency
- Military-Grade Security: TLS 1.3, client certificates, memory-safe Rust implementation
- WASM Plugin System: Extend functionality with sandboxed WebAssembly plugins
- REST API: Complete HTTP API for all operations
- Web Interface: Modern browser-based control panel
- Desktop GUI: Native application with command palette, dark mode, and keyboard shortcuts
- Rich Mapping: Interactive maps with drawing tools, Blue Force Tracking, and offline support
- Natural Language Interface: Create TAK objects using plain English commands
- Real-Time Metrics: Prometheus-compatible metrics and monitoring
Command Palette (Ctrl+K)
- Quick access to all commands with fuzzy search
- Execute actions without leaving the keyboard
- Organized by category: Navigation, Connections, View, Tools, Settings
Keyboard Shortcuts
- Navigate tabs with Ctrl+1 through Ctrl+5
- Ctrl+N to add connections, Ctrl+Shift+N for quick connect wizard
- Ctrl+R to refresh, Ctrl+E to export, Ctrl+I to import
- Full shortcut reference available in Settings
Dark Mode and Theming
- Toggle between light and dark themes with Ctrl+Shift+D
- Adjustable UI scale from 0.5x to 2.0x
- Theme preferences persist between sessions
Interactive Map Features
- Drawing tools: markers, lines, circles, polygons, range rings
- Measurement tool for distance calculations
- Blue Force Tracking with historical trails and velocity vectors
- Track selection and inspection panel
Offline Map Support
- Load MBTiles databases for offline tile storage
- Import GeoJSON files for vector overlays
- Import KML files (Google Earth format)
- Toggle layer visibility and manage multiple overlays
Quick Connect Wizard
- Simplified server setup with guided steps
- Automatic certificate configuration
- Connection testing before saving
Interactive tactical map with real-time positioning and situational awareness
Real-time dashboard, server connections management, and message monitoring
# 1. Install Rust (1.90+)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
# 2. Install Protocol Buffers compiler
# macOS:
brew install protobuf
# Ubuntu/Debian:
sudo apt install protobuf-compiler
# 3. Clone the repository
git clone https://github.com/engindearing-projects/omniTAK.git
cd omniTAKThe main server provides the REST API that all interfaces use.
# Create a basic config file
mkdir -p config
cat > config/omnitak.yaml << 'EOF'
api:
bind_addr: "0.0.0.0:9443"
enable_tls: false
jwt_expiration: 86400
servers: []
logging:
level: "info"
EOF
# Build and run the server
cargo run --bin omnitak --release -- \
--config config/omnitak.yaml \
--admin-password your_secure_passwordWait for this message:
Server listening address=0.0.0.0:9443
The server is now running! Keep this terminal open.
Default credentials:
- Username:
admin - Password: Whatever you set with
--admin-password
The web interface is a browser-based control panel for managing TAK server connections.
In a new terminal:
cd omniTAK/web-client
python3 -m http.server 8080Open your browser:
- URL: http://localhost:8080
- Login with:
admin/your_secure_password
Features:
- Real-time dashboard with system metrics
- Add/remove TAK server connections
- View connection status
- Monitor message throughput
The native desktop application provides advanced features beyond the web interface, including command palette, keyboard shortcuts, and rich mapping capabilities.
# Build the GUI
cargo build --bin omnitak-gui --release
# Run it
./target/release/omnitak-guiFeatures:
- Command palette with Ctrl+K for quick actions
- Keyboard shortcuts for efficient navigation
- Dark mode with adjustable UI scale
- Interactive map with drawing tools
- Blue Force Tracking visualization
- Offline map support (MBTiles, GeoJSON, KML)
- Real-time connection monitoring
Default API: http://localhost:9443 (configurable at login)
Create TAK objects using plain English commands.
# Install Python dependencies
cd claude-interface
pip3 install -r requirements.txt
# Run the interactive demo
python3 interactive_demo.pyExample commands:
# Create a 5km exclusion zone
circle 34.0522,-118.2437 5 "Exclusion Zone" red
# Create an area of operations
polygon 34.0,-118.0 34.0,-117.0 33.5,-117.0 "AO Alpha" blue
# Create a patrol route
route 34.0,-118.0:Start 34.1,-118.1:Mid 34.2,-118.2:End "Patrol 1" yellow
# Exit
quitAll interfaces connect to a single REST API backend:
┌─────────────────────────────────┐
│ Main Server (Port 9443) │
│ - REST API │
│ - Connection Pool │
│ - Message Aggregator │
└────────┬────────────────────────┘
│ REST API
┌────┼────┬────────┐
│ │ │ │
Web UI GUI Python Mobile
CLI (future)
- Open http://localhost:8080
- Login with admin credentials
- Click "Add Connection"
- Fill in:
- Name: Friendly name for the connection
- Address:
hostname:port(e.g.,takserver.local:8089) - Protocol: TCP, TLS, UDP, or WebSocket
- Click "Add Connection"
# 1. Login to get a token
TOKEN=$(curl -s -X POST http://localhost:9443/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"your_password"}' | \
python3 -c "import sys, json; print(json.load(sys.stdin)['access_token'])")
# 2. Add a connection
curl -X POST http://localhost:9443/api/v1/connections \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Primary TAK Server",
"address": "takserver.local:8089",
"protocol": "tcp"
}'
# 3. List all connections
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:9443/api/v1/connectionsNEW! Automatically pull TAK certificates from your ATAK device via USB:
# 1. Install Android SDK Platform-Tools
sudo apt-get install android-tools-adb # Linux
brew install android-platform-tools # macOS
# 2. Enable USB debugging on your Android device
# Settings → Developer Options → USB Debugging
# 3. Connect device via USB and accept authorization prompt
# 4. Run the automated script
./examples/adb_pull_certs.sh
# Or use the CLI tool directly
cargo run --bin omnitak-adb-setup -- --output config/config.yamlThe ADB integration will:
- ✅ Detect connected ATAK devices
- ✅ Pull certificates from
/sdcard/atak/cert/ - ✅ Extract TAK server configuration
- ✅ Automatically create a connection
- ✅ Convert PKCS#12 to PEM if needed
See ADB_INTEGRATION.md for complete documentation.
Base URL: http://localhost:9443
POST /api/v1/auth/login
Body: {"username": "admin", "password": "your_password"}
Returns: {"access_token": "...", "expires_at": "...", "role": "admin"}GET /api/v1/health # No auth required
GET /api/v1/status # Requires auth
GET /api/v1/metrics # Prometheus metricsGET /api/v1/connections # List all connections
POST /api/v1/connections # Add new connection
GET /api/v1/connections/:id # Get connection details
DELETE /api/v1/connections/:id # Remove connectionPOST /api/v1/cot/send # Send CoT message to all connected serversFull API documentation: http://localhost:9443/api-docs.html (when server is running)
Main config file: config/omnitak.yaml
# API Server Configuration
api:
bind_addr: "0.0.0.0:9443" # API server address
enable_tls: false # Use TLS (recommended for production)
jwt_expiration: 86400 # Token expiration (24 hours)
rate_limit_rps: 100 # Rate limit requests per second
enable_swagger: true # Enable API documentation
# TAK Server Connections (managed via API/UI)
servers: []
# Logging
logging:
level: "info" # trace, debug, info, warn, error
format: "text" # text or json
# Metrics
metrics:
enabled: trueIf connecting to a TAK server that requires TLS:
# 1. Obtain certificates from your TAK server admin
# You'll need:
# - client.pem (client certificate)
# - client.key (private key)
# - ca.pem (CA certificate)
# 2. Convert to PEM format if needed
openssl pkcs12 -in client.p12 -out client.pem -clcerts -nokeys
openssl pkcs12 -in client.p12 -out client.key -nocerts -nodes
openssl rsa -in client.key -out client-rsa.key
# 3. Add via Web UI:
# - Select "TLS (Secure)" as protocol
# - Upload certificate files
# - Enter certificate password if required
# 4. Or add via API with base64-encoded cert dataSee docs/ADB_SETUP.md for automatic certificate extraction from Android devices.
# Build everything
cargo build --release
# Build specific components
cargo build --bin omnitak --release # Main server
cargo build --bin omnitak-gui --release # Desktop GUI
cargo build --bin omnitak-gen --release # CoT generator tool
cargo build --bin omnitak-adb-setup --release # ADB setup toolBinaries will be in target/release/
cargo build# Run all tests
cargo test --workspace
# Run specific crate tests
cargo test -p omnitak-cot
cargo test -p omnitak-client
cargo test -p omnitak-pool
# Run with logging
RUST_LOG=debug cargo test| Platform | Main Server | Web UI | Desktop GUI | Status |
|---|---|---|---|---|
| macOS (Intel) | ✅ | ✅ | ✅ | Tested |
| macOS (Apple Silicon) | ✅ | ✅ | ✅ | Tested |
| Ubuntu 20.04+ | ✅ | ✅ | ✅ | Tested |
| Windows 11 (WSL2) | ✅ | ✅ | ✅ | Tested |
| Windows (Native) | ⏳ | ✅ | ⏳ | In Progress |
Port already in use:
# Check what's using port 9443
lsof -i :9443
# Kill the process or change port in config.yamlPermission denied:
# Don't use privileged ports (< 1024) without sudo
# Use ports like 8443, 9443 insteadCheck server is running:
curl http://localhost:9443/api/v1/healthShould return: {"status":"healthy","timestamp":"..."}
CORS issues:
- Web UI must be served from same host as API, or
- Configure CORS in
config.yaml
Invalid credentials:
- Check username is
admin - Verify password matches what you set with
--admin-password
Token expired:
- Tokens expire after 24 hours by default
- Login again to get a new token
TCP connections:
- Verify TAK server address and port
- Check firewall allows outbound connections
- Test with:
telnet takserver.local 8089
TLS connections:
- Ensure certificates are in correct format (PEM)
- Verify certificate matches server hostname
- Check certificate is not expired
- Enable debug logging:
RUST_LOG=debug cargo run ...
For high-throughput scenarios:
# config.yaml
application:
max_connections: 10000 # Maximum TAK server connections
worker_threads: 8 # CPU cores * 2 recommended
performance:
buffer_size: 16384 # Increase for high message rates
max_message_size: 2097152 # 2MB max message size
connection_timeout: 30
keepalive_interval: 60- Enable TLS for API:
api:
enable_tls: true
tls_cert_path: "/path/to/api-cert.pem"
tls_key_path: "/path/to/api-key.pem"- Use strong passwords:
# Generate a random password
openssl rand -base64 32
# Set via environment variable
export OMNITAK_ADMIN_PASSWORD='your_strong_password'
cargo run --bin omnitak --release- Enable audit logging:
security:
audit_logging: true- Restrict CORS origins:
security:
cors_origins:
- "https://your-dashboard.example.com"- Use API keys for automation:
# Create an API key via the API
curl -X POST http://localhost:9443/api/v1/auth/api-keys \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "automation-key", "role": "operator"}'OmniTAK features a powerful plugin system based on WebAssembly Components, allowing you to extend functionality with custom message filters, transformers, and analyzers written in any WASM-compatible language.
- Sandboxed Execution: Plugins run in isolated environments with no access to filesystem or network unless explicitly granted
- Language Agnostic: Write plugins in Rust, C/C++, Go, Python, or any language that compiles to WASM
- Near-Native Performance: WASM compiles to machine code for fast execution
- Hot-Reload: Update plugins without restarting the server
- Type-Safe Interfaces: WIT (WebAssembly Interface Types) provides strong typing between host and plugins
# 1. Install the WASM target
rustup target add wasm32-wasip2
# 2. Navigate to the example plugin
cd plugins/example-filter
# 3. Build the plugin
cargo build --target wasm32-wasip2 --release
# 4. The WASM file is ready!
ls target/wasm32-wasip2/release/example_filter.wasmThe included example plugin demonstrates message filtering by detecting hostile keywords in CoT messages:
// Detects keywords: hostile, enemy, threat, attack, danger
// Tags detected messages with: hostile_detected="true" keywords="..."
impl Guest for ExampleFilterPlugin {
fn filter_message(cot_xml: String) -> Result<String, String> {
// Plugin logic here
if contains_hostile_keywords(&cot_xml) {
Ok(tag_as_hostile(cot_xml))
} else {
Ok(cot_xml) // Pass through unchanged
}
}
}1. Create a new plugin project:
cargo new --lib my-filter-plugin
cd my-filter-plugin2. Configure Cargo.toml:
[package]
name = "my-filter-plugin"
version = "0.1.0"
edition = "2021"
[dependencies]
wit-bindgen = "0.47.0"
[lib]
crate-type = ["cdylib"]3. Implement the message filter interface:
// src/lib.rs
wit_bindgen::generate!({
world: "message-filter",
path: "../wit"
});
struct MyFilterPlugin;
impl Guest for MyFilterPlugin {
fn filter_message(cot_xml: String) -> Result<String, String> {
// Your custom filtering logic
Ok(cot_xml)
}
fn get_name() -> String {
"My Custom Filter".to_string()
}
fn get_version() -> String {
"0.1.0".to_string()
}
}
export!(MyFilterPlugin);4. Build and deploy:
cargo build --target wasm32-wasip2 --release
cp target/wasm32-wasip2/release/my_filter_plugin.wasm /path/to/omnitak/plugins/Plugins can call these functions provided by OmniTAK:
// Simple logging
log("Processing message...");
// Structured logging with properties
log_structured("Hostile detected", vec![
("keyword", "enemy"),
("severity", "high")
]);
// Access configuration
if let Some(threshold) = get_config("sensitivity_threshold") {
// Use config value
}Example use cases for plugins:
- Geofencing: Filter messages based on geographic coordinates
- Content Sanitization: Redact sensitive information from messages
- Protocol Translation: Convert between different CoT versions
- Rate Limiting: Throttle messages from specific sources
- Threat Detection: Analyze patterns for security threats
- Data Enrichment: Add metadata from external sources
- Message Routing: Direct messages to specific servers based on content
- Compliance: Enforce organizational policies on message content
// In your application code
use omnitak_core::plugins::PluginManager;
let mut manager = PluginManager::new(
"plugins/", // Plugin directory
config, // Configuration map
servers // Server list
);
// Load all plugins
manager.load_all()?;
// Filter a message through all plugins
if let Some(filtered) = manager.filter_message(&cot_xml, metadata)? {
// Use filtered message
}
// Hot-reload a specific plugin
manager.reload_plugin("example-filter")?;OmniTAK's WASM runtime provides strong security guarantees:
- Memory Isolation: Plugins cannot access OmniTAK's memory
- No System Calls: Plugins cannot make arbitrary system calls
- No Network Access: Plugins cannot open sockets or make HTTP requests
- No File Access: Plugins cannot read/write files (unless via WASI with explicit permissions)
- Resource Limits: Memory and CPU usage can be capped per plugin
- Deterministic Execution: No threads or timers available to plugins
- Fast Load Times: Plugins load in milliseconds
- Low Overhead: Minimal performance impact on message processing
- Compiled Code: WASM compiles to native machine code
- Example Metrics: Example filter processes 100,000 messages/sec
For detailed plugin development guides:
- API Docs: http://localhost:9443/api-docs.html (when server running)
- Setup Guides:
- Feature Guides:
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Follow Rust style guidelines (
cargo fmt) - Pass all tests (
cargo test) - Pass clippy lints (
cargo clippy) - Update documentation
- Submit a Pull Request
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
- Issues: GitHub Issues
- Documentation: See docs/ directory
Built with Rust for reliability and performance in tactical environments.


