Add server setup scripts (manual + cloud-init)
Two deployment options for recreating the kirgysia server: - manual-setup/: bash script for manual server provisioning - cloud-init/: cloud-init config + data upload script for automated VPS setup Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+296
@@ -0,0 +1,296 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Server Setup Script — воссоздание конфигурации сервера kirgysia
|
||||
# OS: Ubuntu 22.04 LTS
|
||||
# Запуск: sudo bash setup.sh
|
||||
#
|
||||
# Перед запуском:
|
||||
# 1. Положите рядом файлы:
|
||||
# - ../data/x-ui.db (база 3x-ui — скопировать с оригинала)
|
||||
# - ../data/fullchain.pem (SSL-сертификат)
|
||||
# - ../data/privkey.pem (SSL-ключ)
|
||||
# - ../data/authorized_keys (SSH-ключи для доступа)
|
||||
# 2. Отредактируйте переменные ниже под новый сервер
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ============================================================
|
||||
# НАСТРОЙКИ — отредактируйте под новый сервер
|
||||
# ============================================================
|
||||
NEW_USER="eberkheev"
|
||||
SSH_PORT="10001"
|
||||
TIMEZONE="UTC"
|
||||
# Сетевой интерфейс (узнать: ip link show)
|
||||
NET_IFACE="ens18"
|
||||
# Статический IP (оставьте пустым для DHCP)
|
||||
STATIC_IP="" # например: "5.144.180.119/24"
|
||||
GATEWAY="" # например: "5.144.180.1"
|
||||
DNS="8.8.8.8,8.8.4.4"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
DATA_DIR="$SCRIPT_DIR/../data"
|
||||
|
||||
# ============================================================
|
||||
# Проверки
|
||||
# ============================================================
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "ERROR: Запустите с sudo: sudo bash $0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$DATA_DIR" ]; then
|
||||
echo "ERROR: Директория $DATA_DIR не найдена."
|
||||
echo "Создайте её и положите туда: x-ui.db, fullchain.pem, privkey.pem, authorized_keys"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== [1/8] Обновление системы ==="
|
||||
apt update && apt upgrade -y
|
||||
|
||||
echo "=== [2/8] Установка пакетов ==="
|
||||
apt install -y \
|
||||
curl \
|
||||
wget \
|
||||
git \
|
||||
htop \
|
||||
mc \
|
||||
nmap \
|
||||
net-tools \
|
||||
unzip \
|
||||
fail2ban \
|
||||
certbot \
|
||||
docker.io \
|
||||
docker-compose \
|
||||
ufw
|
||||
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
|
||||
echo "=== [3/8] Настройка часового пояса ==="
|
||||
timedatectl set-timezone "$TIMEZONE"
|
||||
|
||||
echo "=== [4/8] Создание пользователя ==="
|
||||
if ! id "$NEW_USER" &>/dev/null; then
|
||||
adduser --disabled-password --gecos "" "$NEW_USER"
|
||||
usermod -aG sudo "$NEW_USER"
|
||||
# Разрешить sudo без пароля (опционально — удалите если не нужно)
|
||||
echo "$NEW_USER ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/$NEW_USER"
|
||||
chmod 440 "/etc/sudoers.d/$NEW_USER"
|
||||
echo "Пользователь $NEW_USER создан"
|
||||
else
|
||||
echo "Пользователь $NEW_USER уже существует"
|
||||
fi
|
||||
|
||||
usermod -aG docker "$NEW_USER"
|
||||
|
||||
# SSH-ключи
|
||||
USER_HOME="/home/$NEW_USER"
|
||||
mkdir -p "$USER_HOME/.ssh"
|
||||
if [ -f "$DATA_DIR/authorized_keys" ]; then
|
||||
cp "$DATA_DIR/authorized_keys" "$USER_HOME/.ssh/authorized_keys"
|
||||
chmod 600 "$USER_HOME/.ssh/authorized_keys"
|
||||
fi
|
||||
chown -R "$NEW_USER:$NEW_USER" "$USER_HOME/.ssh"
|
||||
|
||||
echo "=== [5/8] Настройка SSH ==="
|
||||
cat > /etc/ssh/sshd_config <<SSHEOF
|
||||
Include /etc/ssh/sshd_config.d/*.conf
|
||||
|
||||
Port $SSH_PORT
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication no
|
||||
PermitEmptyPasswords no
|
||||
KbdInteractiveAuthentication no
|
||||
UsePAM yes
|
||||
X11Forwarding yes
|
||||
PrintMotd no
|
||||
AcceptEnv LANG LC_*
|
||||
Subsystem sftp /usr/lib/openssh/sftp-server
|
||||
SSHEOF
|
||||
|
||||
systemctl restart ssh
|
||||
echo "SSH настроен на порт $SSH_PORT"
|
||||
|
||||
echo "=== [6/8] Настройка сети ==="
|
||||
if [ -n "$STATIC_IP" ]; then
|
||||
cat > /etc/netplan/01-netcfg.yaml <<NETEOF
|
||||
network:
|
||||
version: 2
|
||||
ethernets:
|
||||
$NET_IFACE:
|
||||
addresses:
|
||||
- $STATIC_IP
|
||||
gateway4: $GATEWAY
|
||||
nameservers:
|
||||
addresses:
|
||||
- ${DNS//,/$'\n - '}
|
||||
search: []
|
||||
NETEOF
|
||||
netplan apply
|
||||
echo "Статический IP настроен: $STATIC_IP"
|
||||
else
|
||||
echo "Сеть: используется DHCP (не настраивалась)"
|
||||
fi
|
||||
|
||||
echo "=== [7/8] Установка 3x-ui ==="
|
||||
XUI_DIR="$USER_HOME/3x-ui"
|
||||
|
||||
if [ ! -d "$XUI_DIR" ]; then
|
||||
sudo -u "$NEW_USER" git clone https://github.com/MHSanaei/3x-ui.git "$XUI_DIR"
|
||||
else
|
||||
echo "3x-ui уже склонирован"
|
||||
fi
|
||||
|
||||
# Создаём директории для данных
|
||||
mkdir -p "$XUI_DIR/db" "$XUI_DIR/cert" "$USER_HOME/cert"
|
||||
|
||||
# Копируем базу данных
|
||||
if [ -f "$DATA_DIR/x-ui.db" ]; then
|
||||
cp "$DATA_DIR/x-ui.db" "$XUI_DIR/db/x-ui.db"
|
||||
cp "$DATA_DIR/x-ui.db" "$USER_HOME/x-ui-backup.db"
|
||||
echo "База данных x-ui скопирована"
|
||||
else
|
||||
echo "WARNING: x-ui.db не найден в $DATA_DIR — пропущено"
|
||||
fi
|
||||
|
||||
# Копируем сертификаты
|
||||
if [ -f "$DATA_DIR/fullchain.pem" ] && [ -f "$DATA_DIR/privkey.pem" ]; then
|
||||
cp "$DATA_DIR/fullchain.pem" "$XUI_DIR/cert/"
|
||||
cp "$DATA_DIR/privkey.pem" "$XUI_DIR/cert/"
|
||||
cp "$DATA_DIR/fullchain.pem" "$USER_HOME/cert/"
|
||||
cp "$DATA_DIR/privkey.pem" "$USER_HOME/cert/"
|
||||
echo "Сертификаты скопированы"
|
||||
else
|
||||
echo "WARNING: Сертификаты не найдены в $DATA_DIR — пропущено"
|
||||
fi
|
||||
|
||||
# docker-compose.yml
|
||||
cat > "$XUI_DIR/docker-compose.yml" <<'DCEOF'
|
||||
services:
|
||||
3xui:
|
||||
image: ghcr.io/mhsanaei/3x-ui:latest
|
||||
container_name: 3xui_app
|
||||
volumes:
|
||||
- ./db/:/etc/x-ui/
|
||||
- ./cert/:/root/cert/
|
||||
environment:
|
||||
XRAY_VMESS_AEAD_FORCED: "false"
|
||||
XUI_ENABLE_FAIL2BAN: "true"
|
||||
tty: true
|
||||
network_mode: host
|
||||
restart: unless-stopped
|
||||
DCEOF
|
||||
|
||||
chown -R "$NEW_USER:$NEW_USER" "$XUI_DIR"
|
||||
|
||||
# Скрипт обновления
|
||||
cat > "$USER_HOME/update.sh" <<'UPDATEEOF'
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
BACKUP_PATH="/home/eberkheev/x-ui-backup.db"
|
||||
XUI_PATH="/home/eberkheev/3x-ui"
|
||||
DOCKER_IMAGE="ghcr.io/mhsanaei/3x-ui:latest"
|
||||
|
||||
BUILD_MODE="pull"
|
||||
if [ "$1" = "--build" ]; then
|
||||
BUILD_MODE="build"
|
||||
fi
|
||||
|
||||
echo "=== Mode: $BUILD_MODE ==="
|
||||
|
||||
echo "=== System update ==="
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
|
||||
echo "=== Finding x-ui container ==="
|
||||
CONTAINER=$(sudo docker ps --format "{{.Names}}" | grep -i "xui\|x-ui\|3xui" | head -n 1)
|
||||
|
||||
if [ -z "$CONTAINER" ]; then
|
||||
echo "WARNING: x-ui container not found, skipping backup..."
|
||||
if [ ! -f "$BACKUP_PATH" ]; then
|
||||
echo "ERROR: No container and no backup found, aborting!"
|
||||
exit 1
|
||||
fi
|
||||
echo "Existing backup found at $BACKUP_PATH, continuing..."
|
||||
else
|
||||
echo "Found container: $CONTAINER"
|
||||
echo "=== Backup x-ui database ==="
|
||||
sudo docker cp $CONTAINER:/etc/x-ui/x-ui.db $BACKUP_PATH
|
||||
echo "Backup saved to $BACKUP_PATH"
|
||||
fi
|
||||
|
||||
echo "=== Pulling latest from main ==="
|
||||
cd $XUI_PATH
|
||||
sudo git checkout main
|
||||
sudo git pull origin main
|
||||
|
||||
echo "=== Stopping old container ==="
|
||||
sudo docker-compose down
|
||||
|
||||
if [ "$BUILD_MODE" = "build" ]; then
|
||||
echo "--- Building from source ---"
|
||||
sudo docker-compose build --no-cache
|
||||
sudo docker-compose up -d
|
||||
else
|
||||
echo "--- Pulling prebuilt image: $DOCKER_IMAGE ---"
|
||||
sudo docker pull $DOCKER_IMAGE
|
||||
sudo docker rm -f 3xui_app 2>/dev/null || true
|
||||
sudo docker run -d \
|
||||
--name 3xui_app \
|
||||
--restart unless-stopped \
|
||||
--network host \
|
||||
--env XRAY_VMESS_AEAD_FORCED=false \
|
||||
--env XUI_ENABLE_FAIL2BAN=true \
|
||||
-v $XUI_PATH/db/:/etc/x-ui/ \
|
||||
-v $XUI_PATH/cert/:/root/cert/ \
|
||||
-t \
|
||||
$DOCKER_IMAGE
|
||||
fi
|
||||
|
||||
echo "=== Restoring database from backup ==="
|
||||
NEW_CONTAINER=$(sudo docker ps --format "{{.Names}}" | grep -i "xui\|x-ui\|3xui" | head -n 1)
|
||||
if [ -z "$NEW_CONTAINER" ]; then
|
||||
echo "ERROR: Container not found after restart!"
|
||||
exit 1
|
||||
fi
|
||||
sudo docker cp $BACKUP_PATH $NEW_CONTAINER:/etc/x-ui/x-ui.db
|
||||
echo "Database restored, restarting container..."
|
||||
sudo docker restart $NEW_CONTAINER
|
||||
|
||||
echo "=== Status ==="
|
||||
sudo docker ps | grep -i "xui\|x-ui\|3xui"
|
||||
sudo docker logs $NEW_CONTAINER --tail=30
|
||||
|
||||
echo "=== Done! ==="
|
||||
UPDATEEOF
|
||||
|
||||
chown "$NEW_USER:$NEW_USER" "$USER_HOME/update.sh"
|
||||
|
||||
echo "=== [8/8] Запуск 3x-ui ==="
|
||||
cd "$XUI_DIR"
|
||||
docker pull ghcr.io/mhsanaei/3x-ui:latest
|
||||
docker run -d \
|
||||
--name 3xui_app \
|
||||
--restart unless-stopped \
|
||||
--network host \
|
||||
--env XRAY_VMESS_AEAD_FORCED=false \
|
||||
--env XUI_ENABLE_FAIL2BAN=true \
|
||||
-v "$XUI_DIR/db/:/etc/x-ui/" \
|
||||
-v "$XUI_DIR/cert/:/root/cert/" \
|
||||
-t \
|
||||
ghcr.io/mhsanaei/3x-ui:latest
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Сервер настроен!"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo " SSH: порт $SSH_PORT, пользователь $NEW_USER"
|
||||
echo " 3x-ui: запущен в Docker (network_mode: host)"
|
||||
echo " Панель: https://<IP>:10002 (или порт из x-ui.db)"
|
||||
echo ""
|
||||
echo " Для обновления: bash ~/update.sh"
|
||||
echo " Для проверки: docker ps"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user