VPN Stack

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

Панель
Сервер с нуля
Доступ к панели
0
Требования
На сервере уже должно быть настроено:
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 вашего VPS. Узнать: curl ifconfig.me
Домен, на который выпущен сертификат (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
Панель раздаёт клиентам параметры обфускации из 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.
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).
Готово
финальная проверка
curl -sk -o /dev/null -w "%{http_code}\n" https://ДОМЕН
опционально: вставьте HTTP-код ответаожидание вывода
Ответ 200 — панель работает. Откройте в браузере и залогиньтесь.
Сервер
IP
Домен
Протоколы
Панель
Раскладка портов:
443/tcpXray VLESS+TLS
443/udpAWG (если вкл.)
8443/tcpmtg MTProto
8444nginx fallback (localhost)
5000gunicorn panel (localhost)
10085Xray stats API (localhost)
0
Подключение к серверу
Введите данные VPS. Эти значения будут подставляться во все команды дальше.
Стандартный — 22. Если хостер выдал другой (например 23422) — впишите его.
Домен для отображения сайта/панели в браузере. Должен указывать A-записью на IP сервера.
Если хотите разделить — укажите поддомен для XRay SNI, mtg и клиентских ссылок (например vpn.example.com или proxy.example.com). Тоже должен указывать A-записью на IP сервера. Если пусто — используется основной домен.
Будет захэширован SHA256 для admin.json.
По умолчанию 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, серт — всё совпадает). Панель открывается через браузер.
1
Проверка DNS
Убеждаемся что домен (и поддомен, если указан) указывают на IP сервера. Без этого Certbot не выдаст сертификат.
основной домен
dig +short DOMAIN
опционально: вставьте выводожидание вывода
Должен вернуть IP. Если пусто или другой IP — настройте A-запись у регистратора и подождите 5-10 минут.
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
опционально: вставьте выводожидание вывода
4
Fail2ban
Защита от брутфорса SSH. В ignoreip укажите свои 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 активен.
опционально: вставьте выводожидание вывода
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ожидание вывода
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 без ошибок.
опционально: вставьте выводожидание вывода
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 — он пойдёт в конфиг. Вставьте его в поле ниже.
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 выше
запуск
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 — это норма.
опционально: вставьте выводожидание вывода
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 слушает порт.
опционально: вставьте выводожидание вывода
8
AmneziaWG
AWG не выбран — пропускаем. 443/UDP зарезервирован на будущее.
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.
опционально: вставьте выводожидание вывода
Финальная проверка
все порты
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/tcpXray VLESS+TLS
443/udpрезерв (AWG)
8443/tcpmtg MTProto
8444nginx fallback (localhost)
5000gunicorn panel (localhost)
10085Xray stats API (localhost)
Чек-лист частых ошибок:
Xray от nobodysed User=root + NoNewPrivileges=false
chmod сертификатов755 на директории, 644 на .pem
mtg latest/downloadКачать .tar.gz через тег версии
admin.jsonpassword_hash, не password
server.json IP/доменОбновлять сразу после заливки
sni = поддоменЕсли есть поддомен — sni и mtg_fake_host = он, не основной
xray серт = поддоменcertificateFile из /live/поддомен/, не основной
certbot → defaultПроверить что не залез в default
SSH порт ≠ 22UFW правило на реальный порт!
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). Снять порт — в Страница входа, очистив поле порта.