{"id":50496764,"url":"https://github.com/denisakp/ogoune","last_synced_at":"2026-06-02T08:03:07.227Z","repository":{"id":290657454,"uuid":"965208170","full_name":"denisakp/ogoune","owner":"denisakp","description":"An open-source monitoring tool for SSL certificates, domain expirations, TCP services, and cronjobs — with alerting and status pages.","archived":false,"fork":false,"pushed_at":"2026-05-29T13:39:23.000Z","size":3508,"stargazers_count":4,"open_issues_count":6,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-29T15:14:43.392Z","etag":null,"topics":["asynq","golang","monitoring","postgresql","redis"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/denisakp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-04-12T16:46:49.000Z","updated_at":"2026-05-17T10:49:10.000Z","dependencies_parsed_at":"2025-04-30T00:38:46.418Z","dependency_job_id":null,"html_url":"https://github.com/denisakp/ogoune","commit_stats":null,"previous_names":["denisakp/pulseguard","denisakp/ogoune"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/denisakp/ogoune","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisakp%2Fogoune","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisakp%2Fogoune/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisakp%2Fogoune/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisakp%2Fogoune/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/denisakp","download_url":"https://codeload.github.com/denisakp/ogoune/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisakp%2Fogoune/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33812204,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asynq","golang","monitoring","postgresql","redis"],"created_at":"2026-06-02T08:03:06.208Z","updated_at":"2026-06-02T08:03:07.220Z","avatar_url":"https://github.com/denisakp.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"right\"\u003e\n  \u003cimg src=\"./static/logo.png\" width=\"40\" alt=\"Ogoune\" /\u003e\n\u003c/div\u003e\n\n# Ogoune\n\n**Uptime monitoring that confirms before it cries wolf.**\n\n![License](https://img.shields.io/badge/license-AGPL%20v3-blue)\n![Version](https://img.shields.io/badge/version-v1.0.0-green)\n![Go](https://img.shields.io/badge/go-1.24%2B-00ADD8)\n![Vue](https://img.shields.io/badge/vue-3.x-4FC08D)\n![Docker](https://img.shields.io/badge/docker-ready-2496ED)\n[![GitHub Stars](https://img.shields.io/github/stars/denisakp/ogoune?style=flat)](https://github.com/denisakp/ogoune)\n[![GitHub Actions](https://img.shields.io/badge/GitHub%20Actions-passing-brightgreen?logo=github)](https://github.com/denisakp/ogoune/actions)\n[![GitLab CI/CD](https://img.shields.io/badge/GitLab%20CI-ready-orange?logo=gitlab)](./specs/021-gitlab-ci-workflows/quickstart.md)\n\nOgoune monitors your websites, APIs, and services. When something goes down, it **verifies the failure** before \nalerting you. No more 3am pages for a 2-second network blip.\n\n\u003e Most monitoring tools alert on the first failed check. Ogoune confirms failures before creating an incident.\n\u003e Every alert is real.\n\n\u003cimg src=\"./static/dashboard.png\" alt=\"Ogoune Dashboard\" width=\"100%\" style=\"border-radius: 8px; margin-top: 16px;\" /\u003e\n\n---\n\n## Get started in 10 seconds\n\n```bash\ndocker run -d \\\n  -p 8080:8080 \\\n  -v ogoune:/data \\\n  --name ogoune \\\n  ghcr.io/denisakp/ogoune:latest\n```\n\nOpen **http://localhost:8080** and log in:\n\n| | |\n|---|---|\n| Email | `admin@ogoune.test` |\n| Password | `ogu3n3@rd` |\n\nNo PostgreSQL. No Redis. No reverse proxy. One container.\n\n\u003cdetails\u003e\n\u003csummary\u003eOr with Docker Compose\u003c/summary\u003e\n\n```bash\ngit clone https://github.com/denisakp/ogoune.git\ncd ogoune\ncp .env.example .env   # set JWT_SECRET and APP_SECRET_KEY at minimum (see command below)\ndocker compose up -d\n```\n\nDefaults to **SQLite + in-process scheduler** — no external dependencies.\n\nGenerate `APP_SECRET_KEY` (required, 64-char hex):\n\n```bash\nopenssl rand -hex 32\n```\n\nTo switch to the full stack (PostgreSQL + Redis), add these to your `.env`:\n\n```env\nCOMPOSE_PROFILES=full\nDB_DRIVER=postgres\nDATABASE_URL=postgres://ogoune:ogoune@postgres:5432/ogoune?sslmode=disable\nSCHEDULER_MODE=asynq\nREDIS_URL=redis://redis:6379\n```\n\nAdd `ENTERPRISE_LICENSE_KEY=\u003cyour-key\u003e` to activate Enterprise Edition features.\n\n\u003c/details\u003e\n\n---\n\n## Why Ogoune\n\n**The false positive problem.** Most open-source monitors alert the moment a single check fails. Network hiccups, DNS\ntimeouts, rolling deploys, they all trigger alerts. After a few weeks, you stop reading them. Then you miss the real\noutage.\n\nOgoune solves this by **confirming every failure** before alerting:\n\n```\nCheck 1 → DOWN  →  waiting 30s, not alerting yet...\nCheck 2 → DOWN  →  confirmed. incident created. alert sent. ✓\n\nCheck 1 → DOWN  →  waiting 30s...\nCheck 2 → UP    →  false positive. no incident. no noise. ✓\n```\n\nConfigure per monitor:\n\n```\nconfirmation_checks: 2     # failures before alerting\nconfirmation_interval: 30s # gap between confirmation checks\n```\n\nSet `confirmation_checks: 1` to restore immediate alerts.\n\n---\n\n## What you get\n\n| | |\n|---|---|\n| HTTP / HTTPS checks | Monitor websites and APIs |\n| TCP port checks | Monitor any service port |\n| DNS checks | Verify DNS resolution |\n| ICMP ping checks | Optional host reachability monitoring when the runtime has raw-socket capability |\n| Heartbeat / Push monitoring | Verify cron jobs and background workers actually ran |\n| Keyword / content check monitor | Verify response body contains (or does not contain) a string — catches HTTP 200s with degraded content |\n| SSL expiry warnings | Get notified before certs expire |\n| Domain expiry warnings | Get notified before domains expire |\n| Confirmation window | N consecutive failures before alerting |\n| Flap detection | Suppress alerts for unstable resources |\n| Alert grouping | One notification for simultaneous component failures |\n| Incidents \u0026 timeline | Full lifecycle with rich diagnostics |\n| SMTP notifications | Email alerts |\n| Webhook notifications | Slack, Google Chat, Teams, Discord, any HTTP endpoint |\n| Status page | Public page for your customers |\n| Maintenance windows | One-time and recurring (cron) |\n| 2FA | TOTP-based two-factor auth |\n| Tags \u0026 components | Organize your monitors |\n| API keys | Programmatic access (`read` / `read_write`) |\n| Uptime statistics | 2h / 24h / 7d / 30d aggregates |\n\n---\n\n## Zero dependencies\n\nThe Community Edition runs on **embedded SQLite** with an **in-process scheduler**.\n\n```env\nDB_DRIVER=sqlite               # Community (default)\nDB_DRIVER=postgres             # Production\nSCHEDULER_DRIVER=timingwheel   # Community (default)\nSCHEDULER_DRIVER=asynq         # Production (requires Redis)\n```\n\n---\n\n## Comparison\n\n| | Ogoune | Uptime Kuma | UptimeRobot | Prometheus + Alertmanager |\n|---|---|---|---|---|\n| Self-hosted | ✅ | ✅ | ❌ | ✅ |\n| Zero dependencies | ✅ | ✅ | — | ❌ |\n| False positive protection | ✅ | ❌ | ❌ | Manual |\n| Flap detection | ✅ | ❌ | ❌ | Manual |\n| SSL + domain expiry | ✅ | ✅ / ❌ | Paid | Manual |\n| DNS monitoring | ✅ | ✅ | Paid | Manual |\n| Open source | AGPL v3 | MIT | ❌ | Apache |\n| Go backend | ✅ | ❌ | — | ✅ |\n| Setup complexity | Low | Low | None | Very high |\n\n---\n\n## Configuration\n\nAll settings via environment variables. See [`.env.example`](./.env.example).\n\n```env\n# Database\nDB_DRIVER=sqlite\nSQLITE_PATH=/data/ogoune.db\n\n# Scheduler\nSCHEDULER_DRIVER=timingwheel\n\n# Security — generate before production\nJWT_SECRET=change-me\nAPP_SECRET_KEY=change-me    # openssl rand -hex 32\n\n# Open Core\nENTERPRISE_LICENSE_KEY=     # leave empty for Community Edition\n```\n\n### Generate `APP_SECRET_KEY`\n\n`APP_SECRET_KEY` is mandatory and must be a 64-character hex string.\n\n```bash\n# Generate a key value\nopenssl rand -hex 32\n\n# Optional: write it directly to .env\necho \"APP_SECRET_KEY=$(openssl rand -hex 32)\" \u003e\u003e .env\n```\n\nIf you export it in your shell instead of `.env`, verify length:\n\n```bash\necho -n \"$APP_SECRET_KEY\" | wc -c\n```\n\n### Optional ICMP monitoring\n\nICMP monitoring is opt-in because raw ICMP sockets depend on host/container capabilities that are not universally available by default.\n\nEnable it only when you want ping-based monitoring or ICMP-backed network diagnostics for incidents:\n\n```env\nENABLE_ICMP=true\n```\n\nWhen `ENABLE_ICMP=false` (default), Ogoune keeps HTTP, TCP, and DNS behavior unchanged and skips ICMP-specific checks and diagnostics.\n\nWhen `ENABLE_ICMP=true`, Ogoune starts normally in both cases:\n\n- if the runtime has the required capability, ICMP monitor creation and ICMP-backed diagnostics are available\n- 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\n\n---\n\n### Heartbeat / Push monitoring\n\nHeartbeat 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.\n\n```bash\n# At the end of your script, ping Ogoune\ncurl -fsS \"https://your-ogoune-host/ping/\u003cslug\u003e\" \u003e/dev/null\n```\n\n**How it works:**\n- Create a Heartbeat monitor with an interval and grace period.\n- Copy the generated ping URL and add it to your script.\n- Ogoune waits. If no ping arrives within interval + grace seconds, an incident is created.\n- A recovery ping resolves the incident automatically.\n\n**No authentication required.** The slug itself is the token (UUID v4, unguessable). A per-slug rate limit of 100 requests/min applies.\n\nSee [QUICKSTART.md](./QUICKSTART.md) for step-by-step integration.\n\n---\n\n## Roadmap\n\nSee [ROADMAP.md](./ROADMAP.md) for the full roadmap.\n\n**Coming in H2:** Keyword checks, Prometheus metrics, IMAP/SMTP, Telegram, Digest\nnotifications, API v1, credential encryption.\n\n**Coming in H3:** Toolbox, Enterprise Edition (multi-tenancy, SSO, billing, agent device monitoring).\n\n---\n\n## Prometheus Metrics Endpoint\n\nOgoune exposes a standard Prometheus-compatible `GET /metrics` endpoint for observability.\n\n### Configuration\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `ENABLE_METRICS` | `false` | Set to `true` to enable the `/metrics` endpoint |\n| `METRICS_TOKEN` | _(empty)_ | Optional bearer token. When set, requests must include `Authorization: Bearer \u003ctoken\u003e`. Leave empty only on private/firewalled networks (a startup warning is logged). |\n\n### Access modes\n\n| `ENABLE_METRICS` | `METRICS_TOKEN` | Result |\n|-----------------|-----------------|--------|\n| `false` | any | `404 Not Found` — route not registered |\n| `true` | _(empty)_ | `200 OK` — unauthenticated (startup warning logged) |\n| `true` | `\u003ctoken\u003e` | `200 OK` with correct `Authorization: Bearer \u003ctoken\u003e` header; `401` otherwise |\n\n### Available metrics\n\n| Metric | Type | Description |\n|--------|------|-------------|\n| `go_goroutines` | Gauge | Active goroutines |\n| `go_memstats_heap_alloc_bytes` | Gauge | Heap memory in use |\n| `go_gc_duration_seconds` | Summary | GC pause durations |\n| `ogoune_resource_up` | Gauge | `1`=up, `0`=down per resource |\n| `ogoune_resource_status` | Gauge | `0`=unknown `1`=up `2`=down `3`=paused |\n| `ogoune_check_duration_seconds` | Histogram | Check latency in seconds |\n| `ogoune_checks_total` | Counter | Check executions by `status` label (`success`/`failure`/`timeout`) |\n| `ogoune_incidents_total` | Gauge | All-time incident count per resource |\n| `ogoune_incidents_active` | Gauge | Currently open incidents per resource |\n| `ogoune_uptime_ratio` | Gauge | Uptime `0.0–1.0` for `window` label `24h`, `7d`, `30d` |\n\nAll `ogoune_*` metrics carry labels: `id`, `name`, `type`.\n\n### Prometheus scrape config\n\nWithout authentication:\n```yaml\nscrape_configs:\n  - job_name: ogoune\n    scrape_interval: 30s\n    static_configs:\n      - targets: [\"ogoune:8080\"]\n```\n\nWith bearer token:\n```yaml\nscrape_configs:\n  - job_name: ogoune\n    scrape_interval: 30s\n    bearer_token: your-secret-token-here\n    static_configs:\n      - targets: [\"ogoune:8080\"]\n```\n\n---\n\n## Contributing\n\nOgoune welcomes contributions. See [CONTRIBUTING.md](./CONTRIBUTING.md).\n\nAll contributors must sign the **CLA** — the bot handles this automatically on your first PR.\n\n- **Report bugs** → [GitHub Issues](https://github.com/denisakp/ogoune/issues)\n- **Request features** → [GitHub Discussions](https://github.com/denisakp/ogoune/discussions)\n- **Good first issues** → [`good first issue`](https://github.com/denisakp/ogoune/labels/good%20first%20issue)\n\n---\n\n## Licence\n\nOgoune is licensed under **AGPL v3** — see [LICENSE](./LICENSE).\n\nThe `internal/ee/` directory contains Enterprise Edition features and is covered by a separate proprietary licence.\nsee [LICENSE_EE](./LICENSE_EE).\n\nA valid licence key is required to use those features, whether self-hosted or via our Cloud. The rest of the codebase \nis free, open source, and self-hostable with no licence key required. See [ROADMAP.md](./ROADMAP.md) for the Open Core\nmodel.\n\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\nBuilt with ❤️ by [Denis Yaovi](https://github.com/denisakp)\n\n**[⬆ Back to top](#ogoune)**\n\n\u003c/div\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenisakp%2Fogoune","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdenisakp%2Fogoune","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenisakp%2Fogoune/lists"}