All checks were successful
ci/woodpecker/push/push Pipeline was successful
## 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
123 lines
6.4 KiB
Markdown
123 lines
6.4 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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:
|
|
|
|
1. Generate a self-signed cert (once). Use your machine's LAN IP so the phone can use it:
|
|
```bash
|
|
chmod +x scripts/gen-dev-cert.sh
|
|
./scripts/gen-dev-cert.sh 192.168.1.123
|
|
```
|
|
Replace `192.168.1.123` with your server's IP.
|
|
|
|
2. Start the dev server (it will use HTTPS if `.dev-certs/` exists):
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
3. 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://<your-LAN-IP>: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](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 server
|
|
- `npm run build` - production build
|
|
- `npm run test` - run tests
|
|
- `npm run test:coverage` - run tests with coverage (85% threshold)
|
|
- `npm run test:e2e` - Playwright E2E tests
|
|
- `npm run lint` - ESLint (zero warnings)
|
|
|
|
## Documentation
|
|
|
|
Full docs are in the **[docs/](docs/README.md)** directory: [installation](docs/installation.md) (npm, Docker, Helm), [authentication](docs/auth.md) (local login, OIDC), [map and cameras](docs/map-and-cameras.md) (adding IPTV, ALPR, CCTV, NVR, etc.), [ATAK and iTAK](docs/atak-itak.md), and [Share live](docs/live-streaming.md) (mobile device as live camera).
|
|
|
|
## Configuration
|
|
|
|
- **Devices**: Manage cameras/devices via the API (`/api/devices`); see [Map and cameras](docs/map-and-cameras.md). Each device needs `name`, `device_type`, `lat`, `lng`, `stream_url`, and `source_type` (`mjpeg` or `hls`).
|
|
- **Environment**: No required env vars for basic run. For production, set `HOST=0.0.0.0` and expose ports 3000 (web/API) and 8089 (CoT). Set `COT_TTL_MS=90000`, `COT_REQUIRE_AUTH=true`. For TLS use `.dev-certs/` or set `COT_SSL_CERT` and `COT_SSL_KEY`.
|
|
- **Authentication**: The login page always offers password sign-in (local). Optionally set `BOOTSTRAP_EMAIL` and `BOOTSTRAP_PASSWORD` before 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, configure `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`, and optionally `OIDC_LABEL`, `OIDC_REDIRECT_URI`. See [docs/auth.md](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_EMAIL` and `BOOTSTRAP_PASSWORD` before 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
|
|
|
|
```bash
|
|
docker build -t kestrelos:latest .
|
|
docker run -p 3000:3000 -p 8089:8089 kestrelos:latest
|
|
```
|
|
|
|
## Kubernetes (Helm)
|
|
|
|
**From Gitea registry:**
|
|
```bash
|
|
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:**
|
|
```bash
|
|
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 changes
|
|
- `minor:` - new features
|
|
- `patch:` - 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://` or `https://` only; other protocols are rejected.
|
|
|
|
## License
|
|
|
|
MIT
|