Ручной WireGuard — это двадцать команд в терминале, ковыряние ключей через cat и правка wg0.conf в nano. Админы так ставили годами. Но есть способ в десять раз короче: контейнер wg-easy с графическим интерфейсом и генерацией QR-кодов по клику. Ниже — пошагово с граблями, о которых молчит официальная документация.
Что понадобится
- VPS с Ubuntu 24.04, минимум 512 МБ ОЗУ и доступ от root.
- Внешний IP сервера (в примере ниже —
10.10.10.10, подставьте свой). - SSH-клиент: PuTTY, встроенный терминал macOS или Windows Terminal.
- 15 минут и желание не заниматься ерундой.
Шаг 1. Обновить систему и поставить Docker
Первая команда — обновление пакетов. Вторая — официальный установщик Docker от самой компании Docker, а не тот огрызок, что лежит в репозиториях Ubuntu.
sudo apt update && sudo apt upgrade -y
curl -fsSL https://get.docker.com | sudo sh
sudo docker --version
Последняя команда покажет версию — что-то вроде Docker version 29.4.0. Значит встало.
apt часто ругается: «Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1584». Это фоновый unattended-upgrades тянет обновления безопасности. Подождите 2–5 минут и повторите. Если висит дольше — посмотрите, жив ли процесс: ps aux | grep apt. Мёртвый убивается через sudo kill 1584, дальше sudo rm /var/lib/dpkg/lock-frontend и sudo dpkg --configure -a.
Шаг 2. Сгенерировать bcrypt-хэш пароля
В версии wg-easy v14 разработчики запретили передавать пароль в открытом виде через переменную окружения. Теперь принимается только его криптографический отпечаток — bcrypt-хэш. Генерируется одной командой через Python:
sudo apt install python3-pip -y
pip install bcrypt --break-system-packages
python3 -c "import bcrypt; print(bcrypt.hashpw(b'ВашПароль123!', bcrypt.gensalt()).decode())"
Вместо ВашПароль123! — свой пароль. На выходе получите строку вида:
$2b$12$KYum4CSmy2IeYG7K8Y4kPu7rUiBJ99yJZvSe6Ihv6bQk0P8vK7TX6
Сохраните и хэш, и сам пароль. Хэш уйдёт в контейнер. Пароль будете вводить в веб-интерфейсе.
Шаг 3. Запустить контейнер wg-easy
Команда длинная, но её надо выполнить один раз. Подставьте свой внешний IP вместо 10.10.10.10 и свой хэш в PASSWORD_HASH:
sudo docker run -d
--name=wg-easy
-e LANG=ru
-e WG_HOST=10.10.10.10
-e PASSWORD_HASH='$2b$12$KYum4CSmy2IeYG7K8Y4kPu7rUiBJ99yJZvSe6Ihv6bQk0P8vK7TX6'
-e PORT=51821
-e WG_PORT=51820
-v ~/.wg-easy:/etc/wireguard
-p 51820:51820/udp
-p 51821:51821/tcp
--cap-add=NET_ADMIN
--cap-add=SYS_MODULE
--sysctl="net.ipv4.conf.all.src_valid_mark=1"
--sysctl="net.ipv4.ip_forward=1"
--restart unless-stopped
ghcr.io/wg-easy/wg-easy
⚠ Грабли №2. Хэш bcrypt начинается с $2b$. В двойных кавычках bash попытается подставить переменные $2 и $b — пароль сломается. Только одинарные кавычки. Если на выходе контейнер в цикле Restarting и в логах — invalid credentials, дело именно в этом.
Проверяем, что запустилось:
sudo docker ps
В статусе должно быть Up N seconds (health: starting). Надпись Restarting — плохой знак, смотрите логи через sudo docker logs wg-easy.
Шаг 4. Открыть порты в брандмауэре
UDP 51820 — это сам туннель WireGuard. TCP 51821 — веб-интерфейс.
sudo ufw allow OpenSSH
sudo ufw allow 51820/udp
sudo ufw allow 51821/tcp
sudo ufw enable
Совет. Команда OpenSSH в первой строке — не украшение. Без неё при включении ufw вы отвалитесь от сервера и не сможете зайти повторно. SSH открывается первым, всегда.
Шаг 5. Зайти в веб-интерфейс и добавить клиента
Открываем в браузере http://10.10.10.10:51821, вводим пароль. Видим пустой список клиентов. Жмём кнопку «+ New», пишем имя (например, phone), получаем QR-код и файл .conf.
На телефоне: приложение WireGuard из магазина, кнопка «+» → «Сканировать QR-код». На ноутбуке: скачиваем файл, импортируем через клиент WireGuard для Windows, macOS или Linux.
Проверка работы одна: заходим на 2ip.ru с включённым туннелем. Адрес совпал с IP сервера? Всё поднялось.
Грабли, о которых молчит документация
Имя сетевого интерфейса
У ручного WireGuard в wg0.conf есть правила NAT с указанием интерфейса. На VPS он может называться ens3, eth0, enp1s0 или ещё как-то. Узнать своё имя: ip -o -4 route show to default | awk '{print $5}'. У wg-easy этот геморрой скрыт внутри контейнера — ещё один плюс в его копилку.
Старый wg0.conf от предыдущих попыток
Если раньше возились с ручной установкой и пакет wireguard уже стоит, в /etc/wireguard/ лежит старый конфиг с другим портом. Перед запуском wg-easy остановите старый сервис: sudo systemctl stop wg-quick@wg0 && sudo systemctl disable wg-quick@wg0. Иначе два WireGuard подерутся за порт 51820.
Провайдер режет UDP
Некоторые хостеры блокируют UDP на нестандартных портах либо требуют открыть их в панели управления, а не только в ufw. Если docker ps говорит «всё ок», веб-интерфейс доступен, а VPN не подключается — проверьте панель провайдера. Beget, Timeweb, ВДСина — у каждого свои правила.
Обслуживание: шпаргалка команд
sudo docker logs wg-easy # посмотреть логи
sudo docker restart wg-easy # перезапустить
sudo docker stop wg-easy # остановить
sudo docker start wg-easy # запустить
sudo docker rm -f wg-easy # снести контейнер
Данные клиентов и ключи живут в ~/.wg-easy на хосте, не внутри контейнера. Снесёте контейнер — настройки останутся. Захотите обновить образ: sudo docker pull ghcr.io/wg-easy/wg-easy, потом sudo docker rm -f wg-easy и заново запустите команду из Шага 3.
Часто задаваемые вопросы
Чем wg-easy лучше ручной установки WireGuard?Графический интерфейс, QR-коды по клику, добавление и удаление клиентов мышкой, статистика трафика в реальном времени. Ручной вариант даёт те же функции через редактирование конфигов и перезапуск службы. За те же полчаса вы в wg-easy поднимете пять клиентов, а в ручном — один.
Насколько это безопасно?Криптография та же — WireGuard сам по себе. Веб-интерфейс закрыт паролем через bcrypt. Риск — порт 51821 смотрит в интернет. Для серьёзного использования закройте его через iptables и оставьте доступ только со своего IP либо пробрасывайте через SSH-туннель: ssh -L 51821:localhost:51821 root@10.10.10.10, потом localhost:51821 в браузере.
Работает на любом дистрибутиве, где запускается Docker. Инструкция одинакова для Ubuntu 22.04, 24.04, Debian 11, 12 и CentOS Stream. Меняется только менеджер пакетов (apt на dnf) и имя файрвола (ufw или firewalld).
В 90% случаев — из-за пароля. Либо забыли перейти на PASSWORD_HASH (старый PASSWORD в v14 запрещён), либо bash съел знаки доллара из хэша. Лекарство: sudo docker logs wg-easy покажет точную строку ошибки. Вторая по популярности причина — занятый порт 51820, если раньше ставили ручной WireGuard.
На VPS с 1 ГБ ОЗУ и одним виртуальным ядром — 50 одновременных подключений без просадки. WireGuard дико экономичен. Узкое место — не процессор, а канал хостера.
Что делать, если забыл пароль?Генерируете новый bcrypt-хэш, сносите контейнер через docker rm -f wg-easy, запускаете заново с новым PASSWORD_HASH. Конфиги клиентов в ~/.wg-easy останутся живы, переподключаться никому не придётся.
Можно и нужно. Настройте A-запись в DNS (например, vpn.example.ru → IP сервера), подставьте домен в WG_HOST при запуске контейнера. Сверху накрутите reverse proxy через Nginx Proxy Manager или Caddy с Let's Encrypt, чтобы веб-интерфейс работал по HTTPS. На это уходит ещё 20 минут, но появляется зелёный замочек вместо предупреждения о небезопасном соединении.