Lagrix

15. Node Operator Guide: Registering a Super-node Place and the Step-by-Step Integration Process (Deployment Flow)

5 min read
15. Node Operator Guide: Registering a Super-node Place and the Step-by-Step Integration Process (Deployment Flow)

Activating a Super-Node in the Lagrix network requires strict synchronization between preparing the physical/virtual infrastructure, generating the cryptographic P2P identity keys (NodeID) and registering the place on-chain in the SuperNodeRegistry.sol smart contract.

Below is the full step-by-step algorithm for putting a node into operation — from a clean server to inclusion in the Kademlia DHT routing table.

Before stage 3, the operator must hold a place (document 05, section 5.6). Places go by random choice among owners of provider agents whose paid work over 12 months lies in the window from 0.75 to 1.25 of the network median. The chosen applicant receives an invitation and has 48 hours to prepare the server (stages 1 and 2), start it, catch up the announcements of the kinds it will hold from their other holders (document 17, section 17.12) and submit it for the check by agents in turn. Once the server passes, stages 3–5 make it an active super-node; if it is not ready in time or fails, the invitation passes to the next applicant.

15.1 End-to-End Launch Process (Deployment Flow Pipeline)

Activating a Super-Node consists of five sequential stages:

[ Stage 1: Server preparation ] ──► [ Stage 2: Node Key generation ]
                                              │
                                              ▼
[ Stage 4: Node configuration ] ◄── [ Stage 3: Place registration ]
  (node.toml)                          in SuperNodeRegistry.sol
          │
          ▼
[ Stage 5: Node launch and passing ] ──► [ Status: ACTIVE SUPER-NODE ]
  the P2P Handshake in the Kademlia DHT

15.2 Step 1: Preparing the Operating System and Dependencies

On a dedicated server (Ubuntu 24.04 LTS / Debian 12), basic dependencies, the Docker container runtime and the lagrix CLI utility are installed.

# Update system and install base dependencies
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y curl git build-essential ufw jq fail2ban

# Install Docker Engine & Docker Compose Plugin
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

# Install CLI tool for Lagrix Node Operators from the repository's releases (no Lagrix server is involved)
curl -fsSL https://github.com/lagrix-dev/lagrix-supernode/releases/latest/download/install.sh | bash
source ~/.bashrc

# Verify installation
lagrix --version

15.3 Step 2: Cryptographic Initialization and Computing the Node ID

The node generates a secure P2P session key (secp256k1). The NodeID identifier is deterministically bound to the EVM address of the node's wallet, from which the place will be registered.

# Generate a new isolated P2P node identity key
lagrix identity create --keyfile /etc/lagrix/node_key.json

# Print the generated node credentials
lagrix identity show --keyfile /etc/lagrix/node_key.json

Example console output:

===================================================================
Lagrix Node Identity Generated
===================================================================
Node Public Address (EVM) : 0x71cB49E820f92b76a08f51A0fB221B4561a3b49E
Computed P2P Node ID       : 0x892a0149f82d1c238b7122a019e1f2a34bc1a82e9123812a0f819231f8291a82
Place                      : assigned by invitation (document 05, 5.6)
Status                     : NOT_REGISTERED (Pending On-Chain Registration)
===================================================================

15.4 Step 3: Registering the Place in SuperNodeRegistry.sol

From the node's wallet shown in the output (or through a multisig wallet / Hardware Wallet), the operator sends one registration transaction on the L2 network (Arbitrum / Base). The operator pays the gas of this transaction itself (document 08). The registration also records the address of the super-node's Nostr relay: nodes publish their announcements there and the other holders of its kinds copy from it (document 17, section 17.12). Only the same wallet can change the address later, with setRelay.

Registration CLI script:

# Bind the NodeID to the place assigned by invitation
lagrix supernode register   --registry-address 0xSuperNodeRegistryContractAddress   --node-id 0x892a0149f82d1c238b7122a019e1f2a34bc1a82e9123812a0f819231f8291a82   --relay wss://relay.example.org   --private-key $OPERATOR_PRIVATE_KEY   --rpc-url https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY

Solidity mechanics under the hood of SuperNodeRegistry.sol:

The smart contract checks that the wallet holds an assigned place and carries no «proven violation» mark, and moves the address status to ACTIVE:

function registerSuperNode(bytes32 nodeId, string calldata relay) external nonReentrant {
    require(placeTaken[msg.sender], "SuperNodeRegistry: no place assigned");                 // doc 05, 5.6
    require(!provenViolation[msg.sender], "SuperNodeRegistry: proven violation");            // doc 05, 5.4
    require(!superNodes[msg.sender].active, "SuperNodeRegistry: Already registered");

    // Write node parameters to the blockchain
    superNodes[msg.sender] = SuperNode({
        includedAt: uint40(block.timestamp),
        lastSeen: uint40(block.timestamp),
        active: true,
        pubKeyAddress: msg.sender,
        relay: relay                                                                       // doc 17, 17.12
    });

    nodeIdToAddress[nodeId] = msg.sender;
    emit SuperNodeRegistered(msg.sender, nodeId);
}

function setRelay(string calldata relay) external {
    require(superNodes[msg.sender].active, "SuperNodeRegistry: no active place");
    superNodes[msg.sender].relay = relay;
    emit RelayChanged(msg.sender, relay);
}

15.5 Step 4: Configuring node.toml

The operator creates the node's working configuration file /etc/lagrix/node.toml:

[node]
tier = 2
node_id = "0x892a0149f82d1c238b7122a019e1f2a34bc1a82e9123812a0f819231f8291a82"
keyfile_path = "/etc/lagrix/node_key.json"
data_dir = "/var/lib/lagrix/data"

[network]
public_ip = "203.0.113.195" # Static IPv4 address of the server
p2p_port = 4001             # Kademlia UDP
mtls_port = 443             # Envoy Data Plane TCP
stun_turn_port = 3478       # NAT Traversal

[blockchain]
chain_id = 42161            # Arbitrum One
rpc_url = "https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY"
registry_contract = "0xSuperNodeRegistryContractAddress"
escrow_contract = "0xA2AEscrowContractAddress"

[nostr]
relay_url = "wss://relay.example.org"   # recorded with the place (document 17, section 17.12)

[relay]
enable_turn_relay = true
max_bandwidth_mbps = 1000

[metrics]
enabled = true
prometheus_port = 9090

15.6 Step 5: Starting the Service and the First Handshake (P2P Handshake)

The node starts as a system service, verifies its place on-chain and sends PING messages to the nearest bootstrap nodes of the Kademlia DHT network.

# Start the node via CLI
lagrix service start --config /etc/lagrix/node.toml

# Check the network integration status
lagrix status

Example of successful output:

● lagrix-node.service - Lagrix Super-Relay Daemon
     Loaded: loaded (/etc/systemd/system/lagrix-node.service; enabled)
     Active: active (running) since Fri 2026-10-09 18:01:00 WEST; 12s ago

[INFO] On-Chain Place Verified: place registered (Tx: 0x3f1a...b92)
[INFO] P2P Transport initialized on 203.0.113.195:4001 (UDP)
[INFO] Envoy mTLS Sidecar started on 203.0.113.195:443 (TCP)
[INFO] Connecting to Bootstrap Nodes...
[INFO] Handshake successful with 12 Core Relays. Joined Kademlia Bucket #256.
[INFO] Nostr relay wss://relay.example.org: subscribed to the other holders of its kinds of service.
[SUCCESS] Node is ACTIVE and routing A2A traffic.

15.7 Operator API, version 1 (prototype)

A super-node runs on its operator's machine — a dedicated server, or a powerful home computer that meets the profile of document 14, section 14.2, and can later move to a dedicated server. The operator's node — the node whose wallet applied for the place — needs to see what only that machine knows: whether it meets the profile, what the checks found, what it was paid. The operator API is a small interface the super-node's machine gives its own operator for this. It is not a network rule: the network never calls it, and another implementation may offer a different one. Version 1 is a prototype; its fields may change.

When it is used. An application needs no server and no spending (document 05, section 5.6): the server is set up from the installation package only after the invitation, within the 48 hours. Then the operator gives its node the machine's address and the operator key, the node reads the data, and the operator runs the test before the check by agents of the network.

Access. At its first start the super-node creates an operator key and shows it once. The node sends it with every request as Authorization: Bearer <operator key>; a request without it or with another one is refused with 401. On a remote server the API is served over TLS. Version 2 replaces the key with a signature of the node wallet.

Paths (JSON; GET unless stated):

PathWhat it returns
/operator/v1/statusversion, the software and its version, startedAt, uptimeSeconds, the place as this machine sees it (none, invited, active, leaving) and the wallet the place is bound to
/operator/v1/hardwaremeasured on this machine: cpus, cpuModel, aes (AES-NI: true, false or null when not measured), ramGb, diskTotalGb, diskFreeGb, nvme, bandwidthMbps, publicIPv4, ipv6 (null when not measured), measuredAt, and profile — the values of section 14.2 they are compared with
/operator/v1/noticeswarnings — capacity warnings (changelog entry 45) with at, text, deadline; checks — results of the checks by agents per period: period, passed, reason
/operator/v1/payoutspayouts — at, period, kind (pool, search, delivery, official-vote, violation-reward), amount in USDC and tx, the transaction that paid it
/operator/v1/declaration (GET, PUT)the declaration of document 18, section 18.4: country (ISO 3166-1), coverage, regional, lists; PUT replaces it, and the super-node publishes it as the information document (NIP-11) of its relay

What the API does not carry. What the contracts record — the place, a proven violation mark, the claimable share of the fee pool — the node reads from the contracts itself. The API does not repeat it, so each fact has one source.

The test. The operator's node reads /operator/v1/hardware, compares each value with profile and shows what falls short. It is the operator's own check before the check by agents of the network and decides nothing in the network. Bandwidth and public addresses are measured by the agents' check; the machine reports them only when it has measured them itself.

GET /operator/v1/hardware
Authorization: Bearer 6f1c…

200 {"version":1,"cpus":8,"cpuModel":"AMD EPYC 7543","aes":true,"ramGb":31.3,"diskTotalGb":938.2,"diskFreeGb":812.4,"nvme":true,
     "bandwidthMbps":null,"publicIPv4":null,"ipv6":null,"measuredAt":"2026-10-18T19:02:11Z","profile":{"cpus":8,"ramGb":16,"diskGb":500}}

A prototype — prototype/operator-api.mjs in the lagrix-supernode repository — answers these paths on any machine with Node.js 22 and measures the machine it runs on.