diff --git a/grafana/defaults/main.yml b/grafana/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6acdb5307667369056be1f1136272266fddc3cd5
--- /dev/null
+++ b/grafana/defaults/main.yml
@@ -0,0 +1,18 @@
+---
+
+grafana_serve_from_sub_path: "false"
+grafana_ldap: false
+grafana_ldap_allow_sign_up: "false"
+grafana_basic_auth: true
+grafana_cookie_secure: "false"
+grafana_allow_sign_up: "false"
+grafana_allow_org_create: "false"
+grafana_auto_assign_org: "true"
+grafana_auto_assign_org_id: 1
+grafana_auto_assign_org_role: "Viewer"
+grafana_smtp_enabled: false
+grafana_smtp_host: mailrelay.example.org
+grafana_smtp_from_address: grafana@example.org
+grafana_smtp_from_name: Grafana
+grafana_metrics_enabled: "false"
+grafana_extra_config: ""
diff --git a/grafana/files/grafana-server-override.service b/grafana/files/grafana-server-override.service
new file mode 100644
index 0000000000000000000000000000000000000000..a283d92f3e7b346a547783069717c42acbda5bc3
--- /dev/null
+++ b/grafana/files/grafana-server-override.service
@@ -0,0 +1,3 @@
+[Service]
+RuntimeDirectoryMode=0751
+ExecStartPost=sh -c "while test ! -S ${RUNTIME_DIRECTORY}/sock; do sleep 1; done; chmod 0666 ${RUNTIME_DIRECTORY}/sock"
diff --git a/grafana/handlers/main.yml b/grafana/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d4d98b6e35ea5faff5d2f1707afc141fc44eaf31
--- /dev/null
+++ b/grafana/handlers/main.yml
@@ -0,0 +1,10 @@
+---
+
+- name: Restart Grafana
+  systemd:
+    name: grafana-server.service
+    state: restarted
+
+- name: Reload systemd
+  systemd:
+    daemon_reload: true
diff --git a/grafana/tasks/main.yml b/grafana/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6ddae6bf13813ac0f02aadf1720c5456fd95c643
--- /dev/null
+++ b/grafana/tasks/main.yml
@@ -0,0 +1,92 @@
+---
+
+- name: Install Grafana repository keys
+  apt_key:
+    url: https://packages.grafana.com/gpg.key
+    state: present
+  tags:
+    - packages
+    - repo
+    - grafana
+    - config
+
+- name: Install Grafana repo
+  apt_repository:
+    repo: "deb https://packages.grafana.com/enterprise/deb stable main"
+  tags:
+    - packages
+    - repo
+    - grafana
+    - config
+
+- name: Install Grafana
+  apt:
+    name:
+      - grafana-enterprise
+    state: present
+  tags:
+    - packages
+    - grafana
+
+- name: Create systemd unit override directory
+  file:
+    path: /etc/systemd/system/grafana-server.service.d
+    state: directory
+    owner: root
+    group: root
+    mode: "0755"
+  tags:
+    - grafana
+    - config
+
+- name: Configure Grafana systemd service
+  copy:
+    src: grafana-server-override.service
+    dest: /etc/systemd/system/grafana-server.service.d/ansible-override.conf
+    owner: root
+    group: root
+    mode: "0644"
+  notify:
+    - Reload systemd
+    - Restart Grafana
+  tags:
+    - grafana
+    - config
+
+- name: Configure Grafana
+  template:
+    src: grafana.ini.j2
+    dest: /etc/grafana/grafana.ini
+    owner: root
+    group: grafana
+    mode: "0640"
+  notify:
+    - Restart Grafana
+  tags:
+    - config
+    - grafana
+
+- name: Configure Grafana LDAP auth
+  template:
+    src: ldap.toml.j2
+    dest: /etc/grafana/ldap.toml
+    owner: root
+    group: grafana
+    mode: "0640"
+  when:
+    - grafana_ldap
+  notify:
+    - Restart Grafana
+  tags:
+    - config
+    - grafana
+
+- meta: flush_handlers
+
+- name: Enable and start Grafana
+  systemd:
+    name: grafana-server.service
+    state: started
+    enabled: true
+  tags:
+    - grafana
diff --git a/grafana/templates/grafana.ini.j2 b/grafana/templates/grafana.ini.j2
new file mode 100644
index 0000000000000000000000000000000000000000..bbb00196406f57cc2c088ea7a3d89ca19fefeb7e
--- /dev/null
+++ b/grafana/templates/grafana.ini.j2
@@ -0,0 +1,90 @@
+# -*- conf-unix -*-
+
+[server]
+# Protocol (http, https, h2, socket)
+protocol = socket
+
+# The public facing domain name used to access grafana from a browser
+domain = {{ grafana_domain }}
+
+# The full public facing url you use in browser, used for redirects and emails
+# If you use reverse proxy and sub path specify full url (with sub path)
+root_url = {{ grafana_root_url }}
+
+# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons.
+serve_from_sub_path = {{ grafana_serve_from_sub_path }}
+
+# Unix socket path
+socket = /run/grafana/sock
+
+[database]
+{% if grafana_database_url is defined %}
+url = {{ grafana_database_url }}
+{% endif %}
+
+[analytics]
+# Server reporting, sends usage counters to stats.grafana.org every 24 hours.
+# No ip addresses are being tracked, only simple counters to track
+# running instances, dashboard and error counts. It is very helpful to us.
+# Change this option to false to disable reporting.
+reporting_enabled = false
+
+[security]
+# disable creation of admin user on first start of grafana
+disable_initial_admin_creation = true
+
+# disable gravatar profile images
+disable_gravatar = true
+
+{% if grafana_data_source_proxy_whitelist is defined %}
+# data source proxy whitelist (ip_or_domain:port separated by spaces)
+data_source_proxy_whitelist = {{ grafana_data_source_proxy_whitelist }}
+{% endif %}
+
+# set to true if you host Grafana behind HTTPS. default is false.
+cookie_secure = {{ grafana_cookie_secure }}
+
+[users]
+# disable user signup / registration
+allow_sign_up = {{ grafana_allow_sign_up }}
+
+# Allow non admin users to create organizations
+allow_org_create = {{ grafana_allow_org_create }}
+
+# Set to true to automatically assign new users to the default organization (id 1)
+auto_assign_org = {{ grafana_auto_assign_org }}
+
+# Set this value to automatically add new users to the provided organization (if auto_assign_org above is set to true)
+auto_assign_org_id = {{ grafana_auto_assign_org_id }}
+
+# Default role new users will be automatically assigned (if disabled above is set to true)
+auto_assign_org_role = {{ grafana_auto_assign_org_role }}
+
+# Require email validation before sign up completes
+verify_email_enabled = true
+
+[auth.basic]
+enabled = {{ grafana_basic_auth }}
+
+[auth.ldap]
+enabled = {{ grafana_ldap }}
+allow_sign_up = {{ grafana_ldap_allow_sign_up }}
+
+[smtp]
+enabled = {{ grafana_smtp_enabled }}
+host = {{ grafana_smtp_host }}
+from_address = {{ grafana_smtp_from_address }}
+from_name = {{ grafana_smtp_from_name }}
+
+[metrics]
+# Disable / Enable internal metrics
+enabled           = {{ grafana_metrics_enabled }}
+
+{% if grafana_metrics_auth is defined %}
+#If both are set, basic auth will be required for the metrics endpoint.
+basic_auth_username = {{ grafana_metrics_auth.user }}
+basic_auth_password = {{ grafana_metrics_auth.password }}
+{% endif %}
+
+
+{{ grafana_extra_config }}
diff --git a/grafana/templates/ldap.toml.j2 b/grafana/templates/ldap.toml.j2
new file mode 100644
index 0000000000000000000000000000000000000000..8244ac3c6afe67bfe806675f0d59e44ddf417659
--- /dev/null
+++ b/grafana/templates/ldap.toml.j2
@@ -0,0 +1,56 @@
+# -*- toml -*-
+
+{% for s in grafana_ldap_servers %}
+[[servers]]
+
+# Ldap server host (specify multiple hosts space separated)
+host = "{{ s.host }}"
+
+# Default port is 389 or 636 if use_ssl = true
+port = {{ s.port|default(389) }}
+
+# Set to true if ldap server supports TLS
+use_ssl = {{ s.use_ssl|default("false") }}
+
+# Set to true if connect ldap server with STARTTLS pattern (create connection in insecure, then upgrade to secure connection with TLS)
+start_tls = {{ s.start_tls|default("true") }}
+
+{% if s.root_ca_cert is defined %}
+# set to the path to your root CA certificate or leave unset to use system defaults
+root_ca_cert = "{{ s.root_ca_cert }}"
+{% endif %}
+
+# Search user bind dn
+bind_dn = "{{ s.bind_dn }}"
+
+{% if s.bind_password is defined %}
+# Search user bind password
+# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
+bind_password = """{{ s.bind_password }}"""
+{% endif %}
+
+# User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)"
+search_filter = "{{ s.search_filter }}"
+
+# An array of base dns to search through
+search_base_dns = ["{{ s.search_base_dns|join('", "') }}"]
+
+# Specify names of the ldap attributes your ldap uses
+[servers.attributes]
+{% for k, v in s.attributes.items() %}
+{{ k }} = "{{ v }}"
+{% endfor %}
+
+# Map ldap groups to grafana org roles
+{% for m in s.group_mappings %}
+[[servers.group_mappings]]
+group_dn = "{{ m.group_dn }}"
+org_role = "{{ m.org_role }}"
+grafana_admin = {{ m.grafana_admin|default("false") }}
+{% if m.org_id is defined %}
+# The Grafana organization database id, optional, if left out the default org (id 1) will be used
+org_id = {{ m.org_id }}
+{% endif %}
+{% endfor %} {# m in s.group_mappings #}
+
+{% endfor %} {# s in grafana_ldap_servers #}