diff --git a/playbooks/monitoring.archlinux.org.yml b/playbooks/monitoring.archlinux.org.yml
index 2bd20f858573080b1e100e901aa41b6755f43bd6..14e93f5bed2232a8cedc80ef8243bdcad682045c 100644
--- a/playbooks/monitoring.archlinux.org.yml
+++ b/playbooks/monitoring.archlinux.org.yml
@@ -14,6 +14,7 @@
     - { role: prometheus_exporters }
     - { role: loki }
     - { role: promtail }
+    - { role: tempo }
     - { role: certbot }
     - { role: nginx }
     - { role: grafana, grafana_domain: 'monitoring.archlinux.org' }
diff --git a/roles/handlers/main.yml b/roles/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/roles/tempo/handlers/main.yml b/roles/tempo/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cece918ab53448f815921a8cea87ae5ee71d9666
--- /dev/null
+++ b/roles/tempo/handlers/main.yml
@@ -0,0 +1,2 @@
+- name: Restart tempo
+  service: name=tempo state=restarted
diff --git a/roles/tempo/tasks/main.yml b/roles/tempo/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..bb7a23ee052d0efea4f8b8dbec63cf02807ec96d
--- /dev/null
+++ b/roles/tempo/tasks/main.yml
@@ -0,0 +1,16 @@
+- name: Install tempo
+  pacman: name=tempo state=present
+
+- name: Open promtail ipv4 port for monitoring.archlinux.org
+  ansible.posix.firewalld: zone=wireguard state=enabled permanent=true immediate=yes
+    rich_rule="rule family=ipv4 source address={{ hostvars['monitoring.archlinux.org']['wireguard_address'] }} port protocol=tcp port=4318 accept"
+  tags:
+    - firewall
+
+- name: Configure tempo
+  template: src=config.yml.j2 dest=/etc/tempo/config.yml owner=tempo group=tempo mode=0644
+  notify:
+    - Restart tempo
+
+- name: Enable tempo server service
+  systemd: name=tempo enabled=yes daemon_reload=yes state=started
diff --git a/roles/tempo/templates/config.yml.j2 b/roles/tempo/templates/config.yml.j2
new file mode 100644
index 0000000000000000000000000000000000000000..0b1b4f9bd6924335d16466974ec9973b7d63b186
--- /dev/null
+++ b/roles/tempo/templates/config.yml.j2
@@ -0,0 +1,51 @@
+stream_over_http_enabled: true
+server:
+  http_listen_address: 127.0.0.1
+  http_listen_port: 3200
+  grpc_listen_address: 127.0.0.1
+  grpc_listen_port: 3201
+  log_level: info
+
+query_frontend:
+  search:
+    duration_slo: 5s
+    throughput_bytes_slo: 1.073741824e+09
+  trace_by_id:
+    duration_slo: 5s
+
+distributor:
+  receivers:
+    otlp:
+      protocols:
+        http:
+          endpoint: {{ wireguard_address }}:4318
+
+ingester:
+  max_block_duration: 5m               # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally
+
+compactor:
+  compaction:
+    block_retention: 1h                # overall Tempo trace retention. set for demo purposes
+
+metrics_generator:
+  registry:
+    external_labels:
+      source: tempo
+  storage:
+    path: /var/lib/tempo/generator/wal
+    remote_write:
+      - url: http://localhost:9090/api/v1/write
+        send_exemplars: true
+  traces_storage:
+    path: /var/lib/tempo/generator/traces
+
+storage:
+  trace:
+    backend: local                     # backend configuration to use
+    wal:
+      path: /var/lib/tempo/wal             # where to store the wal locally
+    local:
+      path: /var/lib/tempo/blocks
+
+overrides:
+  metrics_generator_processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator