Developer Tools AWS

Stoplight Prism API Mock Server on AWS User Guide

| Product: Stoplight Prism 5.16.0 on AWS

Overview

This guide covers deploying and operating Stoplight Prism on AWS using the cloudimg AWS Marketplace AMI. 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 AMI 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. 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. Prism itself has no native authentication, so rather than expose an open mock this image binds Prism to the loopback interface (127.0.0.1:8080) and fronts it with nginx on port 4010 enforcing HTTP Basic authentication. A unique Basic authentication credential (username prism, a random password) is generated for your instance on first boot, before the mock is reachable, and written to a root only file. No shared or default credential ships in the image, and two instances never share a credential. The mock returns only synthetic example data from the specification you provide, and exposes no host secret, no filesystem and no administrative surface.

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, bound to loopback 127.0.0.1:8080

  • nginx fronting Prism on port 4010 with per-instance HTTP Basic authentication minted at first boot

  • 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) 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

Connecting to your instance

Connect over SSH on port 22 as the default login user for your AMI's operating system:

Operating system SSH login user
Ubuntu 24.04 ubuntu
ssh ubuntu@<vm-ip>

Prerequisites

  • An AWS account and a subscription to the Stoplight Prism listing on AWS Marketplace
  • An EC2 key pair for SSH access
  • A security group allowing TCP 22 (admin) and TCP 4010 (the authenticated mock API) from the developers, test runners and CI agents that will consume the mock

Recommended instance type: m5.large is ample. Prism is a lightweight Node.js process; increase the size only if you drive very high request concurrency.

Step 1: Launch the AMI

Subscribe to Stoplight Prism on AWS Marketplace, then launch the AMI. In the security group, 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: Retrieve your per-instance credential

On first boot the AMI mints a unique HTTP Basic authentication credential for this instance, resolves the instance public address, and writes a root only note recording the reachable mock URL. This completes within seconds. SSH in and read the note:

sudo cat /root/prism-credentials.txt

The note records PRISM_BASIC_AUTH_USER (always prism), the generated PRISM_BASIC_AUTH_PASSWORD, and the PRISM_MOCK_URL for this instance, plus ready to paste curl examples. Store the password somewhere safe.

Step 3: Confirm the services are running

Prism runs on loopback and nginx fronts it on port 4010.

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

prism.service and nginx.service are both active. Prism listens on 127.0.0.1:8080 (loopback only) and nginx listens on 0.0.0.0:4010 (the public, authenticated mock).

prism.service and nginx.service report active, prism --version shows 5.16.0 on Node.js v24.18.0, and ss shows nginx listening on 0.0.0.0:4010 with Prism on loopback 127.0.0.1:8080

Step 4: Call the mock (authentication required)

The mock serves the endpoints defined in the shipped OpenAPI specification, behind HTTP Basic authentication. A request without the credential is rejected with HTTP 401; a request with the per-instance credential returns a real, schema conformant mocked response.

# no credentials -> the mock is refused (401)
curl -s -o /dev/null -w 'unauthenticated -> HTTP %{http_code}\n' http://<vm-ip>:4010/widgets

# with the per-instance credential -> a real mocked response (200)
curl -s -u prism:<PRISM_BASIC_AUTH_PASSWORD> http://<vm-ip>:4010/health | jq .
curl -s -u prism:<PRISM_BASIC_AUTH_PASSWORD> http://<vm-ip>:4010/widgets | 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.

An unauthenticated request to the mock returns HTTP 401, while the same request with the per-instance credential returns a schema conformant JSON array of two widgets straight from the OpenAPI specification

Step 5: 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' \
  -u prism:<PRISM_BASIC_AUTH_PASSWORD> -X POST http://<vm-ip>: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' \
  -u prism:<PRISM_BASIC_AUTH_PASSWORD> -X POST http://<vm-ip>:4010/widgets \
  -H 'Content-Type: application/json' -d '{"color":"red"}'

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 6: Verify the appliance end to end

A self test ships on the image and proves the whole authenticated mock round trip plus contract validation in one command. It reads the per-instance credential itself, so run it with sudo.

sudo /usr/local/bin/prism-selftest

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

Step 7: Serve your own API description

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

sudo nano /etc/prism/prism.env
# point PRISM_SPEC at your own description (a file path or an http(s) URL), save, then:
sudo systemctl restart prism
# your clients now reach the mock at  http://<public-ip>:4010/  (Basic auth)

PRISM_SPEC accepts a local file path or an http(s) URL. The rest of the environment file documents every option inline. Prism stays on loopback and nginx keeps enforcing Basic authentication, so your own API is served securely with no extra configuration.

Step 8: 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  and  PRISM_UPSTREAM=https://<your-domain>
# dynamic responses generated from the schema instead of static examples:
#   set  PRISM_FLAGS=--dynamic
sudo systemctl restart prism

Step 9: Use the mock from your clients and CI

On any workstation or CI agent, point your HTTP client at this instance using the per-instance credential. Replace <public-ip> with this instance's address and make sure the security group allows TCP 4010 from that client.

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

In a test suite or CI pipeline, set the mock base URL and credential as environment variables 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 10: Rotate the credential or add TLS for production

The per-instance credential lives in /etc/nginx/.prism_htpasswd. Rotate it at any time, and for anything shared or internet facing, terminate TLS in front of the mock.

# rotate the Basic auth password (username prism), then reload nginx:
sudo htpasswd -bB /etc/nginx/.prism_htpasswd prism '<new-password>'
sudo systemctl reload nginx

For a shared or internet facing deployment, place the instance behind your own reverse proxy or load balancer that terminates TLS with a certificate for your-domain, or run certbot with the nginx plugin on the instance.

Step 11: Security recommendations

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

  • Keep the per-instance credential secret. It is generated uniquely per instance and never shipped in the image; rotate it as needed with htpasswd.

  • Terminate TLS for anything shared. The mock is served over plain HTTP behind Basic authentication; add a TLS terminating proxy or load balancer when the mock is reachable beyond a trusted subnet.

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

Step 12: Support and Licensing

Stoplight Prism is open source software distributed under the Apache License 2.0. This cloudimg AMI 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 per-instance HTTP Basic authentication front door, the starter OpenAPI specification, the per instance credential automation, the paired deploy guide, and 24/7 support with a one hour average response for critical issues.

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.

Need Help?

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