An open-source, modern, and feature-rich surveillance system powered by OpenCV (not Motion).
9.8K
100% free and open-source AI-powered surveillance with face recognition, motion detection, and smart home integration. Your data stays on your hardware - no subscriptions, no cloud dependencies.
š GitHub: https://github.com/M1K31/OpenEye-OpenCV_Home_Securityā š Full Documentation: README.mdā š API Documentation: API_REFERENCE.mdā š Changelog: CHANGELOG.mdā
Cost: $0/month forever ⢠Privacy: All data stays local ⢠Control: You own everything
httpx.AsyncClient across ecosystem client (eliminates per-request overhead)GROUP BY aggregation instead of per-row queriesecosystem_client/ and ecosystem_auth/ included in Docker buildSee CHANGELOG.mdā for full details.
docker run -d \
-p 8000:8000 \
-v ./data:/app/data \
-v ./recordings:/app/recordings \
-v ./faces:/app/faces \
-e SECRET_KEY=$(openssl rand -hex 32) \
-e JWT_SECRET_KEY=$(openssl rand -hex 32) \
-e NOTIFICATION_ENCRYPTION_KEY=$(python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())") \
-e ECOSYSTEM_HMAC_SECRET=$(openssl rand -hex 32) \
--restart unless-stopped \
--name openeye \
im1k31s/openeye-opencv_home_security:latest
Access: http://localhost:8000ā
Create docker-compose.yml:
services:
openeye:
image: im1k31s/openeye-opencv_home_security:latest
container_name: openeye
ports:
- "8000:8000"
volumes:
- ./data:/app/data
- ./recordings:/app/recordings
- ./faces:/app/faces
environment:
# Security Keys (REQUIRED - generate unique keys for production)
- SECRET_KEY=${SECRET_KEY}
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- NOTIFICATION_ENCRYPTION_KEY=${NOTIFICATION_ENCRYPTION_KEY}
- ECOSYSTEM_HMAC_SECRET=${ECOSYSTEM_HMAC_SECRET}
# Authentication Settings
- ALGORITHM=HS256
- ACCESS_TOKEN_EXPIRE_MINUTES=30
# Database (Optional - default is SQLite)
- DATABASE_URL=sqlite:///./surveillance.db
# CORS (Optional)
- CORS_ORIGINS=http://localhost:8000
# Logging (Optional)
- LOG_LEVEL=INFO
restart: unless-stopped
# Uncomment for NVIDIA GPU acceleration
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: 1
# capabilities: [gpu]
# Optional: PostgreSQL for production (>5 concurrent users)
# postgres:
# image: postgres:15-alpine
# container_name: openeye-db
# environment:
# - POSTGRES_USER=openeye
# - POSTGRES_PASSWORD=secure_password_here
# - POSTGRES_DB=openeye
# volumes:
# - postgres-data:/var/lib/postgresql/data
# restart: unless-stopped
#
#volumes:
# postgres-data:
Generate Secret Keys (save in .env file):
# Create .env file with generated keys
cat > .env << EOF
SECRET_KEY=$(openssl rand -hex 32)
JWT_SECRET_KEY=$(openssl rand -hex 32)
NOTIFICATION_ENCRYPTION_KEY=$(python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())")
ECOSYSTEM_HMAC_SECRET=$(openssl rand -hex 32)
EOF
Start the stack:
docker-compose up -d
View logs:
docker-compose logs -f openeye
Stop the stack:
docker-compose down
You're ready! View live cameras on the dashboard.
| Camera Type | Docker Support | Example |
|---|---|---|
| RTSP/IP Cameras | ā Full | rtsp://admin:[email protected]:554/stream |
| ONVIF Cameras | ā Full | Auto-discovered |
| USB Webcams | ā ļø Linux only | /dev/video0 |
| Mock (Testing) | ā Full | Built-in test camera |
# Hikvision
rtsp://admin:[email protected]:554/Streaming/Channels/101
# Dahua
rtsp://admin:[email protected]:554/cam/realmonitor?channel=1&subtype=0
# Amcrest
rtsp://admin:[email protected]:554/cam/realmonitor?channel=1&subtype=1
# Reolink
rtsp://admin:[email protected]:554/h264Preview_01_main
# Generic
rtsp://username:password@camera-ip:554/stream
Docker Desktop on macOS and Windows runs containers inside a Linux virtual machine. This creates fundamental limitations for hardware access:
| Platform | USB Camera Support | Reason |
|---|---|---|
| Linux | ā Full support | Direct device access via --device=/dev/video0 |
| macOS | ā Not available | Docker VM cannot access USB devices |
| Windows | ā Not available | Docker VM cannot access USB devices |
USB cameras connected to your Mac or Windows PC are not visible to the Docker container. The camera discovery feature will not find any USB cameras in these environments.
The container uses Docker's bridge network by default, which means:
network_mode: host works on Linux but has limitations on macOS/Windows| Solution | Platform | USB Cameras | Network Cameras |
|---|---|---|---|
| 1. Use RTSP URLs manually | All | ā | ā Best option |
| 2. Run OpenEye natively | macOS/Windows | ā Full | ā Full |
| 3. Linux with device passthrough | Linux | ā Full | ā Full |
| 4. Linux with host networking | Linux | ā Full | ā Full |
Recommended for macOS/Windows Docker users: Add IP cameras manually using their RTSP URLs instead of relying on auto-discovery.
services:
openeye:
# ... other config ...
# USB camera passthrough
devices:
- /dev/video0:/dev/video0
- /dev/video1:/dev/video1
# Full network access for camera discovery
network_mode: host
See README.mdā for native installation instructions.
latest - Most recent stable release (v3.11.6)v3.11.6 - Current version - Ecosystem security audit, HMAC signing, SSRF protection, CI/CD automationv3.11.5 - Camera discovery fix, Docker platform documentationv3.11.4 - Scheduled tasks, MagicMirror search APIv3.11.1 - Multi-user system, ecosystem integrationv3.10.2 - Face detection fix, timeline playback improvementsv3.10.1 - Two-way audio enhancements, test infrastructurev3.10.0 - Object detection (YOLOv8), two-way audiov3.9.0 - Security hardening, performance optimizationv3.7.1 - FFmpeg hardware encoding (70-90% CPU reduction)v3.6.0 - Security hardening (2FA, rate limiting, CSRF protection)Recommended: Use latest for automatic updates or specific version tags for production stability.
| Variable | Required | Default | Description |
|---|---|---|---|
SECRET_KEY | Yes | - | Application secret key (32+ hex chars) |
JWT_SECRET_KEY | Yes | - | JWT signing key (32+ hex chars) |
NOTIFICATION_ENCRYPTION_KEY | Yes | - | Fernet key for encrypting notification credentials |
ECOSYSTEM_HMAC_SECRET | Yes | - | HMAC-SHA256 key for signing inter-service messages (32+ hex chars) |
ALGORITHM | No | HS256 | JWT algorithm |
ACCESS_TOKEN_EXPIRE_MINUTES | No | 30 | Token expiration time |
DATABASE_URL | No | sqlite:///./surveillance.db | Database connection string |
CORS_ORIGINS | No | http://localhost:8000 | Allowed CORS origins (comma-separated) |
LOG_LEVEL | No | INFO | Logging level (DEBUG, INFO, WARNING, ERROR) |
OPENEYE_HOST | No | 0.0.0.0 | Server bind address |
OPENEYE_PORT | No | 8000 | Server port |
MAGICMIRROR_HOST | No | - | MagicMirror device address (for ecosystem discovery) |
MAGICMIRROR_PORT | No | - | MagicMirror device port |
| Container Path | Purpose | Recommended Host Path |
|---|---|---|
/app/data | Database, thumbnails, snapshots | ./data |
/app/recordings | Video recordings | ./recordings |
/app/faces | Face recognition training images | ./faces |
/app/models | AI models (auto-downloaded) | ./models |
All notification providers are configured through the Web UI - no environment variables or coding required!
Go to "System & Alerts" ā "Configure Notification Providers"
Click "Add Provider" and choose:
Enter credentials (encrypted automatically with Fernet)
Test the provider
Enable in alert rules
123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11123456789smtp.gmail.com587[email protected]your-16-char-app-passwordAdd to configuration.yaml:
mqtt:
sensor:
- name: "Front Door Motion"
state_topic: "openeye/front_door/motion"
- name: "Front Door Face"
state_topic: "openeye/front_door/face"
automation:
- alias: "Alert on Unknown Face"
trigger:
platform: state
entity_id: sensor.front_door_face
to: "unknown"
action:
service: notify.mobile_app
data:
message: "Unknown person at front door"
openssl rand -hex 32 (never use defaults)docker pull im1k31s/openeye-opencv_home_security:latest regularly/app/data, /app/recordings, /app/faces volumesdocker-compose logs -f for errorsSECRET_KEY and JWT_SECRET_KEY generatedNOTIFICATION_ENCRYPTION_KEY generatedECOSYSTEM_HMAC_SECRET generated (required for inter-service security)# Check if container is running
docker ps
# Check logs
docker logs openeye
# Restart container
docker restart openeye
# Check port binding
lsof -i:8000
vlc rtsp://username:password@camera-ip:554/streamMOTION_DETECTION_SCALE to process smaller framesFor production with >5 concurrent users, switch to PostgreSQL:
services:
openeye:
environment:
- DATABASE_URL=postgresql://openeye:password@postgres:5432/openeye
depends_on:
- postgres
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_USER=openeye
- POSTGRES_PASSWORD=secure_password
- POSTGRES_DB=openeye
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
# Fix volume permissions
sudo chown -R 1000:1000 ./data ./recordings ./faces
# Or run container with your UID
docker run ... -e PUID=$(id -u) -e PGID=$(id -g) ...
environment:
- MOTION_DETECTION_SCALE=0.5 # Process 50% size frames
- RECORDING_FPS=15 # Lower FPS
- LOG_LEVEL=WARNING # Reduce log overhead
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
Then configure cameras to use GPU acceleration in settings.
http://localhost:8000/docs (Swagger UI after starting)MIT License - Free to use, modify, and distribute.
Copyright (c) 2025 Mikel Smart
If you find OpenEye useful:
Made with ā¤ļø using OpenCV, FastAPI, and React
OpenEye - See clearly, secure completely. 100% Free Forever.
Content type
Image
Digest
sha256:f07973468ā¦
Size
577.2 MB
Last updated
22 days ago
docker pull im1k31s/openeye-opencv_home_security