add server scripts

This commit is contained in:
user-penguin 2026-03-24 03:30:16 +07:00
parent 4a62a574b0
commit d3a12fc48a
7 changed files with 769 additions and 0 deletions

196
initializator/README.md Normal file
View File

@ -0,0 +1,196 @@
# Initializator
Набор скриптов для быстрой настройки нового VPS-сервера с нуля: файрвол, веб-сервер, SSL и VPN.
## Требования
- Ubuntu / Debian
- root-доступ
## Быстрый старт
```bash
git clone <repo> && cd initializator
```
### 1. Базовая настройка
```bash
sudo bash common.sh # UFW-файрвол (deny incoming, allow SSH)
sudo bash nginx.sh # Nginx + правила UFW
sudo bash certbot.sh # Certbot для SSL-сертификатов
```
### 2. VPN-сервер
Два варианта — выбирай нужный:
| | `vless.sh` | `vless_ip.sh` |
|---|---|---|
| Подключение | По домену | По IP-адресу |
| Транспорт | WebSocket | TCP |
| Шифрование | TLS (Let's Encrypt) | Reality (XTLS) |
| Nginx | Нужен (проксирует WS) | Не нужен |
| Маскировка | Обычный HTTPS-сайт | TLS-хендшейк с реальным сайтом |
## Скрипты
### `common.sh`
Устанавливает и настраивает UFW:
- deny incoming / allow outgoing
- Открывает порт 22 (SSH)
### `nginx.sh`
- Устанавливает Nginx (если не установлен)
- Включает автозапуск
- Открывает порты 80/443 в UFW
### `certbot.sh`
- Устанавливает Certbot + плагин для Nginx
### `vless.sh` — VLESS + WebSocket + TLS (по домену)
Поднимает Xray-core за Nginx с WebSocket-транспортом и настоящим TLS-сертификатом.
**Переменные `.env`:**
```env
DOMAIN=example.com
VLESS_WS_PATH=stream
PORT=10001
```
**Что делает:**
1. Скачивает Xray-core с GitHub в `~/services/vless`
2. Генерирует UUID, создаёт `config.json`
3. Создаёт systemd-сервис `xray-vless`
4. Получает SSL-сертификат через Certbot (webroot)
5. Настраивает Nginx: HTTP -> HTTPS редирект, WebSocket-прокси
6. Выводит строку подключения
**Архитектура:**
```
Клиент -> :443 (Nginx, TLS) -> WS /$VLESS_WS_PATH -> :$PORT (Xray) -> интернет
```
**Строка подключения:**
```
vless://UUID@DOMAIN:443?encryption=none&security=tls&sni=DOMAIN&type=ws&path=%2FPATH#Fish-VLESS
```
**Запуск:**
```bash
sudo bash vless.sh
```
---
### `vless_ip.sh` — VLESS + Reality (по IP)
Поднимает Xray-core напрямую на порту 443 с протоколом Reality. Nginx не нужен — Xray сам обрабатывает TLS, маскируясь под реальный сайт.
**Переменные `.env`:**
```env
SERVER_IP=45.146.202.107
```
**Что делает:**
1. Скачивает Xray-core с GitHub в `~/services/vless_ip`
2. Генерирует UUID + x25519 keypair + short ID
3. Создаёт `config.json` с Reality
4. Создаёт systemd-сервис `xray-vless-ip`
5. Открывает порт 443 в UFW
6. Выводит строку подключения
**Архитектура:**
```
Клиент -> :443 (Xray, Reality/XTLS) -> интернет
|
└─ TLS fingerprint = www.kuper.ru (маскировка)
```
**Строка подключения:**
```
vless://UUID@IP:443?encryption=none&security=reality&sni=www.kuper.ru&fp=chrome&pbk=PUBLIC_KEY&sid=SHORT_ID&type=tcp&flow=xtls-rprx-vision#VLESS-Reality
```
**Запуск:**
```bash
sudo bash vless_ip.sh
```
---
## Файл `.env`
Создай `initializator/.env` перед запуском VPN-скриптов:
```env
# Для vless.sh (доменный вариант)
DOMAIN=example.com
VLESS_WS_PATH=stream
PORT=10001
# Для vless_ip.sh (IP вариант)
SERVER_IP=45.146.202.107
```
## Управление сервисом
```bash
# Статус
systemctl status xray-vless # доменный
systemctl status xray-vless-ip # IP
# Перезапуск
systemctl restart xray-vless
systemctl restart xray-vless-ip
# Логи
journalctl -u xray-vless -f
journalctl -u xray-vless-ip -f
```
## Структура файлов на сервере
```
~/services/
├── vless/ # доменный вариант
│ ├── xray # бинарник Xray-core
│ ├── config.json # конфиг сервера
│ └── connection.txt # строка подключения
└── vless_ip/ # IP вариант
├── xray
├── config.json
└── connection.txt
/etc/systemd/system/
├── xray-vless.service
└── xray-vless-ip.service
/etc/nginx/sites-available/
└── vless-$DOMAIN # только для доменного варианта
```
## Клиенты
Строку подключения можно импортировать в:
- **Android:** v2rayNG, NekoBox
- **iOS:** Streisand, V2Box
- **Windows:** Nekoray, v2rayN
- **macOS:** V2RayXS, Nekoray
- **Linux:** Nekoray

15
initializator/certbot.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/utils.sh"
require_root
if command -v certbot >/dev/null 2>&1; then
echo "Certbot is already installed: $(certbot --version 2>&1)"
else
echo "Installing Certbot..."
apt-get update -y || { echo "Failed to update package list"; exit 1; }
apt-get install -y certbot python3-certbot-nginx || { echo "Failed to install Certbot"; exit 1; }
echo "Certbot installed successfully."
fi

22
initializator/common.sh Normal file
View File

@ -0,0 +1,22 @@
#!/bin/bash
source "$(dirname "$0")/utils.sh"
require_root
# Check if UFW (Uncomplicated Firewall) is installed and display its status
if command -v ufw >/dev/null 2>&1; then
echo "UFW is installed."
ufw status verbose
else
echo "UFW is not installed. Installing..."
apt update && apt install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp comment 'SSH'
yes | ufw enable
echo "UFW installed and activated."
ufw status verbose
fi

35
initializator/nginx.sh Normal file
View File

@ -0,0 +1,35 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/utils.sh"
require_root
if command -v nginx >/dev/null 2>&1; then
echo "Nginx is already installed: $(nginx -v 2>&1)"
else
echo "Installing Nginx..."
apt-get update -y || { echo "Failed to update package list"; exit 1; }
apt-get install -y nginx || { echo "Failed to install Nginx"; exit 1; }
echo "Nginx installed successfully."
fi
if ! systemctl is-active --quiet nginx; then
echo "Starting Nginx..."
systemctl start nginx || { echo "Failed to start Nginx"; exit 1; }
fi
if ! systemctl is-enabled --quiet nginx; then
echo "Enabling Nginx on boot..."
systemctl enable nginx || { echo "Failed to enable Nginx"; exit 1; }
fi
echo "Nginx status:"
systemctl status nginx --no-pager
if command -v ufw >/dev/null 2>&1; then
ufw allow 'Nginx Full' || { echo "Failed to add UFW rule for Nginx"; exit 1; }
echo "UFW rule for Nginx added."
else
echo "WARNING: UFW is not installed, skipping firewall rule. Run common.sh first."
fi

8
initializator/utils.sh Normal file
View File

@ -0,0 +1,8 @@
#!/bin/bash
require_root() {
if [ $EUID -ne 0 ]; then
echo "This script must be run as root"
exit 1
fi
}

286
initializator/vless.sh Normal file
View File

@ -0,0 +1,286 @@
#!/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}"
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" <<EOF
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": ${PORT},
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${UUID}"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "ws",
"wsSettings": {
"path": "/${VLESS_WS_PATH}"
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
],
"routing": {
"rules": [
{
"type": "field",
"outboundTag": "block",
"protocol": ["bittorrent"]
}
]
}
}
EOF
echo " Config: $VLESS_DIR/config.json"
echo ""
# --- 3. Systemd service ---
SERVICE_NAME="xray-vless"
echo "[3] Creating systemd service..."
cat > "/etc/systemd/system/${SERVICE_NAME}.service" <<EOF
[Unit]
Description=Xray VLESS Server
After=network.target
[Service]
Type=simple
ExecStart=${VLESS_DIR}/xray run -config ${VLESS_DIR}/config.json
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "$SERVICE_NAME" --quiet
systemctl restart "$SERVICE_NAME"
echo " Service $SERVICE_NAME started"
echo ""
# --- 4. SSL certificate ---
NGINX_SITE="vless-${DOMAIN}"
if grep -q '^\s*#.*server_names_hash_bucket_size' /etc/nginx/nginx.conf; then
echo " Enabling server_names_hash_bucket_size in nginx.conf..."
sed -i 's/.*#\s*server_names_hash_bucket_size.*/ server_names_hash_bucket_size 128;/' /etc/nginx/nginx.conf
elif ! grep -rq 'server_names_hash_bucket_size' /etc/nginx/nginx.conf /etc/nginx/conf.d/ 2>/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 "<html><body><h1>Welcome</h1></body></html>" > "/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" <<NGINX
server {
listen 80;
server_name ${DOMAIN};
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
root /var/www/${DOMAIN};
index index.html;
}
}
NGINX
ln -sf "/etc/nginx/sites-available/$NGINX_SITE" "/etc/nginx/sites-enabled/$NGINX_SITE"
nginx -t || { echo "ERROR: nginx config test failed"; exit 1; }
systemctl reload nginx
if ! certbot certonly --webroot -w /var/www/certbot -d "$DOMAIN" \
--non-interactive --agree-tos --email "admin@${DOMAIN}" 2>&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" <<NGINX
server {
listen 80;
server_name ${DOMAIN};
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://\$host\$request_uri;
}
}
server {
listen 443 ssl;
http2 on;
server_name ${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location /${VLESS_WS_PATH} {
proxy_redirect off;
proxy_pass http://127.0.0.1:${PORT};
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
location / {
root /var/www/${DOMAIN};
index index.html;
try_files \$uri \$uri/ =404;
}
}
NGINX
ln -sf "/etc/nginx/sites-available/$NGINX_SITE" "/etc/nginx/sites-enabled/$NGINX_SITE"
nginx -t || { echo "ERROR: nginx config test failed"; exit 1; }
systemctl reload nginx
echo " Nginx configured and reloaded"
echo ""
# --- 6. Fix ownership & output ---
chown -R "$REAL_USER:$REAL_USER" "$VLESS_DIR"
VLESS_LINK="vless://${UUID}@${DOMAIN}:443?encryption=none&security=tls&sni=${DOMAIN}&type=ws&path=%2F${VLESS_WS_PATH}#Fish-VLESS"
echo "$VLESS_LINK" > "$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"

207
initializator/vless_ip.sh Normal file
View File

@ -0,0 +1,207 @@
#!/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: SERVER_IP=45.146.202.107"
exit 1
fi
source "$ENV_FILE"
: "${SERVER_IP:?SERVER_IP is not set in .env}"
REAL_USER="${SUDO_USER:-$(whoami)}"
REAL_HOME=$(eval echo "~$REAL_USER")
VLESS_DIR="$REAL_HOME/services/vless_ip"
SERVICE_NAME="xray-vless-ip"
REALITY_DEST="www.kuper.ru:443"
REALITY_SERVER_NAME="www.kuper.ru"
echo "=== VLESS + Reality Installation ==="
echo " Server IP: $SERVER_IP"
echo " Port: 443"
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 keys & config ---
UUID=$("$VLESS_DIR/xray" uuid)
echo "[2] Generated UUID: $UUID"
KEYS=$("$VLESS_DIR/xray" x25519 2>&1) || true
PRIVATE_KEY=$(echo "$KEYS" | grep -i 'private' | awk '{print $NF}' || true)
PUBLIC_KEY=$(echo "$KEYS" | grep -i 'password' | awk '{print $NF}' || true)
if [ -z "$PRIVATE_KEY" ] || [ -z "$PUBLIC_KEY" ]; then
echo "ERROR: Failed to parse x25519 keys. Raw output:"
echo "$KEYS"
exit 1
fi
echo " Reality private key: $PRIVATE_KEY"
echo " Reality public key: $PUBLIC_KEY"
SHORT_ID=$(openssl rand -hex 4)
echo " Short ID: $SHORT_ID"
cat > "$VLESS_DIR/config.json" <<EOF
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${UUID}",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"dest": "${REALITY_DEST}",
"serverNames": ["${REALITY_SERVER_NAME}"],
"privateKey": "${PRIVATE_KEY}",
"shortIds": ["${SHORT_ID}"]
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
],
"routing": {
"rules": [
{
"type": "field",
"outboundTag": "block",
"protocol": ["bittorrent"]
}
]
}
}
EOF
echo " Config: $VLESS_DIR/config.json"
echo ""
# --- 3. Systemd service ---
echo "[3] Creating systemd service..."
cat > "/etc/systemd/system/${SERVICE_NAME}.service" <<EOF
[Unit]
Description=Xray VLESS Reality Server
After=network.target
[Service]
Type=simple
ExecStart=${VLESS_DIR}/xray run -config ${VLESS_DIR}/config.json
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "$SERVICE_NAME" --quiet
systemctl restart "$SERVICE_NAME"
sleep 1
if systemctl is-active --quiet "$SERVICE_NAME"; then
echo " Service $SERVICE_NAME started"
else
echo "ERROR: Service failed to start"
journalctl -u "$SERVICE_NAME" --no-pager -n 10
exit 1
fi
echo ""
# --- 4. Firewall ---
if command -v ufw >/dev/null 2>&1; then
ufw allow 443/tcp comment 'VLESS Reality' >/dev/null 2>&1 || true
echo "[4] UFW: port 443 opened"
else
echo "[4] UFW not installed, skipping firewall rule"
fi
echo ""
# --- 5. Fix ownership & output ---
chown -R "$REAL_USER:$REAL_USER" "$VLESS_DIR"
VLESS_LINK="vless://${UUID}@${SERVER_IP}:443?encryption=none&security=reality&sni=${REALITY_SERVER_NAME}&fp=chrome&pbk=${PUBLIC_KEY}&sid=${SHORT_ID}&type=tcp&flow=xtls-rprx-vision#VLESS-Reality"
echo "$VLESS_LINK" > "$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"