Guacamole Docker (1.6.0) – RDP Sessions Failing with “Connection to guacd timed out” on Debian 13.4 VM

I am trying to deploy Apache Guacamole (Docker) in my homelab and am encountering persistent issues establishing RDP connection. My setup is as follows:

  • Proxmox VE 9.1.6
  • Debian 13.4 VM running Docker v29.3.1
  • Guacamole 1.6.0 using Docker Compose
  • Windows 11 also running as Proxmox VM (RDP target)

To simplify troubleshooting, I reduced my Docker Compose file to below.

services:
  guacd:
    image: guacamole/guacd:latest
    container_name: guacd
    restart: unless-stopped

    healthcheck:
      test: [ "CMD-SHELL", "kill -0 1 || exit 1" ]
      interval: 10s
      timeout: 3s
      retries: 3
    command: [ "-L", "debug" ]

    networks:
      - guacnet

  postgres:
    image: postgres:16-trixie
    container_name: guacdb
    restart: unless-stopped
    environment:
      POSTGRES_DB: guacdb
      POSTGRES_USER: guacuser
      POSTGRES_PASSWORD: guacpass
    volumes:
      - ${DATADIR}/guacamole/init:/docker-entrypoint-initdb.d
      - ${DATADIR}/guacamole/db:/var/lib/postgresql/data
    networks:
      - guacnet

  guacamole:
    image: guacamole/guacamole:latest
    container_name: guacamole
    restart: unless-stopped
    depends_on:
      - guacd
      - postgres
    environment:
      LOG_LEVEL: debug
      GUACD_HOSTNAME: guacd
      GUACD_PORT: 4822

      POSTGRESQL_HOSTNAME: postgres
      POSTGRESQL_PORT: 5432
      POSTGRESQL_DATABASE: guacdb
      POSTGRESQL_USERNAME: guacuser
      POSTGRESQL_PASSWORD: guacpass
    ports:
      - "8080:8080"
    networks:
      - guacnet

networks:
  guacnet:
    driver: bridge

Now, when I start, all containers start successfully and guacd reports healthy status.

NAME        IMAGE                        COMMAND                  SERVICE     CREATED          STATUS                    PORTS
guacamole   guacamole/guacamole:latest   "/opt/guacamole/bin/…"   guacamole   41 minutes ago   Up 39 minutes             0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp
guacd       guacamole/guacd:latest       "/opt/guacamole/entr…"   guacd       39 minutes ago   Up 39 minutes (healthy)   4822/tcp
guacdb      postgres:16-trixie           "docker-entrypoint.s…"   postgres    24 hours ago     Up 39 minutes             5432/tcp

However, when initiating an RDP connection from the Guacamole web, the session fails with the following message:

The connection has been closed because the server is taking too long to respond. This is usually caused by network problems, such as spotty wireless signal, or slow network speeds. Please check your network connection and try again or contact your system administration.

Guacamole Web Error

I checked the Docker logs, and

  • guacd: No startup errors and none during Windows connection launch
guacd  | guacd[1]: INFO:    Guacamole proxy daemon (guacd) version 1.6.0 started
guacd  | guacd[1]: DEBUG:   Successfully bound AF_INET socket to host 0.0.0.0, port 4822
guacd  | guacd[1]: INFO:    Listening on host 0.0.0.0, port 4822
  • guacamole: No startup errors but error Creation of WebSocket tunnel to guacd failed: Connection to guacd timed out. during Windows connection launch
  16:59:58.138 [http-nio-8080-exec-10] DEBUG o.a.i.t.jdbc.JdbcTransaction - Opening JDBC Connection
  16:59:58.138 [http-nio-8080-exec-10] DEBUG o.a.i.d.pooled.PooledDataSource - Checked out connection 497206453 from pool.
  16:59:58.138 [http-nio-8080-exec-10] DEBUG o.a.i.d.pooled.PooledDataSource - Testing connection 497206453 ...
  16:59:58.138 [http-nio-8080-exec-10] DEBUG o.a.i.d.pooled.PooledDataSource - Connection 497206453 is GOOD!
  16:59:58.138 [http-nio-8080-exec-10] DEBUG o.a.i.t.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [org.postgresql.jdbc.PgConnection@1da2c4b5]
16:59:58.138 [http-nio-8080-exec-10] DEBUG o.a.g.a.j.c.C.insert - ==>  Preparing: INSERT INTO guacamole_connection_history ( connection_id, connection_name, remote_host, sharing_profile_id, sharing_profile_name, user_id, username, start_date, end_date ) VALUES ( ?::integer, ?, ?, ?::integer, ?, (SELECT user_id FROM guacamole_user JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.  entity_id WHERE guacamole_entity.name = ? AND guacamole_entity.type = 'USER'::guacamole_entity_type), ?, ?, ? )
16:59:58.138 [http-nio-8080-exec-10] DEBUG o.a.g.a.j.c.C.insert - ==> Parameters: 1(String), Windows(String), 192.168.7.3(String), null, null, guacadmin(String), guacadmin(String), 2026-04-15 16:59:58.137  (Timestamp), null
  16:59:58.138 [http-nio-8080-exec-10] DEBUG o.a.g.a.j.c.C.insert - <==    Updates: 1
  16:59:58.139 [http-nio-8080-exec-10] DEBUG o.a.g.a.j.c.C.select - ==>  Preparing: SELECT connection_id, parameter_name, parameter_value FROM guacamole_connection_parameter WHERE connection_id = ?::integer
  16:59:58.139 [http-nio-8080-exec-10] DEBUG o.a.g.a.j.c.C.select - ==> Parameters: 1(String)
  16:59:58.140 [http-nio-8080-exec-10] DEBUG o.a.g.a.j.c.C.select - <==      Total: 2
  16:59:58.140 [http-nio-8080-exec-10] DEBUG o.a.g.net.InetGuacamoleSocket - Connecting to guacd at 192.168.2.51:3389.
  17:00:13.143 [http-nio-8080-exec-10] DEBUG o.a.g.a.j.c.C.updateEndDate - ==>  Preparing: UPDATE guacamole_connection_history SET end_date = ? WHERE history_id = ?::integer
  17:00:13.143 [http-nio-8080-exec-10] DEBUG o.a.g.a.j.c.C.updateEndDate - ==> Parameters: 2026-04-15 17:00:13.143(Timestamp), 12(Integer)
  17:00:13.144 [http-nio-8080-exec-10] DEBUG o.a.g.a.j.c.C.updateEndDate - <==    Updates: 1
17:00:13.144 [http-nio-8080-exec-10] DEBUG o.m.g.t.TransactionalMethodInterceptor - [Intercepted method: public org.apache.guacamole.net.GuacamoleTunnel org.apache.guacamole.auth.jdbc.tunnel.AbstractGuacamoleTunnelService.getGuacamoleTunnel(org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser,org.apache.guacamole.auth.jdbc.connection.ModeledConnection,org.apache.guacamole.protocol.  GuacamoleClientInformation,java.util.Map<java.lang.String, java.lang.String>) throws org.apache.guacamole.GuacamoleException] - SqlSession of thread: 42 rolling back
  17:00:13.144 [http-nio-8080-exec-10] DEBUG o.a.i.t.jdbc.JdbcTransaction - Rolling back JDBC Connection [org.postgresql.jdbc.PgConnection@1da2c4b5]
17:00:13.144 [http-nio-8080-exec-10] DEBUG o.m.g.t.TransactionalMethodInterceptor - [Intercepted method: public org.apache.guacamole.net.GuacamoleTunnel org.apache.guacamole.auth.jdbc.tunnel.AbstractGuacamoleTunnelService.getGuacamoleTunnel(org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser,org.apache.guacamole.auth.jdbc.connection.ModeledConnection,org.apache.guacamole.protocol.  GuacamoleClientInformation,java.util.Map<java.lang.String, java.lang.String>) throws org.apache.guacamole.GuacamoleException] - SqlSession of thread: 42 terminated its life-cycle, closing it
  17:00:13.144 [http-nio-8080-exec-10] DEBUG o.a.i.t.jdbc.JdbcTransaction - Resetting autocommit to true on JDBC Connection [org.postgresql.jdbc.PgConnection@1da2c4b5]
  17:00:13.144 [http-nio-8080-exec-10] DEBUG o.a.i.t.jdbc.JdbcTransaction - Closing JDBC Connection [org.postgresql.jdbc.PgConnection@1da2c4b5]
  17:00:13.144 [http-nio-8080-exec-10] DEBUG o.a.i.d.pooled.PooledDataSource - Testing connection 497206453 ...
  17:00:13.145 [http-nio-8080-exec-10] DEBUG o.a.i.d.pooled.PooledDataSource - Connection 497206453 is GOOD!
  17:00:13.145 [http-nio-8080-exec-10] DEBUG o.a.i.d.pooled.PooledDataSource - Returned connection 497206453 to pool.
  17:00:13.145 [http-nio-8080-exec-10] ERROR o.a.g.w.GuacamoleWebSocketTunnelEndpoint - Creation of WebSocket tunnel to guacd failed: Connection to guacd timed out.
  17:00:13.145 [http-nio-8080-exec-10] DEBUG o.a.g.w.GuacamoleWebSocketTunnelEndpoint - Error connecting WebSocket tunnel.
  org.apache.guacamole.GuacamoleUpstreamTimeoutException: Connection to guacd timed out.
      at org.apache.guacamole.io.ReaderGuacamoleReader.read(ReaderGuacamoleReader.java:180)
      at org.apache.guacamole.io.ReaderGuacamoleReader.readInstruction(ReaderGuacamoleReader.java:195)
      at org.apache.guacamole.protocol.ConfiguredGuacamoleSocket.expect(ConfiguredGuacamoleSocket.java:153)
      at org.apache.guacamole.protocol.ConfiguredGuacamoleSocket.<init>(ConfiguredGuacamoleSocket.java:223)
      at org.apache.guacamole.auth.jdbc.tunnel.AbstractGuacamoleTunnelService.assignGuacamoleTunnel(AbstractGuacamoleTunnelService.java:553)
      at org.apache.guacamole.auth.jdbc.tunnel.AbstractGuacamoleTunnelService.getGuacamoleTunnel(AbstractGuacamoleTunnelService.java:713)
      at org.mybatis.guice.transactional.TransactionalMethodInterceptor.invoke(TransactionalMethodInterceptor.java:100)
      at org.apache.guacamole.auth.jdbc.connection.ConnectionService.connect(ConnectionService.java:543)
      at org.apache.guacamole.auth.jdbc.connection.ModeledConnection.connect(ModeledConnection.java:274)
      at org.apache.guacamole.tunnel.TunnelRequestService.createConnectedTunnel(TunnelRequestService.java:216)
      at org.apache.guacamole.tunnel.TunnelRequestService.createTunnel(TunnelRequestService.java:352)
      at org.apache.guacamole.tunnel.websocket.RestrictedGuacamoleWebSocketTunnelEndpoint.createTunnel(RestrictedGuacamoleWebSocketTunnelEndpoint.java:113)
      at org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint.onOpen(GuacamoleWebSocketTunnelEndpoint.java:200)
      at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:131)
      at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:981)
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1854)
      at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
      at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:973)
      at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:491)
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
      at java.base/java.lang.Thread.run(Thread.java:1583)
  Caused by: java.net.SocketTimeoutException: Read timed out
      at java.base/sun.nio.ch.NioSocketImpl.timedRead(NioSocketImpl.java:278)
      at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:304)
      at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:346)
      at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:796)
      at java.base/java.net.Socket$SocketInputStream.read(Socket.java:1099)
      at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:350)
      at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:393)
      at java.base/sun.nio.cs.StreamDecoder.lockedRead(StreamDecoder.java:217)
      at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:171)
      at java.base/java.io.InputStreamReader.read(InputStreamReader.java:188)
      at org.apache.guacamole.io.ReaderGuacamoleReader.read(ReaderGuacamoleReader.java:169)
      ... 20 common frames omitted

I initially suspected this might be due to network level issues, so I checked the following:

Connection from guacamole to guacd:

$ docker exec -it guacamole bash
guacamole@057cfe8c2e92:/opt/guacamole$ echo > /dev/tcp/guacd/4822 && echo "OK: Connected"
OK: Connected

Connection from guacd to Windows host:

docker exec -it guacd sh
/ $ nc -vz 192.168.2.51 3389
Connection to 192.168.2.51 3389 port [tcp/ms-wbt-server] succeeded!

After checking online, I also did below but no success:

  • Disabled Windows Defender Firewall
    • Disabled Windows Network Level Authentication (NLA)
    • Disabled Debian nftables

Despite doing all this the exact same error is returned. At this stage, I am not sure what other factors might be causing this issue. I am wondering if this could be related to network configuration within the Proxmox VM environmen, like bridge settings, NIC type, MTU, or VirtIO behavior or whether there is a Guacamole limitation or compatibility issue when connecting to other VMs hosted on the same Proxmox node.

I would really appreciate any guidance or suggestions in resolving this issue.

Thank you!