How I created a Cosmos Blockchain with Starport running two nodes on DigitalOcean
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