Skip to content

Instantly share code, notes, and snippets.

@marcandreher
Last active January 18, 2025 19:33
Show Gist options
  • Save marcandreher/d730a6117d51b782fc693f570f35b2cb to your computer and use it in GitHub Desktop.
Save marcandreher/d730a6117d51b782fc693f570f35b2cb to your computer and use it in GitHub Desktop.
Bancho.py-ex auto installer
#!/bin/bash
# Exit on any error
set -e
# Define colors for formatting (using tput for better compatibility)
green=$(tput setaf 2)
red=$(tput setaf 1)
yellow=$(tput setaf 3)
blue=$(tput setaf 4)
reset=$(tput sgr0)
# Function to print a divider line
divider() {
echo -e "${blue}=========================================${reset}"
}
ENV_FILE=".env"
set_env() {
local key=$1
local value=$2
# Escape special characters
key=$(echo "$key" | sed 's/[&/\]/\\&/g')
value=$(echo "$value" | sed 's/[&/\]/\\&/g')
# Check if the key exists in the file
if grep -q "^${key}=" "$ENV_FILE"; then
# Update the existing key
sed -i "s/^${key}=.*/${key}=${value}/" "$ENV_FILE"
else
# Add the key-value pair if it doesn't exist
echo "${key}=${value}" >> "$ENV_FILE"
fi
}
# Function to check if script is run as root
check_root() {
if [ "$EUID" -ne 0 ]; then
echo -e "${red}Please run this script as root or with sudo${reset}"
exit 1
fi
}
# Function to detect OS
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
else
echo -e "${red}Cannot detect operating system. Please ensure you're running a supported Linux distribution.${reset}"
exit 1
fi
}
# Print banner
divider
cat << "EOF"
M#"""""""'M dP MMP"""""""MM dP M""M dP dP dP
## mmmm. `M 88 M' .mmmm MM 88 M M 88 88 88
#' .M .d8888b. 88d888b. .d8888b. 88d888b. .d8888b. M `M dP dP d8888P .d8888b. M M 88d888b. .d8888b. d8888P .d8888b. 88 88 .d8888b. 88d888b.
M# MMMb.'YM 88' `88 88' `88 88' `"" 88' `88 88' `88 M MMMMM MM 88 88 88 88' `88 M M 88' `88 Y8ooooo. 88 88' `88 88 88 88ooood8 88' `88
M# MMMM' M 88. .88 88 88 88. ... 88 88 88. .88 M MMMMM MM 88. .88 88 88. .88 M M 88 88 88 88 88. .88 88 88 88. ... 88
M# .;M `88888P8 dP dP `88888P' dP dP `88888P' M MMMMM MM `88888P' dP `88888P' M M dP dP `88888P' dP `88888P8 dP dP `88888P' dP
M#########M MMMMMMMMMMMM MMMM
EOF
divider
# Check root privileges
check_root
# Detect OS
detect_os
if [ "$1" == "--reset" ]; then
echo -e "${green}Resetting.${reset}"
docker stop server-bancho-1
docker rm server-bancho-1
docker stop server-mysql-1
docker rm server-mysql-1
docker stop server-redis-1
docker rm server-redis-1
docker rmi -f bancho
docker volume rm server_data server_db-data server_redis-data
rm -rf /home/bancho
exit 1
fi
# Check for Docker installation
echo -e "${yellow}Checking for Docker installation...${reset}"
if ! command -v docker &>/dev/null; then
echo -e "${red}Docker is not installed on your system.${reset}"
read -p "Do you want to install Docker now? (y/n): " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then
divider
echo -e "${green}Installing Docker...${reset}"
case $OS in
ubuntu|debian)
apt-get update
apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg \
software-properties-common
curl -fsSL https://download.docker.com/linux/$OS/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/$OS $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io
;;
*)
echo -e "${red}Unsupported operating system: $OS${reset}"
exit 1
;;
esac
systemctl start docker
systemctl enable docker
echo -e "${green}Docker installation completed.${reset}"
else
echo -e "${red}Docker is required for Bancho installation. Exiting.${reset}"
exit 1
fi
else
echo -e "${green}Docker is already installed!${reset}"
fi
if ! systemctl is-active --quiet docker; then
echo -e "${yellow}Starting Docker service...${reset}"
systemctl start docker
echo -e "${green}Docker service started.${reset}"
fi
divider
echo -e "${yellow}Checking for Docker Compose installation...${reset}"This i
if ! command -v docker compose &>/dev/null; then
echo -e "${red}Docker Compose is not installed.${reset}"
read -p "Do you want to install Docker Compose now? (y/n): " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then
divider
echo -e "${green}Installing Docker Compose...${reset}"
# Install Docker Compose plugin (recommended method as of Docker Compose v2)
apt-get update
apt-get install -y docker-compose-plugin
# Verify installation
if ! command -v docker compose &>/dev/null; then
echo -e "${red}Docker Compose installation failed.${reset}"
exit 1
fi
echo -e "${green}Docker Compose installation completed.${reset}"
else
echo -e "${red}Docker Compose is required for Bancho installation. Exiting.${reset}"
exit 1
fi
else
echo -e "${green}Docker Compose is already installed!${reset}"
fi
divider
# Check for Make installation
echo -e "${yellow}Checking for Make installation...${reset}"
if ! command -v make &>/dev/null; then
echo -e "${red}Make is not installed.${reset}"
read -p "Do you want to install Make now? (y/n): " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then
divider
echo -e "${green}Installing Make...${reset}"
apt-get install -y make
# Verify installation
if ! command -v make &>/dev/null; then
echo -e "${red}Make installation failed.${reset}"
exit 1
fi
echo -e "${green}Make installation completed.${reset}"
else
echo -e "${red}Make is required for the installation process. Exiting.${reset}"
exit 1
fi
else
echo -e "${green}Make is already installed!${reset}"
fi
divider
echo -e "${yellow}Checking for Git installation...${reset}"
if ! command -v git &>/dev/null; then
echo -e "${red}Git is not installed on your system.${reset}"
read -p "Do you want to install Git now? (y/n): " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then
divider
echo -e "${green}Installing Git...${reset}"
apt-get update
apt-get install -y git
# Verify installation
if ! command -v git &>/dev/null; then
echo -e "${red}Git installation failed.${reset}"
exit 1
fi
echo -e "${green}Git installation completed.${reset}"
else
echo -e "${red}Git is required for Bancho installation. Exiting.${reset}"
exit 1
fi
else
echo -e "${green}Git is already installed!${reset}"
fi
divider
echo -e "${yellow}Checking for Nginx installation...${reset}"
if ! command -v nginx &>/dev/null; then
echo -e "${red}Nginx is not installed on your system.${reset}"
read -p "Do you want to install Nginx now? (y/n): " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then
divider
echo -e "${green}Installing Nginx...${reset}"
apt-get update
apt-get install -y nginx
systemctl start nginx
systemctl enable nginx
# Verify installation and service status
if ! command -v nginx &>/dev/null; then
echo -e "${red}Nginx installation failed.${reset}"
exit 1
fi
if ! systemctl is-active --quiet nginx; then
echo -e "${red}Nginx service failed to start.${reset}"
exit 1
fi
echo -e "${green}Nginx installation completed and service started.${reset}"
else
echo -e "${red}Nginx is required for Bancho installation. Exiting.${reset}"
exit 1
fi
else
echo -e "${green}Nginx is already installed!${reset}"
# Ensure Nginx is running
if ! systemctl is-active --quiet nginx; then
echo -e "${yellow}Starting Nginx service...${reset}"
systemctl start nginx
echo -e "${green}Nginx service started.${reset}"
fi
fi
echo -e "${green}Configuring nginx!${reset}"
mkdir -p /home/bancho/nginx
chmod -R 755 /home/bancho/nginx
mkdir -p /home/bancho/old
if ! grep -q "include /home/bancho/nginx/\*.conf;" /etc/nginx/nginx.conf; then
# Backup of old config
cp /etc/nginx/nginx.conf /home/old/nginx.conf.backup
# Remove any malformed or duplicate includes first
sed -i '/include \/home\/bancho\/nginx\/\*\.conf;/d' /etc/nginx/nginx.conf
# Add the include line after 'http {' only once
sed -i '/http {/a \ include /home/bancho/nginx/*.conf;' /etc/nginx/nginx.conf
echo -e "${green}Include statement added to nginx.conf!${reset}"
else
echo -e "${yellow}Include statement already exists in nginx.conf${reset}"
fi
nginx -t
echo -e "${green}Installing Bancho.py...${reset}"
mkdir -p /home/bancho/server
if [ -z "$(ls -A /home/bancho/server)" ]; then
echo -e "${green}Cloning Bancho.py...${reset}"
git clone https://github.com/osu-NoLimits/bancho.py-ex /home/bancho/server
echo -e "${green}Done${reset}"
else
echo -e "${red}Directory /home/bancho/server is not empty. Please clear it first.${reset}"
exit 1
fi
cd /home/bancho/server
cp .env.example .env
cp logging.yaml.example logging.yaml
set_env "DATA_DIRECTORY" "/var/lib/docker/volumes/server_data/_data"
set_env "SSL_CERT_PATH" ""
set_env "SSL_KEY_PATH" ""
divider
echo "${blue}Please enter your domain (e.g., example.com):${reset}"
read -p "${green}Domain: ${reset}" domain
if [[ -z "$domain" ]]; then
echo "${red}Error: Domain cannot be empty. Please try again.${reset}"
exit 1
elif ! [[ "$domain" =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
echo "${red}Error: Invalid domain format. Please ensure it's like 'example.com'.${reset}"
exit 1
fi
set_env "DOMAIN" "$domain"
set_env "MENU_ONCLICK_URL" "https://$domain"
divider
echo "${blue}Please a secure mysql password (e.g., 8 chars):${reset}"
read -p "${green}Password: ${reset}" msqlpass
if [[ -z "$msqlpass" ]]; then
echo "${red}Error: Password cannot be empty. Please try again.${reset}"
exit 1
fi
set_env "DB_PASS" "$msqlpass"
divider
read -p "${green}osu! API Key (https://osu.ppy.sh/home/account/edit#legacy-api): ${reset}" apikey
if [[ -z "$apikey" ]]; then
echo "${red}Error: API Key cannot be empty. Please try again.${reset}"
exit 1
fi
set_env "OSU_API_KEY" "$apikey"
read -p "${green}Audit Webhook (Leave empty if not used): ${reset}" auwebhook
set_env "DISCORD_AUDIT_LOG_WEBHOOK" "$auwebhook"
read -p "${green}Server Name: ${reset}" servername
set_env "SERVER_NAME" "$servername"
read -p "${green}Discord URL: ${reset}" dcurl
set_env "DISCORD_URL" "$dcurl"
divider
echo "${green}Copying nginx.conf.example to server.conf...${reset}"
cp /home/bancho/server/ext/nginx.conf.example /home/bancho/nginx/server.conf
# Replace variables in the copied file
echo "${yellow}Replacing ${APP_PORT} with 10000, ${DOMAIN} with $domain, and ${DATA_DIRECTORY} with /home/bancho/server/.data...${reset}"
sed -i 's/${APP_PORT}/10000/g' /home/bancho/nginx/server.conf
sed -i "s/\${DOMAIN}/$domain/g" /home/bancho/nginx/server.conf
sed -i 's|\${DATA_DIRECTORY}|/var/lib/docker/volumes/server_data/_data|g' /home/bancho/nginx/server.conf
# Remove specific lines
echo "${yellow}Removing SSL configuration lines...${reset}"
sed -i '/ssl_certificate/d' /home/bancho/nginx/server.conf
sed -i '/ssl_certificate_key/d' /home/bancho/nginx/server.conf
sed -i '/ssl_ciphers/d' /home/bancho/nginx/server.conf
# Replace listen 443 ssl with listen 80
echo "${yellow}Replacing listen 443 ssl with listen 80...${reset}"
sed -i 's/listen 443 ssl;/listen 80;/g' /home/bancho/nginx/server.conf
echo "${green}Uncommenting ports in docker-compose.yml...${reset}"
sed -i '/# ports:/s/# ports:/ports:/' /home/bancho/server/docker-compose.yml
sed -i '/ports:/,/^$/s/^#\s*-/-/' /home/bancho/server/docker-compose.yml
sed -i '/mysql:/,/redis:/s/^\s*#\s*-\s*\${DB_PORT}:\${DB_PORT}/ - ${DB_PORT}:${DB_PORT}/' /home/bancho/server/docker-compose.yml
sed -i '/redis:/,/bancho:/s/^\s*#\s*-\s*\${REDIS_PORT}:\${REDIS_PORT}/ - ${REDIS_PORT}:${REDIS_PORT}/' /home/bancho/server/docker-compose.yml
divider
echo -e "${green}Building docker image${reset}"
docker build -t bancho /home/bancho/server
make run
echo -e "${green}Installation completed successfully!${reset}"
echo -e "${yellow}You can now access your Bancho server at https://$domain:10000 if you have your domain configured${reset}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment