Tencent Lighthouse Hong Kong Phone Setup

This runbook sets up a Tencent Cloud Lighthouse instance in Hong Kong as an always-on codewhale host controlled from Feishu/Lark on a phone.

If you are teaching this as the Tencent-native default path, start with docs/TENCENT_CLOUD_REMOTE_FIRST.md. This file is the implementation runbook for the Lighthouse host itself.

Target Architecture

CNB mirror or GitHub branch
  -> /opt/whalebro/codewhale

Feishu/Lark mobile app
  -> Feishu/Lark long-connection bot
  -> codewhale-feishu-bridge systemd service
  -> http://127.0.0.1:7878 codewhale serve --http
  -> /opt/whalebro
       -> codewhale/

Optional public edge:
EdgeOne -> Caddy/Nginx public site on Lighthouse

The runtime API must stay on 127.0.0.1. The bridge is the only phone-facing control surface. EdgeOne is optional and should only front a deliberate public HTTP service, not the runtime API.

Remote Whalebro Workspace

Use /opt/whalebro as the VPS workspace root. The first-class checkout is /opt/whalebro/codewhale.

Create these paths first:

  • /opt/whalebro/codewhale
  • /opt/whalebro/worktrees

Linux is enough for Rust, Node, and service work. Mac-only release work such as iOS simulator runs, .app/DMG checks, notarization, and Apple signing still belongs on the Mac.

Lighthouse Instance

Recommended package for travel:

  • Region: Hong Kong (China)
  • Image: plain Ubuntu 24.04 LTS or latest Ubuntu LTS
  • Size: buy the HK 2 vCPU / 4 GB / 70 GB plan for the first month
  • Login: SSH key, not password
  • Firewall: SSH open; runtime API on localhost only

Tencent's Lighthouse docs say Linux instances can use SSH keys, and the Lighthouse firewall opens SSH/HTTP/HTTPS by default.

Use 4 GB RAM for compiling Rust and running the bridge comfortably. A 4 vCPU / 8 GB plan is better for multiple parallel agent workers.

Feishu / Lark App

Create an enterprise self-built app in:

  • Feishu China: https://open.feishu.cn/app
  • Lark international: https://open.larksuite.com/app

Configure:

  1. Enable bot capability.
  2. Copy App ID and App Secret.
  3. Add permissions for message send/receive. The minimum practical set is:
    • im:message
    • im:message:send_as_bot
    • direct message read permission for your tenant
    • group @message read permission only if you intentionally enable group control later
  4. Add event subscription im.message.receive_v1.
  5. Use long connection / WebSocket mode.
  6. Publish the app and add the bot to your Feishu/Lark chat.

Server Bootstrap

SSH into the Lighthouse instance and run:

sudo apt-get update
sudo apt-get install -y git
export DEEPSEEK_BRANCH=main
export DEEPSEEK_REPO_URL=https://cnb.cool/codewhale.net/codewhale.git
git clone --branch "$DEEPSEEK_BRANCH" "$DEEPSEEK_REPO_URL" /tmp/codewhale
cd /tmp/codewhale
sudo DEEPSEEK_REPO_URL="$DEEPSEEK_REPO_URL" \
  DEEPSEEK_REPO_BRANCH="$DEEPSEEK_BRANCH" \
  bash scripts/tencent-lighthouse/bootstrap-ubuntu.sh

Use an SSH repo URL instead if you want push access from the VPS. If the CNB mirror is unavailable, fall back to:

export DEEPSEEK_REPO_URL=https://github.com/Hmbown/CodeWhale.git

For stable release docs, confirm the CNB mirror has the branch or tag before using it:

export DEEPSEEK_REPO_URL=https://cnb.cool/codewhale.net/codewhale.git
git ls-remote "$DEEPSEEK_REPO_URL" \
  refs/heads/main \
  refs/tags/v0.8.37

The CNB mirror receives main and release tags. CNB is the default source for this Lighthouse path; GitHub is the fallback only when the CNB workflow or credentials are unhealthy.

If this deployment setup has not been pushed to Git yet, either push the branch first or copy this checkout to the VPS before running these commands. A fresh VPS clone cannot see uncommitted local files.

Install Rust 1.88+ for the codewhale user, then build both shipped binaries:

sudo -iu codewhale
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup-init.sh
sed -n '1,120p' /tmp/rustup-init.sh
sh /tmp/rustup-init.sh -y --profile minimal
. "$HOME/.cargo/env"
rustup default stable
cd /opt/whalebro/codewhale
cargo install --path crates/cli --locked --force
cargo install --path crates/tui --locked --force
exit

Copy and install the bridge/service files:

cd /opt/whalebro/codewhale
sudo bash scripts/tencent-lighthouse/install-services.sh

After editing both env files, validate the bridge/runtime pairing:

sudo -u codewhale node /opt/codewhale/bridge/scripts/validate-config.mjs \
  --env /etc/deepseek/feishu-bridge.env \
  --runtime-env /etc/deepseek/runtime.env \
  --workspace-root /opt/whalebro \
  --check-filesystem

Secrets

Generate one runtime token and put the same value in both env files:

openssl rand -hex 32
sudoedit /etc/deepseek/runtime.env
sudoedit /etc/deepseek/feishu-bridge.env

Required values:

  • /etc/deepseek/runtime.env
    • DEEPSEEK_API_KEY
    • DEEPSEEK_RUNTIME_TOKEN
  • /etc/deepseek/feishu-bridge.env
    • FEISHU_APP_ID
    • FEISHU_APP_SECRET
    • FEISHU_DOMAIN=feishu for Feishu, lark for Lark
    • DEEPSEEK_RUNTIME_TOKEN
    • FEISHU_ALLOW_GROUPS=false for the first deployment

For first pairing, either:

  1. Temporarily set DEEPSEEK_ALLOW_UNLISTED=true, message the bot, copy the returned chat_id, then set DEEPSEEK_CHAT_ALLOWLIST=<chat_id> and turn unlisted access back off.
  2. Or obtain the chat ID from Feishu/Lark event logs and set the allowlist before first start.

Start Services

sudo systemctl start codewhale-runtime
sudo systemctl status codewhale-runtime --no-pager
curl -s http://127.0.0.1:7878/health

sudo systemctl start codewhale-feishu-bridge
sudo journalctl -u codewhale-feishu-bridge -f

Run the Lighthouse doctor after both services are configured:

cd /opt/whalebro/codewhale
sudo bash scripts/tencent-lighthouse/doctor.sh

Enable on boot is done by install-services.sh; if needed:

sudo systemctl enable codewhale-runtime codewhale-feishu-bridge

Phone Commands

DMs can be plain text and are the intended first control path:

check git status and summarize what needs attention

Group chats are disabled by default. If you later set FEISHU_ALLOW_GROUPS=true, group prompts must start with /ds.

Useful commands:

  • /status
  • /threads
  • /new
  • /resume <thread_id>
  • /interrupt
  • /compact
  • /allow <approval_id>
  • /deny <approval_id>
  • /allow <approval_id> remember

Use remember only when you intentionally want the runtime thread to flip toward auto-approval for future tools.

CNB Deploy Button

After the manual Lighthouse setup passes, CNB can become the repeatable deploy button:

  1. Copy deploy/tencent-lighthouse/cnb/cnb.yml.example to .cnb.yml in the CNB repo.
  2. Copy deploy/tencent-lighthouse/cnb/tag_deploy.yml.example to .cnb/tag_deploy.yml.
  3. Configure the CNB deploy secrets documented in deploy/tencent-lighthouse/cnb/README.md.
  4. Trigger the lighthouse-hk deployment environment.

Keep this manual until the server is boring. Automatic deploys on every push are convenient later, but they can consume CNB quota and restart the bridge while a phone turn is active.

EdgeOne

EdgeOne is not required for the first Feishu/Lark long-connection setup. Add it only when you need a public HTTPS domain in front of a deliberate public service on the Lighthouse host.

Good EdgeOne uses:

  • public docs or tutorial site
  • tiny operator status page
  • future webhook-mode bridge endpoint
  • demo web app hosted on the same Lighthouse instance

Do not use EdgeOne to expose:

  • http://127.0.0.1:7878
  • /v1/* runtime endpoints
  • any endpoint that accepts DEEPSEEK_RUNTIME_TOKEN

End-to-End Validation

From a phone DM to the bot:

  1. Send /status and confirm runtime version, localhost bind, auth state, workspace, git repo, branch, and dirty counts.
  2. Send a harmless prompt such as summarize git status.
  3. Send /interrupt while a turn is active and confirm the turn stops.
  4. Send /threads, then /resume <thread_id> for one listed thread.
  5. Trigger a tool approval and verify both /allow <approval_id> and /deny <approval_id> paths.
  6. Restart both services and re-run /status.
  7. Reboot the instance, then confirm systemctl status codewhale-runtime and systemctl status codewhale-feishu-bridge return to active.

Operational Notes

  • Bind codewhale serve --http to 127.0.0.1.
  • Keep the Lighthouse firewall focused on SSH for this setup.
  • Use SSH key auth.
  • Use tmux for emergency terminal work from Blink/Termius.
  • Keep /opt/whalebro/codewhale on a personal branch while working from the phone.