# Changes * package and release helm charts for the project * configure a new release system based of semver * add changelog entries via keep-a-changelog formatting * add gitea releases Co-authored-by: Madison Grubb <madison@elastiflow.com> Reviewed-on: #3
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 architecture details.
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 lint– ESLint (zero warnings)
Configuration
- Devices: Manage cameras/devices via the API (
/api/devices) or the Members/Cameras UI. 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.0andPORTas needed (e.g. in Docker/Helm). - 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 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_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 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