CodamAIDocs
Topicdone

Cold start of an installation

Migrations, bootstrap (platform roles, first tenant, first administrator), intake of the declarations, reconciliation of roles and groups, in this order.

Variants
bootstrap onbootstrap offfirst administrator must exist in Keycloakembeddedstandalone

What this is about

A cold start means an installation comes up in a way that lets it answer the first real request afterwards. Between “process started” and “ready” there are several steps, and they happen in a fixed order.

This page describes the sequence across both modules. What the individual switches mean is under Configuration decides what runs.

The timeline

flowchart LR
    A["1 Schema<br/>create and raise tables"] --> B["2 Context<br/>build beans, check settings"]
    B --> C["3 Bootstrap<br/>platform roles, first tenant,<br/>first administrator"]
    C --> D["4 Reconciliation<br/>realm roles, declarations, groups"]
    D --> E["5 Timers<br/>start if switched on"]
    E --> F(["ready for the first request"])
    classDef stufe fill:#8e24aa,stroke:#8e24aa,color:#fff
    classDef ziel fill:#4d7c0f,stroke:#4d7c0f,color:#fff
    class A,B,C,D,E stufe
    class F ziel

The line between 3 and 4 is not a detail: bootstrap and reconciliation hang on different events of the application start. The bootstrap runs as a startup runner right after the application has come up; the reconciliation only once the application reports itself as ready. The bootstrap is therefore always finished first, and it has to be: it writes the roles into the catalog that the reconciliation then leaves alone.

The five stages one by one

A cold start from top to bottom
  1. 1
    CIAS→Database
    1 Schema. The tables are created or raised before Hibernate ever looks at them
    With the starter, one migration run per CIAS module; without it, through the host's persistence. Details under Databases and schemas.
  2. 2
    CIAS
    2 Context. Spring builds the beans. Every setting CIAS would otherwise have to guess is checked now
    Who answers the tenant gate, the operating mode of the data layer, the list of modules with their names and sources, the reader role for GET /cias/fetch. A missing setting fails here, with its name in the message.
  3. 3
    CIAS→Database
    3 Bootstrap. An empty installation gets its platform roles, its first tenant and its first administrator
    Only when codamai.cias.bootstrap.enabled is true. Everything in it can be repeated: what is already there stays as it is.
  4. 4
    CIAS→Keycloak
    4 Reconciliation. First the installation's realm roles, then every module's declaration, then the groups
    Only when codamai.cias.authorization.startup.enabled is true. This pass never throws: if Keycloak is away or a module cannot be reached, it is reported and the application starts anyway.
  5. 5
    CIAS
    5 Timers. The background passes begin, where they are switched on
    Result: The application accepts requests. The first customer goes through the tenant gate.

Stage 2: what fails the start

Building the context is where most mistakes surface — deliberately, because here a mistake is still a line in a file and not a service without permissions.

What is checked while the context is built
SettingIf it is missing or wrong
codamai.cias.tenancy.lookupThe start fails. Without it nobody would answer the tenant gate
codamai.persistence.tenant.modeThe start fails wherever there is CDMS persistence
codamai.cdms.cias.reader-roles in CDMSThe start fails. An explicitly empty value is allowed and means nobody
a module in the declaration list without a name, or with a duplicate nameThe start fails. The name is what a role belongs to
a module with bean and url, or with neitherThe start fails. Exactly one of them says where the declaration is
a bean this application does not haveThe start fails, with the bean name in the message
a module with url but without a reader-tokenThe start fails. The endpoint wants a reader role
a migration location that carries no scriptsThe start fails. A typo in the location would otherwise migrate nothing, quietly
Keycloak happens to be unreachableNot a start failure. That surfaces in stage 4 and is reported there

Stage 3: what the bootstrap does

A fresh installation has an empty role catalog. Nothing can fill that catalog from the outside: defining a role takes a platform administrator, and who administers the platform is what the catalog says. That circle is broken in exactly one place, on the first start.

The bootstrap, step by step
  1. 1
    CIAS
    gives itself a caller context carrying this installation's platform roles for the duration of the run, and clears it afterwards
    The same seam a validated token would take. It is confined to one method, it runs once, and it writes down what it did.
  2. 2
    CIAS
    adds every configured role that is not in the catalog yet
    At realm level and owned by no module. That is why no reconciliation ever retires them: the reconciliation compares per module, and a role nobody owns is left alone by every module's silence. Typically only the two roles that cross all modules stand here.
  3. 3
    CIAS
    creates the first tenant, if one is configured and does not exist yet
    Through the same path as every later creation, provisioning included. See A new tenant, end to end.
  4. 4
    CIAS→Keycloak
    looks for the account behind the configured administrator address
  5. 5
    CIAS
    There is no such account → the start fails
    CIAS holds no credentials and therefore cannot create an account. An address with nobody behind it is a statement that does not add up — it is not skipped.
  6. 6
    CIAS→Keycloak
    grants the platform roles to that account
    Result: The installation has a catalog, possibly a tenant, and a person who can sign in and carry on.

Stage 4: what the reconciliation does

The startup reconciliation
  1. 1
    CIAS→Keycloak
    creates the realm roles the installation names in its configuration
    These never come from a declaration. Realm level is what crosses all modules, and a module cannot see the consequences of such a role.
  2. 2
    CIAS→CDMS
    reads every configured module's declaration, as a bean or over GET /cias/fetch
  3. 3
    CIAS→Keycloak
    writes the user profile, the client roles and the claim mappers, and then the catalog
  4. 4
    CIAS→Keycloak
    reconciles the groups: create missing copies, bring roles and members up to date

Both passes hang on one switch (codamai.cias.authorization.startup.enabled) plus the module’s own. Neither fails the start. The reasoning is the same in both places: a role that has not been created yet surfaces later and can be caught up; a platform that will not come up because Keycloak is restarting is the greater damage. Creating a role also grants it to nobody — which is what makes running this unattended acceptable.

The variants

What a cold start looks like

When: codamai.cias.bootstrap.enabled: true, usually exactly once on a fresh installation.

Stage 3 runs and fills the catalog, possibly the first tenant and the first administrator's role. On an installation that is already running, the pass finds everything in place and changes nothing.

Result: After the start there is a catalog and somebody allowed to administer it.

When: The switch is missing or false. That is the normal case in operation.

Stage 3 is skipped entirely. Nothing is written, and none of the connections the bootstrap would need is even built — a start without a bootstrap does not ask Keycloak anything at this point.

Result: The start goes straight from stage 2 to stage 4.

When: An administrator address is configured, but there is no account for it.

  1. 1
    CIAS→Keycloak
    looks for the account behind the address
  2. 2
    CIAS
    finds none and fails the start
    The same happens when the installation names no platform role at all: then there is nothing to grant, and one of the two statements is not meant.

Result: Create the account in Keycloak first, then start again. The order is not negotiable — CIAS holds no credentials.

When: CDMS and CIAS run in the same process.

One cold start for both. CDMS's declaration is a bean in the same process, so the reconciliation needs no network and no token. The CIAS tables live in the host's system database. The bootstrap exists only where the host brings the starter.

Result: Once the process is up, everything is up.

When: CIAS is a service of its own.

Two cold starts that know nothing about each other. Each service migrates its own schema and builds its own context. Only in stage 4 do they touch: CIAS calls GET /cias/fetch on the CDMS service. If that one is not up yet, its module counts as unreadable — nothing about its roles changes then, not even a retirement.

Result: The order of the two services is free. Whatever could not be read on the first attempt is caught up by the next reconciliation.

What runs in the background afterwards

Two timers belong to operation, and both are off by default. Starting a background thread is a decision the application makes, not the jar.

TimerSwitchWhat it does
Role synchronizationcodamai.cias.authorization.synchronization.enabledlets expired time-limited roles actually expire, default interval 5 minutes
Tenant reconciliationcodamai.cias.tenancy.reconciliation.enabledfinds abandoned provisionings and marks them FAILED, default interval 15 minutes

The standalone CIAS service switches both on. An application that embeds CIAS without the starter has neither — there is no timer there, and both have to be triggered.

Watch out

Next

Sources in the code and the knowledge base
  • CIAS/cias-spring-boot-starter – AutoConfiguration.imports (order of the auto-configurations), CiasBootstrapAutoConfiguration, CiasBootstrap (defineRoles, createFirstTenant, grantPlatformAdministrator), CiasBootstrapProperties
  • CIAS/cias-spring-boot-starter – CiasSchemaAutoConfiguration (EntityManagerFactoryDependsOnPostProcessor), CiasSchemaMigration, CiasMigrationProperties, CiasDeclarationAutoConfiguration (checks while the context is built), CiasSchedulingAutoConfiguration, CiasReconciliationAutoConfiguration, CiasTenantProvisioningAutoConfiguration
  • CIAS/cias-authorization – CiasAuthorizationConfiguration (ciasRoleStartupPass, ciasGroupStartupPass as ApplicationReadyEvent listeners), RoleStartupPass, GroupStartupPass, RoleReconciliationService
  • CIAS/cias-authentication – CiasTokenConfiguration (TenantLookupPort a required bean); CIAS/cias-tenancy – TenantService.createTenant/rollOut
  • CIAS/cias-runtime – application.yml (bootstrap, migration, startup, reconciliation, synchronization); hub-backend – application.yaml (declarations, startup), pom.xml (no starter)
  • commons-persistence – TenantProperties (mode, @NotNull), TenantProvisioningConfiguration, TenantEntityManagerFactory.buildFactory, ManagedTypesContribution
  • CDMS/cdms-authorization – CiasReaderRoles (codamai.cdms.cias.reader-roles, no default)
Search