Working with /etc/hosts file using Azure IoT and OSConfig
Important
Version 1.0.3 (published 28 June 2022) includes breaking changes to member names which may impact existing users. For more information, see: Member names transition from PascalCase to camelCase in version 1.0.3
Audience and scope
This article is designed to support people who provision or manage devices with Azure IoT. If that doesn't sound like you, consider taking a look at Audiences for OSConfig documentation.
This article is about getting and setting the contents of the /etc/hosts file, used by devices for name resolution. In edge/IoT scenarios, hosts file entries are often used to augment broader name resolution technology such as DNS. For example, you may need all devices on a certain manufacturing floor to map the name "controller-endpoint" to a specific on-prem IP address. Similarly, you might need a set of devices to map the name "camera-feed" to a loopback IP address.
Prerequisites
If you are using this article for reference (for example, you are here to copy a property name), there are no pre-requisites.
If you want to try the examples on live systems (recommended), then:
You will need an Azure account with an IoT Hub
This article assumes some familiarity with IoT Hub and related tools. For example, it assumes you are comfortable creating IoT Hubs and attaching devices. If you prefer a more prescriptive step-by-step introduction to installing and using OSConfig from scratch, see: Quickstart: Manage a single virtual IoT device using Azure CLI instead.
You will need at least one Linux device with the OSConfig agent installed and connected to Azure IoT.
For more information, see: How and where to install the OSConfig agent for Linux.
You will use Azure Portal or Azure CLI to interact with the devices via your IoT Hub
For further steps, choose your preferred experience:
- Ensure you are signed in to the Azure Portal and can access your IoT Hub's Overview page
The object model
The following are the key desired and reported properties related to the hosts file contents.
Important
Version 1.0.3 (published 28 June 2022) includes breaking changes to member names which may impact existing users. For more information, see: Member names transition from PascalCase to camelCase in version 1.0.3
Primary use | Populated by | Notes | |
---|---|---|---|
reported.HostName.hosts |
Get scenarios | OSConfig agent | Analogous to cat /etc/hosts on most Linux systems; see below for the data format |
desired.HostName.desiredHosts |
Set scenarios | Admin or admin tools | Analogous to overwriting cat /etc/hosts on most Linux systems; see below for the data format |
reported.HostName.desiredHosts.value |
Set scenarios | OSConfig agent | Acknowledges receipt of desired hosts details; should match desiredHosts |
reported.HostName.desiredHosts.ac |
Set scenarios | OSConfig agent | Status for reaching desired state for hosts details; 200 indicates success |
Important
desiredHosts
represents a replace operation (not add or merge) for the contents of /etc/hosts. Please ensure that any value you place in desiredHosts
contains all of the entries you need.
Hosts files typically include multiple entries separated by line breaks. To project these as a single string value in IoT Hub, the Hosts
and desiredHosts
properties use semicolons in place of line breaks. Also, comment lines in the existing hosts file are ignored when OSConfig is populating the Hosts
property. For example, assume a hosts file like:
## a comment line
192.168.1.139 host.docker.internal
127.0.0.1 localhost
The corresponding value of the Hosts
property would be: 192.168.1.139 host.docker.internal;127.0.0.1 localhost
. To see examples from a real device's OSConfig twin in IoT Hub, see the reference section at the end of this article.
A. Examples for individual devices
The following demonstrate specific use cases. You can use these as starting points and adapt for your unique environment. For at-scale examples, see: B. At-scale examples for fleets of devices.
Example A.1. How to check hosts file contents for a single device
In this example, we will get the reported.HostName.hosts
property, which reflects the hosts file content on the device.
Using Azure Portal, navigate to the osconfig module twin, then scroll down to find
reported.HostName.hosts
Example A.2. How to modify hosts file contents for single device
In this example, you will replace the contents of /etc/hosts on a device.
Using Azure Portal, set the
desiredHosts
property in the osconfig module twin.You can verify the change is made successfully from the module twin itself or you can verify the contents of /etc/hosts file on the device has been updated. Scroll down the module twin to find reported properties for HostName .
B. At-scale examples for fleets of devices
Example B.1. How to set and report/audit hosts file content for fleet of devices
In this example you will create an IoT Hub Configuration (also known as IoT Hub Automatic Device Management [ADM]). For any devices which meet the target criteria, the IoT Hub Configuration will set the value of desiredHosts
.
From your Azure IoT Hub's portal page, choose Device management --> Configurations --> Add Module Configuration.
Specify a name and update the Twin Settings with the desired host configuration. Set Module Twin Property to
properties.desired.HostName
and set the Module Twin Property Content to the desired content,{"desiredHosts": <YOUR LIST HERE>}
, replacing <YOUR LIST HERE> with your semi-colon delimited list of hostnames and ip addresses.Create a Custom Metric with name successfullyConfigured and the Metric Criteria of
SELECT deviceId from devices.modules where moduleId='osconfig' AND properties.reported.HostName.desiredHosts.ac=200
.For the Target Modules, specify the criteria for which devices are in scope. In this example, we will target all devices with OSConfig capabilities, using a Target Condition of
FROM devices.modules where moduleId='osconfig'
Tip
The background jobs which power IoT Hub Configurations run every few minutes. In the following steps you might initially see results indicating nothing has happened yet. If you encounter this, wait 5 minutes.
To observe which devices' twins have been updated (cloud side), see the Applied metric (also known as appliedCount)
To observe which devices have completed the configuration (device has acknowledged successful change), see the successfullyConfigured metric.
(optional step) You can also observe the new value of the
Hosts
property using IoT Hub Queries. Navigate to Device Management --> Queries and run the querySELECT deviceId, properties.reported.HostName.hosts FROM devices.modules WHERE moduleId='osconfig'"
Reference: Example twin from Iot Hub
The following is excerpted from an osconfig module twin in IoT Hub. For context it includes most of the raw twin, with certain properties (like $metadata) removed for brevity. The properties related to this article are highlighted.
{
"deviceId": "device03",
"moduleId": "osconfig",
"connectionState": "Connected",
"modelId": "dtmi:osconfig:deviceosconfiguration;5",
"version": 28,
"properties": {
"desired": {
"Settings": {
"__t": "c",
"DeviceHealthTelemetryConfiguration": 2,
"DeliveryOptimizationPolicies": {
"PercentageDownloadThrottle": 50,
"CacheHostSource": 1,
"CacheHost": "http://mycachehost"
}
},
"CommandRunner": {
"__t": "c",
"CommandArguments": {
"CommandId": "set_timezone__And_report_back",
"Arguments": "timedatectl set-timezone UTC; timedatect l grep zone | tr -d '[:space:]'",
"SingleLineTextResult": false,
"Action": 3
}
},
"HostName": {
"__t": "c",
"DesiredName": "NewHostName123",
"DesiredHosts": "127.0.0.1 localhost;::1 ip6-localhost ip6-loopback;fe00::0 ip6-localnet;ff00::0 ip6-mcastprefix;ff02::1 ip6-allnodes;ff02::2 ip6-allrouters;ff02::3 ip6-allhosts;10.1.2.3 my-on-prem-equipment"
},
"Ztsi": {
"__t": "c",
"DesiredServiceUrl": "https://my-attestation-endpoint",
"DesiredEnabled": true
},
"$version": 8
},
"reported": {
"Firewall": {
"__t": "c",
"FirewallState": 1,
"FirewallFingerprint": "86cadaa93d8c0e0ee42e36190413265c2e218c87a0c494c026cf7de601765e72"
},
"CommandRunner": {
"__t": "c",
"CommandStatus": {
"CommandId": "set_timezone__And_report_back",
"ResultCode": 0,
"TextResult": "",
"CurrentState": 2
},
"CommandArguments": {
"value": {
"CommandId": "set_timezone__And_report_back",
"Arguments": "timedatectl set-timezone UTC; timedatect l grep zone | tr -d '[:space:]'",
"SingleLineTextResult": false,
"Action": 3
},
"ac": 200,
"ad": "-",
"av": 4
}
},
"HostName": {
"__t": "c",
"Name": "NewHostName123",
"Hosts": "127.0.0.1 localhost;::1 ip6-localhost ip6-loopback;fe00::0 ip6-localnet;ff00::0 ip6-mcastprefix;ff02::1 ip6-allnodes;ff02::2 ip6-allrouters;ff02::3 ip6-allhosts;10.1.2.3 my-on-prem-equipment",
"DesiredName": {
"value": "NewHostName123",
"ac": 200,
"ad": "-",
"av": 5
},
"DesiredHosts": {
"value": "127.0.0.1 localhost;::1 ip6-localhost ip6-loopback;fe00::0 ip6-localnet;ff00::0 ip6-mcastprefix;ff02::1 ip6-allnodes;ff02::2 ip6-allrouters;ff02::3 ip6-allhosts;10.1.2.3 my-on-prem-equipment",
"ac": 200,
"ad": "-",
"av": 6
}
},
"Networking": {
"__t": "c",
"NetworkConfiguration": {
"InterfaceTypes": "eth0=ether;lo=loopback",
"MacAddresses": "eth0=00:22:48:7b:04:39;lo=00:00:00:00:00:00",
"IpAddresses": "eth0=10.0.0.6,fe80::222:48ff:fe7b:439;lo=127.0.0.1,::1",
"SubnetMasks": "eth0=/24,/64;lo=/8,/128",
"DefaultGateways": "eth0=10.0.0.1",
"DnsServers": "eth0=168.63.129.16",
"DhcpEnabled": "eth0=false;lo=false",
"Enabled": "eth0=true;lo=unknown",
"Connected": "eth0=true;lo=true"
}
},
"Tpm": {
"__t": "c",
"TpmStatus": 2
},
"Ztsi": {
"__t": "c",
"Enabled": 0,
"ServiceUrl": "",
"DesiredServiceUrl": {
"value": "https://my-attestation-endpoint",
"ac": 200,
"ad": "-",
"av": 7
},
"DesiredEnabled": {
"value": true,
"ac": 200,
"ad": "-",
"av": 8
}
},
"Settings": {
"__t": "c",
"DeviceHealthTelemetryConfiguration": {
"value": 2,
"ac": 200,
"ad": "-",
"av": 2
},
"DeliveryOptimizationPolicies": {
"value": {
"PercentageDownloadThrottle": 50,
"CacheHostSource": 1,
"CacheHost": "http://mycachehost"
},
"ac": 400,
"ad": "-",
"av": 3
}
},
"$version": 20
}
}
}
Next steps
For an overview of OSConfig scenarios and capabilities, see:
For specific practical examples, see: