Web application for managing game servers running as Docker containers. Features real-time status monitoring, backup scheduling, and Discord notifications via a secure admin interface.
- Features
- Screenshots
- Architecture
- Quick Start
- Management
- Volume Mounts
- Game Server Backups
- External Integrations
- Troubleshooting
- Migration Guide
- Development
- Security
- License
- Contributing
GSM is a modern web-based platform for managing, provisioning, and controlling game servers using Docker Compose.
With GSM, you can:
- Create and deploy new game servers from Compose templates via the web UI
- Monitor real-time status of all managed servers
- Start, stop, restart, and remove game server containers
- Schedule and manage automated backups (with Discord notifications)
- View and edit server details, connection info, and configuration
- Manage Compose files and server definitions directly in the browser
GSM supports both managing existing Docker containers and provisioning new ones, all from a secure, role-based admin interface. See the documentation for advanced Compose management, backup strategies, and integration details.
This project uses several external APIs and services for enhanced functionality, security, and game metadata. See docs/integrations.md for a full list and details on each integration.
- Server Dashboard: Real-time status indicators and connection details
- Admin Control: Start, stop, restart, and backup game servers
- Automated Backups: Scheduled backups with Discord webhook notifications
- User Authentication: Role-based access control (first user becomes admin)
- Docker Integration: Manages external containers via Docker API
- SSL Management: Simple HTTPS setup via Nginx Proxy Manager web UI
πΈ View Application Screenshots (click to expand)
See docs/architecture.md for traffic flow diagrams and security model.
mkdir gsm && cd gsm
curl -O https://raw.githubusercontent.com/michaelsstuff/gsm/main/docker-compose.yml
export MONGO_PASSWORD=$(openssl rand -hex 24)
export SESSION_SECRET=$(openssl rand -hex 48)
export JWT_SECRET=$(openssl rand -hex 48)
docker compose up -d
# Configure SSL at http://YOUR_IP:81, then access https://your-domain.com- Docker and Docker Compose
- Domain name pointing to your server
- Ports 80, 81, and 443 available
mkdir gsm && cd gsmCreate docker-compose.yml:
services:
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:latest
container_name: gsm-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "81:81"
volumes:
- gsm-proxy-data:/data
- gsm-proxy-letsencrypt:/etc/letsencrypt
networks:
- gsm-network
environment:
DISABLE_IPV6: ${DISABLE_IPV6:-false}
mongodb:
image: mongo:5.0
container_name: gsm-mongodb
restart: unless-stopped
volumes:
- mongodb-data:/data/db
environment:
MONGO_INITDB_ROOT_USERNAME: admin
# MongoDB requires the variable name MONGO_INITDB_ROOT_PASSWORD, but you only need to set MONGO_PASSWORD in your .env
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD:?MONGO_PASSWORD must be set}
networks:
- gsm-network
backend:
image: michaelsstuff/gsm-backend:latest
container_name: gsm-backend
restart: unless-stopped
depends_on:
- mongodb
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:5000/api/auth/status', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
volumes:
- /var/run/docker.sock:/var/run/docker.sock # REQUIRED: Docker API access
- ${BACKUP_PATH:-./backups}:/app/backups # REQUIRED: Backup storage path
- ${GAME_VOLUMES_PATH:-/var/opt/container-volumes}:/app/container-volumes:ro # OPTIONAL: Game server data for backups
environment:
NODE_ENV: production # REQUIRED: Set to 'production'
PORT: 5000 # REQUIRED: Backend port
CLIENT_URL: ${CLIENT_URL:-http://localhost:3000} # OPTIONAL: Frontend URL (for CORS)
MONGO_URI: mongodb://admin:${MONGO_PASSWORD}@mongodb:27017/gameserver-manager?authSource=admin # REQUIRED: MongoDB connection string
SESSION_SECRET: ${SESSION_SECRET:?SESSION_SECRET must be set} # REQUIRED: Session secret
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET must be set} # REQUIRED: JWT secret
BACKUP_PATH: /app/backups # REQUIRED: Path inside container for backups
STEAMGRIDDB_API_KEY: ${STEAMGRIDDB_API_KEY} # OPTIONAL: SteamGridDB API key for icons
networks:
- gsm-network
frontend:
image: michaelsstuff/gsm-frontend:latest
container_name: gsm-frontend
restart: unless-stopped
depends_on:
backend:
condition: service_healthy
networks:
- gsm-network
networks:
gsm-network:
driver: bridge
volumes:
mongodb-data:
gsm-proxy-data:
gsm-proxy-letsencrypt:Create .env:
MONGO_PASSWORD=$(openssl rand -hex 24)
SESSION_SECRET=$(openssl rand -hex 48)
JWT_SECRET=$(openssl rand -hex 48)Or use shell exports:
export MONGO_PASSWORD=$(openssl rand -hex 24)
export SESSION_SECRET=$(openssl rand -hex 48)
export JWT_SECRET=$(openssl rand -hex 48)docker compose up -dπ‘ Local Testing: Use
localhostas Domain Name and skip SSL configuration (access viahttp://localhost).
- Access NPM:
http://YOUR_SERVER_IP:81 - On first visit, register admin account
- Add Proxy Host:
- Domain:
your-domain.com - Forward to:
gsm-frontendport80 - Enable: Block Common Exploits, Websockets Support
- Domain:
- SSL Tab: Request SSL Certificate, enable Force SSL and HSTS
- Access:
https://your-domain.com
π Full NPM guide: https://nginxproxymanager.com/guide/
- Register first user (auto-admin)
- Login β Admin Dashboard
- Add game servers with Docker container names
# View logs
docker compose logs -f
# Update images
docker compose pull && docker compose up -d
# Restart
docker compose restart
# Stop
docker compose down
# Backup MongoDB
docker exec gsm-mongodb mongodump \
--username admin \
--password YOUR_MONGO_PASSWORD \
--authenticationDatabase admin \
--db gameserver-manager \
--archive=/data/db/backup.gz \
--gzipBackend requires these mounts:
| Mount | Purpose |
|---|---|
/var/run/docker.sock |
Docker API access to control containers |
/var/opt/container-volumes |
Parent directory containing game server data (read-only) |
./backups |
Where backup archives are stored |
For backups to work, your game server containers must store their persistent data in subdirectories named after the container name you configure in GSM.
Example: When you add a server in GSM with container name minecraft-server, the backup system looks for data at:
/var/opt/container-volumes/minecraft-server/
You control this by configuring your game server's Docker volume mounts:
# Your game server's docker-compose.yml
services:
minecraft-server: # β This is the container name
image: itzg/minecraft-server
volumes:
- /var/opt/container-volumes/minecraft-server:/data # β Must match!Expected structure:
/var/opt/container-volumes/
βββ minecraft-server/ # Matches container name "minecraft-server"
βββ valheim-server/ # Matches container name "valheim-server"
βββ terraria-server/ # Matches container name "terraria-server"
When you trigger a backup in GSM, it archives the directory matching the container name you specified.
Adjust paths in .env if your setup differs:
GAME_VOLUMES_PATH=/your/path
BACKUP_PATH=/your/pathConfigure automated backups per server via Admin Dashboard:
- Cron Schedule: e.g.,
0 2 * * *for daily at 2 AM - Retention: Number of backups to keep
- Discord Webhook: Optional notifications
Backups execute automatically on schedule or via "Backup Now" button.
See docs/troubleshooting.md for common issues and solutions.
See docs/migration-guide.md for step-by-step instructions on moving GSM to a new server.
See docs/development.md for building and running GSM from source.
See SECURITY.md for vulnerability reporting instructions and supported versions.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
See CONTRIBUTING.md for contribution guidelines, pull request expectations, and testing requirements.


