跪拜 Guibai
← All articles
Docker · Agent · Open Source

Ditching QQ's Official Bot for a Self-Hosted SnowLuma + AstrBot Stack

By 时早玖沐 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Anyone who self-hosts a QQ bot runs into the same tiered API and broken card messages; the specific compose flags and networking steps here turn what otherwise becomes hours of trial and error into a checklist. The same ptrace-based pattern also applies on other platforms whose official bot APIs throttle individuals.

Summary

QQ's official bot productized as an enterprise service channel, and individual developers pay for that. A batch of APIs stays gated behind gray-scaling, friend private messages never existed, and card messages render as placeholder garbage on TIM, the desktop client. The replacement stack keeps QQ itself in the loop instead of reimplementing its protocol from scratch.

SnowLuma runs a real QQ client inside Docker, injects hooks via ptrace, and presents a OneBot v11 interface. AstrBot takes the conversation side: model API calls, plugins, persona. One outbound WebSocket carries events from SnowLuma to AstrBot's reverse WS listener; the writeup spells out why the opposite direction fails.

The migration notes name where the official docs mislead: SnowLuma's guide describes server-mode OneBot only, the manual JSON editing it prescribes has a WebUI equivalent with fewer failure modes, and the two compose stacks land on separate Docker networks that never see each other. Parameter errors that break silently, like a missing SYS_PTRACE capability and the 1GB shm bump QQ's Chromium runtime needs, get pinned down along with the security posture: port 6081 is a remote desktop into the QQ account, and third-party clients carry ban risk.

Takeaways
— QQ's official bot gates a batch of interfaces behind gray-scaling for individual-certified developers and provides no friend private messages.
— Card messages from official bots render as placeholder garbage on TIM, the desktop client.
— SnowLuma runs a real QQ client in Docker and injects hooks via ptrace, so it looks like a normal client to Tencent, where protocol reimplementations like NapCat risk bans.
— AstrBot's OneBot v11 adapter (aiocqhttp) is a reverse WebSocket server only; SnowLuma must be configured as the WS client, never as the server.
— SnowLuma requires the SYS_PTRACE capability, seccomp=unconfined, 1GB shm, and SNOWLUMA_HOOK_AUTOLOAD=1; omitting any of them breaks hooks or crashes QQ.
— Ports 3000/3001 on SnowLuma and 6199 on AstrBot stay unmapped to the host in this setup.
— The two compose stacks create separate Docker networks; a shared external network named botnet joins them, declared in compose so it survives container recreation.
— AstrBot's reverse WS host must be 0.0.0.0; 127.0.0.1 makes the container listen on loopback only.
— Use container names like astrbot in the WS URL; IPs change when containers are recreated.
— A 401 from a curl probe proves the port, HTTP, and WS route all work; only the token is wrong.
— Port 6081 is a full remote desktop into the QQ account; the source advises never exposing it bare, and using a reverse proxy with auth or Tailscale/WireGuard instead.
— Third-party QQ clients carry account ban risk; the source's advice is not to run them on a main account.
Conclusions

QQ's official bot productized around enterprise service entries, so individual hobbyists become second-class API users; the feature gating and missing private chat follow from that positioning, not from oversight.

SnowLuma's docs describe the container as a OneBot server, but the AstrBot integration needs it as the outbound WS client; the whole setup depends on flipping that assumption, and the WebUI holds the one field the docs never mention.

ptrace injection of a real QQ client trades protocol-reimplementation risk for behavioral-detection risk; it looks normal to Tencent's servers, but the account still lives or dies by how the hook behaves under actual use.

The security section treats the bot as a remote desktop and an account risk rather than a web service; that framing changes what constitutes acceptable exposure and which account to choose.

Concepts & terms
ptrace
A Linux syscall that lets one process observe and control another. SnowLuma uses it to inject its hook into the running QQ client, which is why the container needs SYS_PTRACE and seccomp=unconfined.
OneBot v11
A standard protocol for exposing QQ bot functionality over HTTP and WebSocket. Support for it means frameworks like AstrBot and NoneBot can drive any client backend that implements it.
Reverse WebSocket
A WebSocket connection where the receiving end is the server and the connecting end is the client. AstrBot's OneBot adapter only works as a reverse WS server, so SnowLuma has to dial out to it with its WS client config.
noVNC
A browser-based VNC client. SnowLuma bundles it so QQ's login screen appears in a web page at port 6081, letting users scan a QR code without installing QQ locally.
Overlay config mode
SnowLuma's config layering where an account-level file like onebot_<uin>.json overrides the base file onebot.json. In overlay mode, editing the wrong file silently changes nothing.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗