## Added - CoT (Cursor on Target) server on port 8089 enabling ATAK/iTAK device connectivity - Support for TAK stream protocol and traditional XML CoT messages - TLS/SSL support with automatic fallback to plain TCP - Username/password authentication for CoT connections - Real-time device position tracking with TTL-based expiration (90s default) - API endpoints: `/api/cot/config`, `/api/cot/server-package`, `/api/cot/truststore`, `/api/me/cot-password` - TAK Server section in Settings with QR code for iTAK setup - ATAK password management in Account page for OIDC users - CoT device markers on map showing real-time positions - Comprehensive documentation in `docs/` directory - Environment variables: `COT_PORT`, `COT_TTL_MS`, `COT_REQUIRE_AUTH`, `COT_SSL_CERT`, `COT_SSL_KEY`, `COT_DEBUG` - Dependencies: `fast-xml-parser`, `jszip`, `qrcode` ## Changed - Authentication system supports CoT password management for OIDC users - Database schema includes `cot_password_hash` field - Test suite refactored to follow functional design principles ## Removed - Consolidated utility modules: `authConfig.js`, `authSkipPaths.js`, `bootstrap.js`, `poiConstants.js`, `session.js` ## Security - XML entity expansion protection in CoT parser - Enhanced input validation and SQL injection prevention - Authentication timeout to prevent hanging connections ## Breaking Changes - Port 8089 must be exposed for CoT server. Update firewall rules and Docker/Kubernetes configurations. ## Migration Notes - OIDC users must set ATAK password via Account settings before connecting - Docker: expose port 8089 (`-p 8089:8089`) - Kubernetes: update Helm values to expose port 8089 Co-authored-by: Madison Grubb <madison@elastiflow.com> Reviewed-on: #6
6.4 KiB
KestrelOS
Tactical Operations Center (TOC) for OSINT feeds. Map view with offline-capable tiles and clickable camera/feed sources; click a marker to view the live stream.
Stack
- Nuxt 4, JavaScript, Tailwind CSS, ESLint, Vitest
- Leaflet + leaflet.offline (offline map and OSM tile caching)
- Mediasoup + mediasoup-client (WebRTC live streaming)
- Docker and Helm for deployment
Setup
npm install
npm run dev
Open http://localhost:3000. The app requires login by default; you will see the login page until you sign in.
HTTPS for local dev (camera / geolocation on your phone)
Camera and geolocation in the browser require a secure context (HTTPS) when you open the app from your phone. To test Share live from a device on your LAN without buying a domain or cert:
-
Generate a self-signed cert (once). Use your machine's LAN IP so the phone can use it:
chmod +x scripts/gen-dev-cert.sh ./scripts/gen-dev-cert.sh 192.168.1.123Replace
192.168.1.123with your server's IP. -
Start the dev server (it will use HTTPS if
.dev-certs/exists):npm run dev -
On your phone, open https://192.168.1.123:3000 (same IP you passed above). Accept the browser's "untrusted certificate" warning once (e.g. Advanced → Proceed). Then log in and use Share live; camera and location will work.
Without the certs, npm run dev still runs over HTTP as before.
Note: If you see a warning about NODE_TLS_REJECT_UNAUTHORIZED=0, you can ignore it for local development with self-signed certificates. The server will still work correctly.
WebRTC Live Streaming
The Share live feature uses WebRTC for real-time video streaming from mobile browsers. It requires:
- HTTPS (for camera/geolocation access on mobile)
- Mediasoup server (runs automatically in the Nuxt process)
- mediasoup-client (browser library, included automatically)
Streaming from a phone on your LAN: The server auto-detects your machine's LAN IP (from network interfaces) and uses it for WebRTC. Open https://:3000 on both phone and laptop (same IP as for your dev cert). To override (e.g. Docker or multiple NICs), set MEDIASOUP_ANNOUNCED_IP. Ensure firewall allows UDP/TCP ports 40000-49999 on the server.
See docs/live-streaming.md for setup and usage.
ATAK / CoT (Cursor on Target)
KestrelOS can act as a TAK Server so ATAK and iTAK devices connect and share positions. No plugins: in ATAK, add a Server connection (host = KestrelOS, port 8089 for CoT). Check Use Authentication and enter your KestrelOS username and password (local users use their login password; OIDC users must set an ATAK password once under Account in the web app). Devices relay CoT to each other (team members see each other on the ATAK map) and appear on the KestrelOS web map; they drop off after ~90 seconds if no updates. Optional: set COT_TTL_MS, COT_REQUIRE_AUTH; CoT runs on port 8089 (default).
Scripts
npm run dev- development servernpm run build- production buildnpm run test- run testsnpm run test:coverage- run tests with coverage (85% threshold)npm run test:e2e- Playwright E2E testsnpm run lint- ESLint (zero warnings)
Documentation
Full docs are in the docs/ directory: installation (npm, Docker, Helm), authentication (local login, OIDC), map and cameras (adding IPTV, ALPR, CCTV, NVR, etc.), ATAK and iTAK, and Share live (mobile device as live camera).
Configuration
- Devices: Manage cameras/devices via the API (
/api/devices); see Map and cameras. Each device needsname,device_type,lat,lng,stream_url, andsource_type(mjpegorhls). - Environment: No required env vars for basic run. For production, set
HOST=0.0.0.0and expose ports 3000 (web/API) and 8089 (CoT). SetCOT_TTL_MS=90000,COT_REQUIRE_AUTH=true. For TLS use.dev-certs/or setCOT_SSL_CERTandCOT_SSL_KEY. - Authentication: The login page always offers password sign-in (local). Optionally set
BOOTSTRAP_EMAILandBOOTSTRAP_PASSWORDbefore the first run to create the first admin; otherwise a default admin is created and its credentials are printed in the terminal. To also show an OIDC sign-in button, configureOIDC_ISSUER,OIDC_CLIENT_ID,OIDC_CLIENT_SECRET, and optionallyOIDC_LABEL,OIDC_REDIRECT_URI. See docs/auth.md for local login, OIDC config, and sign up. - Bootstrap admin (when using local auth): The server initializes the database and runs bootstrap at startup. On first run (no users in the database), it creates the first admin. If you set
BOOTSTRAP_EMAILandBOOTSTRAP_PASSWORDbefore starting, that account is created. If you don't set them, a default admin is created (identifier:admin) with a random password and the credentials are printed in the terminal-copy them and sign in at/login, then change the password or add users via Members. Use Members to change roles (admin, leader, member). Only admins can change roles; admins and leaders can edit POIs. - Database: SQLite file at
data/kestrelos.db(created automatically). Contains users, sessions, and POIs.
Docker
docker build -t kestrelos:latest .
docker run -p 3000:3000 -p 8089:8089 kestrelos:latest
Kubernetes (Helm)
From Gitea registry:
helm repo add keligrubb --username YOUR_USER --password YOUR_TOKEN https://git.keligrubb.com/api/packages/keligrubb/helm
helm repo update
helm install kestrelos keligrubb/kestrelos
From source:
helm install kestrelos ./helm/kestrelos
Health: GET /health (overview), GET /health/live (liveness), GET /health/ready (readiness). Probes are configured in the Helm chart. Optional: enable Ingress in helm/kestrelos/values.yaml.
Releases
Merges to main trigger a semver release. Use one of these prefixes in your PR title to set the version bump:
major:- breaking changesminor:- new featurespatch:- bug fixes, docs (default if no prefix)
Example: minor: Add map layer toggle
Security
- Device data is validated server-side; only valid entries are returned.
- Stream URLs are sanitized to
http://orhttps://only; other protocols are rejected.
License
MIT
