Repository: apache/airavata-custos (language: python)

Issue:
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.
Writing ansible scripts to deploy Custos
As part of the Custos baremetal deployment effort - we need to write ansible scripts to configure and automate deployments.


Discussion / hints:

Fix patch:
diff --git a/ansible/.gitignore b/ansible/.gitignore
new file mode 100644
index 000000000..fffbb8241
--- /dev/null
+++ b/ansible/.gitignore
@@ -0,0 +1,1 @@
+ENV
diff --git a/ansible/README.md b/ansible/README.md
new file mode 100644
index 000000000..58eb0432f
--- /dev/null
+++ b/ansible/README.md
@@ -0,0 +1,157 @@
+# Apache Custos Ansible
+
+Ansible scripts to configure and install Apache Custos pre-requisites and deploy the application on bare-metal web servers. The deployment process is divided into 4 steps - 
+1. [Prerequisites](#prerequisites)
+2. [Initial VM set up](#set-up-vms)
+3. [Generate SSL certificates](#generate-ssl-certificates)
+4. [Deploy application](#deploy-application)
+
+## Prerequisites<a name="prerequisites"/>
+Make sure you have installed all of the following prerequisites on your development machine:
+* Git - [Download & Install Git](https://git-scm.com/downloads). OSX and Linux machines typically have this already installed.
+* Python3 - [Download and Install Python3](https://www.python.org/downloads/). You can also use your system's package manager to install the latest stable version of python3.
+
+Note: the following assumes a Bash shell.
+
+Verify if git was installed successfully.
+```bash
+git --version
+```
+Verify if python3 was installed successfully.
+```bash
+python3 --version
+```
+Clone Custos git repo and switch branch.
+```bash
+git clone https://github.com/abhinav7sinha/airavata-custos.git
+cd airavata-custos
+git switch ansible-baremetal
+```
+Create a virtual environment in the ansible directory
+```bash
+cd ansible
+python3 -m venv ENV
+```
+Activate the virtual environment. (You'll need to do this each time before using ansible commands)
+```bash
+source ENV/bin/activate
+```
+The requirements.txt file contains ansible and any other dependencies. Install it by running the following command:
+```bash
+pip install -r requirements.txt
+```
+## Set up VMs<a name="set-up-vms"/>
+You will need 3 Linux VMs (Preferably Ubuntu 20.04) for Custos Deployment. Make sure you have registered domain names for each of them.
+* _VM #1_: for hosting **Keycloak**
+* _VM #2_: for hosting **Hashicorp Vault** and **Consul**
+* _VM #3_: for hosting **Custos Spring Boot application**.
+
+### Configure Ansible vars with VM details
+Now, you need to configure Ansible vars with the domain names of these VMs so that ansible knows where to install custos dependencies.
+
+Open the file `test/group_vars/all/vars.yml`. Look for `keycloak_domain`, `hashicorp_domain` and `custos_domain` variables. Set these variables with their respective domain names. For ex:
+```yml
+⋮
+# Domain names for VMs
+keycloak_domain: my-keycloak-domain.com
+hashicorp_domain: my-hashicorp-domain.com
+custos_domain: my-custos-domain.com
+⋮
+```
+Ansible connects to these VMs using `ssh`. To allow ansible to do this, you will also need to provide it with ssh passwords for these VMs. To maintain security, these passwords cannot be exposed in plaintext. You can make use of ansible's `ansible-vault` command to encrypt these password strings.
+
+Use the following command to encrypt any string:
+```bash
+ansible-vault encrypt_string "<mysecurepassword>" --ask-vault-pass
+```
+Ansible will ask you to set up a new vault password everytime you run this command. Make sure to use the same password everytime.
+
+In the file `test/group_vars/all/vars.yml`. Look for `keycloak_ssh_password`, `hashicorp_ssh_password` and `custos_ssh_password` variables. Set these variables with their respective encrypted password strings. For ex:
+```yml
+⋮
+keycloak_ssh_password: !vault |
+  $ANSIBLE_VAULT;1.1;AES256
+  36363039363662616335356566613665346161396138303131616334616666623361633765356434
+  3234326462633763636...43161313064
+hashicorp_ssh_password: !vault |
+  $ANSIBLE_VAULT;1.1;AES256
+  62633531346536643234303565373639626464326135653732323266396335353166346132383230
+  3333316665623861326...462353738656662
+custos_ssh_password: !vault |
+  $ANSIBLE_VAULT;1.1;AES256
+  643562326362326461334303565373639626464326135653732323266396335353166346132383230
+  3333316665623861326...065626463633330
+⋮
+```
+Now that you've configured the ssh user and password details for your VMs, we can install nginx on each of these servers at once by running the following command:
+```bash
+ansible-playbook -i inventories/test/ env_setup.yml --ask-vault-pass
+```
+Enter the Vault Password (that you set up while encrypting your ssh password strings) when prompted by ansible.
+
+## Generate SSL certificates<a name="generate-ssl-certificates"/>
+The `env_setup.yml` playbook installed `certbot` along with `nginx` in your VMs. **Certbot** helps manage letsencrypt SSL certificates. You need to generate SSL certs for each of your 3 VMs.
+
+### Generate letsencrypt certificates
+SSH into your VMs with your user:
+```bash
+ssh <myuser>@<my-domain.com>
+```
+Run the following command:
+```bash
+sudo certbot --nginx -d <my-domain.com> -m <myemail@gmail.com> --agree-tos --no-eff-email --redirect
+```
+Certbot generates a cert file (`fullchain.pem`) and a keyfile (`privkey.pem`) in the following location in your VM - `/etc/letsencrypt/live/<my-domain.com>/`
+
+### Generate pkcs12 certs from pem files
+Run the following commands to generate pkcs12 truststore files from you cert and key files. You will be asked to create a password for the pkcs12 file, keep the password in a safe location.
+
+In the hashicorp VM:
+```bash
+openssl pkcs12 -export -out certs/vault-client-truststore.pkcs12 -inkey /etc/letsencrypt/live/<my-hashicorp-domain.com>/privkey.pem -in /etc/letsencrypt/live/<my-hashicorp-domain.com>/fullchain.pem
+```
+In the keycloak VM:
+```bash
+openssl pkcs12 -export -out certs/keycloak-client-truststore.pkcs12 -inkey /etc/letsencrypt/live/<my-keycloak-domain.com>/privkey.pem -in /etc/letsencrypt/live/<my-keycloak-domain.com>/fullchain.pem
+```
+Now, you need to add the pkcs12 passwords in the ansible vars.
+
+Encrypt the passwords using `ansible-vault` just like you did for the ssh passwords. Make sure you still use the same vault password as before. In the file `test/group_vars/all/vars.yml`. Look for `hashicorp_pkcs12_passphrase` and `keycloak_pkcs12_passphrase` variables. Set these variables with their respective encrypted password strings. For ex:
+```yml
+⋮
+# pkcs12 passwords
+hashicorp_pkcs12_passphrase: !vault |
+  $ANSIBLE_VAULT;1.1;AES256
+  65646665313232613265363038633662393438376265663363333434303361656565653763313539
+  393735653837326...537
+keycloak_pkcs12_passphrase: !vault |
+  $ANSIBLE_VAULT;1.1;AES256
+  63303962613033353165646639633338306538666233363735393266386432376663656536633663
+  62313163333631...831303961
+⋮
+```
+
+## Deploy application<a name="deploy-application"/>
+You're just one step away from deploying Custos. The following command runs the ansible playbook `custos.yml` which has roles to install all dependencies and deploy Custos on the given VM.
+```bash
+ansible-playbook -i inventories/test/ custos.yml --ask-vault-pass
+```
+Check if custos core and integration services are up and running using the following commands:
+```bash
+systemctl status intcustos
+```
+```bash
+systemctl status corecustos
+```
+
+## Useful commands
+- Deploy Custos with verbose option for debug messages:
+```bash
+ansible-playbook -i inventories/{inventory}/ custos.yml --ask-vault-pass -vvv
+```
+Adding multiple -v will increase the verbosity, the builtin plugins currently evaluate up to -vvvvvv. A reasonable level to start is -vvv, connection debugging might require -vvvv.
+- Decrypt ansible-vault strings
+```bash
+ansible all -i inventories/test/ -e '@inventories/test/group_vars/all/vars.yml' --ask-vault-pass -m debug -a 'var=secret_string'
+```
+
diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg
new file mode 100644
index 000000000..dd43d2bfa
--- /dev/null
+++ b/ansible/ansible.cfg
@@ -0,0 +1,2 @@
+[defaults]
+host_key_checking = false
diff --git a/ansible/custos.yml b/ansible/custos.yml
new file mode 100644
index 000000000..9a2725bd9
--- /dev/null
+++ b/ansible/custos.yml
@@ -0,0 +1,37 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- hosts: hashicorp
+  roles:
+    - nginx
+    - vault
+    - consul
+- hosts: keycloak
+  roles:
+    - nginx
+    - keycloak
+- hosts: custos
+  roles:
+    - nginx
+    - database
+    - zookeeper
+    - kafka
+    - custos
\ No newline at end of file
diff --git a/ansible/requirements.txt b/ansible/requirements.txt
new file mode 100644
index 000000000..a1fb8c0c5
--- /dev/null
+++ b/ansible/requirements.txt
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+ansible~=3.4.0
diff --git a/ansible/roles/consul/handlers/main.yml b/ansible/roles/consul/handlers/main.yml
new file mode 100644
index 000000000..a5af7c8c5
--- /dev/null
+++ b/ansible/roles/consul/handlers/main.yml
@@ -0,0 +1,28 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+# handlers file for consul-server
+- name: restart consul
+  systemd:
+    name: consul.service
+    daemon_reload: yes
+    state: restarted
+  become: yes
diff --git a/ansible/roles/consul/tasks/main.yml b/ansible/roles/consul/tasks/main.yml
new file mode 100644
index 000000000..bf7a9db7f
--- /dev/null
+++ b/ansible/roles/consul/tasks/main.yml
@@ -0,0 +1,64 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: get consul zip
+  get_url:
+    dest: "/etc/{{ consul_zip_file }}"
+    url: "https://releases.hashicorp.com/consul/{{ consul_version }}/{{ consul_zip_file }}"
+  become: yes
+
+- name: ensure unzip present
+  apt:
+    name: unzip
+    update_cache: yes
+  become: yes
+
+- name: place unzipped consul on path
+  unarchive:
+    src: "/etc/{{ consul_zip_file }}"
+    dest: "{{ consul_install_dir }}"
+    remote_src: yes
+  become: yes
+
+- name: ensure directories for data and config exists
+  file:
+    path: "{{ item }}"
+    state: directory
+  with_items:
+    - "{{ consul_config_dir }}"
+    - "{{ consul_data_dir }}"
+  become: yes
+
+- name: send consul configuration file
+  template:
+    dest: "{{ consul_config_dir }}/config.json"
+    src: consul.config.j2
+  notify: restart consul
+  become: yes
+
+- name: ensure consul service file exists
+  template:
+    dest: /etc/systemd/system/consul.service
+    src: consul.service.j2
+    force: yes
+    mode: 0644
+  notify: restart consul
+  become: yes
\ No newline at end of file
diff --git a/ansible/roles/consul/templates/consul.config.j2 b/ansible/roles/consul/templates/consul.config.j2
new file mode 100644
index 000000000..aba819526
--- /dev/null
+++ b/ansible/roles/consul/templates/consul.config.j2
@@ -0,0 +1,14 @@
+{
+    "node_name": "example",
+    "addresses": {
+        "http": "{{ ansible_facts['all_ipv4_addresses'] | last }} 127.0.0.1"
+    },
+    "server": true,
+    "advertise_addr": "{{ ansible_facts['all_ipv4_addresses'] | last }}",
+    "client_addr": "127.0.0.1 {{ ansible_facts['all_ipv4_addresses'] | last }}",
+    "connect": {
+        "enabled": true
+    },
+    "data_dir": "{{ consul_data_dir }}",
+    "bootstrap": true
+}
\ No newline at end of file
diff --git a/ansible/roles/consul/templates/consul.service.j2 b/ansible/roles/consul/templates/consul.service.j2
new file mode 100644
index 000000000..b0a4e399b
--- /dev/null
+++ b/ansible/roles/consul/templates/consul.service.j2
@@ -0,0 +1,10 @@
+[Unit]
+Description=solo consul server example
+
+[Service]
+WorkingDirectory={{ consul_config_dir }}
+User=root
+ExecStart={{ consul_install_dir }}/consul agent -config-dir={{ consul_config_dir }}
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/ansible/roles/custos/handlers/main.yml b/ansible/roles/custos/handlers/main.yml
new file mode 100644
index 000000000..f85fc12cb
--- /dev/null
+++ b/ansible/roles/custos/handlers/main.yml
@@ -0,0 +1,21 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
\ No newline at end of file
diff --git a/ansible/roles/custos/tasks/main.yml b/ansible/roles/custos/tasks/main.yml
new file mode 100644
index 000000000..73ec4d76c
--- /dev/null
+++ b/ansible/roles/custos/tasks/main.yml
@@ -0,0 +1,122 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: Install Custos pre-requisites (Debian)
+  apt: name={{ item }} state=latest update_cache=yes
+  with_items:
+    - maven
+  become: yes
+  when: ansible_os_family == "Debian"
+
+- name: Copy hashicorp and keycloak truststore files
+  copy:
+    src: "{{ custos_source_dir }}/custos-core-services-server/src/main/dist/conf/{{ item }}"
+    dest: /home/ubuntu/{{ item }}
+    remote_src: yes
+  with_items:
+    - keycloak-client-truststore.pkcs12
+    - vault-client-truststore.pkcs12
+  become: yes
+
+- name: Create Custos deployment directory {{ custos_deployment_dir }}
+  become: yes
+  file: path={{ custos_deployment_dir }}
+    state=directory
+    mode=0755
+    owner={{ user }}
+    group={{ group }}
+
+- name: Create Custos source directory
+  become: yes
+  file: path={{ custos_source_dir }}
+    state=directory
+    mode=0755
+    owner={{ user }}
+    group={{ group }}
+
+- name: git checkout from Custos github repo {{ custos_repo }} branch {{ custos_git_branch }}
+  git: repo="{{ custos_repo }}"
+    dest="{{ custos_source_dir }}"
+    version="{{ custos_git_branch }}"
+  register: checkout
+  tags: update
+  become: yes
+  become_user: "{{ user }}"
+
+- name: Run Custos maven build
+  command: mvn clean install -Dmaven.test.skip=true chdir="{{ custos_source_dir }}/"
+  environment:
+    MAVEN_OPTS: "-Xmx2048m"
+  register: build
+  tags: update
+  become: yes
+  become_user: "{{ user }}"
+
+- name: Delete lib directories of the distributions
+  file:
+    state: absent
+    path: "{{ custos_deployment_dir }}/{{ item }}"
+  with_items:
+    - "Custos-Core-Services-Server-{{custos_distribution_version}}/lib"
+    - "Custos-Integration-Services-Server-{{custos_distribution_version}}/lib"
+  become: yes
+  become_user: "{{ user }}"
+  ignore_errors: yes
+
+- name: Copy Custos distributions to Custos deployment directory
+  unarchive: "src={{ custos_source_dir }}/{{ item }}
+              dest={{ custos_deployment_dir }}/ copy=no"
+  with_items:
+    - "custos-core-services-server/target/Custos-Core-Services-Server-{{custos_distribution_version}}-bin.zip"
+    - "custos-integration-services-server/target/Custos-Integration-Services-Server-{{custos_distribution_version}}-bin.zip"
+  become: yes
+  become_user: "{{ user }}"
+
+- name: Copy Custos property files
+  template: "src={{ item.name }}
+            dest={{ custos_deployment_dir }}/{{ item.dir }}/conf/{{ item.target }}
+            owner={{ user }}
+            group={{ group }}
+            mode=\"u=rw,g=r,o=r\""
+  with_items:
+    - { name: custos-core-services/application.properties.j2,
+        dir: "Custos-Core-Services-Server-{{custos_distribution_version}}",
+        target: application.properties}
+    - { name: custos-core-services/bootstrap.properties.j2,
+        dir: "Custos-Core-Services-Server-{{custos_distribution_version}}",
+        target: bootstrap.properties }
+    - { name: custos-integration-services/application.properties.j2,
+        dir: "Custos-Integration-Services-Server-{{custos_distribution_version}}",
+        target: application.properties }
+  become: yes
+  become_user: "{{ user }}"
+
+- name: Start Custos Core service
+  service:
+    name: corecustos
+    state: restarted
+  become: yes
+
+- name: Start Custos Integration service
+  service:
+    name: intcustos
+    state: restarted
+  become: yes
diff --git a/ansible/roles/custos/templates/custos-core-services/application.properties.j2 b/ansible/roles/custos/templates/custos-core-services/application.properties.j2
new file mode 100644
index 000000000..a8ef9615d
--- /dev/null
+++ b/ansible/roles/custos/templates/custos-core-services/application.properties.j2
@@ -0,0 +1,88 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+#
+
+grpc.port={{ custos_core_grpc_port }}
+server.port={{ custos_core_server_port }}
+##spring.zipkin.baseUrl={{ custos_core_spring_zipkin_baseUrl }}
+spring.application.name={{ custos_core_spring_app_name }}
+##spring.sleuth.sampler.probability={{ custos_core_spring_sleuth_sampler_probability }}
+spring.main.allow-bean-definition-overriding={{ custos_core_spring_main_allow_bean_definition_overriding }}
+management.security.enabled={{ custos_core_management_security_enabled }}
+management.endpoints.web.exposure.include={{ custos_core_management_endpoints_web_exposure_include }}
+management.endpoint.metrics.enabled={{ custos_core_management_endpoint_metrics_enabled }}
+spring.jmx.enabled={{ custos_core_spring_jmx_enabled }}
+
+spring.datasource.url = {{ custos_core_spring_datasource_url }}
+spring.datasource.username = {{ custos_core_spring_datasource_username }}
+spring.datasource.password = {{ custos_core_spring_datasource_password }}
+
+## Hibernate Properties
+# The SQL dialect makes Hibernate generate better SQL for the chosen database
+spring.jpa.properties.hibernate.dialect = {{ custos_core_spring_jpa_properties_hibernate_dialect }}
+spring.jpa.properties.hibernate.enable_lazy_load_no_trans={{ custos_core_spring_jpa_properties_hibernate_enable_lazy_load_no_trans }}
+# Hibernate ddl auto (create, create-drop, validate, update)
+spring.jpa.hibernate.ddl-auto = {{ custos_core_spring_jpa_hibernate_ddl_auto }}
+spring.profiles.active={{ custos_core_spring_profiles_active }}
+logging.level.root={{ custos_core_logging_level_root }}
+
+ciLogon.admin.client.id={{ custos_core_ciLogon_admin_client_id }}
+ciLogon.admin.client.secret={{ custos_core_ciLogon_admin_client_secret }}
+ciLogon.admin.auth.endpoint={{ custos_core_ciLogon_admin_auth_endpoint }}
+
+iam.server.client.id={{ custos_core_iam_server_client_id }}
+iam.server.truststore.path={{ custos_core_iam_server_truststore_path }}
+iam.server.truststore.password={{ custos_core_iam_server_truststore_password }}
+iam.server.url={{ custos_core_iam_server_url }}
+iam.server.admin.username={{ custos_core_iam_server_admin_username }}
+iam.server.admin.password={{ custos_core_iam_server_admin_password }}
+iam.server.super.admin.realm.id={{ custos_core_iam_server_super_admin_realm_id }}
+iam.federated.cilogon.authorization.endpoint={{ custos_core_iam_federated_cilogon_authorization_endpoint }}
+iam.federated.cilogon.token.endpoint={{ custos_core_iam_federated_cilogon_token_endpoint }}
+iam.federated.cilogon.token.userinfo.endpoint={{ custos_core_iam_federated_cilogon_token_userinfo_endpoint }}
+iam.federated.cilogon.issuer={{ custos_core_iam_federated_cilogon_issuer }}
+iam.federated.cilogon.jwksUri={{ custos_core_iam_federated_cilogon_jwksUri }}
+introspection.endpoint={{ custos_core_introspection_endpoint }}
+issuer={{ custos_core_issuer }}
+authorization.endpoint={{ custos_core_authorization_endpoint }}
+token.endpoint={{ custos_core_token_endpoint }}
+end.session.endpoint={{ custos_core_end_session_endpoint }}
+user.info.endpoint={{ custos_core_user_info_endpoint }}
+jwks_uri={{ custos_core_jwks_uri }}
+registration.endpoint={{ custos_core_registration_endpoint }}
+cluster.management.core.service.dns.name={{ custos_core_cluster_management_core_service_dns_name }}
+cluster.management.core.service.port={{ custos_core_cluster_management_core_service_port }}
+
+core.services.server.hostname={{ custos_core_services_server_hostname }}
+core.services.server.port={{ custos_core_services_server_port }}
+
+custos.identity.auth.cache.enabled={{ custos_core_custos_identity_auth_cache_enabled }}
+custos.identity.auth.cache.size={{ custos_core_custos_identity_auth_cache_size }}
+
+core.messaging.service.broker.url={{ custos_core_core_messaging_service_broker_url }}
+core.messaging.service.publisher.id={{ custos_core_core_messaging_service_publisher_id }}
+mail.smtp.auth={{ custos_core_mail_smtp_auth }}
+mail.smtp.starttls.enable={{ custos_core_mail_smtp_starttls_enable }}
+mail.smtp.host={{ custos_core_mail_smtp_host }}
+mail.smtp.port={{ custos_core_mail_smtp_port }}
+mail.smtp.ssl.trust={{ custos_core_mail_smtp_ssl_trust }}
+mail.sender.username={{ custos_core_mail_sender_username }}
+mail.sender.password={{ custos_core_mail_sender_password }}
+
+user.profile.core.service.dns.name={{ custos_core_user_profile_core_service_dns_name }}
+user.profile.core.service.port={{ custos_core_user_profile_core_service_port }}
diff --git a/ansible/roles/custos/templates/custos-core-services/bootstrap.properties.j2 b/ansible/roles/custos/templates/custos-core-services/bootstrap.properties.j2
new file mode 100644
index 000000000..46b31a72f
--- /dev/null
+++ b/ansible/roles/custos/templates/custos-core-services/bootstrap.properties.j2
@@ -0,0 +1,26 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+#  specific language governing permissions and limitations
+#  under the License
+
+spring.cloud.vault.token={{ vault_token }}
+spring.cloud.vault.scheme={{ vault_scheme }}
+spring.cloud.vault.host={{ vault_host }}
+spring.cloud.vault.port={{ vault_port }}
+spring.cloud.vault.uri={{ vault_uri }}
+spring.cloud.vault.authentication={{ spring_cloud_vault_authentication }}
+spring.cloud.vault.ssl.trust-store= {{ spring_cloud_vault_ssl_trust_store }}
+spring.cloud.vault.ssl.trust-store-password={{ spring_cloud_vault_ssl_truststore_password }}
diff --git a/ansible/roles/custos/templates/custos-core-services/config.yml.j2 b/ansible/roles/custos/templates/custos-core-services/config.yml.j2
new file mode 100644
index 000000000..e69de29bb
diff --git a/ansible/roles/custos/templates/custos-integration-services/application.properties.j2 b/ansible/roles/custos/templates/custos-integration-services/application.properties.j2
new file mode 100644
index 000000000..655d60a6d
--- /dev/null
+++ b/ansible/roles/custos/templates/custos-integration-services/application.properties.j2
@@ -0,0 +1,37 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+#
+
+grpc.port={{ custos_int_grpc_port }}
+server.port={{ custos_int_server_port }}
+##spring.zipkin.baseUrl={{ custos_int_spring_zipkin_baseUrl }}
+spring.application.name={{ custos_int_spring_application_name }}
+##spring.sleuth.sampler.probability={{ custos_int_spring_sleuth_sampler_probability }}
+spring.main.allow-bean-definition-overriding={{ custos_int_spring_main_allow_bean_definition_overriding }}
+management.security.enabled={{ custos_int_management_security_enabled }}
+management.endpoints.web.exposure.include={{ custos_int_management_endpoints_web_exposure_include }}
+management.endpoint.metrics.enabled={{ custos_int_management_endpoint_metrics_enabled }}
+spring.jmx.enabled={{ custos_int_spring_jmx_enabled }}
+
+spring.profiles.active={{ custos_int_spring_profiles_active }}
+logging.level.root={{ custos_int_logging_level_root }}
+
+core.services.server.port={{ custos_int_core_services_server_port }}
+core.services.server.hostname={{ custos_int_core_services_server_hostname }}
+iam.server.url={{ custos_int_iam_server_url }}
+tenant.base.uri={{ custos_int_tenant_base_uri }}
\ No newline at end of file
diff --git a/ansible/roles/custos/templates/custos-integration-services/config.yml.j2 b/ansible/roles/custos/templates/custos-integration-services/config.yml.j2
new file mode 100644
index 000000000..e69de29bb
diff --git a/ansible/roles/database/defaults/main.yml b/ansible/roles/database/defaults/main.yml
new file mode 100644
index 000000000..5333f25ea
--- /dev/null
+++ b/ansible/roles/database/defaults/main.yml
@@ -0,0 +1,19 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
diff --git a/ansible/roles/database/handlers/main.yml b/ansible/roles/database/handlers/main.yml
new file mode 100644
index 000000000..d48aa97da
--- /dev/null
+++ b/ansible/roles/database/handlers/main.yml
@@ -0,0 +1,34 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: start mariadb
+  service: name=mariadb state=started enabled=yes
+  become: yes
+
+- name: stop mariadb
+  service: name=mariadb state=stopped
+  become: yes
+
+- name: restart mariadb
+  service: name=mariadb state=restarted enabled=yes
+  become: yes
+
+...
diff --git a/ansible/roles/database/tasks/create_db.yml b/ansible/roles/database/tasks/create_db.yml
new file mode 100644
index 000000000..cd49503bf
--- /dev/null
+++ b/ansible/roles/database/tasks/create_db.yml
@@ -0,0 +1,28 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+
+- name: Create a new database with name "{{ db_name }}"
+  community.mysql.mysql_db:
+    name: "{{ db_name }}"
+    state: present
+    encoding: "UTF8mb3"
+    collation: "utf8_general_ci"
\ No newline at end of file
diff --git a/ansible/roles/database/tasks/keycloak.yml b/ansible/roles/database/tasks/keycloak.yml
new file mode 100644
index 000000000..396492aa5
--- /dev/null
+++ b/ansible/roles/database/tasks/keycloak.yml
@@ -0,0 +1,38 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+
+# Setup keycloak user and database
+- name: create keycloak database
+  mysql_db: name="keycloak" state=present encoding=utf8
+  when: "'keycloak' in groups"
+
+- name: give access to {{ keycloak_db_username }} from remote
+  mysql_user: name="{{ keycloak_db_username }}" password="{{ keycloak_db_password }}" host="{{ item }}"
+  with_items:
+    - "{{ groups['keycloak'] }}"
+
+- name: create new user {{ keycloak_db_username }} with all privilege
+  mysql_user: name="{{ keycloak_db_username }}"
+              password="{{ keycloak_db_password }}"
+              append_privs=yes
+              host_all=yes
+              priv=keycloak.*:ALL,GRANT state=present
diff --git a/ansible/roles/database/tasks/main.yml b/ansible/roles/database/tasks/main.yml
new file mode 100644
index 000000000..8cc53f76b
--- /dev/null
+++ b/ansible/roles/database/tasks/main.yml
@@ -0,0 +1,74 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: Install MySQL
+  apt:
+    name:
+    - mysql-server
+    - python3-pymysql
+  become: yes
+
+- name: Start the MySQL service
+  service:
+    name: mysql
+    state: started
+    enabled: yes
+
+# 'localhost' needs to be the last item for idempotency, see
+# http://ansible.cc/docs/modules.html#mysql-user
+#- name: update mysql root password for all root accounts
+#  mysql_user: name=root host={{ item }} password={{ custos_core_spring_datasource_password }}
+#  with_items:
+#    - "{{ ansible_hostname }}"
+#    - 127.0.0.1
+#    - ::1
+#    - localhost
+- include: secure_install.yml
+- include: create_db.yml
+#
+#- name: copy .my.cnf file with root password credentials
+##  template: src=templates/root/my.cnf.j2 dest=/root/.my.cnf owner=root mode=0600
+#  copy:
+#    src: templates/my.cnf.j2
+#    dest: /root/.my.cnf
+#    owner: root
+#
+#- name: delete anonymous MySQL server user for $server_hostname
+#  action: mysql_user user="" host="{{ server_hostname }}" state="absent"
+#
+#- name: delete anonymous MySQL server user for localhost
+#  action: mysql_user user="" state="absent"
+#
+#- name: remove the MySQL test database
+#  action: mysql_db db=test state=absent
+
+#- name: Create dynamic MySQL variables.
+#  set_fact:
+#    mysql_users:
+#      - name: mycompany_user
+#        host: "{{groups['database'][0]}}"
+#        password: secret
+#        priv: "*.*:SELECT"
+#      - name: mycompany_user
+#        host: "{{groups['database'][1]}}"
+#        password: secret
+#        priv: "*.*:SELECT"
+#    mysql_replication_master: "{{groups['a4d.lamp.db.1'][0]}}"
diff --git a/ansible/roles/database/tasks/secure_install.yml b/ansible/roles/database/tasks/secure_install.yml
new file mode 100644
index 000000000..619884102
--- /dev/null
+++ b/ansible/roles/database/tasks/secure_install.yml
@@ -0,0 +1,51 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+
+# The following works but its not idemmpotent
+- name: Set password for root user
+  mysql_user:
+    # you can get socket path from /etc/mysql/mysql.conf.d/mysqld.cnf
+    check_implicit_admin: yes
+    login_unix_socket: /var/run/mysqld/mysqld.sock  # default path
+    login_user: root
+    login_password: "{{ custos_core_spring_datasource_password }}"
+    name: root
+    password: "{{ custos_core_spring_datasource_password }}"
+    priv: '*.*:ALL,GRANT'
+    host: 'localhost'
+    state: present
+  become: yes
+
+- name: Copy .my.cnf file
+  template: src=my.cnf.j2 dest="{{ user_home }}/.my.cnf"
+  # become: yes
+
+- name: Removes all anonymous user accounts
+  mysql_user: name='' host_all=yes state=absent login_password="{{ custos_core_spring_datasource_password }}"
+
+- name: Secures the MySQL root user for all hosts
+  mysql_user: user=root login_password="{{ custos_core_spring_datasource_password }}" host_all=yes
+
+- name: Removes the MySQL test database
+  mysql_db: db=test state=absent login_password="{{ custos_core_spring_datasource_password }}"
+
+...
diff --git a/ansible/roles/database/templates/my.cnf.j2 b/ansible/roles/database/templates/my.cnf.j2
new file mode 100644
index 000000000..79d0c8bf6
--- /dev/null
+++ b/ansible/roles/database/templates/my.cnf.j2
@@ -0,0 +1,4 @@
+# Example .my.cnf file for setting the root password
+[client]
+user=root
+password="{{ custos_core_spring_datasource_password }}"
diff --git a/ansible/roles/database/vars/main.yml b/ansible/roles/database/vars/main.yml
new file mode 100644
index 000000000..7fdfe7603
--- /dev/null
+++ b/ansible/roles/database/vars/main.yml
@@ -0,0 +1,44 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+#mysql_packages:
+#  - MariaDB-server
+#  - MariaDB-client
+#
+#mysql_databases:
+#    - "{{ app_catalog }}"
+#    - "{{ exp_catalog }}"
+#    - "{{ replica_catalog }}"
+#    - "{{ workflow_catalog }}"
+#    - "{{ credential_store }}"
+#    - "{{ sharing_catalog }}"
+#    - "{{ profile_service }}"
+#
+#mysql_privs:
+#    - "{{ app_catalog }}.*:ALL"
+#    - "{{ exp_catalog }}.*:ALL"
+#    - "{{ replica_catalog }}.*:ALL"
+#    - "{{ workflow_catalog }}.*:ALL"
+#    - "{{ credential_store }}.*:ALL"
+#    - "{{ sharing_catalog }}.*:ALL"
+#    - "{{ profile_service }}.*:ALL"
+#
+#...
diff --git a/ansible/roles/env_setup/tasks/main.yml b/ansible/roles/env_setup/tasks/main.yml
new file mode 100644
index 000000000..68807666f
--- /dev/null
+++ b/ansible/roles/env_setup/tasks/main.yml
@@ -0,0 +1,30 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- hosts: hashicorp
+  roles:
+    - nginx
+- hosts: keycloak
+  roles:
+    - nginx
+- hosts: custos
+  roles:
+    - nginx
\ No newline at end of file
diff --git a/ansible/roles/kafka/defaults/main.yml b/ansible/roles/kafka/defaults/main.yml
new file mode 100644
index 000000000..0b99e0e38
--- /dev/null
+++ b/ansible/roles/kafka/defaults/main.yml
@@ -0,0 +1,43 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+
+kafka_package_name: "confluent-5.3.1"
+kafka_tgz_url: "http://packages.confluent.io/archive/5.3/confluent-5.3.1-2.12.zip"
+kafka_dir: "{{ custos_deployment_dir }}/{{ kafka_package_name }}"
+kafka_rest_proxy_listener_port: 8082
+
+broker_id: "0"
+network_threads_count: "3"
+io_threads_count: "8"
+socket_send_buf_bytes: "102400"
+socket_receive_buf_bytes: "102400"
+socket_request_max_bytes: "104857600"
+num_partitions: "1"
+num_recovery_threads: "1"
+offsets_topic_replication_fac: "1"
+trans_state_log_replication_fac: "1"
+trans_state_log: "1"
+log_retention_hrs: "168"
+log_segment_bytes: "1073741824"
+log_retention_check_interval: "300000"
+grp_initial_rebalance_delay: "0"
+kafka_listener_port: 9092
diff --git a/ansible/roles/kafka/handlers/main.yml b/ansible/roles/kafka/handlers/main.yml
new file mode 100644
index 000000000..985698998
--- /dev/null
+++ b/ansible/roles/kafka/handlers/main.yml
@@ -0,0 +1,45 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+# Kafka related handlers
+- name: start kafka
+  service: name=kafka state=started enabled=yes
+  become: yes
+
+- name: stop kafka
+  service: name=kafka state=stopped enabled=yes
+  become: yes
+
+- name: restart kafka
+  service: name=kafka state=restarted enabled=yes
+  become: yes
+
+- name: start kafka-rest-proxy
+  service: name=kafka-rest-proxy state=started enabled=yes
+  become: yes
+
+- name: stop kafka-rest-proxy
+  service: name=kafka-rest-proxy state=stopped enabled=yes
+  become: yes
+
+- name: restart kafka-rest-proxy
+  service: name=kafka-rest-proxy state=restarted enabled=yes
+  become: yes
diff --git a/ansible/roles/kafka/tasks/main.yml b/ansible/roles/kafka/tasks/main.yml
new file mode 100644
index 000000000..43fb6f6a5
--- /dev/null
+++ b/ansible/roles/kafka/tasks/main.yml
@@ -0,0 +1,139 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+
+# Check for the availability of the Kafka package
+- name: Check kafka package availability
+  stat: path={{ kafka_dir }}
+  register: kafka_package
+  become: yes
+
+- name: Create deployment directory {{ custos_deployment_dir }}
+  file: path={{custos_deployment_dir}}
+    state=directory
+    mode=0755
+    owner={{ user }}
+    group={{ group }}
+  become: yes
+
+# Download Kafka
+- name: Download and unarchive Kafka from {{ kafka_tgz_url }}
+  unarchive: src="{{ kafka_tgz_url }}"
+    dest="{{ custos_deployment_dir }}"
+    copy=no
+    owner="{{ user }}"
+    group="{{ group }}"
+  when: not kafka_package.stat.exists
+  become: yes
+
+# Create kafka logs directory
+- name: Create kafka logs directory
+  file: path="{{ kafka_dir }}/logs" state=directory owner={{ user }} group={{ group }}
+  become: yes
+
+
+# Config kafka server and start
+- name: Copy kafka server properties file
+  template: src=server.properties.j2
+    dest="{{ kafka_dir }}/etc/kafka/server.properties"
+    owner={{ user }}
+    group={{ group }}
+    mode="u=rw,g=r,o=r"
+#  notify: restart kafka
+  become: yes
+
+# Config rest proxy and start
+- name: Copy kafka rest proxy properties file
+  template: src=kafka-rest.properties.j2
+    dest="{{ kafka_dir }}/etc/kafka-rest/kafka-rest.properties"
+    owner={{ user }}
+    group={{ group }}
+    mode="u=rw,g=r,o=r"
+  become: yes
+
+#- name: uninstall firewalld # install firewalld
+#  apt:
+#    name: firewalld
+#    state: absent #latest
+#  become: yes
+
+#- name: start firewalld #and python-firewall
+#  service: name=firewalld state=started
+#  become: yes
+
+#- name: open kafka proxy port
+#  firewalld:
+#    zone: public
+#    permanent: yes
+#    state: enabled
+#    immediate: yes
+#    rich_rule: rule family=ipv4 source address="{{ item }}" port port="{{ kafka_listener_port }}" protocol=tcp accept
+#  become: yes
+#  with_items:
+#    - "{{ sharing_subnets }}"
+#
+#- name: open kafka rest proxy port
+#  firewalld:
+#    zone: public
+#    permanent: yes
+#    state: enabled
+#    immediate: yes
+#    rich_rule: rule family=ipv4 source address="{{ item }}" port port="{{ kafka_rest_proxy_listener_port }}" protocol=tcp accept
+#  become: yes
+#  with_items:
+#    - "{{ sharing_subnets }}"
+
+- name: systemd install kafka service script
+  template: src=kafka.service.j2
+    dest=/usr/lib/systemd/system/kafka.service
+    owner={{ user }}
+    group={{ group }}
+    mode="u=rw,g=r,o=r"
+#  notify: start kafka
+  become: yes
+
+- name: systemd install kafka rest proxy service script
+  template: src=kafka-rest-proxy.service.j2
+    dest=/usr/lib/systemd/system/kafka-rest-proxy.service
+    owner={{ user }}
+    group={{ group }}
+    mode="u=rw,g=r,o=r"
+  become: yes
+
+- name: Reload systemd daemons
+  command: systemctl daemon-reload
+#  notify: restart kafka
+  become: yes
+
+- name: Reload systemd daemons
+  command: systemctl daemon-reload
+#  notify: restart kafka-rest-proxy
+  become: yes
+
+- name: restart kafka
+  service: name=kafka state=restarted enabled=yes
+  become: yes
+
+- name: restart kafka-rest-proxy
+  service: name=kafka-rest-proxy state=restarted enabled=yes
+  become: yes
+
+...
diff --git a/ansible/roles/kafka/templates/kafka-rest-proxy.service.j2 b/ansible/roles/kafka/templates/kafka-rest-proxy.service.j2
new file mode 100644
index 000000000..338de9f26
--- /dev/null
+++ b/ansible/roles/kafka/templates/kafka-rest-proxy.service.j2
@@ -0,0 +1,14 @@
+# {{ansible_managed}}
+
+[Unit]
+Description=Kafka-Rest-Proxy
+Before=
+After=network.target
+
+[Service]
+LOG_DIR={{ kafka_dir }}/logs
+ExecStart={{ kafka_dir }}/bin/kafka-rest-start {{ kafka_dir }}/etc/kafka-rest/kafka-rest.properties
+Restart=on-abort
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/ansible/roles/kafka/templates/kafka-rest.properties.j2 b/ansible/roles/kafka/templates/kafka-rest.properties.j2
new file mode 100644
index 000000000..a512daa6e
--- /dev/null
+++ b/ansible/roles/kafka/templates/kafka-rest.properties.j2
@@ -0,0 +1,25 @@
+#
+# Copyright 2018 Confluent Inc.
+#
+# Licensed under the Confluent Community License (the "License"); you may not use
+# this file except in compliance with the License.  You may obtain a copy of the
+# License at
+#
+# http://www.confluent.io/confluent-community-license
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OF ANY KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations under the License.
+#
+
+#id=kafka-rest-test-server
+#schema.registry.url=http://localhost:8081
+#zookeeper.connect=localhost:2181
+bootstrap.servers=PLAINTEXT://{{ kafka_url }}
+listeners=http://{{ ansible_default_ipv4.address }}:{{ kafka_rest_proxy_listener_port }}
+#
+# Configure interceptor classes for sending consumer and producer metrics to Confluent Control Center
+# Make sure that monitoring-interceptors-<version>.jar is on the Java class path
+#consumer.interceptor.classes=io.confluent.monitoring.clients.interceptor.MonitoringConsumerInterceptor
+#producer.interceptor.classes=io.confluent.monitoring.clients.interceptor.MonitoringProducerInterceptor
diff --git a/ansible/roles/kafka/templates/kafka.service.j2 b/ansible/roles/kafka/templates/kafka.service.j2
new file mode 100644
index 000000000..afc011854
--- /dev/null
+++ b/ansible/roles/kafka/templates/kafka.service.j2
@@ -0,0 +1,14 @@
+# {{ansible_managed}}
+
+[Unit]
+Description=Kafka
+Before=
+After=network.target
+
+[Service]
+LOG_DIR={{ kafka_dir }}/logs
+ExecStart={{ kafka_dir }}/bin/kafka-server-start {{ kafka_dir }}/etc/kafka/server.properties
+Restart=on-abort
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/ansible/roles/kafka/templates/server.properties.j2 b/ansible/roles/kafka/templates/server.properties.j2
new file mode 100644
index 000000000..7498aa0ce
--- /dev/null
+++ b/ansible/roles/kafka/templates/server.properties.j2
@@ -0,0 +1,201 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# see kafka.server.KafkaConfig for additional details and defaults
+
+############################# Server Basics #############################
+
+# The id of the broker. This must be set to a unique integer for each broker.
+broker.id={{ broker_id }}
+
+############################# Socket Server Settings #############################
+
+# The address the socket server listens on. It will get the value returned from
+# java.net.InetAddress.getCanonicalHostName() if not configured.
+#   FORMAT:
+#     listeners = listener_name://host_name:port
+#   EXAMPLE:
+#     listeners = PLAINTEXT://your.host.name:9092
+#listeners=PLAINTEXT://0.0.0.0:{{ kafka_listener_port }}
+
+# Hostname and port the broker will advertise to producers and consumers. If not set,
+# it uses the value for "listeners" if configured.  Otherwise, it will use the value
+# returned from java.net.InetAddress.getCanonicalHostName().
+#advertised.listeners=PLAINTEXT://{{ kafka_url }}
+
+# Maps listener names to security protocols, the default is for them to be the same. See the config documentation for more details
+#listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL
+
+# The number of threads that the server uses for receiving requests from the network and sending responses to the network
+num.network.threads={{ network_threads_count }}
+
+# The number of threads that the server uses for processing requests, which may include disk I/O
+num.io.threads={{ io_threads_count }}
+
+# The send buffer (SO_SNDBUF) used by the socket server
+socket.send.buffer.bytes={{ socket_send_buf_bytes }}
+
+# The receive buffer (SO_RCVBUF) used by the socket server
+socket.receive.buffer.bytes={{ socket_receive_buf_bytes }}
+
+# The maximum size of a request that the socket server will accept (protection against OOM)
+socket.request.max.bytes={{ socket_request_max_bytes }}
+
+
+############################# Log Basics #############################
+
+# A comma separated list of directories under which to store log files
+log.dirs={{ kafka_dir }}/logs
+
+# The default number of log partitions per topic. More partitions allow greater
+# parallelism for consumption, but this will also result in more files across
+# the brokers.
+num.partitions={{ num_partitions }}
+
+# The number of threads per data directory to be used for log recovery at startup and flushing at shutdown.
+# This value is recommended to be increased for installations with data dirs located in RAID array.
+num.recovery.threads.per.data.dir={{ num_recovery_threads }}
+
+############################# Internal Topic Settings  #############################
+# The replication factor for the group metadata internal topics "__consumer_offsets" and "__transaction_state"
+# For anything other than development testing, a value greater than 1 is recommended for to ensure availability such as 3.
+offsets.topic.replication.factor={{ offsets_topic_replication_fac }}
+transaction.state.log.replication.factor={{ trans_state_log_replication_fac }}
+transaction.state.log.min.isr={{ trans_state_log }}
+
+############################# Log Flush Policy #############################
+
+# Messages are immediately written to the filesystem but by default we only fsync() to sync
+# the OS cache lazily. The following configurations control the flush of data to disk.
+# There are a few important trade-offs here:
+#    1. Durability: Unflushed data may be lost if you are not using replication.
+#    2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush.
+#    3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to excessive seeks.
+# The settings below allow one to configure the flush policy to flush data after a period of time or
+# every N messages (or both). This can be done globally and overridden on a per-topic basis.
+
+# The number of messages to accept before forcing a flush of data to disk
+#log.flush.interval.messages=10000
+
+# The maximum amount of time a message can sit in a log before we force a flush
+#log.flush.interval.ms=1000
+
+############################# Log Retention Policy #############################
+
+# The following configurations control the disposal of log segments. The policy can
+# be set to delete segments after a period of time, or after a given size has accumulated.
+# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens
+# from the end of the log.
+
+# The minimum age of a log file to be eligible for deletion due to age
+log.retention.hours={{ log_retention_hrs }}
+
+# A size-based retention policy for logs. Segments are pruned from the log unless the remaining
+# segments drop below log.retention.bytes. Functions independently of log.retention.hours.
+#log.retention.bytes=1073741824
+
+# The maximum size of a log segment file. When this size is reached a new log segment will be created.
+log.segment.bytes={{ log_segment_bytes }}
+
+# The interval at which log segments are checked to see if they can be deleted according
+# to the retention policies
+log.retention.check.interval.ms={{ log_retention_check_interval }}
+
+############################# Zookeeper #############################
+
+# Zookeeper connection string (see zookeeper docs for details).
+# This is a comma separated host:port pairs, each corresponding to a zk
+# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002".
+# You can also append an optional chroot string to the urls to specify the
+# root directory for all kafka znodes.
+zookeeper.connect={{ zookeeper_connection_url }}
+
+# Timeout in ms for connecting to zookeeper
+zookeeper.connection.timeout.ms={{ zookeeper_connection_timeout }}
+
+##################### Confluent Metrics Reporter #######################
+# Confluent Control Center and Confluent Auto Data Balancer integration
+#
+# Uncomment the following lines to publish monitoring data for
+# Confluent Control Center and Confluent Auto Data Balancer
+# If you are using a dedicated metrics cluster, also adjust the settings
+# to point to your metrics kakfa cluster.
+#metric.reporters=io.confluent.metrics.reporter.ConfluentMetricsReporter
+#confluent.metrics.reporter.bootstrap.servers=localhost:9092
+#
+# Uncomment the following line if the metrics cluster has a single broker
+#confluent.metrics.reporter.topic.replicas=1
+
+##################### Confluent Proactive Support ######################
+# If set to true, and confluent-support-metrics package is installed
+# then the feature to collect and report support metrics
+# ("Metrics") is enabled.  If set to false, the feature is disabled.
+#
+confluent.support.metrics.enable=true
+
+
+# The customer ID under which support metrics will be collected and
+# reported.
+#
+# When the customer ID is set to "anonymous" (the default), then only a
+# reduced set of metrics is being collected and reported.
+#
+# Confluent customers
+# -------------------
+# If you are a Confluent customer, then you should replace the default
+# value with your actual Confluent customer ID.  Doing so will ensure
+# that additional support metrics will be collected and reported.
+#
+confluent.support.customer.id=anonymous
+
+############################# Group Coordinator Settings #############################
+
+# The following configuration specifies the time, in milliseconds, that the GroupCoordinator will delay the initial consumer rebalance.
+# The rebalance will be further delayed by the value of group.initial.rebalance.delay.ms as new members join the group, up to a maximum of max.poll.interval.ms.
+# The default value for this is 3 seconds.
+# We override this to 0 here as it makes for a better out-of-the-box experience for development and testing.
+# However, in production environments the default value of 3 seconds is more suitable as this will help to avoid unnecessary, and potentially expensive, rebalances during application startup.
+group.initial.rebalance.delay.ms={{ grp_initial_rebalance_delay }}
+
+
+############################# Confluent Authorizer Settings  #############################
+
+# Uncomment to enable Confluent Authorizer with support for ACLs, LDAP groups and RBAC
+#authorizer.class.name=io.confluent.kafka.security.authorizer.ConfluentServerAuthorizer
+# Semi-colon separated list of super users in the format <principalType>:<principalName>
+#super.users=
+# Specify a valid Confluent license. By default free-tier license will be used
+#confluent.license=
+# Replication factor for the topic used for licensing. Default is 3.
+confluent.license.topic.replication.factor=1
+
+# Uncomment the following lines and specify values where required to enable RBAC
+# Enable RBAC provider
+#confluent.authorizer.access.rule.providers=ACL,RBAC
+# Bootstrap servers for RBAC metadata. Must be provided if this broker is not in the metadata cluster
+#confluent.metadata.bootstrap.servers=PLAINTEXT://127.0.0.1:9092
+# Replication factor for the metadata topic used for authorization. Default is 3.
+confluent.metadata.topic.replication.factor=1
+
+# Listeners for metadata server
+#confluent.metadata.server.listeners=http://0.0.0.0:8090
+# Advertised listeners for metadata server
+#confluent.metadata.server.advertised.listeners=http://127.0.0.1:8090
+
+############################# Additional fixes #######################
+delete.topic.enable = true
+auto.create.topics.enable=true
+# listeners=PLAINTEXT://0.0.0.0:9092
+advertised.listeners = PLAINTEXT://{{ ansible_host }}:9092
diff --git a/ansible/roles/keycloak/README.md b/ansible/roles/keycloak/README.md
new file mode 100644
index 000000000..42f6bd978
--- /dev/null
+++ b/ansible/roles/keycloak/README.md
@@ -0,0 +1,12 @@
+## Keycloak Deployment
+
+###Configuration variables are distributed between :
+1. `roles/keycloak/default/main.yml` - defaults for keycloak internal variables
+2. `inventories/airavata-iam/group_vars/all.yml` - Global variables
+
+###Running instructions:
+
+1. Make sure all the variables are configured correctly
+2. Dont use the Database role, rather set up the VM with default version provided by centos, tested with MySql 5.6 & MariaDB 5.5.52), Ansible role for the same is coming soon.
+3. Ensure the host file: `inventories/airavata-iam/hosts` has correct IP address
+4. For Standalone mode deployment : `ansible-playbook -i inventories/airavata-iam keycloak.yml`
diff --git a/ansible/roles/keycloak/defaults/main.yml b/ansible/roles/keycloak/defaults/main.yml
new file mode 100644
index 000000000..2949ceec7
--- /dev/null
+++ b/ansible/roles/keycloak/defaults/main.yml
@@ -0,0 +1,46 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+keycloak_version: "9.0.2"
+keycloak_downlaod_url: "https://downloads.jboss.org/keycloak/{{keycloak_version}}/keycloak-{{keycloak_version}}.tar.gz"
+keycloak_install_dir: "keycloak-{{keycloak_version}}"
+keycloak_db_connector_name: "mysql-connector-java-5.1.41"
+# keycloak_ssl_keystore_file: "keycloak.jks"
+# keycloak_ssl_keystore_file_name: "keycloak.jks"
+# keycloak_ssl_keystore_password: "Airavata"
+mysql_db_connector_download_url: "https://dev.mysql.com/get/Downloads/Connector-J/{{keycloak_db_connector_name}}.tar.gz"
+keycloak_master_account_username: "username"
+keycloak_master_account_password: "password"
+# keycloak_server_port: "443"
+
+keycloak_db_host: "localhost"
+keycloak_db_port: "3306"
+keycloak_db_schema_name: "postgresDB"
+keycloak_db_url: "jdbc:postgresql://{{keycloak_db_host}}:{{keycloak_db_port}}/{{keycloak_db_schema_name}}"
+keycloak_db_username: "postgres"
+keycloak_db_password: "postgres"
+keycloak_db_pool_size: "20"
+
+keycloak_vhost_servername: "changeme.org"
+keycloak_ssl_certificate_file: "/etc/letsencrypt/live/{{ keycloak_vhost_servername }}/cert.pem"
+keycloak_ssl_certificate_chain_file: "/etc/letsencrypt/live/{{ keycloak_vhost_servername }}/fullchain.pem"
+keycloak_ssl_certificate_key_file: "/etc/letsencrypt/live/{{ keycloak_vhost_servername }}/privkey.pem"
+...
diff --git a/ansible/roles/keycloak/handlers/main.yml b/ansible/roles/keycloak/handlers/main.yml
new file mode 100644
index 000000000..589bdabcd
--- /dev/null
+++ b/ansible/roles/keycloak/handlers/main.yml
@@ -0,0 +1,26 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+
+# Gracefully reload httpd
+- name: restart httpd
+  service: name=httpd state=reloaded enabled=yes
+  become: yes
diff --git a/ansible/roles/keycloak/tasks/main.yml b/ansible/roles/keycloak/tasks/main.yml
new file mode 100644
index 000000000..de9967b8b
--- /dev/null
+++ b/ansible/roles/keycloak/tasks/main.yml
@@ -0,0 +1,267 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+#- name: Install httpd
+#  apt: name="httpd" state=latest update_cache=yes
+#  become: yes
+#
+#- name: allow httpd to proxy to Keycloak process
+#  seboolean:
+#    name: httpd_can_network_connect
+#    state: yes
+#    persistent: yes
+#  become: yes
+#
+#- name: Enable http/s service on public zone (for certbot verification)
+#  firewalld: service={{ item }} permanent=true state=enabled zone=public immediate=True
+#  with_items:
+#    - http
+#    - https
+#  become: yes
+#
+## TODO: it seems like a virtual host config of some type is needed for the following to work
+#- name: copy basic virtual host file so certbot can verify domain
+#  template: src="basic-vhost.conf.j2" dest=/etc/httpd/conf.d/basic-vhost.conf backup=yes
+#  become: yes
+#
+#- name: start httpd
+#  service: name=httpd state=started enabled=yes
+#  become: yes
+#
+#- name: check if SSL certificate exists
+#  stat:
+#    path: "{{ keycloak_ssl_certificate_file }}"
+#  register: stat_ssl_cert_result
+#  become: yes
+#
+#- name: generate certificate if it doesn't exist
+#  command: certbot --apache --non-interactive --agree-tos --email "{{ letsencrypt_email }}" -d {{ keycloak_vhost_servername }} certonly
+#  become: yes
+#  when: not stat_ssl_cert_result.stat.exists
+#
+#- name: Add keycloak virtual host config that proxies to the keycloak server
+#  template: src="vhost.conf.j2" dest=/etc/httpd/conf.d/keycloak.conf backup=yes
+#  become: yes
+#  notify:
+#    - restart httpd
+
+
+- name: Install Keycloak pre-requisites (Debian)
+  apt: name={{ item }} state=latest update_cache=yes
+  with_items:
+    - maven
+  become: yes
+  when: ansible_os_family == "Debian"
+
+- name: Create Keycloak deployment directory {{ keycloak_install_dir }}
+  become: yes
+  file: path={{ keycloak_install_dir }}
+    state=directory
+    mode=0755
+    owner={{ user }}
+    group={{ group }}
+
+- name: Create Keycloak source directory
+  become: yes
+  file: path={{ keycloak_source_dir }}
+    state=directory
+    mode=0755
+    owner={{ user }}
+    group={{ group }}
+
+# Clone Keycloak repo
+- name: git checkout from Keycloak github repo {{ keycloak_repo }} # branch {{ keycloak_git_branch }}
+  git:
+    repo: "{{ keycloak_repo }}"
+    dest: "{{ keycloak_source_dir }}"
+    version: "9.0.2"
+    force: yes
+  register: checkout
+  tags: update
+  become: yes
+  become_user: "{{ user }}"
+
+- name: Run Keycloak maven build
+  command: mvn -Pdistribution -pl distribution/server-dist -am -Dmaven.test.skip clean install chdir="{{ keycloak_source_dir }}/"
+#  mvn clean install -Dmaven.test.skip=true chdir="{{ keycloak_source_dir }}/"
+  environment:
+    MAVEN_OPTS: "-Xmx2048m"
+  register: build
+  tags: update
+  become: yes
+  become_user: "{{ user }}"
+
+- name: Delete configuration directories of the distributions
+  file:
+    state: absent
+    path: "{{ keycloak_install_dir }}/standalone/configuration"
+  become: yes
+  become_user: "{{ user }}"
+  ignore_errors: yes
+
+# Unarchive keycloak distribution
+- name: Unarchive keycloak
+  unarchive:
+    src: "{{ keycloak_source_dir }}/distribution/server-dist/target/keycloak-{{ keycloak_version }}.zip"
+    dest: "{{ user_home }}"
+    copy: no
+  become: yes
+  become_user: "{{ user }}"
+
+# setup postgresql for keycloak
+- name: Install postgresql and postgresql-contrib
+  apt:
+    name:
+      - postgresql
+      - postgresql-contrib
+  become: yes
+#  become_user: "{{ user }}"
+
+- name: Start the postgresql service
+  service:
+    name: postgresql
+    state: started
+    enabled: yes
+  become: yes
+  become_user: "{{ user }}"
+#
+## <---------------------------- Setup Mysql database for keycloak ------------------->
+#
+## create folder structure
+#- file:
+#    path: "{{user_home}}/{{ keycloak_inkeycloak_install_dir }}/modules/system/layers/keycloak/org/mysql/main"
+#    state: directory
+#    mode: 0755
+#  become: true
+#  become_user: "{{ user }}"
+#  tags:
+#       - always
+#
+#- name: Download and unarchive mysql jdbc driver
+#  unarchive: src="{{ mysql_db_connector_download_url }}"
+#      dest="{{ user_home }}"
+#      copy=no
+#      owner="{{ user }}"
+#      group="{{ group }}"
+#      creates="{{user_home}}/{{keycloak_db_connector_name}}/{{keycloak_db_connector_name}}-bin.jar"
+#  become: true
+#  become_user: "{{ user }}"
+#  tags:
+#       - always
+#
+#- name: move jdbc connector to keycloak module
+#  command: mv {{user_home}}/{{keycloak_db_connector_name}}/{{keycloak_db_connector_name}}-bin.jar {{user_home}}/{{ keycloak_install_dir }}/modules/system/layers/keycloak/org/mysql/main/
+#  become: true
+#  become_user: "{{ user }}"
+#  tags:
+#       - always
+#
+#- name: copy jdbc module configuration file
+#  template: >
+#    src=module.j2
+#    dest="{{user_home}}/{{ keycloak_install_dir }}/modules/system/layers/keycloak/org/mysql/main/module.xml"
+#    owner="{{ user }}"
+#    group="{{ group }}"
+#    mode="u=rw,g=r,o=r"
+#  become: true
+#  become_user: "{{ user }}"
+#  tags:
+#       - always
+#
+## </---------------------------- Setup Mysql database for keycloak - END ------------------->
+#
+# <---------------------------- Server Configuration -------------------------------->
+
+# SSL Configuration & postgresql
+- name: copy keycloak configuration file (Standalone)
+  template: >
+    src=standalone.xml.j2
+    dest="{{ user_home }}/{{ keycloak_install_dir }}/standalone/configuration/standalone.xml"
+    owner="{{ user }}"
+    group="{{ group }}"
+    mode="u=rw,g=r,o=r"
+  become: true
+  become_user: "{{ user }}"
+  tags:
+       - standalone
+
+# </------------------------------ Server Configuration ends ---------------------------->
+
+# <---------- setup init script for keycloak, starts the server after reboot ----------->
+
+# Init script to start keycloak in Standalone mode
+- name: copy init script file (Standalone)
+  template: >
+    src=keycloak-standalone-init.j2
+    dest="/etc/init.d/keycloak"
+    owner="{{ user }}"
+    group="{{ group }}"
+    mode="u=rwx,g=rx,o=rx"
+  become: yes
+  become_user: root
+  tags:
+       - standalone
+
+## System command to add the init script to enable on startup
+#- name: add init script to chkconfig and startup on boot
+#  command: chkconfig --level 345 keycloak on
+#  become: yes
+#  become_user: root
+#  tags:
+#       - always
+
+# </---------- setup init script for keycloak, starts the server after reboot ----------->
+
+# <-------------------------Initialize a new admin for keycloak-------------------------->
+
+- name: Add master realm admin account
+  command: "{{user_home}}/{{ keycloak_install_dir }}/bin/add-user-keycloak.sh -r master -u {{ keycloak_master_account_username }} -p {{ keycloak_master_account_password }}"
+  args:
+    creates: "{{user_home}}/{{ keycloak_install_dir }}/standalone/configuration/keycloak-add-user.json"
+  become: yes
+  become_user: root
+  tags:
+       - always
+
+
+# <--------------------------start keycloak Identity server------------------------------>
+- name: reload Keycloak init script
+  command: systemctl daemon-reload
+  become: yes
+  become_user: root
+  tags:
+       - always
+
+# FIXME: restarting Keycloak server doesn't work
+- name: stop Keycloak server
+  service: name=keycloak state=stopped
+  ignore_errors: yes
+  become: yes
+  become_user: root
+  tags:
+       - always
+
+- name: start Keycloak server
+  service: name=keycloak state=started
+  become: yes
+  become_user: root
+  tags:
+       - always
+...
diff --git a/ansible/roles/keycloak/templates/basic-vhost.conf.j2 b/ansible/roles/keycloak/templates/basic-vhost.conf.j2
new file mode 100644
index 000000000..da78c4ce2
--- /dev/null
+++ b/ansible/roles/keycloak/templates/basic-vhost.conf.j2
@@ -0,0 +1,9 @@
+<VirtualHost *:80>
+    ServerName {{ groups['keycloak'][0] }}
+    DocumentRoot "/var/www/html"
+
+    <Directory /var/www/html>
+        Options -Indexes +FollowSymLinks
+        AllowOverride All
+    </Directory>
+</VirtualHost>
diff --git a/ansible/roles/keycloak/templates/keycloak-hacluster-init.j2 b/ansible/roles/keycloak/templates/keycloak-hacluster-init.j2
new file mode 100644
index 000000000..c9b9cca5c
--- /dev/null
+++ b/ansible/roles/keycloak/templates/keycloak-hacluster-init.j2
@@ -0,0 +1,49 @@
+#!/bin/bash
+#
+# chkconfig: 35 90 12
+# description: keycloak server
+#
+
+# Get function from functions library
+. /etc/init.d/functions
+
+# Start the service Keycloak
+start() {
+        initlog -c "echo -n Starting Keycloak server: "
+        nohup {{ user_home }}/{{ keycloak_install_dir }}/bin/standalone.sh -b 0.0.0.0 --server-config=standalone-ha.xml &
+        ### Create the lock file ###
+        touch /var/lock/subsys/keycloak
+        success $"keycloak server running"
+        echo
+}
+
+# Restart the service FOO
+stop() {
+        initlog -c "echo -n Stopping keycloak server: "
+        ps aux | grep keycloak | grep -v grep | awk '{print $2}' | xargs kill
+        ### Now, delete the lock file ###
+        rm -f /var/lock/subsys/keycloak
+        echo
+}
+
+### main logic ###
+case "$1" in
+  start)
+        start
+        ;;
+  stop)
+        stop
+        ;;
+  status)
+        status keycloak
+        ;;
+  restart|reload|condrestart)
+        stop
+        start
+        ;;
+  *)
+        echo $"Usage: $0 {start|stop|restart|reload|status}"
+        exit 1
+esac
+
+exit 0
\ No newline at end of file
diff --git a/ansible/roles/keycloak/templates/keycloak-standalone-init.j2 b/ansible/roles/keycloak/templates/keycloak-standalone-init.j2
new file mode 100644
index 000000000..bc7abe40c
--- /dev/null
+++ b/ansible/roles/keycloak/templates/keycloak-standalone-init.j2
@@ -0,0 +1,46 @@
+#!/bin/bash
+#
+# chkconfig: 35 90 12
+# description: keycloak server
+#
+
+# Get function from functions library
+. /etc/init.d/functions
+
+# Start the service Keycloak
+start() {
+        nohup {{ user_home }}/{{ keycloak_install_dir }}/bin/standalone.sh -b 0.0.0.0 &
+        ### Create the lock file ###
+        touch /var/lock/subsys/keycloak
+        echo $"keycloak server running"
+}
+
+# Restart the service FOO
+stop() {
+        ps aux | grep keycloak | grep -v grep | awk '{print $2}' | xargs kill
+        ### Now, delete the lock file ###
+        rm -f /var/lock/subsys/keycloak
+        echo $"keycloak server stopped"
+}
+
+### main logic ###
+case "$1" in
+  start)
+        start
+        ;;
+  stop)
+        stop
+        ;;
+  status)
+        status keycloak
+        ;;
+  restart|reload|condrestart)
+        stop
+        start
+        ;;
+  *)
+        echo $"Usage: $0 {start|stop|restart|reload|status}"
+        exit 1
+esac
+
+exit 0
\ No newline at end of file
diff --git a/ansible/roles/keycloak/templates/module.j2 b/ansible/roles/keycloak/templates/module.j2
new file mode 100644
index 000000000..45da6243a
--- /dev/null
+++ b/ansible/roles/keycloak/templates/module.j2
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<module xmlns="urn:jboss:module:1.3" name="org.mysql">
+
+    <resources>
+        <resource-root path="{{keycloak_db_connector_name}}-bin.jar"/>
+    </resources>
+
+    <dependencies>
+        <module name="javax.api"/>
+        <module name="javax.transaction.api"/>
+    </dependencies>
+</module>
\ No newline at end of file
diff --git a/ansible/roles/keycloak/templates/standalone-ha.xml.j2 b/ansible/roles/keycloak/templates/standalone-ha.xml.j2
new file mode 100644
index 000000000..e6fa3e837
--- /dev/null
+++ b/ansible/roles/keycloak/templates/standalone-ha.xml.j2
@@ -0,0 +1,539 @@
+<?xml version="1.0" ?>
+
+<server xmlns="urn:jboss:domain:4.0">
+    <extensions>
+        <extension module="org.jboss.as.clustering.infinispan"/>
+        <extension module="org.jboss.as.clustering.jgroups"/>
+        <extension module="org.jboss.as.connector"/>
+        <extension module="org.jboss.as.deployment-scanner"/>
+        <extension module="org.jboss.as.ee"/>
+        <extension module="org.jboss.as.ejb3"/>
+        <extension module="org.jboss.as.jaxrs"/>
+        <extension module="org.jboss.as.jdr"/>
+        <extension module="org.jboss.as.jmx"/>
+        <extension module="org.jboss.as.jpa"/>
+        <extension module="org.jboss.as.jsf"/>
+        <extension module="org.jboss.as.logging"/>
+        <extension module="org.jboss.as.mail"/>
+        <extension module="org.jboss.as.modcluster"/>
+        <extension module="org.jboss.as.naming"/>
+        <extension module="org.jboss.as.remoting"/>
+        <extension module="org.jboss.as.security"/>
+        <extension module="org.jboss.as.transactions"/>
+        <extension module="org.keycloak.keycloak-server-subsystem"/>
+        <extension module="org.wildfly.extension.bean-validation"/>
+        <extension module="org.wildfly.extension.io"/>
+        <extension module="org.wildfly.extension.request-controller"/>
+        <extension module="org.wildfly.extension.security.manager"/>
+        <extension module="org.wildfly.extension.undertow"/>
+    </extensions>
+    <management>
+        <security-realms>
+            <security-realm name="ManagementRealm">
+                <authentication>
+                    <local default-user="$local" skip-group-loading="true"/>
+                    <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization map-groups-to-roles="false">
+                    <properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+            <security-realm name="ApplicationRealm">
+                <authentication>
+                    <local default-user="$local" allowed-users="*" skip-group-loading="true"/>
+                    <properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization>
+                    <properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+        </security-realms>
+        <audit-log>
+            <formatters>
+                <json-formatter name="json-formatter"/>
+            </formatters>
+            <handlers>
+                <file-handler name="file" formatter="json-formatter" relative-to="jboss.server.data.dir" path="audit-log.log"/>
+            </handlers>
+            <logger log-boot="true" log-read-only="false" enabled="false">
+                <handlers>
+                    <handler name="file"/>
+                </handlers>
+            </logger>
+        </audit-log>
+        <management-interfaces>
+            <http-interface security-realm="ManagementRealm" http-upgrade-enabled="true">
+                <socket-binding http="management-http"/>
+            </http-interface>
+        </management-interfaces>
+        <access-control provider="simple">
+            <role-mapping>
+                <role name="SuperUser">
+                    <include>
+                        <user name="$local"/>
+                    </include>
+                </role>
+            </role-mapping>
+        </access-control>
+    </management>
+    <profile>
+        <subsystem xmlns="urn:jboss:domain:logging:3.0">
+            <console-handler name="CONSOLE">
+                <level name="INFO"/>
+                <formatter>
+                    <named-formatter name="COLOR-PATTERN"/>
+                </formatter>
+            </console-handler>
+            <periodic-rotating-file-handler name="FILE" autoflush="true">
+                <formatter>
+                    <named-formatter name="PATTERN"/>
+                </formatter>
+                <file relative-to="jboss.server.log.dir" path="server.log"/>
+                <suffix value=".yyyy-MM-dd"/>
+                <append value="true"/>
+            </periodic-rotating-file-handler>
+            <logger category="com.arjuna">
+                <level name="WARN"/>
+            </logger>
+            <logger category="org.jboss.as.config">
+                <level name="DEBUG"/>
+            </logger>
+            <logger category="sun.rmi">
+                <level name="WARN"/>
+            </logger>
+            <root-logger>
+                <level name="INFO"/>
+                <handlers>
+                    <handler name="CONSOLE"/>
+                    <handler name="FILE"/>
+                </handlers>
+            </root-logger>
+            <formatter name="PATTERN">
+                <pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
+            </formatter>
+            <formatter name="COLOR-PATTERN">
+                <pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
+            </formatter>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:datasources:4.0">
+            <datasources>
+                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
+                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
+                    <driver>h2</driver>
+                    <security>
+                        <user-name>sa</user-name>
+                        <password>sa</password>
+                    </security>
+                </datasource>
+                <datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true">
+                    <connection-url>{{keycloak_db_url}}</connection-url>
+                    <driver>mysql</driver>
+                    <pool>
+                        <max-pool-size>{{keycloak_db_pool_size}}</max-pool-size>
+                    </pool>
+                    <security>
+                        <user-name>{{keycloak_db_username}}</user-name>
+                        <password>{{keycloak_db_password}}</password>
+                    </security>
+                    <validation>
+                        <check-valid-connection-sql>select 1</check-valid-connection-sql>
+                        <validate-on-match>false</validate-on-match>
+                        <background-validation>true</background-validation>
+                        <background-validation-millis>10000</background-validation-millis>
+                    </validation>
+                </datasource>
+                <drivers>
+		            <driver name="mysql" module="org.mysql">
+			            <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
+		            </driver>
+                    <driver name="h2" module="com.h2database.h2">
+                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
+                    </driver>
+                </drivers>
+            </datasources>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0">
+            <deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" runtime-failure-causes-rollback="${jboss.deployment.scanner.rollback.on.failure:false}"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ee:4.0">
+            <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
+            <concurrent>
+                <context-services>
+                    <context-service name="default" jndi-name="java:jboss/ee/concurrency/context/default" use-transaction-setup-provider="true"/>
+                </context-services>
+                <managed-thread-factories>
+                    <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
+                </managed-thread-factories>
+                <managed-executor-services>
+                    <managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" keepalive-time="5000"/>
+                </managed-executor-services>
+                <managed-scheduled-executor-services>
+                    <managed-scheduled-executor-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-threshold="60000" keepalive-time="3000"/>
+                </managed-scheduled-executor-services>
+            </concurrent>
+            <default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/ExampleDS" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ejb3:4.0">
+            <session-bean>
+                <stateless>
+                    <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
+                </stateless>
+                <stateful default-access-timeout="5000" cache-ref="distributable" passivation-disabled-cache-ref="simple"/>
+                <singleton default-access-timeout="5000"/>
+            </session-bean>
+            <pools>
+                <bean-instance-pools>
+                    <!-- Automatically configure pools. Alternatively, max-pool-size can be set to a specific value -->
+                    <strict-max-pool name="slsb-strict-max-pool" derive-size="from-worker-pools" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                    <strict-max-pool name="mdb-strict-max-pool" derive-size="from-cpu-count" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                </bean-instance-pools>
+            </pools>
+            <caches>
+                <cache name="simple"/>
+                <cache name="distributable" passivation-store-ref="infinispan" aliases="passivating clustered"/>
+            </caches>
+            <passivation-stores>
+                <passivation-store name="infinispan" cache-container="ejb" max-size="10000"/>
+            </passivation-stores>
+            <async thread-pool-name="default"/>
+            <timer-service thread-pool-name="default" default-data-store="default-file-store">
+                <data-stores>
+                    <file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
+                </data-stores>
+            </timer-service>
+            <remote connector-ref="http-remoting-connector" thread-pool-name="default"/>
+            <thread-pools>
+                <thread-pool name="default">
+                    <max-threads count="10"/>
+                    <keepalive-time time="100" unit="milliseconds"/>
+                </thread-pool>
+            </thread-pools>
+            <default-security-domain value="other"/>
+            <default-missing-method-permissions-deny-access value="true"/>
+            <log-system-exceptions value="true"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:io:1.1">
+            <worker name="default"/>
+            <buffer-pool name="default"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:infinispan:4.0">
+            <cache-container name="keycloak" jndi-name="infinispan/Keycloak">
+                <transport lock-timeout="60000"/>
+                <local-cache name="realms">
+                    <eviction max-entries="10000" strategy="LRU"/>
+                </local-cache>
+                <local-cache name="users">
+                    <eviction max-entries="10000" strategy="LRU"/>
+                </local-cache>
+                <distributed-cache name="sessions" mode="SYNC" owners="1"/>
+                <distributed-cache name="offlineSessions" mode="SYNC" owners="1"/>
+                <distributed-cache name="loginFailures" mode="SYNC" owners="1"/>
+                <distributed-cache name="authorization" mode="SYNC" owners="1"/>
+                <replicated-cache name="work" mode="SYNC"/>
+                <local-cache name="keys">
+                    <eviction max-entries="1000" strategy="LRU"/>
+                    <expiration max-idle="3600000"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="server" aliases="singleton cluster" default-cache="default" module="org.wildfly.clustering.server">
+                <transport lock-timeout="60000"/>
+                <replicated-cache name="default" mode="SYNC">
+                    <transaction mode="BATCH"/>
+                </replicated-cache>
+            </cache-container>
+            <cache-container name="web" default-cache="dist" module="org.wildfly.clustering.web.infinispan">
+                <transport lock-timeout="60000"/>
+                <distributed-cache name="dist" mode="ASYNC" l1-lifespan="0" owners="2">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store/>
+                </distributed-cache>
+            </cache-container>
+            <cache-container name="ejb" aliases="sfsb" default-cache="dist" module="org.wildfly.clustering.ejb.infinispan">
+                <transport lock-timeout="60000"/>
+                <distributed-cache name="dist" mode="ASYNC" l1-lifespan="0" owners="2">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store/>
+                </distributed-cache>
+            </cache-container>
+            <cache-container name="hibernate" default-cache="local-query" module="org.hibernate.infinispan">
+                <transport lock-timeout="60000"/>
+                <local-cache name="local-query">
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </local-cache>
+                <invalidation-cache name="entity" mode="SYNC">
+                    <transaction mode="NON_XA"/>
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </invalidation-cache>
+                <replicated-cache name="timestamps" mode="ASYNC"/>
+            </cache-container>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jca:4.0">
+            <archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
+            <bean-validation enabled="true"/>
+            <default-workmanager>
+                <short-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </short-running-threads>
+                <long-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </long-running-threads>
+            </default-workmanager>
+            <cached-connection-manager/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jdr:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jgroups:4.0">
+            <channels default="ee">
+                <channel name="ee" stack="udp"/>
+            </channels>
+            <stacks>
+                <stack name="udp">
+                    <transport type="UDP" socket-binding="jgroups-udp"/>
+                    <protocol type="PING"/>
+                    <protocol type="MERGE3"/>
+                    <protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
+                    <protocol type="FD_ALL"/>
+                    <protocol type="VERIFY_SUSPECT"/>
+                    <protocol type="pbcast.NAKACK2"/>
+                    <protocol type="UNICAST3"/>
+                    <protocol type="pbcast.STABLE"/>
+                    <protocol type="pbcast.GMS"/>
+                    <protocol type="UFC"/>
+                    <protocol type="MFC"/>
+                    <protocol type="FRAG2"/>
+                </stack>
+                <stack name="tcp">
+                    <transport type="TCP" socket-binding="jgroups-tcp"/>
+                    <protocol type="MPING" socket-binding="jgroups-mping"/>
+                    <protocol type="MERGE3"/>
+                    <protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
+                    <protocol type="FD"/>
+                    <protocol type="VERIFY_SUSPECT"/>
+                    <protocol type="pbcast.NAKACK2"/>
+                    <protocol type="UNICAST3"/>
+                    <protocol type="pbcast.STABLE"/>
+                    <protocol type="pbcast.GMS"/>
+                    <protocol type="MFC"/>
+                    <protocol type="FRAG2"/>
+                </stack>
+            </stacks>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jmx:1.3">
+            <expose-resolved-model/>
+            <expose-expression-model/>
+            <remoting-connector/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jpa:1.1">
+            <jpa default-datasource="" default-extended-persistence-inheritance="DEEP"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jsf:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:mail:2.0">
+            <mail-session name="default" jndi-name="java:jboss/mail/Default">
+                <smtp-server outbound-socket-binding-ref="mail-smtp"/>
+            </mail-session>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:modcluster:2.0">
+            <mod-cluster-config advertise-socket="modcluster" connector="ajp">
+                <dynamic-load-provider>
+                    <load-metric type="cpu"/>
+                </dynamic-load-provider>
+            </mod-cluster-config>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:naming:2.0">
+            <remote-naming/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:remoting:3.0">
+            <endpoint/>
+            <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:request-controller:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:security-manager:1.0">
+            <deployment-permissions>
+                <maximum-set>
+                    <permission class="java.security.AllPermission"/>
+                </maximum-set>
+            </deployment-permissions>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:security:1.2">
+            <security-domains>
+                <security-domain name="other" cache-type="default">
+                    <authentication>
+                        <login-module code="Remoting" flag="optional">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                        <login-module code="RealmDirect" flag="required">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                    </authentication>
+                </security-domain>
+                <security-domain name="jboss-web-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+                <security-domain name="jboss-ejb-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+                <security-domain name="jaspitest" cache-type="default">
+                    <authentication-jaspi>
+                        <login-module-stack name="dummy">
+                            <login-module code="Dummy" flag="optional"/>
+                        </login-module-stack>
+                        <auth-module code="Dummy"/>
+                    </authentication-jaspi>
+                </security-domain>
+            </security-domains>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:transactions:3.0">
+            <core-environment>
+                <process-id>
+                    <uuid/>
+                </process-id>
+            </core-environment>
+            <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:undertow:3.0">
+            <buffer-cache name="default"/>
+            <server name="default-server">
+                <ajp-listener name="ajp" socket-binding="ajp"/>
+                <http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="true"/>
+                <host name="default-host" alias="localhost">
+                    <location name="/" handler="welcome-content"/>
+                    <filter-ref name="server-header"/>
+                    <filter-ref name="x-powered-by-header"/>
+                </host>
+            </server>
+            <servlet-container name="default">
+                <jsp-config/>
+                <websockets/>
+            </servlet-container>
+            <handlers>
+                <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
+            </handlers>
+            <filters>
+                <response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
+                <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
+            </filters>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
+            <web-context>auth</web-context>
+            <providers>
+                <provider>classpath:${jboss.home.dir}/providers/*</provider>
+            </providers>
+            <master-realm-name>master</master-realm-name>
+            <scheduled-task-interval>900</scheduled-task-interval>
+            <theme>
+                <staticMaxAge>2592000</staticMaxAge>
+                <cacheThemes>true</cacheThemes>
+                <cacheTemplates>true</cacheTemplates>
+                <dir>${jboss.home.dir}/themes</dir>
+            </theme>
+            <spi name="eventsStore">
+                <default-provider>jpa</default-provider>
+                <provider name="jpa" enabled="true">
+                    <properties>
+                        <property name="exclude-events" value="[&quot;REFRESH_TOKEN&quot;]"/>
+                    </properties>
+                </provider>
+            </spi>
+            <spi name="realm">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="user">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="userFederatedStorage">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="userCache">
+                <provider name="default" enabled="true"/>
+            </spi>
+            <spi name="userSessionPersister">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="authorizationPersister">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="timer">
+                <default-provider>basic</default-provider>
+            </spi>
+            <spi name="connectionsHttpClient">
+                <provider name="default" enabled="true"/>
+            </spi>
+            <spi name="connectionsJpa">
+                <provider name="default" enabled="true">
+                    <properties>
+                        <property name="dataSource" value="java:jboss/datasources/KeycloakDS"/>
+                        <property name="initializeEmpty" value="true"/>
+                        <property name="migrationStrategy" value="update"/>
+                        <property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/>
+                    </properties>
+                </provider>
+            </spi>
+            <spi name="realmCache">
+                <provider name="default" enabled="true"/>
+            </spi>
+            <spi name="connectionsInfinispan">
+                <default-provider>default</default-provider>
+                <provider name="default" enabled="true">
+                    <properties>
+                        <property name="cacheContainer" value="java:comp/env/infinispan/Keycloak"/>
+                    </properties>
+                </provider>
+            </spi>
+            <spi name="jta-lookup">
+                <default-provider>${keycloak.jta.lookup.provider:jboss}</default-provider>
+                <provider name="jboss" enabled="true"/>
+            </spi>
+            <spi name="publicKeyStorage">
+                <provider name="infinispan" enabled="true">
+                    <properties>
+                        <property name="minTimeBetweenRequests" value="10"/>
+                    </properties>
+                </provider>
+            </spi>
+        </subsystem>
+    </profile>
+    <interfaces>
+        <interface name="management">
+            <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
+        </interface>
+        <interface name="public">
+            <inet-address value="${jboss.bind.address:127.0.0.1}"/>
+        </interface>
+        <interface name="private">
+            <inet-address value="${jboss.bind.address.private:127.0.0.1}"/>
+        </interface>
+    </interfaces>
+    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
+        <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
+        <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
+        <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
+        <socket-binding name="http" port="${jboss.http.port:8080}"/>
+        <socket-binding name="https" port="${jboss.https.port:8443}"/>
+        <socket-binding name="jgroups-mping" interface="private" port="0" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45700"/>
+        <socket-binding name="jgroups-tcp" interface="private" port="7600"/>
+        <socket-binding name="jgroups-tcp-fd" interface="private" port="57600"/>
+        <socket-binding name="jgroups-udp" interface="private" port="55200" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45688"/>
+        <socket-binding name="jgroups-udp-fd" interface="private" port="54200"/>
+        <socket-binding name="modcluster" port="0" multicast-address="224.0.1.105" multicast-port="23364"/>
+        <socket-binding name="txn-recovery-environment" port="4712"/>
+        <socket-binding name="txn-status-manager" port="4713"/>
+        <outbound-socket-binding name="mail-smtp">
+            <remote-destination host="localhost" port="25"/>
+        </outbound-socket-binding>
+    </socket-binding-group>
+</server>
diff --git a/ansible/roles/keycloak/templates/standalone.xml.j2 b/ansible/roles/keycloak/templates/standalone.xml.j2
new file mode 100644
index 000000000..340e5938b
--- /dev/null
+++ b/ansible/roles/keycloak/templates/standalone.xml.j2
@@ -0,0 +1,494 @@
+<?xml version="1.0" ?>
+
+<server xmlns="urn:jboss:domain:4.0">
+    <extensions>
+        <extension module="org.jboss.as.clustering.infinispan"/>
+        <extension module="org.jboss.as.connector"/>
+        <extension module="org.jboss.as.deployment-scanner"/>
+        <extension module="org.jboss.as.ee"/>
+        <extension module="org.jboss.as.ejb3"/>
+        <extension module="org.jboss.as.jaxrs"/>
+        <extension module="org.jboss.as.jdr"/>
+        <extension module="org.jboss.as.jmx"/>
+        <extension module="org.jboss.as.jpa"/>
+        <extension module="org.jboss.as.jsf"/>
+        <extension module="org.jboss.as.logging"/>
+        <extension module="org.jboss.as.mail"/>
+        <extension module="org.jboss.as.naming"/>
+        <extension module="org.jboss.as.remoting"/>
+        <extension module="org.jboss.as.security"/>
+        <extension module="org.jboss.as.transactions"/>
+        <extension module="org.keycloak.keycloak-server-subsystem"/>
+        <extension module="org.wildfly.extension.bean-validation"/>
+        <extension module="org.wildfly.extension.io"/>
+        <extension module="org.wildfly.extension.request-controller"/>
+        <extension module="org.wildfly.extension.security.manager"/>
+        <extension module="org.wildfly.extension.undertow"/>
+    </extensions>
+    <management>
+        <security-realms>
+            <security-realm name="ManagementRealm">
+                <authentication>
+                    <local default-user="$local" skip-group-loading="true"/>
+                    <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization map-groups-to-roles="false">
+                    <properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+            <security-realm name="ApplicationRealm">
+                <authentication>
+                    <local default-user="$local" allowed-users="*" skip-group-loading="true"/>
+                    <properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization>
+                    <properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+        </security-realms>
+        <audit-log>
+            <formatters>
+                <json-formatter name="json-formatter"/>
+            </formatters>
+            <handlers>
+                <file-handler name="file" formatter="json-formatter" relative-to="jboss.server.data.dir" path="audit-log.log"/>
+            </handlers>
+            <logger log-boot="true" log-read-only="false" enabled="false">
+                <handlers>
+                    <handler name="file"/>
+                </handlers>
+            </logger>
+        </audit-log>
+        <management-interfaces>
+            <http-interface security-realm="ManagementRealm" http-upgrade-enabled="true">
+                <socket-binding http="management-http"/>
+            </http-interface>
+        </management-interfaces>
+        <access-control provider="simple">
+            <role-mapping>
+                <role name="SuperUser">
+                    <include>
+                        <user name="$local"/>
+                    </include>
+                </role>
+            </role-mapping>
+        </access-control>
+    </management>
+    <profile>
+        <subsystem xmlns="urn:jboss:domain:logging:3.0">
+            <console-handler name="CONSOLE">
+                <level name="INFO"/>
+                <formatter>
+                    <named-formatter name="COLOR-PATTERN"/>
+                </formatter>
+            </console-handler>
+            <periodic-rotating-file-handler name="FILE" autoflush="true">
+                <formatter>
+                    <named-formatter name="PATTERN"/>
+                </formatter>
+                <file relative-to="jboss.server.log.dir" path="server.log"/>
+                <suffix value=".yyyy-MM-dd"/>
+                <append value="true"/>
+            </periodic-rotating-file-handler>
+            <logger category="com.arjuna">
+                <level name="WARN"/>
+            </logger>
+            <logger category="org.jboss.as.config">
+                <level name="DEBUG"/>
+            </logger>
+            <logger category="sun.rmi">
+                <level name="WARN"/>
+            </logger>
+            <root-logger>
+                <level name="INFO"/>
+                <handlers>
+                    <handler name="CONSOLE"/>
+                    <handler name="FILE"/>
+                </handlers>
+            </root-logger>
+            <formatter name="PATTERN">
+                <pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
+            </formatter>
+            <formatter name="COLOR-PATTERN">
+                <pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
+            </formatter>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:datasources:4.0">
+            <datasources>
+                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
+                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
+                    <driver>h2</driver>
+                    <security>
+                        <user-name>sa</user-name>
+                        <password>sa</password>
+                    </security>
+                </datasource>
+                <datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true">
+                    <connection-url>{{keycloak_db_url}}</connection-url>
+                    <driver>postgresql</driver>
+                    <pool>
+                        <max-pool-size>{{keycloak_db_pool_size}}</max-pool-size>
+                    </pool>
+                    <security>
+                        <user-name>{{keycloak_db_username}}</user-name>
+                        <password>{{keycloak_db_password}}</password>
+                    </security>
+                    <validation>
+                        <check-valid-connection-sql>select 1</check-valid-connection-sql>
+                        <validate-on-match>false</validate-on-match>
+                        <background-validation>true</background-validation>
+                        <background-validation-millis>10000</background-validation-millis>
+                    </validation>
+                </datasource>
+                <drivers>
+                    <driver name="mysql" module="org.mysql">
+                        <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
+                    </driver>
+                    <driver name="h2" module="com.h2database.h2">
+                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
+                    </driver>
+                </drivers>
+            </datasources>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0">
+            <deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" runtime-failure-causes-rollback="${jboss.deployment.scanner.rollback.on.failure:false}"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ee:4.0">
+            <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
+            <concurrent>
+                <context-services>
+                    <context-service name="default" jndi-name="java:jboss/ee/concurrency/context/default" use-transaction-setup-provider="true"/>
+                </context-services>
+                <managed-thread-factories>
+                    <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
+                </managed-thread-factories>
+                <managed-executor-services>
+                    <managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" keepalive-time="5000"/>
+                </managed-executor-services>
+                <managed-scheduled-executor-services>
+                    <managed-scheduled-executor-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-threshold="60000" keepalive-time="3000"/>
+                </managed-scheduled-executor-services>
+            </concurrent>
+            <default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/ExampleDS" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ejb3:4.0">
+            <session-bean>
+                <stateless>
+                    <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
+                </stateless>
+                <stateful default-access-timeout="5000" cache-ref="simple" passivation-disabled-cache-ref="simple"/>
+                <singleton default-access-timeout="5000"/>
+            </session-bean>
+            <pools>
+                <bean-instance-pools>
+                    <!-- Automatically configure pools. Alternatively, max-pool-size can be set to a specific value -->
+                    <strict-max-pool name="slsb-strict-max-pool" derive-size="from-worker-pools" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                    <strict-max-pool name="mdb-strict-max-pool" derive-size="from-cpu-count" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                </bean-instance-pools>
+            </pools>
+            <caches>
+                <cache name="simple"/>
+                <cache name="distributable" passivation-store-ref="infinispan" aliases="passivating clustered"/>
+            </caches>
+            <passivation-stores>
+                <passivation-store name="infinispan" cache-container="ejb" max-size="10000"/>
+            </passivation-stores>
+            <async thread-pool-name="default"/>
+            <timer-service thread-pool-name="default" default-data-store="default-file-store">
+                <data-stores>
+                    <file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
+                </data-stores>
+            </timer-service>
+            <remote connector-ref="http-remoting-connector" thread-pool-name="default"/>
+            <thread-pools>
+                <thread-pool name="default">
+                    <max-threads count="10"/>
+                    <keepalive-time time="100" unit="milliseconds"/>
+                </thread-pool>
+            </thread-pools>
+            <default-security-domain value="other"/>
+            <default-missing-method-permissions-deny-access value="true"/>
+            <log-system-exceptions value="true"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:io:1.1">
+            <worker name="default"/>
+            <buffer-pool name="default"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:infinispan:4.0">
+            <cache-container name="keycloak" jndi-name="infinispan/Keycloak">
+                <local-cache name="realms">
+                    <eviction max-entries="10000" strategy="LRU"/>
+                </local-cache>
+                <local-cache name="users">
+                    <eviction max-entries="10000" strategy="LRU"/>
+                </local-cache>
+                <local-cache name="sessions"/>
+                <local-cache name="offlineSessions"/>
+                <local-cache name="loginFailures"/>
+                <local-cache name="work"/>
+                <local-cache name="authorization">
+                    <eviction max-entries="100" strategy="LRU"/>
+                </local-cache>
+                <local-cache name="keys">
+                    <eviction max-entries="1000" strategy="LRU"/>
+                    <expiration max-idle="3600000"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="server" default-cache="default" module="org.wildfly.clustering.server">
+                <local-cache name="default">
+                    <transaction mode="BATCH"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="web" default-cache="passivation" module="org.wildfly.clustering.web.infinispan">
+                <local-cache name="passivation">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="true" purge="false"/>
+                </local-cache>
+                <local-cache name="persistent">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="false" purge="false"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="ejb" aliases="sfsb" default-cache="passivation" module="org.wildfly.clustering.ejb.infinispan">
+                <local-cache name="passivation">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="true" purge="false"/>
+                </local-cache>
+                <local-cache name="persistent">
+                    <locking isolation="REPEATABLE_READ"/>
+                    <transaction mode="BATCH"/>
+                    <file-store passivation="false" purge="false"/>
+                </local-cache>
+            </cache-container>
+            <cache-container name="hibernate" default-cache="local-query" module="org.hibernate.infinispan">
+                <local-cache name="entity">
+                    <transaction mode="NON_XA"/>
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </local-cache>
+                <local-cache name="local-query">
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </local-cache>
+                <local-cache name="timestamps"/>
+            </cache-container>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jca:4.0">
+            <archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
+            <bean-validation enabled="true"/>
+            <default-workmanager>
+                <short-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </short-running-threads>
+                <long-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </long-running-threads>
+            </default-workmanager>
+            <cached-connection-manager/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jdr:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jmx:1.3">
+            <expose-resolved-model/>
+            <expose-expression-model/>
+            <remoting-connector/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jpa:1.1">
+            <jpa default-datasource="" default-extended-persistence-inheritance="DEEP"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jsf:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:mail:2.0">
+            <mail-session name="default" jndi-name="java:jboss/mail/Default">
+                <smtp-server outbound-socket-binding-ref="mail-smtp"/>
+            </mail-session>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:naming:2.0">
+            <remote-naming/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:remoting:3.0">
+            <endpoint/>
+            <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:request-controller:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:security-manager:1.0">
+            <deployment-permissions>
+                <maximum-set>
+                    <permission class="java.security.AllPermission"/>
+                </maximum-set>
+            </deployment-permissions>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:security:1.2">
+            <security-domains>
+                <security-domain name="other" cache-type="default">
+                    <authentication>
+                        <login-module code="Remoting" flag="optional">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                        <login-module code="RealmDirect" flag="required">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                    </authentication>
+                </security-domain>
+                <security-domain name="jboss-web-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+                <security-domain name="jboss-ejb-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+                <security-domain name="jaspitest" cache-type="default">
+                    <authentication-jaspi>
+                        <login-module-stack name="dummy">
+                            <login-module code="Dummy" flag="optional"/>
+                        </login-module-stack>
+                        <auth-module code="Dummy"/>
+                    </authentication-jaspi>
+                </security-domain>
+            </security-domains>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:transactions:3.0">
+            <core-environment>
+                <process-id>
+                    <uuid/>
+                </process-id>
+            </core-environment>
+            <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:undertow:3.0">
+            <buffer-cache name="default"/>
+            <server name="default-server">
+                <http-listener name="default" socket-binding="http" redirect-socket="proxy-https" proxy-address-forwarding="true"/>
+                <!-- <http-listener name="default" socket-binding="http" redirect-socket="https"/> -->
+                <!-- <https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/> -->
+                <host name="default-host" alias="localhost">
+                    <location name="/" handler="welcome-content"/>
+                    <filter-ref name="server-header"/>
+                    <filter-ref name="x-powered-by-header"/>
+                </host>
+            </server>
+            <servlet-container name="default">
+                <jsp-config/>
+                <websockets/>
+            </servlet-container>
+            <handlers>
+                <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
+            </handlers>
+            <filters>
+                <response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
+                <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
+            </filters>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
+            <web-context>auth</web-context>
+            <providers>
+                <provider>classpath:${jboss.home.dir}/providers/*</provider>
+            </providers>
+            <master-realm-name>master</master-realm-name>
+            <scheduled-task-interval>900</scheduled-task-interval>
+            <theme>
+                <staticMaxAge>2592000</staticMaxAge>
+                <cacheThemes>true</cacheThemes>
+                <cacheTemplates>true</cacheTemplates>
+                <dir>${jboss.home.dir}/themes</dir>
+            </theme>
+            <spi name="eventsStore">
+                <default-provider>jpa</default-provider>
+                <provider name="jpa" enabled="true">
+                    <properties>
+                        <property name="exclude-events" value="[&quot;REFRESH_TOKEN&quot;]"/>
+                    </properties>
+                </provider>
+            </spi>
+            <spi name="realm">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="user">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="userFederatedStorage">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="userCache">
+                <provider name="default" enabled="true"/>
+            </spi>
+            <spi name="userSessionPersister">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="authorizationPersister">
+                <default-provider>jpa</default-provider>
+            </spi>
+            <spi name="timer">
+                <default-provider>basic</default-provider>
+            </spi>
+            <spi name="connectionsHttpClient">
+                <provider name="default" enabled="true"/>
+            </spi>
+            <spi name="connectionsJpa">
+                <provider name="default" enabled="true">
+                    <properties>
+                        <property name="dataSource" value="java:jboss/datasources/KeycloakDS"/>
+                        <property name="initializeEmpty" value="true"/>
+                        <property name="migrationStrategy" value="update"/>
+                        <property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/>
+                    </properties>
+                </provider>
+            </spi>
+            <spi name="realmCache">
+                <provider name="default" enabled="true"/>
+            </spi>
+            <spi name="connectionsInfinispan">
+                <default-provider>default</default-provider>
+                <provider name="default" enabled="true">
+                    <properties>
+                        <property name="cacheContainer" value="java:comp/env/infinispan/Keycloak"/>
+                    </properties>
+                </provider>
+            </spi>
+            <spi name="jta-lookup">
+                <default-provider>${keycloak.jta.lookup.provider:jboss}</default-provider>
+                <provider name="jboss" enabled="true"/>
+            </spi>
+            <spi name="publicKeyStorage">
+                <provider name="infinispan" enabled="true">
+                    <properties>
+                        <property name="minTimeBetweenRequests" value="10"/>
+                    </properties>
+                </provider>
+            </spi>
+        </subsystem>
+    </profile>
+    <interfaces>
+        <interface name="management">
+            <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
+        </interface>
+        <interface name="public">
+            <inet-address value="${jboss.bind.address:127.0.0.1}"/>
+        </interface>
+    </interfaces>
+    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
+        <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
+        <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
+        <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
+        <socket-binding name="http" port="${jboss.http.port:8080}"/>
+        <!-- <socket-binding name="https" port="${jboss.https.port:8443}"/> -->
+        <socket-binding name="proxy-https" port="443"/>
+        <socket-binding name="txn-recovery-environment" port="4712"/>
+        <socket-binding name="txn-status-manager" port="4713"/>
+        <outbound-socket-binding name="mail-smtp">
+            <remote-destination host="localhost" port="25"/>
+        </outbound-socket-binding>
+    </socket-binding-group>
+</server>
diff --git a/ansible/roles/keycloak/templates/vhost.conf.j2 b/ansible/roles/keycloak/templates/vhost.conf.j2
new file mode 100644
index 000000000..b03a0dcf0
--- /dev/null
+++ b/ansible/roles/keycloak/templates/vhost.conf.j2
@@ -0,0 +1,52 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+
+<VirtualHost *:80>
+    ServerName {{ keycloak_vhost_servername }}
+    
+    ## Redirect all http traffic to https
+    RewriteEngine On
+    RewriteCond %{HTTPS} off
+    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
+</VirtualHost>
+
+<VirtualHost *:443>
+    ServerName {{ keycloak_vhost_servername }}
+
+    RequestHeader set X-Forwarded-Proto "https"
+    ProxyPass / "http://localhost:8080/"
+    ProxyPassReverse / "http://localhost:8080/"
+    ProxyPreserveHost On
+    # See https://issues.redhat.com/browse/KEYCLOAK-3067 for more info
+    LimitRequestFieldSize 65536
+
+    ErrorLog /var/log/httpd/keycloak.error.log
+    CustomLog /var/log/httpd/keycloak.requests.log combined
+
+    SSLEngine on
+    # Disable SSLv3 which is vulnerable to the POODLE attack
+    SSLProtocol All -SSLv2 -SSLv3
+    # Created cert with certbot:
+    #   certbot --apache certonly -d iamdev.scigap.org
+    SSLCertificateFile {{ keycloak_ssl_certificate_file }}
+    SSLCertificateChainFile {{ keycloak_ssl_certificate_chain_file }}
+    SSLCertificateKeyFile {{ keycloak_ssl_certificate_key_file }}
+</VirtualHost>
diff --git a/ansible/roles/nginx/handlers/main.yml b/ansible/roles/nginx/handlers/main.yml
new file mode 100644
index 000000000..d99835134
--- /dev/null
+++ b/ansible/roles/nginx/handlers/main.yml
@@ -0,0 +1,25 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: restart nginx
+  service:
+    name: nginx
+    state: restarted
\ No newline at end of file
diff --git a/ansible/roles/nginx/tasks/main.yml b/ansible/roles/nginx/tasks/main.yml
new file mode 100644
index 000000000..7c5fa1544
--- /dev/null
+++ b/ansible/roles/nginx/tasks/main.yml
@@ -0,0 +1,127 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: apt-get update
+  apt:
+    update_cache: yes
+    cache_valid_time: 86400
+  become: yes
+
+- name: install nginx
+  apt:
+    name: nginx
+    state: latest
+  become: yes
+
+- name: allow OpenSSH
+  ufw:
+    rule: allow
+    name: "OpenSSH"
+    state: enabled
+  become: yes
+
+# It is recommended to enable the most restrictive profile
+#  that will still allow the traffic you’ve configured.
+#  Right now, we will only need to allow traffic on port 80.
+- name: allow traffic on port 80
+  ufw:
+    rule: allow
+    name: "Nginx HTTP"
+#    delete: yes
+    state: enabled # enable the ufw rule
+  become: yes
+
+- name: create www directory at "/var/www/{{ ansible_host }}"
+  file:
+    path: /var/www/{{ ansible_host }}
+    state: directory
+    mode: '0775'
+    owner: "{{ user }}"
+    group: "{{ group }}"
+  become: yes
+
+- name: delete default nginx config
+  file:
+    path: /etc/nginx/sites-enabled/default
+    state: absent
+  become: yes
+
+- name: copy sample index.html from {{ inventory_hostname }} to /var/www/{{ ansible_host }}/html
+  template: >
+    src={{ inventory_hostname }}/index.html.j2
+    dest="/var/www/{{ ansible_host }}/index.html"
+    owner="{{ user }}"
+    group="{{ group }}"
+    mode="u=rw,g=r,o=r"
+
+- name: copy nginx site.conf
+  template:
+    src: "{{ inventory_hostname }}/site.conf.j2"
+    dest: /etc/nginx/sites-available/{{ ansible_host }}
+    owner: root
+    group: root
+    mode: '0644'
+  become: yes
+
+- name: link sample html to sites-enabled directory
+  file:
+    src: /etc/nginx/sites-available/{{ ansible_host }}
+    dest: /etc/nginx/sites-enabled/{{ ansible_host }}
+    state: link
+  become: yes
+
+- name: adjust server_names_hash_bucket_size
+  template: >
+    src={{ inventory_hostname }}/nginx.conf.j2
+    dest="/etc/nginx/nginx.conf"
+    owner="{{ user }}"
+    group="{{ group }}"
+    mode="u=rw,g=r,o=r"
+  become: yes
+
+- name: allow HTTPS traffic
+  ufw:
+    rule: allow
+    name: "Nginx Full"
+    state: enabled # enable the ufw rule
+  become: yes
+
+- name: delete redundant Nginx HTTP
+  ufw:
+    rule: allow
+    name: "Nginx HTTP"
+    delete: yes
+    state: enabled # enable the ufw rule
+  become: yes
+
+- name: Restart nginx
+  service:
+    name: nginx
+    state: restarted
+  become: yes
+
+- name: install certbot
+  apt:
+    name:
+      - certbot
+      - python3-certbot-nginx
+    state: latest
+  become: yes
\ No newline at end of file
diff --git a/ansible/roles/nginx/templates/custos/index.html.j2 b/ansible/roles/nginx/templates/custos/index.html.j2
new file mode 100644
index 000000000..da5a6b58a
--- /dev/null
+++ b/ansible/roles/nginx/templates/custos/index.html.j2
@@ -0,0 +1,8 @@
+<html>
+    <head>
+        <title>Welcome to your_domain!</title>
+    </head>
+    <body>
+        <h1>Success!  The your_domain server block is working!</h1>
+    </body>
+</html>
\ No newline at end of file
diff --git a/ansible/roles/nginx/templates/custos/nginx.conf.j2 b/ansible/roles/nginx/templates/custos/nginx.conf.j2
new file mode 100644
index 000000000..706278c7c
--- /dev/null
+++ b/ansible/roles/nginx/templates/custos/nginx.conf.j2
@@ -0,0 +1,85 @@
+user www-data;
+worker_processes auto;
+pid /run/nginx.pid;
+include /etc/nginx/modules-enabled/*.conf;
+
+events {
+	worker_connections 768;
+	# multi_accept on;
+}
+
+http {
+
+	##
+	# Basic Settings
+	##
+
+	sendfile on;
+	tcp_nopush on;
+	tcp_nodelay on;
+	keepalive_timeout 65;
+	types_hash_max_size 2048;
+	# server_tokens off;
+
+	server_names_hash_bucket_size 64;
+	# server_name_in_redirect off;
+
+	include /etc/nginx/mime.types;
+	default_type application/octet-stream;
+
+	##
+	# SSL Settings
+	##
+
+	ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
+	ssl_prefer_server_ciphers on;
+
+	##
+	# Logging Settings
+	##
+
+	access_log /var/log/nginx/access.log;
+	error_log /var/log/nginx/error.log;
+
+	##
+	# Gzip Settings
+	##
+
+	gzip on;
+
+	# gzip_vary on;
+	# gzip_proxied any;
+	# gzip_comp_level 6;
+	# gzip_buffers 16 8k;
+	# gzip_http_version 1.1;
+	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
+
+	##
+	# Virtual Host Configs
+	##
+
+	include /etc/nginx/conf.d/*.conf;
+	include /etc/nginx/sites-enabled/*;
+}
+
+
+#mail {
+#	# See sample authentication script at:
+#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
+#
+#	# auth_http localhost/auth.php;
+#	# pop3_capabilities "TOP" "USER";
+#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
+#
+#	server {
+#		listen     localhost:110;
+#		protocol   pop3;
+#		proxy      on;
+#	}
+#
+#	server {
+#		listen     localhost:143;
+#		protocol   imap;
+#		proxy      on;
+#	}
+#}
diff --git a/ansible/roles/nginx/templates/custos/site.conf.j2 b/ansible/roles/nginx/templates/custos/site.conf.j2
new file mode 100644
index 000000000..a76add09b
--- /dev/null
+++ b/ansible/roles/nginx/templates/custos/site.conf.j2
@@ -0,0 +1,15 @@
+server {
+  listen 80;
+  listen [::]:80;
+
+  listen 443 ssl;
+  ssl_certificate /etc/letsencrypt/live/{{ ansible_host }}/fullchain.pem;
+  ssl_certificate_key /etc/letsencrypt/live/{{ ansible_host }}/privkey.pem;
+
+  root /var/www/{{ ansible_host }}/html;
+  index index.html index.htm index.nginx-debian.html;
+  server_name {{ ansible_host }} www.{{ ansible_host }};
+  location / {
+    try_files $uri $uri/ =404;
+  }
+}
\ No newline at end of file
diff --git a/ansible/roles/nginx/templates/hashicorp/index.html.j2 b/ansible/roles/nginx/templates/hashicorp/index.html.j2
new file mode 100644
index 000000000..da5a6b58a
--- /dev/null
+++ b/ansible/roles/nginx/templates/hashicorp/index.html.j2
@@ -0,0 +1,8 @@
+<html>
+    <head>
+        <title>Welcome to your_domain!</title>
+    </head>
+    <body>
+        <h1>Success!  The your_domain server block is working!</h1>
+    </body>
+</html>
\ No newline at end of file
diff --git a/ansible/roles/nginx/templates/hashicorp/nginx.conf.j2 b/ansible/roles/nginx/templates/hashicorp/nginx.conf.j2
new file mode 100644
index 000000000..706278c7c
--- /dev/null
+++ b/ansible/roles/nginx/templates/hashicorp/nginx.conf.j2
@@ -0,0 +1,85 @@
+user www-data;
+worker_processes auto;
+pid /run/nginx.pid;
+include /etc/nginx/modules-enabled/*.conf;
+
+events {
+	worker_connections 768;
+	# multi_accept on;
+}
+
+http {
+
+	##
+	# Basic Settings
+	##
+
+	sendfile on;
+	tcp_nopush on;
+	tcp_nodelay on;
+	keepalive_timeout 65;
+	types_hash_max_size 2048;
+	# server_tokens off;
+
+	server_names_hash_bucket_size 64;
+	# server_name_in_redirect off;
+
+	include /etc/nginx/mime.types;
+	default_type application/octet-stream;
+
+	##
+	# SSL Settings
+	##
+
+	ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
+	ssl_prefer_server_ciphers on;
+
+	##
+	# Logging Settings
+	##
+
+	access_log /var/log/nginx/access.log;
+	error_log /var/log/nginx/error.log;
+
+	##
+	# Gzip Settings
+	##
+
+	gzip on;
+
+	# gzip_vary on;
+	# gzip_proxied any;
+	# gzip_comp_level 6;
+	# gzip_buffers 16 8k;
+	# gzip_http_version 1.1;
+	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
+
+	##
+	# Virtual Host Configs
+	##
+
+	include /etc/nginx/conf.d/*.conf;
+	include /etc/nginx/sites-enabled/*;
+}
+
+
+#mail {
+#	# See sample authentication script at:
+#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
+#
+#	# auth_http localhost/auth.php;
+#	# pop3_capabilities "TOP" "USER";
+#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
+#
+#	server {
+#		listen     localhost:110;
+#		protocol   pop3;
+#		proxy      on;
+#	}
+#
+#	server {
+#		listen     localhost:143;
+#		protocol   imap;
+#		proxy      on;
+#	}
+#}
diff --git a/ansible/roles/nginx/templates/hashicorp/site.conf.j2 b/ansible/roles/nginx/templates/hashicorp/site.conf.j2
new file mode 100644
index 000000000..3386e504a
--- /dev/null
+++ b/ansible/roles/nginx/templates/hashicorp/site.conf.j2
@@ -0,0 +1,15 @@
+server {
+  listen 80;
+  listen [::]:80;
+
+  listen 443 ssl;
+  ssl_certificate /etc/letsencrypt/live/{{ ansible_host }}/fullchain.pem;
+  ssl_certificate_key /etc/letsencrypt/live/{{ ansible_host }}/privkey.pem;
+
+  root /var/www/{{ ansible_hostname }}/html;
+  index index.html index.htm index.nginx-debian.html;
+  server_name {{ ansible_host }} www.{{ ansible_host }};
+  location / {
+    try_files $uri $uri/ =404;
+  }
+}
\ No newline at end of file
diff --git a/ansible/roles/nginx/templates/keycloak/index.html.j2 b/ansible/roles/nginx/templates/keycloak/index.html.j2
new file mode 100644
index 000000000..da5a6b58a
--- /dev/null
+++ b/ansible/roles/nginx/templates/keycloak/index.html.j2
@@ -0,0 +1,8 @@
+<html>
+    <head>
+        <title>Welcome to your_domain!</title>
+    </head>
+    <body>
+        <h1>Success!  The your_domain server block is working!</h1>
+    </body>
+</html>
\ No newline at end of file
diff --git a/ansible/roles/nginx/templates/keycloak/nginx.conf.j2 b/ansible/roles/nginx/templates/keycloak/nginx.conf.j2
new file mode 100644
index 000000000..706278c7c
--- /dev/null
+++ b/ansible/roles/nginx/templates/keycloak/nginx.conf.j2
@@ -0,0 +1,85 @@
+user www-data;
+worker_processes auto;
+pid /run/nginx.pid;
+include /etc/nginx/modules-enabled/*.conf;
+
+events {
+	worker_connections 768;
+	# multi_accept on;
+}
+
+http {
+
+	##
+	# Basic Settings
+	##
+
+	sendfile on;
+	tcp_nopush on;
+	tcp_nodelay on;
+	keepalive_timeout 65;
+	types_hash_max_size 2048;
+	# server_tokens off;
+
+	server_names_hash_bucket_size 64;
+	# server_name_in_redirect off;
+
+	include /etc/nginx/mime.types;
+	default_type application/octet-stream;
+
+	##
+	# SSL Settings
+	##
+
+	ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
+	ssl_prefer_server_ciphers on;
+
+	##
+	# Logging Settings
+	##
+
+	access_log /var/log/nginx/access.log;
+	error_log /var/log/nginx/error.log;
+
+	##
+	# Gzip Settings
+	##
+
+	gzip on;
+
+	# gzip_vary on;
+	# gzip_proxied any;
+	# gzip_comp_level 6;
+	# gzip_buffers 16 8k;
+	# gzip_http_version 1.1;
+	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
+
+	##
+	# Virtual Host Configs
+	##
+
+	include /etc/nginx/conf.d/*.conf;
+	include /etc/nginx/sites-enabled/*;
+}
+
+
+#mail {
+#	# See sample authentication script at:
+#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
+#
+#	# auth_http localhost/auth.php;
+#	# pop3_capabilities "TOP" "USER";
+#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
+#
+#	server {
+#		listen     localhost:110;
+#		protocol   pop3;
+#		proxy      on;
+#	}
+#
+#	server {
+#		listen     localhost:143;
+#		protocol   imap;
+#		proxy      on;
+#	}
+#}
diff --git a/ansible/roles/nginx/templates/keycloak/site.conf.j2 b/ansible/roles/nginx/templates/keycloak/site.conf.j2
new file mode 100644
index 000000000..824d08a82
--- /dev/null
+++ b/ansible/roles/nginx/templates/keycloak/site.conf.j2
@@ -0,0 +1,33 @@
+upstream keycloak {
+  server localhost:8080 ;
+}
+server {
+   listen 80;
+   server_name bm-dev-2.usecustos.org;
+   return 301 https://bm-dev-2.usecustos.org$request_uri;
+}
+server {
+  listen 443 ssl;
+  server_name {{ ansible_host }};
+  ssl_certificate /etc/letsencrypt/live/{{ ansible_host }}/fullchain.pem;
+  ssl_certificate_key /etc/letsencrypt/live/{{ ansible_host }}/privkey.pem;
+  ssl_prefer_server_ciphers on;
+
+  add_header 'Access-Control-Allow-Origin' '*' always;
+  add_header 'Access-Control-Allow_Credentials' 'true';
+  add_header 'Access-Control-Allow-Headers' 'Authorization,authorization, Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,user-token';
+  add_header  'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
+  rewrite_log on;
+  error_log   /var/log/nginx/error.log;
+
+  location /auth {
+    proxy_set_header Host $host;
+    proxy_set_header X-Real-IP $remote_addr;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header X-Forwarded-Proto https;
+    proxy_set_header X-Forwarded-Host $server_name;
+    proxy_pass         http://keycloak;
+    add_header Strict-Transport-Security "max-age=31536000" always;
+    add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
+  }
+}
\ No newline at end of file
diff --git a/ansible/roles/pkcs12/tasks/main.yml b/ansible/roles/pkcs12/tasks/main.yml
new file mode 100644
index 000000000..b7d41728e
--- /dev/null
+++ b/ansible/roles/pkcs12/tasks/main.yml
@@ -0,0 +1,46 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: "create certs directory"
+  file:
+    path: /{{ user_home }}/certs
+    state: directory
+    mode: '0775'
+    owner: "{{ user }}"
+    group: "{{ group }}"
+
+#- name: Generate PKCS#12 file "{{ ansible_hostname }}-truststore"
+#  community.crypto.openssl_pkcs12:
+#    action: export
+#    path: /{{ user_home }}/certs/{{ pkcs12_filename }}
+#    friendly_name: "{{ ansible_host }}-truststore"
+#    privatekey_path: /etc/letsencrypt/live/{{ ansible_host }}/privkey.pem
+#    certificate_path: /etc/letsencrypt/live/{{ ansible_host }}/fullchain.pem
+#    state: present
+#    mode: 0777 #0700
+#    passphrase: "{{ pkcs12_passphrase }}"
+#  become: yes
+
+#- name: Remove PKCS#12 file
+#  community.crypto.openssl_pkcs12:
+#    path: /{{ user_home }}/certs/{{ pkcs12_filename }}
+#    state: absent
+#  become: yes
diff --git a/ansible/roles/vault/tasks/main.yml b/ansible/roles/vault/tasks/main.yml
new file mode 100644
index 000000000..15061bfeb
--- /dev/null
+++ b/ansible/roles/vault/tasks/main.yml
@@ -0,0 +1,55 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: add gpg key
+  apt_key:
+    url: https://apt.releases.hashicorp.com/gpg
+    state: present
+  become: yes
+
+- name: add hashicorp linux repo
+  apt_repository:
+    repo: deb [arch=amd64] https://apt.releases.hashicorp.com {{ ansible_distribution_release }} main
+    state: present
+  become: yes
+
+# install vault
+- name: Install vault
+  apt:
+    name:
+      - vault
+  become: yes
+
+# configure vault backend with consul
+- name: Configure vault backend with consul
+  template: >
+    src=vault.hcl.j2
+    dest="/etc/vault.d/vault.hcl"
+    owner="{{ user }}"
+    group="{{ group }}"
+    mode="u=rw,g=r,o=r"
+  become: yes
+
+- name: Restart vault
+  ansible.builtin.service:
+    name: vault
+    state: restarted
+  become: yes
\ No newline at end of file
diff --git a/ansible/roles/vault/templates/vault.hcl.j2 b/ansible/roles/vault/templates/vault.hcl.j2
new file mode 100644
index 000000000..5aa3cd26c
--- /dev/null
+++ b/ansible/roles/vault/templates/vault.hcl.j2
@@ -0,0 +1,47 @@
+# Full configuration options can be found at https://www.vaultproject.io/docs/configuration
+
+ui = true
+
+#mlock = true
+#disable_mlock = true
+
+#storage "file" {
+#  path = "/opt/vault/data"
+#}
+
+storage "consul" {
+  address = "127.0.0.1:8500"
+  path    = "vault"
+}
+
+# HTTP listener
+#listener "tcp" {
+#  address = "127.0.0.1:8200"
+#  tls_disable = 1
+#}
+
+# HTTPS listener
+listener "tcp" {
+  address       = "0.0.0.0:8200"
+  tls_cert_file = "/opt/vault/tls/tls.crt"
+  tls_key_file  = "/opt/vault/tls/tls.key"
+}
+
+# Enterprise license_path
+# This will be required for enterprise as of v1.8
+#license_path = "/etc/vault.d/vault.hclic"
+
+# Example AWS KMS auto unseal
+#seal "awskms" {
+#  region = "us-east-1"
+#  kms_key_id = "REPLACE-ME"
+#}
+
+# Example HSM auto unseal
+#seal "pkcs11" {
+#  lib            = "/usr/vault/lib/libCryptoki2_64.so"
+#  slot           = "0"
+#  pin            = "AAAA-BBBB-CCCC-DDDD"
+#  key_label      = "vault-hsm-key"
+#  hmac_key_label = "vault-hsm-hmac-key"
+#}
diff --git a/ansible/roles/zookeeper/handlers/main.yml b/ansible/roles/zookeeper/handlers/main.yml
new file mode 100644
index 000000000..a15d1b2ac
--- /dev/null
+++ b/ansible/roles/zookeeper/handlers/main.yml
@@ -0,0 +1,32 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: start zookeeper
+  service: name=zookeeper state=started enabled=yes
+  become: yes
+
+- name: stop zookeeper
+  service: name=zookeeper state=stopped
+  become: yes
+
+- name: restart zookeeper
+  service: name=zookeeper state=restarted enabled=yes
+  become: yes
diff --git a/ansible/roles/zookeeper/tasks/main.yml b/ansible/roles/zookeeper/tasks/main.yml
new file mode 100644
index 000000000..8f86745e8
--- /dev/null
+++ b/ansible/roles/zookeeper/tasks/main.yml
@@ -0,0 +1,63 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+################################################################################
+# Setup and run Zookeeper
+- name: Download and unarchive zookeeper
+  unarchive: src="{{ zookeeper_url }}"
+      dest="{{ user_home }}"
+      copy=no
+      owner="{{ user }}"
+      group="{{ group }}"
+  become: yes
+
+- name: Copy zoo.cfg file
+  template: src=zoo.cfg.j2 dest="{{ zookeeper_dir }}/conf/zoo.cfg" owner="{{ user }}" group="{{ group }}" mode="u=rw,g=r,o=r"
+  notify:
+    - restart zookeeper
+  become: yes
+
+- name: Copy java.env file
+  template: src=java.env.j2 dest="{{ zookeeper_dir }}/conf/java.env" owner="{{ user }}" group="{{ group }}" mode="u=rw,g=r,o=r"
+  notify:
+    - restart zookeeper
+  become: yes
+
+- name: Check if systemd exists
+  stat: path=/usr/lib/systemd/system/
+  register: systemd_check
+  become: yes
+
+- name: Systemd script.
+  template: src=zookeeper.service.j2 dest=/usr/lib/systemd/system/zookeeper.service
+  when: systemd_check.stat.exists == true
+  notify:
+    - restart zookeeper
+  become: yes
+
+- name: reload systemd daemons
+  command: systemctl daemon-reload
+  become: yes
+
+- name: restart zookeeper
+  service: name=zookeeper state=restarted enabled=yes
+  become: yes
+...
diff --git a/ansible/roles/zookeeper/templates/java.env.j2 b/ansible/roles/zookeeper/templates/java.env.j2
new file mode 100644
index 000000000..356192c81
--- /dev/null
+++ b/ansible/roles/zookeeper/templates/java.env.j2
@@ -0,0 +1,1 @@
+export ZOO_LOG_DIR={{ zookeeper_dir }}/logs
\ No newline at end of file
diff --git a/ansible/roles/zookeeper/templates/zoo.cfg.j2 b/ansible/roles/zookeeper/templates/zoo.cfg.j2
new file mode 100644
index 000000000..0c40776b9
--- /dev/null
+++ b/ansible/roles/zookeeper/templates/zoo.cfg.j2
@@ -0,0 +1,28 @@
+# The number of milliseconds of each tick
+tickTime={{tick_time}}
+# The number of ticks that the initial
+# synchronization phase can take
+initLimit={{init_limit}}
+# The number of ticks that can pass between
+# sending a request and getting an acknowledgement
+syncLimit={{sync_limit}}
+# the directory where the snapshot is stored.
+# do not use /tmp for storage, /tmp here is just
+# example sakes.
+dataDir={{zookeeper_data_dir}}
+# the port at which the clients will connect
+clientPort={{ client_port }}
+# the maximum number of client connections.
+# increase this if you need to handle more clients
+#maxClientCnxns=60
+#
+# Be sure to read the maintenance section of the
+# administrator guide before turning on autopurge.
+#
+# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
+#
+# The number of snapshots to retain in dataDir
+autopurge.snapRetainCount=3
+# Purge task interval in hours
+# Set to "0" to disable auto purge feature
+autopurge.purgeInterval=1
diff --git a/ansible/roles/zookeeper/templates/zookeeper.service.j2 b/ansible/roles/zookeeper/templates/zookeeper.service.j2
new file mode 100644
index 000000000..8e6ea2a2e
--- /dev/null
+++ b/ansible/roles/zookeeper/templates/zookeeper.service.j2
@@ -0,0 +1,16 @@
+# {{ansible_managed}}
+
+[Unit]
+Description=ZooKeeper
+
+
+[Service]
+Type=forking
+ExecStart={{zookeeper_dir}}/bin/zkServer.sh start
+ExecStop={{ zookeeper_dir }}/bin/zkServer.sh stop
+Restart=always
+TimeoutSec=300
+User={{ user }}
+
+[Install]
+WantedBy=multi-user.target
diff --git a/ansible/roles/zookeeper/vars/main.yml b/ansible/roles/zookeeper/vars/main.yml
new file mode 100644
index 000000000..617133449
--- /dev/null
+++ b/ansible/roles/zookeeper/vars/main.yml
@@ -0,0 +1,37 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+#Variables associated with this role
+# zookeeper related variable
+zookeeper_version: 3.4.8
+zookeeper_url: http://archive.apache.org/dist/zookeeper/zookeeper-{{zookeeper_version}}/zookeeper-{{zookeeper_version}}.tar.gz
+
+apt_cache_timeout: 3600
+client_port: "{{ zookeeper_client_port }}" 
+init_limit: 5
+sync_limit: 2
+tick_time: 2000
+data_dir: /var/lib/zookeeper
+log_dir: /var/log/zookeeper
+zookeeper_dir: "{{ user_home }}/zookeeper-{{zookeeper_version}}"
+zookeeper_data_dir: "{{ zookeeper_dir }}/data"
+
+...
diff --git a/custos-core-services-server/src/main/dist/conf/application.properties b/custos-core-services-server/src/main/dist/conf/application.properties
index ae8050478..d70053767 100644
--- a/custos-core-services-server/src/main/dist/conf/application.properties
+++ b/custos-core-services-server/src/main/dist/conf/application.properties
@@ -1,90 +1,90 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+##  specific language governing permissions and limitations
+##  under the License.
+##
 #
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
+#grpc.port=7000
+#server.port=8080
+###spring.zipkin.baseUrl=http://149.165.169.49:9411/
+#spring.application.name=custos-core-services-server
+###spring.sleuth.sampler.probability=1
+#spring.main.allow-bean-definition-overriding=true
+#management.security.enabled=false
+#management.endpoints.web.exposure.include=*
+#management.endpoint.metrics.enabled=true
+#spring.jmx.enabled=true
 #
-# http://www.apache.org/licenses/LICENSE-2.0
+#spring.datasource.url = jdbc:mysql://@mysql.host@:3306/core-services-db?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false&createDatabaseIfNotExist=true
+#spring.datasource.username = @spring.datasource.username@
+#spring.datasource.password = @spring.datasource.password@
 #
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-#  specific language governing permissions and limitations
-#  under the License.
 #
-
-grpc.port=7000
-server.port=8080
-##spring.zipkin.baseUrl=http://149.165.169.49:9411/
-spring.application.name=custos-core-services-server
-##spring.sleuth.sampler.probability=1
-spring.main.allow-bean-definition-overriding=true
-management.security.enabled=false
-management.endpoints.web.exposure.include=*
-management.endpoint.metrics.enabled=true
-spring.jmx.enabled=true
-
-spring.datasource.url = jdbc:mysql://@mysql.host@:3306/core-services-db?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false&createDatabaseIfNotExist=true
-spring.datasource.username = @spring.datasource.username@
-spring.datasource.password = @spring.datasource.password@
-
-
-## Hibernate Properties
-# The SQL dialect makes Hibernate generate better SQL for the chosen database
-spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
-spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
-# Hibernate ddl auto (create, create-drop, validate, update)
-spring.jpa.hibernate.ddl-auto = update
-spring.profiles.active=@spring.profiles.active@
-logging.level.root=INFO
-
-
-ciLogon.admin.client.id=${cilogon.production.id}
-ciLogon.admin.client.secret=${cilogon.production.sec}
-ciLogon.admin.auth.endpoint=https://test.cilogon.org/oauth2/oidc-cm
-
-
-iam.server.client.id=admin-cli
-iam.server.truststore.path=/home/ubuntu/keystore/keycloak-client-truststore.pkcs12
-iam.server.truststore.password=keycloak
-iam.server.url=https://keycloak.custos.scigap.org:31000/auth/
-iam.server.admin.username=${iam.dev.username}
-iam.server.admin.password=${iam.dev.password}
-iam.server.super.admin.realm.id=master
-iam.federated.cilogon.authorization.endpoint=https://cilogon.org/authorize
-iam.federated.cilogon.token.endpoint=https://cilogon.org/oauth2/token
-iam.federated.cilogon.token.userinfo.endpoint=https://cilogon.org/oauth2/userinfo
-iam.federated.cilogon.issuer=https://cilogon.org
-iam.federated.cilogon.jwksUri=https://cilogon.org/oauth2/certs
-introspection.endpoint=https://custos.scigap.org:32036/identity-management/v1.0.0/token/introspect
-issuer=https://custos.scigap.org/
-authorization.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/authorize
-token.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/token
-end.session.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/logout
-user.info.endpoint=https://custos.scigap.org/apiserver/user-management/v1.0.0/userinfo
-jwks_uri=https://custos.scigap.org/apiserver/identity-management/v1.0.0/certs
-registration.endpoint=https://custos.scigap.org/apiserver/tenant-management/v1.0.0/oauth2/tenant
-cluster.management.core.service.dns.name=cluster-management-core-service.keycloak.svc.cluster.local
-cluster.management.core.service.port=7000
-
-
-custos.identity.auth.cache.enabled=true
-custos.identity.auth.cache.size=1024
-
-
-
-core.messaging.service.broker.url=custos07.sciencegateways.iu.edu:9092
-core.messaging.service.publisher.id=custosEventPublisher
-mail.smtp.auth=true
-mail.smtp.starttls.enable=true
-mail.smtp.host=smtp.gmail.com
-mail.smtp.port=587
-mail.smtp.ssl.trust=smtp.gmail.com
-mail.sender.username=custosemailagent@gmail.com
-mail.sender.password=${custos.email.password}
-user.profile.core.service.dns.name=user-profile-core-service.custos.svc.cluster.local
-user.profile.core.service.port=7000
+### Hibernate Properties
+## The SQL dialect makes Hibernate generate better SQL for the chosen database
+#spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
+#spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
+## Hibernate ddl auto (create, create-drop, validate, update)
+#spring.jpa.hibernate.ddl-auto = update
+#spring.profiles.active=@spring.profiles.active@
+#logging.level.root=INFO
+#
+#
+#ciLogon.admin.client.id=${cilogon.production.id}
+#ciLogon.admin.client.secret=${cilogon.production.sec}
+#ciLogon.admin.auth.endpoint=https://test.cilogon.org/oauth2/oidc-cm
+#
+#
+#iam.server.client.id=admin-cli
+#iam.server.truststore.path=/home/ubuntu/keystore/keycloak-client-truststore.pkcs12
+#iam.server.truststore.password=keycloak
+#iam.server.url=https://keycloak.custos.scigap.org:31000/auth/
+#iam.server.admin.username=${iam.dev.username}
+#iam.server.admin.password=${iam.dev.password}
+#iam.server.super.admin.realm.id=master
+#iam.federated.cilogon.authorization.endpoint=https://cilogon.org/authorize
+#iam.federated.cilogon.token.endpoint=https://cilogon.org/oauth2/token
+#iam.federated.cilogon.token.userinfo.endpoint=https://cilogon.org/oauth2/userinfo
+#iam.federated.cilogon.issuer=https://cilogon.org
+#iam.federated.cilogon.jwksUri=https://cilogon.org/oauth2/certs
+#introspection.endpoint=https://custos.scigap.org:32036/identity-management/v1.0.0/token/introspect
+#issuer=https://custos.scigap.org/
+#authorization.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/authorize
+#token.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/token
+#end.session.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/logout
+#user.info.endpoint=https://custos.scigap.org/apiserver/user-management/v1.0.0/userinfo
+#jwks_uri=https://custos.scigap.org/apiserver/identity-management/v1.0.0/certs
+#registration.endpoint=https://custos.scigap.org/apiserver/tenant-management/v1.0.0/oauth2/tenant
+#cluster.management.core.service.dns.name=cluster-management-core-service.keycloak.svc.cluster.local
+#cluster.management.core.service.port=7000
+#
+#
+#custos.identity.auth.cache.enabled=true
+#custos.identity.auth.cache.size=1024
+#
+#
+#
+#core.messaging.service.broker.url=custos07.sciencegateways.iu.edu:9092
+#core.messaging.service.publisher.id=custosEventPublisher
+#mail.smtp.auth=true
+#mail.smtp.starttls.enable=true
+#mail.smtp.host=smtp.gmail.com
+#mail.smtp.port=587
+#mail.smtp.ssl.trust=smtp.gmail.com
+#mail.sender.username=custosemailagent@gmail.com
+#mail.sender.password=${custos.email.password}
+#user.profile.core.service.dns.name=user-profile-core-service.custos.svc.cluster.local
+#user.profile.core.service.port=7000
diff --git a/custos-core-services-server/src/main/dist/conf/bootstrap.properties b/custos-core-services-server/src/main/dist/conf/bootstrap.properties
index cb3a49eb7..69c021b82 100644
--- a/custos-core-services-server/src/main/dist/conf/bootstrap.properties
+++ b/custos-core-services-server/src/main/dist/conf/bootstrap.properties
@@ -1,26 +1,26 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+##  specific language governing permissions and limitations
+##  under the License
 #
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-#  specific language governing permissions and limitations
-#  under the License
-
-spring.cloud.vault.token=${vault.token}
-spring.cloud.vault.scheme=${vault.scheme}
-spring.cloud.vault.host=${vault.host}
-spring.cloud.vault.port=${vault.port}
-spring.cloud.vault.uri=${vault.uri}
-spring.cloud.vault.authentication=token
-spring.cloud.vault.ssl.trust-store=file:home/ubuntu/vault-client-truststore.pkcs12
-spring.cloud.vault.ssl.trust-store-password=vaultpass
\ No newline at end of file
+#spring.cloud.vault.token=${vault.token}
+#spring.cloud.vault.scheme=${vault.scheme}
+#spring.cloud.vault.host=${vault.host}
+#spring.cloud.vault.port=${vault.port}
+#spring.cloud.vault.uri=${vault.uri}
+#spring.cloud.vault.authentication=token
+#spring.cloud.vault.ssl.trust-store=file:home/ubuntu/vault-client-truststore.pkcs12
+#spring.cloud.vault.ssl.trust-store-password=vaultpass
\ No newline at end of file
diff --git a/custos-core-services-server/src/main/dist/conf/keycloak-client-truststore.pkcs12 b/custos-core-services-server/src/main/dist/conf/keycloak-client-truststore.pkcs12
old mode 100644
new mode 100755
index 7b45d5e27..d36c2ce3f
Binary files a/custos-core-services-server/src/main/dist/conf/keycloak-client-truststore.pkcs12 and b/custos-core-services-server/src/main/dist/conf/keycloak-client-truststore.pkcs12 differ
diff --git a/custos-core-services-server/src/main/dist/conf/vault-client-truststore.pkcs12 b/custos-core-services-server/src/main/dist/conf/vault-client-truststore.pkcs12
old mode 100644
new mode 100755
index 95cb1b2cd..770aadb29
Binary files a/custos-core-services-server/src/main/dist/conf/vault-client-truststore.pkcs12 and b/custos-core-services-server/src/main/dist/conf/vault-client-truststore.pkcs12 differ
diff --git a/custos-core-services-server/src/main/resources/application.properties b/custos-core-services-server/src/main/resources/application.properties
index c0467e7bb..13d454f17 100644
--- a/custos-core-services-server/src/main/resources/application.properties
+++ b/custos-core-services-server/src/main/resources/application.properties
@@ -1,90 +1,90 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+##  specific language governing permissions and limitations
+##  under the License.
+##
 #
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
+#grpc.port=7000
+#server.port=8080
+###spring.zipkin.baseUrl=http://149.165.169.49:9411/
+#spring.application.name=agentProfileCoreService
+###spring.sleuth.sampler.probability=1
+#spring.main.allow-bean-definition-overriding=true
+#management.security.enabled=false
+#management.endpoints.web.exposure.include=*
+#management.endpoint.metrics.enabled=true
+#spring.jmx.enabled=true
 #
-# http://www.apache.org/licenses/LICENSE-2.0
+#spring.datasource.url = jdbc:mysql://@mysql.host@:3306/core-services-db?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false&createDatabaseIfNotExist=true
+#spring.datasource.username = @spring.datasource.username@
+#spring.datasource.password = @spring.datasource.password@
 #
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-#  specific language governing permissions and limitations
-#  under the License.
 #
-
-grpc.port=7000
-server.port=8080
-##spring.zipkin.baseUrl=http://149.165.169.49:9411/
-spring.application.name=agentProfileCoreService
-##spring.sleuth.sampler.probability=1
-spring.main.allow-bean-definition-overriding=true
-management.security.enabled=false
-management.endpoints.web.exposure.include=*
-management.endpoint.metrics.enabled=true
-spring.jmx.enabled=true
-
-spring.datasource.url = jdbc:mysql://@mysql.host@:3306/core-services-db?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false&createDatabaseIfNotExist=true
-spring.datasource.username = @spring.datasource.username@
-spring.datasource.password = @spring.datasource.password@
-
-
-## Hibernate Properties
-# The SQL dialect makes Hibernate generate better SQL for the chosen database
-spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
-spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
-# Hibernate ddl auto (create, create-drop, validate, update)
-spring.jpa.hibernate.ddl-auto = update
-spring.profiles.active=@spring.profiles.active@
-logging.level.root=INFO
-
-
-ciLogon.admin.client.id=${cilogon.production.id}
-ciLogon.admin.client.secret=${cilogon.production.sec}
-ciLogon.admin.auth.endpoint=https://test.cilogon.org/oauth2/oidc-cm
-
-
-iam.server.client.id=admin-cli
-iam.server.truststore.path=/home/ubuntu/keystore/keycloak-client-truststore.pkcs12
-iam.server.truststore.password=keycloak
-iam.server.url=https://keycloak.custos.scigap.org:31000/auth/
-iam.server.admin.username=${iam.dev.username}
-iam.server.admin.password=${iam.dev.password}
-iam.server.super.admin.realm.id=master
-iam.federated.cilogon.authorization.endpoint=https://cilogon.org/authorize
-iam.federated.cilogon.token.endpoint=https://cilogon.org/oauth2/token
-iam.federated.cilogon.token.userinfo.endpoint=https://cilogon.org/oauth2/userinfo
-iam.federated.cilogon.issuer=https://cilogon.org
-iam.federated.cilogon.jwksUri=https://cilogon.org/oauth2/certs
-introspection.endpoint=https://custos.scigap.org:32036/identity-management/v1.0.0/token/introspect
-issuer=https://custos.scigap.org/
-authorization.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/authorize
-token.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/token
-end.session.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/logout
-user.info.endpoint=https://custos.scigap.org/apiserver/user-management/v1.0.0/userinfo
-jwks_uri=https://custos.scigap.org/apiserver/identity-management/v1.0.0/certs
-registration.endpoint=https://custos.scigap.org/apiserver/tenant-management/v1.0.0/oauth2/tenant
-cluster.management.core.service.dns.name=cluster-management-core-service.keycloak.svc.cluster.local
-cluster.management.core.service.port=7000
-
-
-custos.identity.auth.cache.enabled=true
-custos.identity.auth.cache.size=1024
-
-
-
-core.messaging.service.broker.url=custos07.sciencegateways.iu.edu:9092
-core.messaging.service.publisher.id=custosEventPublisher
-mail.smtp.auth=true
-mail.smtp.starttls.enable=true
-mail.smtp.host=smtp.gmail.com
-mail.smtp.port=587
-mail.smtp.ssl.trust=smtp.gmail.com
-mail.sender.username=custosemailagent@gmail.com
-mail.sender.password=${custos.email.password}
-user.profile.core.service.dns.name=user-profile-core-service.custos.svc.cluster.local
-user.profile.core.service.port=7000
+### Hibernate Properties
+## The SQL dialect makes Hibernate generate better SQL for the chosen database
+#spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
+#spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
+## Hibernate ddl auto (create, create-drop, validate, update)
+#spring.jpa.hibernate.ddl-auto = update
+#spring.profiles.active=@spring.profiles.active@
+#logging.level.root=INFO
+#
+#
+#ciLogon.admin.client.id=${cilogon.production.id}
+#ciLogon.admin.client.secret=${cilogon.production.sec}
+#ciLogon.admin.auth.endpoint=https://test.cilogon.org/oauth2/oidc-cm
+#
+#
+#iam.server.client.id=admin-cli
+#iam.server.truststore.path=/home/ubuntu/keystore/keycloak-client-truststore.pkcs12
+#iam.server.truststore.password=keycloak
+#iam.server.url=https://keycloak.custos.scigap.org:31000/auth/
+#iam.server.admin.username=${iam.dev.username}
+#iam.server.admin.password=${iam.dev.password}
+#iam.server.super.admin.realm.id=master
+#iam.federated.cilogon.authorization.endpoint=https://cilogon.org/authorize
+#iam.federated.cilogon.token.endpoint=https://cilogon.org/oauth2/token
+#iam.federated.cilogon.token.userinfo.endpoint=https://cilogon.org/oauth2/userinfo
+#iam.federated.cilogon.issuer=https://cilogon.org
+#iam.federated.cilogon.jwksUri=https://cilogon.org/oauth2/certs
+#introspection.endpoint=https://custos.scigap.org:32036/identity-management/v1.0.0/token/introspect
+#issuer=https://custos.scigap.org/
+#authorization.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/authorize
+#token.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/token
+#end.session.endpoint=https://custos.scigap.org/apiserver/identity-management/v1.0.0/logout
+#user.info.endpoint=https://custos.scigap.org/apiserver/user-management/v1.0.0/userinfo
+#jwks_uri=https://custos.scigap.org/apiserver/identity-management/v1.0.0/certs
+#registration.endpoint=https://custos.scigap.org/apiserver/tenant-management/v1.0.0/oauth2/tenant
+#cluster.management.core.service.dns.name=cluster-management-core-service.keycloak.svc.cluster.local
+#cluster.management.core.service.port=7000
+#
+#
+#custos.identity.auth.cache.enabled=true
+#custos.identity.auth.cache.size=1024
+#
+#
+#
+#core.messaging.service.broker.url=custos07.sciencegateways.iu.edu:9092
+#core.messaging.service.publisher.id=custosEventPublisher
+#mail.smtp.auth=true
+#mail.smtp.starttls.enable=true
+#mail.smtp.host=smtp.gmail.com
+#mail.smtp.port=587
+#mail.smtp.ssl.trust=smtp.gmail.com
+#mail.sender.username=custosemailagent@gmail.com
+#mail.sender.password=${custos.email.password}
+#user.profile.core.service.dns.name=user-profile-core-service.custos.svc.cluster.local
+#user.profile.core.service.port=7000
diff --git a/custos-core-services-server/src/main/resources/bootstrap.properties b/custos-core-services-server/src/main/resources/bootstrap.properties
index cb3a49eb7..75aaee3e2 100644
--- a/custos-core-services-server/src/main/resources/bootstrap.properties
+++ b/custos-core-services-server/src/main/resources/bootstrap.properties
@@ -1,26 +1,26 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+##  specific language governing permissions and limitations
+##  under the License
 #
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-#  specific language governing permissions and limitations
-#  under the License
-
-spring.cloud.vault.token=${vault.token}
-spring.cloud.vault.scheme=${vault.scheme}
-spring.cloud.vault.host=${vault.host}
-spring.cloud.vault.port=${vault.port}
-spring.cloud.vault.uri=${vault.uri}
-spring.cloud.vault.authentication=token
-spring.cloud.vault.ssl.trust-store=file:home/ubuntu/vault-client-truststore.pkcs12
-spring.cloud.vault.ssl.trust-store-password=vaultpass
\ No newline at end of file
+#spring.cloud.vault.token=${vault_token}
+#spring.cloud.vault.scheme=${vault_scheme}
+#spring.cloud.vault.host=${vault_host}
+#spring.cloud.vault.port=${vault_port}
+#spring.cloud.vault.uri=${vault_uri}
+#spring.cloud.vault.authentication=token
+#spring.cloud.vault.ssl.trust-store=file:home/ubuntu/vault-client-truststore.pkcs12
+#spring.cloud.vault.ssl.trust-store-password=vaultpass
\ No newline at end of file
diff --git a/custos-core-services-server/src/main/resources/keycloak-client-truststore.pkcs12 b/custos-core-services-server/src/main/resources/keycloak-client-truststore.pkcs12
old mode 100644
new mode 100755
index 7b45d5e27..d36c2ce3f
Binary files a/custos-core-services-server/src/main/resources/keycloak-client-truststore.pkcs12 and b/custos-core-services-server/src/main/resources/keycloak-client-truststore.pkcs12 differ
diff --git a/custos-core-services-server/src/main/resources/vault-client-truststore.pkcs12 b/custos-core-services-server/src/main/resources/vault-client-truststore.pkcs12
old mode 100644
new mode 100755
index 95cb1b2cd..770aadb29
Binary files a/custos-core-services-server/src/main/resources/vault-client-truststore.pkcs12 and b/custos-core-services-server/src/main/resources/vault-client-truststore.pkcs12 differ
diff --git a/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/KeycloakUtils.java b/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/KeycloakUtils.java
index f79fdb6cd..3d7d184e8 100644
--- a/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/KeycloakUtils.java
+++ b/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/KeycloakUtils.java
@@ -148,7 +148,6 @@ private static KeyStore loadKeyStore(String trustStorePath, String trustorePassw
     public static SSLContext initializeTrustStoreManager(String trustStorePath, String trustStorePassword,
                                                          String profile, ClusterManagementClient clusterManagementClient) throws
             IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, KeyManagementException {
-
         KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
         if (profile.equals("staging") || profile.equals("production")) {
             GetServerCertificateRequest getServerCertificateRequest = GetServerCertificateRequest
diff --git a/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/auth/KeycloakAuthClient.java b/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/auth/KeycloakAuthClient.java
index bc973d97a..ed4d3726e 100644
--- a/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/auth/KeycloakAuthClient.java
+++ b/custos-federated-services-clients/src/main/java/org/apache/custos/federated/services/clients/keycloak/auth/KeycloakAuthClient.java
@@ -124,7 +124,6 @@ public void initializeSecurity() throws CertificateException, NoSuchAlgorithmExc
         }
     }
 
-
     public String authenticate(String clientId, String clientSecret, String realmId, String username, String password) {
 
         try {
diff --git a/custos-integration-services/agent-management-service/pom.xml b/custos-integration-services/agent-management-service/pom.xml
index 931cddcf2..53156c157 100644
--- a/custos-integration-services/agent-management-service/pom.xml
+++ b/custos-integration-services/agent-management-service/pom.xml
@@ -22,7 +22,7 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>agent-management-service-parent</artifactId>
+        <artifactId>custos-integration-services</artifactId>
         <groupId>org.apache.custos</groupId>
        <version>1.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
diff --git a/custos-integration-services/group-management-service/pom.xml b/custos-integration-services/group-management-service/pom.xml
index f3976f017..3b9088253 100644
--- a/custos-integration-services/group-management-service/pom.xml
+++ b/custos-integration-services/group-management-service/pom.xml
@@ -22,7 +22,7 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>group-management-service-parent</artifactId>
+        <artifactId>custos-integration-services</artifactId>
         <groupId>org.apache.custos</groupId>
        <version>1.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
diff --git a/custos-integration-services/identity-management-service/pom.xml b/custos-integration-services/identity-management-service/pom.xml
index 02fd5f0dc..50a4f0baa 100644
--- a/custos-integration-services/identity-management-service/pom.xml
+++ b/custos-integration-services/identity-management-service/pom.xml
@@ -22,7 +22,7 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>identity-management-service-parent</artifactId>
+        <artifactId>custos-integration-services</artifactId>
         <groupId>org.apache.custos</groupId>
        <version>1.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
diff --git a/custos-integration-services/log-management-service/pom.xml b/custos-integration-services/log-management-service/pom.xml
index c0585420a..5d4752446 100644
--- a/custos-integration-services/log-management-service/pom.xml
+++ b/custos-integration-services/log-management-service/pom.xml
@@ -22,7 +22,7 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>log-management-service-parent</artifactId>
+        <artifactId>custos-integration-services</artifactId>
         <groupId>org.apache.custos</groupId>
        <version>1.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
diff --git a/custos-integration-services/resource-secret-management-service/pom.xml b/custos-integration-services/resource-secret-management-service/pom.xml
index 28dde53f3..badd0d1d7 100644
--- a/custos-integration-services/resource-secret-management-service/pom.xml
+++ b/custos-integration-services/resource-secret-management-service/pom.xml
@@ -22,7 +22,7 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>resource-secret-management-service-parent</artifactId>
+        <artifactId>custos-integration-services</artifactId>
         <groupId>org.apache.custos</groupId>
        <version>1.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
diff --git a/custos-integration-services/sharing-management-service/pom.xml b/custos-integration-services/sharing-management-service/pom.xml
index 3c3d83605..8b7902caa 100644
--- a/custos-integration-services/sharing-management-service/pom.xml
+++ b/custos-integration-services/sharing-management-service/pom.xml
@@ -22,7 +22,7 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>sharing-management-service-parent</artifactId>
+        <artifactId>custos-integration-services</artifactId>
         <groupId>org.apache.custos</groupId>
        <version>1.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
diff --git a/custos-integration-services/tenant-management-service/pom.xml b/custos-integration-services/tenant-management-service/pom.xml
index b92afc346..d7a22e0d4 100644
--- a/custos-integration-services/tenant-management-service/pom.xml
+++ b/custos-integration-services/tenant-management-service/pom.xml
@@ -22,7 +22,7 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>tenant-management-service-parent</artifactId>
+        <artifactId>custos-integration-services</artifactId>
         <groupId>org.apache.custos</groupId>
        <version>1.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
diff --git a/custos-integration-services/user-management-service/pom.xml b/custos-integration-services/user-management-service/pom.xml
index c00723ae8..8998d594e 100644
--- a/custos-integration-services/user-management-service/pom.xml
+++ b/custos-integration-services/user-management-service/pom.xml
@@ -22,7 +22,7 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>user-management-service-parent</artifactId>
+        <artifactId>custos-integration-services</artifactId>
         <groupId>org.apache.custos</groupId>
        <version>1.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>


Test patch:
diff --git a/ansible/inventories/test/group_vars/all/vars.yml b/ansible/inventories/test/group_vars/all/vars.yml
new file mode 100644
index 000000000..bb56a2337
--- /dev/null
+++ b/ansible/inventories/test/group_vars/all/vars.yml
@@ -0,0 +1,75 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+ansible_connection: ssh
+
+user: exouser
+group: exouser
+user_home: "/home/{{ user }}"
+
+# Domain names for VMs
+keycloak_domain: "{{ hostvars['keycloak']['domain'] }}"
+hashicorp_domain: "{{ hostvars['hashicorp']['domain'] }}"
+custos_domain: "{{ hostvars['custos']['domain'] }}"
+
+# deployment related variables
+custos_deployment_dir: "{{ user_home }}/custos-deployment"
+custos_source_dir: "{{ user_home }}/custos-source"
+custos_repo: "https://github.com/apache/airavata-custos.git"
+custos_git_branch: berametal
+custos_integration_services_source_dir: "{{ user_home }}/custos_integration_services_source"
+custos_core_services_source_dir: "{{ user_home }}/custos_core_services_source"
+custos_distribution_version: 1.1-SNAPSHOT
+
+# kafka variables
+kafka_listener_port: 9092
+kafka_url: "{{ ansible_host }}:9092"
+zookeeper_client_port: 2181
+zookeeper_connection_url: localhost:2181
+zookeeper_connection_timeout: 18000
+
+custos_host: "{{ hostvars['custos'].ansible_host }}"
+custos_port: 31499
+
+# Letsencrypt
+letsencrypt_email: "abhinav7sinha@gmail.com"
+
+#Keycloak
+keycloak_vhost_servername: "{{ hostvars['keycloak'].ansible_host }}"
+keycloak_repo: https://github.com/keycloak/keycloak.git
+keycloak_source_dir: "{{ user_home }}/keycloak-source"
+
+# Database related variables
+db_name: core_services_server_db
+
+sharing_subnets:
+  - "149.165.152.112/16"
+#  - "140.182.0.0/16"
+#  - "149.165.0.0/16"
+#  - "192.68.133.0/24"
+#  - "192.12.206.0/24"
+#  - "149.159.0.0/16"
+#  - "156.56.0.0/16"
+#  - "149.161.0.0/16"
+#  - "149.160.0.0/16"
+#  - "149.166.0.0/16"
+#  - "134.68.0.0/16"
+#  - "129.79.0.0/16"
diff --git a/ansible/inventories/test/group_vars/all/vault.yml b/ansible/inventories/test/group_vars/all/vault.yml
new file mode 100644
index 000000000..193bfa159
--- /dev/null
+++ b/ansible/inventories/test/group_vars/all/vault.yml
@@ -0,0 +1,345 @@
+$ANSIBLE_VAULT;1.1;AES256
+63663730343730656130666164396165313633343830653361616138343635646461613066613461
+3933386163396630323334313138316662663162323064610a663738306439613866336632336663
+61666134646462613938383964313836376537646264623064333237303832323066356666336130
+6164633039326131620a626165303339613637373330323933666537663761646234636432613336
+32663062653238373866626433343832313036633733633234613233653032636637333531613531
+35383638333463353439373231333139613731346262636236306232666330656162636464306461
+38353238306537306430356130656462663430373465323730353330343062623138636634636432
+31336261623363633537663038393465656331633630393236386166646634346333386239313062
+32326265666533363561343333383564313866376365356464623136323461323763623863383530
+33613835393939343663353431643731633837636363303764366336653533623338633333306162
+34643765343930333038323166386536666230306134616337376337623033633766343237636639
+36326139353865653638643466396437316661626430393433333064373834313435646231663832
+30373630663865653538316566386164393739353266666132343531383264343266366436313933
+61386236383535653966386662623637323663336638616461333538613033353835343538346234
+62343638303339393439636263316365363530393865663661323665363664383336663035653031
+30343033333830333037666336323436383434303738373263643438313833393061666538636436
+35376331663133356231616537303430613832393837393831343938313462353138343236633330
+30326434646464346263653461663035356235363633353932386133653637333434316430393037
+66383764356537666638636463373063656566633336623130373464363262646532613339663239
+33353231636664643663373461366261383335323065396466363564383031366436666538326632
+61303832653437313361666262316538383863653461313035613939663265663832303464656236
+66636232396465363366306233383862396430376630613531663035363766396230643636333033
+30363536373264393361633164396538386238336662316536643564643339326235353231346262
+39363961333635303964323462313633393466363139653939363735333765656630613232623339
+34363164323366626436656565336462393430356561386534366366316630323237666335396333
+33376364633835653235646236393838336530386163373464353139383163323332396234663765
+30653933666466353338633764383361323238383065303931336235626538613234636430656662
+37306665343030666536316237626139656435613530326661353834343032633962306362356365
+33616537643266393539313464323233383434373738636663306631343433386336316536383432
+37663265386264373639666235626364643961366134666564656632623433623338613236346236
+36323662663431346661313435353265393463653134316639336665633736333536316238356333
+31633332363866353737633366653631353234366538623031343162356564393161653835393761
+61323866343732313337626230363065653832303332363764353131633064616433383361333464
+35623461323065393764316265613064303332323131313031653061393230626134323333316231
+65663539326164313133623666643330346134393763366264373963643733636238303035633136
+65656137313735653831383062333530363866616437646134613033326238633639333639323937
+33326333373161393732303739643263616566313464646161396266656139613930653565316634
+61343565306435343065393666636235633462613131336335343935386233306161653338383338
+39313765323838663233333561663337623233323364336636353039326138636533623730616161
+32383235626136643261333639333139373565633532613537393934303162316330663034636330
+36313862383462383565396338366230313266386230663338633262663630353663383031333264
+35653739313834343232346638643339396133626638356430626564643563353735316530306432
+32616636383737643935356666353763646435633961383631393537613065613733663036646661
+64343035326334353736393665303033653139626561316138366334383162353838323537656538
+35383935663830613030383234306235383761306263653434613065646661653564626564353062
+37633066656662313365353638623230333463373237373462313561373137636133383266333831
+33393663613866373131636630373364373435663566326339653039313231366438376537353132
+63353562373131386262636139613036383033663432346438643032323864373938633938303931
+37373032383266646161353664323438393837393038326439646262636334613262396361353433
+35343233363532626466636165353935333162663861376165633338666633333833303534626235
+32643965373734336666323834393233393139343234306461366235346362326631386434653138
+37623036393066346561616437633164633037633631393765653937666362633539613462656533
+31373631633038343934353237613931343864626533373930346530356334656163623265323834
+39316235363934316565323430616237383338313335363136333665353964346636663866383034
+63646138353338363764313561333038373735313064616336333337306530633438323633613637
+64653837366336326637316131383338373039373534633435316265663763363732306565643138
+37643036363336336137643035633333393830653066363939303837373734363262376537306230
+36396137383639376534633163376437633331313133386337366536643935636561336332333432
+33313230613465656233353638303064636238366631313839396537306131323830316438336433
+32386166316265636263383764383135616232316338396439656238613363646337656566356631
+64366461323539613430383964633337383130393764353030356564626132643932303434326364
+33633336323761326262383432326164643335306564666533633566376632323135373236323465
+32643232373032333339633532323435336230336164383132363034303361313637373764636438
+66636466633436636466366437343064346463366661663632393138356261336165303535326533
+30396363623737666563336564363433396431353337336330386435663636306461343631333566
+38343861643461653032306230303938633238383534386361633235653034353635323566313830
+34323736656136396462383361623164353230666530333166663033316464623662376135643137
+31326361323131343338333363633039653162363265393432613033386431323634643736666139
+64656166333937333566623263323231366131666565623563646430323363646437643834616438
+62643831356633393861363762323938383561366431643331646564343666636435616363653662
+30373262306138343364313763373136613531346338636235653365643736323836313866373030
+62306466346236643435616461646130323831316137613238613565383837376239326565623335
+37646262623439646566386264376233383462336230326164386163386130323663373936356338
+32393233623533346435646632666165623463393161643237383635313762323864373832336231
+37626530383865323331663239363831623964636237336430363935313263306633373039613136
+64383061393962626263326138343961353236643233653733656235623665353264343963343839
+34336138346531643665333563303433323733303565363835323833343034336339663136333635
+32613562333264383136306532366161626265353163353366363535333962643131343230373063
+64303431623030396135316337653862623336666439653035653330633636663732383937376236
+35333831353237366464313739316537336439353663613034323434386562363533656463643334
+66353239636262333435373439643963396466303834303438636135323234356262643936356330
+39373130656533643039646165373539393533646232656130346365623239616632616564656633
+33613032333339353433393730616430343539613539373235366365313133613039323465326533
+38323033386364323434323634343564343866366337373164346464643538333639653033626238
+64383666633235303133343333326230396631353631353236353462306265343162613536666538
+31326165643037333734663661353166656462333831383162613230313938316264346261386535
+64376538333061343963363635616535356262666135636336383534303538643230613762633339
+30393030383339623962313734383563323034303963356534306130383863326636396166326161
+32656634363639356131353436316563653463666537396432636333306638633461313662656563
+37383837306661323536303661613333323164666338353034616430333661323966323134383836
+36613238643436336565633136373336336536626465626231376234363163666430613866653331
+33366565373333343530666331373733333031346166393561383433336662346566663533343734
+66393563643862666266336362376564636135666432643765396362623065656131663737303135
+38643730323363356366623735623862613465363566636366623361633631306361383435336461
+34626166383537396336353139613364336133393265353038393735613936346334626232373664
+61303662353534333637353832356432653530313765666338626464663038613036663666643032
+63663635666365383234306161353465336434373834626263376533653632383765376430303836
+62636338613066303066363966346235666131363531333362303336313233316635636131633737
+33663265363761326337373339343433366264306630303865663433626130623736323264396263
+36333763363333383062623165323065346231353639363532363366316339323737393661326331
+37303261333533633739646231376561333664613764663264323561323964313364643535613139
+35643739653830613832323630663237376130346665633131343738373536373232366230316633
+65303135613838383439633462383838353066643066623136396262653965396465353732346537
+30353436346138646665343633373932363063636463363837636466663861616437386633643864
+34393763646566393336303866666237303564656364356562316437613761326664333230626437
+66303336376439626432613332613763376137393563386565366139326139363064666464363164
+63643337623663376535306234613033323930666162653437643064393536353431343561653030
+31623663303161626438633665386564333631353964346134343237616237353439373436656334
+30663931663265666361616139313663313835393361656337343436346136633461353131306331
+63323334323932353461306239306233303335343030326534616563623231333564356265326564
+32616137396433623762323437376262363836316366333265636665323930393764346666653630
+64643965323731653833366638613863353231366365653164343063396161343931363332383137
+31323564373532636565346235333735356633353730303437316137353165393835383730623738
+37643764353066313262353035386130663134616331353738383433346434633436396136626133
+63633138616531393730666232353165646337663031323630623632656434303632376439323939
+37306463383731353230663164326661356332376664393465663562303264313038316638343938
+33313333633337396362343562393830663036653238663463623934643630653739636538663035
+64363861313831343130306263663362383933656461393836376532653337623830316335386630
+30356165363538636336386139653866363363666462396539393337303438653936646634333965
+38363263346431376435353333396633626364393438663465616163613661303838353966373539
+34396261303263346338383937353663643638303163303533613831383135313664393230643637
+38633937383631323963353463393166356534663736616330643034336637376638383664326362
+65646337383864356231346337626565616136356536373731373066373132393432353333306632
+38343637333936343731376462613337666363363432613231363337303362616662376237633837
+32663836333162643065313234613462313663643332353735653463383962363830336362633362
+39326363663735616534316166393036316332306537333536356563646538623337363339346231
+62666462653061383933633034393234333734326561393035313063383833616338636164663761
+39623764323933393431666266373133316362666661633761653534343263383333396365343463
+30313636623166613833393761306663383033333836386538346630323561356334613333336663
+32346562616335303937326231343036303934333534666633663364633931363736626362323162
+61396262386366343535326135316564626562393234316538313833653038313939616164646162
+35333261316531323961343236373736323839336266633834626534353236346239623936303066
+38306637303231303739643130363431623030313765636232386530653364623239363466306439
+35643631323630363437323434336234346338643435316565626633636264323833663836626663
+32663664326535656232363736303663353132306434356466333635316432393830666166666230
+33646230633631633538613035393532613234313164646131316438393966333665376534663465
+62613034323238376539356630303165633335373062363036386235633635613330633063386464
+64313338613063653166316639633236663165653736313331356565633364306136323031363834
+65656532393735666132373932646437353666306265313237316638663961636363643639343937
+65623635353239623233616363613136336362393337613538656132646436323533393730313332
+61356530326164393330633266633362393664663465303562656566383836636663643930643238
+33616364636464613035326538626631633239383934616661393961653633393334333030343362
+36386238353637353339663366663233336539363365323961376565363962663534373237326534
+64636131323136386363623061396431393233343233613638373238393536623537646337393331
+31643133633631633538633333323834636634366162663164353932313564643866623463373030
+31633334653437656462623464353438386532336138383961633235363534303639353134613534
+62396330616130633931663135353861626362356266306231346431303364613764326536373430
+62326434303336393331396639366564393933396434643737383663626636366336313065666231
+37353366346139363238333433323334363465646133653462393033633930616239373139343833
+36393435643036373863633166666536393033333265323239386535633138623434363964373939
+63373263373433336362376639623334613431653264383638376238366636663763646637646330
+38373631346564383231626166646466313033366338383435663932616139313830333761613662
+39333533353866303230313938333063656665396662313933643937656235373766346165316465
+39653138313731333039663566663639383730643261303533323965393631393930383836376465
+62386363373438626363313939656266633131303066346638656365613864613434363466343739
+62313533613635623063353733643038623235636530386365626336353638306266303537383639
+35623330376464653562623264323032393738666166636234636461346164616139313038626636
+32663164313039343364623030636162383035663339333835353034656534336261613533313339
+63383463373966353665313834613831326665363838633135353530386533643864666430376235
+61613536633831353266336537383630663537653831313038663232306563636439613635323538
+37343536623535666238353137653137623232393062333630663136326231343131646566643136
+35666636336132353536343166386334336631623433316134323937303634643431353861626563
+61616132643938336532353139303038346634613963363761393462383937653063613961363663
+35396164363464373630363666613036303530363938356535666663373365373633333336373832
+62353134366637333838646363643261363537313930336232363631366665613439363833303636
+66616230383363336235343666663866666136383234396535666265323036623262646330653966
+36383062366135643634643666663438313937336536626332353564653563666133366432616631
+32393835303465396361653066396230383439646234626464646266313865613536363937616133
+39366631343966653731306338396138343830396561653830353263366632633364633233346439
+64613131386230613234353130666634353662393631616335643230613161613464613365353038
+65363164633239633732306366303434623736613961333263656233396262623138666364376165
+35646236643634323839376366333763616635383063336530373538643162646438613261326435
+37336235633338663765393537616139613031363833306336656334353837346132653636383335
+39396264303031393235366331393662663230383863646535633035613664306165326133663232
+30643332313232623666623933613465616561333737643337323738383366306562396638376532
+35363635326235373564613132613135646437653339316436373632666539363563343266396464
+38666366323532346562336233646465396563656335303766646164333732333135313063636233
+62653765333930656637613330383533363061666532626633303430396231303438613133653163
+32643732623733333838393832646138636439376331626134383438306465376132653664343462
+63656138383664656232663634616335393036323361643836633731326137366434646433623236
+36336165326164326539333431646161653237643833386234303834653835653331343234626333
+66616237623333353430393935653665326634636463363335386564356335353861343532353537
+38303562613361376638356663663861653933386635636332313736383531396336363334636635
+32313037306336396462643663656566653332643738333632393964363139353738383734376537
+31366638666462303262323164313036396537646464623239373066323034333939643665623238
+62623838663139613239623038303331663432313662346665643535643864636564623038626361
+64663764653865363961313635353533323362623364393232343035643834663239373965333861
+39663931383836366435313166356165313965643037626262663965636131356638613932346564
+38666634336637313564376665616236376631313938383265646337333832666234396634636635
+63333632346464633431623463313836616237653563303664373063363733343763346464373330
+65373332333738363232353735396464643166336532363133623233396162653533316262353266
+30346231353663646461666162373061653363663934653633346363363132313964373936633330
+65663039393135363431373462633232333939396361643964616161623362623633326131343164
+34353735333236383733373262383938326566333838393165626237643863333863306336643432
+35383036663363313637313937656238383135336363653633343361626539386165313838346439
+64386539646431653866623964333133316231366539303562623739343536303433393036346465
+63396134313930313534346366363636353931336463613965356537656665393466373064336666
+63323766613035383066616332333130303630376334323733313737386464376464376336653232
+62613136393936623765363563313530313733303630396638636231356131356561303465656633
+62623236643964653537336539623163366465636633333830363938626535333832313462346663
+31613131333462373938343433326338336366376266616235393566383366383935303738386635
+62653436643635323563613563653361643939313038623064623566366365396666336634613533
+32373466633438616432363536313136306239373233303963396264333364646464633730333132
+62313034643239303436353337393766666430306434303333393864323838633332353334616237
+66643962623833363262653734303066343132383532643938663135363266373837613934396235
+38383664666632616133316561656663363336313435666438303162356263376263623634336365
+61393838383531373766383438326332646364663663326136323962626336623131643563326230
+64343164653239336636643132643931633963346433333161656162373863373337396562316233
+63343261336636623136613361623264643764326332666236653432666438386266393630373230
+30383866616534613537393333323462656338613930653438656537626239343539356561303261
+64666261666332316434313934393030346532386236643065306638663363396663663033663061
+37376137663933613361396364663862356665303434626439323133616339613036373734643139
+61653963386262376262386631633734346661323539383430326137396331363561626232373264
+35396536623033613737616466393338336135656436383562663262313934663862633065376365
+31633930373639363530393563323434663733653837386264373830386663363934663135646636
+37366132373432356435383339343736656339346465653661336638353633646262636637376664
+31653732363863663266343364393531616638303037323263353932646132626634373265383839
+34306430643965663131653533643338356437623331373664383661623031303466366136326631
+33396537333061316561376265326333383030666665356431363864633563343165376634333934
+35643162663461306438656631306665366636623763366164306562633362363333376663393834
+30643037663638393135616161643430363636323134326235646166616136623031306233623939
+66636335623561326261323535613237363730326431363665393266363165653861333830653062
+38346438636532633332643330656263623137333461663235336330333931643832653265643334
+39613663653663373631636135653738373334653230663537393463613336653164643365353563
+65623634653836346634663036303631363935636235366635643032366331643065343065636635
+39386561323636313764333434386535653039303731333039323631383730316661643464326265
+35323862376366326263363334643062346231366639333762613339616132336238383464363734
+34363437393464376338393737633131303662623130636164303830656439366634613561656566
+66366231343461383163393138313066316134626465333833363362353866613263343565313763
+34386633626136656439633230613364623365336631643130623265376135623163646539356639
+32306630363261383839393537383636636161376539343762313730363462653264343439333330
+39643064623333303435396263356530386265636130653132393534636134316361343763666436
+33383038386138626634363964313465303937343837386636643937313561363639383564626530
+63656166346361336532646432666163636465303863346364386361636638643230353563653832
+32363465646263313937323435323339303338613038633562353266323939656637316464383539
+32343930636166363330333138323933306461306333306263616437383737643737643966333635
+65356436636331303330313733363239613936313430366634373363393436363538656366356161
+37326335393332653038346266393864376538306235343564333038653330336432323038653839
+35313663386431616130636563353666316337343838396365653263306435633862643133633861
+34363232303335383834353566383435313938323339326161383332393636626132313436346665
+62363932323764636233643164386636626331323036373364656664616435393264353432393636
+30336135353839373335343437343431663132643236306461393066616164396338663735343762
+64666362656134323131633130363766666238313261666130653139666364343561633938326235
+30343262346532373637376235323533386237393866623637323435373434353230323633303566
+61376565643130303062363033303438383263643336363739666166636131656431306264373366
+62663561376338663138313936316562303136633031363834366337343137316536643638663964
+36316134336538393161383930306636336332363461303639313334663434326330623933323566
+62333237656434393139626534376638313434303262333332386365336365323739393833396639
+64346430353561633931666466303134383463323964633664396339363761663934623734373937
+61303238656533396561616336663633623861636634363762663166336438623733663730393961
+30633865313331313730393831373132666530333837393734396332316463363962373738656666
+35333531376361323534633661396335653636653930373064636163613561316339626261623933
+38613836353531643332663238316235386165343937613130313135323636366432376434303337
+30393433356338663538346335356338633639313338633536306263393931633361333137386437
+30636362626136666561663362643438393666666236376134336161623837383161376637643531
+62313638313565383465626238336163663939353031356633613834636563393235613930303136
+36353964393932353535326238353434393763306235303465626237393235366430326663336438
+63353632656234366538386362323133626535376537386463393861363133326164396333353836
+31626534316239346633363739663665363664323765366562633039386430653235373763346338
+63646134393237623534326336633132333733353737653932343466633161303833376230356364
+61356636653430323238626238376162363666383030653061366531343563333930383562383661
+39373131373063653733353261666433323235313239326135333339383233366134383033633830
+30323631663133376635376136633430383430666330363133356265386265653937353162666132
+62653036333435613730313033636639613235393132343535326564653562393139656161303537
+38333634316232333539663532333437636433643535616536383031396665386435616565346566
+37356661386563343933383966353733613335336664313338303563376336663931643936323839
+33656234323630626339383835653436616434393262303438356335636665643161316264653639
+38643035653834343762383266643835343935306361626437643831316566393339366662643332
+35366662613432633635613161303838393030633339373938616433303062633433386162633333
+37623934643163306334356533323537626339343333623762333466353933366434336362333531
+33393234616537626136356433376365393538666166373862306663323833306535343937616134
+66616437353931656130663430363938623732343663383533326437336162646232616164323765
+34326331363932306634383037306361336535613835646564393263373962353232386539653662
+32393339353964633432306337643638623966393831626431336232613734616231323436383264
+62353533653266363133353966646139376431613537656162326463323932303234656636313363
+34383833396631363433353334656236363162636635306632636265303032393331313538353664
+65363162396134663937313534663465643030633864626534663032376437663735396139323838
+31663437363834356330616466636137626130343965323934356537333966363936666133343935
+63393162373737326431323337303934353431636134313131616532616238393137346465396631
+65313338343665326331366566653461633438646231356235343736316238393964663539646530
+39313737653837626661653634303432616337386538366462633861643737626438623364633961
+37626164626261303537333538336462303166303961363839386262653439393462613661626664
+32616165363137343832316333323938613962363530353436323964613038393338613233626532
+35613031333635366130373561373765356365613362326432333734383932383131663036336466
+38633635376261373930616461393030333164376332663639333535303063646163356563356135
+61393662373463666261306136653531363030376238386562326637326665303833343935653365
+63343032613031363765393134623930626237376263336564326235303532346664623266663061
+34623661326132653135636436623063373464373765623566316139633039336234346130323536
+66396637333434653463623636313030646661373837323234363932313763326436343866636439
+61643834336462303436346132333839396133613330653864346434356635386130393961336435
+37663333626534666663623831343537383136346138346163333431323134643863623763376436
+33386363653535313664343033333439373766663934653332646664653061343038353464353430
+65643966373037643333353836653139326564376530656439646139336263656161386363653431
+35336233613864633364383263373937383737646565643434396137646163376462626166323761
+65643661363437633266646233346432336639353338666434626333326237646330313439633761
+63656136616365653863323733366165333465346337643636353062323732646566363464306635
+64366238326133336463323037613235396532636134303232313436616665383865366433363962
+34373332663634386563326662346537626263656531306563336334393135393561613239343835
+37303634303430363364393762613431663138316238356431623835333866646230353933623139
+61616231313063363938643362353562343937313836653235636362306632383161623437336635
+35643765393764373963346338393932316332363832653661636638343563656230333162646535
+34363638636261393161306433356538366234366262656434656530643064306666626664346362
+63386262346633613037363032623862376365383736653132363166313039613465313939636561
+33323466373562616237343163356265313862396139303837313431653236386235363965643261
+65643039643735303238613837366532343365323831653738303334363536376533323435626234
+32343463353863363631356366383736366233396534643739626365633466346634303833653638
+30326664333438663937616532343435643639386131353036616434383064363535393265643533
+30376133656665393035373431633836353436303663393464316231323662366264396437313133
+62363737636632343734323536303262323336313037653765346264303933303637663237343232
+64356466343836656238623766326134376364306661656262363739636635646164323932393138
+65643433663334336563323735306465333765633339313736353930353734393364323032653839
+35333466323261336266666632633633353738363133313532396232643564613364313231363231
+66383234303133303461666364383166383264316133393237386237336535613132366233646437
+32313665356166373930343231366530326637383535656137323433376437633134313863663532
+30343636353465363131313739306265363632346635383438653865366336663162336135623737
+37663563363564323164333065326464663337613165646533323235343332653561383865323333
+64366363313137343033633636613665373832383563626363363332633364306234353832353033
+31626634636231343730363439643761346231366661623962646639656335316138656534343931
+66303737303635343434353566633636323138333538316463393463636663643235373331346137
+63626566306665616535323662386130336436396564373935643562663339343735336232333434
+61663632613237336163323032646232366166633435346231396436346535613861306163323535
+66356332653736363063626562643064663035356638303432333033643130616530386464343365
+66323934393331363934336535353366313866383365633431653235383062616435633333316334
+30323162616463373136323937306634643336326336623932613862653563393261353938386261
+35373765353330643635336164363464666166613766323262646561363731343362353838386162
+37313662626130353063333264646331333033373433616365636635653732633465323265666231
+66623065643136343633663730313361343631626461616266636134653032623339333262383638
+37373135623233383161376266653732326439613233333661643765353465656231353164326432
+66373235616137663132633434323933633562373835636361363938653038363836613061363337
+62616138656439643663353166393965383234383732326165366139346432393639653539356533
+61633063303862643430393161666465356636613931336139643735626366343037333339356636
+66373932316666643939346264323638333561663230346536343063393965663839313566326363
+39393238303731623833666662623734323532353465316438393834666434643731623037633536
+64653439363764633031303630363165323065613262613232616462316366323066396162316266
+32626430613234356230356261303034383561336162616232316331666666376339333136343663
+61306264646436313964626538376162366164393830363136316162323130353666333464383737
+62643830343961343131623136356463393563366138656136666330333333626164323632386337
+66376239653162396362663736353237643931363166323335613363363462336666376663396464
+32646534323265336163336561623731343332663634613039626432346430326236326335663232
+39306437343966313337333461393466653966306464323138353332313965326564393963653636
+39653965353033623339386231653032663562353661356264626233303163326236363339383632
+39363835343733356135313835383730323632346165363633646631353138636466643863356235
+38393063346139643037366435663066363033613037386135633162613838313135333430636339
+32313337316139323231
diff --git a/ansible/inventories/test/group_vars/database/vars.yml b/ansible/inventories/test/group_vars/database/vars.yml
new file mode 100644
index 000000000..029465ecb
--- /dev/null
+++ b/ansible/inventories/test/group_vars/database/vars.yml
@@ -0,0 +1,29 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+#firewall_allowed_tcp_ports:
+#  - "22"
+#  - "3306"
+#mysql_replication_user: {name: 'replication',password: 'secret'}
+#mysql_databases:
+#  - name: mycompany_database
+#    collation: utf8_general_ci
+#    encoding: utf-8
\ No newline at end of file
diff --git a/ansible/inventories/test/host_vars/custos/vars.yml b/ansible/inventories/test/host_vars/custos/vars.yml
new file mode 100644
index 000000000..f211fcf9d
--- /dev/null
+++ b/ansible/inventories/test/host_vars/custos/vars.yml
@@ -0,0 +1,25 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+pkcs12_filename: 'custos-client-truststore.pkcs12'
+pkcs12_passphrase:
+ansible_ssh_password: "{{ custos_ssh_password }}"
+nginx_site_config: site.conf.j2
\ No newline at end of file
diff --git a/ansible/inventories/test/host_vars/hashicorp/vars.yml b/ansible/inventories/test/host_vars/hashicorp/vars.yml
new file mode 100644
index 000000000..dfb5ee4ce
--- /dev/null
+++ b/ansible/inventories/test/host_vars/hashicorp/vars.yml
@@ -0,0 +1,25 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+pkcs12_filename: 'vault-client-truststore.pkcs12'
+pkcs12_passphrase: "{{ hashicorp_pkcs12_passphrase }}"
+ansible_ssh_password: "{{ hashicorp_ssh_password }}"
+nginx_site_config: site.conf.j2
\ No newline at end of file
diff --git a/ansible/inventories/test/host_vars/keycloak/vars.yml b/ansible/inventories/test/host_vars/keycloak/vars.yml
new file mode 100644
index 000000000..ff3f2a1e4
--- /dev/null
+++ b/ansible/inventories/test/host_vars/keycloak/vars.yml
@@ -0,0 +1,25 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+pkcs12_filename: 'keycloak-client-truststore.pkcs12'
+pkcs12_passphrase: "{{ keycloak_pkcs12_passphrase }}"
+ansible_ssh_password: "{{ keycloak_ssh_password }}"
+nginx_site_config: "{{ ansible_host }}.j2"
\ No newline at end of file
diff --git a/ansible/inventories/test/host_vars/testcustos/vars.yml b/ansible/inventories/test/host_vars/testcustos/vars.yml
new file mode 100644
index 000000000..2475b7f81
--- /dev/null
+++ b/ansible/inventories/test/host_vars/testcustos/vars.yml
@@ -0,0 +1,32 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+domain: testcustos-ub20.com
+ansible_ssh_password:
+  !vault |
+  $ANSIBLE_VAULT;1.1;AES256
+  63353537323261646536313439313664393466616161373836346462386638376532636230356531
+  3133326663666630323332666238366534353039303838390a643233393131323165303034653333
+  30633362376530363330616132306230313939386430336135333131363437326131343032363039
+  3636626562373463380a343464636437393536653931343664313630363663626536343232393936
+  32376561636334396264666336336432666465626234333163326536386336613165313336373265
+  64663931643462623634363438333839396666356464323931376164373333633866623632323163
+  623132306164346131313066613337316133
\ No newline at end of file
diff --git a/ansible/inventories/test/hosts.yml b/ansible/inventories/test/hosts.yml
new file mode 100644
index 000000000..78f07a2e0
--- /dev/null
+++ b/ansible/inventories/test/hosts.yml
@@ -0,0 +1,35 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+all:
+  hosts:
+    custos:
+      ansible_host: bm-dev-1.usecustos.org
+      ansible_user: exouser
+      ansible_ssh_pass: "{{ ansible_ssh_password }}"
+    keycloak:
+      ansible_host: bm-dev-2.usecustos.org
+      ansible_user: exouser
+      ansible_ssh_pass: "{{ ansible_ssh_password }}"
+    hashicorp:
+      ansible_host: bm-dev-3.usecustos.org
+      ansible_user: exouser
+      ansible_ssh_pass: "{{ ansible_ssh_password }}"