From 7385eea3d279baea073c2f4ab894df5951f7e91b Mon Sep 17 00:00:00 2001 From: caskd Date: Sat, 23 Mar 2019 16:02:15 +0100 Subject: [PATCH] New plugin formatting and existing plugins added --- .gitignore | 5 +- extensions/gitreleases.func | 7 + manager | 281 ++++++++++++++------------------- plugins/backup/env.example | 17 ++ plugins/backup/main.sh | 17 ++ plugins/cloudflare/env.example | 3 + plugins/cloudflare/main.sh | 65 ++++++++ plugins/docker/main.sh | 42 +++++ plugins/maintenance/main.sh | 18 +++ plugins/pterodactyl/main.sh | 30 ++++ plugins/rx-firewalls/main.sh | 25 +++ plugins/selfupdate/main.sh | 12 ++ plugins/service/main.sh | 35 ++++ plugins/yagpdb/main.sh | 5 + 14 files changed, 399 insertions(+), 163 deletions(-) create mode 100644 extensions/gitreleases.func create mode 100644 plugins/backup/env.example create mode 100644 plugins/backup/main.sh create mode 100644 plugins/cloudflare/env.example create mode 100644 plugins/cloudflare/main.sh create mode 100644 plugins/docker/main.sh create mode 100644 plugins/maintenance/main.sh create mode 100644 plugins/pterodactyl/main.sh create mode 100644 plugins/rx-firewalls/main.sh create mode 100644 plugins/selfupdate/main.sh create mode 100644 plugins/service/main.sh create mode 100644 plugins/yagpdb/main.sh diff --git a/.gitignore b/.gitignore index 641adb2..080c868 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -custom/ -*.sh -*.list \ No newline at end of file +.* +*.list diff --git a/extensions/gitreleases.func b/extensions/gitreleases.func new file mode 100644 index 0000000..884cc5a --- /dev/null +++ b/extensions/gitreleases.func @@ -0,0 +1,7 @@ +function getlatest () { + if [ -x "$(command -v curl)" ]; then + curl -s https://api.github.com/repos/"${1}"/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")' + else + echo "erro" "Could not get latest version of ${1}! curl is not installed!" + fi +} diff --git a/manager b/manager index ebc00a1..91be42c 100755 --- a/manager +++ b/manager @@ -1,168 +1,129 @@ #!/bin/bash - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" - -## Functions - -function getlatest () { - if [ -x "$(command -v curl)" ]; then - curl -s https://api.github.com/repos/"${1}"/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")' - else - echo "err" "Could not get latest version of ${1}! curl is not installed!" - fi -} - -## Output types - -function output () { - case "$1" in - "info") echo -e "${INFO}$2${NC}";; - "done") echo -e "${DONE}$2${NC}";; - "warn") echo -e "${WARN}$2${NC}";; - "err") echo -e "${ERROR}$2${NC}";; - esac -} - -## Pre-/Post- execute - -function exec-com () { - output "info" "Services:" - svc-handler "$1" - if [ -x "$(command -v docker)" ]; then - output "info" "Containers:" - dc-handler "$1" - fi -} - -## Handlers - -## Service handler -function svc-handler () { - servicelist=$(systemctl list-units --type=service --state=active | grep -oe ".*\.service") - mapfile -t services < "${DIR}"/services.list - for i in "${services[@]}"; do - case "$1" in - "start") - if (( $(echo "${servicelist}" | grep -c "$i") > 0 )); then - output "warn" "Service $i was already running!" - else - if (systemctl start "$i" > /dev/null 2>&1); then - output "done" "Started service $i succesfully!" - else - output "err" "Failed to start service $i!" - fi - fi - ;; - "stop") - if (( $(echo "${servicelist}" | grep -c "$i") > 0 )); then - if (systemctl stop "$i" > /dev/null 2>&1); then - output "done" "Stopped service $i succesfully!" - else - output "err" "Failed to stop service $i!" - fi - else - output "warn" "Service $i is already stopped!" - fi - ;; - "status") - if (( $(echo "${servicelist}" | grep -c "$i") > 0 )); then - output "warn" "Service $i is up and running!" - else - output "err" "Service $i is stopped!" - fi - ;; - esac - done -} - -## Docker handler -function dc-handler () { - dockercont=$(docker ps) - dockerstatus=$(systemctl status | grep -c docker) - mapfile -t containers < "${DIR}"/containers.list - for i in "${containers[@]}"; do - if (( "${dockerstatus}" > 0 )); then - case "$1" in - "start") - if (( $(echo "${dockercont}" | grep -c "$i") > 0 )); then - output "warn" "Container $i was already up and running!" - else - if (docker start "$i" > /dev/null 2>&1); then - output "done" "Started container $i succesfully!" - else - output "err" "Failed to start container $i!" - fi - fi - ;; - "stop") - if (( $(echo "${dockercont}" | grep -c "$i") > 0 )); then - if (docker stop --time=20 "$i" > /dev/null 2>&1); then - output "done" "Stopped container $i succesfully!" - else - output "err" "Failed to stop container $i!" - fi - else - output "warn" "Container $i was already stopped!" - fi - ;; - "status") - if (( $(echo "${dockercont}" | grep -c "$i") > 0 )); then - output "warn" "Container $i is up and running!" - else - output "err" "Container $i is stopped!" - fi - ;; - esac - elif (systemctl -q is-active docker); then - output "err" "An error has occured, we are sorry!" - else - output "err" "Docker is stopped, cannot perform check!" - fi - done -} - -## Streamlined functions - -function selfupdate { - if [ -x "$(command -v git)" ]; then - cd ~/bin || exit - output "info" "Self-updating:" - if (git diff --name-only origin/master | grep -q manager); then - git reset --hard HEAD - git pull https://github.com/RXCommunity/manager master - else - output "info" "Already latest version!" - fi - else - output "err" "You do not have GIT installed!" - fi -} +# shellcheck disable=SC1090 ## Definitions +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +PLIST=${DIR}/plugins/plugin.list +ELIST=${DIR}/extensions/extension.list +DEV=true + ## Colors -NC='\033[0m' -ERROR='\033[31m' -WARN='\033[33m' -DONE='\033[32m' -INFO='\033[34m' + +declare -A COLOR +COLOR=( + [nc]='\033[0m' + [erro]='\033[31m' + [warn]='\033[33m' + [done]='\033[32m' + [info]='\033[34m' +) + +## Output types + +if ${DEV}; then + function output () { + declare input="${*:2}"; + echo -e "${COLOR[$1]}$(date +%F\ %T\ %z) | ${1} | ${input}${COLOR[nc]}" + } + function xt () { + output "$1" "Set return code to $2" + return "$2" + } +else + function output () { + declare input=${*:2}; + echo -e "${COLOR[$1]}${input}${COLOR[nc]}" + } + function xt () { + return "$2" + } +fi + +# Main run + +function main () { + export CWDIR=${DIR}/plugins/${1} + if (containsElement "$1" "${plugins[@]}"); then + if [ "$2" = "help" ]; then + output "info" "$1" + else + source "${DIR}/plugins/${1}/main.sh" + fi + else + output "erro" "Plugin $1 not found." + avail-plugins + output "info" "Tip: If you added the plugin recently, add it to the index with '${0##*/} index'" + fi +} + +function containsElement () { + local e match="$1" + shift + for e; do [[ "$e" == "$match" ]] && return 0; done + return 1 +} + +function nopluginlist { + output "warn" "No plugin list found. Try running '${0##*/} index' to index everything." +} + +function avail-plugins { + if [ -f "${PLIST}" ]; then + output "warn" "Available plugins:" + mapfile -t plugins < "${PLIST}" || output "erro" "Failed to load plugin list." + output "warn" "${plugins[@]}" + else + nopluginlist + fi +} + +function index { + output "info" "Indexing plugins" + truncate -s 0 "${PLIST}" + for i in $(find "${DIR}"/plugins/* -type d | grep -P "(?<=\/plugins\/)([\w\d\-\_])*" -o); do + echo "$i" >> "${PLIST}" && output "done" "Added plugin '$i'." + done + output "info" "Indexing extensions" + truncate -s 0 "${ELIST}" + for i in $(find "${DIR}"/extensions/* -type f | grep -P "(?<=\/extensions\/)([\w\d\-\_])*(\.func)" -o); do + echo "$i" >> "${ELIST}" && output "done" "Added extension '$i'." + done +} + +function loadlists { + mapfile -t plugins < "${PLIST}" || output "erro" "Failed to load plugin list." + mapfile -t extensions < "${ELIST}" || output "erro" "Failed to load extension list." + for i in "${extensions[@]}"; do + source "${DIR}/extensions/$i" || output "warn" "Failed to import extension ${i}." + done +} + +function preparedirs { + if mkdir "${DIR}"/plugins/ "${DIR}"/extensions/; then + output "info" "Created a empty plugins and extensions directory." + else + output "err" "Could not create directory." + fi +} ## Main run -case "$1" in - "command") - exec-com "${2}" - ;; - "script") - # shellcheck source=/dev/null - source "${DIR}/custom/$2.sh" - ;; - "maintenance") - # shellcheck source=./maintenance.sh - source "${DIR}/maintenance.sh" - ;; - "selfupdate") selfupdate;; - *) - output "err" "That command does not exist!" - ;; -esac +[ ${DEV} = "true" ] && output "warn" "Running in development mode!" + +if ! [ $# -eq 0 ] && ! [[ "$1" = "index" ]] && [ -f "${PLIST}" ] && [ -f "${ELIST}" ]; then + loadlists + main "$@" +elif [ -d "${DIR}"/plugins/ ] && [ -d "${DIR}"/extensions/ ]; then + if [ $# -eq 0 ]; then + output "warn" "Nothing to do!" + avail-plugins + elif [[ "$1" = "index" ]]; then + index + else + nopluginlist + fi +else + preparedirs +fi +! [[ "$1" = "rawpl" ]] && output "done" "Made with ♥ by casKd | t.me/casKd_dev" diff --git a/plugins/backup/env.example b/plugins/backup/env.example new file mode 100644 index 0000000..916a519 --- /dev/null +++ b/plugins/backup/env.example @@ -0,0 +1,17 @@ +# MySQL / MariaDB +MSQL_HOST="127.0.0.1" +MSQL_PORT="3306" +MSQL_USER="root" +MSQL_PASS="mydatabaseissecured" +MSQL_PATH="/root/backups" + +# Postgres +PSQL_USER="postgres" +PSQL_PATH="/root/backups" + +# InfluxDB +IFXDB_DATABASE="telegraf" +IFXDB_PATH="/root/backups" + +# Backup retention +BR_DAYS="2" diff --git a/plugins/backup/main.sh b/plugins/backup/main.sh new file mode 100644 index 0000000..a53f4d8 --- /dev/null +++ b/plugins/backup/main.sh @@ -0,0 +1,17 @@ +source "${CWDIR}/.env" + +# MariaDB / MySQL +output info "Backing up MariaDB" +mysqldump -h "${MSQL_HOST}" -P"${MSQL_PORT}" -u"${MSQL_USER}" -p"${MSQL_PASS}" -ARE | gzip -c > "${MSQL_PATH}"/mariadb-$(date +%s).sql.gz || output erro "Failed to backup MariaDB" + +# Postgres (Docker) +output info "Backing up PostgreSQL" +docker exec main-db_postgres_1 pg_dumpall -U "${PSQL_USER}" | gzip -c > "${PSQL_PATH}"postgres-$(date +%s).sql.gz || output erro "Failed to backup PostgreSQL" + +# InfluxDB (Docker) +# output info "Backing up InfluxDB" +# docker exec main-db_influxdb_1 bash -c "influxd backup -portable -database telegraf /backups > /dev/null 2>&1 && tar -cz /backups" > "${IFXDB_PATH}"/influxdb-telegraf-$(date +%s).tar.gz || output erro "Failed to backup InfluxDB" + +# Backup maintenance +output info "Removing older backups" +find /root/main-db/backups/* -type f -ctime +${BR_DAYS} -exec rm -rf {} \; diff --git a/plugins/cloudflare/env.example b/plugins/cloudflare/env.example new file mode 100644 index 0000000..967f613 --- /dev/null +++ b/plugins/cloudflare/env.example @@ -0,0 +1,3 @@ +EMAIL="someone@example.co.uk" +AUTH_KEY="cryptic stuff lmao" +ZONE="something something letters" diff --git a/plugins/cloudflare/main.sh b/plugins/cloudflare/main.sh new file mode 100644 index 0000000..c260081 --- /dev/null +++ b/plugins/cloudflare/main.sh @@ -0,0 +1,65 @@ +source "${CWDIR}/.env" + +# Record name $3 +# Record type $4 +# Record content $5 (default: own IP) +# Cloudflare Proxy $6 (true/false) + +if FETCH=$(curl -sX GET "https://api.cloudflare.com/client/v4/zones/$ZONE/dns_records" \ + -H "X-Auth-Email: ${EMAIL}" \ + -H "X-Auth-Key: ${AUTH_KEY}" \ + -H "Content-Type: application/json"); then + DOMAIN=($(echo "${FETCH}" | jq -r '.result[].name')) + case "$2" in + "list") + for ((i=0;i<${#DOMAIN[@]};++i)); do + echo "$(echo "${FETCH}" | jq -r ".result[${i}].name") $(echo "${FETCH}" | jq -r ".result[${i}].type") $(echo "${FETCH}" | jq -r ".result[${i}].content") $(echo "${FETCH}" | jq -r ".result[${i}].id")" | output info $( 0 )); then + case "$2" in + "start") + if (( $(echo "${dockercont}" | grep -c "$i") > 0 )); then + output warn "Container $i was already up and running!" + else + if (docker start "$i" > /dev/null 2>&1); then + output done "Started container $i succesfully!" + else + output erro "Failed to start container $i!" + fi + fi + ;; + "stop") + if (( $(echo "${dockercont}" | grep -c "$i") > 0 )); then + if (docker stop --time=20 "$i" > /dev/null 2>&1); then + output done "Stopped container $i succesfully!" + else + output erro "Failed to stop container $i!" + fi + else + output warn "Container $i was already stopped!" + fi + ;; + "status") + if (( $(echo "${dockercont}" | grep -c "$i") > 0 )); then + output warn "Container $i is up and running!" + else + output erro "Container $i is stopped!" + fi + ;; + esac + elif (systemctl -q is-active docker); then + output erro "An error has occured, we are sorry!" + else + output erro "Docker is stopped, cannot perform check!" + fi +done diff --git a/plugins/maintenance/main.sh b/plugins/maintenance/main.sh new file mode 100644 index 0000000..ff9641e --- /dev/null +++ b/plugins/maintenance/main.sh @@ -0,0 +1,18 @@ +if [ -x "$(command -v docker)" ]; then + output info "Clearing Docker remainings" + docker system prune --all -f +fi +case $(uname -rv) in + *Ubuntu*) + output info "Clearing & Updating APT" + apt-get -y update + apt-get -y autoclean + apt-get -y autoremove + ;; +esac + +output info "Clearing logs" +if [ -x "$(command -v nginx)" ]; then + truncate -s 0 /var/log/nginx/*.* +fi +journalctl --vacuum-size=20M diff --git a/plugins/pterodactyl/main.sh b/plugins/pterodactyl/main.sh new file mode 100644 index 0000000..2b787f3 --- /dev/null +++ b/plugins/pterodactyl/main.sh @@ -0,0 +1,30 @@ +case "$2" in + "update") + cd /var/www/pterodactyl || exit + php artisan down + output info "Fetching latest releases" + curl -L https://github.com/pterodactyl/panel/releases/download/"$(getlatest "Pterodactyl/panel")"/panel.tar.gz | tar --strip-components=1 -xzv + curl -L https://github.com/RXCommunity/RedXen-Panel/archive/"$(getlatest "RXCommunity/RedXen-Panel")".tar.gz | tar --strip-components=1 -xzv + output info "Ensuring permissions are correct" + chown -R www-data:www-data ./* + chmod -R 755 storage/* bootstrap/cache + output info "Getting latest deps" + composer install --no-dev --optimize-autoloader || output erro "Failed to get deps!" + + artisanfunc=( + "view:clear" + "cache:clear" + "config:cache" + "migrate --force" + "db:seed --force" + "p:migration:clean-orphaned-keys -n" + "up" + ) + + output info "Running migrations and clearance" + for f in "${artisanfunc[@]}"; do + php artisan $f || output erro "Failed to execute 'artisan ${f}'" + done + ;; + *); echo "Nothing to do";; +esac diff --git a/plugins/rx-firewalls/main.sh b/plugins/rx-firewalls/main.sh new file mode 100644 index 0000000..9aeee08 --- /dev/null +++ b/plugins/rx-firewalls/main.sh @@ -0,0 +1,25 @@ +source "${CWDIR}/.env" + +function join { local IFS="$1"; shift; echo "$*"; } + +# Main +output "info" "Getting addresses" +ipv4=$(curl https://www.cloudflare.com/ips-v4) || output erro "Failed to get IPv4 addresses" +ipv6=$(curl https://www.cloudflare.com/ips-v6) || output erro "Failed to get IPv6 addresses" +ip=("${ipv4[@]}" "${ipv6[@]}") +output "info" "Truncating existing list" +truncate -s 0 $FILE +output "info" "Writing new IPs to the list" +for i in ${ip[@]}; do + echo "set_real_ip_from ${i};" >> $FILE +done +echo "real_ip_header X-Forwarded-For;" >> $FILE +output "info" "Reloading nginx" +nginx -t && nginx -s reload || echo "Failed to reload nginx" | output erro +output "info" "Updating DigitalOcean Firewall(s)" +DOLIST=() +DLETS=() +for i in ${ip[@]}; do + DOLIST+=(address:${i}) +done +snap run doctl compute firewall update ${FWID} --name ${NAME} --droplet-ids $(join , ${DROPLETS[@]}) --inbound-rules protocol:tcp,ports:443,$(join , ${DOLIST[@]}) diff --git a/plugins/selfupdate/main.sh b/plugins/selfupdate/main.sh new file mode 100644 index 0000000..8a86592 --- /dev/null +++ b/plugins/selfupdate/main.sh @@ -0,0 +1,12 @@ +if [ -x "$(command -v git)" ]; then + cd "${DIR}" || exit + output info "Self-updating:" + if (git diff --name-only origin/master | grep -q manager); then + git reset --hard HEAD | output info + git pull https://github.com/RXCommunity/manager master | output info + else + output info "Already latest version!" + fi +else + output erro "You do not have GIT installed!" +fi diff --git a/plugins/service/main.sh b/plugins/service/main.sh new file mode 100644 index 0000000..2922113 --- /dev/null +++ b/plugins/service/main.sh @@ -0,0 +1,35 @@ +servicelist=$(systemctl list-units --type=service --state=active | grep -oe ".*\.service") +mapfile -t services < ${CWDIR}/services.list +for i in "${services[@]}"; do + case "$2" in + "start") + if (( $(echo "${servicelist}" | grep -c "$i") > 0 )); then + output warn "Service $i was already running!" + else + if (systemctl start "$i" > /dev/null 2>&1); then + output done "Started service $i succesfully!" + else + output erro "Failed to start service $i!" + fi + fi + ;; + "stop") + if (( $(echo "${servicelist}" | grep -c "$i") > 0 )); then + if (systemctl stop "$i" > /dev/null 2>&1); then + output done "Stopped service $i succesfully!" + else + output erro "Failed to stop service $i!" + fi + else + output warn "Service $i is already stopped!" + fi + ;; + "status") + if (( $(echo "${servicelist}" | grep -c "$i") > 0 )); then + output warn "Service $i is up and running!" + else + output erro "Service $i is stopped!" + fi + ;; + esac +done diff --git a/plugins/yagpdb/main.sh b/plugins/yagpdb/main.sh new file mode 100644 index 0000000..2d5931f --- /dev/null +++ b/plugins/yagpdb/main.sh @@ -0,0 +1,5 @@ +cd /root/yagpdb || exit +git pull +cd ./yagpdb_docker || exit +docker-compose build --force-rm --no-cache --pull +docker-compose up -d