wg-easy: веб-панель управления WireGuard без консоли
Если вы уже настраивали WireGuard на VPS вручную, то знаете это ощущение: третий клиент — и вы снова редактируете wg0.conf через nano, вручную подбираете свободный IP в подсети и генерируете QR-код отдельной командой. wg-easy убирает всю эту рутину: один контейнер поднимает и WireGuard, и веб-панель, где клиент добавляется тремя кликами, а конфиг и QR-код появляются сразу же. Ниже — как развернуть wg-easy через Docker, что означают его переменные окружения и на что обратить внимание в первую очередь.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что делает wg-easy и когда он оправдан
wg-easy — это открытый проект, который упаковывает WireGuard-сервер и Node.js-панель в один Docker-контейнер. Внутри контейнер сам генерирует ключи, поднимает интерфейс wg0, прописывает правила iptables для NAT и форвардинга, а панель на порту 51821 даёт веб-интерфейс для управления пирами. Никакого SSH после установки не требуется — все операции с клиентами делаются через браузер.
Это оправдано, когда:
- клиентов больше двух-трёх и они появляются/исчезают регулярно (сотрудники, устройства, гости);
- конфиги и QR-коды нужно выдавать людям, которые не разбираются в WireGuard и не полезут в терминал;
- хочется видеть в одном месте, кто подключён сейчас и когда был последний handshake, без
wg show.
Если сервер один, а клиента два и они не меняются месяцами, ручная настройка по классической схеме будет проще и без лишнего слоя — панель добавляет процесс (контейнер, порт, пароль), за который тоже нужно отвечать. Взамен она экономит время на каждом следующем клиенте.
Установка через Docker Compose
Нужен VPS с публичным IP и установленным Docker Engine с плагином Compose. Если Docker ещё не стоит — сначала установите Docker на Ubuntu 24.04 или на используемый вами дистрибутив.
Понадобятся два открытых порта: 51820/udp — сам туннель WireGuard, и 51821/tcp — веб-панель (номер можно и нужно сменить, об этом ниже). Ядро должно поддерживать WireGuard (в современных дистрибутивах Ubuntu, Debian, AlmaLinux — из коробки) и разрешать форвардинг пакетов:
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wireguard.conf
sysctl -p /etc/sysctl.d/99-wireguard.conf
Проверьте, что порты не заняты другим процессом, и откройте их в firewall хоста заранее — контейнер сам с ufw или firewalld ничего не сделает:
ufw allow 51820/udp
ufw allow 51821/tcp
Порт панели стоит открывать точечно, а не на весь интернет — вернёмся к этому в разделе про безопасность. Теперь создайте каталог проекта и файл docker-compose.yml:
mkdir -p ~/wg-easy && cd ~/wg-easy
nano docker-compose.yml
Базовый конфиг:
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy
container_name: wg-easy
environment:
- WG_HOST=203.0.113.10
- PASSWORD_HASH=замените_на_bcrypt_хэш
- PORT=51821
- WG_PORT=51820
- WG_DEFAULT_DNS=1.1.1.1
- WG_DEFAULT_ADDRESS=10.8.0.x
volumes:
- ./data:/etc/wireguard
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
restart: unless-stopped
Разберём ключевые переменные. WG_HOST — публичный IP или доменное имя сервера, именно этот адрес попадёт в поле Endpoint всех выданных клиентских конфигов, поэтому здесь нужен реальный внешний адрес, а не localhost и не внутренний IP контейнера. WG_PORT — UDP-порт туннеля, PORT — порт веб-панели внутри контейнера (наружу он проброшен той же цифрой в секции ports, но их можно развести). WG_DEFAULT_ADDRESS задаёт шаблон подсети для новых клиентов — символ x панель сама заменит на очередной свободный номер.
Каталог ./data — это единственное, что нужно бэкапить: внутри лежат все ключи сервера и клиентов, конфиг wg0.json и служебные файлы.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверПароль и первый запуск
Открытая веб-панель без пароля — это доступ к вашему VPN-серверу для кого угодно, поэтому PASSWORD_HASH обязателен. Хэш генерируется тем же образом, что и сам сервис, без установки лишних утилит:
docker run --rm ghcr.io/wg-easy/wg-easy wgpw 'ваш_надёжный_пароль'
Команда выведет строку вида PASSWORD_HASH='$2a$...' — вставьте её в docker-compose.yml целиком, вместе с кавычками, если в хэше есть символ $ (в YAML его лучше экранировать одинарными кавычками, как в примере выше). Пустой PASSWORD_HASH в некоторых версиях образа трактуется как «пароль не требуется» — проверьте, что переменная реально попала в контейнер, прежде чем открывать порт наружу.
Запускаем:
docker compose up -d
docker compose logs -f wg-easy
В логах должно появиться сообщение о том, что интерфейс wg0 поднят и панель слушает порт. Дальше открываем http://<IP-сервера>:51821 в браузере и вводим пароль. Если панель не открывается — сначала проверьте docker compose ps (контейнер должен быть running, не restarting), а затем — что порт 51821 действительно проброшен и не блокируется firewall хостера отдельно от ufw на самом сервере.
Добавление и удаление клиентов
Внутри панели вся работа с пирами сведена к кнопке «New Client» вверху экрана:
- нажмите «New Client», введите имя (например,
laptop-annaилиphone-ivan) — по имени потом легче искать нужное устройство в списке; - панель сама сгенерирует пару ключей и выдаст свободный IP из подсети
WG_DEFAULT_ADDRESS; - на карточке клиента сразу доступны кнопка скачивания
.conf-файла и QR-код для мобильных приложений.
Клиента можно временно выключить переключателем — это отключает пира без удаления его конфига и ключей, удобно для сотрудника в отпуске или тестового устройства. Полное удаление — отдельная кнопка с подтверждением, после него конфиг у клиента на телефоне или ноутбуке перестаёт работать сразу, пересоздавать его придётся заново с новыми ключами.
В карточке клиента также видно объём переданного и принятого трафика и время последнего handshake — те же данные, что раньше приходилось смотреть через wg show по SSH, только в браузере и сразу по всем клиентам.
QR-коды и раздача конфигов
Ради этого пункта многие и ставят wg-easy: подключение телефона занимает секунды. На карточке клиента нажмите иконку QR-кода — панель покажет код прямо в браузере. На телефоне откройте приложение WireGuard, выберите подключение с Android или с iPhone через сканирование QR — и туннель поднимется без единого символа, введённого вручную.
Для ноутбуков и десктопов, где сканировать QR неудобно, используйте кнопку скачивания .conf-файла — он импортируется в клиент WireGuard как обычный файл конфигурации.
Важный нюанс: QR-код и файл содержат приватный ключ клиента в открытом виде. Показ QR-кода в браузере — это фактически передача секрета, поэтому не отправляйте скриншот кода в общий чат и не оставляйте открытую вкладку панели на чужом экране. Если конфиг скомпрометирован — просто удалите клиента в панели и создайте нового, старые ключи после удаления теряют силу.
Безопасность: за что отвечаете именно вы
wg-easy снимает рутину с управления клиентами, но не снимает с вас ответственность за периметр. Несколько вещей, на которые стоит обратить внимание сразу после установки:
- Не держите панель открытой на весь интернет. Порт 51821 — привлекательная цель: это единая точка входа ко всем вашим клиентам и ключам. Ограничьте доступ через firewall по конкретным IP, повесьте панель за отдельный VPN-туннель или хотя бы за reverse-proxy с базовой аутентификацией и IP-whitelist.
- Терминируйте HTTPS перед панелью. Сам wg-easy отдаёт интерфейс по HTTP без TLS. Пароль при входе уходит в открытом виде, если между вами и сервером нет шифрования. Поставьте перед контейнером Caddy или nginx с автоматическим Let's Encrypt и проксируйте на
127.0.0.1:51821, не публикуя порт наружу напрямую. - Не теряйте каталог
./data. Это единственное место, где хранятся приватные ключи сервера и всех клиентов. Потеря каталога означает пересоздание всех туннелей с нуля — регулярно копируйте его на отдельный диск или в другое хранилище. - Используйте длинный пароль панели, а не то же самое, что и для SSH или почты — компрометация панели даёт доступ ко всей VPN-инфраструктуре разом.
Обновление и типичные проблемы
Обновление — это пересоздание контейнера с новым образом, данные при этом сохраняются в volume:
docker compose pull
docker compose up -d
Перед обновлением на мажорную версию (например, если в тегах образа сменился номер v1x на v1x+1) загляните в changelog проекта на GitHub — формат wg0.json иногда меняется между крупными релизами, и без миграции старые клиенты могут не подхватиться после обновления. Простое правило: перед любым апдейтом делайте копию каталога ./data, тогда откат — это просто docker compose down, возврат старого образа в compose-файле и up -d заново.
Частые проблемы на практике:
- Панель поднялась, но клиенты не видят интернет — почти всегда причина в
net.ipv4.ip_forward, который сброшен на хосте, или в том, что контейнер не получилcap_add: NET_ADMIN— без этой capability он не может настроитьiptables-правила NAT. WG_HOSTуказывает не туда — если в него по ошибке попал внутренний IP или домен без A-записи, все выданные ранее конфиги окажутся нерабочими; после исправления переменной старым клиентам нужно перевыпустить конфиг заново.- Контейнер не стартует после перезагрузки хоста — проверьте
restart: unless-stoppedв compose-файле и что сам Docker в systemd находится в автозапуске. - Порт 51820 занят — если на сервере уже стоит классический WireGuard, поднятый вручную по инструкции для VPS, сначала остановите системный интерфейс
wg-quick@wg0, иначе оба процесса будут конфликтовать за один порт.
Более общие сетевые сбои самого WireGuard — отсутствие handshake, обрыв туннеля, доступ есть, а трафика нет — разобраны отдельно в статье про частые ошибки WireGuard на сервере, и они актуальны для wg-easy точно так же, потому что внутри контейнера работает тот же протокол.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Чем wg-easy отличается от обычного WireGuard?
Это тот же протокол и тот же интерфейс wg0, но управление вынесено в веб-панель: генерация ключей, IP-адресов, QR-кодов и правил NAT автоматизирована контейнером вместо ручной правки wg0.conf.
Можно ли запустить wg-easy рядом с уже настроенным вручную WireGuard?
Не на одном UDP-порту — будет конфликт. Либо остановите системный wg-quick@wg0, либо запустите wg-easy на другом порту через переменную WG_PORT.
Нужен ли отдельный домен для панели?
Не обязателен, доступ работает и по IP, но домен нужен, если вы хотите поставить перед панелью HTTPS через Let's Encrypt — для валидного сертификата нужна A-запись.
Как перенести wg-easy на другой сервер?
Скопируйте каталог ./data целиком на новый сервер, разверните тот же docker-compose.yml с обновлённым WG_HOST (новый IP) и запустите — ключи и клиенты сохранятся, но конфиги у клиентов из-за смены Endpoint придётся перевыпустить.
Что будет, если забыть пароль от панели?
Штатного восстановления через интерфейс нет — придётся зайти на сервер и задать новый PASSWORD_HASH в compose-файле, затем пересоздать контейнер командой docker compose up -d.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →