{"id":49270688,"url":"https://github.com/fabianwimberger/monitoring-stack","last_synced_at":"2026-05-09T10:58:46.262Z","repository":{"id":350825929,"uuid":"1203208919","full_name":"fabianwimberger/monitoring-stack","owner":"fabianwimberger","description":"Just another Docker Compose monitoring stack. Prometheus, Grafana, Loki, and Uptime Kuma.","archived":false,"fork":false,"pushed_at":"2026-04-25T11:59:06.000Z","size":2178,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-25T12:09:02.962Z","etag":null,"topics":["docker","docker-compose","grafana","loki","monitoring","observability","prometheus","self-hosted","uptime-kuma"],"latest_commit_sha":null,"homepage":"","language":"Makefile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fabianwimberger.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-06T20:36:41.000Z","updated_at":"2026-04-25T10:04:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/fabianwimberger/monitoring-stack","commit_stats":null,"previous_names":["fabianwimberger/monitoring-stack"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fabianwimberger/monitoring-stack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabianwimberger%2Fmonitoring-stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabianwimberger%2Fmonitoring-stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabianwimberger%2Fmonitoring-stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabianwimberger%2Fmonitoring-stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fabianwimberger","download_url":"https://codeload.github.com/fabianwimberger/monitoring-stack/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabianwimberger%2Fmonitoring-stack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32263766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T09:15:33.318Z","status":"ssl_error","status_checked_at":"2026-04-25T09:15:31.997Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["docker","docker-compose","grafana","loki","monitoring","observability","prometheus","self-hosted","uptime-kuma"],"created_at":"2026-04-25T13:27:29.076Z","updated_at":"2026-05-09T10:58:46.221Z","avatar_url":"https://github.com/fabianwimberger.png","language":"Makefile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Monitoring Stack\n\n[![CI](https://github.com/fabianwimberger/monitoring-stack/actions/workflows/ci.yml/badge.svg)](https://github.com/fabianwimberger/monitoring-stack/actions)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA Docker Compose monitoring stack for self-hosted infrastructure. Metrics, logs, dashboards, and uptime monitoring in one command.\n\n- **Metrics** — Prometheus + cAdvisor + node_exporter\n- **Logs** — Loki + Grafana Alloy (Docker containers + systemd journal)\n- **Dashboards** — Grafana with pre-provisioned dashboards\n- **Uptime** — Uptime Kuma for endpoint monitoring\n\n## Background\n\nI kept setting up the same Prometheus, Grafana, and Loki combination on every\nself-hosted box. This is that stack packaged as one command, with the pieces I\nactually use: cAdvisor and node_exporter for metrics, Alloy for Docker and\nsystemd-journal logs, Uptime Kuma for endpoint checks, and Grafana with\ndashboards already wired up.\n\n### Companion projects\n\nThis stack is the dashboard layer. Two of my other repos plug straight into it\nas data sources:\n\n| Repo | What it provides | How this stack uses it |\n|---|---|---|\n| [openwrt-only-home-network](https://github.com/fabianwimberger/openwrt-only-home-network) | Whole-home OpenWrt WiFi blueprint (wired APs + WDS repeaters) | Each node runs `node_exporter`; this stack scrapes them and visualizes them in the bundled OpenWrt WiFi dashboard |\n| [fritzbox-monitoring](https://github.com/fabianwimberger/fritzbox-monitoring) | Prometheus exporter for AVM FritzBox cable modems (DOCSIS, speeds, ping) | Add its `:8000` target to `prometheus.yml` and import its Grafana dashboard |\n\nNeither is required — the stack works standalone — but if you run them, the\nintegration is just a scrape-config edit.\n\n## Architecture\n\n```mermaid\nflowchart LR\n    subgraph Host\n        node[node_exporter]\n        cadvisor[cAdvisor]\n        journal[systemd journal]\n        docker[Docker logs]\n    end\n\n    subgraph Monitoring\n        prom[Prometheus]\n        loki[Loki]\n        alloy[Alloy]\n        grafana[Grafana]\n        kuma[Uptime Kuma]\n    end\n\n    node --\u003e prom\n    cadvisor --\u003e prom\n    docker --\u003e alloy --\u003e loki\n    journal --\u003e alloy\n    prom --\u003e grafana\n    loki --\u003e grafana\n```\n\n## Quick Start\n\n### Option 1: Local / LAN\n\nFor testing or running on your local network with direct port access:\n\n```bash\ngit clone https://github.com/fabianwimberger/monitoring-stack.git\ncd monitoring-stack\n\n# Optional: edit settings\ncp .env.example .env\n\n# Start\nmake up\n```\n\n| Service | URL |\n|---|---|\n| Grafana | http://localhost:3000 |\n| Prometheus | http://localhost:9090 |\n| Uptime Kuma | http://localhost:3001 |\n\nDefault Grafana login: `admin` / `changeme` (set `GRAFANA_ADMIN_PASSWORD` in `.env` to change).\n\n### Option 2: Behind a Reverse Proxy\n\nIf you run [Traefik](https://traefik.io/) (or similar) already, use the proxy overlay:\n\n```bash\ncp .env.example .env\n# Edit .env and set your domains:\n#   GRAFANA_DOMAIN=grafana.example.com\n#   UPTIME_KUMA_DOMAIN=uptime.example.com\n\nmake up-proxy\n```\n\nThis exposes **only** Grafana and Uptime Kuma via your reverse proxy. Prometheus, Loki, Alloy, and cAdvisor stay on an isolated internal network with no public access.\n\nSee `docker-compose.proxy.yml` if you use a different proxy — the labels are easy to adapt.\n\n## Network Isolation\n\nThe compose setup uses two networks:\n\n- **`monitoring`** — internal communication between Prometheus, Loki, Alloy, and cAdvisor\n- **`proxy`** — for services that need external access (Grafana, Uptime Kuma)\n\nIn proxy mode, backend services have no exposed ports and no route from the outside. Grafana and Uptime Kuma are the only entrypoints.\n\n## Screenshots\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/host-dashboard.png\" width=\"100%\" alt=\"Host monitoring dashboard\"\u003e\n  \u003cbr\u003e\u003cem\u003eHost monitoring dashboard — CPU, memory, disk, network\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/log-explorer.png\" width=\"100%\" alt=\"Log explorer\"\u003e\n  \u003cbr\u003e\u003cem\u003eLog explorer — search across Docker containers and systemd journal\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/cadvisor.png\" width=\"100%\" alt=\"cAdvisor container metrics\"\u003e\n  \u003cbr\u003e\u003cem\u003ecAdvisor container metrics — per-container CPU, memory, network, and disk I/O\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/openwrt-wifi-overview.png\" width=\"100%\" alt=\"OpenWrt WiFi overview\"\u003e\n  \u003cbr\u003e\u003cem\u003eOpenWrt WiFi dashboard — per-AP status, client counts, backhaul signal, CPU/RAM, stations per AP, per-client signal\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/openwrt-wifi-backhaul.png\" width=\"100%\" alt=\"OpenWrt WiFi backhaul and system metrics\"\u003e\n  \u003cbr\u003e\u003cem\u003eOpenWrt WiFi dashboard — backhaul signal, bitrate and quality, plus per-node system and network metrics\u003c/em\u003e\n\u003c/p\u003e\n\n## Configuration\n\nAll settings are via `.env` (see [`.env.example`](.env.example)):\n\n| Variable | Default | Description |\n|---|---|---|\n| `TZ` | `UTC` | Timezone for all services |\n| `PROMETHEUS_PORT` | `9090` | Prometheus web UI port (local mode) |\n| `PROMETHEUS_RETENTION` | `30d` | Metrics retention |\n| `GRAFANA_PORT` | `3000` | Grafana web UI port (local mode) |\n| `GRAFANA_ADMIN_PASSWORD` | `changeme` | Grafana admin password |\n| `UPTIME_KUMA_PORT` | `3001` | Uptime Kuma web UI port (local mode) |\n| `GRAFANA_DOMAIN` | — | Domain for Grafana (proxy mode) |\n| `UPTIME_KUMA_DOMAIN` | — | Domain for Uptime Kuma (proxy mode) |\n| `PROXY_NETWORK` | `proxy` | Name of your external Docker proxy network |\n\n### Adding Hosts to Monitor\n\nEdit `config/prometheus.yml` and add your `node_exporter` instances:\n\n```yaml\nscrape_configs:\n  - job_name: \"node\"\n    static_configs:\n      - targets: [\"192.168.1.10:9100\", \"192.168.1.11:9100\"]\n```\n\nThe bundled `dashboards/openwrt-wifi-network.json` expects an `openwrt` job\nwith a `node` label per device — see the commented template in\n`config/prometheus.yml`.\n\n### Adding Dashboards\n\nDrop Grafana dashboard JSON files into `dashboards/`. They are auto-provisioned on startup.\n\n## Requirements\n\n- Docker and Docker Compose v2\n- Linux host (for systemd journal and cAdvisor access)\n- [node_exporter](https://github.com/prometheus/node_exporter) installed on hosts you want to monitor\n- For proxy mode: an existing reverse proxy (Traefik, Nginx, Caddy, etc.)\n\n## Makefile Commands\n\n| Command | Description |\n|---|---|\n| `make up` | Start stack (local mode) |\n| `make down` | Stop stack |\n| `make restart` | Restart all services |\n| `make logs` | Follow logs |\n| `make clean` | Stop and remove all volumes (**deletes data**) |\n| `make up-proxy` | Start stack behind reverse proxy |\n| `make down-proxy` | Stop proxy stack |\n\n## Security Notes\n\n- **Alloy** runs with access to the Docker socket and systemd journal. The container uses `group_add` with `DOCKER_GID` (set in `.env`) so the process can access the Docker socket without full root privileges, and `cap_add: [DAC_READ_SEARCH]` helps with journal access. If you want to run fully unprivileged, set `DOCKER_GID` to your host's docker group ID and override the user in `docker-compose.yml`.\n- **cAdvisor** runs `privileged: true` to read host hardware metrics. This is required by cAdvisor's design.\n- All services include log rotation (`max-size: 10m`, `max-file: 3`) to prevent unbounded disk growth.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabianwimberger%2Fmonitoring-stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffabianwimberger%2Fmonitoring-stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabianwimberger%2Fmonitoring-stack/lists"}