#!/bin/bash #### # Pterodactyl - Panel # Copyright (c) 2015 - 2017 Dane Everitt # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. #### set +e export DEBIAN_FRONTEND=noninteractive INSTALL_DIR="/srv/daemon" DATA_DIR="{{ $node->daemonBase }}" CURRENT_SYSTEM_KERNEL="$(uname -r)" DL_VERSION="0.0.1" command_exists() { command -v "$@" > /dev/null 2>&1 } error_message() { echo -e "\e[1m\e[97m\e[41m$1\e[0m" exit 1 } warning_message() { echo -e "\e[43m\e[30m$1\e[0m" } success_message() { echo -e "\e[32m$1\e[0m" } running_command() { echo -e " ;; \e[47m\e[30m$1\e[0m" } for i in "$@" do case $i in -d|--directory) INSTALL_DIR="$2" ;; -a|--datadir) DATA_DIR="$2" ;; -g|--git) USE_GIT=true ;; -u|--unstable) USE_UNSTABLE=true USE_GIT=true ;; -v|--version) DL_VERSION="$2" ;; -h|--help) echo "./installer [opts]" echo " -d | --directory The directory to install the daemon into. (default: /srv/daemon)" echo " -a | --datadir The directory that daemon users will be stored in. (default: /srv/daemon-data)" echo " -g | --git Use this flag to download the daemon using a git clone. (default: false)" echo " -u | --unstable Install unstable version of the daemon, automatically uses --git flag. (default: false)" echo " -v | --version The version of the daemon to download." exit ;; esac shift done warning_message "This program will automatically configure your system to run the Pterodactyl Daemon." warning_message " - Install Location: $INSTALL_DIR" warning_message " - Data Location: $DATA_DIR" warning_message "This script will continue in 10 seconds. Press CRTL+C to exit now." sleep 10 # Super basic system detection if command_exists apt-get; then INSTALL_CMD="apt-get -y" elif command_exists yum; then INSTALL_CMD="yum -y" else error_message "No supported repository manager was found." fi if ! command_exists curl; then warning_message "No file retrieval method found, installing curl now..." running_command "$INSTALL_CMD -y install curl" $INSTALL_CMD -y install curl if [ "$?" -ne "0" ]; then error_message "Unable to install curl and no other method was found for retrieving files." fi fi # Determine if the kernel is high enough version. if command_exists awk; then PROCESSED_KERNEL_VERSION=$(awk -F. '{print $1$2}' <<< $CURRENT_SYSTEM_KERNEL) elif command_exists cut; then PROCESSED_KERNEL_VERSION=$(cut -d. -f1-2 --output-delimiter='' <<< $CURRENT_SYSTEM_KERNEL) else error_message "You seem to be missing some core tools that this script needs: awk (or) cut" fi if [ "$PROCESSED_KERNEL_VERSION" -lt "310" ]; then error_message "Your kernel version must be at least 3.10 or higher for the daemon to work. You are using $CURRENT_SYSTEM_KERNEL" fi check_cgroups() { # Check CGroups CGROUP_DIRECTORY_LISTING="$(awk '/[, ](cpu|cpuacct|cpuset|devices|freezer|memory)[, ]/ && $3 == "cgroup" { print $2 }' /proc/mounts | head -n1)" if [ ! -z $CGROUP_DIRECTORY_LISTING -a -d $CGROUP_DIRECTORY_LISTING ]; then CGROUP_DIRECTORY="$(dirname $CGROUP_DIRECTORY_LISTING 2>&1)" if [ -d "$CGROUP_DIRECTORY/cpu" -a -d "$CGROUP_DIRECTORY/cpuacct" -a -d "$CGROUP_DIRECTORY/cpuset" -a -d "$CGROUP_DIRECTORY/devices" -a -d "$CGROUP_DIRECTORY/freezer" -a -d "$CGROUP_DIRECTORY/memory" ]; then success_message "cgroups enabled and are valid on this machine." else error_message "You appear to be missing some important cgroups on this machine." fi else if [ ! -e "/proc/cgroups" ]; then error_message "This kernel does not appear to support cgroups! Please see https://gist.github.com/DaneEveritt/0f071f481b4d3fa637d4 for more information." elif [ ! -d "/sys/fs/cgroup" ]; then error_message "This kernel does not appear to support cgroups! Please see https://gist.github.com/DaneEveritt/0f071f481b4d3fa637d4 for more information." fi if [ ! -f "/tmp/mount_cgroup.sh" ]; then # Try to enable cgroups warning_message "Attempting to enable cgroups on this machine..." running_command "curl -L https://raw.githubusercontent.com/tianon/cgroupfs-mount/master/cgroupfs-mount > /tmp/mount_cgroup.sh" curl -L https://raw.githubusercontent.com/tianon/cgroupfs-mount/master/cgroupfs-mount > /tmp/mount_cgroup.sh running_command "chmod +x /tmp/mount_cgroup.sh" chmod +x /tmp/mount_cgroup.sh running_command "bash /tmp/mount_cgroup.sh" bash /tmp/mount_cgroup.sh check_cgroups else rm -rf /tmp/mount_cgroup.sh > /dev/null 2>&1 error_message "Failed to enable cgroups on this machine." fi fi } # Check those groups. check_cgroups # Lets install the dependencies. $INSTALL_CMD install linux-image-extra-$CURRENT_SYSTEM_KERNEL if [ "$?" -ne "0" ]; then warning_message "You appear to have a non-generic kernel meaning we could not install extra kernel tools." warning_message "We will continue to install, but some docker enhancements might not work as expected." warning_message "Continuing in 10 seconds, press CTRL+C to cancel this script." sleep 10 fi success_message "Installing Docker..." running_command "curl -L https://get.docker.com/ | sh" curl -L https://get.docker.com/ | sh if [ "$?" -ne "0" ]; then error_message "Unable to install docker, an error occured!" fi; success_message "Installing NodeJS 5.x..." running_command "curl -L https://deb.nodesource.com/setup_5.x | sudo -E bash -" curl -L https://deb.nodesource.com/setup_5.x | sudo -E bash - if [ "$?" -ne "0" ]; then error_message "Unable to configure NodeJS, an error occured!" fi; running_command "$INSTALL_CMD install tar nodejs" $INSTALL_CMD install tar nodejs if [ "$?" -ne "0" ]; then error_message "Unable to install NodeJS or Tar, an error occured!" fi; running_command "mkdir -p $INSTALL_DIR $DATA_DIR" mkdir -p $INSTALL_DIR $DATA_DIR cd $INSTALL_DIR if [ -z $USE_UNSTABLE -a -z $USE_GIT ]; then CLEANUP_PROGRAMS="nodejs docker-engine" running_command "curl -sI https://github.com/Pterodactyl/Daemon/archive/$DL_VERSION.tar.gz | head -n1 | cut -d$' ' -f2" GITHUB_STATUS="$(curl -sI https://github.com/Pterodactyl/Daemon/archive/$DL_VERSION.tar.gz | head -n1 | cut -d$' ' -f2)" if [ $GITHUB_STATUS -ne "200" ]; then $INSTALL_CMD remove $CLEANUP_PROGRAMS 2>&1 error_message "Github returned a non-200 response code ($GITHUB_STATUS)" fi running_command "curl -L \"https://github.com/Pterodactyl/Daemon/archive/$DL_VERSION.tar.gz\" > daemon.tar.gz" curl -L "https://github.com/Pterodactyl/Daemon/archive/$DL_VERSION.tar.gz" > daemon.tar.gz running_command "tar --strip-components=1 -xzvf daemon.tar.gz" tar --strip-components=1 -xzvf daemon.tar.gz 2>&1 if [ "$?" -ne "0" ]; then $INSTALL_CMD remove $CLEANUP_PROGRAMS 2>&1 cd ~ && rm -rf $INSTALL_DIR 2>&1 error_message "Unable to install the daemon due to an error while attempting to unpack files." fi elif [ $USE_GIT ]; then CLEANUP_PROGRAMS="nodejs docker-engine git" running_command "$INSTALL_CMD install git" $INSTALL_CMD install git running_command "git clone https://github.com/Pterodactyl/Daemon.git ." git clone https://github.com/Pterodactyl/Daemon.git . if [ -z $USE_UNSTABLE ]; then running_command "git checkout tags/$DL_VERSION" git checkout tags/$DL_VERSION fi if [ "$?" -ne "0" ]; then $INSTALL_CMD remove $CLEANUP_PROGRAMS 2>&1 cd ~ && rm -rf $INSTALL_DIR 2>&1 error_message "Unable to install the daemon due to an error while attempting to clone files to the server." fi else error_message "Could not match an install method!" fi running_command "npm install --production" npm install --production if [ "$?" -ne "0" ]; then $INSTALL_CMD remove $CLEANUP_PROGRAMS 2>&1 cd ~ && rm -rf $INSTALL_DIR 2>&1 error_message "Unable to install the daemon due to an error that occured while running npm install." fi running_command "docker run -d --name ptdl-sftp -p 2022:22 -v $DATA_DIR:/sftp-root -v $INSTALL_DIR/config/credentials:/creds quay.io/pterodactyl/scrappy" docker run -d --name ptdl-sftp -p 2022:22 -v $DATA_DIR:/sftp-root -v $INSTALL_DIR/config/credentials:/creds quay.io/pterodactyl/scrappy if [ "$?" -ne "0" ]; then $INSTALL_CMD remove $CLEANUP_PROGRAMS 2>&1 cd ~ && rm -rf $INSTALL_DIR 2>&1 error_message "Unable to install the daemon due to an error while creating a SFTP container." fi echo '{ "web": { "listen": {{ $node->daemonListen }}, "ssl": { "enabled": {{ $node->sceheme === 'https' ? 'true' : 'false' }}, "certificate": "/etc/letsencrypt/live/{{ $node->fqdn }}/fullchain.pem", "key": "/etc/letsencrypt/live/{{ $node->fqdn }}/privkey.pem" } }, "docker": { "socket": "/var/run/docker.sock" }, "sftp": { "path": "{{ $node->daemonBase }}", "port": {{ $node->daemonSFTP }}, "container": "ptdl-sftp" }, "logger": { "path": "logs/", "src": false, "level": "info", "period": "1d", "count": 3 }, "remote": { "download": "{{ route('remote.download') }}", "installed": "{{ route('remote.install') }}" }, "uploads": { "maximumSize": 100000000 }, "keys": [ "{{ $node->daemonSecret }}" ] }' > config/core.json if [ "$?" -ne "0" ]; then $INSTALL_CMD remove $CLEANUP_PROGRAMS cd ~ && rm -rf $INSTALL_DIR 2>&1 error_message "An error occured while attempting to save the JSON file." fi success_message "Congratulations, the daemon is now installed." exit