How to Set Up a Minecraft Server on Windows: A Dev Guide
Tech Setup
Reviewed August 1, 2026

Introduction
Running a Minecraft server locally or on a Windows virtual private server (VPS) is a great exercise in network routing, process management, and resource allocation. While Minecraft's underlying Java architecture is straightforward, turning it into a stable, production-grade instance requires configuring JVM flags, managing headless environments, and handling OS-level persistence.
This guide targets developers and power users who want a robust setup. We will bypass the official, resource-heavy graphical server utility and build a lean, command-line-driven Minecraft server on Windows, optimized for performance and availability.
Prerequisites and Environment Preparation
Before downloading binaries, ensure your host environment meets the necessary runtime requirements.
1. Java Development Kit (JDK)
Minecraft Java Edition runs on the Java Virtual Machine (JVM). Modern versions of Minecraft (1.18+) require Java 17. For the latest releases (1.20.x and 1.21.x), Java 21 is mandatory.
Verify your current Java installation via PowerShell:
java -version
If Java is missing or outdated, install the latest OpenJDK (Temurin build by the Eclipse Foundation is recommended for production environments) using winget:
winget install EclipseAdoptium.Temurin.21.JDK
Note: Restart your terminal session after installation to ensure system environment variables (JAVA_HOME and PATH) update correctly.
2. Network Topology and Static IPs
To allow external connections, your host machine needs a static local IP address. If you are hosting on a home network, you will also need to configure port forwarding later.
Identify your current network configuration:
ipconfig
Note your IPv4 Address and Default Gateway for your router configuration step.
Step 1: Directory Structure and Server Binaries
As a best practice, isolate your server files in a dedicated directory rather than running them from user downloads or temporary folders.
- Open PowerShell and create a dedicated workspace:
mkdir C:\minecraft-server
cd C:\minecraft-server
- Download the official server
.jarfile. You can automate this usingcurl:
# Replace the URL with the specific version jar you require
Invoke-WebRequest -Uri "https://piston-data.mojang.com/v1/objects/c9df48efed58511c60f10629ae994d6345482270/server.jar" -OutFile "server.jar"
(Always fetch the direct download link for the exact Minecraft version from the official launcher or reliable mirrors).
Step 2: Initializing and Accepting the EULA
Running the server jar for the first time will generate the necessary configuration files, including the End User License Agreement (EULA).
Execute the jar via the command line to generate files:
java -Xmx1024M -Xms1024M -jar server.jar nogui
You will notice the process terminates immediately, generating several files in C:\minecraft-server, most notably eula.txt. Mojang requires explicit consent to their EULA before the server engine will spin up.
Open eula.txt in your text editor of choice (e.g., Notepad or VS Code):
code eula.txt
Change the boolean flag from false to true:
#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://aka.ms/MinecraftEULA).
#Sat Oct 14 12:00:00 UTC 2023
eula=true
Save and close the file.
Step 3: Crafting the Startup Script
Running Minecraft with default JVM memory flags leads to garbage collection (GC) stutters and eventual out-of-memory crashes as chunk generation scales. We need to allocate a dedicated heap and tune the Garbage Collector.
Create a file named start.bat in your server root directory:
New-Item -ItemType File -Name "start.bat"
Populate start.bat with optimized JVM flags. This configuration allocates 6GB of RAM (adjust -Xmx and -Xms based on your total system RAM and expected player load) and utilizes the G1 Garbage Collector, which is heavily optimized for low-latency server environments:
@echo off
REM === Minecraft Server Startup Script ===
:: Set window title for process identification
title Minecraft Server
:: Java executable path (leave as 'java' if added to system PATH)
set JAVA="java"
:: Memory Allocation (e.g., 6G minimum and maximum)
set MIN_RAM=6G
set MAX_RAM=6G
:: JVM Flags for G1GC Optimization
set JVM_OPTS=-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4
%JAVA% -Xms%MIN_RAM% -Xmx%MAX_RAM% %JVM_OPTS% -jar server.jar nogui
pause
Save the batch file. Run it manually once to verify the server spins up cleanly and generates the world, logs, and plugins (if running Paper/Spigot) directories. Type stop in the console to safely shut down the instance.
Step 4: Configuring server.properties
The core configuration file for your server is server.properties. Open it to tune gameplay mechanics, networking, and performance parameters.
code server.properties
Key properties to modify for a robust developer or private setup:
| Property | Recommended Value | Description |
|---|---|---|
server-port | 25565 | Default listening port. Change if running multiple instances. |
max-players | 20 | Adjust based on your hardware constraints. |
view-distance | 10 to 12 | Higher values increase CPU/RAM load and network bandwidth. |
simulation-distance | 8 | Keeps tick processing close to players, saving vital CPU cycles. |
online-mode | true | Set to false only if running an offline/LAN network behind a proxy like Velocity/BungeeCord. |
enable-rcon | true | Essential for remote administration and automated scripting. |
white-list | true | Restricts access to authorized UUIDs only. |
Step 5: Network Configuration and Port Forwarding
If your server is hosted on a local machine and you want external players to connect, you must configure network ingress.
Windows Defender Firewall Rule
By default, Windows blocks incoming connections on arbitrary ports. Create an inbound rule to allow traffic on port 25565:
Open PowerShell as Administrator and run:
New-NetFirewallRule -DisplayName "Minecraft Server Inbound" -Direction Inbound -LocalPort 25565 -Protocol TCP -Action Allow
Router Port Forwarding
- Log into your local router's administration panel (using your
Default GatewayIP). - Navigate to the Port Forwarding or Virtual Server section.
- Forward external port 25565 (TCP and UDP) to your server's static internal IPv4 address on port 25565.
- Retrieve your public IP address (via
curl ifconfig.me) to share with remote users.
Step 6: Advanced Production Setup (Running as a Windows Service)
Relying on an interactive PowerShell window or batch script means the server dies if the user logs out. For production environments, run the Minecraft server as a background Windows Service using NSSM (Non-Sucking Service Manager).
- Install NSSM via winget:
winget install NSSM.NSSM
- Launch the graphical service configuration utility:
nssm install MinecraftServer
-
In the NSSM configuration GUI:
- Path:
C:\Program Files\Eclipse Adoptium\jdk-21.x.x\bin\java.exe(or your absolute java path) - Startup directory:
C:\minecraft-server - Arguments:
-Xmx6G -Xms6G -XX:+UseG1GC -jar server.jar nogui
- Path:
-
Click Install service.
You can now manage the server lifecycle natively via PowerShell:
# Start the server silently in the background
Start-Service MinecraftServer
# Check service status
Get-Service MinecraftServer
# Stop the server safely
Stop-Service MinecraftServer
Step 7: Automated Backups via PowerShell
Data corruption during chunk saves or unexpected crashes can ruin worlds. Implement a scheduled backup script using Windows Task Scheduler and PowerShell.
Create a script named backup.ps1 in C:\scripts\backup.ps1:
$SourceDir = "C:\minecraft-server\world"
$BackupDir = "C:\minecraft-backups"
$Timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm"
$Destination = "$BackupDir\world_$Timestamp.zip"
if (!(Test-Path $BackupDir)) {
New-Item -ItemType Directory -Path $BackupDir
}
# Safely issue a save-off command via RCON if configured, or zip directly for local testing
Compress-Archive -Path $SourceDir -DestinationPath $Destination -CompressionLevel Optimal
# Retention policy: Delete backups older than 7 days
Get-ChildItem -Path $BackupDir -Filter "*.zip" | Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-7) } | Remove-Item
Write-Host "Backup completed successfully: $Destination"
To automate this hourly or daily, register it as a Windows Scheduled Task via PowerShell:
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy Bypass -File C:\scripts\backup.ps1"
$Trigger = New-ScheduledTaskTrigger -Daily -At 3AM
Register-ScheduledTask -TaskName "MinecraftDailyBackup" -Action $Action -Trigger $Trigger
Verification and Monitoring
With your server up and running, verify operational health:
- Check Logs: Inspect the latest log outputs in
C:\minecraft-server\logs\latest.logfor memory warnings, slow tick rates (Can't keep up! Is the server overloaded?), or plugin loading errors. - Client Connection: Open Minecraft Java Edition, navigate to Multiplayer -> Add Server, and input your local IP (or
127.0.0.1if testing locally) or public IP. - Resource Utilization: Monitor JVM heap usage using Windows Task Manager or Resource Monitor to ensure your
-Xmxallocations match actual system loads under stress.
Related articles

Setting Up WSL2 with Ubuntu on Windows 11: Dev Guide

Windows Terminal: The Ultimate Power User Guide
