2026-02-16 20:00:32 +00:00
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
2026-02-16 20:05:58 +00:00
Watchdog Docker - OPNsense monitoring system with web dashboard and email notifications. Monitors DHCP leases, new devices (ARP), interface status changes, and gateway status changes.
**Current Version:** See [VERSION ](VERSION ) file
**Changelog:** [CHANGELOG.md ](CHANGELOG.md )
2026-02-16 20:00:32 +00:00
## Tech Stack
- **Backend:** Python 3.11, Flask, Flask-Login
- **Scheduling:** APScheduler (background polling)
- **Database:** SQLite
- **Frontend:** Bootstrap 5, Vanilla JavaScript
- **API:** OPNsense REST API
- **Email:** SMTP with TLS
- **Deployment:** Docker + Docker Compose
## Commands
### Docker
```bash
# Build and start
docker-compose up -d --build
# View logs
docker-compose logs -f
# Stop
docker-compose down
# Restart
docker-compose restart
```
### Local Development
```bash
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Run app
python app/main.py
```
### Testing
```bash
# Test OPNsense API connection
python -c "from app.opnsense_api import OPNsenseAPI; import yaml; config = yaml.safe_load(open('config/config.yaml')); api = OPNsenseAPI(**config['opnsense']); print(api.test_connection())"
# Generate password hash
python -c "from werkzeug.security import generate_password_hash; print(generate_password_hash('your_password'))"
```
## Architecture
### Application Flow
1. **main.py** - Flask app initialization, routes, APScheduler setup
2. **monitor.py** - OPNsenseMonitor class runs periodic checks (check_all)
3. **opnsense_api.py** - OPNsenseAPI client handles all API communication
4. **database.py** - Database class manages SQLite operations
5. **email_handler.py** - EmailHandler sends SMTP notifications
### Monitoring Cycle
- APScheduler triggers `monitor.check_all()` every N seconds (configurable)
- Each check method compares current state vs previous state
- On changes: log to database + send email (if enabled)
- State stored in memory (resets on restart)
### Database Schema
- **events** - All monitored events (id, timestamp, type, interface, details, data JSON)
- **known_devices** - MAC addresses of known devices (auto-populated on first detection)
### Web Interface
- Login required (Flask-Login)
- Dashboard shows stats + filterable event table
- AJAX auto-refresh every 10s via /api/events endpoint
## Key Files
2026-02-16 20:05:58 +00:00
- **VERSION** - Current version number (single source of truth)
- **CHANGELOG.md** - Complete version history and changes
2026-02-16 20:00:32 +00:00
- **config/config.yaml** - ALL settings (OPNsense, monitoring, web, email, database)
2026-02-16 20:05:58 +00:00
- **app/main.py** - Flask app entry point (loads VERSION file)
2026-02-16 20:00:32 +00:00
- **app/monitor.py** - Core monitoring logic with state tracking
- **app/database.py** - SQLite operations
- **app/email_handler.py** - Email notifications with HTML templates
- **app/opnsense_api.py** - OPNsense API wrapper
- **app/templates/** - Jinja2 templates (login.html, dashboard.html)
## Configuration
All settings in `config/config.yaml` :
- OPNsense host, API credentials, SSL verification
- Monitoring interval, monitored interfaces, event toggles
- Web port, secret key, admin password hash
- SMTP settings, recipients
- Database path, retention days
- Logging level
## Important Notes
- **State Tracking:** Monitor uses previous_* dicts to detect changes (DHCP leases, devices, interfaces, gateways)
- **Interface Filtering:** If `monitored_interfaces` is empty, monitor ALL interfaces
- **Known Devices:** New devices are auto-added to known_devices table on first detection
- **Email Logic:** Only send emails for unknown devices (new_device event with known=False)
- **Retention:** Old events auto-cleanup based on retention_days (default 90)
- **Password:** Admin password must be werkzeug scrypt hash in config.yaml
2026-02-16 20:05:58 +00:00
## Versioning
### Version Schema
- **Big changes** (new features, breaking changes): +0.1 (e.g., 0.1.0 → 0.2.0)
- **Small changes** (bugfixes, minor improvements): +0.0.1 (e.g., 0.1.0 → 0.1.1)
- **Major release** (1.x): Only on instruction
### Git Workflow
- **main** - Stable releases only
- **develop** - Active development (current working branch)
- Feature branches for larger features
### Making Changes
1. Work in `develop` branch
2. Update VERSION file with new version number
3. Update CHANGELOG.md with changes (follow Keep a Changelog format)
4. Commit changes with descriptive message
5. Push to develop
6. Merge to main when stable and tested
2026-02-16 20:00:32 +00:00
## Code Style
- German language in UI/emails (Deutsch)
- Docstrings in English
- Logging: logger.info for important events, logger.debug for routine operations
- Error handling: try/except with logger.error(..., exc_info=True)
- Type hints where applicable (Dict, List, Optional)
## Common Tasks
### Add new event type
1. Add check method to `monitor.py` (check_xyz)
2. Add toggle to config.yaml under events
3. Call from check_all() if enabled
4. Update email_handler colors/formatting if needed
### Modify OPNsense API calls
- All API methods in `opnsense_api.py`
- Use requests with basic auth (key:secret)
- SSL warnings suppressed if verify_ssl=false
### Change database schema
- Update initialize() in database.py
- Add migration logic if needed (or recreate DB)