Want to run your own Minecraft world for friends, build a survival realm, or host a creative-mode showcase? Self-hosting is the way to go — and it's far easier than it looks once you have a real deployment workflow behind it. This guide walks you through setting up a Minecraft Java Edition server on a Linux VPS with an automated deployment tool, so every plugin update, config tweak, and version bump ships from Git instead of FTP.
If you're running multiple game servers through a control panel, see our companion guide on Pterodactyl panel deployments. This post focuses on a single-server, plain-VPS setup — the foundation most self-hosters start from.
What you'll need
Before we begin, gather your tools:
- A Linux VPS: We recommend an Ubuntu 24.04 LTS (or Debian 12+) VPS. Ubuntu 20.04 reached end of standard support in May 2025 — don't start a new server on it. New to VPSes? Our What is a VPS? primer covers the basics. For Minecraft 1.21+ vanilla, plan for at least 2 vCPUs, 4 GB RAM, and 50 GB SSD. Modded packs and Paper with many plugins need more — 8 GB RAM is a comfortable floor once you start adding plugins.
- A DeployHQ account: This is where the automation lives. A free trial gets you running.
- An SSH client: macOS/Linux Terminal, Windows Terminal, or any SSH client you prefer.
- A Git repository (GitHub, GitLab, or Bitbucket) to hold your
server.properties,eula.txt, plugin configs, and any datapacks. DeployHQ pulls from there on every change.
Step 1: Prepare your VPS
Connect via SSH
ssh root@your-server-ip
For production, create a non-root sudo user and disable root login over SSH — but that's outside this guide's scope.
Install Java 21 (Minecraft's current requirement)
Minecraft Java Edition 1.21 and later requires Java 21 (Java SE 21 LTS) per the official Minecraft Wiki. Older guides recommending Java 17 are stale — 1.21 won't start on Java 17.
Ubuntu 24.04 ships OpenJDK 21 directly:
sudo apt update
sudo apt install -y openjdk-21-jdk
java -version
You should see openjdk version "21" in the output. If you're sticking with an older Minecraft version (1.20.x) you can substitute openjdk-17-jdk, but the rest of this guide assumes 1.21+.
Create a dedicated user and directory
Running Minecraft as root is sloppy. Create a service user and a home for the server:
sudo adduser --system --group --home /opt/minecraft minecraft
sudo mkdir -p /opt/minecraft
sudo chown -R minecraft:minecraft /opt/minecraft
Open the firewall port
Minecraft uses TCP port 25565 by default:
sudo ufw allow 25565/tcp
sudo ufw enable # only if the firewall isn't already on
Step 2: Choose your server JAR (Vanilla vs Paper)
You have two practical options:
- Vanilla (official
server.jarfrom minecraft.net): faithful to Mojang's release, but slower under load and no plugin support. Fine for small friend-group servers running stock gameplay. - Paper (drop-in replacement): performance-tuned fork of Spigot/Bukkit. Supports thousands of plugins, runs significantly better on a constrained VPS, and is what most serious self-hosters use. PaperMC documents Java requirements per Minecraft version — 1.20-1.21.11 is recommended on Java 21.
For this guide we'll set up Paper, since the build pipeline story (deploying plugins and configs from Git) only becomes useful once plugins are in play. The Java install is identical for vanilla — just swap the JAR.
Step 3: Set up your Git repository
Create a Git repo with this layout:
minecraft-server/
├── server.properties
├── eula.txt
├── ops.json # optional, empty array to start
├── whitelist.json # optional, empty array to start
├── plugins/ # commit any Paper plugins you trust
│ └── .gitkeep
└── README.md
Your eula.txt should contain:
eula=true
By committing eula=true you've already accepted Mojang's EULA — DeployHQ will deploy it on the first push and the server will start without the manual prompt step.
Don't commit paper.jar itself — it's binary, can be large, and you'll download a fresh build directly on the server. Commit a download-paper.sh script alongside it instead (see the build hook in Step 5).
Step 4: Create the DeployHQ project
- Log in to DeployHQ and click New Project.
- Connect the Git repository you just created.
- Once the project exists, head to Servers → New Server.
Fill in:
- Server Name:
Minecraft Production - Protocol: SSH/SFTP
- Hostname: your VPS public IP
- Port: 22
- Username:
minecraft(the user you created in Step 1) — not root - Authentication: SSH Key
- Deployment Path:
/opt/minecraft
- Server Name:
DeployHQ will generate an SSH public key. Copy it and add to
/opt/minecraft/.ssh/authorized_keyson your VPS (create the.sshdirectory with0700and the file with0600first).
If the difference between deployment paths, build commands, and server steps is unfamiliar, our short primer on what a deployment script does is a good detour. If you've never used DeployHQ for a VPS before, our walkthrough on setting up Git-based deployment on a VPS covers the foundational steps that apply to any project — Minecraft or otherwise.
Step 5: Configure deployment hooks
This is where Git-based Minecraft management starts to feel like a real deployment pipeline rather than a glorified FTP push.
Pre-deployment SSH command (stop the server cleanly)
In your DeployHQ project's SSH commands section, add a Before deployment command:
sudo systemctl stop minecraft || true
The || true keeps the deployment from failing on first run when the service doesn't exist yet.
Build pipeline (download Paper)
If your repo doesn't ship paper.jar, add a build step that downloads the version your paper-version.txt pins to. Paper's downloads API exposes per-build URLs — replace 1.21.4 and build with your pinned values:
curl -o paper.jar -L "https://api.papermc.io/v2/projects/paper/versions/1.21.4/builds/<build>/downloads/paper-1.21.4-<build>.jar"
Pinning a specific build is deliberate — latest
silently changing under you is how Minecraft servers crash mid-Friday-night.
Post-deployment SSH command (start the server)
sudo systemctl daemon-reload
sudo systemctl enable minecraft
sudo systemctl start minecraft
The systemd unit (one-time setup on the VPS)
Modern Linux servers don't need screen or tmux. Create /etc/systemd/system/minecraft.service with:
[Unit]
Description=Minecraft Java Edition Server
After=network.target
[Service]
Type=simple
User=minecraft
Group=minecraft
WorkingDirectory=/opt/minecraft
ExecStart=/usr/bin/java -Xms4G -Xmx4G -jar paper.jar --nogui
Restart=on-failure
RestartSec=10
SuccessExitStatus=0 143
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Restart=on-failure is the part screen can never give you — if the JVM crashes the server comes back up by itself. View logs with journalctl -u minecraft -f.
Adjust the -Xms / -Xmx values to match your VPS. The PaperMC docs explicitly recommend leaving 1-1.5 GB for the OS and Java overhead — a 4 GB VPS should set both flags to roughly 3 GB, not 4.
Step 6: Run your first deployment
In DeployHQ, click Deploy. Watch the deployment log: it'll transfer your repo, run the build pipeline, execute the pre/post SSH hooks, and start the systemd service. SSH back in and check:
systemctl status minecraft
journalctl -u minecraft -n 50 --no-pager
You should see Paper's startup banner and an [Done] For help, type
help"" message.
Connect from your Minecraft client (Multiplayer → Add Server → your VPS IP). Done.
Production tuning (the parts other guides skip)
Aikar's JVM flags
For Paper servers under any real load, the community-standard Aikar's flags
tune the G1 garbage collector for the Minecraft tick loop. PaperMC publishes the canonical version at docs.papermc.io/paper/aikars-flags. Replace the ExecStart line in your systemd unit with the full flag set from that page (it's long — quoted in their docs in full). Don't transcribe Aikar's flags from random forum posts; the canonical version evolves and PaperMC's copy is the one to trust.
View distance and simulation distance
Memory-constrained VPSes choke on the default view-distance=10 once a few players are online — each chunk loaded costs RAM. Edit server.properties and commit:
view-distance=8
simulation-distance=6
view-distance controls how far chunks are sent to clients; simulation-distance controls how far entities and redstone are ticked. Lowering simulation-distance more aggressively than view-distance is the cheapest win — most players don't notice, and your TPS recovers significantly.
Plugin and config updates via continuous deployment
This is the whole point of using DeployHQ for a Minecraft server. Once your repo is wired up, the day-to-day looks like:
- Drop a new plugin JAR into
plugins/, or editserver.properties. -
git push. - DeployHQ stops the server, transfers files, runs your build step, and restarts.
- If the new plugin crashes the server, one-click rollback reverts to the previous known-good state — no scrambling through FTP at midnight.
If you run separate creative and survival worlds (or production and a staging test new plugins here
world), our guide on managing multiple environments with DeployHQ shows the pattern.
World backups (3-2-1, game-server edition)
The 3-2-1 rule from data engineering (3 copies, 2 different media, 1 off-site) maps cleanly to Minecraft. Your world is split across three directories Paper creates next to the JAR:
-
world/— overworld -
world_nether/— the Nether -
world_the_end/— the End
Back up all three together — restoring only the overworld will scramble linked portals. A nightly cron that pauses with screen -S minecraft -X stuff "save-off\n" (or mc-send-to-console save-off via RCON), tar-gzips the three directories, then resumes with save-on will get you most of the way there. For the off-site copy, push the tarball to S3, B2, or a second VPS.
Stopping the server cleanly during deployments
Slamming a kill into the JVM mid-tick can corrupt a chunk. The systemd unit above already handles SIGTERM correctly because Paper traps it and runs a save before exit — which is why we used SuccessExitStatus=0 143. Combined with the right Before deployment
command, this gives you zero downtime deployments only for the parts that don't require restart (config-only changes), and clean restarts for the parts that do.
SSH and Agents
If you'd rather skip configuring DeployHQ's SSH hooks by hand and deploy from your terminal instead, DeployHQ Agents wrap the same workflow with a CLI that fits in any shell pipeline — useful when you want to wire Minecraft restarts into existing infra scripts.
Wrapping up
Self-hosting a Minecraft server doesn't have to mean SSHing into the VPS at 11 PM to fix something. With your server.properties, plugins, and configs in Git, DeployHQ handling transfer + restart, and systemd keeping the JVM alive between deployments, day-two operations stop being scary.
Sign up for DeployHQ and start treating your game server like a real production system.
Questions or stuck on a step? Email support@deployhq.com or hit us up on X (@deployhq).