Platform, seed scripts
Initial data seeding for dev and prod first-deploys
Olympus's seeds bootstrap the system with: admin identities, OAuth2 clients (for Athena/Site to function), and identity schemas.
Dev seed: iam-seed-dev.sh
Runs once on first dev stack start. Creates:
- An IAM admin:
admin@demo.user/admin123!withrole: admin. - The OAuth2 clients Athena IAM, Athena CIAM, and Site need to function (with hard-coded dev client_ids and secrets).
#!/usr/bin/env bash
set -euo pipefail
# Wait for Kratos to be ready
until curl -sf http://iam-kratos:7001/admin/identities >/dev/null; do sleep 1; done
# Create admin
curl -X POST http://iam-kratos:7001/admin/identities \
-H 'content-type: application/json' \
-d '{
"schema_id": "default",
"state": "active",
"traits": { "email": "admin@demo.user", "role": "admin" },
"credentials": { "password": { "type": "password", "identifiers": ["admin@demo.user"], "config": { "password": "admin123!" } } },
"verifiable_addresses": [{ "value": "admin@demo.user", "verified": true, "via": "email", "status": "completed" }]
}'
# Register OAuth2 clients
curl -X POST http://iam-hydra:7003/admin/clients \
-H 'content-type: application/json' \
-d '{ "client_id": "athena-iam-dev", ... }'
# More clients...
echo "Seed complete!"Idempotent, re-running is fine; existing identities/clients are updated rather than duplicated.
Prod seed: seed-prod.sh
Prod seeding does not include a default admin (security, no default password to be guessed). The Daedalus Accounts step creates the first admin during deployment.
What runs in prod:
- Schemas are loaded by Kratos on startup from mounted files; no separate seed.
- OAuth2 clients are registered by Daedalus's Applications step, not by an automated script.
- Settings (Athena's settings vault) start empty; operators configure via Athena UI.
Schema reload
Schemas are loaded from kratos.yml's identity.default_schema_id pointer. Changes to schema files require a reload, see Operate, Reload API key rotation for the sidecar mechanism.
The seed script doesn't trigger a reload (it sets up at first-start; the system is fresh).
Idempotency
Seed scripts are designed to be re-runnable. If you destroy and re-create the dev stack, the seed runs again and creates the demo admin again.
For prod, no seed re-runs automatically. To re-seed prod (e.g. starting fresh), use the destroy → re-create Daedalus flow.
init-db.sql
Runs on Postgres first start. Creates the five databases plus per-database users:
CREATE DATABASE ciam_kratos;
CREATE DATABASE ciam_hydra;
CREATE DATABASE iam_kratos;
CREATE DATABASE iam_hydra;
CREATE DATABASE olympus;
CREATE USER ciam_kratos_user WITH PASSWORD '...';
GRANT ALL PRIVILEGES ON DATABASE ciam_kratos TO ciam_kratos_user;
-- ... per-database usersIn production with managed Postgres (Neon), this script doesn't run, the Neon project setup does the equivalent via API.
What the seeds DON'T do
- Don't create customer identities. Customers register via the standard CIAM registration flow.
- Don't configure SMTP. That's via Athena settings or env vars.
- Don't configure Turnstile. Same.
- Don't enable / disable social providers. Done via Athena → Social Connections.
Where to put new seed logic
If you have new bootstrap data:
- For dev: extend
iam-seed-dev.shor add a new<name>-seed-dev.shin the same directory. - For prod: usually wrong place to put it. Prod is operator-driven; the operator does it via Daedalus or Athena.