# Union instruction Run Node

By [GrichaMVP](https://paragraph.com/@grichamvp) · 2024-09-26

---

**Getting Started**
===================

This guide is intended for validators running on bare-metal servers and explains how Union releases work. Check out the [NixOS](https://docs.union.build/infrastructure/node-operators/nixos/) and the [Kubernetes](https://docs.union.build/infrastructure/node-operators/kubernetes/) guide for more production-ready deployments.

Validators are the backbone of the network. Becoming one requires significant token bonding and delegations, and is not intended for non-power users.

[**Obtaining uniond**](https://docs.union.build/infrastructure/node-operators/getting-started/#obtaining-uniond)
----------------------------------------------------------------------------------------------------------------

**Note** Currently, directly downloading the `uniond` binary requires access to our private GitHub repository. We are not currently providing the general public access to our GitHub repositories. If you don’t have access to our private GitHub repository, you can still run our node using the public Docker image.

You can obtain `uniond` from a recent [release](https://github.com/unionlabs/union/releases/latest).

**Caution** Double-check the version and architecture in the link before downloading.

*   [**x86\_64-linux**](https://docs.union.build/infrastructure/node-operators/getting-started/#tab-panel-0)
    
*   [aarch64-linux](https://docs.union.build/infrastructure/node-operators/getting-started/#tab-panel-1)
    

    curl --output uniond --location https://github.com/unionlabs/union/releases/download/$UNIOND_VERSION/uniond-release-x86_64-linux
    

_Where_ `UNIOND_VERSION` is v0.24.0

Verify that the binary works on your server by running:

    ./uniond --help
    

For convenience, we can add the binary to the `PATH`, to make it callable from anywhere.

    mv ./uniond /usr/bin/
    

### [**Using Docker**](https://docs.union.build/infrastructure/node-operators/getting-started/#using-docker)

We also provide containers in our [package registry](https://github.com/orgs/unionlabs/packages/container/package/uniond-release).

    docker pull ghcr.io/unionlabs/uniond-release:$UNIOND_VERSION
    

_Where_ `UNIOND_VERSION` is v0.24.0

When running the container, make sure to map a volume to the path passed in `--home` options to ensure data persistence. From here on the guide assumes the usage of a regular binary. The [docker-compose](https://docs.union.build/infrastructure/node-operators/docker-compose/) section is more suited for docker users.

**Caution** `uniond` is a stateful application and interacts with the file system. Make sure to use [volumes](https://docs.docker.com/storage/volumes/).

[**Initialization**](https://docs.union.build/infrastructure/node-operators/getting-started/#initialization)
------------------------------------------------------------------------------------------------------------

We’ll need to set up a few configuration files and obtain the [genesis.json](https://docs.union.build/genesis.json) before we can run the node.

[https://docs.union.build/genesis.json](https://docs.union.build/genesis.json)

First, set some environment variables, which are used throughout initialization.

    export CHAIN_ID=union-testnet-8export MONIKER="Unionized Goblin"export KEY_NAME=aliceexport GENESIS_URL="https://union.build/genesis.json"
    

Then we’ll have `uniond` initialize our data and configuration directories. By default, `/User/{USER}/.uniond` is used.

    uniond init $MONIKER --chain-id $CHAIN_ID
    

### [**Seeds**](https://docs.union.build/infrastructure/node-operators/getting-started/#seeds)

Next, edit `~/.union/config/config.toml`. We’ll set the seeds to ensure your node can connect to the peer-to-peer network.

For `union-testnet-8` replace `seeds = ""` with:

    seeds = "c2bf0d5b2ad3a1df0f4e9cc32debffa239c0af90@testnet.seed.poisonphang.com:26656"
    

### [**Genesis Configuration**](https://docs.union.build/infrastructure/node-operators/getting-started/#genesis-configuration)

Download the `genesis.json` and copy it to your `uniond` home directory.

    curl $GENESIS_URL | jq '.result.genesis' > ~/.union/config/genesis.json
    

### [**Registration**](https://docs.union.build/infrastructure/node-operators/getting-started/#registration)

To join as a validator, you need to submit a registration transaction. You can do this from the command line on your validator node.

First, add a wallet that holds Union tokens.

    uniond keys add $KEY_NAME --recover
    

**Caution** For production usage, we recommend not storing the wallet on a server.

To submit the registration transaction and become a validator, you must submit a `create-validator` transaction:

    uniond tx staking create-validator \  --amount 1000000muno \  --pubkey $(uniond tendermint show-validator) \  --moniker $MONIKER \  --chain-id $CHAIN_ID \  --from $KEY_NAME \  --commission-max-change-rate "0.1" \  --commission-max-rate "0.20" \  --commission-rate "0.1" \  --min-self-delegation "1"
    

**Note** If your own node isn’t set up to accept RPC request, you can send them to another node via the `--node` option.

[**Systemd Service**](https://docs.union.build/infrastructure/node-operators/getting-started/#systemd-service)
--------------------------------------------------------------------------------------------------------------

We recommend running `uniond` as a systemd service. Create a file in `/etc/systemd/system` called `uniond.service`. Make sure to replace $USER with your username.

    [Unit]Description=uniond[Service]Type=simpleRestart=alwaysRestartSec=1User=$USERExecStart=/usr/bin/uniond start[Install]WantedBy=multi-user.target
    

You should be able to view the node logs by executing

    sudo journalctl -f --user uniond
    

It’s then recommended to back up these files from `~/.union/config` in a secure location:

*   `priv_validator_key.json`
    
*   `node_key.json`
    

**Docker Compose**
==================

This guide assumes you are familiar with running a Union validator. If not, start with the [validator guide](https://docs.union.build/joining-testnet/getting-started/).

[docker-compose](https://docs.docker.com/compose/) is a tool for running containers in a declarative manner. This allows for better automation, upgrades, and monitoring.

[**Configuration**](https://docs.union.build/infrastructure/node-operators/docker-compose/#configuration)
---------------------------------------------------------------------------------------------------------

Our base `compose.yml` is fairly simple:

    services:  node:    image: "ghcr.io/unionlabs/uniond-release:$UNIOND_VERSION"    volumes:      - ~/.union:/.union      - /tmp:/tmp    network_mode: "host"    restart: unless-stopped    command: start --home /.union
    

Pay special attention to the `volumes` key. Here we map an already initialized `~/.uniond` directory to the `node` service. The `~/.uniond` directory should contain a `config` and `data` directory. To properly set these up, check out the [validator guide](https://docs.union.build/joining-testnet/getting-started/).

[**Monitoring**](https://docs.union.build/infrastructure/node-operators/docker-compose/#monitoring)
---------------------------------------------------------------------------------------------------

We suggest adding additional monitoring services, such as [datadog](https://www.datadoghq.com/).

**NixOS**
=========

NixOS deployments can use our **module** to easily manage their validator. It creates a systemd service with a production configuration

**Caution** The current example does not support remote signers yet. We will expand the guide once [horcrux](https://github.com/strangelove-ventures/horcrux) support is implemented.

[**Configuration**](https://docs.union.build/infrastructure/node-operators/nixos/#configuration)
------------------------------------------------------------------------------------------------

Below is an example configuration.nix which can be used in production.

**Caution** The example currently uses `git+ssh://` syntax rather than `github:` syntax because our repository is not public yet. Once it is, this will be simplified. When this happens, `GIT_LFS_SKIP_SMUDGE` will also no longer be required.

    {  inputs = {    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";    union.url = "git+ssh://git@github.com/unionlabs/union";  };  outputs = {self,nixpkgs,union, ... }:    {      nixosConfigurations.testnet-validator =        let          system = "x86_64-linux";          pkgs = importnixpkgs { inherit system; };        in        nixpkgs.lib.nixosSystem {          inherit system;          modules = [            union.nixosModules.unionvisor            {              system.stateVersion = "23.11";              # Base configuration for openstack-based VPSs              imports = [ "${nixpkgs}/nixos/modules/virtualisation/openstack-config.nix" ];              # Allow other validators to reach you              networking.firewall.allowedTCPPorts = [ 80 443 26656 26657 ];              # Unionvisor module configuration              services.unionvisor = {                enable = true;                moniker = "your-testnet-moniker";              };              # OPTIONAL: Some useful inspection tools for when you SSH into your validator              environment.systemPackages = with pkgs; [                bat                bottom                helix                jq                fastfetch                tree              ];            }          ];        };    };}
    

You can then deploy the configuration by running

    GIT_LFS_SKIP_SMUDGE=1 nixos-rebuild switch --flake .\#testnet-validator --target-host user@validator.domain -L
    

[**Upgrading**](https://docs.union.build/infrastructure/node-operators/nixos/#upgrading)
----------------------------------------------------------------------------------------

To upgrade to newer versions, simply run

    nix flake updateGIT_LFS_SKIP_SMUDGE=1 nixos-rebuild switch --flake .\#testnet-validator --target-host user@validator.domain -L
    

This will pull in the latest changes to union configurations and prepare your node for future upgrades.

**Node Configuration**
======================

After successfully running your node with `uniond`, you can refer to this guide to aid you in configuring your node.

This is not a complete guide to all node configuration options, this is intended to help ensure that your node is fully operational.

This guide will assume that you’re starting at the root of your Union node configuration (located at `~/.union/` by default or `~/.unionvisor/home` if you’re using Unionvisor).

[**Client Configuration**](https://docs.union.build/infrastructure/node-operators/node-configuration/#client-configuration)
---------------------------------------------------------------------------------------------------------------------------

Located in `config/client.toml`, this file is host to client settings.

### [**The Network Chain ID**](https://docs.union.build/infrastructure/node-operators/node-configuration/#the-network-chain-id)

Update this value to ensure that your client is supplied with the correct chain ID.

For the Union Testnet, this value should be `"union-testnet-8"`.

    # The network chain IDchain-id = "union-testnet-8"
    

### [**Host/Port for the Tendermint RPC**](https://docs.union.build/infrastructure/node-operators/node-configuration/#hostport-for-the-tendermint-rpc)

This will determine which address your client will listen for Tendermint RPC request on.

This will default to `"tcp://localhost:26657"`, setting this to `"tcp://0.0.0.0:26657"` will ensure it’s listening on every available network interface.

    # <host>:<port> to Tendermint RPC interface for this chainnode = "tcp://0.0.0.0:26657"
    

[**App Configuration**](https://docs.union.build/infrastructure/node-operators/node-configuration/#app-configuration)
---------------------------------------------------------------------------------------------------------------------

Located in `config/app.toml`, this file is host to app settings.

### [**Minimum Gas Price**](https://docs.union.build/infrastructure/node-operators/node-configuration/#minimum-gas-price)

Located under the “Base Configuration” section of `config/app.toml`.

While optional, you may wish to ensure your node receives a minimum fee when processing transactions. Whatever you choose for this value, ensure it uses the correct denom. For the Union Testnet, the correct denom is `muno`.

    # The minimum gas prices a validator is willing to accept for processing a# transaction. A transaction's fees must meet the minimum of any denomination# specified in this config (e.g. 0.25token1;0.0001token2).minimum-gas-prices = "0muno"
    

### [**Pruning**](https://docs.union.build/infrastructure/node-operators/node-configuration/#pruning)

Located under the “Base Configuration” section of `config/app.toml`.

Several options are available here, ensure you’ve selected the one that best fits your nodes storage capabilities.

    # default: the last 362880 states are kept, pruning at 10 block intervals# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)# everything: 2 latest states will be kept; pruning at 10 block intervals.# custom: allow pruning options to be manually specified through 'pruning-keep-recent', and 'pruning-interval'pruning = "default"
    

[**Node Configuration**](https://docs.union.build/infrastructure/node-operators/node-configuration/#node-configuration)
-----------------------------------------------------------------------------------------------------------------------

Located in `config/config.toml`, this file is host to many settings.

### [**Consensus**](https://docs.union.build/infrastructure/node-operators/node-configuration/#consensus)

To achieve a low target block time, the Union team asks validators to make the following changes to their configuration.

Located in the `consensus` TOML table under the “Consensus Configuration Options” section.

    # How long we wait for a proposal block before pre-voting niltimeout_propose = "3s"# How much timeout_propose increases with each roundtimeout_propose_delta = "500ms"# How long we wait after receiving +2/3 prevotes for “anything” (ie. not a single block or nil)timeout_prevote = "1s"# How much the timeout_prevote increases with each roundtimeout_prevote_delta = "500ms"# How long we wait after receiving +2/3 precommits for “anything” (ie. not a single block or nil)timeout_precommit = "1s"# How much the timeout_precommit increases with each roundtimeout_precommit_delta = "500ms"# How long we wait after committing a block, before starting on the new# height (this gives us a chance to receive some more precommits, even# though we already have +2/3).timeout_commit = "1s"
    

### [**RPC Listening Address**](https://docs.union.build/infrastructure/node-operators/node-configuration/#rpc-listening-address)

Located in the `rpc` TOML table under the “RPC Server Configuration Options” section.

You’ll want to ensure your node is configured to accept rpc connections. To do so, set this value to the appropriate address.

For example, to listen on every available network interface - set this to `"tcp://0.0.0.0:26657"`.

    # TCP or UNIX socket address for the RPC server to listen onladdr = "tcp://0.0.0.0:26657"
    

### [**P2P Listening Address**](https://docs.union.build/infrastructure/node-operators/node-configuration/#p2p-listening-address)

Located in the `p2p` TOML table under the “P2P Configuration Options” section.

You’ll want to ensure your node is configured to accept p2p connections. To do so, set this value to the appropriate address.

For example, to listen on every available network interface - set this to `"tcp://0.0.0.0:26656"`.

    # Address to listen for incoming connectionsladdr = "tcp://0.0.0.0:26656"
    

### [**External Address**](https://docs.union.build/infrastructure/node-operators/node-configuration/#external-address)

Located in the `p2p` TOML table under the “P2P Configuration Options” section.

If you’ve configured a domain name for your node, this is the place to inform your node of it.

    # Address to advertise to peers for them to dial# If empty, will use the same port as the laddr,# and will introspect on the listener or use UPnP# to figure out the address. ip and port are required# example: 159.89.10.97:26656external_address = "example.com:26656"
    

### [**Seeds**](https://docs.union.build/infrastructure/node-operators/node-configuration/#seeds)

Located in the `p2p` TOML table under the “P2P Configuration Options” section.

Seed nodes help orchestrate initial connections to the network. For union-testnet-8, the seed nodes are:

    seeds = "c2bf0d5b2ad3a1df0f4e9cc32debffa239c0af90@testnet.seed.poisonphang.com:26656"
    

### [**Seed Mode**](https://docs.union.build/infrastructure/node-operators/node-configuration/#seed-mode)

Located in the `p2p` TOML table under the “P2P Configuration Options” section.

If you’d like to be a seed node, be sure to set this to `true`.

**Caution** If you plan for your node to be a validator, it should not also be a seed node.

    # Seed mode, in which node constantly crawls the network and looks for# peers. If another node asks it for addresses, it responds and disconnects.## Does not work if the peer-exchange reactor is disabled.seed_mode = false

---

*Originally published on [GrichaMVP](https://paragraph.com/@grichamvp/union-instruction-run-node)*
