前言
Guacamole是一个由Apache基金会开发的远程访问网关[1]。他能让客户在浏览器中使用VNC/RDP/SSH等协议来远程访问服务器。本文将会介绍下如何在宝塔面板的环境中安装Guacamole,并附上一些简单的使用案例。
实现思路
guacamole分为两个部分,一个是负责用户网页guacamole本体,基于java实现;另一个是用于协议转换的守护进程guacd,使用C语言实现。这两个相关部分依赖都比较多,所以我们使用docker安装这两个部分。
guacamole也需要连接一个外置数据库(可选Mysql、PostgresSql、SQL server)。而宝塔面板有较好的数据库配置生态,我们本次安装教程将会使用宝塔安装的postgres数据库,我们也会使用宝塔带的Nginx来负责SSL,这样可以复用宝塔的数据库/Nginx的监控、管理、自动化生态,
环境信息
本次安装基于Debian13,(其他Linux系统仍可参考本教程)。使用宝塔面板V11.8.1版本,安装的guacamole版本为1.6.0。
安装过程
基础组件安装
服务器需要先安装好宝塔面板、Nginx、Docker。这些组件的具体安装流程不在本文的涉及范围之中。但是这里要提醒下,为了避免不必要的错误,建议在宝塔中先安装Nginx,再安装Docker[2]。
安装postgres数据库
前往宝塔的软件商店、找到PostgreSQL管理器,点击安装按钮,如图1所示

安装好PostgreSQL管理器,仍然在软件商城界面,点击设置按钮,在弹出的管理器界面中,点击左侧的版本管理页签,切换到对应的页面后,选择一个版本(推荐选择列表中的最新版本),然后点击安装版本这个按钮,如图2所示。安装需要一段时间,请耐心等待,安装过程中请勿关闭当前窗口,否则会中断postgres的安装。

建立对应数据库以及数据表
我们首先在一个地方建立一个目录,比如说这个地方/var/lib/guacamole[3],本文后续相关的操作都会在这个目录下进行。
成功安装完postgres数据库后,我们就来为guacamole准备数据库。guacamole默认启动后,不会自动执行初始化数据库的相关语句,所以我们需要手动初始化数据库。执行下方的命令,我们导出数据库初始化语句。
cd /var/lib/guacamole/
docker run --rm guacamole/guacamole:1.6.0 /opt/guacamole/bin/initdb.sh --postgresql > initdb.sql
此时目录中将会生成出一个initdb.sql文件,如图3所示。

然后我们前往宝塔面板的数据库界面,选中pgSQL页签,切换到对应页面后,点击添加数据库按钮,新建一个数据库,如图4所示。本文中后续数据库名以及数据库用户名均使用值“guacamole”

创建好后,我们点击新创建出来的数据库的权限按钮,在弹出窗口中将访问权限设置为172.17.0.0/16(推荐)或者“所有人(不推荐)”[4],如图5所示。

然后我们重新回到软件商城,打开postgreSQL管理器,找到”配置修改”页签,在配置文件中查找 listen_addresses = '*'这个配置,检查该项目是否被注释掉,正常情况下应该如图6所示,如果像图7一样被注释掉了,请删除这个注释,然后点击保存后重启服务器。[5]

listen_addresses未被注释时候配置界面截图
listen_addresses被注释了的配置界面截图这里还提醒一下,宝塔的pgsql默认配置会记录所有执行过的语句到日志,长期使用下可能会塞满您的硬盘。您可以在这个配置文件最底下,将默认的下述日志配置
logging_collector = on
log_destination = 'stderr'
log_directory = '/www/server/pgsql/logs'
log_filename = 'postgresql-%Y-%m-%d.log'
log_statement = all
log_min_duration_statement = 5000
替换为下面的配置文件(只记录7天的数据库日志,自动轮转,选择性记录部分语句)
logging_collector = on
log_destination = 'stderr'
log_directory = '/www/server/pgsql/logs'
log_filename = 'postgresql-%a.log'
log_statement = 'ddl'
log_min_duration_statement = 2000
log_rotation_age = 1d
log_rotation_size = 0
log_truncate_on_rotation = on
修改完pgsql相关的配置,我们来导入数据表。重新回到/var/lib/guacamole/目录,执行下述命令。这个命令通过psql工具,将刚刚导出的initdb.sql中的初始化语句在guacamole这个数据库中执行,执行完成后的截图应该如图8所示。
sudo -u postgres /www/server/pgsql/bin/psql -d guacamole -f initdb.sql

由于我们刚刚导入数据库的时候,是使用postgres身份执行的,数据库的guacamole用户访问会有一些权限问题。我们执行下述语句将相关的权限修改下,以免后续报错。执行后的截图如图9所示
sudo -u postgres /www/server/pgsql/bin/psql -d guacamole -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO guacamole;"
sudo -u postgres /www/server/pgsql/bin/psql -d guacamole -c "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO guacamole;"
sudo -u postgres /www/server/pgsql/bin/psql -d guacamole -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO guacamole;"
sudo -u postgres /www/server/pgsql/bin/psql -d guacamole -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO guacamole;"

设置NGINX
前往宝塔面板的网站模块,新建一个站点,并为站点设置好SSL证书后,我们点击站点设置,在新界面中左侧点击反向代理模块,然后点击添加反向代理。在新弹出的窗口中,名称填写guacamole(这个名称可以随意),目标URL填写http://127.0.0.1:8080(不是https!),发送域名填写您站点的域名(当然,也可以填写127.0.0.1)。如图10所示。

点击确定后,再次前往站点的反向代理界面,点击新出来的配置的“配置文件”按钮,在弹出的配置文件详情中,在proxy_http_version 1.1; 这个配置下面,添加下面两行配置。如图11所示
proxy_cache off; # 覆盖 http 层继承下来的 proxy_cache cache_on
proxy_buffering off; # Guacamole 官方反代要求,防 HTTP 隧道被缓冲卡死
关于为何需要修改这个配置,见后文“常见问题-guacamole网页端访问一段时间后界面闪烁刷新”

启动镜像
添加好Nginx配置后,我们回到/var/lib/guacamole这个目录。在这个目录下面,我们新建一个docker-compose.yml文件,内容如下(请您将文中的“您的数据库的密码”这个地方,修改为实际的数据库密码[6])
services:
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
group_add:
- "1001"
volumes:
- ./data/drive:/drive
- ./data/record:/record
guacamole:
image: guacamole/guacamole:1.6.0
container_name: guacamole
restart: unless-stopped
depends_on:
- guacd
environment:
GUACD_HOSTNAME: guacd
POSTGRESQL_HOSTNAME: 172.17.0.1
POSTGRESQL_DATABASE: guacamole
POSTGRESQL_USER: guacamole
POSTGRESQL_PASSWORD: 您的数据库的密码
WEBAPP_CONTEXT: ROOT
RECORDING_SEARCH_PATH: /record
REMOTE_IP_VALVE_ENABLED: "true"
volumes:
- ./data/record:/record
ports:
- "127.0.0.1:8080:8080"
然后执行下方命令启动程序,启动完成后请立即完成首次使用设置!
docker compose up -d
首次使用设置
登录系统
前往刚刚设置好的站点对应的域名。可以看到如图12所示的登录界面。(如若显示错误,请看本文末尾的常见问题板块)

guacamole默认登录信息如下:
用户名:guacadmin
密码:guacadmin
登录后请立即修改管理员信息
修改管理员信息
登入系统后,点击右上角用户选项,点击设置,跳转到设置界面后,选中用户页签,点击新用户按钮。如图13

在新用户创建界面,设置好用户名与密码,并在使用权限板块中勾选全部使用权限后,点击保存按钮,如图14所示

设置完成后,退出系统,然后用我们刚刚创建的账号重新登入guacamole,登入后前往设置、用户、选中guacadmin这个选项,点击进入用户设置界面。如图15所示

滑动到页面最底部,点击删除按钮,删除原本的管理员,如图16所示

添加一个远程SSH服务器
使用管理员账号登录后,点击设置,找到连接页签,点击新建连接按钮,如图17。

在新的页面中,填写名称,然后协议选择ssh。接下来是主机名部分,输入主机名(IP地址),端口,然后我们可以选择性输入用户名和密码[7]。填写完后点击保存,如图18所示

点击保存后,便可以在首页看到这个添加后服务器。点击后即可连接。如图19所示。

点击这个服务器,即可在浏览器中远程ssh操作服务器了,如图20所示

启用操作录制功能
既然guacamole已经负责了远程连接,所以为何不让guacamole也负责记录下每次远程我们所有的操作?guacamole默认内带了操作录制功能。但是需要一些配置才能使用。我们首先前往一个远程服务器的配置(比如说我们刚刚新建的那个),找到屏幕录像选项,如图21所示

将录像路径设置为
${HISTORY_PATH}/${HISTORY_UUID}
将录像名设置为
${GUAC_DATE}-${GUAC_TIME}
设置完成后,点击保存按钮。
设置到这里,还有一些权限问题的,无法写入录像文件。我们需要修改下录像目录的权限(此操作只需进行一次,需要这样操作是因为docker启动时如果绑定挂载目录(比如本文中的data目录)不存在时,docker会自动以root身份创建这个目录,权限0755,guacamole容器中默认用户的GID是1001,UID是1001,guacd的GID是1000,UID是1000,guacd默认没有权限向这个目录写入文件)
进入/var/lib/guacamole/data目录,执行下述命令,执行命令后的显示如图22所示
chgrp -R 1001 record
chmod -R 770 record
chmod g+s record

执行完成后,可以在管理员的后台-历史-对应的连接记录,旁边,找到一个查看按钮,点击即可查看屏幕回放,如图23所示。

常见问题
guacamole网页端访问一段时间后界面闪烁刷新
问题详情
访问guacamole时,每隔一段时间整个界面就会闪烁白屏刷新。并且在浏览器开发者工具中有大量/api/session/请求的405报错,如图24所示

问题原因以及解决思路
在部署guacamole1.6.0以上的版本会出现这个问题(1.5.5等之前的不会出现这个问题)。这个问题根因出在宝塔的Nginx中。在guacamole1.6.0版本中前端新增了一个会话有效性检机制,每15s在没有活动隧道时会发一个HEAD类型的请求到/api/session/路径,来验证 token 是否有效[8]。只要这个请求返回任何失败状态(比如405),前端就认为 token 失效,从而刷新。
然而,宝塔的Nginx默认情况下,在所有站点的公共配置文件中(文件在/www/server/nginx/conf/proxy.conf/中),有一行配置”proxy_cache cache_one;“,这个配置让NGINX对反代请求进行了缓存。nginx 有个默认开启的指令 proxy_cache_convert_head,它通过把回源的 HEAD 请求改写成 GET,意图是让 HEAD 请求能复用 GET 的缓存条目。而一旦启用了请求缓存,浏览器的HEAD /api/session请求就会被Nginx改写为GET /api/session,然而guacamole这个接口不支持GET请求,所以报405报错。[9]
解决方案也很简单,直接让宝塔的Nginx不缓存guacamole即可。
解决方案
在对应站点的反代配置文件中,在location ^~ /添加如下配置
proxy_cache off; # 覆盖 http 层继承下来的 proxy_cache cache_one
proxy_buffering off; # Guacamole 官方反代要求,防 HTTP 隧道被缓冲卡死
guacamole界面打开显示错误
问题详情
直接打开显示错误两字,如图25

问题分析
您可以前往宝塔面板的docker模块,找到guacamole容器,点击更多,找到日志选项,查看容器日志(如图26)找到其中的报错信息。

常见解决方案
请您依次进行检查:
pgsql是否正常运行(在宝塔的pgsql管理器中查看pgsql状态)
对应的guacamole数据库是否允许docker所在的网段进行访问
检查docker网段是否为172.17.0.0/16
前往宝塔的安全设置,查看UFW防火墙是否放行了5432端口[10]
检查配置文件中数据库账号密码是否正确
屏幕录像会自动清理吗?
guacamole默认不会自动清理屏幕录像,您需要自行按需清理(录像文件在./data/record这个文件夹中)。
为啥登录显示”Too many failed authentication attempts”
docker版本的guacamole默认带了auth-ban组件,同一 IP 连续 5 次登录失败后封禁 300 秒,请您稍等5分钟后再尝试。