Go-Ethereum Geth 1.17.10
Overview
Go-Ethereum (geth) is the Go implementation of Ethereum from the go-ethereum project. It is an Ethereum execution client: it connects to the Ethereum peer-to-peer network, downloads and verifies blocks, keeps the state, and serves the JSON-RPC API that wallets, indexers and applications use.
This guide covers launching and using the Go-Ethereum (Geth) 1.17.10 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud GIS, health and research applications listing on AWS Marketplace, and you choose it as the software version when you launch. The image is a hardened, ready-to-use geth node.
What this image does, and what it does not. Since the Merge, an Ethereum node is two programs: an execution client (geth) and a consensus client. The consensus client is a beacon node such as Lighthouse, Prysm, Teku, Nimbus or Lodestar. It tells geth which chain head to follow, over the authenticated engine API on port 8551.
This image ships geth only. Out of the box, geth starts, finds peers and answers RPC calls. It does not follow the chain head until you run a consensus client next to it (Step 7). A full mainnet node also needs a large data volume (Step 8).
What you get:
- RPC never open to the network. JSON-RPC (8545), WebSocket (8546) and the engine API (8551) listen on
127.0.0.1only. Only theeth,netandweb3namespaces are served over HTTP and WebSocket. No account is unlocked, and thepersonal,admin,debug,minerandtxpoolnamespaces are not served over the network listeners. A request with a foreignHostheader or a cross-site WebSocketOriginis refused. You reach the RPC from your computer over an SSH tunnel (Step 6). - An identity per instance. The image ships no node key and no JWT secret. geth generates its peer-to-peer node key and the engine API's
jwt.hexon your instance at its first start, so two instances never share an enode identity or a JWT secret. If either file is ever found before the first boot, the first-boot service destroys it. - Chain data on its own volume.
/var/lib/gethis a separate gp3 EBS volume (ext4, mounted by filesystem UUID), shipped empty. You set its size at launch or enlarge it later, and the instance grows the file system online. - An outbound block. geth itself may not open connections to the EC2 metadata service, to link-local, private, CGNAT and reserved ranges, or to this instance's own VPC ranges (systemd
IPAddressDeny). It still reaches public Ethereum peers. The instance reads its VPC ranges from the metadata service at every boot, and geth does not start until it has them. - A checked configuration. Before every start, a guard checks the binary against its pinned SHA-256, the data volume, the four tunables in
/etc/default/gethand the effective systemd configuration. A drop-in that would open the RPC to the network, unlock an account or turn on an unsafe flag is refused. geth then stays stopped (exit 78) instead of restarting in a loop. - An unprivileged service.
gethruns as the geth account (no shell, no password, no sudo) under systemd withNoNewPrivileges, a read-only operating system, no capabilities,MemoryDenyWriteExecuteand core dumps off. - The official release.
/usr/local/bin/gethis the go-ethereum project's own linux-amd64 release build of 1.17.10 (commit1df30b18), verified by its published signature and pinned by SHA-256. The corresponding source and every third-party licence are on the instance (Step 12).
What is on the image: geth 1.17.10, cloud-init and the AWS Systems Manager agent on Ubuntu 24.04. No web server and no consensus client.
Default user: ubuntu. Architecture: x86_64. Recommended instance type: m5.large.
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair, and a VPC subnet with internet access (geth must reach public peers).
- A security group that allows TCP 22 (SSH) from your own address and TCP and UDP 30303 (Ethereum peer-to-peer) from anywhere. Without 30303, geth still connects out to peers, but other nodes cannot connect to it. Never open 8545, 8546 or 8551.
- IMDSv2 enabled (the default for this AMI). The instance reads its VPC ranges and its public address from the metadata service at every boot. With the metadata service switched off, geth does not start (see Step 10).
- A data volume sized for your network. The AMI's data volume is only 20 GiB. That is enough to try the image, but not enough for mainnet. A synced mainnet node needs at least 650 GiB for geth alone, and 1 to 2 TiB is the practical size with room to grow. Size the
/dev/sdfvolume at launch (Step 1), or enlarge it before you start a consensus client (Step 8). A testnet (sepolia,hoodi) needs far less. The image ships set to mainnet with up to 50 peers. On the 20 GiB volume, change the network or keep the instance for evaluation only. - Data transfer costs. geth uploads blocks and transactions to its peers, and that traffic is billed as EC2 data transfer out to the internet. A mainnet node with 50 peers can send hundreds of GB a month. Lower
GETH_MAXPEERSto reduce it (Step 9), and watch the instance'sNetworkOutmetric in CloudWatch. - Memory. By default, geth uses about 1 GiB of cache plus its own working set. m5.large (8 GiB) is the minimum we recommend. A busy RPC node, or a node with a consensus client on the same instance, needs 16 GiB or more.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick Go-Ethereum (Geth) 1.17.10 on Ubuntu 24.04 as the software version and select your Region. Then choose Launch through EC2.
Choose m5.large or larger, your key pair, and a security group as described above. Under Storage, set the size of the second volume (/dev/sdf, the chain data) to what your network needs.
To launch with the AWS CLI instead, replace the values in angle brackets. The example sets a 1,500 GiB data volume:
aws ec2 run-instances --image-id <ami-id-from-the-listing> --instance-type m5.large \
--key-name <your-key-pair> --security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--block-device-mappings 'DeviceName=/dev/sdf,Ebs={VolumeSize=1500,VolumeType=gp3,Iops=6000,Throughput=250}' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=geth}]'First boot takes under a minute after the instance is running. It reads the instance's VPC ranges and public address, grows the data volume's file system to the volume size, and writes /root/geth-notes.txt. It then starts geth, which generates its node key and JWT secret.
Connect to your instance
Connect over SSH as the ubuntu user, which is the SSH user for Ubuntu 24.04.
ssh -i <your-key.pem> ubuntu@<public-ip>The login message shows the node status and the console commands.
Check the services
Confirm that both services are active:
systemctl is-active sac-geth-vpc-cidrs gethactive activegeth-firstboot runs once. systemctl is-active geth-firstboot shows active after the first boot and inactive on every later boot, where it is skipped.
Next, check the listeners. SSH and the peer-to-peer port are open to everyone. The three RPC ports are on the loopback address only:
sudo ss -Htuln | awk '{print $1, $5}' | sort -utcp *:30303 tcp 0.0.0.0:22 tcp 127.0.0.1:8545 tcp 127.0.0.1:8546 tcp 127.0.0.1:8551 tcp 127.0.0.53%lo:53 tcp 127.0.0.54:53 tcp [::]:22 udp *:30303 udp 127.0.0.1:323 udp 127.0.0.53%lo:53 udp 127.0.0.54:53 udp <private-ip>%ens5:68 udp [::1]:323Addresses 127.0.0.53 and 127.0.0.54 belong to Ubuntu's local DNS resolver. Ports 68 and 323 are DHCP and the time service.
Check the node's status
Run the status command:
sudo geth-statusnetwork: mainnet advertised: extip:203.0.113.10 { "enode": "enode://6a017d2a...9464acd9@203.0.113.10:30303", "peers": 6, "syncing": { "currentBlock": 0, "highestBlock": 0, "startingBlock": 0, ... }, "head": 0 }The syncing object has more counters than shown here, and the enode is shortened.
advertised is the public address geth tells other nodes. It is read from the metadata service at this boot, so it follows a new address after a stop and start. The enode is this instance's public peer-to-peer identity, and it is not a secret. syncing and head stay at the genesis block until a consensus client drives geth (Step 7).
To read the notes that first boot wrote, run the command below. No secret is in them:
sudo cat /root/geth-notes.txtThe geth console
geth-attach opens the geth JavaScript console over the IPC socket, as the geth account, in a sandbox that cannot open network connections. With --exec, it runs one expression:
sudo geth-attach --exec 'net.peerCount'6The count is 0 in the first minute after the first boot and rises as geth finds peers.
sudo geth-attach --exec 'eth.chainId()'"0x1"Run sudo geth-attach with no argument for the interactive console, and type exit to leave. The IPC console has every namespace, including admin, so keep it to administrators of the instance.
Use the RPC from your computer
On the instance, the JSON-RPC answers on the loopback address. Send a request:
curl -s -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}' http://127.0.0.1:8545{"jsonrpc":"2.0","id":1,"result":"0x1"}From your own computer, forward the ports over SSH. Then point your tools at http://127.0.0.1:8545, or at ws://127.0.0.1:8546 for WebSocket:
ssh -i <your-key.pem> -N -L 8545:127.0.0.1:8545 -L 8546:127.0.0.1:8546 ubuntu@<public-ip>From outside the instance, the RPC ports are closed. We checked this from another host against two fresh instances. A temporary security group rule allowed 8545 to 8551 from that host only, so that the security group did not hide the answer. geth refused all three:
8545 refused 8546 refused 8551 refusedIf other machines need RPC access, put an authenticating proxy or a private load balancer in front of it. Keep 8545 and 8546 off the internet, because an open Ethereum RPC is scanned and abused within minutes.
Pair a consensus client
geth follows the chain only when a consensus client sends it the chain head over the engine API. Until then, eth.syncing stays at block 0. Once something has called the engine API (the self-test in Step 11 does), the journal repeats Beacon client online, but no consensus updates received in a while. Please fix your beacon client to follow the chain!. That warning is expected until your consensus client runs.
Install a consensus client of your choice (Lighthouse, Prysm, Teku, Nimbus or Lodestar) on this instance, following its own documentation. Configure it with:
- Execution endpoint:
http://127.0.0.1:8551. The engine API listens on the loopback address only. - JWT secret:
/var/lib/geth/jwt.hex, whichgethwrote at its first start. It is readable by the geth account only. Give the consensus client's account its own copy, for examplesudo install -m 0400 -o <beacon-account> /var/lib/geth/jwt.hex /etc/<beacon>/jwt.hex, and never copy it off the instance. - Checkpoint sync from a trusted beacon state provider, so the beacon node syncs in minutes instead of days.
- Network: the same network as geth (
mainnetby default, see Step 9).
The consensus client needs its own inbound peer port in the security group (usually 9000 TCP and UDP) and its own disk space. Once it runs, geth logs the forkchoice updates it receives, and sudo geth-status shows syncing progress and then the head block. Snap sync of mainnet takes many hours, depending on disk throughput.
Storage for the chain
The chain data, the node key and the JWT secret live on the data volume at /var/lib/geth. Check its size and usage:
df -h /var/lib/gethTo enlarge the volume later, increase its size in the EC2 console (Volumes, Modify volume) or with aws ec2 modify-volume. Wait until the modification is in the optimizing or completed state, then grow the file system online:
sudo systemctl restart sac-geth-growfsdf -h /var/lib/gethThe instance also grows the file system at every boot. Use gp3 with enough IOPS and throughput (6000 IOPS and 250 MB/s or more for mainnet). Back up the volume with EBS snapshots.
The tunables
geth reads four settings from /etc/default/geth:
grep -v '^#' /etc/default/gethGETH_NETWORK=mainnet GETH_SYNCMODE=snap GETH_CACHE=1024 GETH_MAXPEERS=50GETH_NETWORK:mainnet,sepoliaorhoodi. Change the network only on an empty data volume. Stop geth, empty/var/lib/geth(this deletes the chain data and the node identity), set the network, then start geth.GETH_SYNCMODE:snap(default) orfull.GETH_CACHE: memory for geth's caches in MB (512 to 65536). Raise it on larger instances, for example 4096 on a 16 GiB instance.GETH_MAXPEERS: 1 to 200.
For example, to lower the peer limit to 25 and reduce upload traffic (see Prerequisites):
sudo sed -i 's/^GETH_MAXPEERS=.*/GETH_MAXPEERS=25/' /etc/default/geth
sudo systemctl restart gethEdit the file with sudo, and restart geth with sudo systemctl restart geth after every change. The guard accepts only these four keys, each once, in the plain KEY=value form. Anything else keeps geth stopped, and the reason is in journalctl -u geth.
Other geth flags are deliberately not configurable through this file. A systemd drop-in that changes the command line is checked by the same guard, which refuses any flag that would expose the RPC or unlock an account.
The VPC ranges and a fail-closed start
At every boot, sac-geth-vpc-cidrs reads this instance's VPC IPv4 and IPv6 ranges from the metadata service (IMDSv2) and adds them to geth's outbound block. geth starts only after that. Check the unit state:
systemctl show -p ActiveState --value sac-geth-vpc-cidrsactiveIf the metadata service does not answer at boot, the unit retries on its own. geth stays stopped instead of starting without the block, and it starts by itself once the ranges are read. On a later boot, if the metadata service is unavailable, the last ranges read successfully on this instance are used.
If you switch the metadata service off, geth does not start. Switch it back on. IMDSv2 only is fine.
Check the whole instance
Run the self-test:
sudo geth-selftestGETH_SELFTEST_OK geth 1.17.10 mainnet chainId 1: user geth (pid 1118); listeners loopback 8545/8546/8551 + 30303 tcp/udp; no personal/admin/debug/miner/txpool over HTTP; Host + WebSocket Origin pinned; engine API JWT-only; IPC console as geth (network-denied): peers 0, syncing yesThe self-test checks the process and its account, the version, the listeners, the chain id, the RPC namespaces, the Host and Origin checks, the engine API's JWT authentication and the IPC console. It authenticates with this instance's secret and never prints it.
Versions, licences and source
Read the version record on the instance:
cat /usr/share/doc/geth/README.sacgeth 1.17.10 1df30b18d9ed35ee9d28ffd4648442c2204554ad release geth-linux-amd64-1.17.10-1df30b18.tar.gz sha256 e016aca8cc391c8d5d14dc17c9af589488d99c37ed71d892213c80757935ba64 source go-ethereum-v1.17.10.zip h1:b3WO+xux3pItpm13kqT5Xddv01zOxBFZxQgk/Ate4/M= modules 129 (third-party/MODULES.txt) guide https://secureanycloud.com/stacks/go-ethereum-geth-1-17-10/geth is free software. The geth command is under the GNU General Public License version 3 or later, and the go-ethereum library is under the GNU Lesser General Public License version 3 or later.
The binary is the go-ethereum project's own release build, and it links many Go modules statically. /usr/share/doc/geth/NOTICE lists them and their licences, and /usr/share/doc/geth/third-party/ holds every module's licence and notice files. The complete go-ethereum source at the release tag is on the instance in /usr/src/geth. /usr/share/doc/geth/WRITTEN-OFFER explains how to get the corresponding source of everything else.
Ubuntu's unattended upgrades keep the operating system patched. geth does not update itself. The SecureAnyCloud listing adds a new version when the go-ethereum project releases one, and upgrading a running node is a stop, a binary swap and a start on the same data volume. Watch the go-ethereum releases for hard forks, because every node must run a release that supports the next network upgrade before it activates.
go-ethereum is developed by the go-ethereum project and its contributors. SecureAnyCloud packages and configures it and is not affiliated with or endorsed by the go-ethereum project or the Ethereum Foundation. Running a node does not need a wallet or funds, and this image holds none.
Support
SecureAnyCloud provides support for this image by email at sales@secureanycloud.com, 24 hours a day, 7 days a week. Tell us the AMI ID and Region, and include the output of sudo geth-selftest and systemctl status geth sac-geth-vpc-cidrs. For questions about geth itself, see the go-ethereum documentation.
Deploy on AWS
Launch Go-Ethereum (Geth) 1.17.10 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com