Linux + SQLite
Run oidc-exchange on one Linux host with SQLite for persistent storage. This deployment uses one binary, a configuration file, and a database file. It needs no external database service.
Optionally, store refresh token sessions in Lightning Memory-Mapped Database (LMDB). This adds a local session store without a network service.
A runnable example is in examples/linux-sqlite/.
When to use this
Section titled “When to use this”- You want a single server with no external database dependencies.
- You expect low to moderate traffic, such as hundreds of requests per second.
- You want to keep persistent data in one directory for backups.
- You want the option to store sessions in LMDB 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 enables write-ahead logging (WAL) and foreign key checks 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 a local key-value database designed for frequent reads. oidc-exchange looks up a session on each token refresh. LMDB reads session data through files mapped into memory.
[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 limits the LMDB memory map size. At roughly 500 bytes per session, 256 MB holds about 500,000 sessions. LMDB reserves this space and allocates it as needed.
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.targetSet ReadWritePaths=/var/lib/oidc-exchange to give the service 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”The service stores its database files in /var/lib/oidc-exchange/. Back up SQLite with:
# SQLite: use the .backup command for a consistent snapshotsqlite3 /var/lib/oidc-exchange/data/oidc-exchange.db ".backup /tmp/oidc-exchange-backup.db"To back up LMDB, stop the service and copy /var/lib/oidc-exchange/lmdb/.
LMDB sessions expire. Losing session data requires users to sign in again.
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.
- Scaling across hosts: Each host would have its own SQLite or LMDB database. Use a shared database to run instances across hosts.