├── .gitignore ├── config ├── ca-csr.json ├── mqtt-broker │ └── certificate.json ├── chirpstack-gateway-bridge │ └── basicstation │ │ └── certificate.json └── ca-config.json ├── docker-compose.yml ├── Dockerfile-devel ├── set-hosts.sh ├── Makefile └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # generated certificates 2 | certs/* 3 | 4 | # hidden files 5 | .* 6 | -------------------------------------------------------------------------------- /config/ca-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "ChirpStack CA", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | chirpstack-certificates: 3 | build: 4 | context: . 5 | dockerfile: Dockerfile-devel 6 | volumes: 7 | - ./:/chirpstack-certificates 8 | -------------------------------------------------------------------------------- /config/mqtt-broker/certificate.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "mqtt-broker", 3 | "hosts": [ 4 | "127.0.0.1", 5 | "localhost" 6 | ], 7 | "key": { 8 | "algo": "rsa", 9 | "size": 2048 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Dockerfile-devel: -------------------------------------------------------------------------------- 1 | FROM alpine:edge 2 | 3 | WORKDIR /chirpstack-certificates 4 | 5 | RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories 6 | RUN apk add --no-cache make curl jq cfssl bash 7 | -------------------------------------------------------------------------------- /config/chirpstack-gateway-bridge/basicstation/certificate.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "chirpstack-gateway-bridge", 3 | "hosts": [ 4 | "127.0.0.1", 5 | "localhost" 6 | ], 7 | "key": { 8 | "algo": "rsa", 9 | "size": 2048 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /config/ca-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "signing": { 3 | "default": { 4 | "expiry": "8760h" 5 | }, 6 | "profiles": { 7 | "client": { 8 | "expiry": "8760h", 9 | "usages": [ 10 | "signing", 11 | "key encipherment", 12 | "client auth" 13 | ] 14 | }, 15 | "server": { 16 | "expiry": "8760h", 17 | "usages": [ 18 | "signing", 19 | "key encipherment", 20 | "server auth" 21 | ] 22 | }, 23 | "signing": { 24 | "expiry": "8760h", 25 | "usages": [ 26 | "signing", 27 | "key encipherment" 28 | ] 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /set-hosts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [[ ( $@ == "--help") || $@ == "-h" ]] 6 | then 7 | echo "Usage: $0 path/to/certificate.json host-one,host-two,host-three" 8 | exit 0 9 | fi 10 | 11 | jq_hosts_command() { 12 | local HOSTS=$1 13 | local INDEX=0 14 | local COMMAND=".hosts=[]" 15 | local HOSTS_LIST=$(echo ${HOSTS} | sed -n 1'p' | tr ',' '\n') 16 | for HOST in ${HOSTS_LIST} 17 | do 18 | COMMAND="${COMMAND} | .hosts[${INDEX}]=\"${HOST}\"" 19 | INDEX=$(( ${INDEX} + 1 )) 20 | done 21 | 22 | echo "$COMMAND" 23 | } 24 | 25 | echo "Configuring '${1}' with hosts '${2}'" 26 | COMMAND=$(jq_hosts_command "${2}") 27 | contents=$(eval jq \'${COMMAND}\' ${1}) 28 | echo "${contents}" > ${1} -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MQTT_BROKER_HOSTS ?= 127.0.0.1,localhost 2 | CHIRPSTACK_GATEWAY_BRIDGE_HOSTS ?= 127.0.0.1,localhost 3 | 4 | make: certs/ca \ 5 | certs/chirpstack-gateway-bridge/basicstation \ 6 | certs/mqtt-broker 7 | 8 | set-hosts: 9 | ./set-hosts.sh config/mqtt-broker/certificate.json $(MQTT_BROKER_HOSTS) 10 | ./set-hosts.sh config/chirpstack-gateway-bridge/basicstation/certificate.json $(CHIRPSTACK_GATEWAY_BRIDGE_HOSTS) 11 | 12 | docker: 13 | docker compose run --rm chirpstack-certificates 14 | 15 | clean: 16 | rm -rf certs 17 | 18 | certs/ca: 19 | mkdir -p certs/ca 20 | cfssl gencert -initca config/ca-csr.json | cfssljson -bare certs/ca/ca 21 | 22 | certs/chirpstack-gateway-bridge/basicstation: certs/ca 23 | mkdir -p certs/chirpstack-gateway-bridge/basicstation 24 | 25 | # basicstation websocket server certificate 26 | cfssl gencert -ca certs/ca/ca.pem -ca-key certs/ca/ca-key.pem -config config/ca-config.json -profile server config/chirpstack-gateway-bridge/basicstation/certificate.json | cfssljson -bare certs/chirpstack-gateway-bridge/basicstation/basicstation 27 | 28 | certs/mqtt-broker: certs/ca 29 | mkdir -p certs/mqtt-broker 30 | 31 | # MQTT broker / server certificate 32 | cfssl gencert -ca certs/ca/ca.pem -ca-key certs/ca/ca-key.pem -config config/ca-config.json -profile server config/mqtt-broker/certificate.json | cfssljson -bare certs/mqtt-broker/mqtt-broker 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChirpStack certificates 2 | 3 | This repository contains configuration to generate certificates that can be 4 | used by [ChirpStack](https://www.chirpstack.io/) for securing gateway 5 | connections and the per-application MQTT integration connections: 6 | 7 | * Generating a "common authority" for 8 | * Signing (client-)certificates 9 | * Validating (client-)certificates 10 | * Server-certificate for the ChirpStack Gateway Bridge to use mTLS if configured with the Basics Station backend 11 | * Server-certificate for the MQTT broker to allow mTLS based authentication and authorization for 12 | * Gateways connecting over MQTT (certificate per Gateway ID) 13 | * Per-application MQTT integrations (certificate per Application ID) 14 | 15 | ## Requirements 16 | 17 | For generating the certificates, [cfssl](https://github.com/cloudflare/cfssl) 18 | is used. Make sure you have this tool installed. 19 | 20 | To modify the hosts using the `set-hosts` command you will need 21 | [jq](https://stedolan.github.io/jq/) installed. 22 | 23 | ## Modifying hosts 24 | 25 | You can modify all `certificate.json` files at once with specific hosts with the 26 | `make set-hosts` command: 27 | 28 | ``` 29 | MQTT_BROKER_HOSTS=127.0.0.1,localhost,mqtt.example.com \ 30 | CHIRPSTACK_GATEWAY_BRIDGE_HOSTS=127.0.0.1,localhost,cgwb.example.com \ 31 | make set-hosts 32 | ``` 33 | 34 | The `make set-hosts` accepts the following environment variables: 35 | 36 | * `MQTT_BROKER_HOSTS`: comma-separated list of hostnames for the MQTT broker 37 | * `CHIRPSTACK_GATEWAY_BRIDGE_HOSTS`: comma-separated list of hostnames for the ChirpStack Gateway Bridge (Basics Station backend) 38 | 39 | In case the environment variable is not specified, then it will fallback to 40 | `127.0.0.1,localhost`. 41 | 42 | ## Modifying hosts using Docker Compose 43 | 44 | Using Docker Compose, you can use the following command: 45 | 46 | ``` 47 | docker-compose run --rm \ 48 | -e MQTT_BROKER_HOSTS="localhost,mqtt.example.com" \ 49 | -e CHIRPSTACK_GATEWAY_BRIDGE_HOSTS="localhost,cgwb.example.com" \ 50 | chirpstack-certificates make set-hosts 51 | ``` 52 | 53 | ## Generating certificates 54 | 55 | Simply run `make` to generate all certificates. All certificates will be 56 | written to the `certs` folder. See also the `Makefile` for all commands 57 | being executed. 58 | 59 | You probably want to make changes to the `certificate.json` files under 60 | `config`. Please see [https://cfssl.org](https://cfssl.org) for documentation 61 | about the `cfssl` usage. 62 | 63 | ## Generating certificates using Docker Compose 64 | 65 | An alternate way to generate the certificates that does not require to have the 66 | different dependencies installed is by using docker (you will need docker, of course). 67 | 68 | ``` 69 | docker-compose run --rm chirpstack-certificates make 70 | ``` 71 | 72 | ## Certificates 73 | 74 | ### certs/ca 75 | 76 | This directory contains the CA certificate and private key that you must configure 77 | in the `chirpstack.toml` configuration, such that it can generate 78 | client-certificates for gateways and application integrations. 79 | 80 | The CA certificate must also be configured in the MQTT broker and by the 81 | ChirpStack Gateway Bridge Basics Station backend (if used) to validate the 82 | client-certificate of connecting clients. 83 | 84 | ### certs/chirpstack-gateway-bridge/basicstation 85 | 86 | This directory contains the server-certificate and private key used by the 87 | ChirpStack Gateway Bridge Basics Station backend (if used). 88 | 89 | ### certs/mqtt-broker 90 | 91 | This directory contains the server-certificate and private key used by the 92 | MQTT broker. 93 | 94 | ## Configuration examples 95 | 96 | Note that the filenames in the example refer to the filenames as being used 97 | in the `certs/` directory (not including the names of the directories). 98 | 99 | The examples assume that you will copy the generated certificates to the 100 | appropriate directories, and that you will set the correct file-permissions. 101 | 102 | ### ChirpStack 103 | 104 | To enable creating client-certificates for gateways through the web-interface, 105 | you must configure the `[gateway]` section in the `chirpstack.toml` 106 | configuration: 107 | 108 | ```toml 109 | [gateway] 110 | client_cert_lifetime="12months" 111 | ca_cert="/etc/chirpstack/certs/ca.pem" 112 | ca_key="/etc/chirpstack/certs/ca-key.pem" 113 | ``` 114 | 115 | To enable creating client-certificates for (per application) MQTT integrations, 116 | you must configure the `[integration.mqtt.client]` section in the 117 | `chirpstack.toml` configuration: 118 | 119 | ```toml 120 | [integration.mqtt.client] 121 | client_cert_lifetime="12months" 122 | ca_cert="/etc/chirpstack/certs/ca.pem" 123 | ca_key="/etc/chirpstack/certs/ca-key.pem" 124 | ``` 125 | 126 | ### ChirpStack Gateway Bridge 127 | 128 | To enable TLS and validating gateway client-certificates of incoming 129 | Basics Station connections, you must configure the 130 | `[backend.basicstation]` section in the `chirpstack-gateway-bridge.toml` 131 | configuration: 132 | 133 | ```toml 134 | [backend.basic_station] 135 | tls_cert="/etc/chirpstack-gateway-bridge/certs/basicstation.pem" 136 | tls_key="/etc/chirpstack-gateway-bridge/certs/basicstation-key.pem" 137 | ca_cert="/etc/chirpstack-gateway-bridge/certs/ca.pem" 138 | ``` 139 | 140 | ### Mosquitto 141 | 142 | To enable TLS and validating client-certificates of incoming MQTT connections 143 | (gateways and per-application MQTT integrations), you must configure a TLS 144 | listener. Example: 145 | 146 | `/etc/mosquitto/acl`: 147 | 148 | ``` 149 | pattern readwrite +/gateway/%u/# 150 | pattern readwrite application/%u/# 151 | ``` 152 | 153 | `/etc/mosquitto/conf.d/listeners.conf`: 154 | 155 | ``` 156 | per_listener_settings true 157 | 158 | listener 1883 127.0.0.1 159 | allow_anonymous true 160 | 161 | listener 8883 0.0.0.0 162 | cafile /etc/mosquitto/certs/ca.pem 163 | certfile /etc/mosquitto/certs/mqtt-broker.pem 164 | keyfile /etc/mosquitto/certs/mqtt-broker-key.pem 165 | allow_anonymous false 166 | require_certificate true 167 | use_identity_as_username true 168 | acl_file /etc/mosquitto/acl 169 | ``` 170 | 171 | For more information, please refer to the [Mosquitto TLS configuration guide](https://www.chirpstack.io/docs/guides/mosquitto-tls-configuration.html). --------------------------------------------------------------------------------