diff --git a/_modules/opensearch.py b/_modules/opensearch.py
--- a/_modules/opensearch.py
+++ b/_modules/opensearch.py
@@ -49,6 +49,7 @@
         "node_name": nodename,
         "network_host": _get_ip(nodename),
         "lead_nodes": nodes,
+        "dashboards_nodes": nodes,
     })
 
     return config
diff --git a/roles/opensearch/dashboards/config.sls b/roles/opensearch/dashboards/config.sls
new file mode 100644
--- /dev/null
+++ b/roles/opensearch/dashboards/config.sls
@@ -0,0 +1,23 @@
+#   -------------------------------------------------------------
+#   Salt — Provision OpenSearch
+#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#   Project:        Nasqueron
+#   -------------------------------------------------------------
+
+{% set config = salt['opensearch.get_config']() %}
+
+#   -------------------------------------------------------------
+#   OpenSearch
+#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+/opt/opensearch-dashboards/config/opensearch_dashboards.yml:
+  file.managed:
+    - source: salt://roles/opensearch/dashboards/files/opensearch_dashboards.yml
+    - user: opensearch
+    - group: opensearch
+    - mode: 0600
+    - template: jinja
+    - context:
+        config: {{ config }}
+        username: {{ salt['zr.get_username'](config['users']['dashboards']) }}
+        password: {{ salt['zr.get_password'](config['users']['dashboards']) }}
diff --git a/roles/opensearch/dashboards/files/dashboards.service b/roles/opensearch/dashboards/files/dashboards.service
new file mode 100644
--- /dev/null
+++ b/roles/opensearch/dashboards/files/dashboards.service
@@ -0,0 +1,33 @@
+[Unit]
+Description=OpenSearch Dashboards
+Documentation=https://opensearch.org/docs/latest/
+After=network.target
+
+[Service]
+RuntimeDirectory=opensearch-dashboards
+PrivateTmp=true
+
+User=opensearch
+Group=opensearch
+
+LimitNOFILE=65536
+LimitMEMLOCK=infinity
+LimitNPROC=4096
+LimitAS=infinity
+LimitFSIZE=infinity
+
+WorkingDirectory=/opt/opensearch
+ExecStart=/opt/opensearch-dashboards/bin/opensearch-dashboards -q
+
+StandardOutput=journal
+StandardError=inherit
+
+# To shutdown: send SIGTERM signal to JVM, success if exit code 143
+TimeoutStopSec=0
+KillSignal=SIGTERM
+KillMode=process
+SendSIGKILL=no
+SuccessExitStatus=143
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/opensearch/dashboards/files/opensearch_dashboards.yml b/roles/opensearch/dashboards/files/opensearch_dashboards.yml
new file mode 100644
--- /dev/null
+++ b/roles/opensearch/dashboards/files/opensearch_dashboards.yml
@@ -0,0 +1,24 @@
+server.port: 5601
+server.host: {{ config["network_host"] }}
+opensearch.hosts:
+{% for node in config["dashboards_nodes"] %}
+  - https://{{ node }}:9200
+{% endfor %}
+
+opensearch.ssl.verificationMode: none
+opensearch.username: {{ username }}
+opensearch.password: {{ password }}
+
+opensearch.requestHeadersWhitelist:
+  - authorization
+  - securitytenant
+
+opensearch_security.multitenancy.enabled: True
+opensearch_security.multitenancy.tenants.preferred:
+  - Private
+  - Global
+
+opensearch_security.readonly_mode.roles:
+  - kibana_read_only
+
+opensearch_security.cookie.secure: False
diff --git a/roles/opensearch/init.sls b/roles/opensearch/dashboards/init.sls
copy from roles/opensearch/init.sls
copy to roles/opensearch/dashboards/init.sls
--- a/roles/opensearch/init.sls
+++ b/roles/opensearch/dashboards/init.sls
@@ -6,4 +6,5 @@
 #   -------------------------------------------------------------
 
 include:
-  - .opensearch
+  - .config
+  - .service
diff --git a/roles/opensearch/dashboards/service.sls b/roles/opensearch/dashboards/service.sls
new file mode 100644
--- /dev/null
+++ b/roles/opensearch/dashboards/service.sls
@@ -0,0 +1,31 @@
+#   -------------------------------------------------------------
+#   Salt — Provision OpenSearch
+#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#   Project:        Nasqueron
+#   License:        Trivial work, not eligible to copyright
+#   -------------------------------------------------------------
+
+#   -------------------------------------------------------------
+#   systemd
+#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+{% from "map.jinja" import services with context %}
+
+#   -------------------------------------------------------------
+#   Unit configuration
+#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+{% if services['manager'] == 'systemd' %}
+
+opensearch_dashboards_unit:
+  file.managed:
+    - name: /etc/systemd/system/dashboards.service
+    - source: salt://roles/opensearch/dashboards/files/dashboards.service
+    - mode: 0644
+  service.running:
+    - name: dashboards
+    - enable: true
+    - watch:
+      - file: opensearch_dashboards_unit
+
+{% endif %}
diff --git a/roles/opensearch/init.sls b/roles/opensearch/init.sls
--- a/roles/opensearch/init.sls
+++ b/roles/opensearch/init.sls
@@ -7,3 +7,4 @@
 
 include:
   - .opensearch
+  - .dashboards
diff --git a/roles/opensearch/opensearch/files/internal_users.yml.jinja b/roles/opensearch/opensearch/files/internal_users.yml.jinja
--- a/roles/opensearch/opensearch/files/internal_users.yml.jinja
+++ b/roles/opensearch/opensearch/files/internal_users.yml.jinja
@@ -30,6 +30,9 @@
 
 #   -------------------------------------------------------------
 #   Dashboards (formerly Kibana)
+#
+#   Currently, it seems easier to use harcoded `kibanaserver` name
+#   instead of assign a backend role.
 #   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 {{ users['dashboards']['username'] }}: