realm
Manage realms, the isolated tenants that hold clients, users, roles, and credentials.
ferris-ctl realm <subcommand>
Read operations target the realm resolved from your context (or --realm). See Authentication.
realm list
List all realms.
ferris-ctl realm list
Table columns: NAME, ID.
realm get
Show a single realm’s details.
ferris-ctl realm get <name>
| Argument | Required | Description |
|---|---|---|
<name> | yes | Realm name |
realm create
Create a new realm.
ferris-ctl realm create <name>
| Argument | Required | Description |
|---|---|---|
<name> | yes | Name of the realm to create |
realm delete
Delete a realm. This prompts for confirmation, since it also removes the realm’s clients, users, and roles.
ferris-ctl realm delete <name> [--force]
| Argument | Required | Description |
|---|---|---|
<name> | yes | Name of the realm to delete |
--force / -f | no | Skip the confirmation prompt |
Confirmation in scripts
Without --force, the command refuses to run in a non-interactive shell rather than deleting silently. Pass --force (or -f) in CI and automation.
realm role
Manage the roles of a realm, or the roles scoped to one of its clients. Every subcommand takes --realm to target a realm other than the context default, and --client <client_id> to work on that client’s roles instead of the realm’s.
realm role create
ferris-ctl realm role create <name> [--description <text>] [--permission <name>]... [--realm <realm>] [--client <client_id>]
| Argument | Required | Description |
|---|---|---|
<name> | yes | Role name |
--description | no | Free-text description |
--permission | no | A permission granted by the role. Repeat the flag for several |
--realm | no | Realm (defaults to the context realm) |
--client | no | Create a client role scoped to this client id, instead of a realm role |
Permissions are passed by their snake_case name, for example manage_users. See the permissions reference for the full list.
ferris-ctl realm role create user-admin \
--description "Create and update users" \
--permission manage_users \
--permission query_users \
--permission view_users
ferris-ctl realm role create service-reader --client backend
Unknown permission names are dropped
A permission name FerrisKey does not recognize is ignored rather than rejected, so a typo produces a role that grants nothing. Check the created role with realm role get after creating it.
realm role list
ferris-ctl realm role list [--realm <realm>] [--client <client_id>]
Lists realm roles, or the roles of --client when given. Table columns: NAME, ID.
realm role get
ferris-ctl realm role get <name> [--realm <realm>] [--client <client_id>]
realm role delete
ferris-ctl realm role delete <name> [--realm <realm>] [--client <client_id>] [--force]
| Argument | Required | Description |
|---|---|---|
<name> | yes | Role name |
--realm | no | Realm (defaults to the context realm) |
--client | no | Delete a client role instead of a realm role |
--force / -f | no | Skip the confirmation prompt (required in non-interactive shells) |
realm import
Import a realm (its settings, roles, clients, and users) from a description file, a live Keycloak, or a live Zitadel instance.
ferris-ctl realm import --from <kind> [source flags] [--target-realm <name>] [--dry-run]
| Flag | Description |
|---|---|
--from | Source kind: config, keycloak, or zitadel (optional if --source-ref is given) |
--source-ref | Name of a stored source; inline flags below override its values |
--file | Path to a realm description file (required for --from config); .yaml, .yml, or .toml |
--source-url | Base URL of the source instance (Keycloak / Zitadel) |
--source-realm | Source realm name (Keycloak) |
--source-org | Source organization id (Zitadel); sent as the x-zitadel-orgid header |
--source-client-id | Client id for source authentication (Keycloak client credentials) |
--source-client-secret | Client secret for source authentication (Keycloak) |
--source-token | Bearer token / personal access token (Zitadel PAT, or a ready Keycloak token) |
--target-realm | Override the name of the realm created in FerrisKey (defaults to the source realm name) |
--dry-run | Resolve and print the planned realm without calling the FerrisKey API |
ferris-ctl realm import --from config --file examples/realm.yaml --dry-run -o yaml
ferris-ctl realm import --from keycloak \
--source-url https://keycloak.example.com \
--source-realm acme \
--source-client-id admin-cli \
--source-client-secret "$KC_SECRET" \
--target-realm acme
The Import section covers each source in full, including what is and isn’t migrated.
Re-running imports is safe
Imports are idempotent: entities that already exist are skipped with a warning, so you can re-run an import after fixing the source.