import { Callout } from 'nextra/components' import { AccordionTemplate } from 'components/accordion-template.tsx' # NS API: Deployment Guide ## Components The Node Status API is made up of 3 components: - `nym-node-status-api` - `nym-node-status-client` - `nym-node-status-agent` The API stores its data in a local SQLite database. It periodically gets most of its data from a [NymAPI](/apis/nym-api) instance, and for instances also running with the Gateway Probe, uses the stored topology to conduct performance probe tests. ## Gateway Probe You can run the `nym-node-status-api` alone, but if you want to run probes for `nym-node`s running as Gateways, you have to also run the `nym-node-status-agent` (which consumes the `nym-node-status-client` lib). The probe will run a set of tests per Gateway node, and return the sort of results seen [here](https://harbourmaster.nymtech.net/gateway/23A7CSaBSA2L67PWuFTPXUnYrCdyVcB7ATYsjUsfdftb). ## UI The API exposes a [Swagger](https://swagger.io/docs/) documentation UI by default on port `8000` (see an example [here](https://mainnet-node-status-api.nymtech.cc/swagger/)). Currently we are not shipping a custom UI component for the Node Status API. The [Harbourmaster](https://harbourmaster.nymtech.net/) frontend consumes this API, amongst other things, but this is an internal repo we use to experiment with new APIs and data on, so it is not public yet. We invite developers to roll their own UI for their Node Status API instance. ## Docker Images We will ship Docker images for both the `agent` and `api` in the future. There are Docker images for both in root of each corresponding crate ([`agent`](https://github.com/nymtech/nym/blob/09ea406c02e9a3beebc062f525e4ea1b4222dcbb/nym-node-status-api/nym-node-status-agent/Dockerfile), [`api`](https://github.com/nymtech/nym/blob/develop/nym-node-status-api/nym-node-status-api/Dockerfile)) which are used internally, which could be a starting point for developers to dockerize their instance for the moment. ## Build ### Prerequisites - Rust - SQLite - Get an `ipinfo` key following instructions [here](https://github.com/ipinfo/rust?tab=readme-ov-file#getting-started). ### Compilation ```shell cargo build --release --package nym-node-status-api --package nym-node-status-agent --package nym-node-status-client ``` ## Run Since the Node Status API depends on both flags and environmental variables, it might be easier to run the binary via a script like the one below - this this script essentially just `source`-s the defined `.env` file after exporting certain binary-specific variables, and then runs the binary. You can find the `.env` files [here](https://github.com/nymtech/nym/tree/master/envs). All CLI flags are configurable as environmental variables and vice versa, so take the following scripts / setups as guides that you can change however best suits your setup. You can see all definitions [here](https://github.com/nymtech/nym/blob/develop/nym-node-status-api/nym-node-status-api/src/cli/mod.rs#L14). ```bash #!/bin/bash set -e export ENVIRONMENT=${ENVIRONMENT:-"mainnet"} # see nym/envs/ for all possible environments export NYM_API_CLIENT_TIMEOUT=60 export NODE_STATUS_API_TESTRUN_REFRESH_INTERVAL=120 export IPINFO_API_TOKEN= monorepo_root= set -a source "${monorepo_root}/envs/${ENVIRONMENT}.env" echo ${monorepo_root}/envs/${ENVIRONMENT}.env set +a export RUST_LOG=${RUST_LOG:-debug} # debug is useful to check everything is working initially, but quite verbose echo "Verifying environment variables were properly sourced:" echo "RUST_LOG=${RUST_LOG}" echo "BECH32_PREFIX=${BECH32_PREFIX}" echo "NETWORK_NAME=${NETWORK_NAME}" nym-node-status-api -- --ipinfo-api-token $IPINFO_API_TOKEN ``` ### Functionality Without Gateway Probe Data will be restricted to information that doesn't involve Probe results; `routing` and `config` scores will be `0` and `last_probe` results `null`, as you can see in this snipped output of the `gateways` endpoint: ```shell { "gateway_identity_key": "23A7CSaBSA2L67PWuFTPXUnYrCdyVcB7ATYsjUsfdftb", "bonded": true, "performance": 99, "self_described": { "authenticator": { "address": "6Gdtw13Fa46AvkqkHELZZCMKWASDodoJeK9APRNpjjdj.7ji8DDkpjA2AdgwK7wbZm8yi4xZGogGJeypBQt4hAw3P@23A7CSaBSA2L67PWuFTPXUnYrCdyVcB7ATYsjUsfdftb" }, "auxiliary_details": { "accepted_operator_terms_and_conditions": true, "announce_ports": { "mix_port": null, "verloc_port": null }, "location": null }, "build_information": { "binary_name": "nym-node", "build_timestamp": "2025-02-13T11:49:34.670488195Z", "build_version": "1.5.0", "cargo_profile": "release", "cargo_triple": "x86_64-unknown-linux-gnu", "commit_branch": "HEAD", "commit_sha": "a3e19b4563843055b305ea9a397eb1ad84b5c378", "commit_timestamp": "2025-02-10T18:14:47.000000000+01:00", "rustc_channel": "stable", "rustc_version": "1.84.1" }, "declared_role": { "entry": true, "exit_ipr": true, "exit_nr": true, "mixnode": false }, "host_information": { "hostname": "bwng1.bwnym.xyz", "ip_address": [ "95.164.2.86" ], "keys": { "ed25519": "23A7CSaBSA2L67PWuFTPXUnYrCdyVcB7ATYsjUsfdftb", "x25519": "H6pFjqtdSVxkxEQ3wFnuSoobDAUqHx1bYMVJzPZdRByn", "x25519_noise": null } }, "ip_packet_router": { "address": "7ms2D2uYiTuhX6MKeVL5rz5usgehEoxAAovwYm9nJyBF.3siMjk3wTU7ykaXLNi9c7LpX8yonYKPCA4BQoMwhsfTV@23A7CSaBSA2L67PWuFTPXUnYrCdyVcB7ATYsjUsfdftb" }, "last_polled": "2025-03-03 09:48:03.635274187 +00:00:00", "mixnet_websockets": { "ws_port": 9000, "wss_port": 9001 }, "network_requester": { "address": "HuNL1pFprNSKW6jdqppibXP5KNKCNJxDh7ivpYcoULN9.C62NahRTUf6kqpNtDVHXoVriQr6yyaU5LtxdgpbsGrtA@23A7CSaBSA2L67PWuFTPXUnYrCdyVcB7ATYsjUsfdftb", "uses_exit_policy": true }, "wireguard": { "port": 51822, "public_key": "6o8x9GitFjcrkjrJnivWaQCPnxXykQPYLneNr2FEB8Vq" } }, "explorer_pretty_bond": { "identity_key": "23A7CSaBSA2L67PWuFTPXUnYrCdyVcB7ATYsjUsfdftb", "location": { "latitude": 52.5083, "longitude": 5.475, "two_letter_iso_country_code": "NL" }, "owner": "n1cp5gq0apat6c7qmenqp5zjprn2vwvc7jl29j8r", "pledge_amount": { "amount": "100000000", "denom": "unym" } }, "description": { "moniker": "bwn_g1", "website": "https://bwnym.xyz", "security_contact": "bwnym@proton.me", "details": "This gateway is part of the NYM project, which is dedicated to create outstanding privacy software that is legally compliant without sacrificing integrity or having any backdoors." }, "last_probe_result": null, "last_probe_log": null, "last_testrun_utc": null, "last_updated_utc": "2025-03-03T10:45:48+00:00", "routing_score": 0.0, "config_score": 0 }, ``` If you have already run the API before, make sure to add the following to your script `--database-url "sqlite://node-status-api.sqlite?mode=rwc` so it will continue using the same DB. ### Functionality with Gateway Probe If you want to enable Gateway node probes and have the NS API store that data, you need to periodically run the `nym-node-status-agent`, authenticated with your `nym-node-status-api` instance. Authentication is to make sure that only the `-agent` you are operating (or others you trust) are submitting data to your API instance. #### Compile Gateway Probe The `nym-node-status-agent` is a thin wrapper around the Gateway Probe binary which lives in the [Nym monorepo](https://github.com/nymtech/nym/tree/develop/nym-gateway-probe). Compile the probe by following the readme instructions there. You will point the `-agent` at this binary when doing Probe testruns. #### Generate Keypair ```shell nym-node-status-agent generate-keypair --path / # e.g. # nym-node-status-agent generate-keypair --path ~/.ssh/ns-agent-key ``` You will then want to export the generated `public-key` so its accessible to the `nym-node-status-api` however you are setting your environmental variables, as `NODE_STATUS_API_AGENT_KEY_LIST`: ```bash export NODE_STATUS_API_AGENT_KEY_LIST= # e.g. "H4z8kx5Kkf5JNQHfxaE1MwRndjDCD1C7HsVhHTFfBZ4J" ``` In this situation, you are probably only using one key. However, it is possible to set multiple keys as a comma seperated list, in case you wish to whitelist multiple `-agent`s to be able to submit to a single `-api` instance. #### Run the Node Status Agent ```shell nym-node-status-agent run-probe --server-address http://127.0.0.1 --server-port 8000 --ns-api-auth-key "" --probe-path nym-gateway-probe ``` You will see a lot of output like so: ```shell listen_port=48586 public_key=3f95caf771b8a63b9bdae6c186f7aba2eae93483f1c82c0243b5e00c85b4ec26 preshared_key=0000000000000000000000000000000000000000000000000000000000000000 protocol_version=1 endpoint=185.186.78.251:51822 last_handshake_time_sec=0 last_handshake_time_nsec=0 tx_bytes=0 rx_bytes=0 persistent_keepalive_interval=0 allowed_ip=0.0.0.0/0 2025/03/03 18:58:28 Pinging nymtech.net seq=0 2025/03/03 18:58:29 Ping latency: 44.503483ms 2025/03/03 18:58:29 Pinging nymtech.net seq=1 2025/03/03 18:58:29 Ping latency: 42.852414ms 2025/03/03 18:58:29 Pinging nymtech.net seq=2 2025/03/03 18:58:29 Ping latency: 43.627256ms 2025/03/03 18:58:29 Pinging nymtech.net seq=3 2025/03/03 18:58:29 Ping latency: 43.638839ms 2025/03/03 18:58:29 Pinging nymtech.net seq=4 2025/03/03 18:58:29 Ping latency: 43.345357ms 2025/03/03 18:58:29 Pinging 1.1.1.1 seq=0 2025/03/03 18:58:29 Ping latency: 46.327233ms 2025/03/03 18:58:34 Pinging 1.1.1.1 seq=1 2025/03/03 18:58:34 Ping latency: 46.273726ms 2025/03/03 18:58:39 Pinging 1.1.1.1 seq=2 2025/03/03 18:58:39 Ping latency: 46.542774ms 2025/03/03 18:58:44 Pinging 1.1.1.1 seq=3 2025/03/03 18:58:44 Ping latency: 45.663545ms 2025/03/03 18:58:49 Pinging 1.1.1.1 seq=4 2025/03/03 18:58:49 Ping latency: 43.803063ms 2025/03/03 18:58:56 Downloaded file content length: 1.00 MB 2025/03/03 18:58:56 Download duration: 1.308072386s 2025/03/03 18:58:56 private_key=1083749e43f4f8fb008f3f7deef9107ef86a68969670ddbb9f07bf85f94fb564 listen_port=39129 public_key=3f95caf771b8a63b9bdae6c186f7aba2eae93483f1c82c0243b5e00c85b4ec26 preshared_key=0000000000000000000000000000000000000000000000000000000000000000 protocol_version=1 endpoint=185.186.78.251:51822 last_handshake_time_sec=0 last_handshake_time_nsec=0 tx_bytes=0 rx_bytes=0 persistent_keepalive_interval=0 allowed_ip=::/0 2025/03/03 18:58:56 Pinging ipv6.google.com seq=0 2025/03/03 18:58:56 Ping latency: 42.839528ms 2025/03/03 18:58:56 Pinging ipv6.google.com seq=1 2025/03/03 18:58:56 Ping latency: 54.844651ms 2025/03/03 18:58:56 Pinging ipv6.google.com seq=2 2025/03/03 18:58:56 Ping latency: 51.23104ms 2025/03/03 18:58:56 Pinging ipv6.google.com seq=3 2025/03/03 18:58:56 Ping latency: 43.320409ms 2025/03/03 18:58:56 Pinging ipv6.google.com seq=4 2025/03/03 18:58:56 Ping latency: 63.517358ms 2025/03/03 18:58:56 Pinging 2001:4860:4860::8888 seq=0 2025/03/03 18:58:56 Ping latency: 54.682534ms 2025/03/03 18:59:01 Pinging 2001:4860:4860::8888 seq=1 2025/03/03 18:59:01 Ping latency: 55.56235ms 2025/03/03 18:59:06 Pinging 2001:4860:4860::8888 seq=2 2025/03/03 18:59:06 Ping latency: 55.970418ms 2025/03/03 18:59:11 Pinging 2001:4860:4860::8888 seq=3 2025/03/03 18:59:14 Failed to send ping: i/o timeout 2025/03/03 18:59:19 Pinging 2001:4860:4860::8888 seq=4 2025/03/03 18:59:22 Failed to send ping: i/o timeout 2025/03/03 18:59:27 Pinging 2606:4700:4700::1111 seq=0 2025/03/03 18:59:27 Ping latency: 45.072616ms 2025/03/03 18:59:32 Pinging 2606:4700:4700::1111 seq=1 2025/03/03 18:59:32 Ping latency: 44.357306ms 2025/03/03 18:59:37 Pinging 2606:4700:4700::1111 seq=2 2025/03/03 18:59:37 Ping latency: 44.013562ms 2025/03/03 18:59:42 Pinging 2606:4700:4700::1111 seq=3 2025/03/03 18:59:42 Ping latency: 46.94342ms 2025/03/03 18:59:47 Pinging 2606:4700:4700::1111 seq=4 2025/03/03 18:59:48 Ping latency: 43.372288ms 2025/03/03 18:59:53 Pinging 2620:fe::fe seq=0 2025/03/03 18:59:53 Ping latency: 42.164952ms 2025/03/03 18:59:58 Pinging 2620:fe::fe seq=1 2025/03/03 18:59:58 Ping latency: 42.295812ms 2025/03/03 19:00:03 Pinging 2620:fe::fe seq=2 2025/03/03 19:00:03 Ping latency: 43.117534ms 2025/03/03 19:00:08 Pinging 2620:fe::fe seq=3 2025/03/03 19:00:08 Ping latency: 44.26068ms 2025/03/03 19:00:13 Pinging 2620:fe::fe seq=4 2025/03/03 19:00:13 Ping latency: 45.29956ms 2025/03/03 19:00:21 Downloaded file content length: 10.00 MB 2025/03/03 19:00:21 Download duration: 3.39529252s ``` Whilst you can run the `-agent` directly, it might be easier to run multiple instances in parallel with a script like so: ```bash #!/bin/bash set -eu export ENVIRONMENT=${ENVIRONMENT:-"mainnet"} probe_git_ref="nym-vpn-core-v1.4.0" # check for the most recent release monorepo_root= set -a source "${monorepo_root}/envs/${ENVIRONMENT}.env" set +a export RUST_LOG="info" export NODE_STATUS_AGENT_SERVER_ADDRESS="http://127.0.0.1" export NODE_STATUS_AGENT_SERVER_PORT="8000" export NODE_STATUS_AGENT_AUTH_KEY= export NODE_STATUS_AGENT_PROBE_MNEMONIC= export NODE_STATUS_AGENT_PROBE_EXTRA_ARGS="netstack-download-timeout-sec=30,netstack-num-ping=2,netstack-send-timeout-sec=1,netstack-recv-timeout-sec=1" workers=${1:-1} echo "Running $workers workers in parallel" function swarm() { local workers=$1 for ((i = 1; i <= workers; i++)); do ${monorepo_root}/target/release/nym-node-status-agent run-probe --probe-path ${monorepo_root}/target/release/nym-gateway-probe & done wait echo "All agents completed" } swarm $workers ``` And run specifying the number of workers with `./.sh `. When running the probe, use logging level `RUST_LOG=info`. The Node Status API relies on that granularity for parsing probe results, and the logs grow incessantly if a lower level (e.g. `DEBUG`) is used. ### Ports By default the API listens on `8000`, so you will need to configure this post to be reachable on your remote server. You can modify this with the `--http_port` flag.