This directory provides sample Docker Compose configuration files to demonstrate setting up Ed‑Fi OneRoster and the supporting Ed‑Fi ODS/API stack in containers. These files are intended for demo purposes only and are not intended for production use. It contains:
- Compose definitions that describe the database tier, the Ed-Fi v7 API, NGINX, and the OneRoster Node.js service.
- PowerShell helpers that standardize how the stack is started and stopped.
- Version-specific
.envfiles that capture the image tags, credentials, and OneRoster-specific configuration.
For lightweight dev workflows that run only the OneRoster API against a
pre-existing database, see docker-compose.dev.yml and
docker-compose.dev-dual.yml in the repo root.
- Docker Engine with Docker Compose support
- PowerShell 7+ (
pwsh)
On Linux and macOS, use pwsh to run the .ps1 scripts directly; there is no
separate .sh entrypoint for starting/stopping this stack.
pwsh ./start-services.ps1 [-Rebuild] [-EnvFile <path>] [-GenerateSigningKeys] [-InitializeAdminClients] [-InitializeOneRosterViews]- Provisions the shared
edfioneroster-network(if missing) and runsdocker compose up -dacross all compose files. -Rebuildforces a rebuild of the local OneRoster image from the repo rootDockerfilebefore containers start. Use this whenever you change OneRoster source code. When omitted, the stack uses the pre-built image specified byONEROSTER_IMAGEin the env file (defaulting toedfialliance/one-roster-api:pre).-EnvFilelets you point at any dotenv file (defaults to.envinside this folder). Relative paths are resolved fromstack/.-GenerateSigningKeyscreates ephemeral RSA keys viapublic-private-key-pair.psm1and injects them into the process environment. Use this for quick trials when you do not haveSECURITY__JWT__PRIVATEKEYandSECURITY__JWT__PUBLICKEYset.-InitializeAdminClientscopiessettings/bootstrap.shinto the runningdb-admincontainer and executes it withLEA_KEY,LEA_SECRET,SCHOOL_KEY, andSCHOOL_SECRETtaken from the selected.env. Use this to seed the test vendors/clients without recreating containers.-InitializeOneRosterViewsruns the OneRoster SQL artifacts fromstandard/{ONEROSTER_ARTIFACT_VERSION}/artifacts/pgsql/coreagainst the ODS database. It readsCONNECTION_CONFIG(from the env file or theCONNECTION_CONFIGenvironment variable) to locateEdFi_Admin, queries the first record fromdbo.OdsInstancesto obtain the ODS connection string, and executes each.sqlfile in order against that ODS database. Use this after-InitializeAdminClientsto bootstrap the OneRoster schema.- The script validates that JWT signing keys exist either in the environment,
the chosen
.env, or via-GenerateSigningKeysbefore invoking Docker Compose.
pwsh ./stop-services.ps1 [-Purge] [-EnvFile <path>]- Runs
docker compose down --remove-orphansacross every compose file listed below using the provided env file. -Purgeadds--volumes --rmi all, removing database volumes, named volumes, and images created by the stack (helpful when switching data standards or templates).-EnvFilemirrors the flag instart-services.ps1so you can stop the exact stack you started.
These three files are loaded together by the helper scripts (via repeated -f
flags) so they behave as a single logical stack.
| File | Purpose | Key services |
|---|---|---|
edfi-services.yml |
Core Ed-Fi ODS/API dependencies. | db-ods, db-admin, v7-single-api, swagger, pgadmin4 |
nginx-compose.yml |
HTTPS reverse proxy that fronts all APIs and terminates TLS using the templates under stack/ssl. |
nginx |
oneroster-service.yml |
Builds and runs the OneRoster Node.js API, wiring it to the Ed-Fi ODS database and JWT issuer. | oneroster-api |
If you replace or extend these sample compose files with your own, apply the same least-privilege controls before running in shared, staging, or production environments.
- Drop Linux capabilities by default (
cap_drop: [ALL]) and add back only capabilities your container actually needs. - Run workload containers as non-root users. Set
USERin the Dockerfile and, when practical, enforce it in Compose withuser:. - Enable
security_opt: ["no-new-privileges:true"]to prevent privilege escalation through setuid/setgid binaries. - Apply restrictive runtime security profiles (seccomp, AppArmor, or SELinux) according to your host platform policy.
- Do not use
privileged: true, avoid host namespaces (pid: host,ipc: host,network_mode: host), and avoid device mounts unless required.
Example service hardening (Node.js app):
services:
oneroster-api:
build: ../
user: appuser
cap_drop:
- ALL
security_opt:
- no-new-privileges:trueFor third-party images (database, reverse proxy, admin tools), validate vendor guidance before dropping all capabilities to avoid startup regressions.
- db-ods / db-admin – PostgreSQL containers seeded by
settings/init-databases.shandsettings/bootstrap.sh. Credentials are sourced fromPOSTGRES_USERandPOSTGRES_PASSWORD. - v7-single-api – The Ed-Fi v7 Web API container. JWT details
(
Security__Jwt__*), feature flags, and health checks rely on the.envvalues. - swagger – Bundled Swagger UI that points at the v7 API.
- pgadmin4 – Optional DBA cockpit available on
127.0.0.1:5050for local troubleshooting. - nginx – Terminates TLS on
https://localhost:443and routes traffic to the v7 API, OneRoster API, and Swagger virtual hosts usingsettings/default.conf.template. - oneroster-api – Builds from the repo root (via the local Dockerfile),
exposing
/health-checkfor readiness and consuming OAuth/JWT settings listed below.
stack/.env.5.2.0.example– Defaults for Ed-Fi Data Standard 5.2.0.stack/.env.4.0.0.example– Defaults for Data Standard 4.0.0.- Rename a copy to
.envor pass the file directly to the scripts using-EnvFile. Version-numbered files (.env.5.2.0,.env.4.0.0) are git-ignored working copies.
| Section | Representative variables | Notes |
|---|---|---|
| Common DB credentials | POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_PORT |
Shared across ODS, Admin, and the Node service. Match whatever is baked into the Ed-Fi images. |
| Database engine options | DB_ENGINE |
Control whether OneRoster speaks to PostgreSQL or MSSQL. |
| Pooling & TPDM | NPG_POOLING_ENABLED, NPG_API_MAX_POOL_SIZE_*, TPDM_ENABLED |
Tune Npgsql pooling and enable TPDM support in the Ed-Fi API images. |
| Image tags & templates | ODS_DB_IMAGE_7X, ODS_DB_TAG_7X, ODS_API_TAG_7X, SWAGGER_TAG_7X, ADMIN_DB_TAG_7X |
Pin the Docker images for the Ed-Fi stack. Switch between populated/minimal templates by swapping values. |
| OneRoster image | ONEROSTER_IMAGE |
Docker image used for the oneroster-api service. Defaults to edfialliance/one-roster-api:pre. Override to use a specific release tag (e.g. edfialliance/one-roster-api:1.2.0) or a locally built image. When running start-services.ps1 -Rebuild, the service is built from source, but ONEROSTER_IMAGE still determines the image name/tag that is built and started. |
| URLs and hostnames | BASE_URL, V7_SINGLE_API_VIRTUAL_NAME, ONEROSTER_API_VIRTUAL_NAME, DOCS_VIRTUAL_NAME |
Must stay aligned with the NGINX template so that TLS certificates and reverse-proxy routes resolve correctly. |
| Database names | TARGET_DB, TEMPLATE_DB |
Used by the bootstrap scripts to clone populated templates into the working ODS. |
| Ed-Fi API health checks | V7_SINGLE_API_HEALTHCHECK, SWAGGER_HEALTHCHECK_TEST |
Executed by Docker to mark containers healthy before dependent services start. |
| JWT & OAuth | SECURITY__JWT__PRIVATEKEY, SECURITY__JWT__PUBLICKEY, OAUTH2_ISSUERBASEURL, OAUTH2_AUDIENCE, OAUTH2_PUBLIC_KEY_PEM |
Required for OneRoster to validate JWTs issued by the Ed-Fi API. Populate with PEM-formatted keys (newline-escaped). |
| OneRoster app settings | PORT, DB_TYPE, API_BASE_PATH, CORS_ORIGINS, ONEROSTER_ARTIFACT_VERSION |
Tailor the Node service runtime and artifact set mounted from /standard. |
| pg-boss (scheduled refresh) | PG_BOSS_CONNECTION_CONFIG, PGBOSS_CRON |
PG_BOSS_CONNECTION_CONFIG is the explicit PostgreSQL admin connection used for pg-boss job metadata. PGBOSS_CRON sets the refresh schedule (cron expression). Only relevant when DB_TYPE=postgres. |
| Multi-tenancy & context routing | MULTITENANCY_ENABLED, ODS_CONTEXT_ROUTE_TEMPLATE, TENANTS_CONNECTION_CONFIG, CONNECTION_CONFIG |
Control multi-tenancy support and ODS context routing. When MULTITENANCY_ENABLED=true, use TENANTS_CONNECTION_CONFIG to define multiple tenant databases (JSON). For single-tenant mode (default), use CONNECTION_CONFIG to specify the EdFi_Admin connection. ODS_CONTEXT_ROUTE_TEMPLATE enables context-based routing (e.g., {schoolYearFromRoute:range(2026,2027)}). |
| Logging & TLS trust | LOGS_FOLDER, NODE_EXTRA_CA_CERTS, TRUST_PROXY |
LOGS_FOLDER is bind-mounted into v7-single-api; NODE_EXTRA_CA_CERTS points at the self-signed CA bundled under compose/ssl. TRUST_PROXY tells Express to trust forwarded headers from reverse proxies. |
Note
The start-services.ps1 check ensures
SECURITY__JWT__PRIVATEKEY/PUBLICKEY exist before containers start. Either
set them in the env file or run with -GenerateSigningKeys for a temporary
pair.
The OneRoster API supports both single-tenant and multi-tenant deployments:
Set MULTITENANCY_ENABLED=false and configure CONNECTION_CONFIG with your
EdFi_Admin database connection:
MULTITENANCY_ENABLED=false
CONNECTION_CONFIG={"adminConnection":"host=db-admin;port=5432;username=postgres;password=<your_db_password>;database=EdFi_Admin;pooling=true;minimum pool size=10;maximum pool size=50;"}Set MULTITENANCY_ENABLED=true and configure TENANTS_CONNECTION_CONFIG with a JSON
object mapping tenant names to their admin database connections:
PostgreSQL example:
MULTITENANCY_ENABLED=true
TENANTS_CONNECTION_CONFIG={"Tenant1":{"adminConnection":"host=localhost;port=5432;database=EdFi_Admin_Tenant1;username=postgres;password=<tenant1_db_password>"},"Tenant2":{"adminConnection":"host=localhost;port=5432;database=EdFi_Admin_Tenant2;username=postgres;password=<tenant2_db_password>"}}MSSQL example:
MULTITENANCY_ENABLED=true
TENANTS_CONNECTION_CONFIG={"Tenant1":{"adminConnection":"server=localhost;database=EdFi_Admin_Tenant1;user id=sa;password=<tenant1_db_password>;encrypt=false"},"Tenant2":{"adminConnection":"server=localhost;database=EdFi_Admin_Tenant2;user id=sa;password=<tenant2_db_password>;encrypt=false"}}Enable context-based routing by setting ODS_CONTEXT_ROUTE_TEMPLATE to define
route patterns that map to different ODS contexts:
ODS_CONTEXT_ROUTE_TEMPLATE={schoolYearFromRoute:range(2026,2027)}This allows the API to route requests to different ODS instances based on the school year or other contextual parameters in the URL. Leave empty to disable context routing.
When DB_TYPE=postgres, the OneRoster API uses pg-boss
to schedule periodic refresh of the OneRoster materialized views.
PG_BOSS_CONNECTION_CONFIG must be set explicitly to a PostgreSQL admin
connection so that the pg-boss backing store is stable across configuration
changes. Valid options:
- Tenant admin DB (multi-tenant mode) — point to one of the tenant admin databases
- Same admin DB as
CONNECTION_CONFIG(single-tenant mode) — reuse the single admin connection - Dedicated pg-boss database — use a separate database reserved solely for pg-boss job metadata
# Single-tenant example — reuse the admin DB
PG_BOSS_CONNECTION_CONFIG={"adminConnection":"host=db-admin;port=5432;database=EdFi_Admin;username=postgres;password=<your_db_password>"}
PGBOSS_CRON=*/15 * * * *
# Multi-tenant example — point to a specific tenant admin DB
PG_BOSS_CONNECTION_CONFIG={"adminConnection":"host=db-admin;port=5432;database=EdFi_Admin_Tenant1;username=postgres;password=<your_db_password>"}
PGBOSS_CRON=*/15 * * * *- Copy the example env file that matches your target data standard and edit the values you care about (credentials, BASE_URL, image tags, keys).
- Ensure the required
.crt,.key, and.pemfiles exist understack/ssl; run./generate-certificate.shin that folder to create fresh self-signed certificates when needed. - Run
pwsh ./start-services.ps1 -EnvFile .env.5.2.0(or your variant). Include-Rebuildwhenever you change OneRoster source. - Optionally seed bootstrap data:
- Run with
-InitializeAdminClientsto create the test LEA/School API clients. - Run with
-InitializeOneRosterViewsto apply the OneRoster SQL schema artifacts against the ODS database. RequiresCONNECTION_CONFIGandONEROSTER_ARTIFACT_VERSIONto be set in the env file (orCONNECTION_CONFIGas an environment variable).
- Run with
- Access the stack:
- Ed-Fi API:
https://localhost/<V7_SINGLE_API_VIRTUAL_NAME> - OneRoster API:
https://localhost/<ONEROSTER_API_VIRTUAL_NAME> - Swagger UI:
https://localhost/<DOCS_VIRTUAL_NAME> - PGAdmin:
http://localhost:5050
- Ed-Fi API:
- Stop the stack with
pwsh ./stop-services.ps1 [-Purge] -EnvFile .env.5.2.0.