Madison Grubb 15625dc86f
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline failed
try fixing e2e tests
2026-02-11 23:02:54 -05:00
2026-02-11 23:02:54 -05:00
2026-02-11 22:38:50 -05:00
2026-02-10 23:32:26 -05:00
2026-02-10 23:32:26 -05:00
2026-02-10 23:32:26 -05:00
2026-02-11 22:38:50 -05:00
2026-02-10 23:32:26 -05:00
2026-02-10 23:32:26 -05:00
2026-02-10 23:32:26 -05:00
2026-02-11 22:38:50 -05:00
2026-02-10 23:32:26 -05:00
2026-02-11 22:38:50 -05:00
2026-02-11 22:38:50 -05:00
2026-02-11 22:38:50 -05:00
2026-02-11 22:38:50 -05:00
2026-02-10 23:32:26 -05:00
2026-02-10 23:32:26 -05:00
2026-02-10 23:32:26 -05:00
2026-02-10 23:32:26 -05: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.

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 machines 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 browsers “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 machines 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 4000049999 on the server.

See docs/live-streaming.md for architecture details.

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 lint ESLint (zero warnings)

Configuration

  • Feeds: Edit server/data/feeds.json to add cameras/feeds. Each feed needs id, name, lat, lng, streamUrl, and sourceType (mjpeg or hls). Home Assistant and other sources use the same shape; use proxy URLs for HA.
  • Environment: No required env vars for basic run. For production, set HOST=0.0.0.0 and PORT as needed (e.g. in Docker/Helm).
  • 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 provider-specific examples.
  • 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 dont 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 kestrelos:latest

Kubernetes (Helm)

helm install kestrelos ./helm/kestrelos --set image.repository=your-registry/kestrelos --set image.tag=latest

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.

Security

  • Feed list is validated server-side (getValidFeeds); only valid entries are returned.
  • Stream URLs are treated as untrusted; the UI only uses http:// or https:// URLs for display.

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%