Public Status Page for Nagios
A standalone public status page application that displays selected hosts and services from your Nagios monitoring system.
📦 PyPI: https://pypi.org/project/nagios-public-status-page/
🐳 Docker Hub: https://hub.docker.com/r/pgmac/nagios-public-status-page
📦 GitHub Container Registry: https://github.com/pgmac-net/nagios-public-status-page/pkgs/container/nagios-public-status-page
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
From PyPI (Recommended)
The easiest way to install is directly from PyPI:
# Install the package
pip install nagios-public-status-page
# Or using pipx for isolated installation
pipx install nagios-public-status-page
# Run the status page CLI
status-page --help
The PyPI package includes:
- Python package with all dependencies
- CLI command:
status-page - All static web assets
- Example configuration files
From Source with UV
# Clone the repository
git clone https://github.com/pgmac/nagios-public-status-page.git
cd nagios-public-status-page
# UV will automatically create a virtual environment and install dependencies
uv sync
From Source with pip
# Clone the repository
git clone https://github.com/pgmac/nagios-public-status-page.git
cd nagios-public-status-page
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install in development mode
pip install -e .
Quick Start
After installing from PyPI:
# 1. Install the package
pip install nagios-public-status-page
# 2. Create a basic config file
cat > config.yaml << EOF
nagios:
status_dat_path: "/usr/local/nagios/var/status.dat"
hostgroups:
- "public-status"
servicegroups:
- "public-status-services"
polling:
interval_seconds: 300
database:
path: "./data/status.db"
api:
host: "0.0.0.0"
port: 8000
EOF
# 3. Run the status page
status-page
# Or using Python module directly
python -m nagios_public_status_page.main
# 4. Access the dashboard
# Open http://localhost:8000 in your browser
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
Pre-built images are available from Docker Hub and GitHub Container Registry:
# Pull from Docker Hub (recommended)
docker pull pgmac/nagios-public-status-page:latest
# Or pull from GitHub Container Registry
docker pull ghcr.io/pgmac/nagios-public-status-page:latest
# Run the container
docker run -d \
-p 8000:8000 \
-v /usr/local/nagios/var/status.dat:/app/status.dat:ro \
-v ./config.yaml:/app/config.yaml:ro \
-v ./data:/app/data \
--name status-page \
pgmac/nagios-public-status-page:latest
# Access the dashboard
open http://localhost:8000
Available Image Tags:
latest- Latest stable release (semver tagged)v1.0.0- Specific version (replace with desired version)v1.0- Latest patch version in the 1.0 seriesv1- Latest minor version in the 1.x seriessha-<hash>- Specific commit hash (for testing)
Note: Only semver-tagged releases (e.g., v1.0.0) are pushed to the registries to keep them clean. SHA-tagged images are built but not pushed.
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
Creating a Release
To publish a new version to Docker registries, PyPI, and GitHub Releases:
-
Create and push a semver tag (the version in
pyproject.tomlwill be automatically updated):git tag v1.0.0 git push origin v1.0.0
-
GitHub Actions will automatically:
- Run tests, linting, and type checks
- Update version in
pyproject.tomlto match the tag - Build and publish Python package to PyPI
- Create a GitHub Release with distribution files
- Build and push Docker images to Docker Hub and GHCR with multiple tags
Note: The version in pyproject.toml is automatically updated from the git tag during the release process, so you don't need to manually update it before tagging.
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=nagios_public_status_page
Code Quality
# Run ruff linter
uv run ruff check src/ tests/
# Run pylint
uv run pylint src/nagios_public_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/
nagios_public_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/nagios_public_status_page/
Security & Code Quality
This project follows OpenSSF security best practices with automated scanning, dependency updates, and comprehensive code quality checks.
- Report vulnerabilities: See SECURITY.md
- Security setup guide: See SECURITY_QUICKSTART.md
- Repository security: See REPOSITORY_SECURITY.md
- Code scanning & coverage: See CODE_SCANNING_SETUP.md
License
MIT License - see LICENSE file for details
Author
@pgmac
Metadata
Release files for nagios-public-status-page 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nagios_public_status_page-0.3.2.tar.gz | 30.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nagios_public_status_page-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 68.9 kB
Release files / nagios_public_status_page-0.3.2.tar.gz
| Download URL | nagios_public_status_page-0.3.2.tar.gz |
|---|---|
| Size | 30.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c432aff82df8da866aa6e8a2f100bd9547382e7aad271a2a098d4ae9e145b74b
|
|
BLAKE2b-256 checksum How to use checksums |
b766e6bf0535c00306349d9958734305fa82fdae69b7d2bc8195081683b910da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","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}
|
Release files / nagios_public_status_page-0.3.2-py3-none-any.whl
| Download URL | nagios_public_status_page-0.3.2-py3-none-any.whl |
|---|---|
| Size | 38.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2a6e31688878fcf208e136dd549331edae847e5fb15ec855405cefd0161007e8
|
|
BLAKE2b-256 checksum How to use checksums |
58e18c5dc8fb8ba1c167e91bc45e695c3527d07728dac5114feafcc736493267
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","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}
|