A high-performance, open-source WebSocket server written in Go that's compatible with Pusher and PusherJS SDK.
- Pusher Compatibility: Works seamlessly with PusherJS SDK and Pusher protocol
- High Performance: Built on Fiber framework for exceptional speed and low latency
- Lightweight: Dockerfile is ~10MB, really low memory and cpu usage
- Production Ready: Graceful shutdown, error handling, and logging
- Go 1.24.6 or higher
git clone https://github.com/mertek-dev/go-pusher.git
cd go-pushergo mod download# Development mode
make dev
# Or directly with Go
go run cmd/server/main.goThe server will start on http://localhost:8080 by default.
# Start the service
docker-compose up -d
# View logs
docker-compose logs -f
# Stop the service
docker-compose down# Build the image
docker build -t go-pusher .
# Run the container
docker run -p 8080:8080 go-pusherGo Pusher supports both HTTP and HTTPS/WSS connections. You can enable TLS for secure communications.
# Generate self-signed certificates for development
./scripts/generate-certs.sh
# Start with TLS enabled
docker-compose up -dEnvironment Variables:
# Enable TLS
GOPUSHER_SERVER_ENABLE_TLS=true
# Certificate files (mounted in Docker)
GOPUSHER_SERVER_TLS_CERT_FILE=/certs/server.crt
GOPUSHER_SERVER_TLS_KEY_FILE=/certs/server.key
# TLS port (default: 8443)
GOPUSHER_SERVER_TLS_PORT=8443Access URLs:
- HTTP:
http://localhost:8080 - HTTPS:
https://localhost:8443 - WS:
ws://localhost:8080/app/your-app-key - WSS:
wss://localhost:8443/app/your-app-key
For production, use certificates from a trusted Certificate Authority:
# Mount your production certificates
docker run -d \
--name go-pusher-tls \
-p 8080:8080 -p 8443:8443 \
-v /path/to/production/certs:/certs:ro \
-e GOPUSHER_SERVER_ENABLE_TLS=true \
-e GOPUSHER_SERVER_TLS_CERT_FILE=/certs/production.crt \
-e GOPUSHER_SERVER_TLS_KEY_FILE=/certs/production.key \
-e GOPUSHER_APP_PROD_KEY=prod-key \
-e GOPUSHER_APP_PROD_SECRET=prod-secret \
ghcr.io/mertek-dev/go-pusher:latestThis project automatically builds and publishes Docker images to GitHub Container Registry on every push to the main branch and on tag releases.
# Pull and run the latest image
docker run -d \
--name go-pusher \
-p 8080:8080 \
-e GOPUSHER_APP_LOCAL_KEY=local-key \
-e GOPUSHER_APP_LOCAL_SECRET=local-secret \
ghcr.io/mertek-dev/go-pusher:latestRepository: ghcr.io/mertek-dev/go-pusher
Tags:
main- Latest from main branch0.1.0- Specific version releasesmain-abc123- Commit-based tags (for testing specific commits)
Architectures:
linux/amd64(Intel/AMD 64-bit)linux/arm64(ARM 64-bit - Apple Silicon, AWS Graviton, etc.)
# List available tags
docker search ghcr.io/mertek-dev/go-pusher
# Pull specific image
docker pull ghcr.io/mertek-dev/go-pusher:latest
docker pull ghcr.io/mertek-dev/go-pusher:0.1.0
# Check image details
docker inspect ghcr.io/mertek-dev/go-pusher:latestBasic Usage:
# Simple run
docker run -p 8080:8080 ghcr.io/mertek-dev/go-pusher:latest
# Run in background
docker run -d --name go-pusher -p 8080:8080 ghcr.io/mertek-dev/go-pusher:latest
# Run with custom port
docker run -p 9000:8080 ghcr.io/mertek-dev/go-pusher:latestWith Configuration:
# Single app configuration
docker run -d \
--name go-pusher \
-p 8080:8080 \
-e GOPUSHER_APP_LOCAL_KEY=local-key \
-e GOPUSHER_APP_LOCAL_SECRET=local-secret \
ghcr.io/mertek-dev/go-pusher:latest
# Multiple apps configuration
# {LOCAL} and {PROD} will be id for the app (lowercase)
docker run -d \
--name go-pusher \
-p 8080:8080 \
-e GOPUSHER_APP_LOCAL_KEY=local-key \
-e GOPUSHER_APP_LOCAL_SECRET=local-secret \
-e GOPUSHER_APP_PROD_KEY=prod-key \
-e GOPUSHER_APP_PROD_SECRET=prod-secret \
ghcr.io/mertek-dev/go-pusher:latestCreate a docker-compose.yml file:
version: '3.8'
services:
go-pusher:
image: ghcr.io/mertek-dev/go-pusher:latest
container_name: go-pusher
ports:
- "8080:8080"
- "8443:8443" # TLS port
environment:
- GOPUSHER_APP_LOCAL_KEY=local-key
- GOPUSHER_APP_LOCAL_SECRET=local-secret
- GOPUSHER_LOG_LEVEL=info
# TLS Configuration (uncomment to enable)
# - GOPUSHER_SERVER_ENABLE_TLS=true
# - GOPUSHER_SERVER_TLS_CERT_FILE=/certs/server.crt
# - GOPUSHER_SERVER_TLS_KEY_FILE=/certs/server.key
# - GOPUSHER_SERVER_TLS_PORT=8443
volumes:
# Mount TLS certificates (uncomment to enable TLS)
# - ./certs:/certs:ro
restart: unless-stopped
healthcheck:
test: ["CMD", "/server", "-health"]
interval: 30s
timeout: 10s
retries: 3Basic Usage:
docker-compose up -dWith TLS Enabled:
# Generate certificates first
./scripts/generate-certs.sh
# Uncomment TLS lines in docker-compose.yml, then:
docker-compose up -dEnvironment Variables:
# Server configuration
GOPUSHER_SERVER_HOST=0.0.0.0
GOPUSHER_SERVER_PORT=8080
GOPUSHER_LOG_LEVEL=info
# TLS configuration (for production)
GOPUSHER_SERVER_ENABLE_TLS=true
GOPUSHER_SERVER_TLS_CERT_FILE=/certs/production.crt
GOPUSHER_SERVER_TLS_KEY_FILE=/certs/production.key
GOPUSHER_SERVER_TLS_PORT=8443
# App configuration
GOPUSHER_APP_PROD_KEY=your-production-key
GOPUSHER_APP_PROD_SECRET=your-production-secret
GOPUSHER_APP_PROD_MAX_CONNECTIONS=10000
GOPUSHER_APP_PROD_MAX_CHANNEL_NAME_LENGTH=200Docker Run with Production Settings:
docker run -d \
--name go-pusher-prod \
--restart unless-stopped \
-p 8080:8080 -p 8443:8443 \
-v /path/to/production/certs:/certs:ro \
-e GOPUSHER_SERVER_HOST=0.0.0.0 \
-e GOPUSHER_SERVER_PORT=8080 \
-e GOPUSHER_LOG_LEVEL=info \
-e GOPUSHER_SERVER_ENABLE_TLS=true \
-e GOPUSHER_SERVER_TLS_CERT_FILE=/certs/production.crt \
-e GOPUSHER_SERVER_TLS_KEY_FILE=/certs/production.key \
-e GOPUSHER_SERVER_TLS_PORT=8443 \
-e GOPUSHER_APP_PROD_KEY=your-production-key \
-e GOPUSHER_APP_PROD_SECRET=your-production-secret \
-e GOPUSHER_APP_PROD_MAX_CONNECTIONS=10000 \
-e GOPUSHER_APP_PROD_MAX_CHANNEL_NAME_LENGTH=200 \
ghcr.io/mertek-dev/go-pusher:latestThe container includes built-in health checks:
# Check container health
docker ps
docker inspect go-pusher | grep Health -A 10
# Manual health check
docker exec go-pusher /server -health# Stop and remove container
docker stop go-pusher
docker rm go-pusher
# Remove image
docker rmi ghcr.io/mertek-dev/go-pusher:latest
# Clean up unused images
docker image prune -fThe server can be configured using environment variables or a .env file. All configuration keys are prefixed with GOPUSHER_. See env.example.
Go Pusher supports multiple application configurations, allowing you to manage different environments (local, staging, production) with their own settings. Each app can have its own:
- Unique ID and Key: For identification and authentication
- Secret: For API authentication
- Connection Limits: Maximum concurrent connections and channel name length
- Enabled/Disabled State: Control which apps are active
Apps are configured using environment variables following this pattern:
GOPUSHER_APP_{APP_ID}_{FIELD}
Where:
{APP_ID}is your app identifier (e.g., LOCAL, STAGING, PROD){FIELD}is the configuration field (e.g., KEY, SECRET, ENABLED)
| Variable | Default | Description |
|---|---|---|
GOPUSHER_APP_NAME |
Go Pusher |
Application name |
GOPUSHER_SERVER_HOST |
0.0.0.0 |
Server host address |
GOPUSHER_SERVER_PORT |
8080 |
Server port |
GOPUSHER_SERVER_READ_TIMEOUT |
30s |
Read timeout duration |
GOPUSHER_SERVER_WRITE_TIMEOUT |
30s |
Write timeout duration |
GOPUSHER_SERVER_IDLE_TIMEOUT |
120s |
Idle timeout duration |
GOPUSHER_SERVER_BODY_LIMIT |
104857600 |
Maximum request body size (100MB) |
GOPUSHER_SERVER_READ_BUFFER_SIZE |
1048576 |
Read buffer size (1MB) |
GOPUSHER_SERVER_WRITE_BUFFER_SIZE |
1048576 |
Write buffer size (1MB) |
GOPUSHER_SERVER_PREFORK |
false |
Enable prefork mode |
GOPUSHER_LOG_LEVEL |
info |
Logging level (debug, info, warn, error, fatal, panic) |
Each app supports these configuration fields:
{ID} will be the your-app-id that you can use in your pusher-js client sdk, but in lowercase.
For example. If you starts the server with env GOPUSHER_APP_LOCAL_KEY=xxx, the local will be your-app-id.
| Field | Required | Default | Description |
|---|---|---|---|
GOPUSHER_APP_{ID}_KEY |
Yes | - | Unique authentication key |
GOPUSHER_APP_{ID}_SECRET |
No | "" | API authentication secret |
GOPUSHER_APP_{ID}_ENABLED |
No | true | Whether the app is active |
GOPUSHER_APP_{ID}_MAX_CONNECTIONS |
No | 1000 | Max concurrent connections |
GOPUSHER_APP_{ID}_MAX_CHANNEL_NAME_LENGTH |
No | 100 | Max channel name length |
import Pusher from 'pusher-js';
const pusher = new Pusher('your-app-id', {
wsHost: 'localhost',
wsPort: 8080,
forceTLS: false,
enabledTransports: ['ws', 'wss'],
disableStats: true,
cluster: 'mt1'
});
const channel = pusher.subscribe('my-channel');
channel.bind('my-event', function(data) {
console.log('Received:', data);
});const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:8080/app/your-app-id');
ws.on('open', function open() {
console.log('Connected to Go Pusher server');
});
ws.on('message', function message(data) {
console.log('Received:', data.toString());
});
ws.on('close', function close() {
console.log('Disconnected from server');
});# Local Development App
GOPUSHER_APP_LOCAL_KEY=unique-uuid-key-1
GOPUSHER_APP_LOCAL_SECRET=local-secret-key
GOPUSHER_APP_LOCAL_ENABLED=true
GOPUSHER_APP_LOCAL_MAX_CONNECTIONS=1000
# Production App
GOPUSHER_APP_PROD_KEY=prod-unique-key-3
GOPUSHER_APP_PROD_SECRET=prod-secret-key
GOPUSHER_APP_PROD_ENABLED=true
GOPUSHER_APP_PROD_MAX_CONNECTIONS=10000package main
import (
"log"
"github.com/mertek-dev/go-pusher/internal/config"
"github.com/mertek-dev/go-pusher/internal/app"
)
func main() {
// Load configuration (includes apps)
cfg, err := config.Load()
if err != nil {
log.Fatal("Failed to load configuration:", err)
}
// Create app manager
appManager := app.NewAppManager(cfg.Apps)
// Find apps by ID or key
localApp := appManager.FindByID("local")
prodApp := appManager.FindByKey("prod-unique-key-3")
if localApp != nil {
log.Printf("Local app: %s, Max connections: %d",
localApp.ID, localApp.MaxConnections)
}
}go-pusher/
βββ cmd/
β βββ server/
β βββ main.go # Application entry point
βββ internal/
β βββ api/
β β βββ router.go # HTTP router setup
β β βββ socket/
β β βββ handler.go # WebSocket handlers
β βββ config/
β βββ config.go # Configuration management
βββ go.mod # Go module file
βββ go.sum # Go module checksums
βββ Makefile # Build and development commands
βββ README.md # This file
# Build for current platform
go build -o go-pusher cmd/server/main.go
# Build for specific platform
GOOS=linux GOARCH=amd64 go build -o go-pusher-linux-amd64 cmd/server/main.gogo test ./...go fmt ./...golangci-lint runWe welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Go coding standards and conventions
- Add tests for new features
- Update documentation as needed
- Use meaningful variable names
- Keep functions small and focused
This project is licensed under the MIT License.
- Fiber - Fast HTTP framework for Go
- Pusher - Real-time communication platform
- Soketi - Pusher-compatible, open-source WebSockets server
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Wiki