Configuration
Your dashboard is a file.
Clerk configures your auth through a hosted dashboard — the settings that govern your login live on their servers. Signet configures through one file, signet.toml, that lives in your git repository and travels inside the binary. Every feature is compiled in; there is no toggle in someone else’s console.
# signet.toml — the whole configuration surface, in your repo.
# Secrets are env:/file: refs, never literals in the file.
[server]
base_url = "https://auth.example.com"
trusted_origins = ["https://app.example.com"]
[database]
adapter = "postgres" # your Postgres — Clerk has no such key
# dsn supplied out-of-band via env:SIGNET_DATABASE_URL
[session]
expires_in = 604800 # 7 days, in seconds
fresh_age = 900 # step-up window for sensitive actions
[password]
min = 12
max = 128
[rate_limit]
window = 10
max = 100
[[rate_limit.rules]]
path = "/sign-in/email" # throttle the door you most want bounded
window = 60
max = 5
[lockout]
max_failures = 5
window = 600 # seconds; state persists in Postgres
lock_duration = 900
backoff_multiplier = 2
max_lock_duration = 86400
[email_policy]
allow = ["example.com", "*.partners.example"]
block = ["blocked.example", "abuse@example.com"]
[disposable_email]
enabled = true
extra_deny = ["throwaway.example"]
# list_path = "/etc/signet/disposable.txt" # replaces bundled list
[plugins]
haveibeenpwned = true # breach-password check (HIBP)
[[social_providers]]
id = "google"
client_id = "env:GOOGLE_CLIENT_ID"
client_secret = "env:GOOGLE_CLIENT_SECRET"
[events]
url = "https://app.example.com/webhooks/signet"
secret = "env:SIGNET_EVENTS_SECRET" # must resolve to >=32 characters
# Generate the signing secret with: openssl rand -hex 32
[admin]
enabled = true # the /admin operator surface
# key supplied via env:SIGNET_ADMIN_KEYThe difference
Settings you hold, not settings you rent.
A hosted dashboard is convenient right up to the moment it becomes the thing that owns you. The rules that decide who gets through your front door — rate limits, password policy, which social providers are trusted, where session events are sent — sit in a vendor’s console, changeable by whoever holds that account, invisible to your version control, and gone the day the plan changes.
Signet turns every one of those settings into a key in signet.toml. The file sits in your repository next to your code. Change a rate-limit rule and it is a diff; review a new OAuth provider and it is a pull request; roll back a bad password policy and it is a git revert. Nothing about your auth is configured anywhere you cannot see, and the same file boots the same instance on an air-gapped host with no network to a console at all.
The mapping
Every dashboard toggle, as a key you own.
Each row pairs a Clerk hosted-dashboard capability with the real signet.toml key that does the same job. Every key traces to the generated config reference a running instance serves from inside the binary — if it is not in that reference, it is not on this page.
| Clerk dashboard | signet.toml | What the key configures |
|---|---|---|
| Account lockout / cooldown | [lockout] | Persistent per-email failed-attempt state: max_failures, window, initial lock_duration, capped exponential backoff_multiplier, max_lock_duration, and lock_level_decay. |
| Email allowlist / blocklist | [email_policy] | Deny-first allow/block entries in exact-email, apex-domain, or *.subdomain form. Block wins; a non-empty allowlist then gates every address. |
| Disposable-email blocking | [disposable_email] | On by default for new identities with a versioned bundled list. Add extra_deny/allow carve-outs, or use list_path to replace the snapshot with a local one-domain-per-line file. |
| Rate-limit rules | [rate_limit] [[rate_limit.rules]] | A default window/max, plus one [[rate_limit.rules]] block per path (path, window, max) — throttle /sign-in/email harder than the rest. |
| Social connections | [[social_providers]] | One block per provider: id, client_id, client_secret, the OAuth endpoints, and a pkce flag. google and github carry built-in defaults; a custom id declares its own endpoints. |
| Session lifetime | [session] | expires_in, update_age, and fresh_age — all in seconds. fresh_age is the step-up window that gates sensitive actions. |
| Password rules | [password] | min and max length (8–128 by default), plus the scrypt_concurrency cost factor. |
| Breach-password protection | [plugins] haveibeenpwned | Toggle the Have I Been Pwned check; hibp_range_endpoint points it at a self-hosted mirror so even that lookup stays inside your walls. |
| Webhook endpoints (Clerk: Svix) | [events] | url and secret (HMAC-SHA256, minimum 32 characters; generate with openssl rand -hex 32), with dead_letter for replay — the user.created, account.locked, session.created, and session.revoked event stream. |
| Email / SMTP settings | [delivery] [delivery.smtp] [delivery.webhook] | mode (smtp, webhook, or none) and dead_letter; SMTP host/port/username/password/from, or a signed-JSON webhook url/secret. |
| Allowed origins & paths | [server] | base_url, the API base_path, and extra trusted_origins for CORS and callback validation. |
| OAuth proxy | [plugins] oauth_proxy | A single toggle for the OAuth proxy plugin. |
| Admin / dashboard access | [admin] | enabled turns on the /admin dashboard and /admin/v1; the admin key (≥ 32 chars) is supplied out-of-band via SIGNET_ADMIN_KEY. |
| User impersonation & admin roles — Clerk meters this | [admin_plugin] | impersonation_session_duration time-boxes an impersonated session (default 3600s, 60–86400) and allow_impersonating_admins gates impersonating other admins; admin_roles, admin_user_ids, roles, and default_role decide who holds admin permissions. Every impersonation is audited. |
| Auto sign-in after sign-up | auto_sign_in (top level) | One boolean: sign a new user in immediately after sign-up rather than requiring a separate sign-in. |
| Where your data lives — no Clerk equivalent | [database] | adapter, dsn, migrate, max_connections. Clerk has no such setting because your users live in their database; here they live in yours. |
signet.toml key today, and we would rather you find that out from us than from a config file that ignores you. Every row traces to the generated reference a running instance serves from inside its own binary.Sources: the generated config-reference.md (from the *FileConfig structs) and the Clerk parity audit, retrieved 2026-07-21.
The payoff
Config-as-file is the sovereignty story, stated plainly.
A hosted dashboard gives you none of the things a file in version control gives you for free:
signet.toml boots the same instance anywhere — on a colleague’s laptop, in CI, or on a sealed host with no route to anyone’s dashboard.This is the same ownership the rest of Signet is built on: your users, sessions, and secrets in your own PostgreSQL, and now the configuration that governs them in your own repository. Owning auth, in depth →
The config travels with the binary.
Every deployed instance serves its own generated config reference at /docs — the same keys you see here, never drifted from the build you run. Get an instance and write the file.