Skip to content

Configuration

OPaperStream edited this page Oct 6, 2026 · 2 revisions

Configuration

PaperProxy keeps Velocity's velocity.toml as it is and adds its own files:

File Content
paperproxy.toml All PaperProxy features (below)
messages.yml Every proxy message, MiniMessage and & codes, {placeholders}. New keys are merged in after updates, your texts are kept. Optional per language files like messages_de.yml.
motd.yml Rotating or random MOTDs, hover lines, text instead of the player count

/pp reload reloads all three. A few settings (punish.enabled, party.enabled) need a restart.

Default paperproxy.toml

# PaperProxy settings.
# Velocity's own settings (servers, bind address, online mode, ...) stay in velocity.toml.
# Reload with /paperproxy reload. Errors are reported with the setting's name and the file is
# never overwritten with defaults.

[forwarding]
# Forwarding mode per server, overriding player-info-forwarding-mode from velocity.toml.
# Modes: "modern", "paperguard", "bungeeguard", "legacy", "none".
#   modern      Paper 1.13+ built in, recommended
#   paperguard  signed and replay-proof, needs the PaperGuard plugin on the backend
#   bungeeguard needs the BungeeGuard plugin on the backend
#   legacy      plain BungeeCord forwarding, only safe behind a strict firewall
[forwarding.servers]
# old-pvp = "paperguard"

[paperguard]
# How long a signed login stays valid, in seconds. Proxy and backends need roughly the
# same clock (NTP).
max-age-seconds = 10

[versions]
# Allowed client versions per server, e.g. lobby = "1.8-latest" or pvp = "1.8-1.8.9".
# Players with other versions get a clear message instead of a protocol error.
# lobby = "1.8-latest"

[health-check]
enabled = true
# Seconds between pings to every backend server.
interval-seconds = 10
# Players with this permission are told when a server goes down or comes back.
notify-permission = "paperproxy.notify.health"

[maintenance]
# Global maintenance: only players with paperproxy.maintenance.bypass or on the whitelist
# may join. Toggle with /paperproxy maintenance on|off [server].
enabled = false
# Servers in maintenance (players without bypass cannot connect to them).
servers = []
whitelist = []

[groups]
# Servers that act as one. Players are sent to the member with the fewest players; full or
# offline members are skipped. Use a member name in velocity.toml (try, forced-hosts) and the
# group decides which member is used.
# lobby = ["lobby-1", "lobby-2"]

[queue]
# When a server is full or offline, players wait in a queue and are connected automatically
# as soon as there is room. Higher paperproxy.queue.priority.<0-100> goes first,
# paperproxy.queue.bypass joins full servers directly.
enabled = true
# Seconds between queue updates and position messages.
interval-seconds = 2
# Players leave the queue after this many minutes.
timeout-minutes = 10
# Players moved away because their server restarted are sent back once it is online again.
rejoin-after-restart = true

[hub-command]
# /hub and /lobby send players to this server or group. Empty disables the command.
target = ""
aliases = ["hub", "lobby"]

[antibot]
# Protection against bot floods.
enabled = true
# More new connections per second than this switch on attack mode.
attack-threshold = 30
# Attack mode ends this many seconds after the last burst.
attack-duration-seconds = 60
# During an attack only players who joined before may connect (kept in known-players.txt).
attack-known-only = true
# Players online from the same IP. 0 = unlimited. paperproxy.antibot.bypass skips the limit.
max-accounts-per-ip = 0
# Names matching this regular expression are refused, e.g. "^(bot|test)_\\d+$". Empty = off.
blocked-name-pattern = ""
# New players must have pinged the server list in the last 10 minutes before they can join.
# "off", "attack" (only during an attack) or "always". Players who joined before are never
# asked. Most bots skip the server list.
require-ping = "attack"

[metrics]
# Prometheus endpoint with players, servers, queues and memory, at http://<bind>:<port>/metrics.
enabled = false
bind = "127.0.0.1"
port = 9225

[shutdown]
# When the proxy stops, send players to another proxy instead of kicking them
# (Minecraft 1.20.5+ clients), e.g. "play2.example.net:25565". Empty = kick as usual.
transfer-to = ""

[sync]
# Connect several PaperProxy instances through Redis: network wide player count, /find and
# /alert across proxies, /pp network, and no double logins on two proxies.
enabled = false
# Name of this proxy. Empty = hostname:port.
proxy-id = ""
redis-host = "127.0.0.1"
redis-port = 6379
redis-password = ""
redis-database = 0
# Show the players of all proxies in the server list.
network-player-count = true

[tab-complete]
# Commands players do not get suggested, e.g. ["plugins", "version", "server"].
# The commands still work. Players with paperproxy.tabcomplete.bypass see them anyway.
hidden-commands = []

[query]
# Answer server queries (enable-query in velocity.toml) with the map, version and plugins of
# this backend server. Empty = the proxy answers itself.
passthrough-server = ""
# Query port of that server, 0 = its game port (query.port in server.properties).
passthrough-port = 0

[limbo]
# When a server restarts or crashes and no other server can take its players, they stay
# connected in the last world they saw and are sent back as soon as the server (or another
# member of its group) is online. Real kicks (bans, AFK) are not affected.
enabled = true
max-wait-seconds = 300
# Kick messages that mean "restarting". A lost connection always counts.
kick-messages = ["server closed", "restarting", "server is restarting", "server stopped"]

[discord]
# Post network events to a Discord channel. Create the webhook under
# channel settings > Integrations > Webhooks. Empty = off.
webhook-url = ""
username = "PaperProxy"
# proxy, health, antibot, maintenance, update, restart, punish
events = ["proxy", "health", "antibot", "maintenance", "update", "restart", "punish"]

[restart]
# Restart the proxy every day at these times, e.g. ["04:00"]. Players get a countdown and go
# to shutdown.transfer-to if set. Your start script or panel has to start the proxy again.
times = []
# Seconds before the restart at which players are warned.
warn-seconds = [600, 300, 60, 30, 10, 5, 4, 3, 2, 1]

[party]
# /party and /pc. Members follow the leader to other servers.
enabled = true
max-size = 8
follow-leader = true

[punish]
# /ban, /unban, /mute, /unmute, /kick and /banlist for the whole network, stored in
# punishments.json and shared through [sync]. Off by default because backend servers and ban
# plugins have commands with the same names. Needs a restart.
enabled = false

[ping-cache]
# Server list responses are reused for this many seconds. 0 disables the cache.
seconds = 5

[watchdog]
# Warn when a plugin listener blocks an event for longer than this (milliseconds).
# 0 disables the watchdog.
warn-after-ms = 500

[plugin-reload]
# Require "confirm" after /paperproxy plugin reload|load|unload.
require-confirm = true
# Plugins that are never reloaded because they are known to break.
blocked = ["viaversion", "viabackwards", "viarewind", "luckperms", "geyser", "floodgate"]

[updates]
# Check GitHub releases for new PaperProxy versions and announce them.
check = true
# "auto" follows the version you run: on an alpha you hear about alphas, betas and
# releases, on a beta about betas and releases, on a release only about releases.
# Or "release", "beta" or "alpha".
channel = "auto"

[auto-update]
# Download verified updates automatically; they become active on the next restart.
enabled = false
# Never install a new major version automatically.
allow-major = false

Clone this wiki locally