Skip to content

Deploying an Instance ​

A Medipal instance is a self-contained deployment serving one organisation. Partners who host Medipal for their customers deploy and operate instances on their own Kubernetes infrastructure using the charts, images and tooling provided by Medipal.

Requirements ​

RequirementDetail
Kubernetes clusterA current Kubernetes release with a Gateway API or Ingress controller and persistent storage.
Container registry accessCredentials for Medipal's private registry, which hosts the images and Helm charts. Provided at onboarding.
DNS and TLSTwo hostnames per instance (web application and API), covered by a wildcard certificate or one certificate per host.
Outbound emailAn SMTP relay for transactional email (invitations, password resets, notifications).
Operator toolingkubectl, helm and the Medipal provisioning CLI installed on the operator's workstation, with a kubeconfig for the cluster.
Optional: single sign-onAn Azure AD / Microsoft Entra application registration if the organisation signs in with SSO.
Optional: EHRNetwork access from the cluster to the organisation's FHIR server. See EHR Connectors.

What gets deployed ​

Each instance lives in its own namespace and consists of:

ComponentRole
API serverThe Medipal backend. On start-up it waits for the database, applies schema migrations, seeds reference data and registers plugins before serving traffic.
Web applicationThe clinician and administrator interface, served behind the instance's web hostname.
DatabaseA PostgreSQL database dedicated to the instance, deployed in the namespace or provided externally.
RoutesGateway API routes (or Ingress rules) mapping the two hostnames to the web application and the API.

Cluster-wide, one shared namespace holds settings common to every instance (registry pull credentials, SMTP settings) and, optionally, a synthetic FHIR test server used by evaluation instances.

The provisioning CLI ​

The provisioning CLI wraps kubectl and helm so that day-to-day operation does not require hand-written manifests. It creates and manages instances by a short name; the name becomes part of both hostnames.

CommandPurpose
bootstrapOne-time cluster setup: shared namespace, shared settings, registry credentials.
provisionCreate a new instance from scratch: namespace, secrets, database, charts, routes, first administrator.
statusReadiness of the instance's pods and routes, plus a live health probe of the API.
listAll instances managed on the cluster.
secretRe-display the first-login information for an instance.
upgradeRoll the API server and/or the web application to new versions, keeping configuration.
setChange one or more runtime settings; the affected component is restarted automatically.
restartRestart the instance's components without changing anything.
destroyRemove the instance, its namespace and, optionally, its registration with the tracker.

Every command accepts a kubeconfig option and can print machine-readable output for automation.

Configuration ​

Configuration is provided per instance and falls into these categories. The CLI generates what can be generated and asks for the rest.

CategoryExamplesSource
Cryptographic materialToken signing key, encryption key for the Vault, service API keyGenerated at provisioning
DatabaseHost, name, credentialsGenerated or supplied
AddressesWeb and API hostnames, cluster domainDerived from the instance name
EmailSMTP relay, sender name and addressShared cluster settings
Single sign-onAzure AD tenant and client identifiersSupplied per instance
Feature flagsAnalytics, EHR, workflows, anonymous questionnaires, engine builder, AI toolsOff by default; enabled per instance
AI assistantProvider and model selection, provider credentialsSupplied if AI tools are on
First administratorEmail and initial passwordGenerated at provisioning

Sensitive values are stored as Kubernetes secrets; non-sensitive values as configuration maps. The set command routes each key to the right place.

Configuration as code ​

Beyond runtime settings, an instance's content configuration (folders, roles, plugin instances, workflows, consent documents) can be described in a declarative file and applied with the API server's configuration commands: validate checks the file, plan shows what would change, apply makes the changes, and sync exports the current state. This is how partners reproduce a standard set-up across many instances and keep it under version control.

Provisioning walkthrough ​

  1. Run bootstrap once per cluster with the shared settings.
  2. Run provision <name> with the environment type and, if used, the SSO identifiers. The command creates everything and prints the first-login details once.
  3. Open the web hostname and sign in as the first administrator. Change the password.
  4. Create folders, roles and users, or apply a configuration-as-code file.
  5. Enable the feature flags the organisation needs with set.
  6. If applicable, register the organisation's EHR (see EHR Connectors).

Upgrades ​

Releases of the API server and the web application are versioned independently. To upgrade, run upgrade <name> with the new version tags. Schema migrations run automatically before the new API server accepts traffic, and the previous configuration is preserved. Test upgrades on a staging instance first; instances of different versions can coexist on one cluster.

Backups and restore ​

The partner is responsible for backing up each instance's database and for the Vault encryption key, which is required to read secrets in a restored database. Restoring an instance means restoring the database and re-applying the same secrets; the charts and images are stateless.

Health ​

The API server exposes a health endpoint used by the cluster's readiness checks and by status. The web application is healthy when it serves its start page. Both hostnames should be monitored externally.

Troubleshooting ​

SymptomLikely causeWhat to do
Pods stay in image pull errorsRegistry credentials missing in the namespaceRe-run bootstrap or check that the pull secret exists in the instance namespace.
API pod does not become readyMigration or seeding step failedRead the logs of the API pod's start-up steps; fix the database connection or credentials and restart.
Web hostname returns 404Route not yet accepted by the gatewayWait briefly and check the route's status in the namespace.
First login failsSeeding has not completed or the password was mistypedRun secret <name> to re-display the credentials once the API pod is ready.
Email is not sentSMTP settings incorrectUpdate the SMTP keys with set; the API server restarts automatically.
SSO login failsRedirect URIs not registered on the identity providerRegister the web hostname's callback and logout addresses on the application registration.