Database setup
FastAuth creates its tables, six standard roles, and a superadmin user for you, from the command line or at app startup.
What gets created#
FastAuth works with your existing SQLModel engine rather than a database of its own, so initialization adds a small number of tables alongside whatever you already have.
| Table | What it holds |
|---|---|
user | One row per account: username, email, hashed_password, disabled, email_verified, token_version |
role | One row per role, with a name and description |
userrolelink | The join between users and roles: one row per role a user holds |
Three columns on user do more work than their names suggest:
hashed_passwordis a bcrypt hash, never a password. It includes the salt, which is why the rows look like random noise even for identical passwords. See how auth works for what that means.disabledlocks an account out at every step — login, refresh, and every protected route — without deleting anything.token_versionis stamped into each issued token. Raising it invalidates every token that user holds, which is howPOST /logout/alland password changes sign someone out everywhere.
CLI initialization#
Where the CLI looks for settings#
You rarely need to pass --db-url or --secret-key, because the CLI finds
them. It checks these sources in order and stops at the first hit:
| Order | Source |
|---|---|
| 1 | The flags you passed, --db-url and --secret-key |
| 2 | Real environment variables: DATABASE_URL, SECRET_KEY |
| 3 | A .env file in the current or parent directory |
| 4 | The app file you named |
| 5 | config.py, settings.py, db.py, database.py, models.py beside it |
For the last two it reads assignments directly, and if that finds nothing it
imports the module and inspects it — so a live engine object works even when
its URL is built at runtime.
The environment always beats .env. A .env file only fills in what the
environment has not already set. This matters in deployment: if a .env
could override a real SECRET_KEY, a stale file left in an image would sign
every token with the wrong key, and nothing would tell you. Before v0.8.0
.env did win, so upgrade if you deploy with both.
Programmatic initialization#
Running it in the app's lifespan means a fresh checkout or a new deployment comes up ready, with no separate setup step to forget.
Each step is idempotent — running it twice leaves the same result as running it once. Tables are only created if missing, roles are skipped if already present, and the superadmin is only created when no admin exists. So calling it on every boot is safe, and there is no need to guard it with a "first run" check.
Pass admin_username and admin_password explicitly during app startup.
Otherwise FastAuth prompts on the console and startup blocks waiting for
input — which, on a server with no attached terminal, looks exactly like a
hang.
Schema changes later#
SQLModel's create_all only creates tables that do not exist. It never alters
one that does. Add a column to your user model and it will simply not appear,
and you will get a no such column error at runtime.
While developing against SQLite, deleting the database file and letting it
rebuild is the fastest fix. Once you have data worth keeping, use
Alembic migrations. The same applies to
upgrading FastAuth itself: v0.6.0 added email_verified and token_version,
so databases created before it need those columns added. See
production.