Linux + SQLite
Run oidc-exchange on a single Linux host using SQLite for all persistent storage. No external database services needed. This is the simplest production deployment: one binary, one config file, one database file.
Optionally, use LMDB for session storage when you want faster session lookups without adding a network service.
A runnable example is in examples/linux-sqlite/.
When to use this
Section titled “When to use this”- Single-server deployment with no external database dependencies
- Low to moderate traffic (hundreds of requests per second)
- You want the simplest possible ops story: back up one directory, restore anywhere
- Optionally: use LMDB for faster session reads on the same server
Architecture
Section titled “Architecture” ┌──────────────┐ │ nginx │ │ (TLS term) │ └──────┬───────┘ │ ┌──────┴───────┐ │oidc-exchange │ └──┬───────┬───┘ │ │ ┌────────┴──┐ ┌─┴──────────┐ │ SQLite │ │ LMDB │ │ (users) │ │ (sessions) │ └────────────┘ └─────────────┘ optionalWithout LMDB, SQLite handles both users and sessions.
Prerequisites
Section titled “Prerequisites”- A Linux server with oidc-exchange binary (see build instructions)
- A writable directory for the SQLite database file
- (Optional) A writable directory for the LMDB environment
Step-by-step
Section titled “Step-by-step”1. Create directories
Section titled “1. Create directories”sudo mkdir -p /var/lib/oidc-exchange/datasudo mkdir -p /etc/oidc-exchangesudo chown -R oidc-exchange:oidc-exchange /var/lib/oidc-exchangeIf using LMDB for sessions:
sudo mkdir -p /var/lib/oidc-exchange/lmdbsudo chown oidc-exchange:oidc-exchange /var/lib/oidc-exchange/lmdb2. Generate a signing key
Section titled “2. Generate a signing key”openssl genpkey -algorithm ed25519 -out /etc/oidc-exchange/signing-key.pemchmod 600 /etc/oidc-exchange/signing-key.pem3. Configure (SQLite only)
Section titled “3. Configure (SQLite only)”Create /etc/oidc-exchange/config/production.toml:
[server]host = "127.0.0.1"port = 8080issuer = "https://auth.example.com"
[key_manager]adapter = "local"
[key_manager.local]private_key_path = "/etc/oidc-exchange/signing-key.pem"algorithm = "EdDSA"kid = "prod-1"
[repository]adapter = "sqlite"
[repository.sqlite]path = "/var/lib/oidc-exchange/data/oidc-exchange.db"
[audit]adapter = "stdout"durability = "observe"
[telemetry]enabled = trueexporter = "stdout"
[providers.google]adapter = "oidc"issuer = "https://accounts.google.com"client_id = "${GOOGLE_CLIENT_ID}"client_secret = "${GOOGLE_CLIENT_SECRET}"scopes = ["openid", "email", "profile"]# Origins Google's discovery document may name beyond the issuer's origin:endpoint_origins = ["https://oauth2.googleapis.com", "https://www.googleapis.com"]endpoint_origins pins which origins a provider’s discovery document is allowed to name; each entry must be a bare https://host[:port], and an unpinned origin logs a warning when discovered (see Identity Providers).
SQLite runs with WAL journal mode and foreign keys enabled automatically. The database file and tables are created on first startup.
4. Configure (SQLite + LMDB for sessions)
Section titled “4. Configure (SQLite + LMDB for sessions)”LMDB is an embedded key-value store optimized for read-heavy workloads. Session lookups (every token refresh) are the hottest path in oidc-exchange, and LMDB serves these from memory-mapped files with zero-copy reads.
[server]host = "127.0.0.1"port = 8080issuer = "https://auth.example.com"
[key_manager]adapter = "local"
[key_manager.local]private_key_path = "/etc/oidc-exchange/signing-key.pem"algorithm = "EdDSA"kid = "prod-1"
# Users in SQLite[repository]adapter = "sqlite"
[repository.sqlite]path = "/var/lib/oidc-exchange/data/oidc-exchange.db"
# Sessions in LMDB[session_repository]adapter = "lmdb"
[session_repository.lmdb]path = "/var/lib/oidc-exchange/lmdb"max_size_mb = 256
[audit]adapter = "stdout"durability = "observe"
[telemetry]enabled = trueexporter = "stdout"
[providers.google]adapter = "oidc"issuer = "https://accounts.google.com"client_id = "${GOOGLE_CLIENT_ID}"client_secret = "${GOOGLE_CLIENT_SECRET}"scopes = ["openid", "email", "profile"]The max_size_mb setting controls the LMDB memory map size. 256 MB is generous for session data: each session is roughly 500 bytes, so 256 MB supports ~500,000 concurrent sessions. The space is reserved but not allocated until used.
5. Create the environment file
Section titled “5. Create the environment file”cat > /etc/oidc-exchange/env <<'EOF'GOOGLE_CLIENT_ID=your-client-idGOOGLE_CLIENT_SECRET=your-client-secretEOF
chmod 600 /etc/oidc-exchange/env6. Create the systemd service
Section titled “6. Create the systemd service”[Unit]Description=oidc-exchange token serviceAfter=network-online.targetWants=network-online.target
[Service]Type=simpleUser=oidc-exchangeGroup=oidc-exchangeExecStart=/usr/local/bin/oidc-exchangeWorkingDirectory=/etc/oidc-exchangeRestart=on-failureRestartSec=5
EnvironmentFile=/etc/oidc-exchange/envEnvironment=OIDC_EXCHANGE_ENV=production
NoNewPrivileges=trueProtectSystem=strictProtectHome=trueReadOnlyPaths=/etc/oidc-exchangeReadWritePaths=/var/lib/oidc-exchangePrivateTmp=true
[Install]WantedBy=multi-user.targetNote ReadWritePaths=/var/lib/oidc-exchange: the service needs write access to the SQLite and LMDB data directories.
7. Install and start
Section titled “7. Install and start”sudo cp target/release/oidc-exchange /usr/local/bin/sudo useradd --system --no-create-home oidc-exchangesudo systemctl daemon-reloadsudo systemctl enable --now oidc-exchange8. Reverse proxy
Section titled “8. Reverse proxy”See the generic Linux server guide for the nginx configuration.
Backup
Section titled “Backup”All state lives in /var/lib/oidc-exchange/. To back up:
# SQLite: use the .backup command for a consistent snapshotsqlite3 /var/lib/oidc-exchange/data/oidc-exchange.db ".backup /tmp/oidc-exchange-backup.db"For LMDB, copy the directory while the service is running; LMDB’s copy-on-write design means readers never block writers and file copies are crash-consistent. Alternatively, stop the service and copy /var/lib/oidc-exchange/lmdb/.
LMDB session data is ephemeral (sessions expire). Losing it only forces users to re-authenticate.
Limitations
Section titled “Limitations”- Single-server only: SQLite and LMDB do not support concurrent access from multiple processes on different hosts. For multi-server deployments, use PostgreSQL or DynamoDB.
- Write throughput: SQLite with WAL handles hundreds of writes per second. If you need thousands, consider PostgreSQL.
- No horizontal scaling: you cannot add more oidc-exchange instances behind a load balancer with SQLite/LMDB. Each instance would have its own database.