Skip to main content

Forced Hosts Configuration

ForcedHosts allows you to route players to specific backend servers based on the hostname they use to connect to your Gate proxy. This enables multiple domains to point to the same proxy but direct players to different servers.
ForcedHosts is available in classic mode (when lite.enabled: false). For lightweight deployments, see Gate Lite Mode which provides similar host-based routing with advanced load balancing.

How It Works

When a player connects to your Gate proxy, the client sends the hostname they used in the initial handshake packet. Gate examines this hostname and routes the player based on your ForcedHosts configuration.

Configuration

config.forcedHosts
object
Map of hostnames to server name lists. Keys are hostnames (case-insensitive), values are arrays of server names for load balancing.
forcedHosts:
  'creative.example.com': ['creative']
  'survival.example.com': ['survival']
  'lobby.example.com': ['lobby-1', 'lobby-2']

Key Features

Hostname-Only Matching

Port numbers are ignored - creative.example.com:25565 matches creative.example.com

Case-Insensitive

Creative.Example.COM matches creative.example.com

Load Balancing

List multiple servers per hostname for distribution

Automatic Fallback

Uses try list when no forced host matches

Basic Configuration

Simple Domain Routing

Route different domains to different game modes:
config.yml
config:
  bind: 0.0.0.0:25565
  
  servers:
    lobby: localhost:25566
    creative: localhost:25567
    survival: localhost:25568
    minigames: localhost:25569
  
  try:
    - lobby  # Default for unmatched hostnames
  
  forcedHosts:
    'creative.example.com': ['creative']
    'survival.example.com': ['survival']
    'games.example.com': ['minigames']
    'lobby.example.com': ['lobby']

Load Balancing Setup

Distribute players across multiple servers for the same hostname:
config.yml
config:
  servers:
    lobby-1: localhost:25566
    lobby-2: localhost:25567
    creative-1: localhost:25568
    creative-2: localhost:25569
    survival: localhost:25570
  
  try:
    - lobby-1
    - lobby-2
  
  forcedHosts:
    # Load balance between multiple lobby servers
    'lobby.example.com': ['lobby-1', 'lobby-2']
    
    # Load balance between multiple creative servers  
    'creative.example.com': ['creative-1', 'creative-2']
    
    # Single survival server
    'survival.example.com': ['survival']
Gate tries servers in order from the list. For advanced load balancing strategies (random, round-robin, least-connections), use Gate Lite mode.

Advanced Examples

Multi-Domain Network

Support multiple domains and aliases for a large server network:
config.yml
config:
  servers:
    hub: localhost:25566
    skyblock: localhost:25567
    prison: localhost:25568
    creative: localhost:25569
    survival: localhost:25570
  
  try:
    - hub
  
  forcedHosts:
    # Main network domains
    'play.mynetwork.com': ['hub']
    'hub.mynetwork.com': ['hub']
    
    # Game mode specific domains
    'skyblock.mynetwork.com': ['skyblock']
    'prison.mynetwork.com': ['prison']
    'creative.mynetwork.com': ['creative']
    'survival.mynetwork.com': ['survival']
    
    # Short aliases
    'sb.mynetwork.com': ['skyblock']
    'build.mynetwork.com': ['creative']

Development and Production

Separate development and production environments:
config.yml
config:
  servers:
    prod-lobby: production-lobby.internal:25565
    prod-survival: production-survival.internal:25565
    dev-lobby: dev-lobby.internal:25565
    dev-survival: dev-survival.internal:25565
    test-lobby: test-lobby.internal:25565
  
  try:
    - prod-lobby
  
  forcedHosts:
    # Production domains (public)
    'play.example.com': ['prod-lobby']
    'survival.example.com': ['prod-survival']
    
    # Development domains (internal)
    'dev.example.com': ['dev-lobby']
    'dev-survival.example.com': ['dev-survival']
    
    # Testing domains
    'test.example.com': ['test-lobby']
    'staging.example.com': ['dev-lobby']

Mixed Load Balancing Strategy

Combine load balancing with single servers:
config.yml
config:
  servers:
    lobby-1: 192.168.1.10:25565
    lobby-2: 192.168.1.11:25565
    creative-main: 192.168.1.20:25565
    creative-backup: 192.168.1.21:25565
    survival: 192.168.1.30:25565
    minigames-1: 192.168.1.40:25565
    minigames-2: 192.168.1.41:25565
  
  try:
    - lobby-1
    - lobby-2
  
  forcedHosts:
    # Load balanced lobbies (tries in order)
    'lobby.example.com': ['lobby-1', 'lobby-2']
    
    # Primary with backup fallback
    'creative.example.com': ['creative-main', 'creative-backup']
    
    # Single dedicated server
    'survival.example.com': ['survival']
    
    # Multiple game servers
    'games.example.com': ['minigames-1', 'minigames-2']

DNS Configuration

For ForcedHosts to work, configure DNS records to point all domains to your Gate proxy IP:
# Point each domain to Gate proxy
creative.example.com    A    203.0.113.10
survival.example.com    A    203.0.113.10
lobby.example.com       A    203.0.113.10
play.example.com        A    203.0.113.10

Behavior and Matching

Understanding how Gate matches hostnames:

Matching Rules

  1. Port Ignored - example.com:25565 matches example.com
  2. Case Insensitive - Example.COM matches example.com
  3. Exact Match - No wildcard or regex support
  4. Virtual Host Cleaning - Handles Forge FML separators automatically
  5. IP Addresses - Raw IP connections don’t match, use try list

Connection Examples

Given this configuration:
forcedHosts:
  'creative.example.com': ['creative-server']
  'survival.example.com': ['survival-server']

try:
  - lobby-server
How different connections are routed:
Player Connects ToRoutes ToReason
creative.example.com:25565creative-serverMatches forced host
CREATIVE.EXAMPLE.COM:25565creative-serverCase-insensitive match
survival.example.com:12345survival-serverPort ignored, hostname matches
other.example.com:25565lobby-serverNo match, uses try list
192.168.1.100:25565lobby-serverIP address, uses try list
example.com:25565lobby-serverNo match, uses try list

Forge/FML Handling

Forge clients append \x00FML\x00 to virtual host. Gate automatically strips this before matching:
# Forge client connects with: creative.example.com�FML�
# Gate normalizes to: creative.example.com
# Matches: 'creative.example.com'

Load Balancing Behavior

When multiple servers are listed for a hostname:
forcedHosts:
  'lobby.example.com': ['lobby-1', 'lobby-2', 'lobby-3']
Gate tries servers in order:
  1. Attempts connection to lobby-1
  2. If lobby-1 is offline or fails, tries lobby-2
  3. If lobby-2 is offline or fails, tries lobby-3
  4. If all fail, uses try list or disconnects player
This is sequential failover, not random load balancing. All players go to first available server. For true load balancing (random, round-robin, least-connections), use Gate Lite mode.

Complete Example

A full configuration for a multi-server network with forced hosts:
config.yml
config:
  bind: 0.0.0.0:25565
  onlineMode: true
  
  # Backend servers
  servers:
    # Main lobby servers (load balanced)
    lobby-1: 10.0.1.10:25565
    lobby-2: 10.0.1.11:25565
    
    # Game mode servers
    survival: 10.0.2.10:25565
    creative: 10.0.3.10:25565
    skyblock: 10.0.4.10:25565
    
    # Minigame servers
    bedwars: 10.0.5.10:25565
    skywars: 10.0.5.11:25565
    duels: 10.0.5.12:25565
    
    # Development
    dev: 10.0.9.10:25565
  
  # Default connection order
  try:
    - lobby-1
    - lobby-2
  
  # Hostname-based routing
  forcedHosts:
    # Main domain - load balanced lobbies
    'play.example.com': ['lobby-1', 'lobby-2']
    'lobby.example.com': ['lobby-1', 'lobby-2']
    
    # Game modes
    'survival.example.com': ['survival']
    'creative.example.com': ['creative']
    'skyblock.example.com': ['skyblock']
    
    # Minigames
    'bedwars.example.com': ['bedwars']
    'skywars.example.com': ['skywars']
    'duels.example.com': ['duels']
    
    # Development (internal only)
    'dev.example.internal': ['dev']
  
  # Player info forwarding
  forwarding:
    mode: velocity
    velocitySecret: your-secret-here
  
  # Enable failover
  failoverOnUnexpectedServerDisconnect: true

Troubleshooting

Problem: Players connecting to creative.example.com end up on wrong serverDiagnosis:
  1. Enable debug logging: debug: true
  2. Check logs for hostname Gate receives
  3. Verify DNS points to Gate proxy
  4. Test with /connect creative.example.com (if different result, it’s DNS)
Common Causes:
  • DNS not pointing to Gate
  • Hostname mismatch (check case, spacing)
  • Server name in forcedHosts doesn’t exist in servers section
  • Player connecting via IP address instead of domain
Problem: All players go to same server despite multiple listedExplanation: This is expected - Gate uses sequential failover, not random distributionSolution: For true load balancing, use Gate Lite mode with load balancing strategies:
lite:
  enabled: true
  routes:
    - host: 'lobby.example.com'
      backend: ['lobby-1:25565', 'lobby-2:25565']
      strategy: random  # or round-robin, least-connections
Problem: Players connecting via IP address don’t get routedExplanation: This is expected - ForcedHosts only work with domain namesSolutions:
  • Encourage players to use domain names
  • Configure try list as your “default” routing
  • Block IP connections: set server-ip=127.0.0.1 on Gate bind
Error: Forced host "creative.example.com" server "creative" must be registered under serversSolution: Add server to servers section:
servers:
  creative: localhost:25567  # Add this

forcedHosts:
  'creative.example.com': ['creative']
Problem: Players get disconnected when hostname doesn’t matchDiagnosis:
  • Check try list is configured with available servers
  • Verify servers in try list exist in servers section
  • Check if servers in try list are actually online
Solution:
servers:
  lobby: localhost:25566

try:
  - lobby  # Must exist in servers

Migration from Broken Configs

If you configured ForcedHosts before it was fixed (PR #560), your configuration should now work automatically! The fix included proper hostname extraction, case normalization, and fallback behavior.
No changes needed - existing forcedHosts configurations will work after updating Gate.

Comparison: ForcedHosts vs Gate Lite

FeatureForcedHosts (Classic)Gate Lite
Hostname-based routing
Sequential failover
Random load balancing
Round-robin
Least-connections
Lowest-latency
Wildcard hostnames
Hostname regex✅ (patterns)
Server switching✅ (/server command)❌ (thin proxy)
Proxy commands
Extensions/plugins✅ (full access)⚠️ (limited)
PerformanceGoodExcellent (lower latency)
For advanced routing and load balancing, consider Gate Lite mode.

Best Practices

Choose clear, memorable hostnames:
  • creative.example.com, survival.example.com
  • s1.example.com, server2.example.com
Always have reliable fallback servers in try list for unmatched hostnames or IP connections:
try:
  - lobby-1
  - lobby-2
  - hub
Keep documentation of which domains route where. Add comments:
forcedHosts:
  # Public domains
  'play.example.com': ['lobby-1', 'lobby-2']
  
  # Internal domains
  'dev.internal': ['dev-server']
After configuration changes, test each hostname:
# Test from Minecraft client
# Connect to: creative.example.com
# Verify lands on creative server
If using wildcard DNS (*.example.com), remember all subdomains will resolve. Consider:
  • Adding explicit forcedHosts for intended subdomains
  • Having good default try list for unmatched subdomains

Servers

Configure backend servers and try list

Gate Lite Mode

Advanced host-based routing with load balancing

Forwarding

Forward player info to backend servers

Status Ping

Customize server list appearance per hostname

Build docs developers (and LLMs) love