The official OOTB ("out of the box") deployment for OCTO — both the
single-node Docker Compose stack under docker/ and the
multi-node Kubernetes manifests under kustomize/ for
the OCTO platform.
This repository is the single source of truth for OCTO deployment. The
deployment artefacts that previously lived inside Mininglamp-OSS/octo-server
(docker/octo/, docker/tsdd/) are now retired; consume them from
here instead.
OCTO is an open-source team collaboration and communication platform designed for lawful internal organizational use. It is provided as a technology framework — the OCTO project and its contributors do not operate, host, or manage any messaging service for end users.
You must not use OCTO, directly or indirectly, for any of the following:
- Unauthorized surveillance, interception, or monitoring of private communications
- Circumventing law enforcement, regulatory oversight, or lawful government requests
- Distributing illegal, harmful, or prohibited content (including but not limited to fraud, harassment, terrorism-related material, and child exploitation content)
- Operating an unlicensed public instant messaging service in jurisdictions that require such licensing
- Any activity that violates applicable local, national, or international laws and regulations
By deploying OCTO, you (the deployer/operator) assume full responsibility for:
- Regulatory compliance — Obtaining all required licenses and permits in your jurisdiction. In the People's Republic of China, this may include but is not limited to: ICP filing (ICP 备案), Value-Added Telecommunications Business License (增值电信业务经营许可证) for instant messaging services, and compliance with the Cybersecurity Law (《网络安全法》), Data Security Law (《数据安全法》), and Personal Information Protection Law (《个人信息保护法》). In the European Union, the Digital Services Act (DSA), General Data Protection Regulation (GDPR), and ePrivacy Directive may apply. In the United States, the Electronic Communications Privacy Act (ECPA), Communications Assistance for Law Enforcement Act (CALEA), and state-level privacy laws may apply. Other jurisdictions have their own requirements.
- Content moderation — Implementing appropriate content review, reporting mechanisms, and user safety measures as required by applicable laws.
- Data protection — Ensuring proper data handling, storage, retention, and deletion practices in compliance with applicable data protection regulations.
- User notification — Informing your users about data collection, processing, and their rights under applicable laws.
- Security — Maintaining the security of your deployment, including timely application of updates and patches.
OCTO is provided "AS IS" without warranty of any kind, express or implied. The OCTO project, Mininglamp, and its contributors shall not be held liable for any claim, damage, legal consequence, regulatory penalty, or other liability arising from the deployment, operation, or use of this software. This includes, without limitation, any liability arising from a deployer's failure to comply with applicable laws and regulations.
See LICENSE for the full Apache 2.0 license terms.
中文版:README.zh.md
For a single-node Docker Compose trial, use
docker/in this repository — it brings up the full OCTO stack (server + admin + web + matter + smart-summary + WuKongIM + MySQL + Redis + MinIO + nginx) with onedocker compose up -d. Seedocker/README.mdfor the walkthrough (中文版docker/README.zh.md). Thiskustomize/tree remains the canonical reference for multi-node Kubernetes deployment.
git clone https://github.com/Mininglamp-OSS/octo-deployment.git
cd octo-deployment
./setup.sh # step 1: interactive — auto-detects public IP, generates all secrets in docker/.env (no sudo)
sudo ./setup.sh --up # step 2: start the stack (start-only — never regenerates secrets); sudo needed for Docker + .env
sudo ./setup.sh --smoke-test # step 3: admin login + presign PUT end-to-end check (alias: --verify, deprecated)--up is a start-only subcommand (R6 / GH#33, R8 / GH#43): it
requires an existing docker/.env (generated by step 1). If
docker/.env is missing, --up exits 1 with a concrete remediation
message — it will not silently regenerate secrets, because a single
typo in deploy automation would otherwise rotate every
MySQL/MinIO/admin secret on a live host. To bootstrap + start in one
command (generating fresh secrets), pass --up --force explicitly:
sudo ./setup.sh --non-interactive --ip <PUBLIC_IP> --up --force # explicit one-shot bootstrap (writes new secrets)--up runs docker compose up -d --wait --wait-timeout 240 and
blocks until every long-running service reports (healthy) and every
one-shot init job (preflight, minio-init) exits 0. On timeout or
startup failure it prints compose ps, the specific failing service
names, and a logs <svc> hint for each, then exits 1. The wrapper
retries once on a soft timeout (warm mysql / image caches make the
second attempt typically <10s), so worst-case wall-clock is 2 × 240s.
It prints a . every 5 seconds while waiting so you can see the run
is alive. --up (without --force) will never rewrite/regenerate
secrets in docker/.env — that file is owned by step 1's caller, and
--up only chown root:root + chmod 600 it (ownership hardening,
never a content change).
For unattended provisioning, do step 1 non-interactively and chain into step 2:
./setup.sh --non-interactive --ip <PUBLIC_IP> # step 1: gen .env, no prompts
sudo ./setup.sh --up # step 2: start + wait-for-healthy
sudo ./setup.sh --smoke-test # step 3: verifysetup.sh prints the admin URL + superAdmin password at the end of
step 1. The password is also persisted to docker/.env (mode 600) —
treat that file as a secret and rotate the password from the admin
UI after first login (see docker/README.md "First-admin
bootstrap"). After step 2 the file ends up owned by root (because
--up runs under sudo); both --up and --smoke-test continue to
require sudo because the file contains MySQL/MinIO/admin credentials
and Compose control inputs (COMPOSE_PROJECT_NAME,
OCTO_MASTER_KEY, OCTO_ADMIN_PWD, …) — user-write would silently
alter the next privileged docker compose run.
The OOTB stack is
single-port for clients: only TCP 28080 (OCTO_HTTP_PORT, the
nginx HTTP vhost) needs to be open. With HTTPS the client port becomes
28443 (OCTO_HTTPS_PORT). All other ports (MinIO, MySQL, Redis,
WuKongIM monitor, direct REST) default to loopback.
Uninstall / reset is interactive:
./setup.sh --uninstall
# Three granularity levels: 1) full 2) data-only 3) containers onlyFull docs: docker/README.md (Uninstall / Reset,
Network surface, MinIO bootstrap, Hardening checklist, troubleshooting).
| Service | Image | Container ports |
|---|---|---|
| octo-server | mininglamposs/octo-server |
8090 (http) / 6979 (grpc) |
| octo-web | mininglamposs/octo-web |
80 |
| octo-admin | mininglamposs/octo-admin |
80 |
| octo-matter | mininglamposs/octo-matter |
8080 |
| octo-smart-summary-api | mininglamposs/octo-smart-summary-api |
8080 / 8081 |
| octo-smart-summary-worker | mininglamposs/octo-smart-summary-worker |
8082 |
External infrastructure expected (provisioned separately, not in this repo):
- MySQL 8 with three databases —
octo(IM core),octo_matter,octo_summary - Redis 7
- WuKongIM ≥ v2 (the IM long-connection backend)
- S3-compatible object storage (MinIO, AWS S3, Tencent COS, etc.)
OCTO does not embed an IM engine — it consumes WuKongIM over the latter's HTTP API and webhook gRPC. You can run any of the deployment modes documented at https://docs.githubim.com/installation/overview:
- Docker / docker-compose (single node, fastest to try)
- Kubernetes / Helm (multi-node, for production)
- Standalone binary
Whichever you pick, three things must line up between WuKongIM and octo-server:
| WuKongIM config | OCTO setting |
|---|---|
managerToken |
octo-server-config.tsdd.yaml → wukongIM.managerToken (also set as WUKONGIM_MANAGER_TOKEN in octo-server-secret for env-driven setups) |
webhook.grpcAddr (the address WuKongIM dials back into) |
<octo-server-svc>:6979 so message events reach OCTO |
external.ip / external.wsAddr / external.wssAddr (the public endpoints WuKongIM advertises to clients) |
should match how end-user clients reach WuKongIM via your ingress / LB |
kustomize/
├── base/ Generic OSS templates (this is the canonical reference)
│ ├── kustomization.yaml Pulls all resources, applies image transformer
│ ├── octo-*.yaml Deployments + Services
│ ├── octo-*-config.yaml ConfigMaps (non-sensitive)
│ └── octo-*-secret.example.yaml
│ Secret templates with CHANGE_ME_* placeholders
└── overlays/
├── dev/ Image tag = "dev"
└── prod/ Multi-replica production overlay
For single-node Docker Compose evaluation, go to
docker/README.md— it owns the prerequisites checklist (Docker daemon, ports, RAM/disk, image-pull network access), thesetup.shone-liner, and the pre-flight warning for hosts that already run another OCTO stack.The walkthrough below is for the Kubernetes / kustomize path.
- A Kubernetes cluster you can
kubectl applyagainst (≥ 1 worker node; production overlay assumes a multi-node cluster). kubectl≥ 1.27 on your shell with kubeconfig pointing at the target cluster.- An Ingress controller (NGINX / Traefik / cloud-managed) — this repo does NOT ship one; see the open item below.
- External infrastructure already provisioned: MySQL 8 (three DBs:
octo,octo_matter,octo_summary), Redis 7, WuKongIM ≥ v2, and an S3-compatible object store. The base manifests reference these via Secrets / ConfigMaps and assume you bring them yourself.
Namespace is not hardcoded — specify it on the CLI.
# 1. Create the target namespace
kubectl create namespace octo
# 2. Prepare Secrets (one-time per environment).
# Copy the *.example templates, fill in real values, then apply.
cd kustomize/base
for f in *-secret.example.yaml; do cp "$f" "${f/.example/}"; done
$EDITOR octo-*-secret.yaml # replace every CHANGE_ME_*
kubectl apply -n octo \
-f octo-server-secret.yaml \
-f octo-matter-secret.yaml \
-f octo-smart-summary-secret.yaml
# 3. Apply ConfigMaps + workloads
kubectl apply -n octo -k .For environment-specific overrides:
kubectl apply -n octo-dev -k kustomize/overlays/dev
kubectl apply -n octo-prod -k kustomize/overlays/prodPreview the rendered manifests without applying:
kubectl kustomize kustomize/baseEdit kustomize/base/kustomization.yaml and replace newTag: latest with a release tag, e.g. newTag: v0.1.0. Each images: entry can be overridden independently.
Each service consumes a small Secret. Required keys per service:
| Secret | Required keys |
|---|---|
octo-server-secret |
DM_MYSQL_DSN, DM_REDIS_ADDR, WUKONGIM_MANAGER_TOKEN, OCTO_ADMIN_PASSWORD, OCTO_MASTER_KEY, DMWORK_MASTER_KEY (legacy alias of master key), NOTIFY_INTERNAL_TOKEN, OCTO_INTERNAL_HMAC_SECRET, OCTO_JWT_SECRET. Plus OIDC / COS / SMTP / APNS keys when those features are enabled. |
octo-matter-secret |
MYSQL_DSN, LLM_API_KEY, NOTIFY_INTERNAL_TOKEN (must match octo-server-secret). |
octo-smart-summary-secret |
MYSQL_DSN, IM_MYSQL_DSN, LLM_API_URL, LLM_API_KEY. |
Generate strong random tokens with:
openssl rand -hex 32 # for *_TOKEN / *_SECRET / MASTER_KEY
openssl rand -base64 32 # for DM_OIDC_RT_ENC_KEYSecret files (
*-secret.yaml) are git-ignored. Only the*.example.yamltemplates are tracked.
Default image references point at docker.io/mininglamposs/<service>:latest. To use a self-hosted registry, edit the images: block in kustomize/base/kustomization.yaml:
images:
- name: mininglamposs/octo-server
newName: my-registry.example.com/octo/octo-server
newTag: v0.1.0For private registries that require authentication, create a Docker config Secret and reference it via imagePullSecrets on each Deployment (or patch via overlay).
- Add an Ingress / Gateway example for
octo-web+octo-admin(current README assumes you bring your own controller) - Document the database bootstrap (which migrations the services apply on boot, vs. which require a one-shot Job)
- Add a sample MinIO + WuKongIM in-cluster manifest set for users who want a fully self-contained stack
- APNS
.p8key mounting (or instructions to disable iOS push)
Apache 2.0 — same as the rest of the OCTO suite.