Deploying AnyCable
Introduction
AnyCable is a high-performance, language-agnostic real-time server that enables reliable two-way communication over WebSockets and Server-Sent Events (SSE). Built with Go, AnyCable is designed to handle thousands of concurrent connections efficiently while seamlessly integrating with Ruby on Rails, Node.js, Laravel, and other backend frameworks.
Unlike traditional WebSocket solutions that run within your application server, AnyCable separates the WebSocket handling from your application logic. This architecture allows your backend to focus on business logic while AnyCable handles the heavy lifting of managing persistent connections, resulting in significant performance improvements and reduced resource consumption.
Deploying AnyCable on Klutch.sh gives you a scalable, production-ready real-time infrastructure with automatic HTTPS, easy Redis integration for pub/sub, and simple configuration through environment variables. Whether you’re building chat applications, live notifications, collaborative editing, or real-time dashboards, AnyCable provides the foundation for responsive, real-time user experiences.
This guide walks you through deploying AnyCable using the official Docker image on Klutch.sh, configuring Redis for broadcasting, setting up environment variables, and best practices for production deployments.
What You’ll Learn
- How to deploy AnyCable-Go with a Dockerfile on Klutch.sh
- Setting up Redis for pub/sub and broadcasting
- Configuring environment variables for your backend RPC server
- Connecting AnyCable to your Rails, Node.js, or other application
- Best practices for production deployment and scaling
Prerequisites
Before you begin, ensure you have:
- A Klutch.sh account
- A GitHub repository (can be a new empty repo)
- Basic familiarity with Docker and WebSocket concepts
- A backend application (Rails, Node.js, etc.) that will handle the RPC calls
- (Optional) A Redis instance for pub/sub broadcasting
Understanding AnyCable Architecture
AnyCable uses a split architecture to maximize performance:
- AnyCable-Go Server: A Go-based WebSocket server that handles all client connections, manages subscriptions, and routes messages
- RPC Backend: Your application server (Rails, Node.js, etc.) that handles authentication, authorization, and business logic via gRPC or HTTP
- Pub/Sub Layer: Redis, NATS, or HTTP for distributing broadcast messages across multiple AnyCable instances
[Browser/Client] ←WebSocket→ [AnyCable-Go :8080] ↓ gRPC/HTTP [Your App Server :50051] ↓ [Redis/NATS]The default port for AnyCable-Go is 8080 for WebSocket connections and 50051 for gRPC communication with your backend.
Step 1: Set Up Redis (Optional but Recommended)
For production deployments with multiple AnyCable instances or when you need to broadcast messages from your backend, you’ll need Redis.
Option A: Deploy Redis on Klutch.sh
-
Log in to Klutch.sh and navigate to the dashboard.
-
Create a new project (if you don’t have one) or select an existing project.
-
Create a Redis TCP app:
- Click “New App”
- Select “TCP” as the traffic type
- Connect a GitHub repository containing a Redis Dockerfile
-
Create a
Dockerfilefor Redis in a separate repository: -
Configure a persistent volume for Redis data:
- Mount Path:
/data - Size: 5 GB (adjust based on expected data volume)
- Mount Path:
-
Deploy the Redis app. Note the app URL for connecting AnyCable (e.g.,
redis-app.klutch.sh:8000).
FROM redis:7-alpine
# Expose Redis portEXPOSE 6379
# Start Redis with persistenceCMD ["redis-server", "--appendonly", "yes"]Option B: Use an External Redis Service
You can also use managed Redis services like:
If using an external service, note the connection URL for later configuration.
Step 2: Prepare Your GitHub Repository
-
Create a new GitHub repository for your AnyCable deployment.
-
Create a
Dockerfilein the root of your repository: - (Optional) Create a configuration file named
anycable.tomlfor complex setups: - Update the Dockerfile to include the config file (if using):
- (Optional) Create a
.dockerignorefile: - Commit and push your changes to GitHub:
FROM anycable/anycable-go:1.5
# Set default environment variablesENV ANYCABLE_HOST=0.0.0.0ENV ANYCABLE_PORT=8080ENV ANYCABLE_PATH=/cable
# Increase file descriptor limits for high concurrency# This is handled at runtime, but we set defaults here
# Expose WebSocket portEXPOSE 8080
# Health check endpointHEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
# Start AnyCableCMD ["anycable-go"]# AnyCable configuration file
[server]host = "0.0.0.0"port = 8080path = "/cable"
[rpc]host = "your-app.klutch.sh:50051"
[redis]url = "redis://redis-app.klutch.sh:8000/0"channel = "__anycable__"
[logging]level = "info"FROM anycable/anycable-go:1.5
# Copy configuration fileCOPY anycable.toml /etc/anycable/anycable.toml
ENV ANYCABLE_HOST=0.0.0.0ENV ANYCABLE_PORT=8080
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
CMD ["anycable-go", "--config-path=/etc/anycable/anycable.toml"].git.github*.md.env.env.localgit add .git commit -m "Add AnyCable deployment configuration for Klutch.sh"git push origin mainStep 3: Create Your App on Klutch.sh
-
Log in to Klutch.sh and navigate to the dashboard.
-
Create a new project (if you don’t have one already) by clicking “New Project” and providing a project name.
-
Create a new app within your project by clicking “New App”.
-
Connect your GitHub repository by selecting it from the list of available repositories.
-
Configure the build settings:
- Klutch.sh will automatically detect the Dockerfile in your repository root
- The build will use this Dockerfile automatically
-
Set the internal port to
8080(AnyCable’s default WebSocket port). This is the port that traffic will be routed to within the container. -
Select HTTP traffic for the app’s traffic type.
Step 4: Configure Environment Variables
Configure the necessary environment variables for AnyCable to connect to your backend and Redis.
-
In your app settings, navigate to the “Environment Variables” section.
-
Add core configuration variables:
- Add security settings:
- Configure logging and debugging (optional):
- Add standalone mode settings (if not using RPC):
- Mark sensitive values as secrets in the Klutch.sh UI to prevent them from appearing in logs.
# Server configurationANYCABLE_HOST=0.0.0.0ANYCABLE_PORT=8080ANYCABLE_PATH=/cable
# RPC backend configuration (your Rails/Node.js app)ANYCABLE_RPC_HOST=your-backend-app.klutch.sh:50051
# Redis configuration for pub/subANYCABLE_REDIS_URL=redis://redis-app.klutch.sh:8000/0ANYCABLE_REDIS_CHANNEL=__anycable__
# Broadcasting adapterANYCABLE_BROADCAST_ADAPTER=redis# Secret key for JWT authentication (generate with: openssl rand -hex 32)ANYCABLE_SECRET=your-64-character-secret-key-here
# Broadcast authentication keyANYCABLE_BROADCAST_KEY=your-broadcast-secret-key
# Allowed origins for CORS (comma-separated)ANYCABLE_ALLOWED_ORIGINS=https://your-frontend.com,https://example-app.klutch.sh# Log level: debug, info, warn, errorANYCABLE_LOG_LEVEL=info
# Enable debug mode for verbose loggingANYCABLE_DEBUG=false# Enable standalone mode (no RPC backend required)ANYCABLE_NORPC=true
# Allow public connections without authenticationANYCABLE_PUBLIC=true
# Enable public streams for direct subscriptionsANYCABLE_PUBLIC_STREAMS=trueStep 5: Deploy Your Application
-
Review your configuration to ensure all settings are correct:
- Dockerfile is detected
- Internal port is set to
8080 - Environment variables are configured
- Traffic type is set to HTTP
-
Click “Deploy” to start the build and deployment process.
-
Monitor the build logs to ensure the deployment completes successfully. The build typically takes 1-2 minutes.
-
Wait for the deployment to complete. Once done, you’ll see your app URL (e.g.,
https://example-app.klutch.sh).
Step 6: Test Your Deployment
- Check the health endpoint:
- Test WebSocket connectivity using a WebSocket client or browser console:
- Verify metrics endpoint (if enabled):
curl https://example-app.klutch.sh/healthYou should receive a 200 OK response.
// In browser consoleconst ws = new WebSocket('wss://example-app.klutch.sh/cable');
ws.onopen = () => { console.log('Connected to AnyCable'); // Send a subscribe message ws.send(JSON.stringify({ command: 'subscribe', identifier: JSON.stringify({ channel: 'ChatChannel' }) }));};
ws.onmessage = (event) => { console.log('Received:', event.data);};
ws.onerror = (error) => { console.error('WebSocket error:', error);};curl https://example-app.klutch.sh/metricsGetting Started: Integration Examples
Rails Integration
Configure your Rails application to use AnyCable:
config/cable.yml:
production: adapter: any_cableconfig/anycable.yml:
production: redis_url: <%= ENV.fetch("REDIS_URL", "redis://localhost:6379/1") %> broadcast_adapter: redis rpc_host: 0.0.0.0:50051 secret: <%= ENV.fetch("ANYCABLE_SECRET") %>Gemfile:
gem "anycable-rails", "~> 1.4"Start the RPC server alongside your Rails app:
bundle exec anycableNode.js Integration
For serverless or Node.js applications, use signed streams:
server.js:
const crypto = require('crypto');
// Generate a signed stream namefunction signedStream(streamName, secret) { const signature = crypto .createHmac('sha256', secret) .update(streamName) .digest('base64url');
return `${streamName}--${signature}`;}
// Use in your applicationconst signedName = signedStream('chat:room_1', process.env.ANYCABLE_SECRET);client.js:
import { createCable } from '@anycable/web';
const cable = createCable('wss://example-app.klutch.sh/cable');
// Subscribe to a channelconst channel = cable.subscribeTo('ChatChannel', { room: 'general' });
channel.on('message', (data) => { console.log('New message:', data);});Standalone Mode with HTTP Broadcasting
For simple use cases without an RPC backend:
Environment variables:
ANYCABLE_NORPC=trueANYCABLE_PUBLIC=trueANYCABLE_BROADCAST_ADAPTER=httpANYCABLE_HTTP_BROADCAST_PORT=8090ANYCABLE_BROADCAST_KEY=your-secret-keyBroadcasting from your backend:
curl -X POST https://example-app.klutch.sh/_broadcast \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret-key" \ -d '{ "stream": "chat:room_1", "data": "{\"message\": \"Hello, World!\"}" }'Advanced Configuration
Using NATS Instead of Redis
For high-throughput applications, consider using embedded NATS:
# Enable embedded NATSANYCABLE_PUBSUB=natsANYCABLE_BROADCAST_ADAPTER=nats
# Or use external NATSANYCABLE_NATS_SERVERS=nats://nats-server.klutch.sh:8000ANYCABLE_NATS_CHANNEL=__anycable__JWT Authentication
Enable JWT-based authentication for stateless connections:
ANYCABLE_JWT_ID_KEY=your-jwt-secretANYCABLE_JWT_ID_ENFORCE=trueGenerate JWT tokens in your backend:
const jwt = require('jsonwebtoken');
const token = jwt.sign( { sub: 'user_123', exp: Math.floor(Date.now() / 1000) + 3600 }, process.env.ANYCABLE_JWT_ID_KEY);
// Client connects with: wss://example-app.klutch.sh/cable?jid=<token>Multiple WebSocket Paths
Configure multiple endpoints for different use cases:
ANYCABLE_PATH=/cable,/admin/cable,/api/wsConnection Limits and Tuning
For high-concurrency deployments:
# Ping interval (seconds)ANYCABLE_PING_INTERVAL=3
# Disconnect rate limit (per second)ANYCABLE_DISCONNECT_RATE=100
# Shutdown timeout (seconds)ANYCABLE_SHUTDOWN_TIMEOUT=30Production Best Practices
Security
- Use HTTPS only: Klutch.sh provides automatic HTTPS for all apps
- Set allowed origins: Configure
ANYCABLE_ALLOWED_ORIGINSto prevent unauthorized connections - Use authentication: Enable JWT authentication or RPC-based auth
- Rotate secrets: Periodically update
ANYCABLE_SECRETandANYCABLE_BROADCAST_KEY - Secure Redis: Use authentication for your Redis instance
Performance
- Monitor connections: Track active connections via the
/metricsendpoint - Scale horizontally: Deploy multiple AnyCable instances with shared Redis
- Tune ping interval: Adjust
ANYCABLE_PING_INTERVALbased on your use case - Use connection pooling: Configure Redis connection pool for high traffic
Monitoring
- Prometheus metrics: Available at
/metricsendpoint - Health checks: Use
/healthfor load balancer health checks - Structured logging: Enable JSON logging for log aggregation
Key metrics to monitor:
anycable_clients_num: Current number of connected clientsanycable_broadcast_msg_total: Total broadcast messages sentanycable_failed_auths_total: Failed authentication attemptsanycable_rpc_call_total: RPC calls to your backend
Troubleshooting
Connection Issues
Issue: Clients cannot establish WebSocket connections
Solutions:
- Verify the WebSocket URL uses
wss://(secure) - Check
ANYCABLE_ALLOWED_ORIGINSincludes your frontend domain - Ensure the internal port is set to
8080 - Review logs for authentication errors
RPC Connection Failures
Issue: AnyCable cannot reach the RPC backend
Solutions:
- Verify
ANYCABLE_RPC_HOSTis correct - Ensure your backend’s gRPC server is running on port 50051
- Check network connectivity between AnyCable and your backend
- Enable debug logging with
ANYCABLE_DEBUG=true
Redis Connection Problems
Issue: Cannot connect to Redis for pub/sub
Solutions:
- Verify
ANYCABLE_REDIS_URLformat:redis://host:port/db - For Klutch.sh TCP apps, use port 8000 externally
- Test Redis connectivity manually
- Check Redis authentication if configured
High Memory Usage
Issue: AnyCable consuming excessive memory
Solutions:
- Monitor client count and adjust resources accordingly
- Enable slow drain mode for graceful shutdowns
- Review ping interval settings
- Check for connection leaks in your client code
Messages Not Broadcasting
Issue: Broadcast messages not reaching clients
Solutions:
- Verify Redis is connected and working
- Check that
ANYCABLE_BROADCAST_ADAPTERis set correctly - Ensure broadcast key matches between sender and AnyCable
- Review channel subscription identifiers
Local Development with Docker Compose
For local testing before deploying to Klutch.sh:
version: '3.8'
services: anycable: image: anycable/anycable-go:1.5 ports: - "8080:8080" environment: - ANYCABLE_HOST=0.0.0.0 - ANYCABLE_PORT=8080 - ANYCABLE_RPC_HOST=backend:50051 - ANYCABLE_REDIS_URL=redis://redis:6379/0 - ANYCABLE_BROADCAST_ADAPTER=redis - ANYCABLE_DEBUG=true depends_on: - redis - backend
redis: image: redis:7-alpine ports: - "6379:6379"
backend: build: ./your-app ports: - "3000:3000" - "50051:50051" environment: - REDIS_URL=redis://redis:6379/0 depends_on: - redisRun locally with:
docker-compose up -dAccess AnyCable at ws://localhost:8080/cable.
Note: Docker Compose is for local development only. Deploy to Klutch.sh using the Dockerfile approach described in this guide.
Updating AnyCable
To update to a newer version of AnyCable:
- Update your Dockerfile to use a specific version or latest:
- Commit and push the changes:
-
Redeploy through the Klutch.sh dashboard.
-
Verify the update by checking the logs for the version number.
# Use a specific versionFROM anycable/anycable-go:1.5
# Or use latest (not recommended for production)FROM anycable/anycable-go:latestgit add Dockerfilegit commit -m "Update AnyCable to version 1.5"git push origin mainScaling AnyCable
Horizontal Scaling
Deploy multiple AnyCable instances with shared Redis:
- Ensure Redis is configured as the broadcast adapter
- Deploy additional AnyCable apps with the same configuration
- Use a load balancer (Klutch.sh provides this automatically)
Connection Distribution
AnyCable automatically distributes connections across instances when using Redis pub/sub. Messages broadcast to one instance are delivered to clients on all instances.
Sticky Sessions
For optimal performance with multiple instances:
- Enable WebSocket sticky sessions in your load balancer
- Use Redis for session storage
- Consider using JWT authentication for stateless connections
Resources
- AnyCable GitHub Repository
- AnyCable Official Documentation
- AnyCable Rails Integration Guide
- AnyCable Serverless Guide
- Klutch.sh Quick Start Guide
- Klutch.sh Volumes Guide
- Redis Deployment Guide
Conclusion
You now have a fully functional AnyCable deployment running on Klutch.sh, ready to handle real-time WebSocket connections for your applications. This setup provides:
- High-performance WebSocket handling with Go
- Seamless integration with Rails, Node.js, and other backends
- Redis-based pub/sub for scalable broadcasting
- JWT authentication for stateless connections
- Automatic HTTPS and load balancing
AnyCable’s architecture separates WebSocket handling from your application logic, allowing you to scale each component independently and build responsive, real-time features without compromising on performance or resource efficiency.
For community support and discussions, visit the AnyCable GitHub Discussions or check the official documentation.