---
title: Bioreactor suite
slug: solutions/bioreactor-suite
docTags: 
createdAt: 2026-08-17T14:31:57.177Z
---

A monoclonal antibody fermentation suite running ISA-88 batches: media charge, bioreactor, harvest, with the cleanroom environment judged across the whole batch. Five devices and 94 tags over Modbus TCP.

| Operator view      | port **4011**            |
| ------------------ | ------------------------ |
| Protocol server    | port **5021**            |
| Devices and tags   | 5 devices, 94 tags       |
| Litmus Edge driver | Modbus TCP               |
| Image              | `pharma-bioreactor-demo` |

## Scenarios

- **A batch that cannot be released.** A critical process parameter leaves its recipe band for long enough to matter. The deviation is recorded against the batch, not against a shift, and it is visible while the batch is still running.
- **Right first time.** Across a campaign, the proportion of batches that completed without a deviation, which is the number a quality organisation is actually measured on.
- **The batch record itself.** An electronic record assembled from what Litmus Edge recorded: phases, parameters, deviations and environment, exportable at the end of the batch.

## What it creates on Litmus Edge

Five DeviceHub devices covering the reactor, the media charge and harvest vessels, the temperature control unit and the cleanroom, with 94 tags. A Digital Twin model and instance per vessel. Analytics groups behind the deviation, yield and release figures.

## Requirements

- Litmus Edge 4.0.x, reachable over HTTPS from the host running the solution
- An API token for that Edge, or a username and password, or a client id and secret
- Docker, and Docker Compose for the compose deployment
- A network path in both directions: the solution reaches the Edge's API, and the Edge reaches this host on the protocol port

## Deploy

The solution ships two ways. Use the registry if the host can reach Google Artifact Registry, and the downloaded archive if it cannot.

### Option 1: pull from the registry

Requires a read-only registry credential, supplied by Litmus separately.

```bash
cat key.json | docker login -u _json_key --password-stdin https://us-docker.pkg.dev
```

Save this as `docker-compose.yml`:

```yaml
services:
  pharma-bioreactor:
    image: us-docker.pkg.dev/litmus-customer-facing/litmus-solutions/pharma-bioreactor-demo:0.6.1
    container_name: pharma-bioreactor-demo
    restart: unless-stopped
    ports:
      - target: 4011
        published: 4011
        protocol: tcp
      - target: 5021
        published: 5021
        protocol: tcp
    environment:
      # Fill these in.
      EDGE_URL: "${EDGE_URL:-}"
      EDGE_API_TOKEN: "${EDGE_API_TOKEN:-}"
      SIM_HOST: "${SIM_HOST:-auto}"
      APPLY_ON_START: "${APPLY_ON_START:-1}"
      EDGE_VERIFY_TLS: "${EDGE_VERIFY_TLS:-0}"
      # Optional: publish the twins into Litmus Unify.
      UNIFY_URL: "${UNIFY_URL:-}"
      UNIFY_USERNAME: "${UNIFY_USERNAME:-}"
      UNIFY_PASSWORD: "${UNIFY_PASSWORD:-}"
      UNIFY_CONNECTOR: "${UNIFY_CONNECTOR:-}"
      HTTP_PORT: "4011"
      MODBUS_PORT: "5021"
      AUTOSTART: "1"
      TICK_SECONDS: "0.2"
      SEED: "11"
      LOG_LEVEL: "INFO"
```

```javascript
EDGE_URL=https://10.0.0.5
EDGE_API_TOKEN=your-token
SIM_HOST=10.0.0.9
```

```bash
docker compose up -d
```

Or, without Docker Compose, run the same image with the same `.env`:

```bash
docker run -d \
  --name pharma-bioreactor-demo \
  --restart unless-stopped \
  -p 4011:4011 \
  -p 5021:5021 \
  --env-file .env \
  -e APPLY_ON_START=1 \
  -e EDGE_VERIFY_TLS=0 \
  -e HTTP_PORT=4011 \
  -e MODBUS_PORT=5021 \
  -e AUTOSTART=1 \
  -e TICK_SECONDS=0.2 \
  -e SEED=11 \
  -e LOG_LEVEL=INFO \
  us-docker.pkg.dev/litmus-customer-facing/litmus-solutions/pharma-bioreactor-demo:0.6.1
```

Flags given with `-e` take precedence over `.env`, so change `APPLY_ON_START` or `EDGE_VERIFY_TLS` on the command line rather than in the file.

Open `http://localhost:4011`.

**The page stays on its waiting panel until the Edge carries this solution's devices.** That is deliberate: the simulation does not tick and no value is shown until Litmus Edge is verified to hold the devices and poll them, so nothing on screen can be mistaken for data that never made the trip. With `APPLY_ON_START` at its default of `1` the solution configures the Edge itself on startup, which takes 30 to 60 seconds. If you set it to `0`, or the apply failed, press **Apply to Edge** in the page header.

### Option 2: load the downloaded archive

Download `pharma-bioreactor-demo-0.6.1-amd64.tar.gz` from the solution's page on portal.litmus.io. The archive is the container image, not a source bundle, and needs no registry access.

```bash
docker load -i pharma-bioreactor-demo-0.6.1-amd64.tar.gz
```

`docker load` prints the image it added:

```javascript
Loaded image: us-docker.pkg.dev/litmus-customer-facing/litmus-solutions/pharma-bioreactor-demo:0.6.1
```

That reference is the one the compose file above already names, so the same `docker-compose.yml` and `.env`, or the `docker run` command above, now work offline with no `docker login`:

```bash
docker compose up -d
```

To run it without Compose, pass the same three values on the command line:

```bash
docker run -d \
  --name pharma-bioreactor-demo \
  --restart unless-stopped \
  -p 4011:4011 \
  -p 5021:5021 \
  -e EDGE_URL=https://10.0.0.5 \
  -e EDGE_API_TOKEN=your-token \
  -e SIM_HOST=10.0.0.9 \
  us-docker.pkg.dev/litmus-customer-facing/litmus-solutions/pharma-bioreactor-demo:0.6.1
```

## Configuration

| Variable          | Default             | What it does                                                               |
| ----------------- | ------------------- | -------------------------------------------------------------------------- |
| `EDGE_URL`        | the Docker host     | Litmus Edge to configure                                                   |
| `EDGE_API_TOKEN`  | unset               | token for that Edge. Or a username and password, or a client id and secret |
| `SIM_HOST`        | `auto`              | address the Edge polls to reach this solution                              |
| `APPLY_ON_START`  | `1`                 | configure the Edge on startup                                              |
| `EDGE_VERIFY_TLS` | `0`                 | `1` checks the Edge's certificate                                          |
| `UNIFY_URL`       | unset               | optional: Litmus Unify to publish the twins into                           |
| `UNIFY_USERNAME`  | unset               | optional: a Unify user                                                     |
| `UNIFY_PASSWORD`  | unset               | optional: that user's password                                             |
| `UNIFY_CONNECTOR` | the Edge's only one | optional: which Litmus UNS connector on the Edge to publish through        |
| `AUTOSTART`       | `1`                 | start a batch on boot                                                      |
| `SEED`            | `11`                | makes a run repeatable                                                     |

## Litmus Unify (optional)

This solution can also publish its 5 Digital Twins into Litmus Unify, one message per asset under `litmus/pharma-site-01/...`. It stays off until two things are true: the `UNIFY_` values above are set, and the Litmus Edge has a Litmus UNS connector, which the [Solutions provisioner](solutions-provisioner) can pair in one click. The next apply then publishes the twins, the page header shows how many are arriving, and removing the solution from the Edge removes its branch from Unify as well. Leave the values empty to keep Unify out of it.

## Operator view

The batch runs through its ISA-88 phases along the top: sterilise in place, charge media, growth, harvest. Below, the vessels fill and drain, the agitator turns, and each critical process parameter is shown against the recipe band it has to stay inside.

The environment section is judged across the whole batch rather than sampled, so a room pressure excursion during growth counts against the batch even if the reading has recovered by harvest.

Preview or export the batch record at any point to see what has been recorded so far.

Faults available include parameter excursions, a jacket temperature fault and a cleanroom pressure loss.

## Apply and remove

```bash
docker compose down
```

Use Clean up in the [Solutions provisioner](solutions-provisioner) to remove what it created on the Edge.

## Support

[support@litmus.io](mailto\:support@litmus.io)
