1. Гайды
  2. Панели и Xray

Remnawave с нуля: панель в Docker за reverse proxy

Установка панели по официальной инструкции: compose, секреты в .env, Caddy или nginx перед ней, первый вход и что бэкапить. Плюс грабли, на которые сообщество уже наступило.

Актуально для Remnawave 3.4.4 (по официальному репозиторию на 2026-09-24)Обновлено 24.09.2026 7 мин чтения

Официальная установка Remnawave занимает три команды и один конфиг прокси. Большая часть проблем в чатах начинается с попытки сэкономить на последнем: открыть порт 3000 наружу «на пять минут» или поставить скрипт, который делает всё сразу и непонятно как.

Заметка

Гайд опирается на Remnawave 3.4.4 (релиз backend и panel от 2026-09-12) и на файлы docker-compose-prod.yml и .env.sample из ветки main репозитория remnawave/backend на 2026-09-24. Переменные окружения между версиями меняются: при 3.0 сообщество, например, ловило переименование секрета JWT в APP_SECRET ( Env). Перед установкой и каждым обновлением сверяйся с актуальным .env.sample.

Что понадобится

Требования из документации:

МинимумРекомендуется
CPU2 ядра4 ядра
RAM2 ГБ4 ГБ
Диск20 ГБ20 ГБ
ОСUbuntu или Debian

Нужен Docker с плагином Compose. Документация ставит его официальным скриптом:

sudo curl -fsSL https://get.docker.com | sh

И обязательно свой домен, направленный A/AAAA-записью на сервер. Без домена официально только TryCloudflare, и то для разработки.

Панель не содержит Xray: трафик пользователей обслуживают ноды на отдельных серверах, их подключение описано в гайде Нода Remnawave.

Лайфхак

Опыт сообщества (июль 2026): панель в РФ держать не советуют, а сам сайт docs.rw из РФ без VPN может не открываться ( Ошибки → фиксы, Установка и обновление). Документацию лучше открыть заранее.

  1. Браузер
  2. Caddy / nginx
  3. Панель remnawave
  4. Нода
Путь запроса к панели по официальной схеме: прокси в той же docker-сети remnawave-network, панель опубликована только на loopback

Установка

Файлы

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

Путь /opt/remnawave не обязателен, но на него ссылаются все остальные страницы документации, включая обновление.

Секреты

APP_SECRET, METRICS_PASS и WEBHOOK_SECRET_HEADER в примере заданы значениями по умолчанию (change_me, admin и публичная строка из репозитория). Документация генерирует их так:

sed -i "s/^APP_SECRET=.*/APP_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

Пароль Postgres по умолчанию postgres, его настоятельно советуют сменить. Команда из доки меняет его сразу в двух местах, POSTGRES_PASSWORD и DATABASE_URL:

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

Грабли

Меняй пароль Postgres до первого docker compose up. Образ postgres берёт POSTGRES_PASSWORD только при инициализации пустого тома. Если база уже создана, новая строка в .env не сменит пароль внутри базы, и панель перестанет к ней подключаться.

Домены

В .env правишь вручную:

.envbash
FRONT_END_DOMAIN=panel.example.com
SUB_PUBLIC_DOMAIN=panel.example.com/api/sub
PANEL_DOMAIN=panel.example.com
ПеременнаяОбязательнаЗачем
APP_SECRETдасекрет приложения, дока рекомендует от 64 символов
FRONT_END_DOMAINдадомен панели, из него строятся CORS-заголовки
SUB_PUBLIC_DOMAINдадомен и путь публичной ссылки подписки, без http(s):// и без / в конце
PANEL_DOMAINнетпрямые ссылки на панель, например в Telegram-уведомлениях
DATABASE_URLдастрока подключения к Postgres в формате postgresql://user:password@host:port/db

Пока отдельной страницы подписки нет, SUB_PUBLIC_DOMAIN равен домену панели плюс /api/sub. Остальные переменные (уведомления, вебхуки, метрики) описаны на странице Environment Variables.

Что внутри compose

Официальный docker-compose.yml поднимает три контейнера в сети remnawave-network:

КонтейнерОбразПорт на хосте
remnawaveremnawave/backend:3127.0.0.1:3000 (панель), 127.0.0.1:3001 (метрики)
remnawave-dbpostgres:18.4127.0.0.1:6767
remnawave-redisvalkey/valkey:9-alpineнет, только unix-сокет

Что из этого следует:

  • Все порты уже опубликованы на 127.0.0.1. Не «исправляй» это на 3000:3000.
  • Тег remnawave/backend:3 держит мажорную версию: docker compose pull обновит до последней 3.x, но не перепрыгнет на 4.
  • Valkey запущен с --save "" и --appendonly no, то есть ничего не пишет на диск. Всё, что нужно сохранить, лежит в Postgres.
  • У всех сервисов ограничены логи (json-file, 100 МБ × 5 файлов).

Запуск

cd /opt/remnawave && docker compose up -d && docker compose logs -f -t

Важно

.env читается при создании контейнера. Документация прямо пишет: после правки переменных нужен docker compose down && docker compose up -d, простой restart старое окружение не заменит. В сообществе это одна из самых частых причин «поменял, а не работает» ( Установка и обновление).

Reverse proxy

Документация выделяет это красным: прокси обязателен, наружу сервисы не выставлять, только 127.0.0.1. Дополнительные требования:

  • Панель работает только на корне домена или поддомена. Путь вида example.com/remnawave не поддерживается.
  • SSH-проброс порта (ssh -L 3000:...) тоже не поддерживается.

Причина в коде backend: middleware разрывает соединение, если в запросе нет заголовка X-Forwarded-For или X-Forwarded-Proto не равен https, и пишет в лог Reverse proxy and HTTPS are required. Поэтому curl http://127.0.0.1:3000 получит обрыв соединения вместо ответа, и это нормально.

Caddy (официальный вариант)

Caddy сам получает сертификат и сам проставляет X-Forwarded-For и X-Forwarded-Proto.

/opt/remnawave/caddy/Caddyfilecaddy
https://panel.example.com {
        encode
        reverse_proxy * http://remnawave:3000
}
:443 {
    tls internal
    respond 204
}

Второй блок ловит всё остальное на 443: запросы с чужим именем или по голому IP получают самоподписанный сертификат и пустой ответ 204, а не панель.

/opt/remnawave/caddy/docker-compose.ymlyaml
services:
  caddy:
    image: caddy:2.9
    container_name: 'caddy'
    hostname: caddy
    restart: always
    ports:
      - '0.0.0.0:443:443'
      - '0.0.0.0:80:80'
    networks:
      - remnawave-network
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy-ssl-data:/data

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

volumes:
  caddy-ssl-data:
    driver: local
    external: false
    name: caddy-ssl-data
cd /opt/remnawave/caddy && docker compose up -d && docker compose logs -f -t

Caddy подключается к внешней сети remnawave-network и ходит к панели по имени контейнера. Поэтому панель сначала, прокси потом: сеть создаёт compose панели.

nginx

Официальный гайд по nginx устроен так же (контейнер remnawave-nginx в сети remnawave-network, proxy_pass http://remnawave:3000), но сертификат выпускается отдельно через acme.sh в режиме TLS-ALPN на порту 8443. Две детали оттуда: порт 8443 должен быть свободен и открыт при каждом продлении, а зоны .ru, .su и .рф этот способ не поддерживает, потому что их не обслуживает ZeroSSL. В конфиге обязательны proxy_set_header X-Forwarded-For и X-Forwarded-Proto $scheme, иначе сработает проверка выше. Про сертификаты подробнее в гайде TLS-сертификаты.

Панель наружу

ports:
  - 3000:3000

Порт открыт миру в обход файрвола, а панель всё равно разорвёт соединение без HTTPS-прокси.

ports:
  - 127.0.0.1:3000:${APP_PORT:-3000}

Как в официальном compose. Снаружи только 443 у Caddy или nginx.

Панель за прокси

Заметка

Документация советует проксировать домен через Cloudflare (оранжевое облако), если Cloudflare нормально работает в твоём регионе. Для аудитории из РФ это «если» важное, разбор в гайдах nginx за Cloudflare и Сайт не открывается из РФ.

Первый вход

Открываешь https://panel.example.com, видишь форму регистрации. Первый зарегистрированный пользователь становится суперадмином. Поэтому регистрируйся сразу, как только прокси заработал, а не оставляй свежую панель висеть в интернете.

Забыл пароль или случайно отключил вход по паролю через OAuth-настройки: поможет Rescue CLI.

docker exec -it remnawave cli

В меню есть сброс суперадмина (после него панель снова предложит создать аккаунт) и включение входа по паролю.

Данные и бэкапы

ЧтоГде
База панелиdocker-том remnawave-db-data
Секреты и настройки/opt/remnawave/.env, /opt/remnawave/docker-compose.yml
ПроксиCaddyfile и том caddy-ssl-data (или конфиг nginx и сертификаты)

В базе, кроме пользователей и настроек, лежит таблица keygen: корневой сертификат, которым панель подписывает ключи нод. Потеряешь базу без дампа, и каждой ноде придётся выдавать новый SECRET_KEY. Восстановишь из дампа, и ноды подключатся со старыми ключами.

Бэкапить логическим дампом pg_dump, а не копией тома. Скрипт, шифрованный репозиторий и проверка восстановления в гайде Бэкапы: pg_dump, restic и systemd, опыт сообщества в Бэкапах.

Безопасность

  • Проверь, что наружу смотрят только 80/443 прокси: ss -tlnp. Почему ufw и nftables не видят опубликованные Docker-порты, разобрано в гайде Docker для панелей и ботов.
  • Файрвол хоста по гайду nftables: минимальный файрвол. Для связи с нодами на панели ничего открывать не нужно: соединение инициирует панель.
  • Дополнительная защита страницы входа из официального раздела Panel Security: Caddy с авторизацией и секретным путём (remnawave/caddy-with-auth), TinyAuth для nginx, Cloudflare Zero Trust.

Обновление

cd /opt/remnawave && docker compose pull && docker compose down && docker compose up -d && docker compose logs -f
docker image prune

Порядок из документации: сначала панель, потом ноды. Перед обновлением дамп базы и чтение changelog. Подробно в гайде Обновления без поломок.

Типовые ошибки

СимптомПричина и что делать
Соединение рвётся, в логе Reverse proxy and HTTPS are required.Запрос пришёл мимо прокси или прокси не передал X-Forwarded-For / X-Forwarded-Proto: https. Проверь заголовки в конфиге nginx.
Поменял .env, ничего не изменилосьНужен docker compose down && docker compose up -d, не restart.
Панель не подключается к базе после смены пароляПароль сменили в .env уже после инициализации тома, а образ postgres применяет его только к пустому каталогу данных. Меняй пароль внутри базы или делай это до первого запуска.
В nginx host not found in upstreamПрокси не в сети remnawave-network. В сообществе классика ( Реверс-прокси).
Прокси не стартует, 443 занятВ сообществе фиксировали: nginx и Caddy на одном сервере вместе не живут, оставь один ( Реверс-прокси).
После обновления сломались бот или нодыСообщество регулярно ловит несовместимость версий: при 3.0 бот Bedolaga падал с KeyError: 'uuid', ноды не стыковались с панелью другой версии ( Ошибки → фиксы, Релизы). Бот и панель обновляй согласованно, см. Бот Bedolaga.

Больше случаев с датами в индексе ошибок.

Источники