CoinCashew
English
Search
⌃K
Links

Guide | Operation Client Diversity: Migrate Prysm to Teku

Step by step guide on how to switch for the solo home or cloud staker.
🎊
Support us on Gitcoin Grants: We improve this guide with your support!🙏

Complete step by step guide

The following steps align with our mainnet guide. You may need to adjust file names and directory locations where appropriate. The core concepts remain the same.
As per best practices, always try everything on a testnet before doing it for real on mainnet.

🔥
Problem: Why the commotion?

If improving the stability of the beacon chain is not a good enough reason for you to switch from Prysm to either Teku or Nimbus, you also need to consider that due to the design of the beacon chain you will be subject to severe financial penalties if Prysm ever has an issue. ~Lamboshi on Twitter

🚀
Solution: Increase client diversity by migrating to Teku

🚧
How to Migrate from Prysm to Teku

PegaSys Teku (formerly known as Artemis) is a Java-based Ethereum 2.0 client designed & built to meet institutional needs and security requirements. PegaSys is an arm of ConsenSys dedicated to building enterprise-ready clients and tools for interacting with the core Ethereum platform. Teku is Apache 2 licensed and written in Java, a language notable for its materity & ubiquity.

1. Setup Teku CL

Install git.
sudo apt-get install git -y
Install Java 17 LTS
sudo apt update
sudo apt install openjdk-17-jdk -y
Verify Java 17+ is installed.
java --version
Install and build Teku.
mkdir ~/git
cd ~/git
git clone https://github.com/ConsenSys/teku.git
cd teku
./gradlew distTar installDist
This build process may take a few minutes.
Verify Teku was installed properly by displaying the version.
cd $HOME/git/teku/build/install/teku/bin
./teku --version
Copy the Teku binary file to /usr/bin/teku
sudo cp -r $HOME/git/teku/build/install/teku /usr/bin/teku
Teku combines both the beacon chain and validator into one process.
Setup a directory structure for Teku.
sudo mkdir -p /var/lib/teku
sudo mkdir -p /etc/teku
sudo chown $USER:$USER /var/lib/teku
Create your teku.yaml configuration file.
sudo nano /etc/teku/teku.yaml
Paste the following configuration into the file.
# network
network: "mainnet"
initial-state: "https://beaconstate.info/eth/v2/debug/beacon/states/finalized"
# validators
validators-graffiti: "<MY_GRAFFITI>"
# execution engine
ee-endpoint: http://localhost:8551
ee-jwt-secret-file: "/secrets/jwtsecret"
# fee recipient
validators-proposer-default-fee-recipient: "<0x_CHANGE_THIS_TO_MY_ETH_FEE_RECIPIENT_ADDRESS>"
# metrics
metrics-enabled: true
metrics-port: 8008
# database
data-path: "/var/lib/teku"
data-storage-mode: "prune"
  • Replace<0x_CHANGE_THIS_TO_MY_ETH_FEE_RECIPIENT_ADDRESS> with your own Ethereum address that you control. Tips are sent to this address and are immediately spendable, unlike the validator's attestation and block proposal rewards.
  • Replace <MY_GRAFFITI> with your own graffiti message. However for privacy and opsec reasons, avoid personal information. Optionally, leave it blank by deleting the flag option.

🛑
2. Stop and disable Prysm

Stop and disable the Prysm services. Choose your guide.
CoinCashew
SomerEsat
sudo systemctl stop validator beacon-chain
sudo systemctl disable validator beacon-chain
sudo systemctl stop prysmvalidator
sudo systemctl stop prysmbeacon
sudo systemctl disable prysmvalidator
sudo systemctl disable prysmbeacon
Confirm the Prysm validator is stopped by checking the service status.
CoinCashew
SomerEsat
service validator status
service prysmvalidator status
Delete existing Prysm validators keys so that there's no accidental starting of Prysm's validator.
CoinCashew
SomerEsat
sudo rm -rf ~/.eth2validators
sudo rm -rf /var/lib/prysm/validator
As a double check, verify that Prysm validator can't find it's keys by starting the validator again.
CoinCashew
SomerEsat
sudo systemctl start validator
sudo systemctl start prysmvalidator
Observe the logs and check for errors about missing validator keys.
CoinCashew
SomerEsat
journalctl -fu validator
journalctl -fu prysmvalidator
Finally, stop Prysm validator.
CoinCashew
SomerEsat
sudo systemctl stop validator
sudo systemctl stop prysmvalidator
Before continuing - Required Waiting Period !!!
Wait until your validator's last attestation is in a finalized epoch - usually about 15 minutes.
By waiting for a finalized epoch, there's no need to migrate the slashing database.
Confirm that your validator has stopped attesting with block explorer beaconcha.in or beaconscan.com

🧱
3. Update firewall / port forwarding.

Allow Teku ports:
sudo ufw allow 9000/tcp
sudo ufw allow 9000/udp
Delete Prysm firewall rules:
sudo ufw delete allow 13000/tcp
sudo ufw delete allow 12000/udp
Verify that your firewall configuration is correct.
sudo ufw status numbered
Example output of firewall configuration:
To Action From
-- ------ ----
[ 1] 22/tcp ALLOW IN Anywhere # SSH
[ 2] 9000/tcp ALLOW IN Anywhere # eth2 p2p traffic
[ 3] 9000/udp ALLOW IN Anywhere # eth2 p2p traffic
[ 4] 30303/tcp ALLOW IN Anywhere # eth1
[ 5] 22/tcp (v6) ALLOW IN Anywhere (v6) # SSH
[ 6] 9000/tcp (v6) ALLOW IN Anywhere (v6) # eth2 p2p traffic
[ 7] 9000/udp (v6) ALLOW IN Anywhere (v6) # eth2 p2p traffic
[ 8] 30303/tcp (v6) ALLOW IN Anywhere (v6) # eth1
Your router's port forwarding setup or cloud provider settings will need to be updated to ensure your validator's firewall ports are open and reachable.
You'll need to add new port forwarding rules for Teku and remove the existing Prysm port forwarding rules.
Optional - Update your server and reboot for best practice.
sudo apt update && sudo apt upgrade
sudo apt dist-upgrade && sudo apt autoremove
sudo reboot

🗝
4. Import Validator Keys

Copy your validator_keys directory to the data directory we created above and remove the extra deposit_data file. If you no longer have the validator keys on your node, you will need to restore from file backup or restore from secret recovery phrase.
cp -r $HOME/eth2deposit-cli/validator_keys /var/lib/teku
rm /var/lib/teku/validator_keys/deposit_data*
🛑
FINAL WARNING REMINDER !!! Do not start the Teku validator client until you have stopped the Prysm one, or you will get slashed (penalized and exited from the system).
Wait until your validator's last attestation is in a finalized epoch - usually about 15 minutes.
Confirm that your validator has stopped attesting with block explorer beaconcha.in or beaconscan.com
Storing your keystore password in a text file is required so that Teku can decrypt and load your validators automatically.
Replace <my_keystore_password_goes_here> with your keystore password between the single quotation marks and then run the command to save it to validators-password.txt
echo '<my_keystore_password_goes_here>' > $HOME/validators-password.txt
Confirm that your keystore password is correct.
cat $HOME/validators-password.txt
Move the password file and make it read-only.
sudo mv $HOME/validators-password.txt /etc/teku/validators-password.txt
sudo chmod 600 /etc/teku/validators-password.txt
Clear the bash history in order to remove traces of keystore password.
shred -u ~/.bash_history && touch ~/.bash_history
When specifying directories for your validator-keys, Teku expects to find identically named keystore and password files. For example keystore-m_12221_3600_1_0_0-11222333.json and keystore-m_12221_3600_1_0_0-11222333.txt
Create a corresponding password file for every one of your validators.
for f in /var/lib/teku/validator_keys/keystore*.json; do cp /etc/teku/validators-password.txt /var/lib/teku/validator_keys/$(basename $f .json).txt; done
Verify that your validator's keystore and validator's passwords are present by checking the following directory.
ll /var/lib/teku/validator_keys
Add validator-keys configuration to teku.yaml
cat >> /etc/teku/teku.yaml << EOF
validator-keys: "/var/lib/teku/validator_keys:/var/lib/teku/validator_keys"
EOF

🚀
5. Setup and start the Teku service

Run the following to create a unit file to define yourbeacon-chain.service configuration.
cat > $HOME/beacon-chain.service << EOF
# The eth beacon chain service (part of systemd)
# file: /etc/systemd/system/beacon-chain.service
[Unit]
Description = eth beacon chain service
Wants = network-online.target
After = network-online.target
[Service]
User = $USER
ExecStart = /usr/bin/teku/bin/teku -c /etc/teku/teku.yaml
Restart = on-failure
Environment = JAVA_OPTS=-Xmx5g
[Install]
WantedBy = multi-user.target
EOF
Move the unit file to /etc/systemd/system
sudo mv $HOME/beacon-chain.service /etc/systemd/system/beacon-chain.service
Update file permissions.
sudo chmod 644 /etc/systemd/system/beacon-chain.service
Run the following to enable auto-start at boot time and then start your beacon node service.
sudo systemctl daemon-reload
sudo systemctl enable beacon-chain
sudo systemctl start beacon-chain
Syncing the beacon node might take up to 36 hours depending on your hardware. Keep validating using your current Prysm setup until it completes. However, thanks to Teku's Checkpoint sync, you'll complete this step in a few minutes.
Syncing is complete when your beacon node's slot matches that of a block explorer's slot number (i.e. https://beaconcha.in/)
Check the beacon node syncing progress with the following:
journalctl -fu beacon-chain
Check the logs to verify the services are working properly and ensure there are no errors.
#view and follow the log
journalctl -fu beacon-chain
Confirm that your new Teku validator has started attesting with block explorer beaconcha.in or beaconscan.com

🛠 Some helpful systemd commands

🗄 Viewing and filtering logs
#view and follow the log
journalctl -fu beacon-chain
#view log since yesterday
journalctl --unit=beacon-chain --since=yesterday
#view log since today
journalctl --unit=beacon-chain --since=today
#view log between a date
journalctl --unit=beacon-chain --since='2020-12-01 00:00:00' --until='2020-12-02 12:00:00'
🔎
View the status of the beacon chain
sudo systemctl status beacon-chain
🔁
Restart the beacon chain
sudo systemctl restart beacon-chain
🛑
Stop the beacon chain
sudo systemctl stop beacon-chain

📡
6. Update Prometheus and Grafana monitoring

Select your Ethereum execution engine and then re-create your prometheus.yml configuration file to match Teku's metric's settings.
Geth
Besu
Nethermind
OpenEthereum
Erigon
cat > $HOME/prometheus.yml << EOF
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'codelab-monitor'
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'nodes'
metrics_path: /metrics
static_configs:
- targets: ['localhost:8008']
- job_name: 'geth'
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /debug/metrics/prometheus
scheme: http
static_configs:
- targets: ['localhost:6060']
EOF
cat > $HOME/prometheus.yml << EOF
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'codelab-monitor'
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'nodes'
metrics_path: /metrics
static_configs:
- targets: ['localhost:8008']
- job_name: 'besu'
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- localhost:9545
EOF
cat > $HOME/prometheus.yml << EOF
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'codelab-monitor'
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'nodes'
metrics_path: /metrics
static_configs:
- targets: ['localhost:8008']
- job_name: 'nethermind'
scrape_interval: 15s
scrape_timeout: 10s
honor_labels: true
static_configs:
- targets: ['localhost:9091']
EOF
Nethermind monitoring requires Prometheus Pushgateway. Install with the following command.
sudo apt-get install -y prometheus-pushgateway
Pushgateway listens for data from Nethermind on port 9091.
cat > $HOME/prometheus.yml << EOF
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'codelab-monitor'
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'nodes'
metrics_path: /metrics
static_configs:
- targets: ['localhost:8008']
- job_name: 'openethereum'
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets: ['localhost:6060']
EOF
cat > $HOME/prometheus.yml << EOF
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
# Attach these labels to any time series or alerts when communicating with
# external systems (federation, remote storage, Alertmanager).
external_labels:
monitor: 'codelab-monitor'
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'nodes'
metrics_path: /metrics
static_configs:
- targets: ['localhost:8008']
- job_name: 'erigon'
scrape_interval: 10s
scrape_timeout: 3s
metrics_path: /debug/metrics/prometheus
scheme: http
static_configs:
- targets: ['localhost:6060']
EOF
Move it to /etc/prometheus/prometheus.yml
sudo mv $HOME/prometheus.yml /etc/prometheus/prometheus.yml
Update file permissions.
sudo chmod 644 /etc/prometheus/prometheus.yml
Finally, restart the services.
sudo systemctl restart grafana-server prometheus prometheus-node-exporter

Import your new Teku dashboard into Grafana.

  1. 1.
    Open http://localhost:3000 or http://<your validator's ip address>:3000 in your local browser.
  2. 2.
    Login with your credentials
  3. 3.
    Download and save Teku's Dashboard json file.
  4. 4.
    Click Create + icon > Import
  5. 5.
    Add the ETH2 client dashboard via Upload JSON file
Teku by PegaSys Engineering

🌊
7. Clean up Prysm Storage

After a period of stable attestations on Teku, you can safely dispose of the former Prysm files and reclaim disk space.
CoinCashew
SomerEsat
# executables
rm -rf ~/prysm
# Validator Keys
rm -rf ~/.eth2validators
# Beacon Chain Data
rm -rf ~/.eth2
# executables
sudo rm /usr/local/bin/validator
sudo rm /usr/local/bin/beacon-chain
# datadir
sudo rm -rf /var/lib/prysm
# users
sudo deluser prysmbeacon
sudo deluser prysmvalidator
Well done on successfully switching! Cheers to client diversity and a healthy beacon chain.

🙏
Alternative Community Migration Guides