How to Set Up an Amadeus Protocol Node: Complete Installation Guide

Set up an Amadeus Protocol node by building a Docker image with Erlang/OTP and RocksDB, compiling the release with ./build.sh, and launching with TESTNET=true for local development or configuring systemd with AUTOUPDATE=true for production.

This guide walks you through deploying an Amadeus Protocol node, an Elixir/Erlang OTP application that powers a high-performance, UDP-based blockchain engine. The node manages networking, persistent storage, and JSON-RPC handling through supervised GenServer processes, with support for WebAssembly contracts written in AssemblyScript or Rust.

Prerequisites for Amadeus Protocol Node Setup

Before building the node, ensure your system meets these requirements:

Requirement Purpose Installation
Docker or Podman Containerized build environment sudo apt install podman or sudo apt install docker.io
Erlang OTP 26+ / Elixir 1.16+ BEAM VM runtime for the node Included in Docker image; optional local install for development
Rust toolchain (optional) Compile Rust contracts to WebAssembly curl https://sh.rustup.rs -sSf | sh
Node.js 20+ (optional) Build AssemblyScript contracts sudo apt install nodejs
High file descriptor limits Support many UDP sockets and open files Apply sysctl and limits.conf settings (see Production Deployment section)

The node runs as a single OS process inside the BEAM virtual machine, using message-passing between components for fault tolerance and low latency.

Architecture Overview

Understanding the core components helps troubleshoot issues and optimize performance:

Component File Path Function
OTP Supervision Tree ex/lib/node/node_gen.ex Creates the main supervision hierarchy managing socket, reassembly, net-guard, and RPC processes
UDP Socket Layer ex/lib/node/node_gen_socket_gen.ex, ex/lib/node/node_gen_netguard.ex Handles raw UDP packets, NAT traversal, and packet size enforcement
RocksDB Storage ex/lib/misc/rocksdb.ex Persistent key/value store for blocks, state, and contract data
STUN/NAT Helper ex/lib/misc/stun.ex Discovers public IP/port for peer-to-peer communication
RPC API ex/lib/api/rpc_api.ex Exposes JSON-RPC endpoint for browsers, wallets, and CLI tools
Contract Loader ex/lib/ex_bakeware.ex Loads WebAssembly contracts and routes RPC calls to them

All components are supervised, meaning failures in one process trigger automatic restarts without stopping the entire node.

Building the Amadeus Protocol Node

Step 1: Build the Docker Image

The build.Dockerfile provides a reproducible environment with Erlang/Elixir, RocksDB native libraries, and optional Rust tooling:


# Build the Erlang/Elixir base image with RocksDB

podman build --tag erlang_builder -f build.Dockerfile

# Compile the production release

./build.sh

The build.sh script produces a BEAM release at _build/prod/rel/amadeusd and copies the executable amadeusd to your repository root.

Step 2: Verify the Build

Check that the binary exists and is executable:

ls -la ./amadeusd
file ./amadeusd

Running a Local Testnet Node

The fastest way to set up an Amadeus Protocol node is testnet mode, which starts a single-node network with an in-process RPC server:


# Start testnet with HTTP RPC on localhost port 80

TESTNET=true WORKFOLDER=/tmp/testnet HTTP_IPV4=127.0.0.1 HTTP_PORT=80 ./amadeusd

Environment variables control the node behavior:

Variable Description Example
TESTNET=true Enable single-node testnet mode Required for local development
WORKFOLDER Data directory for blocks and state /tmp/testnet
HTTP_IPV4 IP address to bind RPC server 127.0.0.1
HTTP_PORT Port for JSON-RPC endpoint 80

Interacting with the Running Node

Once started, connect via the Elixir REPL (iex) or direct HTTP calls:

Using the REPL:

iex -S mix

# Load trainer keys (pre-funded in testnet)

iex> pk = Application.fetch_env!(:ama, :trainer_pk)
iex> sk = Application.fetch_env!(:ama, :trainer_sk)

# Transfer AMA tokens

iex> Testnet.call(sk, "Coin", "transfer", [pk, "5", "AMA"])

# Deploy a WebAssembly contract

iex> Testnet.deploy "/path/to/node/contract_samples/assemblyscript/counter.wasm"

# Call contract methods

iex> Testnet.call(sk, pk, "get", [])
iex> Testnet.call(sk, pk, "increment", ["2"])

Using curl (external clients):

curl -X POST http://127.0.0.1:80/rpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"call","params":["<sk>","Coin","balance",["<pk>"]],"id":1}'

Deploying Custom WebAssembly Contracts

The Amadeus Protocol node executes contracts compiled to WebAssembly. Two toolchains are supported:

AssemblyScript Contracts

cd contract_samples/assemblyscript

# Compile and validate

./build_and_validate.sh my_contract.ts

# Output: my_contract.wasm ready for deployment

Upload via Testnet.deploy in the REPL or through the RPC API.

Rust Contracts

Follow contract_samples/rust/README.md for project setup, then:

cargo build --release --target wasm32-unknown-unknown

Critical: Use wasm32-unknown-unknown target only. Other targets produce invalid WASM for the node runtime.

Production Deployment with Systemd

For persistent, auto-updating nodes, configure systemd with optimized kernel parameters.

System Limits Configuration

Apply UDP buffer sizes and security settings (referenced in README.md lines 49–62):

cat <<'EOF' | sudo tee /etc/sysctl.d/99-amadeusd.conf
net.core.wmem_max = 268435456
net.core.rmem_max = 268435456
net.ipv4.udp_mem = 3060432 4080578 6120864
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
EOF

sudo sysctl --system

Set file descriptor and process limits (README.md lines 65–78):

cat <<'EOF' | sudo tee /etc/security/limits.d/99-amadeusd.conf
*    hard    nofile    1048576
*    soft    nofile    1048576
*    hard    nproc     unlimited
*    soft    nproc     unlimited
*    hard    memlock   unlimited
*    soft    memlock   unlimited
EOF

Systemd Service File

Create the service unit (adapted from README.md lines 98–115):

cat <<'EOF' | sudo tee /etc/systemd/system/amadeusd.service
[Unit]
Description=AmadeusD Node
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
LimitNOFILE=1048576
KillMode=control-group
Restart=always
RestartSec=3
User=root
WorkingDirectory=/root
Environment="AUTOUPDATE=true"
ExecStart=/usr/bin/screen -UdmS amadeusd bash -c './amadeusd'

[Install]
WantedBy=multi-user.target
EOF

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable amadeusd
sudo systemctl start amadeusd

For non-root deployment, modify User and WorkingDirectory as shown in README.md lines 124–128.

Troubleshooting Common Issues

Symptom Root Cause Solution
EADDRINUSE on port 80/443 Privileged port restrictions Run sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80 (README line 27)
Browser CORS errors Cross-origin security policy Launch Chrome with --ignore-certificate-errors --disable-web-security (README line 23)
Node crashes under load Insufficient nofile/memlock limits Apply limits.conf settings from production section
"Invalid wasm" on contract upload Wrong compilation target Verify wasm32-unknown-unknown for Rust, or use provided AssemblyScript build script
STUN/NAT traversal failures Firewall blocking UDP Open UDP ports used by node_gen_socket_gen.ex and verify stun.ex can reach public STUN servers

Summary

  • Build process: Use build.Dockerfile and ./build.sh to compile the amadeusd binary with all native dependencies
  • Local development: Launch with TESTNET=true for immediate RPC access via REPL or HTTP
  • Contract support: Compile AssemblyScript with build_and_validate.sh or Rust with wasm32-unknown-unknown target
  • Production readiness: Configure systemd with AUTOUPDATE=true, apply kernel tuning for UDP buffers, and set high file descriptor limits
  • Core files: Reference ex/lib/node/node_gen.ex for supervision tree, ex/lib/api/rpc_api.ex for RPC handling, and ex/lib/misc/rocksdb.ex for storage implementation

Frequently Asked Questions

What hardware is required to run an Amadeus Protocol node?

A node runs on modest hardware: 2+ CPU cores, 4GB RAM, and SSD storage for RocksDB. The critical requirement is network capacity—the UDP-heavy architecture in node_gen_socket_gen.ex benefits from low-latency connections and sufficient kernel buffer sizes (rmem_max/wmem_max).

How does the node handle software updates?

Set AUTOUPDATE=true in the environment to enable the built-in updater. The node checks for releases and applies them automatically while maintaining state in the WORKFOLDER directory. For manual control, run without this flag and replace the amadeusd binary directly.

Can I run multiple nodes on the same machine?

Yes. Specify distinct WORKFOLDER, HTTP_PORT, and UDP port ranges for each instance. The node_gen.ex supervision tree isolates processes within each BEAM VM, though you must ensure sufficient file descriptors (nofile limits) for the combined socket count.

Is there a difference between testnet and mainnet binaries?

No. The same amadeusd binary serves both modes. Testnet behavior is activated solely by the TESTNET=true environment variable, which modifies the genesis block and consensus rules in node_gen.ex without requiring a separate build.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →