{"slug": "monitoring-literally-everything-with-prometheus-grafana", "title": "Monitoring literally everything with Prometheus & Grafana", "summary": "A hobbyist's work-in-progress guide documents building an all-in-one Prometheus and Grafana monitoring stack across 14 targets, including an Unraid NAS, an Ubuntu Plex server, two Windows 11 PCs, a Raspberry Pi running Pi-hole, an OPNsense box, a Mikrotik 2.5G switch, two Xbox Series X consoles and a CyberPower UPS. The author reports fixing Unraid's default 99:100 user ID by running chown -R 65534:65534 on the Prometheus data directory and removing --user from the container's Extra Parameters, and uses a 15s scrape_interval with node_exporter on port 9100 and cAdvisor on port 8080. The author discloses using Claude for troubleshooting, including running Tailscale as a separate Docker container because it does not initialize normally for Prometheus and Grafana in the Unraid UI, and plans to evaluate Grafana Alloy in place of node_exporter and windows_exporter and to add Loki for logging.", "body_md": "AI Disclosure:\n\nI used Claude to walk me through some troubleshooting steps I otherwise didn’t expect. For instance, Tailscale does not initialize normally for Prometheus and Grafana in the Unraid UI, so Tailscale had to be created and linked as a separate Docker container. Or, when the Miktotik switch would not work I asked Claude to help me with a custom user for scraping. I also periodically sanity-checked with Claude to make sure I was on the right track to avoid hours of frustration. Otherwise, I wanted to understand well how everything links together.\n\nI’ve wanted better all-in-one monitoring for my Unraid server, plex server, pihole, OPNsense box, dad’s pc, mikrotik switch, etc. for a while now since it’s just cool to have, but never got around to it since it would be a sizable chunk of work to figure out something I’ve never used before… Then I realized what better time than Devember??  naturally, all of these platofrms have great monitoring systems I can individually go to, but we’re making the one-stop-shop for whatever I want to know.\n\nNot done. WIP. Will update my list periodically. Once said and done with things talking correctly, I will customize my dashboards and probably upload the custom board for people to download. I will also be adding more and more pictures over time for other visual learners like me.\n\n**Legend**\n\n|  |  | \n|  | done and working in grafana. | \n|  | made some progress, but not done/scraping properly yet. | \n|  | not started. | \n\n **Progress**\n\n| Status | Machine | OS | Exporter | Port | \n|  | big-boss (NAS/*arr Suite) | Unraid | node_exporter OR alloy?, smartctl_exporter, cAdvisor | 9100/514, 8088, 9633 | \n|  | little-boss (plex server/live transcoding, tdarr/cpu archive transcoding) | Ubuntu | node_exporter OR alloy? | 9100/514 | \n|  | little-boss nvidia dash | Ubuntu | node_exporter? | ? | \n|  | plex | Ubuntu (Docker) | plex-exporter | 32400 | \n|  | tautilli | Ubuntu (Docker) | tautulli-exporter | 9595 | \n|  | tdarr | Ubtuntu (Docker) | tdarr-exporter | 9596 | \n|  | amber-pc-win11 | Windows 11 | windows_exporter OR alloy? | 9182/514 | \n|  | dads-pc-win11 | Windows 11 | windows_exporter | 9182 | \n|  | raspberrypi-pihole | Linux | node_exporter | 9100 | \n|  | opnsense | FreeBSD | node_exporter plugin | 9100 | \n|  | mikrotik 2.5G switch | RouterOS | mktxp | 9115 | \n|  | xbox series x (1) | n/a | ping | 9115 | \n|  | xbox series x (2) | n/a | ping | 9115 | \n|  | cyberpower ups | n/a | apcupsd | 9162 | \n\n **Things to look into**\n\n- alloy – I want to get prometheus, exporters, and grfana all working and then I’ll go back and check out alloy in place of node_exporter and windows_exporter.\n\n- loki – want to do, will do after exporters. Logging would be very helpful.\n\n \n\n# \n\nUnraid UI → APPS\n\n## \n\nYou need a 1-time use tailscale auth key from your admin console:\n\n## \n\n## \n\nUnraid assigns Prometheus a dummy user ID of 99:100 by default, but it doesn’t have proper permissions to access the appdata folder. This has to be fixed so it can initialize.\n\n```\ndocker stop prometheus\nchown -R 65534:65534 /mnt/user/appdata/prometheus/data\n```\n\nThen we just delete --user from Extra Parameters of the container.\n\n## \n\n```\nglobal:\n  scrape_interval: 15s\n\nscrape_configs:\n  - job_name: prometheus\n    static_configs:\n      - targets: ['localhost:9090']\n\n  - job_name: node\n    static_configs:\n      - targets: ['LOCAL-IP:9100']   # Unraid\n        labels:\n          host: unraid\n\n  - job_name: cadvisor\n    static_configs:\n      - targets: ['LOCAL-IP:8080']   # per-container stats\n```\n\n# \n\n# \n\nUnraid UI → APPS\n\ndefault permissions:\n\nadmin | admin\n\nadd data source (prometheus)\n\n## \n\n#$ empty grafana, let’s configure!\n\nprometheus is itself a tailnet node, so it can scrape the 100.x addresses directly. They don’t change, which suits Windows PCs on DHCP. Then, I used the LAN address for little-boss because it’s on the same network.\n\n# \n\n## \n\nUnraid → APPs → Node Exporter Plugin Installs\n\n```\n  - job_name: node\n    static_configs:\n      - targets: ['TAILSCALE-IP:9100']\n        labels: {host: big-boss}\n      - targets: ['TAILSCALE-IP:9100']\n        labels: {host: little-boss}\n      - targets: ['TAILSCALE-IP:9100']\n        labels: {host: raspberrypi}\n      - targets: ['TAILSCALE-IP:9100']\n        labels: {host: opnsense}\n\n  - job_name: windows\n    static_configs:\n      - targets: ['TAILSCALE-IP-IP:9182']\n        labels: {host: amber-pc-win11}\n\n  - job_name: cadvisor\n    static_configs:\n      - targets: ['TAILSCALE-IP:8088']\n        labels: {host: big-boss}\n```\n\n# \n\n## \n\nThankfully, my UPS makes this very easy with a plug-and-play USB-A (Unraid) → USB-B 2.0 (UPS) cable!\n\n```\n  - job_name: ups\n    static_configs:\n      - targets: ['TAILSCALE-IP:9162']\n        labels: {host: big-boss-ups}\n```\n\nSettings → UPS Settings\n\nStart APC UPS Deamon: Yes\n\nApply.\n\nHowever, to see it in Prometheus, we need another container that’s not in Uraid’s community apps:\n\n```\ndocker run -d --name=apcupsd-exporter --network=host --restart unless-stopped okaeri/apcupsd_exporter\n```\n\nID: 21119\n\n## \n\nid: 22604\n\nThis has already been helpful as I apparently have an m.2 dying… lol\n\n## \n\n```\nsudo apt install prometheus-node-exporter\n```\n\nShould pickup auto-magically in the prometheus health overview.\n\n```\nsudo nano docker-compose-exporters.yml\n```\n\nInstall exporters\n\n```\nname: exporters\n\nservices:\n  plex-exporter:\n    image: cplieger/plex-exporter:latest\n    container_name: plex-exporter\n    restart: unless-stopped\n    network_mode: host\n    environment:\n      PLEX_URL: \"http://LAN-IP:32400\"\n      PLEX_TOKEN: \"YOUR_PLEX_TOKEN\"\n\n  tautulli-exporter:\n    image: mm404/tautulli-exporter:latest\n    container_name: tautulli-exporter\n    restart: unless-stopped\n    network_mode: host\n    environment:\n      TAUTULLI_URL: \"http://localhost:8181\"\n      TAUTULLI_API_KEY: \"YOUR_TAUTULLI_API_KEY\"\n      METRICS_PORT: \"9595\"\n\n  tdarr-exporter:\n    image: homeylab/tdarr-exporter:latest\n    container_name: tdarr-exporter\n    restart: unless-stopped\n    network_mode: host\n    environment:\n      TDARR_URL: \"http://localhost:8265\"\n      PROMETHEUS_PORT: \"9596\"\n```\n\nstart containers\n\n``` bash\n$ sudo docker compose -f docker-compose-exporters.yml up -d\ncurl -s http://localhost:9594/metrics | head -5\ncurl -s http://localhost:9595/metrics | head -5\ncurl -s http://localhost:9596/metrics | head -5\n[+] up 33/33\n ✔ Image mm404/tautulli-exporter:latest Pulled                                                                      1.6s\n ✔ Image homeylab/tdarr-exporter:latest Pulled                                                                      2.7s\n ✔ Image cplieger/plex-exporter:latest  Pulled                                                                      3.9s\n ✔ Container tdarr-exporter             Started                                                                     0.3s\n ✔ Container plex-exporter              Started                                                                     0.4s\n ✔ Container tautulli-exporter          Started                                                                     0.5s\n# HELP go_gc_duration_seconds A summary of the wall-time pause (stop-the-world) duration in garbage collection cycles.\n# TYPE go_gc_duration_seconds summary\ngo_gc_duration_seconds{quantile=\"0\"} 0\ngo_gc_duration_seconds{quantile=\"0.25\"} 0\ngo_gc_duration_seconds{quantile=\"0.5\"} 0\n# HELP go_gc_duration_seconds A summary of the wall-time pause (stop-the-world) duration in garbage collection cycles.\n# TYPE go_gc_duration_seconds summary\ngo_gc_duration_seconds{quantile=\"0\"} 0\ngo_gc_duration_seconds{quantile=\"0.25\"} 0\ngo_gc_duration_seconds{quantile=\"0.5\"} 0\n```\n\nadd scrap jobs\n\n```\n  - job_name: plex\n    static_configs:\n      - targets: ['TAILSCALE-IP:9594']\n        labels: {host: little-boss}\n\n  - job_name: tautulli\n    scrape_interval: 30s\n    static_configs:\n      - targets: ['TAILSCALE-IP:9595']\n        labels: {host: little-boss}\n\n  - job_name: tdarr\n    scrape_interval: 30s\n    static_configs:\n      - targets: ['TAILSCALE-IP:9596']\n        labels: {host: little-boss}\n```\n\n## \n\nHad to get Claude help because I had no clue what to do lol\n\nPS C:\\Users\\Admin> # 1. Must print True. If it prints False, reopen PowerShell as administrator.\n\n```\nPS C:\\Users\\Admin> ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)\nTrue\n```\n\ndownload the latest release\n\n```\nPS C:\\Users\\Admin> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12\nPS C:\\Users\\Admin> $rel = Invoke-RestMethod https://api.github.com/repos/prometheus-community/windows_exporter/releases/latest\nPS C:\\Users\\Admin> $asset = $rel.assets | Where-Object { $_.name -like \"*amd64.msi\" } | Select-Object -First 1\nPS C:\\Users\\Admin> $msi = Join-Path $env:TEMP $asset.name\nPS C:\\Users\\Admin> Invoke-WebRequest $asset.browser_download_url -OutFile $msi\nPS C:\\Users\\Admin> Get-Item $msi\n\n    Directory: C:\\Users\\Admin\\AppData\\Local\\Temp\n\nMode                 LastWriteTime         Length Name\n----                 -------------         ------ ----\n-a----         11/8/2026   3:32 PM       14643200 windows_exporter-0.32.1-amd64.msi\n```\n\ninstall and check\n\n```\nPS C:\\Users\\Admin> Start-Process msiexec -Wait -ArgumentList \"/i `\"$msi`\" LISTEN_PORT=9182 REMOTE_ADDR=100.100.217.91 /qn /l*v `\"$env:TEMP\\we-install.log`\"\"\nPS C:\\Users\\Admin> Get-Service windows_exporter\n\nStatus   Name               DisplayName\n------   ----               -----------\nRunning  windows_exporter   windows_exporter\n\nPS C:\\Users\\Admin> (Invoke-WebRequest -UseBasicParsing http://localhost:9182/metrics).StatusCode\n200\n```\n\ncreates a PC selector in node exporter\n\n## \n\nI needed to configure the Mikrotik for LAN access. I have been using the switch for a while, but realized it was still thinking I was using the default “192.168.X.X” default IP config. My home LAN in “10.1.1.1”, so although it was functioning for its purpose, I actually had no LAN access.\n\nIP → DHCP Server → Networks\n\n- Address: 10.1.1.0/24\n- Gateway: 10.1.1.1\n- DNS Servers: 10.1.1.155\n\nIP → Routes\n\n- Dst. Address: 0.0.0.0/24\n- Gateway: 10.1.1.1\n- Immediate Gateway: 10.1.1.1%bridge\n\nnew read-only user to scrape data\n\n```\n[admin@MikroTik] > /user group add name=mktxp_group policy=api,read\n[admin@MikroTik] > /user add name=mktxp_user group=mktxp_group password=CHOOSE-A-STRONG-PASSWORD\n[admin@MikroTik] > /ip service print\nFlags: X - DISABLED, I - INVALID\nColumns: NAME, PORT, CERTIFICATE, VRF\n#   NAME     PORT  CERTIFICATE  VRF \n0   telnet     23               main\n1   ftp        21                   \n2   www        80               main\n3   ssh        22               main\n4 X www-ssl   443  none         main\n5   api      8728               main\n6   winbox   8291               main\n7   api-ssl  8729  none         main\n[admin@MikroTik] > /ip service set api disabled=no address=10.1.1.183/32\n```\n\nadd to docker-compose-exporters.yml\n\n```\nname: exporters\n\nservices:\n  plex-exporter:\n    ...\n  tautulli-exporter:\n    ...\n  tdarr-exporter:\n    ...\n  mktxp:\n    image: ghcr.io/akpw/mktxp:latest\n    container_name: mktxp\n    restart: unless-stopped\n    network_mode: host\n    security_opt:\n      - apparmor=unconfined\n    configs:\n      - source: mktxp_conf\n        target: /home/mktxp/mktxp/mktxp.conf\n\nconfigs:\n  mktxp_conf:\n    content: |\n      [CRS310]\n          enabled = True\n          hostname = 10.1.1.2\n          port = 8728\n          username = mktxp_user\n          password = ${MKTXP_PASSWORD}\n          use_ssl = False\n\n          interface = True\n          monitor = True\n          dhcp = False\n          dhcp_lease = False\n          pool = False\n          firewall = False\n          route = False\n          wireless = False\n          wireless_clients = False\n          capsman = False\n          capsman_clients = False\n```\n\nID: 13679\n\n# \n\nI like it. Can easily connect and see from my phone with tailscale. Necessary? No lol\n\nFrom the three dots in the corner choose to add shortcut. Then it will let you install grafana PWS-style.\n\n**nice**\n# \n\n[https://forum.mikrotik.com/t/guide-grafana-](https://forum.mikrotik.com/t/guide-grafana-)", "url": "https://wpnews.pro/news/monitoring-literally-everything-with-prometheus-grafana", "canonical_source": "https://forum.level1techs.com/t/monitoring-literally-everything-with-prometheus-grafana/260366#post_16", "published_at": "2026-11-11 22:56:22+00:00", "updated_at": "2026-11-12 00:20:07.572329+00:00", "lang": "en", "topics": ["ai-tools"], "entities": ["Prometheus", "Grafana", "Unraid", "Tailscale", "Claude", "Plex", "Pi-hole", "OPNsense"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/monitoring-literally-everything-with-prometheus-grafana", "markdown": "https://wpnews.pro/news/monitoring-literally-everything-with-prometheus-grafana.md", "text": "https://wpnews.pro/news/monitoring-literally-everything-with-prometheus-grafana.txt", "jsonld": "https://wpnews.pro/news/monitoring-literally-everything-with-prometheus-grafana.jsonld"}}