# Installing without Docker

This guide will guide the installation process when Docker is not allowed in the target environment.

The procedures in this guide have been tested on a RHEL 7.5 distribution. All the following components will be installed and configured :

  • Postgres 12.3
  • Keycloak IAM Server
  • NGINX
  • Hume Web Frontend Service
  • SSL Certificate and necessary keys
  • Hume API Service
  • Hume Orchestra Service

The following Linux users and groups will be created and run their respectives services :

  • nginx
  • postgres
  • keycloak
  • hume

This guide also assumes that :

  • We have a domain myhumeapp.com where Hume will be accessible.
  • The frontend application will be accessible under myhumeapp.com/web
  • The api will be accessible under myhumeapp.com/api
  • The SSO login will be accessible under myhumeapp.com/sso
  • All the network communications have to occur on a TLS encrypted channel

# Download and OS preparation

# Update latest OS dependencies

sudo yum update

# Create the hume user

sudo groupadd hume
sudo useradd hume -g hume

# Create the hume directory

sudo mkdir -p /opt/hume
sudo chown -R hume:hume /opt/hume
sudo chmod 755 /opt/hume

# Download Hume

Contact your GraphAware Hume Sales Representative for receiving your download link.

sudo su hume
cd /opt/hume
wget <download-link>
unzip graphaware-hume-2.7.0.zip

TIP

replace 2.7.0 throughout this guide with the Hume version you're installing.


# Install the Postgres server

sudo su
yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum install postgresql12
yum install postgresql12-server

// initialize the database and start postgres

/usr/pgsql-12/bin/postgresql-12-setup initdb
systemctl enable postgresql-12
systemctl start postgresql-12

Allow services on this machine to connect to the postgres server with username/password connection

Edit the file in /var/lib/pgsql/12/data/pg_hba.conf

vi /var/lib/pgsql/12/data/pg_hba.conf

Locate the line that contains

host    all             all             127.0.0.1/32            ident

And replace ident with md5 :

host    all             all             127.0.0.1/32            md5

Restart postgres service

systemctl restart postgresql-12

## Install JAVA

sudo yum -y install java-11-openjdk

# Install the IAM server

# Create the Keycloak database

Keycloak requires a Postgres database with UTF8 encoding.

sudo -u postgres -i
psql

Check if the current database encoding is in utf8 :

show server_encoding;
postgres=# show server_encoding;
 server_encoding
-----------------
 UTF8
(1 row)

If the result is UTF8 :

create database keycloak;

otherwise :

create database keycloak with encoding 'UTF8';

Create the Keycloak user and grant him privileges on the database :

CREATE USER keycloak WITH ENCRYPTED PASSWORD 'kc123456';
GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak;

Exit the psql shell and return to the user session by typing twice exit.

# Install Keycloak

cd /opt/hume
unzip graphaware-hume-2.7.0/keycloak-10.0.1.zip
chown -R hume:hume keycloak-10.0.1

Keycloak is now extracted under /opt/hume/keycloak-10.0.1.

Create a file named keycloak.env where we will specify our database credentials :

vi /opt/hume/keycloak.env

And copy the following contents :

KEYCLOAK_DB_HOST=jdbc:postgresql://localhost/keycloak
KEYCLOAK_DB_USER=keycloak
KEYCLOAK_DB_PASSWORD=kc123456

TIP

Replace accordingly the variables above if you have specified different values during the previous step.

Secure the file :

chmod 600 /opt/hume/keycloak.env

# Create a systemd service for running Keycloak as a daemon

Create the following entry in /etc/systemd/system/hume-keycloak.service :

sudo vi /etc/systemd/system/hume-keycloak.service

And paste the following systemd configuration

[Unit]
Description=Keycloak
After=network.target

[Service]
Type=idle
EnvironmentFile=/opt/hume/keycloak.env
User=hume
ExecStart=/opt/hume/keycloak-10.0.1/bin/standalone.sh -b 0.0.0.0
ExecStop=/opt/hume/keycloak-10.0.1/bin/jboss-cli.sh --connect command=:shutdown
ExecReload=/opt/keycloak-10.0.1/bin/jboss-cli.sh --connect command=:reload
TimeoutStartSec=600
TimeoutStopSec=600

[Install]
WantedBy=multi-user.target

Reload the daemon and enable the service :

systemctl daemon-reload
systemcl enable hume-keycloak

And run Keycloak as a system service :

service hume-keycloak.service start

You can see the logs by running :

journalctl -u hume-keycloak.service -f

Create the master user :

/opt/hume/keycloak-10.0.1/bin/add-user-keycloak.sh -r master -u <username> -p <password>

For configuring Keycloak, refer to the Keycloak configuration document.

Summary of the steps :

  • Create the KC admin (of KC)
  • Create a new Realm hume
  • Create a new client hume-web - openid public - all redirect uris
  • In the client, create a role ROLE_ADMINISTRATOR
  • Create a test user for now give a username and password, assign him the ROLE_ADMINISTRATOR role

# Install the Hume Frontend application

The unzipped package contains inside a hume-web-${VERSION}.zip file. This contains the sources of the frontend application which have to be served by a web server ( see nginx installation later ).

# Prepare the frontend application

Before serving it to nginx we will need to place the sources in the directory of our choice, for this guide we will use /opt/hume/2.7.0/web

cd /opt/hume
unzip graphaware-hume-2.7.0/hume-web-2.7.0.zip
// this will create a `dist` directory, rename it to `web`
mv dist/ web
ll

total 449976
drwxr-xr-x. 2 hume hume       117 May 24 10:59 graphaware-hume-2.7.0
-rw-rw-r--. 1 hume hume 460774740 May 24 11:00 graphaware-hume-2.7.0.zip
drwxr-xr-x. 8 hume hume       200 May 24 07:54 web

# Install NGINX

sudo su
sudo yum install nginx

Check the NGINX version

nginx -v

// nginx version: nginx/1.16.1

Check the nginx user has been correctly created

cat /etc/passwd | grep nginx

// nginx:x:996:991:Nginx web server:/var/lib/nginx:/sbin/nologin

# Configure NGINX

Create a hume.conf file under the /etc/nginx/conf.d/ directory with the following content :


server {
    client_max_body_size 0;
    client_body_buffer_size 16k;
    listen 80;
    server_name myhumeapp.com;

    location / {
        return 301 https://$host$request_uri;
    }

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
}

server {
  listen 443 ssl;
  index index.html;
  server_name myhumeapp.com;
  # path to the front-end location,
  root /opt/hume/web;

  ssl_certificate /etc/letsencrypt/live/myhumeapp.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/myhumeapp.com/privkey.pem;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  location /web {
    alias /opt/hume/web;
    add_header "Set-Cookie" 'HUME_WEB_CONFIG={"baseUrl":"https://myhumeapp.com/api", "keycloakEnabled": "true", "keycloakUrl":"https://myhumeapp.com/sso/auth", "keycloakRealm":"hume", "keycloakClient":"hume-web","basePath":"/web"};path=/;Secure;SameSite=strict';
    try_files $uri $uri/ /web/index.html;
  }

  # direct all the assets to the basePath
  location ~ ^/assets {
      rewrite ^/assets(/.*)$ /$1;
  }

  location @rewrites {
    rewrite ^(.+)$ /index.html last;
  }

  location /api/ {
    proxy_pass https://localhost:8444/;
  }

  location /sso {
    proxy_pass https://localhost:8443;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $host;
  }
}

NO SSL

server {
  listen 80;
  index index.html;
  server_name myhumeapp.com;
  # path to the front-end location,
  root /opt/hume/web;

  location /web {
    alias /opt/hume/web;
    add_header "Set-Cookie" 'HUME_WEB_CONFIG={"baseUrl":"https://myhumeapp.com/api", "keycloakEnabled": "true", "keycloakUrl":"https://myhumeapp.com/sso/auth", "keycloakRealm":"hume", "keycloakClient":"hume-web","basePath":"/web"};path=/;SameSite=strict';
    try_files $uri $uri/ /web/index.html;
  }

  # direct all the assets to the basePath
  location ~ ^/assets {
      rewrite ^/assets(/.*)$ /$1;
  }

  location @rewrites {
    rewrite ^(.+)$ /index.html last;
  }

  location /api/ {
    proxy_pass http://localhost:8444/;
  }

  location /sso {
    proxy_pass https://localhost:8443;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $host;
  }
}

This configuration file describes the following :

  • Disable any non https connection by returning a 301 Moved Permantly response
  • Serve the content of /opt/hume/web under /web and expose a Secure Cookie with some dynamic variables to be used by the frontend application
  • Acts as proxy for the API service, it will root any request to /api to the service running on https://localhost:8444
  • Acts as proxy for the IAM server, it will root any request to /sso to the service running on https://localhost:8443

# Restart NGINX

service nginx restart

The restart will fail because the SSL section of the nginx configuration refers to an SSL certificate that is not yet existing.

You can see the last 10 lines of the nginx service log :

journalctl -u nginx.service -n 10 --no-pager
-- Logs begin at Sun 2020-05-24 10:42:40 UTC, end at Sun 2020-05-24 12:05:51 UTC. --
May 24 10:51:32 acme-stage-vm systemd[1]: Unit nginx.service cannot be reloaded because it is inactive.
May 24 12:02:41 acme-stage-vm systemd[1]: Starting The nginx HTTP and reverse proxy server...
May 24 12:02:41 acme-stage-vm nginx[35283]: nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/myhumeapp.com/fullchain.pem": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/letsencrypt/live/myhumeapp.com/fullchain.pem','r') error:2006D080:BIO routines:BIO_new_file:no such file)
May 24 12:02:41 acme-stage-vm nginx[35283]: nginx: configuration file /etc/nginx/nginx.conf test failed
May 24 12:02:41 acme-stage-vm systemd[1]: nginx.service: control process exited, code=exited status=1
May 24 12:02:41 acme-stage-vm systemd[1]: Failed to start The nginx HTTP and reverse proxy server.
May 24 12:02:41 acme-stage-vm systemd[1]: Unit nginx.service entered failed state.
May 24 12:02:41 acme-stage-vm systemd[1]: nginx.service failed.

# Create a certificate SSL/TLS certificate

If you have your own SSL/TLS certificate, feel free to skip this section.

We will use Let's Encrypt to create a SSL/TLS certificate for the domain myhumeapp.com .

Install the certbot :

sudo pip uninstall -y requests urllib3
sudo yum -y install certbot

Create the certificate

sudo mkdir -p /var/www/certbot
sudo certbot certonly --webroot -w /var/www/certbot --email hume@graphaware.com -d myhumeapp.com --rsa-key-size 4096 -n --agree-tos



 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/myhumeapp.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/myhume.com/privkey.pem
   Your cert will expire on 2020-08-22. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Restart NGINX

sudo service nginx restart

Now go to https://myhumeapp.com/web/, you should be redirected to Keycloak for login and after a successful login it should throw an exception because the API is not created yet ( check the browser console, you should see a 502 error in one of the network calls )


# Create certificates for internal communication

TIP

if you have your own CA certificate, you can skip the creation section.

add the hostname to /etc/hosts so it gets the loopback ip

sudo sed -i "s/localhost/$(hostname) localhost/" /etc/hosts

Create the directory where we will put the certificates

sudo mkdir -p /opt/hume/security
cd  /opt/hume/security

Create the CA key and certificate

sudo openssl genrsa -des3 -out rootCA.key 4096
sudo openssl req -x509 -new -nodes -key rootCA.key -sha256 -subj "/C=UK/O=GraphAware Ltd/CN=Local CA" -days 1024 -out rootCA.crt

Create server key and signed server certificate

HOSTNAME=`hostname`; sudo openssl genrsa -out $HOSTNAME.key 2048; sudo openssl req -new -sha256 -key $HOSTNAME.key -subj "/C=UK/O=GraphAware Ltd/CN=$HOSTNAME" -out $HOSTNAME.csr; sudo openssl x509 -req -in $HOSTNAME.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out $HOSTNAME.crt -days 500 -sha256

Convert PEM to pkcs12 and import pkcs12 chain and key to java keystore

HOSTNAME=`hostname`; sudo openssl pkcs12 -export -in $HOSTNAME.crt -inkey $HOSTNAME.key -chain -CAfile rootCA.crt -name server -out $HOSTNAME.p12; sudo keytool -importkeystore -deststorepass changeit -destkeystore hume-keystore -srckeystore $HOSTNAME.p12 -srcstoretype PKCS12

Import custom CA to the java trust store

sudo cp $JRE_HOME/lib/security/cacerts hume-truststore
sudo keytool -keystore hume-truststore -storepass changeit -importcert -alias local-ca -file rootCA.crt

Set correct permissions

sudo chown -R hume: /opt/hume/
sudo chmod 400  /opt/hume/security/*

# Provide the certificate to Keycloak

Edit the /opt/hume/keycloak-10.0.1/standalone/configuration/standalone.xml file and search for ApplicationRealm.

Replace the ssl section with the following :

<server-identities>
  <ssl>
      <keystore path="/opt/hume/security/hume-keystore"  keystore-password="changeit"/>
  </ssl>
</server-identities>

# Install the Hume API

Create the hume database and user :

sudo -u postgres -i
psql
create database hume;
CREATE USER hume WITH ENCRYPTED PASSWORD 'hume123456';
GRANT ALL PRIVILEGES ON DATABASE hume TO hume;

TIP

Replace the values accordingly if the guide if you choose to use different credentials

Create a directory for the hume api and its configuration :

sudo su hume
cd /opt/hume
mkdir api
cp graphaware-hume-2.7.0/hume-api-2.7.0.jar ./api/
cd api

Create a configuration file for the api :

vi application.yml

And add the following content

server:
  ssl:
    key-store: /opt/hume/security/hume-keystore
    key-store-type: pkcs12
    key-store-password: changeit
    key-alias: server
  port: 8444
hume:
  security:
    audit:
      enabled: true
    provider: keycloak
  orchestra:
    enabled: false
    uri: "https://localhost:8100"
keycloak:
  enabled: true
  auth-server-url: https://myhumeapp.com/sso/auth
  realm: hume
  resource: hume-web
  principal-attribute: preferred_username
  use-resource-role-mappings: true
spring:
  datasource:
    url: "jdbc:postgresql://localhost:5432/hume"
    username: hume
    password: hume123456

NO SSL

server:
  port: 8444
  address: 0.0.0.0
hume:
  security:
    audit:
      enabled: true
    provider: keycloak
  orchestra:
    enabled: false
    uri: "https://localhost:8100"
keycloak:
  enabled: true
  auth-server-url: https://myhumeapp.com/sso/auth
  realm: hume
  resource: hume-web
  principal-attribute: preferred_username
  use-resource-role-mappings: true
spring:
  datasource:
    url: "jdbc:postgresql://localhost:5432/hume"
    username: hume
    password: hume123456

WARNING

setsebool httpd_can_network_connect on -P

Create a systemd service for the hume api

sudo vi /etc/systemd/system/hume-api.service

And paste the following :

[Unit]
Description=Hume Rest
After=syslog.target
 
[Service]
User=hume
WorkingDirectory=/opt/hume/api
ExecStart=/usr/bin/java -Djava.net.preferIPv4Stack=true -Djavax.net.ssl.trustStore=/opt/hume/security/hume-truststore -jar hume-api-2.7.0.jar
SuccessExitStatus=143
 
[Install]
WantedBy=multi-user.target
sudo systemctl enable hume-api.service
service hume-api start
journalctl -u hume-api -f

# Install Orchestra

Create the directory for Orchestra and its configuration

sudo su hume
cd /opt/hume
mkdir orchestra
cp graphaware-hume-2.7.0/hume-orchestra-2.7.0.jar ./orchestra
cd orchestra

Create a configuration file for Orchestra :

vi application.yml

And add the following content :

NO SSL

server:
  port: 8100

SSL

server:
  port: 8100
  ssl:
    key-store: /opt/hume/ssl/hume.jks
    key-store-type: "pkcs12"
    key-store-password: "password"
    key-password: "password"
    key-alias: "hume-orchestra"

Create the systemd service file :

sudo vi /etc/systemd/system/hume-orchestra.service
[Unit]
Description=Hume Orchestra
After=syslog.target
 
[Service]
User=hume
WorkingDirectory=/opt/hume/orchestra
ExecStart=/usr/bin/java -Djava.net.preferIPv4Stack=true -jar hume-orchestra-2.7.0.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Start the service

sudo systemctl enable hume-orchestra.service
service hume-orchestra start
journalctl -u hume-orchestra -f

You also need to let the API know that Orchestra is available, replace the following section in /opt/hume/api/application.yml

  orchestra:
    enabled: true
    uri: "https://localhost:8100"

# Install the Hume Alerting

Once the followings steps are done (Install the Hume Alerting Controller and Install the Hume Alerting Operator), to enable the Alerting System you have to add this snippet to the application.yml of the hume-api:

hume:
  ...
  feature:
    alerts:
      enabled: true
    collections:
      enabled: true
  ...
  alerting:
    uri: http://YOUR_CONTROLLER_HOST:8200

# Install the Hume Alerting Controller

Create the hume-alerting-controller database and user:

sudo -u postgres -i
psql
create database "alert-controller";
CREATE USER "alert-controller" WITH ENCRYPTED PASSWORD 'controller123456';
GRANT ALL PRIVILEGES ON DATABASE "alert-controller" TO "alert-controller";

TIP

Replace the values of the guide accordingly if you choose to use different credentials

Create a directory for the hume alerting-controller and its configuration:

sudo su hume
cd /opt/hume
mkdir controller
cp graphaware-hume-2.9.0-alpha3/hume-alerting-controller-2.9.0-alpha3.jar ./controller/
cd controller

Create a configuration file for the hume-alerting-controller:

vi application.yml

And add the following content changing the following placeholders:

  • YOUR_KAFKA_HOST
  • YOUR_NO_REPLY@YOUR_DOMAIN.COM
  • YOUR_NOTIFICATION_EMAIL_ADDRESS@YOUR_DOMAIN.COM
  • YOUR_SMTP_SERVER_HOST
  • YOUR_SMTP_SERVER_PASSWORD
  • YOUR_SMTP_SERVER_PORT
  • YOUR_SMTP_SERVER_USERNAME

accordingly your installation

kafka:
  topics:
    actions: alerting-actions
    feedback: alerting-feedback
    notification: alerting-notification
    scheduler: alerting-scheduler
logging:
  level:
    org:
      quartz: INFO
      springframework:
        scheduling:
          quartz: INFO
notifier:
  mail:
    from: YOUR_NO_REPLY@YOUR_DOMAIN.COM
    to: YOUR_NOTIFICATION_EMAIL_ADDRESS@YOUR_DOMAIN.COM
scheduler:
  engine: quartz
scheduling:
  messenger:
    type: kafka
server:
  error:
    include-message: always
  port: 8200
spring:
  datasource:
    driverClassName: org.postgresql.Driver
    password: controller123456
    url: jdbc:postgresql://localhost:5432/alert-controller
    username: alert-controller
  jpa:
    database-platform: org.hibernate.dialect.PostgreSQLDialect
    database-platform.hibernate.ddl-auto: none
    generate-ddl: false
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    properties:
      hibernate:
        jdbc:
          time_zone: UTC
  kafka:
    consumer:
      auto-offset-reset: earliest
      bootstrap-servers: YOUR_KAFKA_HOST:9092
      group-id: group-id
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
    producer:
      bootstrap-servers: YOUR_KAFKA_HOST:9092
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
  liquibase:
    change-log: classpath:liquibase/liquibase-changelog-master.xml
  mail:
    host: YOUR_SMTP_SERVER_HOST
    password: YOUR_SMTP_SERVER_PASSWORD
    port: YOUR_SMTP_SERVER_PORT
    properties:
      mail:
        smtp:
          auth: true
          connectiontimeout: 5000
          starttls:
            enable: true
          timeout: 5000
          writetimeout: 5000
    username: YOUR_SMTP_SERVER_USERNAME
  quartz:
    jdbc:
      initialize-schema: never
    job-store-type: jdbc
    properties:
      org:
        quartz:
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
            isClustered: false
            tablePrefix: QRTZ_
          scheduler:
            idleWaitTime: 5000
            instanceId: AUTO
            instanceName: SampleJobScheduler
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 4
            threadPriority: 5
    propertiesorg:
      quartz:
        jobStore:
          useProperties: true

Create a systemd service for the hume-alerting-controller:

sudo vi /etc/systemd/system/hume-alerting-controller.service

And paste the following:

[Unit]
Description=Hume Alerting Controller
After=syslog.target
 
[Service]
User=hume
WorkingDirectory=/opt/hume/controller
ExecStart=/usr/bin/java -Djava.net.preferIPv4Stack=true -Djavax.net.ssl.trustStore=/opt/hume/security/hume-truststore -jar hume-alerting-controller-2.9.0-alpha3.jar
SuccessExitStatus=143
 
[Install]
WantedBy=multi-user.target

sudo systemctl enable hume-alerting-controller.service
service hume-alerting-controller start
journalctl -u hume-alerting-controller -f

# Install the Hume Alerting Operator

Create the hume-alerting-operator database and user:

sudo -u postgres -i
psql
create database "alert-operator";
CREATE USER "alert-operator" WITH ENCRYPTED PASSWORD 'operator123456';
GRANT ALL PRIVILEGES ON DATABASE "alert-operator" TO "alert-operator";

TIP

Replace the values of the guide accordingly if you choose to use different credentials

Create a directory for the hume-alerting-operator and its configuration:

sudo su hume
cd /opt/hume
mkdir operator
cp graphaware-hume-2.9.0-alpha3/hume-alerting-operator-2.9.0-alpha3.jar ./operator/
cd operator

Create a configuration file for the hume-alerting-operator:

vi application.yml

And add the following content changing the following placeholders

  • YOUR_KAFKA_HOST
  • YOUR_ZOOKEEPER_HOST

accordingly your installation

spring:
  datasource:
    driverClassName: org.postgresql.Driver
    url: jdbc:postgresql://localhost:5432/alert-operator?reWriteBatchedInserts=true
    username: alert-operator
    password: operator123456
  jpa:
    properties:
      hibernate:
        jdbc:
          time_zone: UTC
    database-platform: org.hibernate.dialect.PostgreSQLDialect
    hibernate:
      ddl-auto: update
  kafka:
    producer:
      bootstrap-servers: YOUR_KAFKA_HOST:9092
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
  cloud:
    function:
      definition: operator;action
    stream:
      bindings:
        operator-in-0:
          consumer:
            max-attempts: 1
            #default-retryable: false
          destination: alerting-scheduler
          group: topic-grp
        action-in-0:
          destination: alerting-actions
      kafka:
        binder:
          brokers: YOUR_KAFKA_HOST:9092
          zkNodes: YOUR_ZOOKEEPER_HOST:2181
          #deserialization-exception-handler: sendToDlq
          consumer-properties:
            max.poll.records: 1
            max.poll.interval.ms: 600000000
        bindings:
          operator-in-0:
            consumer:
              auto-commit-offset: true
              auto-commit-on-error: true
              enable-dlq: true
              dlq-name: topic-errors
              dlq-producer-properties:
                configuration:
                  key:
                    serializer: org.apache.kafka.common.serialization.StringSerializer
                  value:
                    serializer: com.graphaware.humealertingoperator.serializer.DlqSerializer

neo4j:
  max-transaction-retry-time-sec: 0
  connection-acquisition-timeout-sec: 3
  connection-timeout-sec: 3
server:
  port: 8083
kafka:
  topics:
    notify: alerting-notification
    feedback: alerting-feedback
operator:
  global-batch-size: 100000
  slot-batch-size: 50000

Create a systemd service for the hume-alerting-operator

sudo vi /etc/systemd/system/hume-alerting-operator.service

And paste the following:

[Unit]
Description=Hume Alerting Operator
After=syslog.target
 
[Service]
User=hume
WorkingDirectory=/opt/hume/operator
ExecStart=/usr/bin/java -Djava.net.preferIPv4Stack=true -Djavax.net.ssl.trustStore=/opt/hume/security/hume-truststore -jar hume-alerting-operator-2.9.0-alpha3.jar
SuccessExitStatus=143
 
[Install]
WantedBy=multi-user.target

sudo systemctl enable hume-alerting-operator.service
service hume-alerting-operator start
journalctl -u hume-alerting-operator -f

# Miscellaneous

# Securing connection to Postgres with SSL

Edit the Postgres server configuration block for SSL

sudo vim /var/lib/pgsql/12/data/postgresql.conf
# update the following block to:
ssl = on
#ssl_ca_file = ''
ssl_cert_file = 'server.crt'
#ssl_crl_file = ''
ssl_key_file = 'server.key'
ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
#ssl_prefer_server_ciphers = on
#ssl_ecdh_curve = 'prime256v1'
ssl_min_protocol_version = 'TLSv1.2'
#ssl_max_protocol_version = ''
#ssl_dh_params_file = ''
#ssl_passphrase_command = ''
#ssl_passphrase_command_supports_reload = off

Copy the certificates in the directories needed for Postgres and set the permissions :

sudo cp /opt/hume/security/test-vm.crt /var/lib/pgsql/12/data/server.crt
sudo cp /opt/hume/security/test-vm.key /var/lib/pgsql/12/data/server.key
sudo chown postgres: /var/lib/pgsql/12/data/server.key
sudo chown postgres: /var/lib/pgsql/12/data/server.crt
sudo chmod 400 /var/lib/pgsql/12/data/server.key
sudo chmod 400 /var/lib/pgsql/12/data/server.crt

Restart the Postgres server

sudo systemctl restart postgresql-12

# Keycloak transaction timeout

Large transactional operations such as synchronization of large LDAP structures, the default transaction timeout might be too small.

You can change it with the command line :

sudo su hume
cd /opt/hume/keycloak-${VERSION}
./bin/jboss-cli.sh
connect
/subsystem=transactions:write-attribute(name=default-timeout,value=10000)
CTRL-D

# Securing sensitive values

Some values, such as password of databases or access keys of s3 buckets need to not be as secure as possible, at rest and in transit.

Such values need to be configured as Ecosystem Variables, where the administrator can opt-in for encryption of the value.

The method of encryption can be configured in the hume-api application.yml. The following section describe how the Keystore encryption method works and how to configure it.

# Keystore Encryption method

With the Keystore security enabled, every sensitive value will be stored encrypted into the Core API database, with an AES algorithm, which is a symmetric one; the key to decrypt a secret value can hence be stored (securely) into the Java Keystore: and, once again, to reveal the content of the secret key, we will need to know the Keystore password, which must be held in a place as much secure as possible.

In the following diagram it's depicted what happens behind the scenes when a secured ecosystem variable is being saved into Core API DB.

foo

As you can see, the Keystore provides the Secret Key to Core API, which has the responsibility to encrypt the value with that key as salt and store it into its database.

WARNING

No value in clear text has been persisted during this stage.

On the other hand, at some point we will need to decrypt a given value. It could be the case of Orchestra, which receives the encrypted value of our Neo4j password, together with the algorithm used to cipher the value. Orchestra, in turn, having the same configuration of Core API, will be able to query the Keystore: from this query we will get the secret key which is required to decrypt the value of the above mentioned password.

Please, check the diagram below out to understand all the flow of info among Core API, Orchestra and Java Keyestore.

foo

# How to enable Java Keystore

To enable Java Keystore to store and serve securely the symmetric secret key to be used while encrypting and decrypting encoded values (like Ecosystem Variables), the following steps are required.

  1. Insert the secret key into Java Keystore
  2. Configure Core API and Orchestra for using keystore
# Insert the secret key into Java Keystore

Let's assume that we're creating an entry named secret and that the keystore password for this entry is changeit

keytool -genseckey \
 -alias secret \
  -keyalg AES \
 -keysize 256 \
 -keystore hume-keystore \
 -storepass changeit \
 -storetype PKCS12 \
 -v
# Configure Core API and Orchestra for using keystore

In order to make API and Orchestra able to retrieve the secret key from Keystore, it's required to add the following entries in their respective application.yml

hume:
  security:
  ...
    encryption:
      engine: keystore
      keystore:
        file: /opt/hume/security/hume-keystore
        password: changeit
        secret:
          alias: secret
  ...

where:

  • file is the absolute path of the hume-keystore file previously created
  • alias is the name of the secret key previously stored
  • password is required for getting the secret key value from the Keystore

# Installing the NLP Ecosystem

Start by downloading the packages, containing :

  • Hume Gateway Service
  • Hume Discovery Service
  • Hume Entity Extraction Service
  • Hume Keyword Extraction Service
sudo su hume
cd /opt/hume
wget https://downloads.graphaware.com/graphaware-hume-nlp-2.5.0.zip
unzip graphaware-hume-nlp-2.5.0.zip

# Install the Discovery Service

sudo su hume
mkdir discovery
cp graphaware-hume-nlp-2.5.0/hume-cloud-discovery.jar ./discovery
cd discovery

Create the configuration file :

vi application.yml

And paste the following content

server:
  ssl:
    key-store: /opt/hume/security/hume-keystore
    key-store-type: pkcs12
    key-store-password: changeit
    key-alias: server
  port: 8761
security:
  require-ssl: true

Create a systemd service

sudo su
vi /etc/systemd/system/hume-discovery.service

And paste the following :

[Unit]
Description=Hume Discovery
After=syslog.target
 
[Service]
User=hume
WorkingDirectory=/opt/hume/discovery
ExecStart=/usr/bin/java -Djava.net.preferIPv4Stack=true -jar hume-cloud-discovery.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

And start it

sudo su
systemctl enable hume-discovery.service
systemctl start hume-discovery.service
journalctl -u hume-discovery.service -f

# Install the Entity Extraction Service

sudo su hume
mkdir annotation
cp graphaware-hume-nlp-2.5.0/hume-annotation-service.jar ./annotation
cd annotation

Create the configuration file :

vi application.yml

And paste the following content

server:
  tomcat:
    max-connections: 4
  servlet:
    context-path: "/"
  ssl:
    key-store: /opt/hume/security/hume-keystore
    key-store-type: pkcs12
    key-store-password: changeit
    key-alias: server
  port: 8085
security:
  require-ssl: true

hume:
  cloud:
    enabled: true
spring:
  application:
    name: annotation-service
  cloud:
    service-registry:
      auto-registration:
        enabled: true
eureka:
  client:
    securePortEnabled: true
    service-url:
      defaultZone: https://localhost:8761/eureka
  instance:
    nonSecurePortEnabled: false
    securePortEnabled: true
    securePort: ${server.port}
    statusPageUrl: https://localhost:${server.port}/info
    healthCheckUrl: https://localhost:${server.port}/health
    homePageUrl: https://localhost:${server.port}
    preferIpAddress: true

Create a systemd service

sudo su
vi /etc/systemd/system/hume-annotation.service

And paste the following :

[Unit]
Description=Hume Entity Extraction
After=syslog.target
 
[Service]
User=hume
WorkingDirectory=/opt/hume/annotation
ExecStart=/usr/bin/java -Djava.net.preferIPv4Stack=true -jar hume-annotation-service.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

And start it

sudo su
systemctl enable hume-annotation.service
systemctl start hume-annotation.service
journalctl -u hume-annotation.service -f

# Install the Keyword Extraction Service

sudo su hume
mkdir textrank
cp graphaware-hume-nlp-2.5.0/hume-textrank-web.jar ./textrank
cd textrank

Create the configuration file :

vi application.yml

And paste the following content

server:
  servlet:
    context-path: "/"
  ssl:
    key-store: /opt/hume/security/hume-keystore
    key-store-type: pkcs12
    key-store-password: changeit
    key-alias: server
  port: 8086
security:
  require-ssl: true

hume:
  cloud:
    enabled: true
spring:
  application:
    name: textrank-service
  cloud:
    service-registry:
      auto-registration:
        enabled: true
eureka:
  client:
    securePortEnabled: true
    service-url:
      defaultZone: https://localhost:8761/eureka
  instance:
    nonSecurePortEnabled: false
    securePortEnabled: true
    securePort: ${server.port}
    statusPageUrl: https://localhost:${server.port}/info
    healthCheckUrl: https://localhost:${server.port}/health
    homePageUrl: https://localhost:${server.port}
    preferIpAddress: true

TIP

Replace instances of localhost with your hostname.

Create a systemd service

sudo su
vi /etc/systemd/system/hume-textrank.service

And paste the following :

[Unit]
Description=Hume Keyword Extraction
After=syslog.target
 
[Service]
User=hume
WorkingDirectory=/opt/hume/textrank
ExecStart=/usr/bin/java -Djava.net.preferIPv4Stack=true -jar hume-textrank-web.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

And start it

sudo su
systemctl enable hume-textrank.service
systemctl start hume-textrank.service
journalctl -u hume-textrank.service -f

# Install the Gateway Service

sudo su hume
mkdir gateway
cp graphaware-hume-nlp-2.5.0/hume-cloud-gateway.jar ./gateway
cd gateway

Create the configuration file :

vi application.yml

And paste the following content

server:
  ssl:
    enabled: true
    key-store: /opt/hume/security/hume-keystore
    key-store-type: "pkcs12"
    key-store-password: changeit
    key-alias: "server"
  port: "10000"
eureka:
  client:
    register-with-eureka: false
    service-url:
        defaultZone: https://localhost:8761/eureka

TIP

Replace localhost in the defaultZone with the host name of where the discovery service is.

Create a systemd service

sudo su
vi /etc/systemd/system/hume-gateway.service

And paste the following :

[Unit]
Description=Hume Gateway
After=syslog.target
 
[Service]
User=hume
WorkingDirectory=/opt/hume/gateway
ExecStart=/usr/bin/java -Djava.net.preferIPv4Stack=true -jar hume-cloud-gateway.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

And start it

sudo su
systemctl enable hume-gateway.service
systemctl start hume-gateway.service
journalctl -u hume-gateway.service -f

Test the connection between the gateway, discovery and annotation service :

curl -X POST https://localhost:10000/annotation-service/annotate -H 'Content-Type: application/json' -d '{"text": "Barach Obama is born in Hawai", "pipeline": "default"}'

# Installing PDF parser

Start by downloading the package.

sudo su hume
cd /opt/hume
wget https://downloads.graphaware.com/graphaware-hume-tika-pdf-1.0.0.zip
unzip graphaware-hume-tika-pdf-1.0.0.zip

# Install the PDF Parser Service

sudo su hume
cd /opt/hume
mkdir tika-pdf
cp graphaware-hume-tika-pdf-1.0.0/hume-tika-pdf.jar ./tika-pdf
cd tika-pdf

Create the configuration file :

vi application.yml

And paste the following content

hume:
  cloud:
   enabled: true
spring:
  application:
    name: tika-pdf
  cloud:
   service-registry:
     auto-registration:
       enabled: true
  servlet:
   multipart:
     max-file-size: 16MB
     max-request-size: 16MB
eureka:
  client:
    securePortEnabled: true
    service-url:
      defaultZone: https://localhost:8761/eureka
  instance:
    nonSecurePortEnabled: false
    securePortEnabled: true
    securePort: ${server.port}
    preferIpAddress: true
server:
  ssl:
    enabled: true
    key-store: /opt/hume/security/hume-keystore
    key-store-type: "pkcs12"
    key-store-password: changeit
    key-alias: "server"
  port: 8089

Create a systemd service

sudo su
vi /etc/systemd/system/hume-tika-pdf.service

And paste the following :

[Unit]
Description=Hume Tika PDF parser
After=syslog.target

[Service]
User=hume
WorkingDirectory=/opt/hume/tika-pdf
ExecStart=/usr/bin/java -Djava.net.preferIPv4Stack=true -jar hume-tika-pdf.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

And start it

sudo su
systemctl enable hume-tika-pdf.service
systemctl start hume-tika-pdf.service
journalctl -u hume-tika-pdf.service -f

# Add OCR support

Tika supports OCR of PDF through the tesseract command line tool.

To enable the Tika's OCR capability install the tesseract cli application:

sudo yum install tesseract

Test tesseract availability and version:

tesseract -v
#tesseract 3.04.00
# leptonica-1.72
#  libgif 4.1.6(?) : libjpeg 6b (libjpeg-turbo 1.2.90) : libpng 1.5.13 : libtiff 4.0.3 : zlib 1.2.7 : libwebp 0.3.0

# Test the service through the gateway:

curl -F file=@some-file.pdf http://localhost:10000/tika-pdf/parse

# Appendix A : Environment Variables

In order to avoid to use passwords and/or other variables in your application.yml or application.properties files, it is recommended to use environment variables at the systemd level.

To do so, you will need to override the systemd service file and add a section with the environment.

For example, in order to set as environment variable the neo4j service account password for Orchestra, you will do the following :

# Create the systemd service override

sudo su
systemctl edit hume-orchestra

it will open the editor (vim or nano) amd you will insert the following content :

[Service]
Environment="NEO4JPASS=sup3rS3cr3tPassw0rd"

Save the file and restart the orchestra service.

service hume-orchestra restart

When configuring a resource, you can now use ${NEO4JPASS} instead of the real value in the password field.

::: info The naming for referencing environment variables is ${ENV_VARIABLE_NAME} :::

You can also use environment variables in the application.yml files of your services. For example, to use an environment variable created as above but with the key PGSQLPASS for the hume-api service, you can inject it in the application.yml config like this :

spring:
  datasource:
    url: "jdbc:postgresql://localhost:5432/hume"
    username: hume
    password: ${PGSQLPASS}