# vmess-domain-rotator This repo provides a first working version of an automated pipeline: 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. Edit `config.json` directly (single runtime config file). For your sample response (`data.good[].ip`), parser config can be: ```json "parser": { "field_paths": ["data.good[].ip"], "json_paths": [], "regex": "[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}" } ``` 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: ```json "healthcheck": { "enabled": false } ``` 2. Run once: ```bash python3 scripts/domain_updater.py --config config.json ``` 3. Check output files: - `runtime/current_domain.txt` - `runtime/current_domain.json` - `runtime/state.json` ## What the script exports - `current_domain.txt`: plain text domain. - `current_domain.json`: machine-readable payload: ```json { "domain": "best.example.com", "updated_at": "2026-04-13T07:00:00Z", "status": "ok", "source_count": 15, "checked_count": 10 } ``` - `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. ## How to connect with Sub-Store Two practical modes: 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. Minimal smoke test (local): ```bash python3 -m http.server 8080 --directory runtime ``` Then test: ```bash curl http://127.0.0.1:8080/current_domain.json ``` ## 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. Then reload service: ```bash systemctl reload v2ray ``` ## Update Base64 VMess links If your node list uses `vmess://`, use: ```bash python3 scripts/update_vmess_links.py \ --input ./nodes.txt \ --output ./nodes.updated.txt \ --domain-file ./runtime/current_domain.txt ``` Only update specific node names (`ps`) by regex: ```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)" ``` If the whole subscription file is itself base64-encoded, add: ```bash --subscription-base64 ``` ## Scheduling ### Cron ```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 ``` ### systemd timer Use files under `systemd/` and adjust paths/user. Default timer interval in this repo is `1h`. ### Debian install/uninstall scripts Install on a Debian server (creates systemd service+timer): ```bash sudo bash scripts/install_debian.sh ``` 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. Non-interactive push/auth options: ```bash # Disable push completely (only local runtime-state commits) sudo bash scripts/install_debian.sh --git-push 0 # 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 ``` 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`. 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. Uninstall: ```bash sudo bash scripts/uninstall_debian.sh ``` Keep auth/env files during uninstall: ```bash sudo bash scripts/uninstall_debian.sh --keep-auth-files ``` Useful options: ```bash sudo bash scripts/install_debian.sh --user aurora --group aurora --interval 5min sudo bash scripts/install_debian.sh --git-push-remote origin ``` ## Config notes - 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. ## 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. Common deployment cases: - Docker: check mounted volume path, then back up that volume. - Node/PM2: check app directory `data/` or database file. In practice, you can avoid touching backend db files directly: 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 - Do not commit API tokens. - Use reverse proxy auth if exposing `current_domain.json` publicly. - Keep `runtime/state.json` persisted (for fallback).