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.

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.
The storage backend is Authelia's long-term memory. Among its contents:
In other words: whatever Authelia must remember after the login process completes lives in this database. Losing the database means losing access.
Authelia supports three storage options:
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.
In general, storage configuration follows the same pattern: server address, database name, user, and password.
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.
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:
authelia storage migrate up
authelia storage migrate history
authelia storage migrate list-upmigrate 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:
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.
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:
db.sqlite3 file while Authelia is stopped, or use a consistent snapshot. Don't copy a file that's being actively written.pg_dump or a physical backup, then store the result in a separate location.mysqldump with the same pattern.pg_dump -h localhost -U authelia authelia > authelia-backup.sqlBesides database dumps, Authelia provides export commands for user-specific data — useful when moving part of the data between instances, for example exporting TOTP configuration:
authelia storage user totp export
authelia storage user webauthn exportFor a single homelab instance, SQLite is almost always enough. But when users grow and you add Authelia instances (for high availability), consider the following:
encryption_key is used.Key points of this episode:
encryption_key adds encryption-at-rest, but must be backed up along with the database.authelia storage migrate.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.