Sp
Developer Tools Azure

Stoplight Prism on Ubuntu 24.04 on Azure User Guide

| Product: Stoplight Prism 5.16.0 on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of Stoplight Prism on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Prism is a popular open source HTTP mock server and contract validation proxy. You point it at an API description in OpenAPI, Swagger or Postman format and it stands up a live mock server in seconds: every endpoint returns realistic, schema conformant example responses, and every incoming request is validated against the contract so mismatches are caught immediately. It lets front end, mobile and integration teams build against an API before the real backend exists, and lets teams prove that a running service actually honours its published contract.

The image installs Prism 5.16.0 (@stoplight/prism-cli) from the public npm registry, pinned to an exact version, on the Node.js 24 LTS runtime that Prism requires. Prism runs as a dedicated unprivileged prism system user under systemd (prism.service) and serves the mock on port 4010. A sensible starter OpenAPI 3.0 specification, the cloudimg Sample Widgets API, ships at /opt/prism/spec/cloudimg-sample-api.yaml and is served on first boot, so you can call a live mock immediately and then replace it with your own description whenever you are ready.

Secure by default, and honest about what that means. Prism is by design an unauthenticated mock server: serving a mock API to any client that can reach the port is its normal, intended function, so there is no login, password or token to manage and nothing to rotate. The image applies an honest secure by default posture around it: the mock returns only synthetic example data from the specification you provide and exposes no host secret, no filesystem and no administrative surface; Prism runs as an unprivileged user under a hardened systemd unit with the operating system kept read only outside its own state directory; and the only network listener is the mock itself. No SSH key and no default operating system credential are baked into the image.

What is included:

  • Stoplight Prism 5.16.0 (@stoplight/prism-cli) from the public npm registry, pinned, run under systemd (prism.service) as an unprivileged prism user, serving the mock on port 4010

  • Node.js 24 LTS (Krypton) from NodeSource, the runtime Prism 5.16.0 requires (engines node >=24.18.0)

  • A starter OpenAPI 3.0 specification (the cloudimg Sample Widgets API) at /opt/prism/spec/cloudimg-sample-api.yaml, served as a working mock out of the box, ready to be replaced with your own description

  • A hardened systemd unit and a run wrapper that selects mock or proxy mode from /etc/prism/prism.env

  • A fully patched Ubuntu 24.04 LTS base with unattended security upgrades enabled

Prerequisites

  • Active Azure subscription, SSH public key, VNet + subnet in target region

  • Subscription to the Stoplight Prism listing on Azure Marketplace

  • Network Security Group rules allowing TCP 22 (admin) and TCP 4010 (the mock API) from the developers, test runners and CI agents that will consume the mock

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample. Prism is a lightweight Node.js process; increase the size only if you drive very high request concurrency.

Step 1: Deploy from the Azure Portal

Search Stoplight Prism in Marketplace, select the cloudimg publisher, and click Create. Configure the Network Security Group to allow TCP 4010 from the clients and CI agents that will use the mock, and TCP 22 for administration. Keep 4010 restricted to the networks you serve.

Step 2: Deploy from the Azure CLI

RG="stoplight-prism-prod"; LOCATION="eastus"; VM_NAME="prism1"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/stoplight-prism-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$GALLERY_IMAGE_ID" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 4010 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1002

Step 3: First boot and the per instance info note

On first boot the image resolves this VM's address, (re)starts Prism with the shipped configuration, and writes a root only info note recording the reachable mock URL. This completes within seconds. SSH in as azureuser and read the note:

sudo cat /root/prism-info.txt

The note records PRISM_MOCK_URL for this instance plus ready to paste curl examples. Because Prism is an unauthenticated mock by design, the note contains no credential; it is purely a convenience.

Step 4: Confirm the service is running

prism.service is active and Prism is listening on port 4010.

systemctl is-active prism.service
prism --version
sudo ss -tlnp | grep ':4010 '

prism.service reports active, prism --version shows 5.16.0 on Node.js v24.18.0, and ss shows Prism listening on 0.0.0.0 port 4010

Step 5: Call the mock

The mock serves the endpoints defined in the shipped OpenAPI specification. GET /health is a liveness probe, and GET /widgets returns a schema conformant example array straight from the spec. These are real mocked responses, not just status codes.

curl -s http://127.0.0.1:4010/health | jq .
curl -s http://127.0.0.1:4010/widgets | jq .
curl -s http://127.0.0.1:4010/widgets/1 | jq .

Prism selects the example from the specification and returns it with the correct status code and content type, so your clients receive realistic data before the real backend exists.

GET /health returns status ok, and GET /widgets returns a schema conformant JSON array of two widgets straight from the OpenAPI specification

Step 6: Contract validation catches bad requests

Prism validates every incoming request against the contract. A request that matches the specification is accepted; a request that violates it is rejected with HTTP 422 and a body that explains exactly what was wrong. The sample POST /widgets requires a name property, so a request without one is rejected.

# a valid request that matches the contract is accepted (201)
curl -s -o /dev/null -w 'valid POST   -> HTTP %{http_code}\n' \
  -X POST http://127.0.0.1:4010/widgets \
  -H 'Content-Type: application/json' -d '{"name":"Gadget","color":"red"}'

# an invalid request (missing the required name) is rejected (422)
curl -s -o /dev/null -w 'invalid POST -> HTTP %{http_code}\n' \
  -X POST http://127.0.0.1:4010/widgets \
  -H 'Content-Type: application/json' -d '{"color":"red"}'

# the 422 body explains exactly which part of the contract was violated
curl -s -X POST http://127.0.0.1:4010/widgets \
  -H 'Content-Type: application/json' -d '{"color":"red"}' | jq .

The validation message reads Request body must have required property 'name', which is how Prism tells a client precisely how it broke the contract.

a valid POST returns HTTP 201 and an invalid POST that omits the required name returns HTTP 422, with the body reporting that the request body must have the required property name

Step 7: Verify the appliance end to end

A self test ships on the image and proves the whole mock round trip plus contract validation in one command. Run it at any time.

sudo /usr/local/bin/prism-selftest
grep '^PRISM_MOCK_URL=' /root/prism-info.txt

It prints an OK line after confirming /health, /widgets, a valid create and the invalid request rejection.

the prism selftest prints OK after proving the mock round trip and the contract validation, and the info note records the per instance mock URL

Step 8: Serve your own API description

Replace the sample specification with your own OpenAPI, Swagger or Postman description. Copy your file onto the VM, point PRISM_SPEC at it, and restart the service.

sudo nano /etc/prism/prism.env
# set  PRISM_SPEC=/opt/prism/spec/my-api.yaml  (or a URL), then save and:
sudo systemctl restart prism.service

PRISM_SPEC accepts a local file path or an http(s) URL. The rest of the environment file documents every option inline.

Step 9: Switch between mock, proxy and dynamic modes

Prism runs as a mock by default. It can instead run as a validation proxy that forwards requests to a real upstream and validates both the request and the response against the contract, or generate dynamic responses from the schema instead of static examples. Set the mode in the environment file.

# validation proxy: forward to a real backend and validate against the contract
#   in /etc/prism/prism.env set:
#     PRISM_MODE=proxy
#     PRISM_UPSTREAM=<upstream-url>
# dynamic responses generated from the schema instead of static examples:
#     PRISM_FLAGS=--dynamic
sudo systemctl restart prism.service

Step 10: Use the mock from your clients and CI

On any workstation or CI agent, point your HTTP client at this instance. Replace <vm-ip> with this instance's address (or a DNS name you point at it) and make sure the Network Security Group allows TCP 4010 from that client.

curl http://<vm-ip>:4010/widgets
curl -X POST http://<vm-ip>:4010/widgets -H 'Content-Type: application/json' -d '{"name":"Sprocket"}'

In a test suite or CI pipeline, set the mock base URL as an environment variable and point your integration tests at the instance. Every request then exercises a predictable, controllable endpoint you own instead of a shared service or an unfinished backend.

Step 11: Put a real domain and TLS in front for production

Prism serves plain HTTP because a mock returns only synthetic data. For a shared or internet facing deployment, place Prism behind your own reverse proxy that terminates TLS and, if you wish, adds authentication. Bind Prism to loopback by setting PRISM_HOST=127.0.0.1 in /etc/prism/prism.env so only your proxy can reach it, then front it with nginx and a CA signed certificate for <your-domain>.

Step 12: Security recommendations

  • Restrict the NSG. Allow TCP 4010 only from the developers, test runners and CI agents that consume the mock, and TCP 22 only from your administration network.

  • Front it with your own TLS proxy for anything shared. Bind Prism to loopback and terminate TLS at nginx with a real certificate when the mock is reachable beyond a trusted subnet.

  • Remember the mock is unauthenticated by design. It serves only synthetic data from your specification, but treat the port as open to whoever can reach it and scope the NSG accordingly.

  • Keep the OS patched. Unattended security upgrades remain enabled on the running VM.

Step 13: Support and Licensing

Stoplight Prism is open source software distributed under the Apache License 2.0. This cloudimg image bundles the unmodified upstream @stoplight/prism-cli release from the public npm registry. cloudimg provides the packaging, the systemd hardening, the dedicated unprivileged service account, the starter OpenAPI specification, the per instance info automation, the paired deploy guide, and 24/7 support with a guaranteed 24 hour response SLA.

cloudimg is not affiliated with or endorsed by Stoplight or the Prism project. Stoplight and Prism are marks of their respective owner and are used here only to identify the software.

Deploy on Azure

Find Stoplight Prism on Ubuntu 24.04 LTS on the Azure Marketplace, published by cloudimg. Deploy from the Portal or the Azure CLI as shown above.

Need Help?

Email support@cloudimg.co.uk for deployment help, configuration questions, or licensing enquiries.