This is an automated email from the ASF dual-hosted git repository.

chrisdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x-extras.git


The following commit(s) were added to refs/heads/develop by this push:
     new 95103b0  doc: Added a README.md and website page for using the 
plc4x-server.
95103b0 is described below

commit 95103b00fb22394d6caf151b33e7bdac2be11bce
Author: Christofer Dutz <[email protected]>
AuthorDate: Tue Jun 23 23:24:28 2026 +0200

    doc: Added a README.md and website page for using the plc4x-server.
---
 plc4j/tools/plc4x-server/README.md | 186 +++++++++++++++++++++++++++++++++++++
 1 file changed, 186 insertions(+)

diff --git a/plc4j/tools/plc4x-server/README.md 
b/plc4j/tools/plc4x-server/README.md
new file mode 100644
index 0000000..e69b02a
--- /dev/null
+++ b/plc4j/tools/plc4x-server/README.md
@@ -0,0 +1,186 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+# PLC4X Server
+
+A small relay server that speaks the **PLC4X proxy protocol**. A client using 
the
+`plc4x` driver connects to this server, and the server opens the *real* 
connection to a
+PLC on its behalf and forwards reads and writes. This is useful when the PLCs 
are only
+reachable from the machine running the server (e.g. behind a firewall or on an 
isolated
+OT network), while clients live elsewhere.
+
+```
+ ┌────────────┐   plc4x proxy protocol    ┌──────────────┐   native protocol   
┌───────┐
+ │  client    │ ────────────────────────▶ │ PLC4X Server │ ──────────────────▶ 
│  PLC  │
+ │ (plc4x drv)│        TLS + auth         │              │   (s7, modbus, …)   
│       │
+ └────────────┘                           └──────────────┘                     
└───────┘
+```
+
+The server bundles **all** PLC4X drivers, so the relayed connection string can 
target any
+supported protocol (`s7`, `modbus`, `ads`, `opcua`, `simulated`, …).
+
+## Security model
+
+- **Authentication is mandatory.** Every client connection must complete a
+  username/password handshake before any operation is accepted. There is no
+  unauthenticated mode.
+- **TLS is the default transport.** Credentials and payloads are encrypted in 
transit.
+  Plaintext TCP is available only as an explicit opt-in for trusted 
networks/testing.
+
+## Building
+
+From the module directory:
+
+```bash
+mvn package
+```
+
+This produces a runnable fat-jar at:
+
+```
+target/plc4j-plc4x-server-<version>.jar
+```
+
+## Running the server
+
+```bash
+java -jar target/plc4j-plc4x-server-<version>.jar [port]
+```
+
+The listen port may be given as the first argument, or via the
+`plc4x.server.port` system property / `PLC4X_SERVER_PORT` environment variable.
+If omitted it defaults to **59837**.
+
+### First start with no configuration
+
+If you start the server without configuring credentials, it generates a 
default identity
+and prints it **once** to the console:
+
+```
+============================================================
+ No PLC4X server credentials configured - generated defaults:
+   username: toddy
+   password: 3Qm0v2yq... (randomly generated)
+ Provide plc4x.server.username/password to set your own.
+============================================================
+```
+
+Because no keystore is configured either, it also generates an ephemeral 
self-signed
+TLS certificate and logs its fingerprint so a client can trust/pin it:
+
+```
+No keystore configured - generated an ephemeral self-signed certificate.
+Server certificate SHA-256 fingerprint: B1:A5:51:F8:...:35:CE
+```
+
+> Configured credentials are **never** logged — only generated ones are 
printed.
+
+## Configuration
+
+All settings are read from system properties (`-D…`) or environment variables.
+
+| Setting        | System property                  | Environment variable     
     | Default            |
+|----------------|----------------------------------|-------------------------------|--------------------|
+| Listen port    | `plc4x.server.port`              | `PLC4X_SERVER_PORT`      
     | `59837`            |
+| Username       | `plc4x.server.username`          | `PLC4X_SERVER_USERNAME`  
     | `toddy`            |
+| Password       | `plc4x.server.password`          | `PLC4X_SERVER_PASSWORD`  
     | *(generated)*      |
+| Plaintext mode | `plc4x.server.plaintext`         | `PLC4X_SERVER_PLAINTEXT` 
     | `false` (TLS on)   |
+| TLS keystore   | `plc4x.server.keystore`          | —                        
     | *(self-signed)*    |
+| Keystore pass. | `plc4x.server.keystore-password` | —                        
     | —                  |
+
+### Example: explicit credentials + your own TLS certificate
+
+```bash
+java \
+  -Dplc4x.server.port=59837 \
+  -Dplc4x.server.username=operator \
+  -Dplc4x.server.password='s3cr3t!' \
+  -Dplc4x.server.keystore=/etc/plc4x/server.p12 \
+  -Dplc4x.server.keystore-password='keystorepass' \
+  -jar target/plc4j-plc4x-server-<version>.jar
+```
+
+The keystore must be a PKCS12 (or JKS) file containing the server's private 
key and
+certificate.
+
+### Example: plaintext (trusted network / local testing only)
+
+```bash
+java -Dplc4x.server.plaintext=true \
+     -Dplc4x.server.username=operator \
+     -Dplc4x.server.password='s3cr3t!' \
+     -jar target/plc4j-plc4x-server-<version>.jar
+```
+
+## Connecting a client
+
+A client uses the `plc4x` driver. The connection string points at the server, 
and the
+**`remote-connection-string`** parameter (URL-encoded) tells the server which 
PLC to open.
+
+### Connection string format
+
+```
+plc4x:<transport>://<server-host>:<server-port>?remote-connection-string=<url-encoded-plc-url>&username=<user>&password=<pass>[&tls.verify-ssl=false]
+```
+
+- `<transport>` is `tls` (default) or `tcp` (plaintext). `plc4x://…` without a 
prefix
+  uses the default, TLS.
+- `remote-connection-string` is the **URL-encoded** connection string the 
server should
+  open to the actual PLC.
+- `username` / `password` are mandatory.
+- `tls.verify-ssl=false` disables certificate validation — needed when the 
server uses an
+  auto-generated self-signed certificate. With a properly trusted (CA-signed) 
certificate,
+  leave it at its default (`true`).
+
+### Example (Java)
+
+Target PLC URL `s7://10.10.1.5` → URL-encoded as `s7%3A%2F%2F10.10.1.5`.
+
+```java
+String url = "plc4x:tls://server.example.com:59837"
+    + "?remote-connection-string=s7%3A%2F%2F10.10.1.5"
+    + "&username=operator"
+    + "&password=s3cr3t!"
+    + "&tls.verify-ssl=false"; // self-signed server cert
+
+try (PlcConnection connection = new 
DefaultPlcDriverManager().getConnection(url)) {
+    PlcReadRequest request = connection.readRequestBuilder()
+        .addTagAddress("value", "%DB1.DBW0:INT")
+        .build();
+    PlcReadResponse response = request.execute().get();
+    System.out.println(response.getInteger("value"));
+}
+```
+
+### Plaintext client
+
+```java
+String url = "plc4x:tcp://server.example.com:59837"
+    + "?remote-connection-string=s7%3A%2F%2F10.10.1.5"
+    + "&username=operator&password=s3cr3t!";
+```
+
+## Troubleshooting
+
+| Symptom                                                              | Cause 
/ fix                                                                           
        |
+|----------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|
+| `Server certificate not trusted … PKIX path building failed`         | TLS 
cert not trusted by the client. Add `tls.verify-ssl=false`, or trust/pin the 
server cert. |
+| Connect fails with `ACCESS_DENIED` / authentication error            | 
Missing or wrong `username`/`password`.                                         
              |
+| Connect hangs or fails immediately on a `tcp` client vs `tls` server | 
Transport mismatch — client and server must agree on TLS vs plaintext.          
              |
+| `INVALID_ADDRESS` on connect                                         | The 
server could not open the `remote-connection-string` (bad URL, PLC 
unreachable).          |

Reply via email to