DK Studio/Documentation
ProductChangelog

Network requirements

This page introduces the connection model: which side initiates the connection, which ports are involved, and what an agent must be able to reach. The short version β€” the agent dials the studio, and you do not have to open a single inbound port on a bench.

Who talks to whom

   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚  DK Studio            β”‚   :3000
   β”‚  UI Β· REST Β· Socket.IOβ”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚  outbound HTTP + Socket.IO from the agent
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚  DK Studio Agent      β”‚   :3001 (its own page, local)
   β”‚  bench-01             β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Every connection is initiated by the agent. The studio never dials an agent: there is no inbound command channel, no port forwarding and no reverse tunnel in the product. The studio is the only server you expose.

Keep the studio on a trusted network

The studio's REST API answers anything that can reach port 3000, so the install belongs on the lab network. If it has to be reachable from beyond that, front it with a proxy that authenticates callers. See Security and privacy.

An agent uses two channels to the studio, both outbound:

  • Socket.IO at /api/socket.io on the studio's port, for the push path: auth, command, agent_status, device_event, ping.
  • REST on the same origin and port, for registration, authentication and the polling fallback.

If the socket cannot be established, the agent falls back to polling GET /api/agent/commands?agentId= every 5000 ms and posts results to POST /api/agent/commands/result. Both paths write the same command rows, so a blocked websocket degrades latency rather than breaking function.

Ports

PortWho listensConfigured byNotes
3000The studioPORTThe UI, the REST API and the Socket.IO endpoint, all on one port and one origin.
3001The agentAGENT_PORTThe agent's own page, on the bench.
β€”The agentAGENT_HOSTThe interface the agent binds to. Defaults to 127.0.0.1, so the page is reachable only from the bench itself unless you change it.

Socket.IO is not a separate port. It is mounted on the studio's port under the path /api/socket.io, with transports ["websocket","polling"].

The agent's page is not part of the studio's surface

The agent's page on port 3001 is a local convenience: a registration form, a serial console and a status badge. It talks to http://localhost:3001 from the browser regardless of where the browser is. You do not need to expose it, and nothing in the studio depends on it.

Outbound access

From each bench, the agent must be able to reach the studio's base URL over http or https. Those are the only schemes supported β€” the agent builds its Socket.IO URL and its REST calls from the URL you type into the registration form.

What the agent needs to reach, at the studio's host and port:

PathUsed for
/api/socket.ioThe Socket.IO handshake and the push channel.
/api/agent/registerClaiming the licence.
/api/agent/commandsThe polling fallback.
/api/agent/commands/resultReturning command results over polling.

Nothing on the studio needs to reach the bench.

Do not use a websocket-only proxy path

The Socket.IO server offers both websocket and polling. A proxy that only forwards /api/socket.io/ as an ordinary HTTP route, or that blocks upgrade requests, will break the push path. If you terminate TLS in front of the studio, forward websocket upgrades.

Proxies and TLS

The studio serves plain HTTP and does not terminate TLS itself. Terminate TLS at a reverse proxy β€” nginx, Caddy, HAProxy β€” and forward to the studio's port on the private network.

The session cookie is marked secure when NODE_ENV=production, so a production deployment without TLS will not keep sessions.

server {
    listen 443 ssl http2;
    server_name studio.lab.internal;
 
    ssl_certificate     /etc/ssl/studio.crt;
    ssl_certificate_key /etc/ssl/studio.key;
 
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host       $host;
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_read_timeout 300s;
    }
}

The long proxy_read_timeout matters: the socket sits idle between commands, and a proxy that closes idle connections will push agents onto the polling path.

The Socket.IO server is configured with CORS origin: "*" and credentials: true. The studio is meant to sit on a trusted network. If it is reachable beyond your own network, put an authenticating proxy in front of it, and see Security and privacy.

Connectivity checklist

Run these from the bench, with the studio running.

  1. The studio answers HTTP
    curl -s http://studio.lab.internal:3000/api/system/status

    Expect {"status":"ready","databaseConfigured":true,"adminCreated":true,…}.

  2. The Socket.IO endpoint answers
    curl -s "http://studio.lab.internal:3000/api/socket.io/?EIO=4&transport=polling"

    Expect an Engine.IO payload beginning with 0{.

  3. Registration is reachable
    curl -s -X POST http://studio.lab.internal:3000/api/agent/license?code=dk_l_…

    Expect "success":true with the licence's type. This does not consume the licence β€” use the agent's own registration form to register with it.

  4. The agent shows as connected

    In the studio, open Agents. The agent appears as online only while its socket is live. If the list is empty, the agent has not completed the handshake β€” check the studio's log and the agent's own console on the bench.

A polling-only agent still works

If the socket is blocked but REST works, the agent registers and executes commands through the polling path. Commands arrive on the next 5-second poll. See Agent offline.