diff --git a/ansible/roles/rabbitmq/defaults/main.yml b/ansible/roles/rabbitmq/defaults/main.yml
index f709401e95eca73c6943993bd521d3badf3544dc..d9b92040efd7f42d3dbf82dcafec59eefdfa2252 100644
--- a/ansible/roles/rabbitmq/defaults/main.yml
+++ b/ansible/roles/rabbitmq/defaults/main.yml
@@ -39,3 +39,4 @@ rabbitmq_dimensions: "{{ default_container_dimensions }}"
 rabbitmq_user: "openstack"
 rabbitmq_cluster_name: "openstack"
 rabbitmq_hostname: "{{ ansible_hostname }}"
+rabbitmq_pid_file: "/var/lib/rabbitmq/mnesia/rabbitmq.pid"
diff --git a/ansible/roles/rabbitmq/handlers/main.yml b/ansible/roles/rabbitmq/handlers/main.yml
index 3c31cf700d6c269de69b18a51d6d47c6f51f4e45..d25f4e2ef7f52880969011c3b9f0faec0687fbc1 100644
--- a/ansible/roles/rabbitmq/handlers/main.yml
+++ b/ansible/roles/rabbitmq/handlers/main.yml
@@ -1,5 +1,5 @@
 ---
-- name: Restart rabbitmq container
+- name: Restart rabbitmq container (first node)
   vars:
     service_name: "rabbitmq"
     service: "{{ rabbitmq_services[service_name] }}"
@@ -16,7 +16,40 @@
     dimensions: "{{ service.dimensions }}"
   when:
     - kolla_action != "config"
-    - inventory_hostname in groups[service.group]
+    - inventory_hostname == groups[service.group]|first
+    - service.enabled | bool
+    - config_json.changed | bool
+      or rabbitmq_confs.changed | bool
+      or rabbitmq_container.changed | bool
+  notify:
+    - Waiting for rabbitmq to start on first node
+
+- name: Waiting for rabbitmq to start on first node
+  vars:
+    service_name: "rabbitmq"
+    service: "{{ rabbitmq_services[service_name] }}"
+  shell: "docker exec {{ service.container_name }} rabbitmqctl wait {{ rabbitmq_pid_file }}"
+  when:
+    - inventory_hostname == groups[service.group]|first
+
+- name: Restart rabbitmq container (rest of nodes)
+  vars:
+    service_name: "rabbitmq"
+    service: "{{ rabbitmq_services[service_name] }}"
+    config_json: "{{ rabbitmq_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}"
+    rabbitmq_container: "{{ check_rabbitmq_containers.results|selectattr('item.key', 'equalto', service_name)|first }}"
+  become: true
+  kolla_docker:
+    action: "recreate_or_restart_container"
+    common_options: "{{ docker_common_options }}"
+    name: "{{ service.container_name }}"
+    image: "{{ service.image }}"
+    volumes: "{{ service.volumes }}"
+    environment: "{{ service.environment }}"
+    dimensions: "{{ service.dimensions }}"
+  when:
+    - kolla_action != "config"
+    - inventory_hostname != groups[service.group]|first
     - service.enabled | bool
     - config_json.changed | bool
       or rabbitmq_confs.changed | bool
diff --git a/ansible/roles/rabbitmq/tasks/config.yml b/ansible/roles/rabbitmq/tasks/config.yml
index 5c96364ddb9a9561c1a134c21ad7a5948433b893..df42bbe1b57212e8227be4b490bcedf9460a82c5 100644
--- a/ansible/roles/rabbitmq/tasks/config.yml
+++ b/ansible/roles/rabbitmq/tasks/config.yml
@@ -24,7 +24,8 @@
     - item.value.enabled | bool
   with_dict: "{{ rabbitmq_services }}"
   notify:
-    - Restart rabbitmq container
+    - Restart rabbitmq container (first node)
+    - Restart rabbitmq container (rest of nodes)
 
 - name: Copying over rabbitmq configs
   vars:
@@ -40,10 +41,11 @@
     - service.enabled | bool
   with_items:
     - "rabbitmq-env.conf"
-    - "rabbitmq.config"
+    - "rabbitmq.conf"
     - "definitions.json"
   notify:
-    - Restart rabbitmq container
+    - Restart rabbitmq container (first node)
+    - Restart rabbitmq container (rest of nodes)
 
 - name: Check rabbitmq containers
   become: true
@@ -62,4 +64,5 @@
     - item.value.enabled | bool
   with_dict: "{{ rabbitmq_services }}"
   notify:
-    - Restart rabbitmq container
+    - Restart rabbitmq container (first node)
+    - Restart rabbitmq container (rest of nodes)
diff --git a/ansible/roles/rabbitmq/tasks/upgrade.yml b/ansible/roles/rabbitmq/tasks/upgrade.yml
index f7f74c97c55f9c5f644ca67ebf554681b71394c6..3c176eb532fdc3bfba572702b64178c0c062304e 100644
--- a/ansible/roles/rabbitmq/tasks/upgrade.yml
+++ b/ansible/roles/rabbitmq/tasks/upgrade.yml
@@ -1,4 +1,7 @@
 ---
+# NOTE(pbourke): These tasks perform a 'full stop upgrade', which is necessary when moving between
+# major releases. In future kolla-ansible releases we may be able to change this to a rolling
+# restart. For info on this process see https://www.rabbitmq.com/upgrade.html
 - name: Checking if rabbitmq container needs upgrading
   vars:
     service_name: "rabbitmq"
@@ -15,14 +18,25 @@
 
 - include_tasks: config.yml
 
-- name: Flush handlers
-  meta: flush_handlers
+- name: Stopping all rabbitmq instances but the first node
+  become: true
+  kolla_docker:
+    action: "stop_container"
+    common_options: "{{ docker_common_options }}"
+    name: "{{ project_name }}"
   when:
-    - rabbitmq_hostname == (gospel_node.stdout | from_json).hostname
+    - inventory_hostname != groups[role_rabbitmq_groups]|first
     - rabbitmq_differs['result']
 
-- name: Flush handlers
-  meta: flush_handlers
+- name: Stopping rabbitmq on the first node
+  become: true
+  kolla_docker:
+    action: "stop_container"
+    common_options: "{{ docker_common_options }}"
+    name: "{{ project_name }}"
   when:
-    - rabbitmq_hostname != (gospel_node.stdout | from_json).hostname
+    - inventory_hostname == groups[role_rabbitmq_groups]|first
     - rabbitmq_differs['result']
+
+- name: Flush handlers
+  meta: flush_handlers
diff --git a/ansible/roles/rabbitmq/templates/definitions.json.j2 b/ansible/roles/rabbitmq/templates/definitions.json.j2
index be3c47ee02912c4f9e6e22efb43a46b2f1e0fe41..e06ae867c3101021709e476ce8b2c940f3255010 100644
--- a/ansible/roles/rabbitmq/templates/definitions.json.j2
+++ b/ansible/roles/rabbitmq/templates/definitions.json.j2
@@ -5,7 +5,7 @@
     {% endif %}
   ],
   "users": [
-    {"name": "{{ role_rabbitmq_user }}", "password": "password", "tags": "administrator"}{% if role_rabbitmq_monitoring_user is defined and role_rabbitmq_monitoring_user %},
+    {"name": "{{ role_rabbitmq_user }}", "password": "{{ role_rabbitmq_password }}", "tags": "administrator"}{% if role_rabbitmq_monitoring_user is defined and role_rabbitmq_monitoring_user %},
     {"name": "{{ role_rabbitmq_monitoring_user }}", "password": "{{ role_rabbitmq_monitoring_password }}", "tags": "monitoring"}{% endif %}{% if project_name == 'outward_rabbitmq' %},
     {"name": "{{ murano_agent_rabbitmq_user }}", "password": "{{ murano_agent_rabbitmq_password }}", "tags": "management"}
     {% endif %}
diff --git a/ansible/roles/rabbitmq/templates/rabbitmq-env.conf.j2 b/ansible/roles/rabbitmq/templates/rabbitmq-env.conf.j2
index e2eea5e87cfde38154577333625d1e6b00a261e1..3d750fdd992e1717651ea8d1f1403a96b54b36cd 100644
--- a/ansible/roles/rabbitmq/templates/rabbitmq-env.conf.j2
+++ b/ansible/roles/rabbitmq/templates/rabbitmq-env.conf.j2
@@ -1,14 +1,7 @@
 RABBITMQ_NODENAME=rabbit@{{ ansible_hostname }}
 RABBITMQ_LOG_BASE=/var/log/kolla/{{ project_name }}
+RABBITMQ_DIST_PORT={{ role_rabbitmq_cluster_port }}
+RABBITMQ_PID_FILE={{ rabbitmq_pid_file }}
 
-# TODO(sdake, vhosakot)
-# erlang by default binds to wildcard (all interfaces) and can potentially
-# interfere with the neutron external or tenant networks. We should in theory
-# bind epmd to the host's IPv4 address to address the issue however this also
-# has issues and can crash erlang when it is compiled with IPv6 support.
-# See bugs:
-# https://bugs.launchpad.net/ubuntu/+source/erlang/+bug/1374109
-# https://bugs.launchpad.net/kolla/+bug/1562701
-# https://bugzilla.redhat.com/show_bug.cgi?id=1324922
-#export ERL_EPMD_ADDRESS={{ api_interface_address }}
+export ERL_EPMD_ADDRESS={{ api_interface_address }}
 export ERL_EPMD_PORT={{ role_rabbitmq_epmd_port }}
diff --git a/ansible/roles/rabbitmq/templates/rabbitmq.conf.j2 b/ansible/roles/rabbitmq/templates/rabbitmq.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..e95b7cccabc4deabf96eec1212384127c9458ec1
--- /dev/null
+++ b/ansible/roles/rabbitmq/templates/rabbitmq.conf.j2
@@ -0,0 +1,14 @@
+listeners.tcp.1 = {{ api_interface_address }}:{{ role_rabbitmq_port }}
+{% if rabbitmq_hipe_compile|bool %}
+hipe_compile = true
+{% endif %}
+cluster_partition_handling = autoheal
+
+management.listener.ip = {{ api_interface_address }}
+management.listener.port = {{ role_rabbitmq_management_port }}
+management.load_definitions = /etc/rabbitmq/definitions.json
+
+cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
+{% for host in groups[role_rabbitmq_groups] %}
+cluster_formation.classic_config.nodes.{{ loop.index0 }} = rabbit@{{ hostvars[host]['ansible_hostname'] }}
+{% endfor %}
diff --git a/ansible/roles/rabbitmq/templates/rabbitmq.config.j2 b/ansible/roles/rabbitmq/templates/rabbitmq.config.j2
deleted file mode 100644
index 960f9fb8a7cd0ebda4c66ac87bfb1ff82b3fcc4d..0000000000000000000000000000000000000000
--- a/ansible/roles/rabbitmq/templates/rabbitmq.config.j2
+++ /dev/null
@@ -1,24 +0,0 @@
-[
-  {kernel, [
-    {inet_dist_use_interface, {% raw %}{{% endraw %}{{ api_interface_address | regex_replace('\.', ',') }}}},
-    {inet_dist_listen_min, {{ role_rabbitmq_cluster_port }}},
-    {inet_dist_listen_max, {{ role_rabbitmq_cluster_port }}}
-  ]},
-  {rabbit, [
-{% if rabbitmq_hipe_compile|bool %}
-    {hipe_compile, true},
-{% endif %}
-    {tcp_listeners, [
-      {"{{ api_interface_address }}", {{ role_rabbitmq_port }}}
-    ]},
-    {cluster_partition_handling, autoheal}
-  ]},
-  {rabbitmq_management, [
-    {listener, [
-      {ip, "{{ api_interface_address }}"},
-      {port, {{ role_rabbitmq_management_port }}}
-    ]},
-    {load_definitions, "/etc/rabbitmq/definitions.json"}
-  ]}
-].
-% EOF
diff --git a/ansible/roles/rabbitmq/templates/rabbitmq.json.j2 b/ansible/roles/rabbitmq/templates/rabbitmq.json.j2
index c2b9269f6c630c3cb1a3044cb4807a50dc0d0811..284a823b0f08b5a50e02f47507dda96863893efa 100644
--- a/ansible/roles/rabbitmq/templates/rabbitmq.json.j2
+++ b/ansible/roles/rabbitmq/templates/rabbitmq.json.j2
@@ -8,8 +8,8 @@
             "perm": "0600"
         },
         {
-            "source": "{{ container_config_directory }}/rabbitmq.config",
-            "dest": "/etc/rabbitmq/rabbitmq.config",
+            "source": "{{ container_config_directory }}/rabbitmq.conf",
+            "dest": "/etc/rabbitmq/rabbitmq.conf",
             "owner": "rabbitmq",
             "perm": "0600"
         },
diff --git a/releasenotes/notes/update-rabbitmq-5db770469b9bae18.yaml b/releasenotes/notes/update-rabbitmq-5db770469b9bae18.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8d919cf6f736ecac8dea833e02a2f0f91afdf875
--- /dev/null
+++ b/releasenotes/notes/update-rabbitmq-5db770469b9bae18.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+  - |
+    Rabbitmq has been updated to 3.7.x. This comes with a new config format
+    which is now called rabbitmq.conf rather than rabbitmq.config.
diff --git a/tests/templates/globals-default.j2 b/tests/templates/globals-default.j2
index 2ea3107849474b025a08028d2851a37a4c2f74b0..95a7f27c83290b5e87a2ec1b1432444cf88a62bf 100644
--- a/tests/templates/globals-default.j2
+++ b/tests/templates/globals-default.j2
@@ -45,6 +45,3 @@ ceph_pool_pgp_num: 8
 {% endif %}
 
 keystone_token_provider: "fernet"
-
-# TODO(pbourke): remove once https://review.openstack.org/#/c/584427/ is merged
-rpc_transport_url: "rabbit://openstack:password@{{ api_interface_address }}:5672"
diff --git a/tools/setup_gate.sh b/tools/setup_gate.sh
index 18903d25c480e84fd32b18a389b1e36c5402e755..bdb0ec6e4f3cdd388c8da1be67ff9fe9150cd806 100755
--- a/tools/setup_gate.sh
+++ b/tools/setup_gate.sh
@@ -149,8 +149,7 @@ function test_openstack {
     tools/kolla-ansible -i ${RAW_INVENTORY} -vvv prechecks > /tmp/logs/ansible/prechecks1
     # TODO(jeffrey4l): add pull action when we have a local registry
     # service in CI
-    # TODO(pbourke): remove '-e rabbitmq_password=password' once https://review.openstack.org/#/c/584427/ is merged
-    tools/kolla-ansible -i ${RAW_INVENTORY} -vvv deploy -e rabbitmq_password=password > /tmp/logs/ansible/deploy
+    tools/kolla-ansible -i ${RAW_INVENTORY} -vvv deploy > /tmp/logs/ansible/deploy
     tools/kolla-ansible -i ${RAW_INVENTORY} -vvv post-deploy > /tmp/logs/ansible/post-deploy
     tools/kolla-ansible -i ${RAW_INVENTORY} -vvv check > /tmp/logs/ansible/check-deploy