A public-facing status page that displays Nagios monitoring data with incident tracking and RSS feeds
Project description
Public Status Page for Nagios
A standalone public status page application that displays selected hosts and services from your Nagios monitoring system.
Features
- Reads from Nagios
status.datfile (no additional plugins required) - Filters hosts and services by hostgroups and servicegroups
- Configurable polling interval
- Tracks incidents with start/end times
- Manual status comments and updates
- Optional Nagios comment integration
- Post-Incident Review (PIR) document linking - Link resolved incidents to their PIR docs
- RSS feeds (global, per-host, per-service)
- Data staleness detection and warnings
- RESTful API for extensibility
- Completely separate from Nagios
- Simple deployment with SQLite
Architecture
The application consists of several components:
- Status.dat Parser: Parses Nagios status.dat and filters by hostgroups/servicegroups
- Data Collector: Background poller that tracks incidents and state changes
- REST API: FastAPI-based API for querying status and managing comments
- RSS Feed Generator: Generates RSS feeds for incidents
- Database: SQLite database for incidents, comments, and metadata
Requirements
- Python 3.11+
- Access to Nagios
status.datfile - UV package manager (recommended) or pip
Installation
Using UV (Recommended)
# Clone or download the project
cd public-status-page
# UV will automatically create a virtual environment and install dependencies
uv sync
Using pip
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install dependencies
pip install -e .
Configuration
1. Choose Your Filtering Method
The public status page supports two methods for filtering which hosts and services to display:
Method A: Hostgroups and Servicegroups (Recommended)
In your Nagios configuration, create hostgroups and servicegroups for public display:
# In your Nagios host definition
define host {
host_name webserver01
address 192.168.1.10
hostgroups linux-servers,public-status # Add to public-status
...
}
# In your Nagios service definition
define service {
service_description HTTP
host_name webserver01
servicegroups web-services,public-status-services # Add to public group
...
}
Note: This method requires that Nagios writes host_groups and service_groups fields to status.dat. Some Nagios configurations may not include these fields.
Method B: Explicit Host and Service Lists
If your Nagios doesn't write group fields to status.dat, you can explicitly list which hosts and services to monitor in config.yaml:
nagios:
status_dat_path: "/usr/local/nagios/var/status.dat"
hosts:
- "webserver01"
- "dbserver01"
services:
- host_name: "macro"
service_description: "plexweb"
- host_name: "webserver01"
service_description: "HTTP"
You can also use environment variables:
NAGIOS_HOSTS="webserver01,dbserver01"
NAGIOS_SERVICES="macro:plexweb,webserver01:HTTP"
Tip: You can combine both methods - the status page will include hosts/services that match either the groups or the explicit lists.
2. Configure the Application
Copy the example config and customize:
cp .env.example .env
# Edit config.yaml with your settings
Key configuration options in config.yaml:
nagios:
status_dat_path: "/usr/local/nagios/var/status.dat"
hostgroups:
- "public-status"
servicegroups:
- "public-status-services"
polling:
interval_seconds: 300 # Poll every 5 minutes
staleness_threshold_seconds: 600 # Warn if data > 10 minutes old
database:
path: "./data/status.db"
api:
host: "0.0.0.0"
port: 8000
Environment variables override config file values. See .env.example for available variables.
Deployment
Multiple deployment options are available:
Quick Start with Docker Compose
# Edit docker-compose.yml to configure your Nagios status.dat path
docker-compose up -d
# View logs
docker-compose logs -f
# Access the dashboard
open http://localhost:8000
Other Deployment Options
- Docker: Containerized deployment with multi-stage builds
- Systemd: Linux service deployment
- Manual: Direct Python deployment
See DEPLOYMENT.md for complete deployment documentation including:
- Docker and Docker Compose setup
- Systemd service configuration
- Production best practices
- Security hardening
- Troubleshooting guide
Usage
Running Tests
# Run all tests
uv run pytest
# Run with verbose output
uv run pytest -v
# Run with coverage
uv run pytest --cov=status_page
Code Quality
# Run ruff linter
uv run ruff check src/ tests/
# Run pylint
uv run pylint src/status_page/
# Auto-fix issues
uv run ruff check --fix src/ tests/
Project Status
Phase 1: Core Parser & Data Model ✅ COMPLETED
- Python project setup with UV
- status.dat parser with hostgroup/servicegroup filtering
- SQLAlchemy models and SQLite database
- Configuration loader with environment variable support
- Comprehensive test suite (17 tests passing)
- Code quality checks (ruff + pylint: 9.63/10)
Phase 2: Data Collector ✅ COMPLETED
- Incident tracker service for host/service problems
- Automatic incident creation, update, and closure
- APScheduler background poller
- Incident detection and tracking logic
- Nagios comment extraction during incidents
- Automatic comment linking to incidents
- Staleness detection and warnings
- Old incident cleanup
- Comprehensive test suite (13 additional tests = 30 total)
- Code quality checks (ruff + pylint: 9.74/10)
Phase 3: REST API ✅ COMPLETED
- FastAPI application with auto-generated docs
- Pydantic schemas for type-safe API responses
- Background poller integration (starts/stops with app)
- Health check endpoint with staleness detection
- Status summary endpoint (hosts/services counts)
- Hosts and services listing endpoints
- Incidents endpoint (filter by active/recent)
- Individual incident detail endpoint with comments
- POST endpoint to add comments to incidents
- CORS middleware configuration
- Comprehensive error handling
- Code quality checks (ruff + pylint: 9.34/10)
Phase 4: RSS Feeds ✅ COMPLETED
- feedgen integration
- IncidentFeedGenerator class with RSS generation
- Global RSS feed for all incidents
- Per-host RSS feeds
- Per-service RSS feeds
- Feed endpoints (GET /feed/rss, /feed/host/{name}/rss, /feed/service/{name}/{service}/rss)
- Configurable max_items and feed metadata
- Proper RSS XML formatting with pub dates and descriptions
- Comprehensive test suite (11 additional tests = 41 total)
- Code quality checks (ruff + pylint: 9.12/10)
Phase 5: Frontend ✅ COMPLETED
- Modern HTML5 dashboard with responsive design
- CSS styling with gradient headers and card-based layout
- JavaScript for API interaction (vanilla JS, no frameworks)
- Real-time status summary display (hosts/services/incidents)
- Incident list with active/recent/all filtering
- Host and service status displays
- Incident detail modal with comments
- Comment submission form with validation
- Staleness warning banner
- Auto-refresh every 60 seconds
- FastAPI static file serving configuration
- Secure DOM manipulation (XSS protection)
- RSS feed subscription links
- All 41 tests passing
- Code quality checks (ruff + pylint: 9.01/10)
Phase 6: Deployment ✅ COMPLETED
- Multi-stage Dockerfile for efficient containerization
- docker-compose.yml for easy deployment
- Comprehensive deployment documentation (DEPLOYMENT.md)
- systemd service file for Linux deployments
- .dockerignore for optimized builds
- Docker build tested successfully (290MB image)
- Health checks and security hardening
Phase 7: Post-Incident Review Integration ✅ COMPLETED
- Database schema: Added
post_incident_review_urlfield to incidents table - Database migration script (001_add_pir_url.py)
- API schemas updated to include PIR URL
- PATCH endpoint to set/update PIR URLs (
/api/incidents/{id}/pir) - Frontend displays PIR links in incident detail modal
- Comprehensive test suite (10 additional tests = 51 total)
- Documentation updated
API Endpoints
GET /api/status - Overall system status
GET /api/hosts - Filtered host statuses
GET /api/services - Filtered service statuses
GET /api/incidents - Active and recent incidents
GET /api/incidents/{id} - Specific incident details
POST /api/incidents/{id}/comments - Add manual status update
PATCH /api/incidents/{id}/pir - Link PIR document to incident
GET /api/health - Data freshness check
GET /feed/rss - RSS feed (all incidents)
GET /feed/host/{host_name}/rss - Per-host RSS feed
GET /feed/service/{host_name}/{service}/rss - Per-service RSS feed
Database Schema
The SQLite database includes:
- incidents: Host and service incidents with start/end times (includes
post_incident_review_url) - comments: Manual status updates
- nagios_comments: Comments pulled from Nagios
- poll_metadata: Polling history and metadata
Post-Incident Review (PIR) Integration
Link resolved incidents to their post-incident review documents for better incident tracking and learning.
Setting a PIR URL for an Incident
Use the PATCH endpoint to associate a PIR document with an incident:
curl -X PATCH http://localhost:8000/api/incidents/123/pir \
-H "Content-Type: application/json" \
-d '{"post_incident_review_url": "https://your-pir-docs.com/incidents/2025-01-10-incident/"}'
Viewing PIR Links
PIR links appear:
- In the incident detail modal on the dashboard (with a document icon)
- In API responses for incidents (
GET /api/incidents/{id}andGET /api/incidents) - PIR URLs are optional and can be null for incidents without documentation
Database Migration
If upgrading from an earlier version, run the migration to add the PIR URL column:
python migrations/001_add_pir_url.py data/status.db
Development
Project Structure
public-status-page/
src/
status_page/
parser/ # status.dat parser
collector/ # Background polling
api/ # FastAPI routes
rss/ # RSS feed generator
db/ # Database setup
models.py # SQLAlchemy models
config.py # Configuration
tests/ # Test suite
static/ # Frontend files
config.yaml # Configuration
pyproject.toml # Dependencies
Contributing
- Ensure tests pass:
uv run pytest - Run linters:
uv run ruff check src/ tests/ - Run pylint:
uv run pylint src/status_page/
License
[Your License Here]
Author
@pgmac
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nagios_public_status_page-0.1.0.tar.gz.
File metadata
- Download URL: nagios_public_status_page-0.1.0.tar.gz
- Upload date:
- Size: 20.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3ecdf6ca6ace60fa77f477c19f418944cc7f02a9b7908980445b72f56cea3f7
|
|
| MD5 |
d3baedbc660a490ba07cec3ab1e2eee9
|
|
| BLAKE2b-256 |
b562a9cda4c1d391f8b9a545258f4817bb137eaa976172317ba163442a48d294
|
File details
Details for the file nagios_public_status_page-0.1.0-py3-none-any.whl.
File metadata
- Download URL: nagios_public_status_page-0.1.0-py3-none-any.whl
- Upload date:
- Size: 28.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
109f04557d3e9d74ff5ae470e59fdc9f3a168fc7827cd9028df8a1e55340c99f
|
|
| MD5 |
c4b0b5bace0529765217c001f54e1f0b
|
|
| BLAKE2b-256 |
7e4637cd34fb5d5f09cd8a0161f373c505a4d35138f637d54a6b345b612d6675
|