From b63447f4fe3481ee0b02818cd2af434915d35bb4 Mon Sep 17 00:00:00 2001 From: Panos Kalogeropoulos
Date: Sat, 18 Oct 2025 17:40:33 +0200
Subject: [PATCH 1/7] Update documentation to include changes needed to locally
run the central instance and edge gateway Docker profiles for development
---
.../gateway-tunnelling-setup.md | 154 ++++++++++++++++++
1 file changed, 154 insertions(+)
diff --git a/docs/developer-guide/gateway-tunnelling-setup.md b/docs/developer-guide/gateway-tunnelling-setup.md
index 7413a953..f9aecac1 100644
--- a/docs/developer-guide/gateway-tunnelling-setup.md
+++ b/docs/developer-guide/gateway-tunnelling-setup.md
@@ -39,3 +39,157 @@ This guide describes the steps necessary to setup the gateway tunnelling functio
* Set TCP port range in sish service (to allow raw TCP tunnelling)
* Allow inbound access to port `2222` and to the TCP port range exposed on the instance
* Generate or select existing SSH private key and add this to the deployment image and set SISH variable: `--private-keys-directory`
+
+# Gateway Tunnelling Development Setup
+
+To run the manager locally as an edge gateway, to test the gateway tunnelling functionality, two different docker compose profiles need to be running:
+* The central instance profile (e.g. `docker-compose.central.yml`) needs to be running to provide the sish server functionality, with the correctly configured environment variables
+* The proxy development profile needs to be running to provide the correctly setup proxying functionality, with the correctly configured environment variables
+
+You need to setup the SSH keys as described in the "Edge Instance Setup" section above.
+
+For the **central instance** profile:
+
+Run the main `docker-compose.yml` file with `OR_HOSTNAME=localhost`, and add the following:
+* In the proxy service:
+ * SISH_PORT: 8090
+ * SISH_HOST: sish
+* In the manager service:
+ * Remove the manager port exports for metrics etc., and add ``8008:8008`` to allow attaching the debugger from the IDE
+ * Optionally, set the manager to be built from context ``./manager/build/install/manager``, so that code changes are reflected during Docker image rebuild (after running `./gradlew clean installDist`)
+ * Add `OR_JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8008"` to allow remote debugging from the IDE
+ * `OR_METRICS_ENABLED: false`
+ * `OR_GATEWAY_TUNNEL_SSH_HOSTNAME: "localhost"`
+ * `OR_GATEWAY_TUNNEL_SSH_PORT: 2222`
+ * `OR_GATEWAY_TUNNEL_TCP_START: 9000`
+ * `OR_GATEWAY_TUNNEL_HOSTNAME: "localhost"`
+ * `OR_GATEWAY_TUNNEL_AUTO_CLOSE_MINUTES: 2`
+* Add the ``sish`` service, as found in `deploy.yml`, and modify:
+ * Add volume ``./deployment:/deployment`` so that you can map the SSH keys as instructed above
+
+For the **proxy development profile**:
+
+* Modify the proxy service:
+ * Instead of extending from `deploy.yml`, instead use the default proxy image:
+ * `image: openremote/proxy:latest`
+ * Set the ports of the proxy service, so that they dont clash with the central instance's proxy ports:
+ * `- "444:443"`
+ * `- "808:80"`
+ * Set the sish environment variables:
+ * `SISH_HOST: sish`
+ * `SISH_PORT: 8090`
+
+The above setup should make the **`org.openremote.test.gateway.GatewayTest#Gateway Tunneling Edge Gateway Integration test`** pass when run from the IDE or via Gradle.
+
+
+Here's a Git diff you can apply to your local `docker-compose.central.yml` and `docker-compose.proxy.dev.yml` files to get the above setup:
+
+
+Click to see the patch
+
+```diff
+Index: profile/dev-proxy.yml
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+diff --git a/profile/dev-proxy.yml b/profile/dev-proxy.yml
+--- a/profile/dev-proxy.yml (revision 2b8c46b824dd3a48657fd71defd6699dac65b98e)
++++ b/profile/dev-proxy.yml (date 1760799651300)
+@@ -16,9 +16,16 @@
+ services:
+
+ proxy:
+- extends:
+- file: deploy.yml
+- service: proxy
++# extends:
++# file: deploy.yml
++# service: proxy
++ image: openremote/proxy:latest
++ depends_on:
++ keycloak:
++ condition: service_healthy
++ ports:
++ - "444:443"
++ - "808:80"
+ environment:
+ MANAGER_HOST: 'host.docker.internal'
+ # Uncomment to use sish in development
+Index: docker-compose.yml
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+diff --git a/docker-compose.yml b/docker-compose.yml
+--- a/docker-compose.yml (revision 2b8c46b824dd3a48657fd71defd6699dac65b98e)
++++ b/docker-compose.yml (date 1760798570417)
+@@ -33,7 +33,8 @@
+ DOMAINNAMES: ${OR_ADDITIONAL_HOSTNAMES:-}
+ # USE A CUSTOM PROXY CONFIG - COPY FROM https://raw.githubusercontent.com/openremote/proxy/main/haproxy.cfg
+ #HAPROXY_CONFIG: '/data/proxy/haproxy.cfg'
+-
++ SISH_PORT: 8090
++ SISH_HOST: sish
+ postgresql:
+ restart: always
+ image: openremote/postgresql:${POSTGRESQL_VERSION:-latest}
+@@ -57,16 +58,19 @@
+
+
+ manager:
+-# privileged: true
++ # privileged: true
+ restart: always
+ image: openremote/manager:${MANAGER_VERSION:-latest}
++# build:
++# context: ./manager/build/install/manager
+ depends_on:
+ keycloak:
+ condition: service_healthy
+ ports:
+- - "127.0.0.1:8405:8405" # Localhost metrics access
+- - "${PRIVATE_IP:-127.0.0.1}:8405:8405" # Allows to also expose metrics on a given IP address,
++# - "127.0.0.1:8405:8405" # Localhost metrics access
++# - "${PRIVATE_IP:-127.0.0.1}:8405:8405" # Allows to also expose metrics on a given IP address,
+ # intended to be IP of the interface of the private subnet of the EC2 VM
++ - "8008:8008"
+ environment:
+ OR_SETUP_TYPE:
+ OR_ADMIN_PASSWORD:
+@@ -77,11 +81,19 @@
+ OR_EMAIL_X_HEADERS:
+ OR_EMAIL_FROM:
+ OR_EMAIL_ADMIN:
+- OR_METRICS_ENABLED: ${OR_METRICS_ENABLED:-true}
++ OR_METRICS_ENABLED: ${OR_METRICS_ENABLED:-false}
+ OR_HOSTNAME: ${OR_HOSTNAME:-localhost}
+ OR_ADDITIONAL_HOSTNAMES:
+ OR_SSL_PORT: ${OR_SSL_PORT:--1}
+ OR_DEV_MODE: ${OR_DEV_MODE:-false}
++ OR_JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8008"
++
++
++ OR_GATEWAY_TUNNEL_SSH_HOSTNAME: "localhost"
++ OR_GATEWAY_TUNNEL_SSH_PORT: 2222
++ OR_GATEWAY_TUNNEL_TCP_START: 9000
++ OR_GATEWAY_TUNNEL_HOSTNAME: "localhost"
++ OR_GATEWAY_TUNNEL_AUTO_CLOSE_MINUTES: 2
+
+ # The following variables will configure the demo
+ OR_FORECAST_SOLAR_API_KEY:
+@@ -90,3 +102,10 @@
+ OR_SETUP_IMPORT_DEMO_AGENT_VELBUS:
+ volumes:
+ - manager-data:/storage
++
++ sish:
++ extends:
++ file: profile/deploy.yml
++ service: sish
++ volumes:
++ - ./deployment:/deployment
+```
+
+
Date: Tue, 28 Oct 2025 16:10:35 +0200
Subject: [PATCH 2/7] Update documentation to include changes needed to locally
run the central instance and edge gateway Docker profiles for development
---
.../gateway-tunnelling-setup.md | 133 +-----------------
1 file changed, 4 insertions(+), 129 deletions(-)
diff --git a/docs/developer-guide/gateway-tunnelling-setup.md b/docs/developer-guide/gateway-tunnelling-setup.md
index f9aecac1..9e69965e 100644
--- a/docs/developer-guide/gateway-tunnelling-setup.md
+++ b/docs/developer-guide/gateway-tunnelling-setup.md
@@ -44,7 +44,7 @@ This guide describes the steps necessary to setup the gateway tunnelling functio
To run the manager locally as an edge gateway, to test the gateway tunnelling functionality, two different docker compose profiles need to be running:
* The central instance profile (e.g. `docker-compose.central.yml`) needs to be running to provide the sish server functionality, with the correctly configured environment variables
-* The proxy development profile needs to be running to provide the correctly setup proxying functionality, with the correctly configured environment variables
+* The testing (unproxied) development profile needs to be running to allow the manager to run properly in the IDE.
You need to setup the SSH keys as described in the "Edge Instance Setup" section above.
@@ -55,7 +55,7 @@ Run the main `docker-compose.yml` file with `OR_HOSTNAME=localhost`, and add the
* SISH_PORT: 8090
* SISH_HOST: sish
* In the manager service:
- * Remove the manager port exports for metrics etc., and add ``8008:8008`` to allow attaching the debugger from the IDE
+ * Add ``8008:8008`` to allow attaching the debugger from the IDE
* Optionally, set the manager to be built from context ``./manager/build/install/manager``, so that code changes are reflected during Docker image rebuild (after running `./gradlew clean installDist`)
* Add `OR_JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8008"` to allow remote debugging from the IDE
* `OR_METRICS_ENABLED: false`
@@ -65,131 +65,6 @@ Run the main `docker-compose.yml` file with `OR_HOSTNAME=localhost`, and add the
* `OR_GATEWAY_TUNNEL_HOSTNAME: "localhost"`
* `OR_GATEWAY_TUNNEL_AUTO_CLOSE_MINUTES: 2`
* Add the ``sish`` service, as found in `deploy.yml`, and modify:
- * Add volume ``./deployment:/deployment`` so that you can map the SSH keys as instructed above
+ * Add volume ``./deployment:/deployment`` so that you can map the SSH keys that were generated above
-For the **proxy development profile**:
-
-* Modify the proxy service:
- * Instead of extending from `deploy.yml`, instead use the default proxy image:
- * `image: openremote/proxy:latest`
- * Set the ports of the proxy service, so that they dont clash with the central instance's proxy ports:
- * `- "444:443"`
- * `- "808:80"`
- * Set the sish environment variables:
- * `SISH_HOST: sish`
- * `SISH_PORT: 8090`
-
-The above setup should make the **`org.openremote.test.gateway.GatewayTest#Gateway Tunneling Edge Gateway Integration test`** pass when run from the IDE or via Gradle.
-
-
-Here's a Git diff you can apply to your local `docker-compose.central.yml` and `docker-compose.proxy.dev.yml` files to get the above setup:
-
-
-Click to see the patch
-
-```diff
-Index: profile/dev-proxy.yml
-IDEA additional info:
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
-<+>UTF-8
-===================================================================
-diff --git a/profile/dev-proxy.yml b/profile/dev-proxy.yml
---- a/profile/dev-proxy.yml (revision 2b8c46b824dd3a48657fd71defd6699dac65b98e)
-+++ b/profile/dev-proxy.yml (date 1760799651300)
-@@ -16,9 +16,16 @@
- services:
-
- proxy:
-- extends:
-- file: deploy.yml
-- service: proxy
-+# extends:
-+# file: deploy.yml
-+# service: proxy
-+ image: openremote/proxy:latest
-+ depends_on:
-+ keycloak:
-+ condition: service_healthy
-+ ports:
-+ - "444:443"
-+ - "808:80"
- environment:
- MANAGER_HOST: 'host.docker.internal'
- # Uncomment to use sish in development
-Index: docker-compose.yml
-IDEA additional info:
-Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
-<+>UTF-8
-===================================================================
-diff --git a/docker-compose.yml b/docker-compose.yml
---- a/docker-compose.yml (revision 2b8c46b824dd3a48657fd71defd6699dac65b98e)
-+++ b/docker-compose.yml (date 1760798570417)
-@@ -33,7 +33,8 @@
- DOMAINNAMES: ${OR_ADDITIONAL_HOSTNAMES:-}
- # USE A CUSTOM PROXY CONFIG - COPY FROM https://raw.githubusercontent.com/openremote/proxy/main/haproxy.cfg
- #HAPROXY_CONFIG: '/data/proxy/haproxy.cfg'
--
-+ SISH_PORT: 8090
-+ SISH_HOST: sish
- postgresql:
- restart: always
- image: openremote/postgresql:${POSTGRESQL_VERSION:-latest}
-@@ -57,16 +58,19 @@
-
-
- manager:
--# privileged: true
-+ # privileged: true
- restart: always
- image: openremote/manager:${MANAGER_VERSION:-latest}
-+# build:
-+# context: ./manager/build/install/manager
- depends_on:
- keycloak:
- condition: service_healthy
- ports:
-- - "127.0.0.1:8405:8405" # Localhost metrics access
-- - "${PRIVATE_IP:-127.0.0.1}:8405:8405" # Allows to also expose metrics on a given IP address,
-+# - "127.0.0.1:8405:8405" # Localhost metrics access
-+# - "${PRIVATE_IP:-127.0.0.1}:8405:8405" # Allows to also expose metrics on a given IP address,
- # intended to be IP of the interface of the private subnet of the EC2 VM
-+ - "8008:8008"
- environment:
- OR_SETUP_TYPE:
- OR_ADMIN_PASSWORD:
-@@ -77,11 +81,19 @@
- OR_EMAIL_X_HEADERS:
- OR_EMAIL_FROM:
- OR_EMAIL_ADMIN:
-- OR_METRICS_ENABLED: ${OR_METRICS_ENABLED:-true}
-+ OR_METRICS_ENABLED: ${OR_METRICS_ENABLED:-false}
- OR_HOSTNAME: ${OR_HOSTNAME:-localhost}
- OR_ADDITIONAL_HOSTNAMES:
- OR_SSL_PORT: ${OR_SSL_PORT:--1}
- OR_DEV_MODE: ${OR_DEV_MODE:-false}
-+ OR_JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8008"
-+
-+
-+ OR_GATEWAY_TUNNEL_SSH_HOSTNAME: "localhost"
-+ OR_GATEWAY_TUNNEL_SSH_PORT: 2222
-+ OR_GATEWAY_TUNNEL_TCP_START: 9000
-+ OR_GATEWAY_TUNNEL_HOSTNAME: "localhost"
-+ OR_GATEWAY_TUNNEL_AUTO_CLOSE_MINUTES: 2
-
- # The following variables will configure the demo
- OR_FORECAST_SOLAR_API_KEY:
-@@ -90,3 +102,10 @@
- OR_SETUP_IMPORT_DEMO_AGENT_VELBUS:
- volumes:
- - manager-data:/storage
-+
-+ sish:
-+ extends:
-+ file: profile/deploy.yml
-+ service: sish
-+ volumes:
-+ - ./deployment:/deployment
-```
-
-
Date: Tue, 25 Nov 2025 14:55:41 +0100 Subject: [PATCH 3/7] Copilot corrections --- docs/developer-guide/gateway-tunnelling-setup.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/developer-guide/gateway-tunnelling-setup.md b/docs/developer-guide/gateway-tunnelling-setup.md index 9e69965e..566947fb 100644 --- a/docs/developer-guide/gateway-tunnelling-setup.md +++ b/docs/developer-guide/gateway-tunnelling-setup.md @@ -55,8 +55,8 @@ Run the main `docker-compose.yml` file with `OR_HOSTNAME=localhost`, and add the * SISH_PORT: 8090 * SISH_HOST: sish * In the manager service: - * Add ``8008:8008`` to allow attaching the debugger from the IDE - * Optionally, set the manager to be built from context ``./manager/build/install/manager``, so that code changes are reflected during Docker image rebuild (after running `./gradlew clean installDist`) + * Add `8008:8008` to allow attaching the debugger from the IDE + * Optionally, set the manager to be built from context `./manager/build/install/manager`, so that code changes are reflected during Docker image rebuild (after running `./gradlew clean installDist`) * Add `OR_JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8008"` to allow remote debugging from the IDE * `OR_METRICS_ENABLED: false` * `OR_GATEWAY_TUNNEL_SSH_HOSTNAME: "localhost"` @@ -64,7 +64,7 @@ Run the main `docker-compose.yml` file with `OR_HOSTNAME=localhost`, and add the * `OR_GATEWAY_TUNNEL_TCP_START: 9000` * `OR_GATEWAY_TUNNEL_HOSTNAME: "localhost"` * `OR_GATEWAY_TUNNEL_AUTO_CLOSE_MINUTES: 2` -* Add the ``sish`` service, as found in `deploy.yml`, and modify: - * Add volume ``./deployment:/deployment`` so that you can map the SSH keys that were generated above +* Add the `sish` service, as found in `deploy.yml`, and modify: + * Add volume `./deployment:/deployment` so that you can map the SSH keys that were generated above -The above setup should make the **`org.openremote.test.gateway.GatewayTest#Gateway Tunneling Edge Gateway Integration test`** pass when run from the IDE or via Gradle. \ No newline at end of file +The above setup should make the **`org.openremote.test.gateway.GatewayTest#Gateway Tunnelling Edge Gateway Integration test`** pass when run from the IDE or via Gradle. \ No newline at end of file From b5c14537fe9fa65659bb275b860bcc5b45ad4c84 Mon Sep 17 00:00:00 2001 From: Panos Kalogeropoulos
Date: Tue, 25 Nov 2025 15:05:35 +0100
Subject: [PATCH 4/7] Add `/etc/hosts` file edit description
---
docs/developer-guide/gateway-tunnelling-setup.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/docs/developer-guide/gateway-tunnelling-setup.md b/docs/developer-guide/gateway-tunnelling-setup.md
index 566947fb..75c81e89 100644
--- a/docs/developer-guide/gateway-tunnelling-setup.md
+++ b/docs/developer-guide/gateway-tunnelling-setup.md
@@ -67,4 +67,10 @@ Run the main `docker-compose.yml` file with `OR_HOSTNAME=localhost`, and add the
* Add the `sish` service, as found in `deploy.yml`, and modify:
* Add volume `./deployment:/deployment` so that you can map the SSH keys that were generated above
+The routing of requests from the central instance to the gateway looks like this: Central Instance --> Sish --> Gateway Proxy --> Keycloak/Manager
+
+For the "Sish --> Gateway Proxy" requests to be routed correctly, we need to edit the local `/etc/hosts` file to route the
Date: Tue, 25 Nov 2025 15:58:30 +0100
Subject: [PATCH 5/7] Fixes
---
.../gateways-and-devices/auto-provisioning.md | 333 +++++++++++++++++-
1 file changed, 325 insertions(+), 8 deletions(-)
diff --git a/docs/user-guide/gateways-and-devices/auto-provisioning.md b/docs/user-guide/gateways-and-devices/auto-provisioning.md
index 17b59521..ed480462 100644
--- a/docs/user-guide/gateways-and-devices/auto-provisioning.md
+++ b/docs/user-guide/gateways-and-devices/auto-provisioning.md
@@ -17,11 +17,33 @@ When the auto provisioning is configured, an authorised device will first create
There are two basic mechanisms for client provisioning.
-### X.509 Client Certificate
+### X.509 Client Certificate (Message-Based)
-Supports the industry standard X.509 certificate authentication mechanism where each client has a unique client certificate that is signed by a CA certificate that must also be registered within OpenRemote, the certificate must contain a unique ID within the CN attribute of the certificate. OpenRemote then verifies the certificate and CN attribute presented during provisioning.
+Supports the industry standard X.509 certificate authentication mechanism where each client has a unique client certificate that is signed by a CA certificate that must also be registered within OpenRemote. The certificate must contain a unique ID within the CN attribute of the certificate. OpenRemote then verifies the certificate and CN attribute presented during provisioning.
-This is the most secure authentication mechanism but adds complexity to the manufacturing/flashing process.
+In this mode, the client connects to the standard MQTT broker (default port 1883) and sends the certificate as part of the provisioning message payload.
+
+This is a secure authentication mechanism but adds complexity to the manufacturing/flashing process.
+
+### mTLS (Mutual TLS) Client Certificate
+
+Supports automatic provisioning using mTLS (Mutual TLS) at the transport layer. This is the **recommended approach** for production deployments as it provides the highest security by enforcing client authentication at the TLS handshake level before any MQTT communication occurs.
+
+In this mode, clients connect to a dedicated mTLS MQTT broker endpoint (default port 8884) and present their client certificate during the TLS handshake. OpenRemote extracts the realm from the certificate's `OU` (Organizational Unit) field and the unique device ID from the `CN` (Common Name) field.
+
+**Key differences from message-based X.509:**
+* Client authentication happens at the TLS layer (before MQTT connection)
+* No need to send certificate in the provisioning message
+* Realm is extracted from the certificate's `OU` field
+* Device ID is extracted from the certificate's `CN` field
+* More secure as unauthenticated clients cannot connect at all
+* Simpler provisioning message format
+
+**Certificate Requirements for mTLS:**
+* Client certificate must be signed by a CA registered in OpenRemote
+* Certificate subject must include: `CN=
Date: Tue, 25 Nov 2025 16:00:33 +0100
Subject: [PATCH 7/7] Fixes
---
.../gateways-and-devices/auto-provisioning.md | 333 +-----------------
1 file changed, 8 insertions(+), 325 deletions(-)
diff --git a/docs/user-guide/gateways-and-devices/auto-provisioning.md b/docs/user-guide/gateways-and-devices/auto-provisioning.md
index ed480462..17b59521 100644
--- a/docs/user-guide/gateways-and-devices/auto-provisioning.md
+++ b/docs/user-guide/gateways-and-devices/auto-provisioning.md
@@ -17,33 +17,11 @@ When the auto provisioning is configured, an authorised device will first create
There are two basic mechanisms for client provisioning.
-### X.509 Client Certificate (Message-Based)
+### X.509 Client Certificate
-Supports the industry standard X.509 certificate authentication mechanism where each client has a unique client certificate that is signed by a CA certificate that must also be registered within OpenRemote. The certificate must contain a unique ID within the CN attribute of the certificate. OpenRemote then verifies the certificate and CN attribute presented during provisioning.
+Supports the industry standard X.509 certificate authentication mechanism where each client has a unique client certificate that is signed by a CA certificate that must also be registered within OpenRemote, the certificate must contain a unique ID within the CN attribute of the certificate. OpenRemote then verifies the certificate and CN attribute presented during provisioning.
-In this mode, the client connects to the standard MQTT broker (default port 1883) and sends the certificate as part of the provisioning message payload.
-
-This is a secure authentication mechanism but adds complexity to the manufacturing/flashing process.
-
-### mTLS (Mutual TLS) Client Certificate
-
-Supports automatic provisioning using mTLS (Mutual TLS) at the transport layer. This is the **recommended approach** for production deployments as it provides the highest security by enforcing client authentication at the TLS handshake level before any MQTT communication occurs.
-
-In this mode, clients connect to a dedicated mTLS MQTT broker endpoint (default port 8884) and present their client certificate during the TLS handshake. OpenRemote extracts the realm from the certificate's `OU` (Organizational Unit) field and the unique device ID from the `CN` (Common Name) field.
-
-**Key differences from message-based X.509:**
-* Client authentication happens at the TLS layer (before MQTT connection)
-* No need to send certificate in the provisioning message
-* Realm is extracted from the certificate's `OU` field
-* Device ID is extracted from the certificate's `CN` field
-* More secure as unauthenticated clients cannot connect at all
-* Simpler provisioning message format
-
-**Certificate Requirements for mTLS:**
-* Client certificate must be signed by a CA registered in OpenRemote
-* Certificate subject must include: `CN=