> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# 全节点安装

export const networks = {
  mainnet: {
    monad_version: "0.16.2",
    mip8: {
      hardfork_timestamp: 1788359400
    }
  },
  testnet: {
    monad_version: "0.16.3",
    mip8: {
      hardfork_timestamp: 1786545000
    }
  }
};

## 组件

Monad 节点使用 `systemd` 运行以下服务:

* `monad-bft` - 共识客户端
* `monad-execution` - 执行客户端
* `monad-rpc` - RPC 服务器
* `monad-mpt` - 用于初始化 TrieDB 磁盘的一次性执行服务
* `monad-cruft` - 每小时运行一次的清理服务
* `otelcol` - 用于指标收集的 OTEL 采集器服务

这些 systemd 服务以 `monad` 服务用户身份运行。

配置与数据结构如下:

* `/home/monad/.env` - 包含用于配置 monad 服务的环境变量
* `/home/monad/monad-bft/config/node.toml` - 包含可配置的共识参数,其中最值得注意的是节点名称(通常为 `"<PROVIDER_NAME>-1"`)和一个上游验证者列表(由 secp 公钥和 DNS 标识),这些验证者被配置为将区块转发到您的全节点。
* `/home/monad/monad-bft/config/forkpoint/` - 包含 [forkpoint](/zh/monad-arch/consensus/forkpoint),即用于在启动时引导节点的共识状态快照
* `/home/monad/monad-bft/config/validators/` - 包含在[边界区块](/zh/monad-arch/consensus/staking#epochs-and-boundaries)处生成的验证者集合。新生成的文件包含当前 epoch 和即将到来的 epoch 的共识验证者集合。最新的验证者集合可在 `validators.toml` 找到。
* `/home/monad/monad-bft/ledger/` - 包含共识(BFT)区块头和区块体,包括交易
* `/dev/triedb` - TrieDB 数据库设备,包含区块链的状态

## 前置条件

在继续之前,请先参阅[硬件要求](/zh/node-ops/hardware-requirements)。

* 裸金属服务器
* Ubuntu 24.04+ 操作系统
* 通过 BIOS 设置禁用超线程(HT)或同时多线程(SMT)。这些特性会降低 Monad 节点的性能。

## 准备节点

<Info>
  以下说明假定命令以 `root` 用户身份执行。
</Info>

### 更新系统

更新系统。

```bash theme={null}
apt update
apt upgrade -y
```

若有需要请重启机器,例如当升级过程中提示 `Pending kernel upgrade!`。

安装其他依赖。

```bash theme={null}
apt install -y curl nvme-cli aria2 jq
```

### 安装 `monad` 软件包

配置 APT 仓库。

```bash theme={null}
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
```

<Tabs>
  <Tab title="主网">
    安装 `monad` 软件包。

    <CodeBlock
      language="bash"
      children={`apt update
apt install -y monad=${networks.mainnet.monad_version}
apt-mark hold monad`}
    />
  </Tab>

  <Tab title="测试网">
    安装 `monad` 软件包。

    <CodeBlock
      language="bash"
      children={`apt update
apt install -y monad=${networks.testnet.monad_version}
apt-mark hold monad`}
    />
  </Tab>
</Tabs>

### 创建 `monad` 用户

创建一个名为 `monad` 的非特权用户,带主目录并使用 Bash shell。

```bash theme={null}
useradd -m -s /bin/bash monad
```

在 `/home/monad` 下创建配置目录结构。

```bash theme={null}
mkdir -p /home/monad/monad-bft/config \
         /home/monad/monad-bft/ledger \
         /home/monad/monad-bft/config/forkpoint \
         /home/monad/monad-bft/config/validators
```

### 配置 TrieDB 设备

#### 创建设备

设置将用于 TrieDB 设备的 NVMe 驱动器(例如 `/dev/nvme1n1`),创建一个新的分区表,并创建一个覆盖整个驱动器的分区。该驱动器所在磁盘应未挂载任何文件系统,也未配置 RAID。

<Warning title="重要:仔细识别驱动器">
  **格式化错误的驱动器会摧毁您的操作系统!**
  在继续之前,请核实要使用的驱动器:

  ```bash theme={null}
  nvme list
  lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,MODEL
  ```

  查找一个**没有挂载点**的驱动器。您的操作系统驱动器会显示 `/`、`/boot` 或 swap 分区。
</Warning>

```bash theme={null}
TRIEDB_DRIVE=/dev/nvme1n1 # CHANGE THIS TO YOUR NVME DRIVE

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

创建 udev 规则以设置权限并为该分区创建符号链接。

```bash theme={null}
PARTUUID=$(lsblk -o PARTUUID $TRIEDB_DRIVE | tail -n 1)
echo "Disk PartUUID: ${PARTUUID}"

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

触发并重新加载 udev 规则,并验证 TrieDB 指向 NVMe 设备。

```bash theme={null}
udevadm trigger
udevadm control --reload
udevadm settle
ls -l /dev/triedb
```

#### 验证 LBA 配置

验证 LBA 配置,并在尚未启用时启用 512 字节 LBA。

检查 `TRIEDB_DRIVE` 上是否启用了 512 字节 LBA:

```bash theme={null}
nvme id-ns -H $TRIEDB_DRIVE | grep 'LBA Format' | grep 'in use'
```

该命令应返回以下期望输出:

```
LBA Format  0 : Metadata Size: 0   bytes - Data Size: 512 bytes - Relative Performance: 0 Best (in use)
```

<Info>
  `Data Size` 应设置为 `512 bytes` 并标记为 `(in use)`。如果**不是**这样,您需要使用以下命令将 `TRIEDB_DRIVE` 设置为使用 512 字节 LBA。

  ```bash theme={null}
  nvme format --lbaf=0 $TRIEDB_DRIVE
  ```

  验证配置已修正。

  ```bash theme={null}
  nvme id-ns -H $TRIEDB_DRIVE | grep 'LBA Format' | grep 'in use'
  ```
</Info>

#### 格式化分区

通过执行 `monad-mpt` 一次性服务来格式化 TrieDB 分区。

```
systemctl start monad-mpt
journalctl -u monad-mpt -n 14 -o cat
```

这应返回类似输出。

```
MPT database on storages:
          Capacity           Used      %  Path
           1.75 Tb      256.03 Mb  0.01%  "/dev/nvme1n1p1"
MPT database internal lists:
     Fast: 1 chunks with capacity 256.00 Mb used 0.00 bytes
     Slow: 1 chunks with capacity 256.00 Mb used 0.00 bytes
     Free: 7148 chunks with capacity 1.75 Tb used 0.00 bytes
MPT database has 1 history, earliest is 18446744073709551615 latest is 18446744073709551615.
     It has been configured to retain no more than 33554432.
     Latest proposed is (18446744073709551615, 0000000000000000000000000000000000000000000000000000000000000000).
     Latest voted is (18446744073709551615, 0000000000000000000000000000000000000000000000000000000000000000).
     Latest finalized is 18446744073709551615, latest verified is 18446744073709551615, auto expire version is 0
monad-mpt.service: Deactivated successfully.
Finished monad-mpt.service - "Service file for Monad MPT".
```

### 配置防火墙规则

配置以下防火墙规则:

* 阻止所有传入流量并允许所有传出流量(默认)
* 允许 SSH 传入连接(远程访问)
* 允许对端口 8000 的 TCP/UDP 双向流量(共识客户端 P2P 流量)

配置 UFW 防火墙:

```bash theme={null}
ufw allow ssh
ufw allow 8000
ufw allow 8001
ufw enable
ufw status
```

配置以下 iptables 规则以提高对垃圾流量的抗性:

```bash theme={null}
sudo iptables -I INPUT -p udp --dport 8000 -m length --length 0:1400 -j DROP
```

请注意,该规则在重启后会重置,因此节点运维人员应使用自己偏好的机制(例如 `iptables-persistent`)来持久化 iptables 规则。

<Tip title="硬件防火墙">
  如果使用硬件防火墙,您可能需要执行额外步骤以开放对 8000 端口的 UDP 与 TCP 流量。
</Tip>

<Note title="测试出站 TCP">
  若要验证 TCP 端口 8000 的出站连通性,可测试与远程主机的连接:

  ```
  $ nc -vz 64.31.29.190 8000
  Connection to 64.31.29.190 8000 port [tcp/*] succeeded!
  ```

  请查阅 `node.toml` 文件,以使用远程引导对等节点进行测试。
</Note>

### 配置 OTEL 采集器

monad 包支持 OTEL 采集器。通过它,您可以在 `http://0.0.0.0:8889/metrics` 查看所有相关的 Monad 特定指标。

```bash theme={null}
OTEL_VERSION="0.139.0"
OTEL_CHECKSUM="1a1576dde7d51fa7094f4963ceaff37c91ac7b9c9593ba735a3a328ec6f8acd9"
OTEL_PACKAGE="https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${OTEL_VERSION}/otelcol_${OTEL_VERSION}_linux_amd64.deb"
OTEL_DEB="/tmp/otelcol_linux_amd64.deb"

curl -fsSL "$OTEL_PACKAGE" -o "$OTEL_DEB"

if echo "${OTEL_CHECKSUM}  ${OTEL_DEB}" | sha256sum --check --quiet; then
  dpkg -i "$OTEL_DEB"
  cp /opt/monad/scripts/otel-config.yaml /etc/otelcol/config.yaml
  systemctl restart otelcol
else
  echo "Checksum verification failed — aborting install." >&2
fi
```

## 配置节点

### 获取配置文件

<Tabs>
  <Tab title="主网">
    **全节点**的配置文件:

    ```bash theme={null}
    MF_BUCKET=https://bucket.monadinfra.com
    curl -o /home/monad/.env $MF_BUCKET/config/mainnet/latest/.env.example
    curl -o /home/monad/monad-bft/config/node.toml $MF_BUCKET/config/mainnet/latest/full-node-node.toml
    ```

    **验证者**的配置文件:

    ```bash theme={null}
    MF_BUCKET=https://bucket.monadinfra.com
    curl -o /home/monad/.env $MF_BUCKET/config/mainnet/latest/.env.example
    curl -o /home/monad/monad-bft/config/node.toml $MF_BUCKET/config/mainnet/latest/node.toml
    ```
  </Tab>

  <Tab title="测试网">
    **全节点**的配置文件:

    ```bash theme={null}
    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/full-node-node.toml
    ```

    **验证者**的配置文件:

    ```bash theme={null}
    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
    ```
  </Tab>
</Tabs>

### 定义密钥库密码

为 `KEYSTORE_PASSWORD` 设置您自己独有且强壮的密码。此密码用于加密与解密您的密钥库。它必须用单引号包围(例如 `'password'`)。

假设 `/home/monad/.env` 文件中的 `KEYSTORE_PASSWORD` 尚未设置,生成一个安全的随机密码。

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

mkdir -p /opt/monad/backup/
echo "Keystore password: ${KEYSTORE_PASSWORD}" > /opt/monad/backup/keystore-password-backup
```

### 生成密钥库

使用 `monad-keystore` 二进制文件生成加密的 BLS 和 SECP 密钥。

```bash theme={null}
bash <<'EOF'
set -e

source /home/monad/.env

if [[ -z "$KEYSTORE_PASSWORD" || \
      -f /home/monad/monad-bft/config/id-secp || \
      -f /home/monad/monad-bft/config/id-bls ]]; then
  echo "Skipping: missing KEYSTORE_PASSWORD or keys already exist."
  exit 1
fi

monad-keystore create \
  --key-type secp \
  --keystore-path /home/monad/monad-bft/config/id-secp \
  --password "${KEYSTORE_PASSWORD}" > /opt/monad/backup/secp-backup

monad-keystore create \
  --key-type bls \
  --keystore-path /home/monad/monad-bft/config/id-bls \
  --password "${KEYSTORE_PASSWORD}" > /opt/monad/backup/bls-backup

grep "public key" /opt/monad/backup/secp-backup /opt/monad/backup/bls-backup \
  | tee /home/monad/pubkey-secp-bls

echo "Success: New keystores generated"

EOF
```

为方便起见,公钥会导出到 `/home/monad/pubkey-secp-bls`。

<Warning title="外部备份">
  这些文件包含您节点的私钥 — 它们定义了您的节点身份。任何能够访问它们的人都可以接管您节点的身份。

  **请务必将这些备份文件存储在节点之外的外部位置(例如密码管理器或密钥库)。在硬件故障或系统丢失时,您需要它们来恢复全节点或验证者身份:**

  * `/opt/monad/backup/secp-backup`
  * `/opt/monad/backup/bls-backup`

  对于验证者而言,这一点尤为重要:丢失密钥意味着您无法迁移验证者,并且使用新身份重新注册需要手动迁移所有委托。
</Warning>

### 更新 `node.toml`

<Note title="公共全节点配置">
  全节点可以直接从将其列入白名单的验证者接收区块提案,或通过 raptorcast 组接收。这些不同的配置在[此处](/zh/node-ops/full-node-block-delivery)进行了描述。

  以下说明适用于**公共全节点**配置,在这种模式下,全节点通过连接到参与次要 raptorcast 的可用上游验证者来加入网络。以这种模式加入是**无需许可的**。
</Note>

更新此前下载的配置(可参阅[测试网配置](https://bucket.monadinfra.com/config/testnet/latest/full-node-node.toml)和[主网配置](https://bucket.monadinfra.com/config/mainnet/latest/full-node-node.toml)):

1. 使用文本编辑器编辑 `/home/monad/monad-bft/config/node.toml`(例如 `nano /home/monad/monad-bft/config/node.toml`)。

2. `beneficiary` 字段应包含应接收区块奖励的地址。<br />
   对于**全节点**,此字段可设置为销毁地址。
   ```
   beneficiary = "0x0000000000000000000000000000000000000000"
   ```
   对于**验证者**,请使用受益人钱包地址。该地址应以 `0x` 为前缀。
   ```
   beneficiary = "0x<VALIDATOR_REWARDS_ADDRESS>"
   ```

3. 更新 `node_name` 字段以包含您的提供者名称。请注意,如果您运营多个节点,**节点名称必须唯一**。
   ```bash theme={null}
   node_name = "full_<PROVIDER>-<OPTIONAL_SUFFIX>"
   ```

4. 确保 `[fullnode_raptorcast]` 下的 `enable_client = true`。

5. 确保 `[statesync]` 下的 `expand_to_group = true`。

6. 对于公共全节点,`[blocksync_override]` 中的对等节点应保持为空。

### 节点签名记录

节点名称记录是一条经过加密签名的记录,包含节点的网络地址信息,用于 monad-bft 系统中的对等发现和网络拓扑管理。

使用已创建的密钥对,全节点需要使用 SECP 密钥签名其名称记录,才能参与对等发现。

记录中的序列号(seq)使各节点能够判定对等节点地址信息的最新版本,支持节点变更网络位置的场景。

生成节点记录签名:

```
source /home/monad/.env
monad-sign-name-record \
  --ip $(curl -s4 ifconfig.me) \
  --tcp-port 8000 \
  --udp-port 8000 \
  --authenticated-udp-port 8001 \
  --keystore-path /home/monad/monad-bft/config/id-secp \
  --password "${KEYSTORE_PASSWORD}" \
  --self-record-seq-num 1
```

运行上述命令会打印下一步所需的字段,例如:

```
self_ip = "91.203.44.216"
self_tcp_port = 8000
self_udp_port = 8000
self_record_seq_num = 1
self_name_record_sig = "5995f8dc5af4ca70e3b49ce793e7fe353d72b261c14037272958a9f0cc105fdd4890e56cb99765750ca48bab113cccbb378fc61dff8b23da4a03c07bba60034300"
```

使用上一步生成的 IP 地址、序列号和名称记录签名更新 `node.toml` 中的 `peer_discovery` 部分,示例如下。`node.toml` 仍然期望使用单个 `self_address` 字段:

* 若要构造 `self_address`,请将 `self_ip` 与 `self_tcp_port` 拼接为 `"<self_ip>:<self_tcp_port>"`
* `self_udp_port` 可以忽略

```toml theme={null}
[peer_discovery]
self_address = "91.203.44.216:8000"
self_record_seq_num = 1
self_name_record_sig = "5995f8dc5af4ca70e3b49ce793e7fe353d72b261c14037272958a9f0cc105fdd4890e56cb99765750ca48bab113cccbb378fc61dff8b23da4a03c07bba60034300"
```

### 远程配置获取(v0.12.1+)

节点可以在启动时自动从远程位置获取 `forkpoint.toml` 和 `validators.toml`。
该功能通过 `/home/monad/.env` 中以下环境变量进行配置:

<Tabs>
  <Tab title="主网">
    ```bash theme={null}
    REMOTE_VALIDATORS_URL='https://bucket.monadinfra.com/validators/mainnet/validators.toml'
    REMOTE_FORKPOINT_URL='https://bucket.monadinfra.com/forkpoint/mainnet/forkpoint.toml'
    ```
  </Tab>

  <Tab title="测试网">
    ```bash theme={null}
    REMOTE_VALIDATORS_URL='https://bucket.monadinfra.com/validators/testnet/validators.toml'
    REMOTE_FORKPOINT_URL='https://bucket.monadinfra.com/forkpoint/testnet/forkpoint.toml'
    ```
  </Tab>
</Tabs>

这些 URL 指向最新的配置文件。
当定义了这些变量后,节点会在启动时自动尝试下载最新的配置文件,从而简化节点运维,减少网络更新期间的人工干预。
Monad 基金会并不是这些配置文件的唯一提供者。您可以随意将上述远程链接替换为其他提供者的链接。

### 调用跟踪(可选)

对于用于归档或 RPC 工作流的全节点,建议启用 `--trace_calls`。这将保留调用跟踪(例如 `debug_traceTransaction`)所需的详细错误信息。如需进行此覆盖,请运行 `systemctl edit monad-execution`,并将 `--trace_calls` CLI 参数添加到 `ExecStart` 定义中(可能需要行延续符 `\`):

```sh theme={null}
systemctl edit monad-execution
```

```toml theme={null}
[Service]
Type=simple
ExecStart=
ExecStart=/usr/local/bin/monad \
    ...
    --trace_calls
    ...
```

### Monad Cruft 服务

安装 `monad` Debian 软件包会启用 `monad-cruft` 定时器,该定时器每小时运行一次以清理旧的产物(`/opt/monad/scripts/clear-old-artifacts.sh`)。这是必要的,可以防止产物(例如 `forkpoint.toml` 和账本文件)不断累积导致 inode 耗尽。

从 v0.12.2 开始,您可以通过在 `/home/monad/.env` 中设置环境变量来配置产物的保留时间。以下变量控制产物在被删除前的保留时长(所有数值以分钟为单位):

* `RETENTION_LEDGER` - 账本文件(区块头和区块体,默认:600 = 10 小时)
* `RETENTION_WAL` - WAL 文件(默认:300 = 5 小时)
* `RETENTION_FORKPOINT` - Forkpoint 文件(默认:300 = 5 小时)
* `RETENTION_VALIDATORS` - Validators 文件(默认:43200 = 30 天)

```bash theme={null}
# Example: Add retention configuration to /home/monad/.env
RETENTION_LEDGER=600
RETENTION_WAL=300
RETENTION_FORKPOINT=300
RETENTION_VALIDATORS=43200
```

若要自定义保留时间,请在 `/home/monad/.env` 中添加或修改这些变量。例如,若要将账本文件保留 20 小时:

```bash theme={null}
echo "RETENTION_LEDGER=1200" >> /home/monad/.env
```

这些设置将在 `monad-cruft` 定时器下一次每小时运行时自动生效。

## 启动节点

设置文件系统权限:

```bash theme={null}
chown -R monad:monad /home/monad/
```

启用 monad 服务,使其在服务器重启后自动启动:

```bash theme={null}
systemctl enable monad-bft monad-execution monad-rpc
```

**接下来,请运行[硬重置说明](/zh/node-ops/node-recovery/hard-reset)** 将最近的数据库快照导入到节点。

启动 monad 服务:

```bash theme={null}
systemctl start monad-bft monad-execution monad-rpc
```

**这样就完成了全节点启动流程!**

请参阅[常规运维](/zh/node-ops/general-operations)以监控节点状态。

## 保持更新

若要及时了解新版本发布:

* 加入 [Monad Node Announcements](https://t.me/MonadNodeAnnouncements) telegram 群组,或
* 加入 [Monad Developer Discord](https://discord.gg/monaddev),并关注 `#mainnet-fullnode-announcements` 频道
