adlee-was-taken e6069a68fc refactor(events): drop forward-ref quote and test triggered_by default
Code review follow-up on f4d66dd:
- _handle_arm_request signature used "ArmStateFSM" as a string forward
  reference even though the type is imported at module top.
  _handle_event uses the bare form; match it for consistency.
- Add a test asserting that omitting triggered_by in an arm-request
  payload defaults to "unknown". That value feeds the audit log, so
  it deserves explicit regression coverage.

No behavior change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 12:58:09 -04:00
2026-04-05 10:23:29 -04:00

Vigilar

DIY offline-first home security. Your cameras, your house, your data.

Vigilar runs on a small mini PC in your home, records from your IP cameras, detects motion, and pushes notifications to your phone — with no cloud, no account, and no external service in the critical path.

Vigilar web UI grid view

Why Vigilar

  • Offline-first. No cloud dependency. No external calls in the hot path.
  • Multi-camera live view. HLS grid for bandwidth efficiency, MJPEG single view for low-latency focus.
  • On-device motion detection. OpenCV MOG2 with a 5-second pre-motion ring buffer, so the run-up to a trigger is captured.
  • Adaptive FPS. Cameras idle at 2 FPS and jump to 30 FPS on motion.
  • Event timeline and highlight reels. Plus timelapses and visitor, pet, and wildlife tracking as separate views.
  • Phone push notifications. PWA + VAPID web push. No Firebase, no Google Cloud Messaging.
  • Encrypted recordings at rest. AES-256-CTR .vge files, key stays on your box. (Confidential, not tamper-evident — see the Operator Guide for the details of the threat model.)
  • UPS aware. NUT integration, graceful shutdown on critical battery.
  • Runs on a cheap mini PC. 4 GB RAM, 128 GB SSD, any modern x86_64 box.

Quick paths

I want to… Start here
Set it up at home on a mini PC Home User Guide
Run it as a self-hoster / sysadmin Operator Guide
Understand how it works internally Architecture Overview
Pick cameras that work well with it Camera Hardware Guide

60-second overview

   [IP cameras] ──RTSP──▶  [mini PC running Vigilar]  ──LAN──▶  [phone / browser]
                                      │
                                      └── optional nightly ──▶ [NAS]
  • Language: Python 3.11+
  • Web: Flask + Bootstrap 5 dark + hls.js
  • Storage: SQLite (WAL) via SQLAlchemy Core
  • Bus: Local Mosquitto on 127.0.0.1:1883
  • Video: OpenCV (capture + motion), FFmpeg subprocess (recording, HLS)

Status

Alpha. Works on the author's hardware. Expect rough edges and breaking changes. Not recommended for anyone who cannot read a stack trace.

Known limitations worth calling out up front:

  • The in-browser event timeline does not yet update live. Push notifications to your phone work in real time; the timeline itself needs a page refresh.
  • Recording encryption is AES-256-CTR: confidential at rest, but not tamper-evident.
  • There is no automated database migration framework yet. Schema changes are forward-only.

See the Operator Guide for the full list.

Installation (TL;DR)

git clone <repo URL> vigilar
cd vigilar
sudo ./scripts/install.sh
sudo systemctl enable --now vigilar

Then open http://<mini-pc-ip>:49735 on your LAN.

For the full walkthrough (OS install, camera setup, PIN, push notifications, NAS backup), see the Home User Guide.

For configuration, CLI, secrets, backups, and upgrades, see the Operator Guide.

Documentation

License

Vigilar is distributed under the GNU General Public License v3.0. See LICENSE for the full text. (If the LICENSE file is not yet in the tree, it will be added in a follow-up.)

Contributing

Issues and pull requests are welcome. Before sending a PR:

  • Read CLAUDE.md for the project's code conventions, or the human-friendly distillation at docs/architecture/conventions.md.
  • Run ruff check vigilar/ and pytest — both must pass.
  • Keep commits small and focused.
Description
Local AI-model assisted home security and surveillance system for those that don't trust that data to the cloud.
Readme 851 KiB
Languages
Python 63.7%
HTML 21.6%
Shell 8.2%
JavaScript 5.5%
CSS 1%