diff --git a/azure/terraform/init.tf b/azure/terraform/init.tf
index 1b508b4f24b0af03947f707636466fcb7848fce4..8f1f4c75c53e20b2ce61bbda8f96199fba80ccca 100644
--- a/azure/terraform/init.tf
+++ b/azure/terraform/init.tf
@@ -22,11 +22,21 @@ data "azurerm_subnet" "default" {
   resource_group_name  = "swh-resource"
 }
 
+variable "firstboot_script" {
+  type = string
+  default = "/root/firstboot.sh"
+}
+
 variable "ssh_key_data_ardumont" {
   type    = string
   default = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZarzgHrzUYspvrgSI6fszrALo92BDys7QOkJgUfZa9t9m4g7dUANNtwBiqIbqijAQPmB1zKgG6QTZC5rJkRy6KqXCW/+Qeedw/FWIbuI7jOD5WxnglbEQgvPkkB8kf1xIF7icRfWcQmK2je/3sFd9yS4/+jftNMPPXkBCxYm74onMenyllA1akA8FLyujLu6MNA1D8iLLXvz6pBDTT4GZ5/bm3vSE6Go8Xbuyu4SCtYZSHaHC2lXZ6Hhi6dbli4d3OwkUWz+YhFGaEra5Fx45Iig4UCL6kXPkvL/oSc9KGerpT//Xj9qz1K7p/IrBS8+eA4X69bHYYV0UZKDADZSn ardumont@yavin4"
 }
 
+variable "ssh_key_data_olasd" {
+  type    = string
+  default = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZ1TCpfzrvxLhEMhxjbxqPDCwY0nazIr1cyIbhGD2bUdAbZqVMdNtr7MeDnlLIKrIPJWuvltauvLNkYU0iLc1jMntdBCBM3hgXjmTyDtc8XvXseeBp5tDqccYNR/cnDUuweNcL5tfeu5kzaAg3DFi5Dsncs5hQK5KQ8CPKWcacPjEk4ir9gdFrtKG1rZmg/wi7YbfxrJYWzb171hdV13gSgyXdsG5UAFsNyxsKSztulcLKxvbmDgYbzytr38FK2udRk7WuqPbtEAW1zV4yrBXBSB/uw8EAMi+wwvLTwyUcEl4u0CTlhREljUx8LhYrsQUCrBcmoPAmlnLCD5Q9XrGH nicolasd@darboux id_rsa.inria.pub"
+}
+
 variable "user_admin" {
   type    = string
   default = "tmpadmin"
diff --git a/azure/terraform/kafka.tf b/azure/terraform/kafka.tf
new file mode 100644
index 0000000000000000000000000000000000000000..50f54e80725a69a0f14e7cadf7491b85891eeda1
--- /dev/null
+++ b/azure/terraform/kafka.tf
@@ -0,0 +1,132 @@
+variable "kafka_servers" {
+  default = 6
+}
+
+variable "kafka_disk_size" {
+  default = 8192
+}
+
+resource "azurerm_resource_group" "euwest-kafka" {
+  name     = "euwest-kafka"
+  location = "westeurope"
+
+  tags = {
+    environment = "Kafka"
+  }
+}
+
+resource "azurerm_network_interface" "kafka-interface" {
+  count = var.kafka_servers
+
+  name                      = format("kafka%02d-interface", count.index + 1)
+  location                  = "westeurope"
+  resource_group_name       = "euwest-kafka"
+  network_security_group_id = data.azurerm_network_security_group.worker-nsg.id
+
+  ip_configuration {
+    name                          = "vaultNicConfiguration"
+    subnet_id                     = data.azurerm_subnet.default.id
+    public_ip_address_id          = ""
+    private_ip_address_allocation = "Dynamic"
+  }
+}
+
+resource "azurerm_virtual_machine" "kafka-server" {
+  count = var.kafka_servers
+
+  name                  = format("kafka%02d", count.index + 1)
+  location              = "westeurope"
+  resource_group_name   = "euwest-kafka"
+  network_interface_ids = [azurerm_network_interface.kafka-interface[count.index].id]
+  vm_size               = "Standard_B2s"
+
+  storage_os_disk {
+    name              = format("kafka%02d-osdisk", count.index + 1)
+    caching           = "ReadWrite"
+    create_option     = "FromImage"
+    managed_disk_type = "Premium_LRS"
+  }
+
+  storage_data_disk {
+    name              = format("kafka%02d-datadisk", count.index + 1)
+    caching           = "None"
+    create_option     = "Empty"
+    managed_disk_type = "Standard_LRS"
+    disk_size_gb      = var.kafka_disk_size
+    lun               = 1
+  }
+
+  storage_image_reference {
+    publisher = "credativ"
+    offer     = "Debian"
+    sku       = "9"
+    version   = "latest"
+  }
+
+  os_profile {
+    computer_name  = format("kafka%02d", count.index + 1)
+    admin_username = var.user_admin
+  }
+
+  os_profile_linux_config {
+    disable_password_authentication = true
+    ssh_keys {
+      path     = "/home/${var.user_admin}/.ssh/authorized_keys"
+      key_data = var.ssh_key_data_olasd
+    }
+  }
+
+  provisioner "remote-exec" {
+    inline = [
+      "sudo mkdir /root/.ssh",
+      "echo ${var.ssh_key_data_ardumont} | sudo tee -a /root/.ssh/authorized_keys",
+      "echo ${var.ssh_key_data_olasd} | sudo tee -a /root/.ssh/authorized_keys",
+    ]
+
+    connection {
+      type = "ssh"
+      user = var.user_admin
+      host = azurerm_network_interface.kafka-interface[count.index].private_ip_address
+    }
+  }
+
+  provisioner "file" {
+    content     = templatefile("templates/firstboot.sh.tpl", {
+      hostname   = format("kafka%02d", count.index + 1),
+      fqdn       = format("kafka%02d.euwest.azure.internal.softwareheritage.org", count.index + 1),
+      ip_address = azurerm_network_interface.kafka-interface[count.index].private_ip_address,
+      facter_location = "azure_euwest",
+      disks = [{
+        base_disk = "/dev/sdc",
+        mountpoint = "/srv/kafka",
+        filesystem = "ext4",
+        mount_options = "defaults",
+      }]
+    })
+    destination = var.firstboot_script
+
+    connection {
+      type = "ssh"
+      user = "root"
+      host = azurerm_network_interface.kafka-interface[count.index].private_ip_address
+    }
+  }
+
+  provisioner "remote-exec" {
+    inline = [
+      "userdel -f ${var.user_admin}",
+      "chmod +x ${var.firstboot_script}",
+      "cat ${var.firstboot_script}",
+      "${var.firstboot_script}",
+    ]
+    connection {
+      type = "ssh"
+      user = "root"
+      host = azurerm_network_interface.kafka-interface[count.index].private_ip_address
+    }
+  }
+
+  tags = {
+    environment = "Kafka"
+  }
+}
diff --git a/azure/terraform/templates/firstboot.sh.tpl b/azure/terraform/templates/firstboot.sh.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..77057e782cac08982811c45b4ffeb431f83e38b5
--- /dev/null
+++ b/azure/terraform/templates/firstboot.sh.tpl
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+set -ex
+
+cd /
+
+PUPPET_MASTER=pergamon.internal.softwareheritage.org
+
+# Variables provided by terraform
+HOSTNAME=${hostname}
+FQDN=${fqdn}
+IP=${ip_address}
+FACTER_LOCATION=${facter_location}
+
+%{ for disk in disks }
+# Make one large partition on ${disk.base_disk}
+echo ';' | sudo sfdisk --label gpt ${disk.base_disk}
+
+mkfs.${disk.filesystem} ${disk.base_disk}1
+
+mkdir -p ${disk.mountpoint}
+
+uuid=$(blkid -o value -s UUID ${disk.base_disk}1)
+echo "UUID=\"$uuid\" ${disk.mountpoint} ${disk.filesystem} ${disk.mount_options} 0 0" >> /etc/fstab
+%{ endfor }
+
+mount -a
+
+apt-get -y install lsb-release
+debian_suite=$(lsb_release -cs)
+
+# Enable backports
+cat > /etc/apt/sources.list.d/backports.list <<EOF
+deb http://deb.debian.org/debian $${debian_suite}-backports main
+EOF
+
+# Update packages
+apt-get update
+apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
+
+# Properly set hostname and FQDN
+echo $HOSTNAME > /etc/hostname
+hostnamectl set-hostname $HOSTNAME
+echo "$IP $FQDN $HOSTNAME" >> /etc/hosts
+
+# install puppet dependencies
+apt-get -y install -t $${debian_suite}-backports facter
+apt-get -y install puppet
+
+# do not need the service live as we need to install some more setup first
+service puppet stop
+systemctl disable puppet.service
+
+# Install the location fact as that is needed by our puppet manifests
+mkdir -p /etc/facter/facts.d
+echo location=$FACTER_LOCATION > /etc/facter/facts.d/location.txt
+
+# first time around, this will:
+# - update the node's puppet agent configuration defining the puppet master
+# - generate the certificates with the appropriate fqdn
+# - unfortunately, for now, this fails though, when not being able to
+#   install the apt-transport-https package
+puppet agent --server $PUPPET_MASTER --waitforcert 60 --test
+
+#reboot