# Azure Iot Edge > Azure IoT Edge runtime and architecture explained | Microsoft Learn [Skip to main content][Skip to Ask Learn chat experience] --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/iot-edge-runtime Azure IoT Edge runtime and architecture explained | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Azure IoT Edge runtime and architecture overview Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. The IoT Edge runtime is a set of programs that turn a device into an IoT Edge device. The runtime components let IoT Edge devices receive code to run at the edge and communicate results. The IoT Edge runtime is responsible for the following functions on IoT Edge devices: - Install and update workloads. - Maintain Azure IoT Edge security standards. - Ensure [IoT Edge modules ]keep running. - Report module health to the cloud for remote monitoring. - Manage communication between: - Downstream devices and IoT Edge devices - Modules on an IoT Edge device - An IoT Edge device and the cloud - IoT Edge devices [] The responsibilities of the IoT Edge runtime fall into two categories: communication and module management. These two roles are performed by two components that are part of the IoT Edge runtime. The *IoT Edge agent *deploys and monitors the modules, while the *IoT Edge hub *is responsible for communication. Both the IoT Edge agent and the IoT Edge hub are modules, just like any other module running on an IoT Edge device. They're sometimes referred to as the *runtime modules *. ## IoT Edge agent The IoT Edge agent is one of two modules in the Azure IoT Edge runtime. It instantiates modules, ensures they keep running, and reports their status to IoT Hub. This configuration data is written as a property of the IoT Edge agent module twin. The [IoT Edge security daemon ]starts the IoT Edge agent on device startup. The agent retrieves its module twin from IoT Hub and inspects the deployment manifest. The deployment manifest is a JSON file that declares the modules that need to be started. Each item in the deployment manifest contains specific information about a module and is used by the IoT Edge agent for controlling the module's lifecycle. For more information about all the properties used by the IoT Edge agent to control modules, read about the [Properties of the IoT Edge agent and IoT Edge hub module twins ]. The IoT Edge agent sends runtime response to IoT Hub. Here's a list of possible responses: - 200 - OK - 400 - The deployment configuration is malformed or invalid. - 417 - The device doesn't have a deployment configuration set. - 412 - The schema version in the deployment configuration is invalid. - 406 - The IoT Edge device is offline or not sending status reports. - 500 - An error occurred in the IoT Edge runtime. For more information about creating deployment manifests, see [Learn how to deploy modules and establish routes in IoT Edge ]. ### Security The IoT Edge agent plays a critical role in the security of an IoT Edge device. For example, it performs actions like verifying a module's image before starting it. For more information about the Azure IoT Edge security framework, read about the [IoT Edge security manager ]. ## IoT Edge hub The IoT Edge hub is the other module that makes up the Azure IoT Edge runtime. It acts as a local proxy for IoT Hub by exposing the same protocol endpoints as IoT Hub. This consistency means that clients can connect to the IoT Edge runtime just as they would to IoT Hub. The IoT Edge hub isn't a full local version of IoT Hub. It delegates some tasks to IoT Hub. For example, IoT Edge hub automatically downloads authorization information from IoT Hub on its first connection to enable a device to connect. After the first connection is established, authorization information is cached locally by IoT Edge hub. Future connections from that device are authorized without having to download authorization information from the cloud again. ### Cloud communication To reduce the bandwidth that your IoT Edge solution uses, the IoT Edge hub optimizes how many actual connections are made to the cloud. IoT Edge hub takes logical connections from modules or downstream devices and combines them for a single physical connection to the cloud. The details of this process are transparent to the rest of the solution. Clients think they have their own connection to the cloud even though they're all being sent over the same connection. The IoT Edge hub can either use the AMQP or the MQTT protocol to communicate upstream with the cloud, independently from protocols used by downstream devices. However, the IoT Edge hub currently only supports combining logical connections into a single physical connection by using AMQP as the upstream protocol and its multiplexing capabilities. AMQP is the default upstream protocol. [] IoT Edge hub can determine whether it's connected to IoT Hub. If the connection is lost, IoT Edge hub saves messages or twin updates locally. Once a connection is reestablished, it syncs all the data. The location used for this temporary cache is determined by a property of the IoT Edge hub's module twin. The size of the cache isn't capped and grows as long as the device has storage capacity. For more information, see [Offline capabilities ]. ### Local communication IoT Edge hub facilitates local communication. It enables device-to-module and module-to-module communications by brokering messages to keep devices and modules independent from each other. The IoT Edge hub supports the [message routing features supported by IoT Hub ]. #### Using routing The brokering mechanism uses the same routing features as IoT Hub to specify how messages are passed between devices or modules. First devices or modules specify the inputs on which they accept messages and the outputs to which they write messages. Then a solution developer can route messages between a source (for example, outputs), and a destination (for example, inputs), with potential filters. [] Routing can be used by devices or modules built with the Azure IoT Device SDKs using the AMQP protocol. All messaging IoT Hub primitives (for example, telemetry), direct methods, C2D, twins, are supported but communication over user-defined topics isn't supported. For more information about routes, see [Learn how to deploy modules and establish routes in IoT Edge ]. Brokering mechanism features available: Features Routing D2C telemetry ✔ Local telemetry ✔ DirectMethods ✔ Twin ✔ C2D for devices ✔ Ordering ✔ Filtering ✔ User-defined topics Device-to-Device Local broadcasting ### Connecting to the IoT Edge hub The IoT Edge hub accepts connections from device or module clients, either over the MQTT protocol or the AMQP protocol. Note IoT Edge hub supports clients that connect using MQTT or AMQP. It doesn't support clients that use HTTP. When a client connects to the IoT Edge hub, the following happens: - If Transport Layer Security (TLS) is used (recommended), a TLS channel is built to establish an encrypted communication between the client and the IoT Edge hub. - Authentication information is sent from the client to IoT Edge hub to identify itself. - IoT Edge hub authorizes or rejects the connection based on its authorization policy. #### Secure connections (TLS) By default, the IoT Edge hub only accepts connections secured with Transport Layer Security (TLS), for example, encrypted connections that a third party can't decrypt. When a client connects on port 8883 (MQTTS) or 5671 (AMQPS) to the IoT Edge hub, it establishes a TLS channel. During the TLS handshake, the IoT Edge hub sends its certificate chain that the client needs to validate. In order to validate the certificate chain, the root certificate of the IoT Edge hub must be installed as a trusted certificate on the client. If the root certificate isn't trusted, the client library is rejected by the IoT Edge hub with a certificate verification error. The steps to follow to install this root certificate of the broker on device clients are described in the [transparent gateway ]and in the [prepare a downstream device ]documentation. Modules can use the same root certificate as the IoT Edge hub by using the IoT Edge daemon API. #### Authentication The IoT Edge Hub only accepts connections from devices or modules that have an IoT Hub identity. For example, those that are registered in IoT Hub and have one of the three client authentication methods supported by IoT Hub to prove their identity: [Symmetric keys authentication ], [X.509 self-signed authentication ], [X.509 CA signed authentication ]. These IoT Hub identities can be verified locally by the IoT Edge hub so connections can still be made while offline. IoT Edge modules currently only support symmetric key authentication. #### Authorization By verifying that a client belongs to its set of trusted clients defined in IoT Hub. The set of trusted clients is specified by setting up parent/child or device/module relationships in IoT Hub. When a module is created in IoT Edge, a trust relationship is automatically established between this module and its IoT Edge device. This is the only authorization model supported by the routing brokering mechanism. ### Remote configuration The IoT Edge hub is entirely controlled by the cloud. It gets its configuration from IoT Hub via its [module twin ]. The twin contains a desired property called routes that declares how messages are passed within a deployment. For more information on routes, see [declare routes ]. Additionally, several configurations can be done by setting up [environment variables on the IoT Edge hub ]. ## Runtime quality telemetry IoT Edge collects anonymous telemetry from the host runtime and system modules to improve product quality. This information is called runtime quality telemetry. The collected telemetry is periodically sent as device-to-cloud messages to IoT Hub from the IoT Edge agent. These messages don't appear in customer's regular telemetry and don't consume any message quota. The IoT Edge agent and hub generate metrics that you can collect to understand device performance. A subset of these metrics is collected by the IoT Edge Agent as part of runtime quality telemetry. The metrics collected for runtime quality telemetry are labeled with the tag `ms_telemetry `. For information about all the available metrics, see [Access built-in metrics ]. Any personally or organizationally identifiable information, such as device and module names, are removed before upload to ensure the anonymous nature of the runtime quality telemetry. The IoT Edge agent collects the runtime quality telemetry hourly and sends one message to IoT Hub every 24 hours. If you wish to opt out of sending runtime quality telemetry from your devices, there are two ways to do so: - Set the `SendRuntimeQualityTelemetry `environment variable to `false `for **edgeAgent ** - Uncheck the option in the Azure portal during deployment. ## Next steps - [Understand Azure IoT Edge modules ] - [Learn how to deploy modules and establish routes in IoT Edge ] - [Learn how to publish and subscribe with IoT Edge ] - [Learn about IoT Edge runtime metrics ] ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-03-20 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/how-to-deploy-modules-portal Deploy modules from Azure portal - Azure IoT Edge | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Deploy Azure IoT Edge modules from the Azure portal Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. Important Starting August 28, 2024, Microsoft Azure Marketplace is updating the distribution model for IoT Edge modules. Partners (module publishers) begin [hosting their IoT Edge modules ]on publisher-owned container registries. IoT Edge module images aren't available for download from the container registry for Azure Marketplace. Contact the [IoT Edge module publisher ]to obtain the updated container image URI and [update your IoT Edge device configurations ]with the new image URI provided by the publisher. IoT Edge devices that don't use [partner modules ]acquired from Azure Marketplace aren't affected and no action is required. Once you create IoT Edge modules with your business logic, you want to deploy them to your devices to operate at the edge. If you have multiple modules that work together to collect and process data, you can deploy them all at once and declare the routing rules that connect them. This article shows how the Azure portal guides you through creating a deployment manifest and pushing the deployment to an IoT Edge device. For information about creating a deployment that targets multiple devices based on their shared tags, see [Deploy IoT Edge modules at scale using the Azure portal ]. ## Prerequisites - An [IoT hub ]in your Azure subscription. - An IoT Edge device. If you don't have an IoT Edge device set up, you can create one in an Azure virtual machine. Follow the steps in one of the quickstart articles to [create a virtual Linux device ]or [create a virtual Windows device ]. ## Configure a deployment manifest A deployment manifest is a JSON document that describes which modules to deploy, how data flows between the modules, and desired properties of the module twins. For more information about how deployment manifests work and how to create them, see [Learn how to deploy modules and establish routes in IoT Edge ]. The Azure portal has a wizard that walks you through creating the deployment manifest, instead of building the JSON document manually. It has three steps: **Add modules **, **Specify routes **, and **Review deployment **. Note The steps in this article reflect the latest schema version of the IoT Edge agent and hub. Schema version 1.1 was released along with IoT Edge version 1.0.10, and enables the module startup order and route prioritization features. If you're deploying to a device running version 1.0.9 or earlier, edit the **Runtime Settings **in the **Modules **step of the wizard to use schema version 1.0. ### Select device and add modules - Sign in to the [Azure portal ]and navigate to your IoT hub. - On the left pane, select **Devices **under the **Device management **menu. - Select the target IoT Edge device from the list. - On the upper bar, select **Set Modules **. - In the **Container Registry Credentials **section of the page, provide credentials to access container registries that contain module images. For example, your modules are in your private container registry or you're using a partner container registry that requires authentication. - In the **IoT Edge Modules **section of the page, select **Add **. - Choose the type of modules you want to add from the drop-down menu. You can add IoT Edge modules or Azure Stream Analytics modules. #### IoT Edge Module Use this option to add Microsoft modules, partner modules, or custom modules. You provide the module name and container image URI. The container image URI is the location of the module image in a container registry. For a list of Microsoft IoT Edge module images, see the [Microsoft Artifact Registry ]. For partner modules, contact the IoT Edge module publisher to obtain the container image URI. For example to add the Microsoft simulated temperature sensor module: - Enter the following settings: Setting Value Image URI `mcr.microsoft.com/azureiotedge-simulated-temperature-sensor `Restart Policy always Desired Status running - Select **Add **. - After adding a module, select the module name from the list to open the module settings. Fill out the optional fields if necessary. For more information about the available module settings, see [Module configuration and management ]. For more information about the module twin, see [Define or update desired properties ]. #### Azure Stream Analytics Module Use this option for modules generated from an Azure Stream Analytics workload. - Select your subscription and the Azure Stream Analytics Edge job that you created. - Select **Save **. For more information about deploying Azure Stream Analytics in an IoT Edge module, see [Tutorial: Deploy Azure Stream Analytics as an IoT Edge module ]. ### Specify routes On the **Routes **tab, you define how messages are passed between modules and the IoT hub. Messages are constructed using name/value pairs. By default, the first deployment for a new device includes a route called **route **and defined as **FROM /messages/* INTO $upstream **, which means that any messages output by any modules are sent to your IoT hub. The **Priority **and **Time to live **parameters are optional parameters that you can include in a route definition. The priority parameter allows you to choose which routes should have their messages processed first, or which routes should be processed last. Priority is determined by setting a number 0-9, where 0 is top priority. The time to live parameter allows you to declare how long messages in that route should be held until they're either processed or removed from the queue. For more information about how to create routes, see [Declare routes ]. Once the routes are set, select **Next: Review + create **to continue to the next step of the wizard. ### Review deployment The review section shows you the JSON deployment manifest that was created based on your selections in the previous two sections. There are two modules declared that you didn't add: **$edgeAgent **and **$edgeHub **. These two modules make up the [IoT Edge runtime ]and are required defaults in every deployment. Review your deployment information, then select **Create **. ## View modules on your device Once you deploy modules to your device, you can view all of them in the device details page of your IoT hub. This page displays the name of each deployed module, and useful information like the deployment status and exit code. Select **Next: Routes **and continue with deployment as described by [Specify routes ]and [Review deployment ]earlier in this article. ## Next steps Learn how to [Deploy IoT Edge modules at scale using the Azure portal ]. ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-05-12 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2026 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/module-composition Deploy modules and establish routes in Azure IoT Edge | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Learn how to deploy modules and establish routes in IoT Edge Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. Each IoT Edge device runs at least two modules: $edgeAgent and $edgeHub, which are part of the IoT Edge runtime. An IoT Edge device can run multiple modules for different processes. Use a deployment manifest to tell your device which modules to install and how to set them up to work together. The *deployment manifest *is a JSON document that describes: - The **IoT Edge agent **module twin, which includes three components: - The container image for each module that runs on the device - The credentials to use private container registries that have module images - Instructions for how each module is created and managed - The **IoT Edge hub **module twin, which includes how messages flow between modules and to IoT Hub - The desired properties of any extra module twins (optional) All IoT Edge devices need a deployment manifest. A newly installed IoT Edge runtime shows an error code until it's set up with a valid manifest. In the Azure IoT Edge tutorials, you build a deployment manifest by using a wizard in the Azure IoT Edge portal. You can also apply a deployment manifest programmatically by using REST or the IoT Hub Service SDK. For more information, see [Understand IoT Edge deployments ]. ## Create a deployment manifest A deployment manifest is a list of module twins set with their desired properties. It tells an IoT Edge device or group of devices which modules to install and how to set them up. Deployment manifests include the *desired properties *for each module twin. IoT Edge devices report the *reported properties *for each module. Every deployment manifest requires two modules: `$edgeAgent `and `$edgeHub `. These modules are part of the IoT Edge runtime that manages the IoT Edge device and the modules running on it. For more information about these modules, see [Understand the IoT Edge runtime and its architecture ]. You can add up to 50 additional modules to run on an IoT Edge device, in addition to the two runtime modules. A deployment manifest that has only the IoT Edge runtime ( `$edgeAgent `and `$edgeHub `) is valid. Deployment manifests use this structure: ``` `{ "modulesContent": { "$edgeAgent": { // required "properties.desired": { // desired properties of the IoT Edge agent // includes the image URIs of all deployed modules // includes container registry credentials } }, "$edgeHub": { //required "properties.desired": { // desired properties of the IoT Edge hub // includes the routing information between modules and to IoT Hub } }, "module1": { // optional "properties.desired": { // desired properties of module1 } }, "module2": { // optional "properties.desired": { // desired properties of module2 } } } } ` ``` ## Configure modules Define how the IoT Edge runtime installs the modules in your deployment. The IoT Edge agent is the runtime component that manages installation, updates, and status reporting for an IoT Edge device. So, the $edgeAgent module twin has the configuration and management information for all modules. This information includes the configuration parameters for the IoT Edge agent itself. The $edgeAgent properties follow this structure: ``` `{ "modulesContent": { "$edgeAgent": { "properties.desired": { "schemaVersion": "1.1", "runtime": { "settings":{ "registryCredentials":{ // let the IoT Edge agent use container images that aren't public } } }, "systemModules": { "edgeAgent": { // configuration and management details }, "edgeHub": { // configuration and management details } }, "modules": { "module1": { // configuration and management details }, "module2": { // configuration and management details } } } }, "$edgeHub": { ... }, "module1": { ... }, "module2": { ... } } } ` ``` The IoT Edge agent schema version 1.1 was released with IoT Edge version 1.0.10 and lets you set module startup order. Use schema version 1.1 for any IoT Edge deployment running version 1.0.10 or later. ### Module configuration and management The IoT Edge agent desired properties list is where you define which modules run on an IoT Edge device and how they're set up and managed. For a complete list of desired properties that can or must be included, see [Properties of the IoT Edge agent and IoT Edge hub ]. For example: ``` `{ "modulesContent": { "$edgeAgent": { "properties.desired": { "schemaVersion": "1.1", "runtime": { ... }, "systemModules": { "edgeAgent": { ... }, "edgeHub": { ... } }, "modules": { "module1": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "startupOrder": 2, "settings": { "image": "myacr.azurecr.io/module1:latest", "createOptions": "{}" } }, "module2": { ... } } } }, "$edgeHub": { ... }, "module1": { ... }, "module2": { ... } } } ` ``` Every module has a **settings **property with the module **image **, an address for the container image in a container registry, and any **createOptions **to set up the image on startup. For more information, see [How to configure container create options for IoT Edge modules ]. The edgeHub module and custom modules also have three properties that tell the IoT Edge agent how to manage them: - **Status **: Whether the module runs or stops when first deployed. Required. - **RestartPolicy **: When and if the IoT Edge agent restarts the module if it stops. If the module stops without any errors, it doesn't start automatically. For more information, see [Docker Docs - Start containers automatically ]. Required. - **StartupOrder **: *Introduced in IoT Edge version 1.0.10. *The order the IoT Edge agent uses to start the modules when first deployed. The order uses integers, where a module with a startup value of 0 starts first and then higher numbers follow. The edgeAgent module doesn't have a startup value because it always starts first. Optional. The IoT Edge agent starts the modules in order of the startup value, but doesn't wait for each module to finish starting before starting the next one. Startup order helps if some modules depend on others. For example, you might want the edgeHub module to start first so it's ready to route messages when the other modules start. Or you might want to start a storage module before you start modules that send data to it. But always design your modules to handle failures of other modules. Containers can stop and restart at any time, and any number of times. Note Changing a module's properties restarts that module. For example, a restart happens if you change properties for the: - module image - Docker create options - environment variables - restart policy - image pull policy - version - startup order If no module properties are changed, a module restart isn't triggered. ## Declare routes IoT Edge hub manages communication between modules, IoT Hub, and downstream devices. The $edgeHub module twin has a desired property called *routes *that defines how messages move within a deployment. You can set up multiple routes in the same deployment. Declare routes in the **$edgeHub **desired properties using this syntax: ``` `{ "modulesContent": { "$edgeAgent": { ... }, "$edgeHub": { "properties.desired": { "schemaVersion": "1.1", "routes": { "route1": "FROM WHERE INTO ", "route2": { "route": "FROM WHERE INTO ", "priority": 0, "timeToLiveSecs": 86400 } }, "storeAndForwardConfiguration": { "timeToLiveSecs": 10 } } }, "module1": { ... }, "module2": { ... } } } ` ``` IoT Edge hub schema version 1 released with IoT Edge version 1.0.10 and lets you set route prioritization and time to live. Use schema version 1.1 for any IoT Edge deployment running version 1.0.10 or later. Each route needs a *source *for incoming messages and a *sink *for outgoing messages. The *condition *is optional and lets you filter messages. Assign *priority *to routes to process important messages first. This feature helps when the upstream connection is weak or limited and you need to prioritize critical data over standard telemetry messages. ### Source The source specifies where the messages come from. IoT Edge can route messages from modules or downstream devices. With the IoT SDKs, modules can set specific output queues for their messages using the ModuleClient class. Output queues aren't required, but they help manage multiple routes. Downstream devices use the DeviceClient class in the IoT SDKs to send messages to IoT Edge gateway devices, just like they send messages to IoT Hub. For more information, see [Understand and use Azure IoT Hub SDKs ]. The source property can use any of these values: Source Description `/* `All device-to-cloud messages or twin change notifications from any module or downstream device `/twinChangeNotifications `Any twin change (reported properties) coming from any module or downstream device `/messages/* `Any device-to-cloud message sent by a module through some or no output, or by a downstream device `/messages/modules/* `Any device-to-cloud message sent by a module through some or no output `/messages/modules//* `Any device-to-cloud message sent by a specific module through some or no output `/messages/modules//outputs/* `Any device-to-cloud message sent by a specific module through some output `/messages/modules//outputs/ `Any device-to-cloud message sent by a specific module through a specific output ### Condition The condition is optional in a route declaration. To pass all messages from the source to the sink, leave out the **WHERE **clause. Or use the [IoT Hub query language ]to filter messages or message types that meet the condition. IoT Edge routes don't support filtering messages based on twin tags or properties. Messages that move between modules in IoT Edge use the same format as messages between your devices and Azure IoT Hub. All messages use JSON format and have **systemProperties **, **appProperties **, and **body **parameters. Build queries around any of the three parameters using this syntax: - System properties: `$ `or `{$} ` - Application properties: ` ` - Body properties: `$body. ` For examples of how to create queries for message properties, see [Device-to-cloud message routes query expressions ]. For example, you might want to filter messages that arrive at a gateway device from a downstream device. Messages sent from modules include a system property called **connectionModuleId **. To route messages from downstream devices directly to IoT Hub and exclude module messages, use this route: ``` `FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream ` ``` ### Sink The sink defines where messages are sent. Only modules and IoT Hub can receive messages. You can't route messages to other devices. The sink property doesn't support wildcards. The sink property can use any of these values: Sink Description `$upstream `Send the message to IoT Hub `BrokeredEndpoint("/modules//inputs/") `Send the message to a specific input of a specific module IoT Edge provides *at least once *guarantees. IoT Edge hub stores messages locally if a route can't deliver the message to its sink. For example, if IoT Edge hub can't connect to IoT Hub or the target module isn't connected. IoT Edge hub stores messages up to the time set in the `storeAndForwardConfiguration.timeToLiveSecs `property of the [IoT Edge hub desired properties ]. ### Priority and time-to-live Declare routes as a string that defines the route, or as an object with a route string, a priority integer, and a time-to-live integer. #### Option 1 ``` `"route1": "FROM WHERE INTO ", ` ``` #### Option 2 (introduced in IoT Edge version 1.0.10 with IoT Edge hub schema version 1.1) ``` `"route2": { "route": "FROM WHERE INTO ", "priority": 0, "timeToLiveSecs": 86400 } ` ``` **Priority **values range from 0 to 9, where 0 is the highest priority. Messages are queued by their endpoints. All priority 0 messages for a specific endpoint are processed before any priority 1 messages for the same endpoint. If multiple routes for the same endpoint have the same priority, messages are processed in the order they arrive. If you don't set a priority, the route uses the lowest priority. The **timeToLiveSecs **property uses the value from IoT Edge hub's **storeAndForwardConfiguration **unless you set it directly. The value can be any positive integer. For details about how priority queues are managed, see [Route priority and time-to-live ]. ## Define or update desired properties The deployment manifest sets desired properties for each module deployed to the IoT Edge device. Desired properties in the deployment manifest overwrite any desired properties currently in the module twin. If you don't set a module twin's desired properties in the deployment manifest, IoT Hub doesn't change the module twin. Instead, set the desired properties programmatically. The same mechanisms that let you change device twins also let you change module twins. For more information, see the [module twin developer guide ]. ## Deployment manifest example The following example shows what a valid deployment manifest document can look like. ``` `{ "modulesContent": { "$edgeAgent": { "properties.desired": { "schemaVersion": "1.1", "runtime": { "type": "docker", "settings": { "minDockerVersion": "v1.25", "loggingOptions": "", "registryCredentials": { "ContosoRegistry": { "username": "myacr", "password": "", "address": "myacr.azurecr.io" } } } }, "systemModules": { "edgeAgent": { "type": "docker", "settings": { "image": "mcr.microsoft.com/azureiotedge-agent:1.5", "createOptions": "{}" } }, "edgeHub": { "type": "docker", "status": "running", "restartPolicy": "always", "startupOrder": 0, "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.5", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}" } } }, "modules": { "SimulatedTemperatureSensor": { "version": "1.5", "type": "docker", "status": "running", "restartPolicy": "always", "startupOrder": 2, "settings": { "image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.5", "createOptions": "{}" } }, "filtermodule": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "startupOrder": 1, "env": { "tempLimit": {"value": "100"} }, "settings": { "image": "myacr.azurecr.io/filtermodule:latest", "createOptions": "{}" } } } } }, "$edgeHub": { "properties.desired": { "schemaVersion": "1.1", "routes": { "sensorToFilter": { "route": "FROM /messages/modules/SimulatedTemperatureSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/filtermodule/inputs/input1\")", "priority": 0, "timeToLiveSecs": 1800 }, "filterToIoTHub": { "route": "FROM /messages/modules/filtermodule/outputs/output1 INTO $upstream", "priority": 1, "timeToLiveSecs": 1800 } }, "storeAndForwardConfiguration": { "timeToLiveSecs": 100 } } } } } ` ``` ## Next steps - For a complete list of properties you can or must include in $edgeAgent and $edgeHub, see [Properties of the IoT Edge agent and IoT Edge hub ]. - Now that you know how IoT Edge modules work, [learn about the requirements and tools for developing IoT Edge modules ]. ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-05-19 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/how-to-develop-csharp-module Develop Azure IoT Edge modules using Visual Studio Code tutorial | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Tutorial: Develop IoT Edge modules using Visual Studio Code Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. This tutorial shows how to develop and deploy your code to an IoT Edge device. Azure IoT Edge modules enable you to deploy code that runs your business logic directly on your IoT Edge device. In the [Deploy code to a Linux device ]quickstart, you set up an IoT Edge device and deployed a module from the Azure Marketplace. This article describes the steps for two IoT Edge development tools: - **Azure IoT Edge Dev Tool **command-line (CLI), which is preferred for development. - **Azure IoT Edge tools for Visual Studio Code **extension, which is in [maintenance mode ]. Use the tool selector button at the beginning of this article to choose your tool. In this tutorial, you learn how to: - Set up your development machine - Use the IoT Edge tools to create a new project - Build your project as a [Docker container ]and store it in an Azure container registry - Deploy your code to an IoT Edge device The IoT Edge module you create in this tutorial filters the temperature data your device generates. It sends messages upstream only if the temperature is above a set threshold. This kind of analysis at the edge helps reduce the amount of data sent to and stored in the cloud. ## Prerequisites A development machine: - Use your own computer or a virtual machine. - Make sure your development machine supports [nested virtualization ]to run a container engine. - You can use most operating systems that run a container engine to develop IoT Edge modules for Linux devices. This tutorial uses a Windows computer, but it also points out known differences on macOS or Linux. - Install [Visual Studio Code ] - Install the [Azure CLI ]. An Azure IoT Edge device: - Run IoT Edge on a separate device. Keeping the development machine and IoT Edge device separate simulates a real deployment scenario and helps keep the concepts clear. Use the quickstart article [Deploy code to a Linux Device ]to create an IoT Edge device in Azure or the [Azure Resource Manager template to deploy an IoT Edge-enabled VM ]. Cloud resources: - Use a free or standard-tier [Azure IoT Hub ]. If you don't have an Azure account, create a [free account ]before you begin. Tip For guidance on interactive debugging in Visual Studio Code or Visual Studio 2022: - [Debug Azure IoT Edge modules using Visual Studio Code ] - [Use Visual Studio 2022 to develop and debug modules for Azure IoT Edge ] This tutorial covers development steps for Visual Studio Code. ## Key concepts This tutorial walks through developing an IoT Edge module. An *IoT Edge module *is a container with executable code. You can deploy one or more modules to an IoT Edge device. Modules do specific tasks like ingesting data from sensors, cleaning and analyzing data, or sending messages to an IoT Hub. For more information, see [Understand Azure IoT Edge modules ]. When you develop IoT Edge modules, you should understand the difference between the development machine and the target IoT Edge device where the module deploys. The container you build to hold your module code must match the operating system (OS) of the target device. For example, the most common scenario is developing a module on a Windows computer to target a Linux device running IoT Edge. In that case, the container operating system is Linux. As you go through this tutorial, keep in mind the difference between the *development machine OS *and the *container OS *. Tip If you're using [IoT Edge for Linux on Windows ], the target device in your scenario is the Linux virtual machine, not the Windows host. This tutorial targets devices running IoT Edge with Linux containers. Use your preferred operating system as long as your development machine runs Linux containers. Visual Studio Code is recommended for developing with Linux containers, so this tutorial uses it. You can use Visual Studio as well, although there are differences in support between the two tools. The following table lists supported development scenarios for Linux containers in Visual Studio Code and Visual Studio. Visual Studio Code Visual Studio 2019/2022 **Linux device architecture **Linux AMD64 Linux ARM32v7 Linux ARM64 Linux AMD64 Linux ARM32 Linux ARM64 **Azure services **Azure Functions Azure Stream Analytics Azure Machine Learning **Languages **C C# Java Node.js Python C C# **More information **[Azure IoT Edge for Visual Studio Code ][Azure IoT Edge Tools for Visual Studio 2019 ] [Azure IoT Edge Tools for Visual Studio 2022 ] ## Install container engine IoT Edge modules are packaged as containers, so you need a [Docker compatible container management system ]on your development machine to build and manage them. Docker Desktop is a popular choice for development because it has strong feature support. Docker Desktop on Windows lets you switch between Linux containers and Windows containers, so you can develop modules for different types of IoT Edge devices. Use the Docker documentation to install Docker on your development machine: - [Install Docker Desktop for Windows ]. When you install Docker Desktop for Windows, you're asked whether you want to use Linux or Windows containers. You can change this setting at any time. This tutorial uses Linux containers because the modules target Linux devices. For more information, see [Switch between Windows and Linux containers ]. - [Install Docker Desktop for Mac ] - Read [About Docker CE ]for installation information on several Linux platforms. For the Windows Subsystem for Linux (WSL), install Docker Desktop for Windows. ## Set up tools Install the Python-based [Azure IoT Edge Dev Tool ]to create your IoT Edge solution. You have two options: - Use the preferred prebuilt [IoT Edge Dev Container ]. - Install the tool using the [iotedgedev development setup ]. Important The **Azure IoT Edge tools for Visual Studio Code **extension is in [maintenance mode ]. The preferred development tool is the command-line (CLI) **Azure IoT Edge Dev Tool **. Use the IoT extensions for Visual Studio Code to develop IoT Edge modules. These extensions offer project templates, automate the creation of the deployment manifest, and let you monitor and manage IoT Edge devices. In this section, you install Visual Studio Code and the IoT extension, then set up your Azure account to manage IoT Hub resources from within Visual Studio Code. - Install [Azure IoT Edge ]extension. - Install [Azure IoT Hub ]extension. - After you install the extensions, open the command palette by selecting **View > Command Palette **. - In the command palette, search for and select **Azure IoT Hub: Select IoT Hub **. Follow the prompts to select your Azure subscription and IoT Hub. - Open the explorer section of Visual Studio Code by selecting the icon in the activity bar or by selecting **View > Explorer **. - At the bottom of the explorer section, expand the collapsed **Azure IoT Hub / Devices **menu. You see the devices and IoT Edge devices associated with the IoT Hub that you selected through the command palette. ### Install language specific tools Install tools specific to the language you're developing in: - [C# ] - [C ] - [Java ] - [Node.js ] - [Python ] - [.NET Core SDK ] - [C# Visual Studio Code extension ] - [C/C++ Visual Studio Code extension ] - Installing the Azure IoT C SDK isn't required for this tutorial, but can provide helpful functionality like IntelliSense and reading program definitions. For installation information, see [Azure IoT C SDKs and Libraries ]. - [Java SE Development Kit 11 ]and [Maven ]. You need to [set the `JAVA_HOME `environment variable ]to point to your JDK installation. - [Maven ] - [Java Extension Pack for Visual Studio Code ] Tip The Java and Maven installation processes add environment variables to your system. Restart any open Visual Studio Code terminal, PowerShell, or command prompt instances after you finish installation. This step makes sure these utilities recognize the Java and Maven commands. - [Node.js ]. - [Yeoman ] - [Azure IoT Edge Node.js Module Generator ]. To develop an IoT Edge module in Python, install these extra prerequisites on your development machine: - [Python ]and [Pip ]. - [Cookiecutter ]. - [Python extension for Visual Studio Code ]. Note Make sure your `bin `folder is on your path for your platform. Typically, it's `~/.local/ `for UNIX and macOS, or `%APPDATA%\Python `on Windows. ## Create a container registry In this tutorial, you use the [Azure IoT Edge ]and [Azure IoT Hub ]extensions to build a module and create a container image from the files. Then you push this image to a registry that stores and manages your images. Finally, you deploy your image from your registry to run on your IoT Edge device. Important The Azure IoT Edge Visual Studio Code extension is in [maintenance mode ]. You can use any Docker-compatible registry to hold your container images. Two popular Docker registry services are [Azure Container Registry ]and [Docker Hub ]. This tutorial uses Azure Container Registry. If you don't already have a container registry, follow these steps to create a new one in Azure: - In the [Azure portal ], select **Create a resource **> **Containers **> **Container Registry **. - Provide the following required values to create your container registry: Field Value Subscription Select a subscription from the drop-down list. Resource group Use the same resource group for all of the test resources that you create during the IoT Edge quickstarts and tutorials; for example, **IoTEdgeResources **. Registry name Provide a unique name. Location Choose a location close to you. SKU Select **Basic **. - Select **Review + create **, then **Create **. - Select your new container registry from the **Resources **section of your Azure portal home page to open it. - In the left pane of your container registry, select **Access keys **from the menu located under **Settings **. [] - Enable **Admin user **with the toggle button and view the **Username **and **Password **for your container registry. - Copy the values for **Login server **, **Username **, and **password **and save them somewhere convenient. You use these values throughout this tutorial to provide access to the container registry. ## Create a new module project The Azure IoT Edge extension offers project templates for all supported IoT Edge module languages in Visual Studio Code. These templates include all the files and code you need to deploy a working module to test IoT Edge, or give you a starting point to customize the template with your own business logic. ### Create a project template The [IoT Edge Dev Tool ]simplifies Azure IoT Edge development, with commands driven by environment variables. It helps you get started with IoT Edge development using the IoT Edge Dev Container and IoT Edge solution scaffolding that includes a default module and all the required configuration files. - Create a directory for your solution at the path you want. Change to your `iotedgesolution `directory. ``` `mkdir c:\dev\iotedgesolution cd c:\dev\iotedgesolution ` ``` - Use the `iotedgedev solution init `command to create a solution and set up your Azure IoT Hub in the development language of your choice: - [C# ] - [C ] - [Java ] - [Node.js ] - [Python ] ``` `iotedgedev solution init --template csharp ` ``` ``` `iotedgedev solution init --template c ` ``` ``` `iotedgedev solution init --template java ` ``` ``` `iotedgedev solution init --template nodejs ` ``` ``` `iotedgedev solution init --template python ` ``` The `iotedgedev solution init `command prompts you to complete several steps, including: - Authenticate to Azure - Choose an Azure subscription - Choose or create a resource group - Choose or create an Azure IoT Hub - Choose or create an Azure IoT Edge device Use Visual Studio Code and the [Azure IoT Edge ]extension. Start by creating a solution, then generate the first module in that solution. Each solution can include multiple modules. - Select **View > Command Palette **. - In the command palette, enter and run the command **Azure IoT Edge: New IoT Edge Solution **. - Browse to the folder where you want to create the new solution, then select **Select folder **. - Enter a name for your solution. - Select a module template for your preferred development language to be the first module in the solution. - Enter a name for your module. Choose a name that's unique within your container registry. - Enter the name of the module's image repository. Visual Studio Code autopopulates the module name with **localhost:5000/ **. Replace it with your own registry information. Use **localhost **if you use a local Docker registry for testing. If you use Azure Container Registry, use **Login server **from your registry's settings. The sign-in server looks like *** *.azurecr.io **. Only replace the **localhost:5000 **part of the string, so that the final result looks like **< *registry name *>.azurecr.io/ * ***. Visual Studio Code takes the information you provided, creates an IoT Edge solution, and then loads it in a new window. After you create the solution, these main files are in the solution: - The **.vscode **folder includes the configuration file **launch.json **. - The **modules **folder has subfolders for each module. In each subfolder, the module.json file controls how modules are built and deployed. - The **.env **file lists your environment variables. The environment variable for the container registry is **localhost:5000 **by default. - Two module deployment files, **deployment.template.json **and **deployment.debug.template.json **, list the modules to deploy to your device. By default, the list includes the IoT Edge system modules (edgeAgent and edgeHub) and sample modules such as: - **filtermodule **is a sample module that implements a simple filter function. - **SimulatedTemperatureSensor **module simulates data you can use for testing. For more information about how deployment manifests work, see [Learn how to use deployment manifests to deploy modules and establish routes ]. For more information about how the simulated temperature module works, see the [SimulatedTemperatureSensor.csproj source code ]. Note The exact modules installed can depend on your language of choice. ### Set IoT Edge runtime version The latest stable IoT Edge system module version is 1.5. Set your system modules to version 1.5. - In Visual Studio Code, open the **deployment.template.json **deployment manifest file. The [deployment manifest ]is a JSON document that describes the modules to be configured on the targeted IoT Edge device. - Change the runtime version for the system runtime module images `edgeAgent `and `edgeHub `. For example, if you want to use the IoT Edge runtime version 1.5, change the following lines in the deployment manifest file: ``` `"systemModules": { "edgeAgent": { "image": "mcr.microsoft.com/azureiotedge-agent:1.5", "edgeHub": { "image": "mcr.microsoft.com/azureiotedge-hub:1.5", ` ``` ### Provide your registry credentials to the IoT Edge agent The environment file stores the credentials for your container registry and shares them with the IoT Edge runtime. The runtime needs these credentials to pull your container images to the IoT Edge device. The IoT Edge extension tries to pull your container registry credentials from Azure and populate them in the environment file. Note The environment file is only created if you provide an image repository for the module. If you accepted the localhost defaults to test and debug locally, then you don't need to declare environment variables. Check if your credentials exist. If not, add them now: - If Azure Container Registry is your registry, set an Azure Container Registry username and password. Get these values from your container registry's **Settings **> **Access keys **menu in the Azure portal. - Open the **.env **file in your module solution. - Add the **username **and **password **values that you copied from your Azure container registry. For example: ``` `CONTAINER_REGISTRY_SERVER="myacr.azurecr.io" CONTAINER_REGISTRY_USERNAME="myacr" CONTAINER_REGISTRY_PASSWORD="" ` ``` - Save your changes to the **.env **file. Note This tutorial uses administrator credentials for Azure Container Registry that are convenient for development and test scenarios. When you're ready for production scenarios, we recommend a least-privileged authentication option like service principals or repository-scoped tokens. For more information, see [Manage access to your container registry ]. ### Target architecture Select the architecture you're targeting with each solution, because that affects how the container is built and runs. The default is Linux AMD64. For this tutorial, use an Ubuntu virtual machine as the IoT Edge device and keep the default **amd64 **. If you need to change the target architecture for your solution, follow these steps. - Open the command palette and search for **Azure IoT Edge: Set Default Target Platform for Edge Solution **, or select the shortcut icon in the sidebar at the bottom of the window. - In the command palette, select the target architecture from the list of options. - [C# ] - [C, Java, Node.js, Python ] The target architecture is set when you create the container image in a later step. - Open or create **settings.json **in the **.vscode **directory of your solution. - Change the `platform `value to `amd64 `, `arm32v7 `, `arm64v8 `, or `windows-amd64 `. For example: ``` `{ "azure-iot-edge.defaultPlatform": { "platform": "amd64", "alias": null } } ` ``` ### Update module with custom code Each template includes sample code that takes simulated sensor data from the **SimulatedTemperatureSensor **module and routes it to the IoT Hub. The sample module receives messages and passes them on. The pipeline functionality shows an important concept in IoT Edge: how modules communicate with each other. Each module can have multiple *input *and *output *queues declared in its code. The IoT Edge hub running on the device routes messages from the output of one module to the input of one or more modules. The specific code for declaring inputs and outputs varies between languages, but the concept is the same for all modules. For more information about routing between modules, see [Declare routes ]. - [C# ] - [C ] - [Java ] - [Node.js ] - [Python ] The sample C# code that comes with the project template uses the [ModuleClient class ]from the IoT Hub SDK for .NET. - In the Visual Studio Code explorer, open **modules > filtermodule > ModuleBackgroundService.cs **. - Before the `filtermodule `namespace, add three `using `statements for types that are used later: ``` `using System.Collections.Generic; // For KeyValuePair<> using Microsoft.Azure.Devices.Shared; // For TwinCollection using Newtonsoft.Json; // For JsonConvert ` ``` - Add the `temperatureThreshold `variable to the `ModuleBackgroundService `class. This variable sets the value that the measured temperature must exceed for the data to be sent to the IoT Hub. ``` `static int temperatureThreshold { get; set; } = 25; ` ``` - Add the `MessageBody `, `Machine `, and `Ambient `classes. These classes define the expected schema for the body of incoming messages. ``` `class MessageBody { public Machine machine {get;set;} public Ambient ambient {get; set;} public string timeCreated {get; set;} } class Machine { public double temperature {get; set;} public double pressure {get; set;} } class Ambient { public double temperature {get; set;} public int humidity {get; set;} } ` ``` - Find the `ExecuteAsync `function. This function creates and configures a `ModuleClient `object that allows the module to connect to the local Azure IoT Edge runtime to send and receive messages. After creating the `ModuleClient `, the code reads the `temperatureThreshold `value from the module twin's desired properties. The code registers a callback to receive messages from an IoT Edge hub via an endpoint called `input1 `. Replace the call to the `ProcessMessageAsync `method with a new one that updates the name of the endpoint and the method that's called when input arrives. Also, add a `SetDesiredPropertyUpdateCallbackAsync `method for updates to the desired properties. To make this change, replace the last line of the `ExecuteAsync `method with the following code: ``` `// Register a callback for messages that are received by the module. // await _moduleClient.SetInputMessageHandlerAsync("input1", PipeMessage, cancellationToken); // Read the TemperatureThreshold value from the module twin's desired properties var moduleTwin = await _moduleClient.GetTwinAsync(); await OnDesiredPropertiesUpdate(moduleTwin.Properties.Desired, _moduleClient); // Attach a callback for updates to the module twin's desired properties. await _moduleClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertiesUpdate, null); // Register a callback for messages that are received by the module. Messages received on the inputFromSensor endpoint are sent to the FilterMessages method. await _moduleClient.SetInputMessageHandlerAsync("inputFromSensor", FilterMessages, _moduleClient); ` ``` - Add the `OnDesiredPropertiesUpdate `method to the `ModuleBackgroundService `class. This method receives updates on the desired properties from the module twin, and updates the `temperatureThreshold `variable to match. All modules have their own module twin, which lets you configure the code that's running inside a module directly from the cloud. ``` `static Task OnDesiredPropertiesUpdate(TwinCollection desiredProperties, object userContext) { try { Console.WriteLine("Desired property change:"); Console.WriteLine(JsonConvert.SerializeObject(desiredProperties)); if (desiredProperties["TemperatureThreshold"]!=null) temperatureThreshold = desiredProperties["TemperatureThreshold"]; } catch (AggregateException ex) { foreach (Exception exception in ex.InnerExceptions) { Console.WriteLine(); Console.WriteLine("Error when receiving desired property: {0}", exception); } } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("Error when receiving desired property: {0}", ex.Message); } return Task.CompletedTask; } ` ``` - Add the `FilterMessages `method. This method is called whenever the module receives a message from the IoT Edge hub. It filters out messages that report temperatures below the temperature threshold set via the module twin. It also adds the `MessageType `property to the message with the value set to `Alert `: ``` `async Task FilterMessages(Message message, object userContext) { var counterValue = Interlocked.Increment(ref _counter); try { ModuleClient moduleClient = (ModuleClient)userContext; var messageBytes = message.GetBytes(); var messageString = Encoding.UTF8.GetString(messageBytes); Console.WriteLine($"Received message {counterValue}: [{messageString}]"); // Get the message body. var messageBody = JsonConvert.DeserializeObject(messageString); if (messageBody != null && messageBody.machine.temperature > temperatureThreshold) { Console.WriteLine($"Machine temperature {messageBody.machine.temperature} " + $"exceeds threshold {temperatureThreshold}"); using (var filteredMessage = new Message(messageBytes)) { foreach (KeyValuePair prop in message.Properties) { filteredMessage.Properties.Add(prop.Key, prop.Value); } filteredMessage.Properties.Add("MessageType", "Alert"); await moduleClient.SendEventAsync("output1", filteredMessage); } } // Indicate that the message treatment is completed. return MessageResponse.Completed; } catch (AggregateException ex) { foreach (Exception exception in ex.InnerExceptions) { Console.WriteLine(); Console.WriteLine("Error in sample: {0}", exception); } // Indicate that the message treatment is not completed. var moduleClient = (ModuleClient)userContext; return MessageResponse.Abandoned; } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("Error in sample: {0}", ex.Message); // Indicate that the message treatment is not completed. ModuleClient moduleClient = (ModuleClient)userContext; return MessageResponse.Abandoned; } } ` ``` - Save the **ModuleBackgroundService.cs **file. - In the Visual Studio Code explorer, open the **deployment.template.json **file in your IoT Edge solution workspace. - Since we changed the name of the endpoint that the module listens on, we also need to update the routes in the deployment manifest so that the **edgeHub **sends messages to the new endpoint. Find the `routes `section in the **$edgeHub **module twin. Update the `sensorTofiltermodule `route to replace `input1 `with `inputFromSensor `: ``` `"sensorTofiltermodule": "FROM /messages/modules/tempSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/filtermodule/inputs/inputFromSensor\")" ` ``` - Add the **filtermodule **module twin to the deployment manifest. Insert the following JSON content at the bottom of the `modulesContent `section, after the **$edgeHub **module twin: ``` `"filtermodule": { "properties.desired":{ "TemperatureThreshold":25 } } ` ``` - Save the **deployment.template.json **file. - The data from the sensor in this scenario comes in JSON format. To filter messages in JSON format, import a JSON library for C. This tutorial uses Parson. - Download the [Parson GitHub repository ]. Copy the **parson.c **and **parson.h **files into the **filtermodule **folder. - Open **modules > filtermodule > CMakeLists.txt **. At the top of the file, import the Parson files as a library called **my_parson **: ``` `add_library(my_parson parson.c parson.h ) ` ``` - Add `my_parson `to the list of libraries in the `target_link_libraries `function of CMakeLists.txt. - Save the **CMakeLists.txt **file. - Open **modules > filtermodule > main.c **. At the bottom of the list of `include `statements, add a new one to include `parson.h `for JSON support: ``` `#include "parson.h" ` ``` - In the **main.c **file, add a global variable called `temperatureThreshold `after the `include `section. This variable sets the value that the measured temperature must exceed in order for the data to be sent to IoT Hub: ``` `static double temperatureThreshold = 25; ` ``` - Find the `CreateMessageInstance `function in **main.c **. Replace the inner `if-else `statement with the following code that adds a few lines of functionality: ``` `if ((messageInstance->messageHandle = IoTHubMessage_Clone(message)) == NULL) { free(messageInstance); messageInstance = NULL; } else { messageInstance->messageTrackingId = messagesReceivedByInput1Queue; MAP_HANDLE propMap = IoTHubMessage_Properties(messageInstance->messageHandle); if (Map_AddOrUpdate(propMap, "MessageType", "Alert") != MAP_OK) { printf("ERROR: Map_AddOrUpdate Failed!\r\n"); } } ` ``` The new lines of code in the `else `statement add a new property to the message, which labels the message as an alert. This code labels all messages as alerts, because we'll add functionality that only sends messages to IoT Hub if they report high temperatures. - Replace the entire `InputQueue1Callback `function with the following code. This function implements the actual messaging filter. When a message is received, it checks whether the reported temperature exceeds the threshold. If it does, then it forwards the message through its output queue. If not, then it ignores the message: ``` `static unsigned char *bytearray_to_str(const unsigned char *buffer, size_t len) { unsigned char *ret = (unsigned char *)malloc(len + 1); memcpy(ret, buffer, len); ret[len] = '\0'; return ret; } static IOTHUBMESSAGE_DISPOSITION_RESULT InputQueue1Callback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback) { IOTHUBMESSAGE_DISPOSITION_RESULT result; IOTHUB_CLIENT_RESULT clientResult; IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle = (IOTHUB_MODULE_CLIENT_LL_HANDLE)userContextCallback; unsigned const char* messageBody; size_t contentSize; if (IoTHubMessage_GetByteArray(message, &messageBody, &contentSize) == IOTHUB_MESSAGE_OK) { messageBody = bytearray_to_str(messageBody, contentSize); } else { messageBody = ""; } printf("Received Message [%zu]\r\n Data: [%s]\r\n", messagesReceivedByInput1Queue, messageBody); // Check if the message reports temperatures higher than the threshold JSON_Value *root_value = json_parse_string(messageBody); JSON_Object *root_object = json_value_get_object(root_value); double temperature; if (json_object_dotget_value(root_object, "machine.temperature") != NULL && (temperature = json_object_dotget_number(root_object, "machine.temperature")) > temperatureThreshold) { printf("Machine temperature %f exceeds threshold %f\r\n", temperature, temperatureThreshold); // This message should be sent to next stop in the pipeline, namely "output1". What happens at "output1" is determined // by the configuration of the Edge routing table setup. MESSAGE_INSTANCE *messageInstance = CreateMessageInstance(message); if (NULL == messageInstance) { result = IOTHUBMESSAGE_ABANDONED; } else { printf("Sending message (%zu) to the next stage in pipeline\n", messagesReceivedByInput1Queue); clientResult = IoTHubModuleClient_LL_SendEventToOutputAsync(iotHubModuleClientHandle, messageInstance->messageHandle, "output1", SendConfirmationCallback, (void *)messageInstance); if (clientResult != IOTHUB_CLIENT_OK) { IoTHubMessage_Destroy(messageInstance->messageHandle); free(messageInstance); printf("IoTHubModuleClient_LL_SendEventToOutputAsync failed on sending msg#=%zu, err=%d\n", messagesReceivedByInput1Queue, clientResult); result = IOTHUBMESSAGE_ABANDONED; } else { result = IOTHUBMESSAGE_ACCEPTED; } } } else { printf("Not sending message (%zu) to the next stage in pipeline.\r\n", messagesReceivedByInput1Queue); result = IOTHUBMESSAGE_ACCEPTED; } messagesReceivedByInput1Queue++; return result; } ` ``` - Add a `moduleTwinCallback `function. This method receives updates on the desired properties from the module twin, and updates the `temperatureThreshold `variable to match. All modules have their own module twin, which lets you configure the code running inside a module directly from the cloud: ``` `static void moduleTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback) { printf("\r\nTwin callback called with (state=%s, size=%zu):\r\n%s\r\n", MU_ENUM_TO_STRING(DEVICE_TWIN_UPDATE_STATE, update_state), size, payLoad); JSON_Value *root_value = json_parse_string(payLoad); JSON_Object *root_object = json_value_get_object(root_value); if (json_object_dotget_value(root_object, "desired.TemperatureThreshold") != NULL) { temperatureThreshold = json_object_dotget_number(root_object, "desired.TemperatureThreshold"); } if (json_object_get_value(root_object, "TemperatureThreshold") != NULL) { temperatureThreshold = json_object_get_number(root_object, "TemperatureThreshold"); } } ` ``` - Find the `SetupCallbacksForModule `function. Replace the function with the following code that adds an `else if `statement to check if the module twin is updated: ``` `static int SetupCallbacksForModule(IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle) { int ret; if (IoTHubModuleClient_LL_SetInputMessageCallback(iotHubModuleClientHandle, "input1", InputQueue1Callback, (void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK) { printf("ERROR: IoTHubModuleClient_LL_SetInputMessageCallback(\"input1\")..........FAILED!\r\n"); ret = MU_FAILURE; } else if (IoTHubModuleClient_LL_SetModuleTwinCallback(iotHubModuleClientHandle, moduleTwinCallback, (void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK) { printf("ERROR: IoTHubModuleClient_LL_SetModuleTwinCallback(default)..........FAILED!\r\n"); ret = MU_FAILURE; } else { ret = 0; } return ret; } ` ``` - Save the **main.c **file. - In the Visual Studio Code explorer, open the **deployment.template.json **file in your IoT Edge solution workspace. - Add the **filtermodule **module twin to the deployment manifest. Insert the following JSON content at the bottom of the `moduleContent `section, after the `$edgeHub `module twin: ``` `"filtermodule": { "properties.desired":{ "TemperatureThreshold":25 } } ` ``` - Save the **deployment.template.json **file. - In the Visual Studio Code explorer, open **modules > filtermodule > src > main > java > com > edgemodule > App.java **. - Add the following code at the top of the file to import new referenced classes. ``` `import java.io.StringReader; import java.util.concurrent.atomic.AtomicLong; import java.util.HashMap; import java.util.Map; import javax.json.Json; import javax.json.JsonObject; import javax.json.JsonReader; import com.microsoft.azure.sdk.iot.device.DeviceTwin.Pair; import com.microsoft.azure.sdk.iot.device.DeviceTwin.Property; import com.microsoft.azure.sdk.iot.device.DeviceTwin.TwinPropertyCallBack; ` ``` - Add the following definition into the `App `class. This variable sets a temperature threshold. The measured machine temperature isn't reported to IoT Hub until it exceeds this value: ``` `private static final String TEMP_THRESHOLD = "TemperatureThreshold"; private static AtomicLong tempThreshold = new AtomicLong(25); ` ``` - Replace the execute method of `MessageCallbackMqtt `with the following code. This method is called whenever the module receives an MQTT message from the IoT Edge hub. It filters out messages that report temperatures below the temperature threshold set via the module twin: ``` `protected static class MessageCallbackMqtt implements MessageCallback { private int counter = 0; @Override public IotHubMessageResult execute(Message msg, Object context) { this.counter += 1; String msgString = new String(msg.getBytes(), Message.DEFAULT_IOTHUB_MESSAGE_CHARSET); System.out.println( String.format("Received message %d: %s", this.counter, msgString)); if (context instanceof ModuleClient) { try (JsonReader jsonReader = Json.createReader(new StringReader(msgString))) { final JsonObject msgObject = jsonReader.readObject(); double temperature = msgObject.getJsonObject("machine").getJsonNumber("temperature").doubleValue(); long threshold = App.tempThreshold.get(); if (temperature >= threshold) { ModuleClient client = (ModuleClient) context; System.out.println( String.format("Temperature above threshold %d. Sending message: %s", threshold, msgString)); client.sendEventAsync(msg, eventCallback, msg, App.OUTPUT_NAME); } } catch (Exception e) { e.printStackTrace(); } } return IotHubMessageResult.COMPLETE; } } ` ``` - Add the following two static inner classes into the `App `class. These classes update the `tempThreshold `variable when the module twin's desired property changes. All modules have their own module twin, which lets you configure the code that's running inside a module directly from the cloud: ``` `protected static class DeviceTwinStatusCallBack implements IotHubEventCallback { @Override public void execute(IotHubStatusCode status, Object context) { System.out.println("IoT Hub responded to device twin operation with status " + status.name()); } } protected static class OnProperty implements TwinPropertyCallBack { @Override public void TwinPropertyCallBack(Property property, Object context) { if (!property.getIsReported()) { if (property.getKey().equals(App.TEMP_THRESHOLD)) { try { long threshold = Math.round((double) property.getValue()); App.tempThreshold.set(threshold); } catch (Exception e) { System.out.println("Failed to set TemperatureThread with exception"); e.printStackTrace(); } } } } } ` ``` - Add the following lines to the `main `method after `client.open() `to subscribe the module twin updates: ``` `client.startTwin(new DeviceTwinStatusCallBack(), null, new OnProperty(), null); Map> onDesiredPropertyChange = new HashMap>() { { put(new Property(App.TEMP_THRESHOLD, null), new Pair(new OnProperty(), null)); } }; client.subscribeToTwinDesiredProperties(onDesiredPropertyChange); client.getTwin(); ` ``` - Save the **App.java **file. - In the Visual Studio Code explorer, open the **deployment.template.json **file in your IoT Edge solution workspace. - Add the **filtermodule **module twin to the deployment manifest. Insert the following JSON content at the bottom of the `moduleContent `section, after the **$edgeHub **module twin: ``` `"filtermodule": { "properties.desired":{ "TemperatureThreshold":25 } } ` ``` - Save the **deployment.template.json **file. - In the Visual Studio Code explorer, open **modules > filtermodule > app.js **. - Add a temperature threshold variable to the beginning of **app.js **. The temperature threshold sets the value that the measured temperature must exceed in order for the data to be sent to IoT Hub: ``` `var temperatureThreshold = 25; ` ``` - Replace the entire `PipeMessage `function with the `FilterMessage `function. ``` `// This function filters out messages that report temperatures below the temperature threshold. // It also adds the MessageType property to the message with the value set to Alert. function filterMessage(client, inputName, msg) { client.complete(msg, printResultFor('Receiving message')); if (inputName === 'input1') { var message = msg.getBytes().toString('utf8'); var messageBody = JSON.parse(message); if (messageBody && messageBody.machine && messageBody.machine.temperature && messageBody.machine.temperature > temperatureThreshold) { console.log(`Machine temperature ${messageBody.machine.temperature} exceeds threshold ${temperatureThreshold}`); var outputMsg = new Message(message); outputMsg.properties.add('MessageType', 'Alert'); client.sendOutputEvent('output1', outputMsg, printResultFor('Sending received message')); } } } ` ``` - Replace the function name `pipeMessage `with `filterMessage `in the `client.on() `call: ``` `client.on('inputMessage', function (inputName, msg) { filterMessage(client, inputName, msg); }); ` ``` - Copy the following code into the `client.open() `function callback, after `client.on() `inside the `else `statement. This function is invoked when the desired properties are updated: ``` `client.getTwin(function (err, twin) { if (err) { console.error('Error getting twin: ' + err.message); } else { twin.on('properties.desired', function(delta) { if (delta.TemperatureThreshold) { temperatureThreshold = delta.TemperatureThreshold; } }); } }); ` ``` - Save the **app.js **file. - In the Visual Studio Code explorer, open the **deployment.template.json **file in your IoT Edge solution workspace. - Add the **filtermodule **module twin to the deployment manifest. Insert the following JSON content at the bottom of the `moduleContent `section, after the `$edgeHub `module twin: ``` `"filtermodule": { "properties.desired":{ "TemperatureThreshold":25 } } ` ``` - Save the **deployment.template.json **file. In this section, add the code that expands the **filtermodule **to analyze the messages before sending them. You add code that filters messages where the reported machine temperature is within the acceptable limits. - In the Visual Studio Code explorer, open **modules > filtermodule > main.py **. - At the top of the **main.py **file, import the **json **library: ``` `import json ` ``` - Add global definitions for the **TEMPERATURE_THRESHOLD **, **RECEIVED_MESSAGES **and **TWIN_CALLBACKS **variables. The temperature threshold sets the value that the measured machine temperature must exceed for the data to be sent to the IoT Hub: ``` `# global counters TEMPERATURE_THRESHOLD = 25 TWIN_CALLBACKS = 0 RECEIVED_MESSAGES = 0 ` ``` - Replace the `create_client `function with the following code: ``` `def create_client(): client = IoTHubModuleClient.create_from_edge_environment() # Define function for handling received messages async def receive_message_handler(message): global RECEIVED_MESSAGES print("Message received") size = len(message.data) message_text = message.data.decode('utf-8') print(" Data: <<<{data}>>> & Size={size}".format(data=message.data, size=size)) print(" Properties: {}".format(message.custom_properties)) RECEIVED_MESSAGES += 1 print("Total messages received: {}".format(RECEIVED_MESSAGES)) if message.input_name == "input1": message_json = json.loads(message_text) if "machine" in message_json and "temperature" in message_json["machine"] and message_json["machine"]["temperature"] > TEMPERATURE_THRESHOLD: message.custom_properties["MessageType"] = "Alert" print("ALERT: Machine temperature {temp} exceeds threshold {threshold}".format( temp=message_json["machine"]["temperature"], threshold=TEMPERATURE_THRESHOLD )) await client.send_message_to_output(message, "output1") # Define function for handling received twin patches async def receive_twin_patch_handler(twin_patch): global TEMPERATURE_THRESHOLD global TWIN_CALLBACKS print("Twin Patch received") print(" {}".format(twin_patch)) if "TemperatureThreshold" in twin_patch: TEMPERATURE_THRESHOLD = twin_patch["TemperatureThreshold"] TWIN_CALLBACKS += 1 print("Total calls confirmed: {}".format(TWIN_CALLBACKS)) try: # Set handler on the client client.on_message_received = receive_message_handler client.on_twin_desired_properties_patch_received = receive_twin_patch_handler except: # Cleanup if failure occurs client.shutdown() raise return client ` ``` - Save the **main.py **file. - In the Visual Studio Code explorer, open the **deployment.template.json **file in your IoT Edge solution workspace. - Add the **filtermodule **module twin to the deployment manifest. Insert the following JSON content at the bottom of the `modulesContent `section, after the **$edgeHub **module twin: ``` `"filtermodule": { "properties.desired":{ "TemperatureThreshold":25 } } ` ``` - Save the **deployment.template.json **file. ## Build and push your solution You updated the module code and the deployment template to help understand some key deployment concepts. Now, you're ready to build your module container image and push it to your container registry. In Visual Studio Code, open the **deployment.template.json **deployment manifest file. The [deployment manifest ]describes the modules to be configured on the targeted IoT Edge device. Before deployment, you must update your Azure Container Registry credentials and your module images with the proper `createOptions `values. For more information about `createOptions `values, see [How to configure container create options for IoT Edge modules ]. If you use an Azure Container Registry to store your module image, add your credentials to the `modulesContent > edgeAgent > settings > registryCredentials `section in **deployment.template.json **. Replace `myacr `with your own registry name and provide your password and login server address. For example: ``` `"registryCredentials": { "myacr": { "username": "myacr", "password": "", "address": "myacr.azurecr.io" } } ` ``` Add or replace the following stringified content to the `createOptions `value for each system ( **edgeHub **and * **edgeAgent **) and custom module ( **filtermodule **and **tempSensor **) listed. Change the values if necessary: ``` `"createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}" ` ``` For example, the `filtermodule `configuration should be similar to: ``` `"filtermodule": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "myacr.azurecr.io/filtermodule:0.0.1-amd64", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}" } ` ``` #### Build module Docker image Open the Visual Studio Code integrated terminal by selecting **Terminal > New Terminal **. - [C# ] - [C, Java, Node.js, Python ] Use the `dotnet publish `command to build the container image for Linux and amd64 architecture. Change directory to the **filtermodule **directory in your project and run the `dotnet publish `command. ``` `dotnet publish --os linux --arch x64 /t:PublishContainer ` ``` Currently, the **iotedgedev **tool template targets .NET 7.0. If you want to target a different version of .NET, you can edit the **filtermodule.csproj **file and change the `TargetFramework `and `PackageReference `values. For example to target .NET 8.0, your **filtermodule.csproj **file should look like this: ``` ` net8.0 enable enable ` ``` Tag the docker image with your container registry information, version, and architecture. Replace `myacr `with your own registry name: ``` `docker tag filtermodule myacr.azurecr.io/filtermodule:0.0.1-amd64 ` ``` Use the module's Dockerfile to [build ]and tag the module Docker image: ``` `docker build --rm -f "" -t "" ` ``` For example, to build the image for the local registry or an Azure container registry, run the following commands: ``` `# Build and tag the image for the local registry docker build --rm -f "./modules/filtermodule/Dockerfile.amd64.debug" -t localhost:5000/filtermodule:0.0.1-amd64 "./modules/filtermodule" # Or build and tag the image for an Azure Container Registry. Replace myacr with your own registry name. docker build --rm -f "./modules/filtermodule/Dockerfile.amd64.debug" -t myacr.azurecr.io/filtermodule:0.0.1-amd64 "./modules/filtermodule" ` ``` #### Push module Docker image Provide your container registry credentials to Docker so that it can push your container image to storage in the registry. - Sign in to Docker with the Azure Container Registry (ACR) credentials: ``` `docker login -u -p ` ``` You might receive a security warning recommending the use of `--password-stdin `. While that's a recommended best practice for production scenarios, it's outside the scope of this tutorial. For more information, see the [docker login ]reference. - Sign in to the Azure Container Registry. You must [install Azure CLI ]to use the `az `command. This command asks for your user name and password found in your container registry in **Settings > Access keys **: ``` `az acr login -n ` ``` Tip If you are logged out at any point in this tutorial, repeat the Docker and Azure Container Registry sign-in steps to continue. - [Push ]your module image to the local registry or a container registry: ``` `docker push ` ``` For example: ``` `# Push the Docker image to the local registry docker push localhost:5000/filtermodule:0.0.1-amd64 # Or push the Docker image to an Azure Container Registry. Replace myacr with your Azure Container Registry name. az acr login --name myacr docker push myacr.azurecr.io/filtermodule:0.0.1-amd64 ` ``` #### Update the deployment template Update the deployment template **deployment.template.json **with the container registry image location. For example, if you're using an Azure Container Registry **myacr.azurecr.io **and your image is **filtermodule:0.0.1-amd64 **, update the `filtermodule `configuration to: ``` `"filtermodule": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "myacr.azurecr.io/filtermodule:0.0.1-amd64", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}" } } ` ``` In the Visual Studio Code explorer, right-click the **deployment.template.json **file and select **Build and Push IoT Edge Solution **. The build and push command starts three operations. First, it creates a new folder in the solution called **config **that holds the full deployment manifest, built out of information in the deployment template and other solution files. Second, it runs `docker build `to build the container image based on the appropriate dockerfile for your target architecture. Then, it runs `docker push `to push the image repository to your container registry. This process might take several minutes the first time, but it's faster the next time you run the commands. #### Optional: Update the module and image If you make changes to your module code, you must rebuild and push the module image to your container registry. Use the steps in this section to update the build and container image. You can skip this section if you didn't make any changes to your module code. Open the **deployment.amd64.json **file in newly created config folder. The filename reflects the target architecture, so it's different if you chose a different architecture. Notice that the two parameters that had placeholders now contain their proper values. The `registryCredentials `section has your registry username and password pulled from the **.env **file. The `filtermodule `has the full image repository with the name, version, and architecture tag from the **module.json **file. - Open the **module.json **file in the **filtermodule **folder. - Change the version number for the module image. For example, increment the patch version number to `"version": "0.0.2" `as if you made a small fix in the module code. Tip Module versions enable version control, and allow you to test changes on a small set of devices before you deploy updates to production. If you don't increment the module version before building and pushing, then you overwrite the repository in your container registry. - Save your changes to the **module.json **file. Build and push the updated image with a **0.0.2 **version tag. For example, to build and push the image for the local registry or an Azure container registry, use the following commands: - [C# ] - [C, Java, Node.js, Python ] ``` `# Build the container image for Linux and amd64 architecture. dotnet publish --os linux --arch x64 # For local registry: # Tag the image with version 0.0.2, x64 architecture, and the local registry. docker tag filtermodule localhost:5000/filtermodule:0.0.2-amd64 # For Azure Container Registry: # Tag the image with version 0.0.2, x64 architecture, and your container registry information. Replace **myacr** with your own registry name. docker tag filtermodule myacr.azurecr.io/filtermodule:0.0.2-amd64 ` ``` ``` `# Build and push the 0.0.2 image for the local registry docker build --rm -f "./modules/filtermodule/Dockerfile.amd64.debug" -t localhost:5000/filtermodule:0.0.2-amd64 "./modules/filtermodule" docker push localhost:5000/filtermodule:0.0.2-amd64 # Or build and push the 0.0.2 image for an Azure Container Registry. Replace myacr with your own registry name. docker build --rm -f "./modules/filtermodule/Dockerfile.amd64.debug" -t myacr.azurecr.io/filtermodule:0.0.2-amd64 "./modules/filtermodule" docker push myacr.azurecr.io/filtermodule:0.0.2-amd64 ` ``` Right-click the **deployment.template.json **file again, and select **Build and Push IoT Edge Solution **again. Open the **deployment.amd64.json **file again. Notice the build system doesn't create a new file when you run the build and push command again. Rather, the same file updates to reflect the changes. The **filtermodule **image now points to the 0.0.2 version of the container. To further verify what the build and push command did, go to the [Azure portal ]and navigate to your container registry. In your container registry, select **Repositories **then **filtermodule **. Verify that both versions of the image push to the registry. [] ### Troubleshoot If you encounter errors when building and pushing your module image, it often has to do with Docker configuration on your development machine. Use the following checks to review your configuration: - Did you run the `docker login `command using the credentials that you copied from your container registry? These credentials are different than the ones that you use to sign in to Azure. - Is your container repository correct? Does it have your correct container registry name and your correct module name? Open the **module.json **file in the **filtermodule **folder to check. The repository value should be similar to **.azurecr.io/filtermodule **. - If you used a different name than **filtermodule **for your module, is that name consistent throughout the solution? - Is your machine running the same type of containers that you're building? This tutorial is for Linux IoT Edge devices, so Visual Studio Code should say **amd64 **or **arm32v7 **in the side bar, and Docker Desktop should be running Linux containers. ## Deploy modules to device You verified that there are built container images stored in your container registry, so it's time to deploy them to a device. Make sure that your IoT Edge device is up and running. Use the IoT Edge Azure [CLI set-modules ]command to deploy the modules to the Azure IoT Hub. For example, to deploy the modules defined in the **deployment.template.json **file to the IoT Hub **my-iot-hub **for the IoT Edge device **my-device **, use the following command. Replace the **hub-name **, **device-id **, and **login **IoT Hub connection string values with your own. ``` `az iot edge set-modules --hub-name my-iot-hub --device-id my-device --content ./deployment.template.json --login "HostName=my-iot-hub.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=" ` ``` Tip Find your IoT Hub connection string, including the shared access key, in the Azure portal. Go to your IoT Hub, and select **Security settings > Shared access policies > iothubowner **. - In the Visual Studio Code explorer, under the **Azure IoT Hub **section, expand **Devices **to see your list of IoT devices. - Right-click the IoT Edge device that you want to deploy to, then select **Create Deployment for Single Device **. - In the file explorer, navigate into the **config **folder then select the **deployment.amd64.json **file. Don't use the deployment.template.json file, which doesn't have the container registry credentials or module image values in it. If you target a Linux ARM32 device, the deployment manifest's name is **deployment.arm32v7.json **. - Under your device, expand **Modules **to see a list of deployed and running modules. Select the refresh button. You should see the new **tempSensor **and **filtermodule **modules running on your device. It can take a few minutes for the modules to start. The IoT Edge runtime receives its new deployment manifest, pulls down the module images from the container runtime, then starts each new module. ## View messages from device The sample module code gets messages through its input queue and sends them through its output queue. The deployment manifest sets up routes that send messages to **filtermodule **from **tempSensor **, and then forward messages from **filtermodule **to IoT Hub. The Azure IoT Edge and Azure IoT Hub extensions let you see messages as they arrive at IoT Hub from your device. - In the Visual Studio Code explorer, select the IoT Edge device you want to monitor, then select **Start Monitoring Built-in Event Endpoint **. - Watch the output window in Visual Studio Code to see messages arrive at your IoT Hub. ## View changes on device To see what's happening on your device, use the commands in this section to inspect the IoT Edge runtime and modules running on your device. These commands are for your IoT Edge device, not your development machine. If you're using a virtual machine for your IoT Edge device, connect to it now. In Azure, go to the virtual machine's overview page and select **Connect **to access the secure shell connection. - View all modules deployed to your device, and check their status: ``` `iotedge list ` ``` You see four modules: the two IoT Edge runtime modules, **tempSensor **, and **filtermodule **. All four should be listed as running. - Inspect the logs for a specific module: ``` `iotedge logs ` ``` Module names are case-sensitive. The **tempSensor **and **filtermodule **logs show the messages they're processing. The **edgeAgent **module starts the other modules, so its logs have information about the deployment manifest. If a module isn't listed or isn't running, check the edgeAgent logs for errors. The **edgeHub **module manages communication between the modules and IoT Hub. If the modules are running but messages aren't arriving at your IoT Hub, check the **edgeHub **logs for errors. ## Clean up resources If you want to continue to the next recommended article, keep the resources and configurations you created and reuse them. You can also keep using the same IoT Edge device as a test device. Otherwise, to avoid charges, delete the local configuration and the Azure resources you used in this article. ### Delete Azure resources Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the wrong resource group or resources. If you created the IoT Hub inside an existing resource group that has resources that you want to keep, delete only the IoT Hub resource itself, not the resource group. To delete the resources: - Sign in to the [Azure portal ], and then select **Resource groups **. - Select the name of the resource group that contains your IoT Edge test resources. - Review the list of resources that your resource group contains. If you want to delete all of them, you can select **Delete resource group **. If you want to delete only some of them, you can select each resource to delete them individually. ## Next steps In this tutorial, you set up Visual Studio Code on your development machine and deploy your first IoT Edge module with code that filters raw data generated by your IoT Edge device. Continue to the next tutorials to learn how Azure IoT Edge lets you deploy Azure cloud services to process and analyze data at the edge. [Debug Azure IoT Edge modules ][Functions ][Stream Analytics ][Custom Vision Service ] ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-11-03 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/module-development Develop modules for Azure IoT Edge | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Develop your own IoT Edge modules Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. Azure IoT Edge modules can connect with other Azure services and contribute to your larger cloud data pipeline. This article describes how you can develop modules to communicate with the IoT Edge runtime and IoT Hub, and therefore the rest of the Azure cloud. ## IoT Edge runtime environment The IoT Edge runtime provides the infrastructure to integrate the functionality of multiple IoT Edge modules and to deploy them onto IoT Edge devices. Any program can be packaged as an IoT Edge module. To take full advantage of IoT Edge communication and management functionalities, a program running in a module can use the Azure IoT Device SDK to connect to the local IoT Edge hub. ### Packaging your program as an IoT Edge module To deploy your program on an IoT Edge device, it must first be containerized and run with a Docker-compatible engine. IoT Edge uses [Moby ], the open-source project behind Docker, as its Docker-compatible engine. The same parameters that you're used to with Docker can be passed to your IoT Edge modules. For more information, see [How to configure container create options for IoT Edge modules ]. ## Using the IoT Edge hub The IoT Edge hub provides two main functionalities: a proxy to IoT Hub and local communications. ### Connecting to IoT Edge hub from a module Connecting to the local IoT Edge hub from a module involves the same connection steps as for any clients. For more information, see [Connecting to the IoT Edge hub ]. To use IoT Edge routing over AMQP, you can use the ModuleClient from the Azure IoT SDK. Create a ModuleClient instance to connect your module to the IoT Edge hub running on the device, similar to how DeviceClient instances connect IoT devices to IoT Hub. For more information about the ModuleClient class and its communication methods, see the API reference for your preferred SDK language: [C# ], [C ], [Python ], [Java ], or [Node.js ]. ### IoT Hub primitives IoT Hub sees a module instance as similar to a device. A module instance can: - Send [device-to-cloud messages ] - Receive [direct methods ]targeted specifically at its identity - Have a module twin that's distinct and isolated from the [device twin ]and the other module twins of that device Currently, modules can't receive cloud-to-device messages or use the file upload feature. When writing a module, you can connect to the IoT Edge hub and use IoT Hub primitives as you would when using IoT Hub with a device application. The only difference between IoT Edge modules and IoT device applications is that with modules you have to refer to the module identity instead of the device identity. #### Device-to-cloud messages An IoT Edge module can send messages to the cloud via the IoT Edge hub that acts as a local broker and propagates messages to the cloud. To enable complex processing of device-to-cloud messages, an IoT Edge module can intercept and process messages sent by other modules or devices to its local IoT Edge hub. The IoT Edge module then sends new messages with processed data. Chains of IoT Edge modules can thus be created to build local processing pipelines. To send device-to-cloud telemetry messages using routes: - Use the ModuleClient class of the [Azure IoT SDK ]. Each module has *input *and *output *endpoints. - To send messages on the output endpoint of your module, use a send message method from your ModuleClient class. - To send this output endpoint to IoT Hub, set up a route in the edgeHub module of your device. To process messages using routes: - Set up a route to send messages coming from another endpoint (module or device) to the input endpoint of your module. - Listen for messages on the input endpoint of your module. Each time a new message comes back, the Azure IoT SDK triggers a callback function. - Process your message with this callback function and (optionally) send new messages in your module endpoint queue. Note To learn more about declaring a route, see [Learn how to deploy modules and establish routes in IoT Edge ] #### Twins Twins are one of the primitives provided by IoT Hub. There are JSON documents that store state information including metadata, configurations, and conditions. Each module or device has its own twin. - To get a module twin with the [Azure IoT SDK ], call the `ModuleClient.getTwin `method. - To receive a module twin patch with the Azure IoT SDK, implement a callback function and register it with the `ModuleClient.moduleTwinCallback `method from the Azure IoT SDK so that your callback function is triggered each time a twin patch comes in. #### Receive direct methods To receive a direct method with the [Azure IoT SDK ], implement a callback function and register it with the `ModuleClient.methodCallback `method from the Azure IoT SDK so that your callback function is triggered each time that a direct method comes in. ## Language and architecture support IoT Edge supports multiple operating systems, device architectures, and development languages so you can build the scenario that matches your needs. Use this section to understand your options for developing custom IoT Edge modules. You can learn more about tooling support and requirements for each language in [Prepare your development and test environment for IoT Edge ]. ### Linux For all languages in the following table, IoT Edge [supports ]development for AMD64 and most ARM64 Linux containers. There's support for Debian 11 ARM32 containers, as well. Development language Development tools C Visual Studio Code Visual Studio 2019/2022 C# Visual Studio Code Visual Studio 2019/2022 Java Visual Studio Code Node.js Visual Studio Code Python Visual Studio Code Note For cross-platform compilation, like compiling an ARM32 IoT Edge module on an AMD64 development machine, you need to configure the development machine to compile code on target device architecture matching the IoT Edge module. For more information about target device architectures, see [Tutorial: Develop Azure IoT Edge modules using Visual Studio Code ]. ### Windows We no longer support Windows containers. [IoT Edge for Linux on Windows ]is the recommended way to run IoT Edge on Windows devices. ## Module security You should develop your modules with security in mind. To learn more about securing your modules, see [Docker Engine security ]. To help improve module security, IoT Edge disables some container features by default. You can override the defaults to provide privileged capabilities to your modules if necessary. ### Allow elevated Docker permissions In the config file on an IoT Edge device, there's a parameter called `allow_elevated_docker_permissions `. When set to **true **, this flag allows the `--privileged `flag and any other capabilities that you define in the `CapAdd `field of the Docker HostConfig in the [container create options ]. Note Currently, this flag is true by default, which allows deployments to grant privileged permissions to modules. We recommend that you set this flag to false to improve device security. ### Enable CAP_CHOWN and CAP_SETUID The Docker capabilities **CAP_CHOWN **and **CAP_SETUID **are disabled by default. These capabilities can be used to write to secure files on the host device and potentially gain root access. If you need these capabilities, you can manually re-enable them using CapADD in the container create options. ## Next steps [Prepare your development and test environment for IoT Edge ] [Tutorial: Develop Azure IoT Edge modules using Visual Studio Code ] [Debug Azure IoT Edge modules using Visual Studio Code ] [Azure IoT Hub SDKs ] ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-05-16 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/how-to-update-iot-edge Update IoT Edge version on devices | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Update IoT Edge Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 IoT Edge 1.4 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. As the IoT Edge service releases new versions, update your IoT Edge devices for the latest features and security improvements. This article provides information about how to update your IoT Edge devices when a new version is available. Two logical components of an IoT Edge device need to be updated if you want to move to a newer version. - *Security subsystem *- It runs on the device, handles security-based tasks, and starts the modules when the device starts. The *security subsystem *can only be updated from the device itself. - *IoT Edge runtime *- The IoT Edge runtime is made up of the IoT Edge hub ( `edgeHub `) and IoT Edge agent ( `edgeAgent `) modules. Depending on how you structure your deployment, the *runtime *can be updated from either the device or remotely. ## How to update Use the sections of this article to update both the security subsystem and runtime containers on a device. ### Patch releases When you upgrade between *patch *releases, for example 1.5.1 to 1.5.2, the update order isn't important. You can upgrade the security subsystem or the runtime containers before or after the other. To update between patch releases: - [Update the security subsystem ] - [Update the runtime containers ] - [Verify versions match ] You can [troubleshoot ]the upgrade process at any time. ### Major or minor releases When you upgrade between major or minor releases, for example from 1.4 to 1.5, update both the security subsystem and the runtime containers. Before a release, we test the security subsystem and the runtime container version combination. To update between major or minor product releases: - On the device, stop IoT Edge using the command `sudo systemctl stop iotedge `and [uninstall ]. - On the device, upgrade your container engine, either [Docker ]or [Moby ]. - On the device, [install IoT Edge ]. If you're importing an old configuration using `iotedge config import `, then modify the [agent.config] image of the generated `/etc/aziot/config.toml `file to use the 1.5 image for edgeAgent. For more information, see [Configure IoT Edge device settings ]. - In IoT Hub, [update the module deployment ]to reference the newest system modules. - On the device, start the IoT Edge using `sudo iotedge config apply `. You can [troubleshoot ]the upgrade process at any time. ## Update the security subsystem The IoT Edge security subsystem includes a set of native components that need to be updated using the package manager on the IoT Edge device. Check the version of the security subsystem running on your device by using the command `iotedge version `. If you're using IoT Edge for Linux on Windows, you need to SSH into the Linux virtual machine to check the version. - [Ubuntu / Debian ] - [Red Hat Enterprise Linux ] - [Linux on Windows ] - [Windows ] On Linux x64 devices, use `apt-get `or your appropriate package manager to update the security subsystem to the latest version. Update `apt `: ``` `sudo apt-get update ` ``` Note For instructions to get the latest repository configuration from Microsoft see the preliminary steps to [Install IoT Edge ]. Check to see which versions of IoT Edge are available: ``` `apt list -a aziot-edge ` ``` Update IoT Edge: ``` `sudo apt-get install aziot-edge ` ``` Running `apt-get install aziot-edge `upgrades the security subsystem and installs the [identity service ], `aziot-identity-service `, as a required dependency. Check to see which versions of IoT Edge are available. ``` `yum list aziot-edge ` ``` If you want to update to the most recent version of IoT Edge, use the following command, which also updates the [identity service ]to the latest version: ``` `sudo yum install aziot-edge ` ``` For information about IoT Edge for Linux on Windows updates, see [EFLOW Updates ]. Note Currently, there is no support for IoT Edge running on Windows devices in Windows containers. Use a Linux container to run IoT Edge on Windows. Then, reapply configuration to ensure system is fully updated. ``` `sudo iotedge config apply ` ``` ## Update the runtime containers The way that you update the IoT Edge agent and IoT Edge hub containers depends on whether you use rolling tags (like 1.5) or specific tags (like 1.5.1) in your deployment. Check the version of the IoT Edge agent and IoT Edge hub modules currently on your device using the commands `iotedge logs edgeAgent `or `iotedge logs edgeHub `. If you're using IoT Edge for Linux on Windows, you need to SSH into the Linux virtual machine to check the runtime module versions. [] ### Understand IoT Edge tags The IoT Edge agent and IoT Edge hub images are tagged with the IoT Edge version that they're associated with. There are two different ways to use tags with the runtime images: - **Rolling tags **- Use only the first two values of the version number to get the latest image that matches those digits. For example, 1.5 is updated whenever there's a new release to point to the latest 1.5.x version. If the container runtime on your IoT Edge device pulls the image again, the runtime modules are updated to the latest version. Deployments from the Azure portal default to rolling tags. *This approach is suggested for development purposes. * - **Specific tags **- Use all three values of the version number to explicitly set the image version. For example, 1.5.0 won't change after its initial release. You can declare a new version number in the deployment manifest when you're ready to update. *This approach is suggested for production purposes. * ### Update a rolling tag image If you use rolling tags in your deployment (for example, mcr.microsoft.com/azureiotedge-hub: **1.5 **) then you need to force the container runtime on your device to pull the latest version of the image. Delete the local version of the image from your IoT Edge device. On Windows machines, uninstalling the security subsystem also removes the runtime images, so you don't need to take this step again. ``` `docker rmi mcr.microsoft.com/azureiotedge-hub:1.5 docker rmi mcr.microsoft.com/azureiotedge-agent:1.5 ` ``` You may need to use the force `-f `flag to remove the images. The IoT Edge service pulls the latest versions of the runtime images and automatically starts them on your device again. ### Update a specific tag image If you use specific tags in your deployment (for example, mcr.microsoft.com/azureiotedge-hub: **1.5 **) then all you need to do is update the tag in your deployment manifest and apply the changes to your device. - In the IoT Hub in the Azure portal, select your IoT Edge device, and select **Set Modules **. - On the **Modules **tab, select **Runtime Settings **. - In **Runtime Settings **, update the **Image URI **value in the **Edge Agent **section with the desired version. For example, `mcr.microsoft.com/azureiotedge-agent:1.5 `Don't select **Apply **yet. - Select the **Edge Hub **tab and update the **Image URI **value with the same desired version. For example, `mcr.microsoft.com/azureiotedge-hub:1.5 `. - Select **Apply **to save changes. - Select **Review + create **, review the deployment as seen in the JSON file, and select **Create **. ## Update partner module URIs If you use partner modules, update your module deployments with image URIs provided by the partner. Contact the [IoT Edge module publisher ]to obtain the updated container image URI. Update your device configurations with the new image URI provided by the publisher. - Sign in to the [Azure portal ]and navigate to your IoT Hub. - On the left pane, select **Devices **under the **Device management **menu. - Select the IoT Edge device that uses the partner module from the list. - On the upper bar, select **Set Modules **. - Choose the IoT Edge partner module that you want to update with the new image URI. - Update the **Image URI **value with the new image URI provided by the publisher. - Select **Apply **to save changes. - Select **Review + create **, review the deployment as seen in the JSON file, and select **Create **. ## Verify versions match - On your device, use `iotedge version `to check the security subsystem version. The output includes the major, minor, and revision version numbers. For example, *iotedge 1.5.13 *. - In your device deployment runtime settings, verify the *edgeHub *and *edgeAgent *image URI versions match the major and minor version of the security subsystem. If the security subsystem version is 1.5.15, the image versions would be 1.5. For example, *mcr.microsoft.com/azureiotedge-hub:1.5 *and *mcr.microsoft.com/azureiotedge-agent:1.5 *. Note Update the IoT Edge security subsystem and runtime containers to the same supported release version. While mismatched versions are supported, we haven't tested all version combinations. To find the latest version of Azure IoT Edge, see [Azure IoT Edge releases ]. ## Troubleshooting You can view logs of your system at any time by running the following commands from your device. - Start troubleshooting using the [check ]command. It runs a collection of configuration and connectivity tests for common issues. ``` `sudo iotedge check --verbose ` ``` - To view the status of the IoT Edge system, run: ``` `sudo iotedge system status ` ``` - To view host component logs, run: ``` `sudo iotedge system logs ` ``` - To check for recurring issues reported with edgeAgent and edgeHub, run: Be sure to replace ` `with your own module name. If there are no issues, you see no output. ``` `sudo iotedge logs ` ``` For more information, see [Troubleshoot your IoT Edge device ]. ## Next steps View the latest [Azure IoT Edge releases ]. Stay up-to-date with recent updates and announcements in the [Internet of Things blog ] ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-01-23 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/how-to-provision-single-device-linux-symmetric Create IoT Edge device on Linux using symmetric keys - Azure IoT Edge | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Create and provision an IoT Edge device on Linux using symmetric keys Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. This article provides end-to-end instructions for registering and provisioning a Linux IoT Edge device that includes installing IoT Edge. Each device that connects to an [IoT hub ]has a device ID that's used to track [cloud-to-device ]or [device-to-cloud ]communications. You configure a device with its connection information, which includes: - IoT hub hostname - Device ID - Authentication details to connect to IoT Hub The steps in this article walk through a process called *manual provisioning *, where you connect a single device to its IoT hub. For manual provisioning, you have two options for authenticating IoT Edge devices: - **Symmetric keys **: When you create a new device identity in IoT Hub, the service creates two keys. You place one of the keys on the device, and it presents the key to IoT Hub when authenticating. This authentication method is faster to get started, but not as secure. - **X.509 self-signed **: You create two X.509 identity certificates and place them on the device. When you create a new device identity in IoT Hub, you provide thumbprints from both certificates. When the device authenticates to IoT Hub, it presents one certificate and IoT Hub verifies that the certificate matches its thumbprint. This authentication method is more secure and recommended for production scenarios. This article covers using symmetric keys as your authentication method. If you want to use X.509 certificates, see [Create and provision an IoT Edge device on Linux using X.509 certificates ]. Note If you have many devices to set up and don't want to manually provision each one, use one of the following articles to learn how IoT Edge works with the IoT Hub device provisioning service: - [Create and provision IoT Edge devices at scale on Linux using X.509 certificates ] - [Create and provision IoT Edge devices at scale with a TPM on Linux ] - [Create and provision IoT Edge devices at scale on Linux using symmetric keys ] ## Prerequisites This article shows how to register your IoT Edge device and install IoT Edge (also called IoT Edge runtime) on your device. Make sure you have the device management tool of your choice, for example Azure CLI, and device requirements before you register and install your device. ### Device management tools You can use the **Azure portal **, **Visual Studio Code **, or **Azure CLI **for the steps to register your device. Each utility has its own prerequisites or might need to be installed: - [Portal ] - [Visual Studio Code ] - [Azure CLI ] A free or standard [IoT hub ]in your Azure subscription. - A free or standard [IoT hub ]in your Azure subscription - [Visual Studio Code ] - [Azure IoT Edge ]extension. The *Azure IoT Edge tools for Visual Studio Code *extension is in [maintenance mode ]. - [Azure IoT Hub ]extension - A free or standard [IoT hub ]in your Azure subscription - [Azure CLI ]in your environment At a minimum, your Azure CLI version must be 2.0.70 or newer. Use `az --version `to validate. This version supports `az `extension commands and introduces the Knack command framework. ### Device requirements An X64, ARM32, or ARM64 Linux device. Microsoft publishes installation packages for various operating systems. For the latest information about which operating systems are currently supported for production scenarios, see [Azure IoT Edge supported platforms ]. ### Visual Studio Code extensions If you're using Visual Studio Code, there are helpful Azure IoT extensions that make the device creation and management process easier. Install both the Azure IoT Edge and Azure IoT Hub extensions: - [Azure IoT Edge ]. The *Azure IoT Edge tools for Visual Studio Code *extension is in [maintenance mode ]. - [Azure IoT Hub ] ## Register your device You can use the **Azure portal **, **Visual Studio Code **, or **Azure CLI **to register your device, depending on your preference. - [Portal ] - [Visual Studio Code ] - [Azure CLI ] In your IoT hub in the Azure portal, IoT Edge devices are created and managed separately from IoT devices that aren't edge enabled. - Sign in to the [Azure portal ]and navigate to your IoT hub. - In the left pane, select **Devices **from the menu, then select **Add Device **. - On the **Create a device **page, provide the following information: - Create a descriptive Device ID, for example `my-edge-device-1 `(all lowercase). Copy this Device ID, as you use it later. - Check the **IoT Edge Device **checkbox. - Select **Symmetric key **as the authentication type. - Use the default settings to autogenerate authentication keys, which connect the new device to your hub. - Select **Save **. You should see your new device listed in your IoT hub. ### Sign in to Azure You can use the Azure IoT extensions for Visual Studio Code to perform operations with your IoT hub. Make sure you install the Azure IoT extension prerequisites. Once Azure IoT Edge and Azure IoT Hub extensions are installed, you notice an Azure icon gets added to the left icon menu. You can sign in to your Azure account through Visual Studio Code by selecting the Azure icon and then select **Sign in to Azure **. ### Register a new device with Visual Studio Code Registering a new device is akin to creating an IoT Edge device in the Azure portal. This virtual device is one of the *twins *, whereas the real world device is the other twin. Visual Studio Code can set up this virtual device for you through the following steps. - In the Visual Studio Code Explorer menu, expand the **Azure IoT Hub **section. - Select on the **... **in the **Azure IoT Hub **section header. If you don't see the ellipsis, select or hover over the header. - Select **Create IoT Edge Device **. - In the text box that opens, give your device an ID, for example `my-edge-device-1 `(all lowercase), then press enter. In the output console of Visual Studio Code, you see the result of the command: a JSON printout. The device information includes the **deviceId **that you provided and generates a **connectionString **that you can use to connect your physical device to your IoT hub. The output console also shows your keys and other device identifying information. You can now see your device listed under the **Azure IoT Hub **> **Devices **section of the Explorer menu. Note If your device isn't listed, you might need to choose your IoT hub from the link **Select IoT Hub **provided under **Azure IoT Hub **and then follow the prompts. The prompts ask you to choose your subscription first and then your IoT hub. This process lets Visual Studio Code know about your IoT hub (and all devices in it). Refresh Visual Studio Code and your device should show. Use the [az iot hub device-identity create ]command to create a new device identity in your IoT hub. Replace `device_id_here `with your own new and unique device ID, for example `my-edge-device-1 `(all lowercase). Replace `hub_name_here `with your existing IoT hub. This command includes three parameters: - `--device-id `or `-d `: Provide a descriptive name that's unique within your IoT hub. - `--hub-name `or `-n `: Provide the name of your IoT hub. - `--edge-enabled `or `--ee `: Declare that the device is an IoT Edge device. ``` `az iot hub device-identity create --device-id device_id_here --hub-name hub_name_here --edge-enabled ` ``` If your CLI says **The command requires the extension azure-iot. Do you want to install it now? **, then type `Y `and press `Enter `to initiate the download to create your device. Now that you have a device registered in IoT Hub, you can retrieve provisioning information used to complete the installation and provisioning of the [IoT Edge runtime ]in the next step. ## View registered devices and retrieve provisioning information Devices that use symmetric key authentication need their connection strings to complete installation and provisioning of the IoT Edge runtime. The connection string gets generated for your IoT Edge device when you create the device. For Visual Studio Code and Azure CLI, the connection string is in the JSON output. If you use the Azure portal to create your device, you can find the connection string from the device itself. When you select your device in your IoT hub, it's listed as `Primary connection string `on the device page. - [Portal ] - [Visual Studio Code ] - [Azure CLI ] The edge-enabled devices that connect to your IoT hub are listed on the **Devices **page of your IoT hub. If you have multiple devices, you can filter the list by selecting the type **Iot Edge Devices **, then select **Apply **. When you're ready to set up your device, you need the connection string that links your physical device with its identity in the IoT hub. Devices that authenticate with symmetric keys have their connection strings available to copy in the portal. To find your connection string in the portal: - From the **Devices **page, select the IoT Edge device ID from the list. - Copy the value of either **Primary Connection String **or **Secondary Connection String **. Either key works. All the devices that connect to your IoT hub are listed in the **Azure IoT Hub **section of the Visual Studio Code Explorer. IoT Edge devices are distinguishable from non-Edge devices because they have a different icon and you see the **$edgeAgent **and **$edgeHub **modules are deployed to each IoT Edge device. When you're ready to set up your device, you need the connection string that links your physical device with its identity in the IoT hub. Here's how to get your connection string from Visual Studio Code. - Right-click on the ID (name) of your device in the **Azure IoT Hub **section. - Select **Copy Device Connection String **. The connection string is copied to your clipboard. You can also select **Get Device Info **from the right-click menu to see all the device info, including the connection string, in the output window. To see all devices in your IoT hub, use the [az iot hub device-identity list ]command. Replace `hub_name_here `with your own IoT hub name. ``` `az iot hub device-identity list --hub-name hub_name_here ` ``` Any device that is registered as an IoT Edge device has the property **capabilities.iotEdge **set to **true **. You see a lot of other metadata as JSON output as well, including your device IDs. When you're ready to set up your device, you need its connection string that links your physical device with its identity in the IoT hub. Use the following [az iot hub device-identity connection-string show ]command to return the connection string for a single device. Replace `[device_id] `and `[hub_name] `with your own values. The value for the `device-identity `parameter is case-sensitive. ``` `az iot hub device-identity connection-string show --device-id [device_id] --hub-name [hub_name] ` ``` You should see JSON output in the console, similar to the following example: ``` `{ "connectionString": "HostName=[hub_name].azure-devices.net;DeviceId=[device_id];SharedAccessKey=[device_key]" } ` ``` Tip The `connection-string show `command was introduced in version 0.9.8 of the Azure IoT extension, replacing the deprecated `show-connection-string `command. If you get an error running this command, make sure your extension version is updated to 0.9.8 or later. For more information and the latest updates, see [Microsoft Azure IoT extension for Azure CLI ]. When copying the connection string to use on a device, don't include the quotation marks around the connection string. ## 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 (optional) ]. - [Ubuntu ] - [Debian ] - [Red Hat Enterprise Linux ] - [Ubuntu Core snaps ] 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 ` ``` Installing with APT can be done with a few commands. Open a terminal and run the following commands: - **12 - Bookworm (arm32v7) **: ``` `curl https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb > ./packages-microsoft-prod.deb sudo apt install ./packages-microsoft-prod.deb ` ``` - **11 - Bullseye (arm32v7) **: ``` `curl https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb > ./packages-microsoft-prod.deb sudo apt install ./packages-microsoft-prod.deb ` ``` Tip If you gave the "root" account a password during the OS install, you don't need 'sudo' and can run the previous command by starting with 'apt'. Installing can be done with a few commands. Open a terminal and run the following commands: - **9.x (amd64) **: ``` `wget https://packages.microsoft.com/config/rhel/9.0/packages-microsoft-prod.rpm -O packages-microsoft-prod.rpm sudo yum localinstall packages-microsoft-prod.rpm rm packages-microsoft-prod.rpm ` ``` - **8.x (amd64) **: ``` `wget https://packages.microsoft.com/config/rhel/8/packages-microsoft-prod.rpm -O packages-microsoft-prod.rpm sudo yum localinstall packages-microsoft-prod.rpm rm packages-microsoft-prod.rpm ` ``` You install IoT Edge runtime from the snap store in a later step. Continue to the next section. 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 before 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're using Ubuntu Core snaps, the Docker snap is serviced by Canonical and supported for production scenarios. - [Ubuntu ] - [Debian ] - [Red Hat Enterprise Linux ] - [Ubuntu Core snaps ] Install the Moby engine. ``` `sudo apt-get update; \ sudo apt-get install moby-engine ` ``` Install the Moby engine. ``` `sudo apt-get update; \ sudo apt-get install moby-engine ` ``` Install the Moby engine and CLI. ``` `sudo yum install moby-engine moby-cli ` ``` Tip If you get errors when you install the Moby container engine, verify your Linux kernel for Moby compatibility. Some embedded device manufacturers ship device images that contain custom Linux kernels without the features required for container engine compatibility. Run the following command, which uses the [check-config script ]provided by Moby, to check your kernel configuration: ``` `curl -ssl https://raw.githubusercontent.com/moby/moby/master/contrib/check-config.sh -o check-config.sh chmod +x check-config.sh ./check-config.sh ` ``` In the output of the script, check that all items under `Generally Necessary `and `Network Drivers `are enabled. If you're missing features, enable them by rebuilding your kernel from source and selecting the associated modules for inclusion in the appropriate kernel .config. Similarly, if you're using a kernel configuration generator like `defconfig `or `menuconfig `, find and enable the respective features and rebuild your kernel accordingly. After you deploy your newly modified kernel, run the check-config script again to verify that all the required features were successfully enabled. IoT Edge has dependencies on Docker and IoT Identity Service. Install the dependencies using the following commands: ``` `sudo snap install docker sudo snap install azure-iot-identity ` ``` The Docker snap is serviced by Canonical and supported for production scenarios. By default, the container engine doesn't set container log size limits. Over time, this situation 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 [Prepare to deploy your IoT Edge solution in production ]. The following steps show you how to configure your container to use [`local `logging driver ]as the logging mechanism. - [Ubuntu / Debian / RHEL ] - [Ubuntu Core snaps ] - Create or edit the existing Docker [daemon's config file ] ``` `sudo nano /etc/docker/daemon.json ` ``` - Set the default logging driver to the `local `logging driver as shown in the example. ``` `{ "log-driver": "local" } ` ``` - Restart the container engine for the changes to take effect. ``` `sudo systemctl restart docker ` ``` Currently, the `local `logging driver setting isn't supported for the Docker snap. ### 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 [Azure 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 prerelease 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 IoT Edge ]. Later versions are sufficiently different from previous versions of IoT Edge that specific steps are necessary to upgrade. - [Ubuntu ] - [Debian ] - [Red Hat Enterprise Linux ] - [Ubuntu Core snaps ] 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 ` ``` Install the latest version of IoT Edge and the IoT identity service package (if you're not already [up-to-date ]): ``` `sudo apt-get update; \ sudo apt-get install aziot-edge ` ``` Install the latest version of IoT Edge and the IoT identity service package (if you're not already [up-to-date ]): ``` `sudo yum install aziot-edge ` ``` Install IoT Edge from the snap store: ``` `sudo snap install azure-iot-edge ` ``` ### Connect snaps By default, snaps are dependency-free, untrusted, and strictly confined. Hence, snaps must be connected to other snaps and system resources after installation. Use the following commands to connect the IoT Identity Service and IoT Edge snaps to each other and to system resources. To get started, snaps need to be manually connected. For production deployments, they can be configured to automatically connect to reduce the provisioning workload. ``` `#------------------------ # IoT Identity Service #------------------------ # Connect the Identity Service snap to the logging system # and grant permission to query system info sudo snap connect azure-iot-identity:log-observe sudo snap connect azure-iot-identity:mount-observe sudo snap connect azure-iot-identity:system-observe sudo snap connect azure-iot-identity:hostname-control # If using a TPM, enable TPM access sudo snap connect azure-iot-identity:tpm #------------ # IoT Edge #------------ # Connect to your /home directory to enable writing support bundles sudo snap connect azure-iot-edge:home # Connect to logging and grant permission to query system info sudo snap connect azure-iot-edge:log-observe sudo snap connect azure-iot-edge:mount-observe sudo snap connect azure-iot-edge:system-observe sudo snap connect azure-iot-edge:hostname-control # Allow IoT Edge to connect to the /var/run/iotedge folder and use sockets sudo snap connect azure-iot-edge:run-iotedge # Connect IoT Edge to Docker sudo snap connect azure-iot-edge:docker docker:docker-daemon ` ``` ## Provision the device with its cloud identity Now that the container engine and the IoT Edge runtime are installed on your device, you're ready to set up the device with its cloud identity and authentication information. - [Ubuntu / Debian / RHEL ] - [Ubuntu Core snaps ] You can configure your IoT Edge device with symmetric key authentication using the following command: ``` `sudo iotedge config mp --connection-string 'PASTE_DEVICE_CONNECTION_STRING_HERE' ` ``` This `iotedge config mp `command creates a configuration file on the device and enters your connection string in the configuration file. - Apply the configuration changes. ``` `sudo iotedge config apply ` ``` - To view the configuration file, you can open it: ``` `sudo nano /etc/aziot/config.toml ` ``` - Create a **config.toml **file in your home directory and configure your IoT Edge device with a symmetric key authentication for the snap. ``` `sudo nano ~/config.toml ` ``` - You can manually provision with a connection string using the following provisioning settings: ``` `[provisioning] source = "manual" connection_string = "REPLACE_WITH_DEVICE_CONNECTION_STRING" ` ``` For more information about provisioning configuration settings, see [Configure IoT Edge device settings ]. - Set the configuration for IoT Edge and the Identity Service using the following command: ``` `sudo snap set azure-iot-edge raw-config="$(cat ~/config.toml)" ` ``` ## Deploy modules To deploy your IoT Edge modules, go to your IoT hub in the Azure portal, then: - Select **Devices **from the IoT Hub menu. - Select your device to open its page. - Select the **Set Modules **tab. - Since we want to deploy the IoT Edge default modules (edgeAgent and edgeHub), we don't need to add any modules to this pane, so select **Review + create **at the bottom. - You see the JSON confirmation of your modules. Select **Create **to deploy the modules. For more information, see [Deploy a module ]. ## Verify successful configuration Verify that the runtime was successfully installed and configured on your IoT Edge device. Tip You need elevated privileges to run `iotedge `commands. Once you sign out of your machine and sign back in the first time after installing the IoT Edge runtime, your permissions are automatically updated. Until then, use `sudo `in front of the commands. - Check to see that the IoT Edge system service is running. ``` `sudo iotedge system status ` ``` A successful status response shows the `aziot `services as running or ready. - If you need to troubleshoot the service, retrieve the service logs. ``` `sudo iotedge system logs ` ``` - Use the `check `tool to verify configuration and connection status of the device. ``` `sudo iotedge check ` ``` You can expect a range of responses that might include **OK **(green), **Warning **(yellow), or **Error **(red). For troubleshooting common errors, see [Solutions to common issues for Azure IoT Edge ]. [] Tip Always use `sudo `to run the check tool, even after your permissions are updated. The tool needs elevated privileges to access the config file to verify configuration status. Note On a newly provisioned device, you might see an error related to IoT Edge Hub: **× production readiness: Edge Hub's storage directory is persisted on the host filesystem - Error ****Could not check current state of edgeHub container ** This error is expected on a newly provisioned device because the IoT Edge Hub module isn't yet running. Be sure your IoT Edge modules were deployed in the previous steps. Deployment resolves this error. Alternatively, you might see a status code as `417 -- The device's deployment configuration is not set `. Once your modules are deployed, this status changes. - When the service starts for the first time, you should only see the **edgeAgent **module running. The edgeAgent module runs by default and helps to install and start any other modules that you deploy to your device. Check that your device and modules are deployed and running, by viewing your device page in the Azure portal. [] Once your modules are deployed and running, list them in your device or virtual machine with the following command: ``` `sudo iotedge list ` ``` ## Offline or specific version installation (optional) The steps in this section are for scenarios not covered by the standard installation steps. These scenarios might include: - Installing IoT Edge while offline - Installing a release candidate version Use the steps in this section if you want to install a [specific version of the Azure IoT Edge runtime ]that isn't available through your package manager. The Microsoft package list only contains a limited set of recent versions and their subversions, so these steps are for anyone who wants to install an older version or a release candidate version. If you're using Ubuntu snaps, you can download a snap and install it offline. For more information, see [Download snaps and install offline ]. Using curl commands, you can target the component files directly from the IoT Edge GitHub repository. - Navigate to the [Azure IoT Edge releases ], and find the release version that you want to target. - Expand the **Assets **section for that version. - Every release should have new files for IoT Edge and the identity service. If you're going to install IoT Edge on an offline device, download these files ahead of time. Otherwise, use the following commands to update those components. - Find the **aziot-identity-service **file that matches your IoT Edge device's architecture. Right-click on the file link and copy the link address. - Use the copied link in the following command to install that version of the identity service: - [Ubuntu / Debian ] - [Red Hat Enterprise Linux ] - [Ubuntu Core snaps ] ``` `curl -L -o aziot-identity-service.deb && sudo apt-get install ./aziot-identity-service.deb ` ``` ``` `curl -L -o aziot-identity-service.rpm && sudo yum localinstall ./aziot-identity-service.rpm ` ``` If you're using Ubuntu snaps, you can download a snap package and install it offline. For more information, see [Download snaps and install offline ]. - Find the **aziot-edge **file that matches your IoT Edge device's architecture. Right-click on the file link and copy the link address. - Use the copied link in the following command to install that version of IoT Edge. - [Ubuntu / Debian ] - [Red Hat Enterprise Linux ] - [Ubuntu Core snaps ] ``` `curl -L -o aziot-edge.deb && sudo apt-get install ./aziot-edge.deb ` ``` ``` `curl -L -o aziot-edge.rpm && sudo yum localinstall ./aziot-edge.rpm ` ``` If you're using Ubuntu snaps, you can download a snap package and install it offline. For more information, see [Download snaps and install offline ]. ## Uninstall IoT Edge If you want to remove the IoT Edge installation from your device, use the following commands. Remove the IoT Edge runtime. - [Ubuntu / Debian ] - [Red Hat Enterprise Linux ] - [Ubuntu Core snaps ] ``` `sudo apt-get autoremove --purge aziot-edge ` ``` Leave out the `--purge `flag if you plan to reinstall IoT Edge and use the same configuration information in the future. The `--purge `flag deletes all the files associated with IoT Edge, including your configuration files. ``` `sudo yum remove aziot-edge ` ``` Remove the IoT Edge runtime: ``` `sudo snap remove azure-iot-edge ` ``` Remove Azure Identity Service: ``` `sudo snap remove azure-iot-identity ` ``` When the IoT Edge runtime is removed, any containers that it created are stopped but still exist on your device. View all containers to see which ones remain. ``` `sudo docker ps -a ` ``` Delete the containers from your device, including the two runtime containers. ``` `sudo docker rm -f ` ``` Finally, remove the container runtime from your device. - [Ubuntu / Debian ] - [Red Hat Enterprise Linux ] - [Ubuntu Core snaps ] ``` `sudo apt-get autoremove --purge moby-engine ` ``` ``` `sudo yum remove moby-cli sudo yum remove moby-engine ` ``` ``` `sudo snap remove docker ` ``` ## Next steps Continue to [deploy IoT Edge modules ]to learn how to deploy modules onto your device. ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-04-29 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/development-environment Azure IoT Edge development environment | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Prepare your development and test environment for IoT Edge Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. IoT Edge moves your existing business logic to devices operating at the edge. To prepare your applications and workloads to run as [IoT Edge modules ], you need to build them as containers. This article provides guidance around how to configure your development environment so that you can successfully create an IoT Edge solution. Once you have your development environment set up, you can learn how to [develop your own IoT Edge modules ]. In any IoT Edge solution, there are at least two machines to consider: the IoT Edge device (or devices) that runs the IoT Edge module, and the development machine that builds, tests, and deploys modules. This article focuses primarily on the development machine. For testing purposes, the two machines can be the same. You can run IoT Edge on your development machine and deploy modules to it. ## Operating system IoT Edge runs on a specific set of [supported operating systems ]. When developing for IoT Edge, you can use most operating systems that can run a container engine. The container engine is a requirement on the development machine to build your modules as containers and push them to a container registry. If your development machine can't run IoT Edge, skip to the [Testing tools ]section of this article to learn how to test and debug locally. The operating systems of the development machine and IoT Edge devices don't need to match. However, the container operating system must be consistent with the development machine and the IoT Edge device. For example, you can develop modules on a Windows machine and deploy them to a Linux device. The Windows machine needs to run Linux containers to build the modules for the Linux device. ## Container engine The central concept of IoT Edge is that you can remotely deploy your business and cloud logic to devices by packaging it into containers. To build containers, you need a container engine on your development machine. Any container engine compatible with the Open Container Initiative, like Docker, is capable of building IoT Edge module images. Moby is the supported container engine for IoT Edge devices in production. If you're using Ubuntu Core snaps, the Docker snap is serviced by Canonical and supported for production scenarios. ## Development tools The Azure [IoT Edge Dev Tool ]is a command line tool to develop and test IoT Edge modules. You can create new IoT Edge scenarios, build module images, run modules in a simulator, and monitor messages sent to IoT Hub. The *iotedgedev *tool is the recommended tool for developing IoT Edge modules. Both Visual Studio and Visual Studio Code have add-on extensions to help develop IoT Edge solutions. These extensions provide language-specific templates to help create and deploy new IoT Edge scenarios. The Azure IoT Edge extensions for Visual Studio and Visual Studio Code help you code, build, deploy, and debug your IoT Edge solutions. You can create an entire IoT Edge solution that contains multiple modules, and the extensions automatically update a deployment manifest template with each new module addition. The extensions also enable management of IoT devices from within Visual Studio or Visual Studio Code. You can deploy modules to a device, monitor the status, and view messages as they arrive at IoT Hub. Finally, both extensions use the IoT EdgeHub Dev Tool to enable local running and debugging of modules on your development machine. ### IoT Edge Dev Tool The Azure IoT Edge Dev Tool simplifies IoT Edge development with command-line abilities. This tool provides CLI commands to develop, debug, and test modules. The IoT Edge Dev Tool works with your development system, whether you manually installed the dependencies on your machine or are using the prebuilt [IoT Edge Dev Container ]to run the *iotedgedev *tool in a container. For more information and to get started, see [IoT Edge Dev Tool wiki ]. ### Visual Studio Code extension The Azure IoT Edge extension for Visual Studio Code provides IoT Edge module templates built on programming languages including C, C#, Java, Node.js, and Python. Templates for Azure functions in C# are also included. Important The Azure IoT Edge Visual Studio Code extension is in [maintenance mode ]. The *iotedgedev *tool is the recommended tool for developing IoT Edge modules. For more information and to download, see [Azure IoT Edge for Visual Studio Code ]. In addition to the IoT Edge extensions, you might find it helpful to install other extensions for developing. For example, you can use [Docker for Visual Studio Code ]to manage your images, containers, and registries. Additionally, all the major supported languages have extensions for Visual Studio Code that can help when you're developing modules. The [Azure IoT Hub ]extension is useful as a companion for the Azure IoT Edge extension. ### Visual Studio 2017/2019 extension The Azure IoT Edge tools for Visual Studio provide an IoT Edge module template built on C# and C. Important The Azure IoT Edge Visual Studio extensions are in maintenance mode. The *iotedgedev *tool is the recommended tool for developing IoT Edge modules. For more information and to download, see [Azure IoT Edge Tools for Visual Studio 2017 ]or [Azure IoT Edge Tools for Visual Studio 2019 ]. ## Testing tools Several testing tools exist to help you simulate IoT Edge devices or debug modules more efficiently. The following table shows a high-level comparison between the tools and the following individual sections describe each tool more specifically. Only the IoT Edge runtime is supported for production deployments, but the following tools allow you to simulate or easily create IoT Edge devices for development and testing purposes. These tools aren't mutually exclusive, but can work together for a complete development experience. Tool Also known as Supported platforms Best for IoT EdgeHub Dev Tool iotedgehubdev Windows, Linux, macOS Simulating a device to debug modules. IoT Edge Dev Container iotedgedev Windows, Linux, macOS Developing without installing dependencies. ### IoT EdgeHub Dev Tool The Azure IoT EdgeHub Dev Tool provides a local development and debug experience. The tool helps start IoT Edge modules without the IoT Edge runtime so that you can create, develop, test, run, and debug IoT Edge modules and solutions locally. You don't have to push images to a container registry and deploy them to a device for testing. The IoT EdgeHub Dev Tool was designed to work in tandem with the Visual Studio and Visual Studio Code extensions, and with the IoT Edge Dev Tool. The dev tool supports inner loop development and outer loop testing, so it integrates with other DevOps tools too. Important The IoT EdgeHub Dev Tool is in [maintenance mode ]. Consider using a [Linux virtual machine with IoT Edge runtime installed ], physical device, or [EFLOW ]. For more information and to install, see [Azure IoT EdgeHub Dev Tool ]. ### IoT Edge Dev Container The Azure IoT Edge Dev Container is a Docker container that has all the dependencies that you need for IoT Edge development. This container makes it easy to get started with whichever language you want to develop in, including C#, Python, Node.js, and Java. All you need to install is a container engine, like Docker or Moby, to pull the container to your development machine. For more information, see [Azure IoT Edge Dev Container ]. ## DevOps tools When you're ready to develop at-scale solutions for extensive production scenarios, take advantage of modern DevOps principles including automation, monitoring, and streamlined software engineering processes. IoT Edge has extensions to support DevOps tools including Azure DevOps, Azure DevOps Projects, and Jenkins. If you want to customize an existing pipeline or use a different DevOps tool like CircleCI or TravisCI, you can do so with the CLI features included in the IoT Edge Dev Tool. For more information, guidance, and examples, see the following pages: - [Continuous integration and continuous deployment to Azure IoT Edge devices ] - [IoT Edge DevOps GitHub repo ] ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-05-09 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/offline-capabilities Operate Azure IoT Edge devices offline | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Understand extended offline capabilities for IoT Edge devices, modules, and child devices Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. Azure IoT Edge lets your IoT Edge devices work offline for extended periods and lets downstream devices work offline too. After an IoT Edge device connects to IoT Hub once, the device and any downstream device can keep working with intermittent or no internet connection. ## How it works When an IoT Edge device goes into offline mode, the IoT Edge hub takes on three roles: - Stores any messages that goes upstream and saves them until the device reconnects. - Acts on behalf of IoT Hub to authenticate modules and downstream devices so they can keep operating. - Enables communication between downstream devices that normally go through IoT Hub. The following example shows how an IoT Edge scenario operates in offline mode: - **Configure devices ** IoT Edge devices have offline capabilities enabled by default. To extend this capability to other devices, configure downstream devices to trust their assigned parent device and route device-to-cloud communications through the parent as a gateway. - **Sync with IoT Hub ** After you install the IoT Edge runtime, make sure the IoT Edge device is online at least once to sync with IoT Hub. During this sync, the IoT Edge device gets details about any downstream devices assigned to it. The IoT Edge device also securely updates its local cache to enable offline operations and gets settings for local storage of telemetry messages. - **Go offline ** While disconnected from IoT Hub, the IoT Edge device, its deployed modules, and any downstream devices can keep operating indefinitely. Modules and downstream devices can start and restart by authenticating with the IoT Edge hub while offline. Device telemetry bound upstream to IoT Hub is stored locally. Communication between modules or between downstream devices is maintained through direct methods or messages. - **Reconnect and resync with IoT Hub ** When the connection with IoT Hub is restored, the IoT Edge device syncs again. Locally stored messages are delivered to IoT Hub right away, but delivery depends on the speed of the connection, IoT Hub latency, and related factors. Messages are delivered in the same order in which they were stored. Any differences between the desired and reported properties of the modules and devices are reconciled. The IoT Edge device updates any changes to its set of assigned downstream devices. ## Restrictions and limits IoT Edge devices and their assigned downstream devices can function indefinitely offline after the initial, one-time sync. However, message storage depends on the [time to live (TTL) setting ]and available disk space. A device's *EdgeAgent *updates its reported properties whenever deployment status changes, like a new or failed deployment. When a device is offline, the *EdgeAgent *can't report status to the Azure portal. Therefore, the device status in the Azure portal can remain **200 OK **when the IoT Edge device has no internet connectivity. ## Set up parent and child devices By default, a parent device can have up to 100 children. Change this limit by setting the **MaxConnectedClients **environment variable in the edgeHub module. A child device only has one parent. Note A downstream device sends data directly to the internet or to gateway devices (IoT Edge-enabled or not). A child device can be a downstream device or a gateway device in a nested topology. A downstream device can be any device, IoT Edge or non-IoT Edge, registered to the same IoT Hub. For more information about creating a parent-child relationship between an IoT Edge device and an IoT device, see [Authenticate a downstream device to Azure IoT Hub ]. The symmetric key, self-signed X.509, and CA-signed X.509 sections show examples of how to use the Azure portal and Azure CLI to define the parent-child relationships when creating devices. For existing devices, declare the relationship from the device details page in the Azure portal of either the parent or child device. For more information about creating a parent-child relationship between two IoT Edge devices, see [Connect a downstream IoT Edge device to an Azure IoT Edge gateway ]. ### Set up the parent device as a gateway Think of a parent/child relationship as a transparent gateway, where the child device has its own identity in IoT Hub but communicates through the cloud via its parent. For secure communication, the child device needs to verify that the parent device comes from a trusted source. Otherwise, third-parties could set up malicious devices to impersonate parents and intercept communications. One way to create this trust relationship is described in detail in the following articles: - [Configure an IoT Edge device to act as a transparent gateway ] - [Connect a downstream (child) device to an Azure IoT Edge gateway ] ## Specify DNS servers To improve robustness, specify the DNS server addresses used in your environment. To set your DNS server for IoT Edge, see the resolution for [Edge Agent module reports 'empty config file' and no modules start on the device ]in the troubleshooting article. ## Optional offline settings If your devices go offline, the IoT Edge parent device stores all device-to-cloud messages until the connection is reestablished. The IoT Edge hub module manages storing and forwarding offline messages. For devices that can go offline for a long time, optimize performance by setting two IoT Edge hub options: - Increase the *time to live *setting so the IoT Edge hub keeps messages until your device reconnects. - Add more disk space for message storage. ### Time to live The *time to live *setting is how long (in seconds) a message waits to be delivered before it expires. The default is 7,200 seconds (two hours). The maximum value is limited by the maximum value of an integer variable, which is about 2 billion. This setting is a desired property of the IoT Edge hub, stored in the module twin. Configure it in the Azure portal or directly in the deployment manifest. ``` `"$edgeHub": { "properties.desired": { "schemaVersion": "1.1", "routes": {}, "storeAndForwardConfiguration": { "timeToLiveSecs": 7200 } } } ` ``` ### Host storage for system modules By default, the IoT Edge hub stores messages and module state in its local container filesystem. For better reliability, especially when offline, dedicate storage on the host IoT Edge device. For more information, see [Give modules access to a device's local storage ]. ## Next steps Learn more about how to set up a transparent gateway for your parent/child device connections: - [Configure an IoT Edge device to act as a transparent gateway ] - [Authenticate a downstream device to Azure IoT Hub ] - [Connect a downstream device to an Azure IoT Edge gateway ] ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-06-04 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/about-iot-edge What is Azure IoT Edge | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # What is Azure IoT Edge Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. Azure IoT Edge is a device-focused runtime that enables you to deploy, run, and monitor containerized Linux workloads, bringing analytics closer to your devices for faster insights and offline decision-making. Analytics drives business value in IoT solutions, but not all analytics need to be in the cloud. Azure IoT Edge helps you bring the analytical power of the cloud closer to your devices to drive better business insights and enable offline decision making. For example, you can run anomaly detection workloads at the edge to respond as quickly as possible to emergencies happening on a production line. If you want to reduce bandwidth costs and avoid transferring terabytes of raw data, you can clean and aggregate the data locally then only send the insights to the cloud for analysis. Azure IoT Edge brings edge-based capabilities to a cloud-based solution and is a feature of [Azure IoT Hub ]that enables you to scale out and manage an IoT solution from the cloud. By packaging your business logic into standard containers and using optional pre-built IoT Edge module images from partners or the [Microsoft Artifact Registry ], you can easily compose, deploy, and maintain your solution. Azure IoT Edge is made up of three components: - **IoT Edge modules **are containers that run Azure services, third-party services, or your own code. Modules are deployed to IoT Edge devices and execute locally on those devices. - The **IoT Edge runtime **runs on each IoT Edge device and manages the modules deployed to each device. - A **cloud-based interface **enables you to remotely monitor and manage IoT Edge devices. Note Azure IoT Edge is available in the free and standard tier of IoT Hub. The free tier is for testing and evaluation only. For more information about the basic and standard tiers, see [How to choose the right IoT Hub tier ]. ## IoT Edge modules IoT Edge modules are units of execution, implemented as Docker-compatible containers, that run your business logic at the edge. Multiple modules can be configured to communicate with each other, creating a pipeline of data processing. You can develop custom modules or package certain Azure services into modules that provide insights offline and at the edge. ### Artificial intelligence at the edge Azure IoT Edge allows you to deploy advanced AI workloads like machine learning, image recognition, and complex event processing directly at the edge—without the need for in-house development. Azure services like Azure Stream Analytics and Azure Machine Learning can all be run on-premises via Azure IoT Edge. You're not limited to Azure services, though. Anyone can create AI modules for their own use. ### Bring your own code When you want to deploy your own code to your devices, Azure IoT Edge supports that, too. Azure IoT Edge holds to the same programming model as the other Azure IoT services. You can run the same code on a device or in the cloud. Azure IoT Edge supports both Linux and Windows so you can code to the platform of your choice. It supports Java, .NET Core 3.1, Node.js, C, and Python, so your developers can code in a language they already know and use existing business logic. ## IoT Edge runtime The Azure IoT Edge runtime enables custom and cloud logic on IoT Edge devices. The runtime sits on the IoT Edge device, and performs management and communication operations. The runtime performs several functions: - Installs and updates workloads on the device. - Maintains Azure IoT Edge security standards on the device. - Ensures that IoT Edge modules are always running. - Reports module health to the cloud for remote monitoring. - Manages communication between downstream devices and an IoT Edge device, between modules on an IoT Edge device, and between an IoT Edge device and the cloud. [] How you use an Azure IoT Edge device is up to you. The runtime is often used to deploy AI to gateway devices that aggregate and process data from other on-premises devices, but this deployment model is just one option. The Azure IoT Edge runtime runs on a large set of IoT devices that enables using it in a wide variety of ways. It supports both Linux and Windows operating systems and abstracts hardware details. Use a device smaller than a Raspberry Pi 3 if you're not processing much data, or use an industrial server to run resource-intensive workloads. ## IoT Edge cloud interface It's difficult to manage the software lifecycle for millions of IoT devices that are often different makes and models or geographically scattered. Workloads are created and configured for a particular type of device, deployed to all of your devices, and monitored to catch any misbehaving devices. These activities can't be done on a per-device basis and must be done at scale. Azure IoT Edge integrates seamlessly with [Azure IoT Central ]to provide one control plane for your solution's needs. Cloud services allow you to: - Create and configure a workload to be run on a specific type of device. - Send a workload to a set of devices. - Monitor workloads running on devices in the field. [] ## Next steps Take the next step in learning IoT Edge concepts by deploying your first IoT Edge module to a device: - [Deploy modules to a Linux IoT Edge device ] - [Deploy modules to a Windows IoT Edge device ] ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-08-28 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/quickstart-linux Quickstart: Create an Azure IoT Edge Device on Linux | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Quickstart: Deploy your first IoT Edge module to a virtual Linux device Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. Try Azure IoT Edge in this quickstart by deploying containerized code to a virtual Linux IoT Edge device. IoT Edge lets you remotely manage code on your devices so you can send more of your workloads to the edge. For this quickstart, use an Azure virtual machine for your IoT Edge device. It lets you quickly create a test machine and delete it when you're done. In this quickstart, you learn how to: - Create an IoT Hub. - Register an IoT Edge device to your IoT hub. - Install and start the IoT Edge runtime on a virtual device. - Deploy a module remotely to an IoT Edge device. This quickstart walks you through creating a Linux virtual machine that's configured to be an IoT Edge device. Then, you deploy a module from the Azure portal to your device. This quickstart uses a simulated sensor module that generates temperature, humidity, and pressure data. The other Azure IoT Edge tutorials build upon the work you do here by deploying additional modules that analyze the simulated data for business insights. If you don't have an active Azure subscription, create a [free account ]before you begin. ## Prerequisites Set up your environment for the Azure CLI. - Use the Bash environment in [Azure Cloud Shell ]. For more information, see [Get started with Azure Cloud Shell ]. [] - If you prefer to run CLI reference commands locally, [install ]the Azure CLI. If you're running on Windows or macOS, consider running Azure CLI in a Docker container. For more information, see [How to run the Azure CLI in a Docker container ]. - If you're using a local installation, sign in to the Azure CLI by using the [az login ]command. To finish the authentication process, follow the steps displayed in your terminal. For other sign-in options, see [Authenticate to Azure using Azure CLI ]. - When you're prompted, install the Azure CLI extension on first use. For more information about extensions, see [Use and manage extensions with the Azure CLI ]. - Run [az version ]to find the version and dependent libraries that are installed. To upgrade to the latest version, run [az upgrade ]. A resource group to manage all the resources you use in this quickstart. This quickstart and the following tutorials use the example resource group name **IoTEdgeResources **. ``` `az group create --name IoTEdgeResources --location westus2 ` ``` ## Create an IoT Hub Start the quickstart by creating an IoT Hub with the Azure CLI. The free tier of IoT Hub works for this quickstart. If you've used IoT Hub in the past and already have a hub created, you can use that IoT hub. The following code creates a free **F1 **hub in the resource group **IoTEdgeResources **. Replace ` `with a unique name for your IoT Hub. Creating an IoT Hub might take a few minutes. ``` `az iot hub create --resource-group IoTEdgeResources --name --sku F1 --partition-count 2 ` ``` If you get an error because there's already one free IoT Hub in your subscription, change the SKU to **S1 **. Each subscription can only have one free IoT hub. If you get an error that the IoT Hub name isn't available, it means that someone else already has a hub with that name. Try a new name. ## Register an IoT Edge device Register an IoT Edge device with the IoT hub you just created. Create a device identity for your IoT Edge device so that it can communicate with your IoT hub. The device identity lives in the cloud, and you use a unique device connection string to associate a physical device to a device identity. Because IoT Edge devices behave and are managed differently from typical IoT devices, declare this identity as an IoT Edge device using the `--edge-enabled `flag. - Enter the following command in Azure Cloud Shell to create a device named **myEdgeDevice **in your hub. ``` `az iot hub device-identity create --device-id myEdgeDevice --edge-enabled --hub-name ` ``` If you get an error about *iothubowner *policy keys, make sure that your Cloud Shell is running the latest version of the *azure-iot *extension. - Check the connection string for your device, which links the physical device to its identity in IoT Hub. It includes the name of your IoT Hub, the name of your device, and a shared key that authenticates connections between them. You use this connection string again in the next section to set up your IoT Edge device. ``` `az iot hub device-identity connection-string show --device-id myEdgeDevice --hub-name ` ``` For example, the connection string should look similar to `HostName=contoso-hub.azure-devices.net;DeviceId=myEdgeDevice;SharedAccessKey= `. ## Configure your IoT Edge device Create a virtual machine with the Azure IoT Edge runtime. The IoT Edge runtime is deployed on all IoT Edge devices and has three components. The *IoT Edge security daemon *starts each time an IoT Edge device boots and bootstraps the device by starting the IoT Edge agent. The *IoT Edge agent *facilitates deployment and monitoring of modules on the IoT Edge device, including the IoT Edge hub. The *IoT Edge hub *manages communications between modules on the IoT Edge device, and between the device and IoT Hub. During runtime configuration, provide a device connection string. This string is retrieved from the Azure CLI. This string associates your physical device with the IoT Edge device identity in Azure. ### Deploy the IoT Edge device This section uses an Azure Resource Manager template to create a new virtual machine and install the IoT Edge runtime on it. If you want to use your own Linux device instead, you can follow the installation steps in [Manually provision a single Linux IoT Edge device ], then return to this quickstart. Use the **Deploy to Azure **button or CLI commands to create an IoT Edge device based on the prebuilt [iotedge-vm-deploy ]template. - Deploy using the IoT Edge Azure Resource Manager template. [] - For bash or Cloud Shell users, copy the following command into a text editor, replace the placeholder text with your information, then copy into your bash or Cloud Shell window: ``` `az deployment group create \ --resource-group IoTEdgeResources \ --template-uri "https://raw.githubusercontent.com/Azure/iotedge-vm-deploy/main/edgeDeploy.json" \ --parameters dnsLabelPrefix='' \ --parameters adminUsername='azureUser' \ --parameters deviceConnectionString=$(az iot hub device-identity connection-string show --device-id myEdgeDevice --hub-name -o tsv) \ --parameters authenticationType='password' \ --parameters adminPasswordOrKey="" ` ``` - For PowerShell users, copy the following command into your PowerShell window, then replace the placeholder text with your own information: ``` `az deployment group create ` --resource-group IoTEdgeResources ` --template-uri "https://raw.githubusercontent.com/Azure/iotedge-vm-deploy/main/edgeDeploy.json" ` --parameters dnsLabelPrefix='' ` --parameters adminUsername='azureUser' ` --parameters deviceConnectionString=$(az iot hub device-identity connection-string show --device-id myEdgeDevice --hub-name -o tsv) ` --parameters authenticationType='password' ` --parameters adminPasswordOrKey="" ` ``` This template takes the following parameters: Parameter Description **resource-group **The resource group in which the resources are created. Use the default **IoTEdgeResources **that we've been using throughout this article or provide the name of an existing resource group in your subscription. **template-uri **A pointer to the Resource Manager template that we're using. **dnsLabelPrefix **A string that is used to create the virtual machine's hostname. Replace the placeholder text with a name for your virtual machine. **adminUsername **A username for the admin account of the virtual machine. Use the example **azureUser **or provide a new username. **deviceConnectionString **The connection string from the device identity in IoT Hub, which is used to configure the IoT Edge runtime on the virtual machine. The CLI command within this parameter grabs the connection string for you. Replace the placeholder text with your IoT hub name. **authenticationType **The authentication method for the admin account. This quickstart uses **password **authentication, but you can also set this parameter to **sshPublicKey **. **adminPasswordOrKey **The password or value of the SSH key for the admin account. Replace the placeholder text with a secure password. Your password must be at least 12 characters long and have three of four of the following: lowercase characters, uppercase characters, digits, and special characters. After deployment completes, JSON-formatted output in the CLI contains the SSH information to connect to the virtual machine. Copy the value of the **public SSH **entry of the **outputs **section. For example, your SSH command should look similar to `ssh azureUser@edge-vm.westus2.cloudapp.azure.com `. ### View the IoT Edge runtime status The rest of the commands in this quickstart take place on your IoT Edge device itself, so that you can see what's happening on the device. If you're using a virtual machine, connect to that machine now using the admin username that you set up and the DNS name that was output by the deployment command. You can also find the DNS name on your virtual machine's overview page in the Azure portal. Use the following command to connect to your virtual machine. Replace ` `and ` `with your own values. ``` `ssh @ ` ``` Once connected to your virtual machine, verify that the runtime was successfully installed and configured on your IoT Edge device. - Check if IoT Edge is running. The following command returns a status of **Ok **if IoT Edge is running or provides any service errors. ``` `sudo iotedge system status ` ``` Tip You need elevated privileges to run `iotedge `commands. Once you sign out of your machine and sign back in the first time after installing the IoT Edge runtime, your permissions are automatically updated. Until then, use `sudo `in front of the commands. - If you need to troubleshoot the service, retrieve the service logs. ``` `sudo iotedge system logs ` ``` - View all the modules running on your IoT Edge device. Since the service just started for the first time, you should only see the **edgeAgent **module running. The edgeAgent module runs by default and helps to install and start any additional modules that you deploy to your device. ``` `sudo iotedge list ` ``` Your IoT Edge device is now configured. It's ready to run cloud-deployed modules. ## Deploy a module Manage your Azure IoT Edge device from the cloud to deploy a module that sends device telemetry data to IoT Hub. A key capability of Azure IoT Edge is deploying code to your IoT Edge devices from the cloud. *IoT Edge modules *are executable packages implemented as containers. In this section, you deploy a pre-built module from the [IoT Edge Modules section of Microsoft Artifact Registry ]. The module that you deploy in this section simulates a sensor and sends generated data. This module is a useful piece of code when you're getting started with IoT Edge because you can use the simulated data for development and testing. If you want to see exactly what this module does, you can view the [simulated temperature sensor source code ]. Use these steps to deploy your first module. - Sign in to the [Azure portal ]and go to your IoT Hub. - From the menu on the left, under **Device Management **, select **Devices **. - Select the device ID of the target IoT Edge device from the list. When you create a new IoT Edge device, it displays the status code `417 -- The device's deployment configuration is not set `in the Azure portal. This status is normal, and means that the device is ready to receive a module deployment. - On the upper bar, select **Set Modules **. Select the modules you want to run on your device. You can choose from modules that you've built yourself or images in a container registry. In this quickstart, you deploy a module from the Microsoft container registry. - In the **IoT Edge modules **section, select **Add **then choose **IoT Edge Module **. - Update the following module settings: Setting Value IoT Module name `SimulatedTemperatureSensor `Image URI `mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:latest `Restart policy always Desired status running - Select **Next: Routes **to continue to configure routes. - Add a route that sends all messages from the simulated temperature module to IoT Hub. Setting Value Name `SimulatedTemperatureSensorToIoTHub `Value `FROM /messages/modules/SimulatedTemperatureSensor/* INTO $upstream ` - Select **Next: Review + create **. - Review the JSON file, and then select **Create **. The JSON file defines all the modules that you deploy to your IoT Edge device. Note When you submit a new deployment to an IoT Edge device, nothing is pushed to your device. Instead, the device queries IoT Hub regularly for any new instructions. If the device finds an updated deployment manifest, it uses the information about the new deployment to pull the module images from the cloud then starts running the modules locally. This process can take a few minutes. After you create the module deployment details, the wizard returns you to the device details page. View the deployment status on the **Modules **tab. You should see three modules: **$edgeAgent **, **$edgeHub **, and **SimulatedTemperatureSensor **. If one or more of the modules has **Yes **under **Specified in Deployment **but not under **Reported by Device **, your IoT Edge device is still starting them. Wait a few minutes and refresh the page. [] If you have issues deploying modules, learn more in [Troubleshoot IoT Edge devices from the Azure portal ]. ## View generated data In this quickstart, you create a new IoT Edge device and install the IoT Edge runtime on it. Then, you use the Azure portal to deploy an IoT Edge module to run on the device without making changes to the device itself. In this case, the module that you pushed generates sample environment data that you can use for testing later. The simulated sensor is monitoring both a machine and the environment around the machine. For example, this sensor can be in a server room, on a factory floor, or on a wind turbine. The message includes ambient temperature and humidity, machine temperature and pressure, and a timestamp. The IoT Edge tutorials use the data created by this module as test data for analytics. Open the command prompt on your IoT Edge device, or use the SSH connection from Azure CLI. Confirm that the module you deployed from the cloud is running on your IoT Edge device: ``` `sudo iotedge list ` ``` [] View the messages sent from the temperature sensor module: ``` `sudo iotedge logs SimulatedTemperatureSensor -f ` ``` [] Tip IoT Edge commands are case sensitive when referring to module names. ## Clean up resources To continue with the IoT Edge tutorials, use the device you registered and set up in this quickstart. Otherwise, delete the Azure resources you created to avoid charges. If you created your virtual machine and IoT hub in a new resource group, you can delete that group and all the associated resources. Double-check the contents of the resource group to ensure there's nothing you want to keep. If you don't want to delete the whole group, you can delete individual resources instead. Important Deleting a resource group is irreversible. Delete the **IoTEdgeResources **group. Deleting a resource group might take a few minutes. ``` `az group delete --name IoTEdgeResources --yes ` ``` Confirm the resource group is deleted by viewing the list of resource groups. ``` `az group list ` ``` ## Next steps In this quickstart, you created an IoT Edge device and used the Azure IoT Edge cloud interface to deploy code onto the device. Now, you use a test device that generates raw data about its environment. In the next tutorial, you'll learn how to monitor the activity and health of your device from the Azure portal. [Monitor IoT Edge devices ] ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-09-04 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2025 --- # Source: https://learn.microsoft.com/en-us/azure/iot-edge/troubleshoot Troubleshoot Azure IoT Edge | Microsoft Learn [Skip to main content ][Skip to Ask Learn chat experience ] This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. [Download Microsoft Edge ][More info about Internet Explorer and Microsoft Edge ]Table of contents Exit editor mode Ask Learn Ask Learn Focus mode Table of contents [Read in English ]Add Add to plan [Edit ] #### Share via [Facebook ][x.com ][LinkedIn ][Email ]Print Note Access to this page requires authorization. You can try [signing in ]or [changing directories ]. Access to this page requires authorization. You can try [changing directories ]. # Troubleshoot your IoT Edge device Feedback Summarize this article for me ## In this article **Applies to: **IoT Edge 1.5 Important IoT Edge 1.5 LTS is the [supported release ]. IoT Edge 1.4 LTS is end of life as of November 12, 2024. If you are on an earlier release, see [Update IoT Edge ]. If you experience issues running Azure IoT Edge in your environment, use this article as a guide for troubleshooting and diagnostics. ## Run the 'check' command Your first step when troubleshooting IoT Edge should be to use the `check `command, which runs a collection of configuration and connectivity tests for common issues. The `check `command is available in [release 1.0.7 ]and later. Note The troubleshooting tool can't run connectivity checks if the IoT Edge device is behind a proxy server. You can run the `check `command as follows, or include the `--help `flag to see a complete list of options: ``` `sudo iotedge check ` ``` The troubleshooting tool runs many checks that are sorted into these three categories: - *Configuration checks *examine details that could prevent IoT Edge devices from connecting to the cloud, including issues with the config file and the container engine. - *Connection checks *verify that the IoT Edge runtime can access ports on the host device and that all the IoT Edge components can connect to the IoT Hub. This set of checks returns errors if the IoT Edge device is behind a proxy. - *Production readiness checks *look for recommended production best practices, such as the state of device certificate authority (CA) certificates and module log file configuration. The IoT Edge check tool uses a container to run its diagnostics. The container image, `mcr.microsoft.com/azureiotedge-diagnostics:latest `, is available through the [Microsoft Artifact Registry ](MAR). If you need to run a check on a device without direct access to the internet, your devices need access to the container image. In a scenario using nested IoT Edge devices, you can get access to the diagnostics image on downstream devices by routing the image pull through the parent devices. ``` `sudo iotedge check --diagnostics-image-name :/azureiotedge-diagnostics:1.2 ` ``` For information about each of the diagnostic checks this tool runs, including what to do if you get an error or warning, see [Built-in troubleshooting functionality ]. ## Gather debug information with 'support-bundle' command When you need to gather logs from an IoT Edge device, the most convenient way is to use the `support-bundle `command. By default, this command collects module, IoT Edge security manager and container engine logs, `iotedge check `JSON output, and other useful debug information. It compresses them into a single file for easy sharing. The `support-bundle `command is available in [release 1.0.9 ]and later. Run the `support-bundle `command with the `--since `flag to specify how long from the past you want to get logs. For example `6h `gets logs since the last six hours, `6d `since the last six days, `6m `since the last six minutes and so on. Include the `--help `flag to see a complete list of options. ``` `sudo iotedge support-bundle --since 6h ` ``` By default, the `support-bundle `command creates a zip file called **support_bundle.zip **in the directory where the command is called. Use the flag `--output `to specify a different path or file name for the output. For more information about the command, view its help information. ``` `iotedge support-bundle --help ` ``` You can also use the built-in direct method call [UploadSupportBundle ]to upload the output of the support-bundle command to Azure Blob Storage. Warning Output from the `support-bundle `command can contain host, device names, module names, and information logged by your modules. Be aware of this inclusion if sharing the output in a public forum. ## Review metrics collected from the runtime The IoT Edge runtime modules produce metrics to help you monitor and understand the health of your IoT Edge devices. Add the **metrics-collector **module to your deployments to handle collecting these metrics and sending them to the cloud for easier monitoring. For more information, see [Collect and transport metrics ]. ## Check your IoT Edge version If you're running an older version of IoT Edge, then upgrading might resolve your issue. The `iotedge check `tool checks that the IoT Edge security daemon is the latest version, but doesn't check the versions of the IoT Edge hub and agent modules. To check the version of the runtime modules on your device, use the commands `iotedge logs edgeAgent `and `iotedge logs edgeHub `. The version number is declared in the logs when the module starts up. For instructions on how to update your device, see [Update IoT Edge ]. ## Verify the installation of IoT Edge on your devices You can verify the installation of IoT Edge on your devices by [monitoring the edgeAgent module twin ]. To get the latest edgeAgent module twin, run the following command from [Azure Cloud Shell ]: ``` `az iot hub module-twin show --device-id --module-id '$edgeAgent' --hub-name ` ``` This command outputs all the edgeAgent [reported properties ]. Here are some helpful ones monitor the status of the device: - runtime status - runtime start time - runtime last exit time - runtime restart count ## Check the status of the IoT Edge security manager and its logs The [IoT Edge security manager ]is responsible for operations like initializing the IoT Edge system at startup and provisioning devices. If IoT Edge isn't starting, the security manager logs can provide useful information. - View the status of the IoT Edge system services: ``` `sudo iotedge system status ` ``` - View the logs of the IoT Edge system services: ``` `sudo iotedge system logs -- -f ` ``` - Enable debug-level logs to view more detailed logs of the IoT Edge system services: - Enable debug-level logs. ``` `sudo iotedge system set-log-level debug sudo iotedge system restart ` ``` - Switch back to the default info-level logs after debugging. ``` `sudo iotedge system set-log-level info sudo iotedge system restart ` ``` ## Check container logs for issues Once the IoT Edge security daemon is running, look at the logs of the containers to detect issues. Start with your deployed containers, then look at the containers that make up the IoT Edge runtime: edgeAgent and edgeHub. The IoT Edge agent logs typically provide info on the lifecycle of each container. The IoT Edge hub logs provide info on messaging and routing. You can retrieve the container logs from several places: - On the IoT Edge device, run the following command to view logs: ``` `iotedge logs ` ``` - On the Azure portal, use the built-in troubleshoot tool. For more information, see [Troubleshoot IoT Edge devices from the Azure portal ]. - Use the [UploadModuleLogs direct method ]to upload the logs of a module to Azure Blob Storage. ## Clean up container logs By default the Moby container engine doesn't set container log size limits. Over time extensive logs can lead to the device filling up with logs and running out of disk space. If large container logs are affecting your IoT Edge device performance, use the following command to force-remove the container along with its related logs. If you're still troubleshooting, wait until after you inspect the container logs to take this step. Warning If you force remove the edgeHub container while it has an undelivered message backlog and no [host storage ]configured, the undelivered messages are lost. ``` `docker rm --force ` ``` For more information about ongoing logs maintenance and production scenarios, see [Set up default logging driver ]. ## View the messages going through the IoT Edge hub You can view the messages going through the IoT Edge hub and gather insights from verbose logs from the runtime containers. To turn on verbose logs on these containers, set the `RuntimeLogLevel `environment variable in the deployment manifest. To view messages going through the IoT Edge hub, set the `RuntimeLogLevel `environment variable to `debug `for the edgeHub module. Both the edgeHub and edgeAgent modules have this runtime log environment variable, with the default value set to `info `. This environment variable can take the following values: - fatal - error - warning - info - debug - verbose You can also check the messages being sent between IoT Hub and IoT devices. View these messages by using the [Azure IoT Hub extension for Visual Studio Code ]. For more information, see [Handy tool when you develop with Azure IoT ]. ## Restart containers After investigating the logs and messages for information, you can try restarting containers. On the IoT Edge device, use the following commands to restart modules: ``` `iotedge restart ` ``` Restart the IoT Edge runtime containers: ``` `iotedge restart edgeAgent && iotedge restart edgeHub ` ``` You can also restart modules remotely from the Azure portal. For more information, see [Troubleshoot IoT Edge devices from the Azure portal ]. ## Check your firewall and port configuration rules Azure IoT Edge allows communication from an on-premises server to Azure cloud using supported IoT Hub protocols. For more information, see [Choose a device communication protocol ]. For enhanced security, communication channels between Azure IoT Edge and Azure IoT Hub are always configured to be Outbound. This configuration is based on the [Service Assisted Communication pattern ], which minimizes the attack surface for a malicious entity to explore. Inbound communication is only required for [specific scenarios ]where Azure IoT Hub needs to push messages to the Azure IoT Edge device. Cloud-to-device messages are protected using secure TLS channels and can be further secured using X.509 certificates and TPM device modules. The Azure IoT Edge Security Manager governs how this communication can be established. For more information, see [Azure IoT Edge security manager ]. While IoT Edge provides enhanced configuration for securing Azure IoT Edge runtime and deployed modules, it's still dependent on the underlying machine and network configuration. Hence, it's imperative to ensure proper network and firewall rules are set up for secure edge to cloud communication. The following table can be used as a guideline when configuration firewall rules for the underlying servers where Azure IoT Edge runtime is hosted: Protocol Port Incoming Outgoing Guidance MQTT 8883 BLOCKED (Default) BLOCKED (Default) - Configure Outgoing (Outbound) to be Open when using MQTT as the communication protocol. - IoT Edge doesn't support port 1883 for MQTT. - Incoming (Inbound) connections should be blocked. AMQP 5671 BLOCKED (Default) OPEN (Default) - Default communication protocol for IoT Edge. - Must be configured to be Open if Azure IoT Edge isn't configured for other supported protocols or AMQP is the desired communication protocol. - IoT Edge doesn't support port 5672 for AMQP. - Block this port when Azure IoT Edge uses a different IoT Hub supported protocol. - Incoming (Inbound) connections should be blocked. HTTPS 443 BLOCKED (Default) OPEN (Default) - Configure Outgoing (Outbound) to be Open on 443 for IoT Edge provisioning. This configuration is required when using manual scripts or Azure IoT Device Provisioning Service (DPS). - [Incoming (Inbound) connection ]should be Open only for specific scenarios: - If you have a transparent gateway with downstream devices that can send method requests. In this case, port 443 doesn't need to be open to external networks to connect to IoT Hub or provide IoT Hub services through Azure IoT Edge. Thus the incoming rule could be restricted to only open Incoming (Inbound) from the internal network. - For Client to Device (C2D) scenarios. - IoT Edge doesn't support port 80 for HTTP. - If non-HTTP protocols (for example, AMQP or MQTT) can't be configured in the enterprise; the messages can be sent over WebSockets. Port 443 is used for WebSocket communication in that case. ## Last resort: stop and recreate all containers Sometimes, a system might require significant special modification to work with existing networking or operating system constraints. For example, a system could require a different data disk mount and proxy settings. If you tried all previous steps and still get container failures, the docker system caches or persisted network settings might not up to date with the latest reconfiguration. In this case, the last resort option is to use [`docker prune `]get a clean start from scratch. The following command stops the IoT Edge system (and thus all containers), uses the "all" and "volume" option for `docker prune `to remove all containers and volumes. Review the warning that the command issues and confirm with `y `when ready. ``` `sudo iotedge system stop docker system prune --all --volumes ` ``` ``` `WARNING! This will remove: - all stopped containers - all networks not used by at least one container - all volumes not used by at least one container - all images without at least one container associated to them - all build cache Are you sure you want to continue? [y/N] ` ``` Start the system again. To be safe, apply any potentially remaining configuration and start the system with one command. ``` `sudo iotedge config apply ` ``` Wait a few minutes and check again. ``` `sudo iotedge list ` ``` ## Next steps Do you think that you found a bug in the IoT Edge platform? [Submit an issue ]so that we can continue to improve. If you have more questions, create a [Support request ]for help. ## Feedback Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? ## Additional resources - Last updated on 2025-05-05 ### In this article Was this page helpful? Yes No No Need help with this topic? Want to try using Ask Learn to clarify or guide you through this topic? Ask Learn Ask Learn Suggest a fix? [en-us ][Your Privacy Choices ]Theme - Light - Dark - High contrast - - [AI Disclaimer ] - [Previous Versions ] - [Blog ] - [Contribute ] - [Privacy ] - [Terms of Use ] - [Trademarks ] - © Microsoft 2026