# Run a devnet node

> Download Heartwood Core, configure a relay, and follow the public lab devnet on Linux.

Source: https://docs.iceroot.com/network/run-a-node/

The public lab devnet lets anyone run a Heartwood relay. It has **no value**, may be reset or shut down at any time, and is not the public testnet or mainnet. Never reuse real keys or passphrases. Running a node is not validating: [validators apply separately](https://docs.iceroot.com/network/validators/index.md#how-to-apply). A joining relay needs no private keys and receives no tokens.

This network uses the current classical signatures and reference-compatible formats. The [proposed mainnet protocol](https://docs.iceroot.com/core/protocol-design/index.md) is a separate target.

## Requirements

Use Linux x86-64 and a normal user account with `HOME` set. You need Git, curl, tar, SHA-256 tools and a C compiler to build from source, plus Rust 1.98 or later. Release binaries do not need Rust; they need glibc 2.34 or newer (Ubuntu 22.04 or later, Debian 12 or later), and on an older system you build from source. Keep a **correct clock using NTP or chrony** before starting; the node does not synchronize the host clock for you.

Use local SSD storage. The operator guide’s planning figures for a relay are 4 vCPU, 8 GB RAM, 250 GB NVMe storage and a 1 Gbit/s network port. These are planning figures, not measured minimums. Storage grows with the chain. See the repository’s [operating guide](https://github.com/iceroot-network/heartwood-core/blob/prod/docs/operating.md).

Allow outbound TCP 6002 to the seeds below. This guide binds both listeners to loopback. You can sync without opening an inbound port. To accept outside peers, follow [Accept outside peers](https://docs.iceroot.com/network/run-a-node/index.md#accept-outside-peers-optional). **Do not expose your node’s API to the internet without a proxy** that supplies access controls and rate limits. Keep `CORE_API_HOST=127.0.0.1`.

## Download

Choose one method. Install the binary at a permanent path before creating a service.

**Release binary:** the [v0.1.0-devnet.1 release](https://github.com/iceroot-network/heartwood-core/releases/tag/v0.1.0-devnet.1) carries a Linux x86-64 tarball and its `SHA256SUMS` file. Download both into one empty directory, verify the checksum, then install the `heartwood` executable. The tarball’s SHA-256 is `11c639568fc8acaab5e2195fd13d79b2e668f8e9e6f76cf9427ee11f0770b95c`; compare it with the release page too.

```sh
cd "$(mktemp -d)"
curl -fLO https://github.com/iceroot-network/heartwood-core/releases/download/v0.1.0-devnet.1/heartwood-v0.1.0-devnet.1-linux-x86_64.tar.gz
curl -fLO https://github.com/iceroot-network/heartwood-core/releases/download/v0.1.0-devnet.1/SHA256SUMS
sha256sum -c SHA256SUMS
tar -xzf heartwood-v0.1.0-devnet.1-linux-x86_64.tar.gz
mkdir -p "$HOME/.local/bin"
install -m 755 heartwood "$HOME/.local/bin/heartwood"
export PATH="$HOME/.local/bin:$PATH"
heartwood --version
```

The last command prints `heartwood 4.3.1-heartwood.0.1.0`.

**Build from source:**

```sh
git clone --branch prod https://github.com/iceroot-network/heartwood-core.git
cd heartwood-core
cargo build --release --locked -p heartwood-core
mkdir -p "$HOME/.local/bin"
install -m 755 target/release/heartwood "$HOME/.local/bin/heartwood"
export PATH="$HOME/.local/bin:$PATH"
heartwood --version
cd ..
```

For repeatable upgrades, check out the revision named by the release before building. Build only `heartwood-core` for a release; workspace builds enable test features.

## Configure the network

Download the public parameters from this docs site. Verify the archive before extracting it:

```sh
curl -fLO https://docs.iceroot.com/devnet/join-bundle.tar.gz
printf '%s  join-bundle.tar.gz\n' 'fcf9126765e91a4036d9a7be9767d092a508e2d45dd08a2e2d51858e2e0b6f5a' | sha256sum -c -
mkdir -p "$HOME/.config/iceroot-core/preview"
tar -xzf join-bundle.tar.gz -C "$HOME/.config/iceroot-core/preview"
(cd "$HOME/.config/iceroot-core/preview" && sha256sum -c SHA256SUMS)
```

Use a fresh configuration directory. The bundle supplies `app.json`, `peers.json`, `.env`, an empty `delegates.json` key list and four `crypto/*.json` files. Public genesis delegate keys are network parameters, not private signing keys. Do not generate a new network or change the crypto files.

| Parameter                  | Value                                                              |
| -------------------------- | ------------------------------------------------------------------ |
| Configuration network name | `preview`                                                          |
| Local token directory name | `iceroot`                                                          |
| Nethash                    | `d720707ae730d4ec79f83b6a3735c4eb0bf5abe8d911222845386b99843938b4` |
| Active delegates           | 53                                                                 |
| Block interval             | 8 seconds                                                          |
| Seeds, TCP 6002            | `2.31.21.34`, `2.31.23.5`, `188.245.3.39`                          |
| Local API                  | `http://127.0.0.1:6003/api/`                                       |

The reference API node is not a P2P seed. The `--token iceroot` flag names local directories; it does not give you currency or credentials. The relay reads these files from `~/.config/iceroot-core/preview`, keeps data in `~/.local/share/iceroot-core/preview`, and writes logs in `~/.local/state/iceroot-core/preview`. `heartwood env paths --token iceroot --network preview` shows all five directories.

If ports 6002 or 6003 are already occupied, choose unused local ports before starting. For example:

```sh
heartwood env set --token iceroot --network preview --key CORE_P2P_PORT --value 26002
heartwood env set --token iceroot --network preview --key CORE_API_PORT --value 26003
```

These change local listeners only; leave the seed ports at 6002. Use the chosen API port in the checks below.

## Run and check sync

```sh
heartwood relay run --token iceroot --network preview
```

Leave this terminal open. Initial sync downloads and applies the chain; the API may not answer until startup sync finishes. Logs should show responsive peers and downloaded blocks. In another terminal, check at most once every few seconds:

```sh
curl -fsS http://127.0.0.1:6003/api/blockchain
curl -fsS http://127.0.0.1:6003/api/peers
```

`data.block.height` is your local height; `/api/peers` lists discovered peers. Peer discovery can add the reference node even though it is absent from the seed list. Compare your height with the lab explorer at [scan.iceroot.com](https://scan.iceroot.com/). A few blocks of difference while requests run is normal; compare block IDs at the same height when investigating a disagreement. This network has no deterministic finality.

Press Ctrl-C to stop gracefully. If startup cannot reach the seeds, check outbound TCP 6002, the network files and the clock. If it reports another network, download the current bundle and follow the reset instructions. Check `heartwood doctor --token iceroot --network preview` and the logs before changing configuration.

The API applies a request limit to loopback too. Pace scripts below two requests per second and back off when you receive HTTP 429.

## Run with systemd

After the foreground run succeeds, stop it before starting a service. A user service needs a working systemd user manager; a minimal container may not have one.

```sh
heartwood service install --role relay --token iceroot --network preview
systemctl --user daemon-reload
systemctl --user enable --now iceroot-preview-relay.service
loginctl enable-linger "$USER"
systemctl --user status iceroot-preview-relay.service
journalctl --user -u iceroot-preview-relay.service -f
```

`loginctl enable-linger` may need administrator authorization under your host’s policy. The generated unit fixes the binary and data paths. `heartwood relay status --token iceroot --network preview` reports the service state. Use the journal for a service, and `heartwood relay log --token iceroot --network preview` for a relay started with the built-in supervisor.

## Accept outside peers (optional)

By default your relay only connects outward and listens on loopback, so no other node can connect to it. You can also accept inbound connections, which helps other nodes find the network. This shows your server’s address to the network, and peer traffic is not encrypted, so use a server with nothing else important on it. The steps below never open the API.

1. Allow inbound TCP 6002, or the P2P port you chose, on the host firewall, on any cloud firewall and, at home, as a router port forward. Do not open the API port.

2. Make only the P2P listener public:

   ```sh
   heartwood env set --token iceroot --network preview --key CORE_P2P_HOST --value 0.0.0.0
   ```

3. Restart the relay. Press Ctrl-C and start it again, or for a service run `systemctl --user restart iceroot-preview-relay.service`.

4. Check the listeners and the connections:

   ```sh
   ss -Htln | grep -E ':600[23]\b'
   ss -Htn state established '( sport = :6002 )'
   curl -fsS http://127.0.0.1:6003/api/peers
   ```

   The first command should show `0.0.0.0:6002` for P2P and `127.0.0.1:6003` for the API. Use your own port numbers if you changed them. Within a minute the second command lists inbound connections from the network’s nodes, and `/api/peers` shows them. On a fresh server, the three seeds and the reference node connected in about 15 seconds.

To check from another machine, probe once with `nc -vz <your-address> 6002`. After the first minute of operation, a connection that never completes its handshake, such as a plain port probe, gets its address banned from your node for 10 seconds.

Validator applicants need this: the team’s [sync proof](https://docs.iceroot.com/network/validators/index.md#sync-proof) looks for your node in the network’s peer lists.

To stop accepting outside peers, set `CORE_P2P_HOST` back to `127.0.0.1` and restart.

## Upgrade, reset and uninstall

Read the release announcement before upgrading. Stop the relay with Ctrl-C for a foreground run or `systemctl --user stop iceroot-preview-relay.service` for a service. Replace the binary at the same permanent path with a verified release or a source build, then start it again. Keep configuration and data unless the announcement requires a reset.

For a lab reset, stop the relay, save any logs you need, and remove only this instance’s data directory, `~/.local/share/iceroot-core/preview`. Replace its configuration with the new verified bundle, then start again. Old heights, block IDs and balances do not survive a reset. Never copy keys from another network into this one.

To uninstall a service:

```sh
systemctl --user disable --now iceroot-preview-relay.service
heartwood service uninstall --role relay --token iceroot --network preview
systemctl --user daemon-reload
```

After stopping the process, use `heartwood env paths --token iceroot --network preview` to identify this instance’s directories and remove them if you no longer need them. Remove `~/.local/bin/heartwood` only if no other instance uses it.

## What this guide does not cover

- **Validators.** A relay follows the chain; it does not produce blocks. Validators [apply separately](https://docs.iceroot.com/network/validators/index.md#how-to-apply), and forging instructions are not published yet.
- **The public testnet and mainnet.** This guide is for the lab devnet only. The public testnet opens later; see [Network status](https://docs.iceroot.com/network/status/index.md).
- **A network of your own.** There is no guide for creating a separate genesis or a private network.
- **Serving the API.** The guide keeps your node’s API on loopback. Do not expose it to the internet without a proxy that supplies access controls and rate limits.

[Network status →](https://docs.iceroot.com/network/status/index.md)
