Dew-OF-Aurora 2 هفته پیش
والد
کامیت
ef44c9b6a3
4فایلهای تغییر یافته به همراه195 افزوده شده و 301 حذف شده
  1. 0 48
      AGENTS.md
  2. 20 11
      CLAUDE.md
  3. 175 139
      README.md
  4. 0 103
      git-push-authentication.md

+ 0 - 48
AGENTS.md

@@ -1,48 +0,0 @@
-# AGENTS
-
-## Repo Purpose (verified)
-- This repo is an automation utility for VMess preferred-domain rotation: fetch API candidates, pick one domain, write runtime artifacts, then let Sub-Store/V2Ray consume them.
-- Main entrypoint is `scripts/domain_updater.py`; optional post-processor for VMess links is `scripts/update_vmess_links.py`.
-- Scheduled runtime entrypoint is `scripts/run_update_and_commit.sh` (runs updater, then commits only when domain changed).
-
-## High-value Files
-- `config.json`: active runtime config (single source for runtime settings).
-- `runtime/current_domain.json` and `runtime/current_domain.txt`: outputs consumed by Sub-Store/operator scripts.
-- `substore/operator_template.js`: Sub-Store script-operation template using `$substore.http.get` and `scriptResourceCache`.
-- `systemd/vmess-domain-rotator.service` and `systemd/vmess-domain-rotator.timer`: deployment templates (must customize user/path).
-
-## Commands You Should Actually Use
-- Syntax check after Python edits:
-  - `python3 -m py_compile scripts/domain_updater.py`
-  - `python3 -m py_compile scripts/update_vmess_links.py`
-- Manual refresh run:
-  - `python3 scripts/domain_updater.py --config config.json`
-- Manual refresh + conditional git commit:
-  - `bash scripts/run_update_and_commit.sh config.json`
-- Update VMess links (`add` field) from selected domain:
-  - `python3 scripts/update_vmess_links.py --input <in> --output <out> --domain-file runtime/current_domain.txt`
-- Debian one-shot deploy/remove:
-  - `sudo bash scripts/install_debian.sh`
-  - `sudo bash scripts/uninstall_debian.sh`
-- Local output smoke test endpoint:
-  - `python3 -m http.server 8080 --directory runtime`
-
-## Behavior/Gotchas That Are Easy To Miss
-- For vps789 Top20, keep API ranking order (`scoring.use_api_order=true`) and keep only domains (filter IPv4 via `domain_filter.exclude_regex`).
-- `healthcheck.enabled` may be intentionally `false` in vps789 mode; do not re-enable unless you want local TLS checks to override API ranking behavior.
-- `domain_updater.py` fallback behavior depends on persisted `runtime/state.json` (`last_good_domain`). Do not delete this file in normal operation.
-- `run_update_and_commit.sh` commits only when `runtime/current_domain.txt` changed before/after update.
-- Sub-Store script preview may show no change if `NODE_NAME_REGEX` in `substore/operator_template.js` does not match node names, or if cached output is reused.
-- In Sub-Store operators here, use `$substore.http.get(...)` (not plain `fetch`) for compatibility.
-
-## Deployment Notes (systemd templates)
-- Template service assumes:
-  - Working dir: `/opt/vmess-domain-rotator`
-  - User: `vmessrotator`
-- Template timer interval is `12h` by default.
-- Before enabling timer, adjust `User`, `WorkingDirectory`, and `ExecStart` in `systemd/vmess-domain-rotator.service` to match the real host.
-- Enable flow: copy unit files to `/etc/systemd/system/` -> `systemctl daemon-reload` -> `systemctl enable --now vmess-domain-rotator.timer`.
-
-## Editing Constraints For This Repo
-- Keep secrets out of source snapshots/backups: avoid placing tokens in tracked/shared files.
-- `runtime/` is operational output; avoid treating it as source-of-truth code.

+ 20 - 11
CLAUDE.md

@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
 
 ## Project Overview
 
-VMess domain rotator: fetch candidate domains from an API, select a preferred domain, write runtime artifacts, and optionally auto-commit runtime changes to a dedicated branch.
+VMess domain rotator: fetch candidate domains from an API, select a preferred domain, write runtime artifacts, and optionally auto-commit/push runtime changes to a dedicated branch (`runtime-state`).
 
 ## Common Commands
 
@@ -12,6 +12,9 @@ VMess domain rotator: fetch candidate domains from an API, select a preferred do
 ```bash
 python3 -m py_compile scripts/domain_updater.py
 python3 -m py_compile scripts/update_vmess_links.py
+bash -n scripts/run_update_and_commit.sh
+bash -n scripts/install_debian.sh
+bash -n scripts/uninstall_debian.sh
 ```
 
 ### Run domain selection once
@@ -19,7 +22,7 @@ python3 -m py_compile scripts/update_vmess_links.py
 python3 scripts/domain_updater.py --config config.json
 ```
 
-### Run scheduler entrypoint with conditional git commit
+### Run scheduler entrypoint (updater + runtime-state commit/push)
 ```bash
 bash scripts/run_update_and_commit.sh config.json
 ```
@@ -49,10 +52,15 @@ curl http://127.0.0.1:8080/current_domain.json
 
 ### Debian systemd install/uninstall
 ```bash
+# Recommended default install (1h timer, push enabled, credential-helper mode)
 sudo bash scripts/install_debian.sh
+
+# Useful variants
 sudo bash scripts/install_debian.sh --interval 5min
 sudo bash scripts/install_debian.sh --git-push 0
+sudo bash scripts/install_debian.sh --git-push-remote origin
 sudo bash scripts/install_debian.sh --git-http-username aurora --git-http-token-file /root/.config/vmess-token --git-use-credential-store 1
+
 sudo bash scripts/uninstall_debian.sh
 sudo bash scripts/uninstall_debian.sh --keep-auth-files
 ```
@@ -60,7 +68,7 @@ sudo bash scripts/uninstall_debian.sh --keep-auth-files
 ## Testing and verification status
 
 - There is currently no dedicated `tests/` directory or unit test suite.
-- Primary verification is Python syntax check (`py_compile`) plus manual script runs.
+- Primary verification is syntax checks plus manual script runs.
 
 ## Architecture (big picture)
 
@@ -74,21 +82,22 @@ sudo bash scripts/uninstall_debian.sh --keep-auth-files
 - Optionally healthchecks candidates with TLS handshake (`healthcheck`).
 - Selects winner from scored/check results (`selection.top_n`).
 - Writes runtime artifacts under `runtime/`.
+- Resolves relative `output.runtime_dir` against the config file directory.
 - Falls back to `last_good_domain` from `runtime/state.json` when selection fails.
 
 ### 2) Runtime-state git automation
 `scripts/run_update_and_commit.sh` wraps the updater and git workflow:
-- Resolves git top-level robustly and skips commit if service is not running inside a git repo.
-- Skips commit if domain unchanged or empty.
+- Resolves git top-level robustly and skips git actions if not inside a git repo.
+- Requires non-empty `runtime/current_domain.txt` after updater run.
+- Copies runtime outputs into `runtime-state` (same branch or temporary worktree).
 - Commits only runtime outputs (`runtime/current_domain.txt`, `runtime/current_domain.json`, `runtime/state.json`, `runtime/substore_vars.json`).
-- Targets `runtime-state` branch (configurable via `GIT_RUNTIME_BRANCH`) and includes a branch safety check before staging.
-- Uses a temporary git worktree when current branch is not `runtime-state`.
+- Commits when `runtime-state` staged diff is non-empty (comparison is branch-targeted, not main-working-tree-only).
+- Targets `runtime-state` branch (configurable via `GIT_RUNTIME_BRANCH`) and includes branch safety check before staging.
 - Supports non-interactive push auth in two modes:
   - credential helper mode (`GIT_CREDENTIAL_HELPER`, e.g. `store`)
   - header mode (`GIT_HTTP_USERNAME` + `GIT_HTTP_TOKEN`/`GIT_HTTP_TOKEN_FILE`)
 - `GIT_PUSH_REQUIRED` defaults to `GIT_PUSH_ENABLED`; when enabled, push failure returns non-zero for systemd visibility.
-- Disables interactive git prompts via `GIT_TERMINAL_PROMPT=0` to avoid systemd hangs.
-
+- Disables interactive git prompts via `GIT_TERMINAL_PROMPT=0`.
 
 ### 3) VMess subscription post-processing
 `scripts/update_vmess_links.py`:
@@ -129,6 +138,6 @@ Generated in `runtime/`:
 
 - Fallback behavior is stateful: `last_good_domain` persistence is critical for resilience.
 - `runtime-state` branch is intended to isolate frequently changing runtime outputs from `main` source history.
-- Debian installer (`scripts/install_debian.sh`) writes `/etc/vmess-domain-rotator.env` (service env), configures oneshot service+timer, and can store HTTPS token in `/var/lib/vmess-domain-rotator/git_http_token`.
-- For non-interactive systemd runs, prefer SSH deploy key or installer-provided HTTPS token env configuration.
+- Debian installer (`scripts/install_debian.sh`) writes `/etc/vmess-domain-rotator.env`, configures oneshot service+timer, and sets push-required behavior when push is enabled.
+- Default install path is in-place (current git clone), default service user is `SUDO_USER`, and default auth mode is credential helper store.
 - Uninstaller removes systemd units and, by default, removes service auth/env files unless `--keep-auth-files` is set.

+ 175 - 139
README.md

@@ -1,17 +1,48 @@
 # vmess-domain-rotator
 
-This repo provides a first working version of an automated pipeline:
+一个用于 **自动获取优选域名**、写入 `runtime/` 运行时文件,并按计划将运行时变更提交到 `runtime-state` 分支的工具。
 
-1. Pull preferred domains from an API (like vps789).
-2. Validate and optionally health-check candidates.
-3. Pick the best domain automatically.
-4. Export runtime files for Sub-Store and V2Ray integration.
+---
 
-## Quick start
+## 1. 功能概览
 
-1. Edit `config.json` directly (single runtime config file).
+本项目主要完成以下流程:
 
-For your sample response (`data.good[].ip`), parser config can be:
+1. 从 API 拉取候选域名/IP
+2. 解析并过滤候选结果
+3. 按规则打分/选择最终域名
+4. 写入运行时文件到 `runtime/`
+5. (可选)将运行时变更自动提交并 push 到 `runtime-state`
+
+核心脚本:
+
+- `scripts/domain_updater.py`:执行域名拉取、选择与写文件
+- `scripts/run_update_and_commit.sh`:执行 updater + git 提交/推送
+- `scripts/install_debian.sh`:Debian 下安装 systemd service + timer
+- `scripts/uninstall_debian.sh`:卸载 systemd 与认证环境文件
+
+---
+
+## 2. 运行产物
+
+默认写入仓库根目录 `runtime/`:
+
+- `runtime/current_domain.txt`:当前域名(纯文本)
+- `runtime/current_domain.json`:当前结果 JSON
+- `runtime/state.json`:状态文件(含 `last_good_domain`)
+- `runtime/substore_vars.json`:给外部系统消费的变量
+
+> 注意:`domain_updater.py` 现在会按 `--config` 文件所在目录解析 `output.runtime_dir`(默认 `./runtime`),避免误写到 `scripts/runtime/`。
+
+---
+
+## 3. 本地快速开始
+
+### 3.1 配置
+
+编辑 `config.json`。
+
+典型解析路径(如 API 返回 `data.good[].ip`):
 
 ```json
 "parser": {
@@ -21,213 +52,218 @@ For your sample response (`data.good[].ip`), parser config can be:
 }
 ```
 
-For vps789 Top20 ranking, if you want "directly use first ranked domain":
-
-```json
-"scoring": {
-  "enabled": true,
-  "records_path": "data.good[]",
-  "ip_field": "ip",
-  "created_time_field": "createdTime",
-  "within_hours": 24,
-  "use_api_order": true
-}
-```
-
-Then set:
+### 3.2 语法检查
 
-```json
-"healthcheck": { "enabled": false }
+```bash
+python3 -m py_compile scripts/domain_updater.py
+python3 -m py_compile scripts/update_vmess_links.py
 ```
 
-2. Run once:
+### 3.3 运行一次
 
 ```bash
 python3 scripts/domain_updater.py --config config.json
 ```
 
-3. Check output files:
+### 3.4 本地查看结果
 
-- `runtime/current_domain.txt`
-- `runtime/current_domain.json`
-- `runtime/state.json`
-
-## What the script exports
+```bash
+cat runtime/current_domain.txt
+cat runtime/current_domain.json
+```
 
-- `current_domain.txt`: plain text domain.
-- `current_domain.json`: machine-readable payload:
+可选 HTTP 验证:
 
-```json
-{
-  "domain": "best.example.com",
-  "updated_at": "2026-04-13T07:00:00Z",
-  "status": "ok",
-  "source_count": 15,
-  "checked_count": 10
-}
+```bash
+python3 -m http.server 8080 --directory runtime
+curl http://127.0.0.1:8080/current_domain.json
 ```
 
-- `state.json`: includes `last_good_domain` for automatic fallback.
+---
 
-If you need Sub-Store to fetch these files over HTTP, you can expose `runtime/` via nginx or caddy.
+## 4. Debian 一键部署(完整教程)
 
-## How to connect with Sub-Store
+## 4.1 前置条件
 
-Two practical modes:
+- Debian/Ubuntu
+- 项目已 `git clone` 到服务器(在仓库目录执行安装)
+- 远程仓库 `origin` 可用
+- 用于运行服务的用户有仓库读写权限
 
-1. **Recommended**: run updater externally and let Sub-Store operator fetch `current_domain.json`.
-2. Keep Sub-Store static and update V2Ray template directly (token replacement).
+---
 
-`substore/operator_template.js` is a starter operator script showing how to replace VMess `server` fields by regex match on node names.
+### 4.2 推荐方案(不传参数)
 
-Minimal smoke test (local):
+如果你采用“每台机器先手动保存 git 凭证”的流程,直接执行:
 
 ```bash
-python3 -m http.server 8080 --directory runtime
+sudo bash scripts/install_debian.sh
 ```
 
-Then test:
+默认行为:
 
-```bash
-curl http://127.0.0.1:8080/current_domain.json
-```
+- 服务用户:当前 `sudo` 执行前用户(`SUDO_USER`)
+- 定时间隔:`1h`
+- 自动 push:开启(`--git-push 1`)
+- 认证模式:`credential.helper store`
+- 推送分支:`runtime-state`
 
-## How to connect with V2Ray
+---
 
-If you maintain a template config (containing `__AUTO_DOMAIN__` token), this script can render a real config file with the selected domain.
+### 4.3 Git 凭证(无交互)配置建议
 
-Then reload service:
+#### 方式 A:手动存凭证(你当前采用的方式)
+
+在**服务用户**下执行一次:
 
 ```bash
-systemctl reload v2ray
+git config --global credential.helper store
+git push origin runtime-state:runtime-state
 ```
 
-## Update Base64 VMess links
+首次输入用户名/密码(或 PAT)后,后续 systemd 可无交互 push。
+
+> 关键点:保存凭证的用户必须和 service 的 `User=` 一致。
 
-If your node list uses `vmess://<base64-json>`, use:
+#### 方式 B:安装脚本带 token(可选)
 
 ```bash
-python3 scripts/update_vmess_links.py \
-  --input ./nodes.txt \
-  --output ./nodes.updated.txt \
-  --domain-file ./runtime/current_domain.txt
+sudo bash scripts/install_debian.sh \
+  --git-http-username <your-user> \
+  --git-http-token-file /root/.config/vmess-token \
+  --git-use-credential-store 1
 ```
 
-Only update specific node names (`ps`) by regex:
+---
+
+### 4.4 安装后验证
 
 ```bash
-python3 scripts/update_vmess_links.py \
-  --input ./nodes.txt \
-  --output ./nodes.updated.txt \
-  --domain-file ./runtime/current_domain.txt \
-  --name-regex "(argo|cf|vm)"
-```
+sudo systemctl status vmess-domain-rotator.timer
+sudo systemctl status vmess-domain-rotator.service
 
-If the whole subscription file is itself base64-encoded, add:
+# 手动触发一次
+sudo systemctl start vmess-domain-rotator.service
 
-```bash
---subscription-base64
+# 看日志
+sudo journalctl -u vmess-domain-rotator.service -n 120 --no-pager
 ```
 
-## Scheduling
+成功时应看到:
+
+- updater 输出 JSON
+- `committed runtime changes on runtime-state ...`
+- `pushed to origin/runtime-state`
+
+---
 
-### Cron
+## 5. install_debian.sh 参数说明
 
-```cron
-0 * * * * /bin/bash /opt/vmess-domain-rotator/scripts/run_update_and_commit.sh /opt/vmess-domain-rotator/config.json >> /var/log/vmess-domain-rotator.log 2>&1
+```bash
+sudo bash scripts/install_debian.sh [options]
 ```
 
-### systemd timer
+| 参数 | 说明 | 默认值 |
+|---|---|---|
+| `--user <name>` | 指定 service 用户 | 当前 `sudo` 用户 |
+| `--group <name>` | 指定 service 用户组 | 当前 `sudo` 用户主组 |
+| `--interval <value>` | 定时周期(如 `1h`/`5min`) | `1h` |
+| `--git-push <0|1>` | 是否自动 push | `1` |
+| `--git-push-remote <name>` | 远程名 | `origin` |
+| `--git-http-username <u>` | HTTPS 认证用户名 | `git` |
+| `--git-http-token <t>` | HTTPS token(明文参数) | 空 |
+| `--git-http-token-file <f>` | 从文件读取 token | 空 |
+| `--git-use-credential-store <0|1>` | 是否使用 `credential.helper store` | `1` |
+| `--git-credentials-file <f>` | 指定 credential store 文件路径 | 空(Git 默认) |
+| `--no-install-deps` | 跳过 apt 安装依赖 | 关闭 |
+| `-h, --help` | 查看帮助 | - |
 
-Use files under `systemd/` and adjust paths/user.
-Default timer interval in this repo is `1h`.
+说明:
 
-### Debian install/uninstall scripts
+- `--git-push 1` 时,push 失败会返回非 0,systemd 任务标记失败(便于监控)。
+- 安装会写入环境文件:`/etc/vmess-domain-rotator.env`。
 
-Install on a Debian server (creates systemd service+timer):
+---
 
-```bash
-sudo bash scripts/install_debian.sh
-```
+## 6. 自动提交/推送逻辑说明
 
-This installer is in-place only (service runs from current git clone path). Runtime updates are committed to `runtime-state` and when push is enabled (`--git-push 1`, default), push failure is treated as a service failure.
+`scripts/run_update_and_commit.sh` 的行为:
 
-Non-interactive push/auth options:
+1. 运行 `domain_updater.py` 更新根目录 `runtime/`
+2. 切到(或创建)`runtime-state` worktree
+3. 将 `runtime/` 下四个文件同步到 `runtime-state` worktree
+4. 仅当 **runtime-state 分支内容有差异** 时才 commit
+5. `--git-push 1` 时要求 push 成功
 
-```bash
-# Disable push completely (only local runtime-state commits)
-sudo bash scripts/install_debian.sh --git-push 0
+即:不再只看 main 分支当前文件是否变化,而是看 `runtime-state` 目标内容是否有变化。
 
-# Recommended: credential.helper store (same style as manual git config --global credential.helper store)
-sudo bash scripts/install_debian.sh \
-  --user aurora --group aurora \
-  --git-http-username aurora \
-  --git-http-token-file /root/.config/vmess-token \
-  --git-use-credential-store 1
+---
 
-# Optional: set explicit credential store file
-sudo bash scripts/install_debian.sh \
-  --user aurora --group aurora \
-  --git-http-username aurora \
-  --git-http-token-file /root/.config/vmess-token \
-  --git-use-credential-store 1 \
-  --git-credentials-file /home/aurora/.git-credentials
-```
+## 7. 常用运维命令
 
-Installer behavior for auth:
-- With `--git-use-credential-store 1`, installer configures service user global git credential helper and writes credentials via `git credential approve`.
-- With `--git-use-credential-store 0`, installer stores token at `/var/lib/vmess-domain-rotator/git_http_token` and service uses header-based auth.
-- Service environment is written to `/etc/vmess-domain-rotator.env`.
+### 7.1 service / timer
 
-Push behavior:
-- `--git-push 1` (default): commit + push are required; push failure exits non-zero so systemd marks run failed.
-- `--git-push 0`: only local runtime-state commit is attempted, push skipped.
+```bash
+sudo systemctl status vmess-domain-rotator.timer
+sudo systemctl status vmess-domain-rotator.service
+sudo systemctl start vmess-domain-rotator.service
+sudo systemctl restart vmess-domain-rotator.timer
+```
 
-Uninstall:
+### 7.2 日志
 
 ```bash
-sudo bash scripts/uninstall_debian.sh
+sudo journalctl -u vmess-domain-rotator.service -n 200 --no-pager
+sudo journalctl -u vmess-domain-rotator.service -f
 ```
 
-Keep auth/env files during uninstall:
+### 7.3 查看 runtime-state 提交
 
 ```bash
-sudo bash scripts/uninstall_debian.sh --keep-auth-files
+git log runtime-state --oneline -n 20
 ```
 
-Useful options:
+---
+
+## 8. 卸载
 
 ```bash
-sudo bash scripts/install_debian.sh --user aurora --group aurora --interval 5min
-sudo bash scripts/install_debian.sh --git-push-remote origin
+sudo bash scripts/uninstall_debian.sh
 ```
 
-## Config notes
+保留认证/env 文件:
 
-- API response formats differ. Use one of:
-  - `parser.json_paths` (preferred)
-  - `parser.regex` fallback
-- If API has occasional bad results, keep `healthcheck.enabled=true`.
-- If API may return IPv4 addresses, consider `healthcheck.tls_verify=false`.
-- If all checks fail, script falls back to last known good domain.
+```bash
+sudo bash scripts/uninstall_debian.sh --keep-auth-files
+```
 
-## About Sub-Store "config file location"
+---
 
-If you use Sub-Store web UI, rules are usually stored in backend data storage (sqlite/json), not a simple editable config file.
+## 9. VMess 链接批量替换(可选)
 
-Common deployment cases:
+```bash
+python3 scripts/update_vmess_links.py \
+  --input ./nodes.txt \
+  --output ./nodes.updated.txt \
+  --domain-file ./runtime/current_domain.txt
+```
 
-- Docker: check mounted volume path, then back up that volume.
-- Node/PM2: check app directory `data/` or database file.
+仅替换匹配名称(`ps`)的节点:
 
-In practice, you can avoid touching backend db files directly:
+```bash
+python3 scripts/update_vmess_links.py \
+  --input ./nodes.txt \
+  --output ./nodes.updated.txt \
+  --domain-file ./runtime/current_domain.txt \
+  --name-regex "(argo|cf|vm)"
+```
 
-1. Keep your node logic in Sub-Store operator script (web UI).
-2. Let operator fetch `current_domain.json` from this project.
-3. Dynamic replacement happens at subscription processing time.
+---
 
-## Security and reliability
+## 10. 注意事项
 
-- Do not commit API tokens.
-- Use reverse proxy auth if exposing `current_domain.json` publicly.
-- Keep `runtime/state.json` persisted (for fallback).
+1. **服务用户与 git 凭证用户必须一致**,否则会出现:
+   - `fatal: could not read Username ... terminal prompts disabled`
+2. `credential.helper store` 为明文存储,建议仅在可控服务器使用。
+3. 不要把 token 提交进仓库。
+4. `runtime/state.json` 需要持久化,保障 fallback 能用。

+ 0 - 103
git-push-authentication.md

@@ -1,103 +0,0 @@
-# Git Push 认证配置指南(无 Token 文件方案)
-
-> 适用场景:每台服务器上都有完整项目;你会先手动 push 一次,并用 `git config --global credential.helper store` 保存凭据;之后 systemd 服务无交互自动 push `runtime-state`。
-
-## 核心结论
-
-可以,按你的逻辑完全可行:
-
-1. 每台服务器手动配置 `credential.helper store`
-2. 每台服务器手动 `git push` 一次(触发输入用户名/密码或 Token)
-3. 后续服务定时任务可直接无交互 push
-
-不需要 `--git-http-token-file`。
-
----
-
-## 每台服务器的标准步骤
-
-假设项目目录为 `/home/aurora/vmess-domain-rotator`,远端为 `origin`。
-
-### 1) 先确认 remote 是 HTTPS
-
-```bash
-cd /home/aurora/vmess-domain-rotator
-git remote get-url origin
-```
-
-必须是 `https://...`,例如:
-
-```text
-https://git.example.com/aurora/vmess-domain-rotator.git
-```
-
-> 如果是 SSH 地址(`git@...`),就不是 credential store 这套流程。
-
-### 2) 配置凭据持久化(服务用户)
-
-```bash
-git config --global credential.helper store
-```
-
-### 3) 手动 push 一次,触发保存凭据
-
-你可以 push 任意分支(同一个 HTTPS 主机即可),例如:
-
-```bash
-git push origin main
-```
-
-首次会提示输入用户名与密码(或 Token),输入后会写入 `~/.git-credentials`。
-
-### 4) 安装 systemd 服务(不传 token 文件)
-
-```bash
-sudo bash scripts/install_debian.sh \
-  --interval 1h \
-  --git-push 1 \
-  --git-use-credential-store 1
-```
-
-> 默认会使用当前 `sudo` 执行者作为服务用户(即 `SUDO_USER`)。
-
-### 5) 验证服务是否能自动 push
-
-```bash
-sudo systemctl start vmess-domain-rotator.service
-sudo journalctl -u vmess-domain-rotator.service -n 120 --no-pager
-```
-
-日志应看到:
-
-- `committed domain change on runtime-state ...`
-- `pushed to origin/runtime-state`
-
----
-
-## 为什么这套流程可行
-
-- `run_update_and_commit.sh` 在服务里是无交互执行(`GIT_TERMINAL_PROMPT=0`)。
-- 但只要服务用户已在本机有可用凭据(`credential.helper store` + 曾成功 push),后续 push 不需要再交互。
-
----
-
-## 换新服务器时怎么做
-
-每台服务器都重复同样流程(凭据不会跨机器同步):
-
-1. `git config --global credential.helper store`
-2. 手动 `git push` 一次保存凭据
-3. 运行 `install_debian.sh --git-push 1 --git-use-credential-store 1`
-
-即:**一机一初始化**。
-
----
-
-## 常见坑
-
-1. **服务用户不一致**
-   - 你是 `aurora` 手动保存的凭据,但服务跑在别的用户下,就读不到。
-2. **remote 不是 HTTPS**
-   - `credential.helper store` 对 SSH remote 不生效。
-3. **凭据存储是明文**
-   - `~/.git-credentials` 为明文,请确保服务器权限可控。