---
title: Cấu hình dưới dạng mã
description: Xuất cấu hình panel ra file YAML, xem trước và áp dụng qua nexcmp config hoặc trang Import/Export; secret nằm ngoài file và được JSON Schema kiểm tra.
url: https://nexcmp.com/vi/docs/configure-with-ai/config-as-code/
applies_to: NexCMP 1.6.1
updated: 2026-11-02
---

# Cấu hình dưới dạng mã {#configuration-as-code}

> **Vị trí trong admin:** System › Settings › Import/Export (`/agent/config`). Trên máy chủ: các lệnh `nexcmp config export`, `plan` và `apply`, cùng `nexcmp admin <tool>`.

## Chức năng {#what-it-does}

Cấu hình panel của bạn (branding, cài đặt chung, email, cảnh báo Telegram, module, tiền tệ, cổng thanh toán, giới hạn, zone, gói dịch vụ, nhà cung cấp AI và các trang pháp lý) có thể được lưu thành một file YAML duy nhất. Bạn có thể tự chỉnh sửa file, nhờ trợ lý AI chỉnh sửa, lưu vào hệ thống quản lý phiên bản và áp dụng cho cùng panel đó hoặc panel khác. Trước khi có bất kỳ thay đổi nào, bạn luôn thấy danh sách khác biệt. Secret không bao giờ được ghi vào file.

Hãy dùng tính năng này để sao chép cấu hình sang bản cài đặt thứ hai, xem xét thay đổi trước khi áp dụng thực tế, khôi phục cài đặt sau sự cố hoặc để AI đề xuất toàn bộ cấu hình giúp bạn xem lại trong một tài liệu duy nhất.

## Yêu cầu {#requirements}

| Hạng mục | Yêu cầu |
|---|---|
| NexCMP | 1.4.0 trở lên. |
| Dòng lệnh | Bạn là `root` trên máy chủ panel (dùng `sudo`). Lệnh này sẽ tự động yêu cầu panel cấp một key tạm thời (15 phút, tất cả scope). Để dùng một key có phạm vi hẹp hơn, hãy đặt `NEXCMP_KEY` thành một [admin API key](https://nexcmp.com/vi/docs/configure-with-ai/admin-api-keys/) và giữ nguyên biến qua sudo, ví dụ `sudo --preserve-env=NEXCMP_KEY nexcmp config plan -f nexcmp.yaml`. |
| Trang Admin | Đã đăng nhập vào admin. Trang này ở chế độ chỉ đọc trên panel demo. |
| Bí mật | Giá trị được cung cấp tại thời điểm áp dụng (xem [Secrets](#secrets)); không bao giờ nằm trong file. |

## Xuất, chỉnh sửa, xem trước, áp dụng {#export-edit-preview-apply}

1. Xuất cấu hình hiện tại:

   ```bash
   sudo nexcmp config export -o nexcmp.yaml
   ```

   Nếu không có `-o`, nội dung YAML sẽ được in ra màn hình.
2. Chỉnh sửa `nexcmp.yaml` (xem [ví dụ](#example-file) bên dưới). Giữ `version: 1` ở dòng đầu tiên.
3. Xem trước những thay đổi dự kiến. Lệnh này không thay đổi bất kỳ điều gì:

   ```bash
   sudo nexcmp config plan -f nexcmp.yaml
   ```

   Mỗi dòng hiển thị section, item, trường và `old → new`. Các dòng có dấu `$` thuộc về các section thanh toán (xem [Billing sections](#billing-sections)). Nếu panel đã khớp với file, bạn sẽ thấy "No changes".
4. Áp dụng. Nếu không có `--yes`, lệnh sẽ chạy ở chế độ **dry run** và chỉ in ra danh sách tương tự:

   ```bash
   sudo nexcmp config apply -f nexcmp.yaml --yes
   ```

5. Đọc kết quả: `applied`, `pending` (chờ bạn xác nhận), `skipped` và `errors`.

| Tùy chọn | Ý nghĩa |
|---|---|
| `-f <file>` | File YAML (bắt buộc đối với `plan` và `apply`). |
| `--yes` | Thực sự áp dụng. Nếu không có tùy chọn này, `apply` sẽ là dry run. |
| `--confirm-billing` | Áp dụng cả các section thanh toán (`payments`, `currency`, `plans`). Nếu không có tùy chọn này, chúng sẽ bị bỏ qua. |
| `--section <name>` | Chỉ áp dụng section này. Lặp lại tùy chọn nếu muốn áp dụng nhiều section. |
| `-o <file>` | Khi dùng `export`: ghi nội dung YAML vào file. |

Mã thoát (exit code) là 0 khi mọi thứ đã được áp dụng hoặc không có gì thay đổi, 1 khi có lỗi trả về, 2 khi sai cú pháp sử dụng hoặc lỗi key.

### Bí mật {#secrets}

File chứa các tham chiếu thay vì secret, ví dụ `password: secret://smtp_password`. Khi áp dụng, giá trị sẽ được lấy từ biến môi trường có tên `NEXCMP_SECRET_` kết hợp với tên tham chiếu viết hoa:

```bash
sudo -i
read -rs NEXCMP_SECRET_SMTP_PASSWORD && export NEXCMP_SECRET_SMTP_PASSWORD
read -rs NEXCMP_SECRET_STRIPE_SECRET_KEY && export NEXCMP_SECRET_STRIPE_SECRET_KEY
nexcmp config apply -f nexcmp.yaml --yes --confirm-billing
```

Nếu một tham chiếu không có giá trị, secret đã lưu trong panel sẽ được **giữ nguyên**. Secret chưa từng được lưu và không được cung cấp sẽ để trống.

| Tên tham chiếu | Nơi áp dụng |
|---|---|
| `smtp_password` | `email.smtp.password` |
| `telegram_bot_token` | `telegram.bot_token` |
| `stripe_secret_key`, `stripe_webhook_secret` | `payments.stripe` |
| `paypal_client_secret` | `payments.paypal.client_secret` |
| `binance_api_key`, `binance_api_secret` | `payments.crypto` |
| `sepay_api_token`, `sepay_webhook_secret` | `payments.bank` |
| `ai_provider_key` | `ai_provider.api_key` |

## File mẫu {#example-file}

```yaml
# NexCMP configuration. Preview: nexcmp config plan -f nexcmp.yaml
version: 1

branding:
  name: Example Cloud
  primary: "#1677ff"
  currency: usd
  seller_name: Example Cloud LLC

settings:
  brand_name: Example Cloud
  support_email: support@example.com
  default_lang: en
  invoice_prefix: EX
  company_name: Example Cloud LLC
  company_address: "1 Example Street, New York, NY"
  min_topup_cents: 500

email:
  smtp:
    host: smtp.example.com
    port: 587
    security: starttls
    username: mailer@example.com
    password: secret://smtp_password
    from_email: no-reply@example.com
    from_name: Example Cloud
    reply_to: support@example.com

telegram:
  enabled: true
  chat_id: "123456789"
  bot_token: secret://telegram_bot_token

modules:
  s3: true
  k8s: false

currency:
  site_currency: usd
  manual_rate_vnd: 0        # 0 = automatic

payments:
  stripe:
    mode: test
    publishable_key: pk_test_XXXX
    secret_key: secret://stripe_secret_key
    webhook_secret: secret://stripe_webhook_secret
  bank:
    bank_code: BANK
    account_number: "0000000000"
    account_name: EXAMPLE CLOUD LLC
    prefix: EX
    api_token: secret://sepay_api_token
  channels:
    pay_card_enabled: true

quotas:
  quota_enabled: true
  quota_max_vms_24h: 5
  quota_max_vms_30d: 30

zones:
  - slug: new-york
    name: New York
    country: US
    city: New York
    enabled: true
    is_default: true

plans:
  - slug: vps-1c-1g
    name: 1 vCPU, 1 GB RAM, 25 GB
    cpu: 1
    ram_mb: 1024
    disk_gb: 25
    hourly_usd: 0.0112
    cs_offering_id: OFFERING_ID
    enabled: true
    visible: true

ai_provider:
  enabled: true
  name: Example AI
  base_url: https://api.example.com/v1
  model: example-model
  fallback_models: [example-model-mini]
  reasoning_effort: low
  api_key: secret://ai_provider_key

legal:
  terms:
    en: |
      # Terms of service
      Your terms in simple markdown (no HTML).
  privacy:
    en: |
      # Privacy policy
      Your policy in simple markdown (no HTML).
```

Một file có thể chứa tập hợp con bất kỳ của các section. Section mà bạn bỏ qua sẽ không bị tác động. File lớn hơn 1 MB, thiếu `version: 1`, phiên bản khác hoặc chứa section không xác định sẽ bị từ chối trước khi có bất kỳ thao tác nào được thực thi.

## Các mục {#sections}

| Mục | Nội dung điều khiển | Ghi chú |
|---|---|---|
| `branding` | Tên thương hiệu (tối đa 60 ký tự), màu chủ đạo, đơn vị tiền tệ hiển thị (`usd` hoặc `vnd`), tên người bán. | Logo không nằm trong file; hãy dùng [trang thương hiệu](https://nexcmp.com/vi/docs/customers/branding/). |
| `settings` | Danh sách cố định các cài đặt chung: `brand_name`, `support_email`, `support_telegram_url`, `default_lang`, `require_email_verified`, `min_topup_cents`, `max_topup_cents`, `invoice_prefix`, `company_name`, `company_address`, `company_tax_id`, `auto_destroy_days`, `low_balance_cents`. | Các key khác sẽ bị bỏ qua. |
| `email.smtp` | SMTP host, port, bảo mật (`starttls`, `tls`, `none`), user, password, tên và địa chỉ người gửi, reply-to. | [SMTP và mẫu e-mail](https://nexcmp.com/vi/docs/administration/smtp-and-emails/). Việc thay đổi host, port hoặc bảo mật yêu cầu nhập lại password. |
| `telegram` | Bật hoặc tắt kênh cảnh báo, chat id, bot token. | [Thông báo Telegram](https://nexcmp.com/vi/docs/administration/telegram-notifications/). |
| `modules` | Bật hoặc tắt các module tùy chọn (`key: true/false`). | Chỉ các key mà panel cho phép bật/tắt. Xem [Modules](https://nexcmp.com/vi/docs/infrastructure/modules/). |
| `currency` | Đơn vị tiền tệ hiển thị và tỷ giá USD sang VND thủ công (`0` tự động, nếu không sẽ từ 15000 đến 50000). | Section billing. Xem [Tiền tệ và tỷ giá hối đoái](https://nexcmp.com/vi/docs/catalog/currency-and-exchange-rates/). |
| `payments` | Thông tin xác thực `stripe`, `paypal`, `crypto`, `bank` và các công tắc `channels` (`pay_card_enabled`, `pay_wallets_enabled`, `pay_alipay_enabled`, `pay_paypal_enabled`, `pay_usdt_enabled`, `pay_sepay_enabled`). | Section billing. Xem [Kênh thanh toán](https://nexcmp.com/vi/docs/billing/payment-channels/). |
| `quotas` | Giới hạn `quota_*`. | Xem [Quotas](https://nexcmp.com/vi/docs/billing/quotas/). |
| `zones` | Các zone theo `slug` (bắt buộc: `slug`, `name`, `country`; tùy chọn `city`, `enabled`, `is_default`). | Các zone mới sẽ được tạo. Zone đã tồn tại sẽ **không bị thay đổi** bởi file. Xem [Zones](https://nexcmp.com/vi/docs/infrastructure/zones/). |
| `plans` | Các plan theo `slug` (bắt buộc: `slug`, `name`, `cpu`, `ram_mb`, `disk_gb`, `hourly_usd`; tùy chọn `cs_offering_id`, `backend_id`, `zone_id`, `enabled`, `visible`, `sort`, `description`). | Section billing. Các plan mới sẽ được tạo, plan hiện có được cập nhật theo slug. Giá tính theo USD mỗi giờ. Xem [Plans](https://nexcmp.com/vi/docs/catalog/plans/). |
| `ai_provider` | Nhà cung cấp AI của panel được dùng cho AI Chat và AI Agent của khách hàng. | [AI provider](https://nexcmp.com/vi/docs/ai/ai-providers/). |
| `legal` | Nội dung điều khoản và quyền riêng tư theo từng ngôn ngữ (`en`, `vi`). | [Trang pháp lý](https://nexcmp.com/vi/docs/customers/legal/). |

Thứ tự áp dụng tuân theo danh sách trên: các mục hạ tầng trước, plan sau.

## Các quy tắc cần nhớ {#rules-to-remember}

- **Idempotent.** Áp dụng cùng một file hai lần sẽ không làm thay đổi gì ở lần thứ hai. `plan` hiển thị "No changes".
- **Không xóa dữ liệu.** File không bao giờ xóa zone, plan hay cài đặt. Xóa một mục khỏi file vẫn sẽ giữ nguyên trạng thái trên panel.
- **Các quy tắc an toàn thông thường vẫn được áp dụng.** Từ dòng lệnh, mỗi thay đổi đều trải qua các bước kiểm tra tương tự như thay đổi qua API: scope và quy tắc IP. Thay đổi cần xác nhận (ví dụ: công tắc ảnh hưởng toàn hệ thống) sẽ được báo cáo dưới `pending` kèm bản xem trước thay vì được áp dụng ngay, trừ khi bạn truyền `--confirm-billing` để xác nhận tất cả.
- **Client AI không thể mở khóa billing.** Khi `config_apply` được gọi bởi client MCP, `confirm_billing` sẽ bị bỏ qua; các thay đổi liên quan đến tiền bạc sẽ chờ bạn xác nhận.
- **Kiểm tra trước khi áp dụng.** JSON Schema mô tả chi tiết từng trường. Hãy trỏ trình soạn thảo vào schema này hoặc cung cấp cho AI để tạo file YAML hợp lệ: `https://cloud.example.com/v1/admin/agent/config/schema.json` (cho phép đọc công khai).

### Các section billing {#billing-sections}

`payments`, `currency` và `plans` làm thay đổi giá hoặc luồng tiền. `nexcmp config apply --yes` **bỏ qua** các mục này trừ khi bạn thêm `--confirm-billing`; khi đó chúng được liệt kê dưới `skipped` ("billing section - pass confirm_billing"). Cờ này đóng vai trò xác nhận: khi có nó, mọi thay đổi billing trong file (và bất kỳ thay đổi nào khác yêu cầu xác nhận) sẽ được áp dụng mà không cần hỏi lại. Hãy chạy `plan` trước và đọc kỹ từng dòng được đánh dấu `$`.

Khi tệp tương tự được áp dụng bởi AI (công cụ `config_apply` trong MCP client hoặc AI Chat), cờ này sẽ bị bỏ qua và các thay đổi liên quan đến tiền sẽ chờ bạn phê duyệt.

## Sử dụng trang Import/Export {#use-the-import-export-page}

1. Mở **System › Settings › Import/Export**.
2. Dưới mục **Export**, nhấp vào **Get current configuration**, sau đó chọn **Download .yaml** để lưu `nexcmp.yaml`. Các secret sẽ hiển thị dưới dạng placeholder.
3. Dưới mục **Import**, hãy chọn một tệp, kéo tệp vào khung hoặc dán nội dung YAML.
4. Tùy chọn: mở **Secrets that come with it (not in the file)** rồi thêm tên và giá trị cho từng tham chiếu, ví dụ `smtp_password`.
5. Nhấp vào **Preview changes**. Bảng sẽ nhóm các thay đổi theo từng phần; các phần liên quan đến tiền sẽ có nhãn "Money-related". Bỏ chọn những phần bạn không muốn áp dụng.
6. Nếu có các phần liên quan đến tiền được liệt kê, hãy đánh dấu chọn **Also apply money-related changes (prices, payment gateways, balances)**. Nếu không chọn, các phần này sẽ bị bỏ qua.
7. Nhấp vào **Apply selected**. Kết quả sẽ hiển thị những gì đã được áp dụng, bỏ qua hoặc thất bại. Thay đổi nào được trả về ở trạng thái chờ xác nhận sẽ xuất hiện dưới dạng thẻ xác nhận; hãy nhấn **Confirm** trên thẻ đó.

Nút **JSON Schema** ở góc trên bên phải sẽ mở schema.

![Trang Import/Export với thẻ Export và thẻ Import chứa YAML đã xuất](https://nexcmp.com/vi/docs/images/configure-with-ai/config-as-code-01-import-export.webp)

![Bảng xem trước các thay đổi được nhóm theo phần kèm nhãn billing và nút Apply selected](https://nexcmp.com/vi/docs/images/configure-with-ai/config-as-code-02-preview.webp)

## Chạy bất kỳ công cụ nào từ dòng lệnh {#run-any-tool-from-the-command-line}

`nexcmp admin` chạy cùng các công cụ như trợ lý AI ([danh sách công cụ](https://nexcmp.com/vi/docs/configure-with-ai/mcp-admin/#tools)) và xuất ra JSON:

```bash
sudo nexcmp admin tools                       # name, scope and title of every tool
sudo nexcmp admin system_health
sudo nexcmp admin customers_search q=customer@example.com
sudo nexcmp admin settings_update --json '{"values":{"support_email":"support@example.com"}}'
```

Các đối số là các cặp `key=value` (giá trị được đọc dưới dạng JSON khi parse được, nếu không sẽ là văn bản) hoặc một đối tượng `--json '{...}'`. Nếu thao tác cần xác nhận, lệnh sẽ in bản xem trước và dừng lại với mã thoát 3 kèm thông báo "Nothing changed". Hãy đọc bản xem trước, sau đó chạy lại lệnh với `--yes` để áp dụng. Khi chạy dưới quyền root, lệnh sẽ nhận một khóa 15 phút với đầy đủ phạm vi quyền, vì vậy bước xác nhận là chốt an toàn của bạn; với `NEXCMP_KEY`, phạm vi quyền riêng của khóa sẽ được áp dụng.

## Kiểm tra {#verify}

1. `sudo nexcmp config plan -f nexcmp.yaml` ngay sau `apply --yes` sẽ in ra "No changes".
2. Trong trang admin, các trang bạn đã thay đổi sẽ hiển thị giá trị mới, và **Logs › Admin actions** sẽ liệt kê các thay đổi.
3. Áp dụng lại cùng một tệp sẽ không thay đổi bất kỳ điều gì.

## Hạn mức & lưu ý {#limits-notes}

- Tệp này áp dụng cho các cài đặt ở trên, không bao gồm khách hàng, máy chủ, hóa đơn hay tài nguyên hạ tầng (kết nối CloudStack và Proxmox). Hãy kết nối các mục đó bằng [AI Chat](https://nexcmp.com/vi/docs/configure-with-ai/ai-chat-in-admin/) hoặc qua các trang admin.
- Zone và plan được khớp theo `slug`. Không đổi tên slug trong tệp: nó sẽ được tạo thành một mục mới.
- Không thể thay đổi quy mô của plan mà khách hàng đang sử dụng; thay vào đó hãy tạo một plan mới.
- Hãy bảo mật các tệp đã xuất dù chúng không chứa secret: chúng liệt kê giá cả, địa chỉ và tên tài khoản của bạn.

## Xử lý sự cố {#troubleshooting}

| Hiện tượng | Nguyên nhân | Cách khắc phục |
|---|---|---|
| `missing version: 1` | Tệp không bắt đầu bằng `version: 1` | Thêm vào. |
| `unsupported version 2` | Tệp có số phiên bản khác | Panel này chỉ đọc phiên bản 1. |
| `unknown section 'x' (known: ...)` | Khóa top-level bị viết sai chính tả hoặc không được hỗ trợ | Sử dụng các phần ở trên. |
| `YAML error: ...` | YAML không hợp lệ (thụt lề, ký tự tab) | Sửa dòng được chỉ ra trong thông báo. |
| `config is larger than 1 MB` | Tệp quá lớn | Chia nhỏ tệp và sử dụng `--section`. |
| `no API key: set NEXCMP_KEY=ak_... or run as root on the server` | Lệnh không tìm thấy khóa | Chạy bằng `sudo`, hoặc export `NEXCMP_KEY` và giữ biến môi trường đó qua sudo. |
| `panel not reachable` | Dịch vụ panel không chạy trên cổng mặc định | Kiểm tra `sudo nexcmp status`. |
| Các dòng billing dưới `skipped` | Các phần billing cần `--confirm-billing` | Thêm cờ này và xem lại các dòng `$` trước. |
| Các mục dưới `pending` | Thay đổi cần được xác nhận | Mở **API & AI agents**, hoặc kết quả Import/Export, rồi nhấn **Confirm** trên thẻ. |
| Secret không được cập nhật | Không có giá trị `NEXCMP_SECRET_<NAME>` nào được thiết lập, nên secret đã lưu được giữ nguyên | Export biến này và áp dụng lại. |
| Mục dưới `errors` gặp lỗi HTTP 403 `insufficient_scope` | Key thiếu scope của phần đó | Sử dụng key có scope này, hoặc chạy dưới quyền root. |
| Mục dưới `errors` gặp lỗi HTTP 403 `demo_read_only` | Panel demo | Áp dụng trên bản cài đặt thực tế. |


