Cockpit 与 Webmin 如何选择:Ubuntu VPS 管理面板对比
对比 Cockpit 与 Webmin 在 Ubuntu VPS 上能修改的内容、登录方式及安全边界,说明为何不应将密码登录暴露在公共端口,以及何时应改用 SSH 加 Ansible。
Cockpit 与 Webmin:简短结论
Cockpit 和 Webmin 都是用于通过浏览器管理 Linux 服务器的 Web 面板,但它们解决的问题不同。Cockpit 由发行版自己的软件仓库提供,并通过 systemd、journald、polkit 和 udisks 读取计算机状态,因此它展示的是一台仍然通过 SSH 管理的服务器。Webmin 更早出现,功能范围也更广:它可以为 Apache、BIND、Postfix、MariaDB 以及 Cockpit 不会接触的数十种其他服务写入配置文件,并以 root 身份运行自己的 Web 服务器来完成这些操作。
如果您需要查看单台服务器的实时状态、读取日志和使用应急终端,请安装 Cockpit。如果您需要通过表单编辑器配置不想手动配置的服务,请安装 Webmin。不要让任何一个面板通过公共端口提供密码登录。如果您已经运行两三台以上服务器,通常更实际的答案是两者都不用;与任何面板相比,SSH 加 Ansible 的方式更易于扩展。
每个面板实际可以修改的内容
Cockpit 的基础安装很小,大多数功能区域都是独立软件包,可以不安装:
- systemd 服务和计时器:启动、停止、启用服务,以及读取单元文件
- 按单元和优先级筛选的日志,并通过
journalctl使用日期选择器 - 本地账户、组成员关系和已授权的 SSH 密钥
- 使用
cockpit-storaged管理存储:分区、LVM 卷组、文件系统和挂载点 - 使用
cockpit-podman管理容器,但它只管理 Podman - 使用
cockpit-packagekit管理软件包更新 - 使用
cockpit-pcp查看 CPU、内存、磁盘和网络图表 - 浏览器标签页中的 root 终端
在 Ubuntu VPS 上,有两个区域看起来像是损坏了,但实际上并非如此。Cockpit 的 Networking 页面是 NetworkManager 的前端,而 Ubuntu 服务器镜像使用 netplan 和 systemd-networkd,因此该页面会缺失或为空。不要为了恢复该页面而在远程主机上安装 NetworkManager,因为它会接管网络接口,配置错误还会导致 SSH 会话中断。Cockpit 的防火墙控制功能是 firewalld 的前端,而 Ubuntu 使用 ufw,因此你完全看不到防火墙控制项。你仍需在终端中运行 sudo ufw status。
Webmin 覆盖的功能范围更广,因为它不是一个单体程序,而是一组按服务划分的模块:
- 通过表单配置 Apache、nginx、BIND、Postfix、Dovecot、MariaDB、PostgreSQL 和 Samba
- 用户、组和磁盘配额
- cron 任务和系统时钟
- 软件包更新,以及支持上传和下载的文件管理器
- 防火墙前端,包括 iptables 和 firewalld 的前端
- 配置文件备份,以及可将一项更改推送到其他 Webmin 服务器的集群模块
大多数 Webmin 表单都会直接编辑 /etc 下的实际文件,背后没有隐藏数据库。因此,如果 /etc 处于版本控制中,保存表单后查看 sudo git -C /etc diff,即可看到该模块写入其中的内容。对于 MariaDB 和 PostgreSQL 模块执行命令或运行 SQL 的操作,它不会显示;对于写入 /etc 之外文件的操作,它也不会显示。在这些限制内,这是了解 Webmin 页面实际执行内容的最快方式。Webmin 安装和首次登录指南会详细介绍模块树。Virtualmin 和 Usermin 是基于同一引擎构建的独立产品,分别面向共享主机和终端用户;这里关于暴露面的所有说明同样适用于它们。
每种方式如何进行身份验证
Cockpit 没有自己的用户数据库。其登录页面会在 /etc/pam.d/cockpit 中调用 PAM(可插拔认证模块)堆栈,因此使用的是 Unix 账户和 Unix 密码。默认情况下,root 会被拒绝,因为 /etc/cockpit/disallowed-users 将其列入了拒绝列表。特权操作通过 polkit 执行。界面在执行更改前会再次要求您输入密码。因此,在完成提权前,页面标题可能显示为“有限访问”。
在经过加固的服务器上,这种设计会带来一个常见后果。如果您按照仅使用密钥登录 SSH 并禁用密码认证的方式配置,账户可能根本没有可用密码。此时 Cockpit 登录会被拒绝,但 ssh 仍可正常使用。请在服务器上检查:
sudo passwd -S deploy以 deploy L 开头的输出表示密码已锁定。因此 PAM 没有可接受的密码,您输入的任何密码都无法生效。P 表示已设置可用密码。Cockpit 自己的登录页面不接受 SSH 密钥。密钥仅用于 Cockpit 从当前登录的计算机继续连接到其他主机时进行认证。
Webmin 将自己的用户存储在 /etc/webmin/miniserv.users 中,与 /etc/passwd 分开;也可以配置为使用 Unix 账户进行认证。无论用户的登录 shell 如何设置,获得所有模块权限的 Webmin 用户都相当于该计算机上的 root。Webmin 自带 TOTP(基于时间的一次性密码)支持,也支持在多次登录失败后阻止主机。这两项功能都可在 Webmin Configuration 中启用。只有将第二因素添加到 PAM 后,Cockpit 才能使用第二因素,例如通过 libpam-google-authenticator。
每种工具如何更新
Cockpit 由发行版打包。在 Ubuntu 24.04 中,它来自软件仓库;上游项目建议使用 backports 仓库获取更新的构建版本:
. /etc/os-release
sudo apt update
sudo apt install -t ${VERSION_CODENAME}-backports cockpit
sudo systemctl status cockpit.socket
apt policy cockpitapt policy cockpit会显示已安装的版本及其来源仓库。不指定软件包名称运行时,apt policy只会列出各个来源的优先级。如果 backports 中没有更新的构建版本,apt 会回退到软件仓库中的版本,这没有问题。cockpit.socket应显示为 active (listening)。之后,安全修复会通过与内核相同的 unattended-upgrades 运行获取,来源是你已经信任的发布者。
Webmin 不在 Ubuntu 的软件仓库中。官方安装脚本会先添加 Webmin 自己的软件仓库和签名密钥:
curl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh
sudo sh webmin-setup-repo.sh
sudo apt-get install webmin --install-recommends运行前请先阅读该脚本,因为它会以 root 身份运行。此后,服务器上的每次 apt upgrade 也会从 Webmin 的软件仓库获取更新。因此,你已在该服务器上加入了一个拥有 root 级信任权限的第二个发布者。这就是使用 Webmin 的实际代价,下面给出一个明确的例子:CVE-2019-15107 是多个 1.9x 软件包中的后门,可在未通过身份验证的情况下执行命令。之所以影响用户,是因为项目的构建主机遭到入侵,而不是其源代码仓库被入侵。发行版打包无法完全避免这类问题,但会增加一个由发行版维护者负责的构建和审查步骤。
为什么二者都不应监听公网端口
Cockpit 监听 TCP 9090,Webmin 监听 TCP 10000。二者都通过 TLS(传输层安全)提供服务,并使用自签名证书,因此首次访问时首先看到的是浏览器警告。创建并信任自签名证书解释了该警告能说明什么,以及不能说明什么。这两个端口都会持续受到扫描,而且两个面板都可进入 root,因此一旦密码被猜中或重复使用,整个服务器就会被攻破。
安全做法是让面板绑定到 localhost,再通过 SSH 隧道访问。对于 Cockpit,覆盖其 socket unit:
sudo systemctl edit cockpit.socket[Socket]
ListenStream=
ListenStream=127.0.0.1:9090必须单独保留一行空的 ListenStream=。systemd 会向列表设置追加值,因此如果没有这一行,unit 会保留原始的 0.0.0.0:9090,并添加新的地址,面板仍会暴露在公网。应用覆盖配置,然后检查当前监听的地址:
sudo systemctl daemon-reload
sudo systemctl restart cockpit.socket
sudo ss -lntp | grep 9090输出必须显示 127.0.0.1:9090。如果显示 *:9090 或 0.0.0.0:9090,说明覆盖配置未生效。现在从本机建立隧道,并访问 https://localhost:9090:
ssh -N -L 9090:127.0.0.1:9090 deploy@203.0.113.10本地端口应与远端端口相同。Cockpit 会将浏览器的 Origin 标头与它认为自己提供服务的地址进行比较。因此,使用本地端口 9999 建立隧道时,登录页面可以正常加载,但登录会失败,journalctl -u cockpit 会记录被拒绝的来源。如果需要使用其他本地端口,请在 /etc/cockpit/cockpit.conf 中指定:
[WebService]
Origins = https://localhost:9999 https://127.0.0.1:9999使用 sudo systemctl restart cockpit.socket 重启服务,使该配置生效。对于 Webmin,对应的设置位于 /etc/webmin/miniserv.conf:
bind=127.0.0.1sudo systemctl restart webmin
sudo ss -lntp | grep 10000
ssh -N -L 10000:127.0.0.1:10000 deploy@203.0.113.10Webmin 还会检查表单提交中的 Referer 标头,并拒绝看起来来自其他主机的请求。这正是首次尝试使用反向代理时会失败的原因。/etc/webmin/config 中的 referers= 行用于允许代理的主机名,同一文件中的 webprefix= 用于告知 Webmin 自身位于某个路径下。
另一种方案是使用经过身份验证的反向代理:前端运行 nginx,并通过 Authentik 单点登录层处理登录。该方案可行,但次于 SSH 隧道。面板仍以 root 身份运行在代理之后,而且现在需要维护两个入口,而不是一个。SSH 隧道完全不会向互联网增加监听服务,并且可以复用你已经妥善保护的 SSH 密钥。
已运行生产服务的服务器应选择哪个面板
Cockpit,原因有两个,而且在其他人依赖这台机器时尤其重要。它由 socket 激活,因此 cockpit-ws 仅在会话打开期间运行,不会有永久驻留、等待端口连接的 root 守护进程。它也不会接管任何内容:移除软件包后,所有服务仍会完全按原样运行,因为 Cockpit 不存储自己的配置。无论是否有人登录,Webmin 的 miniserv.pl 都会持续驻留。使用 systemctl status webmin 检查它占用的资源,该命令会输出运行中进程的常驻内存。
如果需要 Webmin 的 DNS 或邮件模块,请为它们单独提供一台服务器。只执行一项工作并绑定到 127.0.0.1 的 Webmin 服务器,其风险是可控的。让 Webmin 与面向客户的应用共享主机则不是这样。安装任一面板前,先完成基础配置:新 VPS 上的前十分钟介绍了两个面板都假定已经存在的非 root 用户和防火墙。
何时不应使用面板
面板按服务器单独配置,而且不会记录修改了什么或为什么修改。管理一台服务器时这没有问题。管理五台服务器时,您会重复相同操作;管理二十台时,您只能猜测哪台服务器漏掉了修改。Cockpit 可以通过 SSH 将其他主机添加到同一个会话,但该主机切换器自 Cockpit 322 起已弃用,其默认状态现在取决于发行版;如果该功能处于关闭状态,则需要在 /etc/cockpit/cockpit.conf 中设置 AllowMultiHost=yes。即使启用该功能,您仍然需要对五台服务器重复点击相同的修改。
另一种方法是使用普通 SSH,并将配置存放在 git 仓库中。集中管理多台 Linux 服务器介绍了这种配置的基本结构;第一个 Ansible playbook 则可以从一个能够以 diff 形式审查的文件,将相同的防火墙规则应用到每台主机。容器管理也是如此:按照Docker Compose 基础指南中的方法,从 git 文件通过 SSH 使用 docker compose up -d,比在任何面板中逐项点击更可靠;而且 Cockpit 本身并不管理 Docker。
对于终端不擅长的任务,可以使用面板,例如查看指标图表,或快速找出四十个单元中哪些启动失败。凡是需要执行超过两次的操作,都应使用代码。
故障模式及您将看到的字符串
Cockpit 拒绝 SSH 接受的密码。该账户仅允许使用密钥登录。sudo passwd -S alice 在第二个字段输出 L,因此 PAM 没有可验证的密码。使用 sudo passwd alice 设置密码,或者继续使用该账户进行 SSH 登录,再使用其他用户登录 Cockpit。
即使密码正确,Cockpit 仍拒绝 root。/etc/cockpit/disallowed-users 列出 root。请使用具有 sudo 权限的普通用户登录。这是预期的登录方式,因为 polkit 随后会记录由哪个用户执行了提权。
Cockpit 不显示 Networking 或 Firewall 页面。这些页面需要 NetworkManager 和 firewalld。Ubuntu VPS 使用 netplan、systemd-networkd 和 ufw,因此不会显示这些页面。系统没有故障;请继续通过 SSH 使用 ufw。
通过隧道加载 Cockpit 登录页面后,登录失败。本地端口与远程端口不同,因此 Origin 检查失败,journalctl -u cockpit 会显示该问题。请匹配两个端口,或在 /etc/cockpit/cockpit.conf 中设置 Origins。
将 Webmin 放在代理后面后,表单提交失败。Referer 检查会拒绝这些请求。将代理主机名添加到 /etc/webmin/config 中的 referers=,并在该文件中设置 webprefix=,前提是面板通过路径提供服务。
您不确定面板是否对外暴露。sudo ss -lntp | grep -E '9090|10000' 可直接从服务器本身给出答案;Webmin 会将每次登录尝试写入 /var/webmin/miniserv.log。只要监听方式发生变化,就值得查看一次该日志。
FAQ
对于单台 Ubuntu VPS,Cockpit 和 Webmin 哪个更好?
对大多数用户而言,Cockpit 更合适,因为它来自 Ubuntu 官方软件仓库,会随系统一起获得补丁,并且只在浏览器会话打开期间运行。如果需要使用基于表单的编辑器来配置 Cockpit 不支持的服务(例如 BIND 或 Postfix),可以选择 Webmin,但需要接受以下代价:其 Web 服务器始终以 root 身份运行,更新也来自 Webmin 自己的软件仓库。
可以在同一台服务器上运行 Cockpit 和 Webmin 吗?
可以。它们使用不同的端口,即 9090 和 10000,因此不会冲突,因为它们都是直接编辑系统,而不是独占系统。不过,这样做并不划算。两个面板都会在同一台机器上提供一个具备 root 权限的独立登录入口,因此只是为了少执行几次操作,却将暴露面增加了一倍。如果同时安装两者,请将它们绑定到 127.0.0.1,并通过 SSH 隧道访问。
将端口 9090 或 10000 开放到互联网安全吗?
使用密码登录时不安全。这两个面板都可以访问 root 权限,开放端口后,通常几小时内就会被常规扫描发现。将面板绑定到 127.0.0.1,然后运行 ssh -N -L 9090:127.0.0.1:9090 user@host 并访问 https://localhost:9090。使用 sudo ss -lntp | grep 9090 确认结果,其中必须显示 127.0.0.1:9090,而不是 0.0.0.0:9090。经过身份验证的反向代理是另一个可接受的方案。
为什么 SSH 使用密钥可以登录,但 Cockpit 登录失败?
Cockpit 通过 PAM 使用 Unix 密码进行身份验证,其登录页面不接受 SSH 密钥。在经过加固的服务器上,该账户通常没有可用密码。运行 sudo passwd -S youruser:如果第二个字段中出现 L,表示密码已锁定,因此 PAM 没有可接受的密码,所有登录尝试都会被拒绝。使用 sudo passwd youruser 设置密码,或者为面板使用其他账户。
Cockpit 可以管理 Docker 容器吗?
不可以。Cockpit 的容器页面来自 cockpit-podman,用于管理 Podman。旧版 Docker 模块多年前已被移除,目前不会恢复。如果服务运行在 Docker 中,请通过 SSH 使用版本控制中的 compose 文件进行管理,并让 Cockpit 负责管理周边系统,例如日志和磁盘。