Skip to content

Fix terminal WebSocket handshake failure via platform-ui nginx for /api/containers/*/terminal/ws #1337

@rowan-stein

Description

@rowan-stein

User request

Terminal access fails when running from prebuilt images (repo: agynio/bootstrap). Creating a terminal session via POST /api/containers/{id}/terminal/sessions succeeds, but the WebSocket connection to /api/containers/{id}/terminal/ws?... fails. Running from sources (repo: agynio/platform) works. Tested with latest main and build 0.14.4.

Research findings

Most plausible root cause: the prebuilt platform-ui image’s nginx does not forward WebSocket Upgrade/Connection headers for /api routes, while the terminal stream endpoint is under /api/containers/{id}/terminal/ws. Session creation (HTTP) works; WS handshake fails at the proxy.

Source reference:

  • platform-ui nginx template: platform/packages/platform-ui/docker/nginx.conf.template
  • location /socket.io has Upgrade/Connection headers, but location /api does not; in fact it sets proxy_set_header Connection "".

Proposed fix (minimal)

Add a dedicated nginx location (placed before location /api) that enables WS upgrade for the terminal endpoint:

location ~ ^/api/containers/[^/]+/terminal/ws$ {
    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_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_read_timeout 60s;
    proxy_pass ${API_UPSTREAM};
}

Implementation plan

  1. Update platform/packages/platform-ui/docker/nginx.conf.template with the WS-enabled location above.
  2. Build and publish a new platform-ui image (e.g., ghcr.io/agynio/platform-ui:0.14.5).
  3. Verify WS handshake returns 101 Switching Protocols and terminal works end-to-end.
  4. Update agynio/bootstrap docker-compose to pin the new platform-ui tag.

Notes

  • Quick validation: bypass UI proxy and connect WS directly to platform-server to confirm upstream works; inspect nginx logs for non-101 responses on the WS endpoint pre-fix.
  • This change should not affect other /api routes; it targets only the terminal WS path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions