> For the complete documentation index, see [llms.txt](https://skyneticlabs.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://skyneticlabs.gitbook.io/docs/services/testnet-networks/monad/installation.md).

# Installation

### Scope & Assumptions

This guide covers:

* System preparation
* Full node installation and synchronization
* Validator key management
* Validator registration via staking CLI

#### You **must already have**:

* A synced Monad full node (execution + bft + rpc)
* Root access to a Linux server (Ubuntu 22.04 / 24.04 recommended)
* A funded EVM address for staking

***

### Hardware Requirements (Production)

| Component        | Minimum          | Recommended         |
| ---------------- | ---------------- | ------------------- |
| CPU              | 16 cores         | 32+ cores           |
| RAM              | 64 GB            | 128 GB              |
| NVMe (Execution) | 1 TB             | 2 TB+               |
| NVMe (TrieDB)    | Dedicated device | Dedicated high‑IOPS |
| Network          | 1 Gbps           | 10 Gbps             |

⚠️ TrieDB **must** be placed on a dedicated NVMe device.

***

### System Preparation

Run all commands as **root** unless stated otherwise.

#### Update system

```bash
apt update && apt upgrade -y
```

Reboot if the kernel was updated.

#### Install base dependencies

```bash
apt install -y curl nvme-cli aria2 jq ufw
```

***

### Install Monad Packages

#### Configure APT repository

```bash
cat <<EOF > /etc/apt/sources.list.d/category-labs.sources
Types: deb
URIs: https://pkg.category.xyz/
Suites: noble
Components: main
Signed-By: /etc/apt/keyrings/category-labs.gpg
EOF

curl -fsSL https://pkg.category.xyz/keys/public-key.asc | \
  gpg --dearmor --yes -o /etc/apt/keyrings/category-labs.gpg
```

#### Install Monad

```bash
apt update
apt install -y monad=0.12.7
apt-mark hold monad
```

***

### Create Monad User & Directories

```bash
useradd -m -s /bin/bash monad

mkdir -p /home/monad/monad-bft/config/{forkpoint,validators} \
         /home/monad/monad-bft/ledger
```

***

### TrieDB NVMe Setup

#### Identify NVMe device

```bash
nvme list
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,MODEL
```

⚠️ Ensure the device has **no mounted filesystem**.

#### Partition device

```bash
TRIEDB_DRIVE=/dev/nvme1n1   # CHANGE THIS

parted $TRIEDB_DRIVE mklabel gpt
parted $TRIEDB_DRIVE mkpart triedb 0% 100%
```

#### Create stable udev symlink

```bash
PARTUUID=$(lsblk -o PARTUUID $TRIEDB_DRIVE | tail -n 1)

echo "ENV{ID_PART_ENTRY_UUID}==\"$PARTUUID\", MODE=\"0666\", SYMLINK+=\"triedb\"" \
  > /etc/udev/rules.d/99-triedb.rules

udevadm trigger
udevadm control --reload
udevadm settle
ls -l /dev/triedb
```

#### Verify 512‑byte LBA

```bash
nvme id-ns -H $TRIEDB_DRIVE | grep 'LBA Format' | grep 'in use'
```

Expected:

```
Data Size: 512 bytes (in use)
```

If not:

```bash
nvme format --lbaf=0 $TRIEDB_DRIVE
```

***

### Initialize TrieDB (MPT)

```bash
systemctl start monad-mpt
journalctl -u monad-mpt -n 20 -o cat
```

Expected:

```
monad-mpt.service: Deactivated successfully.
```

***

### Firewall & Network Hardening

```bash
ufw allow ssh
ufw allow 8000
ufw enable
ufw status
```

Optional UDP anti‑spam filter:

```bash
iptables -I INPUT -p udp --dport 8000 -m length --length 0:1400 -j DROP
```

Persist using `iptables-persistent` if required.

***

### Telemetry (OTEL Collector)

```bash
OTEL_VERSION=0.139.0
curl -fsSL https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${OTEL_VERSION}/otelcol_${OTEL_VERSION}_linux_amd64.deb \
  -o /tmp/otelcol.deb

dpkg -i /tmp/otelcol.deb

cp /opt/monad/scripts/otel-config.yaml /etc/otelcol/config.yaml
systemctl restart otelcol
```

Metrics endpoint:

```
http://<NODE_IP>:8889/metrics
```

***

### Download Network Configuration

```bash
MF_BUCKET=https://bucket.monadinfra.com

curl -o /home/monad/.env \
  $MF_BUCKET/config/testnet/latest/.env.example

curl -o /home/monad/monad-bft/config/node.toml \
  $MF_BUCKET/config/testnet/latest/node.toml
```

***

### Validator Key Management

#### Generate keystore password

```bash
sed -i "s|^KEYSTORE_PASSWORD=$|KEYSTORE_PASSWORD='$(openssl rand -base64 32)'|" /home/monad/.env
source /home/monad/.env
```

Backup password securely:

```bash
mkdir -p /opt/monad/backup
echo "$KEYSTORE_PASSWORD" > /opt/monad/backup/keystore-password-backup
```

#### Generate validator keys

```bash
monad-keystore create --key-type secp \
  --keystore-path /home/monad/monad-bft/config/id-secp \
  --password "$KEYSTORE_PASSWORD"

monad-keystore create --key-type bls \
  --keystore-path /home/monad/monad-bft/config/id-bls \
  --password "$KEYSTORE_PASSWORD"
```

⚠️ Store backups **off‑server**.

***

### Snapshot Restore (Fast Sync)

```bash
systemctl stop monad-bft monad-execution monad-rpc
bash /opt/monad/scripts/reset-workspace.sh

curl -sSL $MF_BUCKET/scripts/testnet/restore-from-snapshot.sh | bash
```

***

### Validator Node Configuration

Edit:

```
/home/monad/monad-bft/config/node.toml
```

Mandatory:

```toml
beneficiary = "0x<VALIDATOR_REWARD_ADDRESS>"
node_name   = "validator_<YOUR_NAME>"
```

Reload config **without restart**:

```bash
monad-debug-node \
  --control-panel-ipc-path /home/monad/monad-bft/controlpanel.sock \
  reload-config
```

***

### Start Monad Services

```bash
chown -R monad:monad /home/monad
systemctl enable monad-bft monad-execution monad-rpc
systemctl start  monad-bft monad-execution monad-rpc
```

***

### Validator Eligibility Requirements

| Requirement         | Value              |
| ------------------- | ------------------ |
| Minimum self‑stake  | 100,000 MON        |
| Minimum total stake | 10,000,000 MON     |
| Active set size     | Top 200 validators |

Validator becomes active **next epoch** once all conditions are met.

***

### Install Staking CLI

```bash
git clone https://github.com/monad-developers/staking-sdk-cli.git
cd staking-sdk-cli

python -m venv cli-venv
source cli-venv/bin/activate
pip install .
```

Create config:

```bash
cp staking-cli/config.toml.example config.toml
```

***

### Extract Validator Keys (Required)

```bash
source /home/monad/.env

monad-keystore recover \
  --password "$KEYSTORE_PASSWORD" \
  --keystore-path /home/monad/monad-bft/config/id-secp \
  --key-type secp

monad-keystore recover \
  --password "$KEYSTORE_PASSWORD" \
  --keystore-path /home/monad/monad-bft/config/id-bls \
  --key-type bls
```

Verify recovered public keys match your node identity.

***

### Register Validator (CLI)

```bash
python staking-cli/main.py add-validator \
  --secp-privkey "${SECP_PRIVATE_KEY}" \
  --bls-privkey  "${BLS_PRIVATE_KEY}" \
  --auth-address "${AUTH_ADDRESS}" \
  --amount 100000
```

Confirm derived public keys when prompted.

Successful tx:

```
Tx status: 1
Tx hash: 0x...
```

***

### Verification

```bash
python staking-cli/main.py query validator-set --type execution
python staking-cli/main.py query validator --validator-id <ID>
```

***

### Security Best Practices

* Use Ledger hardware wallets in production
* Never store private keys in git or plaintext
* Restrict RPC access
* Monitor validator health continuously
