Init Bundle
Available since the 2411 release.
Init Bundle creates configuration resources when Aidbox starts.
It is equivalent to executing Bundle in Aidbox using POST /fhir, with some differences:
- It is executed before the internal HTTP server starts, and before the health check response.
- Unsuccessful execution of the init bundle of type transaction prevents Aidbox from starting.
- Unsuccessful execution of the init bundle of type batch triggers warnings in the log; Aidbox continues the startup process.
- Aidbox startup will be interrupted if the specified file is unavailable or is not a valid bundle resource of transaction or batch type.
- Only JSON format is supported.
Why Init Bundle instead of a seed service
A common alternative is a self-written seed service: a sidecar, an init container, or a script that waits for Aidbox to boot and then POSTs the configuration resources to /fhir. Init Bundle runs inside Aidbox before the HTTP server opens, which removes the problems that approach carries.
- No race window. A seed service
POSTs after Aidbox reports healthy, so the orchestrator can route traffic before the configuration lands. Init Bundle finishes before/healthresponds, so a green health check guarantees it applied. - Fail-fast on a bad bundle. A failed transaction init bundle stops Aidbox from starting, so the orchestrator holds back traffic or rolls the deployment back. A failed seed service leaves Aidbox serving with missing configuration.
- No bootstrap credentials. A seed service needs a
ClientandAccessPolicybefore it can write the ones you want to seed. Init Bundle runs before authentication serves, so it needs no external credentials. - Nothing extra to operate. Init Bundle is one environment variable and one file, with no additional container or process to monitor and retry.
Usage
Specify BOX_INIT_BUNDLE env. The value must be a URL.
BOX_INIT_BUNDLE=<URL>
Examples of URLs:
file:///tmp/bundle.jsonhttps://storage.googleapis.com/<BUCKET_NAME>/<OBJECT_NAME>
Example
If a Bundle file is created at /tmp/bundle.json:
{
"type": "batch",
"resourceType": "Bundle",
"entry": [
{
"request": {
"method": "POST",
"url": "/Observation",
"ifNoneExist": "_id=o1"
},
"resource": {
"id": "o1",
"code": {
"text": "text"
},
"status": "final",
"effectiveDateTime": "2000-01-01"
}
}
]
}
Aidbox will apply it if the BOX_INIT_BUNDLE is set to:
BOX_INIT_BUNDLE=file:///tmp/bundle.json
Delivering the bundle to the pod
BOX_INIT_BUNDLE points at a file:// path inside the container or an https:// URL, so deploying an init bundle comes down to getting that file to the container. Common options:
| Method | How | Pros | Cons |
|---|---|---|---|
| Bake into a custom image | FROM healthsamurai/aidboxone, COPY bundle.json into the image, set BOX_INIT_BUNDLE=file:///… | Immutable, versioned artifact; atomic deploy and rollback by image tag; no boot-time external dependency | Rebuild and push the image on every bundle change |
| Mounted volume / ConfigMap | Mount the file into the stock image (a Kubernetes ConfigMap or a volume); BOX_INIT_BUNDLE=file://<mount> | Stock image; change the bundle without rebuilding (GitOps-friendly) | A ConfigMap is text-only and limited to ~1 MiB, so large bundles hit the limit |
| Init container / sidecar | An init container builds or downloads the bundle into a shared volume that the Aidbox container reads via file:// | Stock image; can fetch from private storage using the pod's identity | An extra container and its wiring to operate |
| Remote URL (object storage) | Upload the bundle to object storage (GCS, S3, Azure Blob); BOX_INIT_BUNDLE=https://… | Stock image; fully decoupled; per-environment is a different URL; versioned in the bucket | Startup depends on storage availability and access |
Keep secrets out of the bundle. A bundle baked into an image layer or served from a public URL exposes any secret it contains. Keep secrets out of the static bundle and inject them at container start. See How to inject env variables into init bundle.
Fetching from private storage. BOX_INIT_BUNDLE fetches an https:// URL with a plain HTTP GET and does not authenticate with cloud IAM. For a private bucket, either put a pre-signed URL (S3 pre-signed URL, Azure SAS) in BOX_INIT_BUNDLE, or let an init container or a CSI volume driver (Azure Blob CSI or GCS FUSE with workload identity) fetch the object using the pod's identity and expose it to Aidbox as a file:// path.
Bundling a local FHIR package
If the init bundle installs a local FHIR package with $fhir-package-install, it references the package as a .tgz tarball on a file:// path. That tarball is a second file, so it has to reach the container the same way the bundle does: bake it into the image, place it on the shared volume, or serve it from an https:// URL. A ConfigMap is text-only and cannot hold it.
Add the install as a bundle entry that POSTs the tarball path to $fhir-package-install:
{
"request": {
"method": "POST",
"url": "$fhir-package-install"
},
"resource": {
"resourceType": "Parameters",
"parameter": [
{
"name": "package",
"valueString": "file:///tmp/ig/custom-ig.tgz"
}
]
}
}
Put this entry before the resources that depend on the package (profiles, custom types), so the package is loaded by the time they apply. For a full working setup, see the init-bundle-from-directories example.
Hints
-
First, check that Aidbox handles the Bundle as it should using
POST /fhir. Try to post it several times to make sure it is idempotent. Then add it toBOX_INIT_BUNDLE. -
Note that the Aidbox format is not supported.
-
Aidbox handles an
idin the body of the POST request. That's why posting the resource with an id twice will cause anduplicate keyerror. Use conditional create or update for that. -
Most resources support
PUTfor idempotent updates inside an init bundle. Exception:AidboxTopicDestinationis immutable and rejectsPUT/PATCH(also inside bundles). Use a conditional create (POSTwithifNoneExist=_id=<id>) so the entry is a no-op when the resource already exists and creates it on the first run:{ "request": { "method": "POST", "url": "AidboxTopicDestination", "ifNoneExist": "_id=<id>" }, "resource": { "resourceType": "AidboxTopicDestination", "id": "<id>", "...": "..." } }To change configuration of an already-created destination, delete it manually and let the next bundle run recreate it. See Updating a TopicDestination.