From 8b340f0303153976506db8b4d6fad109cee9c54a Mon Sep 17 00:00:00 2001 From: Arda Nakisci Date: Tue, 10 Mar 2026 10:17:19 +0300 Subject: [PATCH 1/2] Add developer onboarding docs and production operations guide Rewrite README with correct local dev workflow (config setup, COMMIT_SHA, --config flag) and add OPERATIONS.md for production server management, logging, deployment, and key management. --- OPERATIONS.md | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 87 +++++++++++++++--------------- 2 files changed, 188 insertions(+), 43 deletions(-) create mode 100644 OPERATIONS.md diff --git a/OPERATIONS.md b/OPERATIONS.md new file mode 100644 index 0000000..f7b1c3d --- /dev/null +++ b/OPERATIONS.md @@ -0,0 +1,144 @@ +# Operations + +Production server management for the st0x REST API. + +## Server Access + +```sh +ssh root@ +``` + +## Service Management + +The API runs as a systemd service called `rest-api.service`. + +```sh +# Status +systemctl status rest-api.service + +# Restart +systemctl restart rest-api.service + +# Stop / Start +systemctl stop rest-api.service +systemctl start rest-api.service +``` + +## Logs + +Live logs: + +```sh +journalctl -u rest-api.service -f +``` + +Historical logs (last hour, last 100 lines, since a date): + +```sh +journalctl -u rest-api.service --since "1 hour ago" +journalctl -u rest-api.service -n 100 +journalctl -u rest-api.service --since "2026-03-01" +``` + +### File-based logs + +All tracing output is also written as structured JSON to daily-rotating log files. The log directory is configured via `log_dir` in the config file. + +Production log directory: `/mnt/data/st0x-rest-api/logs` + +Files follow the pattern `st0x-rest-api.log.YYYY-MM-DD` — a new file is created each day: + +``` +st0x-rest-api.log.2026-03-08 +st0x-rest-api.log.2026-03-09 +st0x-rest-api.log.2026-03-10 +``` + +To browse them: + +```sh +ls -lt /mnt/data/st0x-rest-api/logs/ +tail -f /mnt/data/st0x-rest-api/logs/st0x-rest-api.log.$(date +%Y-%m-%d) +``` + +Since the files are JSON, you can use `jq` to filter: + +```sh +# All errors from today +cat /mnt/data/st0x-rest-api/logs/st0x-rest-api.log.$(date +%Y-%m-%d) | jq 'select(.level == "ERROR")' + +# Requests to a specific endpoint +cat /mnt/data/st0x-rest-api/logs/st0x-rest-api.log.$(date +%Y-%m-%d) | jq 'select(.fields.uri | contains("/v1/tokens"))' +``` + +Locally, the same file-based logs are written to `./logs/` (relative to where you run the server). + +## Configuration + +The production config is passed via the `ExecStart` line in the service file. To find the current config path: + +```sh +systemctl cat rest-api.service | grep ExecStart | grep -o '\-\-config [^ ]*' | cut -d' ' -f2 +``` + +Production database: `sqlite:///mnt/data/st0x-rest-api/st0x.db` + +## Production Key Management + +Key management commands on the server use the production config path. First, find it: + +```sh +CONFIG=$(systemctl cat rest-api.service | grep ExecStart | grep -o '\-\-config [^ ]*' | cut -d' ' -f2) +``` + +Then use the binary directly: + +```sh +BINARY=/nix/var/nix/profiles/per-service/rest-api/bin/st0x_rest_api + +# Create a key +$BINARY keys --config $CONFIG create --label "partner-name" --owner "contact@example.com" + +# List keys +$BINARY keys --config $CONFIG list + +# Revoke a key +$BINARY keys --config $CONFIG revoke + +# Delete a key +$BINARY keys --config $CONFIG delete +``` + +## Registry Updates + +The strategy registry URL can be updated at runtime via the admin API: + +```sh +curl -X PUT \ + -u "ADMIN_KEY_ID:ADMIN_SECRET" \ + -H "Content-Type: application/json" \ + -d '{"registry_url":"https://raw.githubusercontent.com/rainlanguage/rain.strategies//registry"}' \ + https:///admin/registry -k +``` + +Admin credentials are shared separately and should never be committed. + +## Deployment + +Deployments are triggered manually via the **Deploy** workflow in GitHub Actions (`cd.yaml`, `workflow_dispatch`). To deploy: + +1. Go to the repo's **Actions** tab +2. Select the **Deploy** workflow +3. Click **Run workflow** on the target branch + +The workflow builds the Nix package and deploys it to the server via `deploy-rs`. + +## API Documentation + +User-facing API docs are built with mdbook from `docs/src/`. On the server, the built docs are served from `/var/lib/st0x-docs`. + +To update the docs: + +1. Edit files in `docs/src/` +2. Rebuild locally: `nix develop -c mdbook build docs` +3. Deploy (docs are included in the deployment) diff --git a/README.md b/README.md index ae6dafd..ad09ee8 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ REST API for st0x orderbook operations. Built with Rocket, backed by SQLite, and authenticated via API keys using HTTP Basic auth. +## Prerequisites + +- [Nix](https://nixos.org/download/) with flakes enabled + ## Setup ### 1. Clone and initialize submodules @@ -20,90 +24,87 @@ nix develop -c bash prep.sh This writes `COMMIT_SHA` to `.env` and bootstraps the orderbook submodule. -## Usage - -The binary has two subcommands: +### 3. Configure -``` -st0x_rest_api serve Start the API server -st0x_rest_api keys Manage API keys -``` +The config file is at `config/dev.toml`. The only value that may need updating is `registry_url` — it points to a pinned GitHub raw URL so it should work out of the box. -### Starting the server +If it's stale, grab the latest from production: ```sh -nix develop -c cargo run serve +curl -u "KEY_ID:SECRET" https:///registry -k ``` -The server starts on `http://localhost:8000` by default. Swagger UI is available at `/swagger`. +and update `registry_url` in `config/dev.toml`. -### API key management - -All API routes (except `/health`) require HTTP Basic authentication. Use the `keys` subcommand to manage credentials. - -#### Create a key +### 4. Create an API key ```sh -nix develop -c cargo run keys create --label "partner-x" --owner "contact@example.com" +nix develop -c cargo run -- keys --config config/dev.toml create \ + --label "dev-key" \ + --owner "you@example.com" ``` -Output: - -``` -API key created successfully +This prints a **Key ID** (UUID) and **Secret** (base64 string). Save both — the secret is hashed with Argon2 and cannot be recovered. -Key ID: -Secret: -Label: partner-x -Owner: contact@example.com +### 5. Set log level (optional) -IMPORTANT: Store the secret securely. It will not be shown again. +```sh +export RUST_LOG=st0x_rest_api=info,rocket=warn,warn ``` -The secret is hashed with Argon2 before storage. There is no way to recover it. - -#### List keys +### 6. Start the server ```sh -nix develop -c cargo run keys list +COMMIT_SHA=$(git rev-parse HEAD) nix develop -c cargo run -- serve --config config/dev.toml ``` -Shows all keys with their ID, label, owner, active status, and timestamps. +Server runs on `http://127.0.0.1:8000`. Swagger UI is available at `/swagger`. -#### Revoke a key +The database (`data/st0x.db`) is created and migrated automatically on first run — no manual DB setup needed. + +### 7. Test it ```sh -nix develop -c cargo run keys revoke +curl -u "KEY_ID:SECRET" http://localhost:8000/v1/tokens ``` -Sets the key to inactive. Revoked keys are rejected at authentication. +All endpoints except `/health` require HTTP Basic Auth with the key ID and secret. + +## API Key Management -#### Delete a key +Use the `keys` subcommand to manage credentials. All commands require `--config` to point at the config file. ```sh -nix develop -c cargo run keys delete -``` +# List keys +nix develop -c cargo run -- keys --config config/dev.toml list + +# Revoke a key (sets it to inactive, rejected at auth) +nix develop -c cargo run -- keys --config config/dev.toml revoke -Permanently removes the key from the database. +# Delete a key (permanent removal) +nix develop -c cargo run -- keys --config config/dev.toml delete +``` -### Authenticating API requests +## Authenticating API Requests Use HTTP Basic auth with the key ID as the username and the secret as the password: ```sh -curl -u ":" http://localhost:8000/v1/tokens +curl -u "KEY_ID:SECRET" http://localhost:8000/v1/tokens ``` Or with an explicit header: ```sh -curl -H "Authorization: Basic $(echo -n ':' | base64)" http://localhost:8000/v1/tokens +curl -H "Authorization: Basic $(echo -n 'KEY_ID:SECRET' | base64)" http://localhost:8000/v1/tokens ``` ## Development ```sh -nix develop -c cargo fmt -nix develop -c rainix-rs-static -nix develop -c cargo test +nix develop -c cargo fmt # format +nix develop -c rainix-rs-static # lint +nix develop -c cargo test # test ``` + +Always run the formatter and linter before committing. From e5d91d96ff3c975fb00c5e71890923f5f39f5550 Mon Sep 17 00:00:00 2001 From: Arda Nakisci Date: Fri, 13 Mar 2026 08:35:36 +0100 Subject: [PATCH 2/2] Clarify setup and operations docs --- OPERATIONS.md | 11 ++++++++++- README.md | 6 +++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/OPERATIONS.md b/OPERATIONS.md index f7b1c3d..8d15936 100644 --- a/OPERATIONS.md +++ b/OPERATIONS.md @@ -96,9 +96,12 @@ Then use the binary directly: ```sh BINARY=/nix/var/nix/profiles/per-service/rest-api/bin/st0x_rest_api -# Create a key +# Create a standard key $BINARY keys --config $CONFIG create --label "partner-name" --owner "contact@example.com" +# Create an admin key (required for /admin/* endpoints) +$BINARY keys --config $CONFIG create --label "ops-admin" --owner "ops@example.com" --admin + # List keys $BINARY keys --config $CONFIG list @@ -123,6 +126,12 @@ curl -X PUT \ Admin credentials are shared separately and should never be committed. +There is no dedicated admin-key rotation command. Rotate admin credentials manually: + +1. Create a new admin key with `--admin` +2. Update the systems or operators using the old credentials +3. Revoke or delete the old admin key + ## Deployment Deployments are triggered manually via the **Deploy** workflow in GitHub Actions (`cd.yaml`, `workflow_dispatch`). To deploy: diff --git a/README.md b/README.md index ad09ee8..79ee313 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ git submodule update --init --recursive nix develop -c bash prep.sh ``` -This writes `COMMIT_SHA` to `.env` and bootstraps the orderbook submodule. +This initializes submodules, runs the orderbook prep script, and builds the local mdBook into `docs/book` for the `/docs` route. Run it before the first `serve`. ### 3. Configure @@ -58,7 +58,7 @@ export RUST_LOG=st0x_rest_api=info,rocket=warn,warn COMMIT_SHA=$(git rev-parse HEAD) nix develop -c cargo run -- serve --config config/dev.toml ``` -Server runs on `http://127.0.0.1:8000`. Swagger UI is available at `/swagger`. +Server runs on `http://127.0.0.1:8000`. Swagger UI is available at `/swagger`, and the mdBook docs are served at `/docs`. The database (`data/st0x.db`) is created and migrated automatically on first run — no manual DB setup needed. @@ -68,7 +68,7 @@ The database (`data/st0x.db`) is created and migrated automatically on first run curl -u "KEY_ID:SECRET" http://localhost:8000/v1/tokens ``` -All endpoints except `/health` require HTTP Basic Auth with the key ID and secret. +API routes require HTTP Basic Auth with the key ID and secret. `/health`, `/docs`, `/swagger`, and `/api-doc/openapi.json` are public. ## API Key Management