Backup и восстановление VPN-сервера: автоматизация
Сервер с VPN упал, диск умер, хостер потерял виртуалку при миграции — и выясняется, что конфиги, ключи и список пользователей нигде, кроме этой машины, не лежали. Восстанавливать всё руками — это не про пять минут: заново поднимать CA, перевыпускать сертификаты, вспоминать, какие маршруты и правила firewall были настроены полгода назад. Ниже — рабочая схема автоматического бэкапа для WireGuard и OpenVPN и скрипт, который разворачивает рабочий сервер на чистой машине за несколько минут вместо нескольких часов.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что нужно бэкапить на VPN-сервере
Список короче, чем кажется, но пропуск любого пункта означает ручную работу при восстановлении:
- Ключи и конфиги WireGuard —
/etc/wireguard/*.conf, приватные и публичные ключи, при необходимости — база клиентских конфигов, если она генерируется скриптом (например, wg-easy). - PKI и конфиги OpenVPN —
/etc/openvpn/server.conf, вся директорияeasy-rsaс CA, сертификатами иcrl.pem. Потеря CA — самая болезненная: перевыпустить клиентские сертификаты без него нельзя, только выпустить новые и переустановить всем. Структура PKI — в статье OpenVPN Multi-User: сертификаты через Easy-RSA. - Правила firewall — вывод
iptables-save/nft list ruleset, включая NAT и проброс портов. - Сетевые настройки —
/etc/sysctl.d/*.conf(форвардинг пакетов),/etc/netplan/или/etc/network/interfaces, DNS-конфиг, если правился вручную. - Systemd unit-файлы, если использовались кастомные (например,
openvpn-client@.serviceдля нескольких профилей). - Список пользователей и их привязка к IP — без него сложно понять, какой конфиг кому принадлежит и кого отзывать при увольнении.
- Данные RADIUS/NPS, если используется аутентификация через AD — сама конфигурация не на VPN-сервере, но привязка (shared secret, IP RADIUS) должна быть в бэкапе.
Секреты в этом списке требуют шифрования бэкапа — отдельный пункт ниже, не откладывайте на "потом".
Скрипт автоматического бэкапа
Идея — один скрипт, который собирает всё нужное в архив, шифрует и складывает в надёжное место. Ниже вариант, который работает и для WireGuard, и для OpenVPN одновременно (лишние пути просто пропускаются, если их нет):
#!/usr/bin/env bash
# vpn-backup.sh — бэкап конфигов и ключей VPN-сервера
set -euo pipefail
BACKUP_DIR="/var/backups/vpn"
DATE=$(date +%Y%m%d-%H%M%S)
ARCHIVE_NAME="vpn-backup-${DATE}.tar.gz"
GPG_RECIPIENT="admin@example.com" # публичный ключ для шифрования
mkdir -p "$BACKUP_DIR"
STAGING=$(mktemp -d)
# Собираем то, что реально существует на сервере
for path in \
/etc/wireguard \
/etc/openvpn \
/etc/sysctl.d \
/etc/netplan \
/etc/network/interfaces \
/etc/systemd/system/openvpn-client@.service \
/etc/systemd/system/wg-quick@*.service.d; do
if [ -e "$path" ]; then
mkdir -p "$STAGING$(dirname "$path")"
cp -a "$path" "$STAGING$(dirname "$path")/"
fi
done
# Правила firewall — отдельными файлами, не как runtime-состояние
mkdir -p "$STAGING/firewall"
if command -v iptables-save >/dev/null; then
iptables-save > "$STAGING/firewall/iptables.rules"
fi
if command -v nft >/dev/null; then
nft list ruleset > "$STAGING/firewall/nftables.rules" 2>/dev/null || true
fi
# Метаданные — версии ПО, чтобы восстановление шло на совместимую версию
{
echo "date: $(date -Iseconds)"
echo "hostname: $(hostname)"
wg --version 2>/dev/null || true
openvpn --version 2>/dev/null | head -1 || true
} > "$STAGING/meta.txt"
tar -czf "/tmp/${ARCHIVE_NAME}" -C "$STAGING" .
rm -rf "$STAGING"
# Шифруем архив публичным GPG-ключом (приватный ключ хранится отдельно, не на сервере)
gpg --output "${BACKUP_DIR}/${ARCHIVE_NAME}.gpg" --encrypt --recipient "$GPG_RECIPIENT" "/tmp/${ARCHIVE_NAME}"
rm "/tmp/${ARCHIVE_NAME}"
# Ротация: держим последние 14 бэкапов локально
find "$BACKUP_DIR" -name "vpn-backup-*.tar.gz.gpg" -mtime +14 -delete
echo "Бэкап готов: ${BACKUP_DIR}/${ARCHIVE_NAME}.gpg"
Права на скрипт и директорию — только root: chmod 700 /usr/local/bin/vpn-backup.sh, chmod 700 /var/backups/vpn. Не храните незашифрованные приватные ключи в бэкапе дольше, чем нужно для создания архива — скрипт выше шифрует и сразу удаляет промежуточный .tar.gz.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверХранение: локально мало, нужна ещё одна копия вне сервера
Бэкап на том же диске, что и оригинал, — не бэкап: если сервер потерян физически (диск, весь ДЦ, аккаунт хостера заблокирован), локальная копия пропадает вместе с ним. Практичная схема — три уровня:
| Уровень | Где | Зачем |
|---|---|---|
| Локально | /var/backups/vpn на самом сервере | Быстрый откат после случайной правки конфига |
| Другой сервер | Резервный VPN-сервер или отдельная машина в другой локации | Переживает падение основного хостинга |
| Облако/объектное хранилище | S3-совместимое хранилище (Backblaze B2, Wasabi, DigitalOcean Spaces) | Переживает потерю обоих серверов одновременно |
Для отправки на удалённое хранилище проще всего rclone — настраивается один раз, дальше просто вызов из скрипта бэкапа:
# Установка и настройка (один раз)
curl https://rclone.org/install.sh | sudo bash
rclone config # интерактивно: тип s3, endpoint, ключи доступа
# Добавить в конец vpn-backup.sh, после шифрования архива
rclone copy "${BACKUP_DIR}/${ARCHIVE_NAME}.gpg" remote:vpn-backups/ --quiet
Альтернатива без S3 — обычный rsync на второй сервер, если он уже есть (например, тот же сервер, что используется как резервный для автопереключения при падении основного):
rsync -avz "${BACKUP_DIR}/${ARCHIVE_NAME}.gpg" backup-user@203.0.113.20:/var/backups/vpn-remote/
Держите приватный GPG-ключ для расшифровки не на VPN-сервере — иначе при компрометации сервера злоумышленник получает доступ и к бэкапам, и к ключу их расшифровки одним пакетом.
Автоматизация по расписанию: cron или systemd timer
Ручной запуск бэкапа рано или поздно забывается. Через systemd timer расписание надёжнее cron — есть логирование через journalctl и явный контроль пропущенных запусков:
# /etc/systemd/system/vpn-backup.service
[Unit]
Description=VPN config and keys backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/vpn-backup.sh
# /etc/systemd/system/vpn-backup.timer
[Unit]
Description=Daily VPN backup
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=600
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now vpn-backup.timer
systemctl list-timers vpn-backup.timer # проверить, когда следующий запуск
Persistent=true гарантирует, что пропущенный из-за перезагрузки запуск выполнится сразу после старта системы. Если предпочитаете cron: 0 3 * * * /usr/local/bin/vpn-backup.sh >> /var/log/vpn-backup.log 2>&1 в crontab -e для root — работает так же, просто без журналирования systemd.
Частота зависит от того, как часто меняются конфиги: раз в сутки хватает для стабильного списка пользователей, а при частых изменениях (текучка в команде) добавьте отдельный триггер бэкапа сразу после выпуска или отзыва сертификата, а не только по расписанию.
Быстрое восстановление на новом сервере
Наличие бэкапа не спасает, если процесс восстановления никогда не проверялся и существует только в виде "ну, наверное, распакуем архив". Скрипт разворачивания должен приводить чистый сервер к рабочему состоянию без импровизации:
#!/usr/bin/env bash
# vpn-restore.sh — восстановление конфигов VPN на новом сервере
set -euo pipefail
ARCHIVE="$1" # путь к скачанному .tar.gz.gpg
if [ -z "$ARCHIVE" ]; then
echo "Использование: $0 /путь/к/vpn-backup-XXXX.tar.gz.gpg"
exit 1
fi
# Расшифровка (требует приватный GPG-ключ, импортированный на этой машине)
gpg --output /tmp/vpn-restore.tar.gz --decrypt "$ARCHIVE"
STAGING=$(mktemp -d)
tar -xzf /tmp/vpn-restore.tar.gz -C "$STAGING"
rm /tmp/vpn-restore.tar.gz
# Ставим сначала пакеты — конфиги без бинарников бесполезны
apt-get update
apt-get install -y wireguard openvpn iptables
# Раскладываем конфиги обратно по местам
[ -d "$STAGING/etc/wireguard" ] && cp -a "$STAGING/etc/wireguard/." /etc/wireguard/
[ -d "$STAGING/etc/openvpn" ] && cp -a "$STAGING/etc/openvpn/." /etc/openvpn/
[ -d "$STAGING/etc/sysctl.d" ] && cp -a "$STAGING/etc/sysctl.d/." /etc/sysctl.d/
# Права на приватные ключи — узкие сразу после восстановления
chmod -R 600 /etc/wireguard/*.conf 2>/dev/null || true
chmod -R 600 /etc/openvpn/easy-rsa/pki/private/* 2>/dev/null || true
# Восстанавливаем firewall
[ -f "$STAGING/firewall/iptables.rules" ] && iptables-restore < "$STAGING/firewall/iptables.rules"
[ -f "$STAGING/firewall/nftables.rules" ] && nft -f "$STAGING/firewall/nftables.rules"
sysctl --system
# Запуск сервисов
[ -d /etc/wireguard ] && for conf in /etc/wireguard/*.conf; do
[ -f "$conf" ] && systemctl enable --now "wg-quick@$(basename "$conf" .conf)"
done
[ -f /etc/openvpn/server.conf ] && systemctl enable --now openvpn@server
rm -rf "$STAGING"
echo "Восстановление завершено. Проверьте: wg show / systemctl status openvpn@server"
Важные оговорки:
- IP нового сервера почти всегда другой — клиентские конфиги с endpoint по IP требуют правки этого поля (или используйте доменное имя с обновлённой A-записью, как в схеме резервного сервера с автопереключением).
- Версия ПО может отличаться — синтаксис конфигов WireGuard/OpenVPN между версиями обычно совместим, но сверьтесь с
meta.txtиз архива перед тем, как считать восстановление законченным. - Публичный ключ WireGuard завязан на приватный — восстановив приватный ключ, вы автоматически получаете тот же публичный, и клиентам нужно менять только IP/домен в
Endpoint, не сам ключ. - DNS и маршрутизация вне конфигов VPN — если сервер сам раздаёт DNS клиентам, это тоже часть минимального восстановления, а не мелочь на потом.
Если вы переезжаете на нового хостера с нуля и заодно пересматриваете топологию — общий план такого переезда разобран в статье Как составить план миграции на новый сервер.
Тестирование восстановления и типичные ошибки
Бэкап, который ни разу не разворачивался на чистой машине, — это гипотеза, а не рабочий план. Проверяйте цикл целиком не реже раза в квартал: поднимите временную VM у любого хостера с почасовой оплатой, скачайте последний бэкап, прогоните vpn-restore.sh, подключитесь тестовым клиентом и убедитесь, что трафик реально идёт через туннель, а не просто интерфейс поднялся. Такой прогон вскрывает то, что не видно на бумаге: забытую зависимость, файл, который скрипт бэкапа не подхватил, права доступа, разошедшиеся после cp -a.
Частые ошибки, которые всплывают именно на этом шаге:
- Бэкапится только
wg0.conf, но не сами ключевые файлы, если они лежат отдельно (например, в/etc/wireguard/keys/) — восстановленный конфиг ссылается на несуществующие файлы. - CRL (список отозванных сертификатов) не входит в бэкап — после восстановления ранее отозванные сертификаты снова становятся рабочими, пока CRL не пересоздан вручную.
- Скрипт бэкапа запускается не от root и молча пропускает файлы с правами
600— бэкап "выполняется успешно", но реально сохраняет не всё. Проверяйте вывод и размер архива, а не только код возврата. - Тестовое восстановление проверяют на той же версии ОС, что и прод, но никогда — на следующей мажорной, хотя именно туда рано или поздно придётся мигрировать.
- Приватный ключ для расшифровки теряется вместе с уходом администратора из команды — держите его в общем защищённом хранилище, а не только на личной машине одного человека.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Нужно ли бэкапить весь сервер целиком, а не только конфиги?
Обычно достаточно конфигов и ключей — ОС и пакеты переустанавливаются за пару команд. Полный снапшот диска избыточен по объёму и медленнее в восстановлении, но оправдан при сложной кастомной настройке, которую тяжело описать скриптом.
Как часто нужен бэкап, если конфиги почти не меняются?
Не реже раза в неделю даже при редких правках — цена лишнего запуска минимальна, а цена пропущенного изменения (например, только что добавленного пользователя) может быть в разы дороже.
Что если потерял приватный GPG-ключ?
Расшифровать архив без него невозможно — это суть шифрования. Поэтому ключ хранится отдельно от сервера и дублируется в защищённом месте, доступном хотя бы двум людям в команде.
Можно ли объединить бэкап с ротацией ключей клиентов?
Да — скрипт, который перевыпускает сертификаты по расписанию, может вызывать vpn-backup.sh сразу после перевыпуска, чтобы бэкап всегда отражал актуальный набор ключей.
Стоит ли включать двухфакторную аутентификацию в тот же бэкап?
Да, конфиги 2FA-интеграции (привязка к RADIUS) стоит бэкапить вместе с остальным — иначе после восстановления сервер поднимется без второго фактора. Подробности — в статье Двухфакторная аутентификация для VPN.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →