#!/usr/bin/env bash # sdm-xray — установка сервера stealth-туннеля на свежую Ubuntu VPS. # Использование: # bash <(curl -fsSL https://git.my-handbook.ru/ded_ikar/sdm-xray/raw/main/install.sh) # — с доменом: Let's Encrypt-сертификат (A-запись домена должна указывать на IP VPS) # bash <(curl -fsSL https://git.my-handbook.ru/ded_ikar/sdm-xray/raw/main/install.sh) --selfsigned # — БЕЗ домена: self-signed сертификат, клиент доверяет по pinnedPeerCertSha256 # (pin печатается в клиентском конфиге; панель сама подставляет его в ссылки/конфиги) set -euo pipefail SELFSIGNED=0 if [ -z "${1:-}" ] || [ "$1" = "--selfsigned" ]; then SELFSIGNED=1 DOMAIN="" else DOMAIN="$1" fi GITEA="https://git.my-handbook.ru/ded_ikar/sdm-xray" VERSION="v0.2.2" BIN="xray-stealth-server-linux-amd64" PANEL_BIN="sdm-panel-linux-amd64" INSTALL_DIR="/usr/local/xray" DATA_DIR="/etc/xray" WEBROOT="/var/www/html" VPS_IP="$(curl -fsSL --max-time 10 https://api.ipify.org 2>/dev/null || echo UNKNOWN)" if [ "$SELFSIGNED" -eq 1 ]; then echo "=== sdm-xray installer ${VERSION} (SELF-SIGNED, без домена) ===" echo "vps-ip: $VPS_IP (используй его как serverName/адрес в клиенте)" else echo "=== sdm-xray installer ${VERSION} ===" echo "domain: $DOMAIN vps-ip: $VPS_IP" fi export DEBIAN_FRONTEND=noninteractive echo "=== apt: deps ===" apt-get update -qq apt-get install -y -qq curl openssl jq nginx certbot >/dev/null 2>&1 echo "=== download server binary + geo files ===" mkdir -p "$INSTALL_DIR" "$DATA_DIR" "$WEBROOT" curl -fsSL -o "$INSTALL_DIR/xray" "$GITEA/releases/download/$VERSION/$BIN" curl -fsSL -o "$INSTALL_DIR/geoip.dat" "$GITEA/releases/download/$VERSION/geoip.dat" curl -fsSL -o "$INSTALL_DIR/geosite.dat" "$GITEA/releases/download/$VERSION/geosite.dat" chmod 755 "$INSTALL_DIR/xray" "$INSTALL_DIR/xray" version | sed -n '1p' echo "=== generate secrets ===" UUID="$(cat /proc/sys/kernel/random/uuid)" KEY="$(openssl rand -hex 8)" echo "$UUID" > "$DATA_DIR/uuid" echo "$KEY" > "$DATA_DIR/key" # --- TLS: либо LE-серт (домен), либо self-signed (без домена) --- if [ "$SELFSIGNED" -eq 1 ]; then echo "=== self-signed certificate (CN=$VPS_IP, 10 лет) ===" openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \ -subj "/CN=$VPS_IP" \ -keyout "$DATA_DIR/server.key" -out "$DATA_DIR/server.crt" >/dev/null 2>&1 CERT_FILE="$DATA_DIR/server.crt" KEY_FILE="$DATA_DIR/server.key" PIN="$(openssl x509 -in "$CERT_FILE" -outform der | openssl dgst -sha256 -hex | awk '{print $NF}')" echo "pinnedPeerCertSha256: $PIN" echo " (панель подставит его в клиентские конфиги/ссылки автоматически)" else echo "=== nginx on 80 (acme) ===" mkdir -p "$WEBROOT/.well-known/acme-challenge" cat > /etc/nginx/sites-available/sdm <<'NGX' server { listen 80; listen [::]:80; server_name DOMAIN; root /var/www/html; index index.html; location /.well-known/acme-challenge/ { alias /var/www/html/.well-known/acme-challenge/; } location / { return 301 https://$host$request_uri; } } NGX sed -i "s/DOMAIN/$DOMAIN/" /etc/nginx/sites-available/sdm ln -sf /etc/nginx/sites-available/sdm /etc/nginx/sites-enabled/sdm rm -f /etc/nginx/sites-enabled/default nginx -t >/dev/null 2>&1 && systemctl reload nginx echo "=== Let's Encrypt cert ===" certbot certonly --webroot -w "$WEBROOT" -d "$DOMAIN" \ --register-unsafely-without-email --agree-tos --no-eff-email -n \ --cert-name "$DOMAIN" >/dev/null 2>&1 || true CERT_DIR="/etc/letsencrypt/live/$DOMAIN" if [ ! -f "$CERT_DIR/fullchain.pem" ]; then echo "ERROR: сертификат не получен. Проверьте, что $DOMAIN -> $VPS_IP и порт 80 открыт." exit 1 fi CERT_FILE="$CERT_DIR/fullchain.pem" KEY_FILE="$CERT_DIR/privkey.pem" fi echo "=== xray config ===" cat > "$DATA_DIR/config.json" < /etc/systemd/system/xray.service <<'UNIT' [Unit] Description=sdm-xray stealth tunnel After=network.target nss-lookup.target [Service] ExecStart=/usr/local/xray/xray run -c /etc/xray/config.json Restart=on-failure RestartPreventExitStatus=23 LimitNOFILE=65535 [Install] WantedBy=multi-user.target UNIT systemctl daemon-reload systemctl enable xray >/dev/null 2>&1 || true systemctl restart xray sleep 1 if ! systemctl is-active xray >/dev/null 2>&1; then echo "ERROR: xray не запустился:"; journalctl -u xray -n 20 --no-pager || true; exit 1 fi echo echo "=== INSTALLED OK ===" echo "uuid: $UUID" echo "key: $KEY" # --- panel --- echo echo "=== control panel (sdm-panel) ===" curl -fsSL -o "$INSTALL_DIR/sdm-panel" "$GITEA/releases/download/$VERSION/$PANEL_BIN" chmod 755 "$INSTALL_DIR/sdm-panel" PANEL_PASS="$(openssl rand -hex 8)" PANEL_LOGIN="admin" if [ "$SELFSIGNED" -eq 1 ]; then PANEL_SERVER="$VPS_IP" else PANEL_SERVER="$DOMAIN" fi cat > "$DATA_DIR/panel.json" < /etc/systemd/system/sdm-panel.service <<'PANEL' [Unit] Description=sdm-xray control panel After=network.target xray.service [Service] ExecStart=/usr/local/xray/sdm-panel Restart=on-failure RestartSec=3 [Install] WantedBy=multi-user.target PANEL systemctl daemon-reload systemctl enable sdm-panel >/dev/null 2>&1 || true systemctl restart sdm-panel sleep 1 echo "panel login: $PANEL_LOGIN panel password: $PANEL_PASS (запомни — больше не покажем)" echo "Доступ к панели (SSH-туннель, шифрованный):" echo " ssh -L 8080:127.0.0.1:8080 root@" echo " затем открой в браузере http://localhost:8080 (login: $PANEL_LOGIN / пароль выше)" echo echo "=== client config (client-stealth.json) ===" if [ "$SELFSIGNED" -eq 1 ]; then cat <