Configuration Basics
This guide covers the basics of configuring Passage for your Minecraft network. For the complete field-by-field reference, see the Configuration Reference.
Configuration Files
Section titled “Configuration Files”Passage uses a layered configuration system. Higher layers override lower ones:
- Environment Variables — Override any setting at runtime
- Auth Secret File — Dedicated file for the authentication cookie secret
- Config File — Your deployment-specific settings (YAML, TOML, or JSON)
- Built-in Defaults — Sensible defaults compiled into the binary
File Locations
Section titled “File Locations”Directoryconfig/
- config.yaml Your configuration file
- auth_secret Authentication cookie secret (optional)
Both the config file and auth secret file paths can be customized via environment variables:
# Default: config/config (auto-detects .yaml, .toml, .json extension)CONFIG_FILE=config/config
AUTH_SECRET_FILE=config/auth_secretRoutes-Based Configuration
Section titled “Routes-Based Configuration”Unlike traditional Minecraft proxies that use a flat configuration, Passage organizes everything into routes. Each route matches a hostname pattern and defines its own set of adapters:
routes:- hostname: "mc.example.net" status: type: fixed name: "My Network" authentication: type: mojang discovery: type: fixed_discovery targets: - identifier: "lobby-1" address: "10.0.1.10:25565"This is conceptually similar to virtual hosts in a web server — each hostname gets its own independent configuration. See Adapters for a full overview of the adapter system.
Minimal Configuration
Section titled “Minimal Configuration”The simplest working configuration:
routes:- hostname: ".*" discovery: type: fixed_discovery targets: - identifier: "server-1" address: "127.0.0.1:25566"This configuration:
- Listens on
0.0.0.0:25565(the default) - Matches any hostname (
.*is a regex) - Uses Mojang authentication (the default)
- Returns the default status response
- Routes all players to
127.0.0.1:25566
Most settings have sensible defaults, so you only need to configure what you want to change.
Environment Variables
Section titled “Environment Variables”All configuration fields can be overridden with environment variables using the format PASSAGE_<FIELD>:
export PASSAGE_ADDRESS="0.0.0.0:25565"export PASSAGE_TIMEOUT=120Custom Prefix
Section titled “Custom Prefix”Change the default PASSAGE prefix:
ENV_PREFIX=MYNETWORKMYNETWORK_ADDRESS="0.0.0.0:25565" passageCore Settings
Section titled “Core Settings”Connection Settings
Section titled “Connection Settings”# Bind address for incoming connections (default: "0.0.0.0:25565")address: "0.0.0.0:25565"
# Connection timeout in seconds (default: 120)timeout: 120
# Maximum packet size in bytes (default: 2097152 / 2 MiB)max_packet_length: 2097152
# Authentication cookie expiry in seconds (default: 30)auth_cookie_expiry: 30Rate Limiting
Section titled “Rate Limiting”Prevent connection floods by limiting connections per IP:
rate_limiter: duration: 60 # Time window in seconds limit: 60 # Max connections per IP in that windowThe rate limiter is disabled by default. Adding the rate_limiter section enables it — there is no separate enabled field.
PROXY Protocol
Section titled “PROXY Protocol”If Passage is behind a load balancer (HAProxy, AWS NLB, etc.), enable PROXY protocol to preserve client IP addresses:
proxy_protocol: allow_v1: true # Accept PROXY protocol v1 headers allow_v2: true # Accept PROXY protocol v2 headersLike the rate limiter, PROXY protocol is disabled by default and enabled by adding the section.
Per-Route Adapters
Section titled “Per-Route Adapters”Each route configures four adapter categories that control different aspects of the connection:
routes:- hostname: "mc.example.net" # 1. Status: What players see in the server list status: type: fixed name: "My Network"
# 2. Authentication: How players are verified authentication: type: mojang
# 3. Localization: Disconnect messages in multiple languages localization: type: fixed default_locale: "en_US"
# 4. Discovery: How backend servers are found and selected 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| Adapter | Purpose | Default | Options |
|---|---|---|---|
| Status | Server list response (MOTD, players, favicon) | fixed | fixed, http, grpc |
| Authentication | Player identity verification | mojang | mojang, disabled, fixed, grpc |
| Localization | Disconnect message translations | fixed | fixed, grpc |
| Discovery | Backend server selection | fixed_discovery | fixed_discovery, dns_discovery, agones_discovery, grpc_discovery |
The discovery adapter also supports an actions pipeline that filters, reorders, or customizes the target list. See Discovery Actions for details.
Observability
Section titled “Observability”OpenTelemetry
Section titled “OpenTelemetry”Send traces, metrics, and logs to any OTLP-compatible backend (Grafana Cloud, Datadog, etc.):
otel: environment: "production" traces: address: "https://otlp.example.com/v1/traces" token: "base64_auth_token" metrics: address: "https://otlp.example.com/v1/metrics" token: "base64_auth_token" logs: address: "https://otlp.example.com/v1/logs" token: "base64_auth_token"Each endpoint (traces, metrics, logs) is optional and independently configured.
Sentry
Section titled “Sentry”Enable error tracking by adding a sentry section:
sentry: environment: "production" debug: falseLike other optional sections, Sentry is enabled by its presence — there is no enabled field.
Example Configurations
Section titled “Example Configurations”Simple Static Setup
Section titled “Simple Static Setup”A single backend server with default settings:
routes:- hostname: "mc.example.net" status: type: fixed name: "My Network" description: "\"Welcome to my server!\"" discovery: type: fixed_discovery targets: - identifier: "lobby" address: "10.0.0.10:25565"DNS Discovery with Load Balancing
Section titled “DNS Discovery with Load Balancing”Automatically discover servers via DNS and fill the fullest available:
address: "0.0.0.0:25565"timeout: 120
rate_limiter: duration: 60 limit: 60
routes:- hostname: "mc.example.net" status: type: http address: "https://example.net/status" cache_duration: 30 discovery: type: dns_discovery domain: "servers.example.net" record_type: srv actions: - type: meta_filter name: "online-filter" rules: - key: "status" op: equals value: "online" - type: player_fill_strategy name: "fill-strategy" field: "players" max_players: 50Full gRPC Setup
Section titled “Full gRPC Setup”Delegate all logic to external services:
address: "0.0.0.0:25565"
routes:- hostname: "mc.example.net" status: type: grpc address: "http://status-service:50051" authentication: type: grpc address: "http://auth-service:50051" localization: type: grpc address: "http://localization-service:50051" discovery: type: grpc_discovery address: "http://discovery-service:50051" actions: - type: grpc name: "custom-router" address: "http://router-service:50051"Validation
Section titled “Validation”Passage validates the configuration on startup. Run it to check for errors:
# Run with debug logging to see configuration detailsRUST_LOG=debug passageCommon issues:
- Invalid regex in
hostnamefield - Missing required fields (e.g.,
addressfor gRPC adapters) - Unknown adapter
typevalues - Malformed YAML syntax
Best Practices
Section titled “Best Practices”- Store secrets separately: Use
config/auth_secretfor the authentication secret, not the main config file - Use environment variables for sensitive values in CI/CD pipelines
- Don’t commit your config file to version control if it contains secrets
- Enable rate limiting in production to prevent connection floods
- Set reasonable timeouts (60-300 seconds depending on your network)
- Use descriptive names for discovery actions to simplify debugging