From 7f1e11f86d2f31e48e51475f44a24384ba4f281e Mon Sep 17 00:00:00 2001 From: fryorcraken <110212804+fryorcraken@users.noreply.github.com> Date: Mon, 14 Oct 2024 16:17:56 +1100 Subject: [PATCH] feat: script to guesstimate store retention size (#133) --- README.md | 114 ++++++++++++++++++++++++++++++++++++--- run_node.sh | 4 +- set_storage_retention.sh | 91 +++++++++++++++++++++++++++++++ setup_wizard.sh | 103 +++++++++++++++++++++++++++++++++++ 4 files changed, 302 insertions(+), 10 deletions(-) create mode 100755 set_storage_retention.sh create mode 100755 setup_wizard.sh diff --git a/README.md b/README.md index 97280c0..6e8a76d 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,9 @@ Ready to use docker-compose to run your own [nwaku](https://github.com/waku-org/ * Grafana dashboard for advanced users or node operators. * Requires `docker-compose` and `git`. +## Setup and Run -**📝 0. Prerequisites** +### 📝 0. Prerequisites You need: * Ethereum Sepolia HTTP endpoint. Get one free from [Infura](https://www.infura.io/). @@ -23,8 +24,18 @@ ${EDITOR} .env Make sure to **NOT** place any secrets into `.env.example`, as they might be unintentionally published in the Git repository. +### EXPERIMENTAL - Use wizard script -**🔑 1. Register RLN membership** +Run the wizard script. +Once the script is done, the node will be started for you, so there is nothing else to do. + +The script is experimental, feedback and pull requests are welcome. + +``` +./setup_wizard.sh +``` + +### 🔑 1. Register RLN membership The RLN membership is your access key to The Waku Network. Its registration is done onchain, and allows your nwaku node to publish messages in a decentralized and private way, respecting some [rate limits](https://rfc.vac.dev/spec/64/#rate-limit-exceeded). Messages exceeding the rate limit won't be relayed by other peers. @@ -36,15 +47,32 @@ Note that if you just want to relay traffic (not publish), you don't need one. ./register_rln.sh ``` -**🖥️ 2. Start your node** +### 💽 2. Select storage size + +Waku runs a PostgreSQL Database to store messages from the network and serve them to other peers. +To prevent the database to grow indefinitely, you need to select how much disk space to allocate. +You can either run a script that will estimate and set a good value: + +``` +./set_storage_retention.sh +``` + +Or select your own value. For example, `50GB`: + +```shell +echo "STORAGE_SIZE=50GB" >> .env +``` + +### 🖥️ 3. Start your node Start all processes: nwaku node, database and grafana for metrics. Your [RLN](https://rate-limiting-nullifier.github.io/rln-docs/what_is_rln.html) membership is loaded into nwaku under the hood. ```console docker-compose up -d ``` -⚠️ The node might take ~5' the very first time it runs because it needs to build locally the RLN community membership tree. +⚠️ The node might take a few minutes the very first time it runs because it needs to build locally the RLN community membership tree. + +###🏄🏼‍♂️ 4. Interact with your nwaku node -**🏄🏼‍♂️ 3. Interact with your nwaku node** * See [localhost:3000](http://localhost:3000/d/yns_4vFVk/nwaku-monitoring) for node metrics. * See [localhost:4000](http://localhost:4000) for a nice frontend to chat with other users. @@ -76,11 +104,13 @@ curl -X GET "http://127.0.0.1:8645/store/v1/messages?contentTopics=%2Fmy-app%2F2 For advanced documentation, refer to [ADVANCED.md](https://github.com/waku-org/nwaku-compose/blob/master/ADVANCED.md). ----- -# How to update to latest version +## How to update to latest version We regularly announce new available versions in our [Discord](https://discord.waku.org/) server. -If your last running version is `v0.29` or older, you will need to delete both the `keystore` and `rln_tree` folders, and register your membership again before using the new version by running the following commands: +### From `v0.29` or older + +You will need to delete both the `keystore` and `rln_tree` folders, and register your membership again before using the new version by running the following commands: 1. `cd nwaku-compose` ( go into the root's repository folder ) 2. `docker-compose down` @@ -89,12 +119,80 @@ If your last running version is `v0.29` or older, you will need to delete both t 5. `./register_rln.sh` 6. `docker-compose up -d` -For nodes running on `v0.30` or newer, updating the node is as simple as running the following: +### From `v0.30` or newer + +Updating the node is as simple as running the following: 1. `cd nwaku-compose` ( go into the root's repository folder ) 2. `docker-compose down` 3. `git pull origin master` 4. `docker-compose up -d` +### Set size + +To improve storage on the network, you can increase the allocated space for the database. +To do so, you can simply run: + +``` +./set_storage_retention.sh +``` + +### Check + +Once done, check your node is healthy: + +``` +./chkhealth.sh +``` + +All good: +``` +02:15:51 - node health status is: + +{ + "nodeHealth": "Ready", + "protocolsHealth": [ + { + "Rln Relay": "Ready" + } + ] +} +``` + +If the `./chkhealth.sh` script is hanging or returns the following, wait a few minutes and run it again: +``` +02:17:57 - node health status is: + +{ + "nodeHealth": "Initializing", + "protocolsHealth": [] +} +``` + +### Clean-up + +Docker artefact can take some precious disk space, run the following commands to free space **while your node is running**. + +**Only do this if this machine is solely used for Waku and you have no other docker services**. + +**I repeat, this will clean other docker services and images not running, only do this if this machine is only used for Waku**. + +``` +# Be sure that your containers **are running** +sudo docker-compose up -d + +# Clean docker system files +sudo docker system prune -a + +# Delete docker images +sudo docker image prune -a + +# Delete docker containers +sudo docker container prune + +# Delete docker volumes +sudo docker volume prune +``` + ----- # FAQ [see](FAQ.md) diff --git a/run_node.sh b/run_node.sh index b2e2fae..2a776b5 100755 --- a/run_node.sh +++ b/run_node.sh @@ -22,7 +22,7 @@ if [ -z "${DOMAIN}" ]; then # Check if we have an IP IPCHECK=$(echo "${MY_EXT_IP}" | grep -c '^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$') - if [ "${IPCHECK}" -ne 1 ]; then + if [ "${IPCHECK}" -ne 1 ]; then echo "Failed to get ip, received: '${MY_EXT_IP}'" else echo "auto-domain: ip is '${MY_EXT_IP}'" @@ -33,7 +33,7 @@ if [ -z "${DOMAIN}" ]; then # Check if looks like a DNS DNSCHECK=$(echo "${DNS}" | grep -c '^\([a-zA-Z0-9_\-]\+\.\)\+$') - if [ "${DNSCHECK}" -ne 1 ]; then + if [ "${DNSCHECK}" -ne 1 ]; then echo "Failed to get DNS, received: '${DNS}'" else DOMAIN=$(echo "${DNS}" | sed s/\.$//) diff --git a/set_storage_retention.sh b/set_storage_retention.sh new file mode 100755 index 0000000..1b81f2e --- /dev/null +++ b/set_storage_retention.sh @@ -0,0 +1,91 @@ +#!/bin/sh + +# args +# set SELECTED_STORAGE_SIZE_MB +select_store_size() +{ + _AVAIL_SPACE_MB=$1 + _PGSQL_SIZE_MB=$2 + _MARGIN_MB=$3 + _MIN_SIZE_MB=$4 + _MAX_SIZE_MB=$5 + unset SELECTED_STORAGE_SIZE_MB + if [ -z "$_AVAIL_SPACE_MB" ] || [ -z "$_PGSQL_SIZE_MB" ] || [ -z "$_MARGIN_MB" ] || [ -z "$_MIN_SIZE_MB" ] || [ -z "$_MAX_SIZE_MB" ]; then + >&2 echo "Internal error, not enough arguments passed to select_store_size" + fi + + _USABLE_SPACE_MB=$(( _AVAIL_SPACE_MB + _PGSQL_SIZE_MB )) + + # Give all the available space to the DB, minus what is already used and 3GB for logs etc + _TARGET_MB=$(( _USABLE_SPACE_MB - _MARGIN_MB)) + + if [ $_TARGET_MB -lt $_MIN_SIZE_MB ]; then + >&2 echo "Flooring storage retention to ${_MIN_SIZE_MB}MB" + SELECTED_STORAGE_SIZE_MB=$_MIN_SIZE_MB + elif [ $_TARGET_MB -gt $_MAX_SIZE_MB ]; then + >&2 echo "Capping storage retention to ${_MAX_SIZE_MB}MB" + SELECTED_STORAGE_SIZE_MB=$_MAX_SIZE_MB + else + >&2 echo "Storage retention set to ${_TARGET_MB}" + SELECTED_STORAGE_SIZE_MB=$_TARGET_MB + fi +} + +if [ "$1" = "test" ]; then + echo "Running tests" + i=0 + # avail pgdir marg min max + echo "test $i"; i=$(( i + 1)); select_store_size 10000 0 1000 1000 20000; [ "$SELECTED_STORAGE_SIZE_MB" -eq 9000 ] || echo "fail: $SELECTED_STORAGE_SIZE_MB" + echo "test $i"; i=$(( i + 1)); select_store_size 5000 5000 1000 1000 20000; [ "$SELECTED_STORAGE_SIZE_MB" -eq 9000 ] || echo "fail: $SELECTED_STORAGE_SIZE_MB" + echo "test $i"; i=$(( i + 1)); select_store_size 30000 10000 1000 1000 20000; [ "$SELECTED_STORAGE_SIZE_MB" -eq 20000 ] || echo "fail: $SELECTED_STORAGE_SIZE_MB" + echo "test $i"; i=$(( i + 1)); select_store_size 30000 0 1000 1000 20000; [ "$SELECTED_STORAGE_SIZE_MB" -eq 20000 ] || echo "fail: $SELECTED_STORAGE_SIZE_MB" + echo "test $i"; i=$(( i + 1)); select_store_size 1000 2000 1000 1000 20000; [ "$SELECTED_STORAGE_SIZE_MB" -eq 2000 ] || echo "fail: $SELECTED_STORAGE_SIZE_MB" + echo "test $i"; i=$(( i + 1)); select_store_size 1000 0 1000 1000 20000; [ "$SELECTED_STORAGE_SIZE_MB" -eq 1000 ] || echo "fail: $SELECTED_STORAGE_SIZE_MB" + echo "test $i"; i=$(( i + 1)); select_store_size 500 0 1000 1000 20000; [ "$SELECTED_STORAGE_SIZE_MB" -eq 1000 ] || echo "fail: $SELECTED_STORAGE_SIZE_MB" + exit 0 +fi + +# Check we are in right folder +if ! [ -f "./run_node.sh" ]; then + >&2 echo "This script must be run from inside the 'nwaku-compose' folder" + exit 1 +fi + +# check if STORAGE_SIZE is already specified +if [ -f "./.env" ]; then + . ./.env + if [ -n "$STORAGE_SIZE" ]; then + >&2 echo "STORAGE_SIZE is specified in .env file, doing nothing" + exit 0 + fi +fi + +SUDO="" +PGSQL_SIZE_MB=0 +if [ -d "./postgresql" ]; then + # Check if we need to use SUDO moving forward + if [ "$(ls postgresql/* 2>&1 | grep -c "Permission denied")" ]; then + SUDO="sudo" + fi + + PGSQL_SIZE_MB=$($SUDO du -sm "./postgresql" | awk '{ print $1 }' | sed 's/^\([0-9]\+\)M$/\1/') +fi + +AVAIL_SPACE_MB=$(df -m . | tail -1 | awk '{ print $4 }' | sed 's/^\([0-9]\+\)M$/\1/') + +# Select a store size with the following constraints: +# - Margin: 1GB - 1GB will be left over for the system and logs +# - Min: 1GB - The minimum allocated space will be 1GB (old default) +# - Max: 30GB - The maximum allocated space will be 30GB +select_store_size $AVAIL_SPACE_MB $PGSQL_SIZE_MB 1024 1024 $(( 30 * 1024 )) + +if [ -z "$SELECTED_STORAGE_SIZE_MB" ]; then + >&2 echo "Failed to selected a storage size" + exit 1 +fi + +if [ "$1" = "echo-value" ]; then + echo ${SELECTED_STORAGE_SIZE_MB}MB +else + echo "STORAGE_SIZE=${SELECTED_STORAGE_SIZE_MB}MB" >> .env +fi diff --git a/setup_wizard.sh b/setup_wizard.sh new file mode 100755 index 0000000..257fe2e --- /dev/null +++ b/setup_wizard.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +if [ -f ./.env ] ; then + echo "'./.env\` already exists, exiting wizard" + exit 1 +fi + +if [ -f keystore/keystore.json ] ; then + echo "'keystore/keystore.json\` already exists, exiting wizard" + exit 1 +fi + +if [ -z "$(which docker 2>/dev/null)" ]; then + echo "Ensure that 'docker\` is installed and in \$PATH" + exit 1 +fi + +if [ -z "$(which docker-compose 2>/dev/null)" ]; then + echo "Ensure that 'docker-compose' is installed and in \$PATH" + exit 1 +fi + +echocol() +{ + COL='\033[0;32m' + NC='\033[0m' + printf "$COL${1}${NC}\n" +} + +echocol "##############################" +echocol "#### nwaku-compose wizard ####" +echocol "##############################" +echocol "First, you need a RPC HTTP endpoint for Ethereum Sepolia" +echocol "If you don't have one, try out https://www.infura.io/" +echocol "Expected format is https://sepolia.infura.io/v3/:" +read -r RLN_RELAY_ETH_CLIENT_ADDRESS + +if [ -z "$RLN_RELAY_ETH_CLIENT_ADDRESS" ] \ + || [ $(echo "$RLN_RELAY_ETH_CLIENT_ADDRESS" | grep -c "^https:") -eq 0 ]; then + echo "Invalid value, received '$RLN_RELAY_ETH_CLIENT_ADDRESS'" + exit 1 +fi + +echocol "...." +echocol "Double check you have some Eth Sepolia, at least 0.01Eth." +echocol "If not, you can use this faucet: https://www.infura.io/faucet/sepolia" +echocol "Now enter your SEPOLIA TESTNET private key in hex format 0a...1f without 0x prefix" +read ETH_TESTNET_KEY + +if [ -z "$ETH_TESTNET_KEY" ] \ + || [ $(echo -n "$ETH_TESTNET_KEY" | grep -c '^[0-9a-fA-F]\{64\}$' ) -ne 1 ]; then + echo "Invalid value, received '$ETH_TESTNET_KEY'" + exit 1 +fi + +echocol "...." +echocol "Generating a password for the RLN membership keystore file..." +RLN_RELAY_CRED_PASSWORD=$(< /dev/urandom tr -dc ',/.;:<>?!@#$%^&*()+\-_A-Z-a-z-0-9' | head -c${1:-16};echo;) + +echocol "...." +echocol "Selecting a size for DB..." +STORAGE_SIZE=$(./set_storage_retention.sh echo-value) + +if [ -z "$STORAGE_SIZE" ]; then + echo "Error encountered when estimating storage size, exiting" + exit 1 +fi + +echocol "...." +echocol "The following parameters will be saved to your .env file. Press ENTER to confirm or quit with CONTROL-C to abort:" +echo "RLN_RELAY_ETH_CLIENT_ADDRESS='$RLN_RELAY_ETH_CLIENT_ADDRESS' +ETH_TESTNET_KEY=$ETH_TESTNET_KEY +RLN_RELAY_CRED_PASSWORD='$RLN_RELAY_CRED_PASSWORD' +STORAGE_SIZE=$STORAGE_SIZE" +read foo + +echo "RLN_RELAY_ETH_CLIENT_ADDRESS='$RLN_RELAY_ETH_CLIENT_ADDRESS' +ETH_TESTNET_KEY=$ETH_TESTNET_KEY +RLN_RELAY_CRED_PASSWORD='$RLN_RELAY_CRED_PASSWORD' +STORAGE_SIZE=$STORAGE_SIZE" > ./.env + +SUDO="" +if ! docker info > /dev/null 2>&1; then + echocol "...." + echocol "'sudo' seems to be needed to run docker, your unix password will be asked" + SUDO="sudo" +fi + + +echocol "...." +echocol "Registering an RLN membership..." +if ! $SUDO ./register_rln.sh; then + echocol "###" + echocol "Failed to register RLN membership, usually due to high gas fee" + echocol "Double check you have enough Sepolia eth and run the following command:" + echocol "$SUDO ./register_rln.sh" + echocol "###" + exit 1 +fi + +echocol "...." +echocol "Your node is ready! enter the following command to start it:" +echo "> $SUDO docker-compose up -d" \ No newline at end of file