Skip to content

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.


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

    1. Log in to Klutch.sh and navigate to the dashboard.

    2. Create a new project (if you don’t have one) or select an existing project.

    3. Create a Redis TCP app:

      • Click “New App”
      • Select “TCP” as the traffic type
      • Connect a GitHub repository containing a Redis Dockerfile
    4. Create a Dockerfile for Redis in a separate repository:

    FROM redis:7-alpine
    # Expose Redis port
    EXPOSE 6379
    # Start Redis with persistence
    CMD ["redis-server", "--appendonly", "yes"]
    1. Configure a persistent volume for Redis data:

      • Mount Path: /data
      • Size: 5 GB (adjust based on expected data volume)
    2. Deploy the Redis app. Note the app URL for connecting AnyCable (e.g., redis-app.klutch.sh:8000).

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

    1. Create a new GitHub repository for your AnyCable deployment.

    2. Create a Dockerfile in the root of your repository:

    FROM anycable/anycable-go:1.5
    # Set default environment variables
    ENV ANYCABLE_HOST=0.0.0.0
    ENV ANYCABLE_PORT=8080
    ENV ANYCABLE_PATH=/cable
    # Increase file descriptor limits for high concurrency
    # This is handled at runtime, but we set defaults here
    # Expose WebSocket port
    EXPOSE 8080
    # Health check endpoint
    HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
    CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
    # Start AnyCable
    CMD ["anycable-go"]
    1. (Optional) Create a configuration file named anycable.toml for complex setups:
    # AnyCable configuration file
    [server]
    host = "0.0.0.0"
    port = 8080
    path = "/cable"
    [rpc]
    host = "your-app.klutch.sh:50051"
    [redis]
    url = "redis://redis-app.klutch.sh:8000/0"
    channel = "__anycable__"
    [logging]
    level = "info"
    1. Update the Dockerfile to include the config file (if using):
    FROM anycable/anycable-go:1.5
    # Copy configuration file
    COPY anycable.toml /etc/anycable/anycable.toml
    ENV ANYCABLE_HOST=0.0.0.0
    ENV 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"]
    1. (Optional) Create a .dockerignore file:
    .git
    .github
    *.md
    .env
    .env.local
    1. Commit and push your changes to GitHub:
    Terminal window
    git add .
    git commit -m "Add AnyCable deployment configuration for Klutch.sh"
    git push origin main

Step 3: Create Your App on Klutch.sh

    1. Log in to Klutch.sh and navigate to the dashboard.

    2. Create a new project (if you don’t have one already) by clicking “New Project” and providing a project name.

    3. Create a new app within your project by clicking “New App”.

    4. Connect your GitHub repository by selecting it from the list of available repositories.

    5. Configure the build settings:

      • Klutch.sh will automatically detect the Dockerfile in your repository root
      • The build will use this Dockerfile automatically
    6. Set the internal port to 8080 (AnyCable’s default WebSocket port). This is the port that traffic will be routed to within the container.

    7. 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.

    1. In your app settings, navigate to the “Environment Variables” section.

    2. Add core configuration variables:

    Terminal window
    # Server configuration
    ANYCABLE_HOST=0.0.0.0
    ANYCABLE_PORT=8080
    ANYCABLE_PATH=/cable
    # RPC backend configuration (your Rails/Node.js app)
    ANYCABLE_RPC_HOST=your-backend-app.klutch.sh:50051
    # Redis configuration for pub/sub
    ANYCABLE_REDIS_URL=redis://redis-app.klutch.sh:8000/0
    ANYCABLE_REDIS_CHANNEL=__anycable__
    # Broadcasting adapter
    ANYCABLE_BROADCAST_ADAPTER=redis
    1. Add security settings:
    Terminal window
    # Secret key for JWT authentication (generate with: openssl rand -hex 32)
    ANYCABLE_SECRET=your-64-character-secret-key-here
    # Broadcast authentication key
    ANYCABLE_BROADCAST_KEY=your-broadcast-secret-key
    # Allowed origins for CORS (comma-separated)
    ANYCABLE_ALLOWED_ORIGINS=https://your-frontend.com,https://example-app.klutch.sh
    1. Configure logging and debugging (optional):
    Terminal window
    # Log level: debug, info, warn, error
    ANYCABLE_LOG_LEVEL=info
    # Enable debug mode for verbose logging
    ANYCABLE_DEBUG=false
    1. Add standalone mode settings (if not using RPC):
    Terminal window
    # Enable standalone mode (no RPC backend required)
    ANYCABLE_NORPC=true
    # Allow public connections without authentication
    ANYCABLE_PUBLIC=true
    # Enable public streams for direct subscriptions
    ANYCABLE_PUBLIC_STREAMS=true
    1. Mark sensitive values as secrets in the Klutch.sh UI to prevent them from appearing in logs.

Step 5: Deploy Your Application

    1. 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
    2. Click “Deploy” to start the build and deployment process.

    3. Monitor the build logs to ensure the deployment completes successfully. The build typically takes 1-2 minutes.

    4. 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

    1. Check the health endpoint:
    Terminal window
    curl https://example-app.klutch.sh/health

    You should receive a 200 OK response.

    1. Test WebSocket connectivity using a WebSocket client or browser console:
    // In browser console
    const 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);
    };
    1. Verify metrics endpoint (if enabled):
    Terminal window
    curl https://example-app.klutch.sh/metrics

Getting Started: Integration Examples

Rails Integration

Configure your Rails application to use AnyCable:

config/cable.yml:

production:
adapter: any_cable

config/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:

Terminal window
bundle exec anycable

Node.js Integration

For serverless or Node.js applications, use signed streams:

server.js:

const crypto = require('crypto');
// Generate a signed stream name
function signedStream(streamName, secret) {
const signature = crypto
.createHmac('sha256', secret)
.update(streamName)
.digest('base64url');
return `${streamName}--${signature}`;
}
// Use in your application
const 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 channel
const 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:

Terminal window
ANYCABLE_NORPC=true
ANYCABLE_PUBLIC=true
ANYCABLE_BROADCAST_ADAPTER=http
ANYCABLE_HTTP_BROADCAST_PORT=8090
ANYCABLE_BROADCAST_KEY=your-secret-key

Broadcasting from your backend:

Terminal window
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:

Terminal window
# Enable embedded NATS
ANYCABLE_PUBSUB=nats
ANYCABLE_BROADCAST_ADAPTER=nats
# Or use external NATS
ANYCABLE_NATS_SERVERS=nats://nats-server.klutch.sh:8000
ANYCABLE_NATS_CHANNEL=__anycable__

JWT Authentication

Enable JWT-based authentication for stateless connections:

Terminal window
ANYCABLE_JWT_ID_KEY=your-jwt-secret
ANYCABLE_JWT_ID_ENFORCE=true

Generate 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:

Terminal window
ANYCABLE_PATH=/cable,/admin/cable,/api/ws

Connection Limits and Tuning

For high-concurrency deployments:

Terminal window
# Ping interval (seconds)
ANYCABLE_PING_INTERVAL=3
# Disconnect rate limit (per second)
ANYCABLE_DISCONNECT_RATE=100
# Shutdown timeout (seconds)
ANYCABLE_SHUTDOWN_TIMEOUT=30

Production Best Practices

Security

  • Use HTTPS only: Klutch.sh provides automatic HTTPS for all apps
  • Set allowed origins: Configure ANYCABLE_ALLOWED_ORIGINS to prevent unauthorized connections
  • Use authentication: Enable JWT authentication or RPC-based auth
  • Rotate secrets: Periodically update ANYCABLE_SECRET and ANYCABLE_BROADCAST_KEY
  • Secure Redis: Use authentication for your Redis instance

Performance

  • Monitor connections: Track active connections via the /metrics endpoint
  • Scale horizontally: Deploy multiple AnyCable instances with shared Redis
  • Tune ping interval: Adjust ANYCABLE_PING_INTERVAL based on your use case
  • Use connection pooling: Configure Redis connection pool for high traffic

Monitoring

  • Prometheus metrics: Available at /metrics endpoint
  • Health checks: Use /health for load balancer health checks
  • Structured logging: Enable JSON logging for log aggregation

Key metrics to monitor:

  • anycable_clients_num: Current number of connected clients
  • anycable_broadcast_msg_total: Total broadcast messages sent
  • anycable_failed_auths_total: Failed authentication attempts
  • anycable_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_ORIGINS includes 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_HOST is 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_URL format: 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_ADAPTER is 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:
- redis

Run locally with:

Terminal window
docker-compose up -d

Access 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:

    1. Update your Dockerfile to use a specific version or latest:
    # Use a specific version
    FROM anycable/anycable-go:1.5
    # Or use latest (not recommended for production)
    FROM anycable/anycable-go:latest
    1. Commit and push the changes:
    Terminal window
    git add Dockerfile
    git commit -m "Update AnyCable to version 1.5"
    git push origin main
    1. Redeploy through the Klutch.sh dashboard.

    2. Verify the update by checking the logs for the version number.


Scaling AnyCable

Horizontal Scaling

Deploy multiple AnyCable instances with shared Redis:

  1. Ensure Redis is configured as the broadcast adapter
  2. Deploy additional AnyCable apps with the same configuration
  3. 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


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.