Browse OpenIMSDK Guides
Guides

Cluster Deployment

Deploy OpenIMServer across multiple nodes behind Nginx.

Copy

This guide illustrates deploying a two-node OpenIMServer cluster across Node A and Node B. Both machines reside on the same internal network with private IP addresses IP_A and IP_B, and each node possesses an external public IP. This guide focuses on the application nodes and Nginx reverse proxy configuration, excluding the initial setup of external component clusters.

Before starting, prepare a minimum 3-node Redis cluster, MongoDB sharded cluster, Kafka cluster, and Etcd cluster, along with an operational MinIO instance. Record the following connection endpoints:

  • Redis: redisAddr1, redisAddr2, redisAddr3
  • MongoDB: mongoAddr1, mongoAddr2, mongoAddr3
  • Kafka: kafkaAddr1, kafkaAddr2, kafkaAddr3
  • Etcd: etcdAddr1, etcdAddr2, etcdAddr3
  • MinIO internal address: your_minio_internal_address
  • MinIO external address: your_minio_external_address

Both OpenIMServer nodes must have reliable network connectivity to all external backing components.

Deploy identical OpenIMServer versions

Execute these steps on both Node A and Node B. Both nodes must be pinned to the exact same official release tag:

git clone https://github.com/openimsdk/open-im-server
cd open-im-server
git fetch --tags
LATEST_STABLE_TAG=$(basename "$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/openimsdk/open-im-server/releases/latest)")
git checkout "$LATEST_STABLE_TAG"
echo "using open-im-server stable release tag: $LATEST_STABLE_TAG"

main is the active development branch; do not deploy it to a production cluster. Pre-release tags such as alpha, beta, and rc should also never be used in production.

Configure external components

Apply identical cluster configuration files on both machines. Endpoint lists use single-line bracket syntax.

Kafka

Modify config/kafka.yml:

address: [kafkaAddr1, kafkaAddr2, kafkaAddr3]

MinIO

Modify config/minio.yml:

internalAddress: your_minio_internal_address
externalAddress: your_minio_external_address

externalAddress must be reachable by client devices. When utilizing a unified domain name, configure it to the HTTPS object storage gateway path.

MongoDB

Modify config/mongodb.yml:

address: [mongoAddr1, mongoAddr2, mongoAddr3]

Etcd

Modify config/discovery.yml:

etcd:
  address: [etcdAddr1, etcdAddr2, etcdAddr3]

Redis

Modify config/redis.yml and enable cluster mode:

address: [redisAddr1, redisAddr2, redisAddr3]
clusterMode: true

Configure Nginx

You can deploy an identical Nginx configuration on both hosts. Replace the domain name, SSL certificate paths, and upstream node addresses with your actual values:

events {
    worker_connections 1024;
}

http {
    upstream msg_gateway {
        server IP_A:10001;
        server IP_B:10001;
    }

    upstream im_api {
        server IP_A:10002;
        server IP_B:10002;
    }

    server {
        listen 443 ssl;
        server_name yourhost.com;

        ssl_certificate /usr/local/nginx/conf/ssl/your_host_bundle.pem;
        ssl_certificate_key /usr/local/nginx/conf/ssl/your_host.key;

        location ^~ /api/ {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header X-Request-Api $scheme://$host/api;
            proxy_pass http://im_api/;
        }

        location /msg_gateway/ {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_pass http://msg_gateway/;
        }
    }

    server {
        listen 80;
        server_name yourhost.com;
        return 301 https://$host$request_uri;
    }
}

Verify syntax and reload Nginx:

nginx -t
nginx -s reload

Configure DNS records resolving yourhost.com to the public IPs of both entry nodes. In production environments, configure DNS-level or load balancer health checks to prevent routing traffic to unhealthy nodes.

Compile and start both nodes

Install project dependencies on initial setup:

bash bootstrap.sh

In mainland China networks, configure a Go module proxy:

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

Compile and launch on Node A and Node B:

mage
mage start
mage check

Configure OpenIMClientSDK using the unified endpoints:

apiAddr: https://yourhost.com/api
wsAddr: wss://yourhost.com/msg_gateway

Pre-launch checklist

  1. Kafka's KAFKA_CFG_ADVERTISED_LISTENERS must broadcast network addresses reachable by every OpenIMServer node (for example: PLAINTEXT://kafka:9092,EXTERNAL://192.168.2.36:19094).
  2. Clocks across all nodes must be synchronized via NTP. Token issuance permits a maximum clock drift of 5s.
  3. Both nodes must run the exact same official tag, use identical secret keys, and share identical external component configurations.
  4. Stop each node sequentially to verify that API and WebSocket traffic fails over smoothly to the surviving healthy node.
  5. Follow Deployment verification to validate message gateways, authentication, and messaging pipelines.