@@ -17,12 +17,12 @@ Configure authentication and authorization for Hadrian in `hadrian.toml` using t
1717
1818Hadrian uses a single ` [auth.mode] ` to control authentication for both the API and the web UI. Select exactly one mode.
1919
20- | Mode | ` type ` | API Keys | IdP Sessions | Identity Headers | Use Case |
21- | --------- | --------- | -------- | ------------ | ---------------- | ---- ------------------------------ |
22- | None | ` none ` | No | No | No | Local development |
23- | API Key | ` api_key ` | Yes | No | No | Programmatic access only |
24- | IdP | ` idp ` | Yes | Yes | No | Full deployment with SSO + API |
25- | IAP | ` iap ` | Yes | No | Yes | Behind an identity-aware proxy |
20+ | Mode | ` type ` | API Keys | IdP Sessions | Identity Headers | Use Case |
21+ | ------- | --------- | -------- | ------------ | ---------------- | ------------------------------ |
22+ | None | ` none ` | No | No | No | Local development |
23+ | API Key | ` api_key ` | Yes | No | No | Programmatic access only |
24+ | IdP | ` idp ` | Yes | Yes | No | Full deployment with SSO + API |
25+ | IAP | ` iap ` | Yes | No | Yes | Behind an identity-aware proxy |
2626
2727### None
2828
@@ -985,6 +985,93 @@ admin_identities = ["alice@acme.com"]
985985 and organizations are not modified.
986986</Callout >
987987
988+ ### Bootstrap API Key Generation
989+
990+ Create an API key during bootstrap for programmatic access:
991+
992+ ``` toml
993+ [auth .bootstrap ]
994+ api_key = " ${HADRIAN_BOOTSTRAP_KEY}"
995+ auto_verify_domains = [" acme.com" ]
996+
997+ [auth .bootstrap .initial_org ]
998+ slug = " acme-corp"
999+ name = " Acme Corporation"
1000+ admin_identities = [" admin@acme.com" ]
1001+
1002+ [auth .bootstrap .initial_api_key ]
1003+ name = " production-api-key"
1004+ ```
1005+
1006+ | Setting | Type | Description |
1007+ | ---------------------- | ------ | ------------------------------------------------------------- |
1008+ | ` initial_api_key.name ` | string | Name for the auto-created API key (scoped to the initial org) |
1009+
1010+ The generated API key is printed to stdout on first creation. Subsequent runs skip creation if a key with the same name already exists.
1011+
1012+ ### Bootstrap SSO Configuration
1013+
1014+ Pre-configure SSO for the initial organization directly in the config file, avoiding manual Admin UI setup:
1015+
1016+ ``` toml
1017+ [auth .bootstrap .initial_org ]
1018+ slug = " acme-corp"
1019+ name = " Acme Corporation"
1020+ admin_identities = [" admin@acme.com" ]
1021+
1022+ [auth .bootstrap .initial_org .sso ]
1023+ provider_type = " oidc"
1024+ issuer = " https://accounts.google.com"
1025+ client_id = " ${OIDC_CLIENT_ID}"
1026+ client_secret = " ${OIDC_CLIENT_SECRET}"
1027+ redirect_uri = " https://gateway.example.com/auth/callback"
1028+ discovery_url = " https://accounts.google.com/.well-known/openid-configuration"
1029+ allowed_email_domains = [" acme.com" ]
1030+ ```
1031+
1032+ | Setting | Type | Description |
1033+ | --------------------------- | -------- | ----------------------------------------------- |
1034+ | ` sso.provider_type ` | string | ` "oidc" ` or ` "saml" ` |
1035+ | ` sso.issuer ` | string | IdP issuer URL |
1036+ | ` sso.client_id ` | string | OAuth client ID |
1037+ | ` sso.client_secret ` | string | OAuth client secret (stored in secrets manager) |
1038+ | ` sso.redirect_uri ` | string | OAuth redirect URI |
1039+ | ` sso.discovery_url ` | string | OIDC discovery endpoint (optional) |
1040+ | ` sso.allowed_email_domains ` | string[ ] | Restrict SSO login to these email domains |
1041+
1042+ Domains listed in both ` auto_verify_domains ` and ` sso.allowed_email_domains ` are automatically verified during bootstrap.
1043+
1044+ ### Bootstrap CLI
1045+
1046+ Run bootstrap as a standalone CLI command instead of at server startup. This is the recommended approach for GitOps and IaC workflows:
1047+
1048+ ``` bash
1049+ # Run bootstrap against the database
1050+ hadrian bootstrap --config hadrian.toml
1051+
1052+ # Preview what would be created without making changes
1053+ hadrian bootstrap --config hadrian.toml --dry-run
1054+ ```
1055+
1056+ The ` hadrian bootstrap ` command:
1057+
1058+ - Connects directly to the database (no HTTP server started)
1059+ - Runs pending migrations before bootstrapping
1060+ - Creates the initial organization, SSO config, and API key as specified in ` [auth.bootstrap] `
1061+ - Is fully idempotent — safe to run repeatedly (skips resources that already exist)
1062+ - Prints the generated API key to stdout on first creation (pipe to a secret manager or file)
1063+
1064+ ``` bash
1065+ # Example: capture the generated API key
1066+ API_KEY=$( hadrian bootstrap --config hadrian.toml 2> /dev/null)
1067+ echo " Generated key: $API_KEY "
1068+ ```
1069+
1070+ <Callout type = " info" >
1071+ Use ` --dry-run ` to verify your bootstrap configuration before applying it to a production
1072+ database.
1073+ </Callout >
1074+
9881075## Emergency Access Configuration
9891076
9901077Emergency access provides break-glass admin access when SSO is unavailable. Unlike bootstrap mode, emergency access remains available indefinitely (when enabled) and is designed for disaster recovery scenarios.
@@ -1212,6 +1299,9 @@ admin_identities = ["admin@acme.com"]
12121299slug = " acme-corp"
12131300name = " Acme Corporation"
12141301admin_identities = [" admin@acme.com" ]
1302+
1303+ [auth .bootstrap .initial_api_key ]
1304+ name = " admin-key"
12151305```
12161306
12171307### Multi-Org with Per-IdP API Authentication
0 commit comments