# Git deploy

> Deploy từ repository Git với nhận diện framework tự động, build trong sandbox, phát hành không gián đoạn có health check, webhook khi push và rollback một chạm.

Source: https://zopanel.net/vi/docs/git-deploy  
Updated: 2026-10-07

Git deploy build và chạy code trực tiếp từ repository. ZoPanel nhận diện framework, đề xuất lệnh cài đặt, build và chạy, build trong sandbox giới hạn theo CPU và RAM của tài khoản, và chỉ chuyển lưu lượng sang bản mới khi bản đó vượt qua health check. Nếu có lỗi, bản cũ vẫn tiếp tục chạy.

## Tạo website từ Git

1. Vào **Website → Thêm website** và chọn loại **Git deploy**.
2. Nhập **Địa chỉ repository**, **Nhánh** (mặc định `main`) và, với monorepo, **Thư mục gốc** (ví dụ `apps/web`).
3. Giữ **SSL miễn phí (Let's Encrypt)** đang bật rồi bấm **Tạo website**.

Lần deploy đầu tiên bắt đầu ngay. Khi xong, ZoPanel cấp chứng chỉ SSL trong cùng tác vụ để hai việc không giẫm lên nhau.

Bạn cũng có thể deploy vào website có sẵn từ tab **Deploy** của website đó.

### Địa chỉ repository

| Dạng | Ví dụ |
| --- | --- |
| HTTPS công khai | `https://github.com/owner/repo` |
| SSH (repository riêng tư) | `git@github.com:owner/repo.git` hoặc `ssh://git@git.example.com:2222/owner/repo` |

Máy chủ Git phải là địa chỉ công khai. Với repository riêng tư, mở **Deploy → Deploy key (repository riêng tư)**, bấm **Hiện deploy key**, thêm public key đó làm deploy key (chỉ đọc) trong repository, rồi dùng URL dạng `git@…`.

Các nguồn khác trong danh sách **Nguồn**: **File đã tải lên (Quản lý file)**, khi bạn tải dự án lên `domains/<tên-miền>/source` bằng Quản lý file hoặc SFTP; và **Docker image có sẵn**.

## Nhận diện framework

Mỗi lần deploy (trừ khi bạn tắt **Tự nhận diện**), ZoPanel đọc repository và điền cấu hình build. Quy tắc khớp đầu tiên được áp dụng:

| Tìm thấy trong repository | Nhận diện là |
| --- | --- |
| `composer.json` (và không có framework server Node) | Laravel (`artisan` hoặc `laravel/framework`), Symfony hoặc PHP (Composer). Asset front-end được build bằng npm khi `package.json` có script `build`. |
| `package.json` | Next.js, Nuxt, Remix / React Router, SvelteKit, Astro, NestJS, Gatsby, Angular, Create React App, Docusaurus, VitePress, Vite (React/Vue/Svelte) hoặc server Node.js (Express, Fastify, Koa, Hono…) |
| `wp-config-sample.php` + `wp-login.php` | WordPress |
| `Gemfile` | Ruby on Rails, Rack (Sinatra, Hanami…) hoặc Ruby |
| `pom.xml`, `build.gradle` | Java / Spring Boot |
| `*.csproj` | .NET / ASP.NET Core |
| `manage.py`, `requirements.txt`, `pyproject.toml`, `Pipfile` | Django, FastAPI, Flask hoặc Python |
| `go.mod` | Go |
| `index.php` / `index.html` | PHP / HTML tĩnh |
| Chỉ có `Dockerfile` | Dockerfile (container) |

Một số chi tiết đáng chú ý:

- **Trình quản lý package:** `pnpm-lock.yaml` → `pnpm install --frozen-lockfile`, `yarn.lock` → `yarn install --frozen-lockfile`, `package-lock.json` → `npm ci`, còn lại dùng `npm install`.
- **Phiên bản Node.js:** lấy từ `.nvmrc`, `.node-version` hoặc `engines.node`. Nếu phiên bản chính đó chưa cài, hệ thống dùng bản mới nhất đã cài.
- **Xuất tĩnh:** Next.js với `output: 'export'`, Astro không có `@astrojs/node`, SvelteKit dùng `adapter-static`, Vite, Angular và các bản build tương tự được phục vụ như website tĩnh từ thư mục kết quả build.
- **Procfile:** dòng `web:` luôn được dùng làm lệnh chạy.
- **Laravel:** tự tạo `APP_KEY` nếu thiếu, giữ `storage` và `.env` giữa các lần deploy, session và cache dùng Redis của tài khoản khi có sẵn.

Bấm **Phân tích repository** để xem kết quả nhận diện trước khi deploy, rồi chọn **Dùng cấu hình này và tuỳ chỉnh** nếu muốn sửa.

## Cấu hình build và chạy

Thẻ **Build & chạy** cho biết những gì sẽ được thực thi:

| Trường | Ghi chú |
| --- | --- |
| Runtime / Phiên bản | node, python, go, php, ruby, java, dotnet, static hoặc docker. **Bản mới nhất đã cài** dùng phiên bản mới nhất trên máy chủ. |
| Loại | **Ứng dụng server (tiến trình)**, **Website tĩnh**, **PHP (PHP-FPM)** hoặc **Container (Dockerfile)**. |
| Lệnh cài đặt | Ví dụ `npm ci` hoặc `composer install --no-dev --optimize-autoloader --no-interaction`. |
| Lệnh build | Ví dụ `npm run build`. Nối nhiều lệnh bằng `&&` trên một dòng. |
| Lệnh chạy | Chỉ cho ứng dụng server. Ứng dụng phải lắng nghe tại `127.0.0.1:$PORT`. |
| Thư mục kết quả build / Thư mục gốc web | Thư mục được phục vụ với website tĩnh và PHP, ví dụ `dist` hoặc `public`. |
| Đường dẫn lưu trữ cố định | Giữ lại giữa các lần deploy, ví dụ `storage`, `uploads`, `.env`. |
| Đường dẫn health check | Phải trả về mã dưới 500 thì bản mới mới được đưa lên. Mặc định `/`. |

**Biến môi trường** dùng được khi build và khi chạy; `PORT` được đặt tự động. Dùng **Dán .env** để thêm nhiều biến một lúc (tối đa 200 biến, giá trị trên một dòng).

Chế độ Container (Dockerfile) cần quản trị viên bật một lần trên máy chủ:

```bash
zopanel ctl feature enable custom-docker
```

## Quy trình một lần deploy

1. Code được lấy về thư mục release mới: `domains/<tên-miền>/releases/<thời-điểm>/`.
2. Lệnh cài đặt và build chạy dưới quyền tài khoản hosting qua systemd, trong giới hạn CPU và RAM của tài khoản, không ghi được ra ngoài thư mục home.
3. Ứng dụng server khởi động ở slot đang rảnh, trên cổng riêng. ZoPanel chờ tối đa 90 giây để đường dẫn health check trả lời.
4. nginx chuyển sang bản mới (reload nhẹ nhàng), sau đó tiến trình cũ được dừng. `current` trỏ tới bản đang chạy.

Mỗi lần deploy được ghi trong **Lịch sử deploy** cùng commit, kiểu kích hoạt (**Thủ công**, **Git push** hoặc **Khi tạo**) và trạng thái. Nếu deploy lỗi, chủ website nhận thông báo **Deploy bị lỗi**.

## Tự động deploy khi push

1. Trong tab **Deploy**, ở thẻ **Tự động deploy**, bật **Deploy khi push lên nhánh main**.
2. Sao chép **Payload URL** (`https://<tên-miền-panel>:8888/api/hooks/deploy/<id>`) và **Secret**.
3. Thêm webhook ở dịch vụ Git:
   - **GitHub:** Settings → Webhooks → dán URL, chọn content type `application/json` và nhập secret.
   - **GitLab / Gitea:** dán URL và nhập secret vào ô **Secret token**.

ZoPanel kiểm tra chữ ký (`X-Hub-Signature-256` của GitHub) hoặc header token (GitLab, Gitea); secret không bao giờ được chấp nhận qua URL. Chỉ push lên đúng nhánh đã cấu hình mới kích hoạt deploy. Lần gửi trùng lặp bị bỏ qua, mỗi 15 giây chỉ khởi động tối đa một lần deploy qua webhook, và không bao giờ khi đang có deploy khác chạy. Sự kiện ping của GitHub được trả lời `pong`.

**Tạo lại secret** thay secret mới; sau đó nhớ cập nhật webhook ở dịch vụ Git.

### Deploy từ CI bằng API token

Với license Pro, tạo API token ở **Tài khoản của tôi → API token** và gọi deploy từ bất kỳ hệ thống CI nào:

```bash
curl -X POST \
  -H "Authorization: Bearer zpat_..." \
  https://panel.example.com:8888/api/sites/<site-id>/app/deploy
```

## Rollback

Thẻ **Các bản release** giữ 5 bản build gần nhất. Bấm **Rollback** ở bản bất kỳ: ứng dụng server được khởi động ở slot rảnh và chỉ chuyển sang sau khi qua health check, giống hệt một lần deploy, nên rollback không gây gián đoạn.

## Nhật ký

- **Deploy → Log ứng dụng** hiển thị output mới nhất của ứng dụng đang chạy; bật **Trực tiếp** để theo dõi liên tục.
- Log build của từng lần deploy được lưu trong **Tác vụ**.
- Tab **Nhật ký** của website hiển thị access log và error log của nginx, còn **Chạy chẩn đoán** giải thích các lỗi gần đây.
