Docker Deployment Guide
December 4, 2025 ยท View on GitHub
SuperChat provides two Docker images:
- Server:
aeolun/superchat:latest- The chat server - Website:
aeolun/superchat-website:latest- The marketing website
Quick Start
Using Docker Run
# Run the server
docker run -d \
--name superchat \
-p 6465:6465 \
-v superchat-data:/data \
aeolun/superchat:latest
# View logs
docker logs -f superchat
# Stop the server
docker stop superchat
Using Docker Compose
The docker-compose.yml runs both server and website:
docker-compose up -d
Services:
- superchat - Chat server on port 6465
- website - Marketing site on port 8080
Note: SuperChat uses a custom binary TCP protocol (not HTTP), so port 6465 must be exposed directly. HTTP reverse proxies like Caddy/Nginx won't work without their TCP streaming modules.
Clients connect to: superchat.win:6465 or your-server-ip:6465
Website: http://localhost:8080
Configuration
The server auto-creates a default config at /data/config.toml on first run.
Option 1: Environment Variables (Recommended for Docker)
Configuration can be overridden using environment variables:
docker run -d \
--name superchat \
-p 6465:6465 \
-e SUPERCHAT_SERVER_TCP_PORT=8080 \
-e SUPERCHAT_LIMITS_MAX_MESSAGE_LENGTH=8192 \
-v superchat-data:/data \
aeolun/superchat:latest
Available environment variables:
Server Section:
SUPERCHAT_SERVER_TCP_PORT- Main TCP port (default: 6465)SUPERCHAT_SERVER_SSH_PORT- SSH port (default: 6466)SUPERCHAT_SERVER_SSH_HOST_KEY- Path to SSH host keySUPERCHAT_SERVER_DATABASE_PATH- Database file path
Limits Section:
SUPERCHAT_LIMITS_MAX_CONNECTIONS_PER_IP- Max connections per IP (default: 10)SUPERCHAT_LIMITS_MESSAGE_RATE_LIMIT- Messages per minute (default: 10)SUPERCHAT_LIMITS_MAX_MESSAGE_LENGTH- Max message bytes (default: 4096)SUPERCHAT_LIMITS_MAX_NICKNAME_LENGTH- Max nickname length (default: 20)SUPERCHAT_LIMITS_SESSION_TIMEOUT_SECONDS- Session timeout (default: 120)
Retention Section:
SUPERCHAT_RETENTION_DEFAULT_RETENTION_HOURS- Message retention hours (default: 168 = 7 days)SUPERCHAT_RETENTION_CLEANUP_INTERVAL_MINUTES- Cleanup interval (default: 60)
Discovery Section:
SUPERCHAT_DISCOVERY_DIRECTORY_ENABLED- Accept server registrations (default: true)SUPERCHAT_DISCOVERY_PUBLIC_HOSTNAME- Public hostname/IP for clients (auto-detect if empty)SUPERCHAT_DISCOVERY_SERVER_NAME- Display name in directory (default: "SuperChat Server")SUPERCHAT_DISCOVERY_SERVER_DESCRIPTION- Description in directory (default: "A SuperChat community server")SUPERCHAT_DISCOVERY_MAX_USERS- User limit, 0 = unlimited (default: 0)
Option 2: Config File
To customize via config file:
- Run the container once to generate the default config
- Copy it out:
docker cp superchat:/data/config.toml ./config.toml - Edit
config.toml - Mount it back:
docker run -v ./config.toml:/data/config.toml ...
Or create your own config and mount it:
docker run -d \
--name superchat \
-p 6465:6465 \
-v superchat-data:/data \
-v ./my-config.toml:/data/config.toml \
aeolun/superchat:latest
Note: Environment variables override config file values.
Data Persistence
All data is stored in /data inside the container:
/data/superchat.db- SQLite database (messages, channels, sessions)/data/config.toml- Server configuration/data/superchat.db-wal- Write-Ahead Log (SQLite WAL mode)/data/superchat.db-shm- Shared memory file (SQLite WAL mode)
Important: Always use a named volume or bind mount for /data to persist data.
Building the Images
SuperChat uses Depot for fast multi-platform builds via depot bake.
Build all images (server + website)
make docker-build # Build all images locally
make docker-build-push # Build and push all images to Docker Hub
Build individual images
make docker-build-server # Build only server
make docker-build-website # Build only website
Manual build without Depot
# Server
docker build -t aeolun/superchat:latest .
# Website (run from repo root to include shared docs)
docker build -f website/Dockerfile -t aeolun/superchat-website:latest .
Publishing to Docker Hub
# Login (first time only)
docker login
# Build and push all images
make docker-build-push
Images are built for both linux/amd64 and linux/arm64 platforms.
Image Details
Server Image (aeolun/superchat)
- Base Image: Alpine Linux (minimal)
- Size: ~30MB
- User: Runs as non-root user
superchat(UID 1000) - Port: 6465 (TCP)
- Volume:
/data - Platforms: linux/amd64, linux/arm64
Website Image (aeolun/superchat-website)
- Base Image: nginx:alpine
- Size: ~25MB
- User: Runs as nginx default user
- Port: 80 (HTTP)
- Platforms: linux/amd64, linux/arm64
Security
The container:
- Runs as non-root user (
superchat) - Uses Alpine Linux for minimal attack surface
- Only exposes port 6465
- All data isolated in
/datavolume
Troubleshooting
Check if container is running
docker ps | grep superchat
View logs
docker logs superchat
docker logs -f superchat # Follow logs
Access container shell
docker exec -it superchat sh
Inspect database
docker exec superchat ls -la /data
Port already in use
If you get "address already in use", either:
- Stop the conflicting service on port 6465
- Use a different port:
-p 8070:6465
Build Configuration
The build process uses docker-bake.hcl to build both images simultaneously:
group "default" {
targets = ["server", "website"]
}
target "server" {
context = "."
dockerfile = "Dockerfile"
platforms = ["linux/amd64", "linux/arm64"]
tags = ["aeolun/superchat:latest", "aeolun/superchat:${VERSION}"]
}
target "website" {
context = "./website"
dockerfile = "Dockerfile"
platforms = ["linux/amd64", "linux/arm64"]
tags = ["aeolun/superchat-website:latest", "aeolun/superchat-website:${VERSION}"]
}
Version is automatically set from git tags. The build produces:
aeolun/superchat:latestandaeolun/superchat:<version>aeolun/superchat-website:latestandaeolun/superchat-website:<version>