Skip to content

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

ItemDefaultRisk
Hub bind127.0.0.1 (local only)Public mode needs explicit --host 0.0.0.0
Default accountadmin / anethub for quick-start, or set by --username/--passwordRotate immediately with anet passwd
COMMHUB_AUTH_TOKENdeprecated in v0.8No longer part of the main deployment path
tmux control planedisabled by defaultRequires COMMHUB_ENABLE_TMUX=1 + admin auth
Multi-tenant isolationnetwork-scopedUsers only access networks they belong to
HTTPSnone9200 / 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

bash
anet login --username admin --password anethub
anet passwd                       # interactive, ≥ 12 chars, mixed case + digits + symbols

2. Do not configure a master token in v0.8+

bash
anet hub start --host 0.0.0.0

First 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:

caddy
hub.your-domain.com {
    reverse_proxy localhost:9200
    header {
        X-Content-Type-Options nosniff
        -Server
    }
}

dashboard.your-domain.com {
    reverse_proxy localhost:3000
}
bash
sudo systemctl reload caddy

DNS 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:

bash
# 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)   ← expected

Drop 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

bash
crontab -l 2>/dev/null > /tmp/cron
echo "0 3 * * * sqlite3 ~/.commhub/commhub.db \".backup '~/.commhub/backup-\$(date +\\%F).db'\"" >> /tmp/cron
crontab /tmp/cron

Prune weekly: find ~/.commhub/backup-*.db -mtime +30 -delete.

7. Watch failed logins

bash
journalctl --user -u anet-hub | grep -E '401|auth' | tail -50

v0.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_tasks are 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

OptionUse it forNotes
Local onlySolo devSafest, zero config
LANTeam 5–20Trusted network, no TLS needed
VPS + reverse proxyCross-site collaborationRun all 7 steps above
Hosted SaaS❌ Not offeredProject 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/anethub default with required anet passwd rotation ✅ / 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 start reverted 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 ✅ (#142 rss / cpu_pct / uptime_seconds / in_flight_count) + codex app-server stdio direct opt-in ✅ (#141 ANET_CODEX_STDIO_DIRECT=1 bypasses the @openai/codex-sdk wrapper #102 hang root cause family) + release-gate playbook first full run + v0.10.1 PINNED_SERVER_VERSION chain-bump fixes the anet hub start default-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 upgrade UX + Option B detached, anet create --batch wizard, Servers panel UI, commhub attachment metadata, Xiaomi MiMo 5-model preset, envRef wizard-to-start auto-source, grok-build-acp per-node identity isolation + session/prompt timeout 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:

Powered by Sleep2AGI