From 0ffa0e7b951d9772089f632249161d0db9cebbe2 Mon Sep 17 00:00:00 2001 From: ivacom Date: Tue, 3 Sep 2024 06:17:32 +0000 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20marzban.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- marzban.sh | 554 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 554 insertions(+) create mode 100644 marzban.sh diff --git a/marzban.sh b/marzban.sh new file mode 100644 index 0000000..1417720 --- /dev/null +++ b/marzban.sh @@ -0,0 +1,554 @@ +#!/usr/bin/env bash + +# Origin file: https://github.com/Gozargah/Marzban-scripts/raw/master/marzban.sh + +set -e + +INSTALL_DIR="/opt" +if [ -z "$APP_NAME" ]; then + APP_NAME="marzban" +fi +APP_DIR="$INSTALL_DIR/$APP_NAME" +DATA_DIR="/var/lib/$APP_NAME" +COMPOSE_FILE="$APP_DIR/docker-compose.yml" + + +colorized_echo() { + local color=$1 + local text=$2 + + echo "${text}" +} + +check_running_as_root() { + if [ "$(id -u)" != "0" ]; then + colorized_echo red "This command must be run as root." + exit 1 + fi +} + +detect_os() { + # Detect the operating system + if [ -f /etc/lsb-release ]; then + OS=$(lsb_release -si) + elif [ -f /etc/os-release ]; then + OS=$(awk -F= '/^NAME/{print $2}' /etc/os-release | tr -d '"') + elif [ -f /etc/redhat-release ]; then + OS=$(cat /etc/redhat-release | awk '{print $1}') + elif [ -f /etc/arch-release ]; then + OS="Arch" + else + colorized_echo red "Unsupported operating system" + exit 1 + fi +} + +detect_and_update_package_manager() { + colorized_echo blue "Updating package manager" + if [[ "$OS" == "Ubuntu"* ]] || [[ "$OS" == "Debian"* ]]; then + PKG_MANAGER="apt-get" + $PKG_MANAGER update + elif [[ "$OS" == "CentOS"* ]]; then + PKG_MANAGER="yum" + $PKG_MANAGER update -y + $PKG_MANAGER epel-release -y + elif [ "$OS" == "Fedora"* ]; then + PKG_MANAGER="dnf" + $PKG_MANAGER update + elif [ "$OS" == "Arch" ]; then + PKG_MANAGER="pacman" + $PKG_MANAGER -Sy + else + colorized_echo red "Unsupported operating system" + exit 1 + fi +} + +detect_compose() { + # Check if docker compose command exists + if docker compose >/dev/null 2>&1; then + COMPOSE='docker compose' + elif docker-compose >/dev/null 2>&1; then + COMPOSE='docker-compose' + else + colorized_echo red "docker compose not found" + exit 1 + fi +} + +install_package () { + if [ -z $PKG_MANAGER ]; then + detect_and_update_package_manager + fi + + PACKAGE=$1 + colorized_echo blue "Installing $PACKAGE" + if [[ "$OS" == "Ubuntu"* ]] || [[ "$OS" == "Debian"* ]]; then + $PKG_MANAGER -y install "$PACKAGE" + elif [[ "$OS" == "CentOS"* ]]; then + $PKG_MANAGER install -y "$PACKAGE" + elif [ "$OS" == "Fedora"* ]; then + $PKG_MANAGER install -y "$PACKAGE" + elif [ "$OS" == "Arch" ]; then + $PKG_MANAGER -S --noconfirm "$PACKAGE" + else + colorized_echo red "Unsupported operating system" + exit 1 + fi +} + +install_docker() { + # Install Docker and Docker Compose using the official installation script + colorized_echo blue "Installing Docker" + curl -fsSL https://get.docker.com | sh + colorized_echo green "Docker installed successfully" +} + +install_marzban_script() { + FETCH_REPO="Gozargah/Marzban-scripts" + SCRIPT_URL="https://github.com/$FETCH_REPO/raw/master/marzban.sh" + colorized_echo blue "Installing marzban script" + curl -sSL $SCRIPT_URL | install -m 755 /dev/stdin /usr/local/bin/marzban + colorized_echo green "marzban script installed successfully" +} + +install_marzban() { + # Fetch releases + FILES_URL_PREFIX="https://raw.githubusercontent.com/Gozargah/Marzban/master" + + mkdir -p "$DATA_DIR" + mkdir -p "$APP_DIR" + + colorized_echo blue "Fetching compose file" + curl -sL "$FILES_URL_PREFIX/docker-compose.yml" -o "$APP_DIR/docker-compose.yml" + colorized_echo green "File saved in $APP_DIR/docker-compose.yml" + + colorized_echo blue "Fetching .env file" + curl -sL "$FILES_URL_PREFIX/.env.example" -o "$APP_DIR/.env" + sed -i 's/^# \(XRAY_JSON = .*\)$/\1/' "$APP_DIR/.env" + sed -i 's/^# \(SQLALCHEMY_DATABASE_URL = .*\)$/\1/' "$APP_DIR/.env" + sed -i 's~\(XRAY_JSON = \).*~\1"/var/lib/marzban/xray_config.json"~' "$APP_DIR/.env" + sed -i 's~\(SQLALCHEMY_DATABASE_URL = \).*~\1"sqlite:////var/lib/marzban/db.sqlite3"~' "$APP_DIR/.env" + + [ -z "$SUDO_USERNAME" ] || echo "SUDO_USERNAME=$SUDO_USERNAME" >> "$APP_DIR/.env" + [ -z "$SUDO_PASSWORD" ] || echo "SUDO_PASSWORD=$SUDO_PASSWORD" >> "$APP_DIR/.env" + + colorized_echo green "File saved in $APP_DIR/.env" + + colorized_echo blue "Fetching xray config file" + curl -sL "$FILES_URL_PREFIX/xray_config.json" -o "$DATA_DIR/xray_config.json" + colorized_echo green "File saved in $DATA_DIR/xray_config.json" + + colorized_echo green "Marzban's files downloaded successfully" +} + + +uninstall_marzban_script() { + if [ -f "/usr/local/bin/marzban" ]; then + colorized_echo yellow "Removing marzban script" + rm "/usr/local/bin/marzban" + fi +} + +uninstall_marzban() { + if [ -d "$APP_DIR" ]; then + colorized_echo yellow "Removing directory: $APP_DIR" + rm -r "$APP_DIR" + fi +} + +uninstall_marzban_docker_images() { + images=$(docker images | grep marzban | awk '{print $3}') + + if [ -n "$images" ]; then + colorized_echo yellow "Removing Docker images of Marzban" + for image in $images; do + if docker rmi "$image" >/dev/null 2>&1; then + colorized_echo yellow "Image $image removed" + fi + done + fi +} + +uninstall_marzban_data_files() { + if [ -d "$DATA_DIR" ]; then + colorized_echo yellow "Removing directory: $DATA_DIR" + rm -r "$DATA_DIR" + fi +} + +up_marzban() { + $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" up -d --remove-orphans +} + +down_marzban() { + $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" down +} + +show_marzban_logs() { + $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" logs +} + +follow_marzban_logs() { + $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" logs -f +} + +marzban_cli() { + $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" exec -e CLI_PROG_NAME="marzban cli" marzban marzban-cli "$@" +} + + +update_marzban_script() { + FETCH_REPO="Gozargah/Marzban-scripts" + SCRIPT_URL="https://github.com/$FETCH_REPO/raw/master/marzban.sh" + colorized_echo blue "Updating marzban script" + curl -sSL $SCRIPT_URL | install -m 755 /dev/stdin /usr/local/bin/marzban + colorized_echo green "marzban script updated successfully" +} + +update_marzban() { + $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" pull +} + +is_marzban_installed() { + if [ -d $APP_DIR ]; then + return 0 + else + return 1 + fi +} + +is_marzban_up() { + if [ -z "$($COMPOSE -f $COMPOSE_FILE ps -q -a)" ]; then + return 1 + else + return 0 + fi +} + +install_command() { + check_running_as_root + # Check if marzban is already installed + if is_marzban_installed; then + colorized_echo red "Marzban is already installed at $APP_DIR" + colorized_echo red "If you want to reinstall it, please run: '$0 uninstall' before" + colorized_echo red "Aborted installation" + exit 0 + fi + detect_os + if ! command -v jq >/dev/null 2>&1; then + install_package jq + fi + if ! command -v curl >/dev/null 2>&1; then + install_package curl + fi + if ! command -v docker >/dev/null 2>&1; then + install_docker + fi + detect_compose + install_marzban_script + install_marzban + up_marzban + show_marzban_logs +} + +uninstall_command() { + check_running_as_root + # Check if marzban is installed + if ! is_marzban_installed; then + colorized_echo red "Marzban's not installed!" + exit 1 + fi + + read -p "Do you really want to uninstall Marzban? (y/n) " + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + colorized_echo red "Aborted" + exit 1 + fi + + detect_compose + if is_marzban_up; then + down_marzban + fi + uninstall_marzban_script + uninstall_marzban + uninstall_marzban_docker_images + + read -p "Do you want to remove Marzban's data files too ($DATA_DIR)? (y/n) " + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + colorized_echo green "Marzban uninstalled successfully" + else + uninstall_marzban_data_files + colorized_echo green "Marzban uninstalled successfully" + fi +} + +up_command() { + help() { + colorized_echo red "Usage: marzban up [options]" + echo "" + echo "OPTIONS:" + echo " -h, --help display this help message" + echo " -n, --no-logs do not follow logs after starting" + } + + local no_logs=false + while [[ "$#" -gt 0 ]]; do + case "$1" in + -n|--no-logs) + no_logs=true + ;; + -h|--help) + help + exit 0 + ;; + *) + echo "Error: Invalid option: $1" >&2 + help + exit 0 + ;; + esac + shift + done + + # Check if marzban is installed + if ! is_marzban_installed; then + colorized_echo red "Marzban's not installed!" + exit 1 + fi + + detect_compose + + if is_marzban_up; then + colorized_echo red "Marzban's already up" + exit 1 + fi + + up_marzban + if [ "$no_logs" = false ]; then + follow_marzban_logs + fi +} + +down_command() { + + # Check if marzban is installed + if ! is_marzban_installed; then + colorized_echo red "Marzban's not installed!" + exit 1 + fi + + detect_compose + + if ! is_marzban_up; then + colorized_echo red "Marzban's already down" + exit 1 + fi + + down_marzban +} + +restart_command() { + help() { + colorized_echo red "Usage: marzban restart [options]" + echo + echo "OPTIONS:" + echo " -h, --help display this help message" + echo " -n, --no-logs do not follow logs after starting" + } + + local no_logs=false + while [[ "$#" -gt 0 ]]; do + case "$1" in + -n|--no-logs) + no_logs=true + ;; + -h|--help) + help + exit 0 + ;; + *) + echo "Error: Invalid option: $1" >&2 + help + exit 0 + ;; + esac + shift + done + + # Check if marzban is installed + if ! is_marzban_installed; then + colorized_echo red "Marzban's not installed!" + exit 1 + fi + + detect_compose + + down_marzban + up_marzban + if [ "$no_logs" = false ]; then + follow_marzban_logs + fi +} + +status_command() { + + # Check if marzban is installed + if ! is_marzban_installed; then + echo -n "Status: " + colorized_echo red "Not Installed" + exit 1 + fi + + detect_compose + + if ! is_marzban_up; then + echo -n "Status: " + colorized_echo blue "Down" + exit 1 + fi + + echo -n "Status: " + colorized_echo green "Up" + + json=$($COMPOSE -f $COMPOSE_FILE ps -a --format=json) + services=$(echo $json | jq -r '.[] | .Service') + states=$(echo $json | jq -r '.[] | .State') + # Print out the service names and statuses + for i in $(seq 0 $(expr $(echo $services | wc -w) - 1)); do + service=$(echo $services | cut -d' ' -f $(expr $i + 1)) + state=$(echo $states | cut -d' ' -f $(expr $i + 1)) + echo -n "- $service: " + if [ "$state" == "running" ]; then + colorized_echo green $state + else + colorized_echo red $state + fi + done +} + +logs_command() { + help() { + colorized_echo red "Usage: marzban logs [options]" + echo "" + echo "OPTIONS:" + echo " -h, --help display this help message" + echo " -n, --no-follow do not show follow logs" + } + + local no_follow=false + while [[ "$#" -gt 0 ]]; do + case "$1" in + -n|--no-follow) + no_follow=true + ;; + -h|--help) + help + exit 0 + ;; + *) + echo "Error: Invalid option: $1" >&2 + help + exit 0 + ;; + esac + shift + done + + # Check if marzban is installed + if ! is_marzban_installed; then + colorized_echo red "Marzban's not installed!" + exit 1 + fi + + detect_compose + + if ! is_marzban_up; then + colorized_echo red "Marzban is not up." + exit 1 + fi + + if [ "$no_follow" = true ]; then + show_marzban_logs + else + follow_marzban_logs + fi +} + +cli_command() { + # Check if marzban is installed + if ! is_marzban_installed; then + colorized_echo red "Marzban's not installed!" + exit 1 + fi + + detect_compose + + if ! is_marzban_up; then + colorized_echo red "Marzban is not up." + exit 1 + fi + + marzban_cli "$@" +} + +update_command() { + check_running_as_root + # Check if marzban is installed + if ! is_marzban_installed; then + colorized_echo red "Marzban's not installed!" + exit 1 + fi + + detect_compose + + update_marzban_script + colorized_echo blue "Pulling latest version" + update_marzban + + colorized_echo blue "Restarting Marzban's services" + down_marzban + up_marzban + + colorized_echo blue "Marzban updated successfully" +} + + +usage() { + colorized_echo red "Usage: marzban [command]" + echo + echo "Commands:" + echo " up Start services" + echo " down Stop services" + echo " restart Restart services" + echo " status Show status" + echo " logs Show logs" + echo " cli Marzban CLI" + echo " install Install Marzban" + echo " update Update latest version" + echo " uninstall Uninstall Marzban" + echo +} + +case "$1" in + up) + shift; up_command "$@";; + down) + shift; down_command "$@";; + restart) + shift; restart_command "$@";; + status) + shift; status_command "$@";; + logs) + shift; logs_command "$@";; + cli) + shift; cli_command "$@";; + install) + shift; install_command "$@";; + update) + shift; update_command "$@";; + uninstall) + shift; uninstall_command "$@";; + *) + usage;; +esac \ No newline at end of file