What is a Minecraft startup script?
This Minecraft startup script generator writes the small file that starts your server: start.sh on Linux and macOS, or start.bat on Windows. It holds the one java command that launches the server jar, with the amount of memory to give it, the JVM flags that tune garbage collection, and nogui so no window opens on a machine without a screen. Around that command it can add a restart loop, so the server comes back by itself after a crash or a stop.
You could type the java command by hand every time, but nobody does. It is long, a typo in a flag stops Java from starting, and a server started from an SSH session without a script dies when you log out. A script in the server folder gives you one command, ./start.sh, or one double-click, and it does the same thing every time.
The script works for Vanilla, Paper, Purpur, Spigot, Fabric, Forge and NeoForge. For Forge and NeoForge on Minecraft 1.17 and newer, which no longer ship a server jar, it finds the args file their installer writes and starts from that instead.
Ask the AI assistant
The AI assistant under the generator reads the script you've built and explains it line by line: what each flag does, how the restart loop works, or why the script closes straight away. It's free, with 20 questions a day.
What goes into the java command
Every startup script, whatever it looks like, comes down to one line with four parts:
java -Xms4G -Xmx4G <JVM flags> -jar server.jar nogui
| Part | What it does |
|---|---|
java | The Java runtime. The script uses the one on your PATH unless you give a full path |
-Xms and -Xmx | The starting and maximum heap, the memory the server can use for the world, players and plugins |
| JVM flags | Garbage collector settings, such as Aikar's flags |
-jar server.jar | The server jar to run. Everything after it goes to Minecraft, not to Java |
nogui | Tells the server not to open its own window with the player list and console |
Order matters. Java options, including the memory and every -XX flag, must come before -jar. Anything written after the jar name is passed to the server as an argument, so a flag placed there is ignored or makes the server complain about an unknown option.
Memory: -Xms and -Xmx
The generator writes the same value for both. Setting the starting heap equal to the maximum means Java takes all the memory at startup instead of growing the heap while players are online, which avoids pauses and makes it obvious at once if the machine does not have enough free memory. Aikar's flags are tuned for this, and their -XX:+AlwaysPreTouch flag touches every page of the heap at startup so that cost is paid before anyone joins.
Do not give Java all the memory the machine has. The heap is only part of what the process uses: Java also needs memory for threads, loaded classes and network buffers, and the operating system needs some for itself and for caching world files. On a machine with 8 GB, a heap of 6 GB is about as high as you should go. The RAM calculator estimates a heap from your player count, plugins or mods and view distance, and the guide on how much RAM a Minecraft server needs explains the numbers behind it.
More memory is not always better. A huge heap that the server never fills still has to be scanned by the garbage collector, and it can hide a memory leak in a plugin until the server has been up for days.
JVM flags
The flags come from the same code as the JVM arguments generator, so both tools give the same result for the same memory and Java version. You can pick one of four sets:
- Aikar's flags. The set most Paper and Spigot servers use. They tune the G1 garbage collector for Minecraft's pattern of many short-lived objects, which cuts down on the long pauses players notice as lag spikes
- MeowIce flags. A newer take on G1 tuning for Java 17 and later
- GraalVM flags. For servers that run on the GraalVM Java distribution
- Basic G1GC. Just the G1 collector with a 200 ms pause target, for small servers or when you want to start simple
If you need a different garbage collector such as ZGC, or extra system properties for a modpack, build the flags in the JVM arguments generator and paste them over the flags in the script. Everything else in the script stays the same.
nogui
Without nogui, the vanilla server opens a Swing window with a player list, memory graph and console whenever it can find a display. On a desktop that can be handy. On a server with no screen it does nothing useful, and on Windows the window uses memory and can be closed by accident, which kills the server. Keep it on unless you want that window.
The restart loop
A plain script starts the server once. When the server stops, the script ends, and the server stays down until someone starts it again. With the restart loop turned on, the script wraps the java command in a loop:
while true; do
java ... -jar server.jar nogui
echo "Server stopped. Restarting in 10 seconds, press Ctrl+C to stop."
sleep 10
done
On Windows the same idea uses a label and goto:
:start
java ... -jar server.jar nogui
echo Server stopped. Restarting in 10 seconds, press Ctrl+C to stop.
timeout /t 10 /nobreak >nul
goto start
This brings the server back after a crash, after the watchdog kills a frozen server, and after you type stop. That last one is useful: restarting a server becomes "type stop and wait", which also works for staff who have console access but no shell access.
To stop the server for good, type stop in the console and then press Ctrl+C while the countdown runs. On Windows, answer Y when it asks "Terminate batch job". The delay is there for that, and so you can read the last lines of a crash before the server starts again. A delay of 10 to 15 seconds works well. With a delay of 0, a server that crashes during startup, for example because of a broken plugin, restarts over and over as fast as it can and fills the logs.
The /restart command on Spigot and Paper
Spigot and Paper have a /restart command that runs the script named in settings.restart-script in spigot.yml, which defaults to ./start.sh. With a restart loop in your script, you do not want that: the loop already starts the server again, and a second copy started by /restart would try to use the same world and port. Point restart-script at a file that does not exist, and /restart just stops the server and lets the loop bring it back. The spigot.yml generator writes that setting.
Forge and NeoForge args files
Forge changed how its server starts in Minecraft 1.17. Older Forge versions installed a forge-<version>.jar you could run with -jar like any other server. Forge 1.17 and newer, and every version of NeoForge, install their libraries instead and start through an args file: a text file listing the classpath and main class, which Java reads when it sees @ in front of a path. The installer writes a run.sh and run.bat that look like this:
java @user_jvm_args.txt @libraries/net/minecraftforge/forge/1.20.1-47.3.0/unix_args.txt "$@"
The version number is part of the path, so a hardcoded script breaks every time you update Forge. The generated script looks for the args file instead: it checks libraries/net/minecraftforge/forge/ (or libraries/net/neoforged/neoforge/ for NeoForge) for a unix_args.txt on Linux or win_args.txt on Windows and uses the one it finds. If you have several versions installed, it uses the last one in name order. If it finds none, it stops with a message telling you to run the installer first.
The JVM flags go straight into the script rather than into user_jvm_args.txt. Both work; Java simply reads the flags from the file when you use @user_jvm_args.txt. Keeping them in the script means one file to edit. If you also keep settings in user_jvm_args.txt, remember that the generated script does not read it.
For Forge 1.16.5 and older, turn off "Start From the Args File" and enter the name of the Forge jar the installer created. Fabric works like a normal jar: run the Fabric server launcher from the Fabric website, or the fabric-server-launch.jar the Fabric installer writes, with -jar.
To install a modpack server in the first place, run the installer in an empty folder with java -jar forge-<version>-installer.jar --installServer (NeoForge: neoforge-<version>-installer.jar --installServer), then put the generated script next to the libraries folder.
Which Java version to use
The server will not start on a Java that is too old for it. The requirements follow the Minecraft version:
| Minecraft version | Java needed |
|---|---|
| 1.20.5 and newer | Java 21 |
| 1.18 to 1.20.4 | Java 17 |
| 1.17 | Java 16 |
| 1.16.5 and older | Java 8 or 11, depending on mods |
Newer Java versions generally run older Minecraft servers fine; the exception is old Forge versions, which often need exactly Java 8. The Java Version option in the generator only changes which flags are written, such as -XX:+UseNUMA for Java 17 and later. It does not pick the Java your machine runs.
If you have several Java versions installed, put the full path in "Java Command", for example /usr/lib/jvm/java-21-openjdk-amd64/bin/java on Debian or Ubuntu, or C:\Program Files\Eclipse Adoptium\jdk-21.0.4.7-hotspot\bin\java.exe on Windows. The generator quotes paths with spaces for you. Run java -version to see which version the plain java command starts.
How to install the script
Linux and macOS
- Save the output as
start.shin the server folder, next to the server jar - Make it executable once:
chmod +x start.sh - Start the server:
./start.sh
The script changes into its own folder first, so you can also start it from anywhere with the full path, such as /home/minecraft/server/start.sh.
A server started straight from an SSH session stops when the session ends. Start it inside screen or tmux so it keeps running after you disconnect:
screen -S minecraft ./start.sh
Press Ctrl+A and then D to leave it running, and screen -r minecraft to get back to the console. With tmux, tmux new -s minecraft ./start.sh, Ctrl+B and then D to detach, and tmux attach -t minecraft to return.
For a server that starts with the machine, run the script from a systemd service or a @reboot crontab entry that starts a detached screen session. With systemd you can leave the restart loop off and let Restart=on-failure in the unit do that job instead.
Windows
- Save the output as
start.batin the server folder - Double-click it
Windows hides known file extensions by default, so a file saved from Notepad as start.bat can end up as start.bat.txt and open in Notepad instead of running. Turn on "File name extensions" in the View menu of File Explorer to check, or use the Download button, which saves the file with the right name. The generator writes the batch file with Windows line endings, which goto needs to work reliably.
To expose a Windows server to friends, you will also need to allow Java through Windows Defender Firewall. On a Linux machine, the firewall rules generator writes the ufw or iptables rules for the game port.
Common mistakes
"Unable to access jarfile server.jar"
Java cannot find the jar. Either the name in the script does not match the file, which happens after every update when the jar is called something like paper-1.21.1-133.jar, or the script is running from another folder. The generated script changes into its own folder, so check the name. Renaming the jar to server.jar after each download means you never have to edit the script again.
"java: command not found" or "'java' is not recognized"
Java is not installed or not on the PATH. Install a Java runtime such as Eclipse Temurin, or put the full path to java in the script.
UnsupportedClassVersionError
The server needs a newer Java than the one that started it. The error mentions a class file version: 61 means Java 17, 65 means Java 21. Install that Java and point the script at it.
"Could not reserve enough space for object heap"
Java could not get the memory you asked for. The machine does not have that much free memory, or you are running a 32-bit Java, which cannot use more than about 1.5 GB. Lower the RAM or install a 64-bit Java.
"Permission denied" or "bad interpreter"
Permission denied means the script is not executable yet: run chmod +x start.sh. /bin/sh^M: bad interpreter means the file has Windows line endings, which happens when it is edited on Windows and uploaded. Fix it with sed -i 's/\r$//' start.sh, or download it again from this page on the server.
The server lags even with good flags
Flags reduce garbage collection pauses, but they cannot fix a server that does too much work on the main thread. High view distances, entity farms and heavy plugins are the usual causes. The guide on how to fix Minecraft server lag walks through finding the cause with a profiler, and the server.properties generator sets view and simulation distance.
Running two copies at once
Double-clicking start.bat twice, or starting a second screen session, starts a second server on the same world. The second one fails to bind the port, but it may still touch the world files first. Check with screen -ls or Task Manager before you start the server again.
Docker and hosting panels
If your server runs in Docker, you do not need a startup script. The itzg/minecraft-server image builds the java command from environment variables: MEMORY sets -Xms and -Xmx, USE_AIKAR_FLAGS=true adds Aikar's flags, and the container's restart policy takes the place of the restart loop.
Hosting panels such as Pterodactyl also start the server themselves, from a startup command in the panel settings. You can paste the java line from this tool into that field; leave out the loop, because the panel handles restarts. On ChunkPod, the server is started for you, so there is no script to maintain.