No description
  • HTML 42.4%
  • Python 35.7%
  • Shell 21.9%
Find a file
2026-11-13 22:05:50 +05:00
nginx feat: automate VPN mask deployment and document setup 2026-11-13 00:26:46 +05:00
scripts feat: automate VPN mask deployment and document setup 2026-11-13 00:26:46 +05:00
site first commit 2026-03-17 20:46:43 +05:00
tests feat: automate VPN mask deployment and document setup 2026-11-13 00:26:46 +05:00
.gitignore feat: automate VPN mask deployment and document setup 2026-11-13 00:26:46 +05:00
docker-compose.yml feat: automate VPN mask deployment and document setup 2026-11-13 00:26:46 +05:00
README.md docs: document public Git installation and archive migration 2026-11-13 22:05:50 +05:00
setup.sh feat: automate VPN mask deployment and document setup 2026-11-13 00:26:46 +05:00

VPN Mask — сайт-заглушка для Xray/Reality

Статический сайт NimbusVault, nginx и сертификаты Let's Encrypt с автоматическим обновлением. setup.sh получает сертификат, создаёт конфиг nginx и запускает сайт вместе с Certbot. На сервер нужно клонировать весь репозиторий, а не скачивать один скрипт.

Выбор режима

Запуск HTTPS nginx Кто принимает публичный HTTPS на 443
По умолчанию 127.0.0.1:8443 Отдельно настроенный Xray/Reality
С --standalone Публичный :443 Сам nginx; Xray не требуется

Для существующей VPN-ноды используйте режим по умолчанию. REALITY передаёт подключения, не прошедшие его аутентификацию, в target. В актуальных версиях Xray target и прежнее имя dest — синонимы. Документация Xray.

В обоих режимах nginx слушает TCP 80 для ACME-проверки доменов и редиректа HTTP → HTTPS. В режиме Reality скрипт не занимает 443 и не настраивает Xray.

Требования

  • Linux и доступ root. Команды на сервере ниже выполняются от root: войдите через ssh root@... либо сначала выполните sudo -i.
  • На Ubuntu/Debian установщик добавляет недостающие утилиты и устанавливает Docker из официального apt-репозитория, если нет существующей установки Docker/container runtime. Для новой установки Docker нужен работающий systemd. Уже установленный Docker не заменяется и не перезапускается скриптом; несовместимость при установке Compose приводит к остановке с пояснением.
  • На других Linux заранее нужны Docker Engine, плагин docker compose, curl, openssl, flock и ss. Docker должен работать на этом же сервере; удалённый Docker context или DOCKER_HOST для этой установки не подходит. Если Docker уже установлен, но daemon остановлен, запустите его перед setup. Установка Docker, установка Compose plugin.
  • A-запись каждого домена должна указывать на публичный IPv4 сервера. Если опубликована AAAA, она также должна вести на этот сервер с рабочим IPv6. Используйте прямые DNS-записи без CDN-прокси.
  • Откройте TCP 80 и 443 в firewall сервера и панели хостинга. Скрипт правила firewall не меняет. В режиме Reality не открывайте 8443 наружу: nginx слушает этот порт только на localhost.
  • Порты 80 и выбранный порт nginx (8443 или 443) должны быть свободны от чужих сервисов. Контейнеры этой установки скрипт останавливает сам на время настройки.

Автоустановка зависимостей, загрузка образов и выпуск сертификата требуют доступа сервера в Интернет. Домены передаются без https://, портов и путей; IDN — в punycode. Wildcard-домены и IP-адреса вместо доменов не поддерживаются.

Новая установка

Подключитесь к новому серверу:

ssh root@YOUR_SERVER_IP

Для клонирования нужны git и корневые сертификаты. На Ubuntu/Debian установите их от root:

apt-get update
apt-get install -y git ca-certificates

Клонируйте открытый репозиторий по HTTPS и запустите установку от root. Логин, пароль и SSH-ключ для клонирования не требуются:

git clone https://git.zeffya.com/zeffya/vpn-mask.git /opt/vpn-mask
cd /opt/vpn-mask
bash setup.sh node.example.com admin@example.com

Для существующей установки используйте раздел обновления проекта ниже. Не переносите приватные ключи и конфиг другой ноды вместе с исходниками.

Замените node.example.com и admin@example.com своими значениями. Для самостоятельного сайта без Xray вместо последней команды используйте:

bash setup.sh --standalone node.example.com admin@example.com

Полный синтаксис:

bash setup.sh [--standalone] DOMAIN EMAIL [EXTRA_DOMAIN ...]

Скрипт загружает образы из Compose до остановки своего сайта, проверяет свободные порты, запускает временный HTTP-сервер и запрашивает сертификат через ACME webroot. Затем создаёт nginx/runtime/default.conf из шаблона, выполняет nginx -t, запускает nginx + Certbot и проверяет локальный HTTPS для каждого переданного домена с проверкой имени и доверия к сертификату, без -k.

При ошибке скрипт удаляет временный контейнер и файлы проверки, сохраняет данные Certbot и пытается восстановить прежний конфиг и ранее работавшие сервисы. Если восстановление не удалось, это отражается в выводе; проверьте логи.

Настройка Xray/Reality

Для режима по умолчанию настройте Xray отдельно:

Параметр Значение
Порт Xray 443
target (или dest) 127.0.0.1:8443
serverNames ["node.example.com"] либо список указанных при установке доменов
xver 0

Если Xray запущен в контейнере, ему нужен network_mode: host, чтобы его localhost совпадал с localhost nginx. Скрипт не устанавливает и не меняет Xray/Remnawave. Без настроенного Xray сайт в этом режиме доступен локально на 8443, но ещё не опубликован на 443.

Успех setup подтверждает локальную проверку nginx. Доступность публичного HTTPS и работу VPN проверьте отдельно с другого компьютера и VPN-клиентом.

Повторный запуск и дополнительные домены

Для повторной настройки используйте ту же команду. Сертификат с тем же набором имён переиспользуется, если обновление ещё не требуется; принудительного перевыпуска при каждом запуске нет. Когда сертификат пора обновлять или меняется набор доменов, Certbot может выпустить новый сертификат.

Чтобы добавить имя, сначала настройте его DNS, затем передайте прежний основной домен и полный список дополнительных имён:

bash setup.sh node.example.com admin@example.com cdn.example.com

В standalone каждый раз указывайте --standalone. Все переданные имена попадут в сертификат и server_name. Отдельно править nginx или запускать интерактивный Certbot для добавления домена не требуется.

Каждый запуск setup загружает образы, указанные в Compose, и пересоздаёт сервисы. Сейчас используются nginx:stable-alpine и certbot/certbot:latest, поэтому повторный запуск может также обновить контейнерные образы. На время настройки возможен перерыв в работе сайта.

Одна копия управляет одним сайтом. Фиксированные имена контейнеров nginx-mask и certbot должны принадлежать этой копии проекта; при совпадении с чужой установкой скрипт остановится. Для другой ноды используйте копию на другом сервере. Смена основного домена сохраняет старые данные Certbot; renew обрабатывает сохранённые сертификаты, а не только текущий домен nginx.

Обновление проекта

Обновляйте существующую установку в том же каталоге. Не удаляйте её certbot/ и nginx/runtime/: там находятся сертификаты и конфиг этой ноды. Перед обновлением исходников сохраните копию рабочего конфига.

Для старой версии, где контейнер напрямую использует nginx/default.conf, из каталога установки выполните:

mkdir -p nginx/runtime
docker cp nginx-mask:/etc/nginx/conf.d/default.conf nginx/runtime/default.conf

Копирование должно завершиться успешно до замены исходников: в новой версии nginx/default.conf — шаблон. Скрипт умеет читать старый конфиг из работающего контейнера, но если исходный bind-mounted файл уже заменён шаблоном, рабочую резервную копию он из него получить не сможет и остановится.

Для установки, уже использующей nginx/runtime/default.conf, сохраните его дополнительную копию перед обновлением:

cp -p nginx/runtime/default.conf nginx/runtime/default.conf.backup

Для установки через git clone обновите исходники и повторите setup со своим режимом и доменами:

cd /opt/vpn-mask
git pull --ff-only
bash setup.sh node.example.com admin@example.com

Если установка расположена не в /opt/vpn-mask, подставьте её существующий путь. Для standalone добавьте --standalone. Если шаблон уже перезаписал старый конфиг, восстановите сохранённый рабочий конфиг в nginx/runtime/default.conf и повторите setup.

После успешного перехода старый cron-файл /etc/cron.d/nginx-ssl-reload, если он был создан по прежней инструкции проекта, больше не нужен: reload выполняется внутри nginx-контейнера. Скрипт сам этот cron-файл не удаляет.

Переход с архива на Git

Существующую установку без .git/ можно перевести на Git в том же каталоге. Сначала сохраните рабочий конфиг по инструкции выше, особенно если контейнер ещё использует nginx/default.conf. Установите git и ca-certificates, как в разделе новой установки. Все команды ниже выполняются на сервере от root. Если проект находится не в /opt/vpn-mask, замените этот путь в командах.

Создайте резервный архив всей установки, включая сертификаты и локальные правки. Архив хранится вне каталога проекта в доступном только root каталоге:

bash <<'BACKUP'
set -e
backup_dir=$(mktemp -d /opt/vpn-mask-backup.XXXXXX)
tar -czf "$backup_dir/vpn-mask.tar.gz" -C /opt/vpn-mask .
printf 'Резервная копия: %s/vpn-mask.tar.gz\n' "$backup_dir"
BACKUP

Продолжайте только после успешного создания архива. Следующие команды привязывают каталог к ветке main и заменяют файлы исходников версиями из репозитория, включая локальные изменения сайта и шаблонов. Каталоги certbot/ и nginx/runtime/ исключены из Git и сохраняются на месте. Рабочий конфиг старой версии должен быть заранее скопирован в nginx/runtime/default.conf.

bash <<'MIGRATE'
set -e
cd /opt/vpn-mask
if [ -e .git ]; then
    echo 'Каталог уже содержит Git. Используйте git pull --ff-only.' >&2
    exit 1
fi
git init
git remote add origin https://git.zeffya.com/zeffya/vpn-mask.git
git fetch origin main
git reset --mixed origin/main
git branch -M main
git branch --set-upstream-to=origin/main main
git restore --source=HEAD --worktree -- .
git status --short --branch
MIGRATE

При ошибке остановитесь и сохраните резервный архив: он содержит исходные файлы и приватные ключи сертификатов. После успешного перехода повторите setup со своими доменами и email; для самостоятельного сайта добавьте --standalone:

cd /opt/vpn-mask
bash setup.sh node.example.com admin@example.com

Дальнейшие обновления выполняются через git pull --ff-only и повторный запуск setup.sh, как описано выше. Если после перехода остались дополнительные файлы старой установки, Git покажет их как неотслеживаемые; проверьте их отдельно.

Обновление сертификатов

Certbot выполняет попытку обновления при старте контейнера, затем ждёт 12 часов между попытками. Nginx проверяет изменение сертификатов каждые 60 секунд и перечитывает их после успешного nginx -t. Отдельный cron не требуется; certbot/flags сохранён для совместимости с прежними deploy hooks.

Обычно ручные действия не нужны. Для ручного обновления, от root из каталога установки, остановите фоновый Certbot на время отдельной команды:

bash <<'RENEW'
set -e
docker compose stop certbot
trap 'docker compose start certbot' EXIT
docker compose run --rm --no-deps --interactive=false --entrypoint certbot certbot renew \
    --webroot -w /var/www/certbot
docker compose exec -T nginx-mask nginx -t
docker compose exec -T nginx-mask nginx -s reload
RENEW

Фоновый контейнер запускается обратно и при ошибке команды. Для теста продления без сохранения нового боевого сертификата добавьте --dry-run к команде renew. --entrypoint certbot нужен, чтобы заменить штатный циклический entrypoint. Семантика docker compose run.

Проверка и диагностика

Команды выполняются от root из каталога установки:

docker compose ps --all
docker compose logs --tail=100 nginx-mask certbot
curl --noproxy '*' -fsS http://127.0.0.1/health
curl --noproxy '*' --resolve node.example.com:8443:127.0.0.1 \
    -fsS https://node.example.com:8443/ -o /dev/null

Подставьте свой домен; в standalone замените 8443 на 443. С другого компьютера проверьте публичный адрес:

curl -fI --connect-timeout 5 --max-time 15 https://node.example.com

Если выпуск сертификата не прошёл, проверьте A/AAAA, доступность TCP 80 и вывод Certbot. При занятом порте остановите или перенастройте его владельца: скрипт не завершает чужие процессы. При ошибке доступа к Docker сначала восстановите работу локального daemon. Публичный HTTPS в режиме Reality требует также работающего Xray с указанным выше target.

Файлы и локальные проверки

  • setup.sh, scripts/install-deps.sh — установка и запуск.
  • docker-compose.yml — nginx и Certbot.
  • nginx/default.conf — общий шаблон; setup его не редактирует.
  • nginx/nginx.conf — общие настройки nginx.
  • nginx/runtime/default.conf — сгенерированный конфиг конкретного сервера.
  • certbot/ — сертификаты, приватные ключи и служебные данные.
  • site/ — HTML сайта-заглушки; настоящего облачного хранилища и регистрации нет.
  • tests/ — изолированные регрессионные проверки установщиков.

nginx/runtime/ и certbot/ исключены из Git. Временные данные тестов также не коммитятся. Для локальной проверки нужны Bash и Python 3.9+; тесты используют стандартную библиотеку Python и подменяют Docker, сеть и системный установщик:

bash -n setup.sh
bash -n scripts/install-deps.sh
python3 -m unittest discover -s tests -v

При установленном плагине Docker Compose дополнительно проверьте структуру:

docker compose config --quiet

Эти проверки не запускают реальные сервисы и не подтверждают выпуск сертификата, работу nginx на Linux-сервере, публичную доступность или VPN-подключение.