Key and Account Confusion when Running gaiad as a Service


Scenario -

Some of us run gaiad as a systemd service, using a specified user and gaiad home directory. Here’s an outdated script that creates the user and directory. It also starts gaiad using the specified home directory. The script is outdated, however the steps are the same for any testnet.

(Script written by @kwunyeung)

I’ve experienced confusion when declaring validator candidacy using this configuration. The confusion comes from having two different config directories -

~/.gaiad/config/ (This is the gaiad home directory of the user you’re logged-in as.)

/opt/gaiad/config/ (This is the gaiad home directory of the user the script runs gaiad as.)

I’m leaving the explanation in raw format. My hope is to come back to edit it. For now, I solved my issue by -

-stopping gaiad

-moving the priv_validator.json file in my /opt/gaiad/config/ to a different filename, effectively making it not usable by gaiad

-copying the priv_validator.json file from my ~/.gaiad/config/ to my /opt/gaiad/config/

-restarting gaiad

Here’s some raw feedback from @mattharrop and @kwunyeung explaining the issue in greater detail -

From @mattharrop -

This is a confusing issue. I don’t think I have 100% clarity on it, but let me see if I can help. Before you declare your candidacy, you use the gaiad tendermint … command to find your node’s ID, which you’ll use when you declare candidacy.
If you just the command like that, gaiad will run as your logged in user, look in ~/.gaiad/config for it’s configuration files, and if it doesn’t find any it will make them. Then, when you run the service, gaiad is running as user gaiad and looking in /opt/gaiad/config for it’s files, and if it doesn’t find any it will make them. So you now have two identities on your server.
So I think the solution here is to run gaiad tendermint … using sudo gaiad and make sure to specificy the home directory, exactly the way the service is configured to run it.

From @kwunyeung -

  1. The key is associated with the delegator address

  2. If your run the gaiad as a service and have already pointed to —home=/opt/gaiad then you don’t have to touch gaiad

  3. Please be reminded that gaiad and gaiacli are two different things

  4. All the config and priv_validator.json are for gaiad to run

  5. gaiacli is accessing keys to send tx

  6. Or query the data from the chain

  7. As you are using gaiacli to create validator, you don’t have to think where the gaiad config are

  8. You should consider what keys your are using to sign those operations

  9. So the key “chainuser010” in your case is the key for the delegator address you defined in your command

  10. Which holds the steak

  11. Please be reminded that gaiad and gaiacli are two different things

That’s why when you want to see your node id and validator pubkey, you are calling gaiad, node_key.json and priv_validator.json are inside gaiad/config. When you send coin you use gaiacli as it reads your keys to access your account (wallet).

  1. If your problem is about priv_validator.json, then it’s about gaiad but not gaiacli command


The gaiad is a node on the blockchain

My script actually does the followings:

  1. Update system software
  2. Install Go
  3. Setup correct paths for compiling
  4. Create a new user gaiad without shell and set the home directory to /opt/gaiad
  5. Get the cosmos repo and build the gaiad and gaiacli binaries
  6. Copy the binaries to /opt/go/bin as system-wise
  7. Install a systemd unit file which runs gaiad as a service as the user gaiad
  8. Run gaiad unsafe_reset_all to create the config directory with config.toml and priv_validator.json

As the home directory of the user gaiad is located at /opt/gaiad, I made the last command run as user gaiad and set the flag --home=/opt/gaiad.

sudo -u gaiad /opt/go/bin/gaiad unsafe_reset_all --home=/opt/gaiad

By doing this, the config.toml and priv_validator.json will be created at /opt/gaiad/ correctly and accessible by the user gaiad. If you read the unit file /etc/systemd/system/gaiad.service, the gaiad start will run with flag --home=/opt/gaiad as user gaiad. gaiad will then start and read the config and write data to /opt/gaiad/. That’s why you also need to put the genesis.json to /opt/gaiad/config and change the owner of it to be user gaiad as I have set the --home flag. And this gaiad is the binary which run as a node on the gaia-8001 blockchain.

So you now know the node is running and it reads and writes data to /opt/gaiad/ as user gaiad. If you want to know the node ID and validator pubkey, you need to run on this instance as the user gaiad as the node reads the files from /opt/gaiad/config/node_key.json and /opt/gaiad/config/priv_validator.json which are located at /opt/gaiad/config and they belong to the user gaiad.

> sudo -u gaiad /opt/go/bin/gaiad tendermint show_node_id --home=/opt/gaiad
> sudo -u gaiad /opt/go/bin/gaiad tendermint show_validator --home=/opt/gaiad

These commands read the files from /opt/gaiad/config/ instead of your current user home directory.

The story for connecting to the network ends here. You don’t have to touch it anymore if you don’t have any specific changes on the config.

The gaiacli is an interface to manipulate the chain

You have run your node and you have the validator pubkey. You now want to create a validator. We use gaiacli to create a validator. gaiacli and gaiad are two different things. gaiacli won’t read the config of gaiad and you don’t need to have gaiad to run gaiacli. gaiacli is an interface to help the user to read data and send tx to the blockchain.

You can run gaiacli on the same instance as the node running on gaiad but it’s not required. To create a validator, we need to run

gaiacli stake create-validator

with flags --address-delegator, --chain-id, --pubkey, --from and --amount.

The gaiacli is the software to interact with the blockchain. When you send a tx, you need your private key to sign the tx. That’s why you need to specify --from flag. It reads the keys from your .gaiacli directory, default to be at your user home directory. What gaiacli is doing is to read the key, sign the tx and send it out. So it doesn’t care if you have the node running in your current machine. As long as the key of the account you are using can be read by gaiacli, it can sign the tx correctly. And you can specify which node to send out the tx. It doesn’t have to be your own validator node. You can do this locally on any computer and run like this

gaiacli stake create-validator --address-delegator=cosaccaddyyyyyyyyyyyyy --pubkey=cosvalpub1xxxxxxxxxxxxxxxxxxxx --from=chainuser010 --amount=1steak --chain-id=gaia-8001 --node="tcp://"

As long as gaiacli can read your key which match cosaccaddyyyyyyyyyyyyy account, the tx can be sent via the node specified. The pubkey is the pubkey you read from gaiad on your validator node. The network won’t care if you create validator on the same machine as the node or not.

In short, with my install script, gaiad reads and writes to /opt/gaiad/ as user gaiad. gaiacli reads and creates keys to .gaiacli directory where you specified as --home on any computer.

Please let me know if you still feel anywhere confused.


Great writeup @kwunyeung! Thank you!