Production-ready Docker deployment of Observium Community Edition with MariaDB, Smokeping latency monitoring, and automated scheduling.
This project provides a containerized Observium Community Edition 24.12 network monitoring platform with:
- Auto-provisioned infrastructure: MariaDB database, Apache web server, Smokeping integration
- Environment-driven configuration: Configure Observium via
.envfile - automatically translated to PHP config - Container-native operations: Logging to stdout/stderr, graceful shutdown handling, health checks
- Automated scheduling: Container-based job scheduler (Ofelia) replaces traditional cron
- Data protection: Automated daily backups of database and RRD files
- Production-ready: Race condition prevention, configurable timeouts, retry logic
- Dynamic PHP Configuration: Generate Observium config.php from environment variables with automatic type conversion (boolean, integer, string)
- Container-Based Scheduling: Ofelia job scheduler handles discovery, polling, housekeeping, and backups
- Centralized Logging: All services log to stdout/stderr for easy monitoring with
docker compose logs - Automated Backups: Daily backups of database and RRD files, automatically retains last 10
- Smokeping Integration: Built-in latency monitoring with automatic config generation
- Graceful Shutdown: Proper SIGTERM handling for clean container stops
- Database Safety: Initialization locking prevents race conditions when scaling
- Configurable Timeouts: Database connection timeout and config generation retry logic
- Enhanced Observability: Startup messages show config processing, warnings, and errors
- httpd: Observium web interface and backend (Apache + PHP 8.2)
- mariadb: MySQL-compatible database (MariaDB 11)
- smokeping: Network latency monitoring
- ofelia: Container-based job scheduler
observium-rrd: RRD graph databases (persistent)observium-logs: Application logsobservium-db: MariaDB data filessmokeping-data: Smokeping RRD filessmokeping-config: Smokeping configuration
- Database check: Wait for MariaDB to be ready (configurable timeout)
- Config generation: Create PHP config from environment variables
- Schema initialization: If database is empty, create tables and admin user (with distributed locking)
- Device import: Import SNMP devices from
snmp-devices.txtif present - Smokeping config: Generate Targets configuration
- Start services: Launch Apache and Smokeping
- Docker Engine 20.10+
- Docker Compose 2.0+
- SNMP-enabled devices to monitor
- (Optional) Observium Unix agent deployed on monitored systems
# 1. Clone repository
git clone https://github.com/trick77/docker-observium.git
cd docker-observium
# 2. Configure environment
cp .env.example .env
# Edit .env and set:
# - MARIADB_ROOT_PASSWORD
# - DB_PASSWORD
# - OBSERVIUM_ADMIN_PASSWORD
# - OBSERVIUM_FQDN
# 3. (Optional) Add SNMP devices to import on first startup
cp observium/conf/snmp-devices.txt.example observium/conf/snmp-devices.txt
# Edit snmp-devices.txt with your devices
# 4. Start services
docker compose up -d
# 5. Monitor startup (wait for "Successfully connected to database!")
docker compose logs -f httpd
# 6. Access web interface
# Navigate to: https://<OBSERVIUM_FQDN>
# Login: admin / <OBSERVIUM_ADMIN_PASSWORD>First startup takes 2-3 minutes for database initialization. Subsequent startups are faster.
Edit .env to configure the deployment:
| Variable | Description | Default |
|---|---|---|
MARIADB_ROOT_PASSWORD |
MariaDB root password | changeme |
DB_NAME |
Database name | observium |
DB_USER |
Database user | observium |
DB_PASSWORD |
Database password | changeme |
OBSERVIUM_ADMIN_USER |
Web UI admin username | admin |
OBSERVIUM_ADMIN_PASSWORD |
Web UI admin password | changeme |
OBSERVIUM_FQDN |
Fully qualified domain name | changeme.foobar.com |
DB_CONNECTION_TIMEOUT |
Database connection timeout (seconds) | 60 |
DEBUG_MODE |
Enable debug logging | false |
SHOW_GENERATED_CONFIG_DURING_STARTUP |
Show config in logs ( |
yes |
TZ |
Container timezone | Europe/Berlin |
Configure Observium settings by adding environment variables with the OBSERVIUM__ prefix to .env. These are automatically translated to PHP configuration at container startup.
| Pattern | Description | Example |
|---|---|---|
OBSERVIUM__key |
Simple value | OBSERVIUM__base_url=https://obs.example.com → $config['base_url'] |
OBSERVIUM__key1__key2 |
Nested array | OBSERVIUM__ping__retries=5 → $config['ping']['retries'] |
OBSERVIUM__key___name |
Dash in key name | OBSERVIUM__unix___agent__port=6556 → $config['unix-agent']['port'] |
OBSERVIUM__key__0 |
Indexed array | OBSERVIUM__bad_if__0=docker0 → $config['bad_if'][0] |
Values are automatically converted to appropriate PHP types:
true/false→ PHP boolean (TRUE/FALSE)- Numeric strings → PHP integers
- Strings with leading zeros → Kept as strings (e.g.,
007) - All other values → PHP strings
# Web interface
OBSERVIUM__base_url=https://${OBSERVIUM_FQDN}
OBSERVIUM__web_mouseover=false
OBSERVIUM__web_show_locations=1
# Polling
OBSERVIUM__ping__retries=5
OBSERVIUM__poller___wrapper__threads=2
# Interface filtering (ignore these)
OBSERVIUM__bad_if__0=docker0
OBSERVIUM__bad_if__1=lo
OBSERVIUM__bad_if_regexp__0='/^veth.*/'
OBSERVIUM__bad_if_regexp__1='/^br-.*/'
# Email notifications
OBSERVIUM__email__enable=true
OBSERVIUM__email__backend=smtp
OBSERVIUM__email__smtp_host=smtp.example.com
OBSERVIUM__email__smtp_port=587Translates to:
$config['base_url'] = 'https://observium.example.com';
$config['web_mouseover'] = FALSE;
$config['web_show_locations'] = 1;
$config['ping']['retries'] = 5;
$config['poller-wrapper']['threads'] = 2;
$config['bad_if'][0] = 'docker0';
$config['bad_if'][1] = 'lo';
$config['bad_if_regexp'][0] = '/^veth.*/';
$config['bad_if_regexp'][1] = '/^br-.*/';
$config['email']['enable'] = TRUE;
$config['email']['backend'] = 'smtp';
$config['email']['smtp_host'] = 'smtp.example.com';
$config['email']['smtp_port'] = 587;During startup, the config generator reports:
INFO: Processing 45 OBSERVIUM__ environment variables
Configuration generated successfully!
To debug configuration mapping, set SHOW_GENERATED_CONFIG_DURING_STARTUP=yes in .env and check container logs. Warning: This exposes database credentials in logs.
You can also view the final configuration in Observium's web UI under Global Settings > Full dump or Changed dump.
Add devices to monitor by creating observium/conf/snmp-devices.txt:
# Format: hostname|community|v2c|port|transport|description
192.168.1.1|public|v2c|161|udp|Router
192.168.1.10|secret|v2c|161|udp|Switch
Devices are automatically imported on container startup. Check logs:
docker compose logs httpd | grep "Importing SNMP devices"To add devices after initial startup:
# Restart container to trigger import
docker compose restart httpd
# Or add manually via web UI: Devices > Add DeviceOfelia scheduler manages background tasks:
| Job | Schedule | Description |
|---|---|---|
| discover-all | Every 6 hours | Full discovery of all devices |
| discover-new | Every 5 minutes | Discover new devices |
| poll | Every 5 minutes | Poll all devices for metrics |
| cleanup-logs | Daily at 05:13 | Clean up old log entries |
| cleanup-rrds | Daily at 04:47 | Clean up old RRD files |
| smokeping-config | Every 5 minutes | Regenerate Smokeping targets |
| backup-rrd | Daily | Backup RRD and Smokeping data |
| backup-db | Daily | Backup MariaDB database |
Backups are stored in /backup/destination/ inside the container. The most recent 10 backups are retained.
To persist backups, map a host directory:
# compose.override.yaml
services:
httpd:
volumes:
- ./backups:/backup/destination# All services
docker compose logs -f
# Specific service
docker compose logs -f httpd
docker compose logs -f mariadb
docker compose logs -f smokeping
# Filter by message type
docker compose logs httpd | grep "INFO:"
docker compose logs httpd | grep "WARNING:"
docker compose logs httpd | grep "ERROR:"
# Follow startup sequence
docker compose logs -f httpd | grep -E "(Attempt|Successfully|generated|initialized)"Check service status:
# Service overview
docker compose ps
# Detailed health status
docker compose ps httpd
# MariaDB ready check
docker compose exec mariadb mariadb -uroot -p${MARIADB_ROOT_PASSWORD} -e "SELECT 1"# CPU and memory usage
docker stats
# Disk usage
docker compose exec httpd du -sh /opt/observium/rrd
docker compose exec mariadb du -sh /var/lib/mysqlSymptoms: Container exits immediately after startup
Diagnosis:
docker compose logs httpd | grep ERRORCommon Causes:
-
Missing environment variables: Check for
ERROR: Required environment variable ... is not set- Solution: Ensure
DB_USER,DB_PASSWORD,DB_NAME,OBSERVIUM_ADMIN_USER, andOBSERVIUM_ADMIN_PASSWORDare set in.env
- Solution: Ensure
-
Database connection failure: Check for
ERROR: Failed to connect to database after 60 attempts- Solution: Verify MariaDB is running:
docker compose ps mariadb - Solution: Increase timeout:
DB_CONNECTION_TIMEOUT=120in.env
- Solution: Verify MariaDB is running:
-
Configuration generation failure: Check for
ERROR: Failed to generate configuration after 3 attempts- Solution: Check Python script syntax:
docker compose run --rm httpd python3 /usr/local/bin/generate_config.py
- Solution: Check Python script syntax:
Symptoms: ERROR: Database still not initialized and lock acquisition failed
Cause: Multiple containers trying to initialize simultaneously (race condition)
Solution:
- Stop all containers:
docker compose down - Remove database volume:
docker volume rm docker-observium_observium-db - Start single httpd instance:
docker compose up httpd - Wait for "Database initialization complete"
- Start remaining services:
docker compose up -d
Diagnosis:
# Check if Targets file exists
docker compose exec smokeping cat /etc/smokeping/config.d/Targets
# Check smokeping logs
docker compose logs smokeping
# Verify smokeping process
docker compose exec smokeping ps aux | grep smokepingCommon Issues:
-
Empty Targets file: No devices configured for Smokeping
- Solution: Add devices in Observium UI, wait 5 minutes for config regeneration
-
Smokeping not running: Check for startup errors
- Solution: Restart:
docker compose restart smokeping
- Solution: Restart:
Symptoms: Changed .env but Observium still uses old config
Solution:
# Restart container to regenerate config
docker compose restart httpd
# Verify config regeneration in logs
docker compose logs httpd | grep "Configuration generated"
# View generated config (⚠️ contains secrets)
SHOW_GENERATED_CONFIG_DURING_STARTUP=yes docker compose up httpdDiagnosis:
# Check Apache logs
docker compose logs httpd | grep -E "(error|Error|ERROR)"
# Check PHP errors
docker compose exec httpd cat /var/log/apache2/error.log
# Verify database connection
docker compose exec httpd mariadb -u${DB_USER} -p${DB_PASSWORD} -h mariadb ${DB_NAME} -e "SHOW TABLES"Common Causes:
-
Database not initialized: No tables in database
- Solution: Check initialization logs:
docker compose logs httpd | grep initialization
- Solution: Check initialization logs:
-
Wrong base_url: Config doesn't match accessed URL
- Solution: Set correct
OBSERVIUM__base_urlin.env
- Solution: Set correct
To upgrade to a newer version of Observium:
# Create backup directory
mkdir -p backups/$(date +%Y%m%d)
# Backup database
docker compose exec mariadb mariadb-dump -uroot -p${MARIADB_ROOT_PASSWORD} ${DB_NAME} | gzip > backups/$(date +%Y%m%d)/db_backup.sql.gz
# Backup RRD files
docker compose exec httpd tar czf /tmp/rrd_backup.tar.gz /opt/observium/rrd
docker compose cp httpd:/tmp/rrd_backup.tar.gz backups/$(date +%Y%m%d)/rrd_backup.tar.gzgit pull origin masterdocker compose build --no-cachedocker compose down
docker compose up -d# Check version
docker compose logs httpd | grep "VERSION:"
# Watch for migration messages
docker compose logs -f httpd
# Verify web interface loads
curl -I https://${OBSERVIUM_FQDN}This project is optimized for specific monitoring needs and intentionally excludes:
- RANCID integration
- CollectD support
- rrdcached
- ARM64 support
Pull Requests: Bugfix PRs are welcome. Feature requests will be considered on a case-by-case basis.
Version 24.12 (Current)
- Updated to Observium Community Edition 24.12
- Security: Replaced
evalwith safe indirect expansion - Reliability: Database initialization locking prevents race conditions
- Observability: Enhanced logging with INFO/WARNING/ERROR messages
- Containers: Graceful shutdown handling (SIGTERM)
- Configuration: Improved type conversion and validation
- Error Handling: Retry logic for config generation
# Build all images
docker compose build
# Build specific service
docker compose build httpd
# Build without cache
docker compose build --no-cache
# Test build
docker compose up -d
docker compose logs -fFound a bug? Please open an issue.
MIT License - See LICENSE file for details
