Host: 192.168.11.89 (docker)
Stack location: /home/nate/monitoring/
Dashboard URL: https://client.resilientpathconsulting.net/grafana/d/starlink-dish/starlink-dish
Dish gRPC endpoint: 192.168.67.1:9200 (Filmworks subnet)
Starlink Dish (192.168.67.1:9200 gRPC)
|
starlink-exporter (host network, port 9817)
|
Prometheus (port 9090, 90d retention)
|
Grafana (port 3001 -> proxied via Caddy)
^
grafana-renderer (port 8081, PNG export)
All containers defined in /home/nate/monitoring/docker-compose.yml on 192.168.11.89.
Prometheus and Grafana are on the monitoring bridge network.
The starlink-exporter uses network_mode: host so it can reach 192.168.67.1 via host routing.
| Container | Image | Port | Notes |
|---|---|---|---|
prometheus |
prom/prometheus:latest | 9090 | 90d retention, external-url set |
grafana |
grafana/grafana:latest | 3001->3000 | Sub-path serving enabled |
grafana-renderer |
grafana/grafana-image-renderer:latest | 8081 | PNG panel export |
starlink-exporter |
built locally | 9817 | host network mode |
node-exporter |
prom/node-exporter:latest | 9100 | host metrics for .89 |
/home/nate/monitoring/prometheus/prometheus.yml--web.external-url=https://client.resilientpathconsulting.net/prometheus//prometheus or every query returns 404./home/nate/monitoring/grafana/provisioning/datasources/prometheus.ymlhttp://prometheus:9090/prometheus/prometheus suffix is required. Without it Grafana shows no data/home/nate/monitoring/starlink-exporter/STARLINK_ADDRESS=192.168.67.1:9200, LISTEN_PORT=9817, SCRAPE_INTERVAL=10http://192.168.11.89:9817/metricsstarlink_dish_uptime_seconds, starlink_dish_snr,starlink_dish_uplink_throughput_bps, starlink_dish_downlink_throughput_bpsProxied through Caddy on 192.168.11.89. Caddyfile: /home/nate/client-portal/caddy/Caddyfile
handle /grafana/* {
reverse_proxy grafana:3000
}
handle /prometheus/* {
reverse_proxy prometheus:9090
}
# Start/stop/restart entire stack
cd /home/nate/monitoring
sudo docker compose up -d
sudo docker compose stop
sudo docker compose restart
sudo docker compose logs -f
# Verify Starlink data is flowing
curl -s http://localhost:9817/metrics | grep -E "starlink_dish_up|snr|throughput"
# Check Prometheus scrape targets (note /prometheus prefix)
sudo docker exec prometheus wget -qO- http://localhost:9090/prometheus/api/v1/targets | \
python3 -c "import sys,json; d=json.load(sys.stdin); \
[print(t['labels'].get('job'), t['health'], t.get('lastError','')) \
for t in d['data']['activeTargets']]"
Root cause: Two possible causes:
--web.external-url sets a path prefix; Grafana datasource URL must match.Fix applied 2026-03-06: Updated datasource URL to http://prometheus:9090/prometheus.
Verify fix is in place:
sudo cat /home/nate/monitoring/grafana/provisioning/datasources/prometheus.yml
# url should read: http://prometheus:9090/prometheus
If still broken after verifying: Restart Grafana to reload provisioned datasources:
sudo docker restart grafana
Dish at 192.168.67.1 is on the Filmworks (67.x) subnet. If routing is down
(WireGuard, VPN), the exporter logs gRPC timeouts. Self-recovers once routing restores.
Cosmetic only — Prometheus self-scrape target uses wrong path due to external-url prefix.
Does not affect Starlink or node-exporter data. Fix: change self-scrape target to
localhost:9090/prometheus/metrics in prometheus.yml if desired.
starlink-dishPanels: dish uptime, SNR, uplink/downlink throughput, obstruction map, latency.