Fullstack Developer

Hướng dẫn CI/CD Auto-Deploy lên VPS

Hướng dẫn CI/CD Auto-Deploy lên VPS

Hướng dẫn CI/CD Auto-Deploy lên VPS

Tài liệu này mô tả luồng đưa code từ máy dev → GitLab → tự động deploy lên VPS,
đúng như cấu hình đang chạy của dự án ta-tech/cms.


1. Tổng quan luồng hoạt động

`
Máy dev GitLab (gitlab.com/ta-tech/cms) VPS (/opt/ta_cms)
┌────────┐ git push ┌──────────────────────────────┐ SSH ┌──────────────────┐
│ code │ ───────────► │ repo → pipeline CI/CD │ ──────► │ git reset --hard │
└────────┘ (SSH key) │ (.gitlab-ci.yml, runner) │ (key) │ docker compose │
└──────────────────────────────┘ └──────────────────┘
`

Mỗi lần git push lên nhánh main:

  1. GitLab shared runner chạy job deploy trong .gitlab-ci.yml.
  2. Runner SSH vào VPS bằng key ci_deploy.
  3. Trên VPS: git fetch + git reset --hard origin/main (ép khớp đúng commit, không merge).
  4. docker compose up -d --build build lại và chạy container.
Dùng git reset --hard thay vì git pull để deploy idempotent: VPS luôn khớp

chính xác commit trên GitLab, không bao giờ kẹt conflict/merge.


2. Ba loại khóa SSH (đừng nhầm lẫn)

KhóaNằm ở đâuDùng đểKhai báo ở đâu
Dev SSH key (id_ed25519_gitlab)máy devdev git push lên GitLabGitLab → User Settings → SSH Keys
Deploy key (gitlab_deploy)VPSVPS git fetch/pull từ GitLab (read-only)GitLab → repo Settings → Repository → Deploy keys
CI key (ci_deploy)VPSrunner SSH vào VPSprivate key → biến SSH_PRIVATE_KEY; public key → ~/.ssh/authorized_keys trên VPS

Quy tắc: public key (.pub, 1 dòng ssh-ed25519...) thì add vào nơi nhận kết nối;
private key (nhiều dòng BEGIN/END) thì giữ ở nơi khởi tạo kết nối.


3. Cấu hình một lần (đã làm xong)

3.1. Máy dev → GitLab

`bash
ssh-keygen -t ed25519 -C "you@email" -f ~/.ssh/id_ed25519_gitlab -N ""
cat ~/.ssh/id_ed25519_gitlab.pub # → add vào GitLab > User Settings > SSH Keys
`

~/.ssh/config (máy dev):
`
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/id_ed25519_gitlab
IdentitiesOnly yes
`

3.2. VPS pull được từ GitLab (deploy key)

`bash
ssh-keygen -t ed25519 -f ~/.ssh/gitlab_deploy -N ""
cat ~/.ssh/gitlab_deploy.pub # → add vào GitLab > repo Settings > Repository > Deploy keys (KHÔNG cần write)
`

~/.ssh/config (VPS) — bắt buộc, nếu thiếu sẽ Permission denied (publickey):
`
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/gitlab_deploy
IdentitiesOnly yes
`

Biến /opt/ta_cms thành git repo nối GitLab (giữ nguyên .env):
`bash
cd /opt/ta_cms
git init -b main
git remote add origin git@gitlab.com:ta-tech/cms.git
git fetch origin
git reset --hard origin/main # nhận file hiện có vào git, khớp với GitLab
git ls-remote origin >/dev/null && echo "✅ pull OK"
`

3.3. Runner SSH vào VPS (CI key)

`bash
ssh-keygen -t ed25519 -f ~/.ssh/ci_deploy -N ""
cat ~/.ssh/ci_deploy.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
cat ~/.ssh/ci_deploy # → copy TRỌN khối BEGIN..END vào biến SSH_PRIVATE_KEY
`

3.4. Biến CI/CD trên GitLab

GitLab → repo Settings → CI/CD → Variables:

KeyValueLưu ý
SSH_PRIVATE_KEYnội dung private key ci_deploy (cả BEGIN/END, nhiều dòng)bỏ tick Mask + Protect
VPS_HOSTIP/domain VPS
VPS_USERroot
VPS_PATH/opt/ta_cms
⚠️ SSH_PRIVATE_KEY không mask được (key nhiều dòng) → bỏ tick Mask.

Nhánh main mặc định chưa "protected" → bỏ tick Protect, nếu không biến sẽ rỗng trong job.

3.5. File .env production trên VPS

.env không nằm trong git (đã .gitignore). Tạo thủ công một lần trên VPS:
`bash
cd /opt/ta_cms
cp .env.example .env
nano .env # điền secret thật: PAYLOAD_SECRET, MONGO password, S3 keys, SERVER_URL...
`


4. Quy trình dùng hằng ngày

`bash

Trên máy dev

git add .
git commit -m "mô tả thay đổi"
git push origin main
`

→ Xong. Theo dõi deploy tại: https://gitlab.com/ta-tech/cms/-/pipelines

  • ✅ Xanh = đã deploy lên VPS.
  • ❌ Đỏ = mở job deploy xem log.

5. Xử lý sự cố (các lỗi đã gặp)

Log báoNguyên nhânCách sửa
Permission denied (publickey) khi fetch trên VPSthiếu ~/.ssh/config trỏ tới gitlab_deploy, hoặc deploy key chưa addtạo config (mục 3.2) / add deploy key vào GitLab
Error loading key "(stdin)" trong jobSSH_PRIVATE_KEY sai định dạng / dán thiếu BEGIN-ENDcopy lại trọn khối cat ~/.ssh/ci_deploy
untracked working tree files would be overwritten by merge/opt/ta_cms chưa nhận file vào gitđã fix bằng git reset --hard trong CI; thủ công: git reset --hard origin/main
biến rỗng dù đã khailỡ tick Protect mà branch chưa protectedsửa biến, bỏ tick Protect
docker compose lỗithiếu .env production hoặc cổng trùngtạo .env (mục 3.5), kiểm tra docker compose logs payload

6. Lệnh vận hành trên VPS

`bash
cd /opt/ta_cms
docker compose ps # trạng thái container
docker compose logs payload --tail 50 -f # xem log app
docker compose restart payload # restart
docker compose down && docker compose up -d --build # rebuild toàn bộ
`

Rollback về commit trước (khi bản mới lỗi):
`bash
cd /opt/ta_cms
git reset --hard <commit-cũ>
docker compose up -d --build
`

← Về trang chủ