Skip to content

Run secured archive services and Elastic Stack on a single host

Gunter Zeilinger edited this page Sep 23, 2024 · 14 revisions
Secured archive services using Keycloak as Authentication Server and storing System and Audit Logs to Elastic Stack

Ensure that there is a hostname entry in your DNS server for the docker host.
(Optional) Create system groups and users with particular group and user IDs used by the archive services as described in Run secured archive services on a single host.
$ sudo -i
# sysctl -w vm.swappiness=1
# echo 'vm.swappiness=1' >> /etc/sysctl.conf (to persist reboots)
# exit
$ sudo -i
# sysctl -w vm.max_map_count=262144
# echo 'vm.max_map_count=262144' >> /etc/sysctl.conf (to persist reboots)
# exit

If you are bind-mounting a local directory or file, it must be readable by the elasticsearch user. In addition, this user must have write access to the config, data and log dirs (Elasticsearch needs write access to the config directory so that it can generate a keystore). A good strategy is to grant group access to gid 0 for the local directory.

For example, to prepare a local directory for storing data through a bind-mount:

$ sudo mkdir -p /var/local/dcm4chee-arc/esdatadir
$ sudo chmod g+rwx /var/local/dcm4chee-arc/esdatadir
$ sudo chgrp 0 /var/local/dcm4chee-arc/esdatadir
Ensure that Logstash has write access to the file used to persist the fingerprint of the last audit message

You have to mount the file or parent directory specified by environment variable HASH_FILE to a volume or host directory to avoid to start a new hash tree on every re-creation of the container. The file (or parent directory) must be writable by the logstash user of the container (uid=1000). E.g., for mapping the file:

$ sudo mkdir -p /var/local/dcm4chee-arc/logstash
$ sudo touch /var/local/dcm4chee-arc/logstash/filter-hashtree
$ sudo chown 1000:1000 /var/local/dcm4chee-arc/logstash/filter-hashtree

or for mapping the parent directory

$ sudo mkdir -p /var/local/dcm4chee-arc/logstash
$ sudo chown 1000:1000 /var/local/dcm4chee-arc/logstash  

Continue using Docker Command Line or Docker Compose alternatively:

  1. Create an user-defined bridge network
    $ docker network create dcm4chee_default
    
  2. Start Elasticsearch

    Launch a container providing Elasticsearch into the created network, e.g:

    $ docker run --network=dcm4chee_default --name elasticsearch \
               -e ES_JAVA_OPTS="-Xms1024m -Xmx1024m" \
               -e discovery.type=single-node \
               -e xpack.security.enabled=false \
               -p 9200:9200 \
               -p 9300:9300 \
               -v /etc/localtime:/etc/localtime:ro \
               -v /etc/timezone:/etc/timezone:ro \
               -v /var/local/dcm4chee-arc/esdatadir:/usr/share/elasticsearch/data \
               -d docker.elastic.co/elasticsearch/elasticsearch:8.15.1
    

    -e ES_JAVA_OPTS="-Xms1024m -Xmx1024m" - sets the JVM heap size used by Elasticsearch.

    -e discovery.type=single-node - sets the discovery type to single-node; otherwise Elasticsearch will not start caused by failed Bootstrap Checks upon startup.

    -e xpack.security.enabled=false - disable security features, otherwise Logstash will not be able to connect to Elasticsearch via plain http.

    -p 9200:9200 \
    -p 9300:9300 \
    

    publishes the REST (9200) and the node communication (9300) port of Elasticsearch from the container to the host to enable external applications to access Elasticsearch. It is not required for running the Archive, because the Logstash and the Kibana container connects to Elasticsearch over the created bridge network.

    Bind mount -v /etc/localtime:/etc/localtime:ro and -v /etc/timezone:/etc/timezone:ro duplicates your host timezone inside the container. Otherwise the container timezone is UTC. Attention: If there is no /etc/timezone on your host, you have to create one (e.g.: $ echo "Europe/Vienna" > /etc/timezone) before launching the container, otherwise the container will not start.

    Bind mount -v /var/local/dcm4chee-arc/esdatadir:/usr/share/elasticsearch/data takes care to store the data in the specified host directory. It is initialized on first container start-up if it is not already present in the specified host directory. That ensures that the data does not get lost on deletion and re-creation of the Elasticsearch container.

    See further environment variables of Elasticsearch

  3. Start Kibana

    Launch a container providing Kibana into the created network, e.g:

    $ docker run --network=dcm4chee_default --name kibana \
               -v /etc/localtime:/etc/localtime:ro \
               -v /etc/timezone:/etc/timezone:ro \
               -d docker.elastic.co/kibana/kibana:8.15.1
    

    You may enable accessing Kibana from any web browser without user authentication publishing the http port of Kibana from the container to the host by -p 5601:5601.

    Otherwise web browsers have to access Kibana via the Keycloak Proxy which provides the User Authentication against Keycloak and which forwards HTTP requests from authorized users to Kibana over the created bridge network.

    Bind mount -v /etc/localtime:/etc/localtime:ro and -v /etc/timezone:/etc/timezone:ro duplicates your host timezone inside the container. Otherwise the container timezone is UTC. Attention: If there is no /etc/timezone on your host, you have to create one (e.g.: $ echo "Europe/Vienna" > /etc/timezone) before launching the container, otherwise the container will not start.

    See further environment variables of Kibana

  4. Start Logstash

    Launch a container providing Logstash into the created network, e.g:

    $ docker run --network=dcm4chee_default --name logstash \
               -p 12201:12201/udp \
               -p 8514:8514/udp \
               -p 8514:8514 \
               -v /etc/localtime:/etc/localtime:ro \
               -v /etc/timezone:/etc/timezone:ro \
               -v /var/local/dcm4chee-arc/logstash/filter-hashtree:/usr/share/logstash/data/filter-hashtree \
               -d dcm4che/logstash-dcm4chee:8.15.1-17
    
    -p 12201:12201/udp \
    -p 8514:8514/udp \
    -p 8514:8514 \
    

    publishes the configured GELF Logger (12201) and Syslog (8514) port of Logstash from the container to the host to enable external applications to also connect to those ports. Publishing the GELF Logger port is also required if other containers have configured the GELF Logging Driver to log to Logstash. Keycloak and the Archive application connects to Logstash over the created bridge network, so they do not rely on that the ports are published to the docker host.

    Bind mount -v /etc/localtime:/etc/localtime:ro and -v /etc/timezone:/etc/timezone:ro duplicates your host timezone inside the container. Otherwise the container timezone is UTC. Attention: If there is no /etc/timezone on your host, you have to create one (e.g.: $ echo "Europe/Vienna" > /etc/timezone) before launching the container, otherwise the container will not start.

    Bind mount /var/local/dcm4chee-arc/logstash/filter-hashtree:/usr/share/logstash/data/filter-hashtree takes care to store the file with the fingerprint of the last audit message - configurable by environment variable HASH_FILE with default /usr/share/logstash/data/filter-hashtree- outside of the container to avoid to start a new hash tree on every re-creation of the container. Attention: The file must already exist and must be writable by the logstash user of the container (uid=1000).

    See further environment variables of Logstash

  5. Start OpenLDAP Server

    Launch a container providing the LDAP server into the created network, e.g:

    $ docker run --network=dcm4chee_default --name ldap \
               --log-driver gelf \
               --log-opt gelf-address=udp://<docker-host>:12201 \
               --log-opt tag=slapd \
               -p 389:389 \
               -e SYSLOG_HOST=logstash \
               -e SYSLOG_PORT=8514 \
               -e SYSLOG_PROTOCOL=TLS \
               -v /var/local/dcm4chee-arc/ldap:/var/lib/openldap/openldap-data \
               -v /var/local/dcm4chee-arc/slapd.d:/etc/openldap/slapd.d \
               -d dcm4che/slapd-dcm4chee:2.6.7-33.0
    

    which differs from Run minimum set of archive services on a single host by

    • --log-driver gelf, --log-opt gelf-address=udp://<docker-host>:12201, --log-opt tag=slapd - configures the GELF Logging Driver for the container.
    • -e SYSLOG_HOST=logstash, -e SYSLOG_PORT=8514, -e SYSLOG_PROTOCOL=TLS - specifies to emit logs from the LDAP server container and audit logs from the Keycloak and Archive application to the Logstash container, using TLS (default: UDP).

    See further environment variables of Slapd

  6. Start MariaDB Server used by Keycloak Authentication Server

    Launch a container providing Maria DB Server into the created network, e.g:

    $ docker run --network=dcm4chee_network --name mariadb \
               --log-driver gelf \
               --log-opt gelf-address=udp://<docker-host>:12201 \
               --log-opt tag=mariadb \
               -p 3306:3306 \
               -e MYSQL_ROOT_PASSWORD=secret \
               -e MYSQL_DATABASE=keycloak \
               -e MYSQL_USER=keycloak \
               -e MYSQL_PASSWORD=keycloak \
               -v /etc/localtime:/etc/localtime:ro \
               -v /etc/timezone:/etc/timezone:ro \
               -v /var/local/dcm4chee-arc/mysql:/var/lib/mysql \
               -d mariadb:10.11.4
    

    which differs from Run secured archive services on a single host by

    • --log-driver gelf, --log-opt gelf-address=udp://<docker-host>:12201, --log-opt tag=mariadb - configures the GELF Logging Driver for the container.
  7. Start Keycloak Authentication Server

    Launch a container providing preconfigured Keycloak Authentication Server into the created network, e.g:

    $ docker run --network=dcm4chee_default --name keycloak \
               --log-driver gelf \
               --log-opt gelf-address=udp://<docker-host>:12201 \
               --log-opt tag=keycloak \
               -p 8843:8843 \
               -e KC_HTTPS_PORT=8843 \
               -e KC_HOSTNAME=https://<docker-host>:8843 \
               -e KC_HOSTNAME_BACKCHANNEL_DYNAMIC=true \
               -e KEYCLOAK_ADMIN=admin \
               -e KEYCLOAK_ADMIN_PASSWORD=changeit \
               -e KC_DB=mariadb \
               -e KC_DB_URL_DATABASE=keycloak \
               -e KC_DB_URL_HOST=mariadb \
               -e KC_DB_USERNAME=keycloak \
               -e KC_DB_PASSWORD=keycloak \
               -e KC_LOG=file,gelf \
               -e KC_LOG_GELF_HOST=logstash \
               -e ARCHIVE_HOST=<docker-host> \
               -e KIBANA_CLIENT_ID=kibana \
               -e KIBANA_CLIENT_SECRET=<kibana-client-secret> \
               -e KIBANA_REDIRECT_URL=https://<docker-host>:8643/oauth2/callback/* \
               -e KEYCLOAK_WAIT_FOR=ldap:389 mariadb:3306 logstash:8514 \
               -v /etc/localtime:/etc/localtime:ro \
               -v /etc/timezone:/etc/timezone:ro \
               -v /var/local/dcm4chee-arc/keycloak:/opt/keycloak/data \
               -d dcm4che/keycloak:25.0.5
    

    which differs from Run secured archive services on a single host by

    • --log-driver gelf, --log-opt gelf-address=udp://<docker-host>:12201 , --log-opt tag=keycloak - configures the GELF Logging Driver for the container.
    • -e KC_LOG=file,gelf and -e KC_LOG_GELF_HOST=logstash - enables the Quarkus GELF Logger to emit System logs to Logstash.
    • -e KIBANA_CLIENT_ID=kibana - specifies Keycloak client ID for securing the UI of Kibana.
    • -e KIBANA_CLIENT_SECRET=<kibana-client-secret> - specifies client secret for Confidential type kibana client. The same value shall be used in oauth2-proxy container startup explained below.
    • -e KIBANA_REDIRECT_URL=https://<docker-host>:8643/oauth2/callback/* - specifies the Redirect URL of Keycloak client for securing the UI of Kibana.
    • -e KEYCLOAK_WAIT_FOR="ldap:389 mariadb:3306 logstash:8514" - delays the start of Keycloak until OpenLDAP, MariaDB and Logstash are listening on the specified ports.

    See further environment variables of Keycloak

  8. Start PostgreSQL Server

    Launch a container providing the database server into the created network, e.g:

    $ docker run --network=dcm4chee_default --name db \
               --log-driver gelf \
               --log-opt gelf-address=udp://<docker-host>:12201 \
               --log-opt tag=postgres \
               -p 5432:5432 \
               -e POSTGRES_DB=pacsdb \
               -e POSTGRES_USER=pacs \
               -e POSTGRES_PASSWORD=pacs \
               -v /etc/localtime:/etc/localtime:ro \
               -v /etc/timezone:/etc/timezone:ro \
               -v /var/local/dcm4chee-arc/db:/var/lib/postgresql/data \
               -d dcm4che/postgres-dcm4chee:16.4-33
    

    which differs from Run secured archive services on a single host by

    • --log-driver gelf, --log-opt gelf-address=udp://<docker-host>:12201, --log-opt tag=postgres - configures the GELF Logging Driver for the container.

    See further environment variables of PostgreSQL

  9. Start Wildfly with deployed dcm4che Archive 5 application

    Launch a container providing Wildfly with deployed dcm4che Archive 5 application into the created network, e.g:

    $ docker run --network=dcm4chee_default --name arc \
               --log-driver gelf \
               --log-opt gelf-address=udp://<docker-host>:12201 \
               --log-opt tag=dcm4chee-arc \
               -p 8080:8080 \
               -p 8443:8443 \
               -p 9990:9990 \
               -p 9993:9993 \
               -p 2762:2762 \
               -p 2575:2575 \
               -p 12575:12575 \
               -p 11112:11112 \
               -e LOGSTASH_HOST=logstash \
               -e POSTGRES_DB=pacsdb \
               -e POSTGRES_USER=pacs \
               -e POSTGRES_PASSWORD=pacs \
               -e AUTH_SERVER_URL=https://keycloak:8843 \
               -e UI_AUTH_SERVER_URL=https://<docker-host>:8843 \
               -e WILDFLY_WAIT_FOR="ldap:389 db:5432 keycloak:8843 logstash:8514" \
               -v /etc/localtime:/etc/localtime:ro \
               -v /etc/timezone:/etc/timezone:ro \
               -v /var/local/dcm4chee-arc/wildfly:/opt/wildfly/standalone \
               -d dcm4che/dcm4chee-arc-psql:5.33.0-secure
    

    which differs from Run secured archive services on a single host by

    • --log-driver gelf, --log-opt gelf-address=udp://<docker-host>:12201, --log-opt tag=dcm4chee-arc - configures the GELF Logging Driver for the container.
    • -e LOGSTASH_HOST=logstash - configures the GELF Logger to emit System logs to Logstash.
    • -e WILDFLY_WAIT_FOR="ldap:389 db:5432 keycloak:8843 logstash:8514" - delays the start of Wildfly until OpenLDAP slapd, PostgreSQL, Keycloak and Logstash are listening on the specified ports.

    See further environment variables of Archive

  10. Verify OIDC client for Archive UI in Keycloak as described in Run secured archive services on a single host
  11. Verify OIDC client for Wildfly Administration Console in Keycloak as described in Run secured archive services on a single host
  12. Verify OIDC client for OAuth2-Proxy securing Kibana in Keycloak

    Sign in with User/Password root/changeit at the Realm Admin Console of Keycloak at https://<docker-host>:8843/admin/dcm4che/console - you have to replace <docker-host> by the hostname of the docker host. If you changed the default realm name: dcm4che by environment variable REALM_NAME for the Keycloak, the Keycloak Proxy and the Archive Container, you also have to replace dcm4che by the that value in the URL.

    Keycloak docker image dcm4che/keycloak:25.0.5 and newer creates an OIDC client for OAuth2-Proxy for securing Kibana on first startup, customizable by environment variables KIBANA_CLIENT_ID, KIBANA_CLIENT_SECRET and KIBANA_REDIRECT_URL:

    with Audience Token Mapper audience:

    and Client Credential changeit:

    which you can/should Regenerate Secret and copy the new value for passing it as environment variable OAUTH2_PROXY_CLIENT_SECRET to OAuth2 Proxy container in the next step.

  13. Start OAuth2 Proxy securing Kibana

    Oauth2-proxy can be configured via command line options, environment variables or config file (in decreasing order of precedence, i.e. command line options will overwrite environment variables and environment variables will overwrite configuration file settings).

    Launch a container providing OAuth2 Proxy securing Kibana into the created network, e.g:

    $ docker run --network=dcm4chee_default --name oauth2-proxy \
               -p 8643:8643 \
               -e OAUTH2_PROXY_HTTPS_ADDRESS=0.0.0.0:8643 \
               -e OAUTH2_PROXY_PROVIDER=keycloak-oidc \
               -e OAUTH2_PROXY_SKIP_PROVIDER_BUTTON="true" \
               -e OAUTH2_PROXY_UPSTREAMS=http://kibana:5601 \
               -e OAUTH2_PROXY_OIDC_ISSUER_URL=https://<docker-host>:8843/realms/dcm4che \
               -e OAUTH2_PROXY_REDIRECT_URL=https://<docker-host>:8643/oauth2/callback \
               -e OAUTH2_PROXY_ALLOWED_ROLES=auditlog \
               -e OAUTH2_PROXY_CLIENT_ID=kibana \
               -e OAUTH2_PROXY_CLIENT_SECRET=<kibana-client-secret> \
               -e OAUTH2_PROXY_EMAIL_DOMAINS="*" \
               -e OAUTH2_PROXY_OIDC_EMAIL_CLAIM="preferred_username" \
               -e OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL="true" \
               -e OAUTH2_PROXY_COOKIE_SECRET=T0F1dGhLaWJhbmFUZXN0cw== \
               -e OAUTH2_PROXY_SSL_INSECURE_SKIP_VERIFY="true" \
               -e OAUTH2_PROXY_TLS_CERT_FILE=/etc/certs/cert.pem \
               -e OAUTH2_PROXY_TLS_KEY_FILE=/etc/certs/key.pem \
               -e OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR=/templates \
               -d dcm4che/oauth2-proxy:7.6.1 \
    

Note :

  • OAUTH2_PROXY_OIDC_ISSUER_URL: "https://<docker-host>:8843/realms/dcm4che" applies only for Keycloak v18.0+ and if default KC_HTTP_RELATIVE_PATH is used.

  • If lower versions of Keycloak are used or if KC_HTTP_RELATIVE_PATH is set to /auth for Keycloak v18.0+, then OAUTH2_PROXY_OIDC_ISSUER_URL: "https://<docker-host>:8843/auth/realms/dcm4che"

    • -p 8643:8643 - publishes the https (8643) port of the OAuth2-Proxy from the container to the host to enable connections from external https clients to the OAuth2-Proxy, which have to match with

    • -e OAUTH2_PROXY_HTTPS_ADDRESS=0.0.0.0:8643 - the port to be listening, and with the port of

    • -e OAUTH2_PROXY_PROVIDER=kibana-oidc - specifies the OAuth provider.

    • -e OAUTH2_PROXY_SKIP_PROVIDER_BUTTON is optional. If set to true, it will skip sign-in-page specifying Sign-on with Keycloak and directly show the Keycloak login page.

    • -e OAUTH2_PROXY_UPSTREAMS=http://kibana:5601 - specifies Kibana https URL as upstream endpoint

    • -e OAUTH2_PROXY_OIDC_ISSUER_URL=https://<docker-host>:8843/realms/dcm4che - specifies OpenID Connect issuer URL, wherein (8843) port refers KC_HTTPS_PORT used on Keycloak container startup

    • -e OAUTH2_PROXY_REDIRECT_URL=https://<docker-host>:8643/oauth2/callback - the redirection URL for the Keycloak Authentication Server callback URL - you have to replace <docker-host> by the hostname of the docker host, which must be resolvable by your DNS server.

    • -e OAUTH2_PROXY_ALLOWED_ROLES=auditlog - (keycloak-oidc) restrict logins to members of these roles (may be given multiple times)

    • -e OAUTH2_PROXY_CLIENT_ID=kibana - specifies the Client ID used to authenticate to the Keycloak Server,

    • -e OAUTH2_PROXY_CLIENT_SECRET=<kibana-client-secret> - specifies the Client Secret used to authenticate to the Keycloak Authentication Server for Confidential type kibana client. The value should match with that used during keycloak container startup.

    • -e OAUTH2_PROXY_EMAIL_DOMAINS="*" as * specifies to authenticate any email.

    • -e OAUTH2_PROXY_OIDC_EMAIL_CLAIM="preferred_username" which OIDC claim contains the user's email (default "email")

    • -e OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL="true" specifies to not fail if an email address in an id_token is not verified

    • -e OAUTH2_PROXY_COOKIE_SECRET=T0F1dGhLaWJhbmFUZXN0cw== - specifies the seed string for secure cookies (optionally base64 encoded)

    • -e OAUTH2_PROXY_SSL_INSECURE_SKIP_VERIFY=true as true skips validation of certificates presented when using HTTPS

    • -e OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR specifies the custom templates' directory location which contains the customized forbidden error page shown to unauthorized users on authentication. Note : OAuth2 proxy does not yet have a mechanism to only customize one of the templates (i.e. sign_in or error). Hence, if one wants to customize only one, both templates need to be still provided.

    • -e OAUTH2_PROXY_TLS_CERT_FILE and OAUTH2_PROXY_TLS_KEY_FILE specifies path to TLS certificate and private key in Privacy-Enhanced Mail (PEM) format to use for TLS support. To avoid the security warning of Web Browsers connecting to Kibana via OAuth2 Proxy, replace the certificate provided in /etc/certs/cert.pem of the docker image:

      by a certificate whose Common Name and/or Subject Alt Name matches the host name and which is signed by a trusted issuer; bind mount the PEM files with the certificate and corresponding private key and adjust OAUTH2_PROXY_TLS_CERT_FILE and OAUTH2_PROXY_TLS_KEY_FILE to refer their paths inside of the container.

    $ docker run --rm dcm4che/oauth2-proxy:7.6.1 help
    

    will show all available environment variables and command options. See also OAuth2 Proxy as well as Keycloak OIDC Auth Provider of Keycloak for more information about configuration options of OAuth2 Proxy.

    See further environment variables of OAuth2-Proxy

  1. You may stop all 9 containers by:
    $ docker stop elasticsearch kibana logstash ldap mariadb keycloak oauth2-proxy db arc
    

    and start all 9 containers again by:

    $ docker start elasticsearch kibana logstash ldap mariadb keycloak oauth2-proxy db arc
    
  2. You may delete the stopped containers by
    $ docker rm -v elasticsearch kibana logstash ldap mariadb keycloak oauth2-proxy db arc
    

    You may delete the created bridge network by

    $ docker network rm dcm4chee_default
    

Alternatively to Docker Command Line one may use Docker Compose to take care for starting all 8 containers:

  1. Specify the services in a configuration file docker-compose.yml (e.g.):
    version: "3"
    services:
      elasticsearch:
        image: docker.elastic.co/elasticsearch/elasticsearch:8.15.1
        environment:
          ES_JAVA_OPTS: -Xms1024m -Xmx1024m
          discovery.type: single-node
          xpack.security.enabled: "false"
        logging:
          driver: json-file
          options:
            max-size: "10m"
        ports:
          - "9200:9200"
          - "9300:9300"
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /etc/timezone:/etc/timezone:ro
          - /var/local/dcm4chee-arc/esdatadir:/usr/share/elasticsearch/data
      kibana:
        image: docker.elastic.co/kibana/kibana:8.15.1
        logging:
          driver: json-file
          options:
            max-size: "10m"
        depends_on:
          - elasticsearch
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /etc/timezone:/etc/timezone:ro
      logstash:
        image: dcm4che/logstash-dcm4chee:8.15.1-17
        logging:
          driver: json-file
          options:
            max-size: "10m"
        ports:
          - "12201:12201/udp"
          - "8514:8514/udp"
          - "8514:8514"
        depends_on:
          - elasticsearch
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /etc/timezone:/etc/timezone:ro
          - /var/local/dcm4chee-arc/logstash/filter-hashtree:/usr/share/logstash/data/filter-hashtree
      ldap:
        image: dcm4che/slapd-dcm4chee:2.6.7-33.0
        logging:
          driver: gelf
          options:
            gelf-address: "udp://<docker-host>:12201"
            tag: slapd
        ports:
          - "389:389"
          - "636:636"
        environment:
          SYSLOG_HOST: logstash
          SYSLOG_PORT: 8514
          SYSLOG_PROTOCOL: TLS
          STORAGE_DIR: /storage/fs1
        volumes:
          - /var/local/dcm4chee-arc/ldap:/var/lib/openldap/openldap-data
          - /var/local/dcm4chee-arc/slapd.d:/etc/openldap/slapd.d
      mariadb:
        image: mariadb:10.11.4
        logging:
          driver: gelf
          options:
            gelf-address: "udp://<docker-host>:12201"
            tag: mariadb
        ports:
          - "3306:3306"
        environment:
          MYSQL_ROOT_PASSWORD: secret
          MYSQL_DATABASE: keycloak
          MYSQL_USER: keycloak
          MYSQL_PASSWORD: keycloak
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /etc/timezone:/etc/timezone:ro
          - /var/local/dcm4chee-arc/mysql:/var/lib/mysql
      keycloak:
        image: dcm4che/keycloak:25.0.5
        logging:
          driver: gelf
          options:
            gelf-address: "udp://<docker-host>:12201"
            tag: keycloak
        ports:
          - "8843:8843"
        environment:
          KC_HTTPS_PORT: 8843
          KC_HOSTNAME: https://<docker-host>:8843
          KC_HOSTNAME_BACKCHANNEL_DYNAMIC: 'true'
          KEYCLOAK_ADMIN: admin
          KEYCLOAK_ADMIN_PASSWORD: changeit
          KC_DB: mariadb
          KC_DB_URL_DATABASE: keycloak
          KC_DB_URL_HOST: mariadb
          KC_DB_USERNAME: keycloak
          KC_DB_PASSWORD: keycloak
          KC_LOG: file,gelf
          KC_LOG_GELF_HOST: logstash
          ARCHIVE_HOST: <docker-host>
          KIBANA_CLIENT_ID: kibana
          KIBANA_CLIENT_SECRET: <kibana-client-secret>
          KIBANA_REDIRECT_URL: https://<docker-host>:8643/oauth2/callback/*
          KEYCLOAK_WAIT_FOR: ldap:389 mariadb:3306 logstash:8514
        depends_on:
          - ldap
          - mariadb
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /etc/timezone:/etc/timezone:ro
          - /var/local/dcm4chee-arc/keycloak:/opt/keycloak/data
      oauth2-proxy:
        image: dcm4che/oauth2-proxy:7.6.1
        ports:
          - "8643:8643"
        restart: on-failure
        environment:
          OAUTH2_PROXY_HTTPS_ADDRESS: 0.0.0.0:8643
          OAUTH2_PROXY_PROVIDER: keycloak-oidc
          OAUTH2_PROXY_SKIP_PROVIDER_BUTTON: "true"
          OAUTH2_PROXY_UPSTREAMS: "http://kibana:5601"
          OAUTH2_PROXY_OIDC_ISSUER_URL: "https://<docker-host>:8843/realms/dcm4che"
          OAUTH2_PROXY_REDIRECT_URL: "https://<docker-host>:8643/oauth2/callback"
          OAUTH2_PROXY_ALLOWED_ROLES: auditlog
          OAUTH2_PROXY_CLIENT_ID: kibana
          OAUTH2_PROXY_CLIENT_SECRET: <kibana-client-secret>
          OAUTH2_PROXY_EMAIL_DOMAINS: "*"
          OAUTH2_PROXY_OIDC_EMAIL_CLAIM: "sub"
          OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL: "true"
          OAUTH2_PROXY_COOKIE_SECRET: T0F1dGhLaWJhbmFUZXN0cw==
          OAUTH2_PROXY_SSL_INSECURE_SKIP_VERIFY: "true"
          OAUTH2_PROXY_TLS_CERT_FILE: /etc/certs/cert.pem
          OAUTH2_PROXY_TLS_KEY_FILE: /etc/certs/key.pem
          OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR: /templates
        depends_on:
          - keycloak
      db:
        image: dcm4che/postgres-dcm4chee:16.4-33
        logging:
          driver: gelf
          options:
            gelf-address: "udp://<docker-host>:12201"
            tag: postgres
        ports:
          - "5432:5432"
        environment:
          POSTGRES_DB: pacsdb
          POSTGRES_USER: pacs
          POSTGRES_PASSWORD: pacs
        depends_on:
          - logstash
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /etc/timezone:/etc/timezone:ro
          - /var/local/dcm4chee-arc/db:/var/lib/postgresql/data
      arc:
        image: dcm4che/dcm4chee-arc-psql:5.33.0-secure
        logging:
          driver: gelf
          options:
            gelf-address: "udp://<docker-host>:12201"
            tag: dcm4chee-arc
        ports:
          - "8080:8080"
          - "8443:8443"
          - "9990:9990"
          - "9993:9993"
          - "11112:11112"
          - "2762:2762"
          - "2575:2575"
          - "12575:12575"
        environment:
          LOGSTASH_HOST: logstash
          POSTGRES_DB: pacsdb
          POSTGRES_USER: pacs
          POSTGRES_PASSWORD: pacs
          AUTH_SERVER_URL: https://keycloak:8843
          UI_AUTH_SERVER_URL: https://<docker-host>:8843
          WILDFLY_CHOWN: /storage
          WILDFLY_WAIT_FOR: ldap:389 db:5432 keycloak:8843 logstash:8514
        depends_on:
          - ldap
          - keycloak
          - db
          - logstash
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /etc/timezone:/etc/timezone:ro
          - /var/local/dcm4chee-arc/wildfly:/opt/wildfly/standalone
          - /var/local/dcm4chee-arc/storage:/storage

    you have to replace <docker-host> by the hostname of the docker host, which must be resolvable by your DNS server.

    See available environment variables for containers :

Note :

  • OAUTH2_PROXY_OIDC_ISSUER_URL: "https://<docker-host>:8843/realms/dcm4che" applies only for Keycloak v18.0+ and if default KC_HTTP_RELATIVE_PATH is used.
  • If lower versions of Keycloak are used or if KC_HTTP_RELATIVE_PATH is set to /auth for Keycloak v18.0+, then OAUTH2_PROXY_OIDC_ISSUER_URL: "https://<docker-host>:8843/auth/realms/dcm4che"
  • If there are difficulties starting the archive service due to
    There is insufficient memory for the Java Runtime Environment to continue. Cannot create GC thread. Out of system resources.
    
    adding the following option to the arc service
    security_opt:
     - seccomp:unconfined
    
  1. Create and start all 8 containers
    $ docker-compose -p dcm4chee up -d
    Creating network "dcm4chee_default" with the default driver
    Creating dcm4chee_elasticsearch_1       ... done
    Creating dcm4chee_logstash_1            ... done
    Creating dcm4chee_ldap_1                ... done
    Creating dcm4chee_mariadb_1             ... done
    Creating dcm4chee_db_1                  ... done
    Creating dcm4chee_kibana_1              ... done
    Creating dcm4chee_keycloak_1            ... done
    Creating dcm4chee_arc_1                 ... done
    Creating dcm4chee_oauth2-proxy_1        ... done

    in the directory containing docker-compose.yml.

  2. Register the Archive UI as OIDC client in Keycloak as described in Run secured archive services on a single host.
  3. Register the WildFly Administration Console as OIDC client in Keycloak as described in Run secured archive services on a single host.
  4. Register OAuth2 Proxy as OIDC client in Keycloak as described above
  5. (Conditional) Recreate and start the container running OAuth2 Proxy with adjusted Client Secret

    If you configured the client for OAuth2 Proxy with Access Type: confidential, you have to adjust the value for the environment variable OAUTH2_PROXY_CLIENT_SECRET of the oauth2-proxy service in docker-compose.yml to match with the actual value from the Credentials tab for the OIDC client in the Realm Admin Console of Keycloak and recreate and restart the OAuth2 Proxy container by invoking

    $ docker-compose -p dcm4chee up -d
    dcm4chee_elasticsearch_1 is up-to-date
    dcm4chee_kibana_1 is up-to-date
    dcm4chee_logstash_1 is up-to-date
    dcm4chee_ldap_1 is up-to-date
    dcm4chee_mariadb_1 is up-to-date
    dcm4chee_db_1 is up-to-date
    dcm4chee_keycloak_1 is up-to-date
    Recreating dcm4chee_oauth2-proxy_1 ... 
    Recreating dcm4chee_oauth2-proxy_1 ... done

    in the directory containing docker-compose.yml.

  6. You may stop all 9 containers by:
    $ docker-compose -p dcm4chee stop
    Stopping dcm4chee_arc_1                 ... done
    Stopping dcm4chee_oauth2-proxy_1        ... done
    Stopping dcm4chee_keycloak_1            ... done
    Stopping dcm4chee_kibana_1              ... done
    Stopping dcm4chee_logstash_1            ... done
    Stopping dcm4chee_elasticsearch_1       ... done
    Stopping dcm4chee_mariadb_1             ... done
    Stopping dcm4chee_db_1                  ... done
    Stopping dcm4chee_ldap_1                ... done

    and start all 8 containers again by:

    $ docker-compose -p dcm4chee start
    Starting db                  ... done
    Starting elasticsearch       ... done
    Starting kibana              ... done
    Starting ldap                ... done
    Starting mariadb             ... done
    Starting logstash            ... done
    Starting keycloak            ... done
    Starting oauth2-proxy        ... done
    Starting arc                 ... done
  7. You may stop and delete all 9 containers by
    $ docker-compose -p dcm4chee down
    Stopping dcm4chee_arc_1                 ... done
    Stopping dcm4chee_oauth2-proxy_1        ... done
    Stopping dcm4chee_keycloak_1            ... done
    Stopping dcm4chee_kibana_1              ... done
    Stopping dcm4chee_logstash_1            ... done
    Stopping dcm4chee_elasticsearch_1       ... done
    Stopping dcm4chee_mariadb_1             ... done
    Stopping dcm4chee_db_1                  ... done
    Stopping dcm4chee_ldap_1                ... done
    Removing dcm4chee_arc_1                 ... done
    Removing dcm4chee_oauth2-proxy_1        ... done
    Removing dcm4chee_keycloak_1            ... done
    Removing dcm4chee_kibana_1              ... done
    Removing dcm4chee_logstash_1            ... done
    Removing dcm4chee_elasticsearch_1       ... done
    Removing dcm4chee_mariadb_1             ... done
    Removing dcm4chee_db_1                  ... done
    Removing dcm4chee_ldap_1                ... done
    Removing network dcm4chee_default
Clone this wiki locally