#!/bin/bash
#set -x -e

SOLANA_DIR=/root/solana
mkdir -p $SOLANA_DIR

echo "###################### WARNING!!! ###################################"
echo "###   This script will perform the following operations:          ###"
echo "###   * download and install validator binaries                   ###"
echo "###   * system tuning (install systuner.service)                  ###"
echo "###   * system tuning (edit fstrim.timer daily on mainnet)        ###"
echo "###   * create vote account (option)                              ###"
echo "###   * create service files                                      ###"
echo "###   * install monitoring (option)                               ###"
echo "###   * configure firewall                                        ###"
echo "###   * create ramdisk (option)                                   ###"
echo "###                                                               ###"
echo "###   *** Script provided by MARGUS.ONE                           ###"
echo "#####################################################################"
echo
echo "### Which version should I install?? ###"
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
  select cluster in "mainnet-beta" "testnet"; do
      case $cluster in
          mainnet-beta )
            url="https://api.mainnet-beta.solana.com"
            solanaversion="$(wget -q -4 -O- https://api.margus.one/solana/version/?cluster=mainnet)"
			clusternetwork="mainnet"
            break;;
          testnet )
            url="https://api.testnet.solana.com"
            solanaversion="$(wget -q -4 -O- https://api.margus.one/solana/version/?cluster=testnet)"
			clusternetwork="testnet"
            break;;
      esac
  done

apt update -y && apt upgrade -y && apt install curl gnupg git ufw wget -y

install_solana() {
echo "###########################################"
echo "### Installing Solana $solanaversion $cluster" 
echo "###########################################"

sh -c "$(curl -sSfL https://release.solana.com/v$solanaversion/install)" && \
export PATH="/root/.local/share/solana/install/active_release/bin:$PATH"
solana --version && \
solana config set --url $url --keypair $SOLANA_DIR/validator-keypair.json
}


system_tuning() {
echo "###########################################"
echo "###        Start system tuning          ###"
echo "###########################################"

curl -fsSL https://api.margus.one/solana/tuning.sh | bash

if [[ $clusternetwork = testnet ]];then 
echo "This is testnet. No edit fstrim.timer"
elif [ $clusternetwork = mainnet ];then 
echo "Edit /lib/systemd/system/fstrim.timer"
cat > /lib/systemd/system/fstrim.timer <<EOF
[Unit]
Description=Discard unused blocks once a week
Documentation=man:fstrim
ConditionVirtualization=!container

[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true

[Install]
WantedBy=timers.target
EOF
fi
}

create_vote_account() {
echo "###########################################"
echo "### 	      Create vote account?		     "
echo "###########################################"
select new_vote in "Yes, don't use password for keypair (--no-bip39-passphrase)" "Yes, use password for keypair (bip39-passphrase)" "No"; do
    case $new_vote in
        "Yes, don't use password for keypair (--no-bip39-passphrase)")
			if [[ $clusternetwork = mainnet ]];then
			solana-keygen new --no-bip39-passphrase -o $SOLANA_DIR/vote-account-keypair.json
			solana-keygen new --no-bip39-passphrase -o $SOLANA_DIR/aw.json
			solana create-vote-account $SOLANA_DIR/vote-account-keypair.json $SOLANA_DIR/validator-keypair.json $SOLANA_DIR/aw.json --commission 10
			else
			solana-keygen new --no-bip39-passphrase -o $SOLANA_DIR/vote-account-keypair.json
			solana-keygen new --no-bip39-passphrase -o $SOLANA_DIR/aw.json
			solana airdrop 1 $(solana address)
			solana create-vote-account $SOLANA_DIR/vote-account-keypair.json $SOLANA_DIR/validator-keypair.json $SOLANA_DIR/aw.json
			fi
			break
            ;;
		"Yes, use password for keypair (bip39-passphrase)")
		    if [[ $clusternetwork = mainnet ]];then
			solana-keygen new -o $SOLANA_DIR/vote-account-keypair.json
			solana-keygen new -o $SOLANA_DIR/aw.json
			solana create-vote-account $SOLANA_DIR/vote-account-keypair.json $SOLANA_DIR/validator-keypair.json $SOLANA_DIR/aw.json --commission 10
			else
			solana-keygen new -o $SOLANA_DIR/vote-account-keypair.json
			solana-keygen new -o $SOLANA_DIR/aw.json
			solana airdrop 1 $(solana address)
			solana create-vote-account $SOLANA_DIR/vote-account-keypair.json $SOLANA_DIR/validator-keypair.json $SOLANA_DIR/aw.json
			fi
			break
            ;;
        "No")
            break
            ;;
        *) echo "invalid option $REPLY";;
    esac
done
}

create_service_files() {
echo "######################################"
echo "### 	   Create service files		 "
echo "######################################"
if [[ $clusternetwork = testnet ]];then 
cd $SOLANA_DIR
rm -fr solana.service
wget https://api.margus.one/solana/testnet/solana_rpc.service && mv solana_rpc.service solana.service
elif [ $clusternetwork = mainnet ];then 
cd $SOLANA_DIR
rm -fr solana.service
wget https://api.margus.one/solana/mainnet/solana.service
fi

cat > $SOLANA_DIR/solana.logrotate <<EOF
$SOLANA_DIR/solana.log {
  rotate 7
  daily
  missingok
  postrotate
    systemctl kill -s USR1 solana.service
  endscript
}
EOF
}


create_symbolic_link() {
echo "####################################################"
echo "###  Create symbolic link and enable on startup  ###"
echo "####################################################"
sudo ln -s $SOLANA_DIR/solana.service /etc/systemd/system
sudo ln -s $SOLANA_DIR/solana.logrotate /etc/logrotate.d/
systemctl daemon-reload
sudo systemctl enable $SOLANA_DIR/solana.service
}

install_monitoring() {
echo "###########################################"
echo "###         Install monitoring          ###"
echo "###########################################"
#cat <<
#deb https://repos.influxdata.com/ubuntu bionic stable
#EOF
#curl -sL https://repos.influxdata.com/influxdb.key | apt-key add -
wget -q https://repos.influxdata.com/influxdata-archive_compat.key
echo '393e8779c89ac8d958f81f942f9ad7fb82a25e133faddaf92e15b16e6ac9ce4c influxdata-archive_compat.key' | sha256sum -c && cat influxdata-archive_compat.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg > /dev/null
echo 'deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg] https://repos.influxdata.com/debian stable main' | sudo tee /etc/apt/sources.list.d/influxdata.list
apt-get update
apt-get -y install telegraf jq bc
adduser telegraf sudo
adduser telegraf adm
echo "telegraf ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
cp /etc/telegraf/telegraf.conf /etc/telegraf/telegraf.conf.orig
rm -rf /etc/telegraf/telegraf.conf
cd $SOLANA_DIR && git clone https://github.com/solstaker/solanamonitoring/
chmod +x $SOLANA_DIR/solanamonitoring/monitor.sh
echo "###########################################"
echo "### Please type your validator name     ###"
echo "###########################################"
read -p "Validator name:" VALIDATOR_NAME
touch /etc/telegraf/telegraf.conf
cat > /etc/telegraf/telegraf.conf <<EOF
# Global Agent Configuration
[agent]
  hostname = "$VALIDATOR_NAME" # set this to a name you want to identify your node in the grafana dashboard
  flush_interval = "15s"
  interval = "15s"
# Input Plugins
[[inputs.cpu]]
    percpu = true
    totalcpu = true
    collect_cpu_time = false
    report_active = false
[[inputs.disk]]
    ignore_fs = ["devtmpfs", "devfs"]
[[inputs.mem]]
[[inputs.net]]
[[inputs.system]]
[[inputs.swap]]
[[inputs.netstat]]
[[inputs.processes]]
[[inputs.kernel]]
[[inputs.diskio]]
# Output Plugin InfluxDB
[[outputs.influxdb]]
  database = "metricsdb"
  urls = [ "http://metrics.stakeconomy.com:8086" ] # keep this to send all your metrics to the community dashboard otherwise use http://yourownmonitoringnode:8086
  username = "metrics" # keep both values if you use the community dashboard
  password = "password"
[[inputs.exec]]
  commands = ["sudo su -c $SOLANA_DIR/solanamonitoring/monitor.sh -s /bin/bash root"] # change home and username to the useraccount your validator runs at
  interval = "3m"
  timeout = "1m"
  data_format = "influx"
  data_type = "integer"
EOF

sudo systemctl enable --now telegraf
}

ufw_configure() {
echo "###########################################"
echo "###      Configure ufw firewall         ###"
echo "###      Enable ufw (y|n)?              ###"
echo "###########################################"
sudo ufw allow 22/tcp
sudo ufw allow 2222/tcp
sudo ufw allow 8000:8020/tcp
sudo ufw allow 8000:8020/udp
sudo ufw allow 8899:8900/tcp
ufw allow 80:81/tcp
sudo ufw deny out from any to 10.0.0.0/8
sudo ufw deny out from any to 172.16.0.0/12
sudo ufw deny out from any to 192.168.0.0/16
sudo ufw deny out from any to 100.64.0.0/10
sudo ufw deny out from any to 198.18.0.0/15
sudo ufw deny out from any to 169.254.0.0/16
sudo ufw enable
}

ramdisk_setup() {
read -p "Enter new RAM drive size, GB (default: 200):" RAMDISK
read -p "Enter new server swap size GB (ramdisk minus free RAM; default: 168) :" SWAP
RDRIVEINFO=$(df -h | grep ramdisk)
if [ -d /mnt/ramdisk ] & [ "$RDRIVEINFO" != "" ];then
echo "Ramdisk already exists, remount..."
mount -o remount,nodev,nosuid,noexec,nodiratime,size="$RAMDISK"G /mnt/ramdisk
swapoff -a
dd if=/dev/zero of=/root/swapfile bs=1G count=$SWAP
chmod 600 /root/swapfile
mkswap /root/swapfile
swapon /root/swapfile
sed -i '/swap/s/^/#/' /etc/fstab
echo "/root/swapfile none swap sw 0 0" >> /etc/fstab
else
swapoff -a
dd if=/dev/zero of=/root/swapfile bs=1G count=$SWAP
chmod 600 /root/swapfile
mkswap /root/swapfile
swapon /root/swapfile
sed -i '/swap/s/^/#/' /etc/fstab
echo "/root/swapfile none swap sw 0 0
tmpfs /mnt/ramdisk tmpfs nodev,nosuid,noexec,nodiratime,size="$RAMDISK"G 0 0" >> /etc/fstab
mkdir -p /mnt/ramdisk
mount /mnt/ramdisk
fi
}
 
install_solana
create_vote_account
system_tuning
create_service_files
create_symbolic_link
ufw_configure

echo "### Install monitoring?? ###"
  select monitoring in "Yes" "No"; do
      case $monitoring in
          Yes )
            install_monitoring        			
            break;;
          No )
            break;;
      esac
  done

echo "### Create RAMDISK??  ###"
  select createramdisk in "Yes" "No"; do
      case $createramdisk in
          Yes )
            ramdisk_setup        			
            break;;
          No )
            break;;
      esac
  done


echo "### Install is complete."
echo "### Server name: $VALIDATOR_NAME"
echo "### Cluster: $clusternetwork"
echo "### You identity pubkey: $(solana address)"
echo "### You vote pubkey: $(solana-keygen pubkey $SOLANA_DIR/vote-account-keypair.json)"
echo "### You balance: $(solana balance)"
echo "### You IP: $(wget -q -4 -O- http://icanhazip.com)"
echo "### Please reboot your server."

exit 0