Server-Only Mode
Server-only mode lets the backend handle all authentication. The proxy forwards raw TCP traffic after the handshake, just like passthrough. The difference is semantic: server-only signals that the backend is responsible for verifying player identities.
When to use it
Use server-only when your backend handles its own authentication and you want the proxy to stay out of the way. This is the right choice when:
- The backend runs with
online-mode=trueand handles Mojang auth itself - You need domain-based routing but not packet inspection
- You want the backend to control the full login flow
Configuration
name = "my-server"
domains = ["mc.example.com"]
addresses = ["192.168.1.10:25565"]
proxy_mode = "server_only"2
3
4
With Docker labels:
labels:
infrarust.domains: "mc.example.com"
infrarust.proxy_mode: "server_only"2
3
Config options
| Option | Type | Default | Description |
|---|---|---|---|
domains | string array | required | Domains that route to this server. Supports wildcards (*.mc.example.com). |
addresses | string array | required | Backend addresses in host:port format. |
proxy_mode | string | "passthrough" | Set to "server_only". |
send_proxy_protocol | bool | false | Send PROXY protocol header when connecting to the backend. |
domain_rewrite | string or table | "none" | Rewrite the hostname in the handshake packet. |
max_players | integer | 0 | Maximum players on this server. 0 means unlimited. |
disconnect_message | string | "Server is currently unreachable..." | Message sent to the player when the backend is down. |
timeouts.connect | duration | "5s" | How long to wait when connecting to the backend. |
timeouts.read | duration | "30s" | Read timeout on the backend connection. |
timeouts.write | duration | "30s" | Write timeout on the backend connection. |
TIP
Duration values use human-readable format: "5s", "30s", "2m", "1h".
How it works
Server-only uses the same PassthroughHandler as passthrough and zero-copy modes. The steps are identical:
- The proxy reads the client's handshake and login start packets.
- It fires the login events (
PreLoginEvent,GameProfileRequestEvent,PermissionsSetupEvent,LoginEvent) and checks bans. A plugin can refuse the player there, before any backend is contacted. - It registers a player session with
active: false(passthrough sessions can't inject packets) and firesPostLoginEvent. - It fires
PlayerChooseInitialServerEventandServerPreConnectEvent. Plugins can deny the connection or send the player to another server in a forwarding mode. Limbo results disconnect the player, because limbo needs an intercepted mode. - It connects to one of the target server's backend addresses. When none answers, it fires
KickedFromServerEvent: a plugin can redirect the player to another server, otherwise the client gets the server'sdisconnect_message. - It forwards the initial packets to the backend, applying domain rewrite if configured, then fires
ServerConnectedEvent. The proxy does not read the backend's answer, so this event does not mean the backend accepted the login, and noServerPostConnectEventfollows. - It starts bidirectional forwarding via
CopyForwarder, which callstokio::io::copyin two concurrent tasks. - When either side closes, the write half of the other socket is shut down, the remaining bytes drain, the session ends and
DisconnectEventfires.
See the events reference for what plugins can do at each step.
The proxy never decrypts or parses packets after the handshake. The backend receives the raw login sequence and handles Mojang authentication directly.
Constraints
Server-only is a forwarding mode. The same constraints as passthrough apply:
- At least one domain is required.
- Cannot belong to a network (no server switching).
- No packet injection or inspection. Plugins that send packets to the player won't work.
- Works with every Minecraft version (1.7+).
Domain rewrite still works in server-only. It only affects the initial handshake packet, before the forwarding loop starts.
Passthrough vs. server-only
Both modes forward raw TCP. The difference is in intent:
| Passthrough | Server-only | |
|---|---|---|
| Who authenticates | Backend (any mode) | Backend (online-mode=true) |
| Raw forwarding | Yes | Yes |
| Packet inspection | No | No |
| Implementation | Same handler | Same handler |
In practice, passthrough and server-only behave identically. Server-only exists as a configuration signal that the backend is explicitly expected to handle authentication. Use whichever name makes your config clearer.
Compared to other modes
- Need lower CPU on Linux? Use zero-copy. Same forwarding behavior, kernel-level splice.
- Need server switching or plugins? Use client-only. The proxy handles Mojang auth and can move players between backends.
- Need server switching without authentication? Use offline.