#!/bin/bash set -euo pipefail source "$(dirname "$0")/utils.sh" require_root SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" ENV_FILE="$SCRIPT_DIR/.env" if [ ! -f "$ENV_FILE" ]; then echo "ERROR: .env file not found at $ENV_FILE" echo "Create $ENV_FILE with the following variables:" echo " DOMAIN=example.com" echo " VLESS_WS_PATH=stream" echo " PORT=10001" exit 1 fi source "$ENV_FILE" : "${DOMAIN:?DOMAIN is not set in .env}" : "${VLESS_WS_PATH:?VLESS_WS_PATH is not set in .env}" : "${PORT:?PORT is not set in .env}" # If nginx stream SNI routing is active, HTTPS listens on internal port if grep -q 'stream {' /etc/nginx/nginx.conf 2>/dev/null; then HTTPS_LISTEN_PORT=8443 else HTTPS_LISTEN_PORT=443 fi REAL_USER="${SUDO_USER:-$(whoami)}" REAL_HOME=$(eval echo "~$REAL_USER") VLESS_DIR="$REAL_HOME/services/vless" echo "=== VLESS (Xray-core) Installation ===" echo " Domain: $DOMAIN" echo " WS Path: /$VLESS_WS_PATH" echo " Port: $PORT" echo " Directory: $VLESS_DIR" echo "" # --- 1. Download Xray-core --- mkdir -p "$VLESS_DIR" ARCH=$(uname -m) case "$ARCH" in x86_64) XRAY_ARCH="64" ;; aarch64) XRAY_ARCH="arm64-v8a" ;; *) echo "ERROR: unsupported architecture: $ARCH" exit 1 ;; esac XRAY_ZIP="Xray-linux-${XRAY_ARCH}.zip" DOWNLOAD_URL="https://github.com/XTLS/Xray-core/releases/latest/download/${XRAY_ZIP}" if [ -x "$VLESS_DIR/xray" ]; then echo "[1] Xray already installed: $("$VLESS_DIR/xray" version | head -1)" else echo "[1] Downloading Xray-core..." for cmd in wget unzip; do if ! command -v "$cmd" >/dev/null 2>&1; then echo " Installing $cmd..." apt-get install -y -qq "$cmd" fi done wget -q --show-progress -O "/tmp/$XRAY_ZIP" "$DOWNLOAD_URL" unzip -o -q "/tmp/$XRAY_ZIP" -d "$VLESS_DIR" chmod +x "$VLESS_DIR/xray" rm -f "/tmp/$XRAY_ZIP" echo " Installed: $("$VLESS_DIR/xray" version | head -1)" fi echo "" # --- 2. Generate UUID & create config --- UUID=$("$VLESS_DIR/xray" uuid) echo "[2] Generated UUID: $UUID" cat > "$VLESS_DIR/config.json" < "/etc/systemd/system/${SERVICE_NAME}.service" </dev/null; then echo " Setting server_names_hash_bucket_size..." echo 'server_names_hash_bucket_size 128;' > /etc/nginx/conf.d/hash_bucket_size.conf fi mkdir -p "/var/www/certbot" mkdir -p "/var/www/${DOMAIN}" if [ ! -f "/var/www/${DOMAIN}/index.html" ]; then echo "

Welcome

" > "/var/www/${DOMAIN}/index.html" fi if [ -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]; then echo "[4] SSL certificate already exists" else echo "[4] Obtaining SSL certificate..." cat > "/etc/nginx/sites-available/$NGINX_SITE" <&1; then echo " Certbot failed, resetting ACME account and retrying..." rm -rf /etc/letsencrypt/accounts/acme-v02.api.letsencrypt.org/ certbot certonly --webroot -w /var/www/certbot -d "$DOMAIN" \ --non-interactive --agree-tos --email "admin@${DOMAIN}" || { echo "ERROR: Failed to obtain SSL certificate" exit 1 } fi echo " Certificate obtained" fi echo "" # --- 5. Nginx full config (with SSL) --- echo "[5] Configuring nginx (HTTPS + WebSocket proxy)..." cat > "/etc/nginx/sites-available/$NGINX_SITE" < "$VLESS_DIR/connection.txt" chown "$REAL_USER:$REAL_USER" "$VLESS_DIR/connection.txt" echo "=== VLESS READY ===" echo "" echo "$VLESS_LINK" echo "" echo "Saved to: $VLESS_DIR/connection.txt"