Setting up Node.js for Bitrix push notifications
Long Polling via PHP holds one PHP process (or FPM worker) per open connection. At 500 simultaneous users — 500 occupied workers, just waiting for events doing nothing useful. PHP-FPM under such load hits pool limits. Node.js solves this: one Node process handles thousands of connections through an event loop without blocking.
Architecture: Node.js as Push server
The Bitrix Node.js push server is a ready package push-server included in Bitrix VM or installed separately. It receives events from PHP via HTTP API, stores queue in Redis, and delivers to clients via WebSocket or SSE.
PHP → HTTP POST → Node.js push-server ← WebSocket/SSE → browsers
↕
Redis
Installing Node.js push-server
On Bitrix VM push-server is already installed. On clean server:
# Install Node.js LTS
curl -fsSL https://rpm.nodesource.com/setup_20.x | bash -
yum install -y nodejs
# Or for Ubuntu
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
# Download push-server from Bitrix repository
# (package available to BitrixEnv subscribers or in Bitrix VM)
# Usually located at:
ls /opt/push-server/
Typical structure:
/opt/push-server/
app.js — entry point
config.json — configuration
node_modules/ — dependencies
Configuring push-server
File /opt/push-server/config.json:
{
"server": {
"http": {
"port": 9010,
"host": "127.0.0.1"
},
"websocket": {
"port": 9011,
"host": "0.0.0.0"
}
},
"security": {
"key": "your_secret_key_here",
"cors": ["https://example.ru", "https://www.example.ru"]
},
"redis": {
"host": "127.0.0.1",
"port": 6379,
"database": 1
},
"log": {
"level": "warn",
"file": "/var/log/push-server/app.log"
},
"cluster": {
"workers": 2
}
}
Port 9010 — HTTP API for PHP (localhost only). Port 9011 — WebSocket for browsers (public, via Nginx proxy).
Systemd unit for push-server
cat > /etc/systemd/system/push-server.service << 'EOF'
[Unit]
Description=Bitrix Push Server
After=network.target redis.service
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/push-server
ExecStart=/usr/bin/node app.js --config config.json
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable push-server
systemctl start push-server
Nginx proxy for WebSocket
Browsers shouldn't connect to Node.js directly — need Nginx as proxy with SSL termination:
# In HTTPS server block
location /bitrix/subws/ {
proxy_pass http://127.0.0.1:9011;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400; # 24 hours for WebSocket
proxy_send_timeout 86400;
}
location /bitrix/pub/ {
proxy_pass http://127.0.0.1:9010;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 25;
}
Configuration in Bitrix
In admin panel — "Settings" → "Push and Pull" → tab "Server":
- Push server:
http://127.0.0.1:9010 - Pull server (public):
https://example.ru/bitrix/pub/ - WebSocket server (public):
wss://example.ru/bitrix/subws/ - Security key: same as in
config.json
Or via PHP code:
\Bitrix\Main\Config\Option::set('pull', 'PUSH_SERVER_URL', 'http://127.0.0.1:9010');
\Bitrix\Main\Config\Option::set('pull', 'PULL_SERVER_URL', 'https://example.ru/bitrix/pub/');
\Bitrix\Main\Config\Option::set('pull', 'SERVER_ENABLED', 'Y');
\Bitrix\Main\Config\Option::set('pull', 'PUSH_SECURITY_KEY', 'your_secret_key_here');
Checking connection
# HTTP API is available
curl -s http://127.0.0.1:9010/server/ping
# Response: {"result":"pong"}
# WebSocket via wscat
npm install -g wscat
wscat -c wss://example.ru/bitrix/subws/
# push-server logs
journalctl -u push-server -f
Monitoring active connections
# Count of WebSocket connections
curl -s http://127.0.0.1:9010/server/stat | python3 -m json.tool
# Response contains: connections_count, channels_count, memory_usage
If connections_count grows without stopping and doesn't decrease — connection leak. Check logs for client disconnect errors.







