Learn Authelia - Storage Backend
Episode 8 of 31

Learn Authelia - Storage Backend

Understanding Authelia's storage backend that holds permanent data like TOTP secrets and WebAuthn credentials: choosing between SQLite, MySQL, and PostgreSQL, configuring it in configuration.yml, running schema migrations, and backup strategies so users don't lose their MFA devices.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 7, you stored sessions in Redis: fast, temporary, and gone when they expire. But Authelia has data that must never be lost — permanent data that determines whether a user can log in again tomorrow. Sessions are temporary, but the trust that builds them must endure.

This permanent data is stored in the storage backend, a database that remembers: TOTP secrets, WebAuthn credentials, Duo device IDs, identity verification tokens, and OIDC consent records. If this database is corrupted without a backup, every user has to re-register all their MFA devices — an exhausting night for both admins and users. In this episode you'll choose the right backend, configure it, run schema migrations, and build a healthy backup strategy.

What's Stored in Storage?

The storage backend is Authelia's long-term memory. Among its contents:

  • TOTP secrets: the same secret key that's in the user's authenticator app. A leak means an attacker can produce OTP codes.
  • WebAuthn credentials: the public key and authenticator metadata, including YubiKeys and passkeys.
  • Duo device IDs: identities of devices already enrolled for Duo Push.
  • Identity verification tokens: temporary tokens for the password reset or email verification flow.
  • OIDC consent records: permissions a user has given to client applications.

In other words: whatever Authelia must remember after the login process completes lives in this database. Losing the database means losing access.

Choosing the Backend: SQLite, MySQL, or PostgreSQL

Authelia supports three storage options:

  • SQLite (local): the default and simplest. A single database file, no separate server, zero extra configuration. Good for homelabs, single instances, and low traffic.
  • MySQL/MariaDB: a good choice when you already have a MySQL database server. Requires setting up the user and database first.
  • PostgreSQL: the main recommendation for production. Supports encryption keys, connection pooling, and is a solid foundation for high availability.
storage:
  local:
    path: "/config/db.sqlite3"

Note the encryption_key in the PostgreSQL configuration. This key encrypts sensitive data like TOTP secrets and WebAuthn private keys when stored in the database — the last line of defense if the database file leaks. Only available for MySQL and PostgreSQL, not SQLite.

Important

The encryption_key must be identical across all Authelia instances and must be backed up. Without this key, encrypted data can't be read — not just hard to read, but impossible to decrypt. Losing the key is the same as losing the database.

Connection Configuration

In general, storage configuration follows the same pattern: server address, database name, user, and password.

MySQL storage
storage:
  mysql:
    address: "tcp://mysql:3306"
    database: "authelia"
    username: "authelia"
    password: "database-secret"
    encryption_key: "long-encryption-key-same-on-all-instances"

Before Authelia can be used, the database and its user must first be created on the MySQL or PostgreSQL server. Create a dedicated user with restricted access to only the authelia database — never use the root account.

If you're moving from SQLite to PostgreSQL, the safe order is: back up first, create the destination database, then migrate with the CLI while moving user data via the export and import commands.

Database Schema Migrations

Authelia evolves quickly, and each new version can change the database table structure. This schema is kept in sync by migrations. By default, Authelia automatically runs upward migrations at startup. For full control, a CLI subcommand is available:

Running migrations manually
authelia storage migrate up
authelia storage migrate history
authelia storage migrate list-up
  • migrate up: runs all migrations that haven't been applied yet.
  • migrate history: shows the schema version history.
  • migrate list-up and migrate list-down: check available migrations before running them.

When you change the storage configuration (for example moving from SQLite to PostgreSQL), Authelia adjusts the schema in the destination database automatically the first time it connects. The backend migration process can be shown as a configuration change:

Storage configuration change
storage:
  local: 
    path: "/config/db.sqlite3"
  postgres: 
    address: "tcp://postgres:5432"
    database: "authelia"
    username: "authelia"
    password: "database-secret"

Caution

Always back up before running migrations. Upward migrations are generally safe, but reversing downward migrations to support old Authelia versions is a complex operation. A backup-always-stays-a-backup habit will save you at the most unexpected times.

A Healthy Backup Strategy

Backing up Authelia storage is no different from a regular database backup, with one mandatory addition: don't forget the encryption_key. Plan the backup as follows:

  • SQLite: just copy the db.sqlite3 file while Authelia is stopped, or use a consistent snapshot. Don't copy a file that's being actively written.
  • PostgreSQL: use pg_dump or a physical backup, then store the result in a separate location.
  • MySQL: use mysqldump with the same pattern.
Back up the PostgreSQL database
pg_dump -h localhost -U authelia authelia > authelia-backup.sql

Besides database dumps, Authelia provides export commands for user-specific data — useful when moving part of the data between instances, for example exporting TOTP configuration:

Export TOTP configuration
authelia storage user totp export
authelia storage user webauthn export

Production Performance Notes

For a single homelab instance, SQLite is almost always enough. But when users grow and you add Authelia instances (for high availability), consider the following:

  • Use PostgreSQL or MySQL: both backends support concurrent access from many instances safely, while SQLite isn't designed for that.
  • Pair with Redis: the database storage handles permanent data, Redis handles sessions. Both should share equally high availability infrastructure.
  • Avoid excessive writes: storage data is rarely written (only during enrollment, reset, and consent). Make sure the database is on reliable storage, because every write involves encryption if encryption_key is used.

Closing

Key points of this episode:

  • Storage holds permanent data: TOTP secrets, WebAuthn credentials, Duo device IDs, verification tokens, and OIDC consent.
  • SQLite for homelabs; PostgreSQL or MySQL for production and multi-instance.
  • encryption_key adds encryption-at-rest, but must be backed up along with the database.
  • Schema migrations run automatically at startup, with manual control via authelia storage migrate.
  • Database backup is the most important safety plan; backing up the encryption_key is its absolute requirement.

Now that the storage foundation is solid, it's time to turn on the second security layer you promised in episode 6: two_factor. In episode 9, you'll understand TOTP — the six-digit code that changes every 30 seconds — from how it works cryptographically to the enrollment process and its configuration.

Learn Authelia - Storage Backend | Learn Authelia