Rust service that observes Nox protocol flows and materializes handle state in Postgres for debugging and alerting.
- Docker and Docker Compose
Install Rust via rustup if not already present. On Linux these packages are needed:
pkg-configlets the build script locate the system OpenSSL installation.
# Ubuntu / Debian
sudo apt install pkg-configThen run:
cargo build
cargo testdocker compose buildThe service requires Postgres, NATS, and an S3-compatible store. Start Postgres first, then run the service either natively or in Docker.
1. Setup the env file
cp .env.example .envFill in the required credentials for remote service (NATS, S3).
2. Run dependency services
docker compose up -d postgres pgadminsql/schema.sql should be loaded the first time the Postgres volume is created.
Pending migrations then apply automatically when the service starts — see Database migrations below.
3a. Run natively
The .env defaults use docker-compose service names as hosts. For native cargo run some variables need to be overridden:
set -a && source .env && set +a && \
NOX_OBSERVER_DATABASE__HOST=localhost \
cargo run3b. Run in Docker
docker compose up -d nox-observer4. Check the app is running
All services reachable from the host (all bound to 127.0.0.1):
| Service | URL | Notes |
|---|---|---|
nox-observer / |
http://localhost:9000/ | {"service":"nox-observer","timestamp":...} |
nox-observer /health |
http://localhost:9000/health | {"status":"ok"} |
nox-observer /metrics |
http://localhost:9000/metrics | Prometheus metrics |
| pgAdmin | http://localhost:5050 | DB server config is auto-loaded |
| Postgres | localhost:5432 |
psql "$DATABASE_URL" |
sql/schema.sql is only the baseline. Incremental schema changes live in migrations/<version>_<name>.up.sql with a matching .down.sql to reverse them.
Pending migrations are applied automatically on startup using sqlx::migrate! before it begins serving, so a fresh DB and a normal deploy both converge to the latest schema with no extra step. sqlx embeds and validates the migrations/ directory at compile time, tracks applied versions and their checksums in the _sqlx_migrations table, and holds a Postgres advisory lock during the run so multiple instances starting at once serialize instead of racing.
Migrations are immutable once applied, never edit a migration file after it has run anywhere (including in another environment). Sqlx verifies each applied migration's checksum on startup and will refuse to boot on a mismatch. If you need to change behavior, add a new migration instead.
Reverting and adding new migrations can be done using sqlx-cli. Install the CLI using cargo install sqlx-cli:
sqlx migrate add -r <name> # scaffold a new <version>_<name>.up.sql / .down.sql pair
sqlx migrate run # apply pending migrations manually (same as startup does)
sqlx migrate revert # roll back the most recently applied migration (runs its .down.sql)sqlx migrate revert undoes a single migration; repeat it to step further back.
Pointing sqlx-cli at a database: sqlx-cli connects via a single DATABASE_URL (an env var, the --database-url flag, or a .env in the working directory).
# Local docker Postgres
export DATABASE_URL="postgres://nox_user:nox_password@localhost:5432/nox_observer"
sqlx migrate revert
# ...or pass it inline
sqlx migrate revert --database-url $DATABASE_URLFor a remote / production database, append ?sslmode=require to the DB url (matches NOX_OBSERVER_DATABASE__TLS_ENABLED=true).
To ignore an existing handle fill the handle list in sql/ignore_handles.sql and run it manually against a populated database, once those handles have been indexed:
psql "$DATABASE_URL" -f sql/ignore_handles.sqlThe compose stack ships a pgAdmin container reachable at
http://localhost:5050 (default login: admin@example.com / admin).
Prefer another client? Point any Postgres GUI at the DATABASE_URL from your .env
(default: postgres://nox_user:nox_password@localhost:5432/nox_observer). A few good ones: DBeaver, TablePlus, Postico.
The Postgres client connects over TLS, toggled by a single env var:
NOX_OBSERVER_DATABASE__TLS_ENABLED(defaultfalse)
When enabled the client uses sslmode=require: the connection is encrypted but the server certificate is not verified, which matches the trusted private network the managed database sits on. There is no client certificate; the client authenticates with its password. TLS defaults to off so the local docker-compose Postgres (plaintext) works out of the box. In production set NOX_OBSERVER_DATABASE__TLS_ENABLED=true.
The file generated/subgraph/schema.json is the introspected schema of the upstream subgraph. The graphql_client derive macro reads it at compile time and generates Rust types for the queries in src/subgraph/queries.graphql.
Despite the
generated/folder name, this file is committed to Git. The folder name only reflects that the file is produced by a tool, not hand-written. See the rationale below.
Only when the upstream subgraph schema changes — e.g. after the subgraph team deploys a new version with added/removed/renamed fields.
# One-time install (skip if already installed):
cargo install graphql_client_cli
graphql-client introspect-schema \
https://thegraph.arbitrum-sepolia-testnet.noxprotocol.io/api/subgraphs/id/BjQAX2HpmsSAzURJimKDhjZZnkSJtaczA8RPumggrStb \
--output generated/subgraph/schema.jsonAfter regenerating:
- Run
cargo build— if a query insrc/subgraph/queries.graphqlis no longer compatible with the new schema, the build fails with an explicit error. Fix the queries. - Commit both files (
schema.jsonand any updated.graphqlquery) in the same PR so reviewers see the contract change.