React + NestJS + PostgreSQL trên Hostinger: từ deploy thủ công đến nền tảng host nhiều website.
Trang này tổng hợp toàn bộ nội dung từ lúc bạn bắt đầu hỏi cách triển khai source ReactJS + NodeJS/NestJS + PostgreSQL lên Hostinger, sau đó mở rộng dần sang Docker, multi-site, CI/CD, hardening và monitoring.
00. Điểm bắt đầu
Bài toán ban đầu rất đơn giản: có source React + backend Node/NestJS + PostgreSQL và muốn đưa toàn bộ lên Hostinger với chi phí hợp lý.
Build thành static files và serve qua Nginx.
Chạy Node.js, API nội bộ qua port 3000.
Chỉ expose nội bộ, không mở 5432 ra Internet.
01. Chọn gói Hostinger
Ngay từ đầu, kết luận quan trọng là: nếu cần PostgreSQL cùng nằm trên Hostinger thì VPS phù hợp hơn shared hosting hoặc managed Node hosting.
| Gói | CPU | RAM | NVMe | Phù hợp |
|---|---|---|---|---|
| KVM 1 | 1 vCPU | 4 GB | 50 GB | Học, staging, app nhỏ |
| KVM 2 | 2 vCPU | 8 GB | 100 GB | Khuyên dùng ban đầu production nhỏ/vừa |
| KVM 4 | 4 vCPU | 16 GB | 200 GB | Nhiều website nhỏ/vừa |
| KVM 8 | 8 vCPU | 32 GB | 400 GB | Workload lớn hơn |
Tại sao không shared hosting?
Shared/managed hosting đơn giản hơn nhưng không phù hợp nếu bạn cần tự quản PostgreSQL, Node runtime, reverse proxy và các service hệ thống.
Tại sao VPS?
Full root access, tự cài PostgreSQL, Docker, Nginx/Traefik, CI/CD agentless qua SSH, và có thể host nhiều site chung một máy.
Giá khuyến mãi Hostinger thay đổi theo thời điểm và kỳ thanh toán. Website này giữ nguyên logic chọn gói, nhưng khi mua nên kiểm tra lại bảng giá hiện tại.
02. Cách deploy thủ công ban đầu
Đây là cách dễ học nhất trước khi sang Docker: cài trực tiếp Nginx, Node, PM2 và PostgreSQL lên Ubuntu.
Lệnh cài package cơ bản
apt update apt upgrade -y apt install -y \ nginx \ git \ curl \ build-essential \ postgresql \ postgresql-contrib
Tạo PostgreSQL database
sudo -u postgres psql CREATE USER myapp_user WITH PASSWORD 'STRONG_PASSWORD'; CREATE DATABASE myapp_db OWNER myapp_user; GRANT ALL PRIVILEGES ON DATABASE myapp_db TO myapp_user; \q
NestJS + PM2
cd /var/www/myapp/backend npm ci npm run build npm install -g pm2 pm2 start dist/main.js --name myapp-api pm2 save pm2 startup
Nginx cho React + API
server {
listen 80;
server_name example.com www.example.com;
root /var/www/myapp/frontend/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Ưu điểm
Dễ hiểu luồng server, ít abstraction, phù hợp khi mới học VPS/Linux/Nginx.
Nhược điểm
Khó nhân bản, khó rollback, dependency dễ rối, nhiều site sẽ khó quản lý nếu tiếp tục cài trực tiếp.
03. Nâng cấp sang Docker
Sau khi hiểu deploy thủ công, bước tiếp theo là đóng gói từng thành phần để deploy nhất quán và dễ rollback hơn.
Frontend
Multi-stage Dockerfile: Node build → Nginx runtime.
Backend
NestJS listen `0.0.0.0:3000`; không cần PM2 khi Docker có restart policy.
Database
Postgres volume riêng; không publish 5432 ra host.
NestJS phải listen trên 0.0.0.0
await app.listen( process.env.PORT ?? 3000, '0.0.0.0', );
Database URL trong Docker
DATABASE_URL=postgresql://myapp_user:PASSWORD@db:5432/myapp_db
Trong Compose, `db` là hostname service. Không dùng `localhost` từ backend container.
Frontend dùng cùng domain
VITE_API_URL=/api
Frontend gọi `/api/...`, Nginx container proxy request vào service `backend:3000`.
Từ giai đoạn này, architecture tốt hơn là frontend + API cùng domain, ví dụ `example.com` và `example.com/api`, giúp giảm CORS/DNS/SSL complexity.
04. Host nhiều website trên cùng VPS
Khi bắt đầu có nhiều project tương tự, không nên gán tay 8081/8082/8083 cho từng site. Dùng một Traefik gateway chung và mỗi site là một Compose project riêng.
/opt/
├── infrastructure/
│ ├── traefik/
│ └── monitoring/
├── sites/
│ ├── site-a/
│ ├── site-b/
│ └── site-c/
└── backups/
├── site-a/
├── site-b/
└── site-c/
DB riêng từng site
Dễ cô lập lỗi, backup/restore và xóa site. Phù hợp giai đoạn 2–5 site hoặc khi isolation quan trọng.
Shared PostgreSQL
Tiết kiệm RAM khi site tăng nhiều, nhưng tăng blast radius nếu PostgreSQL chung gặp sự cố.
Frontend của mỗi site nối vào cả `internal` và `traefik-proxy`; backend và DB chỉ ở `internal`. Traefik là thành phần duy nhất publish 80/443.
05. CI/CD: từ build trên VPS đến build trên GitHub
Khi số site tăng, build trực tiếp trên VPS dễ gây CPU/RAM spike. Kiến trúc tốt hơn là GitHub Actions build image và đẩy lên GHCR.
Frontend image
`ghcr.io/org/site-frontend:<git-sha>`
Backend image
`ghcr.io/org/site-backend:<git-sha>`
APP_VERSION
Production giữ exact Git SHA để rollback rõ ràng.
Deploy flow tốt hơn
git push origin main # GitHub Actions 1. docker build frontend 2. docker build backend 3. push images to GHCR 4. SSH into VPS 5. backup database 6. run migration hook 7. docker compose pull 8. docker compose up -d 9. health check
Không nên dựa hoàn toàn vào tag `latest` cho production. Dùng Git SHA giúp xác định chính xác version đang chạy và rollback dễ hơn.
06. Backup, migration và rollback
App rollback khá dễ; database rollback thì không. Vì vậy backup/migration phải được xem là một phần của deployment.
Backup PostgreSQL
docker compose exec -T db \
pg_dump \
-U "$POSTGRES_USER" \
"$POSTGRES_DB" \
| gzip \
> /opt/backups/site-a/pre-deploy-$(date +%Y%m%d-%H%M%S).sql.gz
Prisma migration
docker compose run --rm backend \ npx prisma migrate deploy
TypeORM migration
docker compose run --rm backend \ npm run migration:run
Rollback app
Đổi `APP_VERSION` về Git SHA cũ rồi pull/up lại container.
Rollback DB
Không tự động mù quáng. Schema có thể đã thay đổi theo cách không backward-compatible.
Migration production an toàn hơn theo pattern: Add → Migrate → Switch → Remove later.
07. Hardening VPS
Security phải làm theo thứ tự để tránh tự khóa SSH.
docker ps --format 'table {{.Names}}\t{{.Ports}}'
sudo ss -lntup
sudo ufw status verbose
sudo fail2ban-client status sshd
User thuộc `docker` group có quyền rất cao trên host. Không thêm developer/customer thông thường vào group này.
08. Monitoring: biết sự cố trước người dùng
Sau khi hạ tầng ổn, bước tiếp theo là quan sát CPU/RAM/Disk, container usage, HTTP uptime, API health và SSL expiry.
Node Exporter
CPU, RAM, disk, load, network của VPS.
cAdvisor
CPU/RAM/network theo container.
Blackbox Exporter
Website/API uptime, latency và TLS expiry.
Prometheus
Lưu metrics và evaluate alert rules.
Grafana + Alertmanager
Dashboard và lớp alert routing.
| Alert | Ngưỡng gợi ý | Mục đích |
|---|---|---|
| WebsiteDown | Fail > 2 phút | Site/API không truy cập được |
| HighCPU | > 85% trong 10 phút | Server có nguy cơ quá tải |
| HighMemory | > 90% trong 10 phút | Nguy cơ OOM |
| LowDisk | < 15% free | Images/logs/DB/backups đầy disk |
| SSLExpiring | < 14 ngày | ACME renewal có thể lỗi |
09. Vận hành hàng ngày
Cheat sheet các lệnh quan trọng sau khi hệ thống đi vào production.
Docker
docker compose ps docker compose logs -f backend docker compose logs -f db docker stats docker system df docker compose pull docker compose up -d
VPS resources
free -h df -h htop sudo ss -lntup
Không nên chạy tùy tiện
docker compose down -v docker system prune --volumes
Các lệnh này có thể xóa volume/dữ liệu nếu bạn không hiểu chính xác hậu quả.
10. Lộ trình nâng cấp theo quy mô
Không cần nhảy ngay lên Kubernetes. Mở rộng dần theo nhu cầu và metrics thực tế.
11. Checklist từ đầu đến production
Tick trực tiếp; trạng thái được lưu trên trình duyệt.
12. Setup Guides & Downloads
Mỗi bộ setup giờ có trang chi tiết riêng với kiến trúc, prerequisites, step-by-step, verification và troubleshooting.
React + NestJS + PostgreSQL Docker
Deploy một website hoàn chỉnh bằng Docker Compose.
Hostinger Multi-site Platform
Traefik + nhiều Docker Compose project + GHCR.
VPS Hardening Add-on
SSH key-only, UFW, Fail2ban và security audit.
Monitoring Add-on
Prometheus, Grafana, cAdvisor, Blackbox và Alertmanager.