> For the complete documentation index, see [llms.txt](https://docs.bloodgpt.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bloodgpt.com/integration-guides/on-premises.md).

# On-Premises Deployment

Running BloodGPT inside your own network: what the topology looks like, what your side has to provide, what still crosses the boundary, and what you give up by choosing it.

Every other integration path in this guide sends your data to our cloud. This one inverts that: our containers, our FHIR server, our database and our object storage run inside your network, on your volumes, under your network policy. We get no access to the data and no access to the machine.

## Who this is for

On-premises is the answer to a specific objection, and it is an expensive answer. Choose it if:

* Your security team or systems integrator will not grant outside access to patient data, and treats any external endpoint as a way to reach everything.
* Your regulatory position depends on processing staying inside the institution.
* Your organisation's data is a strategic asset and moving it to a vendor's cloud is a commercial non-starter.

If none of those apply, one of the four [Integration Options](/integration-guides/integration-options.md) will get you live in days rather than months.

## The principle: one door out

The whole design follows from a single rule: **at runtime, exactly one container is allowed to open an outbound connection — the model proxy, and only to the LLM provider's endpoints.** Databases, queues, storage, observability and authentication are all served from inside. Egress is denied by default and opened by domain allowlist.

There is a second door, and it matters that we name it rather than round it away: the image supply channel. It lives on your deployment host, not in the running system, opens only for the duration of a pull, and is unreachable from the application containers. So the allowlist has two entries, belonging to different hosts at different moments.

```mermaid
flowchart TB
    subgraph perimeter["Your private network — egress denied by default"]
        direction TB

        subgraph client["Your systems and people"]
            lis[("Your LIS / EHR")]
            idp["Your IdP<br/>OIDC / SAML"]
            clinician(["Clinician"])
        end

        deploy["Deployment host<br/>operated by your staff"]

        subgraph apps["Our containers"]
            ui["Clinician surface"]
            api["Intake API"]
            runner["Analysis runner"]
            norm["Normalization<br/>+ LOINC dictionary<br/>shipped in the image"]
            proxy["Model proxy<br/>the one runtime door out"]
            obs["Observability"]
        end

        subgraph stores["Our data stores — on your volumes"]
            fhir[("FHIR server")]
            pg[("PostgreSQL")]
            obj[("Object storage")]
        end
    end

    llm["LLM provider<br/>outside the perimeter, EU region"]
    registry["Our private image registry<br/>EU region, read-only access"]

    deploy -. "pulls images: first delivery and every update.<br/>Outbound only, open for the duration of the pull" .-> registry
    deploy -->|"deploys"| apps

    lis -->|"export / interface"| api
    idp --> ui
    clinician --> ui
    ui --> api
    ui --> fhir
    api --> pg
    api --> obj
    api --> runner
    runner --> norm
    runner --> fhir
    runner --> pg
    runner --> obj
    runner --> obs
    runner --> proxy
    proxy ==>|"only runtime egress:<br/>HTTPS, domain allowlist"| llm
```

Both outbound lines are initiated from inside. No external party — including us — can open a connection into your network.

## What still crosses the boundary

This is the part to read closely, because it is the part most easily oversold. "Everything except the model stays inside" is a statement about **components**, not about **data**.

The request we send to the language model carries biomarker values, relevant history, medications and clinical context. Under the GDPR that is special-category data, and it does leave your perimeter. Three commitments follow, and we would rather state them here than have your security team extract them:

| Commitment                                                   | What it means                                                                                                                                                                                  |
| ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Direct identifiers are removed before the request leaves** | Name, date of birth and your own patient identifiers are not in the prompt. What goes out is keyed by an internal identifier that can only be resolved back to a person inside your perimeter. |
| **Region and contract are pinned**                           | The provider and the route are pinned to an EU region, enforced in the proxy configuration rather than agreed in a document.                                                                   |
| **Outbound traffic is audited**                              | The proxy records what left and where it went, and that log is yours to read. Without it, "only this goes out" is an assertion with nothing behind it.                                         |

Running the model inside your perimeter too — which would make "data never leaves" literally true — is **not a rejected option, it is an unstudied one.** We have no GPU infrastructure and no experience operating it, and we have not measured open-model quality on clinical material in your language. If this is a hard requirement for you, say so early; it changes the project rather than adding to it.

## What you provide

| Requirement                                                | Detail                                                                                                                                                                                                                                                                                 |
| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Compute inside the perimeter**                           | A host or cluster able to run our containers. Whether that is Kubernetes or plain container runtime changes the shape of the delivery, so tell us which you have — we have shipped into an enclave restricted to bare `docker run`, without Compose, and it is workable but different. |
| **Persistent volumes**                                     | For PostgreSQL, the FHIR server and object storage. Sizing depends on volume and retention; we will size it with you.                                                                                                                                                                  |
| **A deployment host with outbound access to our registry** | Read-only, for the duration of a pull. Your staff operate it; we never touch it.                                                                                                                                                                                                       |
| **Egress allowlist**                                       | Two domains: the LLM provider endpoints and our image registry.                                                                                                                                                                                                                        |
| **An LLM provider account**                                | Inside your perimeter the provider key is **yours**, not ours. Our cloud secrets scheme does not apply here, and the commercial relationship with the model provider becomes yours to hold.                                                                                            |
| **An identity provider**                                   | OIDC or SAML, or local accounts if you prefer.                                                                                                                                                                                                                                         |
| **Operations staff**                                       | Backups, restores, upgrades and failover are on your side. We supply a runbook; we cannot supply an on-call engineer who can see the machine.                                                                                                                                          |
| **A data export or interface from your LIS**               | The intake path is built against whatever your system can produce. Agreeing that format is usually the longest single item in the project.                                                                                                                                             |

## What replaces our managed services

Our cloud stack leans on managed services from Google and other vendors. None of them exist inside your perimeter, so each is replaced by something running in a container next door. The third column is what actually breaks — not an abstract risk.

| In our cloud                   | Inside your perimeter                       | Cost of the swap                                                                                                                                               |
| ------------------------------ | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Google Healthcare API (FHIR)   | HAPI FHIR on your volume                    | Our code is written against Google's behaviour — field selection and resource authorship differ. This needs a compatibility run, not just a change of address. |
| Cloud SQL PostgreSQL           | PostgreSQL in a container                   | Backups, upgrades and failover become yours. You need a runbook, not "it just works".                                                                          |
| Google Cloud Storage           | MinIO or a mounted volume                   | S3 compatibility covers the interface; retention and deletion policies must be written again from scratch.                                                     |
| Managed workflow orchestration | A thin batch runner over the same steps     | No broker to operate. Resumption happens by stage, through artefacts on disk, rather than by durable execution.                                                |
| Hosted identity (WorkOS)       | Your IdP, or local accounts                 | Our role layer is tied to hosted organisations. Inside a perimeter there is one organisation, but the code does not assume that yet.                           |
| Hosted LLM tracing             | Self-hosted tracing, or traces to a file    | We are customers of a hosted product and have no self-hosted deployment of it. This is new work for us.                                                        |
| External LOINC service         | Dictionary shipped inside the image         | Otherwise the step is silently skipped and trends stop keying correctly. Dictionary updates then arrive as a new image.                                        |
| Stripe                         | Absent                                      | No billing inside the perimeter; commercials are settled outside the system.                                                                                   |
| GitOps / ArgoCD                | Your staff deploy from our private registry | Version addressability and rollback survive. Declarative state does not.                                                                                       |
| LLM provider                   | **Stays outside**                           | The single exception to the rule. See [What still crosses the boundary](#what-still-crosses-the-boundary).                                                     |

## Delivery and updates

The supply channel is **read-only access to our private image registry**. You get a principal that can pull, and only from one dedicated repository — no write access, no visibility into neighbouring repositories. The repository sits in our EU-region registry alongside our other images.

The property that matters: **the first delivery and every subsequent update travel the same path.** An update stops being an event with a hand-delivered file and becomes a tag change — you pull when you decide to, and roll forward on your own procedure. Your staff still deploy. We still have no access inside.

What that buys you over a file on a shared drive:

* **Provenance is checkable.** The image is addressed by digest, not by filename. Your security team's inspection before first run does not go away — the scanner gets a stable address instead.
* **Rollback exists.** The previous digest stays in the registry. "Roll back" stops meaning "ask the vendor to re-upload".
* **Both sides know what is running.** Registry access logs show which digest was pulled and when. Without that, the version inside your perimeter is known only by report.
* **Revocation is real, but bounded.** We can revoke read access, and new versions stop being available. Images you already pulled keep running — the registry is a supply channel, not a kill switch, and we will not tell you otherwise.

If your security team says even that is too much — and they are entitled to — the model survives in two fallbacks. **Mirror inside the perimeter:** organisations of this size usually already run a registry; we publish to ours, you copy to yours, and both runtime and deployment stay internal. This is most often what security proposes themselves. **Full air-gap:** we export the image to a signed archive addressed by digest, and it is carried in by hand. That returns a manual channel, but one cured of its worst property — you can still verify what you received.

## What we can and cannot see

Worth settling before deployment rather than after. The sensible split: outputs of the system, component health and errors — yes. Contents of patient records — no.

In practice, observability inside the perimeter writes two streams: a complete one for you, and a sanitised one for us. The second leaves only if you have explicitly agreed to it; if you have not, we collect it by export on request. **Our default assumption is that the second stream does not exist** — the one-door rule outranks our convenience in support.

The direct consequence, which we would rather you hear from us: when something fails inside your perimeter, we can see neither the logs nor the machine. Support runs through your staff reproducing and exporting, so the escalation path and response expectations are agreed as part of scoping rather than assumed from our cloud terms.

## Hardening on the roadmap

Three properties that this topology implies are on the roadmap for first delivery rather than in place today. We flag them here because a security reviewer will ask, and because an evidence request we cannot answer costs more than an early "not yet".

| Property                       | Where it stands                                                                                                                                                                                                                                                                                                     |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Image signing**              | Images are addressed by digest today, which is a property of any OCI registry rather than proof of origin. Signing is the piece that makes the supply channel carry what we moved to a registry for, and it is scheduled ahead of a first deployment. Expect your reviewer to raise it first.                       |
| **Verified registry scanning** | Vulnerability scanning is enabled on our registry; verifying its output end to end, so that we can hand you scan reports as evidence, is outstanding work.                                                                                                                                                          |
| **EU-pinned model routing**    | Some routes to preview models are currently configured to a global region. For an EU deployment those routes are prohibited, and the prohibition belongs in the proxy configuration rather than in an agreement. This is the one of the three we can close with existing work, and it closes before anything ships. |

## Next step

On-premises starts with a scoping conversation, not an API key. Useful things to bring:

1. What "inside the perimeter" means physically for you — your hardware, a tenant you rent, or a machine at your integrator.
2. Whether you have Kubernetes or are limited to running individual containers.
3. Which of the three registry models your security team prefers: direct pull, mirror to your own registry, or full air-gap.
4. What your source system can export, and where it is hosted relative to the perimeter.

{% hint style="info" %}
**Start the conversation:** <contact@bloodgpt.com>. Tell us it is an on-premises enquiry and bring your security team in early — this model is easier to design with them than to justify to them afterwards.
{% endhint %}
