Create and provision IoT Edge devices at scale on Linux using X.509 certificates

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

Important

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 end-to-end instructions for autoprovisioning one or more Linux IoT Edge devices using X.509 certificates. You can automatically provision Azure IoT Edge devices with the Azure IoT Hub device provisioning service (DPS). If you're unfamiliar with the process of autoprovisioning, review the provisioning overview before continuing.

The tasks are as follows:

  1. Generate certificates and keys.
  2. Create either an individual enrollment for a single device or a group enrollment for a set of devices.
  3. Install the IoT Edge runtime and register the device with IoT Hub.

Using X.509 certificates as an attestation mechanism is an excellent way to scale production and simplify device provisioning. Typically, X.509 certificates are arranged in a certificate chain of trust. Starting with a self-signed or trusted root certificate, each certificate in the chain signs the next lower certificate. This pattern creates a delegated chain of trust from the root certificate down through each intermediate certificate to the final downstream device certificate installed on a device.

Tip

If your device has a Hardware Security Module (HSM) such as a TPM 2.0, then we recommend storing the X.509 keys securely in the HSM. Learn more about how to implement the zero-touch provisioning at scale described in this blueprint with the iotedge-tpm2cloud sample.

Prerequisites

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 or virtual Linux device to be the IoT Edge device.

Generate device identity certificates

The device identity certificate is a downstream device certificate that connects through a certificate chain of trust to the top X.509 certificate authority (CA) certificate. The device identity certificate must have its common name (CN) set to the device ID that you want the device to have in your IoT hub.

Device identity certificates are only used for provisioning the IoT Edge device and authenticating the device with Azure IoT Hub. They aren't signing certificates, unlike the CA certificates that the IoT Edge device presents to modules or downstream devices for verification. For more information, see Azure IoT Edge certificate usage detail.

After you create the device identity certificate, you should have two files: a .cer or .pem file that contains the public portion of the certificate, and a .cer or .pem file with the private key of the certificate. If you plan to use group enrollment in DPS, you also need the public portion of an intermediate or root CA certificate in the same certificate chain of trust.

You need the following files to set up automatic provisioning with X.509:

  • The device identity certificate and its private key certificate. The device identity certificate is uploaded to DPS if you create an individual enrollment. The private key is passed to the IoT Edge runtime.
  • A full chain certificate, which should have at least the device identity and the intermediate certificates in it. The full chain certificate is passed to the IoT Edge runtime.
  • An intermediate or root CA certificate from the certificate chain of trust. This certificate is uploaded to DPS if you create a group enrollment.

Use test certificates (optional)

If you don't have a certificate authority available to create new identity certs and want to try out this scenario, the Azure IoT Edge git repository contains scripts that you can use to generate test certificates. These certificates are designed for development testing only, and must not be used in production.

To create test certificates, follow the steps in Create demo certificates to test IoT Edge device features. Complete the two required sections to set up the certificate generation scripts and to create a root CA certificate. Then, follow the steps to create a device identity certificate. When you're finished, you should have the following certificate chain and key pair:

  • <WRKDIR>/certs/iot-edge-device-identity-<name>-full-chain.cert.pem
  • <WRKDIR>/private/iot-edge-device-identity-<name>.key.pem

You need both these certificates on the IoT Edge device. If you're going to use individual enrollment in DPS, then you upload the .cert.pem file. If you're going to use group enrollment in DPS, then you also need an intermediate or root CA certificate in the same certificate chain of trust to upload. If you're using demo certs, use the <WRKDIR>/certs/azure-iot-test-only.root.ca.cert.pem certificate for group enrollment.

Create a DPS enrollment

Use your generated certificates and keys to create an enrollment in DPS for one or more IoT Edge devices.

If you are looking to provision a single IoT Edge device, create an individual enrollment. If you need multiple devices provisioned, follow the steps for creating a DPS group enrollment.

When you create an enrollment in DPS, 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 you need in your solution, like region, environment, location, or device type. These tags are used to create automatic deployments.

For more information about enrollments in the device provisioning service, see How to manage device enrollments.

Create a DPS individual enrollment

Individual enrollments take the public portion of a device's identity certificate and match that to the certificate on the device.

Tip

The steps in this article are for the Azure portal, but you can also create individual enrollments 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, navigate to your instance of IoT Hub device provisioning service.

  2. Under Settings, select Manage enrollments.

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

    • Mechanism: Select X.509.

    • Primary Certificate .pem or .cer file: Upload the public file from the device identity certificate. If you used the scripts to generate a test certificate, choose the following file:

      <WRKDIR>\certs\iot-edge-device-identity-<name>.cert.pem

    • IoT Hub Device ID: Provide an ID for your device if you'd like. You can use device IDs to target an individual device for module deployment. If you don't provide a device ID, the common name (CN) in the X.509 certificate is used.

    • IoT Edge device: Select True to declare that the enrollment is for an IoT Edge device.

    • Select the IoT hubs this device can be assigned to: Choose the linked IoT hub that you want to connect your device to. You can choose multiple hubs, and the device will be assigned to one of them according to the selected allocation policy.

    • Initial Device Twin State: Add a tag value to be added to the device twin if you'd like. You can use tags to target groups of devices for automatic deployment. For example:

      {
          "tags": {
             "environment": "test"
          },
          "properties": {
             "desired": {}
          }
      }
      
  4. Select Save.

Under Manage Enrollments, you can see the Registration ID for the enrollment you just created. Make note of it, as it can be used when you provision your device.

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.

Important

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.

For tier 2 supported platform operating systems, installation packages are made available at Azure IoT Edge releases. See the installation steps in Offline or specific version installation.

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

  • 24.04:

    wget https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
    sudo dpkg -i packages-microsoft-prod.deb
    rm packages-microsoft-prod.deb
    
  • 22.04:

    wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
    sudo dpkg -i packages-microsoft-prod.deb
    rm packages-microsoft-prod.deb
    
  • 20.04:

    wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -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.

Note

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.

Note

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.

Tip

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

Once 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.

Have the following information ready:

  • The DPS ID Scope value. You can retrieve this value from the overview page of your DPS instance in the Azure portal.
  • The device identity certificate chain file on the device.
  • The device identity key file on the device.

Create a configuration file for your device based on a template file that is 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

Find the Provisioning section of the file. Uncomment the lines for DPS provisioning with X.509 certificate, and make sure any other provisioning lines are commented out.

# DPS provisioning with X.509 certificate
[provisioning]
source = "dps"
global_endpoint = "https://global.azure-devices-provisioning.net"
id_scope = "SCOPE_ID_HERE"

# Uncomment to send a custom payload during DPS registration
# payload = { uri = "PATH_TO_JSON_FILE" }

[provisioning.attestation]
method = "x509"
registration_id = "REGISTRATION_ID_HERE"

identity_cert = "DEVICE_IDENTITY_CERTIFICATE_HERE" # For example, "file:///var/aziot/device-id.pem"
identity_pk = "DEVICE_IDENTITY_PRIVATE_KEY_HERE"   # For example, "file:///var/aziot/device-id.key"

# auto_reprovisioning_mode = Dynamic
  1. Update the value of id_scope with the scope ID you copied from your instance of DPS.

  2. Provide a registration_id for the device, which is the ID that the device has in IoT Hub. The registration ID must match the common name (CN) of the identity certificate.

  3. Update the values of identity_cert and identity_pk with your certificate and key information.

    The identity certificate value can be provided as a file URI, or can be dynamically issued using EST or a local certificate authority. Uncomment only one line, based on the format you choose to use.

    The identity private key value can be provided as a file URI or a PKCS#11 URI. Uncomment only one line, based on the format you choose to use.

    If you use any PKCS#11 URIs, find the PKCS#11 section in the config file and provide information about your PKCS#11 configuration.

    For more information about certificates, see Manage IoT Edge certificates.

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

  4. 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.

  5. 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.

  6. Save and close the file.

Apply the configuration changes that you made to IoT Edge.

sudo iotedge config apply

Verify successful installation

If the runtime started successfully, you can go into your IoT Hub and start deploying IoT Edge modules to your device.

You can verify that the individual enrollment that you created in device provisioning service was used. Navigate 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.

Use the following commands on your device to verify that the IoT Edge installed and started successfully.

Check the status of the IoT Edge service.

sudo iotedge system status

Examine service logs.

sudo iotedge system logs

List running modules.

sudo iotedge list

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 using automatic device management. Learn how to Deploy and monitor IoT Edge modules at scale using the Azure portal or using Azure CLI.