Installation
This page builds a working Axum server with email and password authentication on SQLite. Every later page assumes this setup and shows only what changes.
Requirements: Rust 1.99 or newer (edition 2024), and a Tokio runtime. The default build uses OpenSSL (native-tls); see Cargo features for Rustls.
1. Add the dependencies
Section titled “1. Add the dependencies”Install Alibi 0.1.1 from crates.io:
[dependencies]alibi = { version = "0.1.1", features = ["axum"] }axum = "0.8"tokio = { version = "1", features = ["full"] }serde = { version = "1", features = ["derive"] }serde_json = "1"chrono = { version = "0.4", features = ["serde"] }sqlx = { version = "0.9", default-features = false, features = ["sqlite", "chrono", "json", "derive"] }serde, serde_json, chrono and sqlx are needed because the generated models derive from them. Commit your application’s Cargo.lock for reproducible builds, and use the matching alibi-cli version shown below.
2. Set environment variables
Section titled “2. Set environment variables”export BETTER_AUTH_SECRET="$(openssl rand -base64 32)"export BETTER_AUTH_URL="http://localhost:3000"export DATABASE_URL="sqlite://auth.db?mode=rwc"| Variable | Purpose |
|---|---|
BETTER_AUTH_SECRET |
Signs cookies and tokens and derives encryption keys. At least 32 characters; keep it out of source control. |
BETTER_AUTH_URL |
The public origin of the server. Used for cookie security, OAuth callbacks and links in emails. |
DATABASE_URL |
SQLite or PostgreSQL URL. |
The library never reads these itself and does not load .env files; the code below reads them explicitly. To rotate or version secrets, see Secrets and key rotation.
3. Generate the schema
Section titled “3. Generate the schema”cargo install alibi-cli --version 0.1.1 --lockedalibi generate -o src/auth_schema.rsThe generated file is yours to keep and edit. It contains:
user,session,accountandverificationmodels (mod user { pub struct Model … }and so on) derivingsqlx::FromRowandAuthEntity;AppAuthSchema, a unit struct implementingAuthSchemathat names those four models;run_app_migrations, which creates the tables for a new database.
Plugins that need columns or tables (two-factor, organization, admin, API keys, …) are added with --plugins; see Database and the CLI reference.
4. Build the instance and mount it
Section titled “4. Build the instance and mount it”mod auth_schema;
use auth_schema::{AppAuthSchema, run_app_migrations};use axum::Router;use alibi::integrations::axum::AxumIntegration;use alibi::plugins::EmailPasswordPlugin;use alibi::sqlx::{SqlxPool, SqlxStore};use alibi::{AuthConfig, BetterAuth};use std::sync::Arc;
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let config = AuthConfig::new(std::env::var("BETTER_AUTH_SECRET")?) .base_url(std::env::var("BETTER_AUTH_URL")?); let pool = SqlxPool::connect(&std::env::var("DATABASE_URL")?).await?; run_app_migrations(&pool).await?; let store = SqlxStore::<AppAuthSchema>::new(config.clone(), pool);
let auth = Arc::new( BetterAuth::<AppAuthSchema>::new(config) .store(store) .plugin(EmailPasswordPlugin::new().enable_signup(true)) .build() .await?, );
let app = Router::new() .nest("/api/auth", auth.clone().axum_router()) .with_state(auth); let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?; axum::serve(listener, app).await?; Ok(())}What each step does:
AuthConfigis created once and given to both the store and the builder, so they agree on session and field policy.SqlxPool::connectselects SQLite or PostgreSQL from the URL scheme.run_app_migrationscreates the generated tables. It is meant for new local databases; use your own versioned migrations as the schema evolves (see Database)..plugin(...)registers features. Credential sign-in is disabled untilEmailPasswordPluginis registered, and signup is off untilenable_signup(true)..build().awaitvalidates the configuration, initializes every plugin and returns aBetterAuth<AppAuthSchema>.axum_router()returns the auth routes. Nest it atAuthConfig::base_path—/api/authunless you change it.
5. Try it
Section titled “5. Try it”cargo run# in another terminal:curl http://localhost:3000/api/auth/ok{"ok":true}Continue with Basic usage to sign up, sign in and read the session.
Production checklist
Section titled “Production checklist”- Use a long random
BETTER_AUTH_SECRETand anhttps://BETTER_AUTH_URL. HTTPS turns onSecurecookies and the__Secure-cookie prefix. - List every browser origin that calls the API in
AuthConfig::trusted_origin; see Security. - Behind a reverse proxy, configure
advanced.ip_addressso rate limits and session metadata see real client IPs; see Rate limiting. - Replace
run_app_migrationswith your own migrations. - Run more than one instance? Use shared rate-limit storage and, if you use caches or secondary storage, a shared backend (Secondary storage).
Related upstream topic: Installation.