Secure Ubuntu cho WordPress: Nginx, PHP-FPM, SSL, quyền file

13/05/2026 · P T P · Chung

Secure Ubuntu server cho website WordPress: Nginx, PHP-FPM, SSL, quyền file

Một site WordPress nhanh chưa đủ. Site phải khó bị chiếm quyền, dễ khôi phục, ít lộ thông tin, đúng quyền file, có SSL chuẩn, Nginx/PHP-FPM tách bạch. Phần lớn sự cố WordPress không đến từ “hacker quá giỏi”, mà từ cấu hình ẩu: SSH mở rộng, user dùng chung, file 777, PHP execute trong uploads, SSL yếu, plugin lỗi thời, backup không test.

Bài này tập trung vào hardening Ubuntu server chạy WordPress với stack: Ubuntu + Nginx + PHP-FPM + MariaDB/MySQL + SSL.


1. Nền tảng server: cập nhật, user, SSH

Trước WordPress → khóa nền OS.

Cập nhật hệ thống

sudo apt update && sudo apt upgrade -y
sudo apt install unattended-upgrades ufw fail2ban curl unzip -y
sudo dpkg-reconfigure unattended-upgrades

Mục tiêu: vá CVE nhanh, giảm cửa tấn công.

Tạo user deploy, hạn chế root

adduser deploy
usermod -aG sudo deploy

SSH bằng root → rủi ro cao. Tắt root login:

sudo nano /etc/ssh/sshd_config

Khuyến nghị:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Restart:

sudo systemctl restart ssh

Lưu ý: trước khi tắt password, phải test key SSH từ terminal khác. Sai → tự khóa khỏi server.


2. Firewall: chỉ mở cổng cần thiết

UFW đơn giản, đủ dùng.

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status

Port cần: 22, 80, 443. Nếu đổi SSH port, mở port mới trước khi đóng port cũ.

Ví dụ:

sudo ufw allow 2222/tcp

Sau đó chỉnh SSH config.


3. Cài Nginx, PHP-FPM, extension WordPress

sudo apt install nginx php-fpm php-mysql php-cli php-curl php-gd php-mbstring php-xml php-zip php-imagick -y

Kiểm tra PHP-FPM:

systemctl status php8.3-fpm

Phiên bản có thể khác: php8.1-fpm, php8.2-fpm, php8.3-fpm.


4. Cấu hình Nginx an toàn cho WordPress

Tạo server block:

sudo nano /etc/nginx/sites-available/example.com

Mẫu cấu hình:

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com/public;
    index index.php index.html;

access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log;

client_max_body_size 64M;

location / { try_files $uri $uri/ /index.php?$args; }

location ~ .php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; }

location ~ /(?:uploads|files)/..php$ { deny all; }

location ~ /.(?!well-known).* { deny all; }

location ~* .(?:bak|conf|sql|ini|log|sh|inc|swp|dist)$ { deny all; }

location = /xmlrpc.php { deny all; } }

Kích hoạt:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Giải thích nhanh

try_files → permalink WordPress chạy đúng.
– Chặn PHP trong uploads → ngăn upload shell.
– Chặn dotfile → bảo vệ .env, .git.
– Chặn file backup/config/log → giảm rò rỉ.
– Chặn xmlrpc.php nếu không dùng Jetpack/app mobile → giảm brute force/DDoS.

Nếu cần XML-RPC, không deny toàn bộ; giới hạn IP hoặc dùng plugin bảo vệ.


5. PHP-FPM hardening

Mở pool config:

sudo nano /etc/php/8.3/fpm/php.ini

Khuyến nghị:

expose_php = Off
display_errors = Off
log_errors = On
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 120
cgi.fix_pathinfo = 0

Restart:

sudo systemctl restart php8.3-fpm

Tách pool theo site

Nhiều website trên cùng server → nên tách user/pool. Một site bị lỗi → không lan toàn server.

Tạo user riêng:

sudo adduser --system --group --home /var/www/example.com wp-example

Pool riêng:

sudo cp /etc/php/8.3/fpm/pool.d/www.conf /etc/php/8.3/fpm/pool.d/example.com.conf

Chỉnh:

[example.com]
user = wp-example
group = wp-example
listen = /run/php/php8.3-fpm-example.com.sock
listen.owner = www-data
listen.group = www-data
pm = ondemand
pm.max_children = 20

Nginx:

fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock;

Kết quả: site isolation tốt hơn.


6. SSL/TLS với Let’s Encrypt

Cài Certbot:

sudo apt install certbot python3-certbot-nginx -y

Cấp cert:

sudo certbot --nginx -d example.com -d www.example.com

Test renew:

sudo certbot renew --dry-run

Tăng bảo mật HTTPS

Certbot thường tự thêm redirect HTTP → HTTPS. Kiểm tra Nginx có dòng:

return 301 https://$host$request_uri;

Có thể thêm header:

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

HSTS chỉ bật khi chắc chắn HTTPS ổn lâu dài:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Cảnh báo: HSTS sai → browser buộc HTTPS, site phụ/subdomain lỗi SSL cũng bị ảnh hưởng.


7. Quyền file WordPress: điểm sống còn

Sai quyền file → hậu quả nặng. 777 → gần như mời tấn công.

Giả sử source ở:

/var/www/example.com/public

Owner nên là user site, group là web server:

sudo chown -R wp-example:www-data /var/www/example.com/public

Quyền thư mục:

sudo find /var/www/example.com/public -type d -exec chmod 755 {} ;

Quyền file:

sudo find /var/www/example.com/public -type f -exec chmod 644 {} ;

wp-config.php nhạy cảm:

sudo chmod 640 /var/www/example.com/public/wp-config.php

Nếu muốn chặt hơn:

sudo chmod 600 /var/www/example.com/public/wp-config.php

Nhưng phải đảm bảo PHP-FPM user đọc được.

Không cho chỉnh theme/plugin từ admin

Trong wp-config.php:

define('DISALLOW_FILE_EDIT', true);

Nếu muốn chặn cài/update từ admin, dùng:

define('DISALLOW_FILE_MODS', true);

Đổi lại: update phải qua SSH/WP-CLI/deploy pipeline.


8. Bảo vệ database

Tạo DB/user riêng, không dùng root DB cho WordPress.

CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'strong_password_here';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP ON wordpress.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;

Không cấp GRANT ALL nếu không cần. Không mở MySQL ra Internet. Kiểm tra bind:

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

Nên có:

bind-address = 127.0.0.1

9. WordPress hardening bên trong

Salt keys

Tạo salt mới:

https://api.wordpress.org/secret-key/1.1/salt/

Dán vào wp-config.php.

Prefix table

Không dùng wp_ nếu cài mới. Ví dụ:

$table_prefix = 'x7p_';

Không phải lớp bảo vệ mạnh, nhưng giảm bot scan cơ bản.

Giới hạn login

Dùng plugin uy tín: Wordfence, Solid Security, Limit Login Attempts Reloaded. Nhưng đừng cài quá nhiều plugin bảo mật chồng chéo → lỗi, chậm, false positive.

Update đều

Core, plugin, theme lỗi thời → nguyên nhân phổ biến nhất.

wp core update
wp plugin update --all
wp theme update --all

Nên test staging trước site lớn.


10. Backup, log, giám sát

Không backup → không secure. Backup là tuyến phòng thủ cuối.

Nên có

– Backup DB hằng ngày.
– Backup file wp-content.
– Lưu ngoài server: S3, Backblaze, rsync server khác.
– Mã hóa backup.
– Test restore định kỳ.

Dump DB:

mysqldump -u wpuser -p wordpress > wordpress.sql

Log cần xem

/var/log/nginx/example.com.access.log
/var/log/nginx/example.com.error.log
/var/log/auth.log
/var/log/fail2ban.log

Tìm request đáng ngờ:

grep "wp-login.php" /var/log/nginx/example.com.access.log
grep "xmlrpc.php" /var/log/nginx/example.com.access.log

11. Fail2ban cho SSH, Nginx, WordPress

Fail2ban → chặn brute force.

SSH jail thường có sẵn. Kiểm tra:

sudo fail2ban-client status
sudo fail2ban-client status sshd

Có thể thêm jail cho Nginx login flood, nhưng cần regex đúng. Sai regex → chặn nhầm user thật. Với WordPress, plugin login limit thường dễ triển khai hơn.


12. Checklist nhanh sau triển khai

SSH root login: off.
Password SSH: off, dùng key.
UFW: chỉ mở 22/80/443.
Nginx: chặn PHP trong uploads.
SSL: Let’s Encrypt auto-renew OK.
PHP: expose_php=Off, display_errors=Off.
File perms: dir 755, file 644, wp-config.php 640/600.
DB user: riêng, quyền tối thiểu.
WordPress: update, salt mới, không edit file từ admin.
Backup: offsite, test restore.
Logs: theo dõi định kỳ.


Kết luận thực tế

Secure WordPress trên Ubuntu không phải một lệnh cài plugin. Nó là chuỗi lớp bảo vệ: OS an toàn → SSH khóa chặt → firewall tối giản → Nginx chặn đường nguy hiểm → PHP-FPM tách quyền → SSL chuẩn → file permission đúng → DB least privilege → backup phục hồi được.

Nếu chỉ làm 5 việc quan trọng nhất: tắt SSH password/root, bật UFW, chặn PHP trong uploads, sửa quyền file, backup offsite. Làm thêm SSL header, PHP-FPM pool riêng, DB quyền tối thiểu → site WordPress vững hơn rõ rệt, ít phụ thuộc may mắn, dễ vận hành lâu dài.

#nginx #quyen #secure #ubuntu #wordpress
Chia sẻ:
← Trước
Chặn Brute-Force Ubuntu với UFW và Fail2ban trong 10 phút

Bài viết tương tự

Bình luận

Chưa có bình luận. Hãy là người đầu tiên!