Important
Rebranding Announcement
onFHIR has been officially rebranded as Repofyr. This change reflects our transition from a research-focused repository at SRDC to a commercially supported product line by Pontegra.
Note on Technical Migration: As of version 4.0.0 the server's Maven coordinates (io.repofyr:repofyr-*) and Scala packages (io.repofyr.*) carry the new identity. Runtime configuration keys in application.conf, Kafka topic names, and stored-data conventions are unchanged, and the values that carry the legacy onfhir naming (the onfhir.subscription Kafka topic, the onfhir database name and Kafka client id) intentionally keep it for operational compatibility. The reusable libraries consumed from srdc/onfhir-libs keep their io.onfhir coordinates and packages.
Upgrading from onFHIR 3.x? Follow the migration guide. Your configuration, database, and Kafka traffic carry over untouched; what changes is coordinates, package names, and the standalone jar name.
Repofyr is a FHIR-compliant, secure health data repository designed as a central data service for healthcare applications. It is implemented in Scala, built on the Akka framework, and utilizes MongoDB for high-performance persistence.
You can use Repofyr as a standalone server or extend it with custom FHIR Operations to build complex application layers. It uses FHIR Infrastructure Resource definitions (CapabilityStatement, StructureDefinition, SearchParameter, etc.) to tailor the server to your specific profile and search requirements.
This repository builds the Repofyr server family. Most deployments depend on a
single repofyr-server-* module and receive the rest transitively.
| Module | Purpose |
|---|---|
repofyr-core |
Core server runtime: FHIR API endpoints, request and response handling, MongoDB persistence, authorization, and audit. |
repofyr-operations |
The FHIR operations provided out of the box: $validate, $everything, $document, $expand, $meta, $lastn, and bulk $import. |
repofyr-event |
Server event contracts and JSON marshalling; the event bus SPI resource changes are published through. |
repofyr-kafka |
Publishes server events and FHIR Subscription notifications to Kafka topics. |
repofyr-server-r4 |
Runnable server for FHIR R4. |
repofyr-server-r5 |
Runnable server for FHIR R5. |
repofyr-server-stu3 |
Runnable server for FHIR STU3. |
repofyr-embedded-mongo |
Starts an embedded MongoDB for development and tests. Not carried by any runnable server. |
repofyr-dev-server |
Development launcher: embedded MongoDB plus the server for a chosen FHIR release. Not published. |
The reusable modules now live in the independent
srdc/onfhir-libs repository and retain
their io.onfhir coordinates and package names. Repofyr consumes their
independent version through the onfhir.libs.version Maven property. This
repository contains only the server family and remains GPL-3.0.
- Website: repofyr.io
- Open Source Core: Maintained by SRDC
Repofyr ships its defaults as repofyr-core/src/main/resources/repofyr-reference.conf, a fully commented file listing every key and its default. Read it as the reference; you do not need to copy it.
To tailor the server, write your own application.conf containing only the keys you change and point the server at it with -Dconfig.file. It layers over the shipped defaults, so anything you leave out keeps its default and picks up improvements when you upgrade:
mongodb {
host = "mongo.internal:27017"
db = clinical
}For logger configurations, check repofyr-core/src/main/resources/logback.xml
To configure the FHIR API to be provided, you need to supply the following:
- A file providing your Conformance statement (FHIR Capability Statement - See http://hl7.org/fhir/capabilitystatement.html) that describes the capabilities of the FHIR server you want to provide
- A folder including all your Profile definitions (FHIR StructureDefinition - See http://hl7.org/fhir/structuredefinition.html) including resource, data type and extension definitions that will be used in the FHIR server you want to provide
- A folder including all your Compartment definitions (FHIR CompartmentDefinition - See http://hl7.org/fhir/compartmentdefinition.html) for all compartments that you want to support for search
- A folder including all your Search parameter definitions (FHIR SearchParameter - See http://hl7.org/fhir/searchparameter.html) for all extra search parameters (apart from what is available from the base FHIR standard) that you define and support for your resources
- A folder including all your Value sets (FHIR ValueSet - See http://hl7.org/fhir/valueset.html) that you define and refer in your resource profiles
- A folder including all your Operation definitions (FHIR OperationDefinition - http://hl7.org/fhir/operationdefinition.html) that you define and refer from capability statement in operations part (For your OperationDefinitions write the full class path of your implementation of operation in OperationDefinition.name)
You can also provide the ZIP file for FHIR base definitions (validation package: validation-min.xml.zip) that you want to support specifically.
Repofyr supports all stable and build versions of HL7 FHIR. In this project, we provide modules for the last three main versions, configured automatically with standard definitions and dedicated configurators:
- R5 >> repofyr-server-r5
- R4 >> repofyr-server-r4
- STU3 >> repofyr-server-stu3
Repofyr requires a MongoDB database up and running. If you do not use the provided Docker containers, the MongoDB configuration parameters (host, port, dbname, etc.)
should be passed to Repofyr through either the application.conf file or runtime parameters. Parameter names can be seen in the provided application.conf file.
For development you do not need to install one. repofyr-dev-server starts an embedded
MongoDB and boots the server for a chosen FHIR release against it, defaulting to R5:
$ mvn -pl repofyr-dev-server -am exec:java -Dexec.args=r4
The runnable repofyr-server-* artifacts deliberately do not carry the embedded database, so mongodb.embedded = true
is rejected at startup with a message pointing here.
Run the command below to build Repofyr. This will compile your code, execute unit tests and create a single standalone jar with all the dependencies:
$ mvn package
Unit tests may take some time, so you can add -DskipTests=true command line parameter to the above command to skip the test execution, but it is not recommended:
$ mvn package -DskipTests=true
Executable standalone JARs (target/repofyr-server-standalone.jar) will be created under each repofyr-server-* module for
different FHIR versions. Executing the following command will run the Repofyr server for that version with nearly complete FHIR
capabilities.
$ java -jar target/repofyr-server-standalone.jar
You can override in-app configurations by supplying an external application.conf file or JAVA arguments
using the following commands. Both layer over the shipped defaults, so the file needs to carry only
the keys you change, and a -D argument outranks the file:
$ java -Dconfig.file={path-to-application.conf} -jar target/repofyr-server-standalone.jar
$ java -Dserver.port=9999 -Dserver.host=172.17.0.1 -jar target/repofyr-server-standalone.jar
You can develop your own FHIR-compliant backend application based on Repofyr. To do this, you can import the corresponding server module as a dependency in your project and write a Scala App (Boot) that initializes Repofyr with a custom configuration:
<dependency>
<groupId>io.repofyr</groupId>
<artifactId>repofyr-server-r4_2.13</artifactId>
<version>4.0.0</version>
</dependency>Onfhir.scala is the main entry-point of the project. The following is the default server Boot configuration for repofyr-server-r4. It initiates a FHIR R4 server with the given configurations.
object Boot extends App {
// Initialize Onfhir for R4
var onfhir = Onfhir.apply(new FhirR4Configurator())
// Start it
onfhir.start
}
You can extend Repofyr by implementing certain custom mechanisms:
- Custom Authorizer (implementing io.repofyr.authz.IAuthorizer): By default (if configured), Repofyr supports the authorization mechanism defined by the SMART on FHIR initiative, which is based on OAuth 2.0 Bearer Token authorization. If you need a custom authorization mechanism with a different set of scopes (permissions), you can implement an authorizer module and register it with Repofyr.
- Custom Token Resolver (implementing io.repofyr.authz.ITokenResolver): Repofyr supports two default token resolution methods: signed JWT tokens and OAuth 2.0 token introspection. You can use them via configuration or implement a new module.
- Custom Audit Handler (implementing io.repofyr.authz.ICustomAuditHandler): By default, you can configure Repofyr to store FHIR AuditEvent records in its own local repository, or in a remote FHIR server running as a separate audit repository. If you want to create audit events/logs in a different format and send them to a custom audit repository (Elasticsearch + Kibana, etc.), you can extend this interface with your module and register it.
- Further FHIR Operations: You can implement custom FHIR operations by extending io.repofyr.api.service.FHIROperationHandlerService and
preparing an OperationDefinition file describing the input and output parameters of the operation. Group your handlers behind an
implementation of io.repofyr.operation.IFhirOperationLibrary, which declares the operation URLs it supports via
listSupportedOperations()and returns the handler for a given URL viagetOperationHandler(url). Pass your libraries toOnfhir.applyasfhirOperationLibraries. - External Akka Routes: You can also implement non-FHIR REST services for your server and register them with Repofyr.
object Boot extends App {
// Initialize Onfhir for R4
var onfhir =
Onfhir.apply(
fhirConfigurator = new FhirR4Configurator(),
fhirOperationLibraries = Seq(new MyOperationLibrary()),
customAuthorizer = Some(new MyAuthorizer()),
customAuditHandler = Some(new MyAuditHandler()),
externalRoutes = myNonFhirRoutes
)
// Start it
onfhir.start
}
We also provide a simple Docker setup for Repofyr under the docker folder. It includes a docker-compose file with
two containers: one for MongoDB and one for the Repofyr application, plus a sample Repofyr setup in the sample-setup
directory. The sample setup's CapabilityStatement declares FHIR R4, so it runs against the srdc/repofyr:r4 image.
First build the standalone jar, then build the image from the repository root - the Dockerfile copies the jar out of
the server module's target directory:
$ mvn package -pl repofyr-server-r4 -am
$ docker build -f docker/Dockerfile-addJar --build-arg FHIR_VERSION=r4 -t srdc/repofyr:r4 .
Then start the sample setup. docker-compose.yml mounts sample-setup/conf into the container as the server's
configuration directory:
$ cd docker
$ docker compose -f docker-compose.yml -p onfhir up -d
To run another release, build that image and set REPOFYR_TAG, replacing sample-setup/conf with conformance
resources for the matching FHIR version - the CapabilityStatement's fhirVersion has to agree with the image:
$ REPOFYR_TAG=r5 docker compose -f docker-compose.yml -p onfhir up -d
See docker/build.sh for the full set of build commands.
The compose file exists to give you a MongoDB alongside the server. If you already have one, you do not need compose at all - a single container is enough, and no configuration file is required, because the server falls back to its shipped defaults for everything you do not set:
$ docker run -d -p 8080:8080 -e DB_HOST=mongo01.example.org:27017 srdc/repofyr:r4
DB_HOST is the one value nobody can guess for you. The default is localhost:27017, and inside a container
localhost is the container itself - never your host, never another container:
| Where MongoDB runs | DB_HOST |
|---|---|
| Another service in the same compose file | the service name, e.g. mongo:27017 |
| On the Docker host | host.docker.internal:27017 (Docker Desktop; on plain Linux use the gateway address) |
| A separate server or managed service | its real hostname, e.g. mongo01.example.org:27017 |
If the database requires authentication, supply the credentials through the environment. They are read directly from it, so a password never has to be written into a configuration file, and never appears on the JVM command line where the container's process list would expose it:
$ docker run -d -p 8080:8080 \
-e DB_HOST=mongo01.example.org:27017 \
-e DB_USERNAME=fhiruser \
-e DB_PASSWORD="$MONGO_PASSWORD" \
srdc/repofyr:r4
DB_AUTHDB is only needed when the credential lives somewhere other than admin. A user name and a password must
both be present before any credential is sent.
To tailor the FHIR API rather than the database, mount a configuration directory as the compose file does - a
CapabilityStatement, profiles, and an application.conf naming them. That file needs only the keys it changes; see
docker/sample-setup/conf for a worked example.
Mount a Java keystore and name it with SSL_KEYSTORE. Providing a keystore is what enables TLS - there is no separate
switch - and SSL_KEYSTORE_PASSWORD is read from the environment so the password stays off the command line:
$ docker run -d -p 8080:8080 \
-e DB_HOST=mongo01.example.org:27017 \
-e SSL_KEYSTORE=/usr/local/onfhir/ssl/keystore.jks \
-e SSL_KEYSTORE_PASSWORD="$KEYSTORE_PASSWORD" \
-v /path/to/ssl:/usr/local/onfhir/ssl:ro \
srdc/repofyr:r4
Both variables work outside Docker too, since the server reads them directly rather than through the entrypoint.
Then you will be able to send requests to this running instance from your Docker host. The following command returns the CapabilityStatement:
$ curl http://127.0.0.1:8080/fhir/metadata
Repofyr uses specs2 for unit testing. To execute tests for each build, run the following command:
$ mvn test
The repofyr-server-r4 suite boots a full server against an embedded MongoDB instance, so it is the main regression
net for the reactor.
- Migration guide: onFHIR 3.x to Repofyr 4.0.0
- Changelog
- Known limitations
- Contributing and security policy
- Release runbook (maintainers)
Repofyr is licensed under the GNU General Public License v3.0. See LICENSE for the full text.
The reusable onFHIR libraries that Repofyr depends on are licensed separately under Apache License 2.0 and are
released from srdc/onfhir-libs. Depending on those libraries does not place
your project under the GPL; embedding Repofyr itself does.