# Connect to Mainnet or Devnet

> Steps to install Mina and connect a validator node to Mainnet or Devnet.

Canonical URL: https://docs.minaprotocol.com/node-operators/validator-node/connecting-to-the-network

Use this guide to connect a node to either network and verify connectivity.

If you're using Ubuntu or Debian, first follow the [installation guide](/node-operators/validator-node/installing-on-ubuntu-and-debian), then return to this page for node startup.

## Standalone node

### Start

**Note:** A known issue exists with the Hetzner hosting provider. If you are using Hetzner, follow the [Networking troubleshooting](/node-operators/troubleshooting#my-hosting-provider-is-warning-me-abuse-message-netscan-detected) guidance before starting a node.

<Tabs groupId="network">
<TabItem value="mainnet" label="Mainnet">

```sh
mina daemon --peer-list-url https://bootnodes.minaprotocol.com/networks/mainnet.txt
```

</TabItem>
<TabItem value="devnet" label="Devnet">

Devnet is for testing and experimentation. MINA on Devnet has no real value.

```sh
mina daemon --peer-list-url https://bootnodes.minaprotocol.com/networks/devnet.txt
```

</TabItem>
</Tabs>

### Stop

In a new terminal, run:

```sh
mina client stop-daemon
```

## Running mina node as a service

Configure your node to keep running after logout, restart on reboot, and auto-restart on crash or clean exit:

- **Systemd** — the Mina systemd unit ships with `Restart=always` by default, so the daemon is restarted automatically after a crash or a clean exit (e.g. the hard-fork stop-slot shutdown). No extra configuration is required.
- **Docker** — pass `--restart=always` (or `--restart=unless-stopped`) when creating the container. The default (`no`) will **not** restart the daemon.

### Start the service

<Tabs groupId="install-method">
<TabItem value="systemd" label="Systemd">

Create `~/.mina-env` and set options as needed:

```sh
MINA_PRIVKEY_PASS="My_V3ry_S3cure_Password"
LOG_LEVEL=Info
FILE_LOG_LEVEL=Debug
```

Start and enable the service:

```sh
systemctl --user daemon-reload
systemctl --user start mina
systemctl --user enable mina
sudo loginctl enable-linger
```

</TabItem>
<TabItem value="docker" label="Docker">

Prepare directories:

```sh
cd ~
mkdir -p ~/.mina-config
```

Create `~/.mina-env`:

<Tabs groupId="network">
<TabItem value="mainnet" label="Mainnet">

```sh
export MINA_PRIVKEY_PASS="My_V3ry_S3cure_Password"
LOG_LEVEL=Info
FILE_LOG_LEVEL=Debug
PEER_LIST_URL=https://bootnodes.minaprotocol.com/networks/mainnet.txt
```

</TabItem>
<TabItem value="devnet" label="Devnet">

```sh
export MINA_PRIVKEY_PASS="My_V3ry_S3cure_Password"
LOG_LEVEL=Info
FILE_LOG_LEVEL=Debug
PEER_LIST_URL=https://bootnodes.minaprotocol.com/networks/devnet.txt
```

</TabItem>
</Tabs>

Run the container:

<Tabs groupId="network">
<TabItem value="mainnet" label="Mainnet">

```sh
docker run --name mina-node -d \
-p 8302:8302 \
--restart=always \
-v $(pwd)/.mina-env:/entrypoint.d/mina-env:ro \
-v $(pwd)/keys:/keys:ro \
-v $(pwd)/.mina-config:/root/.mina-config \
minaprotocol/mina-daemon:4.0.0-6850301-bullseye-mainnet \
daemon
```

</TabItem>
<TabItem value="devnet" label="Devnet">

```sh
docker run --name mina-node -d \
-p 8302:8302 \
--restart=always \
-v $(pwd)/.mina-env:/entrypoint.d/mina-env:ro \
-v $(pwd)/keys:/keys:ro \
-v $(pwd)/.mina-config:/root/.mina-config \
minaprotocol/mina-daemon:4.0.0-6965b50-bullseye-devnet \
daemon
```

</TabItem>
</Tabs>

</TabItem>
</Tabs>

### Stop the service

<Tabs groupId="install-method">
<TabItem value="systemd" label="Systemd">

```sh
systemctl --user stop mina
```

</TabItem>
<TabItem value="docker" label="Docker">

```sh
docker stop mina-node
```

</TabItem>
</Tabs>

## Monitor the mina client status

<Tabs groupId="install-runtime">
<TabItem value="native" label="Native/Systemd">

```sh
mina client status
```

</TabItem>
<TabItem value="docker" label="Docker">

```sh
docker exec -it mina-node mina client status
```

</TabItem>
</Tabs>

On first bootstrap, expect the following timeline:

| Time after start | Expected status |
|--|--|
| 0 – ~5 min | `mina client status` may fail to connect while the daemon initializes |
| ~5 – ~25 min | `Sync Status: Bootstrap` then `Sync Status: Catchup` |
| ~30 min | `Sync Status: Synced` |

To check the node from a script, a Kubernetes probe, or a Docker `HEALTHCHECK`, use `mina-healthcheck`. See [Health Checks](/node-operators/reference/health-checks).

Subsequent restarts sync faster when the on-disk cache in `~/.mina-config` is preserved. For Docker, ensure `/root/.mina-config` is mounted to a persistent host volume.

## Peer discovery

The daemon connects to the peers in the peer list. It then finds more peers through the libp2p distributed hash table (DHT). The libp2p helper, a process that the daemon starts, does this for as long as the node runs:

- When the node has fewer connections than `--min-connections` (default `20`), the helper queries the DHT for peers and connects to the peers that it finds. The time between two queries starts at the minimum interval and doubles after each query, up to the maximum interval.
- When the node has `--min-connections` connections or more, the helper does not query the DHT, and the interval returns to the minimum.

Two environment variables set the interval:

| Variable | Default | Description |
|--|--|--|
| `MINA_LIBP2P_DISCOVERY_MIN_INTERVAL` | `1s` | First wait between two DHT queries. |
| `MINA_LIBP2P_DISCOVERY_MAX_INTERVAL` | `5m` | Longest wait between two DHT queries. |

The values are Go duration strings, for example `500ms`, `30s`, or `2m`. If a value is not set or is not valid, the helper uses the default. The libp2p helper gets the environment of the daemon, so set these variables in `~/.mina-env` or in the environment of the Docker container. Use shorter intervals in a small test network that must connect quickly. Use longer intervals to send fewer DHT queries.

Other nodes can connect to your node only if they can reach TCP port `8302` (or the port that you set with `--external-port`). A node behind NAT without a forwarded port can only connect to peers that it dials, so it usually has fewer peers than a node that other nodes can reach. See [Do I need to configure port forwarding manually?](/node-operators/troubleshooting#do-i-need-to-configure-port-forwarding-manually).

When the daemon cannot validate a block or a transaction from gossip in the available time, it drops the message. It does not lower the score of the peer that sent the message.

## Step up your game

Once synced, continue with [Sending a Payment](/mina-protocol/sending-a-payment) and [Staking and Snarking](/node-operators/validator-node/staking-and-snarking).
