Initial commit: Vigilar DIY home security system
Phase 1 (Foundation): project skeleton, TOML config + Pydantic validation, MQTT bus wrapper, SQLite schema (9 tables), Click CLI, process supervisor. Phase 2 (Camera): RTSP capture via OpenCV, MOG2 motion detection with configurable sensitivity/zones, adaptive FPS recording (2fps idle/30fps motion) via FFmpeg subprocess, HLS live streaming, pre-motion ring buffer. Phase 3 (Web UI): Flask + Bootstrap 5 dark theme, 6 blueprints, Jinja2 templates (dashboard, kiosk 2x2 grid, events, sensors, recordings, settings), PWA with service worker + Web Push, full admin settings UI with config persistence. Remote Access: WireGuard tunnel configs, nginx reverse proxy with HLS caching + rate limiting, bandwidth-optimized remote HLS stream (426x240 @ 500kbps), DO droplet setup script, certbot TLS. 29 tests passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
165
remote/nginx/vigilar.conf
Normal file
165
remote/nginx/vigilar.conf
Normal file
@@ -0,0 +1,165 @@
|
||||
# Nginx reverse proxy config for Digital Ocean droplet
|
||||
# Proxies HTTPS traffic to Vigilar at home via WireGuard tunnel
|
||||
#
|
||||
# Install: cp vigilar.conf /etc/nginx/sites-available/vigilar
|
||||
# ln -s /etc/nginx/sites-available/vigilar /etc/nginx/sites-enabled/
|
||||
# nginx -t && systemctl reload nginx
|
||||
#
|
||||
# TLS: certbot --nginx -d vigilar.yourdomain.com
|
||||
|
||||
# Rate limiting zones
|
||||
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
|
||||
limit_req_zone $binary_remote_addr zone=stream:10m rate=5r/s;
|
||||
limit_conn_zone $binary_remote_addr zone=connlimit:10m;
|
||||
|
||||
# HLS segment cache — reduces repeat requests hitting the home uplink
|
||||
proxy_cache_path /var/cache/nginx/vigilar_hls
|
||||
levels=1:2
|
||||
keys_zone=hls_cache:10m
|
||||
max_size=256m
|
||||
inactive=30s
|
||||
use_temp_path=off;
|
||||
|
||||
# Upstream: Vigilar on home server via WireGuard tunnel
|
||||
upstream vigilar_home {
|
||||
server 10.99.0.2:49735;
|
||||
# If home server goes down, fail fast
|
||||
keepalive 4;
|
||||
}
|
||||
|
||||
# Redirect HTTP → HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
server_name vigilar.yourdomain.com;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name vigilar.yourdomain.com;
|
||||
|
||||
# TLS (managed by certbot)
|
||||
ssl_certificate /etc/letsencrypt/live/vigilar.yourdomain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/vigilar.yourdomain.com/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 1d;
|
||||
|
||||
# Security headers
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
|
||||
add_header X-Frame-Options DENY always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
||||
|
||||
# Connection limits — protect 22 Mbps home uplink
|
||||
# Max 10 simultaneous connections per IP
|
||||
limit_conn connlimit 10;
|
||||
|
||||
# --- HLS streams (bandwidth-critical path) ---
|
||||
# Cache .ts segments on the droplet to avoid re-fetching from home
|
||||
# when multiple remote viewers request the same segment
|
||||
location ~ ^/cameras/.+/hls/.+\.ts$ {
|
||||
proxy_pass http://vigilar_home;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Cache segments for 10s — they're 2s segments, so this covers
|
||||
# multiple viewers watching the same feed without re-fetching
|
||||
proxy_cache hls_cache;
|
||||
proxy_cache_valid 200 10s;
|
||||
proxy_cache_key $uri;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
|
||||
# Rate limit: 5 segment requests/sec per IP
|
||||
limit_req zone=stream burst=20 nodelay;
|
||||
}
|
||||
|
||||
# HLS playlists — don't cache (they update every segment)
|
||||
location ~ ^/cameras/.+/hls/.+\.m3u8$ {
|
||||
proxy_pass http://vigilar_home;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# No cache — playlists must be fresh
|
||||
proxy_cache off;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
}
|
||||
|
||||
# --- SSE event stream ---
|
||||
location /events/stream {
|
||||
proxy_pass http://vigilar_home;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# SSE: disable buffering, long timeout
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_read_timeout 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
chunked_transfer_encoding on;
|
||||
proxy_set_header Connection '';
|
||||
proxy_http_version 1.1;
|
||||
}
|
||||
|
||||
# --- API endpoints ---
|
||||
location ~ ^/system/api/ {
|
||||
proxy_pass http://vigilar_home;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
limit_req zone=api burst=10 nodelay;
|
||||
}
|
||||
|
||||
# --- Static assets (cache aggressively on droplet) ---
|
||||
location /static/ {
|
||||
proxy_pass http://vigilar_home;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
proxy_cache hls_cache;
|
||||
proxy_cache_valid 200 1h;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
# --- Service worker (must not be cached stale) ---
|
||||
location = /static/sw.js {
|
||||
proxy_pass http://vigilar_home;
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache off;
|
||||
add_header Cache-Control "no-cache";
|
||||
}
|
||||
|
||||
# --- Everything else (pages, PWA manifest, etc.) ---
|
||||
location / {
|
||||
proxy_pass http://vigilar_home;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
|
||||
limit_req zone=api burst=20 nodelay;
|
||||
}
|
||||
|
||||
# Deny access to config/sensitive paths
|
||||
location ~ ^/(config|migrations|scripts|tests) {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Max upload size (for config changes, etc.)
|
||||
client_max_body_size 1m;
|
||||
|
||||
# Logging
|
||||
access_log /var/log/nginx/vigilar_access.log;
|
||||
error_log /var/log/nginx/vigilar_error.log;
|
||||
}
|
||||
Reference in New Issue
Block a user