How I created a Cosmos Blockchain with Starport running two nodes on DigitalOcean

Daniel Fariña
8 min readOct 22, 2021

--

One of the concepts that was difficult to understand when I first started interacting with Cosmos’ Starport was the fact that the application creates a Binary file. This file can be distributed for additional peers to connect to the blockchain.

In this example, I’m going to create two servers which I will call firstNode & secondNode respectively. The first node will run thestarport serve command to build the Cosmos blockchain, create a genesis file, and the configuration. I can do this in the local environment but the purpose of this post is to get the Cosmos blockchain up and running with two nodes on DigitalOcean. I will then publish the application to Github, take a look at the automatic release process, download the release to secondNode and connect to firstnode from the secondNode.

Lastly, I will also run the blockchain locally (This part is pending as first I want to focus on two nodes onDigitalOcean).

The result will be the following:

Step 1

Let’s start by creating two servers on DigitalOcean. If you don’t know how to do this. You can reference the tutorial that helped me understand this here.

Select all the default options except for the size. I selected a $12/month server to run things a little smoother. I also recommend connecting via SSH. You can learn more about this here.

Then create two droplets at once by selecting the add droplet button.

Once this is complete I will have two servers ready to configure.

Step 2

Login to firstNode

ssh root@159.223.108.208

Step 3

Create a new user called “first_user” to run the application with. (Make sure to save the user’s password).

adduser first_user

Adding Sudo User from Usermod Command

usermod -aG sudo first_user

To be able to login as first_user, copy the ssh public key to the new home directory for first_user:

rsync --archive --chown=first_user:first_user ~/.ssh /home/first_user

Switch to the new user

su - first_user

Step 4

Install Golang

wget https://golang.org/dl/go1.17.2.linux-amd64.tar.gzsudo tar -xvf go1.17.2.linux-amd64.tar.gz -C /usr/localsudo chown -R first_user:first_user /usr/local/go

Add Go to the paths in the localprofile:

nano ~/.profile

At the end of the file add the following:

export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin:/usr/local/go/bin

Refresh the profile & check version

source ~/.profile
go version

Result:

Step 5

Install Starport on the firstNode

curl https://get.starport.network/starport! | sudo bash

Step 6

Create Starport application on the firstNode which I will call “myblockchain”.

cd ~/
starport scaffold chain github.com/daniel-farina/myblockchain

Start the application on the firstNode in development mode

cd ~/myblockchain
starport chain serve

This will create new accounts, add tokens to them and configure the blockchain. More about this on the official documentation information here.

This also runs the blockchain in development mode. If you cancel or exit this window the blockchain will stop running. You would usually run this locally when coding.

By the way, the configuration for the first two wallets, validators and faucet for the development environment lives on the config.yml.

The process of adding accounts to your testnet/mainnet requires you to use the add-genesis-account command for your blockchain. There is not a lot documentation about this yet but you can get an idea from here.

Step 7

I created a binary of myblockchain in the firstNode

cd ~/blockchain
starport chain build

This will add myblockchaind to the Go’s bin folder.

I can now start the blockchain anywhere in the system with:

myblockchaind start

Step 8

Create a systemd process for myblockchaind

First, create some necessary files

sudo mkdir -p /var/log/myblockchaind 
sudo touch /var/log/myblockchaind/digitaloceand.log
sudo touch /var/log/myblockchaind/myblockchaind_error.log
sudo touch /etc/systemd/system/myblockchaind.service

Second, edit the systemd service file for myblockchaind.

sudo nano /etc/systemd/system/myblockchaind.service

Next, add the following configuration to it:

Description=myblockchaind daemon
After=network-online.target
[Service]
User=first_user
ExecStart=/home/first_user/go/bin/myblockchaind start --home=/home/first_user/.myblockchain
WorkingDirectory=/home/first_user/go/bin
StandardOutput=file:/var/log/myblockchaind/digitaloceand.log
StandardError=file:/var/log/myblockchaind/digitaloceand_error.log
Restart=always
RestartSec=3
LimitNOFILE=4096
[Install]
WantedBy=multi-user.target

Then, enabled it to run all the time even after it reboots.

sudo systemctl enable myblockchaind.service

Start the process.

sudo systemctl start myblockchaind.service

Lastly, I can see the logs of the new service like this:

sudo journalctl -u myblockchaind -f

Step 9

Create a Github repo and push the code to it. This step is quite important. I will use the automatic actions from github to build a public release of the blockchain.

Create an empty github repo

Add remote and push changes

git remote add origin https://github.com/daniel-farina/myblockchain.git
git push -u origin master

If asked to login, enter the username and token. A token must be created here and used instead of the account password. Make sure to select repo access and workflow access. I recommend deleting that token from the account once it’s not longer needed.

A repo with the base Starport app is now ready.

Step 10

Automatic Release

The team behind Starport created a neat Github action to automatically build the application.

Go to the repo and click the Actions tab. As you can see, a git action is automatically executed once a commit is pushed to the main branch. This git action lives in .github/workflows/release.yml

This action will run the release.yml which has several steps to build and release the application.

The release in the repo contains a distribution binary for the blockchain:

Step 11

Start a secondNode on DigitalOcean

Download this release and start a new node.

Login to the secondNode

ssh second_user@159.223.98.102

Create a new user called “second_user” to run the application with. Make sure to the save the user’s password.

adduser second_user
usermod -aG sudo second_user

To be able to login as second_user, copy the ssh public key to the new home directory for second_user:

rsync --archive --chown=second_user:second_user ~/.ssh /home/second_user

Switch to the new user

su - second_user

Repeat step 4 & 5 (Install Go & Starport)

At this point there should be two consoles running. The firstNode with systemd and the secondNode ready for our next action.

Step 12.

This section will cover installing the blockchain onto another server, initialising it and then adding it to systemd.

Install myblockchaind in the system Learn more.

The binary can be installed using utility from Starport. Replace the bold text with the repo’s info.


curl https://get.starport.network/daniel-farina/myblockchain@latest! | sudo bash

Or the repo can be cloned and built on the secondNode directly.

cd ~/
git clone https://github.com/daniel-farina/myblockchain
cd myblockchain
starport chain build

Initialize the node so all the necessary myblockchain files and directories get created

myblockchaind init {MONIKER}
  • Moniker: The name of the validator (e.g. “secondNode”)

Next copy the genesis from the firstNode (/home/first_user/.myblockchain/config/genesis.json) machine to the secondNode server.

In production it’s a good idea to create a repo with the genesis for testnet and mainnet. You can see an example of this on the Terra repo here.

On this example however, I will use the scp command to copy the genesis from firstnode to secondNode, a ssh-key is needed on the firstNode

Generate a key pair for the firstNode & secondNode

ssh-keygen

Then get the public key from firstNode

cat ~/.ssh/id_rsa.pub

Add the public key to the secondNode (at the end of the file)

nano ~/.ssh/authorized_keys

Now back to the firstNode, copy the genesis from it to the secondNode.

scp /home/first_user/.myblockchain/config/genesis.json second_user@159.223.98.102:/home/second_user/.myblockchain/config/

Configure a persistent connection with the secondNode instance.

On another window in the firstNode machine run the following command to get the node-id.

myblockchaind tendermint show-node-id

Then add the firstNode node-id and IP into the configuration file on the secondNode.

Edit the server’s config.toml on the secondNode

nano ~/.myblockchain/config/config.toml

Add a persistent connection. Use the node-id from the firstNode, IP address and default port.

# Comma separated list of nodes to keep persistent connections to persistent_peers = "148c4d60de49ad6bacbf9abe3c51608f217403c4@159.223.108.208:26656"

Start the blockchain on the secondNode

myblockchaind start

The blockchain on secondNode is now syncing.

To verify that the nodes are connected. Open the terminal on the firstNode and run this command:

go get -u github.com/cosmos/gex
gex

Success! the connected peers should show a number 1 which means the blockchain is successfully running on two nodes. 🎉

Step 13

Finally, I’m going to add secondNode to systemd as well so that it can be running automatically at all times. This is a repeat of step 8.

Create a systemd process for myblockchaind

First, create some necessary files

sudo mkdir -p /var/log/myblockchaind 
sudo touch /var/log/myblockchaind/digitaloceand.log
sudo touch /var/log/myblockchaind/myblockchaind_error.log
sudo touch /etc/systemd/system/myblockchaind.service

Second, edit the systemd service file for myblockchaind.

sudo nano /etc/systemd/system/myblockchaind.service

Next, add the following configuration to it:

Description=myblockchaind daemon
After=network-online.target
[Service]
User=second_user
ExecStart=/home/second_user/go/bin/myblockchaind start --home=/home/second_user/.myblockchain
WorkingDirectory=/home/second_user/go/bin
StandardOutput=file:/var/log/myblockchaind/digitaloceand.log
StandardError=file:/var/log/myblockchaind/digitaloceand_error.log
Restart=always
RestartSec=3
LimitNOFILE=4096
[Install]
WantedBy=multi-user.target

Then, enabled it to run all the time even after it reboots.

sudo systemctl enable myblockchaind.service

Start the process.

sudo systemctl start myblockchaind.service

Lastly, I can see the logs of the new service like this:

sudo journalctl -u myblockchaind -f

Done! Stay tuned for more guides.

--

--