https://github.com/denisakp/ogoune
An open-source monitoring tool for SSL certificates, domain expirations, TCP services, and cronjobs — with alerting and status pages.
https://github.com/denisakp/ogoune
asynq golang monitoring postgresql redis
Last synced: 24 days ago
JSON representation
An open-source monitoring tool for SSL certificates, domain expirations, TCP services, and cronjobs — with alerting and status pages.
- Host: GitHub
- URL: https://github.com/denisakp/ogoune
- Owner: denisakp
- License: agpl-3.0
- Created: 2025-04-12T16:46:49.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2026-05-29T13:39:23.000Z (28 days ago)
- Last Synced: 2026-05-29T15:14:43.392Z (28 days ago)
- Topics: asynq, golang, monitoring, postgresql, redis
- Language: Go
- Homepage:
- Size: 3.35 MB
- Stars: 4
- Watchers: 2
- Forks: 1
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
- Roadmap: roadmap.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Ogoune
**Uptime monitoring that confirms before it cries wolf.**





[](https://github.com/denisakp/ogoune)
[](https://github.com/denisakp/ogoune/actions)
[](./specs/021-gitlab-ci-workflows/quickstart.md)
Ogoune monitors your websites, APIs, and services. When something goes down, it **verifies the failure** before
alerting you. No more 3am pages for a 2-second network blip.
> Most monitoring tools alert on the first failed check. Ogoune confirms failures before creating an incident.
> Every alert is real.

---
## Get started in 10 seconds
```bash
docker run -d \
-p 8080:8080 \
-v ogoune:/data \
--name ogoune \
ghcr.io/denisakp/ogoune:latest
```
Open **http://localhost:8080** and log in:
| | |
|---|---|
| Email | `admin@ogoune.test` |
| Password | `ogu3n3@rd` |
No PostgreSQL. No Redis. No reverse proxy. One container.
Or with Docker Compose
```bash
git clone https://github.com/denisakp/ogoune.git
cd ogoune
cp .env.example .env # set JWT_SECRET and APP_SECRET_KEY at minimum (see command below)
docker compose up -d
```
Defaults to **SQLite + in-process scheduler** — no external dependencies.
Generate `APP_SECRET_KEY` (required, 64-char hex):
```bash
openssl rand -hex 32
```
To switch to the full stack (PostgreSQL + Redis), add these to your `.env`:
```env
COMPOSE_PROFILES=full
DB_DRIVER=postgres
DATABASE_URL=postgres://ogoune:ogoune@postgres:5432/ogoune?sslmode=disable
SCHEDULER_MODE=asynq
REDIS_URL=redis://redis:6379
```
Add `ENTERPRISE_LICENSE_KEY=` to activate Enterprise Edition features.
---
## Why Ogoune
**The false positive problem.** Most open-source monitors alert the moment a single check fails. Network hiccups, DNS
timeouts, rolling deploys, they all trigger alerts. After a few weeks, you stop reading them. Then you miss the real
outage.
Ogoune solves this by **confirming every failure** before alerting:
```
Check 1 → DOWN → waiting 30s, not alerting yet...
Check 2 → DOWN → confirmed. incident created. alert sent. ✓
Check 1 → DOWN → waiting 30s...
Check 2 → UP → false positive. no incident. no noise. ✓
```
Configure per monitor:
```
confirmation_checks: 2 # failures before alerting
confirmation_interval: 30s # gap between confirmation checks
```
Set `confirmation_checks: 1` to restore immediate alerts.
---
## What you get
| | |
|---|---|
| HTTP / HTTPS checks | Monitor websites and APIs |
| TCP port checks | Monitor any service port |
| DNS checks | Verify DNS resolution |
| ICMP ping checks | Optional host reachability monitoring when the runtime has raw-socket capability |
| Heartbeat / Push monitoring | Verify cron jobs and background workers actually ran |
| Keyword / content check monitor | Verify response body contains (or does not contain) a string — catches HTTP 200s with degraded content |
| SSL expiry warnings | Get notified before certs expire |
| Domain expiry warnings | Get notified before domains expire |
| Confirmation window | N consecutive failures before alerting |
| Flap detection | Suppress alerts for unstable resources |
| Alert grouping | One notification for simultaneous component failures |
| Incidents & timeline | Full lifecycle with rich diagnostics |
| SMTP notifications | Email alerts |
| Webhook notifications | Slack, Google Chat, Teams, Discord, any HTTP endpoint |
| Status page | Public page for your customers |
| Maintenance windows | One-time and recurring (cron) |
| 2FA | TOTP-based two-factor auth |
| Tags & components | Organize your monitors |
| API keys | Programmatic access (`read` / `read_write`) |
| Uptime statistics | 2h / 24h / 7d / 30d aggregates |
---
## Zero dependencies
The Community Edition runs on **embedded SQLite** with an **in-process scheduler**.
```env
DB_DRIVER=sqlite # Community (default)
DB_DRIVER=postgres # Production
SCHEDULER_DRIVER=timingwheel # Community (default)
SCHEDULER_DRIVER=asynq # Production (requires Redis)
```
---
## Comparison
| | Ogoune | Uptime Kuma | UptimeRobot | Prometheus + Alertmanager |
|---|---|---|---|---|
| Self-hosted | ✅ | ✅ | ❌ | ✅ |
| Zero dependencies | ✅ | ✅ | — | ❌ |
| False positive protection | ✅ | ❌ | ❌ | Manual |
| Flap detection | ✅ | ❌ | ❌ | Manual |
| SSL + domain expiry | ✅ | ✅ / ❌ | Paid | Manual |
| DNS monitoring | ✅ | ✅ | Paid | Manual |
| Open source | AGPL v3 | MIT | ❌ | Apache |
| Go backend | ✅ | ❌ | — | ✅ |
| Setup complexity | Low | Low | None | Very high |
---
## Configuration
All settings via environment variables. See [`.env.example`](./.env.example).
```env
# Database
DB_DRIVER=sqlite
SQLITE_PATH=/data/ogoune.db
# Scheduler
SCHEDULER_DRIVER=timingwheel
# Security — generate before production
JWT_SECRET=change-me
APP_SECRET_KEY=change-me # openssl rand -hex 32
# Open Core
ENTERPRISE_LICENSE_KEY= # leave empty for Community Edition
```
### Generate `APP_SECRET_KEY`
`APP_SECRET_KEY` is mandatory and must be a 64-character hex string.
```bash
# Generate a key value
openssl rand -hex 32
# Optional: write it directly to .env
echo "APP_SECRET_KEY=$(openssl rand -hex 32)" >> .env
```
If you export it in your shell instead of `.env`, verify length:
```bash
echo -n "$APP_SECRET_KEY" | wc -c
```
### Optional ICMP monitoring
ICMP monitoring is opt-in because raw ICMP sockets depend on host/container capabilities that are not universally available by default.
Enable it only when you want ping-based monitoring or ICMP-backed network diagnostics for incidents:
```env
ENABLE_ICMP=true
```
When `ENABLE_ICMP=false` (default), Ogoune keeps HTTP, TCP, and DNS behavior unchanged and skips ICMP-specific checks and diagnostics.
When `ENABLE_ICMP=true`, Ogoune starts normally in both cases:
- if the runtime has the required capability, ICMP monitor creation and ICMP-backed diagnostics are available
- if the runtime does not have the required capability, startup continues, the UI/API report ICMP as unavailable, and ICMP monitor creation is rejected until capability is granted
---
### Heartbeat / Push monitoring
Heartbeat monitoring lets you verify that cron jobs and background workers actually ran. Instead of Ogoune polling a target, your job calls Ogoune at the end of a successful run.
```bash
# At the end of your script, ping Ogoune
curl -fsS "https://your-ogoune-host/ping/" >/dev/null
```
**How it works:**
- Create a Heartbeat monitor with an interval and grace period.
- Copy the generated ping URL and add it to your script.
- Ogoune waits. If no ping arrives within interval + grace seconds, an incident is created.
- A recovery ping resolves the incident automatically.
**No authentication required.** The slug itself is the token (UUID v4, unguessable). A per-slug rate limit of 100 requests/min applies.
See [QUICKSTART.md](./QUICKSTART.md) for step-by-step integration.
---
## Roadmap
See [ROADMAP.md](./ROADMAP.md) for the full roadmap.
**Coming in H2:** Keyword checks, Prometheus metrics, IMAP/SMTP, Telegram, Digest
notifications, API v1, credential encryption.
**Coming in H3:** Toolbox, Enterprise Edition (multi-tenancy, SSO, billing, agent device monitoring).
---
## Prometheus Metrics Endpoint
Ogoune exposes a standard Prometheus-compatible `GET /metrics` endpoint for observability.
### Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `ENABLE_METRICS` | `false` | Set to `true` to enable the `/metrics` endpoint |
| `METRICS_TOKEN` | _(empty)_ | Optional bearer token. When set, requests must include `Authorization: Bearer `. Leave empty only on private/firewalled networks (a startup warning is logged). |
### Access modes
| `ENABLE_METRICS` | `METRICS_TOKEN` | Result |
|-----------------|-----------------|--------|
| `false` | any | `404 Not Found` — route not registered |
| `true` | _(empty)_ | `200 OK` — unauthenticated (startup warning logged) |
| `true` | `` | `200 OK` with correct `Authorization: Bearer ` header; `401` otherwise |
### Available metrics
| Metric | Type | Description |
|--------|------|-------------|
| `go_goroutines` | Gauge | Active goroutines |
| `go_memstats_heap_alloc_bytes` | Gauge | Heap memory in use |
| `go_gc_duration_seconds` | Summary | GC pause durations |
| `ogoune_resource_up` | Gauge | `1`=up, `0`=down per resource |
| `ogoune_resource_status` | Gauge | `0`=unknown `1`=up `2`=down `3`=paused |
| `ogoune_check_duration_seconds` | Histogram | Check latency in seconds |
| `ogoune_checks_total` | Counter | Check executions by `status` label (`success`/`failure`/`timeout`) |
| `ogoune_incidents_total` | Gauge | All-time incident count per resource |
| `ogoune_incidents_active` | Gauge | Currently open incidents per resource |
| `ogoune_uptime_ratio` | Gauge | Uptime `0.0–1.0` for `window` label `24h`, `7d`, `30d` |
All `ogoune_*` metrics carry labels: `id`, `name`, `type`.
### Prometheus scrape config
Without authentication:
```yaml
scrape_configs:
- job_name: ogoune
scrape_interval: 30s
static_configs:
- targets: ["ogoune:8080"]
```
With bearer token:
```yaml
scrape_configs:
- job_name: ogoune
scrape_interval: 30s
bearer_token: your-secret-token-here
static_configs:
- targets: ["ogoune:8080"]
```
---
## Contributing
Ogoune welcomes contributions. See [CONTRIBUTING.md](./CONTRIBUTING.md).
All contributors must sign the **CLA** — the bot handles this automatically on your first PR.
- **Report bugs** → [GitHub Issues](https://github.com/denisakp/ogoune/issues)
- **Request features** → [GitHub Discussions](https://github.com/denisakp/ogoune/discussions)
- **Good first issues** → [`good first issue`](https://github.com/denisakp/ogoune/labels/good%20first%20issue)
---
## Licence
Ogoune is licensed under **AGPL v3** — see [LICENSE](./LICENSE).
The `internal/ee/` directory contains Enterprise Edition features and is covered by a separate proprietary licence.
see [LICENSE_EE](./LICENSE_EE).
A valid licence key is required to use those features, whether self-hosted or via our Cloud. The rest of the codebase
is free, open source, and self-hostable with no licence key required. See [ROADMAP.md](./ROADMAP.md) for the Open Core
model.
---
Built with ❤️ by [Denis Yaovi](https://github.com/denisakp)
**[⬆ Back to top](#ogoune)**