Skip to content

Commit

Permalink
Run lotus nodes (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelarogbonlo authored Jul 3, 2023
1 parent 0eb67fb commit 23aa998
Show file tree
Hide file tree
Showing 19 changed files with 214 additions and 13 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/deploy-forest-calibnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ jobs:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
working_directory: terraform/calibnet
environment: calibnet
working_directory: terraform/forest-calibnet
environment: Calibnet
new_relic_account_id: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
nr_license_key: ${{ secrets.NR_LICENSE_KEY }}
new_relic_api_key: ${{ secrets.NEW_RELIC_API_KEY }}
4 changes: 2 additions & 2 deletions .github/workflows/deploy-forest-mainnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ jobs:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
working_directory: terraform/mainnet
environment: mainnet
working_directory: terraform/forest-mainnet
environment: Mainnet
new_relic_account_id: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
nr_license_key: ${{ secrets.NR_LICENSE_KEY }}
new_relic_api_key: ${{ secrets.NEW_RELIC_API_KEY }}
Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/deploy-lotus-mainnet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Lotus Mainnet

on:
pull_request:
branches:
- main
paths:
- 'terraform/**'
- 'ansible/**'
push:
branches:
- main
paths:
- 'terraform/**'
- 'ansible/**'
workflow_dispatch:

jobs:
deploy-lotus-calibnet:
name: Deploy
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Checkout the code
uses: actions/checkout@v3

# Using Custom Composite action in ./composite-action/terraform folder
- name: Composite Action for Deploying Terraform Resources
uses: ./composite-action/terraform
with:
do_token: ${{ secrets.DO_TOKEN }}
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
working_directory: terraform/lotus-mainnet
environment: Lotus Mainnet
new_relic_account_id: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
nr_license_key: ${{ secrets.NR_LICENSE_KEY }}
new_relic_api_key: ${{ secrets.NEW_RELIC_API_KEY }}
2 changes: 1 addition & 1 deletion composite-action/terraform/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ runs:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: |
### Forest ${{ inputs.environment }} Infrastructure Plan: ${{ steps.plan.outcome }}
### Forest: ${{ inputs.environment }} Infrastructure Plan: ${{ steps.plan.outcome }}
<details><summary>Show Plan</summary>
Expand Down
2 changes: 1 addition & 1 deletion new-relic/forest.json
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@
"accountIds": [
"${account_id}"
],
"query": "SELECT latest(`host.diskUsedPercent`) FROM Metric WHERE host.hostname = '${name}'"
"query": "SELECT latest(diskUsedPercent) FROM StorageSample WHERE hostname = '${name}' FACET hostname, mountPoint"
}
],
"platformOptions": {
Expand Down
2 changes: 1 addition & 1 deletion new-relic/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ resource "newrelic_nrql_alert_condition" "disk_space" {
violation_time_limit_seconds = 3600

nrql {
query = "SELECT average(`host.diskUsedPercent`) FROM Metric FACET entity.guid, host.hostname"
query = "SELECT latest(diskUsedPercent) FROM StorageSample FACET hostname, mountPoint"
}

critical {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ terraform {
}

module "calibnet" {
source = "../modules/forest_node"
source = "../modules/filecoin_node"

do_token = var.do_token
name = var.name
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ terraform {
}

module "mainnet" {
source = "../modules/forest_node"
source = "../modules/filecoin_node"

do_token = var.do_token
name = var.name
Expand Down
File renamed without changes.
File renamed without changes.
35 changes: 35 additions & 0 deletions terraform/lotus-mainnet/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
terraform {
required_version = ">= 1.2"

backend "s3" {
bucket = "forest-iac"
key = "lotus-mainnet/terraform.tfstate"
region = "us-west-1"
endpoint = "fra1.digitaloceanspaces.com"
skip_credentials_validation = true
skip_metadata_api_check = true
}
}

module "lotus-mainnet" {
source = "../modules/filecoin_node"

do_token = var.do_token
name = "lotus"
region = "fra1"
image = "docker-20-04"
size = "s-4vcpu-8gb"
source_addresses = ["0.0.0.0/0", "::/0"]
attach_volume = true
destination_addresses = ["0.0.0.0/0", "::/0"]
volume_name = "lotus-mainnet-volume"
initial_filesystem_type = "ext4"
volume_size = "1000"
chain = "mainnet"
project = "Forest-DEV"
fw_name = "mainnet-calibnet-fw"
script = "lotus.sh"
NR_LICENSE_KEY = var.NR_LICENSE_KEY
NEW_RELIC_API_KEY = var.NEW_RELIC_API_KEY
NEW_RELIC_ACCOUNT_ID = var.NEW_RELIC_ACCOUNT_ID
}
20 changes: 20 additions & 0 deletions terraform/lotus-mainnet/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

variable "do_token" {
description = "Token for authentication."
type = string
}

variable "NR_LICENSE_KEY" {
description = "New Relic Access Token"
type = string
}

variable "NEW_RELIC_API_KEY" {
description = "New Relic API KEY"
type = string
}

variable "NEW_RELIC_ACCOUNT_ID" {
description = "The New Relic Account ID"
type = string
}
File renamed without changes.
100 changes: 100 additions & 0 deletions terraform/modules/filecoin_node/lotus.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/bin/bash

# This bash script is used to initialize a Lotus Mainnet or Calibnet Droplet.
# It starts the chain (either mainnet or calibnet) as specified in the terraform script.
# The script also runs Watchtower to keep the Lotus Docker images up-to-date,
# and sets up the New Relic agent for system monitoring.

# The script employs Terraform's templating engine, which uses variables defined in terraform.tfvars.
# Thus, the $${VARIABLES} used here are for the template engine, not BASH.

set -euxo pipefail

# Create a new user with a home directory, no password (SSH login only), and no gecos info.
adduser --disabled-password --gecos "" "${NEW_USER}"

# Set up SSH for the new user.
mkdir --parents -- "/home/${NEW_USER}/.ssh"
chown "${NEW_USER}:${NEW_USER}" "/home/${NEW_USER}/.ssh"
chmod 0700 "/home/${NEW_USER}/.ssh"

# Inherit authorized_keys from root, if they exist, to allow the same key-based access for the new user.
if [ -f "/root/.ssh/authorized_keys" ]; then
: Allowing those with root ssh keys to log in as "${NEW_USER}"
cp /root/.ssh/authorized_keys "/home/${NEW_USER}/.ssh/authorized_keys"
chown "${NEW_USER}:${NEW_USER}" "/home/${NEW_USER}/.ssh/authorized_keys"
chmod 0600 "/home/${NEW_USER}/.ssh/authorized_keys"
fi

# Restrict SSH access to the new user only. preventing root user from accessing the system via SSH.
echo "AllowUsers ${NEW_USER}" >> /etc/ssh/sshd_config
systemctl restart sshd

# Enable passwordless sudo for the new user. This allows the user to run sudo commands without being prompted for a password.
echo "${NEW_USER} ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/"${NEW_USER}"

# Add new user to "docker" group so they can run docker commands
usermod --append --groups docker "${NEW_USER}"

# Set up the directory where the lotus container will store its data.
mkdir --parents -- "/home/${NEW_USER}/lotus_data"

# If a volume name is defined, mount the volume to the lotus_data directory.
if [ -n "${VOLUME_NAME}" ]; then
# discard: notify the volume to free blocks (useful for SSDs)
# defaults: default mount options, including rw
# noatime: don't preserve file access times
: mounting volume at the lotus_data directory
mount --options discard,defaults,noatime /dev/disk/by-id/scsi-0DO_Volume_"${DISK_ID_VOLUME_NAME}" "/home/${NEW_USER}/lotus_data"
fi

# Change the ownership of the lotus_data directory to the created user.
chown --recursive "${NEW_USER}":"${NEW_USER}" "/home/${NEW_USER}/lotus_data"

IMAGETAG="stable"

if [ "${CHAIN}" != "mainnet" ]; then
IMAGETAG="stable-calibnet"
fi

sudo --user="${NEW_USER}" -- docker network create lotus

# Run the Lotus Docker container as the created user.
sudo --user="${NEW_USER}" -- \
docker run \
--detach \
--network=lotus \
--name=lotus-"${CHAIN}" \
--volume=parameters:/var/tmp/filecoin-proof-parameters \
--volume=/home/"${NEW_USER}"/lotus_data:/var/lib/lotus \
--publish=1234:1234 \
--restart=always \
filecoin/lotus-all-in-one:"$IMAGETAG" lotus daemon \
--import-snapshot https://snapshots."${CHAIN}".filops.net/minimal/latest.zst

# It monitors running Docker containers and watches for changes to the images that those containers were originally started from.
# If Watchtower detects that an image has changed, it will automatically restart the container using the new image.
# Run the Watchtower Docker container as created user.
sudo --user="${NEW_USER}" -- \
docker run \
--detach \
--network=lotus \
--name=watchtower \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--restart=unless-stopped \
containrrr/watchtower \
--include-stopped --revive-stopped --stop-timeout 120s --interval 600

# Set-up New Relic Agent For logs collection and Infrastruture Metrics
curl -Ls https://download.newrelic.com/install/newrelic-cli/scripts/install.sh | bash && \
sudo NEW_RELIC_API_KEY="${NEW_RELIC_API_KEY}" \
NEW_RELIC_ACCOUNT_ID="${NEW_RELIC_ACCOUNT_ID}" \
NEW_RELIC_REGION="${NEW_RELIC_REGION}" \
/usr/local/bin/newrelic install -y

# Adds custom display name and host-name to the New Relic config.
cat << EOF >> /etc/newrelic-infra.yml
display_name: lotus-${CHAIN}
override_hostname_short: lotus-${CHAIN}
EOF
sudo systemctl restart newrelic-infra
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This terraform script executes the following steps:
# - Boot a New droplet for the Mainnet or Calibnet chain
# - Attach a volume to the droplet if Attach volume is set to true
# - Run the user-data.sh script at the initialization of the new droplet
# - Run the user-data.sh or lotus.sh script at the initialization of the new droplet

terraform {
required_version = "~> 1.3"
Expand Down Expand Up @@ -46,7 +46,7 @@ resource "digitalocean_droplet" "forest" {
ssh_keys = data.digitalocean_ssh_keys.keys.ssh_keys.*.fingerprint
monitoring = true

user_data = templatefile("${path.module}/user-data.sh",
user_data = templatefile("${path.module}/${var.script}",
{
NEW_USER = "${var.name}"
# In the filesystem on the droplet, certain special characters, including "-",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

# This bash script is used to initialize a Mainnet or Calibnet Droplet.
# This bash script is used to initialize a Forest Mainnet or Calibnet Droplet.
# It starts the chain (either mainnet or calibnet) as specified in the terraform script.
# The script also runs Watchtower to keep the Forest Docker images up-to-date,
# and sets up the New Relic agent and openMetrics prometheus for system monitoring and prometheus metrics.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,11 @@ variable "NEW_RELIC_REGION" {
description = "The New Relic Plathom Region"
type = string
default = "EU"
}
}

variable "script" {
description = "The Name of the Script Executed at the Initialization of the Droplet"
type = string
default = "user-data.sh"
}

0 comments on commit 23aa998

Please sign in to comment.