Staking Ether on multiple clients

Document history

18. November 2020Published
19. November 2020Added hardware requirements
20. November 2020Correct typos

Important notes & disclaimer

This guide is provided without any warrenty/guarantee (“as is”). Feel free to let us know your feedback! We are happy to apply healthy critique to this guide!


There are several steps to complete a multi-client Ethereum 2.0 staking setup for Pyrmont testnet. This guide uses ethereum2-docker-compose to orchestrate the services. Some (not all) software used in this particular guide:

Hardware recommendations

Keep in mind these hardware recommendations are high because we run 1 Ethereum client and 3 beacon chain clients. Even if you see low hardware usage on a normal testnet the beacon clients will get resource hungry when the beacon chain (Ethereum 2.0) will reach non-finality phases.

  • CPU: 6-core/12-threads – when running on virtualized hardware (like VPS) 12 vCPUs are recommended
  • Memory: 32gb – on various non-finality tests it shoots up to nearly 45gb, although this shouldn’t happen that much anymore because of beacon clients’ optimization
  • Storage: 256gb for testnets (like Pyrmont); 1tb for mainnet (due to larger geth blockchain data)

Guide’s steps

Together we’ll go through the following steps to accomplish staking with multiple clients:

  1. Basic security on OS level
  2. Prepare ethereum2-docker-compose to run multi-client staking node
  3. Use a launchpad wallet to stake with this node
  4. Kick it off, finally!

Basic OS security

Before you begin, here’s a checklist to ensure you start with the needed resources and skills:

  • Basic understanding of Linux or Ubuntu
  • Ubuntu 20.04 installed on a machine you have access to (either physically or via SSH)
  • Basic knowledge of git

(optional – SSH only) Change your authentication method from password to key

Passwords are somewhat easy to guess or bruteforce, ensuring you are using authentication by key when you access your node via SSH is therefore a recommended and easy way to enhance security of your server. However, this is not mandatory if you either don’t expose the SSH port to the internet or don’t use SSH at all (e. g. having physical access only).

Generate SSH authentication keys

If you don’t alreay use putty, download it and execute puttygen.exe


Now let’s generate a key pair by clicking in “Generate”, move your mouse until the progress bar is full. After the generation finished save the public key as well as the private key. Keep the private key safe, don’t expose it to other users or unsafe storage (unencrypted usb stick). Also copy the text in the locked textbox (usually starts with “ssh-rsa….”) and safe it too. You can close the application.

Connect to your Ethereum 2 node with your regular user, edit the file ~/.ssh/authorized_keys by executing nano ~/.ssh/authorized_keys and add the text you copied previously in a new line, looking looking like this:

ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAxdmaA0w//jS56ZpX+Oxv7pmq58+PrKGYAoKeXm3Z5wdw/MrdFwdNf3rKVyv6GX0RXt2xLhqoPlxrW9YRjwsRIYUTh/XQN7/i/kYewtb/hoJZ2I0U2YbutpqBPdSuMbJZY5lSTx2IH/0AOLG2K4w3W+SYhX4pDuAABzzdBg+W+pmI5nJBdk1YheLKYJVtab1VWK0pX8QfdDDo7qwCoSRlFDOzoNNvvTUVvXmRe+Qy6Sr8WT9LN2d/BDm95DzXzXWzs7SsEKP6MbXCpAp25zBzV3Z+Ltu9uws798IE5/kwQtTTe6geC/g6m15TW8nakgX1Yjff6C1P1P89dTsrfUyhdQ== rsa-key-20201118

Exit and save the file (Ctrl+X), to make this file only accessible by your user execute

chmod 600 ~/.ssh/authorized_keys

Use SSH authentication keys

… with putty

After that try to connect to your server using putty with key authentication. Use the setting “Private key file for authentication” and select your previously generated and saved private key file. Don’t forget to enter an IP in the “Session” and click open. Putty will ask you for your username – as usual – after you enter your username you should immediately login without the need of entering a password.

“Private key file for authentication” in Putty
… with ssh command

If you don’t want to use putty but instead the ssh command of Windows 10, create a directory in your home folder with the name .ssh and copy your private key there, don’t forget to rename the private key file to id_rsa. This also works on linux and mac.

Disable password authentication for SSH

We already managed to login via keys, we can now disable password authentication for SSH. To do this, run the following command to edit the necessary file:

sudo nano /etc/ssh/sshd_config

Edit the following things:

  • Uncomment (remove the “#” infront of the line): PubkeyAuthentication yes
  • Find the line with “PasswordAuthentication” and change it to: PasswordAuthentication no

Exit the config file again (Ctrl+X) and restart SSH by entering:

sudo systemctl restart sshd

Check by reconnecting your SSH session, done!

Keep your Ubuntu up-to-date!

Most security vulnerabilities get fixed fast by the maintainers, it`s important to keep your Ubuntu server updated by running:

sudo apt update && sudo apt upgrade -y

It’s not recommeded to do this automatically because there are updates which need guidance in the update process (e. g. which config file to take, etc.). However, running an update once a week isn’t much work and keeps your system safe and stable.


Commonly used firewall is named “ufw“. There’s also a package named “fail2ban” to block certain attacks on your server (e. g. ssh password guessing). Install both by running:

sudo apt install ufw fail2ban

Default settings will do for now. If you want to dig deeper into those two, look them up (links above).

Prepare to run ethereum2-docker-compose

System packages

Start by installing the necessary packages with apt:

sudo apt install git apt-transport-https ca-certificates curl software-properties-common python3-pip python3-docker virtualenv python3-setuptools gnupg2 pass net-tools

This installs:

  • git (source control to download ethereum2-docker-compose)
  • python3 + tooling
  • various other tooling

docker & docker-compose

Next is docker & docker-compose, we need both to run ethereum2-docker-compose:

  • docker: open source containerization plattform
  • docker-compose: defining and running multi-container docker applications

Run the following commands to install the necessary packages (some of them will be downloaded from the docker repository rather than Ubuntu’s main repositories):

curl -fsSL | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] $(lsb_release -cs) stable"
sudo apt update && sudo apt install docker-ce docker-compose

Last but not least, your user needs the privilege to run docker (replace “<your-user>” with your regular user name):

sudo usermod -aG docker <your-user>

Verify install

After successful installation let’s try to get the version of docker installed and you should see something like this:

user@srv:~$ sudo docker version
Client: Docker Engine - Community
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 17:02:36 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:01:06 2020
  OS/Arch:          linux/amd64
  Experimental:     false
  Version:          1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
  Version:          0.18.0
  GitCommit:        fec3683

Prepare ethereum2-docker-compose

Clone repository

The next steps will guide you to install ethereum2-docker-compose in /opt. If you don’t feel comfortable with the path feel free to replace it with any path you might deem more appropriate.

Change directory by running

cd /opt

That was easy, right? Now a bit more heavy stuff:

  • download (in git terms “clone”) the repository
  • change ownership of repository, replace “<your-user>” with your regular username
  • give execution permission to scripts
sudo git clone
sudo chown -R <your-user>:<your-user> ethereum2-docker-compose
chmod 700 /opt/ethereum2-docker-compose/edc-*

Setup multi-client docker-compose

Go to your new Ethereum 2 node and have a look:

cd /opt/ethereum2-docker-compose

You see a couple of files and directories:

compose-examplesCollection of pre-defined docker-compose.yaml and docker-compose.override.yaml files
configConfig files for all services defined in docker-compose
dataPersistant data of containers
launchpadIf you want to import a launchpad wallet, drop your launchpad validator_keys here
walletsSensitive data! This contains the wallets with the accounts for staking
.envSettings for running docker-compose files (e. g. versions of docker images)
edc-*Small scripts to manage docker-compose
Overview of the structure of ethereum2-docker-compose

Because we want to run a multi-client staking node, copy the related files to the projec’s root directory:

cp compose-examples/multiclient-vouch-dirk/docker-compose.yaml docker-compose.yaml
cp compose-examples/multiclient-vouch-dirk/override-examples/docker-compose.limit-resources.override.yaml docker-compose.override.yaml

The docker-compose.yaml contains the service definitions with networking, storage, etc. On the other hand we also copy docker-compose.override.limit-resources.yaml to limit the resources (cpu and memory) of each node so they don’t affect each other when one is having resource exhausting behaviour. The second file (docker-compose.limit-resources.override.yaml) is optional but recommended.


Often times grafana doesn’t start due to permission issues, we’ll resolve this by using your user to run the grafana container. First, find out your user id:

id -u

Remeber or write down this number and edit the docker-compose.yaml:

nano docker-compose.yaml

Now edit the service “grafana” and add “user: …” to it, so it looks something like this (replace “<your-user-id>” with the number you got above):

    container_name: grafana
    image: grafana/grafana:${GRAFANA_DOCKER_TAG}
    restart: unless-stopped
    user: "<your-user-id>"
    hostname: grafana
      - prometheus
      - ./config/grafana/provisioning:/etc/grafana/provisioning:ro
      - ./data/grafana:/var/lib/grafana
      - n_grafana_prometheus
      - n_bridge
    <<: *logging

Exit and save (Ctrl+X) and we are done with the initial preparations! Continue with building your wallets and accounts…

Use a launchpad wallet to stake

Before you read further make sure you finished up the launchpad process! For the latest testnet access Pyrmont’s launchpad.

Install and configure ethdo

First things first, we need some new tooling:

sudo apt install build-essential gcc golang

Go back to your home directory, just in case you hang around ethereum2-docker-compose still:


Install ethdo (a tool to manage wallets, more flexible than launchpad’s deposit-cli):

GO111MODULE=on go get

After successfully installing ethdo you need to manually fix something in your user’s bash profile. Open up the file:

nano ~/.profile

And add the following block at the end of this file to make your bash aware of ethdo:

if [ -d "$HOME/go/bin" ] ; then

Regenerate your wallet and accounts

Ethdo uses wallet names and account names to identify the wallets/accounts. They don’t have any meaning, just keep in mind you need them to configure vouch later on (especially the wallet name). You should also use one account password for all accounts, and one wallet password for all wallets. That makes configuration of dirk easier.

You got your mnemonic phrase of your launchpad wallet ready, let’s put it to use (replace the value of “<mnemonic>” as well as “<wallet-name>” and “<wallet-password>”):

ethdo wallet create --type=hd --mnemonic="<mnemonic>" --wallet="<wallet-name>" --wallet-passphrase="<wallet-password>"

Now recreate your accounts, one by one (repalace “<index>” with the account number, starting with 0; of course all other “<..>” values too, you know the drill):

ethdo account create --account="<wallet-name>/<account-name>" --path=m/12381/3600/<index>/0/0 --wallet-passphrase="<wallet-password>" --passphrase="<account-password>"

Do this for all your wallets and accounts.

Wallet management in your node’s configureation

You got your wallet(s) with all your account(s), we need to copy them to the correct directory and configure dirk as well as vouch to access them, encrypt them and stake with them! Let’s start…


Dirk needs to be able to find the wallets, copy the wallets to the correct location:

cp -r ~/.config/ethereum2/wallets/* /opt/ethereum2-docker-compose/wallets/.

Now edit dirk’s password files, one for accounts and one for wallets. Put the password in there just in plaintext:

nano /opt/ethereum2-docker-compose/config/dirk/passphrases/account-passphrase.txt
nano /opt/ethereum2-docker-compose/config/dirk/passphrases/wallet-passphrase.txt

And dirk is good to go.


Because vouch is explicit it needs to know what wallets and accounts you want to stake with. Edit the config file of vouch:

nano /opt/ethereum2-docker-compose/config/vouch/vouch.yml

And add the wallet’s name at <wallet-name>. If you have multiple wallets then just add another list entry with the next wallet name:


      - dirk:13141
    client-cert: file:///config/certs/vouch.crt
    client-key: file:///config/certs/vouch.key
    ca-cert: file:///config/certs/ca.crt
      - <wallet-name>

In the config file above it’s also possible to change the graffiti used for proposed blocks:

    value: <your-graffiti-here>

Kick it off, finally!

Ladies and Gentlemen, start the engines (or nodes and services)!

cd /opt/ethereum2-docker-compose

Watch your ethereum2 multi client staking node start up!

At first geth needs to catch up, this might take a while. You can check on geth with

docker-compose logs --tail=100 geth

You can do the same with all other services to check how it’s going:

docker-compose logs --tail=100 prysm_beacon
docker-compose logs --tail=100 lighthouse_beacon
docker-compose logs --tail=100 teku_beacon
docker-compose logs --tail=100 vouch
docker-compose logs --tail=100 grafana

For a complete list and a status of services run:

docker-compose ps


You want to know see some basic metrics? No problem! Grafana is running on port 3000 but only accessible via localhost. This means you need to open a SSH tunnel. When working with ssh command use

ssh -L 3000:localhost:3000 <user>@<your-server-ip-or-dns>

For putty, use this setting and click on add, then start your session normally (don’t forget to save):

putty SSH tunnel configuration

Now open a browser and access http://localhost:3000 and use “admin” for username and password. You might want to enter a new more secure password after this, then click on the left menu on “Dashboard” -> “Manage” and click on an existing dashboard.

You can also try to import other dashboards like:

Please keep in mind these dashboards are not designed for a multi-client setup so there might be some issues with them.

Have fun!

Staking Ether on multiple clients
Scroll to top