# Deploy lên Ubuntu VPS

Chạy lần lượt trên server. Domain `thugiancuoituan.com` đã được điền sẵn vào mọi lệnh
và mọi file cấu hình — copy dán chạy thẳng, không phải sửa gì.

---

## 0. Trước khi bắt đầu

Trỏ DNS về VPS và **đợi nó có hiệu lực trước**, vì certbot sẽ fail nếu domain chưa
trỏ đúng:

| Loại | Tên | Giá trị |
|---|---|---|
| A | `@` | IP của VPS |
| A | `www` | IP của VPS |

Kiểm tra: `dig +short thugiancuoituan.com` phải trả về đúng IP.

---

## 1. Cài Node và MySQL

Node trong kho apt của Ubuntu quá cũ. Dùng NodeSource:

```bash
sudo apt update && sudo apt upgrade -y
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs nginx mysql-server
node -v      # phải >= 18
```

---

## 2. Tạo user hệ thống và database

Không chạy web bằng root.

```bash
# User hệ thống, không login được, không có home
sudo useradd --system --no-create-home --shell /usr/sbin/nologin tiktokauth

# Thư mục code
sudo mkdir -p /srv/tiktok-auth
```

Tạo database. Đổi `MatKhauManh123!` thành mật khẩu của bạn:

```bash
sudo mysql <<'SQL'
CREATE DATABASE IF NOT EXISTS tiktok_auth
  CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS 'tiktok_auth'@'localhost' IDENTIFIED BY 'MatKhauManh123!';
GRANT ALL PRIVILEGES ON tiktok_auth.* TO 'tiktok_auth'@'localhost';
FLUSH PRIVILEGES;
SQL
```

Bảng thì app tự tạo ở lần chạy đầu, không phải import file `.sql` nào.

---

## 3. Đưa code lên

Từ **máy Windows của bạn**, trong thư mục `WEB`:

```powershell
scp -r db.js server.js session-store.js package.json package-lock.json public deploy `
    user@IP_VPS:/tmp/tiktok-auth-code
```

Rồi trên **server**:

```bash
sudo cp -r /tmp/tiktok-auth-code/* /srv/tiktok-auth/
cd /srv/tiktok-auth
sudo npm ci --omit=dev
sudo chown -R root:root /srv/tiktok-auth   # code read-only với user chạy app
```

> Đừng copy `.env` từ máy dev lên. Tạo mới ở bước 4 — file dev có
> `NODE_ENV=development` và redirect URI giả.

---

## 4. Tạo file `.env` trên server

```bash
# Sinh secret mới, KHÔNG dùng lại secret của máy dev
node -e "console.log(require('crypto').randomBytes(48).toString('base64url'))"
```

```bash
sudo -e /srv/tiktok-auth/.env
```

Nội dung:

```ini
TIKTOK_CLIENT_KEY=awxbp03cp3zs1wnm
TIKTOK_CLIENT_SECRET=<client secret của bạn>
TIKTOK_REDIRECT_URI=https://thugiancuoituan.com/auth/tiktok/callback
SESSION_SECRET=<chuỗi vừa sinh ở trên>
DB_HOST=localhost
DB_USER=tiktok_auth
DB_PASSWORD=MatKhauManh123!
DB_NAME=tiktok_auth
```

`NODE_ENV`, `HOST`, `PORT` do systemd đặt, không cần ghi vào đây.

Khoá quyền đọc — đây là file chứa secret:

```bash
sudo chown root:tiktokauth /srv/tiktok-auth/.env
sudo chmod 640 /srv/tiktok-auth/.env
```

---

## 5. Bật service

```bash
sudo cp /srv/tiktok-auth/deploy/tiktok-auth.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now tiktok-auth
sudo systemctl status tiktok-auth
```

Log phải hiện:

```
Đang chạy tại http://127.0.0.1:3000
Redirect URI đã khai báo: https://thugiancuoituan.com/auth/tiktok/callback
MySQL: tiktok_auth@localhost/tiktok_auth
NODE_ENV=production
```

Sai một trong bốn dòng đó là dừng lại sửa, đừng đi tiếp. Xem log đầy đủ:

```bash
journalctl -u tiktok-auth -n 50 --no-pager
```

> Nếu service thoát ngay với *"Sai cấu hình production"* thì đó là chốt chặn cố ý:
> `SESSION_SECRET` ngắn dưới 32 ký tự, hoặc redirect URI không phải `https`.

---

## 6. nginx

```bash
sudo cp /srv/tiktok-auth/deploy/nginx-tiktok-auth.conf /etc/nginx/sites-available/tiktok-auth
sudo ln -sf /etc/nginx/sites-available/tiktok-auth /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
```

Thử: `curl -I http://thugiancuoituan.com` phải ra `200`.

---

## 7. HTTPS

TikTok bắt buộc redirect URI là `https`, nên bước này không bỏ được.

```bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d thugiancuoituan.com -d www.thugiancuoituan.com
```

Chọn tuỳ chọn **redirect** để ép HTTP sang HTTPS. Certbot tự gia hạn; kiểm tra:

```bash
sudo certbot renew --dry-run
```

Sau bước này `curl -I https://thugiancuoituan.com` phải ra `200`.

---

## 8. Tường lửa

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

Cổng 3000 **không** được mở — app chỉ nghe trên `127.0.0.1`, nginx là đường vào duy nhất.

---

## 9. Cập nhật bên TikTok

1. developers.tiktok.com → app của bạn → Login Kit → Redirect URI:
   `https://thugiancuoituan.com/auth/tiktok/callback` — trùng từng ký tự với `.env`.
2. Web/Desktop URL: `https://thugiancuoituan.com`
3. Terms of Service URL: `https://thugiancuoituan.com/terms`
4. Privacy Policy URL: `https://thugiancuoituan.com/privacy`
5. **URL properties** → xác minh quyền sở hữu. Nếu chọn cách tải file chữ ký:

```bash
# Chép file chữ ký TikTok cấp vào thư mục public, nginx/express tự phục vụ
sudo cp tiktok<mã>.txt /srv/tiktok-auth/public/
curl https://thugiancuoituan.com/tiktok<mã>.txt   # kiểm tra trước khi bấm Verify
```

---

## 10. Sao lưu dữ liệu

```bash
sudo mkdir -p /var/backups/tiktok-auth
sudo tee /usr/local/bin/backup-tiktok-auth.sh >/dev/null <<'EOF'
#!/bin/bash
set -e
DEST=/var/backups/tiktok-auth/data-$(date +%F).sql.gz
mysqldump --single-transaction tiktok_auth | gzip > "$DEST"
find /var/backups/tiktok-auth -name 'data-*.sql.gz' -mtime +14 -delete
EOF
sudo chmod +x /usr/local/bin/backup-tiktok-auth.sh

# Chạy 3 giờ sáng mỗi ngày, giữ 14 ngày
echo '0 3 * * * root /usr/local/bin/backup-tiktok-auth.sh' | sudo tee /etc/cron.d/tiktok-auth-backup
```

Chạy thử một lần cho chắc: `sudo /usr/local/bin/backup-tiktok-auth.sh && ls -l /var/backups/tiktok-auth`

---

## 11. Deploy phiên bản mới sau này

```bash
# Từ máy dev: đẩy code mới lên /tmp/tiktok-auth-code
sudo cp -r /tmp/tiktok-auth-code/* /srv/tiktok-auth/
cd /srv/tiktok-auth && sudo npm ci --omit=dev
sudo systemctl restart tiktok-auth
journalctl -u tiktok-auth -n 20 --no-pager
```

Dữ liệu nằm trong MySQL nên user và phiên đăng nhập vẫn còn nguyên.

---

## Gặp lỗi thì xem đâu

| Triệu chứng | Nguyên nhân hay gặp |
|---|---|
| `502 Bad Gateway` | Service chết. `journalctl -u tiktok-auth -n 50` |
| Bấm nút → TikTok báo redirect_uri sai | `.env` và portal lệch nhau, kể cả dấu `/` cuối |
| Đăng nhập xong bị đá về trang chưa đăng nhập | Thiếu `proxy_set_header X-Forwarded-Proto $scheme` trong nginx |
| `State không khớp` | Cookie không được set — kiểm tra dòng trên, và HTTPS đã bật chưa |
| Service không khởi động, log nói "Sai cấu hình production" | `SESSION_SECRET` < 32 ký tự hoặc redirect URI không phải https |
| Log nói `Không kết nối được MySQL` | Sai `DB_USER`/`DB_PASSWORD`/`DB_NAME` trong `.env` |
