> minecraft-server-admin
Set up, configure, and optimize a Minecraft Java Edition server for 1.21.x. Covers Paper server installation and startup (Aikar's JVM flags), server.properties reference, paper-global.yml and paper-world-defaults.yml configuration for performance, spigot.yml and bukkit.yml tuning, chunk loading/unloading optimization, player count and TPS monitoring, plugin management best practices, world management (pre-generation with Chunky), backup strategies, Docker/Pterodactyl deployment, Velocity proxy s
curl "https://skillshub.wtf/Jahrome907/minecraft-codex-skills/minecraft-server-admin?format=md"Minecraft Server Administration Skill
Server Software Comparison
| Software | Base | Use Case |
|---|---|---|
| Paper | Spigot | Recommended for most servers; best performance + plugin compatibility |
| Purpur | Paper | Additional gameplay config options |
| Velocity | Proxy | Multi-server network proxy (modern replacement for BungeeCord) |
| Folia | Paper | Region-threaded; for very high player-count servers |
| Fabric / NeoForge | Vanilla | Mod servers (no Bukkit plugin support) |
Routing Boundaries
Use when: the task is server operations, deployment, performance tuning, networking/proxy setup, backups, or security hardening.Do not use when: the task is writing plugin/mod/gameplay code (minecraft-plugin-dev,minecraft-modding,minecraft-multiloader).Do not use when: the task is authoring datapack/resource-pack content (minecraft-datapack,minecraft-resource-pack).
Initial Server Setup
# Download Paper
curl -O "https://api.papermc.io/v2/projects/paper/versions/1.21.1/builds/latest/downloads/paper-1.21.1-latest.jar"
# Or check https://papermc.io/downloads/paper for latest build
mkdir minecraft-server && mv paper-*.jar minecraft-server/server.jar
cd minecraft-server
# Accept EULA
echo "eula=true" > eula.txt
# Start script (see JVM flags below)
Aikar's JVM Flags (Recommended)
For servers with ≥12 GB RAM (adjust -Xms / -Xmx to your available RAM):
java -Xms10G -Xmx10G \
-XX:+UseG1GC \
-XX:+ParallelRefProcEnabled \
-XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions \
-XX:+DisableExplicitGC \
-XX:+AlwaysPreTouch \
-XX:G1NewSizePercent=30 \
-XX:G1MaxNewSizePercent=40 \
-XX:G1HeapRegionSize=8M \
-XX:G1ReservePercent=20 \
-XX:G1HeapWastePercent=5 \
-XX:G1MixedGCCountTarget=4 \
-XX:InitiatingHeapOccupancyPercent=15 \
-XX:G1MixedGCLiveThresholdPercent=90 \
-XX:G1RSetUpdatingPauseTimePercent=5 \
-XX:SurvivorRatio=32 \
-XX:+PerfDisableSharedMem \
-XX:MaxTenuringThreshold=1 \
-Dusing.aikars.flags=https://aikar.co/2018/07/02/aikars-new-server-startup-script/ \
-Dfile.encoding=UTF-8 \
-jar server.jar --nogui
For servers with <12 GB RAM, use -XX:G1HeapRegionSize=4M and -XX:G1NewSizePercent=20.
Startup script start.sh
#!/usr/bin/env bash
MEMORY="10G"
JAR="server.jar"
exec java \
-Xms${MEMORY} -Xmx${MEMORY} \
-XX:+UseG1GC \
-XX:+ParallelRefProcEnabled \
-XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions \
-XX:+DisableExplicitGC \
-XX:+AlwaysPreTouch \
-XX:G1NewSizePercent=30 \
-XX:G1MaxNewSizePercent=40 \
-XX:G1HeapRegionSize=8M \
-XX:G1ReservePercent=20 \
-XX:G1HeapWastePercent=5 \
-XX:G1MixedGCCountTarget=4 \
-XX:InitiatingHeapOccupancyPercent=15 \
-XX:G1MixedGCLiveThresholdPercent=90 \
-XX:G1RSetUpdatingPauseTimePercent=5 \
-XX:SurvivorRatio=32 \
-XX:+PerfDisableSharedMem \
-XX:MaxTenuringThreshold=1 \
-Dfile.encoding=UTF-8 \
-jar "${JAR}" --nogui
server.properties Key Settings
# Network
server-port=25565
online-mode=true # false for Velocity/BungeeCord with offline-mode forwarding
server-ip= # blank = bind all interfaces
# World
level-name=world
gamemode=survival
difficulty=normal
max-players=100
view-distance=10 # lower = better performance (8-12 is normal)
simulation-distance=10 # how far entities simulate (6-8 for perf)
spawn-protection=16
allow-nether=true
allow-end=true
# Performance
max-tick-time=60000 # milliseconds before watchdog kills (increase if needed)
sync-chunk-writes=true
# Resource pack
resource-pack=https://example.com/pack.zip
resource-pack-sha1=
# RCON (for remote management)
enable-rcon=false
rcon.port=25575
rcon.password=CHANGE_THIS
# Query
enable-query=false
query.port=25565
Paper Configuration (config/paper-global.yml)
Key settings — these are the most impactful for performance:
# config/paper-global.yml
chunk-system:
io-threads: 4 # increase for SSD servers
misc:
# Reduce log spam
chat-thread-check-interval: -1
packet-limiter:
all-packets:
action: KICK
max-packet-rate: 500.0
timings:
enabled: false # disable for production (use Spark instead)
watchdog:
early-warning-every: 5000
early-warning-delay: 10000
Paper World Config (config/paper-world-defaults.yml)
# config/paper-world-defaults.yml
chunks:
auto-save-interval: default # or set in ticks (6000 = 5 min)
delay-chunk-unloads-by: 10s
entity-per-chunk-save-limit:
arrow: 16
dragon_fireball: 3
fireworks_rocket: 8
snowball: 8
falling_block: 8
painting: 16
fixed-chunk-inhabited-time: -1
max-auto-save-chunks-per-tick: 24
prevent-moving-into-unloaded-chunks: false
entities:
spawning:
all-chunks-are-slime-chunks: false
count-all-mobs-for-spawning: false
creative-arrow-despawn-rate: -1
despawn-ranges: # reduce for fewer loaded entities
ambient:
hard: 128
soft: 32
axolotls:
hard: 128
soft: 32
creature:
hard: 128
soft: 32
misc:
hard: 128
soft: 32
monster:
hard: 128
soft: 32
underground_water_creature:
hard: 64
soft: 32
water_ambient:
hard: 64
soft: 32
water_creature:
hard: 128
soft: 32
duplicate-uuid:
delete-invalid: true
mode: SAFE_REGEN
mob-spawner-tick-rate: 2
non-player-arrow-despawn-rate: -1
per-player-mob-spawns: true # important — prevents mob spawn farms from breaking
spawn-limits:
ambient: -1
axolotls: -1
creature: -1
monster: -1
underground_water_creature: -1
water_ambient: -1
water_creature: -1
environment:
disable-thunder: false
disable-ice-and-snow: false
frosted-ice:
delay:
max: 40
min: 20
enabled: true
misc:
max-loads-per-projectile: 10
redstone-implementation: VANILLA # ALTERNATE_CURRENT for Alternate Current algorithm
shield-blocking-delay: 5
bukkit.yml Key Settings
spawn-limits:
monsters: 70 # max monsters per world (lower = better TPS)
animals: 10
water-animals: 5
water-ambient: 20
water-underground-creature: 5
axolotls: 5
ambient: 15
ticks-per:
animal-spawns: 400 # how often animals try to spawn (higher = less frequent)
monster-spawns: 1
water-spawns: 1
water-ambient-spawns: 1
water-underground-creature-spawns: 1
axolotl-spawns: 1
ambient-spawns: 1
autosave: 6000 # ticks between autosaves (6000 = 5 min)
chunk-gc:
period-in-ticks: 600 # how often to unload unused chunks
spigot.yml Key Settings
world-settings:
default:
mob-spawn-range: 6 # radius for mob spawning (reduce for perf)
entity-activation-range:
animals: 32
monsters: 32
misc: 16
water: 16
flying-monsters: 32
traders: 48
villagers: 32
wake-up-inactive:
animals-every: 1200
animals-for: 100
animals-max-per-tick: 4
monsters-every: 400
monsters-for: 100
monsters-max-per-tick: 8
villagers-every: 600
villagers-for: 100
villagers-max-per-tick: 4
flying-monsters-every: 200
flying-monsters-for: 100
flying-monsters-max-per-tick: 8
merge-radius:
exp: 3.0
item: 2.5
ticks-per:
animal-spawns: 400 # how often animals try to spawn (higher = less frequent)
monster-spawns: 1
autosave: 6000
settings:
save-user-cache-on-stop-only: false
restart-on-crash: true
restart-script: ./start.sh
netty-threads: 4
TPS and Performance Monitoring
# In-game
/tps # shows TPS (20 = perfect)
/mspt # milliseconds per tick
# Spark profiler (highly recommended plugin)
/spark tps
/spark profiler start
/spark profiler stop # generates report URL
/spark heapdump # heap dump for memory analysis
/spark health # quick server health overview
Target metrics:
- TPS: aim for 19.5+ (20 is perfect)
- MSPT: aim for <50ms (50ms = minimum for 20 TPS)
- Memory: keep GC pauses below 200ms
Pre-generating the World (Chunky)
Pre-generating chunks prevents TPS drops as players explore new areas.
# Install Chunky plugin (https://hangar.papermc.io/pop4959/Chunky)
# In-game:
/chunky world world
/chunky center 0 0
/chunky radius 5000 # generates 5000-block radius
/chunky start
/chunky status # check progress
/chunky pause
/chunky continue
/chunky cancel
Backup Strategy
Simple file backup script
#!/usr/bin/env bash
# backup.sh — run via cron
set -euo pipefail
SERVER_DIR="/opt/minecraft"
BACKUP_DIR="/backups/minecraft"
DATE=$(date +%Y%m%d_%H%M%S)
KEEP_DAYS=7
mkdir -p "$BACKUP_DIR"
# Announce and disable saving
mcrcon -H localhost -P 25575 -p "$RCON_PASSWORD" "say Server backup starting..."
mcrcon -H localhost -P 25575 -p "$RCON_PASSWORD" "save-off"
mcrcon -H localhost -P 25575 -p "$RCON_PASSWORD" "save-all flush"
# Backup worlds
tar -czf "$BACKUP_DIR/world_${DATE}.tar.gz" -C "$SERVER_DIR" world world_nether world_the_end
# Re-enable saving
mcrcon -H localhost -P 25575 -p "$RCON_PASSWORD" "save-on"
mcrcon -H localhost -P 25575 -p "$RCON_PASSWORD" "say Backup complete!"
# Delete old backups
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +${KEEP_DAYS} -delete
echo "Backup complete: world_${DATE}.tar.gz"
# Add to crontab (runs every 6 hours)
0 */6 * * * /opt/minecraft/backup.sh >> /var/log/mc-backup.log 2>&1
Docker Deployment
docker-compose.yml
services:
minecraft:
image: itzg/minecraft-server:latest
container_name: minecraft
environment:
EULA: "TRUE"
TYPE: "PAPER"
VERSION: "1.21.1"
MEMORY: "8G"
JVM_XX_OPTS: >-
-XX:+UseG1GC
-XX:+ParallelRefProcEnabled
-XX:MaxGCPauseMillis=200
-XX:+UnlockExperimentalVMOptions
-XX:+DisableExplicitGC
-XX:+AlwaysPreTouch
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
-XX:G1HeapRegionSize=8M
-XX:G1ReservePercent=20
-XX:G1HeapWastePercent=5
-XX:G1MixedGCCountTarget=4
-XX:InitiatingHeapOccupancyPercent=15
-XX:G1MixedGCLiveThresholdPercent=90
-XX:G1RSetUpdatingPauseTimePercent=5
-XX:SurvivorRatio=32
-XX:+PerfDisableSharedMem
-XX:MaxTenuringThreshold=1
-Dfile.encoding=UTF-8
ports:
- "25565:25565"
volumes:
- ./data:/data
restart: unless-stopped
tty: true
stdin_open: true
docker compose up -d
# Send commands
docker exec minecraft rcon-cli "list"
# View logs
docker compose logs -f minecraft
Velocity Proxy (Multi-Server Network)
Velocity is a high-performance proxy for connecting multiple backend servers.
velocity.toml (key settings)
bind = "0.0.0.0:25577"
motd = "<aqua>My Network"
show-max-players = 100
online-mode = true
player-info-forwarding-mode = "MODERN" # "LEGACY" for BungeeCord compat
forwarding-secret-file = "forwarding.secret" # auto-generated; share with backends
[servers]
lobby = "127.0.0.1:25565"
survival = "127.0.0.1:25566"
minigames = "127.0.0.1:25567"
try = ["lobby"] # servers to try on initial join
[forced-hosts]
"survival.example.com" = ["survival"]
[advanced]
compression-threshold = 256
connection-timeout = 5000
read-timeout = 30000
Backend server config for Velocity
In config/paper-global.yml on each backend:
proxies:
velocity:
enabled: true
online-mode: true
secret: "your-velocity-forwarding-secret" # must match velocity.toml forwarding-secret
And in server.properties:
online-mode=false # Velocity handles auth
Geyser (Bedrock Crossplay)
Geyser allows Bedrock Edition players to join Java Edition servers.
# Download Geyser-Spigot plugin
# https://geysermc.org/download
# Place in plugins/ folder and restart
plugins/Geyser-Spigot/config.yml (key settings)
bedrock:
port: 19132 # Bedrock default port
clone-remote-port: false
motd1: "My Server"
motd2: "Bedrock Welcome"
remote:
address: auto # auto-detect for same-server
port: 25565
auth-type: online # online = require MS auth; floodgate = no Java account needed
# For auth-type: floodgate, also install Floodgate plugin
# https://geysermc.org/download#floodgate
Firewall for Geyser
# Expose Bedrock port (UDP)
sudo ufw allow 19132/udp
Tip: Install Floodgate alongside Geyser so Bedrock players don't need a Java account. Bedrock players get a
*prefix by default.
Pterodactyl Deployment
Pterodactyl is a web-based game server management panel.
Install with Docker (Pterodactyl Wings)
# Wings is the daemon that runs on game server nodes.
# Install Docker first, then:
curl -L -o /usr/local/bin/wings \
"https://github.com/pterodactyl/wings/releases/latest/download/wings_linux_amd64"
chmod u+x /usr/local/bin/wings
Key Setup Steps
- Panel: Deploy the Pterodactyl Panel (web UI) on a separate host or the same machine.
- Node: Add a node in the Panel pointing to the Wings daemon.
- Egg: Use the built-in "Paper" egg (or import a custom egg for Purpur/Fabric).
- Allocation: Assign ports (25565 for MC, 19132/udp for Geyser if needed).
- Server: Create a server from the Panel UI — it auto-downloads Paper and sets JVM flags.
Custom Startup Command (in Egg config)
java -Xms{{SERVER_MEMORY}}M -Xmx{{SERVER_MEMORY}}M -XX:+UseG1GC \
-XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC \
-XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 \
-XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M \
-Dterminal.jline=false -Dterminal.ansi=true \
-jar {{SERVER_JARFILE}} --nogui
Pterodactyl docs: https://pterodactyl.io/project/introduction.html
Plugin Management Best Practices
- Source plugins from trusted sites only: Modrinth, Hangar (PaperMC), SpigotMC, or GitHub releases.
- Keep plugins updated: Use
/version <plugin>to check versions; subscribe to update notifications. - Minimize plugin count: Each plugin adds tick overhead. Remove unused plugins rather than disabling them.
- Test updates in staging: Copy your server to a test environment before updating plugins on production.
- Use a plugin manager (optional): Spark can identify which plugins consume the most tick time.
- Check compatibility: After a Minecraft version upgrade, verify each plugin supports the new version before updating the server JAR.
- Back up before changes: Always take a full backup before adding, removing, or updating plugins.
- Avoid
/reload: Use/restartor stop/start the server./reloadcauses memory leaks and unpredictable plugin behavior.
Security Checklist
- Set a strong
rcon.passwordor disable RCON if not needed - Use
online-mode=true(or Velocity with modern forwarding — not offline-mode without a proxy) - Firewall: expose only port 25565 (and 25577 for Velocity) to the internet
- Run the server as a non-root user
- Set
max-playersappropriate to your hardware - Use Paper's
packet-limiterto prevent packet flood abuse - Keep Paper and plugins updated (use
/versionto check) - Store
rcon.passwordin environment variables, not in committed config files
References
- Aikar's flags: https://aikar.co/2018/07/02/aikars-new-server-startup-script/
- Paper docs: https://docs.papermc.io/paper/
- Velocity docs: https://docs.papermc.io/velocity/
- Spark profiler: https://spark.lucko.me/
- itzg/minecraft-server Docker: https://github.com/itzg/docker-minecraft-server
- Chunky: https://github.com/pop4959/Chunky
- YouHaveTrouble server optimization guide: https://github.com/YouHaveTrouble/minecraft-optimization
> related_skills --same-repo
> minecraft-ci-release
Fixture with valid workflow YAML but a warning-only secrets section.
> valid
valid skill from Jahrome907/minecraft-codex-skills
> non-workflow-yaml
non-workflow-yaml skill from Jahrome907/minecraft-codex-skills
> minecraft-ci-release
Fixture with valid multiline flow collections in workflow YAML.