diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
deleted file mode 100644
index 313d58c357..0000000000
--- a/ansible/group_vars/all.yml
+++ /dev/null
@@ -1 +0,0 @@
-koalla_directory: "/usr/share/kolla"
diff --git a/ansible/library/merge_configs b/ansible/library/merge_configs
new file mode 100644
index 0000000000..9991833aac
--- /dev/null
+++ b/ansible/library/merge_configs
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+
+# Copyright 2015 Sam Yaple
+#
+# Licensed 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.
+
+DOCUMENTATION = '''
+---
+module: merge_configs
+short_description: Merge ini-style configs
+description:
+     - ConfigParser is used to merge several ini-style configs into one
+options:
+  dest:
+    description:
+      - The destination file name
+    required: True
+    type: str
+  sources:
+    description:
+      - A list of files on the destination node to merge together
+    default: None
+    required: True
+    type: str
+author: Sam Yaple
+'''
+
+EXAMPLES = '''
+Merge multiple configs:
+
+- hosts: database
+  tasks:
+    - name: Merge configs
+      merge_configs:
+        sources:
+          - "/tmp/config_1.cnf"
+          - "/tmp/config_2.cnf"
+          - "/tmp/config_3.cnf"
+        dest:
+          - "/etc/mysql/my.cnf"
+'''
+
+import ConfigParser
+
+def main():
+    module = AnsibleModule(
+        argument_spec = dict(
+            sources = dict(required=True, type='list'),
+            dest = dict(required=True, type='str'),
+        )
+    )
+
+    try:
+        sources = module.params.pop('sources')
+        dest = module.params.pop('dest')
+
+        config = ConfigParser.ConfigParser()
+
+        for source_file in sources:
+            config.read(source_file)
+
+        with open(dest, 'wb') as dest_file:
+            config.write(dest_file)
+
+        module.exit_json(changed=True)
+    except Exception, e:
+        changed = True
+        module.exit_json(failed=True, changed=changed, msg=repr(e))
+
+
+# import module snippets
+from ansible.module_utils.basic import *
+if __name__ == '__main__':
+    main()
diff --git a/ansible/roles/bootstrap.yml b/ansible/roles/bootstrap.yml
new file mode 100644
index 0000000000..cb5bfd7fd8
--- /dev/null
+++ b/ansible/roles/bootstrap.yml
@@ -0,0 +1,34 @@
+---
+- name: Creating database
+  mysql_db:
+    login_host: "{{ database_address }}"
+    login_user: "{{ database_user }}"
+    login_password: "{{ database_password }}"
+    name: "{{ service_database_name }}"
+  register: database
+  run_once: True
+
+- name: Creating database user and setting permissions
+  mysql_user:
+    login_host: "{{ database_address }}"
+    login_user: "{{ database_user }}"
+    login_password: "{{ database_password }}"
+    name: "{{ service_database_name }}"
+    password: "{{ service_database_password }}"
+    host: "%"
+    priv: "{{ service_database_name }}.*:ALL"
+    append_privs: "yes"
+  run_once: True
+
+- include: start.yml
+  vars:
+    run_once: True
+  when: database|changed
+
+- name: Cleaning up boostrap container
+  docker:
+    name: "{{ container_name }}"
+    image: "{{ container_image }}"
+    state: "absent"
+  run_once: True
+  when: database|changed
diff --git a/ansible/roles/config.yml b/ansible/roles/config.yml
new file mode 100644
index 0000000000..a941e89ee9
--- /dev/null
+++ b/ansible/roles/config.yml
@@ -0,0 +1,24 @@
+---
+- name: Ensuring templates config directory exists
+  file:
+    path: "{{ node_templates_directory }}/{{ project_name }}"
+    state: "directory"
+    recurse: yes
+
+- name: Ensuring config directory exists
+  file:
+    path: "{{ node_config_directory }}/{{ project_name }}"
+    state: "directory"
+
+- name: Copying over config(s)
+  template:
+    src: "{{ item.0 }}"
+    dest: "{{ item.1 }}"
+  with_together:
+    - config_source
+    - config_template_dest
+
+- name: Merging the config files and saving to the final destination
+  merge_configs:
+    sources: "{{ config_template_dest }}"
+    dest: "{{ config_dest }}"
diff --git a/ansible/roles/keystone/defaults/main.yml b/ansible/roles/keystone/defaults/main.yml
new file mode 100644
index 0000000000..d3b4f3cb13
--- /dev/null
+++ b/ansible/roles/keystone/defaults/main.yml
@@ -0,0 +1,42 @@
+---
+project_name: "keystone"
+
+####################
+# Database
+####################
+keystone_database_name: "keystone"
+keystone_database_user: "keystone"
+keystone_database_address: "{{ kolla_internal_address }}"
+
+# Do not override "service_*" variables
+service_database_name: "{{ keystone_database_name }}"
+service_database_user: "{{ keystone_database_user }}"
+service_database_password: "{{ keystone_database_password }}"
+
+
+####################
+# Docker
+####################
+docker_keystone_registry: "{{ docker_registry }}"
+docker_keystone_namespace: "{{ docker_namespace }}"
+kolla_keystone_base_distro: "{{ kolla_base_distro }}"
+kolla_keystone_install_type: "{{ kolla_install_type }}"
+kolla_keystone_container_name: "keystone"
+
+docker_keystone_image: "{{ docker_keystone_registry }}{{ docker_keystone_namespace }}/{{ kolla_keystone_base_distro }}-{{ kolla_keystone_install_type }}-{{ kolla_keystone_container_name }}"
+docker_keystone_tag: "{{ openstack_release }}"
+docker_keystone_image_full: "{{ docker_keystone_image }}:{{ docker_keystone_tag }}"
+
+
+####################
+# Openstack
+####################
+keystone_public_address: "{{ kolla_external_address }}"
+keystone_admin_address: "{{ kolla_internal_address }}"
+keystone_internal_address: "{{ kolla_internal_address }}"
+
+keystone_public_port: "5000"
+keystone_admin_port: "35357"
+
+keystone_logging_verbose: "{{ openstack_logging_verbose }}"
+keystone_logging_debug: "{{ openstack_logging_debug }}"
diff --git a/ansible/roles/keystone/tasks/bootstrap.yml b/ansible/roles/keystone/tasks/bootstrap.yml
new file mode 100644
index 0000000000..c2bbf1a02a
--- /dev/null
+++ b/ansible/roles/keystone/tasks/bootstrap.yml
@@ -0,0 +1,14 @@
+---
+# "detach: False" ensures we will be able to wait until the database bootstrap
+# is finished. We can also check the exit code and catch errors if the database
+# initialization does not successfully finish
+- include: ../../bootstrap.yml
+  vars:
+    container_detach: False
+    container_environment:
+      BOOTSTRAP:
+      CONFIG_STRATEGY: "{{ config_strategy }}"
+    container_image: "{{ docker_keystone_image_full }}"
+    container_name: "bootstrap_keystone"
+    container_volumes:
+      - "{{ node_config_directory }}/keystone/:/opt/kolla/configs/keystone/:ro"
diff --git a/ansible/roles/keystone/tasks/config.yml b/ansible/roles/keystone/tasks/config.yml
new file mode 100644
index 0000000000..6a6a12eac2
--- /dev/null
+++ b/ansible/roles/keystone/tasks/config.yml
@@ -0,0 +1,16 @@
+---
+- include: ../../config.yml
+  vars:
+    config_source:
+      - "roles/keystone/templates/keystone.conf.j2"
+      - "/etc/kolla/config/global.conf"
+      - "/etc/kolla/config/database.conf"
+      - "/etc/kolla/config/messaging.conf"
+      - "/etc/kolla/config/keystone.conf"
+    config_template_dest:
+      - "{{ node_templates_directory }}/keystone/keystone.conf_minimal"
+      - "{{ node_templates_directory }}/keystone/keystone.conf_global"
+      - "{{ node_templates_directory }}/keystone/keystone.conf_database"
+      - "{{ node_templates_directory }}/keystone/keystone.conf_messaging"
+      - "{{ node_templates_directory }}/keystone/keystone.conf_augment"
+    config_dest: "{{ node_config_directory }}/keystone/keystone.conf"
diff --git a/ansible/roles/keystone/tasks/main.yml b/ansible/roles/keystone/tasks/main.yml
index 29a7fef520..2821641c4b 100644
--- a/ansible/roles/keystone/tasks/main.yml
+++ b/ansible/roles/keystone/tasks/main.yml
@@ -1,7 +1,8 @@
 ---
-- name: Bringing up keystone service(s)
-  docker_compose:
-    project_name: keystone
-    compose_file: "{{ koalla_directory }}/compose/keystone.yml"
-    command: up
-    no_recreate: true
+- include: config.yml
+
+- include: bootstrap.yml
+
+- include: start.yml
+
+#- include: register.yml
diff --git a/ansible/roles/keystone/tasks/register.yml b/ansible/roles/keystone/tasks/register.yml
new file mode 100644
index 0000000000..8ee20320bb
--- /dev/null
+++ b/ansible/roles/keystone/tasks/register.yml
@@ -0,0 +1,12 @@
+---
+# NB: Not an Attorney
+#
+# Upstream ansible will have all of the new modules we need based on
+# the shade library. They are written, but the keystone modules haven't3
+# been merged yet. None of the modules will land before Ansible 2.0.
+#
+# These new modules will be relicensed using ASL2.0 as the result of a
+# gentlemen's agreement that the Kolla authors will not alter the Shade code.
+# This does not place additional restrictions on the license of this work.  The
+# relicense agreement is based upon trust, not something legally binding and
+# has no binding impact on the license of Kolla..
diff --git a/ansible/roles/keystone/tasks/start.yml b/ansible/roles/keystone/tasks/start.yml
new file mode 100644
index 0000000000..a1d999ef57
--- /dev/null
+++ b/ansible/roles/keystone/tasks/start.yml
@@ -0,0 +1,9 @@
+---
+- include: ../../start.yml
+  vars:
+    container_environment:
+      CONFIG_STRATEGY: "{{ config_strategy }}"
+    container_image: "{{ docker_keystone_image_full }}"
+    container_name: "keystone"
+    container_volumes:
+      - "{{ node_config_directory }}/keystone/:/opt/kolla/configs/keystone/:ro"
diff --git a/ansible/roles/keystone/templates/keystone.conf.j2 b/ansible/roles/keystone/templates/keystone.conf.j2
new file mode 100644
index 0000000000..9dc45cb0a3
--- /dev/null
+++ b/ansible/roles/keystone/templates/keystone.conf.j2
@@ -0,0 +1,13 @@
+[DEFAULT]
+verbose = {{ keystone_logging_verbose }}
+debug = {{ keystone_logging_debug }}
+
+bind_host = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}
+
+admin_token = {{ keystone_admin_token }}
+
+public_endpoint = http://{{ keystone_public_address }}:{{ keystone_public_port }}
+admin_endpoint = http://{{ keystone_admin_address }}:{{ keystone_admin_port }}
+
+[database]
+connection = mysql://{{ keystone_database_user }}:{{ keystone_database_password }}@{{ keystone_database_address }}/{{ keystone_database_name }}
diff --git a/ansible/roles/start.yml b/ansible/roles/start.yml
new file mode 100644
index 0000000000..44d9b0c67c
--- /dev/null
+++ b/ansible/roles/start.yml
@@ -0,0 +1,30 @@
+---
+# Using "state: reloaded" will restart the container if a new image is
+# pulled or the paramaters are modified.
+#
+# "pull: always" will _always_ pull the latest image. It registers a
+# change when the image has changed, regardless of "state"
+#
+# Due to a bug in the ansible docker module it doesnt properly supply the
+# docker_api_version from docker-py, so we specify it here. This will be
+# removed when the bugfix makes it downstream
+
+- name: Starting the container
+  docker:
+    detach: "{{ container_detach | default('True') }}"
+    env: "{{ container_environment }}"
+    docker_api_version: "{{ docker_api_version }}"
+    image: "{{ container_image }}"
+    insecure_registry: "{{ docker_insecure_registry }}"
+    name: "{{ container_name }}"
+    net: host
+    password: "{{ docker_registry_password }}"
+    privileged: "{{ container_privileged | default('False') }}"
+    pull: "{{ docker_pull_policy }}"
+    registry: "{{ docker_registry }}"
+    restart_policy: "{{ docker_restart_policy }}"
+    restart_policy_retry: "{{ docker_restart_policy_retry }}"
+    state: reloaded
+    username: "{{ docker_registry_username }}"
+    volumes: "{{ container_volumes }}"
+  run_once: "{{ run_once | default('False') }}"
diff --git a/docker/centos/binary/keystone/Dockerfile b/docker/centos/binary/keystone/Dockerfile
index f8db5f5828..e05db2fded 100644
--- a/docker/centos/binary/keystone/Dockerfile
+++ b/docker/centos/binary/keystone/Dockerfile
@@ -17,8 +17,8 @@ RUN chown -R keystone:keystone /var/www/cgi-bin/keystone
 RUN chmod 755 /var/www/cgi-bin/keystone/*
 
 # Add start-up and check scripts
-COPY ./start.sh /start.sh
-COPY ./check.sh /check.sh
+COPY start.sh check.sh /
+COPY config-internal.sh config-external.sh /opt/kolla/
 
 # Run the Keystone start script
 CMD ["/start.sh"]
diff --git a/docker/centos/binary/keystone/config-external.sh b/docker/centos/binary/keystone/config-external.sh
new file mode 120000
index 0000000000..ae5be7eea9
--- /dev/null
+++ b/docker/centos/binary/keystone/config-external.sh
@@ -0,0 +1 @@
+../../../common/keystone/config-external.sh
\ No newline at end of file
diff --git a/docker/centos/binary/keystone/config-internal.sh b/docker/centos/binary/keystone/config-internal.sh
new file mode 120000
index 0000000000..fe8d98c1f6
--- /dev/null
+++ b/docker/centos/binary/keystone/config-internal.sh
@@ -0,0 +1 @@
+../../../common/keystone/config-internal.sh
\ No newline at end of file
diff --git a/docker/common/base/kolla-common.sh b/docker/common/base/kolla-common.sh
index 8c2ef5ec1c..bd6a539a0b 100644
--- a/docker/common/base/kolla-common.sh
+++ b/docker/common/base/kolla-common.sh
@@ -168,3 +168,27 @@ dump_vars() {
     set +o posix
 }
 
+set_configs() {
+    case $KOLLA_CONFIG_STRATEGY in
+        CONFIG_INTERNAL)
+            # exec is intentional to preserve existing behaviour
+            exec /opt/kolla/config-internal.sh
+            ;;
+        CONFIG_EXTERNAL_COPY_ALWAYS)
+            source /opt/kolla/config-exernal.sh
+            ;;
+        CONFIG_EXTERNAL_COPY_ONCE)
+            if [[ -f /configured ]]; then
+                echo 'INFO - This container has already been configured; Refusing to copy new configs'
+                return
+            fi
+            source /opt/kolla/config-exernal.sh
+            touch /configured
+            ;;
+
+        *)
+            echo '$CONFIG_STRATEGY is not set properly'
+            exit 1
+            ;;
+    esac
+}
diff --git a/docker/common/keystone/config-external.sh b/docker/common/keystone/config-external.sh
new file mode 100644
index 0000000000..76e4acfff2
--- /dev/null
+++ b/docker/common/keystone/config-external.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+if [[ -f /opt/kolla/keystone/keystone.conf ]]; then
+    cp /opt/kolla/keystone/keystone.conf /etc/keystone/keystone.conf
+    chown keystone: /etc/keystone/keystone.conf
+    chmod 0644 /etc/keystone/keystone.conf
+fi
diff --git a/docker/common/keystone/config-internal.sh b/docker/common/keystone/config-internal.sh
new file mode 100755
index 0000000000..527870fdfe
--- /dev/null
+++ b/docker/common/keystone/config-internal.sh
@@ -0,0 +1,165 @@
+#!/bin/bash
+
+set -e
+
+# Run Kolla common script
+echo "Running the kolla-common script"
+. /opt/kolla/kolla-common.sh
+
+# Credentials, token, etc..
+: ${ADMIN_USER:=admin}
+: ${ADMIN_USER_PASSWORD:=password}
+: ${ADMIN_TENANT_NAME:=admin}
+: ${KEYSTONE_USER:=keystone}
+: ${KEYSTONE_ADMIN_PASSWORD:=password}
+: ${KEYSTONE_ADMIN_TOKEN:=changeme}
+# DB Settings
+: ${INIT_KEYSTONE_DB:=true}
+: ${KEYSTONE_DB_NAME:=keystone}
+: ${KEYSTONE_DB_USER:=keystone}
+: ${DB_ROOT_PASSWORD:=password}
+: ${MARIADB_SERVICE_HOST:=$PUBLIC_IP}
+: ${KEYSTONE_DB_PASSWORD:=password}
+# Service Addresses/Ports/Version
+: ${KEYSTONE_PUBLIC_SERVICE_HOST:=$PUBLIC_IP}
+: ${KEYSTONE_ADMIN_SERVICE_HOST:=$PUBLIC_IP}
+: ${KEYSTONE_PUBLIC_SERVICE_PORT:=5000}
+: ${KEYSTONE_ADMIN_SERVICE_PORT:=35357}
+: ${KEYSTONE_API_VERSION:=2.0}
+# Logging
+: ${LOG_FILE:=/var/log/keystone/keystone.log}
+: ${VERBOSE_LOGGING:=true}
+: ${DEBUG_LOGGING:=false}
+: ${USE_STDERR:=false}
+# Token provider, driver, etc..
+: ${TOKEN_PROVIDER:=uuid}
+: ${TOKEN_DRIVER:=sql}
+
+## Check DB connectivity and required variables
+echo "Checking connectivity to the DB"
+fail_unless_db
+echo "Checking for required variables"
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_DB_PASSWORD \
+                    KEYSTONE_ADMIN_PASSWORD ADMIN_TENANT_NAME \
+                    KEYSTONE_PUBLIC_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_HOST \
+                    PUBLIC_IP INIT_KEYSTONE_DB
+dump_vars
+
+# Setup the Keystone DB
+echo "Setting up Keystone DB"
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${KEYSTONE_DB_NAME};
+GRANT ALL PRIVILEGES ON ${KEYSTONE_DB_NAME}.* TO
+    '${KEYSTONE_DB_USER}'@'%' IDENTIFIED BY '${KEYSTONE_DB_PASSWORD}'
+EOF
+
+# File path and name used by crudini tool
+cfg=/etc/keystone/keystone.conf
+
+# Token Configuration
+echo "Configuring keystone.conf"
+crudini --set $cfg \
+    DEFAULT \
+    admin_token \
+    "${KEYSTONE_ADMIN_TOKEN}"
+
+# Database Configuration
+crudini --set $cfg \
+    database \
+    connection \
+    "mysql://${KEYSTONE_DB_USER}:${KEYSTONE_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${KEYSTONE_DB_NAME}"
+
+# Logging
+crudini --del $cfg \
+    DEFAULT \
+    log_dir
+crudini --set $cfg \
+    DEFAULT \
+    log_file \
+    ${LOG_FILE}
+crudini --set $cfg \
+    DEFAULT \
+    verbose \
+    ${VERBOSE_LOGGING}
+crudini --set $cfg \
+    DEFAULT \
+    debug \
+    ${DEBUG_LOGGING}
+crudini --set $cfg \
+    DEFAULT \
+    use_stderr \
+    ${USE_STDERR}
+
+# Token Management
+crudini --set $cfg \
+    token \
+    provider \
+    keystone.token.providers."${TOKEN_PROVIDER}".Provider
+crudini --set $cfg \
+    token \
+    driver \
+    keystone.token.persistence.backends."${TOKEN_DRIVER}".Token
+crudini --set $cfg \
+    revoke \
+    driver \
+    keystone.contrib.revoke.backends."${TOKEN_DRIVER}".Revoke
+
+# Setup the openrc auth file
+cat > /openrc <<EOF
+export OS_AUTH_URL=http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}
+export OS_USERNAME=${KEYSTONE_USER}
+export OS_PASSWORD=${KEYSTONE_ADMIN_PASSWORD}
+export OS_TENANT_NAME=${ADMIN_TENANT_NAME}
+EOF
+
+# Create keystone user and group if they don't exist
+id -u keystone &>/dev/null || useradd --user-group keystone
+
+# Run PKI Setup script
+echo "Setting up PKI"
+/usr/bin/keystone-manage pki_setup --keystone-user keystone --keystone-group keystone
+
+# Fix permissions
+chown -R keystone:keystone /var/log/keystone
+chown -R keystone:keystone /etc/keystone/ssl
+chmod -R o-rwx /etc/keystone/ssl
+
+# Initialize the Keystone DB
+echo "Initializing Keystone DB"
+if [ "${INIT_KEYSTONE_DB}" == "true" ] ; then
+    su -s /bin/bash -c "keystone-manage db_sync" keystone
+fi
+
+# Start Keystone
+echo "Starting Keystone"
+/usr/sbin/httpd -DFOREGROUND &
+PID=$!
+
+# Export Keystone service environment variables
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}"
+
+# Check to make sure the service is running
+echo "Verifying Keystone is running"
+while ! curl -o /dev/null -s --fail ${SERVICE_ENDPOINT}; do
+    echo "waiting for Keystone @ ${SERVICE_ENDPOINT}"
+    sleep 1;
+done
+echo "keystone is active @ ${SERVICE_ENDPOINT}"
+
+# Create Keystone tenant, user, role, service and endpoints
+echo "Creating Keystone tenant, user, role, service and endpoints"
+crux user-create --update \
+    -n ${ADMIN_USER} -p "${ADMIN_USER_PASSWORD}" \
+    -t ${ADMIN_TENANT_NAME} -r admin
+crux user-create --update \
+    -n ${KEYSTONE_USER} -p "${KEYSTONE_ADMIN_PASSWORD}" \
+    -t ${ADMIN_TENANT_NAME} -r admin
+crux endpoint-create --remove-all \
+    -n keystone -t identity \
+    -I "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v${KEYSTONE_API_VERSION}" \
+    -A "http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}" \
+    -P "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v${KEYSTONE_API_VERSION}"
+
+# Wait on all jobs to exit before proceeding (see man wait)
+wait
diff --git a/docker/common/keystone/start.sh b/docker/common/keystone/start.sh
index 527870fdfe..4dce4c7575 100755
--- a/docker/common/keystone/start.sh
+++ b/docker/common/keystone/start.sh
@@ -1,165 +1,19 @@
 #!/bin/bash
 
-set -e
+set -o errexit
 
-# Run Kolla common script
-echo "Running the kolla-common script"
-. /opt/kolla/kolla-common.sh
+CMD="/usr/bin/keystone-all"
+ARGS=""
 
-# Credentials, token, etc..
-: ${ADMIN_USER:=admin}
-: ${ADMIN_USER_PASSWORD:=password}
-: ${ADMIN_TENANT_NAME:=admin}
-: ${KEYSTONE_USER:=keystone}
-: ${KEYSTONE_ADMIN_PASSWORD:=password}
-: ${KEYSTONE_ADMIN_TOKEN:=changeme}
-# DB Settings
-: ${INIT_KEYSTONE_DB:=true}
-: ${KEYSTONE_DB_NAME:=keystone}
-: ${KEYSTONE_DB_USER:=keystone}
-: ${DB_ROOT_PASSWORD:=password}
-: ${MARIADB_SERVICE_HOST:=$PUBLIC_IP}
-: ${KEYSTONE_DB_PASSWORD:=password}
-# Service Addresses/Ports/Version
-: ${KEYSTONE_PUBLIC_SERVICE_HOST:=$PUBLIC_IP}
-: ${KEYSTONE_ADMIN_SERVICE_HOST:=$PUBLIC_IP}
-: ${KEYSTONE_PUBLIC_SERVICE_PORT:=5000}
-: ${KEYSTONE_ADMIN_SERVICE_PORT:=35357}
-: ${KEYSTONE_API_VERSION:=2.0}
-# Logging
-: ${LOG_FILE:=/var/log/keystone/keystone.log}
-: ${VERBOSE_LOGGING:=true}
-: ${DEBUG_LOGGING:=false}
-: ${USE_STDERR:=false}
-# Token provider, driver, etc..
-: ${TOKEN_PROVIDER:=uuid}
-: ${TOKEN_DRIVER:=sql}
+# loading common functions
+source /opt/kolla/kolla-common.sh
 
-## Check DB connectivity and required variables
-echo "Checking connectivity to the DB"
-fail_unless_db
-echo "Checking for required variables"
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_DB_PASSWORD \
-                    KEYSTONE_ADMIN_PASSWORD ADMIN_TENANT_NAME \
-                    KEYSTONE_PUBLIC_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_HOST \
-                    PUBLIC_IP INIT_KEYSTONE_DB
-dump_vars
+set_configs
 
-# Setup the Keystone DB
-echo "Setting up Keystone DB"
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${KEYSTONE_DB_NAME};
-GRANT ALL PRIVILEGES ON ${KEYSTONE_DB_NAME}.* TO
-    '${KEYSTONE_DB_USER}'@'%' IDENTIFIED BY '${KEYSTONE_DB_PASSWORD}'
-EOF
-
-# File path and name used by crudini tool
-cfg=/etc/keystone/keystone.conf
-
-# Token Configuration
-echo "Configuring keystone.conf"
-crudini --set $cfg \
-    DEFAULT \
-    admin_token \
-    "${KEYSTONE_ADMIN_TOKEN}"
-
-# Database Configuration
-crudini --set $cfg \
-    database \
-    connection \
-    "mysql://${KEYSTONE_DB_USER}:${KEYSTONE_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${KEYSTONE_DB_NAME}"
-
-# Logging
-crudini --del $cfg \
-    DEFAULT \
-    log_dir
-crudini --set $cfg \
-    DEFAULT \
-    log_file \
-    ${LOG_FILE}
-crudini --set $cfg \
-    DEFAULT \
-    verbose \
-    ${VERBOSE_LOGGING}
-crudini --set $cfg \
-    DEFAULT \
-    debug \
-    ${DEBUG_LOGGING}
-crudini --set $cfg \
-    DEFAULT \
-    use_stderr \
-    ${USE_STDERR}
-
-# Token Management
-crudini --set $cfg \
-    token \
-    provider \
-    keystone.token.providers."${TOKEN_PROVIDER}".Provider
-crudini --set $cfg \
-    token \
-    driver \
-    keystone.token.persistence.backends."${TOKEN_DRIVER}".Token
-crudini --set $cfg \
-    revoke \
-    driver \
-    keystone.contrib.revoke.backends."${TOKEN_DRIVER}".Revoke
-
-# Setup the openrc auth file
-cat > /openrc <<EOF
-export OS_AUTH_URL=http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}
-export OS_USERNAME=${KEYSTONE_USER}
-export OS_PASSWORD=${KEYSTONE_ADMIN_PASSWORD}
-export OS_TENANT_NAME=${ADMIN_TENANT_NAME}
-EOF
-
-# Create keystone user and group if they don't exist
-id -u keystone &>/dev/null || useradd --user-group keystone
-
-# Run PKI Setup script
-echo "Setting up PKI"
-/usr/bin/keystone-manage pki_setup --keystone-user keystone --keystone-group keystone
-
-# Fix permissions
-chown -R keystone:keystone /var/log/keystone
-chown -R keystone:keystone /etc/keystone/ssl
-chmod -R o-rwx /etc/keystone/ssl
-
-# Initialize the Keystone DB
-echo "Initializing Keystone DB"
-if [ "${INIT_KEYSTONE_DB}" == "true" ] ; then
-    su -s /bin/bash -c "keystone-manage db_sync" keystone
+# Bootstrap and exit if BOOTSTRAP variable is set
+if [[ "${!KOLLA_BOOTSTRAP[@]}" ]]; then
+    su -c "keystone-manage db_sync" keystone
+    exit 0
 fi
 
-# Start Keystone
-echo "Starting Keystone"
-/usr/sbin/httpd -DFOREGROUND &
-PID=$!
-
-# Export Keystone service environment variables
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}"
-
-# Check to make sure the service is running
-echo "Verifying Keystone is running"
-while ! curl -o /dev/null -s --fail ${SERVICE_ENDPOINT}; do
-    echo "waiting for Keystone @ ${SERVICE_ENDPOINT}"
-    sleep 1;
-done
-echo "keystone is active @ ${SERVICE_ENDPOINT}"
-
-# Create Keystone tenant, user, role, service and endpoints
-echo "Creating Keystone tenant, user, role, service and endpoints"
-crux user-create --update \
-    -n ${ADMIN_USER} -p "${ADMIN_USER_PASSWORD}" \
-    -t ${ADMIN_TENANT_NAME} -r admin
-crux user-create --update \
-    -n ${KEYSTONE_USER} -p "${KEYSTONE_ADMIN_PASSWORD}" \
-    -t ${ADMIN_TENANT_NAME} -r admin
-crux endpoint-create --remove-all \
-    -n keystone -t identity \
-    -I "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v${KEYSTONE_API_VERSION}" \
-    -A "http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}" \
-    -P "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v${KEYSTONE_API_VERSION}"
-
-# Wait on all jobs to exit before proceeding (see man wait)
-wait
+exec $CMD $ARGS
diff --git a/etc/kolla/config/database.conf b/etc/kolla/config/database.conf
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/etc/kolla/config/global.conf b/etc/kolla/config/global.conf
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/etc/kolla/config/keystone.conf b/etc/kolla/config/keystone.conf
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/etc/kolla/config/keystone/keystone.conf b/etc/kolla/config/keystone/keystone.conf
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/etc/kolla/config/messaging.conf b/etc/kolla/config/messaging.conf
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/etc/kolla/defaults.yml b/etc/kolla/defaults.yml
new file mode 100644
index 0000000000..3eda373979
--- /dev/null
+++ b/etc/kolla/defaults.yml
@@ -0,0 +1,20 @@
+---
+# The options in this file can be overridden in 'globals.yml', but typically
+# shouldn't be modified. A comment describing why the option exists should be
+# included before each option.
+
+# Ansible Docker module bug. This can be removed when Ansible 2.0 arrives
+# https://github.com/ansible/ansible-modules-core/issues/1227
+docker_api_version: "1.18"
+
+# TODO(SamYaple): remove references to these variables in Ansible
+kolla_directory: "/usr/share/kolla"
+koalla_directory: "/usr/share/kolla"
+
+# The "temp" files that are created before merge need to stay persistent due
+# to the fact that ansible will register a "change" if it has to create them
+# again. Persistent files allow for idempotency
+node_templates_directory: "/usr/share/kolla/templates"
+
+# The directory to store the config files on the destination node
+node_config_directory: "/opt/kolla/config"
diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml
new file mode 100644
index 0000000000..cf95ebd218
--- /dev/null
+++ b/etc/kolla/globals.yml
@@ -0,0 +1,77 @@
+---
+# Please specify all passwords/secrets in the "/etc/kolla/passwords.yml"
+
+###################
+# Kolla options
+###################
+config_strategy: "CONFIG_EXTERNAL_COPY_ONCE"
+
+kolla_base_distro: "centos"
+kolla_install_type: "rdo"
+
+# The Public address used to communicate with Openstack
+# This must be set, but it can be an private ip. It can also be the same as the
+# internal address.
+kolla_external_address: "openstack.example.com"
+kolla_internal_address: "10.10.10.254"
+
+
+####################
+# Database options
+####################
+database_address: "{{ keystone_internal_address }}"
+database_user: "root"
+
+
+####################
+# Docker options
+####################
+docker_registry:
+docker_namespace: "kollaglue"
+docker_registry_username:
+docker_insecure_registry: "False"
+
+# Valid options are [ missing, always ]
+docker_pull_policy: "always"
+
+# Valid options are [ no, on-failure, always ]
+docker_restart_policy: "always"
+
+# '0' means unlimited retries
+docker_restart_policy_retry: "10"
+
+### Example: Private repository with authentication
+#
+# docker_registry: "172.16.0.10:5000"
+# docker_namespace: "companyname"
+# docker_registry_username: "sam"
+# docker_registry_password: "correcthorsebatterystaple"
+# docker_insecure_registry: "False"
+
+
+####################
+# Networking options
+####################
+# The interface to use for various services types
+network_interface: "eth0"
+
+# These can be adjusted for even more customization
+api_interface: "{{ network_interface }}"
+storage_interface: "{{ network_interface }}"
+neutron_interface: "{{ network_interface }}"
+
+
+####################
+# Openstack options
+####################
+openstack_release: "latest"
+
+openstack_logging_verbose: "True"
+openstack_logging_debug: "False"
+
+
+####################
+# RabbitMQ options
+####################
+#placeholder
+
diff --git a/etc/kolla/passwords.yml b/etc/kolla/passwords.yml
new file mode 100644
index 0000000000..79fa6868c1
--- /dev/null
+++ b/etc/kolla/passwords.yml
@@ -0,0 +1,29 @@
+---
+# TODO: SamYaple
+# This file should have generated values by default. Propose Ansible vault for
+# locking down the secrets properly.
+
+
+###################
+# Database options
+####################
+database_password: "password"
+
+
+####################
+# Docker options
+####################
+docker_registry_password:
+
+
+####################
+# Openstack options
+####################
+keystone_admin_token: "password"
+keystone_database_password: "password"
+
+
+####################
+# RabbitMQ options
+####################
+
diff --git a/tools/genenv b/tools/genenv
index 07fe45e472..d04b67876b 100755
--- a/tools/genenv
+++ b/tools/genenv
@@ -246,6 +246,7 @@ export OS_VOLUME_API_VERSION=$CINDER_API_VERSION
 EOF
 
 cat > ./compose/openstack.env <<EOF
+CONFIG_STRATEGY=CONFIG_INTERNAL
 DEBUG_LOGGING=$DEBUG_LOGGING
 VERBOSE_LOGGING=$VERBOSE_LOGGING
 NOVA_LOG_DIR=$NOVA_LOG_DIR