Madison Grubb fd31038cb7
Some checks failed
PR / install (pull_request) Failing after 51s
PR / lint (pull_request) Has been skipped
PR / test (pull_request) Has been skipped
PR / e2e (pull_request) Has been skipped
PR / docker-build (pull_request) Failing after 1m35s
patch: migrate to gitea actions
2026-03-04 13:41:50 -05:00
2026-02-23 03:45:37 +00:00
2026-02-10 23:32:26 -05:00
2026-02-10 23:32:26 -05:00
2026-02-12 19:50:44 +00:00
2026-02-23 03:45:37 +00:00
2026-02-12 19:50:44 +00:00
2026-02-23 03:45:37 +00:00
2026-02-12 19:50:44 +00:00
2026-02-22 03:34:05 +00:00

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.

KestrelOS map UI

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:

  1. 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.123
    

    Replace 192.168.1.123 with your server's IP.

  2. Start the dev server (it will use HTTPS if .dev-certs/ exists):

    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://: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 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/ 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 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 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

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 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

Description
No description provided
Readme 2.5 MiB
v1.0.7 Latest
2026-03-06 02:30:45 +00:00
Languages
JavaScript 69.8%
Vue 27.3%
CSS 1.6%
Shell 1.1%
Smarty 0.1%
Other 0.1%