The following instructions detail how to connect to Cumulocity and the MQTT Service (i.e. port 9883) from a device.
Pre-requisites
The following pre-requisites are
- bash (or zsh)
- go-c8y-cli and an active go-c8y-cli session
- openssl (>= 3.x)
- curl
- mosquitto_pub (mosquitto client which is an MQTT client)
On macOS (using brew)
You can install the required dependencies using homebrew
brew install bash openssl curl mosquittoSee the go-c8y-cli installation guide for installing go-c8y-cli.
-
Set a device id (this will be the c8y_Serial external id used to reference the device)
DEVICE_ID=$(c8y template execute --template "'example_' + _.Char(10)")The above command just generates a randomized value for you, but you can change it to a fixed value if you want. Though we would recommend to sticking to the character set:
[A-Za-z0-9_-]. -
Register the device
eval "$(c8y deviceregistration register-basic \ --id "$DEVICE_ID" \ --outputTemplate " 'export DEVICE_USER=%s\nexport DEVICE_PASSWORD=%s' % [ std.escapeStringBash(output.username), std.escapeStringBash(output.password) ] " )"
The command will use a randomized password and it will set the value (via the
evalcommand) so that it can be referenced in following commands. -
Use an MQTT client to publish to a custom topic on the Cumulocity MQTT service
mosquitto_pub \ -h "$C8Y_DOMAIN" \ -p 9883 \ --debug \ -i "$DEVICE_ID" \ -u "$DEVICE_USER" \ -P "$DEVICE_PASSWORD" \ --cafile /opt/homebrew/etc/ca-certificates/cert.pem \ -t foo \ -m bar \ -q 1Note: On macOS, the
--cafileargument MUST be set otherwise the connection will fail (as the mosquitto_sub won't be able to establish trust with the Cumulocity endpoint). On other platforms, you might be able to leave out the--cafile, or direct it to the OS's ca file, e.g. on Linux this is typically,--cafile /etc/ssl/certs/ca-certificates.crt.Client example_UqCXbGBXHS sending CONNECT Client example_UqCXbGBXHS received CONNACK (0) Client example_UqCXbGBXHS sending PUBLISH (d0, q1, r0, m1, 'foo', ... (3 bytes)) Client example_UqCXbGBXHS received PUBACK (Mid: 1, RC:0) Client example_UqCXbGBXHS sending DISCONNECT
-
Set a device id (this will be the c8y_Serial external id used to reference the device)
DEVICE_ID=$(c8y template execute --template "'example_' + _.Char(10)")The above command just generates a randomized value for you, but you can change it to a fixed value if you want. Though we would recommend to sticking to the character set:
[A-Za-z0-9_-]. -
Create a private key and CSR
openssl req -new -newkey ec \ -pkeyopt ec_paramgen_curve:prime256v1 \ -nodes \ -keyout "${DEVICE_ID}.key" \ -out "${DEVICE_ID}.csr" \ -subj "/C=US/ST=California/L=SanFrancisco/O=ExampleCorp/OU=IT/CN=$DEVICE_ID"Note: You can change the key algorithm and subject string as you with
-
Register the device with Cumulocity
eval "$( c8y deviceregistration register-ca \ --id "$DEVICE_ID" \ --outputTemplate "'export ONE_TIME_PASSWORD=%s' % std.escapeStringBash(output.password)" )"
The command will use a randomized one-time password and it will set the value (via the
evalcommand) so that it can be referenced in following commands.Alternatively, you can register the device in the Cumulocity Device Management Application, where you'll need to print out the following variables in order to input them into the registration form in the UI:
echo $DEVICE_ID- External IDecho $ONE_TIME_PASSWORD- one-time password
Note: A device managed object is created at this step, however the device user will not.
-
Download the certificate using the device's one-time password
curl \ -f \ -XPOST \ --user "${DEVICE_ID}:${ONE_TIME_PASSWORD}" \ -H "Content-Type: application/pkcs10" \ -H "Content-Transfer-Encoding: base64" \ -H "Accept: application/pkcs10" \ --data-binary "@${DEVICE_ID}.csr" \ "https://$C8Y_DOMAIN/.well-known/est/simpleenroll" > "${DEVICE_ID}.crt"You can inspect the contents of the certificate using:
openssl x509 -in "${DEVICE_ID}.crt" -text -nooutExample output
Certificate: Data: Version: 3 (0x2) Serial Number: 1772700590664 (0x19cbd306248) Signature Algorithm: ecdsa-with-SHA256 Issuer: C=United States, O=Cumulocity, CN=t123445 Validity Not Before: Mar 5 08:49:50 2026 GMT Not After : Mar 5 08:49:50 2027 GMT Subject: C=US, ST=California, L=SanFrancisco, O=ExampleCorp, OU=IT, CN=example_abcdef Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) pub: 04:5b:c2:95:6c:45:50:1b:28:a2:9d:86:fa:ce:85: d4:ea:70:ff:d5:1d:fe:25:8c:a3:7e:f9:8f:19:f1: b6:39:96:80:18:f7:d0:0d:96:ea:67:8c:49:7e:48: 12:56:82:f0:e7:7b:63:e3:63:fc:23:46:f2:d5:0f: 87:82:7f:6c:da ASN1 OID: prime256v1 NIST CURVE: P-256 Signature Algorithm: ecdsa-with-SHA256 Signature Value: 30:45:02:21:00:e2:1b:3b:b3:4e:8e:e6:b4:82:97:a7:da:e3: 84:42:22:b3:17:57:ce:03:3a:58:a3:e6:31:39:a8:8d:a4:3c: 5e:02:20:1d:45:47:69:1d:67:ad:84:ce:26:97:a5:f7:e3:8f: 32:cd:6b:ba:ec:54:56:bb:8c:5a:70:0d:43:5c:d1:9a:52 -
Use an MQTT client to publish to a custom topic on the Cumulocity MQTT service
mosquitto_pub \ -h "$C8Y_DOMAIN" \ -p 9883 \ --debug \ -i "$DEVICE_ID" \ --key "${DEVICE_ID}.key" \ --cert "${DEVICE_ID}.crt" \ --cafile /opt/homebrew/etc/ca-certificates/cert.pem \ -t foo \ -m bar \ -q 1Note: On macOS, the
--cafileargument MUST be set otherwise the connection will fail (as the mosquitto_sub won't be able to establish trust with the Cumulocity endpoint). On other platforms, you might be able to leave out the--cafile, or direct it to the OS's ca file, e.g. on Linux this is typically,--cafile /etc/ssl/certs/ca-certificates.crt.Expected output
Client example_UqCXbGBXHS sending CONNECT Client example_UqCXbGBXHS received CONNACK (0) Client example_UqCXbGBXHS sending PUBLISH (d0, q1, r0, m1, 'foo', ... (3 bytes)) Client example_UqCXbGBXHS received PUBACK (Mid: 1, RC:0) Client example_UqCXbGBXHS sending DISCONNECT
-
Set a device id (this will be the c8y_Serial external id used to reference the device)
DEVICE_ID=$(c8y template execute --template "'example_' + _.Char(10)")The above command just generates a randomized value for you, but you can change it to a fixed value if you want. Though we would recommend to sticking to the character set:
[A-Za-z0-9_-]. -
Enroll a device using the Cumulocity CA EST endpoint
c8y devices enroll --id "$DEVICE_ID"Note: A device managed object is created at this step, however the device user will not.
-
Use an MQTT client to publish to a custom topic on the Cumulocity MQTT service
mosquitto_pub \ -h "$C8Y_DOMAIN" \ -p 9883 \ --debug \ -i "$DEVICE_ID" \ --key "${DEVICE_ID}.key" \ --cert "${DEVICE_ID}.crt" \ --cafile /opt/homebrew/etc/ca-certificates/cert.pem \ -t foo \ -m bar \ -q 1Note: On macOS, the
--cafileargument MUST be set otherwise the connection will fail (as the mosquitto_sub won't be able to establish trust with the Cumulocity endpoint). On other platforms, you might be able to leave out the--cafile, or direct it to the OS's ca file, e.g. on Linux this is typically,--cafile /etc/ssl/certs/ca-certificates.crt.Expected output
Client example_UqCXbGBXHS sending CONNECT Client example_UqCXbGBXHS received CONNACK (0) Client example_UqCXbGBXHS sending PUBLISH (d0, q1, r0, m1, 'foo', ... (3 bytes)) Client example_UqCXbGBXHS received PUBACK (Mid: 1, RC:0) Client example_UqCXbGBXHS sending DISCONNECT