127.0.0.1 SỔ TAY VẬN HÀNH MÁY CHỦ & CỨU HỘ WORDPRESS THỰC CHIẾN
MINH BẠCH

Nhận bàn giao VPS WordPress: Rà soát User, sudoers, SSH Key, Port và phân quyền an toàn

Checklist nhận bàn giao VPS WordPress: rà soát user sudoers, đối chiếu SSH Key trong authorized_keys, kiểm tra Port và thu hồi khóa cũ an toàn.

Bảo mật & Sao lưu // localhost.vn
Mục lục bài viết (13 mục)
ĐÚC KẾT THỰC CHIẾN

Đổi mật khẩu wp-admin mà quên dọn file authorized_keys thì chẳng khác nào thay ổ khóa cổng chính nhưng vẫn để nguyên 5 chùm chìa khóa cửa hậu cho đội freelancer cũ: hãy kiểm kê toàn bộ user, sudoers, SSH Key và giữ sẵn phiên cứu hộ trước khi thu hồi.

Tiếp nhận bàn giao một con VPS chạy WordPress từ đội phát triển cũ hoặc một bạn freelancer vừa kết thúc hợp đồng luôn là khoảnh khắc nửa mừng nửa lo. Rất nhiều chủ website ngây thơ nghĩ rằng chỉ cần vào wp-admin đổi mật khẩu tài khoản Administrator là xong xuôi mọi bề! Thực tế phũ phàng hơn nhiều: đổi mật khẩu WordPress hoàn toàn không thu hồi được SSH Key đang nằm chễm chệ trong file authorized_keys của Linux, không cắt được quyền truy cập bảng điều khiển của nhà cung cấp Cloud, và càng không khóa được kho lưu trữ bản sao lưu (backup). Thế nhưng ở chiều ngược lại, nếu bạn vừa nhận máy đã hấp tấp xóa sạch mọi SSH Key trong khi chưa thử đăng nhập bằng khóa mới, bạn rất dễ tự nhốt mình ở ngoài cửa và biến buổi bàn giao thành ca cấp cứu bất đắc dĩ!

Bài viết này sẽ hướng dẫn anh em quy trình kiểm kê toàn diện danh sách User, quyền sudoers, SSH Key, các cổng mạng (Port) và phân quyền thư mục trước khi tiến hành thu hồi quyền cũ — đi kèm biên bản thực tế lúc 00:36 và kịch bản thu hồi một khóa tạm lúc 11:51 ngày 01/10/2026 trên máy chủ LAB-CF-02 (giờ Việt Nam). Nguyên tắc vàng của đàn anh: trước mỗi thao tác tước quyền truy cập, luôn phải có sự xác nhận của chủ sở hữu hệ thống và giữ sẵn một phiên kết nối quản trị dự phòng (cùng quyền truy cập Console cứu hộ) đã được thử nghiệm thông suốt. Khi thực hành trên lab, hãy dùng tài khoản giả lập; tuyệt đối không phơi bày tên tài khoản thật, khóa bí mật (private key) hay dữ liệu khách hàng lên môi trường công khai.

Điều kiện cần chuẩn bị trước khi thực hành

Để thực hành trơn tru các bước dưới đây, bạn cần có một máy lab riêng được cấp quyền quản trị và đã nắm vững kiến thức nền tảng từ lộ trình cài WordPress trên VPS từ A đến Z. Hệ thống mẫu trong bài sử dụng Ubuntu 24.04 LTS, NGINX, PHP 8.3 và MariaDB 10.11. Trước khi gõ lệnh, nhớ đối chiếu phiên bản phần mềm, tên systemd service và đường dẫn thực tế trên máy chủ của bạn vì mỗi bản cài đặt có thể khác biệt.

Hãy luôn thao tác trên dữ liệu giả lập, sử dụng tài khoản thử nghiệm tách biệt và làm việc bên ngoài thư mục dữ liệu đang phục vụ khách hàng. Các biến môi trường viết hoa cần được điền bằng giá trị thực tế đã xác minh trên lab; tuyệt đối không lưu mật khẩu, khóa SSH hay thông tin nhạy cảm vào bài viết, lịch sử gõ lệnh shell (~/.bash_history) hoặc đẩy lên kho mã nguồn Git. Nếu gặp thông báo “command not found”, hãy bình tĩnh cài đặt gói công cụ tương ứng theo tài liệu chính thức của hệ điều hành — thiếu công cụ dòng lệnh không có nghĩa là website bị lỗi. Các sơ đồ kỹ thuật trong bài giúp tóm tắt quy trình kiểm kê, đi kèm với bộ ảnh chụp màn hình thực nghiệm bên dưới.

Inventory quyền: User và sudo; Fingerprint SSH key; Cổng và dịch vụ; Quyền ngoài VPS

Sơ đồ kỹ thuật 1: Bốn nhóm quyền truy cập cần kiểm kê đầy đủ khi tiếp nhận bàn giao VPS. Sơ đồ do đội ngũ localhost.vn biên soạn.

Rà soát danh sách User hệ thống và quyền leo thang đặc quyền (sudoers)

Việc đầu tiên khi bước chân vào một con VPS mới nhận bàn giao là liệt kê toàn bộ danh sách tài khoản người dùng (user), xem ai đang nằm trong nhóm quản trị sudo và kiểm tra chính sách sudoers thực tế của tài khoản bạn vừa được giao. Đừng chỉ nhìn lướt qua số định danh UID hay tìm chữ “admin” trong tên tài khoản — một tài khoản mang tên rất ngây thơ như deploy hay dev_temp nhưng được cấu hình NOPASSWD: ALL trong /etc/sudoers.d/ thì thực chất chính là ông vua không ngai root đấy!

getent passwd
getent group sudo
id
sudo -l

Hãy lưu kết quả đầu ra vào hồ sơ bàn giao riêng của dự án. Một kinh nghiệm cho anh em mới: khi chạy lệnh getent passwd, bạn sẽ thấy hàng chục tài khoản hệ thống mặc định của Ubuntu (như www-data, mysql, sshd, systemd-network) được gán shell là /usr/sbin/nologin hoặc /bin/false — đó là các tài khoản chạy tiến trình dịch vụ hoàn toàn bình thường, tuyệt đối đừng thấy tên lạ mà nổi hứng xóa bừa làm sập cả máy chủ! Với mỗi tài khoản người dùng thực sự (thường có UID >= 1000 và có login shell như /bin/bash), hãy lập bảng ghi rõ: ai là người sở hữu, tạo ra để làm việc gì, có quyền sudo hay không và bao giờ thì hết hạn sử dụng. Nếu có tài khoản nào không ai nhận trách nhiệm, hãy hỏi kỹ bên bàn giao trước khi khóa hoặc vô hiệu hóa.

Trong đợt rà soát độc lập vào lúc 14:02:36 (giờ Việt Nam, ngày 01/10/2026) trên máy chủ LAB-CF-02, kết quả xác nhận tài khoản vận hành tutorial mang UID/GID 1000, nằm trong nhóm sudo; thư mục cá nhân (home directory) đặt mode 750, thư mục .ssh đặt mode 700 và file authorized_keys đặt mode 600 chuẩn chỉnh, tất cả đều thuộc quyền sở hữu tutorial:tutorial. Quy tắc cấp quyền trong sudoers hiển thị là (ALL : ALL) ALL (yêu cầu nhập mật khẩu khi dùng sudo, không bật cờ NOPASSWD). Đây là bước khảo sát trạng thái hiện có, không tạo mới hay thay đổi bất kỳ quyền hạn nào.

Console LAB-CF-02 kiểm user tutorial, nhóm sudo và quyền home SSH

Ảnh chụp toàn trang (GoFullPage) lúc 14:03:16 (giờ Việt Nam, ngày 01/10/2026): thực hiện khảo sát chỉ đọc từ phiên console root để kiểm tra thông tin user tutorial, nhóm sudo và phân quyền thư mục .ssh. Độ phân giải gốc của vùng chụp được giữ nguyên kèm chân trang logo localhost.vn. Bấm vào ảnh để xem kích thước đầy đủ.

Đối chiếu danh sách SSH Key trong authorized_keys thông qua mã vân tay (Fingerprint)

Sau khi đã nắm rõ danh sách các tài khoản có thể đăng nhập, bước tiếp theo là mở hộp đen authorized_keys nằm trong thư mục home thực tế của từng user đó (kể cả tài khoản root tại /root/.ssh/authorized_keys), đồng thời kiểm tra cấu hình dịch vụ OpenSSH (sshd) xem có đang trỏ đường dẫn đọc khóa sang một file tùy biến nào khác hay không. Kinh nghiệm làm việc chuyên nghiệp khi đối chiếu biên bản bàn giao là sử dụng mã vân tay (Fingerprint SHA256/ED25519/RSA) của khóa công khai thông qua lệnh ssh-keygen -lf — cách này vừa giúp xác định chính xác từng chiếc chìa khóa, vừa không cần phải dán nguyên cả chuỗi khóa dài ngoằng lên tài liệu báo cáo.

ssh-keygen -lf "$HOME/.ssh/authorized_keys"
sudo sshd -t
sudo sshd -T

Lưu ý kỹ thuật khi gõ lệnh: biến môi trường $HOME trong câu lệnh mẫu trên trỏ tới thư mục cá nhân của chính user đang chạy lệnh; khi cần rà soát các user khác trên máy, hãy truyền trực tiếp đường dẫn tuyệt đối tới file authorized_keys của từng người (nhưng tuyệt đối không gán đè lại biến hệ thống export HOME=... kẻo làm loạn môi trường shell hiện tại). Ngoài ra, lệnh sudo sshd -T chỉ in ra cấu hình hiệu lực tổng quát của SSH daemon; nếu trong file /etc/ssh/sshd_config hoặc thư mục sshd_config.d/ có sử dụng các khối điều kiện Match User / Match Address, bạn sẽ cần thêm cờ -C kèm ngữ cảnh kết nối cụ thể để biết chính xác quy tắc nào áp dụng cho ai. Và hãy khắc cốt ghi tâm nguyên tắc sinh tồn: luôn giữ nguyên cửa sổ terminal SSH hiện tại đang mở, đồng thời mở thêm một cửa sổ thứ hai thử đăng nhập bằng SSH Key mới của bạn cho tới khi vào được bên trong ngon lành rồi mới được phép xóa dòng SSH Key của người cũ!

Trước khi thu hồi: Chủ mới đăng nhập được; Phiên SSH thứ hai; Console cứu hộ đã thử; Backup lấy được

Sơ đồ kỹ thuật 2: Bốn chốt chặn an toàn bắt buộc phải xác nhận trước khi bấm nút thu hồi khóa truy cập cũ. Sơ đồ do đội ngũ localhost.vn biên soạn.

Kiểm tra các Port đang lắng nghe (ss -lntup) và tường lửa UFW / Cloud Firewall

Tiếp nhận một con VPS mà không kiểm tra xem nó đang mở những cổng (Port) nào ra ngoài Internet thì chẳng khác nào mua nhà mới mà không đi kiểm tra các cửa sổ tầng trệt. Lệnh ss -lntup sẽ phơi bày toàn bộ các tiến trình dịch vụ đang lắng nghe kết nối mạng bên trong máy chủ, trong khi lệnh ufw status verbose cho biết bộ quy tắc tường lửa ở tầng hệ điều hành đang cho phép hay chặn cổng nào. Tuy nhiên, hãy nhìn kỹ cột địa chỉ giao diện mạng (Local Address): một dịch vụ cơ sở dữ liệu MariaDB đang lắng nghe ở địa chỉ nội bộ 127.0.0.1:3306 hoàn toàn an toàn và khác một trời một vực với việc nó phơi mình ra toàn cầu ở 0.0.0.0:3306 hay [::]:3306! Đồng thời, nhớ rằng cả ss lẫn ufw chỉ nhìn thấy những gì diễn ra bên trong hệ điều hành, chúng không thể biết được lớp tường lửa đám mây (Cloud Firewall / Security Group) bên ngoài bảng điều khiển của nhà cung cấp VPS đang cấu hình ra sao.

sudo ss -lntup
sudo ufw status verbose
systemctl --failed --no-pager

Với mỗi cổng đang mở xuất hiện trong danh sách, hãy đặt câu hỏi: Dịch vụ nào đang đứng sau cổng này? Ai là người cài đặt nó? Và tại sao nó cần phải mở? Các cổng web 80 (HTTP) và 443 (HTTPS) tất nhiên phải mở công khai để đón khách truy cập; nhưng những cổng như 3306 (MySQL/MariaDB), 6379 (Redis) hay cổng trạng thái của PHP-FPM thì gần như chẳng có lý do gì để phơi ra ngoài Internet trên một máy chủ đơn lẻ cả. Đặc biệt, trước khi chỉnh sửa bất kỳ quy tắc tường lửa nào liên quan đến cổng SSH (mặc định là 22 hoặc một cổng tùy chỉnh), bạn phải xác minh chính xác số cổng mà sshd đang lắng nghe thực tế và đảm bảo mình biết cách mở màn hình VNC/Web Console cứu hộ trên trang quản trị Cloud. Cũng lưu ý về mặt đạo đức và pháp lý: chỉ kiểm tra trong đúng phạm vi máy chủ được bàn giao, không tự ý dùng công cụ quét cổng (port scan) bắn sang các máy chủ ngoài phạm vi quản lý.

Trong đợt khảo sát lúc 13:50:46 (giờ Việt Nam, ngày 01/10/2026) trên LAB-CF-02, tường lửa UFW 0.36.2 đang ở trạng thái active, mở các cổng TCP 22, 80 và 443 cho cả IPv4 lẫn IPv6. Đối chiếu với danh sách socket đang lắng nghe thực tế qua ss, máy chủ có các listener trên IPv4 ở cổng 22/80/443, trên IPv6 ở cổng 22/80, và dịch vụ MariaDB khóa chặt ở giao diện nội bộ 127.0.0.1:3306. Chi tiết này cho thấy một bài học rất thực tế: việc tường lửa UFW có dòng quy tắc cho phép cổng 443 (v6) đi qua không có nghĩa là web server NGINX bên trong đã được cấu hình lắng nghe (`listen [::]:443`) trên giao thức IPv6!

Console đọc luật UFW và listener SSH HTTP HTTPS MariaDB trên LAB-CF-02

Ảnh chụp toàn trang (GoFullPage) lúc 13:54:16 (giờ Việt Nam, ngày 01/10/2026) ghi lại kết quả đọc trạng thái tường lửa UFW và các cổng lắng nghe lúc 13:50:46. Phiên khảo sát này hoàn toàn chỉ đọc thông tin tại chỗ, không thay đổi quy tắc tường lửa. Độ phân giải gốc được giữ nguyên kèm chân trang logo localhost.vn. Bấm vào ảnh để xem rõ chi tiết.

Rà soát chủ sở hữu (Owner) và phân quyền tập tin của ứng dụng WordPress

Sau tầng hệ điều hành và mạng, chúng ta tiến vào kiểm tra ngôi nhà của WordPress: ai đang đứng tên sở hữu (owner:group) thư mục gốc webroot, file cấu hình nhạy cảm wp-config.php và thư mục chứa ảnh tải lên wp-content/uploads? Nguyên tắc bảo mật tối thiểu (Least Privilege) ở đây rất rõ ràng: tiến trình xử lý web PHP-FPM bắt buộc phải có quyền đọc được file wp-config.php để lấy thông tin kết nối Database, nhưng các tài khoản vãng lai không liên quan trên hệ thống thì tuyệt đối không được phép nhòm ngó vào file chứa mật khẩu và bộ khóa SALT này (thường đặt mode 640 hoặc 600 tùy mô hình user/group). Tương tự, chỉ cấp quyền ghi (write) cho user chạy PHP-FPM ở đúng những thư mục thực sự cần sinh dữ liệu động như wp-content/uploads, thay vì mở toang quyền ghi trên toàn bộ mã nguồn lõi WordPress.

: "${WP_ROOT:?Chọn WordPress lab}"
stat -c '%U:%G %a %n' "$WP_ROOT" "$WP_ROOT/wp-config.php"   "$WP_ROOT/wp-content/uploads"

Trước khi định gõ lệnh chown hay chmod để chỉnh sửa bất kỳ điều gì, bạn phải xác định rõ mô hình vận hành của máy chủ đó: tài khoản dùng để đẩy code (deploy user) và tài khoản chạy worker của PHP-FPM (ví dụ www-data) là hai tài khoản tách biệt phối hợp qua nhóm chung, hay là cùng một user cho riêng từng pool? Tuyệt đối không chạy các lệnh thay đổi quyền đệ quy mù quáng khi chưa nhìn rõ bức tranh này. Ngoài ra, hãy nhớ rằng những câu lệnh kiểm tra trên Linux như getent, stat hay việc đọc file authorized_keys sẽ không bao giờ nhìn thấy được các quyền truy cập nằm ở tầng ứng dụng và dịch vụ bên ngoài VPS! Trong biên bản bàn giao, bạn bắt buộc phải rà soát thêm: danh sách tài khoản Administrator bên trong bảng wp_users của WordPress, các khóa API (API keys) gắn trong plugin thanh toán/gửi mail SMTP, quyền truy cập kho lưu trữ backup offsite (S3 / R2), tài khoản quản trị tên miền (DNS / Cloudflare) và tài khoản thanh toán tại nhà cung cấp VPS.

Trong đợt khảo sát lúc 10:52:49 (giờ Việt Nam, ngày 01/10/2026) trên máy lab, kết quả ghi nhận file mã nguồn index.php đặt mode 644, file cấu hình wp-config.php khóa chặt ở mode 640, còn thư mục uploads cùng thư mục con theo tháng 2026/09 mang mode 2775 (bật cờ setgid để các file/thư mục tạo mới bên trong tự động kế thừa nhóm sở hữu), tất cả đều đứng tên tutorial:www-data. Thử nghiệm thực tế cho thấy user www-data đọc được file cấu hình ngon lành nhưng bị chặn không cho phép sửa file mã nguồn index.php; đồng thời một file thăm dò (probe file) đặt mode 600 bên trong thư mục uploads đã được tạo thử thành công dưới quyền www-data rồi dọn dẹp sạch sẽ ngay lập tức.

Console kiểm tra phân quyền cấu hình WordPress và probe ghi file uploads dưới www-data

Ảnh chụp toàn trang (GoFullPage) lúc 10:53:28 (giờ Việt Nam, ngày 01/10/2026): tập lệnh kiểm tra phân quyền file cấu hình WordPress và thử khả năng ghi vào thư mục uploads dưới quyền www-data mà không làm lộ mật khẩu hay chuỗi khóa SALT. Độ phân giải gốc được giữ nguyên kèm chân trang logo localhost.vn. Bấm vào ảnh để phóng to.

Quy trình thu hồi SSH Key và quyền truy cập cũ một cách an toàn, không tự nhốt mình

Khi đã có trong tay bản kiểm kê đầy đủ, đừng vội vàng cầm dao đi chém sạch các khóa cũ ngay! Hãy tuân thủ trình tự an toàn của những kỹ sư từng trải: Đầu tiên, hãy xác nhận tài khoản và cặp SSH Key mới của người tiếp nhận đã đăng nhập vào máy chủ và nâng quyền sudo mượt mà; thứ hai, xác nhận bạn đã nắm được quyền truy cập vào kho chứa bản sao lưu (backup) và thử tải về giải nén thành công; thứ ba, đăng nhập thử vào trang quản trị Cloud của nhà cung cấp VPS để chắc chắn rằng nếu lỡ tay làm hỏng cấu hình SSH thì bạn vẫn còn đường mở Web Console / VNC vào cứu máy. Khi cả ba đường lui đó đã vững như bàn thạch, bạn mới bắt đầu gỡ bỏ từng quyền truy cập cũ đã hết hạn sử dụng và kiểm tra đối chứng sau mỗi bước.

Đối với thao tác thu hồi một SSH Key cụ thể trong file authorized_keys, hãy thực hiện chuẩn chỉnh theo 4 bước sau:

  1. Định danh chính xác khóa cần xóa: Đối chiếu mã vân tay (fingerprint), tên tài khoản chứa khóa và chú thích ở cuối dòng khóa để chỉ đích danh chiếc chìa khóa cần thu hồi. Luôn giữ nguyên một cửa sổ terminal đang đăng nhập sẵn (đừng đóng!) và mở sẵn trang Web Console dự phòng.
  2. Thử nghiệm chìa khóa sẽ giữ lại trên một kết nối hoàn toàn mới: Mở một cửa sổ terminal mới và đăng nhập vào VPS bằng chiếc SSH Key của chủ mới (hoặc khóa sẽ được giữ lại). Tuyệt đối không nhìn vào cửa sổ SSH đang mở từ sáng để tự tin rằng khóa mới đã hoạt động!
  3. Sao lưu và xóa đúng dòng khóa chỉ định: Tạo một bản sao lưu dự phòng cho file authorized_keys (giữ nguyên quyền sở hữu và mode 600). Sau đó mở file ra và chỉ xóa đúng dòng chứa public key cần thu hồi, giữ nguyên các dòng khóa hợp lệ khác của đồng nghiệp đang cùng vận hành hệ thống. Đừng bao giờ nhắm mắt xóa trắng cả file authorized_keys!
  4. Kiểm tra đối chứng cả hai chiều: Từ máy trạm bên ngoài, thử mở một kết nối SSH mới bằng chính chiếc chìa khóa vừa bị thu hồi để xác nhận máy chủ từ chối thẳng thừng (Permission denied); ngay sau đó, thử mở tiếp một kết nối mới bằng chiếc chìa khóa được giữ lại để khẳng định đường quản trị chính thức vẫn thông suốt 100%.

Bạn có thể sử dụng khối lệnh mẫu cực kỳ chặt chẽ dưới đây trên máy trạm giữ khóa (sau khi đã điền đúng các biến LAB_SSH_HOST, LAB_SSH_PORT, LAB_SSH_USER, đường dẫn khóa KEY_TO_TEST và file LAB_KNOWN_HOSTS chứa host key đã xác thực của máy chủ). Câu lệnh này được thiết kế để kiểm tra thuần túy khả năng xác thực của đúng một file khóa chỉ định trên một kết nối mới tinh (do cờ -F /dev/null bỏ qua file config cá nhân nên chỉ dùng cho kết nối trực tiếp tới IP/Host, không áp dụng nếu bạn phải đi vòng qua Bastion / Jump Host):

(
  set -eu
  : "${LAB_SSH_HOST:?Đặt host lab đã xác minh}"
  : "${LAB_SSH_PORT:?Đặt cổng SSH thực tế}"
  : "${LAB_SSH_USER:?Đặt user lab}"
  : "${KEY_TO_TEST:?Đặt đường dẫn khóa riêng cần kiểm}"
  : "${LAB_KNOWN_HOSTS:?Đặt file host key đã xác minh}"
  test -f "$KEY_TO_TEST" || exit 1
  test -r "$KEY_TO_TEST" || exit 1
  test -f "$LAB_KNOWN_HOSTS" || exit 1
  test -r "$LAB_KNOWN_HOSTS" || exit 1
  ssh -F /dev/null -i "$KEY_TO_TEST" \
    -o IdentitiesOnly=yes -o IdentityAgent=none \
    -o ControlMaster=no -o ControlPath=none \
    -o ConnectTimeout=10 -o ConnectionAttempts=1 \
    -o BatchMode=yes -o PreferredAuthentications=publickey \
    -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no \
    -o StrictHostKeyChecking=yes -o UserKnownHostsFile="$LAB_KNOWN_HOSTS" \
    -o GlobalKnownHostsFile=/dev/null -o UpdateHostKeys=no \
    -p "$LAB_SSH_PORT" -l "$LAB_SSH_USER" -- "$LAB_SSH_HOST" \
    'id -u; hostname'
)

Hãy để ý các tham số kỹ thuật đắt giá trong câu lệnh trên: cờ BatchMode=yes buộc quá trình kết nối phải diễn ra hoàn toàn tự động mà không dừng lại hỏi mật khẩu trên màn hình. Đồng thời, chúng ta chủ động ngắt biến SSH_AUTH_SOCK (tắt SSH Agent) và đặt ControlPath=none (tắt cơ chế dùng chung đường hầm kết nối Multiplexing) kèm IdentitiesOnly=yes để ép client chỉ được phép chìa ra đúng một chiếc chìa khóa KEY_TO_TEST duy nhất — tránh trường hợp khóa đang thử đã bị xóa trên server nhưng bạn vẫn đăng nhập vào được ngon lành chỉ vì SSH Agent trên máy Mac âm thầm lấy một chiếc chìa khóa khác ra mở cửa hộ, hoặc đi ké qua phiên kết nối cũ đang mở sẵn!

Lưu ý nhỏ: nếu file private key của bạn có đặt mật khẩu bảo vệ (passphrase), việc tắt SSH Agent kết hợp với BatchMode=yes sẽ khiến client không thể mở khóa và báo lỗi ngay tại máy trạm — lỗi đó là do chưa nhập passphrase chứ chưa phải bằng chứng khóa đã bị server từ chối (với khóa có passphrase, bạn có thể đổi riêng thành BatchMode=no để gõ passphrase mở khóa trong khi vẫn khóa chặt PasswordAuthentication=no và KbdInteractiveAuthentication=no). Ngoài ra, mã thoát exit 255 của lệnh ssh có thể xuất phát từ nhiều nguyên nhân (mạng đứt, sai cổng, lệch host key hoặc bị từ chối khóa), nên hãy luôn nhìn thông báo xác thực thực tế và chỉ kết luận thu hồi thành công khi chính chiếc khóa đó vừa đăng nhập được ở bước trước và bị từ chối ở bước sau.

Và đừng quên một sự thật rất quan trọng về cơ chế hoạt động của OpenSSH: việc bạn xóa một dòng public key khỏi file authorized_keys chỉ chặn đứng các lượt đăng nhập mới từ thời điểm đó trở đi, chứ nó KHÔNG tự động đá văng các phiên terminal SSH mà người cũ đã mở sẵn từ trước đó! Nếu quy trình bàn giao yêu cầu cắt đứt ngay lập tức mọi kết nối hiện hành của đội ngũ cũ, người quản trị phải chủ động rà soát các phiên đang hoạt động (qua lệnh who, w hoặc ps) để đóng đúng tiến trình phiên đó. Tương tự, đối với các mật khẩu Database hay khóa API từng chia sẻ chung, hãy xoay vòng (rotate) đổi sang khóa mới ở hệ thống đích rồi cập nhật vào file cấu hình ứng dụng — việc bạn chỉ xóa dòng mật khẩu cũ trong file tài liệu Google Docs hoàn toàn không làm mật khẩu đó hết hiệu lực trên server đâu! Cuối cùng, nhớ bàn giao luôn cả địa chỉ nhận cảnh báo (Alerting), lịch bảo trì định kỳ và đầu mối chịu trách nhiệm khi có sự cố.

Tiêu chuẩn nghiệm thu bàn giao và giới hạn của phiên thực nghiệm

Một biên bản nghiệm thu bàn giao VPS hoàn chỉnh cần xác nhận rành mạch 4 điều: mỗi tài khoản và quyền hạn còn tồn tại trên máy đều có chủ sở hữu rõ ràng; người tiếp nhận mới đã đăng nhập và thực thi quyền quản trị thành công; toàn bộ các khóa và tài khoản hết nhu cầu sử dụng đã được thu hồi và kiểm chứng từ chối kết nối mới; và mọi cổng mạng đang mở đều có lý do phục vụ dịch vụ chính đáng. Khi trích xuất hình ảnh hoặc log đưa vào báo cáo chung, hãy che kỹ địa chỉ IP thực và thông tin cá nhân nhạy cảm.

Bàn giao hoàn tất: Quyền có chủ sở hữu; Bí mật cũ đã thay; Cổng có mục đích; Cảnh báo có người nhận

Sơ đồ kỹ thuật 3: Bốn tiêu chí vàng xác nhận quá trình chuyển giao quyền quản trị VPS đã khép lại an toàn. Sơ đồ do đội ngũ localhost.vn biên soạn.

Biên bản kiểm kê thực tế trên máy chủ LAB-CF-02 ngày 01/10/2026

Đợt khảo sát chỉ đọc đầu tiên diễn ra vào lúc 00:36 (giờ Việt Nam, ngày 01/10/2026) đã ghi nhận toàn bộ trạng thái cấu hình và quyền truy cập trên máy chủ LAB-CF-02 như bảng dưới đây mà không thực hiện bất kỳ thay đổi nào đối với dịch vụ SSH hay tập tin khóa:

Hạng mục kiểm kê Trạng thái ghi nhận thực tế trên máy lab
Kiểm tra cú pháp cấu hình SSH daemon Lệnh sshd -t hoàn tất êm ru (không có lỗi cú pháp)
Các thông số cấu hình sshd đang có hiệu lực Lắng nghe ở cổng 22; bật PubkeyAuthentication yes, PasswordAuthentication yes, PermitRootLogin yes, tắt KbdInteractiveAuthentication no, bật UsePAM yes
Trạng thái SSH Key của 2 tài khoản trên lab (root và tutorial) Mỗi file authorized_keys chứa đúng 1 dòng khóa; mã vân tay (fingerprint) của khóa ở cả hai user trùng khớp nhau. Thư mục .ssh đặt mode 700, file khóa đặt mode 600
Đường dẫn file khóa phụ và lệnh lấy khóa động Cấu hình có khai báo đường dẫn dự phòng authorized_keys2 nhưng tập tin này không tồn tại ở cả hai user; thông số AuthorizedKeysCommand đặt là none
Chính sách cấp quyền sudoers User tutorial nằm trong nhóm sudo với quy tắc chuẩn (ALL : ALL) ALL, không cấu hình NOPASSWD
Trạng thái các dịch vụ hệ thống systemd Lệnh systemctl --failed xác nhận có 0 unit gặp lỗi

Các thông số cấu hình SSH ở bảng trên hoàn toàn đồng nhất giữa kết quả xuất chung của sshd -T và phép kiểm tra theo ngữ cảnh kết nối cụ thể sshd -T -C cho cả hai tài khoản root và tutorial. Để đảm bảo nguyên tắc bảo mật thông tin, biên bản công khai này chỉ ghi nhận số lượng khóa và kết quả đối chiếu trùng khớp, hoàn toàn không in chuỗi khóa hay mã vân tay thật lên mặt báo.

Một nhận xét thẳng thắn của đàn anh kỹ thuật khi nhìn vào bảng kiểm kê hiện trạng trên: việc máy chủ đang bật đồng thời PermitRootLogin yes, PasswordAuthentication yes và để cả hai tài khoản root lẫn tutorial dùng chung một cặp SSH Key chỉ là hiện trạng ban đầu chúng tôi ghi nhận được trên máy lab mới tạo, tuyệt đối KHÔNG phải là hình mẫu bảo mật chuẩn để bạn học theo! Khi tiếp nhận một máy chủ có cấu hình mở toang như vậy trong thực tế, nhiệm vụ của người nhận bàn giao là phải xác minh rõ nhu cầu sử dụng, thiết lập khóa riêng cho từng cá nhân, chuẩn bị sẵn đường Console cứu hộ rồi tiến hành khóa đăng nhập mật khẩu và khóa quyền đăng nhập trực tiếp của root lại.

Về bức tranh cổng mạng tại thời điểm 00:36: các cổng TCP đang lắng nghe gồm có *:22 (SSH), 0.0.0.0:80 và [::]:80 (HTTP), 0.0.0.0:443 (HTTPS), 127.0.0.1:3306 (MariaDB nội bộ) và 127.0.0.1:8081 (vhost bản clone nội bộ); bên cạnh đó cổng DNS 53 chỉ lắng nghe ở địa chỉ loopback stub resolver và cổng UDP 68 phục vụ cấp phát IP động DHCP. Tường lửa UFW đang bật (active), chặn mặc định toàn bộ kết nối chiều vào (deny incoming), mở chiều ra (allow outgoing) và chỉ cho phép đi vào ở 3 cổng TCP 22/80/443 trên cả IPv4 và IPv6.

Về phân quyền thư mục ứng dụng: thư mục gốc webroot của trang chính đặt mode 755 thuộc quyền sở hữu tutorial:www-data; cả hai file wp-config.php ở trang chính và bản clone đều khóa ở mode 640; còn thư mục uploads cùng nhánh thư mục tháng 2026/09 đặt mode 2775.

Bên cạnh bước đọc cấu hình tĩnh lúc 00:36, trong suốt ngày 01/10/2026 chúng tôi đã thực hiện chuỗi các bài kiểm tra hành vi thực tế để xác minh toàn diện đường quản trị, đường cứu hộ và khả năng lấy bản sao lưu (backup):

  • Khung giờ 03:55:11–03:55:13: Trong khi vẫn giữ nguyên một cửa sổ terminal root mở sẵn làm chốt bảo hiểm, chúng tôi thực hiện mở kết nối SSH mới tinh bằng tài khoản tutorial thành công (xác nhận đúng UID 1000 và hostname), sau đó chạy lệnh nâng quyền sudo kèm mật khẩu hiện hành và nhận về UID 0 chuẩn xác. Đồng thời, các bài test tiêu cực dùng thử một khóa chưa được cấp quyền và một file known_hosts chứa khóa máy chủ giả mạo đều bị hệ thống chặn đứng ngay lập tức.

  • Mốc 08:17:04: Đăng nhập trực tiếp vào giao diện bảng điều khiển CloudFly Web Console của máy chủ LAB-CF-02 và đối chiếu mã vân tay khóa máy chủ ED25519 khớp 100% với file known_hosts trên máy trạm. Bước này xác nhận đường cứu hộ vật lý ngoài luồng mạng SSH (out-of-band console) luôn sẵn sàng hoạt động.

  • Khung giờ 08:10:02–08:10:15: Thực hiện kéo 4 thành phần của gói sao lưu WordPress (gồm file nén mã nguồn archive, bản dump cơ sở dữ liệu SQL, file danh mục manifest và bảng mã băm checksum) từ kho lưu trữ mã hóa Restic về máy trạm macOS, giải mã và kiểm tra độ toàn vẹn đạt chuẩn 100%.

  • Khung giờ 12:36:35–12:37:11: Từ bộ sao lưu đã kéo về máy Mac, tiến hành đẩy ngược 4 tập tin này lên một thư mục đích hoàn toàn mới trên VPS để diễn tập khôi phục toàn diện. Toàn bộ 4.012 tập tin khớp mã băm SHA-256; trang WordPress 7.1.2 sau khi khôi phục có đầy đủ 2 bài viết đã xuất bản, vượt qua bài kiểm tra cơ sở dữ liệu, trang chủ và đường dẫn bài viết trả về HTTP 200, đồng thời trình khách HTTP đăng nhập nhận cookie và vào trang quản trị wp-admin nhận mã 200 ngon lành.

  • Mốc 13:52:01: Thực hiện lại một lượt kết nối SSH mới từ máy Mac bằng khóa hiện hữu vào tài khoản tutorial và xác thực quyền sudo thành công (mã thoát exit 0), sau đó xóa ngay bộ đệm thời gian chờ của sudo (sudo -k) để đóng phiên an toàn.

Diễn tập cấp phát và thu hồi một SSH Key tạm thời (Phiên thực nghiệm 11:51)

Trong khoảng thời gian từ 11:51:01 đến 11:51:03 ngày 01/10/2026 (UTC+7), chúng tôi thực hiện một kịch bản diễn tập trọn vòng đời của một chiếc chìa khóa bàn giao: tạo một cặp khóa SSH mới tinh dùng một lần, gắn khóa công khai (public key) đó vào tài khoản tutorial trên LAB-CF-02, kiểm tra đăng nhập, sau đó thu hồi khóa và xác minh kết quả. Ở phía máy trạm, câu lệnh kiểm tra luôn chỉ định tường minh file khóa, tắt SSH Agent và tắt cơ chế tái sử dụng kết nối để đảm bảo mỗi lượt gọi đều là một lần bắt tay xác thực mới hoàn toàn.

Bước thực hiện trong kịch bản Kết quả ghi nhận thực tế
1. Chuẩn bị trước khi cấp khóa Xác nhận đúng máy chủ lab, giữ sẵn phiên quản trị dự phòng, kiểm tra sshd -t đạt chuẩn
2. Sau khi gắn thêm khóa tạm vào authorized_keys Mở kết nối SSH mới bằng chính khóa tạm đó thành công mỹ mãn, trả về đúng UID 1000 và tên máy chủ
3. Thực hiện thu hồi khóa tạm Xóa đúng dòng chứa khóa tạm khỏi file authorized_keys; khôi phục nguyên trạng nội dung gốc cùng quyền sở hữu và mode 600
4. Thử đăng nhập lại bằng chiếc khóa vừa bị thu hồi Kết nối SSH mới bị máy chủ từ chối xác thực ngay lập tức, trả về mã thoát exit 255
5. Kiểm tra quyền quản trị gốc và dọn dẹp Các khóa quản trị chính của root và tutorial vẫn đăng nhập bình thường; mã băm (hash) của file authorized_keys và sshd_config giữ nguyên 100%; cặp file khóa tạm trên máy trạm được xóa bỏ hoàn toàn

Phiên diễn tập ngắn gọn lúc 11:51 này đã chứng minh rõ ràng quy trình chuẩn: chiếc chìa khóa sau khi bị gỡ khỏi authorized_keys đã lập tức mất tác dụng ở lượt kết nối mới tiếp theo mà không làm ảnh hưởng gì tới chiếc chìa khóa chính đang vận hành hệ thống. Lưu ý rằng ba tấm ảnh chụp màn hình console ở các mục trước là ảnh của các đợt khảo sát cấu hình độc lập, không dùng để minh họa giả làm ảnh chụp của ca thu hồi khóa lúc 11:51 này.

Xử lý sự cố khi khóa mới không đăng nhập được và cách khôi phục cấu hình SSH

Trong quá trình chuyển giao, nếu bạn vừa gắn SSH Key mới vào cho người tiếp nhận nhưng họ mở cửa sổ terminal thứ hai thử đăng nhập lại cứ bị báo lỗi Permission denied (publickey), thì quy tắc số một là: tuyệt đối không được xóa khóa cũ và không được đóng cửa sổ terminal đang mở sẵn! Hãy dùng chính cửa sổ đang mở đó để kiểm tra lại 4 điểm hay sai nhất: một là chuỗi public key dán vào file authorized_keys có bị xuống dòng giữa chừng hay mất ký tự đầu/cuối không; hai là quyền sở hữu (chown) và phân quyền (chmod 700 ~/.ssh và chmod 600 ~/.ssh/authorized_keys) đã chuẩn chưa (nếu thư mục home hoặc .ssh mở quyền ghi quá rộng cho nhóm khác như 777 hay 775, chế độ StrictModes của OpenSSH sẽ từ chối đọc file khóa ngay lập tức!); ba là kiểm tra log xác thực tại /var/log/auth.log (hoặc journalctl -u ssh); và bốn là kiểm tra tường lửa UFW.

Khi chỉnh sửa bất kỳ thông số nào trong file /etc/ssh/sshd_config, hãy luôn gõ lệnh sudo sshd -t để rà soát cú pháp trước; nếu lệnh này còn báo lỗi thì tuyệt đối không được gõ systemctl reload ssh! Nếu cấu hình mới làm phát sinh sự cố ngoài ý muốn, hãy bình tĩnh chép đè bản sao lưu sshd_config ban đầu quay trở lại thông qua phiên kết nối dự phòng đang mở hoặc qua màn hình Web Console của nhà cung cấp VPS — đừng bao giờ đợi tới lúc bị đá văng khỏi mọi cửa sổ SSH rồi mới bắt đầu đi hỏi mật khẩu đăng nhập trang quản trị Cloud ở đâu!

Câu hỏi thường gặp (FAQ)

Tôi đã dùng lệnh passwd để đổi mật khẩu của user trên Linux rồi thì các SSH Key cũ của người trước có tự động bị vô hiệu hóa không?

Hoàn toàn không! Cơ chế xác thực bằng cặp khóa bất đối xứng (Public Key Authentication) của OpenSSH hoạt động độc lập hoàn toàn với mật khẩu tài khoản hệ điều hành. Dù bạn có đổi mật khẩu Linux phức tạp cỡ nào đi nữa, nếu khóa công khai của người cũ vẫn còn nằm trong file ~/.ssh/authorized_keys thì họ vẫn đi thẳng vào máy chủ không cần hỏi han một chữ mật khẩu nào. Muốn chặn họ, bạn bắt buộc phải xóa dòng khóa đó trong authorized_keys.

Để cho gọn và an toàn, tôi có nên xóa sạch mọi tài khoản user khác trên máy và chỉ giữ lại duy nhất tài khoản root không?

Đừng bao giờ làm điều dại dột đó! Trong hệ điều hành Ubuntu/Linux có hàng chục tài khoản hệ thống chuyên trách chạy các dịch vụ nền như www-data (chạy NGINX/PHP-FPM), mysql (chạy MariaDB) hay sshd. Xóa các tài khoản này sẽ làm sập toàn bộ máy chủ ngay lập tức. Hơn nữa, thực hành bảo mật tốt là sử dụng tài khoản cá nhân kết hợp quyền sudo để lưu vết nhật ký ai làm gì, thay vì dùng chung tài khoản root cho mọi thao tác.

Chỉ cần tắt đăng nhập SSH bằng mật khẩu (PasswordAuthentication no) là đã đủ bảo mật tuyệt đối cho VPS chưa?

Tắt đăng nhập bằng mật khẩu là một bước cực kỳ quan trọng để vô hiệu hóa các cuộc tấn công dò mật khẩu tự động (brute-force), nhưng một mình nó thì chưa đủ! Một con VPS an toàn còn đòi hỏi bạn phải quản lý chặt chẽ danh sách người đang giữ SSH Key, cấu hình quyền sudoers hợp lý, bật tường lửa giới hạn cổng, cập nhật bản vá bảo mật định kỳ cho cả hệ điều hành lẫn plugin WordPress, và luôn duy trì bản sao lưu offsite kèm đường Console cứu hộ.

Bước tiếp theo sau khi hoàn tất bàn giao quyền truy cập

Ngay sau khi tiếp nhận máy chủ, hãy lập một trang bảng biểu quản lý tài sản truy cập rõ ràng: mỗi tài khoản hoặc SSH Key đang tồn tại thuộc về cá nhân nào (ghi kèm mã vân tay fingerprint), lý do cần duy trì hay đã thu hồi vào ngày giờ nào, và kết quả kiểm tra đăng nhập mới ra sao. Hãy chắc chắn rằng chính tay người nhận bàn giao đã tự đăng nhập thử vào bảng điều khiển Web Console của nhà cung cấp VPS và tự kéo thử một bản sao lưu (backup) về kiểm tra thành công trước khi xóa bỏ quyền truy cập của người bàn giao cũ. Khi ngôi nhà VPS đã thực sự nằm trong tầm kiểm soát an toàn của bạn, mời bạn tiếp tục hoàn thiện các mảnh ghép vận hành khác trong series WordPress từ A đến Z.

Tài liệu tham khảo và trạng thái đối chiếu kỹ thuật

Tài liệu đã đối chiếu ngày 01/10/2026: Tài liệu hướng dẫn chính thức (manpages) của dự án OpenSSH giải thích rõ sự khác biệt giữa việc kiểm tra cú pháp cấu hình (-t), xuất cấu hình hiệu lực tổng thể (-T) và kiểm tra theo ngữ cảnh kết nối cụ thể (-C). Tài liệu phía client SSH làm rõ cơ chế chọn khóa định danh (identity file) tách biệt với SSH Agent và đường hầm kết nối dùng chung. Toàn bộ các đợt kiểm kê, thử nghiệm đăng nhập và thu hồi khóa tạm trên máy lab đều được ghi nhận trung thực theo từng mốc thời gian ở trên.

Tài liệu nền tảng đã đối chiếu ngày 30/09/2026:

Tài liệu tham khảo & Kiểm chứng

CẦN KỸ SƯ HỖ TRỢ TRỰC TIẾP? Đang làm theo hướng dẫn nhưng vướng lỗi hệ thống hoặc sợ đụng chạm dữ liệu đang chạy?

Gửi địa chỉ URL qua Zalo để kỹ thuật viên localhost.vn kiểm tra sơ bộ miễn phí trước khi quyết định can thiệp.

Xem bảng dịch vụ
Góc thực chiến localhost.vn

Mọi hướng dẫn đều dựa trên số liệu đo đạc, log thực tế và nguyên tắc "luôn có đường lùi (Snapshot/Backup) trước khi gõ lệnh".

Nguyên tắc biên tập & Minh bạch ↗