# VPN Stack

Шпаргалка по установке и настройке

Панель
Сервер с нуля
Доступ к панели
0
Требования
На сервере уже должно быть настроено:
Nginx (fallback 127.0.0.1:8444 → proxy на 5000)
SSL-сертификат Let's Encrypt (не нужен если Xray в режиме Reality)
Xray VLESS на 443/tcp (TLS+fallback или Reality)
mtg (MTProto) на 8443/tcp
AmneziaWG на 443/udp (опционально)
AWG необязателен — уберёте из протоколов на шаге 3.
1
Заливка файлов
Залейте папку `awg-panel/` в `/opt/` через scp/sftp.
scp
scp -r awg-panel/ root@IP:/opt/
Результат: `/opt/awg-panel/app.py`, `static/`, `data/`
Файлы залиты
2
Зависимости
выполнить
cd /opt/awg-panel python3 -m venv venv ./venv/bin/pip install gunicorn flask
опционально: вставьте вывод ожидание вывода
Выполнено
3
server.json
Данные вашего сервера. Команда генерируется автоматически.
Название
Произвольное имя для отображения в панели. Любое.
IP сервера
Внешний (публичный) IP вашего VPS. Узнать: `curl ifconfig.me`
Домен (SNI)
Домен, на который выпущен сертификат (TLS-режим) или домен маскировки (Reality-режим, например `www.google.com`). Клиенты будут подключаться с этим SNI.
Протоколы (Xray обязателен):
Xray
MTProto
AWG
server.json
Заполните поля
IP и домен должны быть от этого сервера. Иначе панель будет генерировать ссылки на чужой IP/SNI.
Создан
4
Пароль
Пароль для входа в панель. Хранится как SHA256 в `admin.json`.
Пароль
admin.json
Введите пароль
Ключ должен быть `password_hash`, не `password`. Plaintext → `KeyError`.
Создан
5
Синхронизация AWG
AWG не выбран — пропускаем.
Панель раздаёт клиентам параметры обфускации из `app.py`. Серверный `awg0.conf` обязан содержать те же Jc/Jmin/Jmax/S1/S2/H1-H4. Иначе клиенты не подключатся — handshake не пройдёт.
1. параметры панели
grep -A6 "AWG_PARAMS" /opt/awg-panel/app.py | head -7
Впишите значения в `/etc/amnezia/amneziawg/awg0.conf`. Не трогайте PrivateKey, Address, ListenPort, PostUp/PostDown.
2. перезапуск
awg-quick down awg0 && awg-quick up awg0
3. проверка
awg show awg0
опционально: вставьте вывод ожидание вывода
H1-H4 должны быть случайными большими числами. Дефолтные 1/2/3/4 = обычный WireGuard, детектится DPI.
Параметры совпадают, AWG работает
6
Запуск
создать сервис
cat > /etc/systemd/system/awg-panel.service << 'EOF' [Unit] Description=AWG Panel After=network.target [Service] Type=simple WorkingDirectory=/opt/awg-panel ExecStart=/opt/awg-panel/venv/bin/gunicorn --bind 127.0.0.1:5000 --workers 1 --threads 4 --timeout 120 app:app Restart=always RestartSec=5 User=root [Install] WantedBy=multi-user.target EOF
запустить
systemctl daemon-reload systemctl enable awg-panel systemctl start awg-panel
статус
systemctl status awg-panel --no-pager -l
опционально: вставьте вывод ожидание вывода
Ожидаем `active (running)`.
active (running)
✓
Готово
финальная проверка
curl -sk -o /dev/null -w "%{http_code}\n" https://ДОМЕН
опционально: вставьте HTTP-код ответа ожидание вывода
Ответ `200` — панель работает. Откройте в браузере и залогиньтесь.
Сервер—
IP—
Домен—
Протоколы—
Панель—
Раскладка портов:
443/tcp Xray VLESS+TLS
443/udp AWG (если вкл.)
8443/tcp mtg MTProto
8444 nginx fallback (localhost)
5000 gunicorn panel (localhost)
10085 Xray stats API (localhost)
0
Подключение к серверу
Введите данные VPS. Эти значения будут подставляться во все команды дальше.
IP сервера
SSH-порт
Стандартный — 22. Если хостер выдал другой (например 23422) — впишите его.
Основной домен (сайт)
Домен для отображения сайта/панели в браузере. Должен указывать A-записью на IP сервера.
Поддомен для протоколов (опционально)
Если хотите разделить — укажите поддомен для XRay SNI, mtg и клиентских ссылок (например `vpn.example.com` или `proxy.example.com`). Тоже должен указывать A-записью на IP сервера. Если пусто — используется основной домен.
Пароль панели
Будет захэширован SHA256 для `admin.json`.
Порт mtg (MTProto)
По умолчанию `8443`. Менять обычно не надо. Xray (443/tcp) и AWG (443/udp) не меняются — это маскировка под HTTPS и обход блокировок UDP. Менять mtg-порт имеет смысл только если 8443 заблокирован у провайдера (тогда попробуйте 2096 или 8888).
Как подключиться:
Windows — откройте PowerShell или Windows Terminal. Введите команду ниже. Пароль при запросе вставляйте: `Shift+Insert` (PowerShell), правая кнопка мыши (CMD), `Ctrl+V` (Windows Terminal). Символы при вводе пароля не отображаются — это нормально, просто нажмите Enter.
SSH подключение
ssh root@IP -p 22
macOS / Linux — откройте Terminal и введите ту же команду.
Если при первом подключении спросит `Are you sure you want to continue connecting? (yes/no)` — напишите `yes` и нажмите Enter.
Протоколы для этого сервера:
Xray
MTProto
AWG
Режим TLS для Xray:
Свой домен + TLSLet's Encrypt сертификат, fallback на nginx
RealityМаскировка под чужой сайт, сертификат не нужен
TLS — нужен домен с A-записью на IP. Лучшая обфускация (DNS, IP, серт — всё совпадает). Панель открывается через браузер.
Reality — сертификат не нужен. Xray притворяется чужим сайтом. Панель будет доступна только через VPN (или curl по IP).
Сайт маскировки (dest)
Свой домен маскировки
Подключился к серверу по SSH
1
Проверка DNS
Убеждаемся что домен (и поддомен, если указан) указывают на IP сервера. Без этого Certbot не выдаст сертификат.
основной домен
dig +short DOMAIN
опционально: вставьте вывод ожидание вывода
поддомен для протоколов
dig +short SUBDOMAIN
опционально: вставьте вывод ожидание вывода
Должен вернуть `IP`. Если пусто или другой IP — настройте A-запись у регистратора и подождите 5-10 минут.
Поддомен тоже должен вернуть `IP`. Оба домена должны указывать на один и тот же сервер.
В режиме Reality домен не нужен. Xray маскируется под чужой сайт, свой сертификат не требуется.
DNS в порядке
2
Обновление системы
Обновляем пакеты и ставим инструменты. Каждую команду выполнять отдельно, дождавшись завершения предыдущей.
0. проверка что уже установлено
for p in nginx certbot fail2ban ufw docker.io xray mtg awg; do printf "%-30s " "$p"; if command -v $p >/dev/null 2>&1 || dpkg -l 2>/dev/null | grep -q "^ii $p "; then echo "УСТАНОВЛЕН"; else echo "нет"; fi; done
опционально: вставьте вывод проверки ожидание вывода
Если nginx/certbot/fail2ban/ufw уже установлены — `apt install` ниже их не сломает, просто пропустит. Но если установлены xray, mtg или awg — стоп! Сервер уже настроен. Не следуйте этой шпаргалке, иначе перезатрёте рабочие конфиги. Используйте этот файл только для свежего VPS.
1. обновить список
apt update
2. обновить пакеты
apt upgrade -y
Если спросит про перезапуск сервисов — жмите Enter (оставить по умолчанию). В конце должны увидеть приглашение командной строки `root@server:~#`.
опционально: вставьте вывод apt upgrade ожидание вывода
3. инструменты
apt install -y nginx certbot python3-certbot-nginx fail2ban ufw docker.io curl wget unzip python3-venv python3-pip
В конце должны увидеть приглашение `root@server:~#` и никаких строк с `E:` в начале.
опционально: вставьте вывод apt install ожидание вывода
Всё установлено
3
Файрвол (UFW)
SSH-порт: 22, mtg-порт: 8443. Если SSH-порт неправильный — вернитесь на шаг 0 и исправьте. Ошибка здесь = потеря доступа к серверу!
открыть порты и включить
ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw allow 443/udp && ufw allow 8443/tcp && ufw --force enable
Порты в команде: SSH (доступ), 80/tcp (certbot), 443/tcp (Xray VLESS+TLS), 443/udp (AWG, зарезервировано даже если AWG не ставите), mtg (MTProto).
проверка
ufw status
опционально: вставьте вывод ожидание вывода
UFW активен, порты открыты
4
Fail2ban
Защита от брутфорса SSH. В `ignoreip` укажите свои IP-адреса, чтобы вас не забанило при ошибках пароля.
Ваши IP-адреса (через пробел)
Узнать свой IP: откройте ifconfig.me в браузере. Можно указать несколько через пробел (домашний + рабочий + мобильный).
Совет: если у вас нет выделенного (статического) IP — указывайте подсетью `/24`. Например, ваш IP `1.2.3.246` → пишите `1.2.3.0/24`. Это покроет весь диапазон провайдера, даже если IP сменится. Если не уверены — оставьте пусто (будет только `127.0.0.1/8`, но рискуете забанить себя при ошибке пароля).
1. конфиг
cat > /etc/fail2ban/jail.local << 'EOF' [DEFAULT] ignoreip = 127.0.0.1/8 bantime = 1h findtime = 10m maxretry = 5 [sshd] enabled = true port = ssh logpath = /var/log/auth.log EOF
2. запустить
systemctl enable fail2ban && systemctl restart fail2ban
3. проверка
fail2ban-client status sshd
Должны увидеть строку `Status for the jail: sshd` с числом банов `Currently banned: 0` (или больше, если кто-то уже долбился). Главное — что jail активен.
опционально: вставьте вывод ожидание вывода
Fail2ban работает
5
Nginx + SSL
Настраиваем nginx и получаем SSL-сертификат Let's Encrypt.
1. убрать дефолтный сайт
rm -f /etc/nginx/sites-enabled/default
2. временный конфиг для certbot
cat > /etc/nginx/sites-available/DOMAIN << 'EOF' server { listen 80; server_name DOMAIN www.DOMAIN; root /var/www/html; index index.html; location / { try_files $uri $uri/ =404; } } EOF
3. включить
ln -s /etc/nginx/sites-available/DOMAIN /etc/nginx/sites-enabled/
4. проверить и перезапустить
nginx -t && systemctl reload nginx
Должны увидеть две строки: `nginx: the configuration file /etc/nginx/nginx.conf syntax is ok` и `nginx: configuration file /etc/nginx/nginx.conf test is successful`. После них приглашение командной строки без ошибок.
опционально: вставьте вывод ожидание вывода
5. получить сертификат
certbot --nginx -d DOMAIN -d www.DOMAIN --non-interactive --agree-tos --register-unsafely-without-email
Должны увидеть строку `Successfully received certificate.` и пути к файлам `fullchain.pem` и `privkey.pem`.
опционально: вставьте вывод certbot ожидание вывода
5b. сертификат для поддомена
certbot --nginx -d SUBDOMAIN --non-interactive --agree-tos --register-unsafely-without-email
опционально: вставьте вывод ожидание вывода
Отдельный сертификат для поддомена протоколов. Xray будет использовать именно его.
6. финальный конфиг nginx (fallback)
cat > /etc/nginx/sites-available/DOMAIN << 'EOF' server { listen 127.0.0.1:8444; server_name DOMAIN www.DOMAIN; location / { proxy_pass http://127.0.0.1:5000; 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_set_header X-Forwarded-Proto $scheme; } } server { listen 80; server_name DOMAIN www.DOMAIN; return 301 https://$host$request_uri; } EOF
7. применить
nginx -t && systemctl reload nginx
Должны увидеть `nginx: configuration file ... test is successful` без ошибок.
опционально: вставьте вывод ожидание вывода
В режиме Reality nginx нужен только как резервный fallback. Сертификат не требуется.
1. убрать дефолтный сайт
rm -f /etc/nginx/sites-enabled/default
2. конфиг nginx (fallback)
cat > /etc/nginx/sites-available/fallback << 'EOF' server { listen 127.0.0.1:8444 default_server; location / { proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } EOF
3. включить
ln -s /etc/nginx/sites-available/fallback /etc/nginx/sites-enabled/
4. применить
nginx -t && systemctl reload nginx
Должны увидеть `test is successful` без ошибок.
опционально: вставьте вывод ожидание вывода
Панель будет доступна только через VPN или по `curl http://127.0.0.1:5000` с самого сервера.
Nginx настроен
6
Xray (VLESS)
0. проверка
command -v xray && echo "УЖЕ УСТАНОВЛЕН — STOP" || echo "не установлен, можно ставить"
опционально: вставьте вывод ожидание вывода
Если показывает «УЖЕ УСТАНОВЛЕН» — пропустите шаг 1 (установка). Конфиг в шаге 6 всё равно перезатрёт `/usr/local/etc/xray/config.json`. Если на сервере уже работают клиенты — сначала забэкапьте: `cp /usr/local/etc/xray/config.json /root/xray-config-backup.json`
1. установка
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
Если зависло дольше 2 минут — Ctrl+C, переподключиться по SSH и повторить. GitHub иногда не отдаёт.
2. сгенерировать UUID
xray uuid
Скопируйте UUID — он пойдёт в конфиг. Вставьте его в поле ниже.
UUID клиента
3. фикс прав сервиса
sed -i 's/User=nobody/User=root/' /etc/systemd/system/xray.service sed -i 's/NoNewPrivileges=true/NoNewPrivileges=false/' /etc/systemd/system/xray.service systemctl daemon-reload
4. логи
mkdir -p /var/log/xray && chown -R root:root /var/log/xray
5. права на сертификаты
chmod 755 /etc/letsencrypt/archive/DOMAIN/ chmod 644 /etc/letsencrypt/archive/DOMAIN/*.pem chmod 755 /etc/letsencrypt/live/DOMAIN/
Без этого Xray не прочитает сертификаты даже от root (директории 700 по умолчанию).
6. конфиг xray (TLS + fallback)
Заполните UUID выше
3. сгенерировать ключи Reality
xray x25519
Скопируйте Private key и Public key. Private → в конфиг сервера, Public → клиенту.
Private Key (в конфиг сервера)
Public Key (для клиента — запишите!)
Short ID (8 hex-символов)
Любые 8 hex-символов. Можно оставить по умолчанию.
4. конфиг xray (Reality)
Заполните UUID и ключи выше
запуск
systemctl enable xray && systemctl restart xray
проверка статуса
systemctl status xray --no-pager -l
Должны увидеть `Active: active (running)` зелёным цветом. Ниже — последние строки лога без слов `error` или `failed`.
опционально: вставьте вывод ожидание вывода
проверка портов
ss -tlnp | grep xray
Должны увидеть две строки: одна с `:443` (для VLESS) и одна с `127.0.0.1:10085` (stats API). Если порт 443 показывается с IP `0.0.0.0` — это норма.
опционально: вставьте вывод ожидание вывода
Xray active (running), порты 443 + 10085
7
mtg (MTProto)
MTProto прокси для Telegram. Качаем бинарник с GitHub.
0. проверка
command -v mtg && echo "УЖЕ УСТАНОВЛЕН — STOP" || echo "не установлен, можно ставить"
опционально: вставьте вывод ожидание вывода
Если показывает «УЖЕ УСТАНОВЛЕН» — пропустите шаги 1–3 (загрузку). Конфиг в шаге 5 всё равно перезатрёт `/etc/mtg/config.toml` новым секретом. Если на сервере уже есть клиенты с рабочим секретом — забэкапьте: `cp /etc/mtg/config.toml /root/mtg-config-backup.toml`
Нельзя качать `mtg-linux-amd64` без `.tar.gz` — по ссылке latest/download отдаётся HTML, не бинарник!
1. узнать последнюю версию
cd /tmp LATEST=$(curl -sI https://github.com/9seconds/mtg/releases/latest | grep -i location | grep -oP 'v[\d.]+' | tr -d '\r') echo $LATEST
Должен вернуть что-то вроде `v2.1.7`. Если пусто — GitHub не ответил, повторить.
2. скачать и распаковать
curl -sL "https://github.com/9seconds/mtg/releases/download/${LATEST}/mtg-${LATEST#v}-linux-amd64.tar.gz" -o mtg.tar.gz tar xzf mtg.tar.gz mv mtg-*-linux-amd64/mtg /usr/local/bin/mtg chmod +x /usr/local/bin/mtg
3. проверка
mtg --version
Должны увидеть строку вида `mtg vX.Y.Z` (например `mtg v2.1.7`), затем приглашение командной строки. Если выводится ошибка `command not found` — бинарник не на месте, вернитесь к шагу 2.
опционально: вставьте вывод ожидание вывода
4. секрет и конфиг
mkdir -p /etc/mtg SECRET=$(mtg generate-secret --hex DOMAIN) echo "$SECRET"
Сохраните секрет — он пойдёт в `server.json` панели.
5. конфиг mtg
cat > /etc/mtg/config.toml << EOF secret = "$SECRET" bind-to = "0.0.0.0:8443" EOF
6. сервис
cat > /etc/systemd/system/mtg.service << 'EOF' [Unit] Description=MTG Telegram Proxy After=network.target [Service] Type=simple ExecStart=/usr/local/bin/mtg run /etc/mtg/config.toml Restart=always RestartSec=5 User=root [Install] WantedBy=multi-user.target EOF
7. запуск
systemctl daemon-reload systemctl enable mtg systemctl start mtg
8. проверка статуса
systemctl status mtg --no-pager -l
Должны увидеть `Active: active (running)` зелёным. Ниже — последние строки лога без слов `error` или `fatal`.
и `bind-to = \"0.0.0.0:PORT\"`.;;address already in use:::err:::Порт уже занят другим процессом. `ss -tlnp | grep PORT` покажет кем.">
опционально: вставьте вывод ожидание вывода
9. проверка порта
ss -tlnp | grep 8443
Должны увидеть одну строку с `0.0.0.0:8443` и в конце `users:(("mtg",pid=...))`. Это значит mtg слушает порт.
опционально: вставьте вывод ожидание вывода
MTProto не выбран — пропускаем.
mtg работает на 8443
8
AmneziaWG
AWG — форк WireGuard на уровне ядра с обфускацией. Устанавливается скриптом.
0. проверка
command -v awg && echo "УЖЕ УСТАНОВЛЕН — STOP" || echo "не установлен, можно ставить"
опционально: вставьте вывод ожидание вывода
Если показывает «УЖЕ УСТАНОВЛЕН» — пропустите шаги 1–2. Установщик перезатрёт `/etc/amnezia/amneziawg/awg0.conf` и поломает существующих клиентов. Забэкапьте: `cp -r /etc/amnezia /root/amnezia-backup`
AWG ≠ WireGuard. Команды `wg` не работают — используйте `awg`. DeepSeek и другие AI генерируют неправильные AWG-команды без контекста.
1. скачать установщик
curl -O https://raw.githubusercontent.com/bivlked/amneziawg-installer/main/install_amneziawg_en.sh && chmod +x install_amneziawg_en.sh
2. запустить
bash install_amneziawg_en.sh
Скрипт спросит параметры:
Port Оставьте предложенный (Enter) — скрипт не принимает 443. Поменяем после установки.
Subnet Оставьте предложенный (Enter)
Disable IPv6 Enter (да)
Routing mode Enter (по умолчанию)
Reboot now?`y` — после перезагрузки переподключиться по SSH и запустить скрипт заново
Скрипт может перезагружать сервер 1–2 раза. Каждый раз: подождите 30 сек, переподключитесь по SSH, скачайте скрипт заново (`/tmp` очищается при ребуте!) и запустите повторно. Скрипт подхватит настройки и продолжит с места остановки.
команда для повторного запуска после ребута
cd /tmp && curl -O https://raw.githubusercontent.com/bivlked/amneziawg-installer/main/install_amneziawg_en.sh && chmod +x install_amneziawg_en.sh && bash install_amneziawg_en.sh
опционально: вставьте вывод установщика ожидание вывода
После завершения установки — порт будет не 443 (скрипт не позволяет ниже 1024). Меняем на 443/UDP:
3. узнать текущий порт
grep ListenPort /etc/amnezia/amneziawg/awg0.conf
Покажет строку вроде `ListenPort = 39743` (или другое число). Запомните это число — оно нужно для следующей команды.
Порт из вывода выше
4. сменить порт на 443
awg-quick down awg0 sed -i 's/ListenPort = 39743/ListenPort = 443/' /etc/amnezia/amneziawg/awg0.conf awg-quick up awg0
5. обновить endpoint в клиентских конфигах
sed -i 's/:39743/:443/' /root/awg/*.conf
6. проверить конфиг
cat /etc/amnezia/amneziawg/awg0.conf
Должны увидеть `ListenPort = 443`. H1–H4 — большие числа или диапазоны вида `840491219-878906097` (AWG 2.0). Если H1-H4 равны 1/2/3/4 — это обычный WireGuard, DPI его видит.
опционально: вставьте вывод ожидание вывода
4. статус
awg show awg0
Должны увидеть `interface: awg0`, ниже `public key:`, `private key: (hidden)`, `listening port: 443`. Если уже добавлен peer — будет блок `peer:` с `latest handshake` (только после первого подключения клиента).
опционально: вставьте вывод ожидание вывода
Клиент подключается (handshake есть), но интернета нет
Если политика FORWARD = DROP (Docker или UFW ставят её автоматически), обратный трафик не проходит. Проверьте:
проверка политики
iptables -L FORWARD -v -n | head -1
Если видите `policy DROP` — нужно добавить правило для обратного трафика. Замените PostUp/PostDown в `/etc/amnezia/amneziawg/awg0.conf`:
правильные PostUp/PostDown
PostUp = iptables -I FORWARD -i %i -j ACCEPT; iptables -I FORWARD -o %i -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
После изменения: `awg-quick down awg0 && awg-quick up awg0`
Подсеть клиента не совпадает с сервером
`Address` в клиентском конфиге должен быть из той же подсети, что и `Address` сервера в `awg0.conf`. Например, если сервер `10.9.9.1/24` — клиенты должны быть `10.9.9.2`, `10.9.9.3` и т.д. Если у клиента адрес из другой подсети (например `10.20.0.2`) — handshake пройдёт, но трафик маршрутизироваться не будет. Проверьте также что `AllowedIPs` пира на сервере совпадает с `Address` клиента.
AWG не выбран — пропускаем. 443/UDP зарезервирован на будущее.
AWG готов (или пропущен)
9
AWG Panel
Подготовка окружения. Файлы панели зальёте вручную через scp/sftp.
0. проверка
test -d /opt/awg-panel && echo "УЖЕ СУЩЕСТВУЕТ — STOP" || echo "нет, можно ставить" systemctl is-active awg-panel 2>/dev/null && echo "СЕРВИС РАБОТАЕТ — STOP" || echo "сервис не запущен"
опционально: вставьте вывод ожидание вывода
Если показывает «УЖЕ СУЩЕСТВУЕТ» — панель уже развёрнута. Не запускайте шаги ниже, иначе перезатрёте `admin.json`, `server.json` и venv. Забэкапьте: `cp -r /opt/awg-panel /root/awg-panel-backup`
1. создать директорию и venv
mkdir -p /opt/awg-panel cd /opt/awg-panel python3 -m venv venv ./venv/bin/pip install gunicorn flask
⏸ СТОП — залейте файлы панели в `/opt/awg-panel/`
Откройте новое окно терминала на своём компьютере (не тот где SSH) и скопируйте файлы через scp. Или залейте через sftp-клиент (WinSCP, FileZilla).
Путь к папке панели на вашем компьютере
scp (выполнить на своём компьютере!)
scp -P 22 -r "ПУТЬ\*" root@IP:/opt/awg-panel/
После заливки вернитесь в SSH-окно сервера и проверьте:
проверка (на сервере!)
ls /opt/awg-panel/
Должны увидеть `app.py` прямо в списке (не внутри вложенной папки). Если видите только имя папки вместо файлов — файлы залились папка-в-папку, переместите: `mv /opt/awg-panel/deploy/* /opt/awg-panel/ && rmdir /opt/awg-panel/deploy`
вставьте вывод ls ожидание вывода
2. пароль (admin.json)
HASH=$(python3 -c "import hashlib; print(hashlib.sha256('PASS'.encode()).hexdigest())") cat > /opt/awg-panel/admin.json << EOF {"password_hash": "$HASH"} EOF
Ключ — `password_hash`, не `password`. Plaintext → KeyError.
3. server.json
Генерируется из параметров шага 0
IP и домен — от этого сервера! Иначе панель генерирует ссылки на чужой IP.
4. сервис
cat > /etc/systemd/system/awg-panel.service << 'EOF' [Unit] Description=AWG Panel After=network.target [Service] Type=simple WorkingDirectory=/opt/awg-panel ExecStart=/opt/awg-panel/venv/bin/gunicorn --bind 127.0.0.1:5000 --workers 1 --threads 4 --timeout 120 app:app Restart=always RestartSec=5 User=root [Install] WantedBy=multi-user.target EOF
5. запуск
systemctl daemon-reload systemctl enable awg-panel systemctl start awg-panel
6. проверка
systemctl status awg-panel --no-pager -l
Должны увидеть `Active: active (running)` зелёным, ниже строку `Main PID: ... (gunicorn)` и последние строки лога без `error`/`traceback`.
опционально: вставьте вывод ожидание вывода
Панель active (running)
✓
Финальная проверка
все порты
ss -tlnp
панель (https)
curl -sk -o /dev/null -w "%{http_code}\n" https://DOMAIN
опционально: вставьте HTTP-код ожидание вывода
Ответ `200` — панель работает. Откройте в браузере.
редирект (http)
curl -s -o /dev/null -w "%{http_code}\n" http://DOMAIN
опционально: вставьте HTTP-код ожидание вывода
Ответ `301` — редирект на HTTPS. Норма.
IP—
Домен—
Поддомен (протоколы)—
SNI клиентов—
Режим TLS—
Протоколы—
Панель—
Раскладка портов:
443/tcp Xray VLESS+TLS
443/udp резерв (AWG)
8443/tcp mtg MTProto
8444 nginx fallback (localhost)
5000 gunicorn panel (localhost)
10085 Xray stats API (localhost)
Чек-лист частых ошибок:
Xray от nobody sed User=root + NoNewPrivileges=false
chmod сертификатов 755 на директории, 644 на .pem
mtg latest/download Качать .tar.gz через тег версии
admin.json password_hash, не password
server.json IP/домен Обновлять сразу после заливки
sni = поддомен Если есть поддомен — sni и mtg_fake_host = он, не основной
xray серт = поддомен certificateFile из /live/поддомен/, не основной
certbot → default Проверить что не залез в default
SSH порт ≠ 22 UFW правило на реальный порт!
AWG H1-H4 Случайные большие числа, не 1/2/3/4
ALPN Только http/1.1 (h2 → ERR_HTTP2_PROTOCOL_ERROR)
Как зайти в панель в разных режимах XRay. Панель сама детектит TLS/Reality и в разделе `⚙ → Страница входа` показывает рабочий адрес. Ниже — что выбрать в каждом случае. Везде `<IP>`, `<домен>`, `<ключ>`, `<порт>` — подставь свои.
★
Универсально: SSH-туннель (работает всегда)
Если снаружи панель закрыта (Reality, сбитая маскировка, потерян адрес) — заходишь напрямую к gunicorn через туннель. Через него же можно настроить всё остальное.
на своём компьютере
ssh -L 8080:127.0.0.1:5000 root@<IP>
Оставь окно открытым → открой в браузере `http://localhost:8080` (если маскировка/ключ — `http://localhost:8080/<ключ>`).
1
XRay в режиме TLS (сертификат на домен)
Панель едет на 443 «прицепом»: XRay-TLS → fallback → nginx → панель. Отдельный порт не нужен.
Вход: `https://<домен>/` — или `https://<домен>/<ключ>`, если включена маскировка.
В `Страница входа` выбери «Вход по IP» (корень = панель) или «Маскировка фейк-сайтом» (корень = сайт, панель по ключу).
2
XRay в режиме Reality
443 целиком занят Reality (уводит на dest-сайт) — на 443 панель НЕ отдаётся. Нужен отдельный порт.
1. Первый вход — через SSH-туннель (см. выше).
2. `⚙ → Страница входа → Доступ к панели по порту` → впиши порт (напр. `2096`) → выбери режим «Только по ключу» → `Сохранить`. Панель сама поднимет nginx и откроет порт в ufw.
Вход: `https://<домен>:<порт>/<ключ>` (TLS, если есть серт) или `http://<IP>:<порт>/<ключ>` (если серта нет).
Конфиг XRay/Reality панель не трогает — поднимает только свой отдельный nginx-блок `awg-panel-access`.
→
Переезд: был TLS, стал Reality
Был доступ `https://<домен>/`. После смены XRay на Reality 443 перестаёт отдавать панель — веб-доступ пропадёт.
1. Зайди через SSH-туннель.
2. `Страница входа` → задай порт → режим «Только по ключу» → `Сохранить`.
Новый вход: `https://<домен>:<порт>/<ключ>`.
←
Переезд: был Reality, стал TLS
Вернул XRay на TLS+fallback на 443 → панель снова доступна на 443 через домен. Отдельный порт больше не нужен.
1. Зайди по старому порту (если оставлял) или через SSH-туннель.
2. `Страница входа` → очисти поле порта → `Сохранить` (порт закроется в ufw, nginx-блок снимется). Режим верни на «Маскировка» или «Вход по IP».
Вход: `https://<домен>/<ключ>` (или `https://<домен>/` без маскировки).
!
Потерял адрес входа
Сбрось маскировку и key-only через SSH — панель вернётся на корень (доступный через 443-TLS / порт / туннель):
на сервере
sed -i 's/"fake_enabled": true/"fake_enabled": false/;s/"login_block_root": true/"login_block_root": false/' /opt/awg-panel/server.json && systemctl restart awg-panel
Это не закрывает отдельный порт (он в ufw/nginx). Снять порт — в `Страница входа`, очистив поле порта.