Rclone давно стал де-факто стандартом для работы с Object Storage у админов и devops. Он понимает практически все S3‑совместимые хранилища, умеет шифрование, проверку целостности, версионирование и при этом спокойно запускается из cron без лишней магии. В этой статье разберем практическую связку rclone + cron для регулярных бэкапов на VDS: файлов, MySQL и PostgreSQL в S3‑совместимый Object Storage.
Фокус будет на:
- конфигурации rclone для S3‑совместимого Object Storage;
- организации структуры backup‑ов (daily/weekly/monthly);
- бэкапах баз данных MySQL и Postgres с консистентностью;
- настройке cron, логов и уведомлений;
- проверке целостности и периодических тестовых восстановлений.
Зачем именно rclone для бэкапов в Object Storage
Для выгрузки бэкапов в S3‑совместимое хранилище выбор обычно между aws-cli, s5cmd, специализированными бэкап‑утилитами и rclone. Rclone выигрывает, когда нужно:
- работать не только с S3, но и с другими бекендами (WebDAV, SFTP, Google Drive и т.п.);
- делать sync с удалением старых файлов;
- использовать client‑side шифрование (модуль
crypt); - получать подробный лог и удобные проверки целостности;
- легко запускать всё это из cron без сложных зависимостей.
Важно: rclone сам по себе не делает дампы баз данных. Его задача — безопасно и предсказуемо доставить уже подготовленные архивы и дампы в Object Storage и управлять их ротацией.
Типичный pipeline на вашем VDS выглядит так:
- Локальный скрипт собирает бэкап: архивирует файлы, делает дампы MySQL/PostgreSQL, кладет в каталог
/var/backups/<date>. - rclone синхронизирует этот каталог в бакет Object Storage (условно
backup-s3:my-backups/...). - Отдельное задание cron периодически удаляет или архивирует старые бэкапы.
Установка rclone на сервер (VDS)
На большинстве Linux‑дистрибутивов rclone есть в репозиториях, но версии там иногда сильно отстают. Для свежих фич S3 (multipart, параметры performance, checksum) лучше ставить актуальный релиз, но и пакетной версии обычно достаточно для старта.
Установка из репозитория дистрибутива
Для быстрого старта чаще всего хватает стандартных пакетов:
# Debian/Ubuntu
apt-get update
apt-get install -y rclone
# CentOS/Rocky/Alma
yum install -y epel-release
yum install -y rclone
Проверьте версию:
rclone version
Если нужна самая свежая (например, для тонкой настройки multipart под конкретного S3‑провайдера), можно использовать официальный инсталлер или скачать бинарник и положить его в /usr/local/bin/rclone. В продовом окружении фиксируйте версию и обновляйтесь осознанно.
Базовая конфигурация rclone под S3‑совместимый Object Storage
Rclone хранит конфигурацию по умолчанию в файле ~/.config/rclone/rclone.conf для пользователя, под которым вы его запускаете. Если вы планируете запуск из root через cron, конфиг должен быть в /root/.config/rclone/rclone.conf или путь нужно указать явно через параметр --config.
Создание remote для S3
Запускаем интерактивный конфиг:
rclone config
Минимальный набор шагов:
- New remote → задайте имя, например
backup-s3. - Тип хранилища:
s3. - Провайдер:
Other(для любого S3‑совместимого Object Storage). - Введите
access_key_idиsecret_access_key. - Укажите
endpointвашего S3 (смотрите документацию провайдера). - Выберите или оставьте регион (часто можно указать условный, если провайдер его игнорирует).
- Остальные вопросы пока можно оставить по умолчанию.
Проверяем доступ:
rclone lsd backup-s3:
Если видите список бакетов или пустой вывод без ошибок — всё ок. Ошибки авторизации или TLS лучше отловить и починить на этом шаге, до интеграции с cron.
Пример конфигурации rclone для S3
Фрагмент rclone.conf (для понимания, как это выглядит внутри):
[backup-s3]
type = s3
provider = Other
access_key_id = YOUR_ACCESS_KEY
secret_access_key = YOUR_SECRET_KEY
endpoint = s3.example.local
acl = private
force_path_style = true
location_constraint = us-east-1
Параметр force_path_style часто нужен для S3‑совместимых сервисов, которые не используют схему адресов вида bucket.s3.example.local. В документации вашего Object Storage обычно есть готовый пример конфига для rclone — свериться с ним не помешает.
Если вы только планируете инфраструктуру и выбираете, куда пристраивать бэкапы, удобно сразу заложить отдельный бакет под резервные копии рядом с основными сайтами на виртуальном хостинге или VDS.

Структура backup‑ов в Object Storage
Чтобы через полгода не утонуть в хаосе, имеет смысл сразу определиться со структурой хранения. Типовой вариант:
my-backups/
hostname-1/
files/
daily/
weekly/
monthly/
mysql/
daily/
weekly/
postgres/
daily/
hostname-2/
...
Удобно включать в путь:
- имя хоста (
hostnameили FQDN), чтобы хранить бэкапы от разных VDS в одном бакете; - тип данных (
files,mysql,postgresи т.п.); - частоту или класс бэкапа (
daily,weekly,monthly).
Файлы удобно именовать так: YYYY-MM-DD-HHMM-type.tar.zst или с timestamp в секундах. Главное — чтобы по имени легко читать дату и тип, а сортировка по имени совпадала с хронологией.
Бэкап файлов проекта и синхронизация rclone
Начнем с самого простого — бэкап директории с файлами сайта или приложения. Обычно это корень проекта, например /var/www или /srv/app.
Скрипт локального архивирования
Создадим каталог для локальных бэкапов:
mkdir -p /var/backups/files
Пример скрипта /usr/local/sbin/backup-files.sh:
#!/usr/bin/env bash
set -euo pipefail
HOSTNAME_SHORT=$(hostname -s)
BACKUP_DIR=/var/backups/files
DATE=$(date +%Y-%m-%d-%H%M)
SRC_DIR=/var/www
mkdir -p "${BACKUP_DIR}"
ARCHIVE="${BACKUP_DIR}/${HOSTNAME_SHORT}-files-${DATE}.tar.zst"
tar -I 'zstd -19 --long=25' -cf "${ARCHIVE}" "${SRC_DIR}"
find "${BACKUP_DIR}" -type f -mtime +7 -delete
Здесь:
- используется zstd для хорошего баланса скорость/степень сжатия;
- локальные архивы хранятся только 7 дней (Object Storage будет основным долгосрочным хранилищем);
- скрипт падает при любой ошибке (
set -euo pipefail), что удобно для мониторинга.
Синхронизация архивов в S3 через rclone
Отдельный скрипт, который только выгружает готовые архивы, например /usr/local/sbin/backup-files-upload.sh:
#!/usr/bin/env bash
set -euo pipefail
HOSTNAME_SHORT=$(hostname -s)
LOCAL_DIR=/var/backups/files
REMOTE=backup-s3:my-backups/${HOSTNAME_SHORT}/files/daily
LOGFILE=/var/log/backup-files-upload.log
rclone sync "${LOCAL_DIR}" "${REMOTE}" --s3-chunk-size 64M --s3-upload-concurrency 4 --checksum --fast-list --log-file "${LOGFILE}" --log-level INFO
Ключевые моменты:
syncгарантирует, что на удаленной стороне будет то же содержимое, что и локально (старые файлы могут удаляться);--checksumзаставляет rclone сверять контрольные суммы, а не только размер и время;--log-fileи--log-levelнужны, чтобы отлавливать проблемы после запуска из cron;- параметры
--s3-chunk-sizeи--s3-upload-concurrencyподбирайте под сеть, размер файлов и лимиты провайдера.
Бэкап MySQL с выгрузкой в Object Storage
Для MySQL/MariaDB основной риск — неконсистентный дамп под нагрузкой. Для небольших и средних БД на VDS обычно достаточно использовать mysqldump с правильными опциями. Для больших (десятки и сотни гигабайт) лучше смотреть в сторону физического бэкапа и PITR, об этом подробнее в материале о PITR‑бэкапах MySQL по бинлогам и GTID.
Скрипт дампа MySQL
Создадим каталог под дампы:
mkdir -p /var/backups/mysql
Скрипт /usr/local/sbin/backup-mysql.sh может выглядеть так:
#!/usr/bin/env bash
set -euo pipefail
HOSTNAME_SHORT=$(hostname -s)
BACKUP_DIR=/var/backups/mysql
DATE=$(date +%Y-%m-%d-%H%M)
MYSQL_USER=backup
MYSQL_PASS='STRONG_PASSWORD'
mkdir -p "${BACKUP_DIR}"
DUMP_FILE="${BACKUP_DIR}/${HOSTNAME_SHORT}-mysql-${DATE}.sql.zst"
mysqldump --user="${MYSQL_USER}" --password="${MYSQL_PASS}" --single-transaction --routines --events --all-databases --flush-logs --master-data=2 | zstd -19 --long=25 -o "${DUMP_FILE}"
find "${BACKUP_DIR}" -type f -mtime +7 -delete
Что здесь важно:
--single-transactionдает консистентный дамп для InnoDB без глобальной блокировки;--master-data=2полезен, если вы хотите иметь данные для репликации (если не нужно — уберите);- пароль лучше не хранить в скрипте: используйте
~/.my.cnfс правами600или переменные окружения через unit systemd.
Загрузка дампов MySQL в S3
Скрипт /usr/local/sbin/backup-mysql-upload.sh:
#!/usr/bin/env bash
set -euo pipefail
HOSTNAME_SHORT=$(hostname -s)
LOCAL_DIR=/var/backups/mysql
REMOTE=backup-s3:my-backups/${HOSTNAME_SHORT}/mysql/daily
LOGFILE=/var/log/backup-mysql-upload.log
rclone copy "${LOCAL_DIR}" "${REMOTE}" --include "${HOSTNAME_SHORT}-mysql-*.sql.zst" --s3-chunk-size 64M --s3-upload-concurrency 4 --checksum --fast-list --log-file "${LOGFILE}" --log-level INFO
Здесь используется copy, а не sync, чтобы не задеть бэкапы с других хостов или других периодов в том же каталоге. Если каждый хост пишет строго в свой изолированный путь .../hostname/mysql/daily, можно смело использовать sync.
Бэкап PostgreSQL с rclone
Для PostgreSQL классический инструмент — pg_dump и pg_dumpall. Для point‑in‑time recovery и больших прод‑кластеров обычно используют WAL‑архивацию и специализированные утилиты (подробнее см. отдельный разбор в статье про pgBackRest и бэкапы PostgreSQL), но здесь разберем базовый логический дамп на VDS.
Скрипт дампа PostgreSQL
Каталог для дампов:
mkdir -p /var/backups/postgres
Скрипт /usr/local/sbin/backup-postgres.sh (запускать обычно под пользователем postgres):
#!/usr/bin/env bash
set -euo pipefail
HOSTNAME_SHORT=$(hostname -s)
BACKUP_DIR=/var/backups/postgres
DATE=$(date +%Y-%m-%d-%H%M)
mkdir -p "${BACKUP_DIR}"
DUMP_FILE="${BACKUP_DIR}/${HOSTNAME_SHORT}-postgres-${DATE}.sql.zst"
pg_dumpall --clean --if-exists | zstd -19 --long=25 -o "${DUMP_FILE}"
find "${BACKUP_DIR}" -type f -mtime +7 -delete
Если баз много и они большие, удобнее делать отдельные дампы по БД через pg_dump, а не pg_dumpall, но схема выгрузки и синхронизации с Object Storage останется той же.
Загрузка дампов PostgreSQL в Object Storage
Скрипт /usr/local/sbin/backup-postgres-upload.sh:
#!/usr/bin/env bash
set -euo pipefail
HOSTNAME_SHORT=$(hostname -s)
LOCAL_DIR=/var/backups/postgres
REMOTE=backup-s3:my-backups/${HOSTNAME_SHORT}/postgres/daily
LOGFILE=/var/log/backup-postgres-upload.log
rclone copy "${LOCAL_DIR}" "${REMOTE}" --include "${HOSTNAME_SHORT}-postgres-*.sql.zst" --s3-chunk-size 64M --s3-upload-concurrency 4 --checksum --fast-list --log-file "${LOGFILE}" --log-level INFO
Логика полностью аналогична MySQL‑скриптам: отдельно отвечаем за создание дампа, отдельно — за его доставку в Object Storage.

Настройка cron: расписание и логика запуска
Дальше нужно грамотно раскидать задачи в cron, чтобы бэкапы не мешали друг другу и не ложились на пиковые часы нагрузки. Классический вариант — ночное окно по часовому поясу проекта.
Простая схема cron для ежедневных бэкапов
Пример crontab для root (редактируем через crontab -e):
# Ежедневный бэкап файлов + выгрузка в S3
0 2 * * * /usr/local/sbin/backup-files.sh
30 2 * * * /usr/local/sbin/backup-files-upload.sh
# Ежедневный дамп MySQL + выгрузка
0 3 * * * /usr/local/sbin/backup-mysql.sh
30 3 * * * /usr/local/sbin/backup-mysql-upload.sh
# Ежедневный дамп PostgreSQL (под пользователем postgres)
0 4 * * * su - postgres -c '/usr/local/sbin/backup-postgres.sh'
30 4 * * * su - postgres -c '/usr/local/sbin/backup-postgres-upload.sh'
Замечания:
- между созданием дампа и выгрузкой в Object Storage оставляем небольшой буфер времени;
- время выбираем из «ночного» окна конкретного проекта;
- для PostgreSQL чаще логичнее запускать скрипты под пользователем
postgres, а неroot.
Защита от параллельных запусков через flock
Если дамп или загрузка по какой‑то причине затянутся, cron может запустить следующий экземпляр, и они начнут конкурировать за ресурсы. Лечится это использованием flock или lock‑файлов.
Пример для скрипта MySQL с использованием flock в crontab:
0 3 * * * flock -n /var/lock/backup-mysql.lock /usr/local/sbin/backup-mysql.sh
30 3 * * * flock -n /var/lock/backup-mysql-upload.lock /usr/local/sbin/backup-mysql-upload.sh
Ключ -n заставляет flock немедленно завершиться, если lock уже захвачен. Это удобнее, чем накапливать повисшие задания.
Ротация старых бэкапов: что оставляем локально, что в Object Storage
Локальное хранилище на VDS обычно ограничено, Object Storage — дешевле и масштабируемее. Поэтому логика часто такая:
- локально держим только последние несколько дней (3–7), чтобы быстро восстановить «горячие» данные;
- в Object Storage храним daily за 30–60 дней, weekly за 3–6 месяцев, monthly за год и более.
Ротацию можно делать:
- через политики жизненного цикла Object Storage (если провайдер позволяет настраивать по префиксам);
- или через скрипты с rclone:
rclone delete,rclone rmdirs, фильтры по времени.
Примитивный вариант удаления старых daily‑бэкапов средствами rclone (например, оставлять 30 дней):
HOSTNAME_SHORT=$(hostname -s)
rclone delete backup-s3:my-backups/${HOSTNAME_SHORT}/mysql/daily --min-age 30d --fast-list --log-file /var/log/backup-mysql-rotate.log --log-level INFO
Во многих случаях проще задать lifecycle‑политику на уровне бакета или префикса и не городить собственный велосипед — тогда rclone занимается только доставкой, а не удалением.
Проверка целостности и тестовые восстановления
Бэкап, из которого нельзя восстановиться, — это не бэкап. В проде обязательно нужны регулярные проверки:
- что бэкапы физически есть в Object Storage;
- что контрольные суммы совпадают;
- что вы умеете из них поднимать рабочий инстанс БД или хотя бы дамп в тестовую БД.
Проверка через rclone check
Команда rclone check сравнивает содержимое локального каталога и Object Storage:
HOSTNAME_SHORT=$(hostname -s)
rclone check /var/backups/mysql backup-s3:my-backups/${HOSTNAME_SHORT}/mysql/daily --checksum --size-only=false --log-file /var/log/backup-mysql-check.log --log-level INFO
Её можно раз в несколько дней запускать из cron и мониторить лог на предмет расхождений. Либо интегрировать парсинг логов в существующий мониторинг.
Тестовое восстановление MySQL/PostgreSQL
Минимальный сценарий проверки восстановления:
- развернуть временный инстанс MySQL/PostgreSQL (на том же VDS или отдельном тестовом сервере);
- скачать один из бэкапов с Object Storage через rclone;
- разжать
.zstи выполнить восстановление в эту временную БД; - убедиться, что ключевые таблицы и данные на месте, нет ошибок при импорте.
Такую проверку полезно автоматизировать: например, раз в неделю поднимать тестовую БД в контейнере, восстанавливать из свежего бэкапа и отправлять отчет в monitoring или чат.
Безопасность: ключи доступа, шифрование, права
С Object Storage и rclone связаны несколько типичных рисков безопасности.
- Минимальные права для access‑ключей. Аккаунт и ключ, который вы используете в rclone, должен иметь доступ только к конкретному бакету или префиксу и только на те операции, которые реально нужны.
- Защита конфигов. Файл
rclone.conf, скрипты с паролями MySQL/Postgres, локальные дампы — всё это должно иметь режимы доступа вида600и принадлежать только нужному пользователю. - Client‑side шифрование. Если вы храните чувствительные данные (персональные данные, платежные данные), стоит рассмотреть использование модуля
cryptв rclone, чтобы шифровать бэкапы перед отправкой в Object Storage. В этом случае провайдер видит только зашифрованный набор байтов, а ключ хранится у вас. - Сегрегация окружений. Для dev, stage и prod используйте разные бакеты и разные ключи, чтобы не перепутать и не дать лишние права.
Пример конфига rclone с использованием crypt здесь опустим, но если в дампах есть персональные данные, к этому вопросу стоит вернуться отдельно и формально закрыть требования по безопасности.
Отладка, типичные ошибки и как их ловить
При первом запуске связки rclone + cron полезно:
- все скрипты прогнать вручную в интерактивной сессии и проверить, что дампы создаются, а файлы улетают в Object Storage;
- включить более подробный лог rclone с
--log-level DEBUGна период отладки; - смотреть
/var/log/syslogили/var/log/cron(в зависимости от дистрибутива) на предмет ошибок cron; - следить за потреблением диска на VDS, чтобы локальные бэкапы не забили файловую систему.
Популярные проблемы:
- Не тот конфиг rclone у cron. В интерактивной сессии используется
~/.config/rclone/rclone.confтекущего пользователя, а cron дляrootсмотрит в/root/.config. Лечится явным указанием--configили созданием нужного каталога с конфигом. - Отсутствие PATH. В cron переменная
PATHможет быть минимальной, поэтомуrclone,mysqldump,pg_dumpне находятся. Решение — полные пути к бинарникам или установка нужного PATH в начале crontab. - Падение из‑за недостатка памяти или CPU. Сжатие на максимальных уровнях и параллельные multipart‑загрузки могут заметно грузить VDS. Подбирайте уровни zstd,
--s3-upload-concurrencyи расписание под реальные ресурсы.
Итоги
Связка rclone + cron дает простой и гибкий способ вывозить бэкапы с вашего VDS в S3‑совместимый Object Storage, не завязываясь на конкретного провайдера и не таща тяжелые системы бэкапов. Ключ к надежности здесь не только в корректной конфигурации rclone и cron, но и в:
- проверенных скриптах создания дампов MySQL/PostgreSQL и архивов файлов;
- продуманной структуре каталогов и политике ротации;
- регулярных проверках целостности и тестовых восстановлениях;
- аккуратном обращении с ключами доступа, конфигами и правами на файлы.
Если всё это аккуратно собрать и автоматизировать, вы получите предсказуемый, воспроизводимый и относительно недорогой backup‑контур, который не стыдно использовать в боевом продакшене и масштабировать при росте нагрузки.


