Document history
Date | Changes |
18. November 2020 | Published |
19. November 2020 | Added hardware requirements |
20. November 2020 | Correct 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!
Overview
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:
- Ubuntu 20.04 LTS
- Ethereum 1:
- Ethereum 2:
- Lighthouse
- Prysm (including slasher)
- Teku
- Vouch & Dirk
- Prometheus (metrics collector)
- Grafana (metrics visualizer)
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:
- Basic security on OS level
- Prepare ethereum2-docker-compose to run multi-client staking node
- Use a launchpad wallet to stake with this node
- 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.

… 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.
Firewall
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 https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(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
Engine:
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
containerd:
Version: 1.3.7
GitCommit: 8fba4e9a7d01810a393d5d25a3621dc101981175
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
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 https://github.com/stereum-dev/ethereum2-docker-compose.git 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 ll
You see a couple of files and directories:
Directory/file | Description |
---|---|
compose-examples | Collection of pre-defined docker-compose.yaml and docker-compose.override.yaml files |
config | Config files for all services defined in docker-compose |
data | Persistant data of containers |
launchpad | If you want to import a launchpad wallet, drop your launchpad validator_keys here |
wallets | Sensitive data! This contains the wallets with the accounts for staking |
.env | Settings for running docker-compose files (e. g. versions of docker images) |
edc-* | Small scripts to manage 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.
Grafana
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):
grafana:
container_name: grafana
image: grafana/grafana:${GRAFANA_DOCKER_TAG}
restart: unless-stopped
user: "<your-user-id>"
hostname: grafana
depends_on:
- prometheus
ports:
- 127.0.0.1:3000:3000
volumes:
- ./config/grafana/provisioning:/etc/grafana/provisioning:ro
- ./data/grafana:/var/lib/grafana
networks:
- 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:
cd
Install ethdo (a tool to manage wallets, more flexible than launchpad’s deposit-cli):
GO111MODULE=on go get github.com/wealdtech/ethdo
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
PATH="$PATH:$HOME/go/bin"
fi
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
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.
Vouch
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:
....
accountmanager:
dirk:
endpoints:
- dirk:13141
client-cert: file:///config/certs/vouch.crt
client-key: file:///config/certs/vouch.key
ca-cert: file:///config/certs/ca.crt
accounts:
- <wallet-name>
In the config file above it’s also possible to change the graffiti used for proposed blocks:
graffiti:
static:
value: <your-graffiti-here>
Kick it off, finally!
Ladies and Gentlemen, start the engines (or nodes and services)!
cd /opt/ethereum2-docker-compose ./edc-up.sh
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
Monitoring
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):

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!