SSD Nodes Learn 🎉 VPS từ $4.99/tháng
Hướng dẫn Matt ConnorBởi Matt Connor

Cockpit hay Webmin: nên dùng panel nào?

So sánh Cockpit và Webmin trên Ubuntu VPS: panel nào sửa được gì, cách đăng nhập, vì sao không nên mở cổng public và khi nào nên dùng SSH cùng Ansible.

Cockpit và Webmin: câu trả lời ngắn gọn

Cockpit và Webmin đều là web panel để quản lý máy chủ Linux từ trình duyệt, nhưng chúng giải quyết các nhu cầu khác nhau. Cockpit có sẵn trong repository của chính bản phân phối và đọc thông tin máy thông qua systemd, journald, polkit và udisks. Vì vậy, nó hiển thị máy chủ mà bạn vẫn quản lý bằng SSH. Webmin ra đời sớm hơn và có phạm vi rộng hơn nhiều: nó ghi các file cấu hình cho Apache, BIND, Postfix, MariaDB và hàng chục service khác mà Cockpit không can thiệp, đồng thời chạy web server riêng dưới quyền root để thực hiện việc đó.

Cài Cockpit khi bạn cần theo dõi trực tiếp một máy, đọc log và dùng terminal khẩn cấp. Cài Webmin khi bạn cần trình chỉnh sửa dạng biểu mẫu cho một service mà bạn không muốn cấu hình thủ công. Không đặt bất kỳ panel nào trong hai panel này trên cổng public với kiểu đăng nhập bằng password. Nếu bạn đã vận hành hơn hai hoặc ba máy chủ, câu trả lời thực tế thường là không dùng panel nào cả; SSH kết hợp với Ansible sẽ mở rộng tốt hơn bất kỳ panel nào.

Những gì mỗi panel thực sự có thể thay đổi

Bản cài đặt cơ bản của Cockpit khá nhỏ. Phần lớn các khu vực là các package riêng mà bạn có thể không cài:

  • service và timer của systemd: khởi động, dừng, enable và đọc unit file
  • journal, được lọc theo unit và priority, có journalctl kèm bộ chọn ngày
  • account cục bộ, thành viên group và SSH key được cấp quyền
  • storage với cockpit-storaged: partition, LVM volume group, filesystem và mount point
  • container với cockpit-podman, chỉ quản lý Podman
  • cập nhật package với cockpit-packagekit
  • biểu đồ CPU, memory, disk và network với cockpit-pcp
  • terminal root trong tab trình duyệt

Có 2 khu vực trông như bị hỏng trên Ubuntu VPS, nhưng thực ra không phải. Trang Networking của Cockpit là front end cho NetworkManager, còn image Ubuntu server dùng netplan với systemd-networkd, nên trang này bị thiếu hoặc để trống. Đừng cài NetworkManager trên máy chủ remote chỉ để khôi phục trang đó, vì nó sẽ tiếp quản interface và một lỗi cấu hình có thể làm mất luôn phiên SSH. Các control firewall của Cockpit là front end cho firewalld, còn Ubuntu dùng ufw, nên bạn hoàn toàn không có control firewall trong Cockpit. Bạn vẫn chạy sudo ufw status trong terminal.

Webmin quản lý được nhiều hơn đáng kể vì nó là một tập hợp module riêng cho từng service, thay vì một chương trình duy nhất:

  • cấu hình Apache, nginx, BIND, Postfix, Dovecot, MariaDB, PostgreSQL và Samba qua form
  • user, group và disk quota
  • cron job và system clock
  • cập nhật package, cùng file manager có chức năng upload và download
  • front end cho firewall, gồm một front end cho iptables và một front end cho firewalld
  • backup file cấu hình và các module cluster để đẩy một thay đổi sang những Webmin server khác

Webmin chỉnh sửa các file thực dưới /etc. Không có database ẩn phía sau các form. Vì vậy, nếu /etc nằm trong version control, sudo git -C /etc diff sau khi lưu một form sẽ cho thấy chính xác module đã ghi gì. Đây là cách nhanh nhất để biết một trang Webmin thực sự làm gì. Hướng dẫn cài đặt Webmin và đăng nhập lần đầu trình bày chi tiết cây module. Virtualmin và Usermin là các sản phẩm riêng được xây dựng trên cùng engine, lần lượt dành cho shared hosting và end user. Những sản phẩm này cũng chịu mọi vấn đề về exposure đã nêu ở đây.

Cách mỗi công cụ xác thực

Cockpit không có cơ sở dữ liệu người dùng riêng. Trang đăng nhập của nó chạy ngăn xếp PAM (pluggable authentication modules) trong /etc/pam.d/cockpit, vì vậy các tài khoản chính là tài khoản Unix và mật khẩu là mật khẩu Unix. Theo mặc định, root bị từ chối vì /etc/cockpit/disallowed-users liệt kê tài khoản này. Các thao tác cần quyền cao chạy qua polkit. Giao diện yêu cầu nhập lại mật khẩu trước khi thay đổi bất cứ thứ gì. Vì vậy, tiêu đề trang có thể hiển thị "Limited access" cho đến khi bạn nâng quyền.

Thiết kế này dẫn đến một vấn đề thường gặp trên máy chủ đã được hardening. Nếu bạn đã làm theo hướng dẫn đăng nhập SSH chỉ bằng key khi đã tắt xác thực bằng mật khẩu, tài khoản có thể hoàn toàn không có mật khẩu sử dụng được. Khi đó, đăng nhập Cockpit bị từ chối trong khi ssh vẫn hoạt động. Kiểm tra trên server:

sudo passwd -S deploy

Nếu output bắt đầu bằng deploy L, mật khẩu đang bị khóa. PAM không có mật khẩu để chấp nhận, vì vậy không mật khẩu nào bạn nhập có thể hoạt động. P nghĩa là tài khoản đã được đặt mật khẩu có thể sử dụng. Trang đăng nhập riêng của Cockpit không chấp nhận SSH key. Key chỉ được dùng khi Cockpit kết nối tiếp từ máy bạn đã đăng nhập đến một host khác.

Webmin lưu người dùng riêng trong /etc/webmin/miniserv.users, tách biệt với /etc/passwd, và cũng có thể được cấu hình để xác thực bằng tài khoản Unix. Người dùng Webmin được cấp quyền cho tất cả module có quyền root trên máy đó, bất kể login shell của họ được khai báo là gì. Webmin có sẵn hỗ trợ TOTP (time-based one-time password) và tính năng chặn host sau nhiều lần đăng nhập thất bại. Cả hai tính năng đều được bật trong Webmin Configuration. Cockpit chỉ có yếu tố xác thực thứ hai nếu bạn thêm yếu tố đó vào PAM, chẳng hạn bằng libpam-google-authenticator.

Cách cập nhật từng công cụ

Cockpit được đóng gói bởi bản phân phối của bạn. Trên Ubuntu 24.04, Cockpit đến từ archive, còn dự án upstream khuyến nghị dùng pocket backports để cài bản build mới hơn:

. /etc/os-release
sudo apt update
sudo apt install -t ${VERSION_CODENAME}-backports cockpit
sudo systemctl status cockpit.socket
apt policy cockpit

apt policy hiển thị phiên bản đã cài và repository cung cấp phiên bản đó. Nếu backports không có bản build mới hơn, apt sẽ dùng phiên bản trong archive. Trường hợp này không có vấn đề gì. cockpit.socket phải trả về active (listening). Sau đó, các bản sửa lỗi bảo mật sẽ được cung cấp trong cùng lần chạy unattended-upgrades với kernel, từ một publisher mà bạn đã tin cậy.

Webmin không nằm trong archive của Ubuntu. Quy trình cài đặt chính thức trước tiên thêm repository riêng của Webmin và signing key:

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

Hãy đọc script đó trước khi chạy vì nó chạy với quyền root. Từ thời điểm đó, mỗi lần apt upgrade trên server cũng lấy package từ repository của Webmin. Như vậy, bạn đã thêm một publisher thứ hai có mức độ tin cậy root trên máy. Đây là chi phí thực sự khi dùng Webmin, và cần một ví dụ cụ thể: CVE-2019-15107 là backdoor trong một số package phiên bản 1.9x, cho phép thực thi lệnh không cần xác thực. Lỗ hổng này đến với người dùng vì build host của dự án bị xâm nhập, không phải source repository của dự án. Việc đóng gói bởi bản phân phối không thể loại trừ hoàn toàn rủi ro này. Tuy nhiên, nó bổ sung một bước build và review mà bạn không phải tự duy trì.

Vì sao không nên để cả hai trên cổng public

Cockpit lắng nghe trên TCP 9090 và Webmin trên TCP 10000, cả hai đều dùng TLS (transport layer security) với chứng chỉ tự ký, nên thứ đầu tiên bạn thấy là cảnh báo của trình duyệt. Tạo và tin cậy chứng chỉ tự ký giải thích cảnh báo đó cho biết và không cho biết điều gì. Cả hai cổng đều bị scan liên tục, và cả hai panel đều dẫn đến root. Vì vậy, một mật khẩu bị đoán ra hoặc được dùng lại có thể khiến toàn bộ server bị chiếm quyền.

Cách an toàn là bind panel vào localhost rồi truy cập qua SSH tunnel. Với Cockpit, hãy override socket unit:

sudo systemctl edit cockpit.socket
[Socket]
ListenStream=
ListenStream=127.0.0.1:9090

Dòng ListenStream= trống đứng riêng là bắt buộc. systemd nối thêm vào các thiết lập dạng danh sách. Nếu thiếu dòng này, unit vẫn giữ 0.0.0.0:9090 ban đầu và thêm địa chỉ mới, nên panel vẫn public. Áp dụng override rồi kiểm tra tiến trình nào đang listening:

sudo systemctl daemon-reload
sudo systemctl restart cockpit.socket
sudo ss -lntp | grep 9090

Output phải hiển thị 127.0.0.1:9090. Địa chỉ *:9090 hoặc 0.0.0.0:9090 nghĩa là override chưa có hiệu lực. Bây giờ mở tunnel từ máy của bạn rồi truy cập https://localhost:9090:

ssh -N -L 9090:127.0.0.1:9090 deploy@203.0.113.10

Giữ local port bằng remote port. Cockpit so sánh header Origin của trình duyệt với địa chỉ mà nó cho rằng mình đang phục vụ. Vì vậy, tunnel từ local port 9999 sẽ tải được trang đăng nhập nhưng sau đó đăng nhập thất bại, còn journalctl -u cockpit sẽ ghi lại origin bị từ chối. Nếu cần local port khác, hãy khai báo trong /etc/cockpit/cockpit.conf:

[WebService]
Origins = https://localhost:9999 https://127.0.0.1:9999

Khởi động lại bằng sudo systemctl restart cockpit.socket để áp dụng thiết lập đó. Với Webmin, thiết lập tương đương nằm trong /etc/webmin/miniserv.conf:

bind=127.0.0.1
sudo systemctl restart webmin
sudo ss -lntp | grep 10000
ssh -N -L 10000:127.0.0.1:10000 deploy@203.0.113.10

Webmin cũng kiểm tra header Referer trong các form post và từ chối những request có vẻ đến từ host khác. Đây là nguyên nhân khiến lần thử reverse proxy đầu tiên thất bại. Dòng referers= trong cùng file là nơi cho phép hostname của proxy, còn webprefix= là nơi khai báo Webmin chạy dưới một path.

Một lựa chọn khác là dùng reverse proxy có xác thực: nginx đứng phía trước, với lớp single sign-on Authentik xử lý đăng nhập. Cách này hoạt động, nhưng vẫn là lựa chọn thứ hai. Panel vẫn chạy với quyền root phía sau proxy, và bây giờ bạn phải duy trì hai cửa vào thay vì một. Tunnel không thêm bất kỳ service nào listening trên Internet, đồng thời tái sử dụng SSH key mà bạn đã bảo vệ.

Nên chọn panel nào trên máy đã chạy các service production

Cockpit, vì 2 lý do quan trọng khi có người khác phụ thuộc vào máy này. Cockpit được kích hoạt bằng socket, nên cockpit-ws chỉ chạy khi có session đang mở và không có root daemon chạy thường trực để chờ trên một port. Cockpit cũng không quản lý gì ngoài chính nó: gỡ package này thì mọi service vẫn chạy chính xác như trước, vì Cockpit không lưu cấu hình riêng. miniserv.pl của Webmin vẫn chạy thường trú dù không có ai đăng nhập. Kiểm tra mức tiêu thụ của tiến trình bằng systemctl status webmin; lệnh này in ra memory thường trú của process đang chạy.

Nếu cần các module DNS hoặc mail của Webmin, hãy dành cho chúng một server riêng. Một máy Webmin chỉ làm một nhiệm vụ và bind vào 127.0.0.1 là rủi ro được giới hạn. Webmin dùng chung host với ứng dụng phục vụ khách hàng thì không như vậy. Hãy hoàn tất phần cấu hình nền trước khi cài một trong hai panel: 10 phút đầu tiên trên một VPS mới đề cập đến user không phải root và firewall mà cả 2 panel đều giả định là đã có.

Khi câu trả lời là không dùng cả hai

Một panel được quản lý thủ công trên từng server và không lưu lại thay đổi nào đã thực hiện hoặc lý do thực hiện. Cách này phù hợp với một máy. Với năm máy, bạn phải lặp lại thao tác. Với hai mươi máy, bạn phải đoán server nào đã bỏ sót thay đổi. Cockpit có thể thêm các host khác vào cùng một session qua SSH, nhưng các phiên bản gần đây tắt tính năng này theo mặc định và yêu cầu AllowMultiHost=yes trong /etc/cockpit/cockpit.conf. Dù vậy, bạn vẫn phải thực hiện cùng một thay đổi năm lần.

Cách khác là dùng SSH thuần với cấu hình được lưu trong một git repository. Quản lý nhiều server Linux từ một nơi trình bày cấu trúc của mô hình này. Playbook Ansible đầu tiên áp dụng cùng một firewall rule cho mọi host từ một file duy nhất, để bạn có thể review dưới dạng diff. Công việc với container cũng tương tự: dùng docker compose up -d qua SSH từ một file trong git, như hướng dẫn cơ bản về Docker Compose, hiệu quả hơn việc thao tác trên bất kỳ panel nào. Hơn nữa, Cockpit vốn không quản lý Docker.

Hãy dùng panel cho những việc terminal không thuận tiện, chẳng hạn đọc biểu đồ metrics hoặc xác định unit nào trong số bốn mươi unit đã fail. Dùng code cho mọi việc bạn sẽ thực hiện nhiều hơn hai lần.

Các tình huống lỗi và chuỗi bạn sẽ thấy

Cockpit từ chối mật khẩu mà SSH chấp nhận. Tài khoản này chỉ dùng key. sudo passwd -S alice in L ở trường thứ hai, nên PAM không có mật khẩu để kiểm tra. Đặt mật khẩu bằng sudo passwd alice, hoặc tiếp tục dùng tài khoản đó cho SSH và đăng nhập Cockpit bằng người dùng khác.

Cockpit từ chối root dù mật khẩu đúng. /etc/cockpit/disallowed-users liệt kê root. Hãy đăng nhập bằng người dùng thông thường có quyền sudo. Đây là cách được thiết kế, vì polkit sẽ ghi lại người nào đã thực hiện thao tác nâng quyền.

Cockpit không hiển thị trang Networking hoặc Firewall. Các trang này cần NetworkManager và firewalld. Ubuntu VPS dùng netplan với systemd-networkd và ufw, nên các trang này không xuất hiện. Không có gì bị hỏng; cách xử lý là tiếp tục dùng ufw qua SSH.

Trang đăng nhập Cockpit tải được qua tunnel nhưng đăng nhập thất bại. Cổng local khác cổng remote, nên bước kiểm tra Origin thất bại và journalctl -u cockpit hiển thị lỗi đó. Hãy dùng cùng một cổng, hoặc đặt Origins trong /etc/cockpit/cockpit.conf.

Form Webmin gửi dữ liệu thất bại sau khi bạn đặt nó phía sau proxy. Bước kiểm tra Referer từ chối các request này. Thêm hostname của proxy vào referers= trong /etc/webmin/miniserv.conf, và đặt webprefix= khi panel được phục vụ dưới một path.

Bạn không chắc panel có đang public hay không. sudo ss -lntp | grep -E '9090|10000' kiểm tra điều đó từ chính server, còn Webmin ghi mọi lần đăng nhập vào /var/webmin/miniserv.log. Bạn nên đọc log này một lần sau mỗi thay đổi về cách panel lắng nghe.

FAQ

Cockpit hay Webmin phù hợp hơn cho một Ubuntu VPS duy nhất?

Với hầu hết người dùng, Cockpit phù hợp hơn vì nó có trong repository của Ubuntu, được cập nhật bản vá cùng với phần còn lại của hệ thống và chỉ chạy khi có phiên trình duyệt đang mở. Chọn Webmin khi bạn cần trình biên tập dạng biểu mẫu cho một service mà Cockpit không hỗ trợ, chẳng hạn như BIND hoặc Postfix. Đổi lại, bạn phải chấp nhận web server của Webmin luôn chạy dưới quyền root và các bản cập nhật được lấy từ repository riêng của Webmin.

Có thể chạy Cockpit và Webmin trên cùng một server không?

Có. Chúng dùng các cổng khác nhau, 9090 và 10000, nên không xung đột vì mỗi panel chỉnh sửa trực tiếp hệ thống thay vì độc quyền quản lý hệ thống. Tuy vậy, đây vẫn là một đánh đổi không đáng. Mỗi panel là một điểm đăng nhập riêng có khả năng dùng root trên cùng một máy, nên bạn tăng gấp đôi bề mặt tấn công chỉ để giảm vài thao tác. Nếu cài cả hai, hãy bind cả hai vào 127.0.0.1 và truy cập chúng qua SSH tunnel.

Mở cổng 9090 hoặc 10000 ra Internet có an toàn không?

Không nếu dùng đăng nhập bằng password. Cả hai panel đều dẫn đến root, và cả hai cổng thường bị phát hiện qua các đợt quét tự động trong vòng vài giờ sau khi mở. Bind panel vào 127.0.0.1, sau đó chạy ssh -N -L 9090:127.0.0.1:9090 user@host và truy cập https://localhost:9090 bằng trình duyệt. Xác nhận bằng sudo ss -lntp | grep 9090; kết quả phải hiển thị 127.0.0.1:9090 thay vì 0.0.0.0:9090. Dùng reverse proxy có xác thực là một lựa chọn thứ hai chấp nhận được.

Vì sao đăng nhập Cockpit thất bại khi SSH bằng key vẫn hoạt động?

Cockpit xác thực qua PAM bằng Unix password, và trang đăng nhập của nó không chấp nhận SSH key. Trên server được harden, account thường không có password có thể sử dụng. Chạy sudo passwd -S youruser: nếu trường thứ hai chứa L thì password đã bị khóa, nên PAM không có thông tin nào để chấp nhận và mọi lần thử đều bị từ chối. Đặt password bằng sudo passwd youruser, hoặc dùng một account khác cho panel.

Cockpit có quản lý Docker container không?

Không. Trang quản lý container của Cockpit lấy từ cockpit-podman và quản lý Podman. Docker module cũ đã bị loại bỏ từ nhiều năm trước và sẽ không được đưa trở lại. Nếu các service của bạn chạy dưới Docker, hãy quản lý chúng bằng compose file được lưu trong version control qua SSH, còn Cockpit xử lý phần hệ thống xung quanh, chẳng hạn như journal và disk.

#cockpit#webmin#server-management#admin-panel#ubuntu