diff --git a/promtail/defaults/main.yml b/promtail/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..31b9b686720a0c7d3390ebd415d37d666a1b2716
--- /dev/null
+++ b/promtail/defaults/main.yml
@@ -0,0 +1,29 @@
+---
+
+promtail_version: "2.6.1"
+
+promtail_scrape_journal:
+  job_name: journal
+  journal:
+    json: true
+    labels:
+      job: journal
+
+promtail_scrape_varlog:
+  job_name: varlog
+  static_configs:
+    - labels:
+        job: varlog
+        __path__: /var/log/**/*.log
+
+promtail_config_server:
+  disable: true
+promtail_config_clients:
+  - url: http://loki.example.com:3100/loki/api/v1/push
+promtail_config_positions: {}
+promtail_config_scrape:
+  - "{{ promtail_scrape_journal }}"
+  - "{{ promtail_scrape_varlog }}"
+promtail_config_limits: {}
+promtail_config_target: {}
+promtail_config_options: {}
diff --git a/promtail/files/promtail.service b/promtail/files/promtail.service
new file mode 100644
index 0000000000000000000000000000000000000000..bda880afcad105d5f7855d614c545ce85b9d64ff
--- /dev/null
+++ b/promtail/files/promtail.service
@@ -0,0 +1,46 @@
+[Unit]
+Description=Grafana Loki Promtail log scraper
+Wants=network-online.target
+After=network-online.target
+
+[Service]
+ExecStart=/usr/local/bin/promtail \
+	-config.file ${CONFIGURATION_DIRECTORY}/config.yaml \
+	-config.expand-env=true \
+	$PROMTAIL_EXTRA_ARGS
+EnvironmentFile=-/etc/default/promtail
+
+### File system protection dance
+# Access files regardless of permissions
+AmbientCapabilities=CAP_DAC_OVERRIDE
+DynamicUser=true
+# Explicitly allow access to specific config and state directory …
+ConfigurationDirectoryMode=0700
+ConfigurationDirectory=promtail
+StateDirectory=promtail
+# … but otherwise block non-system data.
+InaccessiblePaths=-/srv -/exports /media /mnt
+# Nesting allowed paths below InaccessiblePaths= does not work,
+# cf. systemd.exec(5)
+TemporaryFileSystem=/var:ro /etc:ro
+BindReadOnlyPaths=/var/log /var/lib/dbus/machine-id /etc/machine-id /etc/resolv.conf /etc/nsswitch.conf /etc/hosts /etc/timezone /etc/localtime /etc/ssl/certs
+
+### Boilerplate protection stuff
+ProtectProc=invisible
+NoNewPrivileges=true
+ProtectSystem=strict
+ProtectHome=true
+PrivateTmp=true
+PrivateDevices=true
+# PrivateUsers must be false for the capability stuff above to work
+PrivateUsers=false
+ProtectKernelLogs=false
+RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+RestrictNamespaces=true
+LockPersonality=true
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
+SystemCallArchitectures=native
+
+[Install]
+WantedBy=multi-user.target
diff --git a/promtail/handlers/main.yml b/promtail/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..189c57fe36505d1c935932870e89493e757010a7
--- /dev/null
+++ b/promtail/handlers/main.yml
@@ -0,0 +1,10 @@
+---
+
+- name: Reload systemd
+  systemd:
+    daemon_reload: true
+
+- name: Restart promtail
+  systemd:
+    name: promtail.service
+    state: restarted
diff --git a/promtail/tasks/main.yml b/promtail/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d27a1cf7bdb9bd6bef22eac72e09c6476d3d5326
--- /dev/null
+++ b/promtail/tasks/main.yml
@@ -0,0 +1,56 @@
+---
+
+- name: Install promtail binary
+  unarchive:
+    # yamllint disable-line rule:line-length
+    src: "https://github.com/grafana/loki/releases/download/v{{ promtail_version }}/promtail-linux-{{ promtail_arch }}.zip"
+    dest: /usr/local/bin
+    remote_src: true
+    owner: root
+    group: root
+    mode: "0755"
+    include:
+      - "promtail-linux-{{ promtail_arch }}"
+
+- name: Create promtail binary link
+  file:
+    path: /usr/local/bin/promtail
+    src: "promtail-linux-{{ promtail_arch }}"
+    state: link
+
+- name: Create promtail configuration directory
+  file:
+    path: /etc/promtail
+    state: directory
+    owner: root
+    group: root
+    mode: "0700"
+
+- name: Configure promtail
+  template:
+    src: config.yaml.j2
+    dest: /etc/promtail/config.yaml
+    owner: root
+    group: root
+    mode: "0644"
+  notify:
+    - Restart promtail
+
+- name: Configure promtail service
+  copy:
+    src: promtail.service
+    dest: /etc/systemd/system/promtail.service
+    owner: root
+    group: root
+    mode: "0644"
+  notify:
+    - Reload systemd
+    - Restart promtail
+
+- meta: flush_handlers
+
+- name: Enable and start promtail service
+  systemd:
+    name: promtail.service
+    enabled: true
+    state: started
diff --git a/promtail/templates/config.yaml.j2 b/promtail/templates/config.yaml.j2
new file mode 100644
index 0000000000000000000000000000000000000000..4345f58a604ab2fe4f84bedf480477218a868d11
--- /dev/null
+++ b/promtail/templates/config.yaml.j2
@@ -0,0 +1,26 @@
+{# -*- yaml -*- #}
+---
+
+server:
+  {{ promtail_config_server|to_yaml|indent(2, False) }}
+
+clients:
+  {{ promtail_config_clients|to_yaml|indent(2, False) }}
+
+positions:
+  filename: /var/lib/private/promtail/positions.yaml
+{% for k, v in promtail_config_positions %}
+  {{ k }}: {{ v|to_yaml|indent(4, False) }}
+{% endfor %}
+
+scrape_configs:
+  {{ promtail_config_scrape|to_yaml|indent(2, False) }}
+
+limits_config:
+  {{ promtail_config_limits|to_yaml|indent(2, False) }}
+
+target_config:
+  {{ promtail_config_target|to_yaml|indent(2, False) }}
+
+options:
+  {{ promtail_config_options|to_yaml|indent(2, False) }}
diff --git a/promtail/vars/main.yml b/promtail/vars/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..af517bb07f1ccda9828657f6bbb97b31bbf2ccb7
--- /dev/null
+++ b/promtail/vars/main.yml
@@ -0,0 +1,12 @@
+---
+
+promtail_arch: >-
+  {% if ansible_architecture == "x86_64" -%}
+  amd64
+  {%- elif ansible_architecture == "aarch64" -%}
+  arm64
+  {%- elif ansible_architecture[:3] == "arm" -%}
+  {{ ansible_architecture[:3] }}
+  {%- else -%}
+  {{ ansible_architecture }}
+  {%- endif %}