yiekheng 66737596b8 fix(scripts): publish.sh routes docker through sudo by default
Mirrors the SUDO=/NO_SUDO=1 pattern from scripts/dev.sh so the script
works on hosts where the user isn't in the docker group (the default
on this dev box). Without this, 'docker info' fails immediately even
though 'docker login' (which needs no daemon socket) succeeds, and
publish.sh aborts before doing anything.

Reminder text updated to tell operators to 'sudo docker login' (or to
opt into rootless docker via NO_SUDO=1).
2026-05-03 10:39:59 +08:00

CM Bot v2 Portainer Setup (Gitea Registry)

Brief, copy/paste-ready steps to run the published images from gitea.04080616.xyz using Portainer.

What gets deployed

  • cm-api (port 3000, internal-only), cm-web (Next.js dashboard, container port 3000 → host CM_WEB_HOST_PORT), cm-telegram, cm-transfer
  • Container names prefixed with CM_DEPLOY_NAME (e.g. rex-cm-telegram-bot)
  • Docker network: ${CM_DEPLOY_NAME}-network (bridge)
  • Named volume: ${CM_DEPLOY_NAME}-web-auth-data for /data/auth (passkey JSON store)

Environment configs

Per-deployment templates live in envs/<name>/.env.example (committed). Each operator copies the example to a sibling .env (gitignored — never committed) and fills in the real secrets:

envs/
├── dev/.env.example      # Local development tier (port 8010)
├── rex/.env.example      # Rex deployment (port 8011)
└── siong/.env.example    # Siong deployment (port 8012)

For Portainer-hosted deployments (rex/siong):

cp envs/rex/.env.example envs/rex/.env
# Fill in DB_PASSWORD, CM_AGENT_*, CM_SECURITY_PIN, TELEGRAM_BOT_TOKEN, etc.
# Then load the variables into the Portainer stack environment.

For local development, see the dev tier flow:

cp envs/dev/.env.example .env
bash scripts/dev.sh up

Key variables

Variable Description
CM_DEPLOY_NAME Unique prefix for containers/network (e.g. rex-cm, siong-cm)
CM_WEB_HOST_PORT Host port for the Next.js dashboard (unique per deployment; e.g. 8010/8011/8012)
CM_AUTH_SECRET 64-hex session signing secret (bash scripts/gen_auth_secret.sh --write)
TELEGRAM_BOT_TOKEN Your Telegram bot token
DB_HOST / DB_USER / DB_PASSWORD / DB_NAME Database connection
CM_PREFIX_PATTERN Username prefix pattern
CM_AGENT_ID / CM_AGENT_PASSWORD / CM_SECURITY_PIN Agent credentials (also used as the dashboard sign-in identity)
CM_BOT_BASE_URL Bot API base URL

One-time: add the registry in Portainer

  1. Portainer → RegistriesAdd registryCustom.
  2. Name: gitea-prod (any)
  3. Registry URL: gitea.04080616.xyz
  4. Username: your Gitea username; Password: the PAT. Save.

Deploy the stack (fast path)

  1. Portainer → StacksAdd stackWeb editor.
  2. Paste the contents of docker-compose.yml from this repo (not the override).
  3. Load all variables from the appropriate envs/<name>/.env into the stack environment variables. Make sure CM_AUTH_SECRET is present (generate with bash scripts/gen_auth_secret.sh).
  4. Click Deploy the stack. Portainer will pull cm-<service>:<tag> from gitea.04080616.xyz/yiekheng and start all four containers.

Migrating an existing pre-B4 stack

The Flask web (port 8000-range) was retired and replaced by the Next.js dashboard. To upgrade:

  1. In your stack .env, drop CM_WEB_NEXT_HOST_PORT. Set CM_WEB_HOST_PORT to what CM_WEB_NEXT_HOST_PORT was (e.g. 8011/8012). Add CM_AUTH_SECRET=$(openssl rand -hex 32).
  2. Update aaPanel proxy_pass if it pointed to the old Flask port (8001/8005) — switch it to the new one (8011/8012).
  3. Redeploy the stack. The old ${CM_DEPLOY_NAME}-web-view and ${CM_DEPLOY_NAME}-web-next containers go away; a single ${CM_DEPLOY_NAME}-web takes over.

Updating to a new image tag

  1. Edit the stack → change DOCKER_IMAGE_TAGUpdate the stack.
  2. Portainer re-pulls and recreates the services with the new tag.

Running multiple deployments on same host

Each deployment needs unique values for:

  • CM_DEPLOY_NAME avoids container/network name conflicts
  • CM_WEB_HOST_PORT avoids port conflicts

Common issues

  • Pull denied: PAT missing read:package or wrong username/PAT in the registry entry.
  • Port already allocated: check CM_WEB_HOST_PORT is unique across deployments.
  • No port bindings applied: ensure network driver stays bridge (not host or macvlan).
Description
No description provided
Readme 665 KiB
Languages
Python 49.5%
TypeScript 45.6%
Shell 4%
Dockerfile 0.8%