想在浏览器里临时打开一个隔离的 Chrome、Firefox 或 Linux 桌面,又不想把真实电脑、Cookie 和下载文件暴露给未知网站,Kasm Workspaces 是一套很有针对性的自托管方案。它会为用户按需创建容器化工作区,浏览器只负责显示远程画面;会话结束后,可以自动销毁整个环境。
这篇教程使用 Kasm Workspaces 1.17.0,在 Ubuntu 24.04 VPS 上完成单机安装、Caddy HTTPS、浏览器隔离、用户与权限、资源限制、数据库备份和安全升级。Kasm 的安装器会管理多组 Docker 服务,适合放在专用 VPS 上,不建议硬塞进已经运行大量生产容器的主机。
Kasm 的核心不是“在网页里再打开一个网页”,而是把浏览器、Linux 桌面或远程服务器会话放进受控工作区。常见用途包括:
- 打开不可信链接,避免下载内容直接落到本机;
- 给临时员工提供统一浏览器或 Linux 桌面;
- 为开发、培训、客服准备一次性工作环境;
- 通过浏览器连接已有的 RDP、VNC 或 SSH 主机;
- 限制复制粘贴、文件上传下载、音频和会话时长;
- 为不同用户组分配不同镜像和资源额度。
如果需求只是集中管理固定的 RDP、VNC、SSH 连接,Apache Guacamole 教程通常更轻;Kasm 的优势是能按需创建隔离容器,并在会话结束后销毁。它也不是通用虚拟机平台:需要完整 Windows VM、内核级隔离或 GPU 虚拟化时,应使用专门的虚拟化方案。
Kasm 官方最低要求是 2 核 CPU、4GB 内存和 50GB SSD,支持 Ubuntu 22.04/24.04、Debian 11/12 等系统,也明确不建议运行在 LXC 或 WSL/WSL2 中。
最低配置只代表安装能通过。官方默认工作区通常为单个会话预留 2 核和 2768MB 内存,因此 4GB VPS 实际只适合管理员测试一个轻量会话。
| 使用场景 | 建议 VPS | 并发建议 |
|---|---|---|
| 个人浏览器隔离、测试 | 4 vCPU、8GB、80GB NVMe | 1–2 个标准会话 |
| 小团队浏览器与 Linux 桌面 | 8 vCPU、16GB、160GB NVMe | 4–6 个轻量会话 |
| 多人培训或远程办公 | 先做压测,再拆分 Web、数据库与 Agent | 按峰值并发规划 |
不要只按总用户数买机器。Kasm 容量的核心指标是同时在线会话数,还要考虑分辨率、音频、视频页面、浏览器标签页和工作区镜像。官方给出的节省资源配置可低至 0.5 核、768MB、1024×768、关闭音频;标准体验则约为 1.5 核和 2GB 内存。
如果还在 2核4G、4核8G 之间犹豫,可先看 VPS 配置选择指南。Kasm 的交互体验也依赖延迟,机房应尽量靠近最终用户。
本文采用单服务器架构:
用户浏览器
|
v
Caddy :443 ---- 自动 HTTPS
|
v
Kasm Proxy :8443 ---- API / Manager / PostgreSQL / Agent
|
v
按需创建 Workspace 容器
Kasm 默认监听 443。为了让 Caddy 占用公网 443,安装时把 Kasm 改到 8443,再由 Caddy反向代理。云防火墙或安全组只需要允许:
- 22/TCP:SSH,最好限制管理 IP;
- 80/TCP:Caddy 申请证书与 HTTP 跳转;
- 443/TCP:Kasm Web 入口。
本教程不使用本地 RDP 客户端网关,因此不开放 3389。8443 只供本机 Caddy 连接,不应在云防火墙中放行。
把 kasm.example.com 的 A/AAAA 记录指向 VPS。先检查系统、架构、内存、磁盘和端口:
cat /etc/os-release
uname -m
free -h
df -h /var/lib/docker 2>/dev/null || df -h /
sudo ss -lntup | grep -E ':(80|443|8443)\b' || true
Kasm 安装器会安装或使用 Docker,并在 /opt/kasm 下创建服务。已经运行 Nginx、Traefik、数据库或其他 Docker 项目时,先评估端口、磁盘和 Docker 网络冲突。长期使用最好选择一台独立 VPS。
更新系统并安装必要工具和 Caddy:
sudo apt update
sudo apt upgrade -y
sudo apt install -y ca-certificates curl caddy
sudo systemctl enable --now caddy
配置 UFW 前保留当前 SSH 会话,并确认云厂商控制台可用:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
Docker 发布端口可能绕过部分 UFW 转发规则,所以还应在云防火墙层明确拒绝公网 8443,而不是只依赖 UFW。
官方 1.17.0 AMD64 安装包和 SHA-256 如下:
cd /tmp
curl -fLO \
https://kasm-static-content.s3.amazonaws.com/kasm_release_1.17.0.7f020d.tar.gz
echo \
'22a293ea52b2adb7f3f72a2de8e9be799f443b9da040e066df403478da77f62d kasm_release_1.17.0.7f020d.tar.gz' \
| sha256sum -c -
tar -xzf kasm_release_1.17.0.7f020d.tar.gz
必须看到 OK 后再运行安装器。ARM64 的安装包与离线镜像哈希不同,不能复用上面的校验值;而且并非所有工作区镜像都支持 ARM64,购买 ARM VPS 前应检查官方镜像矩阵。
先检查是否已有 Swap:
swapon --show
free -h
如果没有 Swap,可让安装器创建 8GB Swap:
cd /tmp
sudo bash kasm_release/install.sh \
--accept-eula \
--swap-size 8192 \
-L 8443
已有合适 Swap 时移除 --swap-size 8192。安装过程会拉取多组服务与工作区镜像,50GB 只是最低磁盘要求;网络慢时不要反复重新安装,先查看当前目录保留的 kasm_install_时间戳.log。
安装结束会输出随机生成的 [email protected] 和 [email protected] 密码。立即保存到密码管理器,不要把终端截图发到群聊,也不要把密码写进本文命令。
确认容器和健康接口:
sudo docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
curl -kfsS https://127.0.0.1:8443/api/__healthcheck
sudo /opt/kasm/bin/status
健康接口应返回 {"ok": true}。这里使用 -k 是因为 Kasm 8443 上游暂时使用自签名证书,只允许从本机检查。
编辑 /etc/caddy/Caddyfile:
kasm.example.com {
encode zstd gzip
reverse_proxy https://127.0.0.1:8443 {
transport http {
tls_insecure_skip_verify
}
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto https
header_up X-Forwarded-Port 443
flush_interval -1
}
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
Referrer-Policy "same-origin"
}
}
tls_insecure_skip_verify 只用于 Caddy 到本机 8443 的回环连接,因为 Kasm 上游证书是自签名;公网用户与 Caddy 之间仍使用受信任证书。如果 Caddy 与 Kasm 不在同一台机器,不能这样跳过验证,应为上游配置可信证书。
验证并加载:
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -fsS https://kasm.example.com/api/__healthcheck
Caddy 原生支持 WebSocket,不需要手写 Upgrade 头。flush_interval -1 关闭响应缓冲,更适合长时间交互流。多域名和证书排错可参考 Caddy 反向代理教程。
能打开登录页不代表工作区一定能连接。登录管理后台后进入:
Infrastructure -> Zones -> default
修改两个值:
- Upstream Auth Address:
proxy; - Proxy Port:
0。
保存后结束旧测试会话,再新建会话。官方说明 Zone 修改只对新会话生效;如果只刷新已经存在的会话,可能仍然看到断开或循环重连。
如果以后启用本地 RDP Client Workspace,并通过反向代理访问,还要按官方提示评估是否关闭 Restrict RDP Client IP Address,否则代理后的客户端 IP 可能导致 Invalid Request. Wrong client IP。
使用安装器输出的管理员密码登录后,按以下顺序处理:
- 修改
[email protected]的随机密码; - 删除或禁用默认
[email protected]; - 为管理员启用 TOTP 或 WebAuthn 双因素认证;
- 新建日常管理账号,不把默认管理员用于普通浏览;
- 把最大登录尝试次数从默认 5 调低到 3;
- 缩短会话与空闲超时时间;
- 检查匿名访问未启用。
Kasm 支持本地账号、LDAP、SAML 和 OIDC。多人团队应接入统一身份提供商;保留一个启用 MFA 的本地紧急管理员,并把恢复凭据离线保存。
在 Access Management -> Groups 新建例如 Browser-Isolation 组。用户所属多个组时,优先级数值更低的设置会覆盖同名设置,因此不要随意创建多组重叠规则。
建议先在 All Users 组设置最严格基线:
- 禁止文件上传与下载;
- 关闭双向剪贴板;
- 关闭麦克风和摄像头;
- 限制空闲断开与最大会话时长;
- 限制同时运行的会话数;
- 默认不分配新工作区镜像。
再在特定组中按业务需要逐项放开。官方安全指南建议关闭“新 Workspaces 自动加入 All Users”,改为管理员显式把镜像分配给组,避免刚导入的高权限镜像自动对所有人可见。
进入 Workspaces -> Registry,添加官方 Registry 后选择需要的镜像。不要一次安装全部桌面镜像:每个镜像可能占用数 GB,升级时还会同时保留新旧层。
一个稳妥的起步组合是:
- Chromium 或 Firefox:不可信网站与临时登录;
- Ubuntu Desktop:需要文件管理器与终端的任务;
- Remmina:通过受控入口访问 RDP/VNC/SSH;
- VS Code:短期开发或培训环境。
在 Workspace 设置中先使用保守额度,例如 1.5 CPU、2GB 内存,再根据实际页面调整。普通网页浏览与高清视频会议的资源需求差异很大,不要给所有镜像套同一个上限。
首次验收至少测试:
- 普通用户只能看到分配给所在组的镜像;
- 启动浏览器工作区并访问测试网站;
- 剪贴板、上传、下载符合组策略;
- 关闭会话后对应容器被回收;
- 再次启动时,临时下载和 Cookie 不应意外保留。
浏览器隔离的价值来自“用完即弃”。处理不可信链接时,优先使用临时会话,不要挂载宿主机目录,也不要启用持久 Profile。
持久 Profile 适合需要长期保留浏览器配置、开发工具或用户文件的场景,但它会改变安全边界:
- 恶意扩展、Cookie 和下载文件可能跨会话保留;
- 持久目录必须纳入备份、配额和恶意文件扫描;
- 用户删除与数据删除要有明确流程;
- 不同用户不能共享同一写入目录。
如果只需要打开一次链接,结束会话即销毁通常更安全。确实需要持久化时,为每个用户映射独立目录,并做恢复演练。
Kasm 把远程画面传到浏览器,视频、动画、分辨率和音频都会增加 CPU 与带宽。低配 VPS 可以从以下设置开始:
- 视频质量设为 Low 或 Medium;
- 最大分辨率限制为 1280×720;
- 不需要时关闭音频;
- 轻量浏览器会话分配 0.5–1 CPU、1–1.5GB 内存;
- 限制每个用户只运行一个会话;
- 为会话设置空闲自动销毁;
- 只预拉取真正使用的镜像。
用 docker stats 观察实际峰值:
sudo docker stats
sudo docker system df
free -h
df -h /var/lib/docker
测试时同时打开预期数量的真实会话,播放视频、滚动网页、复制文本并保持 20–30 分钟。只测试登录页没有意义。CPU 长期超过 80%、Swap 持续增长或会话反复重连时,应减少并发或升级配置。
工作区镜像和容器层主要存放在 /var/lib/docker。宿主机其他磁盘空闲,并不能解决 Docker 数据目录不足。至少监控:
- 根分区与 Docker 分区使用率;
- inode 使用率;
- Kasm 核心容器状态和重启次数;
/api/__healthcheck;- CPU、内存、Swap 和网络流量;
- PostgreSQL 备份是否成功。
快速检查:
sudo /opt/kasm/bin/status
curl -kfsS https://127.0.0.1:8443/api/__healthcheck
sudo docker ps --filter 'name=kasm_' \
--format 'table {{.Names}}\t{{.Status}}\t{{.RunningFor}}'
sudo docker system df
多台 VPS 已使用统一监控时,可把健康接口、磁盘与容器重启接入 Zabbix 监控教程。
Kasm 的用户、组、工作区定义和系统设置存放在 PostgreSQL。官方给出的在线数据库备份命令是:
sudo mkdir -p /var/backups/kasm
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
sudo docker exec kasm_db \
pg_dump -U kasmapp -F t kasm \
| sudo tee "/var/backups/kasm/kasm-db-$STAMP.tar" >/dev/null
再备份配置:
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
sudo tar -czf "/var/backups/kasm/kasm-config-$STAMP.tar.gz" \
/opt/kasm/current/conf \
/opt/kasm/current/docker
sudo sha256sum /var/backups/kasm/kasm-* \
| sudo tee "/var/backups/kasm/SHA256SUMS-$STAMP" >/dev/null
如果启用了 Persistent Profile、Volume Mapping 或用户共享目录,还必须单独备份这些路径。数据库与配置备份不会自动包含外部 NFS、对象存储或自定义宿主机目录。
至少把备份加密复制到另一台主机或对象存储,并每月做一次恢复抽查。完整的远端保留、校验与演练方法见 VPS 备份恢复演练。
官方数据库恢复示例会使用 pg_restore -c 覆盖现有对象。恢复属于破坏性操作,只能在维护窗口或独立测试 VPS 上执行:
sudo docker cp kasm-db-backup.tar kasm_db:/tmp/backup.tar
sudo docker exec kasm_db \
pg_restore -d kasm /tmp/backup.tar -c -U kasmapp
恢复成功标准包括:管理员能登录、用户组和 Workspace 分配存在、新会话能创建、策略生效、持久目录可读,而不是仅看到容器处于 Running。
升级前先阅读目标版本发行说明,确认操作系统、Docker、镜像和配置文件迁移变化。Kasm 1.17.0 调整了多项配置路径,不能把旧教程的文件位置直接套用。
升级顺序:
- 通知用户维护窗口;
- 结束所有活动工作区;
- 生成数据库备份、配置归档和 VPS 快照;
- 检查 Docker 数据目录至少有 50GB 可用空间;
- 下载目标版本并校验 SHA-256;
- 使用该版本官方
upgrade.sh; - 验证登录、Zone、浏览器会话、权限和备份;
- 再从 Registry 更新 Workspace 镜像。
当 Kasm 运行在 8443 时,升级命令必须保留端口:
cd /tmp
curl -fLO \
https://kasm-static-content.s3.amazonaws.com/kasm_release_1.17.0.7f020d.tar.gz
echo \
'22a293ea52b2adb7f3f72a2de8e9be799f443b9da040e066df403478da77f62d kasm_release_1.17.0.7f020d.tar.gz' \
| sha256sum -c -
tar -xzf kasm_release_1.17.0.7f020d.tar.gz
sudo bash kasm_release/upgrade.sh --proxy-port 8443
已经在 1.17.0 的服务器不需要重复执行这条命令;它展示的是从受支持旧版本升级到 1.17.0 时应保留的端口参数。跨版本操作以目标版本文档为准,不要把“重新运行 install.sh”当作升级。
先分层检查 Kasm、Caddy 和公网 DNS:
curl -kfsS https://127.0.0.1:8443/api/__healthcheck
sudo systemctl status caddy --no-pager
sudo journalctl -u caddy -n 100 --no-pager
curl -fsS https://kasm.example.com/api/__healthcheck
本机 8443 失败时查 Kasm;本机成功、域名失败时查 Caddy、DNS 和安全组。
确认 Zone 的 Upstream Auth Address 为 proxy、Proxy Port 为 0,然后彻底结束旧会话并创建新会话。再检查 Caddy 是否把请求代理到 https://127.0.0.1:8443,以及 WebSocket 是否被上游 CDN 或额外代理阻断。
free -h
swapon --show
sudo docker stats --no-stream
sudo docker system df
降低 Workspace 的 CPU/内存要求只能解决确实有余量的边界情况。主机已经使用 Swap 或内存接近满载时,应减少并发或扩容,而不是继续压低限制。
先在管理后台删除不用的 Workspace 定义与镜像,再检查 Docker:
df -h /var/lib/docker
df -i /var/lib/docker
sudo docker system df -v
不要直接运行不带范围判断的 docker system prune -a。它可能删除仍计划使用的镜像,导致下次会话重新拉取,甚至影响同机其他项目。
cd /tmp
ls -lh kasm_install_*.log
tail -n 200 kasm_install_*.log
sudo docker info
df -h /
常见原因是空间不足、已有 Docker 版本不兼容、443/8443 被占用或无法访问镜像仓库。先根据日志定位,不要连续重复运行安装器。
- Kasm 主题与 slug 已确认不重复;
- VPS 使用官方支持的系统,不是 LXC;
- 资源按峰值并发会话而不是注册用户数规划;
- 安装包 SHA-256 校验通过;
- 公网只开放 22、80、443;
- 8443 未在云防火墙中公开;
- Caddy HTTPS 与健康接口正常;
- Zone 已设置 Upstream Auth Address=proxy、Proxy Port=0;
- 默认普通用户已禁用,管理员已启用 MFA;
- All Users 使用最严格权限,镜像按组显式分配;
- 上传、下载、剪贴板和会话销毁策略经过实测;
- Docker 分区、Swap、健康接口与容器重启有告警;
- 数据库、配置和持久目录都进入远端备份;
- 恢复演练能重新创建真实 Workspace;
- 升级时先清空活动会话并保留 8443 端口参数。
能完成安装和轻量测试,但默认单会话就可能申请 2 核、2768MB 内存。实际长期使用建议从 4 核 8GB 起步,并根据同时在线会话压测。
Guacamole 主要把已有 RDP、VNC、SSH 主机放到浏览器里;Kasm 还能按需创建隔离的浏览器和 Linux 容器。固定远程主机用 Guacamole 更轻,临时隔离工作区用 Kasm 更合适。
官方不建议。Kasm 自身和工作区都依赖 Docker 容器、网络与内核能力,嵌套在 LXC 中容易遇到权限和兼容问题。优先选择 KVM 虚拟机或裸金属。
最常见原因是 Zone 仍保存旧代理地址。把 Upstream Auth Address 设为 proxy、Proxy Port 设为 0,结束旧会话后重新创建,并确认 WebSocket 没有被中间代理阻断。
临时容器会被销毁,但 Persistent Profile、Volume Mapping、共享目录或外部存储中的数据会保留。安全性取决于 Workspace 和组策略,不能只看容器是否删除。
不包含全部用户文件。数据库保存用户、组、工作区定义和设置;持久 Profile、映射目录、NFS 或对象存储必须另行备份,并与数据库在同一恢复演练中验证。
