RE:NODE

Эксплуатация11 мин чтения

Backup игрового сервера в S3: внешние копии мира по расписанию

Каждую ночь копируйте миры и сохранения в хранилище S3 через rclone или restic: что копировать, как получить чистое сохранение, хранить историю, чистить старое и восстанавливать.

0 прочтений

Надёжный способ каждую ночь отправлять мир игрового сервера в хранилище S3 - небольшое задание на машине, которую вы контролируете: оно забирает мир по SFTP и загружает его в бакет через несколько минут после того, как серверу велели сохраниться. rclone делает обе половины одной командой, потому что умеет работать и с SFTP, и с S3 напрямую; restic добавляет шифрование и дедупликацию, если вам нужна история за несколько месяцев в небольшом объёме. Собственные backup панели остаются первой линией защиты - их быстро делать и можно восстановить одной кнопкой, - а копия в S3 переживает то, чего не переживают backup панели: удалённый сервер, ошибку, поверх которой уже успел пройти backup, или аккаунт, к которому у вас больше нет доступа. В этой статье мы соберём такое задание целиком: что копировать, как получить чистую копию, как хранить историю без версионирования, как удалять старое и как убедиться, что из копии действительно можно восстановиться.

Зачем вторая копия и от чего она защищает#

Backup панели и копия в S3 ломаются по-разному - именно поэтому стоит иметь обе.

РискBackup панелиКопия в хранилище S3Копия дома
Гриферы, плохой плагин, повреждённое сохранениеДаДаДа
Ротация слотов вытеснила хорошую копиюТолько если заблокированДа, при более долгом храненииДа
Сервер удалён (backup удаляются вместе с ним)НетДаДа
Потеря всей площадкиЗависитНет, если в той же площадкеДа
Вы потеряли доступ к аккаунту хостингаНетТолько если это отдельный аккаунтДа

На RE:NODE в тарифы игровых серверов входят слоты backup, которые хранятся не на той машине, которую защищают, могут быть заблокированы от ротации и восстанавливаются одной кнопкой, - но при удалении сервера удаляются и его backup, включая заблокированные. Копия в бакете это переживёт. Но будьте честны насчёт другой строки: хранилище S3 у RE:NODE держит одну копию ваших данных на NVMe в одной площадке, в Германии, там же, где и игровые серверы. Оно защищает от удаления и ошибок, но не от потери площадки. Для мира, потеря которого разбила бы вам сердце, важен и третий столбец, и то же задание rclone может положить копию на ваш собственный диск. Логика 3-2-1 подробно разобрана в статье backup, которые действительно восстанавливаются, а в статье размер хранилища S3 и правило 3-2-1 она применена к бакетам.

Как устроена схема#

Игровой сервер в панели - это контейнер, в котором работает игра, а не машина общего назначения: у вас есть консоль, файловый менеджер, SFTP и планировщик, который запускает консольные команды, backup и действия с питанием, - но не произвольные shell-скрипты. Поэтому задание копирования работает где-то ещё и забирает файлы по SFTP.

команда saveчтение по SFTP в 04:00загрузка в S3по желаниюРасписание панелисохранение в 03:55Задание backuprclone на VDS или ПКИгровой серверфайлы мираБакет S3game-backupsЛокальный дисктретья копия по желанию
Ночное копирование с игрового сервера в бакет

Забирать файлы может всё, что запускается по таймеру: Linux VDS, домашний сервер или Raspberry Pi, либо Windows-ПК, который включён ночью. Ему нужны rclone, данные SFTP игрового сервера и ключи бакета. Ему никогда не нужно запускать игру или хранить файлы между запусками - разве что вы выберете restic, который держит небольшой кэш.

Если игра работает на VDS или на вашей собственной машине, половину с SFTP можно пропустить: задание запускается на той же машине и читает папку мира напрямую.

Что копировать#

Копируйте состояние и конфигурацию; пропускайте всё, что можно скачать заново. Папка мира обычно весит от мегабайт до нескольких гигабайт, а файлы игры вокруг неё часто занимают десятки гигабайт, которые SteamCMD переустановит за минуты.

ИграКопироватьПропустить
Minecraft (Paper)world*/, plugins/, server.properties, списки *.jsoncache/, libraries/, versions/, jar сервера
Valheimworlds_local/ из папки сохранений, три файла списковустановку игры
PalworldPal/Saved/всё остальное
Project ZomboidZomboid/Saves/, Zomboid/db/, Zomboid/Server/установку игры, Zomboid/Logs/
Terrariaфайлы .wld, serverconfig.txt, tshock/бинарники сервера
Factoriosaves/, data/server-settings.json, mods/установку игры

Эти пути меняются, если сервер запущен с собственным каталогом сохранений, поэтому сверьте их со своей строкой запуска. В статье стратегия backup игрового сервера список длиннее, включая игры, где очевидная папка - это ещё не всё; классический пример - база игроков в Project Zomboid.

Запишите этот выбор в виде файла фильтров rclone. Заодно он служит документацией того, что на самом деле лежит в вашем backup:

minecraft.filter
+ /world/**+ /world_nether/**+ /world_the_end/**+ /plugins/**+ /server.properties+ /*.json- /plugins/*.jar.old- /plugins/**/logs/**- *

Правила читаются сверху вниз, срабатывает первое совпадение, а последнее - * исключает всё, что не перечислено. Jar-файлы плагинов попадают в копию намеренно: мир, восстановленный рядом с более новой версией плагина, - частый способ его сломать, а тот самый jar, на котором вы работали, позже может оказаться недоступен для скачивания.

Настройка remote в rclone#

Установите rclone на машину, которая забирает файлы (sudo apt install rclone часто ставит старую версию; скрипт установки или готовый бинарник с rclone.org дают актуальную), затем опишите два remote - один для SFTP игрового сервера, другой для хранилища.

~/.config/rclone/rclone.conf
[mc]type = sftphost = sftp.example-node.netport = 2022user = yourname.a1b2c3d4pass = <output of: rclone obscure 'your-sftp-password'>[store]type = s3provider = Otheraccess_key_id = AKIA...secret_access_key = ...endpoint = https://s3.example.comregion = us-east-1force_path_style = true

Хост, порт и имя пользователя SFTP берите ровно такими, какими их показывает панель для этого сервера: в панелях на базе Pterodactyl к имени пользователя добавлен суффикс сервера, а порт обычно не 22. В поле pass должен быть вывод rclone obscure, а не пароль открытым текстом. rclone obscure - это обратимое кодирование, а не шифрование, поэтому защитите сам файл через chmod 600. Откуда берутся учётные данные, объясняет статья SFTP и файловый менеджер.

Для remote хранилища provider = Other - это универсальная настройка для S3-совместимых сервисов, а force_path_style = true и так используется в rclone по умолчанию. Endpoint - это HTTPS-имя хоста, которое вы направили на proxy-слот тарифа хранилища; голый порт с обычным HTTP тоже работает, но тогда ваш мир передаётся без шифрования. Прежде всего проверьте оба remote:

bash
$ rclone lsd mc:/$ rclone ls mc:/ --filter-from minecraft.filter | head$ rclone lsd store:$ rclone mkdir store:game-backups

Главная здесь вторая строка: она показывает ровно те файлы, которые заберёт backup. Если папки мира в этом списке нет, всё дальнейшее не имеет значения. Remote, флаги и ограничение скорости подробнее разобраны в статье rclone с хранилищем S3.

Чистая копия: сначала сохранение#

Большинство игр держат мир в памяти и записывают его на диск по таймеру. Если копировать файлы, пока игра на середине записи, получится backup, который выглядит полным, но не загружается. Решение - велеть игре сохраниться незадолго до начала копирования с помощью планировщика панели.

На RE:NODE вкладка Schedules запускает по cron-выражению упорядоченные задачи с задержками. Для Minecraft ночное расписание на 03:55 будет таким:

Schedule: pre-backup save, 55 3 * * *
Task 1  command  save-offTask 2  command  save-all flush       (delay 5 s)Task 3  command  save-on              (delay 600 s)

save-off отключает автосохранения, чтобы игра не начала переписывать файлы регионов посреди копирования, save-all flush записывает всё на диск и дожидается окончания записи, а save-on через десять минут снова включает автосохранение - уже после того, как задание в 04:00 закончит работу. Для мира, который копируется за минуту, десяти минут с запасом хватит; для мира в несколько гигабайт засеките время одного прогона и увеличьте промежуток. В других играх своя команда сохранения - save в Project Zomboid и Terraria, saveworld в 7 Days to Die, /server-save в Factorio, - а у некоторых, например Valheim и DayZ, нет серверной консольной команды, и их безопаснее всего копировать из backup панели по расписанию или после чистого рестарта. Планировщику посвящены статьи полезные задачи по расписанию и cron-выражения простыми словами.

Часы машины, которая забирает файлы, и расписание панели должны сходиться в часовом поясе. Прежде чем полагаться на промежуток в пять минут, запишите оба времени в UTC или проверьте, что подразумевает каждое из них.

История без версионирования#

Одиночный rclone sync держит бакет идентичным серверу - а значит, если в 21:00 мир разнесли гриферы, синхронизация в 04:00 добросовестно запишет испорченный мир поверх хорошего. Backup нужна история. Без версионирования бакета получить её можно тремя способами.

Полные копии по датам. Каждая ночь ложится в свой префикс. Просто, восстанавливать очевидно, а стоит это полный размер мира за каждый день.

bash
$ rclone copy mc:/ store:game-backups/mc/daily/$(date -u +%F) \    --filter-from minecraft.filter --transfers 4 --log-file /var/log/mc-backup.log

Sync с каталогом для старых версий. В бакете лежит одна текущая копия, а каждый файл, который sync перезаписал бы или удалил, сначала переносится в папку с датой. История стоит лишь столько, сколько весят изменившиеся файлы, - для мира Minecraft это файлы регионов, где игроки действительно побывали.

bash
$ rclone sync mc:/ store:game-backups/mc/current \    --backup-dir store:game-backups/mc/changed/$(date -u +%F) \    --filter-from minecraft.filter

Чтобы восстановить прошлый день при такой схеме, нужно взять current и накладывать на него папки с датами, от самой новой до нужного дня, - это возможно, но неудобно, когда горит.

restic. Заберите файлы rclone в локальную промежуточную папку, а затем пусть restic сделает снимок в бакет. restic дедуплицирует данные на уровне фрагментов и всё шифрует, поэтому тридцать ежедневных снимков мира, который понемногу меняется каждый день, стоят ненамного больше одного. Восстановление любого снимка - одна команда. Это лучший вариант, если на машине, которая забирает файлы, найдётся немного локального диска.

bash
$ rclone sync mc:/ /srv/stage/mc --filter-from minecraft.filter$ restic -r s3:https://s3.example.com/game-backups/restic backup /srv/stage/mc --tag mc

restic читает AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY и RESTIC_PASSWORD (или RESTIC_PASSWORD_FILE) из окружения. Потеряете пароль restic - репозиторий станет нечитаемым, и так задумано. Инициализация репозитория и всё остальное описаны в статье backup с restic в S3.

Срок хранения и очистка#

Хранилище без правил жизненного цикла само ничего не удаляет, поэтому срок хранения - часть вашего скрипта.

Очевидная команда здесь неверна. rclone delete --min-age 14d фильтрует по времени изменения каждого объекта, а rclone при загрузке сохраняет время изменения исходного файла (оно записывается в метаданные объекта). Конфиг, который никто не трогал месяц, попадает в сегодняшнюю папку с датой уже «месячной давности», и --min-age 14d удаляет его сразу после окончания задания. Ваш самый свежий backup незаметно теряет все файлы, которые давно не менялись, - именно те, проверить которые вам не придёт в голову.

Вместо этого удаляйте целые префиксы с датами по их имени. Имя папки - это дата, когда сделана копия, а именно это вы и имеете в виду под возрастом:

bash
CUTOFF=$(date -u -d '14 days ago' +%F)rclone lsf --dirs-only store:game-backups/mc/daily | while read -r d; do  d=${d%/}  if [[ "$d" < "$CUTOFF" ]]; then    rclone purge "store:game-backups/mc/daily/$d"  fidone

Даты в формате ISO (2026-10-08) сортируются одинаково и как текст, и как время, поэтому простое сравнение строк работает. date -d - это GNU date, стандартный в Linux; в macOS используйте date -u -v-14d +%F. То же касается схемы с --backup-dir: удаляйте папки changed/ с датами по имени, никогда через --min-age. В restic срок хранения задаётся политикой:

bash
$ restic -r s3:https://s3.example.com/game-backups/restic forget \    --tag mc --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Разумная политика для большинства игровых серверов - неделя ежедневных копий, месяц еженедельных и копия перед каждым крупным обновлением, которая хранится бессрочно. Отсюда и считайте размер бакета: мир Minecraft на 2 GB с полными копиями по датам за четырнадцать дней требует около 28 GB; та же история в restic обычно занимает лишь в несколько раз больше одного мира. С той частью расчёта, что касается мира, поможет статья сколько места нужно игровому серверу.

Запуск по расписанию#

Соберите всё в один скрипт, чтобы расписание уместилось в одну строку:

/usr/local/bin/mc-backup.sh
#!/usr/bin/env bashset -euo pipefailDAY=$(date -u +%F)CUTOFF=$(date -u -d '14 days ago' +%F)rclone copy mc:/ "store:game-backups/mc/daily/$DAY" \  --filter-from /etc/rclone/minecraft.filter --log-file /var/log/mc-backup.logrclone lsf --dirs-only store:game-backups/mc/daily | while read -r d; do  d=${d%/}  if [[ "$d" < "$CUTOFF" ]]; then rclone purge "store:game-backups/mc/daily/$d"; fidonecurl -fsS -m 10 https://hc.example.com/ping/mc-backup > /dev/null || true

Затем crontab -e и 0 4 * * * /usr/local/bin/mc-backup.sh. set -euo pipefail останавливает скрипт на первой же ошибке, так что неудачное копирование никогда не перейдёт к удалению старых backup. Последняя строка отправляет сигнал монитору типа dead man's switch (Healthchecks.io и похожие сервисы), который предупредит вас, если сигнал не пришёл, - единственный надёжный способ заметить задание backup, которое молча перестало работать. На Windows-машине Планировщик заданий запускает те же команды rclone из файла .bat; rclone ведёт себя там точно так же.

Восстановление из бакета#

Backup, из которого никто не восстанавливался, - это гипотеза. Восстановитесь один раз до того, как это понадобится:

  1. Выберите день и скачайте его на свой ПК: rclone copy store:game-backups/mc/daily/2026-10-07 ./restore-test.
  2. Откройте мир в локальной копии игры или на тестовом сервере и пройдитесь по главной базе.
  3. Для настоящего восстановления остановите игровой сервер, отодвиньте повреждённую папку мира в сторону, загрузите восстановленную через rclone или файловый менеджер и запустите сервер.

Отправить восстановленные файлы прямо обратно по SFTP можно той же командой в обратную сторону - rclone copy store:game-backups/mc/daily/2026-10-07 mc:/, - но только при остановленном сервере, иначе следующее сохранение игры перезапишет то, что вы только что вернули. Статья проверка восстановления до того, как оно понадобится превращает это в ежеквартальную привычку.

FAQ#

Может ли игровой сервер сам отправлять данные в S3?

Не игровой сервер в панели: его планировщик запускает консольные команды, backup и действия с питанием, а не shell-скрипты. Для некоторых игр есть плагины, которые загружают backup в S3, и они работают, если вы доверяете плагину. В остальных случаях забирайте файлы снаружи через rclone, как описано выше.

Как часто копировать мир на внешнее хранилище?

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

Разве backup панели недостаточно?

Его хватает на большинство ошибок, и из него быстрее всего восстанавливаться. Но он не переживает удаление сервера, а слоты ротируются. Копия в S3 нужна для тех случаев, которые backup панели покрыть не может.

Нужно ли шифровать backup игровых миров?

restic по умолчанию шифрует всё. В rclone remote хранилища можно обернуть в remote типа crypt. Для игрового мира главная причина в том, что в конфигах часто лежат пароли RCON и баз данных.

Замедлит ли копирование мира работу сервера?

Чтение нескольких сотен мегабайт по SFTP - лёгкая нагрузка, но большой мир на загруженном сервере может вызвать кратковременные подлагивания. Запускайте задание в самый тихий час и используйте --bwlimit в rclone, если игроки это замечают.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000