Guide to Staking on Ethereum 2.0 (Ubuntu/Prater/Nimbus)

Last updated: 2021–08–29
- Added support for Prater testnet
WARNING — do not use this guide for connecting to the Eth2 Mainnet. Mainnet guides are here.
This is a step-by-step guide to staking on the Ethereum 2.0 Prater multi-client testnet via the Status Nimbus client. It is based on the following technologies:
- Ubuntu v20.04 (LTS) x64 server
- Go Ethereum Node (code branch)
- Status’ Ethereum 2.0 client, Nimbus (code branch)
- Official multi-client testnet public network, Prater
- MetaMask crypto wallet browser extension
- Prometheus metrics
- Grafana dashboard
This guide includes instructions on how to:
- Generate and fund Prater validator account keys.
- Configure a newly running Ubuntu server instance.
- Configure and run an Ethereum 1.0 node as a service.
- Import Prater validator account keys to Nimbus.
- Compile and configure the Nimbus client software for Ethereum 2.0 (Prater testnet) and run as a service.
- Install and configure Prometheus metrics and set up a Grafana dashboard.
Warnings
This guide is written for the Prater testnet which runs on the Göerli Test Network. DO NOT, under any circumstances, send mainnet ETH to the Göerli Test Network. You will lose it.
This guide SHOULD NOT be used for connecting to the Eth2 mainnet. Eth2 mainnet specific guides can be found here.
Acknowledgements and Disclaimer
This guide is based on information I pulled together from various online resources and this guide wouldn’t exist without them. Thank you, all!
Thanks to the folks on the Nimbus Discord for their help and review!
Special thanks to the Nimbus client team and the EF researchers.
This guide is for educational purposes only. I’m not an expert in any of the technologies listed in this guide. The accuracy of this guide is not guaranteed and I am not responsible for any damages or losses incurred by following this guide.
Feedback is always welcome!
Support
This stuff can be tricky. If you need help there are two great resources you can reach out to (besides me):
- EthStaker community on Reddit or Discord. Knowledgeable and friendly community passionate about staking on Ethereum 2.0.
- Nimbus client team Discord. The client software engineering team. Experts on Nimbus and its usage.
Prerequisites
This guide assumes knowledge of Ethereum, ETH, staking, testnets, Linux, and MetaMask.
This guide also requires the following before getting started:
- Ubuntu server v20.04 (LTS) amd64 or newer, installed and running on a local computer or in the cloud (AWS, Digital Ocean, Microsoft Azure, etc.). A local computer is encouraged for greater decentralization — if the cloud provider goes down then all nodes hosted with that provider go down.
- MetaMask crypto wallet browser extension, installed and configured. A computer with a desktop (Mac, Windows, Linux) and a browser (Safari, Brave, FireFox, etc.) is required.
Note for Raspberry Pi Users
I haven’t tested this guide on a Rpi. If you want to try, just swap out the software listed below for the ARM version, where available. No guarantee it will work!
Requirements
- Ubuntu server instance. I used v20.04 (LTS) amd64 server VM.
- MetaMask crypto wallet browser extension, installed and configured.
- Hardware recommended hardware requirements:
- Processor: Modern CPU (within the last 3 years should be fine)
- Memory: 8GB RAM (16GB is better)
- Storage: 500GB available space SSD (1TB if you plan to run long term)
NOTE: Check your available disk space. Even you have a large SSD there are cases where Ubuntu is reporting only 200GB free. If this applies to you then take a look at Appendix E — Expanding the Logical Volume.
Overview
This is a long and detailed guide. Here’s a simplified diagram to help you conceptualize what we are going to do. The yellow boxes are the parts this guide mostly covers.

The conceptual flow is:
- Generate the staking Validator Keys and Deposit Data.
- Prepare the Ubuntu Server (firewall, security, etc.).
- Set up a Eth1 Node and sync it with the Eth1 Blockchain (Göerli Testnet).
- Configure the Nimbus client and sync it with the Eth1 Node.
- Deposit Göerli Test Network ETH to activate the Validator Keys.
Let’s get started!
Step 1— Generate Staking Data
To run a validator on the Prater testnet it is necessary to generate some data files based on the number of validators you’d like to fund and operate. Each validator requires a 32 Göerli ETH deposit to activate it.
NOTE: If you have already generated your deposit data and validator key(s) you can skip this step.
Download the Deposit Tool (Eth2 Deposit CLI)
To generate the data files we will use the official Eth2 Deposit CLI tool. The deposit tool generates files for staking as well as a mnemonic key to secure the data.
Go here to get the “Latest release”.

To ensure your generated data is secure you should run the tool from an air-gapped machine (never been connected to the internet) or a disconnected machine (temporarily disconnected from the internet).
Option 1: Air-Gapped Machine (recommended) — Download and extract the binary file. Copy the binary file to a USB drive. Connect to a fully air-gapped machine (never previously connected to the internet), copy the file over and run it from there.
Option 2: Download Machine (not recommended) — Run from the machine used to download the binary. An internet connection may be an opportunity to leak your mnemonic key. If a fully air-gapped machine isn’t available, after downloading the binary disconnect the internet on the current machine before proceeding.
You can use any machine to run the tool — it does not have to be your staking machine, but note that you will need to be able to access the generated files from a machine running MetaMask to do the Göerli ETH deposit AND from your staking machine to configure your validators.
In the Assets section of the webpage shown above locate the version matching the required platform. If Linux or Mac, download the archive using the commands below. If Windows, right-click the link and download.
Modify the URL below to match the download link for the latest version.
$ cd ~
$ sudo apt install curl
$ curl -LO https://github.com/ethereum/eth2.0-deposit-cli/releases/download/v1.2.0/eth2deposit-cli-256ea21-linux-amd64.tar.gz
If on Linux or Mac, unpack the tar archive using the commands below and go into the directory it created. If on Windows, unzip the archive and go into the folder created.
Modify the file name below to match the downloaded version.
$ sudo tar xvf eth2deposit-cli-256ea21-linux-amd64.tar.gz
$ cd eth2deposit-cli-256ea21-linux-amd64
There should be a binary file (executable) inside.
Run the Deposit Tool (Eth2 Deposit CLI)
On your secure machine run the binary file in a terminal window (or CMD in Windows).
Replace NumberOfValidators
with the number of validators you want to fund. E.g. --num_validators 2
.
$ ./deposit new-mnemonic --num_validators NumberOfValidators --mnemonic_language=english --chain prater
Or if running on Windows:
deposit.exe new-mnemonic --num_validators NumberOfValidators --mnemonic_language=english --chain prater
It will prompt you to create a validator keystore password. Back it up somewhere safe. This is critical. We will use this later to load the validator keys into the Nimbus validator wallet.

A seed phrase (mnemonic) will be generated. Back it up somewhere safe. This is critical. You will eventually use this to generate your withdrawal keys or to add additional validators.

Once you have confirmed your mnemonic your validator keys will be created.

The newly created validator keys and deposit data file are created at the specified location. E.g. eth2deposit-cli-ed5a6d3-linux-amd64/validator_keys
. Make a note of this. We will need it later.
The contents of the folder are shown below.

The deposit_data-[timestamp].json
file contains the public keys for the validators and information about the deposit. This file will be used to complete the deposit process later on.
The keystore-m...json
files contain the encrypted signing key. There is one keystore-m per validator. These will be used to set up the Nimbus validator wallet.
Now that we have the validator password, mnemonic, deposit data, and keystore files we will move on to set up Nimbus.
We will complete the set up before funding the keys (depositing the Göerli ETH to activate the validators) so we can verify everything works, first. If the validator deposits become active and the system is not ready we will be penalized for non-participation.
Step 2— Connect to the Server
Using a SSH client, connect to your Ubuntu server. The root
user account on Ubuntu server is normally disabled by default, however some cloud providers enable it. Using the root user to log in is risky. If you are logged in as root
(e.g. the terminal prompt has a #
symbol instead of a $
symbol), then create a user-level account with admin privileges instead.
NOTE: If you are NOT logged in as root then skip this and go to Step 3.
# adduser <yourusername>
You will asked to create a password and some other information.
Grant admin rights to the new user by adding it to the sudo group.
# usermod -aG sudo <yourusername>
When you log in as <yourusername>
you can type sudo before commands to perform actions with superuser privileges.
Optional: If you used SSH keys to connect to your Ubuntu instance via the root
user you will need to associate the new user with the root user’s SSH key data.
# rsync --archive --chown=<yourusername>:<yourusername> ~/.ssh /home/<yourusername>
Finally, log out of root
and log in as <yourusername>
.
Step 3— Update the Server
Make sure your system is up to date with the latest software and security updates.
$ sudo apt update && sudo apt upgrade
$ sudo apt dist-upgrade && sudo apt autoremove
$ sudo reboot
Step 4— Secure the Server
Security is important. This is not a comprehensive security guide, just some basic settings: a firewall and a different SSH port.
Configure the firewall
Ubuntu 20.04 servers can use the default UFW firewall to restrict inbound traffic to the server. Before we enable it we need to allow inbound traffic for SSH, Go Ethereum, Grafana, and Nimbus.
Allow SSH
Allows connection to the server over SSH. For security reasons we are going to modify the default port of 22 because it is a common attack vector.
NOTE: If you would rather not change the default SSH port (not recommended), then include a rule allowing the default SSH port
$ sudo ufw allow 22/tcp
and move onto the “Allow Go Ethereum” section.
Choose a port number between 1024–49151 and run the following command to make sure your selection is not already in use on the server. If it is (red text), choose a different port. E.g. sudo ss -tulpn | grep ':6673'
$ sudo ss -tulpn | grep ':<yourSSHportnumber>'
Update the firewall to allow inbound traffic on <yourSSHportnumber>
. SSH requires TCP. E.g. sudo ufw allow 6673/tcp
$ sudo ufw allow <yourSSHportnumber>/tcp
Next change the default SSH port.
$ sudo nano /etc/ssh/sshd_config
Find the line with # Port 22
or Port 22
and change it to Port <yourSSHportnumber>
. Remove the #
if it was present.
Check the screen shot below for reference. Your file should look similar to that (but with the port number you chose). Exit and save.

Restart the SSH service.
$ sudo systemctl restart ssh
Next time you log in via SSH use <yourSSHportnumber>
for the port.
Optional: If you were already using UFW with port 22/TCP allowed then update the firewall to deny inbound traffic on that port. Only do this after you log in using the new SSH port.
$ sudo ufw deny 22/tcp
Allow Go Ethereum
Allows incoming requests from Go Ethereum peers (port 30303/TCP and 30303/UDP). If you’d rather use a node hosted by a 3rd party (Infura, Alchemy, etc.) then skip this step.
NOTE: If you are hosting your Ubuntu instance locally your internet router may need to be configured to allow incoming traffic on these ports as well.
$ sudo ufw allow 30303
Allow Nimbus
Allows P2P connections with peers for actions on the beacon node (ports 9000/TCP and 9000/UDP).
NOTE: If you are hosting your Ubuntu instance locally your internet router and/or firewall will need to be configured to allow incoming traffic on these ports as well.
$ sudo ufw allow 9000
Allow Grafana
Allows incoming requests to the Grafana web server (port 3000/TCP).
$ sudo ufw allow 3000/tcp
Allow Prometheus (Optional)
If you want direct access to the Prometheus data service you can open up port 9090/TCP as well. This is not necessary if you are solely using Grafana to view the data. I did not open this port.
$ sudo ufw allow 9090/tcp
Now enable the firewall and check to verify the rules have been correctly configured.
$ sudo ufw enable
$ sudo ufw status numbered
Output should look something like this.

Step 5— Configure Timekeeping
Ubuntu has time synchronization built in and activated by default using systemd’s timesyncd service. Verify it’s running correctly.
$ timedatectl
If the NTP service
is not active
then run:
$ sudo timedatectl set-ntp on
Output should look like this:

You should only be using a single keeping service. If you were using NTPD from a previous installation you can check if it exists and remove it using the following commands.
$ ntpq -p
$ sudo apt-get remove ntp
Step 6— Install and Run Go Ethereum Node
Install and configure an Ethereum 1.0 node that the Nimbus beacon node will connect to. If you’d rather use a node hosted by a 3rd party (Infura, Alchemy, etc.) then skip this step.
Install Go Ethereum
Go Ethereum recommends using PPA’s (Personal Package Archives).
$ sudo add-apt-repository -y ppa:ethereum/ethereum
Update the packages and install the latest stable version.
$ sudo apt update
$ sudo apt install geth
Run Go Ethereum as a Background Service
Create an account for the service to run under. This type of account can’t log into the server.
$ sudo useradd --no-create-home --shell /bin/false goeth
Create the data directory for the Eth1 chain. This is required for storing the Eth1 node data. Use the -p
option to create the full path.
$ sudo mkdir -p /var/lib/goethereum
Set directory permissions. The goeth
account needs permission to modify the data directory.
$ sudo chown -R goeth:goeth /var/lib/goethereum
Create a systemd service file to store the service config. We will use the config file to tell systemd to run the geth
process.
$ sudo nano /etc/systemd/system/geth.service
Paste the following service configuration into the file.
[Unit]
Description=Ethereum go client
After=network.target
Wants=network.target[Service]
User=goeth
Group=goeth
Type=simple
Restart=always
RestartSec=5
ExecStart=geth --goerli --ws --datadir /var/lib/goethereum[Install]
WantedBy=default.target
The --goerli
flag is used to target the Göerli test network and the --ws
flag is to expose a web socket endpoint (ws://127.0.0.1:8546) that the beacon node will connect to.
Check the screen shot below for reference. Your file should look like that. Exit and save.

Reload systemd to reflect the changes.
$ sudo systemctl daemon-reload
Start the service and check to make sure it’s running correctly.
$ sudo systemctl start geth
$ sudo systemctl status geth
Output should look like this.

If you did everything right, it should say active (running) in green text. If not then go back and repeat the steps to fix the problem. Press Q to quit.
Enable the geth service to automatically start on reboot.
$ sudo systemctl enable geth
The Go Ethereum node will begin to sync. You can follow the progress by running the journal command. Press Ctrl+C to quit.
$ sudo journalctl -f -u geth.service
Sometimes it can take a while to find peers to sync. If so, you can add some peers to help things along. Go here for the latest list and modify the geth service as follows:
$ sudo systemctl stop geth
$ sudo nano /etc/systemd/system/geth.service
Modify the ExecStart line and add the --bootnodes
flag with a few of the latest peers (comma separated).
ExecStart=geth --goerli --http --datadir /var/lib/goethereum --bootnodes "enode://46add44b9f13965f7b9875ac6b85f016f341012d84f975377573800a863526f4da19ae2c620ec73d11591fa9510e992ecc03ad0751f53cc02f7c7ed6d55c7291@94.237.54.114:30313,enode://119f66b04772e8d2e9d352b81a15aa49d565590bfc9a80fe732706919f8ccd00a471cf8433e398c55c4862aadb4aadf3a010201483b87e8358951698aa0b6f07@13.250.50.139:30303"
Save the file and exit. Restart the service and observe.
$ sudo systemctl daemon-reload
$ sudo systemctl start geth
$ sudo journalctl -f -u geth.service
Once it gets started the output should look like this.

NOTE: You should wait for the node sync to complete before you run the beacon node. You can see the latest block here.
For example, the screen shot above shows the node is processing block number=498880
and looking at the screen shot below (from here), we can see the latest block number is 3391213
. So based on that we still have a while to go before completing the sync.

Next we will prepare the Nimbus client. If you want to check the status of the Geth sync you can do so at any time by running sudo journalctl -fu geth.service
.
NOTE: It is necessary to follow a specific series of steps to update Geth. See Appendix A — Updating Geth for further information.
Step 7 — Install Nimbus Dependencies
A number of dependencies Developer tools (C compiler, Make, Bash, Git) are required to build the Nimbus client.
$ sudo apt-get install build-essential git
Step 8— Clone and Build Nimbus
Now we’re ready to build Nimbus. The Nimbus build produces a nimbus_beacon_node
binary. We execute the binary with different subcommands or flags to get the functionality we need. E.g.:
nimbus_beacon_node deposits import
will import validator keys into the client wallet.
nimbus_beacon_node --network=prater
will run a beacon node instance connected to the Prater network.
Clone the Nimbus main repository.
$ cd ~
$ git clone https://github.com/status-im/nimbus-eth2
$ cd nimbus-eth2
Use Make to compile the Nimbus binary.
$ make nimbus_beacon_node
Output looks like this.

Depending on your hardware it can take a while to build. Good time to get a fresh beverage and hydrate. Maybe check out a few of my other articles.
If the build succeeds then continue. If not get help on the Nimbus Discord.
Step 9— Copy the Nimbus Binary
Copy the compiled nimbus_beacon_node
binary to the /usr/local/bin
directory. The Nimbus service will run it from there.
$ sudo cp /$HOME/nimbus-eth2/build/nimbus_beacon_node /usr/local/bin
NOTE: You will need to do this step each time you pull/build a new version of the
nimbus_beacon_node
binary. See Appendix B — Updating Nimbus at the end of this guide.
Step 10 — Import Validator Keys
The validator wallet is created by importing the keystore-m
JSON files. We generated these files in Step 1. You may need to copy the files to your staking machine. You can do this using a USB drive (if your server is local), or via secure FTP (SFTP). Place them here for convenience: $HOME/eth2deposit-cli-256ea21-linux-amd64/validator_keys
. Create the directories if necessary.
First, create a directory to store the validator data and give the current user permissions to access it. The current user needs access because they will be doing the import. Change <yourusername>
to your logged in username.
$ sudo mkdir -p /var/lib/nimbus
$ sudo chown -R <yourusername>:<yourusername> /var/lib/nimbus
Set up the correct permissions on the folder. Enforced by the wallet creation process. Applies permissions to the data folder.
$ sudo chmod 700 /var/lib/nimbus
$ ls -dl /var/lib/nimbus
Should look like this:

Next, run the validator key import process. The nimbus_beacon_node deposits import
function. We will need to provide the directory where the generated keystore-m
files are located. E.g. $HOME/eth2deposit-cli-256ea21-linux-amd64/validator_keys
.
$ cd ~
$ cd /usr/local/bin
$ nimbus_beacon_node deposits import --data-dir=/var/lib/nimbus $HOME/eth2deposit-cli-256ea21-linux-amd64/validator_keys
The --data-dir
flag specifies the location to output the wallet data.
You will be asked to provide the password for the validator keys. This is the password you set when you created the keys during Step 1.
Output should look like:

That’s it! Now that the validator keys have been imported we will set up the Nimbus client to run as a service.
NOTE: After completing this guide, it is necessary to follow a specific series of steps to add an additional validator. See Appendix C — Adding Validators for further information.
Step 11 — Configure the Beacon Node and Validator
We will run Nimbus as a service so if the system restarts the process will automatically start back up again.
Setup Accounts and Directories
Create an account for the beacon node to run under. This type of account can’t log into the server.
$ sudo useradd --no-create-home --shell /bin/false nimbus
Set directory permissions. We created a data directory (/var/lib/nimbus
) in the previous step. The nimbus
account needs permission to modify that data directory.
$ sudo chown -R nimbus:nimbus /var/lib/nimbus
$ ls -dl /var/lib/nimbus
Your user account can no longer access the directory. Should look like this:

Create and Configure the Service
Create a systemd service file to store the service config.
$ sudo nano /etc/systemd/system/nimbus.service
Paste the following into the file.
[Unit]
Description=Nimbus Beacon Node
Wants=network-online.target
After=network-online.target[Service]
Type=simple
User=nimbus
Group=nimbus
Restart=always
WorkingDirectory=/var/lib/nimbus
Environment="ClientIP=$(curl -s v4.ident.me)"
ExecStart=/bin/bash -c '/usr/local/bin/nimbus_beacon_node --network=prater --data-dir=/var/lib/nimbus --web3-url=ws://127.0.0.1:8546 --metrics --metrics-port=8008 --rpc --rpc-port=9091 --nat=extip:${ClientIP} --validators-dir=/var/lib/nimbus/validators --secrets-dir=/var/lib/nimbus/secrets --log-level=INFO --log-file=/var/lib/nimbus/beacon_node.log'[Install]
WantedBy=multi-user.target
Replace the --web3-url
if you are using a remote or third party Eth1 node. If you created the Eth1 node locally (via Step 6), you don’t need to change this value.
The flags supplied are:
--network
— the network the client is connecting to. In this case, prater.
--data-dir
— the directory to store the beacon node and validator data.
--web3-url
— the web socket (ws) URL to the Eth1 node (local or remote).
--metrics
— toggles the metrics server on.
--metrics-port
— redundant since it’s set to the default, but included for convenience. Must match the Nimbus metrics port in the Prometheus configuration file.
--rpc
— toggles the RPC API on.
--rpc-port
— required to avoid conflicting with Prometheus.
--nat
— the external IP address of your server. We use an Environment variable Environment="ClientIP=$(curl -s v4.ident.me)"
to get the client IP address because ExecStart doesn’t allow the call in-line. Using --nat=extip:${ClientIP}
is the work-around.
--validators-dir
— the directory where the validator key data is located.
--secrets-dir
— the directory where the validator key secrets are located.
--log-level
— the logging verbosity level. INFO
is used for performance reasons.
--log-file
— required so the service can create the log-file. Path must match the service WorkingDirectory
.
Check the screen shot below for reference. Your file should look like that. Exit and save.

Reload systemd to reflect the changes.
$ sudo systemctl daemon-reload
NOTE: If you are running a local Eth1 node (see Step 6) you should wait until it fully syncs before starting the Nimbus service. Check progress here:
sudo journalctl -fu geth.service
Start the service and check to make sure it’s running correctly.
$ sudo systemctl start nimbus
$ sudo systemctl status nimbus
Output should look like this.

If you did everything right, it should say active (running) in green text. If not then go back and repeat the steps to fix the problem. Press Q to quit.
Enable the service to automatically start on reboot.
$ sudo systemctl enable nimbus
The beacon-chain will begin to sync. It may take several hours for the node to fully sync. You can check the progress by running the journal command. Press Ctrl+C to quit.
$ sudo journalctl -fu nimbus.service
The journal output is similar to this:
Nov 24 22:25:56 ETH-STAKER-001 bash[65560]: INF 2020-11-24 22:25:31.197+00:00 Slot start topics="beacnde" tid=65560 file=nimbus_beacon_node.nim:473 lastSlot=46326 scheduledSlot=46327 beaconTime=6d10h25m24s197ms907us264ns peers=1 head=1e6df25a:242 headEpoch=7 finalized=542c17b2:128 finalizedEpoch=4
Nov 24 22:25:56 ETH-STAKER-001 bash[65560]: NOT 2020-11-24 22:25:31.203+00:00 Syncing in progress; skipping validator duties for now topics="beacval" tid=65560 file=validator_duties.nim:519 slot=46327 headSlot=242
Nov 24 22:25:56 ETH-STAKER-001 bash[65560]: INF 2020-11-24 22:25:31.203+00:00 Slot end topics="beacnde" tid=65560 file=nimbus_beacon_node.nim:559 slot=46327 nextSlot=46328 head=1e6df25a:242 headEpoch=7 finalizedHead=542c17b2:128 finalizedEpoch=4
Nov 24 22:25:56 ETH-STAKER-001 bash[65560]: NOT 2020-11-24 22:25:34.396+00:00 Reached new finalization checkpoint topics="chaindag" tid=65560 file=chain_dag.nim:910 finalizedHead=6ad92bbe:189@192 heads=1 newHead=23e933aa:256
To determine the distance between current and head, you can compare the headEpoch
to the current epoch on the prater.beaconcha.in site.
For example, the journal output above shows the node is processing headEpoch: 7
and looking at the screen shot below, we can see the latest epoch is 34,014
. So based on that we still have a while to go before completing the sync.

Now your beacon chain is running as a service. Congratulations!
NOTE: The validator(s) will automatically start attesting/proposing once the beacon node has fully synced.
You can check the status of your validator(s) via prater.beaconcha.in. Simply do a search for your validator public key(s) or search using your MetaMask wallet address. It may be a while before they appear on the site.
Step 12 — Fund the Validator Keys
Now that your set up is up and running, to actually being staking on the Prater testnet you will need to deposit your 32 Göerli ETH.
NOTE: If you have already submitted your staking deposits you can skip this step.
Get Göerli ETH
Each validator requires a deposit of 32 Göerli ETH. You will need sufficient Göerli ETH in your MetaMask wallet to fund each validator. For example if you plan to run 2 validators you will need to have (2 x 32) = 64 Göerli ETH plus some extra to cover the gas fees. There are two ways to get Göerli ETH.
Method 1 — Request From Faucet (max 37.5 ETH)
- Go to a computer with the MetaMask browser extension installed.
- Click on MetaMask and log in.
- Using the dropdown at the top, select the Göerli Test Network.
- Click on the account name to copy your Göerli ETH wallet address.
- Using your address, get Göerli ETH from the authenticated faucet (requires posting on a social account such as Facebook or Twitter).
Method 2 — Request Via Discord
Using this method, the bot will do the deposit for you. Follow this section up until the point where you upload your deposit_data-[timestamp].json
file, then go here (requires joining the EthStaker discord) and follow the instructions to complete the deposit.
Complete the Launchpad
This step involves depositing the required amount of Göerli ETH to the Prater testnet staking contract. This is done in a web browser running MetaMask via the Eth2.0 Launchpad website.
NOTE: If this guide was for mainnet (it’s not) you would wait until your Eth1 node and beacon node have fully synced before proceeding with the deposit. If they have not then your validator would be inactive and you would be subject to inactivity penalties.
Go here: prater.launchpad.ethereum.org
Click on Become a Validator, click through the warning steps and continue through the screens until you get to the Generate Key Pairs section. Select the number of validators you are going to run. Choose a value that matches the number of validators you created in Step 1.

Scroll down, check the box, and click continue.

You will be asked to upload the deposit_data-[timestamp].json
file. We generated this file in Step 1. You may need to copy the file to the computer you are running the launchpad from. There are no security concerns copying the file. Browse or drag the file to upload and click continue.

At this point, if you are using the EthStaker Discord method to fund your validator(s) (Method 2 as described at the beginning of this step), head over to here now to do the deposit and return to complete the guide from the next step.
Otherwise, it is assumed you have sufficient Göerli ETH in your wallet to fund your validator(s). Continue.
Connect your wallet. Choose MetaMask, log in, select the account where you have your Göerli ETH on the Göerli Test Network and click Continue.

WARNING: Be absolutely 100% sure you have selected the Göerli Test Network in MetaMask. DO NOT sent real ETH to the Prater testnet.
Your MetaMask balance will be displayed. The site will allow you to continue if you have selected the Göerli Test Network and you have sufficient Göerli ETH balance.

A summary shows the number of validators and total amount of Göerli ETH required. Tick the boxes if you agree and click continue.

Click on Initiate All Transactions.

This will pop open multiple instances of MetaMask, each with a 32 Göerli ETH transaction request to the Prater testnet deposit contract. Confirm each transaction.

Once all the transactions have successfully completed you are done!

Congratulations are due!

There is a checklist at the end of the process. Lots of good information there. Take a look.

Check the Status of Your Validators
Newly added validators can take a while (hours to days) to activate. You can check the status of your keys with these steps:

- Copy your Göerli Test Network MetaMask wallet address.
- Go here: prater.beaconcha.in
- Search for your key(s) using your wallet address.

Digging into a specific validator we see a Status section that provides an estimate until activation for each validator.

That’s it. We have a functioning beacon-chain and validator and our testnet deposit is in. Once your deposit is active you will begin staking and earning rewards. Congratulations: you are awesome!
Step 13 — Monitoring: Install Prometheus
Prometheus is an open-source systems monitoring and alerting toolkit. It runs as a service on your Ubuntu server and its job is to capture metrics. More information here.
We are going to use Prometheus to expose runtime data from the beacon-chain and validator as well as instance specific metrics.
Create User Accounts
Accounts for the services to run under. These accounts can’t log into the server.
$ sudo useradd --no-create-home --shell /bin/false prometheus
$ sudo useradd --no-create-home --shell /bin/false node_exporter
Create Directories
Program and data directories.
$ sudo mkdir /etc/prometheus
$ sudo mkdir /var/lib/prometheus
Set directory ownership. The prometheus
account will manage these.
$ sudo chown -R prometheus:prometheus /etc/prometheus
$ sudo chown -R prometheus:prometheus /var/lib/prometheus
Download Prometheus software
Adjust the version number to the latest version from the Prometheus download page. Rpi users be sure to get the ARM binary.
$ cd ~
$ curl -LO https://github.com/prometheus/prometheus/releases/download/v2.29.2/prometheus-2.29.2.linux-amd64.tar.gz
Unpack the archive. It contains two binaries and some content files.
$ tar xvf prometheus-2.29.2.linux-amd64.tar.gz
Copy the binaries to the following locations.
$ sudo cp prometheus-2.29.2.linux-amd64/prometheus /usr/local/bin/
$ sudo cp prometheus-2.29.2.linux-amd64/promtool /usr/local/bin/
Set directory ownership. The prometheus
account will manage these.
$ sudo chown -R prometheus:prometheus /usr/local/bin/prometheus
$ sudo chown -R prometheus:prometheus /usr/local/bin/promtool
Copy the content files to the following locations.
$ sudo cp -r prometheus-2.29.2.linux-amd64/consoles /etc/prometheus
$ sudo cp -r prometheus-2.29.2.linux-amd64/console_libraries /etc/prometheus
Set directory and file (-R) ownership. The prometheus
account will manage these.
$ sudo chown -R prometheus:prometheus /etc/prometheus/consoles
$ sudo chown -R prometheus:prometheus /etc/prometheus/console_libraries
Remove the downloaded archive.
$ rm -rf prometheus-2.29.2.linux-amd64.tar.gz prometheus-2.29.2.linux-amd64
Edit the Configuration File
Prometheus uses a configuration file so it knows where to scrape the data from. We will set this up here.
Open the YAML config file for editing.
$ sudo nano /etc/prometheus/prometheus.yml
Paste the following into the file taking care not to make any additional edits and exit and save the file.
global:
scrape_interval: 15s
evaluation_interval: 15sscrape_configs:
- job_name: 'nimbus'
static_configs:
- targets: ['localhost:8008']
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
The scrape_configs define the output target for the different job names. The node_exporter
is for metrics related to the server instance itself (memory, CPU, disk, network etc.). We will install and configure node_exporter below.
Set ownership for the config file. The prometheus account will own this.
$ sudo chown -R prometheus:prometheus /etc/prometheus/prometheus.yml
Finally, let’s test the service is running correctly.
$ sudo -u prometheus /usr/local/bin/prometheus \
--config.file /etc/prometheus/prometheus.yml \
--storage.tsdb.path /var/lib/prometheus/ \
--web.console.templates=/etc/prometheus/consoles \
--web.console.libraries=/etc/prometheus/console_libraries
Output should look something like this. Press Ctrl + C to exit.
level=info ts=2021-09-06T16:57:40.941Z caller=main.go:784 msg="Server is ready to receive web requests."
Set Prometheus to Auto-Start as a Service
Create a systemd service file to store the service config which tells systemd to run Prometheus as the prometheus user, with the configuration file located in the /etc/prometheus/prometheus.yml directory, and to store its data in the /var/lib/prometheus directory.
$ sudo nano /etc/systemd/system/prometheus.service
Paste the following into the file. Exit and save.
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target[Service]
Type=simple
User=prometheus
Group=prometheus
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/prometheus \
--config.file /etc/prometheus/prometheus.yml \
--storage.tsdb.path /var/lib/prometheus/ \
--web.console.templates=/etc/prometheus/consoles \
--web.console.libraries=/etc/prometheus/console_libraries[Install]
WantedBy=multi-user.target
Reload systemd to reflect the changes.
$ sudo systemctl daemon-reload
And then start the service with the following command and check the status to make sure it’s running correctly.
$ sudo systemctl start prometheus
$ sudo systemctl status prometheus
Output should look something like this.

If you did everything right, it should say active (running) in green. If not then go back and repeat the steps to fix the problem. Press Q to quit.
Lastly, enable Prometheus to start on boot.
$ sudo systemctl enable prometheus
Step 14 — Monitoring: Install Node Exporter
Prometheus will provide metrics about the beacon chain and validators. If we want metrics about our Ubuntu instance, we’ll need an extension called Node_Exporter. You can find the latest stable version here if you want to specify a different version below. Rpi users remember to get the ARM binary.
$ cd ~
$ curl -LO https://github.com/prometheus/node_exporter/releases/download/v1.2.2/node_exporter-1.2.2.linux-amd64.tar.gz
Unpack the downloaded software.
$ tar xvf node_exporter-1.2.2.linux-amd64.tar.gz
Copy the binary to the /usr/local/bin directory and set the user and group ownership to the node_exporter user we created above.
$ sudo cp node_exporter-1.2.2.linux-amd64/node_exporter /usr/local/bin
$ sudo chown -R node_exporter:node_exporter /usr/local/bin/node_exporter
Remove the downloaded archive.
$ rm -rf node_exporter-1.2.2.linux-amd64.tar.gz node_exporter-1.2.2.linux-amd64
Set Node Exporter to Auto-Start as a Service
Create a systemd service file to store the service config which tells systemd to run Node_Exporter as the node_exporter user.
$ sudo nano /etc/systemd/system/node_exporter.service
Paste the following into the file. Exit and save.
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter[Install]
WantedBy=multi-user.target
Reload systemd to reflect the changes.
$ sudo systemctl daemon-reload
And then start the service with the following command and check the status to make sure it’s running correctly.
$ sudo systemctl start node_exporter
$ sudo systemctl status node_exporter
Output should look something like this.

If you did everything right, it should say active (running) in green. If not then go back and repeat the steps to fix the problem. Press Q to quit.
Finally, enable Node Exporter to start on boot.
$ sudo systemctl enable node_exporter
Test Prometheus and Node Exporter (Optional)
Everything should be ready to go. You may optionally test the functionality by opening a port in the firewall (see Step 4) and on a machine with a web browser, browsing to http://<yourserverip>:9090
. From there you can run queries to view different metrics. For example try this query to see how much memory is free in bytes:
http://<yourserverip>:9090/new/graph?g0.expr=node_memory_MemFree_bytes&g0.tab=1&g0.stacked=0&g0.range_input=1h
Results should look something like this:

Step 15 —Monitoring: Install Grafana
While Prometheus is our data source, Grafana is going provide our reporting dashboard capability. Let’s install it and configure a dashboard.
We will install using an APT repository because it is easier to install and update. Grafana is available in the official Ubuntu packages repository, however the version of Grafana there may not be the latest, so we will use Grafana’s official repository.
Download the Grafana GPG key with wget, then pipe the output to apt-key. This will add the key to your APT installation’s list of trusted keys.
$ wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
Add the Grafana repository to the APT sources.
$ sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
Refresh the apt cache.
$ sudo apt update
Make sure Grafana is installed from the repository.
$ apt-cache policy grafana
Output should look like this.
grafana:
Installed: (none)
Candidate: 8.1.2
Version table:
8.1.2 500
500 https://packages.grafana.com/oss/deb stable/main amd64 Packages
8.1.1 500
500 https://packages.grafana.com/oss/deb stable/main amd64
...
Verify the version at the top matches the latest version shown here. Then proceed with the installation.
$ sudo apt install grafana
Start the Grafana server and check the status to make sure it’s running correctly.
$ sudo systemctl start grafana-server
$ sudo systemctl status grafana-server
Output should look something like this.

If you did everything right, it should say active (running) in green. If not then go back and repeat the steps to fix the problem. Press Q to quit.
Enable Grafana to start on boot.
$ sudo systemctl enable grafana-server
Configure Grafana Login
Great job on getting this far! Now that you have everything up and running you can go to http://<yourserverip>:3000/
in a browser and the Grafana login screen should come up.
Enter admin
for the username and password. It will prompt you to change your password and you should definitely do that.
Configure the Grafana Data Source
Let’s configure a datasource. Move your mouse over the gear icon on the left menu bar. A menu will pop-up — choose Data Sources
.

Click on Add Data Source
and then choose Prometheus
. Enter http://localhost:9090
for the URL then click on Save & test
.


Import a Grafana Dashboard
Now let’s import a dashboard. Move your mouse over the +
icon on the left menu bar. A menu will pop-up - choose Import
.
Paste the JSON from here (copy from raw) and click Load
then Import
. You should be able to view the dashboard.

Alerts are also available through Telegram and Discord. See here for instructions.
Final Remarks and Recommended Next Steps
Thanks for the opportunity. Hopefully this guide was helpful for you.
Next steps:
- Reboot your machine and make sure the services come back up.
- Understand how to update the client and server software.
- Use
htop
to monitor resources on the local machine. - Get familiar with beaconcha.in so you can monitor your validators. They offer alerting (via email — sign up required) and monitoring.
- Join the Ethstaker and Nimbus Discord for important notifications.
- Share any feedback for this guide on Discord, Twitter, or Reddit.
- Help others with their setup on the Ethstaker discord.
- Share this guide with your friends!
- Tips appreciated: somer.eth
Further Reading
It is strongly recommended that you evaluate information from as many sources as possible. These are additional resources to help familiarize yourself with staking on Eth2.
The author has not tested or verified these resources. Use at your own risk.
- Client team official documentation Prysm | Lighthouse | Teku | Nimbus
- /r/EthStaker Sticky
- Unofficial docker environment for Ethereum 2.0 clients
- Setup a Validator on Eth2 Testnet Prater
- Setup an Eth2 Mainnet Validator System on Ubuntu
- Guide | How to setup a validator on ETH2 mainnet
- Guide | Security Best Practices for a ETH2 validator beaconchain node
- Additional Monitoring for ETH2 Staking Nodes
- Mobile App Monitoring with Beaconcha.in
- Guide on how to do monitoring for an Ethereum validator
- Guide on how to do alerting for an Ethereum validator
- Telegram Service for Ethereum 2.0 Staking
Appendix A — Updating Geth
If you need to update to the latest version of Geth follow these steps:
$ sudo systemctl stop geth
$ sudo systemctl stop nimbus
$ sudo apt update && upgrade
$ sudo systemctl start geth
$ sudo systemctl status geth # <-- Check for errors
$ sudo journalctl -f -u geth # <-- Monitor
$ sudo systemctl start nimbus
$ sudo systemctl status nimbus # <-- Check for errors
$ sudo journalctl -f -u nimbus.service # <-- Monitor
Appendix B— Updating Nimbus
If you need to update the code due to changes in the Git repository follow these steps to get the latest files and build your binaries:
$ cd ~
$ cd nimbus-eth2
$ git pull && make update
$ make nimbus_beacon_node
Next we stop the beacon chain service and copy the binaries over to the /usr/local/bin
directory and then start the services again.
$ sudo systemctl stop nimbus
$ sudo cp /$HOME/nimbus-eth2/build/nimbus_beacon_node /usr/local/bin
$ sudo systemctl start nimbus
$ sudo systemctl status nimbus # <-- Check for errors
$ sudo journalctl -fu nimbus.service # <-- Monitor
That’s it, the services have been updated.
Appendix C — Adding Validators
If you want to add one or more validators to your existing validator wallet use the following steps.
NOTE: This appendix assumes that you have already followed the guide and completed all of the steps. Do not use this section to add validators to an empty validator wallet/incomplete setup.
Generate Deposit Data
You will need to generate deposit data for your new validators. This will be used to add the new validators to your existing wallet.
Go here to get the “Latest release” of the deposit command line interface (CLI) app.
Transfer the binary to a USB stick and copy to an air-gapped machine for safety (recommended), or if not available, copy to a machine that is not connected to the net (not recommended).
When ready, run the file in a terminal window (or CMD in Windows) to continue using the commands below.
The existing-mnemonic
command is used to re-generate or derive new keys from your existing mnemonic. You will need to supply your mnemonic phrase to do this, hence the security requirements.
On Linux/Mac:
./deposit existing-mnemonic --validator_start_index <ValidatorStartIndex> --num_validators <NumberOfValidators> --chain prater
On Windows:
deposit.exe existing-mnemonic --validator_start_index <ValidatorStartIndex> --num_validators <NumberOfValidators> --chain prater
Replace <ValidatorStartIndex>
with the start index of the new validator(s) you are adding. For example: If you have 3 existing validators (#0, #1, #2) and you want to add two more, you would specify 3
(being the next number in the sequence) as the start index. E.g. --validator_start_index 3
.
NOTE: Double check the start index. Be sure you use the correct value.
Replace <NumberOfValidators>
with the number of validators you want to fund. Each validator will require a 32 Göerli ETH deposit to fund. E.g. from the example above, we are adding two new validators: --num_validators 2
.

Enter your mnemonic that you should have stored safely after creating your initial validator(s).

You will be asked to enter your validator keystore password. This password was set in Step 1. You can create a different password here, but it is recommended for simplicity to use the same password as the original keystore. Once you have confirmed your keystore password your validator keys will be created.

The newly created validator keys and deposit data file are created at the specified location. The contents of the folder are shown below.

Notes about the files:
- The newer
deposit_data-[timestamp].json
file contains the public keys for the newly added validators and information about the staking deposit. This file will be used to complete the ETH deposit process later on. - The newly created
keystore-m...json
files contain the encrypted validator signing key. There is one keystore-m per additional validator that you are funding. These will be imported into the Nimbus validator wallet for use while staking. You will copy these files over to the Ubuntu server (if not already there) later.
DO NOT DEPOSIT any ETH at this moment.
It is important to complete and verify your staking setup first. If the ETH deposits become active and your staking setup is not ready you will start receiving penalties for non-activity. Let’s do that next.
Copy the Validator Keystore Files
If you generated the validator keystore-m…json
file(s) on a machine other than your Ubuntu server you will need to copy the file(s) over to your home directory. You can do this using a USB drive (if your server is local), or via secure FTP (SFTP).
Place the files here: $HOME/eth2deposit-cli/validator_keys
. Create the directories if necessary.
Import Keystore Files into the Validator Wallet
We are now ready to import the keystore-m…json
file(s) into our existing validator wallet.
First stop the validator. This is going to cause your validator to miss some attestations, but it is unavoidable. The loss of income is generally small.
$ sudo systemctl stop nimbus
The current logged in user will need access to the validator wallet because they will be performing the import. Change <yourusername>
to the logged in username.
$ sudo chown -R <yourusername>:<yourusername> /var/lib/nimbus
Run the validator key import process. You will need to provide the directory where the generated keystore-m files are located. E.g. $HOME/eth2deposit-cli/validator_keys
.
$ cd ~
$ cd /usr/local/bin
$ nimbus_beacon_node deposits import --data-dir=/var/lib/nimbus $HOME/eth2deposit-cli-256ea21-linux-amd64/validator_keys
The --data-dir
flag specifies the location to output the wallet data.
You will be asked to provide the password for the validator keys. This is the password you set when you created the keys above.
Output should look like this:

Before we can start up the client we will need to reset the user permissions on the data folder so the client can access it.
$ sudo chown -R nimbus:nimbus /var/lib/nimbus
And then finally start up the client and check for errors.
$ sudo systemctl start nimbus
$ sudo systemctl status nimbus # <-- Check for errors
$ sudo journalctl -fu nimbus.service # <-- Monitor
The monitor output should show the public keys that have been loaded from the validator wallet for validation duties.
Now that the validators have been imported into your validator wallet and ready to perform duties, you will need to go over to Step 12 — Fund the Validator Keys above and fund the new validators via the Launchpad. You will need to upload the deposit_data-[timestamp].json
file that was created earlier in this section.
NOTE: The new validators will not be fully functional until you complete Step 12 and the validators clear the activation queue.
Appendix D — Exiting Validators
It is good practice to exit your validators if you are no longer running them. This helps keeps the testnet participation rates up. Once you exit your validators they cannot validate again with the same key.
To exit, run the following commands. Replace ValidatorPublicKey
with the public key of the validator you wish to exit.
$ cd ~
$ cd /usr/local/bin
$ nimbus_beacon_node deposits exit --validator=ValidatorPublicKey --data-dir=/var/lib/nimbus
NOTE: It may take some time for the validators to exit. You may be able to to check the status of the exit by searching for the validator key on prater.beaconcha.in. If the chain isn’t finalizing the exit will not work. Once the exit succeeds you can stop your services, if necessary.
Appendix E — Expanding the Logical Volume
There are cases where Ubuntu is provisioning only 200GB of a larger SSD causing users to run out of disk space when syncing their Eth1 node. The error message is similar to:
Fatal: Failed to register the Ethereum service: write /var/lib/goethereum/geth/chaindata/383234.ldb: no space left on device
To address this issue, assuming you have a SSD that is larger than 200GB, expand the space allocation for the LVM by following these steps:
$ sudo lvdisplay # <-- Check your logical volume size
$ sudo lvm
> lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
> exit
$ sudo resize2fs /dev/ubuntu-vg/ubuntu-lv
$ df -h # <-- Check results
That should resize your disk to the maximum available space.
If you need support on this please check with the EthStaker Discord.