This project helps to expose static metadata using Open Resource Discovery (ORD) protocol via HTTP endpoint. Exposed metadata can be consumed by other application/services or aggregators.
Replace "/path-to-your-metadata" with the directory, that has your ORD Documents.
- Local (default: open)
docker run -p 8080:8080 \
-v "$(pwd)/path-to-your-metadata:/app/data" \
ghcr.io/open-resource-discovery/provider-server:latest \
-d /app/data \
--base-url 'http://127.0.0.1:8080'- Local (basic auth)
docker run -p 8080:8080 -v "$(pwd)/path-to-your-metadata:/app/data" \
-e BASIC_AUTH='{"admin":"$2y$05$TjeC./ljKi7VLTBbzjTVyOi6lQBYpzfXiZSfJiGECHVi0eEN6/QG."}' \
ghcr.io/open-resource-discovery/provider-server:latest \
-d /app/data --auth basic --base-url 'http://127.0.0.1:8080'- GitHub (open)
docker run -p 8080:8080 \
-e GITHUB_TOKEN="<your-token>" \
-e WEBHOOK_SECRET="<your-webhook-secret>" \
-e UPDATE_DELAY="30" \
-e STATUS_DASHBOARD_ENABLED="true" \
-e LOG_LEVEL="info" \
ghcr.io/open-resource-discovery/provider-server:latest \
-s github \
--github-api-url "https://api.github.com" \
--github-repository "owner/repo" \
--github-branch "main" \
--base-url 'http://127.0.0.1:8080'Prerequisites
- Node.js >=22.8.0
- NPM >=10.8.2
- Local (default: open)
npx @open-resource-discovery/provider-server -d /path-to-your-metadata --base-url 'http://127.0.0.1:8080'- Local (basic auth)
BASIC_AUTH='{"admin":"$2y$05$TjeC./ljKi7VLTBbzjTVyOi6lQBYpzfXiZSfJiGECHVi0eEN6/QG."}' npx @open-resource-discovery/provider-server -d /path-to-your-metadata --auth basic --base-url 'http://127.0.0.1:8080'- GitHub (open)
npx @open-resource-discovery/provider-server -s github \
--github-api-url "https://api.github.com" \
--github-repository "owner/repo" \
--github-branch "main" \
--github-token "<your-token>" \
--base-url 'http://127.0.0.1:8080'npx @open-resource-discovery/provider-server --help| Option | Default | Required | Env Var | Description |
|---|---|---|---|---|
-b, --base-url <type> |
local |
Yes | ORD_BASE_URL |
Base URL of the server. If deployed in CF environment, the VCAP_APPLICATION env will be used as fallback |
-s, --source-type <type> |
local |
No | ORD_SOURCE_TYPE |
Source type for ORD Documents (local or github) |
-a, --auth <types> |
open |
No | ORD_AUTH_TYPE |
Server authentication method(s) (open, basic) |
-d, --directory <path> |
- | Yes (for local) | ORD_DIRECTORY |
Root directory containing the ORD Documents directory and resource definition files. |
-ds, --documents-subdirectory <path> |
documents |
No | ORD_DOCUMENTS_SUBDIRECTORY |
Directory containing the ORD Documents with at least one ORD document. Supports nested folder structures. Can also be applied to a GitHub Repository. |
--host <host> |
0.0.0.0 |
No | SERVER_HOST |
Host for server, without port |
--port <number> |
8080 |
No | SERVER_PORT |
Server port |
--github-api-url <apiUrl> |
https://api.github.com |
Yes (for github) | GITHUB_API_URL |
GitHub API endpoint for API calls |
--github-branch <branch> |
main |
Yes (for github) | GITHUB_BRANCH |
GitHub branch to use |
--github-repository <repo> |
- | Yes (for github) | GITHUB_REPOSITORY |
GitHub repository in format <OWNER>/<REPO> |
--github-token <token> |
- | Yes (for github) | GITHUB_TOKEN |
GitHub token for authentication |
--update-delay <seconds> |
5 |
No | UPDATE_DELAY |
Cooldown between webhook-triggered updates (seconds) |
--status-dashboard-enabled <boolean> |
true |
No | STATUS_DASHBOARD_ENABLED |
Enable/disable status dashboard (true/false) |
Some configuration options are only available as environment variables for security reasons:
| Environment Variable | Description |
|---|---|
WEBHOOK_SECRET |
GitHub webhook secret for signature validation (required for webhook security in GitHub mode) |
BASIC_AUTH |
JSON object with username:password-hash pairs for basic authentication (e.g., {"admin":"$2y$..."}) |
The provider server's resource requirements depend on your repository size and content type.
Memory usage varies based on content type:
- Formula: ~4× document size
- Reason: Validation, parsing, caching, and processing overhead
- Example: 500MB of ORD documents → 2GB RAM
- Formula: ~2× file size
- Reason: Git clone operations only, no validation overhead
- Example: 500MB of resource files → ~1GB RAM
If you have 500MB ORD documents + 500MB resource files:
- ORD documents: 500MB × 4 = 2GB
- Resource files: 500MB × 2 = 1GB
- Total: ~3GB RAM recommended
- Small repositories (<10MB): 512MB RAM minimum
- Medium repositories (10-500MB): 1-2GB RAM
- Large repositories (>500MB): Calculate using formulas above
Formula: Total repository size × 2.5
Reason: Space needed for:
- Git repository clone
- Working directory
- Temporary directory during updates
Examples:
- 10MB repository → ~25MB disk space
- 100MB repository → ~250MB disk space
- 1GB repository → ~2.5GB disk space
- Small repositories (<10MB): 512MB disk minimum
- Medium repositories (10-500MB): 1-2GB disk
- Large repositories (>500MB): Calculate using formula above
Note: These are minimum recommendations. Consider adding 20-30% buffer for optimal performance and to handle temporary spikes during operations.
The specified directory path (-d) should contain a documents directory (configurable via --documents-subdirectory, default is documents) with at least one valid ORD Document. Other resources referenced by ORD Documents can be placed anywhere in the specified directory.
This structure applies to both source types:
- Local (
-s local): The path points to a local directory - GitHub (
-s github): The path specifies a subdirectory within the repository
./<directory>/ # Directory specified with -d
├── documents/ # Default folder containing ORD Document(s) (configurable via --documents-subdirectory)
│ └── ord-document.json # ORD Document
└── <ord-id-1> # Optional resources
└── <resource-definition-file-1>
└── <ord-id-2> # Optional resources
├── <resource-definition-file-2>
└── <resource-definition-file-3>
./my-ord-provider/ # Directory specified with -d
├── documents/ # Default folder containing ORD Document(s)
│ ├── ord-document.json # ORD Document
│ └── ord-document2.json # Additional ORD Document
└── sap.xref:apiResource:astronomy:v1/ # Optional resources
└── openapi-v3.json
└── sap.xref:apiResource:astronomy:v2/ # Optional resources
├── openapi-v3.json
└── _metadata.json
└── sap.xref:eventResource:odm-finance-costobject:v0/ # Optional resources
└── asyncapi-v3.json
-
ORD Documents Location
- All ORD Documents must be placed in the documents directory (configurable via
--documents-subdirectory, default isdocuments/) - ORD Documents can be placed in nested folders within the documents directory
- Supported format:
.json
- All ORD Documents must be placed in the documents directory (configurable via
-
Resource References
- Resources referenced in the ORD Documents can be placed anywhere within the
-ddirectory - The URLs in the ORD Document's
resourceDefinitionsmust match the relative paths from the-ddirectory - Example resource definition in an ORD Document:
{ "resourceDefinitions": [ { "type": "openapi-v3", "mediaType": "application/json", "url": "/apis/api-one/openapi.json" } ] } - The server will resolve
/apis/api-one/openapi.jsonrelative to the-ddirectory - The access strategies of the
resourceDefinitionswill be overwritten by the provided authentication method
- Resources referenced in the ORD Documents can be placed anywhere within the
-
Base URL
- The
baseUrlis a required parameter that must match the format specified in the ORD Specification. - For local development:
- Use
http://127.0.0.1:8080instead oflocalhost - Alternatively, use a Fully Qualified Domain Name (FQDN)
- Use
- This
baseUrlvalue will:- Be set in the ORD Configuration
- Override the existing baseUrl in the
describedSystemInstancefield of any ORD Documents
- The
The ORD Configuration endpoint supports filtering documents by perspective using the ?perspective= query parameter:
# Get all documents (default)
curl http://127.0.0.1:8080/.well-known/open-resource-discovery
# Filter by perspective
curl http://127.0.0.1:8080/.well-known/open-resource-discovery?perspective=system-version
curl http://127.0.0.1:8080/.well-known/open-resource-discovery?perspective=system-instance
curl http://127.0.0.1:8080/.well-known/open-resource-discovery?perspective=system-independentNote
ORD documents without an explicit perspective property default to system-instance.
By default, if no --auth parameter is specified, the server starts without authentication.
When the open authentication parameter is used, the server bypasses authentication checks.
Cannot be used together with other authentication types.
The server supports Basic Authentication through an environment variable that contains a JSON string mapping usernames to bcrypt-hashed passwords:
{ "admin": "$2a$05$....", "reader": "$2y$a2$" }To generate hashes, use htpasswd utility:
htpasswd -Bnb <user> <password>This will output something like admin:$2y$05$... - use only the hash part (starting with $2y$) in your BASIC_AUTH JSON.
Important
Make sure to use strong passwords and handle the BASIC_AUTH environment variable securely. Never commit real credentials or .env files to version control.
Using htpasswd in your environment
-
Platform independent:
Prerequisite is to have NodeJS installed on the machine.
npm install -g htpasswd
After installing package globally, command
htpasswdshould be available in the Terminal. -
macOS:
Installation of any additional packages is not required. Utility
htpasswdis available in Terminal by default. -
Linux:
Install apache2-utils package:
# Debian/Ubuntu sudo apt-get install apache2-utils # RHEL/CentOS sudo yum install httpd-tools
First, install the Cloud Foundry CLI by following the official documentation: Cloud Foundry CLI Installation.
The ORD Provider Server can be deployed to Cloud Foundry either by using Cloud Foundry CLI to deploy our Docker image or via a manifest file with the Node.js buildpack.
Deploy using our Docker image from the private repository:
# 1. Login to Cloud Foundry
cf login -a <api-url> -o <org> -s <space>
# 2. Push the app without starting it
cf push <your-app-name> \
--no-manifest \
--docker-image "ghcr.io/open-resource-discovery/provider-server:latest" \
--docker-username <docker-username> \
--memory 512MB \
--disk 512MB \
--no-route \
--no-start
# 3. Set all environment variables
cf set-env <your-app-name> ORD_SOURCE_TYPE <github|local>
cf set-env <your-app-name> GITHUB_BRANCH <branch_name>
cf set-env <your-app-name> GITHUB_API_URL <url>
cf set-env <your-app-name> GITHUB_REPOSITORY <owner/repo>
cf set-env <your-app-name> GITHUB_TOKEN <github_token>
# 4. Add and map a route for your app
cf map-route <your-app-name> <domain> --hostname <your-app-name>
# 5. Start the app
cf start <your-app-name>Via CF Manifest (Alternative Approach)
You can also deploy your current repository using a manifest file:
- Create
manifest.yaml:
---
applications:
- name: <your-app-name>
buildpacks:
- nodejs_buildpack
instances: 1
memory: 512M
disk_quota: 512M
routes:
- route: <your-app-name>.example.com
env:
GITHUB_BRANCH: <branch_name>
GITHUB_API_URL: <url>
GITHUB_REPOSITORY: <owner/repository>
GITHUB_TOKEN: <ghp_token>
ORD_SOURCE_TYPE: <github|local>- Deploy:
cf push# 1. Login to Cloud Foundry
cf login -a <api-url> -o <org> -s <space>
# 2. Push the updated app
cf push <your-app-name> \
--no-manifest \
--docker-image "ghcr.io/open-resource-discovery/provider-server:<your-new-version>" \
--docker-username <docker-username>When using the GitHub source type (-s github), you need to provide a GitHub token with appropriate permissions. Both fine-grained personal access tokens (PATs) and classic tokens are supported.
For Fine-grained personal access tokens:
- Repository Access: Select the specific repository(ies) you need access to
- Permissions: Only
ContentswithRead-onlyaccess is required
For Tokens (classic):
- Repository Access:
repoaccess for private repositoriespublic_reposcope for public repositories only
When using the GitHub source type (-s github), you can configure webhooks to automatically update content when changes are pushed to your repository.
- Go to your GitHub repository → Settings → Webhooks
- Click "Add webhook"
- Configure the webhook:
- Payload URL:
https://your-server.com/api/v1/webhook/github - Content type:
application/json - Secret: A secure random string
- Events: Select "Just the push event"
- Payload URL:
The --update-delay parameter sets a cooldown period between webhook-triggered updates. This prevents excessive updates when multiple commits are pushed in quick succession. During the cooldown period, only the latest push event will be processed after the delay expires.
The provider server includes a built-in status dashboard accessible at /status that provides real-time monitoring of your ORD provider.
Navigate to http://127.0.0.1:8080/status in your browser.
When disabled, /status will redirect to the ORD endpoint.
The provider server implements a sophisticated caching system to optimize performance:
- Memory Cache: Hash-keyed in-memory storage for instant request serving
- Smart Invalidation: Automatic cache invalidation based on file modifications
For detailed information about the caching architecture, cache warming process, and performance characteristics, see ORD Provider Server Caching Architecture.
Copyright 2025 SAP SE or an SAP affiliate company and contributors. Please see our LICENSE for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available via the REUSE tool.