dstack auth-simple

March 19, 2026 ยท View on GitHub

A config-based auth server for dstack KMS webhook authorization. Validates boot requests against a JSON configuration file.

When to Use

Auth ServerUse Case
auth-simpleProduction deployments with config-file-based whitelisting
auth-ethProduction deployments with on-chain governance
auth-mockDevelopment and testing only

Installation

bun install

Configuration

Create auth-config.json (see auth-config.example.json).

For KMS deployment, you must allowlist both the OS image hash and the KMS mrAggregated value:

{
  "osImages": ["0x0b327bcd642788b0517de3ff46d31ebd3847b6c64ea40bacde268bb9f1c8ec83"],
  "kms": {
    "mrAggregated": ["0x<kms-mr-aggregated>"],
    "allowAnyDevice": true
  },
  "apps": {}
}

Add more fields as you deploy Gateway and apps:

{
  "osImages": ["0x..."],
  "gatewayAppId": "0x...",
  "kms": {
    "mrAggregated": ["0x..."],
    "devices": [],
    "allowAnyDevice": true
  },
  "apps": {
    "0xYourAppId": {
      "composeHashes": ["0xabc...", "0xdef..."],
      "devices": [],
      "allowAnyDevice": true
    }
  }
}

Configuration Fields

FieldRequiredDescription
osImagesYesAllowed OS image hashes (from digest.txt)
gatewayAppIdNoGateway app ID (add after Gateway deployment)
kms.mrAggregatedYes for KMS authorizationAllowed KMS aggregated MR values. An empty array denies all KMS boots.
kms.devicesNoAllowed KMS device IDs
kms.allowAnyDeviceNoIf true, skip device ID check for KMS
apps.<appId>.composeHashesNoAllowed compose hashes for this app
apps.<appId>.devicesNoAllowed device IDs for this app
apps.<appId>.allowAnyDeviceNoIf true, skip device ID check for this app

Getting Hash Values

OS Image Hash:

# From meta-dstack build output
cat images/digest.txt

Compose Hash:

sha256sum .app-compose.json | awk '{print "0x"\$1}'

Usage

Development

# Run with hot reload
bun run dev

Production

# Run directly
bun run start

# Or build first
bun run build

Environment Variables

VariableDefaultDescription
PORT3000Server port
AUTH_CONFIG_PATH./auth-config.jsonPath to config file

API Endpoints

GET /

Health check and server info.

Response:

{
  "status": "ok",
  "configPath": "./auth-config.json",
  "gatewayAppId": "0x..."
}

POST /bootAuth/app

App boot authorization.

Request:

{
  "mrAggregated": "0x...",
  "osImageHash": "0x...",
  "appId": "0x...",
  "composeHash": "0x...",
  "instanceId": "0x...",
  "deviceId": "0x...",
  "tcbStatus": "UpToDate"
}

Response:

{
  "isAllowed": true,
  "reason": "",
  "gatewayAppId": "0x..."
}

POST /bootAuth/kms

KMS boot authorization.

Request: Same as /bootAuth/app

Response: Same as /bootAuth/app

Validation Logic

KMS Boot Validation

  1. tcbStatus must be "UpToDate"
  2. osImageHash must be in osImages array
  3. mrAggregated must be in kms.mrAggregated
  4. deviceId must be in kms.devices (unless allowAnyDevice is true)

App Boot Validation

  1. tcbStatus must be "UpToDate"
  2. osImageHash must be in osImages array
  3. appId must exist in apps object
  4. composeHash must be in app's composeHashes array
  5. deviceId must be in app's devices (unless allowAnyDevice is true)

Hot Reload

The config file is re-read on every request. No restart required after config changes.

Integration with KMS

Configure KMS to use webhook auth pointing to this server:

[core.auth_api]
type = "webhook"

[core.auth_api.webhook]
url = "http://localhost:3000"

Testing

# Run tests
bun run test

# Run once
bun run test:run

See Also