Create and provision IoT Edge devices at scale with a TPM on Linux

Applies to: IoT Edge 1.5 checkmark IoT Edge 1.5 IoT Edge 1.4 checkmark IoT Edge 1.4


IoT Edge 1.5 LTS and IoT Edge 1.4 LTS are supported releases. IoT Edge 1.4 LTS is end of life on November 12, 2024. If you are on an earlier release, see Update IoT Edge.

This article provides instructions for autoprovisioning an Azure IoT Edge for Linux device by using a Trusted Platform Module (TPM). You can automatically provision IoT Edge devices with the Azure IoT Hub device provisioning service. If you're unfamiliar with the process of autoprovisioning, review the provisioning overview before you continue.

This article outlines two methodologies. Select your preference based on the architecture of your solution:

  • Autoprovision a Linux device with physical TPM hardware.
  • Autoprovision a Linux virtual machine (VM) with a simulated TPM running on a Windows development machine with Hyper-V enabled. We recommend using this methodology only as a testing scenario. A simulated TPM doesn't offer the same security as a physical TPM.

Instructions differ based on your methodology, so make sure you're on the correct tab going forward.

The tasks are as follows:

  1. Retrieve provisioning information for your TPM.
  2. Create an individual enrollment for your device in an instance of the IoT Hub device provisioning service.
  3. Install the IoT Edge runtime and connect the device to the IoT hub.


Cloud resources

  • An active IoT hub
  • An instance of the IoT Hub device provisioning service in Azure, linked to your IoT hub

Device requirements

A physical Linux device to be the IoT Edge device.

If you are a device manufacturer, then refer to guidance on integrating a TPM into the manufacturing process.


TPM 2.0 is required when you use TPM attestation with the device provisioning service.

You can only create individual, not group, device provisioning service enrollments when you use a TPM.

Set up your device

If you're using a physical Linux device with a TPM, there are no extra steps to set up your device.

You're ready to continue.

Retrieve provisioning information for your TPM


This article previously used the tpm_device_provision tool from the IoT C SDK to generate provisioning info. If you relied on that tool previously, then be aware the steps below generate a different registration ID for the same public endorsement key. If you need to recreate the registration ID as before then refer to how the C SDK's tpm_device_provision tool generates it. Be sure the registration ID for the individual enrollment in DPS matches the regisration ID the IoT Edge device is configured to use.

In this section, you use the TPM2 software tools to retrieve the endorsement key for your TPM and then generate a unique registration ID. This section corresponds with Step 3: Device has firmware and software installed in the process for integrating a TPM into the manufacturing process.

Install the TPM2 Tools

Sign in to your device, and install the tpm2-tools package.

sudo apt-get install tpm2-tools

Run the following script to read the endorsement key, creating one if it does not already exist.

if [ "$USER" != "root" ]; then
  SUDO="sudo "

$SUDO tpm2_readpublic -Q -c 0x81010001 -o 2> /dev/null
if [ $? -gt 0 ]; then
  # Create the endorsement key (EK)
  $SUDO tpm2_createek -c 0x81010001 -G rsa -u

  # Create the storage root key (SRK)
  $SUDO tpm2_createprimary -Q -C o -c srk.ctx > /dev/null

  # make the SRK persistent
  $SUDO tpm2_evictcontrol -c srk.ctx 0x81000001 > /dev/null

  # open transient handle space for the TPM
  $SUDO tpm2_flushcontext -t > /dev/null

printf "Gathering the registration information...\n\nRegistration Id:\n%s\n\nEndorsement Key:\n%s\n" $(sha256sum -b | cut -d' ' -f1 | sed -e 's/[^[:alnum:]]//g') $(base64 -w0
$SUDO rm srk.ctx 2> /dev/null

The output window displays the device's Endorsement key and a unique Registration ID. Copy these values for use later when you create an individual enrollment for your device in the device provisioning service.

After you have your registration ID and endorsement key, you're ready to continue.


If you don't want to use the TPM2 software tools to retrieve the information, you need to find another way to obtain the provisioning information. The endorsement key, which is unique to each TPM chip, is obtained from the TPM chip manufacturer associated with it. You can derive a unique registration ID for your TPM device. For example, as shown above you can create an SHA-256 hash of the endorsement key.

Create a device provisioning service enrollment

Use your TPM's provisioning information to create an individual enrollment in the device provisioning service.

When you create an enrollment in the device provisioning service, you have the opportunity to declare an Initial Device Twin State. In the device twin, you can set tags to group devices by any metric used in your solution, like region, environment, location, or device type. These tags are used to create automatic deployments.


The steps in this article are for the Azure portal, but you can also create individual enrollments by using the Azure CLI. For more information, see az iot dps enrollment. As part of the CLI command, use the edge-enabled flag to specify that the enrollment is for an IoT Edge device.

  1. In the Azure portal, go to your instance of the IoT Hub device provisioning service.

  2. Under Settings, select Manage enrollments.

  3. Select Add individual enrollment, and then complete the following steps to configure the enrollment:

    1. For Mechanism, select TPM.

    2. Provide the Endorsement key and Registration ID that you copied from your VM or physical device.

    3. Provide an ID for your device if you want. If you don't provide a device ID, the registration ID is used.

    4. Select True to declare that your VM or physical device is an IoT Edge device.

    5. Choose the linked IoT hub that you want to connect your device to, or select Link to new IoT Hub. You can choose multiple hubs, and the device will be assigned to one of them according to the selected assignment policy.

    6. Add a tag value to the Initial Device Twin State if you want. You can use tags to target groups of devices for module deployment. For more information, see Deploy IoT Edge modules at scale.

    7. Select Save.

Now that an enrollment exists for this device, the IoT Edge runtime can automatically provision the device during installation.

Install IoT Edge

In this section, you prepare your Linux virtual machine or physical device for IoT Edge. Then, you install IoT Edge.

Run the following commands to add the package repository and then add the Microsoft package signing key to your list of trusted keys.


On June 30, 2022 Raspberry Pi OS Stretch was retired from the Tier 1 OS support list. To avoid potential security vulnerabilities update your host OS to Bullseye.

Installing can be done with a few commands. Open a terminal and run the following commands:

  • 22.04:

    wget -O packages-microsoft-prod.deb
    sudo dpkg -i packages-microsoft-prod.deb
    rm packages-microsoft-prod.deb
  • 20.04:

    wget -O packages-microsoft-prod.deb
    sudo dpkg -i packages-microsoft-prod.deb
    rm packages-microsoft-prod.deb

For more information about operating system versions, see Azure IoT Edge supported platforms.


Azure IoT Edge software packages are subject to the license terms located in each package (usr/share/doc/{package-name} or the LICENSE directory). Read the license terms prior to using a package. Your installation and use of a package constitutes your acceptance of these terms. If you don't agree with the license terms, don't use that package.

Install a container engine

Azure IoT Edge relies on an OCI-compatible container runtime. For production scenarios, we recommend that you use the Moby engine. The Moby engine is the container engine officially supported with IoT Edge. Docker CE/EE container images are compatible with the Moby runtime. If you are using Ubuntu Core snaps, the Docker snap is serviced by Canonical and supported for production scenarios.

Install the Moby engine.

sudo apt-get update; \
  sudo apt-get install moby-engine

By default, the container engine doesn't set container log size limits. Over time, this can lead to the device filling up with logs and running out of disk space. However, you can configure your log to show locally, though it's optional. To learn more about logging configuration, see Production Deployment Checklist.

The following steps show you how to configure your container to use local logging driver as the logging mechanism.

  1. Create or edit the existing Docker daemon's config file

    sudo nano /etc/docker/daemon.json
  2. Set the default logging driver to the local logging driver as shown in the example.

          "log-driver": "local"
  3. Restart the container engine for the changes to take effect.

    sudo systemctl restart docker

Install the IoT Edge runtime

The IoT Edge service provides and maintains security standards on the IoT Edge device. The service starts on every boot and bootstraps the device by starting the rest of the IoT Edge runtime.


Beginning with version 1.2, the IoT identity service handles identity provisioning and management for IoT Edge and for other device components that need to communicate with IoT Hub.

The steps in this section represent the typical process to install the latest IoT Edge version on a device that has internet connection. If you need to install a specific version, like a pre-release version, or need to install while offline, follow the Offline or specific version installation steps later in this article.


If you already have an IoT Edge device running an older version and want to upgrade to the latest release, use the steps in Update the IoT Edge security daemon and runtime. Later versions are sufficiently different from previous versions of IoT Edge that specific steps are necessary to upgrade.

Install the latest version of IoT Edge and the IoT identity service package (if you're not already up-to-date):

  • 22.04:

    sudo apt-get update; \
       sudo apt-get install aziot-edge
  • 20.04:

    sudo apt-get update; \
       sudo apt-get install aziot-edge defender-iot-micro-agent-edge

The optional defender-iot-micro-agent-edge package includes the Microsoft Defender for IoT security micro-agent that provides endpoint visibility into security posture management, vulnerabilities, threat detection, fleet management and more to help you secure your IoT Edge devices. It's recommended to install the micro agent with the Edge agent to enable security monitoring and hardening of your Edge devices. To learn more about Microsoft Defender for IoT, see What is Microsoft Defender for IoT for device builders.

Provision the device with its cloud identity

After the runtime is installed on your device, configure the device with the information it uses to connect to the device provisioning service and IoT Hub.

Know your device provisioning service ID Scope and device Registration ID that were gathered previously.

Create a configuration file for your device based on a template file that's provided as part of the IoT Edge installation.

sudo cp /etc/aziot/config.toml.edge.template /etc/aziot/config.toml

Open the configuration file on the IoT Edge device.

sudo nano /etc/aziot/config.toml
  1. Find the provisioning configurations section of the file. Uncomment the lines for TPM provisioning, and make sure any other provisioning lines are commented out.

    # DPS provisioning with TPM
    source = "dps"
    global_endpoint = ""
    id_scope = "DPS_ID_SCOPE_HERE"
    # Uncomment to send a custom payload during DPS registration
    # payload = { uri = "PATH_TO_JSON_FILE" }
    method = "tpm"
    registration_id = "REGISTRATION_ID_HERE"
    # auto_reprovisioning_mode = Dynamic
  2. Update the values of id_scope and registration_id with your device provisioning service and device information. The scope_id value is the ID Scope from your device provisioning service instance's overview page.

    For more information about provisioning configuration settings, see Configure IoT Edge device settings.

  3. Optionally, find the auto reprovisioning mode section of the file. Use the auto_reprovisioning_mode parameter to configure your device's reprovisioning behavior. Dynamic - Reprovision when the device detects that it may have been moved from one IoT Hub to another. This is the default. AlwaysOnStartup - Reprovision when the device is rebooted or a crash causes the daemons to restart. OnErrorOnly - Never trigger device reprovisioning automatically. Each mode has an implicit device reprovisioning fallback if the device is unable to connect to IoT Hub during identity provisioning due to connectivity errors. For more information, see IoT Hub device reprovisioning concepts.

  4. Optionally, uncomment the payload parameter to specify the path to a local JSON file. The contents of the file is sent to DPS as additional data when the device registers. This is useful for custom allocation. For example, if you want to allocate your devices based on an IoT Plug and Play model ID without human intervention.

  5. Save and close the file.

Give IoT Edge access to the TPM

The IoT Edge runtime relies on a TPM service that brokers access to a device's TPM. This service needs to access the TPM to automatically provision your device.

You can give access to the TPM by overriding the systemd settings so that the aziottpm service has root privileges. If you don't want to elevate the service privileges, you can also use the following steps to manually provide TPM access.

  1. Create a new rule that gives the IoT Edge runtime access to tpm0 and tpmrm0.

    sudo touch /etc/udev/rules.d/tpmaccess.rules
  2. Open the rules file.

    sudo nano /etc/udev/rules.d/tpmaccess.rules
  3. Copy the following access information into the rules file. The tpmrm0 might not be present on devices that use a kernel earlier than 4.12. Devices that don't have tpmrm0 will safely ignore that rule.

    # allow aziottpm access to tpm0 and tpmrm0
    KERNEL=="tpm0", SUBSYSTEM=="tpm", OWNER="aziottpm", MODE="0660"
    KERNEL=="tpmrm0", SUBSYSTEM=="tpmrm", OWNER="aziottpm", MODE="0660"
  4. Save and exit the file.

  5. Trigger the udev system to evaluate the new rule.

    /bin/udevadm trigger --subsystem-match=tpm --subsystem-match=tpmrm
  6. Verify that the rule was successfully applied.

    ls -l /dev/tpm*

    Successful output appears as follows:

    crw-rw---- 1 root aziottpm 10, 224 Jul 20 16:27 /dev/tpm0
    crw-rw---- 1 root aziottpm 10, 224 Jul 20 16:27 /dev/tpmrm0

    If you don't see that the correct permissions applied, try rebooting your machine to refresh udev.

  7. Apply the configuration changes that you made on the device.

    sudo iotedge config apply

Verify successful installation

If you didn't already, apply the configuration changes that you made on the device.

sudo iotedge config apply

Check to see that the IoT Edge runtime is running.

sudo iotedge system status

Examine daemon logs.

sudo iotedge system logs

If you see provisioning errors, it might be that the configuration changes haven't taken effect yet. Try restarting the IoT Edge daemon.

sudo systemctl daemon-reload

Or, try restarting your VM to see if the changes take effect on a fresh start.

If the runtime started successfully, you can go into your IoT hub and see that your new device was automatically provisioned. Now your device is ready to run IoT Edge modules.

List running modules.

iotedge list

You can verify that the individual enrollment that you created in the device provisioning service was used. Go to your device provisioning service instance in the Azure portal. Open the enrollment details for the individual enrollment that you created. Notice that the status of the enrollment is assigned and the device ID is listed.

Next steps

The device provisioning service enrollment process lets you set the device ID and device twin tags at the same time as you provision the new device. You can use those values to target individual devices or groups of devices by using automatic device management.

Learn how to deploy and monitor IoT Edge modules at scale by using the Azure portal or the Azure CLI.