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

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

MAATRIX

Authelia — лёгкий forward-auth сервер: сам он не хранит защищаемые сервисы, но без его конфигов, базы и ключей шифрования вы теряете доступ ко всему, что стоит за Nginx или Traefik — от Grafana до внутренних панелей. Проблема в том, что бэкап «на глаз» здесь часто ломается: люди бэкапят SQLite-файл, но забывают ключ шифрования, из-за которого восстановленная база оказывается нечитаемой. Разберём, что бэкапить, как это делать по-разному для SQLite и PostgreSQL, и как восстановиться так, чтобы пользователям не пришлось заново регистрировать TOTP.

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

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

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

Что реально нужно бэкапить в Authelia

Authelia состоит из нескольких независимых частей, и терять можно каждую по-своему больно:

  • Конфигурацияconfiguration.yml и все файлы, на которые он ссылается (правила доступа, настройки notifier, TLS).
  • База пользователей файлового провайдераusers_database.yml, если вы не используете LDAP. Пароли (bcrypt/argon2 хеши), группы, email.
  • Storage backend — SQLite-файл (db.sqlite3) или внешняя PostgreSQL/MySQL база. Здесь лежат зарегистрированные TOTP-секреты, WebAuthn-устройства, история попыток входа, identity verification токены.
  • Секреты (secrets/* или переменные AUTHELIA_*_SECRET_FILE) — jwt_secret, session_secret, storage_encryption_key, storage_postgres_password и т.п.
  • Redis — хранилище сессий, если вынесено отдельно. Данные там переживаемые (пользователи просто перелогинятся), поэтому это единственная часть, которую бэкапить не обязательно.

Ключевой нюанс, который ломает восстановление чаще всего: TOTP-секреты и данные WebAuthn в storage-базе зашифрованы ключом storage_encryption_key. Если вы восстановили db.sqlite3, но потеряли или не сохранили этот ключ — база поднимется, Authelia запустится, но расшифровать секреты не сможет. Итог тот же, что при полной потере базы: всем пользователям придётся заново привязывать TOTP-приложения и WebAuthn-ключи. Поэтому ключ шифрования — не менее критичная часть бэкапа, чем сама база.

Docker Compose и структура томов

Типичный деплой Authelia за Traefik выглядит так — от этого и отталкиваемся при бэкапе:

# docker-compose.yml (фрагмент)
services:
  authelia:
    image: authelia/authelia:4.38
    container_name: authelia
    volumes:
      - ./config:/config
    environment:
      - TZ=Europe/Moscow
    restart: unless-stopped
    networks:
      - proxy

  redis:
    image: redis:7-alpine
    container_name: authelia-redis
    volumes:
      - redis-data:/data
    restart: unless-stopped
    networks:
      - proxy

volumes:
  redis-data:

networks:
  proxy:
    external: true

Всё важное лежит в ./config на хосте:

config/
├── configuration.yml
├── users_database.yml
├── db.sqlite3
├── notification.txt        # если notifier: filesystem
└── secrets/
    ├── jwt_secret
    ├── session_secret
    └── storage_encryption_key

Если у вас именно такая раскладка — 90% работы по бэкапу сводится к архивации одной директории config. Дальше — детали для двух вариантов storage backend.

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

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

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

Скрипт полного бэкапа: конфиги + secrets + SQLite

Для SQLite достаточно снапшота файла (Authelia не пишет в базу настолько интенсивно, чтобы бояться повреждения при копировании на лету, но лучше делать это через sqlite3 .backup — так гарантированно получите консистентный снимок без блокировок):

#!/usr/bin/env bash
# /opt/scripts/backup-authelia.sh
set -euo pipefail

SRC=/opt/authelia/config
DEST=/opt/backups/authelia
STAMP=$(date +%Y%m%d-%H%M%S)
ARCHIVE="$DEST/authelia-$STAMP.tar.gz"

mkdir -p "$DEST"

# Консистентный снимок SQLite без остановки контейнера
sqlite3 "$SRC/db.sqlite3" ".backup '$SRC/db.sqlite3.snapshot'"

tar -czf "$ARCHIVE" \
  -C "$SRC" \
  configuration.yml \
  users_database.yml \
  db.sqlite3.snapshot \
  secrets/

rm -f "$SRC/db.sqlite3.snapshot"

# Ротация: держим последние 14 архивов
find "$DEST" -name 'authelia-*.tar.gz' -mtime +14 -delete

echo "Бэкап готов: $ARCHIVE ($(du -h "$ARCHIVE" | cut -f1))"

Права на секреты обычно 600, tar их сохранит — но проверьте после восстановления, chown контейнерного пользователя может отличаться от вашего хостового.

Архив весит копейки (конфиги — килобайты, SQLite-база с логами входов редко больше десятков мегабайт), поэтому имеет смысл сразу лить копию за пределы сервера — на другой VPS или в объектное хранилище. Если ещё не настроили офсайт-копирование, посмотрите restic на VPS — инкрементальные снапшоты с шифрованием закроют это одной командой в cron.

Если storage — PostgreSQL или MySQL

На нагруженных инсталляциях (много пользователей, частые попытки входа, audit log) файловый SQLite упирается в блокировки при параллельных запросах, и Authelia переводят на PostgreSQL:

storage:
  postgres:
    address: tcp://postgres:5432
    database: authelia
    username: authelia
    password: ""  # берётся из secrets/storage_postgres_password

Здесь бэкап делится на два независимых потока: конфиги/secrets — как в скрипте выше (без строчки про SQLite), и дамп базы — стандартным pg_dump:

#!/usr/bin/env bash
# /opt/scripts/backup-authelia-pg.sh
set -euo pipefail

DEST=/opt/backups/authelia
STAMP=$(date +%Y%m%d-%H%M%S)

docker exec authelia-postgres pg_dump -U authelia -Fc authelia \
  > "$DEST/authelia-db-$STAMP.dump"

tar -czf "$DEST/authelia-config-$STAMP.tar.gz" \
  -C /opt/authelia/config \
  configuration.yml users_database.yml secrets/

find "$DEST" -mtime +14 -delete

Формат -Fc (custom) даёт сжатие и быстрое частичное восстановление через pg_restore, в отличие от plain SQL. Если PostgreSQL уже обслуживает у вас несколько сервисов, логично унифицировать бэкапы на уровне СУБД — как это сделать правильно, разобрано в статье про настройку PostgreSQL на VPS.

BackendПлюсыМинусы для бэкапа
SQLiteОдин файл, простой снапшот, ноль зависимостейПри росте audit log базу нужно чистить, иначе бэкап пухнет
PostgreSQLВыдерживает нагрузку, точечное восстановлениеОтдельный сервис, нужен pg_dump в цепочке, лишняя точка отказа

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

Порядок действий одинаков для обоих backend, разница только в шаге с базой:

  1. Разверните тот же образ Authelia и Redis тем же docker-compose.yml (версию образа лучше зафиксировать той же, что была — миграции схемы между мажорными версиями иногда требуют ручных шагов).
  2. Распакуйте конфиги:
mkdir -p /opt/authelia/config
tar -xzf authelia-config-20260828-030000.tar.gz -C /opt/authelia/config
chmod 600 /opt/authelia/config/secrets/*
  1. Восстановите базу:
# SQLite
cp db.sqlite3.snapshot /opt/authelia/config/db.sqlite3

# PostgreSQL — сначала поднимите пустую базу authelia,
# затем:
docker exec -i authelia-postgres pg_restore \
  -U authelia -d authelia --clean --if-exists \
  < authelia-db-20260828-030000.dump
  1. Проверьте, что secrets/storage_encryption_key — это именно тот файл, что был на исходном сервере, а не сгенерированный заново. Это самый частый способ незаметно всё сломать: скрипт первого запуска Authelia может создать новый ключ, если файл отсутствует, и тогда старая база станет нечитаемой молча, без явной ошибки при старте.
  2. Запустите стек и проверьте логи:
docker compose up -d
docker compose logs -f authelia
  1. Залогиньтесь под тестовым пользователем и убедитесь, что второй фактор (TOTP/WebAuthn) проходит — это финальное подтверждение, что ключ шифрования восстановлен верно.

Если Authelia у вас в связке с Traefik как forward-auth middleware, после восстановления также проверьте, что middlewares.yml (или динамическая конфигурация Traefik) по-прежнему указывает на правильный адрес контейнера — при переезде на новый сервер имя сервиса в Docker-сети иногда меняется. Базовая настройка reverse proxy описана в статье про установку Traefik на VPS, если разворачиваете стек с нуля.

Автоматизация: systemd timer вместо cron

Cron работает, но не логирует падения и не умеет ретраить. На проде удобнее systemd timer:

# /etc/systemd/system/authelia-backup.service
[Unit]
Description=Backup Authelia config and storage

[Service]
Type=oneshot
ExecStart=/opt/scripts/backup-authelia.sh
User=root
# /etc/systemd/system/authelia-backup.timer
[Unit]
Description=Daily Authelia backup at 03:00

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now authelia-backup.timer
systemctl list-timers authelia-backup.timer

Persistent=true дозапустит бэкап после перезагрузки сервера, если таймер должен был сработать, пока сервер был выключен, — полезно для VPS, которые иногда ребутятся при апгрейде ядра.

Отдельно стоит раз в квартал проверять, что бэкап реально восстанавливается — поднять его на тестовом сервере и залогиниться. Архив, который никто не разворачивал, — это не бэкап, а файл с недоказанной работоспособностью; такая проверка занимает 20 минут, а спасает от ситуации, когда сломанный бэкап обнаруживается в момент реального инцидента. Если у вас Authelia защищает несколько сервисов на одном хосте, логично сверить процесс восстановления с тем, как вы бэкапите сам identity provider целиком — например, Keycloak, если он используется рядом как источник OIDC.

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

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

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

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

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

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

Нужно ли бэкапить Redis?

Обычно нет. Redis хранит только активные сессии — при потере пользователи просто увидят экран логина ещё раз. Исключение — если вы используете Redis Sentinel как единственное хранилище session-данных с длинным TTL "remember me", тогда потеря означает разлогин всех сразу, что неприятно, но не критично для безопасности.

Что будет, если восстановить базу без ключа шифрования?

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

Как часто делать бэкап?

Для файлового провайдера с редкими изменениями хватает раз в сутки. Если пользователи часто регистрируют новые устройства WebAuthn или у вас большой поток попыток входа в audit log — имеет смысл 2-4 раза в сутки, благо архив лёгкий.

Можно ли бэкапить configuration.yml вместе с реальными паролями внутри?

Если вы используете _FILE-переменные и вынесли секреты в secrets/, в configuration.yml паролей нет — это безопасно хранить даже в git (приватном). Если пароли прописаны прямо в YAML — обращайтесь с бэкапом как с секретом: шифрование архива обязательно.

Что делать при миграции с SQLite на PostgreSQL?

У Authelia нет встроенного инструмента переноса между backend — обычно проще заново инициализировать хранилище на PostgreSQL и попросить пользователей перерегистрировать 2FA, либо писать миграционный скрипт вручную через SQL-экспорт таблиц totp_configurations и webauthn_devices с последующей перешифровкой под новый или тот же storage_encryption_key.

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

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

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