Skip to main content

Identity Service — Local Dev Setup

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · DEPLOYMENT_TOPOLOGY

1. Prerequisites

ToolMinimum versionInstall
Node.js22 LTSnvm install 22
pnpm9.xnpm i -g pnpm
Docker Desktop4.xdocker.com
Docker ComposeV2 pluginbundled with Docker Desktop

2. docker compose stack

docker-compose.identity.yml (in repo root infra/local/):

version: "3.9"
services:
identity-postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: identity
POSTGRES_PASSWORD: identity_dev
POSTGRES_DB: identity_db
ports: ["5432:5432"]
volumes:
- identity-pgdata:/var/lib/postgresql/data
- ./init/identity:/docker-entrypoint-initdb.d # runs schema migrations

identity-redis:
image: redis:7-alpine
ports: ["6379:6379"]

nats:
image: nats:2.10-alpine
args: ["-js", "-m", "8222"]
ports: ["4222:4222", "8222:8222"]

keycloak-dev:
image: quay.io/keycloak/keycloak:24.0
command: start-dev
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
ports: ["8080:8080"]

volumes:
identity-pgdata:

Start the stack:

docker compose -f infra/local/docker-compose.identity.yml up -d

3. Service environment (.env.example)

Copy services/identity-service/.env.example.env.local and fill:

DATABASE_URL=postgresql://identity:identity_dev@localhost:5432/identity_db
DATABASE_REPLICA_URL=postgresql://identity:identity_dev@localhost:5432/identity_db
REDIS_URL=redis://localhost:6379
NATS_URL=nats://localhost:4222
IDENTITY_JWT_ISSUER=http://localhost:3001
IDENTITY_JWT_AUDIENCE=ghasi-ehealth-local
# Dev: use local software KMS mock (localstack or fake-kms)
IDENTITY_KMS_KEY_ARN=arn:aws:kms:us-east-1:000000000000:key/local-dev-key
IDENTITY_DEVICE_CERT_KEY_ARN=arn:aws:kms:us-east-1:000000000000:key/local-dev-device-key
IDENTITY_KEYCLOAK_URL=http://localhost:8080
IDENTITY_SESSION_ABSOLUTE_TTL_S=28800
IDENTITY_ARGON2_MEMORY_KIB=65536
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_SERVICE_NAME=identity-service

For local KMS, use LocalStack or the fake-kms Docker image and seed keys with aws kms create-key --endpoint-url http://localhost:4566.

4. Run the service

cd services/identity-service

# Install dependencies (from monorepo root)
pnpm install

# Run database migrations
pnpm drizzle-kit push:pg

# Seed module catalogue
pnpm run seed:modules

# Start in watch mode
pnpm dev

Service listens on http://localhost:3001. JWKS: http://localhost:3001/.well-known/jwks.json

5. Seed data

pnpm run seed:modules inserts the following always-on module catalogue entries:

CodeName
platform.iamPlatform IAM
platform.auditPlatform Audit
ehr.coreEHR Core

Additional seed scripts:

  • pnpm run seed:dev-tenant — creates a ten_DEV00000000001 test tenant and admin user.
  • pnpm run seed:licenses — assigns always-on licenses to the dev tenant root node.

6. Common commands

CommandPurpose
pnpm devStart with hot reload
pnpm testRun unit tests
pnpm test:integrationRun integration tests (requires docker compose stack)
pnpm test:covCoverage report
pnpm drizzle-kit generate:pgGenerate migration from schema changes
pnpm drizzle-kit push:pgApply migrations to local DB
pnpm lintESLint
pnpm typechecktsc --noEmit

7. Useful local endpoints

EndpointDescription
POST http://localhost:3001/api/v1/auth/loginLogin (email + password)
GET http://localhost:3001/.well-known/jwks.jsonLocal JWKS
GET http://localhost:3001/api/v1/licensing/modulesModule catalogue
GET http://localhost:3001/healthHealth check
http://localhost:8080Keycloak admin console (admin / admin)
http://localhost:8222NATS monitoring

8. Troubleshooting

SymptomLikely causeFix
KMS key not foundLocalStack not running or key not seededStart LocalStack; run pnpm run seed:kms
argon2 ENOMEMContainer memory limit too lowRaise Docker Desktop memory limit to ≥ 4 GB
NATS connection refusedNATS container not healthydocker compose logs nats; check JetStream flag
RLS error: app.tenant_id not setMissing tenant context in testPass tenantId header or use identity_rls_bypass role in tests