Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Docker Publish (GHCR)
on:
release:
types: [published]
permissions:
contents: read
packages: write
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
21 changes: 21 additions & 0 deletions .github/workflows/pypi-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: PyPI Publish
on:
release:
types: [published]
permissions:
contents: read
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install build tools
run: pip install build
- name: Build package
run: python -m build
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
19 changes: 19 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
fail_on_unmatched_files: false
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,20 @@ build/

# OneByJorah portfolio tooling
.venv-screenshot/

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
.venv/
*.egg-info/
.eggs/
dist/
build/
*.egg
.pytest_cache/
.mypy_cache/
152 changes: 80 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

# DirWatch

**A lightweight, self-hosted dashboard for monitoring Active Directory domain controller health — replication, SYSVOL, LDAP bind, and service status at a glance.**
**Lightweight, self-hosted dashboard for Active Directory domain controller health — replication, SYSVOL, LDAP bind, and service status at a glance**

<a href="https://github.com/OneByJorah/DirWatch/stargazers"><img src="https://img.shields.io/github/stars/OneByJorah/DirWatch?style=flat-square" alt="Stars"></a>
<a href="https://github.com/OneByJorah/DirWatch/commits"><img src="https://img.shields.io/github/last-commit/OneByJorah/DirWatch?style=flat-square" alt="Last commit"></a>
<img src="https://img.shields.io/github/license/OneByJorah/DirWatch?style=flat-square" alt="License">
<img src="https://img.shields.io/badge/Python-3.11-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python 3.11">
<img src="https://img.shields.io/badge/Flask-3-000000?style=flat-square&logo=flask&logoColor=white" alt="Flask 3">
<img src="https://img.shields.io/badge/PowerShell-5.1-5391FE?style=flat-square&logo=powershell&logoColor=white" alt="PowerShell">
[![GitHub release](https://img.shields.io/github/v/release/OneByJorah/DirWatch?color=3776AB&label=release&logo=github)](https://github.com/OneByJorah/DirWatch/releases)
[![PyPI version](https://img.shields.io/pypi/v/dirwatch?color=3776AB&label=pip&logo=pypi)](https://pypi.org/project/dirwatch/)
[![Docker](https://img.shields.io/badge/Docker-2496ED?style=flat-square&logo=docker&logoColor=white)](https://www.docker.com/)
[![Python 3.11](https://img.shields.io/badge/Python-3.11-3776AB?style=flat-square&logo=python&logoColor=white)](https://www.python.org/downloads/)
[![Flask](https://img.shields.io/badge/Flask-3-000000?style=flat-square&logo=flask&logoColor=white)](https://flask.palletsprojects.com/)
[![PowerShell](https://img.shields.io/badge/PowerShell-5.1-5391FE?style=flat-square&logo=powershell&logoColor=white)](https://learn.microsoft.com/powershell/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?color=FFB300&logo=open-source-initiative&logoColor=FFB300)](https://opensource.org/licenses/MIT)

</div>

Expand All @@ -21,106 +22,113 @@

DirWatch surfaces the health of your Active Directory domain controllers in a single dark-theme dashboard. A PowerShell collector emits a normalized JSON status file (replication state, SYSVOL, LDAP bind, DHCP scope, and service status) and the Flask app renders it as status cards, DC detail, alerts, and trends.

It is aimed at Windows admins who want a quick, dependency-light DC health view without standing up SCOM or a full monitoring stack.
Built for Windows admins who want a quick, dependency-light DC health view without standing up SCOM or a full monitoring stack.

## Quick Start

### pip

```bash
git clone https://github.com/OneByJorah/DirWatch.git
cd DirWatch
pip install -r requirements.txt
python3 app.py
pip install dirwatch
```

Open **http://localhost:5000**. Or run it in Docker:
### Docker (recommended)

```bash
git clone https://github.com/OneByJorah/DirWatch.git
cd DirWatch
docker compose up -d
```

> [!NOTE]
> The app reads `mock_dc_status.json` at startup. Swap in your own collector output by mounting a real file at the same path. The included `collectors/mock_dc_collector.ps1` generates sample data.
Open **http://localhost:5000**.

## Features
### From Source

- **Domain controller overview** — per-DC status cards with health, replication, SYSVOL, and LDAP bind state.
- **Replication monitoring** — track replication health between controllers.
- **Service status** — DNS, DHCP, and ADWS service state per DC.
- **Alerts** — severity-coded alert feed (critical / warning / info) in the dashboard.
- **Public status endpoint** — `/public` returns a simple "all systems operational" health string.
- **Dark NOC UI** — responsive sidebar layout with stats grid and DC detail pages.
- **Collector scripts** — PowerShell collectors for DC status, with Teams/Telegram notification placeholders.
- **Docker & gunicorn** — production image runs gunicorn as a non-root user.
```bash
git clone https://github.com/OneByJorah/DirWatch.git
cd DirWatch
pip install -r requirements.txt
python3 app.py
```

## Architecture
Open **http://localhost:5000**.

```
PowerShell collector ──▶ mock_dc_status.json ──▶ Flask app (:5000) ──▶ Browser
│
├──▶ Dashboard (/)
└──▶ Public status (/public)
## Install

### pip

```bash
pip install dirwatch
```

The app loads the JSON status file once at startup and renders it through Jinja2 templates. DC data can be refreshed by regenerating the file with a collector.
### Docker

## Configuration
```bash
git clone https://github.com/OneByJorah/DirWatch.git
cd DirWatch
docker compose up -d
```

### From Source

Basic operation needs no environment variables — the app reads `mock_dc_status.json` from its working directory. The Compose/entrypoint flow accepts:
```bash
git clone https://github.com/OneByJorah/DirWatch.git
cd DirWatch
pip install -r requirements.txt
python3 app.py
```

| Variable | Default | Description |
|----------|---------|-------------|
| `FLASK_ENV` | `production` | Flask environment |
| `MOCK_MODE` | `true` | Use mock DC data (no live AD required) |
| `PORT` | `5000` | App port used by the entrypoint |
| `AD_DOMAIN` | — | AD domain (live mode) |
| `AD_SERVER` | — | DC hostname (live mode) |
| `AD_USERNAME` / `AD_PASSWORD` | — | AD bind credentials (live mode) |
| `LOG_LEVEL` | `INFO` | Log verbosity |
## Features

## API / Routes
- **DC health at a glance** — replication state, SYSVOL, LDAP bind, DHCP scope, service status
- **PowerShell collector** — emits normalized JSON status file from any Windows domain controller
- **Flask dashboard** — dark-theme status cards, DC detail view, alerts, and trends
- **Self-hosted** — no external dependencies, no cloud required
- **Docker support** — run with `docker compose up -d`
- **Dependency-light** — Flask + PowerShell, no SCOM, no full monitoring stack

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/` | GET | DC status dashboard |
| `/public` | GET | Public "all systems operational" status string |
## Tech Stack

## Dashboard Panels
- **Backend** — Python 3.11, Flask 3
- **Collector** — PowerShell 5.1 (Windows)
- **Deployment** — Docker Compose, pip install
- **Data** — JSON status file (mock_dc_status.json, replaceable with real collector output)

| Panel | Description |
|-------|-------------|
| **DC Overview** | Status of all domain controllers |
| **Replication** | Inter-DC replication health |
| **Services** | DNS / DHCP / ADWS service state |
| **Alerts** | Recent severity-coded alerts |
## Package Badges

## Use Cases
[![GitHub release](https://img.shields.io/github/v/release/OneByJorah/DirWatch?color=3776AB&label=release&logo=github)](https://github.com/OneByJorah/DirWatch/releases)
[![PyPI version](https://img.shields.io/pypi/v/dirwatch?color=3776AB&label=pip&logo=pypi)](https://pypi.org/project/dirwatch/)
[![Docker](https://img.shields.io/badge/Docker-2496ED?style=flat-square&logo=docker&logoColor=white)](https://www.docker.com/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?color=FFB300&logo=open-source-initiative&logoColor=FFB300)](https://opensource.org/licenses/MIT)

1. **Windows admins** — a fast DC health check without SCOM.
2. **Homelab AD labs** — monitor test domain controllers.
3. **Pre-maintenance checks** — confirm replication and services before a change window.
## Configuration

## Tech Stack
DirWatch reads `mock_dc_status.json` at startup. Swap in your own collector output by mounting a real file at the same path.

Python 3.11, Flask 3, Jinja2, PowerShell 5.1 collectors, gunicorn, Docker Compose.
The included `collectors/mock_dc_collector.ps1` generates sample data for testing.

## Screenshots
| File | Description |
|------|-------------|
| `mock_dc_status.json` | DC status data (replace with real collector output) |
| `collectors/mock_dc_collector.ps1` | Sample PowerShell collector |
| `app.py` | Flask application entry point |

| Dashboard | Full view |
|---|---|
| ![Dashboard](docs/screenshots/main.viewport.png) | ![Full view](docs/screenshots/main.viewport.full.png) |
## Architecture

A short `docs/assets/demo.gif` walkthrough is also included.
```
PowerShell Collector (collectors/mock_dc_collector.ps1)
│
▼
mock_dc_status.json (normalized JSON)
│
▼
Flask App (app.py) ──▶ Dark-theme dashboard (http://localhost:5000)
```

## Contributing

Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). [Open an issue](https://github.com/OneByJorah/DirWatch/issues) to report a bug or request a feature.
Contributions are welcome. [Open an issue](https://github.com/OneByJorah/DirWatch/issues) to report a bug or request a feature.

## License

MIT — see [LICENSE](LICENSE).

## Connect

- [jorahone.com](https://jorahone.com)
- [GitHub Org](https://github.com/OneByJorah)
- [info@jorahone.com](mailto:info@jorahone.com)
40 changes: 40 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "dirwatch"
version = "1.0.0"
description = "Lightweight self-hosted dashboard for monitoring Active Directory domain controller health — replication, SYSVOL, LDAP bind, and service status at a glance."
readme = "README.md"
license = {text = "MIT"}
authors = [{name = "OneByJorah", email = "info@jorahone.com"}]
keywords = ["active-directory", "domain-controller", "monitoring", "dashboard", "flask", "powershell", "windows", "sysadmin", "ad-health", "jorahone"]
classifiers = [
"Development Status :: 4 - Beta",
"Environment :: Web Environment",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: System :: Systems Administration",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
]
requires-python = ">=3.11"
dependencies = [
"flask>=3.0",
"requests>=2.31",
]

[project.optional-dependencies]
dev = ["pytest", "black", "flake8"]

[project.urls]
Homepage = "https://github.com/OneByJorah/DirWatch"
Repository = "https://github.com/OneByJorah/DirWatch"
Issues = "https://github.com/OneByJorah/DirWatch/issues"

[tool.setuptools.packages.find]
include = ["dirwatch*"]
Loading