Self-Hosting
This guide is for anyone running the logi server themselves. If you only want to integrate OAuth, the managed IdP (https://1pass.dev) path in the Quickstart is much faster.
When you need self-hosting
- Contributor: you modify or contribute to the logi server code.
- Enterprise: you need to run an IdP in isolation, serving only your internal users.
- Compliance: user data must not leave your own infrastructure (for example, a domestic data center or on-prem).
- Local integration testing: reproducible scenarios that the managed IdP's sandbox alone can't cover (for example, time manipulation or direct DB inspection).
For most RP integrations, the sandbox tier of the managed IdP is enough.
Requirements
| Component | Version |
|---|---|
| Ruby | 3.3+ |
| Rails | 8.0+ |
| PostgreSQL | 16+ |
| Redis | 7+ (for the SolidQueue / rate-limit backend) |
| Node.js | 20+ (for building JS assets) |
Required environment variables:
SECRET_KEY_BASE=<output of rails secret>
DATABASE_URL=postgres://localhost/logi_development
RAILS_ENV=development
# OAuth provider (Sign in with Apple / Google) — optional; without it, email login only
APPLE_TEAM_ID=...
APPLE_KEY_ID=...
APPLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
APPLE_DEFAULT_CLIENT_ID=com.example.app
GOOGLE_OAUTH_CLIENT_ID=...
GOOGLE_OAUTH_CLIENT_SECRET=...
# APNs (mobile push approval — optional)
APNS_KEY_ID=...
APNS_TEAM_ID=...
APNS_KEY_PATH=/path/to/AuthKey_XXXXX.p8
APNS_TOPIC=com.example.app
APNS_TOPIC_MACOS=com.example.app.mac # if the macOS app is a separate bundle
APNS_ENV=development
# OIDC discovery (the self-hosted issuer URL in production)
OIDC_ISSUER=https://idp.example.com
APP_HOST=idp.example.com # :host for Rails default_url_options
LOGI_API_HOST=api.example.com # when splitting hosts — the quickstart/registering-apps host gate
LOGI_ADMIN_API_HOST=admin.example.com # admin route gate (optional)
# WebAuthn (Passkey)
WEBAUTHN_ORIGIN=https://idp.example.com
WEBAUTHN_RP_ID=example.com
# Android App Links (assetlinks.json) — when running a mobile app
ANDROID_APP_CERT_SHA256=AB:CD:...
# Operational toggles (recommended in production)
ENFORCE_CANONICAL_RESOLUTION=true # enforce canonical_sub after a merge (see the account-merge guide for details)
SOLID_QUEUE_IN_PUMA=true # run SolidQueue inside puma without a separate worker process
JOB_CONCURRENCY=1 # SolidQueue concurrency
LOGI_BETA_AUTO_APPROVE=false # public-client beta auto-approval (beta period only)
# External SaaS — optional, depending on the features you use
RESEND_API_KEY=re_... # email delivery
TELEGRAM_ADMIN_BOT_TOKEN=... # production-promotion alerts
TELEGRAM_ADMIN_CHAT_ID=...
FCM_PROJECT_ID=... # Android push
FCM_SERVICE_ACCOUNT_JSON_PATH=/path/to/sa.jsonProduction host separation
The managed IdP (https://1pass.dev) splits the OAuth/OIDC endpoints onto api.1pass.dev and the console / developer portal onto start.1pass.dev. If you want the same host separation in your self-hosted production, set up LOGI_API_HOST plus the console host environment variables separately; if you'd rather run everything on a single host, point them all at the same domain and the host_constraint simply passes through (in development/test environments, it automatically runs on a single host).
Setup
Source access is provided during onboarding/partnership — contact
support@1pass.dev. Replace<your-logi-repo>below with the repository URL you receive.
git clone <your-logi-repo>
cd logi
bundle install
bin/rails db:setup
bin/rails serverThe server runs at http://localhost:3000. A separate worker process isn't needed in development, since SolidQueue runs inside puma.
Registering your first OAuth app (local)
In a self-hosted environment, every quickstart command works against $LOGI=http://localhost:3000.
1) Create a developer account and sign in
export LOGI="http://localhost:3000"
curl -s -c /tmp/cookies.txt -X POST "$LOGI/developer/signup" \
-H 'Content-Type: application/json' \
-d '{"user": {"email_address": "dev@example.com", "password": "correctHorseBatteryStaple"}}'2) Issue a Personal API Key
/api/v1/applications uses PAK (Personal API Key) Bearer authentication. Issue a PAK once using the session cookie:
curl -s -b /tmp/cookies.txt -X POST "$LOGI/api/v1/me/api_keys" \
-H 'Content-Type: application/json' \
-d '{
"name": "Quickstart CLI",
"scopes": ["apps:manage", "apps:read"]
}' | tee /tmp/pak.json
PAK=$(python3 -c 'import json; print(json.load(open("/tmp/pak.json"))["plaintext"])')3) Register the OAuth app
curl -s -X POST "$LOGI/api/v1/applications" \
-H "Authorization: Bearer $PAK" \
-H 'Content-Type: application/json' \
-d '{
"application": {
"name": "My Local App",
"redirect_uris": ["http://localhost:4000/auth/callback"],
"allowed_scopes": ["profile", "email"]
}
}' | tee /tmp/app.json
CLIENT_ID=$(python3 -c 'import json; print(json.load(open("/tmp/app.json"))["client_id"])')
CLIENT_SECRET=$(python3 -c 'import json; print(json.load(open("/tmp/app.json"))["client_secret"])')You can also create it with a form on the web portal (http://localhost:3000/developer/applications/new).
4) Sign up a test end user
curl -s -c /tmp/user-cookies.txt -X POST "$LOGI/signup" \
-H 'Content-Type: application/json' \
-d '{"user": {"email_address": "user@example.com", "password": "correctHorseBatteryStaple", "device_uuid": "demo-device-1"}}'From here, follow steps 4–7 of the Quickstart (PKCE → authorize → token → userinfo) as-is, but adjust the environment variables to your self-hosted values:
export LOGI="http://localhost:3000"
export CLIENT_ID="logi_..." # the value from step 3) above
export CLIENT_SECRET="..." # the value from step 3) above
export REDIRECT="http://localhost:4000/auth/callback"Operational considerations
Additional items to review when you self-operate:
- Webhook signing key rotation — key expiry and rotation cadence
- Threat Model — Account Merge — the merge attack surface
- Rate Limits — the Redis-based limiting policy
- Refresh Token policy — handling Apple/Google rotation
When you need help
For installation issues, use GitHub Issues; for operational discussions, please contact us through the admin contact channel (FAB).