Skip to content

Customization Overview

Passage is designed to be highly customizable while maintaining simplicity. This page provides an overview of customization options and helps you choose the right approach for your network.

Passage follows a progressive enhancement philosophy:

  1. Start with fixed adapters — Get running quickly with static configuration
  2. Add dynamic elements — Introduce DNS discovery, HTTP status, or Agones as needed
  3. Implement custom logic — Use gRPC adapters for complex requirements
  4. Monitor and optimize — Add observability and fine-tune performance

You don’t need to use all features at once. Many successful networks run with just fixed adapters.

  • Network binding address and port
  • Connection timeouts
  • Rate limiting (per-IP connection flood protection)
  • PROXY protocol support for load balancers
  • Authentication cookie expiry

Configuration Reference

Each route independently configures five adapter categories:

CategoryWhat It ControlsOptions
StatusServer list response (MOTD, player count, favicon)fixed, http, grpc
AuthenticationPlayer identity verificationmojang, disabled, fixed, grpc
DiscoveryHow backend servers are foundfixed_discovery, dns_discovery, agones_discovery, grpc_discovery
Discovery ActionsHow the target list is filtered/orderedmeta_filter, player_allow_filter, player_block_filter, player_fill_strategy, grpc
LocalizationDisconnect message translationsfixed, grpc

Adapter Overview

  • OpenTelemetry traces, metrics, and logs
  • Sentry error tracking
  • Structured logging with configurable levels

Monitoring Guide

2-3 fixed servers, simple routing:

routes:
- hostname: "mc.example.net"
status:
type: fixed
name: "My Network"
discovery:
type: fixed_discovery
targets:
- identifier: "lobby"
address: "10.0.0.10:25565"

Complexity: None — pure configuration.

Fill the fullest server below capacity:

routes:
- hostname: "mc.example.net"
discovery:
type: fixed_discovery
targets:
- identifier: "lobby-1"
address: "10.0.1.10:25565"
meta: { players: "45" }
- identifier: "lobby-2"
address: "10.0.1.11:25565"
meta: { players: "38" }
actions:
- type: player_fill_strategy
field: "players"
max_players: 50

Complexity: Low — requires updating player counts in metadata (or use DNS/Agones for dynamic data).

Automatic server discovery with metadata-based filtering:

routes:
- hostname: "mc.example.net"
discovery:
type: dns_discovery
domain: "servers.example.net"
record_type: srv
actions:
- type: meta_filter
rules:
- key: "status"
op: equals
value: "online"
- type: player_fill_strategy
field: "players"
max_players: 50

Complexity: Medium — requires DNS infrastructure.

Cloud deployment with dynamic game servers:

routes:
- hostname: "mc.example.net"
status:
type: http
address: "http://status-service.minecraft/status"
cache_duration: 30
discovery:
type: agones_discovery
namespace: "minecraft"
selectors:
- matchLabels:
game: "minecraft"
type: "lobby"
scheduling: "Packed"

Complexity: Medium — requires Kubernetes and Agones setup. See Kubernetes Guide.

Full gRPC adapter stack for complex logic:

routes:
- hostname: "mc.example.net"
status:
type: grpc
address: "http://status-service:50051"
discovery:
type: grpc_discovery
address: "http://discovery-service:50051"
actions:
- type: grpc
name: "region-router"
address: "http://router-service:50051"

Complexity: High — requires custom gRPC services. See Custom gRPC Adapters.

  • Choose the simplest adapter that meets your needs
  • Keep adapter response times under 50ms — slow adapters delay player connections
  • Enable rate limiting in production
  • Start with fixed adapters and upgrade as your needs grow
  • Monitor adapter performance with OpenTelemetry
  • Test configuration changes in a staging environment before production
  • Use descriptive name fields on discovery actions for easier debugging