A Guide To Selfhosting A Minecraft Server

Posted on Jul 15, 2026
tl;dr: Wrote a short guide to selfhosting a Minecraft server

My nephew wanted to host a Minecraft server for him and his friend. He asked me for some help since I have hosted a lot of game servers myself.

So I wrote a short guide on how I set up my minecraft servers and how I would recommend him to do so himself.

Preparations

SSH Keys

If you don’t already have a SSH key pair, you should generate one. You should put your public key on your server and use your private key to connect to the server. The private key should, as the name suggests, stay private. You should never post this key online, upload it in a git repo, etc.

To generate the keypair you should run these commands:

ssh-keygen
# Keep everything default
# this generates 2 files
# - <keyname> --> This is your private key
# - <keyname>.pub --> This is your public key 

On linux, put the public key file in /home/<username>/.ssh/authorized_keys. (This may be different for different flavors of linux)

Playit.gg account

If you do not want to port forward on your home router, you can use a proxy service like playit.gg. So I you plan on not port forwarding, you should make an account.

Linux

I have found some linux cheatsheets to help with the linux experience. If needed, you can checkout any of these for help.

To start you should run the update and upgrade commands and make a minecraft folder:

# Update and upgrade the server
sudo apt update
sudo apt upgrade

# Make a minecraft folder in the home folder and move into it
mkdir minecraft
cd minecraft

Minecraft server hosting

You can host the server native or in a Docker container. I prefer the native one, because I find it easier, but the docker containers certainly are also a good option.

Native hosting

Java

Install Java JDK (Ubuntu Forum)

# Search the package you want to install
sudo apt search openjdk
# ... # openjdk-21-jdk-headless/noble-updates,noble-security 21.0.9+10-1~24.04 amd64 # OpenJDK Development Kit (JDK) (headless) # ...

# Download the package 
sudo apt install openjdk-21-jdk-headless

Minecraft server

The vanilla minecraft server that Mojang provides will work, but isn’t as optimized as some other minecraft servers. If you want to install plugins the vanilla server isn’t what you are looking for.

I prefer the PaperMC server as it is more optimized and supports bukkit plugins. Go to the downloads page and copy the download link. Use this link to wget the server software to the server using this command:

# Make sure to use the -O <filename> to change the filename of the download file to whatever you want it to be
wget -O paper-1-21-11.jar 'https://fill-data.papermc.io/v1/objects/cf374f2af9d71dfcc75343f37b722a7abcb091c574131b95e3b13c6fc2cb8fae/paper-1.21.11-69.jar'

Accept the EULA, otherwise the server won’t start.

echo "eula=true" > eula.txt

Start the server with some parameters:

# - Xmx4G -> Max memory used by the server process
# - Xms1G -> memory used by the server process
# - jar <server-file-naam> -> use the filename you entered when you wget the serverfile
# - nogui -> no graphical user interface, only command line
java -Xmx4G -Xms1G -jar minecraft-server-1-21-11.jar nogui

Now your server is started.

Screen

If you are connected to your server with SSH and start the server in your terminal session you will find that whenever you logout or lose connection to your server, the minecraft server process is stopped. We obviously don’t want this, we want the minecraft server to be online 24/7.

There are a few different ways to accomplish this, but I prefer screen. Screen is a connmand line utility, a terminal multiplexer. This allows you to have multiple virtual terminal sessions running, even though you log out of your current SSH session, these will stay active.

# Start a screen session with the name minecraft
screen -S minecraft
# After this you'll just see a normal terminal. You might have to change the directory to your minecraft folder

# To detacht from the screen session press: Ctrl-A, Ctrl-D
# You'll be put back in your normal SSH session

# To list all active screen session run:
screen -ls

# To re-attacht to a screen session run:
screen -r minecraft

# Extra info about the screen command
screen --help

Hosting with docker

To host your minecraft server with Docker, you first should make sure you have Docker installed. To keep it simple for myself, I will not be explaining how to install Docker, this is explained very well on their website: Docker docs

For the docker image I like to use itzg/minecraft-server. Their documentation is quite good so for environment variables and parameters, you should go to their website.

I would recommend using a docker compose file instead of just running a docker run command so you always start your server with the exact same parameters. You can use this generator to generate your docker compose file for your minecraft server. Here is an example of a compose file I generated with the generator:

# Generated by setupmc.com on 2026-07-16T07:50:44.637Z

services:
  mc:
    image: itzg/minecraft-server:latest
    tty: true
    stdin_open: true
    ports:
      - "25565:25565"
    environment:
      EULA: "TRUE"
      MEMORY: "2048M"
      MOTD: "A Minecraft server for Podepod"
      USE_AIKAR_FLAGS: "true"
      TZ: "Europe/Brussels"
      DIFFICULTY: "3"
      SIMULATION_DISTANCE: "16"
      VIEW_DISTANCE: "16"
      SEED: "Podepod"
      SPAWN_PROTECTION: "0"
      OPS: |-
        Podepod
      ENABLE_WHITELIST: "true"
      WHITELIST: |-
        Podepod
        Podepod1
        Podepod2
      PAUSE_WHEN_EMPTY_SECONDS: "0"
      SERVER_NAME: "Podepod"
      SNOOPER_ENABLED: "false"
    volumes:
      - "./data:/data"

After saving that file in your minecraft folder as docker-compose.yml you should just be able to run this command:

# Start the docker container. After this you can use Ctrl-D to detach
docker compose up 

# Start the docker container detached
docker compose up -d

Making the server public

Important to know

A public Minecraft server means the whole internet has access to the server. Even though you might go through a proxy tunnel or only opened the one port on your firewall with port forwarding, you should consider the risk of this.

Make sure the online-mode and whitelist are enabled to avoid griefing:

  • If you turn off online-mode everybody can join with a selected username, even without a mojang/microsoft account. So if my username is Podepod and I am a admin on the server, another person could join the server under the same username. This will kick me off the server and the other person is now admin on my minecraft server untill I log back in which will kick them again. When in offline mode, the whitelist is also useless if everybody can see who is online. They can just join as that username. See https://madelinemiller.dev/blog/minecraft-offline-mode/
  • If you disable the whitelist, the server does not check the usernames of the players that join your server.

There are two ways to make your server public:

Port forwarding

Port forwarding opens a port on your networks firewall and points it to the networkport of a device on your internal network. For this, you should have access your networks firewall.

Proxy / tunneling

For this example I use playit.gg. There are a lot of other websites that provide this service.

Sign in to your PlayIt.gg account and go to Setup > New Account Wizard. Follow these steps and your copy the url they give you. You can now use this URL to connect to your minecraft server from anywhere with an internet connection.

DNS

If you own a domain name, you can set up DNS for your minecraft server aswel. For this you need an A record to point to the public IP of your minecraft server (if you don’t use a proxy. When using a proxy, use a CNAME record to point to your proxy endpoint instead of the A record) and a SRV record for the minecraft service. The SRV record should look like this:

Name _minecraft._tcp.minecraft.podepod.be
Type SRV
Priority 0
Weight 5
Port 25565
Target minecraft.podepod.be
The SRV record name is made up of a few parts:
Service _minecraft
Protocol _tcp
Name minecraft.podepod.be

After this you should be able to join the server by entering the domainname: minecraft.podepod.be

A few other good guides for this:

Customize the server

To change stuff like the name of the server, the Message Of The Day for your server or the server icon, … you will need to change the server settings in the server.properties file in your minecraft folder.

When using docker, you can configure all these settings with the docker compose generator.

Here is an example of this file I used for one of my servers:

#Minecraft server properties
#Fri Dec 05 19:35:55 UTC 2025
accepts-transfers=false
allow-flight=false
broadcast-console-to-ops=true
broadcast-rcon-to-ops=true
bug-report-link=
debug=false
difficulty=hard
enable-code-of-conduct=false
enable-jmx-monitoring=false
enable-query=false
enable-rcon=false
enable-status=true
enforce-secure-profile=true
enforce-whitelist=true
entity-broadcast-range-percentage=100
force-gamemode=false
function-permission-level=2
gamemode=survival
generate-structures=true
generator-settings={}
hardcore=false
hide-online-players=false
initial-disabled-packs=
initial-enabled-packs=vanilla
level-name=world
level-seed=Podepod
level-type=minecraft\:normal
log-ips=true
management-server-enabled=false
management-server-host=localhost
management-server-port=0
management-server-secret=-/-
management-server-tls-enabled=true
management-server-tls-keystore=
management-server-tls-keystore-password=
max-chained-neighbor-updates=1000000
max-players=20
max-tick-time=60000
max-world-size=29999984
motd=Podepod Minecraft Server
network-compression-threshold=256
online-mode=true
op-permission-level=4
pause-when-empty-seconds=60
player-idle-timeout=0
prevent-proxy-connections=false
query.port=25565
rate-limit=0
rcon.password=
rcon.port=25575
region-file-compression=deflate
require-resource-pack=false
resource-pack=
resource-pack-id=
resource-pack-prompt=
resource-pack-sha1=
server-ip=
server-port=25565
simulation-distance=12
spawn-protection=0
status-heartbeat-interval=0
sync-chunk-writes=true
text-filtering-config=
text-filtering-version=0
use-native-transport=true
view-distance=16
white-list=true

Other customization can also be done through plugins or mods, but I won’t go into that here.

Start and backup script

To start and backup my server I have two scripts. I do not run the backup automatically, but this could be done with a cronjob.

Start script

The start script is as simple as running the command itself. But I find it easier to run a script than to have to go through my terminal history to find which parameters I used.

File location: /home/<username>/minecraft/start.sh

#!/bin/bash
# └─> Bash Shebang

echo "Starting Minecraft Server"

java -Xmx4G -Xms2G -jar minecraft-server-1-21-11.jar nogui

Backup script

To run the backup, you should always stop the minecraft server, take the backup and restart the minecraft server. If you don’t do this, your backup might have wrong data and result in a server that won’t start.

File location: /home/<username>/minecraft/backup.sh

#!/bin/bash
# └─> Bash Shebang

echo "Starting Backup"

# Define the source and backup folders
source_dir="`/home/<username>/minecraft"
backup_dir="`/home/<username>/minecraft-backups"

# Define the backup file name (it includes the date and time to avoid duplicates)
timestamp=$(date +%Y-%m-%d-%H-%M-%S)
backup_file="backup_minecraft_$timestamp.tar.gz"

# Make the backup
tar -czf "$backup_dir/$backup_file" "$source_dir"

echo "Backup complete, removing old backup(s)"

# Remove backups older then 7 days
find "$backup_dir/*" -type f -mtime +7 -delete

echo "Done."

Running the scripts

Because of the bash shebangs, you should be able to run the scripts by just running the filenames as commands:

# in the minecraft folder
./start.sh
# or
./backup.sh

If you get an error saying command not found, it means that you do not (yet) have the rights to execute the scripts. You can check this with ls. And look for the x at the front. In the output here, the backup file does have execute permissions, the start file does not.

-rwxr-xr-x  1 podepod podepod        144 Nov 17 12:13 backup.sh*
-rw-r--r--  1 podepod podepod        228 Nov  3 10:56 start.sh

To change the file permissions we use chmod:

# Add the execute permission for the user
chmod u+x start.sh

ls
# output:
# -rwxr-xr-x  1 podepod podepod        144 Nov 17 12:13 backup.sh*
# -rwxr-xr-x  1 podepod podepod        228 Nov  3 10:56 start.sh*

Some interesting links vaguely related to this:

Server optimization

Whenever you are running your minecraft server on a host server with less resources, you should try to optimize the minecraft server. Some stuff to keep in mind:

  • Changing the Render- / viewing distance and / or simulation distance - This way the server has to load less chunks for each player
  • Using Paper MC (or other optimized) server jar - These versions of minecraft servers are more optimized than the default vanilla server software. Most of them also support plugins, which makes sure you get some extra functionality but the player can keep using the vanilla client.
  • Pregenerating chunks - Most of the lag on small servers is caused by new chunks being loaded. To prevent this, you can preload the chunks in your world. By doing this the world folder will get bigger then when you play on the server normally, but the server will not have to load new chunks when a player moves through them when exploring. I use the Chunky plugin for this but you can also do this manually, although this takes a lot of time.
  • “anti lag” plugins in most cases cause more lag then the same server without them, especially on a small scale minecraft server like the ones you most likely host for your friends.

Also have a look at these guides / articles:

Other peoples guides