> For the complete documentation index, see [llms.txt](https://docs.bitplanet.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bitplanet.ai/node-operation/setup-configuration.md).

# Setup & Configuration

> **🔐 Security First:** Throughout this setup, remember that your validator's `priv_validator_key.json` is the most critical file. It must ONLY exist on ONE active node at a time. Running the same key on multiple nodes simultaneously will result in double signing, leading to permanent jail and slashing of your stake.

## Node Installation

### Binary Installation

```bash
# Clone the repository
git clone https://github.com/Bitplanet-L1/Bitplanet-CosmosEVM.git
cd Bitplanet-CosmosEVM

# Build and install the evmd binary
make install

# Verify installation
evmd version
```

### Docker Installation

For operators preferring containerized deployments:

```bash
# Clone the repository
git clone https://github.com/Bitplanet-L1/Bitplanet-CosmosEVM.git
cd Bitplanet-CosmosEVM

# Use docker-compose for quick setup
docker-compose up -d chain

# Check logs
docker-compose logs -f chain
```

**Docker Compose Ports:**

* Automatic port mapping for all services (26656, 26657, 1317, 9090, 8545, 8546)
* Data persisted in Docker volumes
* Use for development/testing, not recommended for production validators

**Production Docker Setup:**

```bash
# Build the Docker image locally
cd Bitplanet-CosmosEVM
docker build -t bitplanet/evmd:latest .

# Create docker volume for persistent data
docker volume create evmd-data

# Run validator node
docker run -d \
  --name evmd-validator \
  --restart unless-stopped \
  -v evmd-data:/home/evmd/.evmd \
  -v $(pwd)/config:/home/evmd/.evmd/config \
  -p 26656:26656 \
  -p 26657:26657 \
  -p 1317:1317 \
  -p 9090:9090 \
  bitplanet/evmd:latest \
  start --home /home/evmd/.evmd

# View logs
docker logs -f evmd-validator
```

**Note:** There is no official public Docker image. You must build the image locally from the repository's Dockerfile.

### System Service Setup

Create a systemd service for automatic restarts and monitoring:

```bash
# Create service file
sudo tee /etc/systemd/system/evmd.service > /dev/null <<EOF
[Unit]
Description=Bitplanet BitEVM Node
After=network-online.target

[Service]
User=$USER
ExecStart=$(which evmd) start --home $HOME/.evmd
Restart=always
RestartSec=3
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable evmd
sudo systemctl start evmd
```

## Configuration Parameters

### Initialize Node

```bash
# Initialize node with moniker and chain ID
evmd init <your-moniker> --chain-id 9001 --home $HOME/.evmd

# Set client configuration
evmd config set client chain-id 9001 --home $HOME/.evmd
evmd config set client keyring-backend file --home $HOME/.evmd
```

**⚠️ CRITICAL SECURITY CHOICE: Keyring Backend**

The keyring backend determines how your validator keys are stored:

**For Production (REQUIRED):**

* `--keyring-backend file` - Keys encrypted with password (RECOMMENDED)
* `--keyring-backend os` - Uses system keyring (macOS Keychain, Windows Credential Manager, etc.)

**For Testing/Development Only:**

* `--keyring-backend test` - **UNENCRYPTED** keys stored in plain text on disk
* **NEVER use in production** - anyone with file access can steal your keys and funds

This documentation uses `file` backend throughout all examples.

### Key Configuration Files

**Location:** `$HOME/.evmd/config/`

1. **config.toml** - Tendermint consensus and networking configuration
2. **app.toml** - Application-level settings (API, gRPC, EVM)
3. **genesis.json** - Chain genesis state
4. **node\_key.json** - P2P node identity (DO NOT share)
5. **priv\_validator\_key.json** - Validator signing key (**CRITICAL - backup securely**)

### Critical Configuration Settings

**config.toml:**

```toml
#######################################################################
###                   Main Base Config Options                      ###
#######################################################################

# Moniker (your node's public name)
moniker = "your-validator-name"

#######################################################################
###                 Advanced Configuration Options                  ###
#######################################################################

[consensus]
# Block time configuration
timeout_propose = "3s"
timeout_propose_delta = "500ms"
timeout_prevote = "1s"
timeout_prevote_delta = "500ms"
timeout_precommit = "1s"
timeout_precommit_delta = "500ms"
timeout_commit = "1000ms"  # Actual block time

[p2p]
# P2P Configuration
laddr = "tcp://0.0.0.0:26656"
persistent_peers = "<node_id>@<ip>:26656,<node_id2>@<ip2>:26656"
seeds = ""
max_num_inbound_peers = 40
max_num_outbound_peers = 10

# Connection timeout and keep-alive settings
dial_timeout = "3s"
handshake_timeout = "20s"
peer_gossip_sleep_duration = "100ms"

[mempool]
# Mempool configuration
size = 5000
cache_size = 10000

[statesync]
# State sync configuration (for fast sync)
enable = false
rpc_servers = ""
trust_height = 0
trust_hash = ""
```

**app.toml:**

```toml
#######################################################################
###                           Base Configuration                    ###
#######################################################################

# Minimum gas prices for transactions
# Production networks typically use higher values (e.g., "10000000bplcoin")
# Test networks may use lower values
minimum-gas-prices = "10000000bplcoin"

#######################################################################
###                         Telemetry Configuration                 ###
#######################################################################

[telemetry]
enabled = true
prometheus-retention-time = 600

#######################################################################
###                           API Configuration                     ###
#######################################################################

[api]
enable = true
swagger = true
address = "tcp://0.0.0.0:1317"
max-open-connections = 1000

#######################################################################
###                           gRPC Configuration                    ###
#######################################################################

[grpc]
enable = true
address = "0.0.0.0:9090"

[grpc-web]
enable = true
address = "0.0.0.0:9091"

#######################################################################
###                        JSON-RPC Configuration                   ###
#######################################################################

[json-rpc]
enable = true
address = "0.0.0.0:8545"
ws-address = "0.0.0.0:8546"
api = "eth,txpool,personal,net,debug,web3"

[json-rpc.evm-timeout]
duration = "5s"

#######################################################################
###                           EVM Configuration                     ###
#######################################################################

[evm]
# EVM tracer configuration
tracer = ""
max-tx-gas-wanted = 500000
```

## Network Joining

### Genesis Setup

**For New Networks (Genesis Validators):**

```bash
# Obtain genesis file from network coordinators
wget https://<network-url>/genesis.json -O $HOME/.evmd/config/genesis.json

# Or if provided locally
cp genesis.json $HOME/.evmd/config/genesis.json

# Validate genesis file structure
evmd genesis validate-genesis --home $HOME/.evmd

# Verify genesis hash matches expected value
sha256sum $HOME/.evmd/config/genesis.json
# Or on macOS:
# shasum -a 256 $HOME/.evmd/config/genesis.json
```

**For Existing Networks (Post-Genesis Validators):**

```bash
# Download genesis from running node
curl -s http://<rpc-endpoint>:26657/genesis | jq -r '.result.genesis' > $HOME/.evmd/config/genesis.json

# Configure persistent peers
PERSISTENT_PEERS="<node_id>@<ip>:26656,<node_id2>@<ip2>:26656"
sed -i.bak "s/^persistent_peers *=.*/persistent_peers = \"$PERSISTENT_PEERS\"/" $HOME/.evmd/config/config.toml

# Start node to sync
evmd start --home $HOME/.evmd
```

### Validator Key Management

<details>

<summary>🚨 CRITICAL SECURITY WARNING: Double Signing Prevention</summary>

**NEVER run the same validator key on multiple nodes simultaneously!** This will result in:

* **Permanent jail** - Your validator will be permanently banned from the network
* **Slashing penalty** - Significant portion of your stake will be burned (typically 5%)
* **Loss of reputation** - Permanent record of double signing violation

**Best Practices:**

* Only ONE active node should have your `priv_validator_key.json` at any time
* Before migrating validators, ALWAYS stop the old node first
* Keep secure backups but NEVER restore keys to a second node while the first is running

**If you accidentally start multiple nodes:**

1. IMMEDIATELY stop ALL nodes
2. Identify which node is properly synced
3. Delete `priv_validator_key.json` from ALL other nodes
4. Start ONLY the chosen node

</details>

**Create Validator Keys:**

> **🔐 Security Reminder:** Always use `--keyring-backend file` or `os` for production. Never use `test` backend as it stores keys unencrypted. See "Keyring Backend" security section above.

```bash
# Create new validator key
evmd keys add validator --keyring-backend file --home $HOME/.evmd

# Or recover from mnemonic
echo "your mnemonic phrase here" | evmd keys add validator --recover --keyring-backend file --home $HOME/.evmd

# Get validator address
VALIDATOR_ADDRESS=$(evmd keys show validator -a --keyring-backend file --home $HOME/.evmd)
echo "Validator address: $VALIDATOR_ADDRESS"

# Get validator consensus public key
VALIDATOR_PUBKEY=$(evmd tendermint show-validator --home $HOME/.evmd)
echo "Validator public key: $VALIDATOR_PUBKEY"
```

**Backup Critical Files:**

```bash
# Create secure backup directory
mkdir -p $HOME/evmd-backups
chmod 700 $HOME/evmd-backups

# Backup validator keys
cp $HOME/.evmd/config/priv_validator_key.json $HOME/evmd-backups/
cp $HOME/.evmd/config/node_key.json $HOME/evmd-backups/

# Backup keyring (if using file backend)
cp -r $HOME/.evmd/keyring-file/ $HOME/evmd-backups/

# Store backups offline or in secure encrypted storage
```

### Create Validator

⚠️ **CRITICAL:** Before creating a validator, ensure you understand the rule that your `priv_validator_key.json` must ONLY exist on ONE active node at a time!

**Prerequisites:**

* Node fully synced with network
* Validator account funded with sufficient tokens
* Understanding of double signing penalties

```bash
# Check sync status (catching_up should be false)
curl -s http://localhost:26657/status | jq '.result.sync_info.catching_up'

# Check account balance (need at least stake amount + fees)
evmd query bank balances $VALIDATOR_ADDRESS --node http://localhost:26657

# Create validator.json configuration
cat > $HOME/.evmd/validator.json << EOF
{
  "pubkey": $VALIDATOR_PUBKEY,
  "amount": "1000000000000000000000bplcoin",
  "moniker": "your-validator-name",
  "identity": "",
  "website": "https://yourwebsite.com",
  "security": "security@yourwebsite.com",
  "details": "Professional validator for Bitplanet network",
  "commission-rate": "0.10",
  "commission-max-rate": "0.20",
  "commission-max-change-rate": "0.01",
  "min-self-delegation": "1"
}
EOF
```

**Understanding the parameters:**

* **pubkey**: Your validator's consensus public key
* **amount**: How much to stake (1,000 BPL in this example)
* **moniker**: Your validator's display name (choose something unique)
* **commission-rate**: Your commission (0.10 = 10%)
* **commission-max-rate**: Maximum commission you can set (0.20 = 20%)
* **commission-max-change-rate**: Max daily change (0.01 = 1% per day)
* **min-self-delegation**: Minimum self-stake to remain active

**Important Notes:**

* **Amount**: Must be in base units (1 bplcoin = 10^18 base units). Ensure you have more than this amount for transaction fees.
* **Commission rates**: Once set, `commission-max-rate` cannot be changed. Choose carefully as it limits your future earning flexibility.
* **Commission changes**: Limited by `commission-max-change-rate`. Example: if set to 0.01, you can only change commission by 1% per day.
* **Min-self-delegation**: If your self-delegation falls below this amount, your validator automatically becomes inactive.

```bash
# Submit create-validator transaction
evmd tx staking create-validator $HOME/.evmd/validator.json \
  --chain-id 9001 \
  --gas auto \
  --gas-adjustment 1.5 \
  --gas-prices 10000000bplcoin \
  --from validator \
  --keyring-backend file \
  --home $HOME/.evmd \
  --node http://localhost:26657 \
  --yes

# Verify validator creation
evmd query staking validator $(evmd keys show validator --bech val -a --keyring-backend file --home $HOME/.evmd) \
  --node http://localhost:26657
```

<details>

<summary>💡 Gas Settings</summary>

* `--gas auto`: Automatically estimates gas needed
* `--gas-adjustment 1.5`: Adds 50% buffer to estimation (matches join\_validator.sh script)
* This ensures your transaction succeeds even if gas estimation is slightly off

</details>

<details>

<summary>ℹ️ Validator Status</summary>

New validators may show as "jailed" initially if they're not signing blocks. This is normal for Method 1 since you're not running a local node. See [Unjailing Your Validator](#unjailing-your-validator) below.

</details>

## Managing Your Validator

Once your validator is running, you'll need to perform regular management tasks.

### Checking Validator Status

Monitor your validator's current state:

```bash
# Get validator operator address
VALOPER=$(evmd keys show validator --bech val -a --keyring-backend file --home $HOME/.evmd)

# Get validator consensus address (needed for signing info queries)
VALCONS=$(evmd tendermint show-address --home $HOME/.evmd)

# Check validator status
evmd query staking validator $VALOPER --node http://localhost:26657

# Key fields to monitor:
# - status: Should be "BOND_STATUS_BONDED" for active validators
# - jailed: Should be "false"
# - tokens: Your total stake (self-delegation + delegations)
# - commission: Your commission rates

# Quick status check (jailed status only)
evmd query staking validator $VALOPER --node http://localhost:26657 | jq '{jailed, status, tokens}'
```

### Unjailing Your Validator

If your validator gets jailed due to downtime:

```bash
# Note: Ensure VALOPER and VALCONS are set (see "Checking Validator Status" section above)

# 1. Check why you were jailed
evmd query slashing signing-info $VALCONS --node http://localhost:26657

# 2. Ensure your node is fully synced
curl -s http://localhost:26657/status | jq '.result.sync_info.catching_up'
# Should return: false

# 3. Unjail your validator
evmd tx slashing unjail \
  --from validator \
  --keyring-backend file \
  --home $HOME/.evmd \
  --chain-id 9001 \
  --gas auto \
  --gas-adjustment 1.5 \
  --gas-prices 10000000bplcoin \
  --node http://localhost:26657 \
  --yes

# 4. Verify unjailing
evmd query staking validator $VALOPER --node http://localhost:26657 | jq '.jailed'
# Should return: false
```

<details>

<summary>⚠️ Why Validators Get Jailed</summary>

Validators are jailed for:

* **Downtime**: Missing too many blocks (usually >5% over a window)
* **Double signing**: Running the same validator key on multiple nodes (results in permanent jail and slashing)

Always ensure you have only one node running with your validator keys.

</details>

**Important**: You can only unjail after the `jailed_until` time has passed. Check this with:

```bash
evmd query slashing signing-info $VALCONS --node http://localhost:26657 | jq '.jailed_until'
```

### Delegating to Your Validator

Increase your self-delegation:

```bash
# Delegate more tokens to your validator
evmd tx staking delegate $VALOPER 100000000000000000000bplcoin \
  --from validator \
  --keyring-backend file \
  --home $HOME/.evmd \
  --chain-id 9001 \
  --gas auto \
  --gas-adjustment 1.5 \
  --gas-prices 10000000bplcoin \
  --node http://localhost:26657 \
  --yes

# Verify delegation
evmd query staking delegation $(evmd keys show validator -a --keyring-backend file --home $HOME/.evmd) $VALOPER \
  --node http://localhost:26657
```

## Firewall & Security

### Basic Firewall Configuration

```bash
# Allow SSH (adjust port if using non-standard)
sudo ufw allow 22/tcp

# Allow P2P communication (required for all validators)
sudo ufw allow 26656/tcp

# Allow RPC (if exposing publicly - use with caution)
sudo ufw allow 26657/tcp

# Allow API/gRPC (if needed)
sudo ufw allow 1317/tcp
sudo ufw allow 9090/tcp

# Allow JSON-RPC for EVM (if exposing publicly - use with caution)
sudo ufw allow 8545/tcp
sudo ufw allow 8546/tcp

# Enable firewall
sudo ufw enable

# Check status
sudo ufw status
```

## Next Steps

* Review hardware requirements in [Hardware Requirements](/node-operation/hardware-requirements.md)
* Learn about daily operations in [Operations](/node-operation/operations.md)
* Follow step-by-step procedures in [Runbooks](/node-operation/runbooks.md)
* Troubleshoot issues in [Troubleshooting](/node-operation/troubleshooting.md)
