Install Script
Script to perform an all-in-one installation, configuration and startup of FIO
The following script encapsulates the workflow and commands from FIO Package Install and FIO Nodeos Replay. It is offered as a means to quickly build and run a node. As such, details on how to connect, and register as a FIO Chain node are not provided. In addition assumptions have been made as to the local environment as well as FIO package URLs, package versioning and authenticity, etc., which may have to be verified and/or updated for the following script to function properly. Please refer to the aforementioned pages for detailed information.
Destructive
The following script must be run as root/using sudo. Note that the use of 'sudo' is for Advanced users!
#!/usr/bin/env bash
echo
if [[ "$EUID" -ne 0 ]]; then
echo "ERROR: Script must be run as root! Use sudo command as follows; sudo ./<script name>"
echo
exit 1
fi
# Utility functions
function pause() {
echo
read -s -n 1 -p "Press any key to continue (CTRL-c to exit)..."
echo
echo
}
function getAndExtract() {
uri=${1}
rsrc=${2}
exitStatus=0
echo
echo "Cleaning any previous archive download..."
rm -f ${rsrc}
echo
echo "Cleaning target directory '/var/lib/fio'..."
rm -rf /var/lib/fio/data /var/lib/fio/history /var/lib/fio/history_index
echo
echo -n "Downloading archive..."
wget -bq --tries 1 --timeout=10 ${uri}/${rsrc}
echo
max=1200
for ((i=1; i<=max; i++)); do
echo -n '.'
sleep 1s
if [[ $(pgrep -f latest) -eq 0 ]]; then
break
fi
done
echo
echo
if [[ ! -e ${rsrc} ]]; then
exitStatus=99
echo "ERROR: Something went wrong downloading archive ${rsrc} from ${uri}!"
pause
else
echo Download complete!
echo
echo "Exracting archives to target directory (silently)..."
tar -xS -I'pixz' -C /var/lib/fio -f ${rsrc}
if [[ $? -ne 0 ]]; then
exitStatus=98
echo
echo "ERROR: Something went wrong extracting contents of ${rsrc}! Inspect archive and fix any errors."
pause
else
echo
echo "Archive successfully extracted to '/var/lib/fio'"
mkdir -p /var/lib/fio/history /var/lib/fio/history_index
chown -R fio:fio /var/lib/fio
chmod -R 0755 /var/lib/fio
echo
read -N 1 -p "Remove downloaded archive (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
rm -f ${rsrc}
fi
fi
fi
return ${exitStatus}
}
function do_net() {
echo
if [[ -n "${type}" ]]; then
read -N 1 -p "${type^^} selected; Change (y/N)? " answer
echo
if [[ "${answer,,}" != "y" ]]; then
return
fi
echo
fi
local PS3="Select *Net: "
local items=("MainNet" "TestNet" )
while true; do
select item in "${items[@]}" "Return to Main Menu"
do
echo
echo -n "You've chosen "
case $REPLY in
1) echo "$item"; type="mainnet"; break 2;;
2) echo "$item"; type="testnet"; break 2;;
$((${#items[@]}+1))) echo "Return to Main Menu!"; echo; return 1;;
*) echo "Ooops - unknown choice $REPLY"; echo; break;;
esac
done
done
return 0
}
function do_configure() {
echo
read -N 1 -p "Edit the FIO Nodeos configuration (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
vi /etc/fio/nodeos/config.ini
fi
echo && echo
read -N 1 -p "Edit the FIO Nodeos exec, e.g. add '--disable-reply-opts' for state history (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
vi /usr/local/bin/fio-nodeos-run
fi
echo && echo
}
function do_configHelp() {
local type="${1}"
echo
echo "Review configuration settings for your install"
echo "- producer-name"
echo "- endpoints and ports"
echo "- history settings"
echo
if [[ ${type} == "v1" || ${type} == "all" ]]; then
# Add/Uncomment the following configuration in the nodeos config.ini for history processing
echo
echo "Add/uncomment the following configuration in the fio-nodeos config.ini located"
echo "in /etc/fio/nodeos"
echo
echo plugin = eosio::history_plugin
echo plugin = eosio::history_api_plugin
echo filter-on = *
echo filter-out = eosio:onblock:
echo history-per-account = 9223372036854775807
echo history-index-state-db-size-mb = 1000000
echo history-state-db-size-mb = 4000000
fi
if [[ ${type} == "state" || ${type} == "all" ]]; then
echo
echo "Add/uncomment the following configuration in the fio-nodeos config.ini located"
echo "in /etc/fio/nodeos"
echo
echo plugin = eosio::state_history_plugin
echo state-history-dir = state-history
echo trace-history = true
echo chain-state-history = true
echo state-history-endpoint = 0.0.0.0:8080
fi
}
function do_replayHelp() {
echo
echo Installation of FIO Blockchain data will include:
echo " Removal of any existing data located in '/var/lib/fio'"
echo " Download and installation of the latest archive to '/var/lib/fio'"
echo " Update of ownership to be accessible by the fio-nodeos process"
echo " Removal of the previously downloaded archive."
echo
}
function do_installuninstall() {
echo
local PS3="Select Action: "
local items=("Install FIO" "Uninstall FIO" )
select item in "${items[@]}" "Return to Main Menu"
do
echo
echo -n "You've chosen to "
case $REPLY in
1) echo "$item"; do_install; break;;
2) echo "$item"; do_uninstall; break;;
$((${#items[@]}+1))) echo "Return to Main Menu!"; echo; break 2;;
*) echo "Ooops - unknown choice $REPLY"; echo; break;;
esac
done
}
function do_uninstall() {
echo
echo "Confirm complete removal of the fioprotocol package and all related artifacts..."
pause
do_stop true
# Remove installed package
echo
echo "Removing fioprotocol package, including binaries, from system..."
pause
apt remove fioprotocol
# Remove leftover artifacts from fio package install
echo
echo "Removing fioprotocol binaries from system..."
rm -f /usr/local/bin/cleos
rm -f /usr/local/bin/fio-cleos
rm -f /usr/local/bin/clio
rm -f /usr/local/bin/nodeos
rm -f /usr/local/bin/fio-nodeos
rm -f /usr/local/bin/fio-wallet
# ********************************** WARNING ***********************************
# The following commands remove runtime data that is critical for node execution
# Only proceed if cleanup of an outdated install is desired
# ******************************************************************************
# Remove configuration, blocks log, history, state
echo
echo "Removing fioprotocol artifacts including configuration, blocks, state, and history, from system..."
pause
rm -rf /etc/fio
rm -rf /var/lib/fio
rm -rf /var/log/fio
# Remove the fio user
# This step is useful if not re-installing/upgrading the fio package
echo
echo "Removing fioprotocol user from system..."
pause
#deluser --system --remove-home --group fio fio
deluser --force fio &>/dev/null
echo
}
function do_install() {
do_net
if [[ $? -ne 0 ]]; then
return
fi
# Determine OS
. /etc/os-release
if [[ ${VERSION_ID} != '18.04' && ${VERSION_ID} != '20.04' ]]; then
echo
echo "Only Ubuntu 18.04 and 20.04 are supported at this time. Exiting..."
echo && return
fi
echo
echo "Checking FIO Package dependencies..."
dpkg-query -W pixz &>/dev/null
if [[ $? -ne 0 ]]; then
echo
echo "Package dependency check failed! pixz is not installed and must be before proceeding."
echo "Install using the commands;"
echo " sudo apt install pixz"
echo
echo "Note that you may need to run 'sudo apt update && sudo apt upgrade -y' first"
echo
read -N 1 -p "Do you wish to install 'pixz' now (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
echo && apt update && echo
apt install pixz
else
echo & return
fi
fi
if [[ ${VERSION_ID} == '20.04' ]]; then
dpkg-query -W libicu60\* &>/dev/null
if [[ $? -ne 0 ]]; then
echo
echo "Package dependency check failed; libicu60 is not installed!"
echo
echo "Get and install libicu60 by;"
echo " Original URL: wget http://archive.ubuntu.com/ubuntu/pool/main/i/icu/libicu60_60.2-3ubuntu3_amd64.deb"
echo " FIO S3 URL: wget https://fioprotocol.s3.us-east-1.amazonaws.com/build-tools/libicu60_60.2-3ubuntu3_amd64.deb"
echo
echo " sudo apt install ./libicu60_60.2-3ubuntu3_amd64.deb"
echo
echo "Note that you may need to run 'sudo apt upgrade && sudo apt update -y' first"
echo
read -N 1 -p "Do you wish to install 'libicu60' now (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
echo && apt update && echo
wget https://fioprotocol.s3.us-east-1.amazonaws.com/build-tools/libicu60_60.2-3ubuntu3_amd64.deb
apt install ./libicu60_60.2-3ubuntu3_amd64.deb
else
echo && return
fi
fi
fi
echo "Package dependency check complete."
# FIO package download examples
# Release candidates and Release versions
# https://github.com/fioprotocol/fio/releases/download/v3.5.1/fioprotocol-3.5.1-rc1-ubuntu-20.04-amd64.deb
# https://github.com/fioprotocol/fio/releases/download/v3.5.1/fioprotocol-3.5.1-ubuntu-20.04-amd64.deb
# https://github.com/fioprotocol/fio/releases/download/v3.5.1/fioprotocol-3.5.1-rc1-ubuntu-22.04-amd64.deb
# https://github.com/fioprotocol/fio/releases/download/v3.5.1/fioprotocol-3.5.1-ubuntu-22.04-amd64.deb
# Note: Release Name only is used in download action
# GitHub
# release=3.5.0-rc1
# release=3.5.1
release=""
echo
echo "The release package version is required and must match a release package located at"
echo " - https://github.com/fioprotocol/fio/releases"
echo "Examples include:"
echo " - 3.5.0-rc1"
echo " - 3.5.1"
echo
read -p "Enter the release package version: " answer
if [[ "${answer,,}" != "" ]]; then
release="${answer}"
echo
read -N 1 -p "You input '${release}'. Correct (y/N)? " answer
if [[ "${answer,,}" != "y" ]]; then
echo && echo
echo Aborting install!
echo
return
fi
else
echo && echo
echo "No release package name entered, Aborting install!"
echo
return
fi
# Release path options
# GitHub
path="fio/releases/download/v${release}"
# Package filename
filename="fioprotocol-${release}-ubuntu-${VERSION_ID}-amd64.deb"
# Full Release download URL
url="${fioReleaseUri}/${path}/${filename}"
echo && echo
echo "Install package will be downloaded from the FIO Releases repository located at ${fioReleaseUri}"
pause
# Clean any previous downloads
rm -f $filename
# Check that file is at uri/filename
status=$( curl -L -o /dev/null --silent -Iw '%{http_code}' "${url}" )
if [[ ${status} -ne 200 ]]; then
echo
echo "Curl exited with status: $status; File, ${filename}, was not found at URL ${url}!"
echo
return
else
echo "Downloading FIO installation package..."
curl -L -sO "${url}"
fi
# Check a file was downloaded and is non-zero size
minimumsize=13142400
actualsize=$(wc -c <"$filename")
if [[ -e ${filename} && ( $actualsize -le $minimumsize) ]]; then
echo
echo "The file size appears incorrect (minimum size: 13142400, actual size: $actualsize). Was the file download interrupted or exit with an error?"
echo
pause
fi
echo
read -N 1 -p "Install package (y/N)? " answer
echo
if [[ "${answer,,}" != "y" ]]; then
echo
echo "You have elected to NOT install package, ${filename}."
echo
return
fi
echo
echo "Installing FIO package..."
echo
apt install ./${filename}
echo
if [[ "testnet" == "${type}" ]]; then
echo
echo "Updating fio-nodeos configuration for TestNet"
cp /etc/fio/nodeos/testnet-config.ini /etc/fio/nodeos/config.ini
rm /etc/fio/nodeos/genesis.json
ln -s /etc/fio/nodeos/genesis-testnet.json /etc/fio/nodeos/genesis.json
echo
echo "Note: Before starting fio-nodeos, verify that the nodeos configuration is"
echo "appropriate for a ${type} install. Parameters may still be set for MainNet"
echo "or may not be set at all, e.g. producer-name."
echo "See /etc/fio/nodeos/config.ini, /etc/fio/nodeos/genesis.json"
echo
fi
echo
echo "It may be necessary to update the FIO configuration to;"
echo "- Add producer name"
echo "- Check settings"
echo
echo "Select 'Configure FIO' or proceed with synchronization/replay"
echo
}
function do_startstop() {
local PS3="Select Action: "
local items=("Start FIO" "Stop FIO" )
select item in "${items[@]}" "Return to Main Menu"
do
echo
echo -n "You've chosen to "
case $REPLY in
1) echo "$item"; do_start; break;;
2) echo "$item"; do_stop; break;;
$((${#items[@]}+1))) echo "Return to Main Menu"; echo; break 2;;
*) echo "Ooops - unknown choice $REPLY"; break;
esac
done
}
function do_start() {
# Start fio-nodeos
echo
echo "Starting the FIO nodeos application may require configuration updates. Skip the"
echo "the following step if those have not yet been performed. The application may be"
echo "started at a later time using the commands;"
echo " - sudo systemctl enable fio-nodeos"
echo " - sudo systemctl start fio-nodeos"
echo
echo "To stop the fio-nodeos application for any reason, run the command;"
echo " - sudo systemctl stop fio-nodeos"
echo
read -N 1 -p "Start service 'fio-nodeos' (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
systemctl enable fio-nodeos
systemctl start fio-nodeos
fi
echo
echo
echo "fio-wallet: The following step will start the fio-wallet service. Things to note are:"
echo " This service is not required to run fio-nodeos."
echo " This service is not needed unless background management of keys is required."
echo " If so, please note that this service is NOT an enterprise application and no"
echo " gaurantee is stated or implied!"
echo " The fio-wallet service may be started anytime or run on demand when necessary"
echo " either stand-alone or via the clio command."
echo
read -N 1 -p "Start service 'fio-wallet' (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
systemctl enable fio-wallet
systemctl start fio-wallet
fi
echo
echo "Review '/var/log/fio/nodeos' for relevant blockchain logging."
echo
echo "FIO installation complete."
echo
}
function do_stop() {
local disable="${1}"
read -N 1 -p "Stop service 'fio-nodeos' (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
# Stop and disable fio-nodeo application
echo
echo "Stopping fio-nodeos..."
systemctl stop fio-nodeos
if [[ ${disable} ]]; then
systemctl -q disable fio-nodeos
fi
fi
read -N 1 -p "Stop service 'fio-wallet' (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
# Stop and disable fio-wallet application
echo
echo "Stopping fio-wallet..."
systemctl -q stop fio-wallet
if [[ ${disable} ]]; then
systemctl -q disable fio-wallet
fi
fi
}
function do_sync() {
echo
echo "Synchronizing from genesis means that your configured node will connect to the FIO P2P network,"
echo "process blocks from the first block of the inception of the chain up to present time, then"
echo "continue processing blocks as produced by the blockchain block producers."
echo
echo "To synchronize from genesis is only a matter of installing FIO, configuring FIO if needed,"
echo "and starting the chain"
echo
echo "Note: Configuration is usually only needed when processing history during synchronization"
do_configHelp "all"
do_configure
}
# Install fio chain state, blocks.log and or history
function do_replay() {
do_net
if [[ $? -ne 0 ]]; then
return
fi
echo
echo "You have elected to replay blocks from archived blockchain data which may include"
echo "state, a blocks.log and history. This will include download of an archive, extraction"
echo "of the archive to '/var/lib/data' and configuration of fio-nodeos."
echo
echo "Note that if startup from genesis is desired (synchronization from the p2p network),"
echo "the following steps are not needed other than possible configuration update."
echo
local PS3="Select Action: "
local items=("Replay from snapshot" "Replay from blocks.log" "Replay with V1 History" "Replay with State History" )
while true; do
select item in "${items[@]}" "Return to Main Menu"
do
echo
echo -n "You've chosen to "
case $REPLY in
1) echo "$item"; do_state; break;;
2) echo "$item"; do_blocks; break;;
3) echo "$item"; do_v1history; break;;
4) echo "$item"; do_statehistory; break;;
$((${#items[@]}+1))) echo "Return to Main Menu!"; echo; break 2;;
*) echo "Ooops - unknown choice $REPLY"; break;
esac
done
done
}
# Snapshot archive
function do_state() {
do_replayHelp
pause
echo
echo "Downloading FIO snapshot archive..."
getAndExtract ${fioArchiveUri} ${type}-latest-snap.txz
if [[ $? -eq 0 ]]; then
stateInstalled=true
do_configHelp "snapshot"
fi
}
# blocks.log and snapshot
function do_blocks() {
do_replayHelp
pause
echo
echo "Downloading FIO blocks.log archive..."
getAndExtract ${fioArchiveUri} ${type}-latest-blocks.txz
if [[ $? -eq 0 ]]; then
stateInstalled=true
do_configHelp "blocks"
fi
}
# v1 history, blocks.log, snapshot
function do_v1history() {
do_replayHelp
pause
echo
echo "Downloading FIO History archive..."
getAndExtract ${fioArchiveUri} ${type}-latest-history.txz
if [[ $? -eq 0 ]]; then
stateInstalled=true
do_configHelp "v1"
fi
}
# state history; blocks.log only
# grep ":state_history_plugin" /etc/fio/nodeos/config.ini | egrep "^[[:space:]]*#" &>/dev/null
# if [[ $? -ne 0 ]]; then
# sed -i '/exec/s/$/ --disable-replay-opts/' /usr/local/bin/fio-nodeos-run
# fi
function do_statehistory() {
do_replayHelp
pause
echo
echo "Downloading FIO blocks.log archive..."
getAndExtract ${fioArchiveUri} ${type}-latest-blocks.txz
if [[ $? -eq 0 ]]; then
stateInstalled=true
rm -f /var/lib/fio/data/blocks/blocks.index
do_configHelp "state"
fi
}
function do_start() {
# Start fio-nodeos
echo
echo "Starting the FIO nodeos application may require configuration updates. Skip the"
echo "the following step if those have not yet been performed. The application may be"
echo "started at a later time using the commands;"
echo " - sudo systemctl enable fio-nodeos"
echo " - sudo systemctl start fio-nodeos"
echo
echo "To stop the fio-nodeos application for any reason, run the command;"
echo " - sudo systemctl stop fio-nodeos"
echo
read -N 1 -p "Start service 'fio-nodeos' (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
systemctl enable fio-nodeos
systemctl start fio-nodeos
fi
echo && echo
echo "fio-wallet: The following step will start the fio-wallet service. Things to note are:"
echo " This service is not required to run fio-nodeos."
echo " This service is not needed unless background management of keys is required."
echo " If so, please note that this service is NOT an enterprise application and no"
echo " gaurantee is stated or implied!"
echo " The fio-wallet service may be started anytime or run on demand when necessary"
echo " either stand-alone or via the clio command."
echo
read -N 1 -p "Start service 'fio-wallet' (y/N)? " answer
if [[ "${answer,,}" == "y" ]]; then
systemctl enable fio-wallet
systemctl start fio-wallet
fi
echo
echo "Review '/var/log/fio/nodeos' for relevant blockchain logging."
echo
echo "FIO installation complete."
echo
}
function do_stop() {
systemctl stop fio-nodeos
systemctl stop fio-wallet
}
# Constants, Variables
# FIO Releases
#fioReleaseUri="https://bin.fioprotocol.io" # S3 Bucket
fioReleaseUri="https://github.com/fioprotocol" # GitHub Releases
# FIO Snapshot, blocks.log, history archive URI
fioArchiveUri="https://snap.blockpane.com"
# TestNet/MainNet deployment type
type=""
# Booleans supporting install workflow
stateInstalled=false
# Main script functionality
PS3="Select Action: "
#items=("Install/Uninstall FIO" "Start/Stop FIO" "Install State" "Install Blocks.log" "Install V1 History" "Install State History" "Edit Config" )
items=("Install/Uninstall FIO" "Start/Stop FIO" "Sync From Genesis" "Replay From Archive" "Configure FIO" )
COLUMNS=1
while true; do
select item in "${items[@]}" Quit
do
echo
echo -n "You've chosen to "
case $REPLY in
1) echo "$item"; do_installuninstall; break;;
2) echo "$item"; do_startstop; break;;
3) echo "$item"; do_sync; break;;
4) echo "$item"; do_replay; break;;
5) echo "$item"; do_configure; break;;
$((${#items[@]}+1))) echo "Exit!"; echo; break 2;;
*) echo "Ooops - unknown choice $REPLY"; echo; break;
esac
done
done
Updated 23 days ago