Use dashboard.thermograph.org + Google SSO for the dashboard
- Grafana served at dashboard.thermograph.org (the record now points at beta) - Google OAuth (OIDC) login, env-gated (OAUTH_ENABLED + GOOGLE_CLIENT_ID/SECRET); allow_sign_up=false so access is locked to pre-provisioned accounts, with a break-glass local admin fallback - README: Google Cloud OAuth client setup with the redirect URIs for both Grafana and Forgejo, plus the Forgejo add-oauth command
This commit is contained in:
parent
46edb0bca0
commit
7e8a484ad5
4 changed files with 71 additions and 16 deletions
17
.env.example
17
.env.example
|
|
@ -1,9 +1,20 @@
|
|||
# Copy to .env on the monitoring host (beta) before `docker compose up`.
|
||||
# .env is gitignored — never commit real secrets.
|
||||
|
||||
# Grafana admin login (the UI's own auth; Grafana is the only thing exposed).
|
||||
# The public hostname beta's Caddy serves Grafana at (see caddy-grafana.conf).
|
||||
GRAFANA_DOMAIN=dashboard.thermograph.org
|
||||
|
||||
# Break-glass local admin (Google SSO below is the primary login). Keep this
|
||||
# strong; it's the fallback if OAuth ever breaks.
|
||||
GF_ADMIN_USER=admin
|
||||
GF_SECURITY_ADMIN_PASSWORD=change-me-to-something-strong
|
||||
|
||||
# The public hostname beta's Caddy serves Grafana at (see caddy-grafana.conf).
|
||||
GRAFANA_DOMAIN=grafana.thermograph.org
|
||||
# --- Google SSO ------------------------------------------------------------------
|
||||
# Create a Google Cloud "OAuth 2.0 Client ID" (type: Web application) and set:
|
||||
# Authorized redirect URI: https://dashboard.thermograph.org/login/google
|
||||
# Then paste the client id/secret here and flip OAUTH_ENABLED=true.
|
||||
# Login is locked to pre-provisioned accounts (allow_sign_up=false) — provision
|
||||
# your email as an admin (see README) so only you can sign in.
|
||||
OAUTH_ENABLED=false
|
||||
GOOGLE_CLIENT_ID=
|
||||
GOOGLE_CLIENT_SECRET=
|
||||
|
|
|
|||
36
README.md
36
README.md
|
|
@ -17,8 +17,8 @@ persistent, queryable, fleet-wide log store and UI.
|
|||
|
||||
- **Loki** stores logs (filesystem, 30-day retention). Listens on the mesh IP
|
||||
`10.10.0.2:3100` — never public.
|
||||
- **Grafana** is the UI, fronted by beta's Caddy at `grafana.thermograph.org`
|
||||
(its own login; Loki is not exposed).
|
||||
- **Grafana** is the UI, fronted by beta's Caddy at `dashboard.thermograph.org`,
|
||||
login via **Google SSO** (with a break-glass local admin); Loki is not exposed.
|
||||
- **Alloy** runs on each node and ships three sources to Loki: every Docker
|
||||
container's stdout/stderr, Caddy's host access logs, and the app's structured
|
||||
JSON logs (`errors`/`access`/`audit` `*.jsonl`, parsed so `level`/`tag`/`phase`
|
||||
|
|
@ -47,9 +47,39 @@ cp .env.example .env # set GF_SECURITY_ADMIN_PASSWORD
|
|||
docker compose up -d # Loki on 10.10.0.2:3100 + 127.0.0.1:3100; Grafana on 127.0.0.1:3000
|
||||
```
|
||||
|
||||
Expose the Grafana UI: point `grafana.thermograph.org` at beta, append
|
||||
Expose the Grafana UI: point `dashboard.thermograph.org` at beta, append
|
||||
`caddy-grafana.conf` to `/etc/caddy/Caddyfile`, `systemctl reload caddy`.
|
||||
|
||||
### Google SSO (Grafana + Forgejo)
|
||||
|
||||
Both the dashboard and Forgejo log in with Google. Create **one** Google Cloud
|
||||
OAuth 2.0 Client (type: *Web application*) and register both redirect URIs:
|
||||
|
||||
- Grafana: `https://dashboard.thermograph.org/login/google`
|
||||
- Forgejo: `https://git.thermograph.org/user/oauth2/google/callback`
|
||||
|
||||
**Grafana:** put the client id/secret in `.env`, set `OAUTH_ENABLED=true`, and
|
||||
`docker compose up -d`. Login is locked to pre-provisioned accounts
|
||||
(`allow_sign_up=false`), so provision your email as an admin once:
|
||||
|
||||
```bash
|
||||
# on beta, after the stack is up (uses the break-glass admin creds from .env):
|
||||
curl -s -u admin:"$GF_SECURITY_ADMIN_PASSWORD" -H 'Content-Type: application/json' \
|
||||
-X POST http://127.0.0.1:3000/api/admin/users \
|
||||
-d '{"name":"you","login":"you@gmail.com","email":"you@gmail.com","password":"'"$(openssl rand -base64 24)"'"}'
|
||||
# then make that user a Grafana admin (org role Admin + server admin) via the UI
|
||||
# or /api/org/users; the Google login matches on email.
|
||||
```
|
||||
|
||||
**Forgejo:** add the Google auth source (once, as a Forgejo admin):
|
||||
|
||||
```bash
|
||||
docker exec -u git <forgejo-container> forgejo admin auth add-oauth \
|
||||
--name google --provider openidConnect \
|
||||
--key "<CLIENT_ID>" --secret "<CLIENT_SECRET>" \
|
||||
--auto-discover-url https://accounts.google.com/.well-known/openid-configuration
|
||||
```
|
||||
|
||||
### 2. Alloy agent (on every node — prod, beta, desktop)
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
# Append to beta's /etc/caddy/Caddyfile (beta is the monitoring host), then
|
||||
# `systemctl reload caddy`. Grafana publishes to 127.0.0.1:3000; this fronts it
|
||||
# with TLS, same pattern as beta's other site blocks. Grafana owns its own login,
|
||||
# so the UI is safe to expose publicly — but Loki (the log store, on
|
||||
# 10.10.0.2:3100) is NOT proxied here and stays mesh-only.
|
||||
# with TLS, same pattern as beta's other site blocks. Login is Google SSO (with a
|
||||
# break-glass local admin); Loki (the log store, on 10.10.0.2:3100) is NOT proxied
|
||||
# here and stays mesh-only.
|
||||
#
|
||||
# Point grafana.thermograph.org's A record at beta (75.119.132.91) first.
|
||||
# dashboard.thermograph.org's A record must already point at beta (75.119.132.91).
|
||||
|
||||
grafana.thermograph.org {
|
||||
dashboard.thermograph.org {
|
||||
encode zstd gzip
|
||||
reverse_proxy 127.0.0.1:3000
|
||||
log {
|
||||
output file /var/log/caddy/grafana.log
|
||||
output file /var/log/caddy/dashboard.log
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,16 +27,30 @@ services:
|
|||
image: grafana/grafana:11.6.1
|
||||
depends_on: [loki]
|
||||
environment:
|
||||
# Grafana owns its own auth. Admin password is injected from the host env
|
||||
# (set GF_SECURITY_ADMIN_PASSWORD before `up`, or in an .env file — see
|
||||
# .env.example); never bake a credential into the compose file.
|
||||
# Primary login is Google SSO (below). The admin user is kept as a
|
||||
# break-glass local fallback; its password comes from the host env
|
||||
# (.env — see .env.example), never baked into the compose file.
|
||||
GF_SECURITY_ADMIN_USER: ${GF_ADMIN_USER:-admin}
|
||||
GF_SECURITY_ADMIN_PASSWORD: ${GF_SECURITY_ADMIN_PASSWORD:?set GF_SECURITY_ADMIN_PASSWORD}
|
||||
GF_USERS_ALLOW_SIGN_UP: "false"
|
||||
GF_ANALYTICS_REPORTING_ENABLED: "false"
|
||||
GF_ANALYTICS_CHECK_FOR_UPDATES: "false"
|
||||
# Served behind Caddy at this external URL (sub-path-safe cookie/redirects).
|
||||
GF_SERVER_ROOT_URL: "https://${GRAFANA_DOMAIN:-grafana.thermograph.org}/"
|
||||
GF_SERVER_ROOT_URL: "https://${GRAFANA_DOMAIN:-dashboard.thermograph.org}/"
|
||||
# --- Google SSO (OIDC) -----------------------------------------------------
|
||||
# Enabled once GOOGLE_CLIENT_ID/SECRET are set in .env and OAUTH_ENABLED=true.
|
||||
# allow_sign_up is FALSE: a Google login only succeeds if a Grafana user with
|
||||
# that email already exists — so this dashboard is locked to pre-provisioned
|
||||
# accounts (see README), not "any Google user". Redirect URI to register in
|
||||
# Google Cloud: https://dashboard.thermograph.org/login/google
|
||||
GF_AUTH_GOOGLE_ENABLED: ${OAUTH_ENABLED:-false}
|
||||
GF_AUTH_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
|
||||
GF_AUTH_GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
|
||||
GF_AUTH_GOOGLE_SCOPES: "openid email profile"
|
||||
GF_AUTH_GOOGLE_AUTH_URL: "https://accounts.google.com/o/oauth2/v2/auth"
|
||||
GF_AUTH_GOOGLE_TOKEN_URL: "https://oauth2.googleapis.com/token"
|
||||
GF_AUTH_GOOGLE_API_URL: "https://openidconnect.googleapis.com/v1/userinfo"
|
||||
GF_AUTH_GOOGLE_ALLOW_SIGN_UP: "false"
|
||||
volumes:
|
||||
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
||||
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
|
||||
|
|
|
|||
Loading…
Reference in a new issue