🛠️ Полная ручная установка

Этот гайд проведет вас через все этапы настройки сервера с нуля.

Ознакомьтесь с документацией.

📚
Remnawave Docs
Официальная документация
Backend Repo
Исходный код панели
Node Repo
Исходный код узла
Xray Torrent Blocker
Исходный код torrent-blocker
distillium warp-native
Исходный код warp-native
Cloudflare WARP Native
Исходный код warp-native

1. Подготовка системы и Ядро

Обновите пакеты
sudo apt update && sudo apt upgrade -y
Установка базовых зависимостей
sudo apt install curl wget unzip git ufw socat jq certbot python3-certbot-nginx haproxy speedtest-cli dnsutils -y
Добавление репозитория XanMod (по желанию)
wget -qO - https://dl.xanmod.org/archive.key | sudo gpg --dearmor -o /usr/share/keyrings/xanmod-archive-keyring.gpg --yes
echo 'deb [signed-by=/usr/share/keyrings/xanmod-archive-keyring.gpg] http://deb.xanmod.org releases main' | sudo tee /etc/apt/sources.list.d/xanmod-release.list
sudo apt update && sudo apt upgrade -y
Установка ядра XanMod (по желанию)
Важно: Вы обновляете ядро! Будьте осторожны.

После обновления рекомендуется сбросить hosts. Если при подключении возникает ошибка Host key verification failed, удалите строку с IP сервера в этом файле (на Windows)

C:\Users\user\.ssh\known_hosts
Проверьте совместимость скриптом ниже
wget -qO - https://dl.xanmod.org/check_x86-64_psabi.sh | awk -f -
sudo apt install linux-xanmod-edge-x64v3 -y
sudo apt install linux-xanmod-edge-x64v2 -y
sudo apt install linux-xanmod-edge-x64v1 -y

Перезагрузите сервер!

reboot now

2. Оптимизация сети

Включение BBR

Редактируем sysctl.conf
nano /etc/sysctl.conf

Вставьте в конец файла (включение BBR):

net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

Отключение ipv6

Вставьте в конец файла (отключение ipv6):

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
Применяем настройки
sudo sysctl -p
depmod -a
modinfo tcp_bbr

Изменение DNS

Редактируем resolved.conf
nano /etc/systemd/resolved.conf

Измените/добавьте DNS:

[Resolve]
DNS=1.1.1.1 8.8.8.8
Применяем настройки
sudo systemctl restart systemd-resolved
resolvectl status

3. Установка Панели

Установка Docker
sudo curl -fsSL https://get.docker.com | sh
Скачивание файлов Remnawave
mkdir /opt/remnawave && cd /opt/remnawave
curl -o docker-compose.yml https://raw.githubusercontent.com/remnawave/backend/refs/heads/main/docker-compose-prod.yml
curl -o .env https://raw.githubusercontent.com/remnawave/backend/refs/heads/main/.env.sample
Генерация паролей и токенов (выполнить одной командой)
sed -i "s/^JWT_AUTH_SECRET=.*/JWT_AUTH_SECRET=$(openssl rand -hex 64)/" .env && sed -i "s/^JWT_API_TOKENS_SECRET=.*/JWT_API_TOKENS_SECRET=$(openssl rand -hex 64)/" .env
sed -i "s/^METRICS_PASS=.*/METRICS_PASS=$(openssl rand -hex 64)/" .env && sed -i "s/^WEBHOOK_SECRET_HEADER=.*/WEBHOOK_SECRET_HEADER=$(openssl rand -hex 64)/" .env
pw=$(openssl rand -hex 24) && sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$pw/" .env && sed -i "s|^\\(DATABASE_URL=\\\"postgresql://postgres:\\)[^\\@]*\\(@.*\\)|\\1$pw\\2|" .env
Важно: Не забудьте отредактировать .env и указать ваш домен подписки в SUB_PUBLIC_DOMAIN.
cd /opt/remnawave && nano .env
Запуск панели
cd /opt/remnawave && docker compose down remnawave && docker compose up -d

4. Страница подписки

Создаем docker-compose.yml для подписки
mkdir -p /opt/remnawave/subscription && cd /opt/remnawave/subscription && nano docker-compose.yml

Вставьте содержимое:

Важно: Только для кастомной подписки добавить volume (нужно сгенерировать json файл, положить в директорию с подпиской).
services:
    remnawave-subscription-page:
        image: remnawave/subscription-page:latest
        container_name: remnawave-subscription-page
        hostname: remnawave-subscription-page
        restart: always
        env_file:
            - .env
        ports:
            - '127.0.0.1:3010:3010'
        networks:
            - remnawave-network
        volumes:
            - ./app-config.json:/opt/app/frontend/assets/app-config.json

networks:
    remnawave-network:
        driver: bridge
        external: true
Создаем .env для подписки
cd /opt/remnawave/subscription && nano .env
Вставьте содержимое. Можете изменить TITLE (название) и DESCRIPTION (описание страницы)
APP_PORT=3010
REMNAWAVE_PANEL_URL=http://remnawave:3000
META_TITLE="Subscription page"
META_DESCRIPTION="Subscription page description"
Запуск
cd /opt/remnawave/subscription && docker compose up -d

5. Nginx и SSL (Reverse Proxy)

Установка acme.sh (Замените email)
curl https://get.acme.sh | sh -s email=my@email.com && source ~/.bashrc

Standalone сертификаты

Получение сертификата (Пример Standalone).

Создайте директорию для nginx.

mkdir -p /opt/remnawave/nginx

Получите сертификаты для панели и подписки.

Важно: Замените panel.yourdomain.com и sub.yourdomain.com. Порт 8443 (или другой) должен быть открыт в файрволле.
acme.sh --issue --standalone -d 'panel.yourdomain.com' --key-file /opt/remnawave/nginx/privkey.key --fullchain-file /opt/remnawave/nginx/fullchain.pem --alpn --tlsport 8443
acme.sh --issue --standalone -d 'sub.yourdomain.com' --key-file /opt/remnawave/nginx/sub_privkey.key --fullchain-file /opt/remnawave/nginx/sub_fullchain.pem --alpn --tlsport 8443
Настройка nginx.conf
cd /opt/remnawave/nginx && nano nginx.conf

Скопируйте полный конфиг для Standalone.

upstream remnawave {
    server remnawave:3000;
}

upstream remnawave-subscription-page {
    server remnawave-subscription-page:3010;
}

server {
    server_name panel.yourdomain.com;

    listen 443 ssl reuseport;
    listen [::]:443 ssl reuseport;
    http2 on;

    location / {
        proxy_http_version 1.1;
        proxy_pass http://remnawave;
        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;
    }

    # SSL Configuration (Mozilla Intermediate Guidelines)
    ssl_protocols          TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets    off;
	
    ssl_certificate "/etc/nginx/ssl/fullchain.pem";
    ssl_certificate_key "/etc/nginx/ssl/privkey.key";
    ssl_trusted_certificate "/etc/nginx/ssl/fullchain.pem";

    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
    resolver_timeout       2s;

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
}

server {
    server_name sub.yourdomain.com;

    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    location / {
        proxy_http_version 1.1;
        proxy_pass http://remnawave-subscription-page;
        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;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;

        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # SSL Configuration (Mozilla Intermediate Guidelines)
    ssl_protocols          TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets    off;
	
    ssl_certificate "/etc/nginx/ssl/sub_fullchain.pem";
    ssl_certificate_key "/etc/nginx/ssl/sub_privkey.key";
    ssl_trusted_certificate "/etc/nginx/ssl/sub_fullchain.pem";

    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
    resolver_timeout       2s;

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
}

server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;

    ssl_reject_handshake on;
}

Docker Compose для Nginx (Standalone)

services:
    remnawave-nginx:
        image: nginx:1.28
        container_name: remnawave-nginx
        hostname: remnawave-nginx
        volumes:
            - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
            - ./fullchain.pem:/etc/nginx/ssl/fullchain.pem:ro
            - ./privkey.key:/etc/nginx/ssl/privkey.key:ro
            - ./subdomain_fullchain.pem:/etc/nginx/ssl/sub_fullchain.pem:ro
            - ./subdomain_privkey.key:/etc/nginx/ssl/sub_privkey.key:ro
        restart: always
        ports:
            - '0.0.0.0:443:443'
        networks:
            - remnawave-network

networks:
    remnawave-network:
        name: remnawave-network
        driver: bridge
        external: true

Wildcard сертификат (Cloudflare)

Получение сертификата (Пример Wildcard).

Создайте директорию для nginx.

mkdir -p /opt/remnawave/nginx

Создайте переменные окружения для подключения к Cloudflare.

Важно: Замените ваш_токен (создайте для вашего домена) и ваш_account_id (скопируйте во вкладке Overview).
export CF_Token="ваш_токен"
export CF_Account_ID="ваш_account_id"

Получите wildcard сертификат.

Важно: Замените yourdomain.com.
acme.sh --issue --dns dns_cf \
-d '.yourdomain.com' \
-d '*.yourdomain.com' \
--key-file /opt/remnawave/nginx/wildcard.key \
--fullchain-file /opt/remnawave/nginx/wildcard.pem

Скопируйте полный конфиг для Wildcard.

upstream remnawave {
    server remnawave:3000;
}

upstream remnawave-subscription-page {
    server remnawave-subscription-page:3010;
}

server {
    server_name panel.yourdomain.com;

    listen 443 ssl reuseport;
    listen [::]:443 ssl reuseport;
    http2 on;

    location / {
        proxy_http_version 1.1;
        proxy_pass http://remnawave;
        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;
    }

    # SSL Configuration (Mozilla Intermediate Guidelines)
    ssl_protocols          TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets    off;
	
    ssl_certificate "/etc/nginx/ssl/fullchain.pem";
    ssl_certificate_key "/etc/nginx/ssl/privkey.key";
    ssl_trusted_certificate "/etc/nginx/ssl/fullchain.pem";

    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
    resolver_timeout       2s;

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
}

server {
    server_name sub.yourdomain.com;

    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    location / {
        proxy_http_version 1.1;
        proxy_pass http://remnawave-subscription-page;
        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;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;

        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # SSL Configuration (Mozilla Intermediate Guidelines)
    ssl_protocols          TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets    off;
	
    ssl_certificate "/etc/nginx/ssl/fullchain.pem";
    ssl_certificate_key "/etc/nginx/ssl/privkey.key";
    ssl_trusted_certificate "/etc/nginx/ssl/fullchain.pem";

    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
    resolver_timeout       2s;

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
}

server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;

    ssl_reject_handshake on;
}

Docker Compose для Nginx (Wildcard)

services:
    remnawave-nginx:
        image: nginx:1.28
        container_name: remnawave-nginx
        hostname: remnawave-nginx
        volumes:
            - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
            - ./wildcard.pem:/etc/nginx/ssl/fullchain.pem:ro
            - ./wildcard.key:/etc/nginx/ssl/privkey.key:ro
        restart: always
        ports:
            - '0.0.0.0:443:443'
        networks:
            - remnawave-network

networks:
    remnawave-network:
        name: remnawave-network
        driver: bridge
        external: true
Запустите
docker compose up -d

6. Установка Ноды

Важно: Если у вас отдельный сервер, не забудьте установить docker и оптимизировать сервер.
sudo curl -fsSL https://get.docker.com | sh
Создайте папку для логов Xray
mkdir -p /var/log/remnanode
Настройка логов (Logrotate)
sudo bash -c 'cat > /etc/logrotate.d/remnanode <<EOF
/var/log/remnanode/*.log {
    size 50M
    rotate 5
    compress
    missingok
    notifempty
    copytruncate
}
EOF'
Создайте docker-compose для ноды
mkdir /opt/remnanode && cd /opt/remnanode && nano docker-compose.yml
Пример конфига ноды
Важно: Замените supersecretkey (ключ необходимо скопировать при создании ноды в панели).
services:
    remnanode:
        container_name: remnanode
        image: remnawave/node:latest
        restart: always
        network_mode: host
        environment:
          - NODE_PORT=2222
          - SECRET_KEY="supersecretkey"
        volumes:
          - '/var/log/remnanode:/var/log/remnanode'
Запустите docker ноды
docker compose up -d

7. Дополнительно

Установка Torrent Blocker

bash <(curl -fsSL git.new/install)
Отредактировать файл докера
nano /opt/tblocker/config.yaml
Вставьте следующее содержимое (измените необходимые переменные)
# Файл логов для мониторинга
LogFile: "/var/log/remnanode/access.log"

# Продолжительность блокировки в минутах
BlockDuration: 10

# Тег, используемый для идентификации торрент-трафика в логах
TorrentTag: "TORRENT"

# Файрволл для блокировки (iptables, nft)
BlockMode: "iptables"
# IP-адреса для обхода блокировки
BypassIPS:
  - "127.0.0.1"
  - "::1"

# Директория для хранения данных о блокировке
StorageDir: "/opt/tblocker"

# Регулярное выражение для обработки имени пользователя в вебхуках
UsernameRegex: "^(.+)$"
Запустите TORRENT-Blocker
systemctl start tblocker
Для чтения логов tblocker вы можете использовать следующую команду:
journalctl -u tblocker -f --no-pager

В конфиг Xray добавьте правило маршрутизации routing:

{
    "type": "field",
    "protocol": ["bittorrent"],
    "outboundTag": "TORRENT"
}

И соответствующий outbound:

{
    "protocol": "blackhole",
    "tag": "TORRENT"
}

Установка WARP

bash <(curl -fsSL https://raw.githubusercontent.com/distillium/warp-native/main/install.sh)
Нативное управление (желательно)
ansible-galaxy install themelbine.warp_native

Пример:

- hosts: warp_servers
  become: yes
  roles:
      - themelbine.warp_native
  vars:
      warp_native_state: present
      warp_native_modify_resolv: true
      warp_native_temp_nameservers:
          - "1.1.1.1"
          - "8.8.8.8"

Добавьте этот блок в раздел outbounds вашего конфига Xray:

{
    "tag": "warp-out",
    "protocol": "freedom",
    "settings": {},
    "streamSettings": {
        "sockopt": {
            "interface": "warp",
            "tcpFastOpen": true
        }
    }
}

Добавьте этот блок в раздел routing вашего конфига Xray:

domain: Прописать домены (или geosite) для маршрутизации определенных сайтов.

inboundTag: Прописать ваши инбаунды "Node-1" и "Node-2", чтобы весь их трафик пустить через WARP

{
    "type": "field",
    "domain": ["netflix.com", "youtube.com", "geosite:category-ru"],
    "inboundTag": ["Node-1", "Node-2"],
    "outboundTag": "warp-out"
}

Настройка Selfsteal

Создайте страницу-заглушку sni.html или скопируйте предложенную:

nano /opt/remnawave/nginx/html/sni.html
📥 Скачать
Загрузка содержимого sni.html...
Важно: Не забудьте выпустить сертификаты или используйте Wildcard-сертификат.
Важно: Добавьте в docker compose порт и volume.

Пример docker-compose.yml для nginx (в режиме hosts):

services:
    remnawave-nginx:
        image: nginx:1.28
        container_name: remnawave-nginx
        hostname: remnawave-nginx
        restart: always
        volumes:
            - ./html:/usr/share/nginx/html/custom:ro
            - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
            - ./wildcard.pem:/etc/nginx/ssl/wildcard.pem:ro
            - ./wildcard.key:/etc/nginx/ssl/wildcard.key:ro
        network_mode: "host"

Пример docker-compose.yml для nginx (существующая сеть с панелью):

services:
    remnawave-nginx:
        image: nginx:1.28
        container_name: remnawave-nginx
        hostname: remnawave-nginx
        restart: always
        ports:
            - '127.0.0.1:9443:9443'
            - '0.0.0.0:443:443'
        volumes:
            - ./html:/usr/share/nginx/html/custom:ro
            - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
            - ./wildcard.pem:/etc/nginx/ssl/wildcard.pem:ro
            - ./wildcard.key:/etc/nginx/ssl/wildcard.key:ro
        networks:
            - remnawave-network

networks:
    remnawave-network:
        name: remnawave-network
        driver: bridge
        external: true

Добавьте секцию сервера в nginx.conf

Замените:

SNI_DOMAIN gateway.domain.com

FALLBACK_PORT 9443

CERT_PATH /etc/nginx/ssl/fullchain.pem

KEY_PATH /etc/nginx/ssl/privkey.key

# --- SNI FALLBACK (SNI_DOMAIN) ---
server {
    server_name SNI_DOMAIN;
    listen FALLBACK_PORT ssl proxy_protocol;
    http2 on;

    set_real_ip_from 127.0.0.1;
    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 172.16.0.0/12;
    set_real_ip_from 192.168.0.0/16;
    real_ip_header proxy_protocol;

    root /usr/share/nginx/html/custom;
    index sni.html;

    # Логика обработки запросов
    location = /sni.html {
        add_header Cache-Control "no-store, no-cache, must-revalidate";
        log_not_found off;
    }

    location / {
        # Если файл не найден - редирект на именованный файл /sni.html
        try_files \$uri \$uri/ /sni.html;
        add_header Cache-Control "no-store, no-cache, must-revalidate";
    }

    # SSL Configuration (Mozilla Intermediate Guidelines)
    ssl_protocols          TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets    off;

    # Пути сертификатов (внутри контейнера)
    ssl_certificate "CERT_PATH";
    ssl_certificate_key "KEY_PATH";
    ssl_trusted_certificate "CERT_PATH";

    ssl_stapling           on;
    ssl_stapling_verify    on;
    resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
    resolver_timeout       2s;

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
}

Перезагрузите docker nginx:

cd /opt/remnawave/nginx && docker compose down && docker compose up -d

Измените ваш streamSettings в inbounds вашего конфига Xray:

Необходимо установить xver 1, так как в nginx включен proxy_protocol, чтобы логи nginx определяли реальный IP клиента, открывшего адрес заглушки.

В target (он же dest) указываем локальный адрес и порт заглушки.

В serverNames указываем domain заглушки.

"streamSettings": {
    "network": "raw",
    "security": "reality",
    "realitySettings": {
        "show": false,
        "xver": 1,
        "target": "127.0.0.1:9443",
        "shortIds": [
            ""
        ],
        "publicKey": "",
        "privateKey": "",
        "serverNames": [
            "gateway.domain.com"
        ]
    }
}

DNS Load Balancer (Auto-Switch)

Эта система позволяет автоматически переключать DNS-запись на наименее загруженную ноду.

Для работы требуется домен, подключенный к Cloudflare!

1. Настройка Агента (на Worker-нодах)

Установите зависимости:

apt install python3-pip python3-psutil -y || pip3 install psutil --break-system-packages

Создайте папку:

mkdir -p /opt/remnawave-balancer

Скачайте или создайте monitor.py:

📥 Скачать
Загрузка содержимого monitor.py...

Создайте сервис и запустите:

cat <<EOF > /etc/systemd/system/remnawave-monitor.service
[Unit]
Description=Remnawave Node Monitor
After=network.target

[Service]
User=root
WorkingDirectory=/opt/remnawave-balancer
ExecStart=/usr/bin/python3 /opt/remnawave-balancer/monitor.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Запускаем демон

systemctl daemon-reload && systemctl enable --now remnawave-monitor

Открываем порт для Balancer (Master-сервер)

Замените IP и порт!
ufw allow from 1.1.1.1 to any port 5050 proto tcp comment 'Master Balancer'

2. Настройка Балансировщика (на Master-сервере)

Установите зависимости:

apt install python3-requests -y
mkdir -p /opt/remnawave-balancer

Скачайте или создайте balancer.py:

Не забудьте отредактировать токены и домен!
📥 Скачать
Загрузка содержимого balancer.py...

Создайте файл nodes.json со списком серверов:

nano /opt/remnawave-balancer/nodes.json
Замените IP и порт!
[
    {
        "name": "Node-1",
        "ip": "1.1.1.1",
        "port": 5050
    }
]

Создайте сервис и запустите:

# Создаем сервис
cat <<EOF > /etc/systemd/system/remnawave-balancer.service
[Unit]
Description=Remnawave DNS Balancer
After=network.target

[Service]
User=root
WorkingDirectory=/opt/remnawave-balancer
ExecStart=/usr/bin/python3 /opt/remnawave-balancer/balancer.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

Запускаем демон

systemctl daemon-reload && systemctl enable --now remnawave-balancer

Просмотр логов

tail -f /var/log/remnawave-balancer.log

Каскадная маршрутизация

Клиент - RU нода - EU нода

Первым пунктом необходимо настроить конфигурацию Xray на зарубежной ноде.

Измените target, serverNames, сгенерируйте ключи publicKey и privateKey

Запомните publicKey вашего инбаунда, он понадобится при настройке RU ноды.

{
  "log": {
    "error": "/var/log/remnanode/error.log",
    "access": "/var/log/remnanode/access.log",
    "loglevel": "error"
  },
  "inbounds": [
    {
      "tag": "Vless TCP Reality EU",
      "port": 443,
      "listen": "0.0.0.0",
      "protocol": "vless",
      "settings": {
        "clients": [],
        "decryption": "none"
      },
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls",
          "quic"
        ]
      },
      "streamSettings": {
        "network": "raw",
        "security": "reality",
        "realitySettings": {
          "show": false,
          "xver": 0,
          "target": "example.com:443",
          "shortIds": [
            ""
          ],
          "publicKey": "12345678qwerty",
          "privateKey": "87654321",
          "serverNames": [
            "example.com"
          ]
        }
      }
    }
  ],
  "outbounds": [
    {
      "tag": "DIRECT",
      "protocol": "freedom"
    },
    {
      "tag": "BLOCK",
      "protocol": "blackhole"
    }
  ],
  "routing": {
    "rules": [
      {
        "ip": [
          "geoip:private"
        ],
        "type": "field",
        "outboundTag": "BLOCK"
      },
      {
        "type": "field",
        "domain": [
          "geosite:private"
        ],
        "outboundTag": "BLOCK"
      },
      {
        "type": "field",
        "protocol": [
          "bittorrent"
        ],
        "outboundTag": "BLOCK"
      }
    ]
  }
}

Вторым этапом необходимо создать пользователя Bridge (он будет сервисным пользователем, не давайте ключи для подключения к данному профилю!).

Запомните VLESS UUID пользователя Bridge, он понадобится при настройке RU ноды.

Третьим этапом необходимо настроить конфигурацию Xray на RU ноде.

В inbounds Vless TCP Reality RU измените target, serverNames, сгенерируйте ключи publicKey и privateKey

В outbounds vnext-outbound замените IP/domain вашей EU ноды, VLESS UUID пользователя Bridge, serverNames EU ноды.

В routing добавьте правила маршрутизации. geoip:ru и geosite:category-ru пустите напрямую с RU ноды, inboundTag укажите ваш inbound RU ноды, чтобы весь оставшийся трафик ушел на EU ноду.

{
  "log": {
    "error": "/var/log/remnanode/error.log",
    "access": "/var/log/remnanode/access.log",
    "loglevel": "error"
  },
  "inbounds": [
    {
      "tag": "Vless TCP Reality RU",
      "port": 443,
      "listen": "0.0.0.0",
      "protocol": "vless",
      "settings": {
        "clients": [],
        "decryption": "none"
      },
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls",
          "quic"
        ]
      },
      "streamSettings": {
        "network": "raw",
        "security": "reality",
        "realitySettings": {
          "target": "example.com:443",
          "show": false,
          "xver": 0,
          "shortIds": [
            ""
          ],
          "publicKey": "REPLACE_WITH_YOUR_PUBLIC_KEY",
          "privateKey": "REPLACE_WITH_YOUR_PRIVATE_KEY",
          "serverNames": [
            "example.com"
          ]
        }
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "tag": "DIRECT"
    },
    {
      "protocol": "blackhole",
      "tag": "BLOCK"
    },
    {
      "protocol": "vless",
      "tag": "vnext-outbound",
      "settings": {
        "vnext": [
          {
            "address": "IP_вашей_ноды_EU",
            "port": 443,
            "users": [
              {
                "id": "VLESS UUID_пользователя_Bride",
                "flow": "xtls-rprx-vision",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "raw",
        "security": "reality",
        "realitySettings": {
          "serverName": "example.com",
          "publicKey": "publicKey_вашей_ноды_EUы",
          "spiderX": "/"
        }
      }
    }
  ],
  "routing": {
    "rules": [
      {
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "BLOCK",
        "type": "field"
      },
      {
        "domain": [
          "geosite:private"
        ],
        "outboundTag": "BLOCK",
        "type": "field"
      },
      {
        "protocol": [
          "bittorrent"
        ],
        "outboundTag": "BLOCK",
        "type": "field"
      },
      {
        "ip": [
          "geoip:ru"
        ],
        "outboundTag": "DIRECT",
        "type": "field"
      },
      {
        "domain": [
          "geosite:category-ru"
        ],
        "outboundTag": "DIRECT",
        "type": "field"
      },
      {
        "type": "field",
        "inboundTag": [
          "Vless TCP Reality RU"
        ],
        "outboundTag": "vnext-outbound"
      }
    ]
  }
}