# Tự cập nhật

> HTML: https://remote.ivjn.us/docs/vi/self-update/

CLI và Agent độc lập có thể cập nhật tệp thực thi của riêng chúng từ trang web đã xuất bản trên Windows x64/arm64, Linux x64/arm64 (bản dựng glibc và musl tĩnh), macOS Apple Silicon và FreeBSD/NetBSD x64/arm64:

```sh
remote-cli update self --check
remote-cli update self
remote-agent update self --check
remote-agent update self
```

| Nền tảng | Phát hành kho lưu trữ | Khởi động lại sau một lần chụp `remote-agent update self` |
| --- | --- | --- |
| Windows x64 / arm64 | `remote-windows-x64.zip` / `remote-windows-arm64.zip` | Tác vụ theo lịch trình `RemoteAgent`, sau đó khởi động lại quy trình |
| Linux glibc x64 / arm64 | `remote-linux-x64.tar.gz` / `remote-linux-arm64.tar.gz` | hệ thống systemd hoặc đơn vị người dùng, OpenRC, sau đó khởi động lại quy trình |
| Linux xạ hương x64 / arm64 | `remote-linux-musl-x64.tar.gz` / `remote-linux-musl-arm64.tar.gz` | Tương tự như Linux glibc |
| macOS Apple Silicon | `remote-macos-arm64.tar.gz` | LaunchAgent `us.ivjn.remote-agent` |
| FreeBSD / NetBSD x64 / arm64 | `remote-freebsd-*.tar.gz` / `remote-netbsd-*.tar.gz` | RC.d `remote_agent` từ `remote-agent install --system`; nếu không thì khởi động lại bằng tay |

Trình cập nhật giữ thời gian chạy C của tệp thực thi đang chạy: bản dựng musl chỉ cài đặt kho lưu trữ musl và bản dựng glibc chỉ cài đặt kho lưu trữ glibc. OpenWrt vẫn ở trên opkg/apk ngay cả trên x64/arm64: các gói của nó được xây dựng mà không có trình cập nhật lưu trữ và tarball musl chạy trên máy chủ có `/etc/openwrt_release` từ chối tự cập nhật. Nền tảng chỉ cập nhật khi kho lưu trữ của nó được liệt kê trong bảng kê khai; các cài đặt được xây dựng trước khi hỗ trợ cho nền tảng đó phải được thay thế thủ công một lần.

Không cần đăng nhập tài khoản hoặc cấu hình thiết bị.

Đối với lần cài đặt đầu tiên của chính Agent (cấu hình nhị phân + riêng tư + tự khởi động hệ điều hành), hãy ưu tiên `remote-agent install` / `remote-agent uninstall` trên Linux, macOS và Windows - xem [platforms.md](/docs/vi/platform-installation.md). Lệnh đó không cần truy cập mạng; ghép nối vẫn riêng biệt. Sau khi tệp nhị phân bao gồm `install` xuất hiện trên máy một lần, các bản nâng cấp sau này có thể sử dụng `update self` hoặc tự động cập nhật nếu được hỗ trợ.

`--check` so sánh siêu dữ liệu SHA-256 có thể thực thi được từ tệp kê khai mà không cần tải xuống bản lưu trữ. Nếu siêu dữ liệu thực thi không có, nó sẽ tải xuống và xác minh kho lưu trữ. So sánh băm phân biệt các bản dựng phát triển có cùng số phiên bản; kiểm tra không bao giờ thay đổi cài đặt. Quá trình cài đặt từ chối hạ cấp và xác minh phiên bản thực thi, kích thước và hàm băm.

Nguồn mặc định là `https://r2.ivjn.us` (miền công cộng R2 lưu trữ `downloads/`). `--source https://your-mirror.example/releases` chọn một máy nhân bản đáng tin cậy có cùng bố cục lưu trữ và `downloads/manifest.json`. Các bản phát hành GitHub ([mbcc2006/bản phát hành điều khiển từ xa](/#downloads)) xuất bản cùng một loại kho lưu trữ trên máy tính để bàn dưới dạng kênh tải xuống **bổ sung**; họ thực hiện **not** thay thế bố cục trang web và tự cập nhật vẫn sử dụng `r2.ivjn.us` trừ khi bạn trỏ `--source` vào gương phục vụ `downloads/manifest.json`. Chỉ HTTPS được chấp nhận, chuyển hướng bị từ chối và không có mã thông báo tài khoản nào được gửi. Tên lưu trữ được chọn từ hệ điều hành/kiến trúc hiện tại, kích thước của nó và SHA-256 được kiểm tra dựa trên tệp kê khai HTTPS và chỉ mục nhập thực thi chính xác mới được trích xuất. Trước khi tin cậy vào bảng kê khai, các máy khách trên máy tính để bàn sẽ xác minh `downloads/manifest.json.sig` bằng các khóa công khai Ed25519 được biên dịch sẵn. Thiếu chữ ký, byte thay đổi hoặc khóa không xác định sẽ từ chối cập nhật. Gương phải phục vụ chính xác bảng kê khai và xe phụ đã ký; xuất bản sidecar trước khi tung ra những khách hàng yêu cầu nó.

Trước khi cài đặt, tệp thực thi mới phải vượt qua kiểm tra giới hạn `--version`. Các bản cập nhật được tuần tự hóa bằng tệp `.update.lock` anh chị em và tệp thực thi hiện tại được kiểm tra lại để phát hiện sự thay thế đồng thời. Bản cập nhật chỉ chạm vào tệp thực thi và các tệp cập nhật/sao lưu của nó; ID thiết bị, thông tin xác thực và tệp cấu hình được giữ nguyên.

Trên macOS, tệp thực thi được tải xuống cũng phải vượt qua `codesign --verify --strict` trước khi kiểm tra phiên bản. Chữ ký và byte đã xuất bản của nó được giữ nguyên trong quá trình thay thế để các phép so sánh băm tiếp theo vẫn ổn định.

Tệp thực thi trước đó được giữ lại dưới dạng `<executable>.previous`. Nếu cần, hãy dừng Agent và khôi phục tệp đó về đường dẫn thực thi ban đầu. Trên Windows, tệp thực thi đã tải được đổi tên thành bản sao lưu trước khi cài đặt bản thay thế; lỗi cài đặt sẽ khôi phục tên gốc.

Sau khi `remote-agent update self` thành công (không phải `--check`), trình cập nhật sẽ cố gắng khởi động lại Agent đang chạy để tệp nhị phân mới được tải: trên Linux (glibc và musl), nó chạy `systemctl restart remote-agent`, rồi `systemctl --user restart remote-agent`, rồi `rc-service remote-agent restart` khi `/etc/init.d/remote-agent` tồn tại (OpenRC) và nếu những thứ đó không có sẵn thì SIGTERM sẽ khởi động lại các quy trình daemon `remote-agent` khác với các đối số trước đó của chúng; trên Windows (x64 và arm64), nó khởi động lại tác vụ đã lên lịch `RemoteAgent`, với dự phòng cấp quy trình; trên FreeBSD/NetBSD, nó chạy tập lệnh RC.d `remote_agent restart` được cài đặt bởi `remote-agent install --system` và mặt khác sẽ báo cáo rằng cần phải khởi động lại thủ công. Nếu bản thân quá trình cập nhật là daemon (các đối số không phải là `update self`), thì `exec` sẽ tạo nhị phân mới trên Unix (bảo toàn PID cho người giám sát) hoặc tạo ra một bản thay thế tách rời trên Windows. `remote-cli update self` không bao giờ khởi động lại Agent. Các dòng trạng thái báo cáo xem việc khởi động lại systemd, OpenRC, rc.d đã sử dụng, tác vụ đã lên lịch, quy trình mới được sinh ra hay không thể thực hiện được (bản cập nhật vẫn thành công). Chạy với sự cho phép của chủ sở hữu cài đặt; trình cập nhật không nâng cao đặc quyền. Các dòng lệnh được ghi lại trong quá trình khởi động lại xác định lại các giá trị `--token`. Nếu Windows Agent trước đó vẫn đang chạy từ bản sao lưu, hãy khởi động lại nó trước khi cập nhật lại.

## Tự động cập nhật (daemon Agent trên máy tính để bàn)

Khi daemon Agent đang chạy (không phải `update self` một lần), ** sẽ kiểm tra định kỳ** cùng một bảng kê khai trang web và áp dụng bản cập nhật khi tệp nhị phân `remote-agent` được xuất bản khác (so sánh hàm băm). Mặc định:

- **EĐược bật theo mặc định** trên các bản dựng máy tính để bàn được hỗ trợ (Windows x64/arm64 / Linux x64/arm64 glibc và musl / macOS arm64 / FreeBSD và NetBSD x64/arm64).
- Vô hiệu hóa với môi trường `REMOTE_AUTO_UPDATE=0` (cũng là `false` / `no` / `off`), cấu hình JSON `"auto_update": false` hoặc CLI `--auto-update false`.
- Kiểm tra lần đầu ~90 giây sau khi bắt đầu; sau đó khoảng 12 giờ một lần (không phải trên mỗi nhịp tim).
- Ghi lại tiến trình rõ ràng; **never** gửi mã thông báo thiết bị tới CDN cập nhật.
- OpenWrt (bao gồm tarball musl trên máy chủ OpenWrt) bỏ qua quá trình tự động cập nhật trên máy tính để bàn; Android sử dụng đường dẫn OTA của riêng mình. Các kiến ​​trúc chưa được ánh xạ như Intel Mac hoặc ARM 32-bit sẽ trả về lỗi thiếu bản lưu trữ phát hành và không thể tự động cập nhật.

## Cập nhật đẩy Remote (nhà điều hành → thiết bị)

Người vận hành có phiên thiết bị thông thường (cùng ACL với `OpenExec`) có thể yêu cầu thiết bị trực tuyến kiểm tra hoặc áp dụng bản cập nhật:

Giao thức (WebSocket JSON):

- `OperatorUp::update_device` `{ session_id, device_id, check_only, source? }`
- Exchange → `DeviceDown::update_req`
- Thiết bị → `DeviceUp::update_status` / `OperatorDown::update_status` lũy tiến với `phase`:
  `checking` | `downloading` | `applying` | `up_to_date` | `available` | `applied` | `error`

Console: trên chi tiết thiết bị, **Kiểm tra các bản cập nhật** / **Cập nhật đẩy**.

CLI (mẫu tương tự như các hoạt động phiên thiết bị khác):

```sh
remote-cli device update <device_id> --check
remote-cli device update <device_id>
remote-cli device update <device_id> --source https://r2.ivjn.us
```

Điều khiển mạng LAN ánh xạ `update_device` giống như các thông báo `OperatorUp` open-* khác khi mạng LAN được bật.

OpenWrt/các Tác nhân không được hỗ trợ khác trả về pha `error` rõ ràng thay vì cài đặt sai tạo phẩm. Windows arm64, Linux musl, macOS Apple Silicon và FreeBSD/NetBSD sử dụng cùng đường dẫn lưu trữ trên máy tính để bàn như Windows x64 và Linux glibc.

## Android Agent OTA

APK Android Agent (`remote-agent-android.apk` trên trang web) có thể tự cập nhật từ cùng một tệp kê khai HTTPS:

Mở **Settings → Kiểm tra các bản cập nhật** trong Agent để kiểm tra thủ công. Kiểm tra tải xuống và xác minh APK; bản cập nhật có sẵn yêu cầu xác nhận riêng trước khi mở trình cài đặt Android.

- Tải xuống APK, xác minh **bytes + sha256**, so sánh `versionCode`/tên gói với ứng dụng đã cài đặt (bản dựng lại cùng phiên bản với hàm băm khác vẫn có thể cài đặt).
- Cài đặt qua `PackageInstaller`. Ứng dụng khai báo `REQUEST_INSTALL_PACKAGES`; trên OTA đầu tiên, người dùng có thể cần cho phép “cài đặt ứng dụng không xác định” cho Remote Agent trong cài đặt hệ thống, sau đó xác nhận giao diện người dùng của trình cài đặt hệ thống khi được hiển thị.
- Việc bắt đầu cài đặt sẽ trả về `available` với thông báo đang chờ cài đặt, không phải `applied`.
  Lệnh gọi lại trình cài đặt riêng sẽ mở ra màn hình xác nhận hệ thống. Yêu cầu lặp đi lặp lại
  đối với cùng một APK đang chờ xử lý, hãy sử dụng lại phiên; phiên tự cập nhật thất bại và cũ là
  bị bỏ rơi. Xác nhận phiên bản/băm đã cài đặt sau khi Agent kết nối lại.
- Tính năng tự động kiểm tra chạy trong khoảng thời gian tương tự khi `AgentService` đang chạy.
- Remote `update_req` được xử lý bởi Agent gốc, gọi là cầu điều khiển APK (`action: ota_update`).
- Bộ nhớ riêng của ứng dụng (id thiết bị/mã thông báo) được bảo toàn trong quá trình thay thế gói; `MY_PACKAGE_REPLACED` vẫn khởi động lại kết nối khi được bật.

Tất cả các thành phần hiện chia sẻ phiên bản phát hành 0.1.27: Rust Agent/CLI/Exchange, tiện ích mở rộng trình duyệt, ứng dụng Android và bảng điều khiển web. Các phiên bản tăng dần cùng nhau; Mã phiên bản Android là 30. Chạy `python scripts/check-release-versions.py` trước khi đóng gói.

## Cập nhật Android Console

Console gốc có nút **Settings → Kiểm tra cập nhật**, có sẵn trước hoặc sau khi đăng nhập. Nó đọc bản kê khai trang web công cộng mà không cần thông tin xác thực tài khoản và so sánh bản dựng đã cài đặt với `versionCode` đã xuất bản. Nếu tệp kê khai không có siêu dữ liệu bản dựng và các phiên bản tiếp thị khớp nhau thì tệp kê khai sẽ cung cấp bản tải xuống mà không xác nhận rằng ứng dụng đã cài đặt là hiện hành.

**Tải xuống trình cài đặt** mở APK trang web trong trình duyệt; hoàn tất cài đặt thông qua màn hình xác nhận của Android. Điều này cập nhật Console trên điện thoại hiện tại. Các điều khiển cập nhật trên trang chi tiết thiết bị vẫn nhắm mục tiêu đến thiết bị từ xa đó.

## Console "Kiểm tra cập nhật" (quy trình làm việc kết hợp)

Chi tiết thiết bị hiển thị một hành động "Kiểm tra bản cập nhật" duy nhất, hành động này sẽ gửi `update_device { check_only: true }` lần đầu tiên:

- `up_to_date`: hiển thị "Đã có trên phiên bản mới nhất x.y.z".
- `available`: hiển thị "Hiện tại → mới nhất (kích thước)" và cung cấp "Cập nhật đẩy / Sau". Sau khi xác nhận, hãy gửi `check_only: false` và hiển thị tiến trình cũng như kết quả.
- Nếu Android trả về "Đang chờ cài đặt ..." sau khi nhấn, hãy nhắc người dùng xác nhận trình cài đặt hệ thống trên thiết bị.
- Thiết bị ngoại tuyến và thiết bị trình duyệt hiển thị lý do trực tiếp; nền tảng không được hỗ trợ hiển thị "Thiết bị này không hỗ trợ cập nhật từ xa".

Thông báo kết quả bao gồm `current <版本>` và `size <字节> bytes`.

Xem thêm kho lưu trữ `docs/watchdog.md` để biết cơ quan giám sát hoạt động tùy chọn (`--watchdog`, `REMOTE_WATCHDOG=1`).

Chẩn đoán Android hiển thị kết quả và dấu thời gian cập nhật tự động gần đây nhất ngay cả khi không có quyền READ_LOGS. Đã khắc phục các lý do lỗi phân biệt trạng thái HTTP, DNS, thời gian chờ, TLS, tệp kê khai, kích thước/băm APK và lỗi cấp phép cài đặt. Thông báo an toàn tương tự được ghi vào logcat dưới dạng RemoteAgentOTA; nhật ký toàn bộ thiết bị vẫn yêu cầu READ_LOGS. Các URL, đường dẫn và thông tin xác thực ngoại lệ không bao giờ được sao chép vào trạng thái này.
