Petrolyst server infrastructure: Traefik, Trino and Superset
Traefik as the server-wide edge (TLS via Let's Encrypt, dashboard on traefik.petrolyst.com behind oauth2-proxy and Keycloak). The fuel-monitoring stack: Superset on atoma.petrolyst.com with Keycloak login and Petrolyst branding, Trino reading the TimescaleDB fuel-db as catalog "fuel". Customization lives in petrolyst-insights/, deployment in the other folders. Deploys run server-side (deploy/deploy.sh) from a Gitea workflow or manually; releases are immutable, Superset metadata is backed up before migrations, and deploy/rollback.sh restores it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
24327f9462
commit
d3800ac9dd
34 files changed
+2117
No files matched your search
@@ -0,0 +1,117 @@
|
||||
# Edge proxy for the whole server. Deployed first by deploy/deploy.sh, which
|
||||
# exports TRAEFIK_CONFIG_HASH from the release's ARTIFACTS file.
|
||||
#
|
||||
# Any stack joins by attaching a service to the external network "proxy" and
|
||||
# setting traefik.* labels; apps without their own login can add the "sso"
|
||||
# middleware (Keycloak client petrolyst, role checked by oauth2-proxy).
|
||||
name: traefik
|
||||
|
||||
services:
|
||||
socket-proxy:
|
||||
image: tecnativa/docker-socket-proxy:v0.5.0
|
||||
environment:
|
||||
CONTAINERS: "1"
|
||||
EVENTS: "1"
|
||||
PING: "1"
|
||||
VERSION: "1"
|
||||
POST: "0"
|
||||
LOG_LEVEL: warning
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- socket
|
||||
restart: unless-stopped
|
||||
mem_limit: 64m
|
||||
|
||||
traefik:
|
||||
image: traefik:v3.7.16
|
||||
command: ["--configFile=/etc/traefik/static/traefik.yml"]
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
# Folders, not single files: promotion replaces files by renaming, which a
|
||||
# single-file bind mount would not follow.
|
||||
volumes:
|
||||
- ./static:/etc/traefik/static:ro
|
||||
- ./dynamic:/etc/traefik/dynamic:ro
|
||||
- letsencrypt:/letsencrypt
|
||||
depends_on:
|
||||
- socket-proxy
|
||||
networks:
|
||||
- proxy
|
||||
- socket
|
||||
restart: unless-stopped
|
||||
mem_limit: 256m
|
||||
healthcheck:
|
||||
test: ["CMD", "traefik", "healthcheck", "--configFile=/etc/traefik/static/traefik.yml"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 6
|
||||
labels:
|
||||
petrolyst.config-hash: ${TRAEFIK_CONFIG_HASH:?TRAEFIK_CONFIG_HASH unset - run through deploy/deploy.sh}
|
||||
traefik.enable: "true"
|
||||
traefik.http.routers.dashboard.rule: Host(`${TRAEFIK_HOST:-traefik.petrolyst.com}`)
|
||||
traefik.http.routers.dashboard.entrypoints: websecure
|
||||
traefik.http.routers.dashboard.tls.certresolver: le
|
||||
traefik.http.routers.dashboard.service: api@internal
|
||||
traefik.http.routers.dashboard.middlewares: sso,secure-headers@file
|
||||
# Keycloak gate for the dashboard host only (cookie, return hosts and
|
||||
# role are tied to it; README "Adding a project"): unauthenticated
|
||||
# requests are sent to Keycloak, users without petrolyst:traefik-admin
|
||||
# get 403.
|
||||
traefik.http.middlewares.sso.forwardauth.address: http://oauth2-proxy:4180/
|
||||
traefik.http.middlewares.sso.forwardauth.trustForwardHeader: "true"
|
||||
traefik.http.middlewares.sso.forwardauth.authResponseHeaders: X-Auth-Request-User,X-Auth-Request-Email
|
||||
|
||||
oauth2-proxy:
|
||||
image: quay.io/oauth2-proxy/oauth2-proxy:v7.15.5
|
||||
command:
|
||||
- --provider=keycloak-oidc
|
||||
- --oidc-issuer-url=${KEYCLOAK_REALM_URL:-https://iam.thedigitalbridge.io/realms/thedigitalbridge}
|
||||
- --client-id=petrolyst
|
||||
- --client-secret-file=/run/secrets/keycloak_petrolyst_client_secret
|
||||
- --cookie-secret-file=/run/secrets/oauth2_proxy_cookie_secret
|
||||
- --code-challenge-method=S256
|
||||
- --allowed-role=petrolyst:traefik-admin
|
||||
# Required by oauth2-proxy at startup; access is decided by the role above.
|
||||
- --email-domain=*
|
||||
- --redirect-url=https://${TRAEFIK_HOST:-traefik.petrolyst.com}/oauth2/callback
|
||||
- --whitelist-domain=${TRAEFIK_HOST:-traefik.petrolyst.com}
|
||||
- --cookie-domain=${TRAEFIK_HOST:-traefik.petrolyst.com}
|
||||
- --cookie-secure=true
|
||||
- --cookie-samesite=lax
|
||||
- --reverse-proxy=true
|
||||
- --upstream=static://202
|
||||
- --skip-provider-button=true
|
||||
- --set-xauthrequest=true
|
||||
- --http-address=0.0.0.0:4180
|
||||
secrets:
|
||||
- keycloak_petrolyst_client_secret
|
||||
- oauth2_proxy_cookie_secret
|
||||
networks:
|
||||
- proxy
|
||||
restart: unless-stopped
|
||||
mem_limit: 128m
|
||||
labels:
|
||||
traefik.enable: "true"
|
||||
traefik.docker.network: proxy
|
||||
traefik.http.routers.oauth2.rule: Host(`${TRAEFIK_HOST:-traefik.petrolyst.com}`) && PathPrefix(`/oauth2/`)
|
||||
traefik.http.routers.oauth2.entrypoints: websecure
|
||||
traefik.http.routers.oauth2.tls.certresolver: le
|
||||
traefik.http.routers.oauth2.middlewares: secure-headers@file
|
||||
traefik.http.services.oauth2.loadbalancer.server.port: "4180"
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
socket:
|
||||
internal: true
|
||||
|
||||
volumes:
|
||||
letsencrypt:
|
||||
|
||||
secrets:
|
||||
keycloak_petrolyst_client_secret:
|
||||
file: ${PETROLYST_ROOT:-/opt/petrolyst}/secrets/shared/keycloak_petrolyst_client_secret
|
||||
oauth2_proxy_cookie_secret:
|
||||
file: ${PETROLYST_ROOT:-/opt/petrolyst}/secrets/traefik/oauth2_proxy_cookie_secret
|
||||
Reference in new issue
Block a user