diff --git a/.github/workflows/build-dockerhub.yml b/.github/workflows/build-dockerhub.yml index dd8896a..a9b918d 100644 --- a/.github/workflows/build-dockerhub.yml +++ b/.github/workflows/build-dockerhub.yml @@ -15,25 +15,29 @@ jobs: environment: PROD steps: - - name: Checkout the code - uses: actions/checkout@v1 + - name: Checkout code + uses: actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 + + - name: Cache Docker layers + uses: actions/cache@v4 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Print SSL Certificates - run: | - echo "CARGO_SERVER_SSL_CA: ${{ secrets.SERVER_SSL_CA }}" - - name: Build and deploy images env: CARGO_SERVER_SSL_CA: ${{ secrets.SERVER_SSL_CA }} diff --git a/Dockerfile b/Dockerfile index aa4cb34..192bffe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,30 +5,45 @@ ARG CARGO_SERVER_SSL_CA ARG CARGO_SERVER_SSL_CERT ARG CARGO_SERVER_SSL_KEY -# Decode the base64 encoded environment variables -RUN export CARGO_SERVER_SSL_CA=$(echo "${CARGO_SERVER_SSL_CA}" | base64 -d) -RUN export CARGO_SERVER_SSL_CERT=$(echo "${CARGO_SERVER_SSL_CERT}" | base64 -d) -RUN export CARGO_SERVER_SSL_KEY=$(echo "${CARGO_SERVER_SSL_KEY}" | base64 -d) - -# Validate that the SSL environment variables are set -RUN /bin/bash -c 'if [ -z "$CARGO_SERVER_SSL_CA" ]; then echo "Error: CARGO_SERVER_SSL_CA is not set"; exit 1; fi && \ - if [ -z "$CARGO_SERVER_SSL_CERT" ]; then echo "Error: CARGO_SERVER_SSL_CERT is not set"; exit 1; fi && \ - if [ -z "$CARGO_SERVER_SSL_KEY" ]; then echo "Error: CARGO_SERVER_SSL_KEY is not set"; exit 1; fi' - -RUN apt update -RUN apt install -y protobuf-compiler libssl-dev gcc pkg-config build-essential cmake clang - +# Decode the base64 encoded environment variables and validate them +RUN export CARGO_SERVER_SSL_CA=$(echo "${CARGO_SERVER_SSL_CA}" | base64 -d) && + export CARGO_SERVER_SSL_CERT=$(echo "${CARGO_SERVER_SSL_CERT}" | base64 -d) && + export CARGO_SERVER_SSL_KEY=$(echo "${CARGO_SERVER_SSL_KEY}" | base64 -d) && + if [ -z "$CARGO_SERVER_SSL_CA" ]; then + echo "Error: CARGO_SERVER_SSL_CA is not set" + exit 1 + fi && + if [ -z "$CARGO_SERVER_SSL_CERT" ]; then + echo "Error: CARGO_SERVER_SSL_CERT is not set" + exit 1 + fi && + if [ -z "$CARGO_SERVER_SSL_KEY" ]; then + echo "Error: CARGO_SERVER_SSL_KEY is not set" + exit 1 + fi + +# Install dependencies +RUN apt update && apt install -y --no-install-recommends \ + protobuf-compiler libssl-dev gcc pkg-config build-essential cmake musl-tools && + rm -rf /var/lib/apt/lists/* + +# Install cross +RUN cargo install cross + +# Set up the build environment RUN mkdir -p ${TAGOIO_SOURCE_FOLDER} WORKDIR ${TAGOIO_SOURCE_FOLDER} ADD . ${TAGOIO_SOURCE_FOLDER} RUN touch .env -RUN cargo build --release +# Build the project +RUN cross build --release # Unset the SSL environment variables RUN unset CARGO_SERVER_SSL_CA CARGO_SERVER_SSL_CERT CARGO_SERVER_SSL_KEY +# Install runtime dependencies FROM debian:bookworm-slim ARG TAGOIO_SOURCE_FOLDER="/tago-io" diff --git a/README.md b/README.md index f185cae..2e941a0 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Before you begin, ensure you have: 1. **Create a Network in TagoIO**: - Navigate to Integrations in your TagoIO Profile and create a new Network. + - Enter the [Middleware Endpoint](#middleware-endpoint-optional) for your Relay (Optional, allows publishing from TagoIO to the Relay). - Enable Serial and write a Payload Parser: ```js if (Array.isArray(payload)) { @@ -68,6 +69,7 @@ Before you begin, ensure you have: serial = payload_received?.metadata.topic.split("/").pop(); } ``` + 2. **Generate Network Token**: Generate and save the Network Token. 3. **Create a Connector**: Create a Connector for your Network. 4. **Generate Authorization**: Navigate to Devices > Authorizations in TagoIO and generate an authorization token. @@ -128,29 +130,9 @@ tagoio-relay start [--verbose info,error,mqtt,network] [--config-path /path/to/c To configure the TagoIO MQTT Relay, you can either use environment variables or edit the `config.toml` file directly. Below are the available configuration parameters: -### Environment Variables - -```sh -export TAGOIO__RELAY__NETWORK_TOKEN="Your-Network-Token" -export TAGOIO__RELAY__AUTHORIZATION_TOKEN="Your-Authorization-Token" -export TAGOIO__RELAY__TAGOIO_URL="https://api.tago.io" -export TAGOIO__RELAY__DOWNLINK_PORT="3001" -export TAGOIO__RELAY__MQTT__CLIENT_ID="tagoio-relay" -export TAGOIO__RELAY__MQTT__TLS_ENABLED="false" -export TAGOIO__RELAY__MQTT__ADDRESS="localhost" -export TAGOIO__RELAY__MQTT__PORT="1883" -export TAGOIO__RELAY__MQTT__SUBSCRIBE="/tago/# /topic/+" -export TAGOIO__RELAY__MQTT__USERNAME="my-username" -export TAGOIO__RELAY__MQTT__PASSWORD="my-password" -export TAGOIO__RELAY__MQTT__BROKER_TLS_CA="" -export TAGOIO__RELAY__MQTT__BROKER_TLS_CERT="" -export TAGOIO__RELAY__MQTT__BROKER_TLS_KEY="" -export TAGOIO__RELAY__CONFIG_PATH="./.config/.tagoio-mqtt-relay.toml" -``` - ### `.tagoio-mqtt-relay.toml` -The `.tagoio-mqtt-relay.toml` file contains the Relay parameters. Here is a reference: +The `.tagoio-mqtt-relay.toml` file generated by the `init` command contains the Relay parameters. Here is a reference: ```toml [relay] @@ -175,6 +157,52 @@ password="my-password" # broker_tls_cert="" # broker_tls_key="" ``` +### Environment Variables + +```sh +export TAGOIO__RELAY__NETWORK_TOKEN="Your-Network-Token" +export TAGOIO__RELAY__AUTHORIZATION_TOKEN="Your-Authorization-Token" +export TAGOIO__RELAY__TAGOIO_URL="https://api.tago.io" +export TAGOIO__RELAY__DOWNLINK_PORT="3001" +export TAGOIO__RELAY__MQTT__CLIENT_ID="tagoio-relay" +export TAGOIO__RELAY__MQTT__TLS_ENABLED="false" +export TAGOIO__RELAY__MQTT__ADDRESS="localhost" +export TAGOIO__RELAY__MQTT__PORT="1883" +export TAGOIO__RELAY__MQTT__SUBSCRIBE="/tago/# /topic/+" +export TAGOIO__RELAY__MQTT__USERNAME="my-username" +export TAGOIO__RELAY__MQTT__PASSWORD="my-password" +export TAGOIO__RELAY__MQTT__BROKER_TLS_CA="" +export TAGOIO__RELAY__MQTT__BROKER_TLS_CERT="" +export TAGOIO__RELAY__MQTT__BROKER_TLS_KEY="" +export TAGOIO__RELAY__CONFIG_PATH="./.config/.tagoio-mqtt-relay.toml" +``` + +### Middleware Endpoint (Optional) +The Middleware Endpoint allows the TagoIO MQTT Relay to receive messages from TagoIO through a secure TLS connection. This feature is optional but can be very useful for advanced integrations. + +The Relay comes with pre-set TLS certificates configured during build time, so you don't need to set them up manually. + +#### Setting Up the Middleware Endpoint + +1. **Public HTTPs Endpoint:**: + Ensure that you have a public HTTPs endpoint that TagoiO can reach. +2. **Configure the Downlink Port:** + The default port for the Middleware Endpoint is 3001, but you can change this by setting the downlink_port in your (configuration file)[#configuration-file-and-environment-variables]. +Repl +3. **Local Testing**: + For local testing, you can use tools like ngrok or tailscale to expose your local server to the internet securely. + + **Using Ngrok:** + ```bash + ngrok tcp 3001 + ``` + + **Using Tailscale:** + ```bash + ngrok funnel 3001 + ``` +4. **Network Middleware Endpoint:** + To enable the Middleware Endpoint, you need to set the field `Middleware Endpoint` in your Network at TagoIO to the generated URL (e.g., https://abcd1234.ngrok.io) as your Middleware Endpoint in TagoIO. ## License diff --git a/src/services/mqttrelay.rs b/src/services/mqttrelay.rs index 19da723..de6cd00 100644 --- a/src/services/mqttrelay.rs +++ b/src/services/mqttrelay.rs @@ -55,7 +55,7 @@ pub async fn run_mqtt_relay_connection(relay_cfg: Arc, publish_rx: return; } let backoff_duration = calculate_backoff(backoff_retry_attempts); - log::info!(target: "mqtt", "Retrying in {:?}", backoff_duration); + log::warn!(target: "mqtt", "Disconnected from MQTT broker. Retrying in {:?}", backoff_duration); publish_task.abort(); sleep(backoff_duration).await; backoff_retry_attempts += 1;