PLC4X Server
The PLC4X Server is 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 the clients live elsewhere.
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:
mvn package
This produces a runnable fat-jar at target/plc4j-plc4x-server-<version>.jar.
Running the server
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 |
|
|
|
Username |
|
|
|
Password |
|
|
(generated) |
Plaintext mode |
|
|
|
TLS keystore |
|
— |
(self-signed) |
Keystore pass. |
|
— |
— |
Example: explicit credentials + your own TLS certificate
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.
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>istls(default) ortcp(plaintext).plc4x://…without a prefix uses the default, TLS. -
remote-connection-stringis the URL-encoded connection string the server should open to the actual PLC. -
username/passwordare mandatory. -
tls.verify-ssl=falsedisables 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.
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"));
}
Troubleshooting
| Symptom | Cause / fix |
|---|---|
|
TLS cert not trusted by the client. Add |
Connect fails with |
Missing or wrong |
Connect hangs or fails immediately on a |
Transport mismatch — client and server must agree on TLS vs plaintext. |
|
The server could not open the |