Use Dev Proxy in CI/CD scenarios

At a glance
Goal: Integrate Dev Proxy in CI/CD
Time: 30 minutes
Plugins: Various
Prerequisites: Set up Dev Proxy

Using Dev Proxy in CI/CD scenarios is a great way to test your applications in a controlled environment. When you combine Dev Proxy with tests that generate API requests in your application, you can cover a wide range of scenarios: from ensuring that your app doesn't use shadow- or nonproduction APIs to checking that it uses minimal Microsoft Graph permissions. While the exact configuration steps vary depending on your CI/CD system, here are some general principles that you should follow.

In most cases, your runner doesn't have Dev Proxy installed. So before you can use Dev Proxy, you need to install it. The installation steps depend on the operating system that your runner uses.

Tip

To speed up your pipeline, consider caching the Dev Proxy installation folder. This way, you don't need to download Dev Proxy every time you run your pipeline. For the exact steps, refer to the documentation of your CI/CD system.

When installing Dev Proxy in a CI/CD setup, you typically want to pin the version of Dev Proxy that you install. Pinning the version ensures that your pipeline uses the same version of Dev Proxy every time you run it. The exact steps to pin a version depend on the operating system of your runner. Here's an example of how you can pin the version of Dev Proxy on a Linux-based runner:

# install Dev Proxy v1.0.0
bash -c "$(curl -sL https://aka.ms/devproxy/setup.sh)" -- v1.0.0

In a CI/CD pipeline, start Dev Proxy with the same set of options every time, so that it runs in the background, doesn't change the runner's configuration, and doesn't wait for user input. We recommend the following options:

Option Why
--detach Runs Dev Proxy in the background, so that it doesn't block your pipeline.
--as-system-proxy false Prevents Dev Proxy from registering itself as the system proxy on the runner. Your app uses Dev Proxy only when you point it to the proxy, for example using the http_proxy and https_proxy environment variables.
--install-cert false Prevents Dev Proxy from trying to install its root certificate. In a pipeline, you trust the certificate yourself, as described in Trust the Dev Proxy root certificate.
--no-first-run Skips the first run experience, which isn't needed on a fresh runner.
--no-watch Disables automatically restarting Dev Proxy when its configuration file changes.

Additionally, before you start Dev Proxy, set the DEV_PROXY_API_TOKEN environment variable to a token that you generate. This way, you know the token that you need to call the Dev Proxy API without having to retrieve it from Dev Proxy. The token must be at least 32 characters long. For the full requirements, see Proxy API.

# generate an API token for this run
export DEV_PROXY_API_TOKEN=$(openssl rand -hex 32)

The examples in this article use these options and the DEV_PROXY_API_TOKEN environment variable.

Get a configuration for recording API calls

If you want to record which APIs your app calls during a CI run, you don't need to build a configuration from scratch. Download the api-inventory preset from the Dev Proxy samples gallery using the config get command:

./devproxy/devproxy config get api-inventory

The preset combines the UrlDiscoveryPlugin and ExecutionSummaryPlugin with reporters, and doesn't register Dev Proxy as the system proxy. When you start Dev Proxy, pass the preset's configuration file, override the URLs to watch with the APIs that your app calls, and use the recommended CI flags:

./devproxy/devproxy --config-file "~dataFolder/configs/api-inventory/.devproxy/devproxyrc.json" --urls-to-watch "https://api.contoso.com/*" --detach --as-system-proxy false --install-cert false --no-first-run --no-watch

For more information about presets, see Use preset configurations.

Start Dev Proxy

After installing Dev Proxy, you need to start it. When starting Dev Proxy in a CI/CD pipeline, it's important that you start it in the background. Otherwise, your pipeline is blocked until you stop Dev Proxy.

Start Dev Proxy in the background using the recommended CI flags:

# start Dev Proxy in detached mode
./devproxy/devproxy --detach --as-system-proxy false --install-cert false --no-first-run --no-watch

Dev Proxy prints startup information including the process ID (PID), Proxy URL, API URL, and log file path:

Dev Proxy started in background.

  PID:       6456
  Proxy URL: http://127.0.0.1:8000
  API URL:   http://127.0.0.1:8897
  Log file:  /home/runner/.local/dev-proxy/logs/devproxy-6456-2026-03-05.log

For machine-readable output, use --output json to get JSONL:

./devproxy/devproxy --detach --as-system-proxy false --install-cert false --no-first-run --no-watch --output json
{"type":"result","data":{"pid":6456,"proxyUrl":"http://127.0.0.1:8000","apiUrl":"http://127.0.0.1:8897","logFile":"/home/runner/.local/dev-proxy/logs/devproxy-6456-2026-03-05.log"},"timestamp":"2026-03-05T14:22:42.0000000Z"}

Tip

Use --port 0 and --api-port 0 to let the OS assign random available ports. The detached mode output shows the actual ports assigned by the OS, which is useful in CI/CD scenarios to avoid port conflicts. When you use random ports, read the proxy URL and API URL from the output instead of using the default http://127.0.0.1:8000 and http://127.0.0.1:8897, as shown in the example start script.

Alternatively, if you're using a Linux-based runner, you can start Dev Proxy in the background using shell job control:

# start Dev Proxy in the background
./devproxy/devproxy --as-system-proxy false --install-cert false --no-first-run --no-watch > devproxy.log 2>&1 &

Wait for Dev Proxy to start

When you start Dev Proxy in the background, your script continues immediately. However, Dev Proxy needs some time to start. To ensure that Dev Proxy is ready before you start issuing requests, wait until its API responds to a GET /proxy request:

api_url=http://127.0.0.1:8897

echo "Waiting for Dev Proxy to start..."
until curl -sf -o /dev/null "$api_url/proxy" -H "Authorization: Bearer $DEV_PROXY_API_TOKEN"; do
  sleep 1
done

# the rest of your script

Polling the API works regardless of the port that Dev Proxy listens on, including when you use --port 0.

Trust the Dev Proxy root certificate

After Dev Proxy starts, you need to trust the Dev Proxy root certificate before sending requests, because Dev Proxy uses a self-signed root certificate.

Depending on your permissions, you might need to create the ~/.config/dev-proxy/rootCert folder, in which Dev Proxy stores its root certificate, before starting Dev Proxy:

# ensure the rootCert folder
echo "Ensuring the Dev Proxy rootCert folder"
mkdir -p ~/.config/dev-proxy/rootCert

To get the public key of the root certificate, download it using the Dev Proxy API. If you're using a Linux-based runner, you can then install the certificate by copying it to the system's trusted CA certificates store:

# download the Dev Proxy's Root Certificate
echo "Downloading the Dev Proxy's Root Certificate"
curl -sf -o dev-proxy-ca.crt "$api_url/proxy/rootCertificate?format=crt" -H "Authorization: Bearer $DEV_PROXY_API_TOKEN"

# install root certificate
echo "Installing the Dev Proxy's Root Certificate"
sudo cp dev-proxy-ca.crt /usr/local/share/ca-certificates/

# update CA certificates
echo "Updating the CA certificates"
sudo update-ca-certificates

Configure proxy environment variables

Many applications and libraries use the http_proxy and https_proxy environment variables to determine the proxy server to use for HTTP and HTTPS requests. Because you start Dev Proxy with --as-system-proxy false, you need to set these environment variables to point to the Dev Proxy instance to ensure that your application uses Dev Proxy.

export http_proxy=http://127.0.0.1:8000
export https_proxy=http://127.0.0.1:8000

Control Dev Proxy

When you run Dev Proxy in a CI/CD pipeline, you can't control it interactively. Instead, you can control it by sending requests to the Dev Proxy API.

All Dev Proxy API requests require a bearer token in the Authorization header. If you set the DEV_PROXY_API_TOKEN environment variable as recommended, use its value. Otherwise, because Dev Proxy doesn't print the token at startup when the CI environment variable is set, retrieve it using the api token command:

export DEV_PROXY_API_TOKEN=$(./devproxy/devproxy api token)

If you want to analyze API requests issued by your app, you can send a POST request to the /proxy endpoint to start recording:

curl -sf -X POST "$api_url/proxy" -H "Authorization: Bearer $DEV_PROXY_API_TOKEN" -H "Content-Type: application/json" -d '{"recording": true}'

To stop recording, send a POST request to the /proxy endpoint with recording set to false:

curl -sf -X POST "$api_url/proxy" -H "Authorization: Bearer $DEV_PROXY_API_TOKEN" -H "Content-Type: application/json" -d '{"recording": false}'

To stop Dev Proxy, you can send a POST request to the /proxy/stopproxy endpoint:

curl -sf -X POST "$api_url/proxy/stopproxy" -H "Authorization: Bearer $DEV_PROXY_API_TOKEN"

After you stop the Dev Proxy process, it can take a moment for it to fully close. To ensure that Dev Proxy finished, wait for its log file, which Dev Proxy prints when it starts in detached mode, to contain one of the completion messages, for example:

echo "Waiting for Dev Proxy to complete..."
while true; do
  if grep -q -e "DONE" -e "No requests to process" -e "An error occurred in a plugin" "$log_file"; then
    break
  fi
  sleep 1
done

When all recording plugins finish running, Dev Proxy prints the DONE message to the output. If there were no requests to process, Dev Proxy prints the No requests to process message. If an error occurred in a plugin, Dev Proxy prints the An error occurred in a plugin message. When you see any of these messages, you can be sure that Dev Proxy finished processing the recorded requests.

Example start script

Here's an example of a bash script that you can use to start Dev Proxy in a CI/CD pipeline. The script uses the recommended CI flags, reads the proxy URL, API URL, and log file path from the JSON output, waits until the Dev Proxy API responds, and trusts the root certificate downloaded from the API. It uses jq to parse the JSON output.

echo "Generating the Dev Proxy API token"
export DEV_PROXY_API_TOKEN=$(openssl rand -hex 32)

echo "Ensuring Dev Proxy rootCert folder"
mkdir -p ~/.config/dev-proxy/rootCert

echo "Starting Dev Proxy"
result=$(./devproxy/devproxy --detach --as-system-proxy false --install-cert false --no-first-run --no-watch --output json | jq -c 'select(.type == "result")')
if [ -z "$result" ]; then
  echo "Failed to start Dev Proxy"
  exit 1
fi

proxy_url=$(echo "$result" | jq -r '.data.proxyUrl')
api_url=$(echo "$result" | jq -r '.data.apiUrl')
log_file=$(echo "$result" | jq -r '.data.logFile')

echo "Waiting for Dev Proxy to start..."
until curl -sf -o /dev/null "$api_url/proxy" -H "Authorization: Bearer $DEV_PROXY_API_TOKEN"; do
  sleep 1
done

echo "Downloading the Dev Proxy's Root Certificate"
curl -sf -o dev-proxy-ca.crt "$api_url/proxy/rootCertificate?format=crt" -H "Authorization: Bearer $DEV_PROXY_API_TOKEN"

echo "Installing the Dev Proxy's Root Certificate"
sudo cp dev-proxy-ca.crt /usr/local/share/ca-certificates/

echo "Updating the CA certificates"
sudo update-ca-certificates

echo "Set proxy variables"
export http_proxy=$proxy_url
export https_proxy=$proxy_url

See also