Description
After upgrading from Metic v2.6.0 to v3.0, Metic reports my Meticulous machine as connected and normal REST-based functionality works, but realtime telemetry is unavailable.
The dashboard:
- Reports the machine as connected
- Can successfully send commands to the machine, including starting a shot
- Can retrieve shot history and profiles
- Does not display live temperature/status telemetry
Investigation indicates that Metic v3 correctly communicates with the machine's REST API on port 80, but its realtime/Socket.IO client continues attempting to connect to port 8080.
My Meticulous firmware exposes both the REST API and Socket.IO endpoint through nginx on port 80. Port 8080 is closed.
This appears related to, but more narrowly scoped than, the previous port-8080 connectivity issue in v2.6 (#573) . In v3, REST connectivity appears to successfully use port 80 while the realtime telemetry connection still attempts port 8080.
Environment
Metic
- Version: 3.0
- Docker image:
ghcr.io/hessius/meticai:3.0
- Fresh v3 installation with a new persistent data volume
- Hosted as a Docker application on TrueNAS / HexOS
- Metic and the machine are on the same LAN
Meticulous
- IP:
192.168.1.47
- Firmware:
0.2.24-376-ga90e330
- Machine software:
2026-08-06 00:33:44
- Image channel: beta
- Image:
2026M1359-beta
The machine currently exposes its API through nginx on port 80. Port 8080 refuses connections.
Steps to reproduce
-
Configure Metic v3 with the Meticulous machine IP directly:
METICULOUS_IP: 192.168.1.47
-
Start Metic.
-
Open the dashboard.
-
Observe that Metic reports the machine as connected.
-
Send a machine command from Metic, such as Start Shot.
The command succeeds.
-
Observe the realtime telemetry area of the dashboard.
Live temperature/status data is unavailable.
Expected behavior
Once Metic establishes connectivity with the machine, it should also establish its realtime Socket.IO connection using the working machine API endpoint.
For a machine whose API is exposed on port 80, I would expect realtime telemetry to connect through:
http://<METICULOUS_IP>/socket.io/
or otherwise use the same detected/fallback port as the REST API.
Actual behavior
REST functionality works through port 80:
- Machine connectivity: Working
- Shot history: Working
- Profile retrieval: Working
- Machine commands: Working
- Machine shown as connected: Yes
Realtime telemetry does not:
- Metic attempts to connect to machine port
8080
- TCP connection is refused
- Metic continues retrying
- Live temperature/status data remains unavailable
Diagnostic findings
1. The machine's Socket.IO endpoint is healthy on port 80
From the TrueNAS host, I tested:
curl -sv --connect-timeout 5 'http://192.168.1.47/socket.io/?EIO=4&transport=polling'
This returns HTTP 200 with a valid Engine.IO handshake beginning with:
0{"sid":"...","upgrades":["websocket"],"pingTimeout":60000,"pingInterval":10000,"maxPayload":1000000}
2. Socket.IO is reachable from Metic's exact Docker network namespace
I also tested from a temporary curl container sharing Metic v3's network namespace:
docker run --rm --network container:ix-metic-v3-metic-1 curlimages/curl:latest -sv --connect-timeout 5 'http://192.168.1.47/socket.io/?EIO=4&transport=polling'
This also returns HTTP 200 and a valid Engine.IO handshake.
This appears to rule out host networking, Docker networking, and nginx reachability.
3. A direct Socket.IO client receives live telemetry correctly
I connected an independent Socket.IO client to:
http://192.168.1.47
from the same Docker network namespace as Metic.
The machine continuously emitted valid status and sensors events, including live temperature data.
Example status event:
EVENT: status {'name': 'heating', 'sensors': {'p': 0.0, 'f': 0.0, 'w': -19.63, 't': 92.96, 'g': 0.0}, ...}
Example sensors event:
EVENT: sensors {'t_ext_1': 118.69, 't_ext_2': 123.66, 't_bar_up': 95.97, 't_bar_mu': 95.73, 't_bar_md': 92.68, 't_bar_down': 88.14, 't_tube': 93.13, ...}
So the Meticulous machine is actively publishing realtime telemetry on the port-80 Socket.IO endpoint.
4. Packet capture shows Metic REST traffic on port 80
While refreshing the Metic dashboard, packet capture showed requests including:
POST /api/v1/history HTTP/1.1
GET /api/v1/history HTTP/1.1
GET /api/v1/profile/list HTTP/1.1
All of these were sent to:
192.168.1.47:80
No request to /socket.io/ was observed on port 80 during the capture.
5. Metic repeatedly attempts port 8080
A simultaneous capture of port 8080 showed repeated connection attempts from the Metic container.
Examples:
16:54:12.266335 172.16.5.2.39290 > 192.168.1.47.8080: Flags [S]
16:54:12.275459 192.168.1.47.8080 > 172.16.5.2.39290: Flags [R.]
16:54:13.057110 172.16.5.2.39292 > 192.168.1.47.8080: Flags [S]
16:54:13.081733 192.168.1.47.8080 > 172.16.5.2.39292: Flags [R.]
16:54:14.786069 172.16.5.2.41080 > 192.168.1.47.8080: Flags [S]
16:54:14.906642 192.168.1.47.8080 > 172.16.5.2.41080: Flags [R.]
The attempts continue with increasing delays, eventually settling into approximately 15-second retries.
This appears consistent with a realtime reconnect/backoff loop rather than a one-time port probe.
SockertIO v HTTP capture.txt
Workaround / confirmation
As a diagnostic test, I added a small socat sidecar that exposes both ports 80 and 8080 internally and forwards both to the machine's actual port 80. This is the same workaround outlined in #573.
The proxy configuration is effectively:
proxy:80 → machine:80
proxy:8080 → machine:80
Metic is then configured with:
METICULOUS_IP: metic-machine-proxy
The proxy service uses:
socat TCP-LISTEN:80,fork,reuseaddr TCP:192.168.1.47:80
socat TCP-LISTEN:8080,fork,reuseaddr TCP:192.168.1.47:80
With this configuration, realtime dashboard telemetry immediately begins working.
Pointing METICULOUS_IP directly back to 192.168.1.47, where port 8080 is unavailable, causes realtime telemetry to disappear again.
This A/B test seems to strongly indicate that the realtime client is attempting to use port 8080 even though the machine's working Socket.IO endpoint is available on port 80.
Possible cause
Based on the behavior above, it appears that the REST and realtime machine connections may be using different port-selection logic in v3.
The REST path appears to correctly communicate through port 80, while the realtime Socket.IO client appears to retain or construct a connection to:
http://<METICULOUS_IP>:8080
instead of using the port detected as functional for the machine API.
If v3 already contains port probing/fallback logic, it may be that the detected API port is not being propagated to the realtime/Socket.IO client.
Suggested behavior
It may make sense for REST and realtime communication to share the same detected machine API port.
For example:
- Probe port
8080
- If successful, use
8080 for REST and Socket.IO
- If unsuccessful, probe port
80
- If port
80 succeeds:
- Use port
80 for REST
- Use port
80 for Socket.IO
This would avoid a situation where REST connectivity reports the machine as fully connected while realtime telemetry silently fails on a different port.
Impact
The issue is somewhat misleading because Metic reports the machine as connected and machine controls continue functioning normally.
A user may therefore see:
- Machine connected: Yes
- Machine commands: Working
- Shot history: Working
- Profiles: Working
- Live telemetry: Missing
There is no obvious indication in the dashboard that the realtime connection is repeatedly failing on port 8080.
Additional note
I observed another v3 realtime-temperature behavior after restoring telemetry through the proxy. I believe that is a separate issue in the telemetry processing path and will report it independently rather than mixing it into this report.
Disclaimer
I am not an experienced developer, and most of the investigation, packet-capture analysis, code-level reasoning, and workaround development for this issue was performed with substantial assistance from GPT-5.6 Sol.
I have personally reproduced and verified the behaviors and test results described above in my environment, but any conclusions about the underlying implementation or proposed fix should be treated as informed observations rather than an authoritative code-level diagnosis.
Description
After upgrading from Metic v2.6.0 to v3.0, Metic reports my Meticulous machine as connected and normal REST-based functionality works, but realtime telemetry is unavailable.
The dashboard:
Investigation indicates that Metic v3 correctly communicates with the machine's REST API on port 80, but its realtime/Socket.IO client continues attempting to connect to port 8080.
My Meticulous firmware exposes both the REST API and Socket.IO endpoint through nginx on port 80. Port 8080 is closed.
This appears related to, but more narrowly scoped than, the previous port-8080 connectivity issue in v2.6 (#573) . In v3, REST connectivity appears to successfully use port 80 while the realtime telemetry connection still attempts port 8080.
Environment
Metic
ghcr.io/hessius/meticai:3.0Meticulous
192.168.1.470.2.24-376-ga90e3302026-08-06 00:33:442026M1359-betaThe machine currently exposes its API through nginx on port 80. Port 8080 refuses connections.
Steps to reproduce
Configure Metic v3 with the Meticulous machine IP directly:
METICULOUS_IP: 192.168.1.47Start Metic.
Open the dashboard.
Observe that Metic reports the machine as connected.
Send a machine command from Metic, such as Start Shot.
The command succeeds.
Observe the realtime telemetry area of the dashboard.
Live temperature/status data is unavailable.
Expected behavior
Once Metic establishes connectivity with the machine, it should also establish its realtime Socket.IO connection using the working machine API endpoint.
For a machine whose API is exposed on port 80, I would expect realtime telemetry to connect through:
http://<METICULOUS_IP>/socket.io/or otherwise use the same detected/fallback port as the REST API.
Actual behavior
REST functionality works through port 80:
Realtime telemetry does not:
8080Diagnostic findings
1. The machine's Socket.IO endpoint is healthy on port 80
From the TrueNAS host, I tested:
curl -sv --connect-timeout 5 'http://192.168.1.47/socket.io/?EIO=4&transport=polling'This returns HTTP 200 with a valid Engine.IO handshake beginning with:
2. Socket.IO is reachable from Metic's exact Docker network namespace
I also tested from a temporary curl container sharing Metic v3's network namespace:
docker run --rm --network container:ix-metic-v3-metic-1 curlimages/curl:latest -sv --connect-timeout 5 'http://192.168.1.47/socket.io/?EIO=4&transport=polling'This also returns HTTP 200 and a valid Engine.IO handshake.
This appears to rule out host networking, Docker networking, and nginx reachability.
3. A direct Socket.IO client receives live telemetry correctly
I connected an independent Socket.IO client to:
http://192.168.1.47from the same Docker network namespace as Metic.
The machine continuously emitted valid
statusandsensorsevents, including live temperature data.Example
statusevent:Example
sensorsevent:So the Meticulous machine is actively publishing realtime telemetry on the port-80 Socket.IO endpoint.
4. Packet capture shows Metic REST traffic on port 80
While refreshing the Metic dashboard, packet capture showed requests including:
POST /api/v1/history HTTP/1.1GET /api/v1/history HTTP/1.1GET /api/v1/profile/list HTTP/1.1All of these were sent to:
192.168.1.47:80No request to
/socket.io/was observed on port 80 during the capture.5. Metic repeatedly attempts port 8080
A simultaneous capture of port 8080 showed repeated connection attempts from the Metic container.
Examples:
The attempts continue with increasing delays, eventually settling into approximately 15-second retries.
This appears consistent with a realtime reconnect/backoff loop rather than a one-time port probe.
SockertIO v HTTP capture.txt
Workaround / confirmation
As a diagnostic test, I added a small
socatsidecar that exposes both ports 80 and 8080 internally and forwards both to the machine's actual port 80. This is the same workaround outlined in #573.The proxy configuration is effectively:
proxy:80→machine:80proxy:8080→machine:80Metic is then configured with:
METICULOUS_IP: metic-machine-proxyThe proxy service uses:
socat TCP-LISTEN:80,fork,reuseaddr TCP:192.168.1.47:80socat TCP-LISTEN:8080,fork,reuseaddr TCP:192.168.1.47:80With this configuration, realtime dashboard telemetry immediately begins working.
Pointing
METICULOUS_IPdirectly back to192.168.1.47, where port 8080 is unavailable, causes realtime telemetry to disappear again.This A/B test seems to strongly indicate that the realtime client is attempting to use port 8080 even though the machine's working Socket.IO endpoint is available on port 80.
Possible cause
Based on the behavior above, it appears that the REST and realtime machine connections may be using different port-selection logic in v3.
The REST path appears to correctly communicate through port 80, while the realtime Socket.IO client appears to retain or construct a connection to:
http://<METICULOUS_IP>:8080instead of using the port detected as functional for the machine API.
If v3 already contains port probing/fallback logic, it may be that the detected API port is not being propagated to the realtime/Socket.IO client.
Suggested behavior
It may make sense for REST and realtime communication to share the same detected machine API port.
For example:
80808080for REST and Socket.IO8080succeeds:80for REST80for Socket.IOThis would avoid a situation where REST connectivity reports the machine as fully connected while realtime telemetry silently fails on a different port.
Impact
The issue is somewhat misleading because Metic reports the machine as connected and machine controls continue functioning normally.
A user may therefore see:
There is no obvious indication in the dashboard that the realtime connection is repeatedly failing on port 8080.
Additional note
I observed another v3 realtime-temperature behavior after restoring telemetry through the proxy. I believe that is a separate issue in the telemetry processing path and will report it independently rather than mixing it into this report.
Disclaimer
I am not an experienced developer, and most of the investigation, packet-capture analysis, code-level reasoning, and workaround development for this issue was performed with substantial assistance from GPT-5.6 Sol.
I have personally reproduced and verified the behaviors and test results described above in my environment, but any conclusions about the underlying implementation or proposed fix should be treated as informed observations rather than an authoritative code-level diagnosis.