P5 - Cài đặt openclaw CLIProxy sử dụng nhiều tài khoản Oauth
Bước 0) Mục tiêu
• Chạy CLIProxyAPI cục bộ trên VPS: 127.0.0.1:8317
• Thêm nhiều tài khoản Codex/ChatGPT (đăng nhập thiết bị) → proxy tự động xoay vòng tài khoản
• OpenClaw trỏ nhà cung cấp openai-codex đến CLIProxyAPI (thay vì chatgpt.com)
• CLIProxyAPI chạy như một dịch vụ (người dùng systemd), tự động khởi động khi khởi động lại hệ thống
Bước 1) Cài đặt Go 1.22.5
cd /tmp
wget https://go.dev/dl/go1.22.5.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.22.5.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/go /usr/local/bin/go
sudo ln -sf /usr/local/go/bin/gofmt /usr/local/bin/gofmt
Kiểm tra version go
which go
go version
Bước 2) Sao chép CLIProxyAPI
cd ~
rm -rf CLIProxyAPI
git clone https://github.com/router-for-me/CLIProxyAPI.git
cd ~/CLIProxyAPI
go build -o cli-proxy-api ./cmd/server
./cli-proxy-api -h
Bước 3) Tạo cấu hình CLIProxyAPI
Cách tạo Key API proxy (tạo bằng Python):
python3 - <<'PY'
import secrets
print(secrets.token_urlsafe(32))
PY
Key: sMPIdzRqbikhhHZ04QD9DHhvwKo32SbinpkkvVNQ9Mo
nano ~/CLIProxyAPI/config.yaml
Dán nội dung
host: "127.0.0.1"
port: 8317
tls:
enable: false
cert: ""
key: ""
remote-management:
allow-remote: false
secret-key: ""
disable-control-panel: true
panel-github-repository: "https://github.com/router-for-me/Cli-Proxy-API-Management-Center"
auth-dir: "/home/bao/.cli-proxy-api"
api-keys:
- "sMPIdzRqbikhhHZ04QD9DHhvwKo32SbinpkkvVNQ9Mo"
debug: true
usage-statistics-enabled: true
routing:
strategy: "round-robin"
Lưu file : Ctrl + O enter, Ctrl X thoát
Lưu ý phải chuẩn format code thụt lùi dòng
Bước 5) Thêm tài khoản Codex/ChatGPT Vào CLIProxyAPI (đăng nhập thiết bị)
Bật Codex trong cài đặt tài khoản Chatgpt
Setting => Security => Enable device code author...
Add account #1
cd ~/CLIProxyAPI
./cli-proxy-api -codex-device-login -config ./config.yaml -no-browser
Nó sẽ in ra:
• URL: https://auth.openai.com/codex/device
• MÃ: XXXX-XXXXX
Mở URL trên máy tính client → nhập mã → đăng nhập vào tài khoản số 1.
Add account #2 (lặp lại tương tư)
Chạy lại lệnh:
cd ~/CLIProxyAPI
./cli-proxy-api -codex-device-login -config ./config.yaml -no-browser
Sau khi thành công, máy chủ proxy sẽ tạo tệp xác thực tại:
ls -la ~/.cli-proxy-api
# Sẽ có 2 tập tin codex-*.json
# Danh sách test
cd ~/CLIProxyAPI
nohup ./cli-proxy-api -config ./config.yaml > proxy.log 2>&1 &
curl -sS -H "Authorization: Bearer sMPIdzRqbikhhHZ04QD9DHhvwKo32SbinpkkvVNQ9Mo" http://127.0.0.1:8317/v1/models
Bước 6) Trỏ OpenClaw đến CLIProxyAPI
OpenClaw đang sử dụng nhà cung cấp openai-codex. Chúng ta chỉnh sửa tệp cấu hình.
Sử dụng Python để chèn các tệp.
python3 - <<'PY'
import json
p = "/home/bao/.openclaw/openclaw.json"
obj = json.load(open(p))
obj.setdefault("models", {})
obj["models"]["mode"] = "merge"
providers = obj["models"].setdefault("providers", {})
providers["openai-codex"] = {
"baseUrl": "http://127.0.0.1:8317/v1",
"api": "openai-completions",
"headers": {
"Authorization": "Bearer sMPIdzRqbikhhHZ04QD9DHhvwKo32SbinpkkvVNQ9Mo"
},
"models": []
}
with open(p, "w") as f:
json.dump(obj, f, indent=2)
f.write("\n")
print("updated", p)
PY
Xác thực config
openclaw config validate --json
Kết quả nên là {"valid":true,...}.
Khởi động lại gateway để tự sinh ra file cấu hình agents/main/agent/models.json
systemctl --user restart openclaw-gateway
Kiểm tra
cat ~/.openclaw/agents/main/agent/models.json
Bước 7) Khởi động lại OpenClaw Gateway
systemctl --user restart openclaw-gateway
Sau đó kiểm tra chức năng nhắn tin Telegram thông thường.
Bước 8) Chạy CLIProxyAPI như một dịch vụ (tự động chạy sau khi khởi động lại)
Tạo file dịch vụ
sudo nano ~/.config/systemd/user/cliproxyapi.service
Dán nội dung này
[Unit]
Description=CLIProxyAPI (local OpenAI-compatible proxy)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=%h/CLIProxyAPI
ExecStart=%h/CLIProxyAPI/cli-proxy-api -config %h/CLIProxyAPI/config.yaml
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=default.target
Enable + start:
systemctl --user daemon-reload
systemctl --user enable --now cliproxyapi.service
Log Follow bằng lệnh:
journalctl --user -u cliproxyapi -f
Bước 9) Ghi chú tùy chọn
routing.strategy: Round-robin là gì và nó nằm ở đâu?
Đây là chiến lược chọn tài khoản/thông tin đăng nhập khi một máy chủ proxy có nhiều tài khoản hợp lệ cho cùng một mô hình.
• Round-robin = luân phiên (A → B → A → B…)
• Fill-first = sử dụng tài khoản ưu tiên trước, sau đó chuyển sang tài khoản tiếp theo
Nó nằm trong file cấu hình CLIProxyAPI:
nano ~/CLIProxyAPI/config.yaml
# Restart proxy
systemctl --user restart cliproxyapi
# Restart gateway
systemctl --user restart openclaw-gateway
Bước 10) Bật kiểm tra hạn mức sử dụng
#0 Tạo khóa bí mật
Tạo khóa bí mật (bạn có thể dùng Python)
(Python tạo khóa dạng văn bản thuần)
python3 - <<'PY'
import secrets
print(secrets.token_urlsafe(32))
PY
Key: rDdnKJu4JYNMnlVp8WRr-7tGgXSBtzMib2c_KQqzs4I
nano ~/CLIProxyAPI/config.yaml
Sau đó restart service
systemctl --user restart cliproxyapi
Khi dịch vụ khởi động, nó sẽ tự động băm khóa bí mật (bcrypt) và ghi đè khóa bí mật trong tệp.
Restart service:
systemctl --user restart cliproxyapi
#1 Tạo file quản lý key (để tránh phải sao chép key mỗi lần)
echo 'rDdnKJu4JYNMnlVp8WRr-7tGgXSBtzMib2c_KQqzs4I' > ~/.cli-proxy-api/.mgmt_key
chmod 600 ~/.cli-proxy-api/.mgmt_key
#2 Tạo tập lệnh Python chính:
Tạo thư mục
mkdir -p ~/bin
Chạy lệnh Python để ghi tệp
cat > ~/bin/cliproxy_stats.py <<'PY'
#!/usr/bin/env python3
import argparse
import json
from datetime import datetime, timezone
try:
from zoneinfo import ZoneInfo
except Exception:
ZoneInfo = None
from urllib.request import Request, urlopen
DEFAULT_URL = "http://127.0.0.1:8317/v0/management/usage"
DEFAULT_AUTHFILES_URL = "http://127.0.0.1:8317/v0/management/auth-files"
DEFAULT_KEY_FILE = "/home/bao/.cli-proxy-api/.mgmt_key"
def fetch_json(url: str, key: str) -> dict:
req = Request(url, headers={"X-Management-Key": key})
with urlopen(req, timeout=10) as resp:
body = resp.read().decode("utf-8", errors="replace")
return json.loads(body)
def iter_details(usage_json: dict):
apis = usage_json.get("usage", {}).get("apis", {})
for _api_key, api in apis.items():
for model, model_info in (api.get("models", {}) or {}).items():
for det in (model_info.get("details", []) or []):
yield model, det
def auth_status_map(auth_files_json: dict) -> dict:
out = {}
files = auth_files_json.get("files", []) or []
for f in files:
email = f.get("email") or f.get("account") or f.get("label")
if not email:
continue
out[email] = {
"status": f.get("status", ""),
"disabled": bool(f.get("disabled", False)),
}
return out
def print_table(rows, headers, limit=None):
if limit is not None:
rows = rows[-limit:]
widths = []
for i, h in enumerate(headers):
w = len(h)
for r in rows:
w = max(w, len(str(r[i])))
widths.append(w)
fmt = " ".join("{:<%d}" % w for w in widths)
print(fmt.format(*headers))
print(fmt.format(*["-" * w for w in widths]))
for r in rows:
print(fmt.format(*[str(x) for x in r]))
def cmd_recent(usage: dict, n: int):
rows = []
for model, det in iter_details(usage):
t = det.get("tokens", {}) or {}
rows.append([
det.get("timestamp", ""),
model,
det.get("source", ""),
det.get("latency_ms", ""),
t.get("input_tokens", 0) or 0,
t.get("output_tokens", 0) or 0,
t.get("cached_tokens", 0) or 0,
t.get("total_tokens", 0) or 0,
"Y" if det.get("failed") else "N",
])
rows.sort(key=lambda r: r[0])
headers = ["time", "model", "account", "lat_ms", "in_tok", "out_tok", "cached", "total", "fail"]
print_table(rows, headers, limit=n)
def cmd_today(usage: dict, authfiles: dict, tz_name: str = "Asia/Ho_Chi_Minh"):
tz = ZoneInfo(tz_name) if ZoneInfo else timezone.utc
today = datetime.now(tz).date().isoformat()
status = auth_status_map(authfiles)
agg = {}
for model, det in iter_details(usage):
ts = det.get("timestamp", "")
if not ts.startswith(today):
continue
acct = det.get("source", "unknown")
t = det.get("tokens", {}) or {}
a = agg.setdefault(acct, {"req": 0, "in": 0, "out": 0, "cached": 0, "total": 0, "fail": 0})
a["req"] += 1
a["in"] += int(t.get("input_tokens", 0) or 0)
a["out"] += int(t.get("output_tokens", 0) or 0)
a["cached"] += int(t.get("cached_tokens", 0) or 0)
a["total"] += int(t.get("total_tokens", 0) or 0)
a["fail"] += 1 if det.get("failed") else 0
print(f"date({tz_name}) = {today}")
accounts = sorted(status.keys() | agg.keys())
rows = []
for acct in accounts:
v = agg.get(acct, {"req": 0, "in": 0, "out": 0, "cached": 0, "total": 0, "fail": 0})
s = status.get(acct, {})
st = s.get("status", "")
dis = "Y" if s.get("disabled") else "N"
rows.append([acct, st, dis, v["req"], v["in"], v["out"], v["cached"], v["total"], v["fail"]])
headers = ["account", "status", "disabled", "req", "in_tok", "out_tok", "cached", "total", "fail"]
print_table(rows, headers)
def main():
ap = argparse.ArgumentParser(description="CLIProxyAPI management usage viewer")
ap.add_argument("--url", default=DEFAULT_URL)
ap.add_argument("--key-file", default=DEFAULT_KEY_FILE)
sub = ap.add_subparsers(dest="cmd", required=True)
p1 = sub.add_parser("recent", help="show last N requests")
p1.add_argument("-n", type=int, default=40)
p2 = sub.add_parser("today", help="show today's totals per account")
p2.add_argument("--tz", default="Asia/Ho_Chi_Minh")
args = ap.parse_args()
with open(args.key_file, "r", encoding="utf-8") as f:
key = f.read().strip()
usage = fetch_json(args.url, key)
authfiles = fetch_json(DEFAULT_AUTHFILES_URL, key)
if args.cmd == "recent":
cmd_recent(usage, args.n)
else:
cmd_today(usage, authfiles, tz_name=args.tz)
if __name__ == "__main__":
main()
PY
Phân quyền
chmod +x ~/bin/cliproxy_stats.py
#3 Tạo file bash ngắn: ~/bin/cliproxy-stats
cat > ~/bin/cliproxy-stats << 'SH'
#!/usr/bin/env bash
set -euo pipefail
exec /home/bao/bin/cliproxy_stats.py "$@"
SH
Phân quyền
chmod +x ~/bin/cliproxy-stats
#4 Thực hiện
• Xem tổng số tiền hôm nay + tài khoản nào đang hoạt động/bị vô hiệu hóa:
~/bin/cliproxy-stats today
~/bin/cliproxy-stats recent -n 30
Tóm lại: Nếu bạn muốn nhanh hơn, chỉ cần sao chép và dán các bước của tôi và để AI tự động thực hiện.
Tham khảo thêm bài viết cùng chủ đề
P10 – Gỡ OpenClaw Windows Sạch Sẽ
P10 – Gỡ OpenClaw Windows Sạch Sẽ https://youtu.be/1ljEMzohiSY 🚀 AI Tutorial – P10: Gỡ OpenClaw trên Windows (Clean Removal & Fix Issues) Nếu bạn đang gặp lỗi với OpenClaw hoặc muốn cài lại từ đầu, việc gỡ openclaw đúng cách là rất quan trọng. Nếu chỉ xóa file đơn giản,...
Read MoreP9 – Cài đặt Telegram Bot Local AI với Ollama nhanh
P9 – Cài đặt Telegram Bot Local AI với Ollama nhanh https://youtu.be/YuiLJDLIVr0 🚀 AI Tutorial – P9: Cài Đặt Telegram Bot Local AI với Ollama Việc cài đặt telegram bot local giúp bạn đưa AI vào thực tế một cách nhanh chóng và hiệu quả. Khi kết hợp Ollama với...
Read MoreP8 – Cài đặt OpenClaw Local AI với Ollama & Qwen
P8 – Cài đặt OpenClaw Local AI với Ollama & Qwen 🚀 AI Tutorial – P8: Cài Đặt OpenClaw Local với Ollama, Qwen & Open WebUI Việc cài đặt openclaw local giúp bạn xây dựng một hệ thống AI chạy hoàn toàn nội bộ, không phụ thuộc vào API bên...
Read More