Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/admin-dashboard-ui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nostream": minor
---

feat: add admin observability dashboard with Grafana embed and provisioned metrics panels
5 changes: 5 additions & 0 deletions .changeset/admin-metrics-sse-endpoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nostream": minor
---

feat: add Prometheus-backed admin metrics SSE endpoint
15 changes: 15 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ WORKER_COUNT=2 # Defaults to CPU count. Use 1 or 2 for local testing.
# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
# OTEL_METRIC_EXPORT_INTERVAL_MS=10000

# --- OBSERVABILITY (Prometheus for Admin Metrics) ---
# PROMETHEUS_URL=http://127.0.0.1:9090
# PROMETHEUS_QUERY_TIMEOUT_MS=5000
# ADMIN_METRICS_SSE_INTERVAL_MS=5000
# ADMIN_METRICS_SNAPSHOT_TIMEOUT_MS=10000
# ADMIN_DEPENDENCY_PING_TIMEOUT_MS=3000

# --- ADMIN CONSOLE (opt-in; disabled by default in default-settings.yaml) ---
# ADMIN_PASSWORD=dev-admin-password
# Set admin.enabled: true in .nostr/settings.yaml to enable the console
# GRAFANA_URL=http://127.0.0.1:3000
# GRAFANA_DASHBOARD_UID=nostream-overview
# GRAFANA_ADMIN_USER=admin
# GRAFANA_ADMIN_PASSWORD=admin

# --- RELAY PRIVATE KEY (Optional) ---
# RELAY_PRIVATE_KEY=your_hex_private_key

Expand Down
5 changes: 5 additions & 0 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ The following environment variables can be set:
| REDIS_PORT | Redis Port | 6379 |
| REDIS_USER | Redis User | default |
| REDIS_PASSWORD | Redis Password | nostr_ts_relay |
| PROMETHEUS_URL | Prometheus base URL for admin metrics queries | http://127.0.0.1:9090 |
| PROMETHEUS_QUERY_TIMEOUT_MS | Timeout for each Prometheus admin metrics query (ms) | 5000 |
| ADMIN_METRICS_SSE_INTERVAL_MS | Interval between `/admin/metrics` SSE snapshots (ms) | 5000 |
| ADMIN_METRICS_SNAPSHOT_TIMEOUT_MS| Timeout for collecting one `/admin/metrics` snapshot (ms) | 10000 |
| ADMIN_DEPENDENCY_PING_TIMEOUT_MS | Timeout for admin DB/Redis dependency pings (ms) | 3000 |
| NOSTR_CONFIG_DIR | Configuration directory | <project_root>/.nostr/ |
| DEBUG | Debugging filter | |
| ZEBEDEE_API_KEY | Zebedee Project API Key | |
Expand Down
26 changes: 26 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ services:
OTEL_SERVICE_NAME: ${OTEL_SERVICE_NAME:-nostream}
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://otel-collector:4318}
OTEL_METRIC_EXPORT_INTERVAL_MS: ${OTEL_METRIC_EXPORT_INTERVAL_MS:-10000}
PROMETHEUS_URL: ${PROMETHEUS_URL:-http://prometheus:9090}
ADMIN_METRICS_SSE_INTERVAL_MS: ${ADMIN_METRICS_SSE_INTERVAL_MS:-5000}
# Enable DEBUG for troubleshooting. Examples:
# DEBUG: "primary:*"
# DEBUG: "worker:*"
Expand Down Expand Up @@ -177,6 +179,29 @@ services:
networks:
default:

grafana:
image: grafana/grafana:11.2.0
container_name: grafana
environment:
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:-admin}
GF_AUTH_ANONYMOUS_ENABLED: 'true'
GF_AUTH_ANONYMOUS_ORG_ROLE: Viewer
GF_SECURITY_ALLOW_EMBEDDING: 'true'
GF_SERVER_ROOT_URL: ${GRAFANA_URL:-http://127.0.0.1:3000}
volumes:
- ./grafana/provisioning:/etc/grafana/provisioning:ro
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
- grafana-data:/var/lib/grafana
ports:
- 127.0.0.1:3000:3000
depends_on:
prometheus:
condition: service_started
restart: always
networks:
default:

networks:
default:
name: nostream
Expand All @@ -188,3 +213,4 @@ networks:
volumes:
cache:
prometheus-data:
grafana-data:
2 changes: 2 additions & 0 deletions docs/REDIS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Nostream needs.

Rate limiting is implemented using a sliding window strategy, which uses Redis sorted sets to track request timestamps. This allows Nostream to accurately enforce rate limits over a rolling time window rather than a fixed one, preventing clients from bursting requests at window boundaries.

When Redis is temporarily unavailable, Nostream keeps serving the relay and admin HTTP endpoints and treats rate-limiter Redis failures as fail-open (events are not blocked solely because Redis is down). Admin health degrades accordingly (`redis.ok=false`), so operators can detect and recover Redis without taking the relay offline.

## Requirements

- Redis 6.0 or higher (for ACL support)
Expand Down
Loading
Loading