Migrate from Aidbox to Multibox
Multibox is a management layer on top of Aidbox that runs many isolated Aidbox instances, called boxes, from a single deployment. A portal provisions, routes to, and manages every box: it keeps its own portal database for box metadata, user accounts, and collaborator relationships, and each box gets a separate PostgreSQL database for its FHIR data, grouped in the same Postgres cluster. Migrating a standalone Aidbox instance into Multibox means creating a new box and moving your existing FHIR data into it.
There is no automated migration tool for this direction. Use the steps below, and test the full flow against a copy of your data before running it against production.
Before you start
- You need a Multibox license. A standalone Aidbox license does not work with Multibox. The license also caps how many boxes you can run.
- Note your source instance's FHIR version. You set the same version on the box you create in Multibox, since Multibox fixes the FHIR version per box at creation time and does not change it afterward. Unlike standalone Aidbox, different boxes in the same Multibox deployment can run different FHIR versions.
- Any custom resources, modules, subscriptions, and AidboxConfig/zen project settings are per-box in Multibox. They are not inherited from other boxes, so plan to redeclare them for the new box.
- Clients connect to a box through its own subdomain (
<box-id>.<cluster-domain>), not through the standalone instance's URL. Plan to update client configuration once the box is live.
Multibox gives each tenant a fully separate database, which is the right fit for strict data separation or tenants that need independent configuration and FHIR versions. If your tenants can share a database and configuration, organization-based access control is a lighter-weight alternative worth considering before you migrate.
Set up Multibox
Aidbox is a full-featured single instance of the Aidbox FHIR server. If you are interested in multi-tenant Aidbox, consider using the Multibox distribution.
All distributions can be used with standard PostgreSQL or managed PostgreSQL services.
A basic installation consists of two components: the backend and the database. Both are released as docker images and can be pulled from the HealthSamurai docker hub. For each type of Aidbox license, an individual backend image is available: Aidbox or Multibox.
Aidbox and Multibox work with standard PostgreSQL 13 and higher. See PostgreSQL Requirements for details.
If you don't have Multibox running yet, pick the path that matches your target environment.
Run locally
Follow the quickstart to run Multibox on your machine with Docker Compose:
Deploy to Kubernetes
Deploying Multibox to Kubernetes follows the same steps as deploying standalone Aidbox:
Apply these differences on top of that guide:
- Use the
healthsamurai/multiboximage instead ofhealthsamurai/aidboxone. - Box subdomains are created on demand, so a single static TLS certificate won't cover them. Request a wildcard certificate for
AIDBOX_CLUSTER_DOMAINinstead, which with cert-manager means using a DNS-01 challenge rather than HTTP-01. - Point your ingress at the wildcard domain so requests for
<box-id>.<cluster-domain>reach the Multibox service, and setAIDBOX_CLUSTER_DOMAINto that same domain. - If you run multiple Multibox replicas, every replica needs the same
AIDBOX_CLUSTER_SECRETand the same RSA keypair and secret. See Highly Available Aidbox, which applies equally to Multibox.
Create a box
Open the Multibox portal and create a new box, or call the multibox/create-box RPC directly against the portal:
POST /rpc
Content-Type: text/yaml
Accept: text/yaml
method: multibox/create-box
params:
id: mycompany
description: Migrated from standalone Aidbox
fhirVersion: fhir-4.0.1
idbecomes the box's subdomain and its database name. It must match^[a-z][a-z0-9]{4,}$: lowercase letters and digits only, at least 5 characters, no hyphens.fhirVersionmust match your source Aidbox's FHIR version, in thefhir-<version>format (for examplefhir-4.0.1,fhir-5.0.0). Callmultibox/fhir-versionsto see which versions your Multibox deployment supports.- You don't need to set a
participant: Multibox assigns the calling user as the box'sowner. Grant teammates access afterward withmultibox/add-collaborator, choosing anadmin,writer, orreaderrole.
Before creating the box, you can call multibox/check-id (no authentication required) to confirm the id is free and avoid a failed creation:
POST /rpc
Content-Type: text/yaml
Accept: text/yaml
method: multibox/check-id
params:
id: mycompany
Multibox provisions a dedicated PostgreSQL database and role for the box the first time it starts. Leave the box empty for now; you populate it in the next step.
Configuration
Multibox and standalone Aidbox share most configuration: JAVA options, web worker and DB pool sizing, SSL, and authentication key setup all work the same way. See the full reference:
A few settings apply differently once you're on Multibox:
- Performance settings (
BOX_WEB_THREAD,BOX_DB_POOL_MAXIMUM_POOL_SIZE,JAVA_OPTS) are set on the Multibox process as a whole, not per box. Size them for the combined load of every box it hosts, including the one you're migrating. - Authentication keys (
BOX_SECURITY_AUTH_KEYS_PRIVATE/PUBLIC/SECRET) are also shared across the Multibox process. If your source Aidbox instance issued JWTs signed with its own key, tokens minted before the migration won't validate against the new box; plan for clients to re-authenticate. BOX_DB_EXTENSION_SCHEMA, if you used a non-default PostgreSQL schema on the source instance, has no equivalent per box in Multibox: each box already gets its own database, so there's no need to separate extensions by schema within it.AIDBOX_CLUSTER_SECRETandAIDBOX_CLUSTER_DOMAINare new, Multibox-only settings with no standalone counterpart. KeepAIDBOX_CLUSTER_SECRETstable across restarts and replicas, since it signs the cross-box tokens the portal uses to move between boxes.
Move your data
Recommended: bulk export and import
Use Aidbox's Bulk API to move data at the FHIR level. This works regardless of where the source and target databases live, and keeps you on documented, supported operations.
- Export each resource type from the source Aidbox instance with
$export, and store the resulting NDJSON files somewhere the new box can reach over HTTP (a public bucket or a pre-signed URL). - Import the files into the new box with
$import. Address the request to the portal host and target the box with thex-boxheader (orAIDBOX_CLUSTER_BOX_HEADER, if you renamed it) instead of relying on subdomain DNS:
POST /fhir/$import
Accept: text/yaml
Content-Type: text/yaml
x-box: mycompany
id: migration
contentEncoding: gzip
inputs:
- resourceType: Patient
url: https://storage.example.com/export/Patient.ndjson.gz
- resourceType: Encounter
url: https://storage.example.com/export/Encounter.ndjson.gz
$import skips validation and does not write history by default. Set update: true if you need history preserved for resources that already exist, and consider running batch validation after the import completes.
- Repeat for every resource type in your source instance, then verify record counts against the source before cutting clients over.
Alternative: direct database restore
For large datasets, restoring a PostgreSQL dump straight into the box's database is faster than round-tripping through NDJSON. This bypasses Aidbox's own import path, so treat it as an advanced option and rehearse it on a staging box first.
- Take a dump of the source Aidbox database:
pg_dump -Fc -h <source-db-host> -U <source-db-user> -d <source-db-name> -f aidbox.dump
- Start the new box once so Multibox provisions its database, then stop it again.
- Restore the dump into the box's database. The database name matches the box id you chose. Use a role with enough privileges on the Multibox PostgreSQL cluster, and drop ownership information so the restore doesn't fight with the role Multibox already created:
pg_restore --no-owner --no-acl -h <multibox-db-host> -U <superuser> -d mycompany aidbox.dump
- Reassign ownership of the restored objects to the box's own role if your setup requires it, then start the box.
Verify and cut over
- Call
multibox/get-boxwith your box'sidto get its livebox-urland a short-livedaccess-token. Openaccess-urlfrom the response (orbox-urldirectly) to sign in and confirm resource counts, search, and any custom modules or subscriptions behave as they did on the standalone instance. - Portal collaborators (
owner/admin/writer/reader, managed throughmultibox/add-collaborator) control who can manage the box from the portal. They are separate from the FHIR API clients your applications use: your source instance'sBOX_ADMIN_PASSWORDandBOX_ROOT_CLIENT_SECRETdon't carry over, so create newClientandAccessPolicyresources inside the box itself for machine-to-machine access, the same way you would on a fresh Aidbox instance. - Point clients at the box's new base URL (
https://<box-id>.<cluster-domain>, or the portal host with anx-boxheader) using the new clients from the previous step. - Once you've confirmed the box is healthy, decommission the standalone Aidbox instance.
Talk to a Health Samurai Engineer
If you'd like to learn more about using Multibox or have any questions about this guide, connect with us on Zulip. We're happy to help.