diff --git a/nodes/deploy/ethereum/deploy.bash b/nodes/deploy/ethereum/deploy.bash index 537b0d90..7e3f44e6 100755 --- a/nodes/deploy/ethereum/deploy.bash +++ b/nodes/deploy/ethereum/deploy.bash @@ -1,6 +1,7 @@ #!/usr/bin/env bash -# Deployment script - intended to run on Moonstream node control server +# Deployment script - intended to run on Moonstream Ethereum node control server + # Colors C_RESET='\033[0m' C_RED='\033[1;31m' @@ -14,54 +15,72 @@ PREFIX_CRIT="${C_RED}[CRIT]${C_RESET} [$(date +%d-%m\ %T)]" # Main AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-us-east-1}" +APP_DIR="${APP_DIR:-/home/ubuntu/moonstream}" +APP_NODES_DIR="${APP_DIR}/nodes" SECRETS_DIR="${SECRETS_DIR:-/home/ubuntu/moonstream-secrets}" -NODE_PARAMETERS_ENV_PATH="${SECRETS_DIR}/node.env" +PARAMETERS_ENV_PATH="${SECRETS_DIR}/app.env" SCRIPT_DIR="$(realpath $(dirname $0))" BLOCKCHAIN="ethereum" -ETHEREUM_GETH_SERVICE="ethereum-node.service" + +# Parameters scripts +CHECKENV_PARAMETERS_SCRIPT="${SCRIPT_DIR}/parameters.bash" +CHECKENV_NODES_CONNECTIONS_SCRIPT="${SCRIPT_DIR}/nodes-connections.bash" + +# Crawlers server service file +NODES_SERVER_SERVICE_FILE="moonstreamnodes.service" + +# Ethereum geth service file +ETHEREUM_GETH_SERVICE_FILE="geth.service" set -eu +echo +echo +echo -e "${PREFIX_INFO} Building executable server of moonstreamnodes with Go" +EXEC_DIR=$(pwd) +cd "${APP_NODES_DIR}/server" +HOME=/root /usr/local/go/bin/go build -o "${APP_NODES_DIR}/server/moonstreamnodes" "${APP_NODES_DIR}/server/main.go" +cd "${EXEC_DIR}" + echo echo echo -e "${PREFIX_INFO} Retrieving deployment parameters" mkdir -p "${SECRETS_DIR}" -> "${NODE_PARAMETERS_ENV_PATH}" +> "${PARAMETERS_ENV_PATH}" +bash "${CHECKENV_PARAMETERS_SCRIPT}" -vn -p "moonstream" -o "${PARAMETERS_ENV_PATH}" +echo +echo +echo -e "${PREFIX_INFO} Updating nodes connection parameters" +bash "${CHECKENV_NODES_CONNECTIONS_SCRIPT}" -v -f "${PARAMETERS_ENV_PATH}" + +echo +echo +echo -e "${PREFIX_INFO} Replacing current node IP environment variable with local IP" LOCAL_IP="$(ec2metadata --local-ipv4)" -echo -e "${PREFIX_INFO} Found assign subnet IP ${C_GREEN}${LOCAL_IP}${C_RESET} for machine" -ENV_PARAMETERS=$(aws ssm describe-parameters \ - --parameter-filters Key=tag:Product,Values=moonstream Key=tag:Blockchain,Values=$BLOCKCHAIN \ - | jq -r .Parameters[].Name) -ENV_PARAMETERS_VALUES=$(aws ssm get-parameters \ - --names $ENV_PARAMETERS \ - --query "Parameters[*].{Name:Name,Value:Value}") -ENV_PARAMETERS_VALUES_LENGTH=$(echo $ENV_PARAMETERS_VALUES | jq length) -echo -e "${PREFIX_INFO} Extracted ${ENV_PARAMETERS_VALUES_LENGTH} parameters" -for i in $(seq 0 $(($ENV_PARAMETERS_VALUES_LENGTH - 1))) -do - param_key=$(echo $ENV_PARAMETERS_VALUES | jq -r .[$i].Name) - if [ "$param_key" == "MOONSTREAM_NODE_ETHEREUM_IPC_ADDR" ] && [ -n "$LOCAL_IP" ] - then - param_value="\"$LOCAL_IP\"" - else - param_value=$(echo $ENV_PARAMETERS_VALUES | jq .[$i].Value) - fi - echo "$param_key=$param_value" >> "${NODE_PARAMETERS_ENV_PATH}" -done +sed -i "s|MOONSTREAM_NODE_ETHEREUM_IPC_ADDR=.*|MOONSTREAM_NODE_ETHEREUM_IPC_ADDR=\"$LOCAL_IP\"|" "${PARAMETERS_ENV_PATH}" + +echo +echo +echo -e "${PREFIX_INFO} Replacing existing moonstreamnodes service definition with ${NODES_SERVER_SERVICE_FILE}" +chmod 644 "${SCRIPT_DIR}/${NODES_SERVER_SERVICE_FILE}" +cp "${SCRIPT_DIR}/${NODES_SERVER_SERVICE_FILE}" "/etc/systemd/system/${NODES_SERVER_SERVICE_FILE}" +systemctl daemon-reload +systemctl restart "${NODES_SERVER_SERVICE_FILE}" +systemctl status "${NODES_SERVER_SERVICE_FILE}" echo echo echo -e "${PREFIX_INFO} Updating Ethereum Geth service" -if systemctl is-active --quiet "${ETHEREUM_GETH_SERVICE}" +if systemctl is-active --quiet "${ETHEREUM_GETH_SERVICE_FILE}" then - echo -e "${PREFIX_WARN} Ethereum Geth service ${ETHEREUM_GETH_SERVICE} already running" + echo -e "${PREFIX_WARN} Ethereum Geth service ${ETHEREUM_GETH_SERVICE_FILE} already running" else - echo -e "${PREFIX_INFO} Restart Geth service ${ETHEREUM_GETH_SERVICE}" - chmod 644 "${SCRIPT_DIR}/${ETHEREUM_GETH_SERVICE}" - cp "${SCRIPT_DIR}/${ETHEREUM_GETH_SERVICE}" "/etc/systemd/system/${ETHEREUM_GETH_SERVICE}" + echo -e "${PREFIX_INFO} Restart Geth service ${ETHEREUM_GETH_SERVICE_FILE}" + chmod 644 "${SCRIPT_DIR}/${ETHEREUM_GETH_SERVICE_FILE}" + cp "${SCRIPT_DIR}/${ETHEREUM_GETH_SERVICE_FILE}" "/etc/systemd/system/${ETHEREUM_GETH_SERVICE_FILE}" systemctl daemon-reload - systemctl disable "${ETHEREUM_GETH_SERVICE}" - systemctl restart "${ETHEREUM_GETH_SERVICE}" + systemctl disable "${ETHEREUM_GETH_SERVICE_FILE}" + systemctl restart "${ETHEREUM_GETH_SERVICE_FILE}" sleep 10 fi diff --git a/nodes/deploy/ethereum/ethereum-node.service b/nodes/deploy/ethereum/geth.service similarity index 52% rename from nodes/deploy/ethereum/ethereum-node.service rename to nodes/deploy/ethereum/geth.service index 22cd22ea..009bb9d2 100644 --- a/nodes/deploy/ethereum/ethereum-node.service +++ b/nodes/deploy/ethereum/geth.service @@ -5,11 +5,14 @@ After=network.target [Service] User=ubuntu Group=www-data -EnvironmentFile=/home/ubuntu/moonstream-secrets/node.env +EnvironmentFile=/home/ubuntu/moonstream-secrets/app.env ExecStart=/usr/bin/geth --syncmode snap --cache 4096 \ - --port "${MOONSTREAM_NODE_ETHEREUM_LISTENING_PORT}" --datadir /mnt/disks/nodes/ethereum \ + --port "${MOONSTREAM_NODE_ETHEREUM_LISTENING_PORT}" \ + --datadir /mnt/disks/nodes/ethereum \ --txpool.globalslots 153600 --txpool.globalqueue 3072 \ - --http --http.addr "${MOONSTREAM_NODE_ETHEREUM_IPC_ADDR}" --http.port "${MOONSTREAM_NODE_ETHEREUM_IPC_PORT}" --http.api eth,web3,txpool + --http --http.api eth,web3,txpool \ + --http.addr "${MOONSTREAM_NODE_ETHEREUM_IPC_ADDR}" \ + --http.port "${MOONSTREAM_NODE_ETHEREUM_IPC_PORT}" ExecStop=/bin/kill -s SIGINT -$MAINPID TimeoutStopSec=300 SyslogIdentifier=ethereum-node diff --git a/nodes/deploy/ethereum/moonstreamnodes.service b/nodes/deploy/ethereum/moonstreamnodes.service new file mode 100644 index 00000000..b7b83405 --- /dev/null +++ b/nodes/deploy/ethereum/moonstreamnodes.service @@ -0,0 +1,14 @@ +[Unit] +Description=Moonstream node server +After=network.target + +[Service] +User=ubuntu +Group=www-data +WorkingDirectory=/home/ubuntu/moonstream/nodes/server +EnvironmentFile=/home/ubuntu/moonstream-secrets/app.env +ExecStart=/home/ubuntu/moonstream/nodes/server/moonstreamnodes -blockchain ethereum -host 0.0.0.0 -port "${MOONSTREAM_NODES_SERVER_PORT}" +SyslogIdentifier=moonstreamnodes + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/nodes/deploy/ethereum/nodes-connections.bash b/nodes/deploy/ethereum/nodes-connections.bash new file mode 100755 index 00000000..3718b5c9 --- /dev/null +++ b/nodes/deploy/ethereum/nodes-connections.bash @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# +# Update nodes connection address environment variables +# from AWS Route53 internal hosted zone + +VERSION='0.0.1' + +# Colors +C_RESET='\033[0m' +C_RED='\033[1;31m' +C_GREEN='\033[1;32m' +C_YELLOW='\033[1;33m' + +# Logs +PREFIX_INFO="${C_GREEN}[INFO]${C_RESET} [$(date +%d-%m\ %T)]" +PREFIX_WARN="${C_YELLOW}[WARN]${C_RESET} [$(date +%d-%m\ %T)]" +PREFIX_CRIT="${C_RED}[CRIT]${C_RESET} [$(date +%d-%m\ %T)]" + +# Print help message +function usage { + echo "Usage: $0 [-h] -p PRODUCT -f FILEPATH" + echo + echo "CLI to update nodes connection address environment + variables from AWS Route53 internal hosted zone" + echo + echo "Optional arguments:" + echo " -h Show this help message and exit" + echo " -f File path where environment variables update at" +} + +file_flag="" +verbose_flag="false" + +while getopts 'f:v' flag; do + case "${flag}" in + f) file_flag="${OPTARG}" ;; + h) usage + exit 1 ;; + v) verbose_flag="true" ;; + *) usage + exit 1 ;; + esac +done + +# Log messages +function verbose { + if [ "${verbose_flag}" == "true" ]; then + echo -e "$1" + fi +} + +# File flag should be specified +if [ -z "${file_flag}" ]; then + verbose "${PREFIX_CRIT} Please specify file path" + usage + exit 1 +fi + +if [ ! -f "${file_flag}" ]; then + verbose "${PREFIX_CRIT} Provided file does not exist" + usage + exit 1 +fi + +verbose "${PREFIX_INFO} Script version: v${VERSION}" + +verbose "${PREFIX_INFO} Source environment variables" +. ${file_flag} + +verbose "${PREFIX_INFO} Retrieving Ethereum node address" +RETRIEVED_NODE_ETHEREUM_IPC_ADDR=$(aws route53 list-resource-record-sets --hosted-zone-id "${MOONSTREAM_INTERNAL_HOSTED_ZONE_ID}" --query "ResourceRecordSets[?Name == '${MOONSTREAM_ETHEREUM_WEB3_PROVIDER_URI}.'].ResourceRecords[].Value" | jq -r .[0]) +if [ "$RETRIEVED_NODE_ETHEREUM_IPC_ADDR" == "null" ]; then + verbose "${PREFIX_CRIT} Ethereum node internal DNS record address is null" + exit 1 +fi + +verbose "${PREFIX_INFO} Retrieving Polygon node address" +RETRIEVED_NODE_POLYGON_IPC_ADDR=$(aws route53 list-resource-record-sets --hosted-zone-id "${MOONSTREAM_INTERNAL_HOSTED_ZONE_ID}" --query "ResourceRecordSets[?Name == '${MOONSTREAM_POLYGON_WEB3_PROVIDER_URI}.'].ResourceRecords[].Value" | jq -r .[0]) +if [ "$RETRIEVED_NODE_POLYGON_IPC_ADDR" == "null" ]; then + verbose "${PREFIX_CRIT} Polygon node internal DNS record address is null" + exit 1 +fi + +# TODO(kompotkot): Modify regexp to work with export prefix +verbose "${PREFIX_INFO} Updating MOONSTREAM_NODE_ETHEREUM_IPC_ADDR with ${RETRIEVED_NODE_ETHEREUM_IPC_ADDR}" +sed -i "s|^MOONSTREAM_NODE_ETHEREUM_IPC_ADDR=.*|MOONSTREAM_NODE_ETHEREUM_IPC_ADDR=\"$RETRIEVED_NODE_ETHEREUM_IPC_ADDR\"|" ${file_flag} + +verbose "${PREFIX_INFO} Updating MOONSTREAM_NODE_POLYGON_IPC_ADDR with ${RETRIEVED_NODE_POLYGON_IPC_ADDR}" +sed -i "s|^MOONSTREAM_NODE_POLYGON_IPC_ADDR=.*|MOONSTREAM_NODE_POLYGON_IPC_ADDR=\"$RETRIEVED_NODE_POLYGON_IPC_ADDR\"|" ${file_flag} diff --git a/nodes/deploy/ethereum/parameters.bash b/nodes/deploy/ethereum/parameters.bash new file mode 100755 index 00000000..605e4d28 --- /dev/null +++ b/nodes/deploy/ethereum/parameters.bash @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# +# Collect secrets from AWS SSM Parameter Store and +# opt out as environment variable exports. + +VERSION='0.0.2' + +# Colors +C_RESET='\033[0m' +C_RED='\033[1;31m' +C_GREEN='\033[1;32m' +C_YELLOW='\033[1;33m' + +# Logs +PREFIX_INFO="${C_GREEN}[INFO]${C_RESET} [$(date +%d-%m\ %T)]" +PREFIX_WARN="${C_YELLOW}[WARN]${C_RESET} [$(date +%d-%m\ %T)]" +PREFIX_CRIT="${C_RED}[CRIT]${C_RESET} [$(date +%d-%m\ %T)]" + +# Print help message +function usage { + echo "Usage: $0 [-h] -p PRODUCT -o OUTPUT" + echo + echo "CLI to collect secrets from AWS SSM Parameter Store +and output as environment variable exports" + echo + echo "Optional arguments:" + echo " -h Show this help message and exit" + echo " -n Provide true if server is Blockchain node" + echo " -o Output file name environment variables export to" + echo " -p Product tag (moonstream, spire, brood, drones)" +} + +# TODO(kompotkot): Flag for export prefix +node_flag="" +output_flag="" +product_flag="" +verbose_flag="false" + +while getopts 'no:p:v' flag; do + case "${flag}" in + n) node_flag="true" ;; + o) output_flag="${OPTARG}" ;; + p) product_flag="${OPTARG}" ;; + h) usage + exit 1 ;; + v) verbose_flag="true" ;; + *) usage + exit 1 ;; + esac +done + +# Log messages +function verbose { + if [ "${verbose_flag}" == "true" ]; then + echo -e "$1" + fi +} + +# Product flag should be specified +# TODO(kompotkot): Extend script to work with few product at once +if [ -z "${product_flag}" ]; then + verbose "${PREFIX_CRIT} Please specify product tag" + usage + exit 1 +fi + +verbose "${PREFIX_INFO} Script version: v${VERSION}" + +PARAMETER_FILTERS="Key=tag:Product,Values=${product_flag}" +if [ "${node_flag}" == "true" ]; then + verbose "${PREFIX_INFO} Node flag provided, extracting environment variables only for nodes" + PARAMETER_FILTERS="$PARAMETER_FILTERS Key=tag:Node,Values=true" +fi + +verbose "${PREFIX_INFO} Retrieving deployment parameters with tag ${C_GREEN}Product:${product_flag}${C_RESET}" +ENV_PARAMETERS=$(aws ssm describe-parameters \ + --parameter-filters ${PARAMETER_FILTERS} \ + | jq -r .Parameters[].Name) +if [ -z "${ENV_PARAMETERS}" ]; then + verbose "${PREFIX_CRIT} There no parameters for provided product tag" + exit 1 +fi + +verbose "${PREFIX_INFO} Retrieving parameters values" +ENV_PARAMETERS_VALUES=$(aws ssm get-parameters \ + --names ${ENV_PARAMETERS} \ + --query "Parameters[*].{Name:Name,Value:Value}") +ENV_PARAMETERS_VALUES_LENGTH=$(echo ${ENV_PARAMETERS_VALUES} | jq length) +verbose "${PREFIX_INFO} Extracted ${ENV_PARAMETERS_VALUES_LENGTH} parameters" +for i in $(seq 0 $((${ENV_PARAMETERS_VALUES_LENGTH} - 1))); do + param_key=$(echo ${ENV_PARAMETERS_VALUES} | jq -r .[$i].Name) + param_value=$(echo ${ENV_PARAMETERS_VALUES} | jq .[$i].Value) + if [ -z "${output_flag}" ]; then + echo "${param_key}=${param_value}" + else + echo "${param_key}=${param_value}" >> "${output_flag}" + fi +done diff --git a/nodes/deploy/polygon/deploy.bash b/nodes/deploy/polygon/deploy.bash index 8d38a83a..d08f90c6 100755 --- a/nodes/deploy/polygon/deploy.bash +++ b/nodes/deploy/polygon/deploy.bash @@ -47,6 +47,12 @@ echo echo -e "${PREFIX_INFO} Updating nodes connection parameters" bash "${CHECKENV_NODES_CONNECTIONS_SCRIPT}" -v -f "${PARAMETERS_ENV_PATH}" +echo +echo +echo -e "${PREFIX_INFO} Replacing current node IP environment variable with local IP" +LOCAL_IP="$(ec2metadata --local-ipv4)" +sed -i "s|MOONSTREAM_NODE_POLYGON_IPC_ADDR=.*|MOONSTREAM_NODE_POLYGON_IPC_ADDR=\"$LOCAL_IP\"|" "${PARAMETERS_ENV_PATH}" + echo echo echo -e "${PREFIX_INFO} Source extracted parameters" @@ -56,5 +62,5 @@ echo echo echo -e "${PREFIX_INFO} Update heimdall config file with Ethereum URI" MOONSTREAM_NODE_ETHEREUM_IPC_URI="http://$MOONSTREAM_NODE_ETHEREUM_IPC_ADDR:$MOONSTREAM_NODE_ETHEREUM_IPC_PORT" -sed -i "s|^eth_rpc_url =.*|eth_rpc_url = \"$MOONSTREAM_NODE_ETHEREUM_IPC_URI\"|" $HEIMDALL_HOME/config/heimdall-config.toml +sed -i "s|^eth_rpc_url =.*|eth_rpc_url = \"$MOONSTREAM_NODE_ETHEREUM_IPC_URI\"|" "${HEIMDALL_HOME}/config/heimdall-config.toml" echo -e "${PREFIX_INFO} Updated ${C_GREEN}eth_rpc_url = $MOONSTREAM_NODE_ETHEREUM_IPC_URI${C_RESET} for heimdall" diff --git a/nodes/deploy/polygon/moonstreamnodes.service b/nodes/deploy/polygon/moonstreamnodes.service new file mode 100644 index 00000000..46ed49a8 --- /dev/null +++ b/nodes/deploy/polygon/moonstreamnodes.service @@ -0,0 +1,14 @@ +[Unit] +Description=Moonstream node server +After=network.target + +[Service] +User=ubuntu +Group=www-data +WorkingDirectory=/home/ubuntu/moonstream/nodes/server +EnvironmentFile=/home/ubuntu/moonstream-secrets/app.env +ExecStart=/home/ubuntu/moonstream/nodes/server/moonstreamnodes -blockchain polygon -host 0.0.0.0 -port "${MOONSTREAM_NODES_SERVER_PORT}" +SyslogIdentifier=moonstreamnodes + +[Install] +WantedBy=multi-user.target \ No newline at end of file