Một blog cá nhân chạy được, an toàn ở mức cơ bản, tốn khoảng 7–9 USD mỗi tháng. Bài này ghi lại tôi đã chọn gì, tốn bao nhiêu, và hai lần đổi ý trên đường đi — để chính tôi đọc lại sau này, và để ai định làm tương tự đỡ mất thời gian.
Làm nghề hơn 15 năm, thứ tôi tiếc nhất không phải là code đã viết, mà là những điều đã học rồi quên: một cách debug hay, những bài học gặp phải trong những va chạm công sở. Hoặc là những trải nghiệm trong các chuyến đi, những gì mình đã nhìn thấy, những bài học đúc kết, đều sẽ dần biến mất nếu ta không giữ lại chúng
Tôi cần một nơi để lưu lại những thứ đó
Make me better — viết trước hết là để mình tốt hơn.
Chọn hạ tầng: rẻ, đủ dùng, học được
Một trang web cá nhân cần ba thứ: tên miền, nơi chạy website, và lớp mạng phía trước (DNS, CDN, bảo vệ). Với phần chạy website, tôi cân nhắc bốn hướng:
| Phương án | Chi phí | Điểm mạnh | Điểm yếu |
|---|---|---|---|
| Shared hosting | Rẻ nhất trong nhóm có server | Cài WordPress một click, không lo vận hành | Chung tài nguyên, ít quyền kiểm soát, khó tuỳ chỉnh |
| Managed WordPress | Đắt nhất | Nhà cung cấp lo bảo mật, backup, tốc độ | Gói rẻ thường giới hạn plugin/theme |
| VPS (AWS Lightsail) | ~7 USD/tháng (1 GB RAM) | Toàn quyền, chi phí cố định, học được rất nhiều | Tự lo cập nhật, bảo mật, backup |
| Static site (Astro/Hugo + Cloudflare Pages) | Gần như 0đ | Nhanh nhất, gần như không có gì để tấn công | Phải tự code, không có trình soạn thảo tiện như WordPress |
Tôi chọn WordPress trên Lightsail, đặt sau Cloudflare Free. Lý do là cần một nền tảng không quá đắt, hỗ trợ mạnh để có thể đáp ứng nhu cầu như bài viết, gallery ảnh, landing page, không cần phải mất quá nhiều thời gian vào việc xây dựng hạ tầng, cũng như bảo mật ở mức ổn.
Ngoài ra, việc tự tay vận hành một server thật để học, để tích hợp các dịch vụ khác nhau, hoặc tối ưu chi phí, tối ưu tốc độ cũng sẽ là kinh nghiệm cho sau này phát triển hoặc review các trang khác.
Static site là hướng đi sau này, khi nội dung đã đủ nhiều và tôi muốn tự code lại. Nhưng đứng ở góc độ vận hành, thì nếu bỏ quá nhiều thời gian vào việc xây lại cái base thì cũng không hẳn là tốt.
Kiến trúc trước mắt:

Với tên miền: mua ở nhà đăng ký nào cũng được, nhưng giá gia hạn mới là thứ cần so, không phải giá năm đầu. Cloudflare Registrar bán đúng giá gốc, không cộng lãi — đáng cân nhắc chuyển về khi sắp gia hạn. Cloudflare Free lo DNS, SSL, CDN và tường lửa ở biên, mất 0đ.
Chi phí thực tế
Hóa đơn AWS một tháng điển hình (tháng 9/2026):
| Khoản | Chi phí/tháng |
|---|---|
| Lightsail 1 GB RAM, 2 vCPU, 40 GB SSD (Singapore) | 7 USD + |
| Thuế | 0,68 USD |
| S3 lưu ~21 MB ảnh | ~0,0006 USD |
| Cloudflare Free (DNS, SSL, CDN, WAF cơ bản) | 0 |
| Tổng | ~7 USD → 9 USD |
Cộng thêm phí tên miền trả theo năm. Snapshot tự động hằng ngày của Lightsail tính thêm theo dung lượng lưu, với site nhỏ chỉ vài cent.
Con số đáng chú ý là dòng S3: gần như bằng 0. Với một blog mới, tiền nằm ở server, không nằm ở lưu trữ ảnh. Muốn giảm chi phí thật sự thì phải bỏ server (static site), chứ không phải tối ưu chỗ để ảnh.
Cài đặt nền: ổn định và bảo mật cơ bản
Bài học đầu tiên: bản WordPress “cài sẵn” của Bitnami trên Lightsail đã ngừng nhận bản vá từ tháng 5/2026 mà tôi không hề để ý. Tôi chuyển sang Ubuntu 24.04 trần và tự cài Nginx + PHP-FPM + MariaDB. Tiện lợi ban đầu không đáng bằng việc biết rõ mình đang chạy gì. Giờ có AI thì những vấn đề này càng đơn giản, không mất công đọc tài liệu và debug như ngày xưa
Danh sách cài đặt tối thiểu tôi áp dụng:
Server
- Static IP gắn vào instance (miễn phí khi đang gắn) — không có nó, chỉ cần stop/start là IP đổi và site sập.
- Firewall chỉ mở cổng 443 cho dải IP của Cloudflare; SSH chỉ dùng key, giới hạn nguồn truy cập.
- Snapshot tự động hằng ngày, và snapshot thủ công trước mọi thay đổi lớn.
- Tự động cài bản vá bảo mật của hệ điều hành.
Cloudflare
- SSL chế độ Full (strict) với Origin Certificate; bật Authenticated Origin Pulls để server chỉ nhận kết nối đến từ chính zone của mình.
- Vài rule WAF miễn phí: chặn
xmlrpc.php, file nhạy cảm, liệt kê user; challenge trang đăng nhập; rate limit khi đoán mật khẩu. - HSTS và vài security header cơ bản.
WordPress
- Chỉ một tài khoản admin, mật khẩu mạnh, bật 2FA.
- Ít plugin nhất có thể; tự động cập nhật bản minor.
- Chặn chạy file PHP trong thư mục upload.
Một điều nhỏ nhưng đắt giá: rule chặn PHP trong upload tôi viết từ đầu chưa từng có tác dụng, vì đặt sai thứ tự trong cấu hình Nginx. Tôi chỉ phát hiện khi test bằng một file có thật. Test với file không tồn tại thì lúc nào cũng ra 404 — và trông như “đã chặn”.
Hai lần đổi ý
Ảnh: từ S3 sang Cloudflare R2
Ban đầu ảnh nằm trên AWS S3, phục vụ qua cdn.nhathm.com. Để Cloudflare gọi được S3, tôi phải để bucket chế độ public và viết thêm một Cloudflare Worker làm trung gian — vì gói Free không cho đổi Host header theo ý S3. Thêm một IAM user, một access key nằm trong file cấu hình WordPress.
Chính tôi phải thừa nhận: với 21 MB ảnh, chuyển sang R2 không tiết kiệm được đồng nào ở thời điểm này. Lý do thật là gọn:
- R2 gắn custom domain trực tiếp, không cần Worker, không cần bucket public.
- Không tính phí băng thông ra (egress), có hạn mức miễn phí dư cho một blog.
- Bỏ được S3, IAM user và key cũ: AWS giờ chỉ còn mỗi Lightsail.
Plugin WP Offload Media bản miễn phí không hỗ trợ R2, nên tôi đổi sang Advanced Media Offloader. Bài học phụ: nếu làm lại từ đầu, tôi sẽ chọn R2 ngay, không phải vì rẻ, mà vì ít mảnh ghép hơn.
Tuy nhiên nếu sau này bắt đầu upload nhiều ảnh hơn, thì S3 có thể trở thành gánh nặng về mặt chi phí, R2 hiện tại đang free nên chuyển sang cũng tốt. Cần tính toán đến việc đưa ảnh lên các host chuyên ảnh, còn website chỉ hiển thị thôi.
Giao diện: từ Elementor về Gutenberg
Elementor đến cùng bộ demo của theme Soledad: kéo-thả trực quan, dựng trang About đẹp trong vài phút mà không cần code. Nhưng khi nhìn kỹ:
- Plugin rất lớn: thêm CSS/JS cho mỗi trang, làm giảm tốc độ trang đáng kể
- Layout lưu dạng JSON riêng — sau này tự code lại site sẽ rất khó mang nội dung đi.
Tôi dựng lại About bằng block Gutenberg (giữ nguyên URL) rồi gỡ Elementor. Kết quả trên trang About, mobile: LCP từ 19,2s xuống 7,7s, dung lượng tải từ 3,9 MB xuống 1,6 MB. Từ giờ mọi nội dung viết bằng Gutenberg. Các trang landing page hoặc tương tự nếu cần sẽ dùng AI generate ra, hợp lý hơn là design bằng Elementor
Tốc độ: chưa vội, nhưng ghi lại để đo
Site chưa có bài nào thì tối ưu tốc độ chưa có nhiều ý nghĩa. Nhưng tôi ghi lại số đo gốc để sau này so sánh.
PageSpeed Insights (Lighthouse 13.6), ngày 03/11/2026: https://pagespeed.web.dev/
| Trang | Mobile | LCP mobile | Desktop | Request / dung lượng |
|---|---|---|---|---|
| Trang chủ | 69 | 6,7s | 98 | 44 / 1,1 MB |
| About | 72 | 7,7s | 95 | 51 / 1,6 MB |
Những việc đã làm: ảnh phục vụ từ R2 qua CDN với cache 1 năm, bỏ Elementor, tắt featured slider ở trang chủ, PHP OPcache.
Những việc sẽ làm khi có nội dung và người đọc, xếp theo hiệu quả dự kiến:
- Ảnh: resize đúng kích thước hiển thị, chuyển WebP/AVIF. Đây là nguyên nhân chính của LCP chậm hiện tại.
- Cache HTML ở Cloudflare: trang phục vụ từ biên, server gần như không phải xử lý.
- Font: tự host, chỉ giữ vài weight cần dùng, subset tiếng Việt.
- CSS/JS thừa của theme: tắt module không dùng.
- Server: Redis object cache, tinh chỉnh PHP-FPM cho máy 1 GB.
Ghi chú để lần sau đo cho đúng:
- Đo cùng hai trang trên, cả mobile và desktop, ghi ngày và phiên bản Lighthouse.
- Chạy 2–3 lần, lấy kết quả giữa; lần đầu thường chậm vì cache còn trống.
- Kiểm tra header
cf-cache-status(HIT hay MISS) để biết trang có được cache không. - Phân biệt điểm lab (Lighthouse) và dữ liệu người dùng thật (Core Web Vitals) khi site đã có lượt truy cập.
Nhìn lại
Nếu làm lại từ đầu, tôi sẽ làm khác ở ba điểm:
- Kiểm tra nền tảng còn được vá không trước khi dùng — đừng tin vào chữ “cài sẵn”.
- Ít mảnh ghép hơn: ít dịch vụ, ít plugin. Mỗi thứ thêm vào đều là một thứ phải cập nhật và bảo vệ.
- Viết trước, tối ưu sau. Tôi đã dành quá nhiều thời gian cho hạ tầng của một trang chưa có bài nào. Hạ tầng chỉ cần đủ an toàn và đủ rẻ; phần còn lại nên dành cho nội dung.
