> For the complete documentation index, see [llms.txt](https://docs.nfh.global/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nfh.global/product-documentation/products/vc-on-edge/docker.md).

# Docker image & API

Run the OpenCred Docker image for headless issuance and verification — cloud, on-prem, and CI/CD. Your infrastructure, your keys.

The OpenCred Docker image is the headless variant of the Desktop client. It exposes an HTTP API (and a CLI) for issuing and verifying credentials — for cloud deployments, on-prem servers, and CI/CD pipelines. It runs in **your** infrastructure; no data is sent to OpenCred or NFH Trust Labs.

## Quick start

```bash
# 1. Pull the public image (no auth required)
docker pull ghcr.io/nfh-trust-labs/opencred/opencred-server:latest

# 2. Run with a mounted signing key
docker run -p 3100:3100 \
  -e OPENCRED_PORT=3100 \
  -e OPENCRED_API_KEY=your-secret-token \
  -e OPENCRED_KEY_PATH=/secrets/issuer-key.pem \
  -v /path/to/your/key.pem:/secrets/issuer-key.pem:ro \
  ghcr.io/nfh-trust-labs/opencred/opencred-server:latest

# 3. Check it's running
curl http://localhost:3100/v1/health
```

A healthy server returns `200 OK`:

```json
{
  "status": "ok",
  "ready": true,
  "signingKeyLoaded": true,
  "dediConfigured": false,
  "timestamp": "2026-04-07T10:00:00.000Z"
}
```

If `signingKeyLoaded` is `false`, the server returns `503` and cannot issue — check your key source.

## Image tags & architecture

```bash
docker pull ghcr.io/nfh-trust-labs/opencred/opencred-server:latest   # floats
docker pull ghcr.io/nfh-trust-labs/opencred/opencred-server:1.2.0    # pin in production
```

Each version tag is built by CI from a signed git tag and scanned with Trivy (CRITICAL/HIGH fail the build). From **v1.2.0** the image is a **multi-arch manifest** (`linux/amd64` + `linux/arm64`) — Docker pulls the right variant automatically on Apple Silicon, AWS Graviton, Ampere, Raspberry Pi 4/5, and amd64 VMs.

> **Pin a version in production.** `:latest` can change underneath you on the next release.

## Production run (hardened)

```bash
docker run -d \
  --name opencred \
  -p 3100:3100 \
  -e OPENCRED_PORT=3100 \
  -e OPENCRED_API_KEY=sk_prod_change_me \
  -e OPENCRED_KEY_PATH=/secrets/issuer-key.pem \
  -e OPENCRED_LOG_LEVEL=info \
  -v /host/path/issuer-key.pem:/secrets/issuer-key.pem:ro \
  --read-only \
  --tmpfs /tmp:noexec,nosuid,size=64m \
  --cap-drop ALL \
  --security-opt no-new-privileges:true \
  ghcr.io/nfh-trust-labs/opencred/opencred-server:latest
```

### Docker Compose

The repo ships a hardened `docker-compose.yml` (read-only FS + tmpfs, all caps dropped except `NET_BIND_SERVICE`, `no-new-privileges`, `/v1/health` check every 30s):

```bash
docker compose up -d            # start
docker compose logs -f server   # follow logs
docker compose down             # stop
```

### Build from source

```bash
docker build -f apps/server/Dockerfile -t opencred:latest .
```

Multi-stage build on a pinned `node:20-alpine` base, runs as non-root `node`, exposes `3100`, starts via `node apps/server/dist/index.js`.

## Providing a signing key

Your key stays in your infrastructure — loaded at startup, never transmitted.

* **File-based (default):** set `OPENCRED_KEY_PATH` to a PEM, JWK, PKCS#8, or PFX file. For PFX, also set `OPENCRED_KEY_PASSWORD`.
* **Cloud HSM:** set `OPENCRED_KMS_PROVIDER` to `aws`, `azure`, or `gcp` with the provider variables. See the in-repo **Cloud HSM** guide (AWS KMS, Azure Key Vault, GCP Cloud KMS).

## HTTP API

All endpoints are under `/v1`. Auth is a required Bearer token (`OPENCRED_API_KEY`); the middleware is fail-closed.

| Endpoint                                 | Purpose                                                    |
| ---------------------------------------- | ---------------------------------------------------------- |
| `GET /v1/health`                         | Readiness + signing-key status                             |
| `GET /v1/keys`                           | Active signer info                                         |
| `GET /v1/schemas`                        | Available credential schemas                               |
| `POST /v1/credentials/issue`             | Issue a single credential                                  |
| `POST /v1/credentials/batch`             | Batch issuance                                             |
| `POST /v1/credentials/verify`            | Verify (JSON-LD / vc-jwt / sd-jwt-vc / PixelPass QR / PDF) |
| `POST /v1/credentials/package`           | Package as printable PDF / QR                              |
| `POST /v1/credentials/revocation-hash`   | Compute a revocation hash                                  |
| `POST /v1/credentials/revoke`            | Revoke a credential                                        |
| `POST /v1/credentials/revocation-status` | Check status                                               |
| `GET /v1/metrics`                        | Metrics                                                    |

> For local development only, `OPENCRED_DEV_MODE_NO_AUTH=true` disables auth. **Never** use it in production.

## CLI

The image bundles an `opencred` CLI for one-off, no-HTTP operations (issue, verify, package) — handy in shells and CI. See [Verifying credentials](/product-documentation/products/vc-on-edge/verifying.md) for `opencred verify`.

## Security defaults

Non-root user · pinned base digests · no secrets in image layers · read-only FS + dropped caps in Compose · JSON-LD contexts bundled at build time (never fetched at runtime) · structured pino logging to stdout with key material redacted. Full model: [Security](/product-documentation/products/vc-on-edge/security.md).

***

**Related:** [Verifying credentials](/product-documentation/products/vc-on-edge/verifying.md) · [Concepts](/product-documentation/products/vc-on-edge/concepts.md) · [Security model](/product-documentation/products/vc-on-edge/security.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.nfh.global/product-documentation/products/vc-on-edge/docker.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
