This server provides a set of server-side services that are useful for the FHIR Community. Each is a module, turned on and configured in config.json. The modules are at different stages, and stability varies between them: a module in production can still be changing in places (and the terminology server's behaviour follows decisions about its content - ICD-11, SNOMED CT - as they are made).
- Terminology server (
tx) - the reference terminology server for the FHIR community and the terminology ecosystem (as running on tx.fhir.org) - TX Registry (
registry) - Terminology System Registry as described by the terminology ecosystem specification (as running at http://tx.fhir.org/tx-reg, moving to https://ecosystem.hl7.org). Its API is described by an OpenAPI 3.1 spec at/tx-reg/openapi.json(and.yaml), with a browsable reference at/tx-reg/openapi - Package server (
packages) - NPM-style FHIR package registry with search, versioning, and downloads, consistent with the FHIR NPM Specification (as running at http://packages2.fhir.org/packages). Its API is described by an OpenAPI 3.1 spec at/packages/openapi.json(and.yaml), with a browsable reference at/packages/openapi - Publisher (
publisher) - FHIR publishing services (as running at healthintersections.com.au) - XIG server (
xig) - Comprehensive FHIR IG analytics with resource breakdowns by version, authority, and realm (as running at http://packages2.fhir.org/packages) - SHL Server (
shl) - SHL/VHL support services (running on healthintersections.com.au, supporting the ICVP demo and the Patient Document Generator)
- Extension tracker (
ext-tracker) - tracks extensions, profiles and extension usage across FHIR Implementation Guides, from data the IG Publisher submits - Folder (
folder) - serves static files from one or more directories, with optional authenticated upload - Testing (
testing) - TestReport repository: receives FHIR TestReports from TxTester and other test tools, with a FHIR API and web pages (as running at https://npm.fhir.org/testing). Its API is described by an OpenAPI 3.1 spec at/testing/openapi.json(and.yaml), with a browsable reference at/testing/openapi - VCL (
vcl) - Parse VCL expressions into FHIR ValueSet resources (as running at http://fhir.org/vcl)
- IPS (
ips) - collections of International Patient Summary documents, each with its own FHIR endpoint, processing (validation, terminology checks, translation, narrative, clinical profiles) and web pages
These are not being actively developed at present.
- NpmProjector (
npmprojector) - watches a local npm package directory and serves its FHIR resources with FHIRPath-based search - Token (
token) - API key services
- R4/R6 interconverter
- Full RESTful server implementation
- How to handle expansions and validations of some kinds of invalid value sets
- more efficient CodeSystem implementations
- more work on internationalization of IPS documents and the IPS repository generally
- Maintainers: Grahame Grieve, Italo Macêdo, Josh Mandel, Jose Costa Teixeira
- Issues / Discussion: Use github issues
- License: BSD-3-Clause (see LICENSE)
- Contribution Policy: Make PRs. PRs have to pass all the tests
- Security Information: See security.md
Note: In production, this server always runs behind an nginx reverse proxy, so there's no in-build support for SSL, rate limiting etc. See nginx.md for how to configure it.
There are 5 executable programs:
- the server (
node server) - the cluster server (
node cluster) - for high performance uses (see cluster.md) - the terminology importer (
node --max-old-space-size=8192 tx/importers/tx-import XXX) - see Doco - the test cases (
npm test) - the test cases generater (
node tx/tests/testcases-generator.js)
Unless you're developing, you only need the first three
FHIRsmith is open source - see below, and you're welcome to use it for any kind of use. Note, though, that if you support FHIRsmith commercially as part of a managed service or product, and you seek support for your implementation from the project team, you are required to be a Commercial Partner of HL7 - consult The FHIR Product Director.
- Install FHIRSmith (using docker, or an NPM release, or just get the code by git)
- Figure out the data directory
- Provide a configuration to tell the server what to run (see CONFIGURATION.md, or use a prebuilt configuration)
- Run the server
For further details of these steps, read on
The server separates code from runtime data. All databases, caches, logs, and downloaded files are stored in a single data directory. The location is determined by:
- The
FHIRSMITH_DATA_DIRenvironment variable (if set) - Otherwise, defaults to
./datarelative to the working directory (development set up)
The data directory contains (depending on which modules are in use):
config.json— server and module configurationlogs/— server and nginx log filesterminology-cache/— downloaded terminology packages and FHIR packagespackages/— package server databasexig/— XIG databaseshl/— SHL databases and certificatesregistry/— registry crawler datapublisher/— publisher database and build workspacetoken/— token database
During development with a cloned repository, the data directory defaults to [root]/data
(the test cases require this setup). When deployed via Docker or npm, the data directory
is provided by the host — see Deployment below.
- Node.js 24+
- NPM or Yarn
- Java 17+ (for FHIR validator, also for the test cases)
These instructions are for Development. For deployment, see below.
# Clone the repository
git clone https://github.com/HealthIntersections/FHIRsmith
cd FHIRsmith
# Install dependencies
npm install
# Create required directories
mkdir -p data data/logs
# Copy example configuration
cp config-template.json data/config.json
# Edit configuration: every module is off until you set "enabled": true (comments are allowed)
nano data/config.jsonThe server reads config.json from the data directory. See CONFIGURATION.md
for the server settings (port, body size, logging, email and the daily report), the environment
variables, and where each module's own settings are documented.
To check the configuration without starting the server: npm run check (node server.js --check).
See Checking the configuration.
# Development mode
npm run dev
# Production mode
npm startThe server will be available at http://localhost:{port} using the port specified in the config.
In the production servers listed above, the server should always sit behind an NGINX server which manages
SSL, security, rate limiting etc. See nginx.md for configuration advice, including
running several servers behind one front door. To use more than one CPU core for terminology on
one machine, see cluster.md: a master and several tx workers, behind nginx.
npm testThere are three deployment options: npm global install, Docker, or clone-and-run. All three
use the FHIRSMITH_DATA_DIR environment variable to locate the data directory.
# Install globally
npm install -g fhirsmith
# Create a data directory
mkdir -p /var/lib/fhirsmith
cp node_modules/fhirsmith/config-template.json /var/lib/fhirsmith/config.json
# Edit config.json as needed
# Set the data directory and run
export FHIRSMITH_DATA_DIR=/var/lib/fhirsmith
fhirsmith --check # check the configuration
fhirsmithOr run it inline:
FHIRSMITH_DATA_DIR=/var/lib/fhirsmith fhirsmithFor cluster mode (a master and tx-workers - see cluster.md), run fhirsmith-cluster
instead of fhirsmith.
Some of FHIRsmith's dependencies (the SQLite drivers) are native modules, built for the
version of Node.js that installed them. After upgrading Node.js, rebuild them - npm rebuild
in the FHIRsmith folder, or npm rebuild -g fhirsmith for a global install - or reinstall
FHIRsmith. Otherwise the server stops at startup with "compiled against a different Node.js
version". (With nvm, each Node.js version has its own global packages, so install FHIRsmith
again under the new version.) Docker images aren't affected.
The server is available as a Docker image. Mount a host directory as the data directory:
# Pull the latest image
docker pull ghcr.io/healthintersections/fhirsmith:latest
# Create and populate data directory on host
mkdir -p /path/to/data
cp config-template.json /path/to/data/config.json
# Edit config.json as needed
# Check the configuration (exits 0 if it's good, 1 if not)
docker run --rm -e FHIRSMITH_DATA_DIR=/app/data -v /path/to/data:/app/data \
ghcr.io/healthintersections/fhirsmith:latest node server.js --check
# Run with data directory mounted
docker run -d --name fhirsmith \
-p 3000:3000 \
-e FHIRSMITH_DATA_DIR=/app/data \
-v /path/to/data:/app/data \
ghcr.io/healthintersections/fhirsmith:latestAvailable tags:
latest: Latest stable releasevX.Y.Z: Specific version (e.g.,v1.0.0)cibuild: Latest build from the main branch
You can install as a windows service using windows-install.js. You might need to hack that.
This project follows Semantic Versioning and uses a CHANGELOG.md file to track changes.
Each GitHub Release includes:
- Release notes extracted from CHANGELOG.md
- Source code archives (zip and tar.gz)
- Docker images pushed to GitHub Container Registry:
ghcr.io/healthintersections/fhirsmith:latestghcr.io/healthintersections/fhirsmith:vX.Y.Zghcr.io/healthintersections/fhirsmith:X.Y.Z
- npm package published to npmjs.org as
fhirsmith
Release images carry OCI labels, so an image says which release it is without having to trust the tag it was pulled under:
docker inspect --format '{{json .Config.Labels}}' ghcr.io/healthintersections/fhirsmith:latestorg.opencontainers.image.version is the release, .revision the commit it was
built from, and .source is what links the package to this repository on GHCR.
Server administrators should follow releases: a server is only as safe as the release it runs.
- Email: on the GitHub repository, choose Watch → Custom → Releases. Each release is emailed with its notes (needs a GitHub account)
- Atom feed:
https://github.com/HealthIntersections/FHIRsmith/releases.atom- each entry carries the release notes, for a feed reader or a Slack/Teams feed integration - The server itself: once a day the server looks up the latest release on npm, and the
dashboard says whether a newer one is available (this is part of the npm audit check, so
npmAudit.enabled = falseturns it off too)
Every push to main also publishes :cibuild and :cibuild-<sha> to the same
package. These are not releases - they are whatever was last merged. The
Docker Build workflow prunes all but the ten most recent afterwards, so they do
not bury the current release on the package page. To prune by hand (or to run
the one-off backfill of images published before that job existed), run the
GHCR Cleanup workflow from the Actions tab with dry_run on first, read the
log, then run it again with dry_run off.
GitHub Actions will automatically:
- Run tests
- Create a GitHub Release with notes from CHANGELOG.md
- Build and publish Docker images with appropriate tags
Prerequisites:
- All tests passing on main branch
- CHANGELOG.md updated with changes
Steps:
- Update
CHANGELOG.mdwith your changes under a new version section:
## [vX.Y.Z] - YYYY-MM-DD
### Added
- New feature description
### Changed
- Change description
### Fixed
- Bug fix description
### Tx Conformance Statement
{copy content from text-cases-summary.txt}- Update
package.json&package-lock.jsonto the release version:
npm version --no-git-tag-version X.Y.Z
npm install --package-lock-onlyThis matters more than it looks. The server reports its version from
package.json (server.js, tx/tx.js) - not from the APP_VERSION build
arg - so a package.json left on the previous number ships a Docker image that
calls itself by the wrong release for good. The Verify Version job fails
the release if package.json or package-lock.json disagrees with the tag.
- Commit your changes:
git commit -m "Prepare release vX.Y.Z"
git push origin main:XXXXXXor do it via a PR
- Run the tx tests (
npx jest tests/tx/test-cases.test.js), then tag and push the release:
./release.sh X.Y.Zrelease.sh checks that the release is ready - on main and pushed, the three versions in
package.json and package-lock.json match, CHANGELOG.md has a dated section with the
conformance statement, and test-cases-report.json passed, is from this version and is
newer than the last code change - then submits the report to
npm.fhir.org (set FHIRSMITH_TESTING_TOKEN if it needs a
token), and only if that is accepted, tags vX.Y.Z and pushes the tag.
The tx test run writes test-cases-report.json next to test-cases-summary.txt (both
are ignored by git). The report records the version in package.json when the tests
ran, so run the tx tests after step 2. To submit a report on its own (to a different
/testing server, say): node utilities/submit-test-report.js [-server {url}] [-token {token}].
-
Monitor the release:
- Check GitHub Actions for the Release workflow
- Verify the GitHub Release was created
- Confirm Docker images are available at GHCR
-
Update
package.jsonto have the next release version -SNAPSHOT
If a release fails:
- Delete the tag:
git tag -d vX.Y.Z && git push origin :refs/tags/vX.Y.Z - Fix the issue
- Re-tag and push
BSD-3-Clause - see also opensource.org
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
- Issues: GitHub Issues
- Documentation: Wiki
- FHIR Community: chat.fhir.org
