Create a Fuji node on AWS
In this section, we will learn how to use the ash.avalanche Ansible collection to provision a Fuji Avalanche node on a AWS EC2 instance.
Requirements
- Python >=3.9 with
venv
module installed - AWS account and access key (see AWS docs) with correct permissions to manage EC2 instances (e.g.:
AmazonEC2FullAccess
) - Terraform installed (see Install Terraform)info
Terraform is an infrastructure as code tool that lets you build, change, and version infrastructure safely and efficiently
- For filtering outputs:
- jq (see Installation)
We recommend installing the Ash CLI to easily get information about your nodes and Subnets. See Ash CLI - Installation.
The tutorials still provide the snippets to query the Avalanche APIs with cURL.
Setup the environment
Clone the Getting Started repository:
git clone https://github.com/AshAvalanche/ansible-avalanche-getting-started
cd ansible-avalanche-collection-getting-startedSetup and activate Python venv:
bin/setup.sh
source .venv/bin/activateInstall the
ash.avalanche
collection:ansible-galaxy collection install git+https://github.com/AshAvalanche/ansible-avalanche-collection.git
Initialize the Terraform modules:
terraform -chdir=terraform/aws init
Create EC2 instance with Terraform
Setup AWS keys environment variables:
export AWS_SECRET_ACCESS_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXX"
export AWS_ACCESS_KEY_ID="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"Created the resources with Terraform:
terraform -chdir=terraform/aws apply
This command will create the resources defined in main.tf
including a t2.2xlarge
EC2 instance with 300GiB
of storage, an associated key pair and a security group configured to allow SSH (port 22) and default AVAX ports (9650 for HTTP and 9651 for staking) as well as all outbound traffic.
Save the IP of the newly created EC2 instance:
terraform -chdir=terraform/aws output fuji_node_ip
Update
inventories/fuji-aws/hosts
with the IP of your EC2 instance. E.g.:inventories/fuji-aws/hostsaws-fuji-node ansible_host=35.171.27.213 ansible_user=ubuntu ansible_ssh_private_key_file=files/ansible_key.pem
[avalanche_nodes]
aws-fuji-node
Creating the EC2 instance with Terraform is not the only way to go, you can also create it manually using the AWS console or CLI. Just make sure to update inventories/fuji-aws/hosts
so that Ansible knows how to connect to your EC2 instance.
Provision Fuji node
We will use the ash.avalanche.provision_nodes playbook to install and configure AvalancheGo on our EC2 instance.
ansible-playbook ash.avalanche.provision_nodes -i inventories/fuji-aws
The inventories/fuji-aws/group_vars/avalanche_nodes.yml
file holds the configuration for the ash.avalanche.node
role. We only override the avalanchego_version
and avalanchego_network_id
variables, leaving the others as default. For a list of all available variables, see ash.avalanche.node reference.
Monitor bootstrapping
We can SSH to our EC2 instance to follow the synchronization of the P, X and C chains. For example with the P-chain:
ssh -i ./files/ansible_key.pem "ubuntu@$YOUR_EC2_INSTANCE_IP"
cd /var/log/avalanche/avalanchego
tail C.log
[06-02|09:16:47.131] INFO <P Chain> platformvm/vm.go:205 initializing last accepted {"blkID": "99BWrAqUMvTp9nXKXyjPsCqjGwDqVFqssTRQbu58af57Cf9VG"}
[06-02|09:16:47.132] INFO <P Chain> snowman/transitive.go:90 initializing consensus engine
[06-02|09:16:47.133] INFO <P Chain> bootstrap/bootstrapper.go:115 starting bootstrapper
[06-02|09:16:53.011] INFO <P Chain> common/bootstrapper.go:244 bootstrapping started syncing {"numVerticesInFrontier": 1}
[06-02|09:16:58.208] INFO <P Chain> bootstrap/bootstrapper.go:495 fetching blocks {"numFetchedBlocks": 5000, "numTotalBlocks": 105347, "eta": "1m44s"}
[06-02|09:17:07.713] INFO <P Chain> bootstrap/bootstrapper.go:495 fetching blocks {"numFetchedBlocks": 10000, "numTotalBlocks": 105347, "eta": "2m20s"}
[06-02|09:17:10.766] INFO <P Chain> bootstrap/bootstrapper.go:495 fetching blocks {"numFetchedBlocks": 15000, "numTotalBlocks": 105347, "eta": "1m47s"}
[06-02|09:17:14.385] INFO <P Chain> bootstrap/bootstrapper.go:495 fetching blocks {"numFetchedBlocks": 20000, "numTotalBlocks": 105347, "eta": "1m31s"}
[06-02|09:17:18.286] INFO <P Chain> bootstrap/bootstrapper.go:495 fetching blocks {"numFetchedBlocks": 25000, "numTotalBlocks": 105347, "eta": "1m21s"}
[06-02|09:17:21.936] INFO <P Chain> bootstrap/bootstrapper.go:495 fetching blocks {"numFetchedBlocks": 30000, "numTotalBlocks": 105347, "eta": "1m13s"}
Logs should look like this once the chain is bootstrapped:
[06-02|09:18:18.373] INFO <P Chain> bootstrap/bootstrapper.go:554 executing blocks {"numPendingJobs": 105347}
[06-02|09:18:48.374] INFO <P Chain> queue/jobs.go:203 executing operations {"numExecuted": 36081, "numToExecute": 105347, "eta": "58s"}
[06-02|09:19:18.395] INFO <P Chain> queue/jobs.go:203 executing operations {"numExecuted": 43933, "numToExecute": 105347, "eta": "1m24s"}
[06-02|09:19:48.398] INFO <P Chain> queue/jobs.go:203 executing operations {"numExecuted": 44159, "numToExecute": 105347, "eta": "2m5s"}
[06-02|09:20:18.554] INFO <P Chain> queue/jobs.go:203 executing operations {"numExecuted": 44364, "numToExecute": 105347, "eta": "2m45s"}
[06-02|09:20:48.555] INFO <P Chain> queue/jobs.go:203 executing operations {"numExecuted": 47613, "numToExecute": 105347, "eta": "3m2s"}
[06-02|09:21:18.556] INFO <P Chain> queue/jobs.go:203 executing operations {"numExecuted": 64999, "numToExecute": 105347, "eta": "1m52s"}
[06-02|09:21:48.557] INFO <P Chain> queue/jobs.go:203 executing operations {"numExecuted": 81297, "numToExecute": 105347, "eta": "1m2s"}
[06-02|09:22:18.558] INFO <P Chain> queue/jobs.go:203 executing operations {"numExecuted": 96176, "numToExecute": 105347, "eta": "23s"}
[06-02|09:22:34.657] INFO <P Chain> queue/jobs.go:224 executed operations {"numExecuted": 105347}
By default, AvalancheGo is configured to use State Sync for faster node bootstrapping. If you want to run an archival node, you need to disable State Sync on the C-chain. This is configurable through the Ansible Avalanche Collection by adding the following keys to avalanche_nodes.yml
:
avalanchego_chains_configs:
C:
state-sync-enabled: false
Issue API calls
The node aws-fuji-node
exposes AvalancheGo APIs on it's public IP: you can query any Avalanche API from your terminal. For example, to check if the P-Chain is done bootstrapping:
- Using the Ash CLI
- Using cURL
ash avalanche node is-bootstrapped C --http-host "$YOUR_EC2_INSTANCE_IP"
Chain 'C' on node '$YOUR_EC2_INSTANCE_IP:9650': Bootstrapped ✓
curl -X POST --data '{
"jsonrpc": "2.0",
"id" : 1,
"method" : "info.isBootstrapped",
"params": {
"chain": "C"
}
}' -H 'content-type:application/json;' "http://$YOUR_EC2_INSTANCE_IP:9650/ext/info"
{"jsonrpc":"2.0","result":{"isBootstrapped":true},"id":1}
Stop or start AvalancheGo
The ash.avalanche collection creates a systemd service to manage AvalancheGo. It can be stopped or started using the following commands:
ssh -i ./files/ansible_key.pem "ubuntu@$YOUR_EC2_INSTANCE_IP"
# Stop AvalancheGo
systemctl stop avalanchego
# Start AvalancheGo
systemctl start avalanchego
Customization
Different aspects of the installation can be customized:
- To customize the EC2 instance specs (e.g.: instance type, storage capacity, etc.): edit
terraform/aws/main.tf
. - To customize AvalancheGo installation: edit the variables in
inventories/fuji-aws/group_vars/avalanche_nodes.yml
.
Where to go next?
All of our tutorials can be run on the EC2 instance created in this tutorial! Go ahead and deploy a Monitoring stack or learn how to Install the Subnet EVM to your node.