From 7b59411e5f4d15291e8ed9ff57e871ebedad2144 Mon Sep 17 00:00:00 2001 From: Uncle Stinky Date: Mon, 7 Oct 2024 20:36:11 +0300 Subject: [PATCH] more or less working version, enough to get started Signed-off-by: Uncle Stinky --- scripts/local-builder.sh | 195 ------------------ scripts/packaging/template.service | 9 +- scripts/starter.sh | 310 +++++++++++++++++++++++++++++ 3 files changed, 314 insertions(+), 200 deletions(-) delete mode 100755 scripts/local-builder.sh create mode 100755 scripts/starter.sh diff --git a/scripts/local-builder.sh b/scripts/local-builder.sh deleted file mode 100755 index 225648a..0000000 --- a/scripts/local-builder.sh +++ /dev/null @@ -1,195 +0,0 @@ -#!/bin/bash - -set -e - -UNIT_FILE=false -SKIP_BUILD=false -EXECUTABLE_PATH="/usr/bin/" -SPECIFICATION_PATH="/etc/ghost/" -SPECIFICATION_NAME="casper" -TARGET="debug" - -CURRENT_PATH=$(pwd) -CURRENT_SCRIPT=$(realpath "$0") -SCRIPT_FOLDER=$(dirname "$CURRENT_SCRIPT") -PROJECT_FOLDER=("$SCRIPT_FOLDER/..") - -prompt() { - while true; do - printf "$1 [y/N]: " - read yn - case $yn in - [Yy]* ) return 0;; - * ) return 1;; - esac - done -} - -clear -echo " ____ _ _ _ _ _" -echo " / ___| |__ ___ ___| |_ | \ | | ___ __| | ___" -echo "| | _| '_ \ / _ \/ __| __| | \| |/ _ \ / _' |/ _ \\" -echo "| |_| | | | | (_) \__ \ |_ | |\ | (_) | (_| | __/" -echo " \____|_| |_|\___/|___/\__| |_| \_|\___/ \__,_|\___|" -echo -e "\n" - -while [ $# -gt 0 ]; do - case "$1" in - --unit-file|-u) - UNIT_FILE=true - ;; - --make-global|-m) - MAKE_GLOBAL=true - ;; - --arguments|-a) - ARGUMENTS=true - ;; - --release|-r) - RELEASE="--release" - TARGET="release" - ;; - --profile*|-p*) - if [[ "$1" != *=* ]]; then shift; fi - RELEASE="--profile=${1#*=}" - TARGET="${1#*=}" - ;; - --feature*|-f*) - if [[ "$1" != *=* ]]; then shift; fi - FEATURES="--features=${1#*=}" - ;; - --executable-path*|-e*) - if [[ "$1" != *=* ]]; then shift; fi - EXECUTABLE_PATH=$(echo ${1#*=}/ | tr -s /) - ;; - --specification-path*|-f*) - if [[ "$1" != *=* ]]; then shift; fi - SPECIFICATION_PATH=$(echo ${1#*=}/ | tr -s /) - ;; - --specification-name*|-n*) if [[ "$1" != *=* ]]; then shift; fi - SPECIFICATION_NAME="${1#*=}" - ;; - --help|-h) - echo "Ghost Node Build automation tool." - echo -e "Use wisely, the main purpose of this script is to help people not to mess up with pathes/folders to the ghost node.\n" - echo "Options:" - echo -e "-b, --skip-build\n\tSkip build only copying." - echo -e "-e, --executable-path\n\tPath to executable ('/usr/lib/' is default)." - echo -e "-a, --specification-path\n\tPath to specification ('/etc/ghost' is default)." - echo -e "-n, --specification-name\n\tSpecification name to be used ('casper' is default)." - echo -e "-r, --release\n\tBuild optimized artifacts with the release profile." - echo -e "-p, --profile\n\tBuild with the given and predefined profile." - echo -e "-h, --help\n\tPrints help information." - exit 0 - ;; - *) - echo -e "[-] Wrong arguments\n" - echo "Ghost Node Build automation tool." - echo -e "Use wisely, the main purpose of this script is to help people not to mess up with pathes/folders to the ghost node.\n" - echo "Options:" - echo -e "-b, --skip-build\n\tSkip build only copying." - echo -e "-e, --executable-path\n\tPath to executable ('/usr/lib/' is default)." - echo -e "-a, --specification-path\n\tPath to specification ('/etc/ghost' is default)." - echo -e "-n, --specification-name\n\tSpecification name to be used ('casper' is default)." - echo -e "-r, --release\n\tBuild optimized artifacts with the release profile." - echo -e "-p, --profile\n\tBuild with the given and predefined profile." - echo -e "-h, --help\n\tPrints help information." - exit 1 - ;; - esac - shift -done - -if [[ ! -z $RELEASE ]]; then - if prompt "[?] 'cargo build $RELEASE $FEATURES' is what you want?"; then - cd $PROJECT_FOLDER - echo "[+] Starting build in 3 seconds..." - sleep 3 - cargo build $RELEASE $FEATURES - fi -fi - -if [[ $MAKE_GLOBAL = true ]]; then - cd $PROJECT_FOLDER - sudo cp target/$TARGET/ghost $EXECUTABLE_PATH - cp service/chain-specs/$SPECIFICATION_NAME.json $SPECIFICATION_PATH - cd $SCRIPT_FOLDER - cp packaging/environment $SPECIFICATION_PATH - - echo "[+] ghost executable copied in '$EXECUTABLE_PATH' from '$TARGET'" - echo "[+] specification '$SPECIFICATION_NAME.json' copied to '$SPECIFICATION_PATH'" - echo "[+] default CLI arguments exported into '$SPECIFICATION_NAME'" -fi - -if [ $UNIT_FILE = true ]; then - cd $SCRIPT_FOLDER - read -p "[?] name for the unit file (default: ghost-node.service) " unit_name - if [ -z $unit_name ]; then - unit_name="ghost-node" - fi - unit_name=$(echo "$unit_name" | sed -e "s/.service//g") - unit_name="$unit_name.service" - - cp /packaging/template.service /etc/systemd/user - sudo systemctl daemon-reload - - if prompt "[?] do you want to start the $unit_name?"; then - sudo systemctl restart $unit_name - fi - - if prompt "[?] do you want to enable the $unit_name?"; then - sudo systemctl enable $unit_name - fi -fi - -if [[ $ARGUMENTS = true ]]; then - echo "[+] setting-up basic CLI arguments" - CLI_ARGS=() - - read -p "[?] specify p2p protocol TCP port (default: 30333): " port - CLI_ARGS+=("--port=${port:-30333}") - - read -p "[?] specify JSON-RPC server TCP port: (default: 9945): " rpc_port - CLI_ARGS+=("--rpc-port=${rpc_port:-9945}") - - read -p "[?] specify the chain specification (default: /etc/ghost/casper.json): " chain - CLI_ARGS+=("--chain=${chain:-/etc/ghost/casper.json}") - - read -p "[?] specify file from which to read the node's secret key for p2p networking (default: /etc/ghost/node-key): " node_key - CLI_ARGS+=("--node-key-file=${node_key:-/etc/ghost/node-key}") - - read -p "[?] specify name for the node (default: RANDOM_NAME): " node_name - if [[ ! -z $node_name ]]; then - CLI_ARGS+=("--name='$node_name'") - fi - - read -p "[?] specify custom base path for the node (default: /var/lib/ghost): " base_path - CLI_ARGS+=("--base-path=${base_path:-/var/lib/ghost}") - - if prompt "[?] enable validator mode?"; then - CLI_ARGS+=("--validator") - fi - - if prompt "[?] enable prometheus?"; then - read -p "[?] specify prometheus exporter TCP port: (default: 9615)" prometheus_port - CLI_ARGS+=("--prometheus-port=${prometheus_port:-9615}") - else - CLI_ARGS+=("--no-prometheus") - fi - - # default for now - CLI_ARGS+=("--state-prunning=archieve") - CLI_ARGS+=("--rpc-external=local") - CLI_ARGS+=("--rpc-methods=auto") - CLI_ARGS+=("--no-telemetry") - CLI_ARGS+=("--no-private-ip") - CLI_ARGS+=("--no-mdns") - CLI_ARGS+=("--no-hardware-benchmarks") - - sudo echo "GHOST_CLI_ARGS=\"$(IFS=' '; echo "${CLI_ARGS[*]}")\"" > /etc/default/ghost - echo "[+] new CLI arguments stored in '/etc/default/ghost'" - cat /etc/default/ghost -fi - -# back to the starting point -cd $CURRENT_PATH -echo "[+] execution finished" diff --git a/scripts/packaging/template.service b/scripts/packaging/template.service index 75836f8..d745ae8 100644 --- a/scripts/packaging/template.service +++ b/scripts/packaging/template.service @@ -7,10 +7,9 @@ Documentation=https://git.ghostchain.io/ghostchain/ghost-node EnvironmentFile=-/etc/default/ghost ExecStart=/usr/bin/ghost $GHOST_CLI_ARGS User=ghost -Group=ghost Restart=always RestartSec=30 -TODO CapabilityBoundingSet= +CapabilityBoundingSet= LockPersonality=true NoNewPrivileges=true PrivateDevices=true @@ -22,10 +21,10 @@ ProtectControlGroups=true ProtectHostname=true ProtectKernelModules=true ProtectKernelTunables=true -TODO ProtectSystem=strict +ProtectSystem=strict RemoveIPC=true -TODO RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX -gRestrictNamespaces=false +RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX +RestrictNamespaces=false RestrictSUIDSGID=true SystemCallArchitectures=native SystemCallFilter=@system-service diff --git a/scripts/starter.sh b/scripts/starter.sh new file mode 100755 index 0000000..51476d5 --- /dev/null +++ b/scripts/starter.sh @@ -0,0 +1,310 @@ +#!/bin/bash + +set -Ee + +UNIT_FILE=false +SKIP_BUILD=false +SET_ENVIRONMENT=false +EXECUTABLE_PATH="/usr/bin/" +SPECIFICATION_PATH="/etc/ghost/" +NODE_PATH="/var/lib/ghost" +SPECIFICATION_NAME="casper" +TARGET="release" + +CURRENT_PATH=$(pwd) +CURRENT_SCRIPT=$(realpath "$0") +SCRIPT_FOLDER=$(dirname "$CURRENT_SCRIPT") +PROJECT_FOLDER=("$SCRIPT_FOLDER/..") + +final() { + cd $CURRENT_PATH + if [[ $1 -eq 1 ]]; then + echo "[-] error occured during execution" + else + echo "[+] execution finished" + fi + exit $1 +} + +prompt() { + while true; do + printf "$1 [y/N]: " + read yn + case $yn in + [Yy]* ) return 0;; + * ) return 1;; + esac + done +} + +trap 'final "$?"' EXIT + +help() { + echo -e "Ghost Node Build automation tool. Helper for Ghost Node environment preparation.\n" + echo -e "With no OPTION nothing will happen, possible OPTION:\n" + echo -e "-i, --set-environment\n\tSet up rust environment." + echo -e "-u, --unit-file\n\tCreation of systemd unit file." + echo -e "-m, --make-global\n\tStore compiled ghost executable and chain specification globally." + echo -e "-a, --set-arguments\n\tPrepare CLI arguments for running ghost node." + echo -e "-r, --release\n\tCompile node with '--release' flag." + echo -e "-p, --profile\n\tCompile node with '--profile [PROFILE]' flag." + echo -e "-f, --features\n\tCompilation features '--features=\"FEATURE1,FEATURE2\"'" + echo -e "-e, --executable-path\n\tPath to executable ('/usr/lib/' is default)." + echo -e "-c, --specification-path\n\tPath to specification ('/etc/ghost' is default)." + echo -e "-n, --specification-name\n\tSpecification name to be used ('casper' is default)." + echo -e "-h, --help\n\tPrints help information." +} + +clear +echo " ____ _ _ _ _ _" +echo " / ___| |__ ___ ___| |_ | \ | | ___ __| | ___" +echo "| | _| '_ \ / _ \/ __| __| | \| |/ _ \ / _' |/ _ \\" +echo "| |_| | | | | (_) \__ \ |_ | |\ | (_) | (_| | __/" +echo " \____|_| |_|\___/|___/\__| |_| \_|\___/ \__,_|\___|" +echo -e "\nCreated by st1nky (stinky@ghostchain.io)" +echo -e "Repository: https://git.ghostchain.io/ghostchain/ghost-node" +echo -e "Usage: local-builder.sh [OPTION]\n" + +while [ $# -gt 0 ]; do + case "$1" in + --set-environment|-i) + SET_ENVIRONMENT=true + ;; + --unit-file|-u) + UNIT_FILE=true + ;; + --make-global|-m) + MAKE_GLOBAL=true + ;; + --set-arguments|-a) + ARGUMENTS=true + ;; + --release|-r) + RELEASE="--release" + TARGET="release" + ;; + --profile*|-p*) + if [[ "$1" != *=* ]]; then shift; fi + RELEASE="--profile=${1#*=}" + TARGET="${1#*=}" + ;; + --feature*|-f*) + if [[ "$1" != *=* ]]; then shift; fi + FEATURES="--features=${1#*=}" + ;; + --executable-path*|-e*) + if [[ "$1" != *=* ]]; then shift; fi + EXECUTABLE_PATH=$(echo ${1#*=}/ | tr -s /) + ;; + --specification-path*|-c*) + if [[ "$1" != *=* ]]; then shift; fi + SPECIFICATION_PATH=$(echo ${1#*=}/ | tr -s /) + ;; + --specification-name*|-n*) if [[ "$1" != *=* ]]; then shift; fi + SPECIFICATION_NAME="${1#*=}" + ;; + --help|-h) + help + exit 0 + ;; + *) + help + exit 1 + ;; + esac + shift +done + +if [[ $SET_ENVIRONMENT = true ]]; then + echo -e "\n" + echo "WARNING!!! THIS IS HIGHLY EXPERIMENTAL FLAG, USE IT ONLY ON YOUR" + echo "OWN RISK! NOT EVERY SYSTEM CHECKED AND PROVED TO BE WORKING AS" + echo "EXPECTED! FOR THOSE WHO FOUND BUG OR SOME INCONSISTENCY FEEL" + echo "FREE TO FILL ISSUE ON https://git.ghostchain.io/ghostchain/ghost-node/issues" + echo -e "\n" + if prompt "[?] are you brave enough?"; then + echo "[+] you were warned, I hope you know what you're doing" + else + echo "[-] aborting environment setup" + exit 1 + fi + + if command -v rustc >/dev/null 2>&1; then + echo "[+] rust already installed" + else + os_name=$(uname -s) + cd $HOME + if [ "$os_name" = "Darwin" ]; then + echo "[+] detected MacOS. installing dependencies via homebrew" + + if command -v brew >/dev/null 2>&1; then + echo "[+] already installed: $(brew --version)" + else + if prompt "[?] do you want to install homebrew?"; then + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + else + echo "[-] cannot continue without homebrew" + exit 1 + fi + fi + + brew update + + if prompt "[?] install git, cmake, openssl and protobuf?"; then + brew install git cmake openssl protobuf + else + echo "[!] assuming git, cmake, openssl and protobuf are present" + fi + elif [ "$os_name" == "Linux" ]; then + distro=$(cat /etc/*-release | tr '[:upper:]' '[:lower:]' | grep -Poi '(debian|ubuntu|arch|fedora|opensuse)' | uniq | head -n 1) + echo $distro + + if [ "$distro" = "ubuntu" ]; then + echo "[+] ubuntu detected, using apt to install dependencies" + sudo apt update + sudo apt install --assume-yes git make clang curl libssl-dev protobuf-compiler + elif [ "$distro" = "debian" ]; then + echo "[+] debian detected, using apt to install dependencies" + sudo apt update + sudo apt install --assume-yes git make clang curl libssl-dev llvm libudev-dev protobuf-compiler + elif [ "$distro" = "arch" ]; then + echo "[+] arch linux detected, using pacman to install dependencies" + sudo pacman -Syu --needed --no-confirm curl git clang make protobuf + elif [ "$distro" = "fedora" ]; then + echo "[+] fedora detected, using dnf to install dependencies" + sudo dnf update --assumeyes + sudo dnf install --assumeyes clang curl git openssl-devel make protobuf-compiler perl + elif [ "$distro" = "opensuse" ]; then + echo "[+] openSUSE detected, using zypper to install dependencies" + sudo zypper install --no-confirm clang gcc gcc-c++ curl git openssl-devel llvm-devel libudev-devel make awk protobuf-devel + else + if prompt "[?] unknown linux distribution, unable to install dependencies. continue anyway?"; then + echo "[+] proceeding with unknown linux distribution" + else + echo "[-] aborting with uknown distribution" + exit 1 + fi + fi + else + echo "[-] unknown operating system" + exit 1 + fi + fi + + if prompt "[?] setup the rust environment (e.g. WASM support)?"; then + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + fi +fi + +if [[ ! -z $RELEASE ]]; then + if prompt "[?] 'cargo build $RELEASE $FEATURES' is what you want?"; then + cd $PROJECT_FOLDER + echo "[+] Starting build in 3 seconds..." + sleep 3 + cargo build $RELEASE $FEATURES + fi +fi + +if [[ $MAKE_GLOBAL = true ]]; then + cd $PROJECT_FOLDER + sudo cp target/$TARGET/ghost $EXECUTABLE_PATH + cp service/chain-specs/$SPECIFICATION_NAME.json $SPECIFICATION_PATH + + echo "[+] ghost executable copied in '$EXECUTABLE_PATH' from '$TARGET'" + echo "[+] specification '$SPECIFICATION_NAME.json' copied to '$SPECIFICATION_PATH'" +fi + +if [ $UNIT_FILE = true ]; then + cd $SCRIPT_FOLDER + read -p "[?] name for the unit file (default: ghost-node.service) " unit_name + if [ -z $unit_name ]; then + unit_name="ghost-node" + fi + unit_name=$(echo "$unit_name" | sed -e "s/.service//g") + unit_name="$unit_name.service" + + user_name="ghost" + if id $user_name > /dev/null 2>&1; then + echo "[+] user ghost found, continue for the user ghost" + else + echo "[!] user ghost not found" + if prompt "[?] do you want to create ghost user? (NOT RECOMMENDED: current $(whoami))"; then + sudo useradd --system --create-home $user_name + if [ ! -d $NODE_PATH ]; then + echo "[+] create folder for the node at '$NODE_PATH'" + sudo mkdir $NODE_PATH + fi + else + user_name=$(whoami) + fi + sudo chown $user_name $NODE_PATH + echo "[+] write permission to '$NODE_PATH'" + fi + + cp packaging/template.service /tmp/$unit_name + sed -i -e "s/User=ghost/User=$user_name/g" /tmp/$unit_name + + sudo cp packaging/template.service /etc/systemd/system/$unit_name + sudo systemctl daemon-reload + + if prompt "[?] do you want to start the $unit_name?"; then + sudo systemctl restart $unit_name + fi + + if prompt "[?] do you want to enable the $unit_name?"; then + sudo systemctl enable $unit_name + fi +fi + +if [[ $ARGUMENTS = true ]]; then + echo "[+] setting-up default CLI arguments" + CLI_ARGS=() + + read -p "[?] specify p2p protocol TCP port (default: 30333): " port + CLI_ARGS+=("--port=${port:-30333}") + + read -p "[?] specify JSON-RPC server TCP port: (default: 9945): " rpc_port + CLI_ARGS+=("--rpc-port=${rpc_port:-9945}") + + read -p "[?] specify the chain specification (default: /etc/ghost/casper.json): " chain + CLI_ARGS+=("--chain=${chain:-/etc/ghost/casper.json}") + + read -p "[?] specify node's secret key file for p2p networking (default: /etc/ghost/node-key): " node_key + CLI_ARGS+=("--node-key-file=${node_key:-/etc/ghost/node-key}") + + read -p "[?] specify name for the node (default: RANDOM_NAME): " node_name + if [[ ! -z $node_name ]]; then + CLI_ARGS+=("--name='$node_name'") + fi + + CLI_ARGS+=("--validator") + if prompt "[?] disable validator mode?"; then + unset CLI_ARGS[-1] + fi + + if prompt "[?] enable prometheus?"; then + read -p "[?] specify prometheus exporter TCP port: (default: 9615)" prometheus_port + CLI_ARGS+=("--prometheus-port=${prometheus_port:-9615}") + else + CLI_ARGS+=("--no-prometheus") + fi + + # default for now + CLI_ARGS+=("--base-path=$NODE_PATH") + CLI_ARGS+=("--state-pruning=archive") + CLI_ARGS+=("--blocks-pruning=archive") + CLI_ARGS+=("--rpc-methods=auto") + CLI_ARGS+=("--no-telemetry") + CLI_ARGS+=("--no-private-ip") + CLI_ARGS+=("--no-mdns") + CLI_ARGS+=("--no-hardware-benchmarks") + + echo "GHOST_CLI_ARGS=\"$(IFS=' '; echo "${CLI_ARGS[*]}")\"" > /tmp/ghost + sudo cp /tmp/ghost /etc/default/ghost + rm /tmp/ghost + echo "[+] new CLI arguments stored in '/etc/default/ghost'" + cat /etc/default/ghost +fi