Supplementary Guide to Staking on Ethereum For Existing Stakers

This is a supplementary guide to my newly released staking guides:

It is ONLY intended for existing stakers — those who used my ORIGINAL Ethereum 2.0 mainnet guides (now deprecated) who are having trouble migrating their setup to a Merge-Ready state using my new guides linked above.

This supplementary guide walks through each client from my original guides and shows you what to change. Assumption is that you used the same directory paths and account names, etc. from my original guides. Also that your validators are loaded and clients are synced, etc. Basically everything should be working per my original guide. If you changed things, like the account or service name, or datadir, then make the necessary adjustments.

Once you have gone through this supplementary guide you should have a:

  • JWT Authentication Token
  • A functioning Merge Ready Geth client (if you are using Geth)
  • A functioning Merge Ready Consensus Client

Once done, you should be at parity with whichever new guide linked above matches your chosen Consensus Client (Lighthouse, Prysm, Nimbus, Teku).

Disclaimer

This article (the guide) is for informational purposes only and does not constitute professional advice. The author does not guarantee accuracy of the information in this article and the author is not responsible for any damages or losses incurred by following this article. A full disclaimer can be found at the bottom of this page — please read before continuing.

Disk Space

If you are running low, especially after moving from an Infura Eth1 setup to installing your own Eth1 (Execution Client) client, this guide explains how to add a new SSD. No warranty — I haven’t tried it myself, so use at your own risk.

JWT Authentication Token

You’ll need this or things wont work. If you haven’t already, create it and then forget about it:

$ sudo mkdir -p /var/lib/jwtsecret
$ openssl rand -hex 32 | sudo tee /var/lib/jwtsecret/jwt.hex > /dev/null

Execution Client

If you haven’t installed an Execution Client (Besu, or Erigon, or Geth, or Nethermind) — basically an Eth1 node — use any of the new guides linked above to install it. Don’t forget to update the firewall to allow port 30303 (see the guide). You’ll need it to be Merge Ready. Infura is no longer an option. The Execution Client requires about 650–700GB disk space fully synced, so make sure your SSD is big enough.

Geth

In my new guides I made some changes to the way Geth is setup. The reasons are:

(a) To bring its setup into alignment with the other Execution clients. My guides try to keep things as consistent as possible. It makes it easier for users to switch between clients and easier for the community to support users who followed the guides.

(b) Get rid of the PPA (Personal Package Archive) installation. Besides being inconsistent, each time you run sudo apt update for any reason, it might try to update the Geth package. Maybe you don’t want to do that. The approach I use in my new guides allows you to easily choose whatever version you would like to install.

To update to the new Geth setup (won’t impact the data directory):

Stop Geth:

$ sudo systemctl stop geth

Remove Geth:

$ sudo apt remove -y geth

Remove Geth PPA:

$ sudo add-apt-repository --remove ppa:ethereum/ethereum

Download latest Geth:

$ cd ~
$ curl -LO https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.10.25-69568c55.tar.gz

Extract it, copy it, clean up.

$ tar xvf geth-linux-amd64-1.10.25-69568c55.tar.gz
$ cd geth-linux-amd64-1.10.25-69568c55
$ sudo cp geth /usr/local/bin
$ cd ~
$ rm geth-linux-amd64-1.10.25-69568c55.tar.gz
$ rm -r geth-linux-amd64-1.10.25-69568c55

Rename the Geth account username and group (goeth -> geth):

$ sudo usermod -l geth goeth
$ sudo groupmod -n geth goeth

Rename the Geth data directory (goethereum -> geth):

$ sudo mv /var/lib/goethereum /var/lib/geth

Give the systemd service permissions to access the data directory:

$ sudo chown -R geth:geth /var/lib/geth

Modify the Geth systemd service config using:

$ sudo nano /etc/systemd/system/geth.service

So that it looks like:

[Unit]
Description=Geth Execution Client (Mainnet)
After=network.target
Wants=network.target
[Service]
User=geth
Group=geth
Type=simple
Restart=always
RestartSec=5
TimeoutStopSec=600
ExecStart=/usr/local/bin/geth --mainnet --datadir /var/lib/geth --authrpc.jwtsecret /var/lib/jwtsecret/jwt.hex
[Install]
WantedBy=default.target

The bits that changed are in bold.

Press <CTRL> + X then Y then <ENTER> to save and exit.

Refresh, restart, monitor:

$ sudo systemctl daemon-reload
$ sudo systemctl start geth
$ sudo journalctl -fu geth.service

Geth now matches the new guides, and is Merge-Ready.

Consensus Clients

My original guides covered the installation of Lighthouse, Nimbus, Prysm, or Teku. Instructions are below for converting them into a Merge Ready state.

Lighthouse

If you used my original guide to install Lighthouse, you can update the existing installation as follows:

Get the latest version of Lighthouse:

$ cd ~
$ curl -LO https://github.com/sigp/lighthouse/releases/download/v3.1.0/lighthouse-v3.1.0-x86_64-unknown-linux-gnu.tar.gz

Stop the Lighthouse beacon chain node and validator:

$ sudo systemctl stop lighthousevalidator
$ sudo systemctl stop lighthousebeacon

Extract it, copy it, clean it up:

$ tar xvf lighthouse-v3.1.0-x86_64-unknown-linux-gnu.tar.gz
$ sudo cp lighthouse /usr/local/bin
$ rm lighthouse-v3.1.0-x86_64-unknown-linux-gnu.tar.gz
$ rm lighthouse

Lighthouse Beacon Chain

Modify the Lighthouse Beacon Chain Node systemd service config using:

$ sudo nano /etc/systemd/system/lighthousebeacon.service

So that it looks like:

[Unit]
Description=Lighthouse Consensus Client BN (Mainnet)
Wants=network-online.target
After=network-online.target
[Service]
User=lighthousebeacon
Group=lighthousebeacon
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/lighthouse bn --network mainnet --datadir /var/lib/lighthouse --http --execution-endpoint http://127.0.0.1:8551 --execution-jwt /var/lib/jwtsecret/jwt.hex
[Install]
WantedBy=multi-user.target

The bits that changed are in bold.

Press <CTRL> + X then Y then <ENTER> to save and exit.

Refresh, restart, monitor:

$ sudo systemctl daemon-reload
$ sudo systemctl start lighthousebeacon
$ sudo journalctl -fu lighthousebeacon

Lighthouse Validator

Modify the Lighthouse Validator systemd service config using:

$ sudo nano /etc/systemd/system/lighthousevalidator.service

So that it looks like:

[Unit]
Description=Lighthouse Consensus Client VC (Mainnet)
Wants=network-online.target
After=network-online.target
[Service]
User=lighthousevalidator
Group=lighthousevalidator
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/lighthouse vc --network mainnet --datadir /var/lib/lighthouse --suggested-fee-recipient FeeRecipientAddress --graffiti "<yourgraffiti>"
[Install]
WantedBy=multi-user.target

The bits that changed are in bold.

Replace FeeRecipientAddress with an Ethereum address in your control.

Replace <yourgraffiti> with your graffiti (max 32 characters).

E.g.:

ExecStart=/usr/local/bin/lighthouse vc --network mainnet --datadir /var/lib/lighthouse --suggested-fee-recipient 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --graffiti "Validatoor"

Press <CTRL> + X then Y then <ENTER> to save and exit.

Refresh, restart, monitor:

$ sudo systemctl daemon-reload
$ sudo systemctl start lighthousevalidator
$ sudo journalctl -fu lighthousevalidator

Lighthouse now matches the new guide, and is Merge-Ready.

Nimbus

If you used my original guide to install Nimbus, you can update the existing installation as follows:

Get the latest version of Nimbus:

$ cd ~
$ curl -LO https://github.com/status-im/nimbus-eth2/releases/download/v22.9.0/nimbus-eth2_Linux_amd64_22.9.0_667c3c97.tar.gz

Stop the Nimbus client:

$ sudo systemctl stop nimbus

Extract it, copy it, clean it up:

$ tar xvf nimbus-eth2_Linux_amd64_22.9.0_667c3c97.tar.gz
$ cd nimbus-eth2_Linux_amd64_22.9.0_667c3c97
$ sudo cp build/nimbus_beacon_node /usr/local/bin
$ cd ~
$ rm nimbus-eth2_Linux_amd64_22.9.0_667c3c97.tar.gz
$ rm -r nimbus-eth2_Linux_amd64_22.9.0_667c3c97

Modify the Nimbus systemd service config using:

$ sudo nano /etc/systemd/system/nimbus.service

So that it looks like:

[Unit]
Description=Nimbus Consensus Client (Mainnet)
Wants=network-online.target
After=network-online.target
[Service]
User=nimbus
Group=nimbus
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/nimbus_beacon_node --network=mainnet --data-dir=/var/lib/nimbus --web3-url=http://127.0.0.1:8551 --jwt-secret=/var/lib/jwtsecret/jwt.hex --suggested-fee-recipient=FeeRecipientAddress --graffiti="<yourgraffiti>"
[Install]
WantedBy=multi-user.target

The bits that changed are in bold.

Replace FeeRecipientAddress with an Ethereum address in your control.

Replace <yourgraffiti> with your graffiti (max 32 characters).

E.g.:

ExecStart=/usr/local/bin/nimbus_beacon_node --network=mainnet --data-dir=/var/lib/nimbus --web3-url=http://127.0.0.1:8551 --jwt-secret=/var/lib/jwtsecret/jwt.hex --suggested-fee-recipient=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --graffiti="Validatoor"

Press <CTRL> + X then Y then <ENTER> to save and exit.

Refresh, restart, monitor:

$ sudo systemctl daemon-reload
$ sudo systemctl start nimbus
$ sudo journalctl -fu nimbus

Nimbus now matches the new guide, and is Merge-Ready.

Prysm

If you used my original guide to install Prysm, you can update the existing installation as follows:

Get the latest version of Prysm:

$ cd ~
$ curl -LO https://github.com/prysmaticlabs/prysm/releases/download/v3.1.1/beacon-chain-v3.1.1-linux-amd64
$ curl -LO https://github.com/prysmaticlabs/prysm/releases/download/v3.1.1/validator-v3.1.1-linux-amd64

Stop the Prysm beacon chain node and validator:

$ sudo systemctl stop prysmvalidator
$ sudo systemctl stop prysmbeacon

Rename it, make it executable, copy it, clean it up:

$ mv beacon-chain-v3.1.1-linux-amd64 beacon-chain
$ mv validator-v3.1.1-linux-amd64 validator
$ chmod +x beacon-chain
$ chmod +x validator
$ sudo cp beacon-chain /usr/local/bin
$ sudo cp validator /usr/local/bin
$ rm beacon-chain && rm validator

Prysm Beacon Chain

Modify the Prysm Beacon Chain Node systemd service config using:

$ sudo nano /etc/systemd/system/prysmbeacon.service

So that it looks like:

[Unit]
Description=Prysm Consensus Client BN (Mainnet)
Wants=network-online.target
After=network-online.target
[Service]
User=prysmbeacon
Group=prysmbeacon
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/beacon-chain --mainnet --datadir=/var/lib/prysm/beacon --execution-endpoint=http://127.0.0.1:8551 --jwt-secret=/var/lib/jwtsecret/jwt.hex --suggested-fee-recipient=FeeRecipientAddress --accept-terms-of-use
[Install]
WantedBy=multi-user.target

The bits that changed are in bold.

Replace FeeRecipientAddress with an Ethereum address in your control.

E.g.:

ExecStart=/usr/local/bin/beacon-chain --mainnet --datadir=/var/lib/prysm/beacon --execution-endpoint=http://127.0.0.1:8551 --jwt-secret=/var/lib/jwtsecret/jwt.hex --suggested-fee-recipient=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --accept-terms-of-use

Press <CTRL> + X then Y then <ENTER> to save and exit.

Refresh, restart, monitor:

$ sudo systemctl daemon-reload
$ sudo systemctl start prysmbeacon
$ sudo journalctl -fu prysmbeacon

Prysm Validator

Modify the Prysm Validator systemd service config using:

$ sudo nano /etc/systemd/system/prysmvalidator.service

So that it looks like:

[Unit]
Description=Prysm Consensus Client VC (Mainnet)
Wants=network-online.target
After=network-online.target
[Service]
User=prysmvalidator
Group=prysmvalidator
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/validator --datadir=/var/lib/prysm/validator --wallet-dir=/var/lib/prysm/validator --wallet-password-file=/var/lib/prysm/validator/password.txt --suggested-fee-recipient=FeeRecipientAddress --graffiti="<yourgraffiti>" --accept-terms-of-use
[Install]
WantedBy=multi-user.target

The bits that changed are in bold.

Replace FeeRecipientAddress with an Ethereum address in your control.

Replace <yourgraffiti> with your graffiti (max 32 characters).

E.g.:

ExecStart=/usr/local/bin/validator --datadir=/var/lib/prysm/validator --wallet-dir=/var/lib/prysm/validator --wallet-password-file=/var/lib/prysm/validator/password.txt --suggested-fee-recipient=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --graffiti="Validatoor" --accept-terms-of-use

Press <CTRL> + X then Y then <ENTER> to save and exit.

Refresh, restart, monitor:

$ sudo systemctl daemon-reload
$ sudo systemctl start prysmvalidator
$ sudo journalctl -fu prysmvalidator

Prysm now matches the new guide, and is Merge-Ready.

Teku

If you used my original guide to install Teku, you can update the existing installation as follows:

Get the latest version of Teku:

$ cd ~
$ curl -LO https://artifacts.consensys.net/public/teku/raw/names/teku.tar.gz/versions/22.9.0/teku-22.9.0.tar.gz

Stop the Teku client:

$ sudo systemctl stop teku

Extract it, copy it, clean it up:

$ tar xvf teku-22.9.0.tar.gz
$ sudo rm -r /usr/local/bin/teku # <-- Remove the old files
$ sudo cp -a teku-22.9.0 /usr/local/bin/teku
$ rm teku-22.9.0.tar.gz
$ rm -r teku-22.9.0

Modify the Teku systemd service config using:

$ sudo nano /etc/systemd/system/teku.service

So that it looks like:

[Unit]
Description=Teku Consensus Client (Mainnet)
Wants=network-online.target
After=network-online.target
[Service]
User=teku
Group=teku
Type=simple
Restart=always
RestartSec=5
Environment="JAVA_OPTS=-Xmx3g"
Environment="TEKU_OPTS=-XX:-HeapDumpOnOutOfMemoryError"
ExecStart=/usr/local/bin/teku/bin/teku --network=mainnet --data-path=/var/lib/teku --validator-keys=/var/lib/teku/validator_keys:/var/lib/teku/validator_keys --ee-endpoint=http://127.0.0.1:8551 --ee-jwt-secret-file=/var/lib/jwtsecret/jwt.hex --validators-proposer-default-fee-recipient=FeeRecipientAddress --validators-graffiti="<yourgraffiti>"
[Install]
WantedBy=multi-user.target

The bits that changed are in bold.

Replace FeeRecipientAddress with an Ethereum address in your control.

Replace <yourgraffiti> with your graffiti (max 32 characters).

E.g.:

ExecStart=/usr/local/bin/teku/bin/teku --network=mainnet --data-path=/var/lib/teku --validator-keys=/var/lib/teku/validator_keys:/var/lib/teku/validator_keys --ee-endpoint=http://127.0.0.1:8551 --ee-jwt-secret-file=/var/lib/jwtsecret/jwt.hex --validators-proposer-default-fee-recipient=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --validators-graffiti="Validatoor"

Press <CTRL> + X then Y then <ENTER> to save and exit.

Refresh, restart, monitor:

$ sudo systemctl daemon-reload
$ sudo systemctl start teku
$ sudo journalctl -fu teku

Teku now matches the new guide, and is Merge-Ready.

Appendix A — Uninstalling Geth

If you installed Geth using my original Ethereum 2.0 mainnet guides, you can follow the instructions below to remove it.

NOTE: You may want to sync a second Execution Client first before you remove Geth. Not critical pre-merge, critical post-merge. Keep in mind that you’ll need around 700GB disk space available to sync a second client and you may need to modify the port number (30303) for either Geth or the new Execution Client to avoid a clash.

Stop and disable the geth service.

$ sudo systemctl stop geth
$ sudo systemctl disable geth

Remove the geth service.

$ sudo rm /etc/systemd/system/geth.service
$ sudo rm /usr/lib/systemd/system/geth.service
$ sudo systemctl daemon-reload
$ sudo systemctl reset-failed

Remove the geth software and the PPA repository.

$ sudo apt remove -y geth
$ sudo add-apt-repository --remove ppa:ethereum/ethereum
$ sudo apt autoremove

Delete data directory and user. Adjust directory path and user as necessary.

$ sudo rm -r /var/lib/goethereum
$ sudo deluser goeth

Geth should now be removed. You can install one of the other Execution Clients using my guides linked at the top of this page.

Here is an example from another user who migrated from Geth to Besu.

Appendix B— Pruning Geth

To avoid running out of disk space on your server, it may be useful to periodically run a prune operation on the Geth database. This operation will attempt to reduce the size of (prune) the Geth database. Thanks to Yorick Downe and his excellent guide for help with this section.

Some important prerequisites:

  • You have followed the instructions above to update Geth to a Merge Ready state.
  • Geth must be fully synced.
  • Geth logs are not showing “state snapshot generation” messages. You can see the service log output using $ sudo journalctl -fu geth.service. If it is, it should show an “eta” with a time interval. Allow that to elapse + 128 blocks (~35 mins) before starting the prune operation.
  • Geth will not be operating normally during the prune operation. The prune operation takes around 4–6 hours.
  • There must be more than 25GB free space on your server for the prune to run without risk of failure. Check available space using the df -h command. For example, the output below shows the main partition is /dev/hda1 and there is 82GB free:
ethstaker@ETH-STAKER-001:~$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 3.9G 0 3.9G 0% /dev
tmpfs 796M 996K 795M 1% /run
/dev/hda1 155G 74G 82G 48% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/vda15 105M 5.2M 100M 5% /boot/efi
tmpfs 796M 0 796M 0% /run/user/1000

If you meet the pre-requisites above then continue on. If not, check for advice on how to proceed with the EthStaker community on Reddit or Discord.

Start the Prune Operation

To run the prune it is necessary to update the service configuration for Geth to add the required prune command.

Stop the geth service.

$ sudo systemctl stop geth

Open the geth service systemd configuration file.

$ sudo nano /etc/systemd/system/geth.service

Add the snapshot prune-state instruction at the end of the ExecStart line.

[Unit]
Description=Geth Execution Client (Mainnet)
After=network.target
Wants=network.target
[Service]
User=geth
Group=geth
Type=simple
Restart=always
RestartSec=5
TimeoutStopSec=600
ExecStart=/usr/local/bin/geth --mainnet --datadir /var/lib/geth --authrpc.jwtsecret /var/lib/jwtsecret/jwt.hex snapshot prune-state
[Install]
WantedBy=default.target

Press <CTRL> + X then Y then <ENTER> to save and exit.

Reload systemd to reflect the changes and start the geth service. Check status to make sure it’s running correctly.

$ sudo systemctl daemon-reload
$ sudo systemctl start geth
$ sudo systemctl status geth

From Yorick’s guide:

Geth will prune in 3 stages: “Iterating state snapshot”, “Pruning state data”, and “Compacting database”. During the “Compacting database” stage, it may not output any log entries for an hour or so (mainstream SSD IOPS). Don’t restart it when this happens, let it run!

If you see messages about “generating snapshot” and an ETA during the prune, you don’t actually have a snapshot yet! Either the --datadir and/or USER aren't right, or Geth just didn't have enough time to complete the snapshot. In that case, do stop the process, run Geth normally again, and observe its logs until snapshot has completed and is 128 blocks old.

Once the prune has completed open the geth service systemd configuration file.

$ sudo systemctl stop geth
$ sudo nano /etc/systemd/system/geth.service

Remove the snapshot prune-state instruction at the end of the ExecStart line.

[Unit]
Description=Geth Execution Client (Mainnet)
After=network.target
Wants=network.target
[Service]
User=geth
Group=geth
Type=simple
Restart=always
RestartSec=5
TimeoutStopSec=600
ExecStart=/usr/local/bin/geth --mainnet --datadir /var/lib/geth --authrpc.jwtsecret /var/lib/jwtsecret/jwt.hex
[Install]
WantedBy=default.target

Press <CTRL> + X then Y then <ENTER> to save and exit.

Reload systemd to reflect the changes and start the geth service. Check status to make sure it’s running correctly.

$ sudo systemctl daemon-reload
$ sudo systemctl start geth
$ sudo systemctl status geth # <-- Check for errors
$ sudo journalctl -fu geth.service # <-- Monitor

The prune operation is now complete. Geth should start syncing to the head of the chain. You can check how much disk space was freed up using df -h.

Full Disclaimer

This article (the guide) is for informational purposes only and does not constitute professional advice. The author does not warrant or guarantee the accuracy, integrity, quality, completeness, currency, or validity of any information in this article. All information herein is provided “as is” without warranty of any kind and is subject to change at any time without notice. The author disclaims all express, implied, and statutory warranties of any kind, including warranties as to accuracy, timeliness, completeness, or fitness of the information in this article for any particular purpose. The author is not responsible for any direct, indirect, incidental, consequential or any other damages arising out of or in connection with the use of this article or in reliance on the information available on this article. This includes any personal injury, business interruption, loss of use, lost data, lost profits, or any other pecuniary loss, whether in an action of contract, negligence, or other misuse, even if the author has been informed of the possibility.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store