Local Installation

End-to-end guide to running Apache Airavata Custos locally: database, OIDC, API server, and portal. For coding conventions and contribution workflow, see CONTRIBUTING.md.

Prerequisites

  • Go 1.24+
  • Node 20+ and pnpm (for the portal)
  • Docker and Docker Compose
  • git

Pick an OIDC provider

Custos is OIDC-generic and verifies bearer tokens against whatever issuer you point it at. For local development you have two convenient options:

  • Bundled Keycloak – the Compose stack ships a Keycloak service with a seeded realm and dev users. Zero external setup, fastest for feature work.
  • Any external OIDC provider – register a client with your IdP whose redirect URI is http://localhost:3000/api/auth/callback/oidc, then plug the issuer, client_id, and client_secret into the env files.

The steps below cover both. Where they differ, they're labeled Bundled Keycloak / External OIDC.

1. Start the database

From dev-ops/compose/:

docker compose up -d db

This starts MariaDB on localhost:3306 and runs dbinit/init-db.sh, which creates the custos database and the admin user (password admin).

Bundled Keycloak only: also bring up Keycloak. On first start it imports the realm definition from dev-ops/compose/keycloak/import/custos-realm.json (OIDC client + dev users inside Keycloak itself).

docker compose up -d keycloak

Keycloak will be available at http://localhost:8081 once healthy (~60s). Skip this if you're using an external OIDC provider.

Stop everything later with docker compose down, or docker compose down -v to also wipe the DB volume.

2. Configure backend env

From the repo root:

cp .env.example .env

Edit .env:

  • Bundled Keycloak: the defaults already point at the local realm, so no edits are needed. Bootstrap admin email stays admin@custos.local (matches the seeded realm user).
  • External OIDC: register a client at your IdP with redirect http://localhost:3000/api/auth/callback/oidc, then:
    • Set OIDC_ISSUER_URL to the issuer URL.
    • Set OIDC_AUDIENCE to whatever your IdP puts in the access-token aud claim (typically your client_id).
    • Set CUSTOS_BOOTSTRAP_ADMIN_EMAIL=<your email>. A PENDING super_admin user is created on first boot; your first sign-in links your OIDC sub to it via email fallback.

Source it: set -a && . ./.env && set +a.

3. Run the API server

From the repo root:

go run ./cmd/server

On startup, the server opens the DB, runs the embedded migrations (internal/db/migrations/), grants super_admin to CUSTOS_BOOTSTRAP_ADMIN_EMAIL (creating a PENDING user if needed), wires the event bus + service layer, and listens on the port from config/custos.yaml (core.api.port, default 8080).

Leave it running.

4. Apply the cluster seed

The migrations create the schema; the cluster seed inserts the default compute_clusters row that connectors and portal features reference by ID. Apply it once, in a second terminal, after the server has come up:

docker exec -i custos_db mariadb -uadmin -padmin custos < dev-ops/compose/seeds/default_cluster.sql

The seed uses INSERT IGNORE, so re-running is safe.

5. (Bundled Keycloak only) Seed dev users

For the bundled Keycloak path there is also a sample identity seed (org, users, roles, role assignments) matched to the users in the imported realm:

docker exec -i custos_db mariadb -uadmin -padmin custos < dev-ops/compose/seeds/dev_users_and_roles.sql

Skip this for external OIDC. You don't need it, and the emails would collide with the identity you actually sign in as.

6. Configure and run the portal

cd web
cp .env.example .env.local
pnpm install

Edit web/.env.local:

  • Generate NEXTAUTH_SECRET with openssl rand -base64 32.
  • Bundled Keycloak: defaults are correct.
  • External OIDC: set OIDC_ISSUER_URL, OIDC_CLIENT_ID, and OIDC_CLIENT_SECRET to the values from the client you registered in step 2.

Start the portal:

pnpm dev

7. Sign in

Open http://localhost:3000 and sign in:

  • Bundled Keycloak: use one of the seeded users (e.g. admin@custos.local / admin; see the realm import for the full list).
  • External OIDC: sign in with your provider. On first sign-in your OIDC sub is linked to the PENDING super_admin user created in step 3, and the user is promoted to ACTIVE.

8. (Optional) Load sample data

After first sign-in the sidebar renders but every screen is empty. That's the correct state on a fresh DB, no allocation or project data has been produced yet. To populate it:

9. (Optional) Public landing page

The portal serves a landing page at / to signed-out users; signed-in users get the portal home instead. The page lives at web/public/landing/index.html, a single self-contained file.

To use your own landing page, replace that file with your index.html before building the portal. Put any assets it needs (images, stylesheets, fonts) anywhere under web/public/ and reference them by their URL path from the site root (web/public/brand/logo.svg is served at /brand/logo.svg). They ship with the build automatically.

Point the page's sign-in links at /api/auth/federated-sign-in to send users straight to the identity provider.