Remove Trino: Superset reads fuel-db directly as fuel_ro (PD-14)

trino/ deleted; the role trino_ro becomes fuel_ro, its password read from a
secret file at connect time; dashboards' SQL and column list for PostgreSQL;
the Compose project is renamed petrolyst, with volumes pinned to their old
names. AGENTS.md points to the architecture context. Not deployed: the next
deploy needs README's one-time steps first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Nasim SadatandClaude Opus 5.5 committed 2026-10-30 10:57:18 +01:00
1 parent 686318dfac
commit 8405706ed8
25 files changed
+453 -410

No files matched your search

+55 -15
View File
@@ -5,7 +5,8 @@ Everything that runs on the petrolyst server (109.199.127.84, Ubuntu 24.04):
- **Traefik** at the edge for every project on the server. Its dashboard is at
https://traefik.petrolyst.com, behind Keycloak.
- **fuel-monitoring** (ATOMA): Superset at https://atoma.petrolyst.com, reading the operational
store `fuel-db` (Postgres 17 with TimescaleDB) through Trino. Sign-in goes through Keycloak
store `fuel-db` (Postgres 17 with TimescaleDB) directly, as the read-only role `fuel_ro`
(Trino was removed on 29 Oct 2026). Sign-in goes through Keycloak
client `petrolyst`, and the UI carries the Petrolyst brand.
**Deploys are manual.** A person deploys a clean commit of `main` from the Mac ("Manual deploy"
@@ -17,7 +18,7 @@ Customization and deployment are separate, as with media-insights and media-inte
|---|---|
| `petrolyst-insights/` | how Superset looks and behaves for Petrolyst: config, Keycloak login code, branding, patches, dashboards. See its README. |
| `traefik/` | edge proxy, TLS, the `sso` middleware (oauth2-proxy) that guards the dashboard |
| `stacks/fuel-monitoring/` | Compose stack, Superset Dockerfile, Trino config and catalog, fuel-db roles |
| `stacks/fuel-monitoring/` | Compose stack, Superset Dockerfile and init, fuel-db roles and migrations |
| `deploy/` | `deploy.sh` (run on the server by a manual deploy), `rollback.sh` (manual), `lib.sh` (shared) |
| `host/` | one-time server setup: `bootstrap.sh`, `secrets-init.sh` |
| `keycloak/` | the `petrolyst` client for Keycloak's partial import |
@@ -38,10 +39,10 @@ No credential is in this repository. Secrets exist only on the server, under
4. It resolves the artifacts and writes them to `releases/<sha>/ARTIFACTS`:
- `SUPERSET_IMAGE_TAG` is a hash of exactly the Superset image's build inputs. They include
`superset/init.sh`, so changing that file runs `superset-init` again.
- `TRINO_CONFIG_HASH` and `TRAEFIK_CONFIG_HASH` are hashes of the bind-mounted config.
- `TRAEFIK_CONFIG_HASH` is a hash of Traefik's bind-mounted static config.
- Compose recreates a container only when its value changes.
5. Preflight, before anything live changes:
- every secret and env file exists;
- every secret file exists;
- `petrolyst-insights/` holds no deployment files;
- `docker compose config` passes for every stack;
- the Superset image is built if it is new;
@@ -52,13 +53,14 @@ No credential is in this repository. Secrets exist only on the server, under
- An empty database is a fresh install: it runs `superset-init`.
- If the image changed, or the database is not at the image's migration head: it stops
`superset`, writes `backups/superset-meta_<old tag>_<revision>_<time>.dump`, then runs
`superset-init` (`db upgrade`, `init`, registers "Fuel (Trino)").
`superset-init` (`db upgrade`, `init`, registers "Fuel": fuel-db as `fuel_ro`, its password
read from `/run/secrets` at connect time, never stored in Superset).
- If the image is unchanged and the schema is at its head, it does none of this.
8. Smoke tests. A failure ends the deploy with an error and prints the stacks' state.
- `/health` answers through Traefik with a valid certificate.
- `/login/` leads to Keycloak with `client_id=petrolyst` and PKCE.
- The dashboard redirects to Keycloak.
- Trino reads `fuel`, and Superset reaches Trino.
- Superset's "Fuel" connection reads fuel-db as `fuel_ro`, and its transactions are read-only.
9. Retention:
- 5 releases;
- backups for 30 days;
@@ -75,7 +77,6 @@ The manual deploy then checks both hosts from outside.
| `/opt/petrolyst/incoming/<sha>-manual-<time>` | deploy | one upload; only `deploy.sh` turns it into a release |
| `/opt/petrolyst/releases/<sha>` | deploy, read-only | finalized release plus `ARTIFACTS`; the last 5 are kept |
| `/opt/petrolyst/secrets/{shared,traefik,fuel-monitoring}/` | root:deploy 0750, files 0444 | secrets, mounted as `/run/secrets/<name>` |
| `/opt/petrolyst/env/fuel-monitoring.env` | root:deploy 0440 | `FUEL_DB_TRINO_PASSWORD` for Trino's `${ENV:…}` |
| `/opt/petrolyst/backups/` | deploy 0750 | Superset metadata dumps |
| `/opt/petrolyst/state/` | deploy | last deployed SHA and Superset image tag; `rollback-in-progress` during a migration rollback |
@@ -160,10 +161,10 @@ becomes the first Superset admin; there is no local admin account.
| Re-deploy a kept release | `sudo -u deploy /opt/petrolyst/infra/deploy/deploy.sh <sha>` |
| Roll back | see below |
| Traefik dashboard | https://traefik.petrolyst.com (role `traefik-admin`) |
| Trino shell | `docker exec -it fuel-monitoring-trino-1 trino` |
| fuel-db shell | `docker exec -it petrolyst-fuel-db-1 psql -U postgres -d fuel` |
| fuel-db from the Mac | `ssh -L 5433:127.0.0.1:5433 petrolyst`, then connect to `localhost:5433`, database `fuel` |
| Logs | `docker compose -p fuel-monitoring logs -f superset` (or `-p traefik`) |
| Superset break-glass | `docker exec -it fuel-monitoring-superset-1 superset fab ...` |
| Logs | `docker compose -p petrolyst logs -f superset` (or `-p traefik`) |
| Superset break-glass | `docker exec -it petrolyst-superset-1 superset fab ...` |
**Manual deploy**, the only way to deploy (there is no CI runner). On the Mac, in this
repository:
@@ -227,12 +228,12 @@ sudo -u deploy /opt/petrolyst/infra/deploy/rollback.sh <sha>
Afterwards, `git revert` the bad commit and push, so `main` matches. A plain revert without the
rollback script is stopped by the downgrade guard.
**Data loaders** (fuel-db). Every table in `public` must belong to `fuel_owner`. `trino_ro` can
**Data loaders** (fuel-db). Every table in `public` must belong to `fuel_owner`. `fuel_ro` can
read new tables only through `fuel_owner`'s default privileges, and PostgreSQL applies those
only to objects `fuel_owner` creates itself. A table that a loader creates as its own role stays
unreadable for Trino. Create each loader role so that its sessions act as `fuel_owner`, and it
unreadable for Superset and the Petrolyst server. Create each loader role so that its sessions act as `fuel_owner`, and it
cannot create anything as itself. Run this in
`docker exec -it fuel-monitoring-fuel-db-1 psql -U postgres -d fuel`:
`docker exec -it petrolyst-fuel-db-1 psql -U postgres -d fuel`:
```sql
CREATE ROLE <loader> LOGIN PASSWORD '<password>';
@@ -240,9 +241,46 @@ GRANT fuel_owner TO <loader> WITH INHERIT FALSE, SET TRUE;
ALTER ROLE <loader> SET role TO 'fuel_owner';
```
Tables it creates, hypertables included, then belong to `fuel_owner`, and Trino can read them.
Tables it creates, hypertables included, then belong to `fuel_owner`, and `fuel_ro` can read them.
After `SET ROLE NONE`, it cannot create anything in `public`. To repair a table that another
role created, run `ALTER TABLE <t> OWNER TO fuel_owner`, then `GRANT SELECT ON <t> TO trino_ro`.
role created, run `ALTER TABLE <t> OWNER TO fuel_owner`, then `GRANT SELECT ON <t> TO fuel_ro`.
**One-time steps after 29 Oct 2026**, at the first deploy that includes them. Two changes
meet there:
- Trino is removed: Superset reads fuel-db directly. The role `trino_ro` becomes `fuel_ro` and
keeps its password (a SCRAM password survives a rename); its secret file moves with it.
- The Compose project `fuel-monitoring` is renamed `petrolyst`. Containers are then called
`petrolyst-<service>-1`. The data volumes keep their names (`fuel-monitoring_superset_db_data`,
`fuel-monitoring_fuel_db_data`; pinned in `compose.yaml`), so no data moves. The old project's
containers must be gone first: two PostgreSQL servers on one data volume corrupt it.
Preflight refuses to deploy while any of them exists.
As root on the server, right before the deploy (Superset is down from step 3 until the deploy
finishes):
```bash
S=/opt/petrolyst/secrets/fuel-monitoring
mv "$S/fuel_db_trino_password" "$S/fuel_db_ro_password" # 1
docker exec -i fuel-monitoring-fuel-db-1 psql -U postgres -d fuel -v ON_ERROR_STOP=1 \
-c 'ALTER ROLE trino_ro RENAME TO fuel_ro' \
-c 'ALTER ROLE fuel_ro SET default_transaction_read_only = on' # 2
docker rm -f $(docker ps -aq --filter label=com.docker.compose.project=fuel-monitoring) # 3
```
4. Deploy as usual ("Manual deploy"). Compose starts the `petrolyst` project on the same volumes
and no longer starts Trino. Compose warns once that the volumes belong to another project;
that is expected. `superset-init` renames the connection "Fuel (Trino)" to "Fuel" and points
it at fuel-db; the smoke test checks that it reads as `fuel_ro`, read-only.
5. Clean up: `rm /opt/petrolyst/env/fuel-monitoring.env`, `rmdir /opt/petrolyst/env`,
`docker image rm trinodb/trino:484`,
`docker network rm fuel-monitoring_backend fuel-monitoring_fuel-db-tunnel`.
**Rollback across the Trino removal** (not tested). `rollback.sh` stops for a release from before
it. To go back anyway: remove the `petrolyst` project's containers, reverse steps 1 and 2 above (rename `fuel_ro` back to `trino_ro` and
`ALTER ROLE trino_ro RESET default_transaction_read_only`, move the secret file back, write
`/opt/petrolyst/env/fuel-monitoring.env` with `FUEL_DB_TRINO_PASSWORD=<that secret>`), rename
the Superset connection "Fuel" back to "Fuel (Trino)" with `trino://superset@trino:8080/fuel`,
then run that release's own script, `/opt/petrolyst/releases/<sha>/deploy/rollback.sh <sha>`.
**Adding a project**: create `stacks/<name>/compose.yaml`, attach the public service to the
external network `proxy`, and set `traefik.*` labels with a unique router name and
@@ -261,6 +299,8 @@ its own gate in its stack:
## Verified locally (2026-10-23)
Before Trino's removal (29 Oct 2026): its lines below are history.
An end-to-end run ran the real `deploy.sh` and `rollback.sh` in a Linux container against
Docker Desktop, with a scratch `/opt/petrolyst`. Production differences in that run:
- a test CA certificate stood in for Let's Encrypt;