Karnak is a DICOM gateway designed for data de-identification and DICOM attribute normalization. It manages continuous DICOM data streams, functioning as a DICOM listener for input and supporting both DICOM and DICOMWeb formats for output.
In practice, Karnak receives DICOM studies from one or more sources (modalities, PACS, workstations…), applies a configurable de-identification / tag-morphing profile, and forwards the result to one or more destinations over DICOM or DICOMWeb (STOW-RS). Everything is configured and monitored from a web interface.
For detailed usage instructions, refer to the Karnak User Guide.
- Fan out from a single source to multiple destinations.
- A destination can be DICOM (C-STORE) or DICOMWeb (STOW-RS).
- Authenticate sources by AE Title and/or hostname to ensure their authenticity.
- Filter by SOP Class UID to forward only specific SOP Classes.
- Use expressions on DICOM tag values to filter which images are forwarded.
- On-the-fly transfer-syntax adaptation (transcoding) per destination.
- Each destination can be configured with a specific de-identification profile.
- Profiles are ordered pipelines of items: basic profile, tag actions (keep, remove, replace, hash), date shifting, UID re-mapping, add/replace tags, and API-based value replacement.
- Pixel-data cleaning: mask burned-in annotations and deface (remove facial features from head studies).
- Deterministic pseudonymization (HMAC-based), so the same patient always maps to the same pseudonym.
- Build your own de-identification profile, edit it directly as YAML in the UI, and import/export profiles to share them with other users.
- Supply your own patient-to-pseudonym mapping instead of the generated one, entered in the UI or imported from a CSV file.
- Mappings are held in a cache (Redis, or an in-memory cache in the portable build).
- Group destinations under a project that carries the secret used for pseudonymization.
- Secrets are stored encrypted at the database layer.
- Track the transfer status of forwarded studies from the web interface, with filtering.
- Built-in tools to check connectivity and query remote nodes: C-ECHO (with a persisted check history) and Modality Worklist (MWL) queries.
You don't need to build Karnak from source to use it. Pick the option that fits your needs:
| I want to… | Use | Details |
|---|---|---|
| Run Karnak in production | Docker | karnak-docker — Postgres + Redis, the recommended setup |
| Try Karnak quickly on a single machine | Portable package | Self-contained, embedded database, no external services — see Run portable package |
| Contribute to / develop Karnak | Build from source | See Build Karnak and Debug Karnak |
Once Karnak is running, with the default configuration:
- Web interface: http://localhost:8081
- Default credentials: user
admin, passwordkarnak(change these in production viaKARNAK_ADMIN/KARNAK_PASSWORD) - DICOM listener: AE Title
KARNAK-GATEWAY, port11119(the portable package uses11112) — point your modality or PACS here to send studies to Karnak
The web port (KARNAK_WEB_PORT), the listener AE Title (DICOM_LISTENER_AET) and port (DICOM_LISTENER_PORT), as well as the sources and destinations, are all configurable; see the Karnak User Guide.
Prerequisites:
- JDK 25
- Maven 3.3+
Execute the maven command mvn clean install -P production in the root directory of the project. The "production" profile builds the Vaadin frontend via pnpm and produces a deployable jar.
Execute the maven command mvn clean install -Pportable in the root directory of the project.
Note: on Windows the bash.exe must be specified: mvn clean install -Pportable -Dbash.executable=${env.LOCALAPPDATA}\Programs\Git\bin\bash.exe
To configure and run Karnak with docker, see karnak-docker. This is the recommended setup for production.
After building the portable package (see Build for portable package), go into the generated folder build-portable/target/karnak-<os>-jdk<version>-<karnak-version> (for example karnak-linux-x86-64-jdk25-...) and launch the executable run.sh (Linux or macOS) or run.bat (Windows).
Settings such as the web port and the DICOM listener can be adjusted in the run.cfg file located next to the executable.
Then open http://localhost:8081 and log in (see Accessing Karnak).
Note: this portable package runs an embedded database (H2) in file mode, and the Redis server is replaced by an in-memory cache. For intensive use, it's recommended to run Karnak with docker and a Postgres database.
- Launch the components needed by Karnak (see below "Run locally the database and the cache with docker")
- Run
mvn clean installonce before the first debug session. Besides building the project, this copies the native OpenCV library intotarget/classes/lib/<os>-<cpu>/— it is loaded at startup by the DICOM gateway, and the application fails with "Cannot register DICOM native librairies" if it is missing. - Enable Spring and Spring Boot for the project
- Create a Spring Boot launcher from the main of
KarnakApplication.java- Working Directory must be the project root directory (the folder containing
pom.xml) - In VM Options:
- Add
-Djava.library.path="/tmp/dicom-opencv". Note: the tmp folder must be adapted according to your system anddicom-opencvis mandatory as the last folder. - Optional: Add
-Dvaadin.productionMode=trueto enable production mode
- Add
- In Environment variables, add the following values. The following values work with our default
configuration defined with docker used for the development (see: "Run locally the database and the cache with docker") :
- Mandatory:
ENVIRONMENT=DEVDB_ENCRYPTION_KEY=fsGuSZRIEr$HwlTDPglZg*Vl7WtJCZz6RLvqoMKWSA!
- Optional:
DB_PASSWORD=karnakDB_PORT=5433DB_USER=karnakDB_NAME=karnakDB_HOST=localhostKARNAK_ADMIN=adminKARNAK_PASSWORD=karnakIDP=undefinedOIDC_CLIENT_ID=undefinedOIDC_CLIENT_SECRET=undefinedOIDC_ISSUER_URI=undefined
- Mandatory:
- Working Directory must be the project root directory (the folder containing
The portable build has no external dependencies: it runs an embedded H2 database (file mode) and an
in-memory cache instead of Postgres + Redis. To debug it in IntelliJ you don't need the docker
components — you only need to activate the portable Spring profile and, optionally, configure a
local DICOM node so received studies are written to disk.
Reuse the Spring Boot launcher from Debug in IntelliJ with the same VM options
(-Djava.library.path=...), then in Environment variables:
- Activate the portable profile (it swaps in
application-portable.yml). Either set it in the launcher's Active profiles field (portable), or add the environment variable:SPRING_PROFILES_ACTIVE=portable
- Mandatory (same as above):
ENVIRONMENT=DEV
- Optional — persist incoming studies to a local folder. When
LOCAL_NODE_PORTandLOCAL_NODE_STORAGE_PATHare both set, Karnak starts an additional DICOM listener that stores received objects on disk:LOCAL_NODE_STORAGE_PATH=./dicomLOCAL_NODE_AE_TITLE=KARNAK-LOCALLOCAL_NODE_PORT=11115LOCAL_NODE_FILEPATH_PATTERN={00100010}/{00080060}/{0020000E}/{00080018}.dcm
The H2 database file is created under ./data in the working directory, so no docker services are
required. Then open http://localhost:8081 and log in (see Accessing Karnak).
- Go in the
dockerfolder located in the root project folder. - To configure third-party components used by karnak, please refer to these links:
- Adapt the values if necessary (copy
.env.exampleinto.envand modify it) - Execute command:
- start:
docker compose up -d - show the logs:
docker compose logs -f - stop:
docker compose down
- start:
Two formatting plugins are bound to the Maven build and run automatically during mvn install:
- spring-javaformat — applies the Spring Java code style (indentation, spacing, line wrapping). It does not modify imports.
- spotless — removes unused imports, sorts them
(static imports first, then a blank line, then the rest) and enforces the EPL-2.0 OR Apache-2.0
license header on every Java file. It neither rejects nor expands wildcard imports
(
import x.y.*;) — it leaves them untouched.
CI and Sonar flag any style violation, so make sure your changes are formatted before pushing. You can apply both formatters locally with:
mvn spring-javaformat:apply spotless:applyNeither plugin expands an existing wildcard import into explicit single-class imports. Configure IntelliJ so it never produces wildcards in the first place:
- Settings → Editor → Code Style → Java → Imports:
- Class count to use import with '*':
999 - Names count to use static import with '*':
999 - Packages to Use Import with '*': remove every entry
- Class count to use import with '*':
- Run Code → Optimize Imports (⌃⌥O) to expand existing wildcards and drop unused imports. The file must compile for IntelliJ to resolve the types.
- Optional: enable Settings → Tools → Actions on Save → Optimize imports to keep imports clean automatically, matching what spotless and spring-javaformat expect.
Minimum docker version: 20.10
Go on the root folder and launch the following command:
- Full independent build:
docker build -t local/karnak:latest -f Dockerfile . - Build from compile package:
mvn clean install -P productiondocker build -t local/karnak:latest -f src/main/docker/Dockerfile .
See karnak-docker
See all the environment variables
This project is divided in two parts:
- backend: spring data (entities, repositories, converters, validators), enums, spring configurations, spring security, cache, spring services, models...
- frontend : Vaadin components: logic services, graphic components, views
An OpenID Connect identity provider can be configured by using the environment variables:
IDP: when this environment variable has the value 'oidc', the following environment variables will configure the OpenID Connect identity provider. Any other value will load the in memory user configuration.OIDC_CLIENT_ID: client id of the identity providerOIDC_CLIENT_SECRET: client secret of the identity providerOIDC_ISSUER_URI: issuer URI of the identity provider
Karnak exposes a small REST API in addition to the web interface. An OpenAPI (Swagger) description is generated by springdoc and the C-ECHO endpoint is available at /api/echo. For the full list of endpoints and their usage, refer to the Karnak User Guide.