Bắt đầuStart here
Hướng dẫn deployDeployment guide
Dựng mới và cập nhật toàn bộ hệ thống: stack fxconsole, bốn broker, cổng firewall, chứng chỉ, terminal MT5, vps-agent, cùng cách kiểm tra, rollback và xử lý sự cố. Setting up and updating the whole system: the fxconsole stack, the four brokers, firewall ports, certificates, MT5 terminals and vps-agent, plus how to verify, roll back and troubleshoot.
- Chạy
docker compose down -vởmonitor/fxconsole: xoá volumetimescale_data(mất toàn bộ lịch sử OHLC) vàclaude_creds/claude_config(mất đăng nhập subscription). - Đổi
APP_KEYcủa fxconsole đã chạy: mọi cột mã hoá (vpses.vnc_password,mt5_accounts.password_encrypted, cookie phiên…) không giải mã được nữa. - Dán secret vào tài liệu, commit
.envhay.setcó token. Trang này chỉ ghi tên biến.
- Run
docker compose down -vinmonitor/fxconsole: it deletes thetimescale_datavolume (all OHLC history) andclaude_creds/claude_config(the subscription login). - Change the
APP_KEYof a running fxconsole: every encrypted column (vpses.vnc_password,mt5_accounts.password_encrypted, session cookies…) becomes undecryptable. - Paste secrets into docs, or commit a
.envor a.setcontaining a token. This page names variables only.
Cần deploy những gìWhat gets deployed
| Thành phầnComponent | Ở đâuWhere | Cách deployHow | Phiên bản hiện tạiCurrent version |
|---|---|---|---|
| fxconsole (web, app, scheduler, redis, timescale, claude-cli, guacamole)(web, app, scheduler, redis, timescale, claude-cli, guacamole) | Docker host · monitor/fxconsole | deploy.sh | app_version 2026.09.22.1 |
| AccountStatusBroker, TickBroker, VpsStreamBroker, EaLinkBroker | Docker host · monitor/<Broker> | deploy.sh | theo commit trên mainwhatever main holds |
| GoldenRobber EA | Terminal MT5MT5 terminal | Copy .ex5, gỡ rồi gắn lại EA, hoặc gói deploy của vps-agentCopy .ex5, remove and re-attach the EA, or a vps-agent deploy package | Production 1.42 b7 · bản cũ 1.41.4 b21 · hotfix b21.1 (không deploy)Production 1.42 b7 · previous 1.41.4 b21 · hotfix b21.1 (never deployed) |
| Config ổn địnhStable config | Terminal MT5MT5 terminal | Nạp .set, điền token trên terminalLoad the .set, type the token on the terminal | v1.42.b7-pass58.set |
| AccountStatusUpdater, TickStreamerPub | Terminal MT5MT5 terminal | Copy .ex5 + inputCopy .ex5 + inputs | 1.14 · 1.04 |
| vps-agent | VPS Windows | prepare-vm.ps1 · lệnh Upgrade từ webUpgrade command from the web | 1.3.2-phase9 |
| cloudflare-tmap-worker | Cloudflare | npm run deploy (tuỳ chọn)(optional) | không dùng ở productionnot used in production |
Kiến trúc, cổng và luồng dữ liệu: Kiến trúc hệ thống.
Architecture, ports and data flows: System architecture.
Điều kiện tiên quyếtPrerequisites
- Docker host Linux có Docker Engine + plugin
docker compose. Tuning Postgres trong compose giả định 8 core / 16 GB RAM / NVMe. - Repo clone tại
~/goldenrobber/GoldenRobber(đường dẫn mặc định củadeploy.sh, đổi được bằng biếnREPO), theo nhánhmain. fxconsole, các broker, TickStreamer, vps-agent đều là thư mục con của repo này. - Mạng Docker
fxconsole_default: được tạo khi stack fxconsole chạy lần đầu. Mọi broker join mạng này dạngexternal, nên luôn bật fxconsole trước. - MySQL từ xa trên host aaPanel (database
trade_copier) truy cập được từ Docker host; user DB của fxconsole cũng được broker dùng. - DNS + reverse proxy:
fxconsole.gamelau.uktrỏ về biên; openresty (aaPanel, Let's Encrypt) proxy HTTPS vềfxconsole-webcổng8080và chuyển headerX-Forwarded-Proto,X-Forwarded-Host. - Firewall: OVH Network Firewall + IPFire, xem checklist cổng.
- Docker host: Linux with Docker Engine + the
docker composeplugin. The Postgres tuning in the compose file assumes 8 cores / 16 GB RAM / NVMe. - Repo cloned at
~/goldenrobber/GoldenRobber(thedeploy.shdefault, overridable with theREPOvariable), trackingmain. fxconsole, the brokers, TickStreamer and vps-agent are all subfolders of this one repo. - Docker network
fxconsole_default: created the first time the fxconsole stack starts. Every broker joins it asexternal, so always start fxconsole first. - Remote MySQL on the aaPanel host (database
trade_copier) reachable from the Docker host; the brokers reuse fxconsole's DB user. - DNS + reverse proxy:
fxconsole.gamelau.ukpoints at the edge; openresty (aaPanel, Let's Encrypt) proxies HTTPS tofxconsole-webon port8080and forwardsX-Forwarded-Proto,X-Forwarded-Host. - Firewall: OVH Network Firewall + IPFire, see the port checklist.
mkdir -p ~/goldenrobber && cd ~/goldenrobber
git clone <repo-url> GoldenRobber
cd GoldenRobber && git checkout main
Cài đặt lần đầuFirst-time setup
Làm theo đúng thứ tự: fxconsole → cấu hình /admin/settings → các broker → firewall → terminal. Sau lần đầu, mọi cập nhật chỉ cần deploy.sh.
Follow this order: fxconsole → /admin/settings → brokers → firewall → terminals. After the first time, every update is just deploy.sh.
fxconsolefxconsole
- Tạo file
.envtừ mẫu và khoá quyền:Create.envfrom the example and lock its permissions:cd ~/goldenrobber/GoldenRobber/monitor/fxconsole cp .env.example .env chmod 600 .env - Điền các biến trong bảng dưới (chỉ tên; giá trị lấy từ nơi ghi ở cột phải).Fill the variables in the table below (names only; take values from where the right-hand column says).
- Khởi động stack (tạo luôn mạng
fxconsole_default):Start the stack (this also creates thefxconsole_defaultnetwork):
Containerdocker compose up -d --build docker compose logs -f appapptự: tạo thư mục storage + chmod,composer install/updatevànpm ci/installkhi manifest mới hơn,npm run build,php artisan key:generate --forcechỉ khi.envchưa cóAPP_KEY=base64:,php artisan migrate --force,php artisan view:clear, rồiphp-fpm -F.schedulerchờvendor/autoload.php, chạyschedule:clear-cacherồischedule:work. Theappcontainer: creates storage dirs + chmod, runscomposer install/updateandnpm ci/installwhen manifests are newer,npm run build,php artisan key:generate --forceonly if.envhas noAPP_KEY=base64:,php artisan migrate --force,php artisan view:clear, thenphp-fpm -F.schedulerwaits forvendor/autoload.php, runsschedule:clear-cache, thenschedule:work. - Sao lưu
.env(đã cóAPP_KEY) ra nơi an toàn.Back up.env(now holdingAPP_KEY) somewhere safe. - Đăng nhập admin, mở
/admin/settings: kiểm traapp_version, điền EALinkBroker Secret Key (settings.broker_internal_secret), secret admin firehose (broker_admin_secret), VpsStreamBroker hostname / port, nhịphb_interval_secs/stream_cadence_ms, Guacamole, token khởi tạo VPS. Giá trị trong DB thắng giá trị.env.Log in as admin, open/admin/settings: checkapp_version, fill EALinkBroker Secret Key (settings.broker_internal_secret), the admin firehose secret (broker_admin_secret), VpsStreamBroker hostname / port, thehb_interval_secs/stream_cadence_mscadences, Guacamole, the VPS bootstrap token. DB values win over.env. - Đăng ký EA product:
/admin/easupported→ Thêm EA → slug (vdgoldenrobber) → secret token tự sinh. URLhttps://fxconsole.gamelau.uk/easupported/goldenrobberđi vàoInpCloudMyApiDomain, token đi vàoInpCloudBearerToken(gõ trên terminal, không commit).Register the EA product:/admin/easupported→ Add EA → slug (e.g.goldenrobber) → the secret token is generated. The URLhttps://fxconsole.gamelau.uk/easupported/goldenrobbergoes intoInpCloudMyApiDomain, the token intoInpCloudBearerToken(typed on the terminal, never committed).
Biến trong monitor/fxconsole/.envVariable in monitor/fxconsole/.env |
Dùng cho / lấy giá trị ở đâuUsed for / where the value comes from |
|---|---|
APP_NAME, APP_ENV, APP_DEBUG | Production: tắt debug. Lưu ý: nếu không đặt REDIS_PREFIX, tiền tố Redis = slug(APP_NAME)-database-; mọi broker mặc định laravel-database-, nên đổi APP_NAME thì phải sửa REDIS_PREFIX ở broker.Production: debug off. Note: without REDIS_PREFIX, the Redis prefix = slug(APP_NAME)-database-; every broker defaults to laravel-database-, so renaming APP_NAME means updating REDIS_PREFIX on the brokers. |
APP_KEY | Để trống lần đầu, container tự tạo. Không bao giờ đổi sau đó.Leave empty the first time; the container generates it. Never change it afterwards. |
APP_URL, TRUSTED_PROXIES | URL https công khai; TRUSTED_PROXIES = IP proxy hoặc * để Laravel tin X-Forwarded-Proto.Public https URL; TRUSTED_PROXIES = proxy IPs or * so Laravel trusts X-Forwarded-Proto. |
APP_TIMEZONE, APP_DATETIME_FORMAT, APP_LOCALE | Hiển thị. Container dùng TZ=Asia/Ho_Chi_Minh.Display. Containers run with TZ=Asia/Ho_Chi_Minh. |
DB_CONNECTION, DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD | MySQL từ xa trên aaPanel (trade_copier). deploy.sh copy sang .env của broker.Remote MySQL on aaPanel (trade_copier). deploy.sh copies them into the brokers' .env. |
TIMESCALE_HOST, TIMESCALE_PORT, TIMESCALE_DATABASE, TIMESCALE_USERNAME, TIMESCALE_PASSWORD | Service timescale đọc cùng file (mặc định DB fxconsole_ts, user fxconsole). Mật khẩu phải khớp lúc volume được khởi tạo.The timescale service reads the same file (default DB fxconsole_ts, user fxconsole). The password must match what the volume was initialised with. |
REDIS_CLIENT, REDIS_HOST, REDIS_PORT, REDIS_PASSWORD | REDIS_HOST=redis (service trong compose, không đặt mật khẩu).REDIS_HOST=redis (compose service, no password configured). |
SESSION_*, CACHE_STORE, QUEUE_CONNECTION, FILESYSTEM_DISK, BROADCAST_CONNECTION | Giữ như mẫu trừ khi có lý do.Keep the example values unless there is a reason. |
MAIL_* | SMTP Mailjet: MAIL_USERNAME = API key, MAIL_PASSWORD = secret key của Mailjet.Mailjet SMTP: MAIL_USERNAME = API key, MAIL_PASSWORD = Mailjet secret key. |
AWS_* | Chỉ cần khi dùng disk S3.Only needed for an S3 disk. |
EA_API_BEARER | Bearer của /api/account-status và backfill OHLC; = InpApiBearer (AccountStatusUpdater) và InpFxconsoleBearer (TickStreamerPub). Setting DB ea_api_bearer ghi đè.Bearer for /api/account-status and OHLC backfill; = InpApiBearer (AccountStatusUpdater) and InpFxconsoleBearer (TickStreamerPub). The DB setting ea_api_bearer overrides it. |
TMAP_SECRET_KEY | Bearer của URL TMap kiểu cũ /api/tmap/* và secret của Cloudflare worker. URL per-EA /easupported/{slug} dùng easupported.secret_token thay thế.Bearer for the legacy /api/tmap/* TMap URL and the Cloudflare worker secret. The per-EA /easupported/{slug} URL uses easupported.secret_token instead. |
BROKER_STREAM_SECRET | = BROKER_SECRET trong monitor/AccountStatusBroker/.env = InpBrokerSecret của EA. Hiện read-only trên Settings để copy.= BROKER_SECRET in monitor/AccountStatusBroker/.env = the EA's InpBrokerSecret. Shown read-only on Settings for copying. |
HB_INTERVAL_SECS_DEFAULT, STREAM_CADENCE_MS_DEFAULT | Giá trị khởi động nguội; nguồn chân lý là /admin/settings.Cold-start defaults; /admin/settings is the source of truth. |
GUAC_JSON_SECRET_KEY | Khoá AES 32 hex (openssl rand -hex 16). Service guacamole đọc cùng giá trị làm JSON_SECRET_KEY.32-hex AES key (openssl rand -hex 16). The guacamole service reads the same value as JSON_SECRET_KEY. |
GUAC_PUBLIC_URL | URL https công khai của Guacamole, không có / cuối. Rỗng = nút Connect tắt. DB ghi đè.Public https URL of Guacamole, no trailing /. Empty = Connect buttons disabled. DB overrides. |
VPS_INIT_BOOTSTRAP_TOKEN | openssl rand -hex 32; bake vào vps-agent.ini.init-template. Rỗng = /api/agent/init-config trả 503.openssl rand -hex 32; baked into vps-agent.ini.init-template. Empty = /api/agent/init-config returns 503. |
VPS_BROKER_HOST, VPS_BROKER_PORT, VPS_BROKER_URL | Giá trị gieo cho "VpsStreamBroker hostname / port" trên Settings. Host phải khớp CERT_HOST của VpsStreamBroker. VPS_BROKER_URL rỗng = tự suy ra tls://host:port.Seed for "VpsStreamBroker hostname / port" on Settings. The host must match VpsStreamBroker's CERT_HOST. Empty VPS_BROKER_URL = derived as tls://host:port. |
BROKER_ADMIN_SECRET | Dự phòng khởi động cho token firehose admin; giá trị sống ở settings.broker_admin_secret.Bootstrap fallback for the admin firehose token; the live value is settings.broker_admin_secret. |
BROKER_INTERNAL_SECRET | Dự phòng khởi động cho header X-Broker-Secret; giá trị sống là "EALinkBroker Secret Key" (settings.broker_internal_secret).Bootstrap fallback for the X-Broker-Secret header; the live value is "EALinkBroker Secret Key" (settings.broker_internal_secret). |
DEFAULT_HEARTBEAT_INTERVAL, STALENESS_MULTIPLIER | Heartbeat mặc định cho VPS mới; hệ số phát hiện "lost" trên dashboard.Default heartbeat for new VPS rows; the dashboard "lost" detection multiplier. |
EA_DOWNLOAD_URL, FAVICON_URL | Tuỳ chọn.Optional. |
Các brokerBrokers
deploy.sh lo phần lớn: trước khi docker compose up mỗi broker, hàm ensure_env
- chưa có
.env→ tạo từ.env.example, mọi giá trị giữ chỗchange_me…bị để trống (broker không bao giờ chạy với secret đoán được),chmod 600, và in tên các biến cần điền; - nếu
.env.examplecóDB_HOST(AccountStatusBroker, VpsStreamBroker, EaLinkBroker) → điềnDB_*từmonitor/fxconsole/.env(DB_DATABASE→DB_NAME,DB_USERNAME→DB_USER). File mới: ghi đè giá trị mẫu. File đã có: chỉ điền ô trống hoặc thiếu, không bao giờ ghi đè.
Sau đó mở từng file được báo, điền ô còn trống, rồi cd monitor/<Broker> && docker compose up -d. Muốn làm tay: cp .env.example .env && chmod 600 .env, rồi sửa.
deploy.sh does most of it: before each broker's docker compose up, ensure_env
- no
.envyet → creates it from.env.example, leaving everychange_me…placeholder empty (a broker never boots with a guessable secret),chmod 600, and prints the names still to fill; - if
.env.examplehasDB_HOST(AccountStatusBroker, VpsStreamBroker, EaLinkBroker) → fillsDB_*frommonitor/fxconsole/.env(DB_DATABASE→DB_NAME,DB_USERNAME→DB_USER). New file: replaces the example values. Existing file: fills only empty or missing keys, never overwrites.
Then open each reported file, fill the blanks, and run cd monitor/<Broker> && docker compose up -d. By hand: cp .env.example .env && chmod 600 .env, then edit.
| Broker | Biến cần cóVariables to set | Giá trị lấy từValue comes from |
|---|---|---|
| TickBroker | TICK_BROKER_SECRET REQUIRED, REDIS_URL, CERT_HOST | Secret = InpSharedSecret của TickStreamerPub (rỗng → FATAL). REDIS_URL mặc định redis://fxconsole-redis:6379. CERT_HOST = InpBrokerHost của EA (mặc định compose fxconsole.gamelau.uk). Không có DB_*.Secret = TickStreamerPub's InpSharedSecret (empty → FATAL). REDIS_URL defaults to redis://fxconsole-redis:6379. CERT_HOST = the EA's InpBrokerHost (compose default fxconsole.gamelau.uk). No DB_*. |
| AccountStatusBroker | BROKER_SECRET REQUIRED, BROKER_ADMIN_SECRET, DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD, REDIS_URL, REDIS_PREFIX, CERT_HOST, HB_INTERVAL_SECS, STREAM_CADENCE_MS | BROKER_SECRET = BROKER_STREAM_SECRET của fxconsole = InpBrokerSecret (rỗng → FATAL). BROKER_ADMIN_SECRET chỉ là dự phòng cuối. DB_* tuỳ chọn nhưng nên có (deploy.sh điền) để đọc broker_admin_secret, hb_interval_secs, stream_cadence_ms từ bảng settings. HB_INTERVAL_SECS 15 / STREAM_CADENCE_MS 900 là mặc định.BROKER_SECRET = fxconsole's BROKER_STREAM_SECRET = InpBrokerSecret (empty → FATAL). BROKER_ADMIN_SECRET is only the last fallback. DB_* optional but recommended (deploy.sh fills it) to read broker_admin_secret, hb_interval_secs, stream_cadence_ms from the settings table. HB_INTERVAL_SECS 15 / STREAM_CADENCE_MS 900 are the defaults. |
| VpsStreamBroker | DB_* REQUIRED, CERT_HOST, BROKER_INTERNAL_URL, BROKER_INTERNAL_SECRET, BROKER_INTERNAL_TIMEOUT_MS, BROKER_ADMIN_SECRET, REDIS_URL, REDIS_PREFIX, PING_INTERVAL, PING_TIMEOUT, HEARTBEAT_TTL, BROKER_DEBUG | DB_* bắt buộc (đọc vpses.secret_key, ghi vps_commands, vpses.account_logins). CERT_HOST phải khớp hostname stunnel kiểm tra (= "VpsStreamBroker hostname" trên Settings). BROKER_INTERNAL_URL = http://fxconsole-web (nginx cổng 80 nội bộ, không phải 8080, không phải fxconsole-app). Secret: DB → Redis → env. PING_INTERVAL 30 / PING_TIMEOUT 10 / HEARTBEAT_TTL 15 mặc định.DB_* required (reads vpses.secret_key, writes vps_commands, vpses.account_logins). CERT_HOST must match the hostname stunnel checks (= "VpsStreamBroker hostname" on Settings). BROKER_INTERNAL_URL = http://fxconsole-web (nginx internal port 80, not 8080, not fxconsole-app). Secrets: DB → Redis → env. Defaults PING_INTERVAL 30 / PING_TIMEOUT 10 / HEARTBEAT_TTL 15. |
| EaLinkBroker | DB_* NEEDED, BROKER_INTERNAL_URL, BROKER_INTERNAL_SECRET, BROKER_INTERNAL_TIMEOUT_MS, REDIS_URL, REDIS_PREFIX, CERT_HOST, HB_TIMEOUT_SEC, HELLO_GRACE_MS, KEY_CACHE_SEC, BROKER_DEBUG, TZ | DB_* để đọc settings.broker_internal_secret thẳng từ MySQL; thiếu thì sau deploy hoặc restart Redis mọi EA dính auth_unavailable. BROKER_INTERNAL_SECRET là dự phòng cuối, giá trị phải bằng "EALinkBroker Secret Key" trên /admin/settings. CERT_HOST chỉ mang tính thông tin (MQL5 không verify). Mặc định HB_TIMEOUT_SEC 60 / HELLO_GRACE_MS 5000 / KEY_CACHE_SEC 60 / timeout 3000 ms.DB_* to read settings.broker_internal_secret straight from MySQL; without it, every EA hits auth_unavailable after a deploy or Redis restart. BROKER_INTERNAL_SECRET is the last fallback and must equal "EALinkBroker Secret Key" on /admin/settings. CERT_HOST is informational only (MQL5 does not verify). Defaults HB_TIMEOUT_SEC 60 / HELLO_GRACE_MS 5000 / KEY_CACHE_SEC 60 / timeout 3000 ms. |
Bảng settings MySQL → Redis laravel-database-app_config:<key> → biến .env, cache 30 s; DB lỗi hoặc chậm quá 2 s thì rơi xuống Redis/env. Lý do: Redis của fxconsole không persistence và mirror chỉ được ghi khi admin mở trang, nên trước đây EaLinkBroker báo auth_unavailable sau mỗi lần deploy.
MySQL settings table → Redis laravel-database-app_config:<key> → the .env variable, 30 s cache; if the DB errors or takes over 2 s, it falls back to Redis/env. Why: fxconsole's Redis has no persistence and the mirror is only written when an admin opens a page, so EaLinkBroker used to report auth_unavailable after every deploy.
Chứng chỉ VpsStreamBroker cho fxconsoleVpsStreamBroker certificate for fxconsole
stunnel trên VPS verify broker (verify = 2, checkHost, CAfile), nên fxconsole phải trao CA của broker qua GET /api/agent/broker-config. Compose của fxconsole mount ../VpsStreamBroker/certs:/broker-certs:ro vào fxconsole-app, nên chỉ cần bật VpsStreamBroker một lần (sinh cert) là tự nối. Cách cũ vẫn dùng được khi cần import tay:
stunnel on the VPS verifies the broker (verify = 2, checkHost, CAfile), so fxconsole must hand out the broker's CA via GET /api/agent/broker-config. fxconsole's compose mounts ../VpsStreamBroker/certs:/broker-certs:ro into fxconsole-app, so starting VpsStreamBroker once (which generates the cert) wires it up. The older manual import still works:
docker cp fxconsole-vps-stream-broker:/app/certs/server.cert /tmp/broker-ca.cert
docker cp /tmp/broker-ca.cert fxconsole-app:/tmp/broker-ca.cert
docker exec fxconsole-app php artisan vps-stream-broker:cert-import /tmp/broker-ca.cert
claude-cli (một lần)claude-cli (one time)
Sidecar được build tự động cùng fxconsole. Lần chạy đầu (hoặc khi refresh token hết hạn sau vài tuần/tháng) phải đăng nhập subscription tương tác, không script được:
The sidecar builds automatically with fxconsole. The first run (or when the refresh token expires after weeks/months) needs an interactive subscription login that cannot be scripted:
cd ~/goldenrobber/GoldenRobber/monitor/fxconsole
docker compose exec -it claude-cli claude login
# open the printed URL, approve, paste the code back
# back up the OAuth creds (treat the file as a secret)
docker compose exec claude-cli sh -c 'tar czf - -C /home/node .claude .config' > claude-creds-backup.tgz
Về sau có thể đăng nhập lại ngay trên /admin/analysis (banner đỏ "CLI cần đăng nhập lại" → Re-login). Muốn khoá phiên bản CLI: docker compose build --build-arg CLAUDE_CODE_VERSION=<x.y.z> claude-cli. Lưu ý vùng xám ToS khi chạy subscription từ backend 24/7: giữ lưu lượng thấp. Chi tiết: claude-cli.
Later re-logins can be done from /admin/analysis (red "CLI cần đăng nhập lại" banner → Re-login). To pin the CLI version: docker compose build --build-arg CLAUDE_CODE_VERSION=<x.y.z> claude-cli. Mind the ToS grey area of driving a subscription from a 24/7 backend: keep volume low. Details: claude-cli.
Cloudflare TMap worker (tuỳ chọn)Cloudflare TMap worker (optional)
Config ổn định để InpCloudCfDomain trống nên production không cần bước này. Nếu muốn backup TMap thứ hai:
The stable config leaves InpCloudCfDomain empty, so production does not need this. For a second TMap backup:
cd cloudflare-tmap-worker
npm install
wrangler login
npm run db:create # copy database_id into wrangler.toml
npm run db:migrate
npm run secret:set # enter TMAP_SECRET_KEY
npm run deploy # → https://gr-tmap.<account>.workers.dev → InpCloudCfDomain
Thêm domain worker vào Allow WebRequest của terminal. Chi tiết: Cloudflare TMap worker.
Add the worker domain to the terminal's Allow WebRequest list. Details: Cloudflare TMap worker.
Deploy thường ngày với deploy.shRoutine deploy with deploy.sh
cd ~/goldenrobber/GoldenRobber
bash deploy.sh
Dòng trong deploy.shLine in deploy.sh |
Làm gìWhat it does |
|---|---|
set -e | Một lệnh lỗi (vd git pull xung đột) là dừng cả script.Any failing command (e.g. a git pull conflict) stops the whole script. |
REPO="${REPO:-$HOME/goldenrobber/GoldenRobber}" | Đường dẫn repo; test có thể source file với REPO khác.Repo path; tests can source the file with another REPO. |
git restore . | Bỏ các thay đổi trên file đã track mà container chạm vào mỗi lần boot (composer.lock, .gitkeep, .gitignore) để git pull không báo "local changes would be overwritten". Không đụng file chưa track (thư mục upload public/theme-bg, broker-logos, packages, dữ liệu storage) và mọi .env. Vì vậy không sửa tay file đã track trên server: sẽ mất ở lần deploy sau.Discards changes to tracked files that containers touch on every boot (composer.lock, .gitkeep, .gitignore) so git pull never fails with "local changes would be overwritten". Untracked files (upload dirs public/theme-bg, broker-logos, packages, storage data) and every .env are left alone. So never hand-edit tracked files on the server: the next deploy wipes them. |
git checkout main · git pull origin main | Production luôn theo main.Production always tracks main. |
cd monitor/fxconsole/; docker compose down; docker compose up -d --build | Dựng lại fxconsole, gồm cả sidecar claude-cli (build context ../claude-cli). Migration tự chạy khi app khởi động. down thường giữ mọi named volume.Rebuilds fxconsole, including the claude-cli sidecar (build context ../claude-cli). Migrations run when app boots. A plain down keeps every named volume. |
compose_up AccountStatusBroker · TickBroker · VpsStreamBroker · EaLinkBroker | Mỗi broker: ensure_env (tạo .env / điền DB_*) → docker compose down → docker compose up -d --build.Each broker: ensure_env (create .env / fill DB_*) → docker compose down → docker compose up -d --build. |
#docker system prune -af | Đang comment, không chạy.Commented out, never runs. |
echo "== Deploy done ==" | In ghi chú .env của broker (nếu có) và nhắc lệnh claude login.Prints broker .env notes (if any) and the claude login reminder. |
flowchart TD A["git restore ."] --> B["git checkout main"] B --> C["git pull origin main"] C --> D["fxconsole: down, up -d --build"] D --> E["AccountStatusBroker: ensure_env, down, up -d --build"] E --> F["TickBroker: ensure_env, down, up -d --build"] F --> G["VpsStreamBroker: ensure_env, down, up -d --build"] G --> H["EaLinkBroker: ensure_env, down, up -d --build"] H --> I["== Deploy done == + .env notes + claude login reminder"]
fxconsole luôn đi trước để mạng fxconsole_default và fxconsole-redis tồn tại khi broker khởi động.
fxconsole always goes first so fxconsole_default and fxconsole-redis exist when the brokers start.
Các dòng ghi chú .env có thể xuất hiện (chuỗi in ra bằng tiếng Việt):
The .env note lines you may see (the script prints them in Vietnamese):
== .env của broker ==
TẠO MỚI monitor/<Broker>/.env — cần điền: <KEY1> <KEY2>
ĐIỀN DB monitor/<Broker>/.env: DB_HOST DB_PORT DB_NAME DB_USER DB_PASSWORD (lấy từ monitor/fxconsole/.env)
THIẾU DB monitor/<Broker>/.env: DB_PASSWORD trống và fxconsole/.env không có giá trị
→ Mở các file trên, điền ô còn trống (vd secret), rồi áp dụng lại cho service đó:
cd ~/goldenrobber/GoldenRobber/monitor/<Broker> && docker compose up -d
Toàn bộ script được bọc trong main() để bash đọc hết file trước khi git pull ghi đè deploy.sh; bản mới chỉ có hiệu lực ở lần chạy sau. Khi một commit vừa đổi deploy.sh (vd commit 15b70c3 thêm tự tạo .env broker), hãy chạy git pull trước rồi mới bash deploy.sh, để logic mới chạy ngay lần này.
The whole script is wrapped in main() so bash has parsed it fully before git pull rewrites deploy.sh; a new version only takes effect on the next run. When a commit has just changed deploy.sh (e.g. commit 15b70c3 added auto-created broker .env), run git pull first, then bash deploy.sh, so the new logic runs this time.
cd ~/goldenrobber/GoldenRobber
git pull origin main
bash deploy.sh
- Gián đoạn: mỗi stack bị
downrồiup, nên có vài giây đến vài phút (npm build của fxconsole) không phục vụ. EA vẫn giao dịch (mất server không đổi hành vi EA); EA Link, AccountStatusUpdater, TickStreamerPub và agent tự kết nối lại với backoff; trong lúc đó EA Link rơi về heartbeat HTTP. - Chỉ cập nhật một broker:
cd ~/goldenrobber/GoldenRobber/monitor/<Broker> && docker compose up -d --build. Chỉ đổi.env:docker compose up -d(compose tạo lại container với env mới). - Xác nhận bản đã lên:
/admin/settingshiệnapp_version(hiện tại2026.09.22.1);git log -1 --onelinetrên server.
- Downtime: each stack goes
downthenup, so expect seconds to minutes (fxconsole's npm build) without service. EAs keep trading (losing the server does not change EA behaviour); EA Link, AccountStatusUpdater, TickStreamerPub and the agents reconnect with backoff; meanwhile EA Link falls back to the HTTP heartbeat. - Update one broker only:
cd ~/goldenrobber/GoldenRobber/monitor/<Broker> && docker compose up -d --build. Only.envchanged:docker compose up -d(compose recreates the container with the new env). - Confirm what went live:
/admin/settingsshowsapp_version(currently2026.09.22.1);git log -1 --onelineon the server.
Checklist firewall và port-forwardFirewall and port-forward checklist
| CổngPort | Service | OVH Network Firewall | IPFire | Ai kết nốiWho connects |
|---|---|---|---|---|
| 443/tcp | openresty (aaPanel) | ACCEPT | theo thiết lập biên hiện tạiper the current edge setup | Trình duyệt, mọi EA (WebRequest), agent, TickStreamerPubBrowsers, every EA (WebRequest), agents, TickStreamerPub |
| 9600/tcp | TickBroker TLS | ACCEPT | WAN:9600 → <docker-host-LAN-IP>:9600 | TickStreamerPub |
| 9602/tcp | AccountStatusBroker TLS | ACCEPT | WAN:9602 → <docker-host-LAN-IP>:9602 | AccountStatusUpdater (TCP / HYBRID)AccountStatusUpdater (TCP / HYBRID) |
| 9605/tcp | VpsStreamBroker TLS | ACCEPT | WAN:9605 → <docker-host-LAN-IP>:9605 | stunnel trên mọi VPSstunnel on every VPS |
| 9607/tcp | EaLinkBroker TLS | ACCEPT | WAN:9607 → <docker-host-LAN-IP>:9607 | GoldenRobber 1.42+ |
| 9601, 9603 | WS của Tick / AccountStatusTick / AccountStatus WS | NO | NO | Compose publish trên host, nhưng trình duyệt đi qua /ws, /status-ws; không cần forward.Published on the host by compose, but browsers use /ws, /status-ws; no forward needed. |
| 9606 | WS của VpsStreamVpsStream WS | NO | NO | Chỉ expose trong mạng Docker, qua /vps-ws.Only exposed on the Docker network, via /vps-ws. |
| 8080, 8282 | fxconsole-web, guacamole | NO | NO | Chỉ reverse proxy truy cập.Reverse proxy only. |
| 5432 | TimescaleDB | BLOCK | NEVER | Publish mọi interface cho LAN; host có IP public thì phải chặn.Published on all interfaces for LAN use; block it if the host has a public IP. |
| 6379, 8788, 4822, 9000 | redis, claude-cli, guacd, php-fpm | NO | NO | Chỉ nội bộ Docker.Docker-internal only. |
| 51820/udp | wg-easy (CT 107) | ALLOW | theo thiết lập VPNper the VPN setup | Client WireGuard (cổng mặc định của wg-easy)WireGuard clients (wg-easy default port) |
Kiểm tra từ bên ngoài sau khi mở cổng. "connection refused / reset / timeout" nghĩa là cổng chưa tới được broker, sửa firewall trước khi đi tiếp.
Test from outside after opening a port. "connection refused / reset / timeout" means the port does not reach the broker yet; fix the firewall before going further.
# Linux / Git Bash
openssl s_client -connect fxconsole.gamelau.uk:9600 -servername fxconsole.gamelau.uk
openssl s_client -connect fxconsole.gamelau.uk:9602 -servername fxconsole.gamelau.uk
openssl s_client -connect fxconsole.gamelau.uk:9605 -servername fxconsole.gamelau.uk
openssl s_client -connect fxconsole.gamelau.uk:9607 -quiet
# Windows VPS
Test-NetConnection fxconsole.gamelau.uk -Port 9605
Phía MT5: SocketConnect() chỉ chạy với host có trong Tools → Options → Expert Advisors → Allow WebRequest for listed URL, cùng danh sách mà WebRequest dùng.
MT5 side: SocketConnect() only works for hosts listed in Tools → Options → Expert Advisors → Allow WebRequest for listed URL, the same list WebRequest uses.
Chứng chỉ TLSTLS certificates
- Phía trình duyệt và WebRequest: chứng chỉ Let's Encrypt của openresty. WebRequest của EA bắt buộc HTTPS có chứng chỉ hợp lệ; chứng chỉ tự ký báo lỗi
GetLastError = 4014. - Broker: Dockerfile chạy
node gen-cert.js "${CERT_HOST:-localhost}" && node broker.js.gen-cert.jsdùng openssl tạocerts/server.key+certs/server.certtự ký, hạn 10 năm,CN=CERT_HOST; đã có cả hai file thì bỏ qua. Thư mụcmonitor/<Broker>/certsđược bind mount nên cert sống qua mọi lần rebuild. Compose đặt mặc địnhCERT_HOST=fxconsole.gamelau.uk. - Nội bộ: nginx của fxconsole proxy tới cổng WS của broker với
proxy_ssl_verify off.
- Browser and WebRequest side: openresty's Let's Encrypt certificate. The EA's WebRequest requires HTTPS with a valid certificate; a self-signed one fails with
GetLastError = 4014. - Brokers: the Dockerfile runs
node gen-cert.js "${CERT_HOST:-localhost}" && node broker.js.gen-cert.jsuses openssl to create a self-signedcerts/server.key+certs/server.cert, valid 10 years,CN=CERT_HOST; if both files exist it skips.monitor/<Broker>/certsis bind-mounted, so the cert survives every rebuild. Compose defaultsCERT_HOST=fxconsole.gamelau.uk. - Internal: fxconsole's nginx proxies to the brokers' WS ports with
proxy_ssl_verify off.
| Broker | Ai kiểm tra certWho checks the cert | CERT_HOST phải bằngCERT_HOST must equal |
|---|---|---|
| TickBroker | MT5 gửi SNI; ghi chú trong compose/.env.example nói handshake bị từ chối nếu CN khácMT5 sends SNI; the compose/.env.example comments say the handshake is rejected if the CN differs | InpBrokerHost (TickStreamerPub) |
| AccountStatusBroker | Như TickBrokerSame as TickBroker | InpBrokerHost (AccountStatusUpdater) |
| VpsStreamBroker | stunnel verify = 2, checkHost, CAfile (chặt nhất)stunnel verify = 2, checkHost, CAfile (strictest) | "VpsStreamBroker hostname" trên /admin/settings (VPS_BROKER_HOST)"VpsStreamBroker hostname" on /admin/settings (VPS_BROKER_HOST) |
| EaLinkBroker | Không ai (MQL5 SocketTlsHandshake không verify)Nobody (MQL5 SocketTlsHandshake does not verify) | Chỉ để thông tin; vẫn nên đặt đúng hostnameInformational; still set the real hostname |
Tạo lại cert (đổi CN, xoay khoá). Sao lưu thư mục cũ trước:
Regenerate a certificate (CN change, key rotation). Back up the old folder first:
cd ~/goldenrobber/GoldenRobber/monitor/<Broker>
docker compose down
cp -a certs "certs.bak-$(date +%F)"
rm -rf certs/
docker compose up -d # regenerates with the current CERT_HOST
Riêng VpsStreamBroker, sau khi xoay cert: fxconsole tự thấy cert mới qua mount /broker-certs (hoặc chạy lại vps-stream-broker:cert-import), rồi chạy lại prepare-vm.ps1 trên mọi VPS để lấy CA mới và ghi lại stunnel.conf. Nếu CERT_HOST đổi thì sửa luôn VPS_BROKER_HOST, "VpsStreamBroker hostname" trên /admin/settings và bản ghi DNS.
For VpsStreamBroker, after rotating: fxconsole sees the new cert through the /broker-certs mount (or re-run vps-stream-broker:cert-import), then re-run prepare-vm.ps1 on every VPS to fetch the new CA and rewrite stunnel.conf. If CERT_HOST changed, also update VPS_BROKER_HOST, "VpsStreamBroker hostname" on /admin/settings, and the DNS record.
Kiểm tra sau deployVerify after deploy
fxconsole
cd ~/goldenrobber/GoldenRobber/monitor/fxconsole
docker compose ps # app, web, scheduler, redis, timescale, claude-cli, guacd, guacamole: Up
docker compose logs --tail=100 app # migrate --force ran, php-fpm started
docker compose logs --tail=50 scheduler # schedule:work running
curl -I http://127.0.0.1:8080 # nginx answers
docker exec -it fxconsole-redis redis-cli PING # PONG
Mở /admin/settings và xác nhận app_version (2026.09.22.1). /admin/analysis không có banner đỏ = claude-cli đã đăng nhập. timescale có healthcheck pg_isready nên docker compose ps hiện healthy.
Open /admin/settings and confirm app_version (2026.09.22.1). No red banner on /admin/analysis = claude-cli is logged in. timescale has a pg_isready healthcheck, so docker compose ps shows healthy.
Tỷ giá, hệ số chia, EA của tôi (fxconsole ≥ 2026.09.14.2)Exchange rate, money divisor, My EAs (fxconsole ≥ 2026.09.14.2)
cd ~/goldenrobber/GoldenRobber/monitor/fxconsole
docker compose exec app php artisan migrate:status | grep 2026_09_1 # 09_13 000001..000004, 09_14 000001, 09_16 000001: Ran
docker compose exec app php artisan schedule:list | grep fx:sync # every minute
docker compose exec app php artisan fx:sync-usdt-vnd --force # USDT/VND = … (median of 10 SELL ads)
docker compose exec app sh -c 'grep fx.usdt_vnd storage/logs/laravel.log | tail -n 5'
- Migration: container
apptự migrate khi boot. Bốn migration ngày 2026-09-13 tạofx_rates, thêmusers.currency,mt5_accounts.is_cent(sau đó cho phép rỗng bằng->change()) vàbroker_profiles.cent_servers; migration2026_09_14_000001chuyển hai cột này thànhmt5_accounts.money_divisorvàbroker_profiles.server_divisors(Cent →/100, Standard →/1) rồi xoá cột cũ. Migration lỗi thì xem logapp.Migrations: theappcontainer migrates on boot. The four 2026-09-13 migrations createfx_ratesand addusers.currency,mt5_accounts.is_cent(then made nullable with->change()) andbroker_profiles.cent_servers; migration2026_09_14_000001turns those two intomt5_accounts.money_divisorandbroker_profiles.server_divisors(Cent →/100, Standard →/1) and drops the old columns. If one fails, read theapplog. - Tỷ giá: lệnh
--forcein ra giá.failed — HTTP 403/429= Binance chặn IP server. Trên web, nút$cạnh nút ngôn ngữ phải có mục VND bấm được và dòng "1 USDT = … ₫".Rate: the--forcerun prints the rate.failed — HTTP 403/429= Binance is blocking the server IP. On the web, the$button next to the language button must offer a clickable VND option and a "1 USDT = … ₫" line. - Hệ số chia:
/admin/brokers→ sửa broker → chọn/100cạnh các server cent (/10nếu broker báo ×10). Trên/deployments, cột Hệ số của account trên server đó hiện "/100 tự động". Ngoại lệ: chọn dòng → menu Hệ số chia.Money divisor:/admin/brokers→ edit the broker → pick/100next to the cent servers (/10if the broker reports ×10). On/deployments, the Divisor column of accounts on that server shows "/100 auto". Exceptions: select the rows → Money divisor menu. - EA của tôi: đăng nhập bằng user có account đang chạy GoldenRobber →
/easupportedhiện thẻ EA với đủ account. Trống thì mở/admin/easupported/{slug}bằng admin: account không có ở đó = EA chưa heartbeat tới URL này (sửaInpCloudMyApiDomain/ token).My EAs: log in as a user with accounts running GoldenRobber →/easupportedshows the EA card with every account. If empty, open/admin/easupported/{slug}as admin: an account missing there = the EA is not heartbeating to that URL (fixInpCloudMyApiDomain/ token).
Các broker: log khởi động cần thấyBrokers: startup log lines to expect
docker logs --tail=50 fxconsole-tick-broker
docker logs --tail=50 fxconsole-account-status-broker
docker logs --tail=50 fxconsole-vps-stream-broker
docker logs --tail=50 fxconsole-ea-link-broker
| Broker | Dòng log mong đợiExpected log lines |
|---|---|
| Mọi broker (boot đầu / các lần sau)Every broker (first boot / later) | Generating self-signed cert for "fxconsole.gamelau.uk" (10y validity)…Certs already exist at /app/certs — skipping generation. |
| TickBroker | TickBroker pub TCP listening on 0.0.0.0:9600 (TLS)TickBroker WS listening on 0.0.0.0:9601 (wss://) |
| AccountStatusBroker | settings DB: on (<DB_HOST>:<DB_PORT>/<DB_NAME>)AccountStatusBroker pub TCP listening on 0.0.0.0:9602 (TLS)AccountStatusBroker WS listening on 0.0.0.0:9603 (wss://)Subscribed to Redis channel: report:request |
| VpsStreamBroker | VpsStreamBroker listening on 0.0.0.0:9605 (TLS)VpsStreamBroker WS listening on 0.0.0.0:9606 (wss://)Subscribed to laravel-database-vps:cmd (channels=1)khi agent nối:when an agent connects: [vps=42] HELLO ok (agent_v=…) |
| EaLinkBroker | settings DB: on (<DB_HOST>:<DB_PORT>/<DB_NAME>) — broker_internal_secret read from settings tableEaLinkBroker listening on 0.0.0.0:9607 (TLS) hb_timeout=60s prefix="laravel-database-"PSubscribed to *ea:link:cfg (subscriptions=1)khi EA nối:when an EA connects: [ea=goldenrobber/vantage::…/21478308] connected inst=… ea=GoldenRobber ver=… ea_id=… |
settings DB: off (DB_HOST empty) ở EaLinkBroker nghĩa là thiếu DB_*: auth EA Link sẽ gãy sau lần restart Redis kế. FATAL: … is empty nghĩa là thiếu secret bắt buộc. Redis main error: getaddrinfo ENOTFOUND fxconsole-redis nghĩa là fxconsole chưa chạy.
settings DB: off (DB_HOST empty) on EaLinkBroker means DB_* is missing: EA Link auth will break on the next Redis restart. FATAL: … is empty means a required secret is missing. Redis main error: getaddrinfo ENOTFOUND fxconsole-redis means fxconsole is not running.
EaLinkBroker từ đầu tới cuốiEaLinkBroker end to end
# 1. TLS + challenge from outside
openssl s_client -connect fxconsole.gamelau.uk:9607 -quiet
# → {"t":"challenge","v":1,"nonce":"…","server_t":…}
# after 5 s → {"t":"hello_err","reason":"timeout"} and the connection closes
# 2. Full auth + heartbeat with the bundled client (or inside the container:
# docker compose exec ea-link-broker node test-client.js …)
node test-client.js --host fxconsole.gamelau.uk --port 9607 \
--slug goldenrobber --token '<secret>' \
--composite vantage::vantagemarkets-live-3::25938032 --magic 21478308 \
--node ops-test --inst 1
# → hello_ok, then hb_ok every 20 s (--key <64hex> passes sha256(token) directly)
# 3. Fire a signal from another shell
docker exec -it fxconsole-redis redis-cli PUBLISH laravel-database-ea:link:cfg \
'{"slug":"goldenrobber","targets":[{"composite_id":"vantage::vantagemarkets-live-3::25938032","magic":"21478308"}],"rev":1}'
# client prints {"t":"cfg","rev":1} and answers cfg_ack
# broker logs: cfg rev=1 slug=goldenrobber targets=1 delivered=1
# 4. Presence
docker exec -it fxconsole-redis redis-cli HGETALL \
'laravel-database-ea_link:presence:goldenrobber:vantage::vantagemarkets-live-3::25938032:21478308'
VpsStreamBrokerVpsStreamBroker
# heartbeat keys of connected agents (refresh every heartbeat, expire 15 s)
docker exec -it fxconsole-redis redis-cli --scan --pattern 'laravel-database-vps:agent:*'
docker exec -it fxconsole-redis redis-cli GET laravel-database-vps:agent:42:heartbeat
# fake command push (agent 42 connected → "cmd push → vps=42 cmd_id=99999 kind=test")
docker exec -it fxconsole-redis redis-cli \
PUBLISH laravel-database-vps:cmd '{"vps_id":42,"cmd_id":99999,"kind":"test"}'
# live UI path: open /vps as admin in two tabs, Disable a VPS in one,
# the badge must flip in the other within ~100 ms
docker exec -it fxconsole-redis redis-cli SUBSCRIBE laravel-database-vps:state
Phía terminal MT5MT5 terminal side
- Allow WebRequest: Tools → Options → Expert Advisors → Allow WebRequest for listed URL, thêm
https://fxconsole.gamelau.uk(chỉ cần origin; một dòng phủ heartbeat, TMap,/api/account-status,/api/sync-*). Socket tới broker dùng chung danh sách này, nên host củaInpLinkHost/InpBrokerHostcũng phải có. Dùng Cloudflare worker thì thêm domain worker. Thiếu →WebRequesttrả-1.Allow WebRequest: Tools → Options → Expert Advisors → Allow WebRequest for listed URL, addhttps://fxconsole.gamelau.uk(origin only; one line covers the heartbeat, TMap,/api/account-status,/api/sync-*). Broker sockets use the same list, so theInpLinkHost/InpBrokerHosthosts must be there too. Using the Cloudflare worker? Add its domain. Missing →WebRequestreturns-1. - Copy file
.ex5vàoMQL5\Expertscủa terminal (đúng đường dẫn mà chart/profile tham chiếu).Copy the.ex5into the terminal'sMQL5\Experts(the path the chart/profile references). - Gỡ EA khỏi chart rồi gắn lại. F7 (mở hộp thoại input) khi EA đang gắn không nạp binary mới.Remove the EA from the chart, then attach it again. F7 (the inputs dialog) on an attached EA does not load the new binary.
- Nếu MT5 hiện hộp thoại "Welcome to LiveUpdate": chọn Later. Restart sẽ tắt mọi EA đang chạy.If MT5 shows the "Welcome to LiveUpdate" dialog: choose Later. Restart kills every running EA.
- Nạp
.set(bản chia sẻ trongREADME/configs/có token trống), gõInpCloudBearerTokenngay trên terminal, kiểm tra lại tab Inputs sau khi nạp (input thiếu trong.setcũ giữ giá trị cũ).Load the.set(the shareable copy inREADME/configs/has a blank token), typeInpCloudBearerTokenon the terminal itself, and re-check the Inputs tab afterwards (inputs missing from an older.setkeep stale values). - Kiểm tra panel: tiêu đề có build (vd
GoldenRobber v1.42 (b3), tên file không cho biết build),Server: CONNECTED (Ns ago),Link: UP fxconsole.gamelau.uk:9607 (Ns)(1.42+), dòngNode: … | LEADER.Check the panel: the title shows the build (e.g.GoldenRobber v1.42 (b3); the filename does not tell you the build),Server: CONNECTED (Ns ago),Link: UP fxconsole.gamelau.uk:9607 (Ns)(1.42+), theNode: … | LEADERline.
| EA | Input liên quan hạ tầngInfrastructure inputs |
|---|---|
| GoldenRobber 1.42 b3 | InpCloudSyncEnable=true, InpCloudMyApiDomain=https://fxconsole.gamelau.uk/easupported/goldenrobber, InpCloudBearerToken (gõ taytyped by hand), InpCloudSyncIntervalSec=10, InpCloudNodePriority=100, InpCloudHeartbeatTimeoutSec=90, InpCloudCfDomain= (trốngempty), InpLinkMode=1, InpLinkHost=fxconsole.gamelau.uk, InpLinkPort=9607 |
| AccountStatusUpdater 1.16 | InpApiUrl (mặc định trong code là http://127.0.0.1:8080/api/account-status, production dùng URL https công khaicode default is http://127.0.0.1:8080/api/account-status; production uses the public https URL), InpApiBearer, InpAccountSecretKey, InpTransport, InpBrokerHost, InpBrokerPort=9602, InpBrokerSecret, InpHybridHttpIntervalSec=30 |
| TickStreamerPub 1.04 | InpBrokerHost, InpBrokerPort=9600, InpSharedSecret, InpFxconsoleUrl, InpFxconsoleBearer, InpCalendarIntervalMinutes=15 |
Checklist rollout GoldenRobber 1.42GoldenRobber 1.42 rollout checklist
Checklist viết cho lần rollout 1.42 b3 (EA Link, commit ff0e30e). Production hiện là 1.42 b7 (commit 663082f, từ 29/09/2026); các bước vẫn dùng khi nâng build 1.42, với config v1.42.b7-pass58.set. Chi tiết thay đổi: Release note 1.42 b7 · Build & release.
Written for the 1.42 b3 rollout (EA Link, commit ff0e30e). Production is now 1.42 b7 (commit 663082f, since 29/09/2026); the steps still apply when upgrading a 1.42 build, with the v1.42.b7-pass58.set config. Change details: Release note 1.42 b7 · Builds & releases.
ServerServer
bash deploy.sh(fxconsole ≥2026.09.12.3: endpoint/api/internal/ea-link/key, notify sau Apply/Clear, badge Link, broker đọc secret từ DB).bash deploy.sh(fxconsole ≥2026.09.12.3: the/api/internal/ea-link/keyendpoint, notify after Apply/Clear, Link badge, brokers read secrets from the DB).monitor/EaLinkBroker/.envcóDB_*; log cósettings DB: onvàPSubscribed to *ea:link:cfg.monitor/EaLinkBroker/.envhasDB_*; the log showssettings DB: onandPSubscribed to *ea:link:cfg./admin/settings→ EALinkBroker Secret Key đã có giá trị./admin/settings→ EALinkBroker Secret Key is set.- Cổng 9607 mở trên OVH + IPFire;
openssl s_client -connect fxconsole.gamelau.uk:9607 -quiettrảchallenge.Port 9607 open on OVH + IPFire;openssl s_client -connect fxconsole.gamelau.uk:9607 -quietreturns achallenge.
Terminal demoDemo terminal
- Copy
GoldenRobber-1.42.ex5; Allow WebRequest cóhttps://fxconsole.gamelau.uk.CopyGoldenRobber-1.42.ex5; Allow WebRequest containshttps://fxconsole.gamelau.uk. - Nạp
v1.42.b7-pass58.set, gõ token, gỡ EA rồi gắn lại, LiveUpdate → Later.Loadv1.42.b7-pass58.set, type the token, remove and re-attach the EA, LiveUpdate → Later. - Panel:
GoldenRobber v1.42 (b7),Server: CONNECTED,Link: UP …. Trên/admin/easupported/goldenrobber: account Online, badge Link.Panel:GoldenRobber v1.42 (b7),Server: CONNECTED,Link: UP …. On/admin/easupported/goldenrobber: account Online, Link badge. - Apply một hot config vô hại cho account demo → log Experts có
[EaLink] cfg rev=… đã áp trong N ms, broker logcfg rev=… delivered=1, dòng Hot Reload trên panel đổi trong ≈ 1 s. Rồi Clear config và kiểm tra EA về giá trị input.Apply a harmless hot config to the demo account → the Experts log shows[EaLink] cfg rev=… đã áp trong N ms, the broker logscfg rev=… delivered=1, the panel's Hot Reload line changes within ≈ 1 s. Then Clear config and check the EA reverts to its inputs. - Thử mất Link:
docker compose stop ea-link-broker→ panelLink: DOWN, retry Ns, EA vẫn nhận config qua heartbeat;docker compose start ea-link-broker→ Link UP lại.Test losing the link:docker compose stop ea-link-broker→ panelLink: DOWN, retry Ns, the EA still gets config via heartbeat;docker compose start ea-link-broker→ Link UP again.
Đóng mọi position của EA trên chart (symbol + magic, gồm lệnh Hedge), không hoàn tác được, chỉ node LEADER thực hiện, sau đó EA đứng yên như Pause tới khi đổi về OFF. Build khác cùng slug (b21, b21.1, b28) không hiểu giá trị 5 và giữ giá trị cũ. Khi nhiều build cùng chạy slug goldenrobber, schema trên web đổi qua lại theo account gửi heartbeat gần nhất. Không thử Close all trên tài khoản thật.
Closes every EA position on the chart (symbol + magic, Hedge orders included), cannot be undone, runs only on the LEADER node, then the EA stays idle like Pause until switched back to OFF. Other builds on the same slug (b21, b21.1, b28) do not understand value 5 and keep their previous value. With several builds on slug goldenrobber, the web schema flips according to whichever account sent the latest heartbeat. Do not test Close all on a live account.
vps-agent và gói MT5vps-agent and MT5 packages
Tóm tắt; từng bước chi tiết ở VPS agent.
Summary; step-by-step detail on VPS agent.
VPS mớiNew VPS
- Server sẵn sàng: VpsStreamBroker chạy, cổng 9605 mở, CA sẵn cho
/api/agent/broker-config, "VpsStreamBroker hostname / port" đã điền,VPS_INIT_BOOTSTRAP_TOKENđã đặt (nếu provisioning tự động).Server ready: VpsStreamBroker running, port 9605 open, CA available to/api/agent/broker-config, "VpsStreamBroker hostname / port" filled,VPS_INIT_BOOTSTRAP_TOKENset (for zero-touch provisioning). - Compile
HeartbeatAgent.au3,CmdAgent.au3(AutoIt 3.3.16+, chế độ GUI, thư mụclib/cạnh source), copy vàoC:\VpsAgent\cùngvps-agent.ini(copy từ/vps) hoặcvps-agent.ini.init-template,bootstrap-fresh-vm.ps1,prepare-vm.ps1. Hoặc dùng góivps-agent-setup-1.3.2-phase9.zip.CompileHeartbeatAgent.au3,CmdAgent.au3(AutoIt 3.3.16+, GUI mode,lib/next to the sources), copy intoC:\VpsAgent\withvps-agent.ini(copied from/vps) orvps-agent.ini.init-template,bootstrap-fresh-vm.ps1,prepare-vm.ps1. Or use thevps-agent-setup-1.3.2-phase9.zippackage. - Màn hình VM: độ phân giải 1600×900, scale 100% (mặc định của Windows), đặt ở Settings › System › Display trước khi snapshot để mọi VM clone ra giống nhau. Không đổi scale: CmdAgent điền danh sách WebRequest trong Options của MT5 bằng cách click theo toạ độ pixel cố định (mỗi dòng 18 px, tính ở scale 100%).VM display: 1600×900 resolution, 100% scale (the Windows default), set in Settings › System › Display before the snapshot so every cloned VM matches. Do not change the scale: CmdAgent fills the WebRequest list in MT5's Options by clicking fixed pixel offsets (18 px rows, measured at 100% scale).
- Windows mới cài, một lần mỗi OS image:
powershell -ExecutionPolicy Bypass -File .\bootstrap-fresh-vm.ps1(Administrator), rồi snapshot VM.Fresh Windows, once per OS image:powershell -ExecutionPolicy Bypass -File .\bootstrap-fresh-vm.ps1(Administrator), then snapshot the VM. .\prepare-vm.ps1(Administrator): chuẩn bị AutoLogon, gỡ MOTW, shortcut Startup cho HeartbeatAgent, cài stunnel + cấu hình từ/api/agent/broker-config, cài dịch vụ TightVNC. Vớiinit = pending: gửi MAC tới/api/agent/init-config, ghi lại ini, đổi tên máy, reboot..\prepare-vm.ps1(Administrator): AutoLogon prep, MOTW strip, Startup shortcut for HeartbeatAgent, stunnel install + config from/api/agent/broker-config, TightVNC service install. Withinit = pending: posts the MAC to/api/agent/init-config, rewrites the ini, renames the computer, reboots.- Reboot, rồi kiểm tra:
tasklist | findstr /I "HeartbeatAgent CmdAgent stunnel";heartbeat-agent.logcóBROKER: HELLO ok — stream healthyvàHB via broker stream …; broker log[vps=N] HELLO ok.Reboot, then check:tasklist | findstr /I "HeartbeatAgent CmdAgent stunnel";heartbeat-agent.logshowsBROKER: HELLO ok — stream healthyandHB via broker stream …; the broker logs[vps=N] HELLO ok.
Nâng cấp agentAgent upgrade
Upload zip release trên /admin/agent-releases (vd vps-agent-upgrade-1.3.2-phase9.zip) → gửi lệnh Upgrade tới VPS → CmdAgent chạy upgrade.ps1: tải /api/agent/release/{id}/download với X-Vps-Secret, so SHA-256, dừng agent, giải nén đè C:\VpsAgent, reboot để AutoLogon khởi động bản mới. upgrade.ps1 không nằm trong zip (không tự ghi đè được); muốn cập nhật chính nó thì chạy lại prepare-vm.ps1.
Upload the release zip on /admin/agent-releases (e.g. vps-agent-upgrade-1.3.2-phase9.zip) → send an Upgrade command to the VPS → CmdAgent runs upgrade.ps1: downloads /api/agent/release/{id}/download with X-Vps-Secret, checks SHA-256, stops the agents, extracts over C:\VpsAgent, reboots so AutoLogon starts the new binaries. upgrade.ps1 is not inside the zip (it cannot overwrite itself); to update it, re-run prepare-vm.ps1.
Gói tài khoản MT5MT5 account packages
/admin/brokers: raw name phải khớp đúngACCOUNT_COMPANY; gói và VPS đều gắn một broker, chỉ ghép được khi cùng broker./admin/brokers: the raw name must matchACCOUNT_COMPANYexactly; packages and VPSes are each tied to a broker and can only be paired when they match.- Chuẩn bị ZIP: thư mục MT5 portable có EA + profile chart; input khác nhau theo user để trong
.setdướiMQL5/Presets/với giá trị giữ chỗ. Tính SHA-256 (certutil -hashfile package.zip SHA256). Tên gói trong repo có dạngGoldenRobber-Pass58_v1-42-b3-Vantage-build-6182.zip.Prepare the ZIP: a portable MT5 folder with the EA + chart profile; per-user inputs go in a.setunderMQL5/Presets/with a placeholder value. Compute SHA-256 (certutil -hashfile package.zip SHA256). Package names in the repo look likeGoldenRobber-Pass58_v1-42-b3-Vantage-build-6182.zip. /admin/packages: URL ZIP (hoặc upload qua/admin/packages/upload, nginx cho phép tới 1024 MB, 600 s), version, profile, MT5 build (tuỳ chọn), SHA-256, danh sách URL Allow WebRequest, value injection (vdMQL5/Presets/AccountStatusUpdater.set·InpAccountSecretKey·user.mt5_secret_key)./admin/packages: ZIP URL (or upload via/admin/packages/upload, nginx allows up to 1024 MB, 600 s), version, profile, MT5 build (optional), SHA-256, Allow WebRequest URL list, value injections (e.g.MQL5/Presets/AccountStatusUpdater.set·InpAccountSecretKey·user.mt5_secret_key).- User deploy ở
/deployments/new; theo dõi ở/vps/{id}và/deployments. Account đã deploy không tự nâng cấp khi gói đổi; có routebulk-upgradetheo gói.Users deploy on/deployments/new; watch/vps/{id}and/deployments. Deployed accounts do not auto-upgrade when a package changes; there is a per-packagebulk-upgraderoute.
chart01.chr trong gói hiện có trỏ tới Experts\GoldenRobber-1.41.4.ex5. Đổi tên GoldenRobber-1.41.4-b21.1.ex5 thành GoldenRobber-1.41.4.ex5 khi cho vào zip (hoặc sửa name=/path= trong .chr), rồi kiểm tra panel có (b21.1).
The existing package's chart01.chr points at Experts\GoldenRobber-1.41.4.ex5. Rename GoldenRobber-1.41.4-b21.1.ex5 to GoldenRobber-1.41.4.ex5 inside the zip (or edit name=/path= in the .chr), then check the panel shows (b21.1).
MySQL trên aaPanelMySQL on aaPanel
- Database
trade_copiernằm trên host aaPanel từ xa, được dùng bởifxconsole-app,fxconsole-schedulervà ba broker (AccountStatusBroker, VpsStreamBroker, EaLinkBroker;deploy.shcopy cùng user DB của fxconsole). User này cần đọcsettings,vpsesvà ghivps_commands,vpses. - Sự cố binlog đầy disk: EA đẩy lại toàn bộ ticket map mỗi 5–10 s và controller cũ xoá-hết rồi insert-hết, tạo ~10 lượt ghi/giây (~873k/ngày) và ~3 GB binlog/ngày trên một DB chỉ 179 MB, cuối cùng làm đầy disk MySQL. Hai biện pháp:
binlog_expire_logs_secondsđã được hạ xuống, và fxconsole2026.09.04.1(commit020339f) bỏ ghi lạitmap_entrieskhi map không đổi (dấu vân tay sha1 trong Redis, kỳ vọng giảm 95–99% lượt ghi; EA không cần đổi). - Theo dõi định kỳ dung lượng binlog và disk của host aaPanel. Đổi cấu hình MySQL qua aaPanel (
my.cnf) để giữ sau restart.
- The
trade_copierdatabase lives on the remote aaPanel host and is used byfxconsole-app,fxconsole-schedulerand three brokers (AccountStatusBroker, VpsStreamBroker, EaLinkBroker;deploy.shcopies fxconsole's DB user). That user needs to readsettings,vpsesand writevps_commands,vpses. - Binlog filled the disk: the EA re-pushed the whole ticket map every 5–10 s and the old controller deleted everything and re-inserted it, producing ~10 writes/s (~873k/day) and ~3 GB of binlog/day on a database of only 179 MB, which eventually filled the MySQL disk. Two remedies:
binlog_expire_logs_secondswas lowered, and fxconsole2026.09.04.1(commit020339f) stopped rewritingtmap_entrieswhen the map is unchanged (sha1 fingerprint in Redis, expected 95–99% fewer writes; no EA change needed). - Watch binlog size and disk usage on the aaPanel host regularly. Change MySQL config through aaPanel (
my.cnf) so it survives restarts.
-- current retention and binlog files
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';
SHOW BINARY LOGS;
-- emergency cleanup (check replicas first if any)
PURGE BINARY LOGS BEFORE NOW() - INTERVAL 1 DAY;
VPN WireGuard (CT 107)WireGuard VPN (CT 107)
wg-easy chạy bằng Docker trong container Proxmox CT 107, 3 NIC (vmbr101 / vmbr102 / vmbr103), MASQUERADE cho dải client 10.8.2.0/24.
wg-easy runs in Docker inside Proxmox container CT 107, with 3 NICs (vmbr101 / vmbr102 / vmbr103) and MASQUERADE for the client range 10.8.2.0/24.
Restart Docker trong CT 107 (docker restart wg-easy hoặc docker compose restart ở thư mục của wg-easy). Nếu không, peer mới không được nạp vào wg0 và client không bao giờ handshake dù cấu hình đúng. Client mới không kết nối được: kiểm tra việc này trước khi soi firewall/NAT.
Restart Docker inside CT 107 (docker restart wg-easy or docker compose restart in wg-easy's folder). Otherwise the new peer is never loaded into wg0 and the client never handshakes even with a correct config. New client cannot connect: check this before digging into firewall/NAT.
Rollback theo thành phầnRollback per component
| Thành phầnComponent | Cách rollbackHow to roll back | Lưu ýNotes |
|---|---|---|
| fxconsole | Revert commit lỗi trên main (git revert <commit> ở máy dev, push), rồi bash deploy.sh. Không checkout commit cũ trên server: deploy.sh luôn quay về main.Revert the bad commit on main (git revert <commit> on a dev machine, push), then bash deploy.sh. Do not check out an old commit on the server: deploy.sh always returns to main. | Migration đã chạy không tự lùi; chỉ php artisan migrate:rollback khi chắc chắn. Không đụng APP_KEY, không down -v.Migrations already applied do not roll back by themselves; only run php artisan migrate:rollback when sure. Never touch APP_KEY, never down -v. |
| EaLinkBroker | Revert + deploy, hoặc tạm docker compose downRevert + deploy, or temporarily docker compose down | EA hiện Link: DOWN và vẫn nhận config qua heartbeat HTTP. Không mất gì.EAs show Link: DOWN and still get config over the HTTP heartbeat. Nothing is lost. |
| VpsStreamBroker | Revert + deploy, hoặc docker compose downRevert + deploy, or docker compose down | Agent rơi về HTTPS polling (heartbeat, lệnh, ACK); lệnh trong vps_commands không bị ảnh hưởng.Agents fall back to HTTPS polling (heartbeats, commands, ACKs); commands in vps_commands are unaffected. |
| AccountStatusBroker | Revert + deployRevert + deploy | EA ở HTTP / HYBRID vẫn đẩy qua HTTP; EA chỉ TCP mất dữ liệu sống; dashboard chuyển sang polling.EAs in HTTP / HYBRID keep posting over HTTP; TCP-only EAs lose live data; the dashboard falls back to polling. |
| TickBroker | Revert + deployRevert + deploy | Charts mất tick sống; nến lịch sử trong TimescaleDB vẫn còn.Charts lose live ticks; historical bars in TimescaleDB remain. |
| Cert brokerBroker cert | Dừng broker, chép lại certs.bak-<ngày> thành certs, bật lạiStop the broker, copy certs.bak-<date> back to certs, start again | VpsStreamBroker: chạy lại prepare-vm.ps1 trên VPS nếu CA đã được phát.VpsStreamBroker: re-run prepare-vm.ps1 on VPSes if the new CA was already distributed. |
| GoldenRobber EA | Lấy lại bản cũ b21 (Git Bash hoặc cmd, không dùng > của PowerShell vì hỏng file nhị phân):Recover the previous build b21 (Git Bash or cmd, not PowerShell's >, which corrupts binaries):git cat-file -p 71dac5f:GoldenRobber-1.41.4.ex5 > GoldenRobber-1.41.4-b21.ex5 | Gỡ EA rồi gắn lại, kiểm tra tiêu đề (b21). Clear override không hiểu được (vd manual_init = 5) trên web. Nạp lại .set của b21 (v1.41.4-pass58-easupported-goldenrobber-29082026.set).Remove and re-attach the EA, check the title shows (b21). Clear overrides it cannot understand (e.g. manual_init = 5) on the web. Reload the b21 .set (v1.41.4-pass58-easupported-goldenrobber-29082026.set). |
| vps-agent | Upload lại zip bản trước (vd vps-agent-upgrade-1.3.1-phase8.zip) trên /admin/agent-releases và gửi Upgrade, hoặc chép binary cũ rồi chạy lại prepare-vm.ps1Re-upload the previous zip (e.g. vps-agent-upgrade-1.3.1-phase8.zip) on /admin/agent-releases and send Upgrade, or copy the old binaries and re-run prepare-vm.ps1 | Tính năng Phase 8 cần agent ≥ 1.3.0-phase4k.Phase 8 features need agent ≥ 1.3.0-phase4k. |
| claude-cli | docker compose build --build-arg CLAUDE_CODE_VERSION=<x.y.z> claude-cli | Khôi phục credential từ bản sao lưu nếu volume mất: docker compose exec -T claude-cli sh -c 'tar xzf - -C /home/node' < claude-creds-backup.tgzRestore credentials from the backup if the volume is lost: docker compose exec -T claude-cli sh -c 'tar xzf - -C /home/node' < claude-creds-backup.tgz |
Xử lý sự cốTroubleshooting
| Triệu chứngSymptom | Nguyên nhânCause | Cách sửaFix |
|---|---|---|
EaLinkBroker logEaLinkBroker log no broker internal secret (DB settings + Redis mirror + env all empty) / [ealink] key lookup slug=… failed | Không tìm được broker_internal_secret: thiếu hoặc sai DB_*, mirror Redis trống (Redis vừa restart), env trốngNo broker_internal_secret found: DB_* missing or wrong, Redis mirror empty (Redis just restarted), env empty | Điền DB_* trong monitor/EaLinkBroker/.env (deploy.sh tự điền), kiểm tra log settings DB: on, đặt "EALinkBroker Secret Key" trên /admin/settings, docker compose up -dFill DB_* in monitor/EaLinkBroker/.env (deploy.sh fills it), check the settings DB: on log line, set "EALinkBroker Secret Key" on /admin/settings, docker compose up -d |
Mọi EA nhậnAll EAs get hello_err auth_unavailable | Laravel không tới được / trả mã khác 200-404 / thiếu secret; BROKER_INTERNAL_URL sai; fxconsole-web chếtLaravel unreachable / non-200/404 / no secret; wrong BROKER_INTERNAL_URL; fxconsole-web down | BROKER_INTERNAL_URL=http://fxconsole-web; sửa secret như dòng trên. EA tự thử lại với backoff.BROKER_INTERNAL_URL=http://fxconsole-web; fix the secret as above. EAs retry with backoff. |
hello_err bad_sig (một EA)(one EA) | Token trên terminal cũ/sai (vd sau Regenerate)Stale/wrong token on that terminal (e.g. after Regenerate) | Gõ lại InpCloudBearerToken. EA chờ 5 phút sau bad_sig; broker cache key 60 s.Retype InpCloudBearerToken. The EA waits 5 minutes after bad_sig; the broker caches keys for 60 s. |
hello_err unknown_ea | Slug chưa đăng ký / product bị tắt / gõ sai slug trong InpCloudMyApiDomainSlug not registered / product disabled / slug typo in InpCloudMyApiDomain | Kiểm tra /admin/easupported và URL …/easupported/{slug}Check /admin/easupported and the …/easupported/{slug} URL |
PanelPanel Link: DOWN, retry Ns | Broker không chạy, 9607 chưa forward, host không có trong Allow WebRequest, InpLinkHost saiBroker not running, 9607 not forwarded, host missing from Allow WebRequest, wrong InpLinkHost | docker logs fxconsole-ea-link-broker; openssl s_client -connect fxconsole.gamelau.uk:9607 -quiet; kiểm tra OVH + IPFire. EA vẫn chạy HTTP.check OVH + IPFire. The EA keeps working over HTTP. |
PanelPanel Link: OFF (missing slug/token) | InpCloudMyApiDomain không có dạng …/easupported/{slug} hoặc token trốngInpCloudMyApiDomain is not …/easupported/{slug} or the token is empty | Sửa inputFix the inputs |
cfg … delivered=0 khi EA đang onlinewhile the EA is online | slug / composite_id / magic Laravel publish không khớp HELLO của EAThe slug / composite_id / magic Laravel publishes differ from the EA's HELLO | So với presence hash; EA vẫn nhận config ở heartbeat kếCompare with the presence hash; the EA still gets config on its next heartbeat |
Redis main error: getaddrinfo ENOTFOUND fxconsole-redis | Broker không ở mạng fxconsole_default (fxconsole chưa chạy)Broker not on fxconsole_default (fxconsole not running) | Bật fxconsole trước, rồi docker compose up -d ở brokerStart fxconsole first, then docker compose up -d in the broker folder |
Heartbeat EA trảEA heartbeat returns 401 · panelpanel Server: NO SYNC | InpCloudBearerToken ≠ easupported.secret_token (URL cũ /api/tmap thì so với TMAP_SECRET_KEY). 404 Unknown EA = slug sai.InpCloudBearerToken ≠ easupported.secret_token (the legacy /api/tmap URL compares with TMAP_SECRET_KEY). 404 Unknown EA = wrong slug. | Copy lại token từ /admin/easupported, gõ trên terminalCopy the token again from /admin/easupported, type it on the terminal |
WebRequest trảreturns -1 | URL chưa có trong Allow WebRequest, hoặc lỗi mạng. 4014 = chứng chỉ không hợp lệ (tự ký)URL not in Allow WebRequest, or a network error. 4014 = invalid (self-signed) certificate | Thêm https://fxconsole.gamelau.uk vào Allow WebRequestAdd https://fxconsole.gamelau.uk to Allow WebRequest |
AccountStatusUpdater 401 Unauthorized bearer token | InpApiBearer ≠ ea_api_bearer / EA_API_BEARER | Đồng bộ bearerAlign the bearer |
AccountStatusUpdater broker HELLO rejected | InpBrokerSecret ≠ BROKER_SECRET, hoặc EA/broker lệch phiên bản HELLO v2InpBrokerSecret ≠ BROKER_SECRET, or an EA/broker HELLO v2 version mismatch | Đồng bộ secret; nâng EA và broker cùng lúcAlign the secret; upgrade EA and broker together |
FATAL: TICK_BROKER_SECRET is empty / FATAL: BROKER_SECRET is empty | .env mới tạo còn trốngFreshly created .env still blank | Điền secret, docker compose up -dFill the secret, docker compose up -d |
FATAL: certs/server.{key,cert} missing | Thư mục certs/ không ghi được, openssl lỗi lúc boot đầucerts/ not writable, openssl failed on first boot | Sửa quyền thư mục, xem log openssl, khởi động lạiFix folder permissions, read the openssl log, restart |
AgentAgent BROKER: HELLO rejected reason=bad_secret | vpses.secret_key ≠ secret_key trongin vps-agent.ini | Copy lại block ini từ /vps/{id} → Reveal SecretRe-copy the ini block from /vps/{id} → Reveal Secret |
| Cổng 9605 local mở nhưng remote bị từ chối / TLS handshake lỗiLocal 9605 open but remote refused / TLS handshake fails | Firewall; hoặc CN không khớp giữa CERT_HOST và vps_broker_hostFirewall; or CN mismatch between CERT_HOST and vps_broker_host | Mở 9605 trên OVH + IPFire; tạo lại cert đúng CN rồi chạy lại prepare-vm.ps1Open 9605 on OVH + IPFire; regenerate the cert with the right CN, re-run prepare-vm.ps1 |
prepare-vm.ps1: broker-config fetch failed | fxconsole chưa có CA của brokerfxconsole does not have the broker CA yet | Kiểm tra mount /broker-certs hoặc chạy vps-stream-broker:cert-importCheck the /broker-certs mount or run vps-stream-broker:cert-import |
Deploy tài khoản kẹt ở pendingAccount deploy stuck at pending | Callback /api/internal/broker/command-ack lỗi (BROKER_INTERNAL_URL / secret sai), hoặc agent không nhận lệnhThe /api/internal/broker/command-ack callback fails (wrong BROKER_INTERNAL_URL / secret), or the agent never got the command | Xem log VpsStreamBroker và cmd-agent.log; sửa URL/secretRead the VpsStreamBroker log and cmd-agent.log; fix URL/secret |
git pull: "local changes would be overwritten" | File đã track bị sửa tay, hoặc file chưa track trùng tên với file mớiHand-edited tracked file, or an untracked file collides with a new one | deploy.sh đã git restore .; file chưa track thì dời đi rồi chạy lạideploy.sh already runs git restore .; move untracked files away and rerun |
| Cột mã hoá không giải mã được sau deployEncrypted columns undecryptable after a deploy | APP_KEY đã bị đổiAPP_KEY was changed | Khôi phục APP_KEY cũ từ bản sao lưu .envRestore the old APP_KEY from the .env backup |
| Task scheduler không chạy lạiScheduled task never runs again | Khoá withoutOverlapping() kẹt sau crashA withoutOverlapping() lock stuck after a crash | docker compose restart scheduler (chạy schedule:clear-cache khi khởi động)(runs schedule:clear-cache on start) |
| Banner đỏRed banner "CLI cần đăng nhập lại" | Refresh token OAuth hết hạn hoặc volume mấtOAuth refresh token expired or volume lost | Re-login trên /admin/analysis hoặc docker compose exec -it claude-cli claude loginRe-login on /admin/analysis or docker compose exec -it claude-cli claude login |
| Guacamole: "Guacamole is not configured"Guacamole: "Guacamole is not configured" | Thiếu GUAC_JSON_SECRET_KEY hoặc GUAC_PUBLIC_URLMissing GUAC_JSON_SECRET_KEY or GUAC_PUBLIC_URL | Điền cả hai (DB hoặc .env), cùng khoá với container guacamoleSet both (DB or .env), same key as the guacamole container |
EA vẫn là bản cũ sau khi copy .ex5EA still the old build after copying the .ex5 | Dùng F7 thay vì gắn lạiUsed F7 instead of re-attaching | Gỡ EA rồi gắn lại, xem build trên tiêu đề panelRemove and re-attach, check the build in the panel title |
| Disk MySQL đầyMySQL disk full | Binlog tăng nhanhFast-growing binlog | Xem MySQL trên aaPanel; đảm bảo fxconsole ≥ 2026.09.04.1See MySQL on aaPanel; make sure fxconsole ≥ 2026.09.04.1 |
| Client WireGuard mới không handshakeNew WireGuard client never handshakes | Chưa restart Docker trong CT 107Docker in CT 107 not restarted | docker restart wg-easy |
/easupported trống dù account đang chạy EA/easupported empty although accounts run the EA | fxconsole < 2026.09.14.1 (GoldenRobber gửi server = tên broker, composite_id chưa đồng bộ), hoặc EA không heartbeat tới /easupported/{slug}fxconsole < 2026.09.14.1 (GoldenRobber sends server = broker name, composite_id not synced), or the EA does not heartbeat to /easupported/{slug} | Nâng fxconsole; xem account có ở /admin/easupported/{slug} không, không có thì sửa InpCloudMyApiDomain / tokenUpgrade fxconsole; check the account is listed on /admin/easupported/{slug}, otherwise fix InpCloudMyApiDomain / token |
| Menu tiền tệ báo "Chưa có tỷ giá", mục VND bị khoáCurrency menu says "No USDT/VND rate yet", VND disabled | fx_rates chưa có dòng: scheduler chưa chạy lệnh, hoặc Binance trả lỗi (log fx.usdt_vnd.failed)fx_rates is empty: the scheduler hasn't run the command, or Binance returns errors (log fx.usdt_vnd.failed) | php artisan fx:sync-usdt-vnd --force; docker compose restart schedulerphp artisan fx:sync-usdt-vnd --force; docker compose restart scheduler |
| Menu báo tỷ giá đã cũMenu says the rate is out of date | Các lần fetch gần đây đều lỗi, web giữ giá cũ. HTTP 403 / 418 / 429 = IP server bị chặn (tự dừng 15 phút)Recent fetches all failed, the web keeps the last rate. HTTP 403 / 418 / 429 = server IP blocked (backs off 15 minutes) | Xem log fx.usdt_vnd.failed; tăng usdt_vnd_interval_minutes trên /admin/settingsRead the fx.usdt_vnd.failed log; raise usdt_vnd_interval_minutes on /admin/settings |
| Số tiền một account lớn gấp 10 hoặc 100 lầnOne account's money is 10× or 100× too large | Account báo ×10 / ×100 (vd. cent) nhưng đang ở /1The account reports ×10 / ×100 (e.g. cent) but is at /1 | Chọn /10 hoặc /100 cho server ở /admin/brokers, hoặc chọn dòng → menu Hệ số chiaPick /10 or /100 for the server on /admin/brokers, or select the row → Money divisor menu |
| Account bị chia sai (số tiền quá nhỏ)An account is divided when it shouldn't be (money too small) | Server của account có hệ số /10 / /100, hoặc account bị đặt tayThe account's server has a /10 / /100 divisor, or the account was set by hand | Menu Hệ số chia → /1 (thắng hệ số server), hoặc đưa server về /1 nếu cả server là standardMoney divisor menu → /1 (overrides the server), or set the server back to /1 if the whole server is standard |
Đọc tiếpRead next
- Kiến trúc hệ thống: cổng, luồng, Redis, secret.
- Các broker realtime, fxconsole, VPS agent, claude-cli, Guacamole.
- Build & release, Release note 1.42 b2, Config ổn định.
- System architecture: ports, flows, Redis, secrets.
- Realtime brokers, fxconsole, VPS agent, claude-cli, Guacamole.
- Builds & releases, Release note 1.42 b2, Stable config.