Production / Public-Internet Deployment
Default config is NOT safe for the public internet
The current stable line (v0.10.13 — the v0.X.Y format mirrors commhub-server's 0.X.Y semver style; the old v2.1.x CLI version scheme is deprecated — see changelog) is tuned for local use only. Running with --host 0.0.0.0 straight to the open internet leaves you wide open.
Read this entire page before opening any firewall ports.
What the defaults look like today
| Item | Default | Risk |
|---|---|---|
| Hub bind | 127.0.0.1 (local only) | Public mode needs explicit --host 0.0.0.0 |
| Default account | admin / anethub for quick-start, or set by --username/--password | Rotate immediately with anet passwd |
COMMHUB_AUTH_TOKEN | deprecated in v0.8 | No longer part of the main deployment path |
| tmux control plane | disabled by default | Requires COMMHUB_ENABLE_TMUX=1 + admin auth |
| Multi-tenant isolation | network-scoped | Users only access networks they belong to |
| HTTPS | none | 9200 / 3000 are plaintext by default |
Full audit: docs/open-source-security-risk-report.md. v0.8.0 / v0.8.1 has closed all P0 items (auth required ✅ / localhost-only default ✅ / admin/anethub default with forced anet passwd rotation ✅ / tmux off ✅ / network scope enforced ✅). This page is kept as a public-deployment checklist.
Minimum checklist for public deployment
1. Change the password — now
anet login --username admin --password anethub
anet passwd # interactive, ≥ 12 chars, mixed case + digits + symbols2. Do not configure a master token in v0.8+
anet hub start --host 0.0.0.0First start provisions an admin user and writes a local recovery admin utok_ to ~/.anet/server/admin-utok.json (chmod 600). Legacy COMMHUB_AUTH_TOKEN / --token remains as a v0.8 soft-compat path only and logs a deprecation warning.
3. Reverse proxy + TLS (required)
Don't expose 9200 / 3000 directly. Caddy gives you automatic HTTPS:
hub.your-domain.com {
reverse_proxy localhost:9200
header {
X-Content-Type-Options nosniff
-Server
}
}
dashboard.your-domain.com {
reverse_proxy localhost:3000
}sudo systemctl reload caddyDNS your hostname to the box and Caddy will fetch a Let's Encrypt cert automatically.
4. Firewall: 22 + 80 + 443 only
Keep the security group / firewall locked down to 22(SSH) + 80 + 443. Don't open 9200 / 3000 to the world — Caddy proxies them through 443.
5. Verify the tmux control plane is off
Since v0.8, the tmux control plane is disabled by default. Verified at server/src/index.ts:14: TMUX_ENABLED = process.env.COMMHUB_ENABLE_TMUX === "1" — only an explicit =1 enables it; =0 / =true / unset all leave it off.
So as long as you do not actively set COMMHUB_ENABLE_TMUX=1, it's already off:
# Default (off, no env needed)
anet hub start --host 0.0.0.0
# Verify by checking the startup banner after the hub boots:
# Tmux: DISABLED (set COMMHUB_ENABLE_TMUX=1) ← expectedDrop COMMHUB_ENABLE_TMUX=1 from legacy scripts
v0.7 / V2-era deployment scripts often passed COMMHUB_ENABLE_TMUX=1 (when it was the default). On a public deployment that leaves tmux HTTP/WS endpoints exposed — even with admin auth + an IP allowlist, that's an unnecessary attack surface. Confirm any --host 0.0.0.0 hub does not set COMMHUB_ENABLE_TMUX=1 in env / systemd unit / docker-compose (the startup banner should show Tmux: DISABLED).
Want to use the tmux control plane (for local dev / Dashboard debugging)
Endpoint details: REST API — Tmux control plane. All three endpoints (GET /api/tmux/list / GET /api/tmux/:name / WebSocket /api/tmux/:name/stream) share the same auth gate (COMMHUB_ENABLE_TMUX=1 + COMMHUB_TMUX_ALLOWLIST IP allowlist + users.role='admin').
6. Back up the SQLite database
crontab -l 2>/dev/null > /tmp/cron
echo "0 3 * * * sqlite3 ~/.commhub/commhub.db \".backup '~/.commhub/backup-\$(date +\\%F).db'\"" >> /tmp/cron
crontab /tmp/cronPrune weekly: find ~/.commhub/backup-*.db -mtime +30 -delete.
7. Watch failed logins
journalctl --user -u anet-hub | grep -E '401|auth' | tail -50v0.8 ships /api/audit-log + a Dashboard Audit Log page (admin role).
Sharing a Hub across users? Read this
v0.8 has multi-tenant isolation
As of v0.8.0:
get_inbox/get_all_status/list_tasksare filtered by the caller's network membership (R7 / R8 fixed)- SSE subscribe enforces network membership
Cross-team / open-registration scenarios are safe to enable, but we still recommend invite-only via anet network invite --role member --uses N rather than fully-open /api/auth/register.
Acceptable today:
- Inside-the-team trust, ≤ 20 people
- Solo with multiple agents
- Trusted contractors with NDAs
Self-host vs. hosted
| Option | Use it for | Notes |
|---|---|---|
| Local only | Solo dev | Safest, zero config |
| LAN | Team 5–20 | Trusted network, no TLS needed |
| VPS + reverse proxy | Cross-site collaboration | Run all 7 steps above |
| Hosted SaaS | ❌ Not offered | Project is self-hosted-first; no hosted tier planned |
Our commitments
- v0.8.0 / v0.8.1 has closed P0: auth required ✅ / localhost-only default ✅ /
admin/anethubdefault with requiredanet passwdrotation ✅ / tmux off ✅ / network scope enforced ✅ - v0.9.0 / v0.9.1 shipped (changelog): vendor-credential envRef mode ✅ (#125 — secrets no longer persist in plaintext
config.json) + default-toolset transparency ✅ (#101 — Claude Code preset by default + behavior-disclosure banner, user-responsibility checklist) + host-telemetry observability ✅ (#119/api/servers+ dashboard ServersDrawer) - v0.9.2 shipped (changelog): vendor API auth fast-fail ✅ (#129 — 15 min → <5 s + vendor-specific URL hint) + fan-out retry-with-backoff ✅ (#132 Tier 1
CLAUDE_MAX_RETRIES=2+ jitter) +anet node startreverted to foreground default ✅ (#136 — fixes the macOS bun setRawMode bug) - v0.10.0 / v0.10.1 shipped (changelog): per-server-daemon Phase 1 observability endpoint family ✅ (#99
GET /api/server/:host/health+/api/server/:host/agents, used by the dashboard ServersDrawer, monitoring scripts, and external observability integrations; auth matches the existing/api/servers) + per-agent process telemetry ✅ (#142rss/cpu_pct/uptime_seconds/in_flight_count) + codex app-server stdio direct opt-in ✅ (#141ANET_CODEX_STDIO_DIRECT=1bypasses the@openai/codex-sdkwrapper #102 hang root cause family) + release-gate playbook first full run + v0.10.1PINNED_SERVER_VERSIONchain-bump fixes theanet hub startdefault-path functionality regression - v0.10.2 → v0.10.13 shipped (changelog): the cumulative chain covers host disk telemetry, dashboard Hero D topology, codex-sdk default model + yolo flags,
anet upgradeUX + Option B detached,anet create --batchwizard, Servers panel UI, commhub attachment metadata, Xiaomi MiMo 5-model preset, envRef wizard-to-start auto-source,grok-build-acpper-node identity isolation +session/prompttimeout hotfix, and more — sustained Method B SOP clean ship (per-patch detail in the changelog) - Unscheduled / future: Argon2id passwords (security report R9) + token TTL + revoke-all + checksummed install scripts — not in the v0.9.x or v0.10.x scope; planned for v0.11+ as priorities permit
- Vulnerabilities: report via GitHub Security Advisories — 48-hour ack, 7-day patch for critical
Feedback
Hitting an edge case this page doesn't cover? Reach out on:
- GitHub Discussions — public
- WeChat community — Chinese-speaking
- Security Advisories — private vulnerabilities