Install and register an AeroNyx node

AeroNyx12 min read

Install the open-source AeroNyx node on a Linux server with the repository's quickstart command, register it with a one-time Nodeboard code, and verify network admission. Also covers relay roles, permissionless join, TEE deployment and AI-assisted installs.

This guide installs the open-source AeroNyx node software on a Linux server, registers it to your Nodeboard operator account with a one-time code, and checks that the network has admitted it. The supported path is the repository script deploy/node/aeronyx-node.sh quickstart, which is the same command Nodeboard generates for you.

Before you operate a node, read the Node Operator Policy.

Before you begin

ItemRequirement
Operating systemLinux with systemd. The installer installs packages with apt-get (Debian, Ubuntu), dnf or yum.
AccessA root shell. Every command in this guide assumes sudo -i first.
TUN device/dev/net/tun must exist for the VPN data plane.
MemoryThe installer warns below 2 GB and continues. The node is compiled from source on the server, so 4 GB or more is a safer choice.
DiskThe installer warns below 4 GB free and continues. Allow 20 GB or more for the build cache and the release backups the upgrade workflow keeps.
Inbound ports51820/UDP (VPN listener) and 8422/TCP (signed discovery and peer API). Open them in your cloud firewall; the installer does not change inbound firewall rules.
Local only127.0.0.1:8421 is the local health and management API. Do not expose it.

Why root: the repository lives in /root/open/AeroNyx, the installer writes /etc/aeronyx and /var/lib/aeronyx with mode 700, and server.toml with mode 600. Commands that read those paths fail for other users, and Git refuses to read a root-owned checkout from another account ("dubious ownership").

What quickstart does

quickstart runs four steps and stops before any host change until you approve:

  1. Prints the resolved install plan (read-only).
  2. Waits for you to type INSTALL. Pressing Enter stops safely.
  3. Runs preflight checks, installs packages and the repository-pinned Rust toolchain, writes /etc/aeronyx/server.toml if it does not exist (an existing file is kept), sets up IP forwarding and NAT, builds the node, installs the aeronyx-server systemd unit, registers the node identity with your code, starts the service, and waits up to 120 seconds for network admission.
  4. Prints status and a health --json summary.

The admission wait checks that local health reports ok, that the backend returned a fresh policy (the heartbeat round trip works), that discovery has at least one validated signed peer and has completed a gossip round, and, for public nodes, that the node is listed in the public pool.

Step 1: create a registration code

  1. Sign in to Nodeboard and open Registration Codes.
  2. Select Generate Code.
  3. Keep the code private. It expires after 15 minutes, works once, and binds the new node to the account that created it.

Nodeboard then shows a quickstart command, step-by-step preview and install commands, a status command and an AI assistant prompt. Its Install Progress column follows the installer through not_started → planning → running → completed | failed.

The backend checks the code when the installer reaches its register step, which comes after the build. A first build on a small server can take longer than 15 minutes. If registration then fails because the code expired, generate a new code and run quickstart again; the second run reuses the build cache.

Step 2: get or update the repository

aeronyx-node.sh is not a system command. It ships in the repository. This is the clone-or-update line Nodeboard uses:

bash
mkdir -p /root/open && cd /root/open
if [ -d AeroNyx/.git ]; then cd AeroNyx && git fetch origin main && git checkout main && git pull --ff-only origin main; else git clone https://github.com/AeroNyxNetwork/AeroNyx.git AeroNyx && cd AeroNyx; fi
git rev-parse HEAD

Always pass --repo-dir "$PWD" (or --repo-dir /root/open/AeroNyx) to the script. Without it, install, upgrade, health and status default to /opt/aeronyx/AeroNyx.

Step 3: run quickstart

Run quickstart without a code on the command line. When it runs in a terminal, it asks for the code with a hidden prompt, so the code is not echoed, not stored in shell history and not passed as a process argument:

bash
cd /root/open/AeroNyx
./deploy/node/aeronyx-node.sh quickstart --repo-dir "$PWD" --branch main --quick \
  --node-name "Example1" --region DE --public-vpn
  • --node-name is the name shown in Nodeboard and in the VPN node list.
  • --region is an ISO 3166-1 alpha-2 country code.
  • --public-vpn publishes the node in the public VPN pool. Omit it to keep the node private.

At Nodeboard registration code: paste the code and press Enter. Review the plan, then type INSTALL.

About the command Nodeboard generates

Nodeboard's quickstart command puts the code inline, for example AERONYX_REGISTRATION_CODE='<code>' ./deploy/node/aeronyx-node.sh quickstart --repo-dir "$PWD" --branch main --quick. That works, but the code is saved in your shell history. If you use it:

  • Check echo "$HISTCONTROL". If it contains ignorespace or ignoreboth, start the command with a space and Bash does not record it.
  • Otherwise remove the entry afterwards with history -d <number>.

The code is single-use and expires after 15 minutes, which limits the exposure, but do not paste it into tickets, screenshots or chats.

Non-interactive install

For automation, preview first, then pass the code on standard input. read -rs keeps it off the screen and out of history:

bash
cd /root/open/AeroNyx
./deploy/node/aeronyx-node.sh plan --repo-dir "$PWD" --branch main
read -rs AERONYX_CODE
printf '%s\n' "$AERONYX_CODE" | ./deploy/node/aeronyx-node.sh install \
  --repo-dir "$PWD" --branch main --quick --registration-code-stdin \
  --node-name "Example1" --region DE --public-vpn
unset AERONYX_CODE

install --quick does not ask for INSTALL. Use it only after you have reviewed the plan.

Step 4: verify the node

bash
cd /root/open/AeroNyx
systemctl is-active aeronyx-server
./deploy/node/aeronyx-node.sh status --repo-dir "$PWD"
./deploy/node/aeronyx-node.sh health --repo-dir "$PWD" --json

A healthy new node shows:

  • aeronyx-server is active, and health reports fail=0
  • the installer printed [OK] Node admission accepted with health=ok, management=fresh and discovery=ready (and public_pool=online for a public node)
  • status prints operator_status=ok and a next step
  • the final JSON line of health --json has "success":true; warnings appear under checks

In Nodeboard, the code shows completed, and the node appears under Nodes with its name, region, visibility and a fresh heartbeat. The node detail page shows a Capacity Decision of ready, watch, blocked or waiting.

For day-to-day checks, logs, upgrades and rollback, see Run and check an AeroNyx node.

Optional: join the encrypted relay

A VPN node and an encrypted relay node are separate choices. Relay participation has three parts: a reachable public peer API, the blind ChatRelay store-and-forward role, and the no-exit OnionMiddle role. Both roles are off in the default configuration.

  1. Make sure 8422/TCP is reachable from the internet.

  2. Edit /etc/aeronyx/server.toml (for example nano /etc/aeronyx/server.toml) and set these keys in the [discovery] section, using your public address:

    toml
    public_endpoint = "http://203.0.113.10:8422"
    public_discovery = true
    region = "DE"
    
  3. Validate the file:

    bash
    cd /root/open/AeroNyx
    ./target/release/aeronyx-server validate -c /etc/aeronyx/server.toml
    
  4. Enable ChatRelay without restarting. The helper backs up the config, asks you to type ENABLE CHATRELAY, validates, and restores the backup if validation fails:

    bash
    ./deploy/node/aeronyx-node.sh chat-relay --repo-dir "$PWD" --enable-chat-relay
    
  5. Enable OnionMiddle and restart in one guarded step. It asks you to type ENABLE ONIONMIDDLE and refuses to restart if the node has active sessions or cannot report a session count:

    bash
    ./deploy/node/aeronyx-node.sh onion-middle --repo-dir "$PWD" --enable-onion-middle --restart
    

    If it refuses, turn on Maintenance Mode for the node in Nodeboard Settings, wait until active sessions reach zero, and run it again. Do not add --yes: it skips the confirmation and the active-session guard.

  6. Check relay readiness:

    bash
    ./deploy/node/aeronyx-node.sh relay-probe --repo-dir "$PWD" --two-hop --json
    

Enabling a role is not the same as being used for routes. A node becomes a route candidate only after peers see it as reachable and fresh path-proof evidence exists. See Node discovery and encrypted relay.

Join without Nodeboard

join installs the node and submits its signed descriptor to a seed node for Stage-A admission, without a registration code or a Nodeboard account:

bash
cd /root/open/AeroNyx
./deploy/node/aeronyx-node.sh join --repo-dir "$PWD" \
  --seed http://SEED_PUBLIC_IP:8422 \
  --public-endpoint http://YOUR_PUBLIC_IP:8422 --json
  • --seed takes 1 to 8 public seed nodes; the request goes to the first one. --public-endpoint is your node's reachable peer API. Both must be http or https URLs with a public IP address, not a hostname.
  • It runs as root on Linux with systemd, and needs Python 3.11 or later, or python3 with the tomli package.
  • It sets six [discovery] values (enabled, advertise_self, public_discovery, gossip_enabled, public_endpoint, seed_endpoints) and leaves the rest of the file untouched.
  • If the service is already running with different settings, it stops without changing anything.
  • --commit <40-hex SHA> pins the exact source commit. --dry-run prints the planned result without changes. --check-only verifies an already joined node without sending anything.

A successful result is "admission_stage":"stage_a_candidate" with "route_authority":false and "route_ready":false. Stage-A admission means the seed accepted your descriptor. It does not make the node routeable, list it in Nodeboard or the VPN pool, or make it eligible for payment. The seed's answer travels over plain HTTP unless the seed uses HTTPS, so it is not a cryptographic receipt.

TEE deployment with Docker

The repository also contains a container deployment for confidential VMs that run dstack (Phala Cloud or self-hosted Intel TDX): deploy/node/Dockerfile, deploy/node/compose.tee.yaml, deploy/node/server.tee.toml and deploy/node/tee-entrypoint.sh.

This role is not a VPN node:

  • vpn.enabled = false: no TUN device, no DNS proxy, no MemChain. The container runs with all Linux capabilities dropped and no-new-privileges.
  • It runs the onion relay (advertise_onion_middle = true), ChatRelay and the anonymous mailbox, and exposes only 8422.
  • The node identity comes from the dstack key management service ([server_key] source = "dstack"). There is no key file.
  • Pinned seeds. server.tee.toml pins four seed nodes with discovery.pinned_seeds. A node without an operator snapshot has no other trust anchors, and each pin is reached only over identity-bound TLS. Keep or replace the pins; see Node Discovery and Encrypted Multi-Hop Relay.

To deploy:

  1. Pick a release image from ghcr.io/aeronyxnetwork/aeronyx-node. CI builds linux/amd64 images from node-v* tags and attaches a build-provenance attestation. Find the digest, for example with docker buildx imagetools inspect ghcr.io/aeronyxnetwork/aeronyx-node:<tag>.
  2. In compose.tee.yaml, replace IMAGE_DIGEST with that digest. Always pin by digest, not by tag; in a dstack VM the compose file is part of the measured deployment.
  3. Set AERONYX_PUBLIC_ENDPOINT to the https:// origin that the dstack gateway assigns to port 8422. The entrypoint refuses any other scheme.
  4. Optionally set AERONYX_REGION (default tee).
  5. For the first start only, provide AERONYX_REGISTRATION_CODE as an encrypted secret. The entrypoint pipes it to aeronyx-server register --code-stdin. After node_info.json exists in the /var/lib/aeronyx volume, the code is no longer needed.

The container does not include aeronyx-node.sh. Monitor a TEE node in Nodeboard and through its public discovery API.

Installing with an AI coding assistant

Terminal assistants such as Claude Code, Codex, OpenClaw or Hermes can run this procedure. Nodeboard offers a ready-made AI assistant prompt next to each code. These rules apply whichever assistant you use.

The human operator:

  • provides the server and approves every host change
  • types INSTALL personally after reading the plan
  • keeps the registration code private. Nodeboard's AI prompt contains the code, so pasting it shares the code with the assistant's provider. To avoid that, let the assistant update the repository and run the code-free plan, then run quickstart yourself and type the code at the hidden prompt. Hand back to the assistant for verification.

The assistant must:

  • use only deploy/node/aeronyx-node.sh from github.com/AeroNyxNetwork/AeroNyx, and pass --repo-dir
  • use only options the script documents (./deploy/node/aeronyx-node.sh help). Unknown options fail; for example, --api-base stops the installer with Unknown option.
  • show or summarise the plan before any host change and wait for approval
  • run status after install or upgrade and report operator_status, operator_title, operator_detail and operator_next_step, then health --json when more detail is needed
  • report warnings as warnings, and not declare success from a running process alone
  • prefer upgrade --no-restart unless you approve a maintenance-window restart
  • never use --force or --yes, and never restart a node with active sessions, without your explicit approval
  • never print registration codes, private keys, API secrets, client public IPs, destinations, DNS contents, packet payloads or chat plaintext

Done means:

  • the repository is on main and the commit is reported
  • quickstart or install finished with Node admission accepted
  • status reports operator_status=ok, or each warning is explained
  • health --json reports "success":true
  • Nodeboard shows the node with a fresh heartbeat and a Capacity Decision
  • Alerts / Events → Incident Closure has no unreviewed open item for the node
  • you know the node's detail page in Nodeboard

What a registered node reports

Local diagnostics (status, health, relay-probe) print aggregate values only: service state, capacity, packet counters, discovery readiness and proof outcomes.

A registered VPN node also reports each VPN session to the AeroNyx backend: session ID, the client's key (client_wallet), the tunnel's virtual IP, byte counts, timing and link quality. It does not report client public IPs, destinations, DNS contents or packet payloads. Operators can see these session records for their own nodes in Nodeboard; see the Nodeboard operator console guide. Like any VPN server, the node itself handles client traffic in the clear at the exit, so operators must follow the Node Operator Policy.

<!-- faq:start -->

Frequently asked questions

Where does aeronyx-node.sh come from?

It is a file in the AeroNyx node repository at deploy/node/aeronyx-node.sh, not a system command. Clone or update https://github.com/AeroNyxNetwork/AeroNyx into /root/open/AeroNyx and run it from there with --repo-dir "$PWD".

How do I keep the registration code out of my shell history?

Run quickstart without the code and type it at the hidden Nodeboard registration code: prompt. For scripts, read it with read -rs and pipe it to install --quick --registration-code-stdin.

Why does the script look in /opt/aeronyx/AeroNyx?

That is the script's built-in default for --repo-dir, while Nodeboard clones into /root/open/AeroNyx. Pass --repo-dir on every command so install, health, status and upgrade all use the checkout the service runs from.

What happens if my code expires during the install?

The register step fails and the installer stops before it starts the service. The code is checked after the build, so generate a new code and run quickstart again; the second run reuses the build cache.

Do I need Nodeboard to run a node?

No, join installs a node and submits it for Stage-A admission without a registration code. A joined node is not routeable, not listed in Nodeboard or the VPN pool, and not eligible for payment.

Can I run a node in a confidential VM?

Yes, the repository includes a Docker deployment for dstack confidential VMs that runs the onion relay, ChatRelay and anonymous mailbox. It does not provide VPN service and takes its identity from the dstack key management service.

<!-- faq:end -->