xrmverse
Documentation menu

Getting started (Docker)

← xrmverse documentation

With a released xrmd CLI (see CLI xrmd; on a server, follow Installing xrmverse), which runs the published server image of its own version (ghcr.io/power-builders-italia/xrmd:<version>):

xrmd server init --dir ./xrmd-server                 # one organization, "xrmd", on port 5001; writes docker-compose.yml and .env (XRMD_IMAGE pinned to the CLI version)
                                                     # asks you to accept the SQL Server license terms (default no; --accept-sql-server-eula)
xrmd sdk install --dir ./xrmd-server                 # the Microsoft SDK, after you accept Microsoft's license terms (asks; default no)
xrmd server up --dir ./xrmd-server                   # refuses to start while ./xrmd-server/sdk/sdk.json is missing
curl http://localhost:5001/healthz                   # -> ok (once the xrmd-xrmd service is up)
export XRMD_DEV_SIGNING_KEY=$(grep '^AUTH_DEV_SIGNING_KEY=' ./xrmd-server/.env | cut -d= -f2)
xrmd auth status                                     # WhoAmI through the dev profile "xrmd" created by server init

While the image is private (preview), docker login ghcr.io first with a token that has read:packages. To reach the organizations at https://<org>.<domain> on 443 instead of one port each, add --domain <domain> --tls acme|files|internal to server init: see Installing xrmverse.

server init generates the SQL Server password and the dev signing key, and creates a dev CLI profile per organization. It also offers to install the Microsoft SDK (see Installing the Microsoft SDK). For several organizations (--org acme --org zenith: ports 5001, 5002, …) see Multiple organizations. The bundled SQL Server runs the free Express edition (at most 10 GB per database); for another edition, and for the license terms you accept, see SQL Server editions. To stop: xrmd server down --dir ./xrmd-server (--volumes also deletes the data volumes).

On startup xrmd waits for SQL Server (30 retries x 2 s), creates its organization database if missing, and applies the migrations and the seed (organization, root business unit, administrator user). Instances started together on the same database are serialized with a sp_getapplock (xrmd-startup:<database>); organizations on other databases of the same SQL Server start without waiting for each other. Versions before this change used one server-wide name (xrmd-startup), so an old and a new process do not serialize each other: during an upgrade, upgrade one host of a database at a time with its other processes stopped (one process per database is the rule anyway). One process per database is enforced by another lock (xrmd-instance, see Multiple organizations).

From a clone

A development CLI (dotnet run --project src/Xrmd.Cli -- from the repository root) has no release version: server init writes XRMD_IMAGE=xrmd:local and prints the command that builds it. Build the image first, then run the same commands:

docker build -f docker/Dockerfile -t xrmd:local .
dotnet run --project src/Xrmd.Cli -- server init --dir ./xrmd-server

Without the CLI (repository compose file)

docker/docker-compose.yml builds the image from source and runs one organization (database xrmverse) on port 5000; it is what the development token script below targets.

cp docker/.env.example docker/.env      # then set SA_PASSWORD and AUTH_DEV_SIGNING_KEY (openssl rand -hex 32); MSSQL_PID: see SQL Server editions
xrmd sdk install                        # the Microsoft SDK into ~/.xrmd/sdk, after you accept Microsoft's license terms (asks; default no)
docker compose -f docker/docker-compose.yml --env-file docker/.env up --build -d
curl http://localhost:5000/healthz      # -> ok

The compose file mounts the SDK folder read-only into the container: XRMD_SDK_HOST_DIR in docker/.env, else ~/.xrmd/sdk (${HOME}/.xrmd/sdk). Without the CLI installed, dotnet run --project src/Xrmd.Cli -- sdk install does the same. Set XRMD_SDK_HOST_DIR when the SDK is elsewhere (xrmd sdk install with XRMD_SDK_DIR set) or when HOME is not set in your shell (some Windows shells), which would turn the mount into /.xrmd/sdk. A missing folder is created empty by Docker, and the container then exits with code 3 and the missing-SDK message.

To stop: docker compose -f docker/docker-compose.yml --env-file docker/.env down (-v also deletes the mssql-data volume).

Development token (AUTH_MODE=Development)

TOKEN=$(docker/dev-token.sh)            # requires only bash + openssl; reads docker/.env
curl -H "Authorization: Bearer $TOKEN" http://localhost:5000/api/data/v9.2/WhoAmI

The token is an HS256 JWT (issuer xrmverse-dev, audience AUTH_AUDIENCE, claim oid = SEED_ADMIN_OBJECT_ID, valid for 1 hour) signed with AUTH_DEV_SIGNING_KEY. With AUTH_MODE=Entra the tokens are Microsoft Entra ID tokens for the tenant AUTH_TENANT_ID, and AUTH_AUDIENCE must match the server's base URL. xrmd accepts only v2.0 tokens (issuer https://login.microsoftonline.com/{tenant}/v2.0): in the app registration manifest set "accessTokenAcceptedVersion": 2 (with the default value Entra issues v1 tokens, with issuer https://sts.windows.net/..., which are rejected), and use the tenant GUID (not the domain name) as AUTH_TENANT_ID, because the token issuer contains the GUID.

Notes

  • ServiceClient: Microsoft.PowerPlatform.Dataverse.Client drops the port from the URI, so it works only if the server responds on the default port (80/443). Give the organizations host names on 443 (server init --domain, see Installing xrmverse), or map 80:5000; the acceptance tests use Kestrel on port 80.
  • Apple Silicon: the mssql/server:2022-latest image is linux/amd64 and runs under emulation (Rosetta/QEMU): startup is slow and SQL Server may take longer to become healthy.
  • The Docker build requires access to api.nuget.org for the restore.