MAATRIX / Блог / Бэкап и восстановление Funkwhale

Бэкап и восстановление Funkwhale

MAATRIX

Funkwhale хранит вашу фонотеку не одним файлом, а тремя разными сущностями сразу: базой PostgreSQL с метаданными и учётками, каталогом с самими треками и обложками, и файлом .env с секретами и настройками федерации. Потеряете диск с музыкой — обидно, но переустановить и залить треки заново можно. Потеряете базу без бэкапа — исчезнут плейлисты, подписки на другие инстансы федивёрса и сама структура библиотеки, а голые аудиофайлы на диске превратятся в набор безымянных .flac без единой связи между собой. Разберём, что и как бэкапить в Funkwhale, и как поднять инстанс заново на чистом сервере.

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →

Что нужно бэкапить в Funkwhale

Инсталляция через Docker Compose (стандартный способ разворачивания, разобранный в статье про установку Funkwhale на VPS) держит данные в четырёх местах, и не все из них одинаково важны:

  • PostgreSQL — сердце инстанса: пользователи и права доступа, структура библиотеки (альбомы, исполнители, плейлисты, теги), подписки на другие инстансы федивёрса через ActivityPub, приватные и публичные ключи актора вашего сервера, история прослушиваний, радио-настройки. Без базы медиафайлы на диске остаются просто файлами — Funkwhale не сможет их ни найти, ни отдать пользователю.
  • data/media — обложки альбомов, аватары пользователей, сгенерированные превью и вложения. Средний по объёму каталог, но визуально заметный: без него интерфейс будет работать, но выглядеть голо.
  • data/music — сами аудиофайлы, если вы используете локальное хранилище (а не подключённое по MUSIC_DIRECTORY_PATH внешнее read-only хранилище с оригиналами). Обычно это самая тяжёлая часть бэкапа по объёму.
  • .env — все настройки инстанса: домен, DJANGO_SECRET_KEY, пароль базы, лимиты загрузки, почтовые настройки. Небольшой файл, но без него после переустановки Funkwhale банально не запустится с прежними параметрами.

Redis в этот список сознательно не входит — там живёт очередь Celery для фоновых задач (транскодирование, импорт, генерация превью) и кэш. Funkwhale пересоздаёт эту структуру сама при старте, бэкапить нечего. Каталог data/staticfiles — тоже не бэкапим, это статика фронтенда, которая генерируется заново командой collectstatic при каждом обновлении образа.

Отдельно стоит сказать про приватный ключ ActivityPub-актора вашего инстанса — он определяет, что для остальной федерации ваш сервер это «тот самый» сервер, на который другие люди подписаны. Ключ хранится в таблице базы данных, а не отдельным файлом, поэтому при регулярном бэкапе PostgreSQL он уже защищён — искать и копировать его отдельно не нужно.

Бэкап базы данных PostgreSQL

Если Funkwhale развёрнут через официальный docker-compose.yml, контейнер PostgreSQL называется postgres, а имя базы и пользователя обычно совпадают со значением funkwhale (проверьте свои .env, если меняли значения по умолчанию). Снимаем дамп через docker compose exec:

cd /srv/funkwhale
docker compose exec -T postgres pg_dump -U funkwhale -Fc funkwhale \
  > /srv/backups/funkwhale/db_$(date +%F_%H%M).dump

Формат -Fc (custom) компактнее обычного SQL-дампа и позволяет восстанавливать выборочно через pg_restore, а не только целиком. Проверить дамп на целостность без реального восстановления можно так:

pg_restore --list /srv/backups/funkwhale/db_2026-08-30_0300.dump | head -20

Если команда вернула список объектов базы, а не ошибку — дамп читаемый и пригоден для восстановления. pg_dump снимает консистентный снапшот через MVCC PostgreSQL и не блокирует запись, так что снимать дамп можно в любое время суток без остановки сервиса — слушатели даже не заметят.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Бэкап медиатеки и загруженных файлов

Медиатека — самая объёмная часть, и здесь важно не тащить в бэкап временный мусор. Простой вариант для небольшой и средней библиотеки — rsync:

rsync -a --delete \
  /srv/funkwhale/data/media/ /srv/backups/funkwhale/media/
rsync -a --delete \
  /srv/funkwhale/data/music/ /srv/backups/funkwhale/music/

Флаг --delete синхронизирует и удаления — если трек удалили из библиотеки, он не будет вечно копироваться в бэкап. Для инстанса с растущим архивом FLAC-альбомов на сотни гигабайт разумнее взять инструмент с дедупликацией, который хранит только изменившиеся блоки, а не гоняет терабайты по кругу при каждом запуске:

restic -r s3:https://s3.example.com/funkwhale-backup init
restic -r s3:https://s3.example.com/funkwhale-backup backup \
  /srv/funkwhale/data/media \
  /srv/funkwhale/data/music

Подробнее про установку и работу с restic — в отдельной статье про restic на VPS, там же разобраны шифрование репозитория и хранение ключа доступа. Если под сами бэкапы вы хотите поднять своё S3-совместимое хранилище на отдельном сервере, а не платить за внешний облачный сервис, посмотрите статью про установку MinIO — связка «Funkwhale плюс отдельный MinIO под бэкапы на другой машине» снимает риск потерять всё разом при отказе одного сервера.

Если библиотека подключена не как data/music внутри контейнера, а как внешний каталог с оригиналами через MUSIC_DIRECTORY_PATH (например, смонтированный сетевой диск с исходниками, которые Funkwhale только читает и импортирует), проверьте, что этот каталог бэкапится отдельно вашим общим процессом резервного копирования — сам Funkwhale его не модифицирует, но и не гарантирует его сохранность.

Бэкап конфигурации

.env — небольшой файл, но в нём секреты, без которых новый инстанс не поднимется с прежними параметрами:

cp /srv/funkwhale/.env /srv/backups/funkwhale/env_$(date +%F).bak
chmod 600 /srv/backups/funkwhale/env_$(date +%F).bak

Храните эти копии отдельно от общего архива медиатеки и желательно в зашифрованном виде — внутри .env лежат пароль базы данных, DJANGO_SECRET_KEY и, если настроена отправка почты, учётные данные SMTP. Если на сервере уже используется docker-compose.yml с кастомными правками (например, изменённые лимиты в nginx-шаблоне nginx/funkwhale.template), включите в архив и его — при переустановке проще подправить готовый файл, чем вспоминать, что именно меняли полгода назад.

Скрипт автоматизации и хранение бэкапов

Собираем всё в один cron-скрипт: дамп базы, синхронизация медиатеки, копия .env, и ротация старых версий:

#!/bin/bash
set -euo pipefail

BACKUP_DIR="/srv/backups/funkwhale"
DATE=$(date +%F_%H%M)
KEEP_DAYS=14

mkdir -p "$BACKUP_DIR"

# 1. База данных
docker compose -f /srv/funkwhale/docker-compose.yml exec -T postgres \
  pg_dump -U funkwhale -Fc funkwhale > "$BACKUP_DIR/db_$DATE.dump"

# 2. Конфигурация
cp /srv/funkwhale/.env "$BACKUP_DIR/env_$DATE.bak"
chmod 600 "$BACKUP_DIR/env_$DATE.bak"

# 3. Медиатека — инкрементально через restic
restic -r s3:https://s3.example.com/funkwhale-backup backup \
  /srv/funkwhale/data/media \
  /srv/funkwhale/data/music \
  --tag "$DATE"

# 4. Ротация локальных дампов и конфигов
find "$BACKUP_DIR" -name "*.dump" -mtime +"$KEEP_DAYS" -delete
find "$BACKUP_DIR" -name "*.bak" -mtime +"$KEEP_DAYS" -delete

# 5. Ротация снапшотов restic
restic -r s3:https://s3.example.com/funkwhale-backup forget \
  --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Ставим в cron на ночное время:

crontab -e
# 0 3 * * * /usr/local/bin/funkwhale-backup.sh >> /var/log/funkwhale-backup.log 2>&1

Разумная периодичность: базу — ежедневно (она лёгкая, дамп занимает секунды), медиатеку — тоже ежедневно инкрементально, если пользуетесь restic или rclone с дедупликацией, либо реже (раз в несколько дней), если синхронизируете тяжёлым полным rsync и объём библиотеки большой. Держите бэкапы правилу 3-2-1: минимум три копии, на двух разных носителях, хотя бы одна — вне основного сервера. Локальная копия на том же диске защищает только от случайного удаления треков внутри интерфейса, но не от отказа диска или блокировки сервера хостером.

Восстановление Funkwhale на новом сервере

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

  1. Разверните ту же версию Funkwhale, что была на исходном сервере — тег образа виден в старом docker-compose.yml или в футере админ-панели, если она успела открыться. Смешение версий — частая причина, почему восстановленный дамп не применяется: новая мажорная версия ожидает уже применённых миграций, которых в старом дампе может не быть.
  2. Подготовьте рабочую директорию так же, как при первой установке — mkdir -p /srv/funkwhale/data/{media,music,staticfiles} — и положите туда восстановленный .env, поправив в нём хост базы или домен, если они изменились.
  3. Поднимите только базу и Redis, не запуская пока api:
   docker compose up -d postgres redis
  1. Восстановите дамп:
   docker compose exec -T postgres pg_restore -U funkwhale -d funkwhale \
     --clean --if-exists < /srv/backups/funkwhale/db_2026-08-30_0300.dump
  1. Верните медиатеку:
   restic -r s3:https://s3.example.com/funkwhale-backup restore latest \
     --target /srv/funkwhale/data

или rsync -a /srv/backups/funkwhale/media/ /srv/funkwhale/data/media/ и аналогично для music/, в зависимости от того, чем бэкапили.

  1. Запустите весь стек и проверьте миграции:
   docker compose up -d
   docker compose logs -f api

В логах api должно пройти применение миграций (если версия новее исходной) без ошибок.

  1. Проверьте вход и федерацию — откройте https://ваш-домен в браузере, войдите под старым аккаунтом администратора, убедитесь, что библиотека, плейлисты и подписки на другие инстансы на месте. Если приватный ключ актора восстановился вместе с базой (а он восстанавливается вместе с ней автоматически), другие инстансы федивёрса продолжат доверять вашему серверу, разрыва подписок быть не должно.

Если старый сервер ещё жив и вы переезжаете планово, а не восстанавливаетесь после аварии, переключайте DNS на новый IP только после проверки, что новый инстанс поднялся и работает корректно — иначе входящие ActivityPub-запросы от подписчиков начнут падать в промежутке, когда старый сервер уже недоступен, а новый ещё не готов принимать трафик.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли бэкапить только базу, без медиатеки?

Нет — база без файлов бессмысленна: вы получите записи о треках, которых физически не существует на диске. Если места под полный бэкап библиотеки не хватает, лучше пересмотреть retention (не хранить историю давно удалённых альбомов) или перейти на restic с дедупликацией вместо полного rsync, чем отказываться от бэкапа медиатеки целиком.

Нужно ли останавливать Funkwhale на время снятия дампа?

Нет, pg_dump снимает консистентный снапшот через MVCC PostgreSQL без блокировки записи. Останавливать сервис имеет смысл только перед восстановлением дампа (после шага 3 в разделе восстановления выше), а не перед регулярным бэкапом.

Что случится с подписчиками с других инстансов, если восстановиться из бэкапа недельной давности?

Вы потеряете действия за эту неделю — новые подписки, комментарии, изменения библиотеки. Сама федерация не сломается, потому что ключ актора и базовый список подписок восстановятся вместе с базой, но события за промежуток между последним бэкапом и аварией не вернутся.

Как часто нужен полный тест восстановления, а не только снятие бэкапа?

Хотя бы раз в квартал, на отдельном тестовом сервере или временном VPS. Бэкап, который ни разу не разворачивали, — это предположение о бэкапе, а не гарантия; частые причины провала восстановления — несовпадение версии Funkwhale и забытые правки в .env, которые вскрываются только в момент, когда они действительно нужны.

Redis точно не нужно бэкапить?

Не нужно. В Redis у Funkwhale хранится только очередь фоновых задач Celery (транскодирование, импорт, генерация превью) и кэш — при перезапуске сервис пересоздаёт эту структуру сам, никаких пользовательских данных там нет.

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →