Getting started (Docker)
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.Clientdrops 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 map80:5000; the acceptance tests use Kestrel on port 80. - Apple Silicon: the
mssql/server:2022-latestimage islinux/amd64and 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.orgfor the restore.