# Mosquitto TLS Setup There is an [official guide](https://www.chirpstack.io/docs/guides/mosquitto-tls-configuration.html) from ChirpStack, which you can cross-reference. It is fairly complete, so some details are omitted here for brevity. In the previous guide, you set up a Caddy web server to proxy the ChirpStack web interface, and you saw that Caddy automatically sets up TLS for you. This secures traffic between web browsers and ChirpStack. However, you *also* need to secure traffic between gateways and ChirpStack. Because the communication protocol between the gateways and ChirpStack is MQTT and not HTTP, security is a little bit trickier. You will still use transport-layer security (TLS) to secure the traffic, but you need to create a certificate authority (CA). The CA is, itself, a certificate with corresponding secret key which you can use to issue certificates for the Mosquitto server and all the gateways connecting to it. ## Create a CA Start by installing the CloudFlare SSL tool: ```sh sudo apt install golang-cfssl ``` Run these commands wherever you like (your home folder is fine) to create a few files: ```sh # Certificate Signing Request (CSR) to create CA # The "request" is local; no third-party involved. cat < ca-csr.json { "CN": "ChirpStack CA", "key": { "algo": "rsa", "size": 4096 } } EOF # Settings for CA creation cat < ca-config.json { "signing": { "default": { "expiry": "8760h" }, "profiles": { "server": { "expiry": "8760h", "usages": [ "signing", "key encipherment", "server auth" ] } } } } EOF ``` With those files in place, generate the CA: ```sh cfssl gencert -initca ca-csr.json | cfssljson -bare ca ``` This creates three files: - `ca.csr` - `ca.pem` - `ca-key.pem` You can discard `ca.csr`. ## (Re-)Configure ChirpStack Copy the remaining two files to a more permanent place and set ownership/permissions: ```sh mkdir -p /etc/chirpstack/certs cp ca.pem /etc/chirpstack/certs cp ca-key.pem /etc/chirpstack/certs chown -R chirpstack:chirpstack /etc/chirpstack/certs chmod 400 /etc/chirpstack/certs/* ``` Then configure ChirpStack to use the CA by modifying `/etc/chirpstack/chirpstack.toml` to have the following: ```toml [gateway] client_cert_lifetime="12months" ca_cert="/etc/chirpstack/certs/ca.pem" ca_key="/etc/chirpstack/certs/ca-key.pem" ``` The official guide also recommends editing the `[integration.mqtt.client]` section, but you don't need to in this setup. **TODO learn about and explain [downlinks](https://www.chirpstack.io/docs/chirpstack/integrations/mqtt.html#scheduling-a-downlink)** Finally, restart Chirpstack to use the updated configuration: ```sh sudo systemctl restart chirpstack ``` ## Generate MQTT Server Certificate Create a CSR for the MQTT server in the same place you created the CA, ensuring you replace the CN with your own site name: ```sh cat < mqtt-server.json { "CN": "your.site.name", "hosts": [ "your.site.name" ], "key": { "algo": "rsa", "size": 4096 } } EOF ``` Generate the certificate: ```sh cfssl gencert -ca ca.pem -ca-key ca-key.pem -config ca-config.json -profile server mqtt-server.json | cfssljson -bare mqtt-server ``` Three more files are generated: - `mqtt-server.csr` - `mqtt-server.pem` - `mqtt-server-key.pem` You can discard `mqtt-server.csr`. ## Configure MQTT Server You need to move the other two files, as well as the CA certificate, to a place where Mosquitto can access them: ```sh mkdir -p /etc/mosquitto/certs cp ca.pem /etc/mosquitto/certs cp mqtt-server.pem /etc/mosquitto/certs cp mqtt-server-key.pem /etc/mosquitto/certs chown root:mosquitto /etc/mosquitto/certs/mqtt-server-key.pem chmod 640 /etc/mosquitto/certs/mqtt-server-key.pem ``` Next, add a configuration for Mosquitto to use a local, non-TLS listener (for use by ChirpStack and for debugging) and an internet-accessible TLS listener that uses the certificate files you just copied: ```sh per_listener_settings true listener 1883 127.0.0.1 allow_anonymous true listener 8883 0.0.0.0 cafile /etc/mosquitto/certs/ca.pem certfile /etc/mosquitto/certs/mqtt-server.pem keyfile /etc/mosquitto/certs/mqtt-server-key.pem allow_anonymous false require_certificate true use_identity_as_username true acl_file /etc/mosquitto/acl ``` The `acl_file` setting references an access control list that doesn't exist yet but which will prevent gateways from reading/writing topics that don't belong to them. Create the file by running the following: ```sh cat < /etc/mosquitto/acl pattern readwrite +/gateway/%u/# pattern readwrite application/%u/# EOF ``` With the configuration files in place, restart Mosquitto: ```sh sudo systemctl restart mosquitto ``` Finally, if your server is running `ufw`, allow external traffic in to the port you configured Mosquitto to use for TLS: ```sh sudo ufw allow 8883 ``` ## Testing/Troubleshooting Once set up, you can create a Gateway in ChirpStack and generate a TLS certificate. The certificate is only shown after being created; clicking the TLS tab again later will not show the cert but will let you generate another one. ChirpStack does not store these generated certs anywhere **(TODO confirm)**. **TODO add screenshots** Save the certs as `ca.crt`, `cert.crt`, and `cert.key` onto a test machine such as your local computer or a different cloud instance. Install `mosquitto-clients` onto the test machine. On the ChirpStack server, open a terminal window and subscribe to all messages: ```sh mosquitto_sub -h localhost -t "#" -v -d ``` Keep the terminal open, and on the test machine, send a message to the `us915_1/gateway//test` topic, substituting `` accordingly: ```sh mosquitto_pub \ -h your.site.name \ -p 8883 \ --cafile ca.crt \ --cert cert.crt \ --key cert.key \ -t "us915_1/gateway//test" \ -d \ -m "hello" ``` In the terminal window on the ChirpStack server, you should see a message show up. **TODO add troubleshooting procedures and other expected output**