Skip to content

Commit 9ae37a3

Browse files
committed
feat: add MkDocs documentation site with GitHub Pages deployment
Adds a searchable, navigable documentation site built with MkDocs and the Material theme. The site includes all 242 plugin READMEs, installation guides, and reference documentation.
1 parent 636b71a commit 9ae37a3

File tree

5 files changed

+321
-0
lines changed

5 files changed

+321
-0
lines changed

.github/workflows/docs.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: 'Deploy Documentation'
2+
3+
on:
4+
push:
5+
branches:
6+
- 'main'
7+
8+
permissions:
9+
contents: 'read'
10+
pages: 'write'
11+
id-token: 'write'
12+
13+
concurrency:
14+
group: 'pages'
15+
cancel-in-progress: true
16+
17+
jobs:
18+
build:
19+
runs-on: 'ubuntu-latest'
20+
steps:
21+
- name: 'Checkout repository'
22+
uses: 'actions/checkout@v6'
23+
24+
- name: 'Set up Python'
25+
uses: 'actions/setup-python@v6'
26+
with:
27+
python-version: '3.12'
28+
29+
- name: 'Install dependencies'
30+
run: 'pip install mkdocs mkdocs-material'
31+
32+
- name: 'Generate docs structure'
33+
run: 'python3 tools/build-docs'
34+
35+
- name: 'Build documentation'
36+
run: 'mkdocs build --strict'
37+
38+
- name: 'Upload Pages artifact'
39+
uses: 'actions/upload-pages-artifact@v4'
40+
with:
41+
path: 'site'
42+
43+
deploy:
44+
needs: 'build'
45+
runs-on: 'ubuntu-latest'
46+
environment:
47+
name: 'github-pages'
48+
url: '${{ steps.deployment.outputs.page_url }}'
49+
steps:
50+
- name: 'Deploy to GitHub Pages'
51+
id: 'deployment'
52+
uses: 'actions/deploy-pages@v5'

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,19 @@ venv.bak/
117117
.ropeproject
118118

119119
# mkdocs documentation
120+
/docs/build.md
121+
/docs/CHANGELOG.md
122+
/docs/check-plugins/
123+
/docs/CODE_OF_CONDUCT.md
124+
/docs/contributing.md
125+
/docs/event-plugins/
126+
/docs/grafana.md
127+
/docs/icinga.md
128+
/docs/install.md
129+
/docs/notification-plugins/
130+
/docs/plugins-*.md
131+
/docs/security.md
132+
/mkdocs.yml
120133
/site
121134

122135
# mypy

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ All plugins are written in Python and licensed under the [UNLICENSE](https://unl
3939
The plugins are fast and reliable, using as few system resources as possible. They report the same metrics consistently and uniformly on all platforms (for example, they always use 'used' instead of a mixture of 'used' and 'free'). Where possible, automatic detection and auto-discovery mechanisms are built in. The plugins use meaningful default settings to trigger WARNs and CRITs only where absolutely necessary. In addition, many plugins offer troubleshooting information. We avoid dependencies on third-party system libraries wherever possible.
4040

4141

42+
## Documentation
43+
44+
Full documentation is available at [linuxfabrik.github.io/monitoring-plugins](https://linuxfabrik.github.io/monitoring-plugins/). It is automatically built and deployed on every push to `main`.
45+
46+
4247
## Want to see some Plugins in Action?
4348

4449
Visit [icinga-demo.linuxfabrik.ch](https://icinga-demo.linuxfabrik.ch).

docs/index.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Linuxfabrik Monitoring Plugins
2+
3+
230+ monitoring plugins for Icinga, Nagios and compatible monitoring systems. Python 3.9+, all platforms. Smart defaults, auto-discovery, consistent cross-platform metrics, minimal dependencies.
4+
5+
Made by [Linuxfabrik](https://www.linuxfabrik.ch).
6+
7+
8+
## Overview
9+
10+
This Enterprise Class Check Plugin Collection offers a package of Python-based, Nagios-compatible check plugins for Icinga, Naemon, Nagios, OP5, Shinken, Sensu and other monitoring applications. Each plugin is a stand-alone command line tool that provides a specific type of check. Typically, your monitoring software will run these check plugins to determine the current status of hosts and services on your network.
11+
12+
All plugins are written in Python and licensed under the [UNLICENSE](https://unlicense.org/). They run on all platforms that support Python 3.9 and above, like Linux, Windows, macOS, FreeBSD and others. For Windows, there are compiled plugins available, meaning you don't need Python.
13+
14+
The plugins are fast and reliable, using as few system resources as possible. They report the same metrics consistently and uniformly on all platforms. Where possible, automatic detection and auto-discovery mechanisms are built in. The plugins use meaningful default settings to trigger WARNs and CRITs only where absolutely necessary.
15+
16+
17+
## Quick Start
18+
19+
1. [Install the plugins](install.md)
20+
2. [Configure Icinga Director](icinga.md)
21+
3. [Set up Grafana dashboards](grafana.md)
22+
23+
24+
## Plugin Groups
25+
26+
Some plugins belong together and share a common setup:
27+
28+
- [Keycloak Plugins](plugins-keycloak.md)
29+
- [MySQL Plugins](plugins-mysql.md)
30+
- [Rocket.Chat Plugins](plugins-rocketchat.md)
31+
- [WildFly Plugins](plugins-wildfly.md)
32+
33+
34+
## Want to see some Plugins in Action?
35+
36+
Visit [icinga-demo.linuxfabrik.ch](https://icinga-demo.linuxfabrik.ch).
37+
38+
39+
## Links
40+
41+
- [GitHub Repository](https://github.com/Linuxfabrik/monitoring-plugins)
42+
- [Report an Issue](https://github.com/Linuxfabrik/monitoring-plugins/issues/new/choose)
43+
- [Linuxfabrik Lib (Python libraries)](https://linuxfabrik.github.io/lib/lib.html)
44+
- [LFOps Ansible Collection](https://github.com/Linuxfabrik/lfops)
45+
- [Linuxfabrik Website](https://www.linuxfabrik.ch)

tools/build-docs

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8; py-indent-offset: 4 -*-
3+
#
4+
# Author: Linuxfabrik GmbH, Zurich, Switzerland
5+
# Contact: info (at) linuxfabrik (dot) ch
6+
# https://www.linuxfabrik.ch/
7+
# License: The Unlicense, see LICENSE file.
8+
9+
"""Generates the docs/ directory structure with symlinks and the mkdocs.yml navigation
10+
for the Linuxfabrik Monitoring Plugins documentation site.
11+
12+
Run this tool from the repository root directory.
13+
"""
14+
15+
import os
16+
import sys
17+
18+
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
19+
__version__ = '2026040701'
20+
21+
REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
22+
DOCS_DIR = os.path.join(REPO_ROOT, 'docs')
23+
24+
# Top-level markdown files to include in the documentation.
25+
# Format: (source filename, target filename in docs/, nav title)
26+
TOP_LEVEL_DOCS = [
27+
('BUILD.md', 'build.md', 'Compiling and Packaging'),
28+
('CHANGELOG.md', 'CHANGELOG.md', None),
29+
('CODE_OF_CONDUCT.md', 'CODE_OF_CONDUCT.md', None),
30+
('CONTRIBUTING.md', 'contributing.md', 'Contributing'),
31+
('GRAFANA.md', 'grafana.md', 'Grafana'),
32+
('ICINGA.md', 'icinga.md', 'Icinga Setup'),
33+
('INSTALL.md', 'install.md', 'Installation'),
34+
('PLUGINS-KEYCLOAK.md', 'plugins-keycloak.md', 'Plugin Group: Keycloak'),
35+
('PLUGINS-MYSQL.md', 'plugins-mysql.md', 'Plugin Group: MySQL'),
36+
('PLUGINS-ROCKETCHAT.md', 'plugins-rocketchat.md', 'Plugin Group: Rocket.Chat'),
37+
('PLUGINS-WILDFLY.md', 'plugins-wildfly.md', 'Plugin Group: WildFly'),
38+
('SECURITY.md', 'security.md', 'Security'),
39+
]
40+
41+
# Plugin directories to scan
42+
PLUGIN_DIRS = [
43+
('check-plugins', 'Check Plugins'),
44+
('notification-plugins', 'Notification Plugins'),
45+
('event-plugins', 'Event Plugins'),
46+
]
47+
48+
49+
def create_symlink(source, target):
50+
"""Create a relative symlink from target to source."""
51+
target_dir = os.path.dirname(target)
52+
rel_source = os.path.relpath(source, target_dir)
53+
if os.path.islink(target):
54+
os.unlink(target)
55+
elif os.path.exists(target):
56+
os.unlink(target)
57+
os.symlink(rel_source, target)
58+
59+
60+
def scan_plugins(plugin_dir):
61+
"""Scan a plugin directory and return sorted list of plugin names that have a README.md."""
62+
full_path = os.path.join(REPO_ROOT, plugin_dir)
63+
if not os.path.isdir(full_path):
64+
return []
65+
plugins = []
66+
for entry in sorted(os.listdir(full_path)):
67+
if entry == 'example':
68+
continue
69+
readme = os.path.join(full_path, entry, 'README.md')
70+
if os.path.isfile(readme):
71+
plugins.append(entry)
72+
return plugins
73+
74+
75+
def generate_mkdocs_yml(nav_sections):
76+
"""Generate the mkdocs.yml content."""
77+
lines = []
78+
lines.append("# This file is auto-generated by tools/build-docs. Do not edit manually.")
79+
lines.append("")
80+
lines.append("site_name: 'Linuxfabrik Monitoring Plugins'")
81+
lines.append("site_url: 'https://linuxfabrik.github.io/monitoring-plugins/'")
82+
lines.append("repo_url: 'https://github.com/Linuxfabrik/monitoring-plugins'")
83+
lines.append("repo_name: 'Linuxfabrik/monitoring-plugins'")
84+
lines.append("")
85+
lines.append("theme:")
86+
lines.append(" name: 'material'")
87+
lines.append(" icon:")
88+
lines.append(" logo: 'material/monitor-dashboard'")
89+
lines.append(" palette:")
90+
lines.append(" - scheme: 'default'")
91+
lines.append(" primary: 'blue grey'")
92+
lines.append(" accent: 'orange'")
93+
lines.append(" toggle:")
94+
lines.append(" icon: 'material/brightness-7'")
95+
lines.append(" name: 'Switch to dark mode'")
96+
lines.append(" - scheme: 'slate'")
97+
lines.append(" primary: 'blue grey'")
98+
lines.append(" accent: 'orange'")
99+
lines.append(" toggle:")
100+
lines.append(" icon: 'material/brightness-4'")
101+
lines.append(" name: 'Switch to light mode'")
102+
lines.append(" features:")
103+
lines.append(" - content.code.copy")
104+
lines.append(" - navigation.expand")
105+
lines.append(" - navigation.instant")
106+
lines.append(" - navigation.sections")
107+
lines.append(" - navigation.top")
108+
lines.append(" - search.highlight")
109+
lines.append(" - search.suggest")
110+
lines.append(" - toc.follow")
111+
lines.append("")
112+
lines.append("markdown_extensions:")
113+
lines.append(" - admonition")
114+
lines.append(" - attr_list")
115+
lines.append(" - def_list")
116+
lines.append(" - tables")
117+
lines.append(" - toc:")
118+
lines.append(" permalink: true")
119+
lines.append("")
120+
lines.append("plugins:")
121+
lines.append(" - search")
122+
lines.append("")
123+
lines.append("not_in_nav: |")
124+
lines.append(" CHANGELOG.md")
125+
lines.append(" CODE_OF_CONDUCT.md")
126+
lines.append("")
127+
128+
# Build nav
129+
lines.append("nav:")
130+
lines.append(" - 'Home': 'index.md'")
131+
lines.append(" - 'Installation': 'install.md'")
132+
lines.append(" - 'Icinga Setup': 'icinga.md'")
133+
lines.append(" - 'Grafana': 'grafana.md'")
134+
135+
for section_dir, section_title, plugins in nav_sections:
136+
lines.append(f" - '{section_title}':")
137+
for plugin in plugins:
138+
lines.append(f" - '{plugin}': '{section_dir}/{plugin}.md'")
139+
140+
lines.append(" - 'Plugin Groups':")
141+
lines.append(" - 'Keycloak': 'plugins-keycloak.md'")
142+
lines.append(" - 'MySQL': 'plugins-mysql.md'")
143+
lines.append(" - 'Rocket.Chat': 'plugins-rocketchat.md'")
144+
lines.append(" - 'WildFly': 'plugins-wildfly.md'")
145+
lines.append(" - 'Compiling and Packaging': 'build.md'")
146+
lines.append(" - 'Contributing': 'contributing.md'")
147+
lines.append(" - 'Security': 'security.md'")
148+
lines.append("")
149+
150+
return '\n'.join(lines)
151+
152+
153+
def main():
154+
os.makedirs(DOCS_DIR, exist_ok=True)
155+
156+
# Create symlinks for top-level docs
157+
for source_name, target_name, _ in TOP_LEVEL_DOCS:
158+
source = os.path.join(REPO_ROOT, source_name)
159+
target = os.path.join(DOCS_DIR, target_name)
160+
if os.path.isfile(source):
161+
create_symlink(source, target)
162+
else:
163+
print(f'WARNING: {source_name} not found, skipping.')
164+
165+
# Create symlinks for plugin READMEs
166+
nav_sections = []
167+
for plugin_dir, section_title in PLUGIN_DIRS:
168+
plugins = scan_plugins(plugin_dir)
169+
if not plugins:
170+
continue
171+
172+
target_dir = os.path.join(DOCS_DIR, plugin_dir)
173+
os.makedirs(target_dir, exist_ok=True)
174+
175+
# Remove stale symlinks
176+
expected_files = {f'{plugin}.md' for plugin in plugins}
177+
for entry in os.listdir(target_dir):
178+
entry_path = os.path.join(target_dir, entry)
179+
if os.path.islink(entry_path) and entry not in expected_files:
180+
os.unlink(entry_path)
181+
182+
for plugin in plugins:
183+
source = os.path.join(REPO_ROOT, plugin_dir, plugin, 'README.md')
184+
target = os.path.join(target_dir, f'{plugin}.md')
185+
create_symlink(source, target)
186+
187+
nav_sections.append((plugin_dir, section_title, plugins))
188+
189+
# Generate mkdocs.yml
190+
mkdocs_content = generate_mkdocs_yml(nav_sections)
191+
mkdocs_path = os.path.join(REPO_ROOT, 'mkdocs.yml')
192+
with open(mkdocs_path, 'w') as f:
193+
f.write(mkdocs_content)
194+
195+
# Count
196+
total_symlinks = len(TOP_LEVEL_DOCS)
197+
for _, _, plugins in nav_sections:
198+
total_symlinks += len(plugins)
199+
print(f'Created {total_symlinks} symlinks in docs/')
200+
print(f'Generated mkdocs.yml with {sum(len(p) for _, _, p in nav_sections)} plugin entries')
201+
202+
return 0
203+
204+
205+
if __name__ == '__main__':
206+
sys.exit(main())

0 commit comments

Comments
 (0)