Minecraft server proxy

Setting up a Velocity Minecraft server for multiple mods on Linux: A Step-by-Step Tutorial

Setting up a Java Minecraft server using a Velocity proxy, with multiple mods and mod frameworks, can be quite challenging. It’s similar to solving a complex puzzle, where each piece must fit perfectly for everything to function correctly. Ensuring that your server mods, client mods, and both server and client frameworks align seamlessly is crucial. Additionally, you need to verify compatibility with your Java version. In this tutorial, ll guide you through the process step by step, making it easier to configure your Minecraft server successfully.

Setup and environment recommendation

For my setup, I use a custom-built Proxmox server, but you can use any environment you prefer. It may be beneficial to use a dedicated computer that can run continuously, as you might not want to start the environment from scratch each time.

Recommend environment:

  • At least 16gb of ram, more is always better
  • Linux, unraid or docker, but Windows or macOS can work too
  • ~100GB storage space or more

Setting up your system for Proxmox

Assuming you are using proxmox, you should have this ready by following the Proxmox installation guide. Now that your system is ready, you can choose to either run it using docker or linux. I prefer using a debian machine, since I may add other software as well on this machine, such as a database for storing plugin data. For setting the debian machine up you can use the debian LXC script on your host, from proxmox helper scripts:

bash -c "$(wget -qLO - https://github.com/tteck/Proxmox/raw/main/ct/debian.sh)"

For proxmox and for other machines, you can set up your system by preparing a folder in which we can make the servers.

Management setup

Since managing multiple servers manually through terminal commands and scripts can quickly become overwhelming, we will use a management tool. In this tool we can manage our minecraft servers and proxy, including management for logs, scheduling, backups, files, configuration, player management, metrics and even webhooks.

During my search for a management tool, I started with MineOS. I will save you the hassle, don’t bother with this tool. The tool does not work properly with external jars and does not support a proxy natively. Also there are some bugs and the UI feels really outdated.

Instead, we will be using Crafty Controller. Crafty Controller is an open source Minecraft Server control panel and provides a web interface for convenient managing of your Minecraft servers. It even has event for detecting crashes and it has all the tools we need for managing our environment.

Installing Crafty is as easy as following the guide on their website. Choose the correct environment and follow the steps. For our environment we will open the linux terminal, get in the correct folder and execute the commands:

git clone https://gitlab.com/crafty-controller/crafty-installer-4.0.git && \
 cd crafty-installer-4.0 && \
 sudo ./install_crafty.sh && \
sudo su crafty && \
cd /var/opt/minecraft/crafty && \
./run_crafty.sh

After it has started you should be able to enter the web interface by going to your IP-address of your machine, and adding the port 8443, such as: “https://192.168.0.4:8443”. You should be greeted and be able to manage your servers in a dashboard like the image below.

Minecraft servers setup

Velocity proxy

The first server we will set up, is the most important, our proxy. This proxy allows us to route the incoming connections of our clients to the proper server. You can see this as our gateway, which directs client requests to the appropriate backend server based on predefined rules.

Since we need a proxy which is stable, can support multiple environments, versions and permission management, we will use Velocity. Other options are Bungeecord, Waterfall, Flamecord or Travertine, but most of these are either deprecated, very bug polluted, slow, or suffer from incompatability.
Velocity is a modern, high-performance proxy that overcomes these problems. It is a high speed and stable alternative and even has its own plugins ecosystem, which allows for custom additions.

While the initial setup of a proxy may be more difficult than directly connecting to a server, it has many advantages in the long run. It allows for easy scalability and managing of a lot of users. Some plugins that can be used are:

  • Luckperms: An easy-to-use permission management plugin
  • Epicguard: Anti bot protection system
  • Maintenance: Maintenance mode for preventing some players to join
  • ViaVersion: Allowing newer clients to connect to older server
  • ViaBackwards: Allowing older clients to connect to newer servers
  • Ambassador: Allowing 1.13-1.20.1 forge clients to join
  • Plan: In dept statistics about the server
  • Slashhub: Accessing lobby and hubs across servers
  • LibertyBans: Bans across servers
    There are way more plugins, here are some useful ones and you can search all of them here

You can install Velocity by going to the crafty dashboard and clicking on ‘create a new server’. In the server type you should be able to choose ‘minecraft proxies’ and select velocity. Use the latest version, assign a name of your preference and assign resources and a port. Note that this port should be unique and the other servers should all have a different port. Now click on ‘build server’ and it should be ready after a couple of seconds.

A new folder is now created on your machine at the directory of /var/opt/minecraft/crafty/crafty-4/servers/UUID. This UUID is visible in your crafty dashboard. By going to the files tab of your velocity server, you should see the same files as your file explorer or terminal.

Configuring Velocity is as easy as going to the files tab in Crafty and editing the Velocity.toml file.
Here you can edit the port, which you need for port-forwarding, the motd, player limit, online-mode and a lot more.

Since there is a lot of configuration going on in this file, below is an example velocity.toml which you can adjust to your needs. Pay specific attention to: your port numbers, forwarding mode, server order and haproxy mode. Since I’m using a Nginx Proxy Manager for my network, I have this enabled. If you do not have this, you should probably disable this.

# Config version. Do not change this
config-version = "2.7"
# What port should the proxy be bound to? By default, we'll bind to all addresses on port 25577.
bind = "0.0.0.0:25577"
# What should be the MOTD? This gets displayed when the player adds your server to
# their server list. Only MiniMessage format is accepted.
motd = "<#09add3>Your super cool Minecraft Server"
# What should we display for the maximum number of players? (Velocity does not support a cap
# on the number of players online.)
show-max-players = 500
# Should we authenticate players with Mojang? By default, this is on.
online-mode = true
# Should the proxy enforce the new public key security standard? By default, this is on.
force-key-authentication = true
# If client's ISP/AS sent from this proxy is different from the one from Mojang's
# authentication server, the player is kicked. This disallows some VPN and proxy
# connections but is a weak form of protection.
prevent-client-proxy-connections = true
# Should we forward IP addresses and other data to backend servers?
# Available options:
# - "none":        No forwarding will be done. All players will appear to be connecting
#                  from the proxy and will have offline-mode UUIDs.
# - "legacy":      Forward player IPs and UUIDs in a BungeeCord-compatible format. Use this
#                  if you run servers using Minecraft 1.12 or lower.
# - "bungeeguard": Forward player IPs and UUIDs in a format supported by the BungeeGuard
#                  plugin. Use this if you run servers using Minecraft 1.12 or lower, and are
#                  unable to implement network level firewalling (on a shared host).
# - "modern":      Forward player IPs and UUIDs as part of the login process using
#                  Velocity's native forwarding. Only applicable for Minecraft 1.13 or higher.
player-info-forwarding-mode = "modern"
# If you are using modern or BungeeGuard IP forwarding, configure a file that contains a unique secret here.
# The file is expected to be UTF-8 encoded and not empty.
forwarding-secret-file = "forwarding.secret"
# Announce whether or not your server supports Forge. If you run a modded server, we
# suggest turning this on.
# 
# If your network runs one modpack consistently, consider using ping-passthrough = "mods"
# instead for a nicer display in the server list.
announce-forge = true
# If enabled (default is false) and the proxy is in online mode, Velocity will kick
# any existing player who is online if a duplicate connection attempt is made.
kick-existing-players = false
# Should Velocity pass server list ping requests to a backend server?
# Available options:
# - "disabled":    No pass-through will be done. The velocity.toml and server-icon.png
#                  will determine the initial server list ping response.
# - "mods":        Passes only the mod list from your backend server into the response.
#                  The first server in your try list (or forced host) with a mod list will be
#                  used. If no backend servers can be contacted, Velocity won't display any
#                  mod information.
# - "description": Uses the description and mod list from the backend server. The first
#                  server in the try (or forced host) list that responds is used for the
#                  description and mod list.
# - "all":         Uses the backend server's response as the proxy response. The Velocity
#                  configuration is used if no servers could be contacted.
ping-passthrough = "ALL"
# If not enabled (default is true) player IP addresses will be replaced by <ip address withheld> in logs
enable-player-address-logging = true
forced-hosts = {}

[servers]
	# Configure your servers here. Each key represents the server's name, and the value
	# represents the IP address of the server to connect to.
	survival = "127.0.0.1:25565"
	lobby = "127.0.0.1:25566"
	neoforge = "127.0.0.1:25567"
	forge = "127.0.0.1:25568"
	fabric = "127.0.0.1:25569"
	# In what order we should try servers when a player logs in or is kicked from a server.
	try = ["neoforge", "survival", "lobby", "forge", "fabric"]

# Configure your forced hosts here.
[advanced]
	# Specify a read timeout for connections here. The default is 30 seconds.
	read-timeout = 30000
	# Enables TCP fast open support on the proxy. Requires the proxy to run on Linux.
	tcp-fast-open = true
	# How much compression should be done (from 0-9). The default is -1, which uses the
	# default level of 6.
	compression-level = 5
	# How large a Minecraft packet has to be before we compress it. Setting this to zero will
	# compress all packets, and setting it to -1 will disable compression entirely.
	compression-threshold = 256
	# How fast (in milliseconds) are clients allowed to connect after the last connection? By
	# default, this is three seconds. Disable this by setting this to 0.
	login-ratelimit = 3000
	# Specify a custom timeout for connection timeouts here. The default is five seconds.
	connection-timeout = 5000
	# Enables logging of player connections when connecting to the proxy, switching servers
	# and disconnecting from the proxy.
	log-player-connections = true
	# Enables BungeeCord plugin messaging channel support on Velocity.
	bungee-plugin-message-channel = true
	# Shows ping requests to the proxy from clients.
	show-ping-requests = false
	#Allows players transferred from other hosts via the
	#Transfer packet (Minecraft 1.20.5) to be received.
	accepts-transfers = false
	# By default, Velocity will attempt to gracefully handle situations where the user unexpectedly
	# loses connection to the server without an explicit disconnect message by attempting to fall the
	# user back, except in the case of read timeouts. BungeeCord will disconnect the user instead. You
	# can disable this setting to use the BungeeCord behavior.
	failover-on-unexpected-server-disconnect = true
	# Declares the proxy commands to 1.13+ clients.
	announce-proxy-commands = true
	# Enables compatibility with HAProxy's PROXY protocol. If you don't know what this is for, then
	# don't enable it.
	haproxy-protocol = true
	# Enables the logging of commands
	log-command-executions = true
[query]
	# If query is enabled, on what port should the query protocol listen on?
	port = 25577
	# Whether plugins should be shown in query response by default or not
	show-plugins = true
	# This is the map name that is reported to the query services.
	map = "Velocity"
	# Whether to enable responding to GameSpy 4 query responses or not.
	enabled = false

Now that the configuration is ready, you can start the server once and continue adding plugins in the plugins folder. In this same directory the plugins will create new folders where you can change the configuration of the plugins. For slashhub for example, you can change the server that will be joined by using /lobby.

Now that Velocity is set up, you can copy the forwarding secret file. This has been made in the velocity root folder and is called forwarding.secret. This file is important as this is the secret that the other servers will need to be allowed by Velocity through the proxy.

Vanilla server

We will start off easy, by connecting a vanilla server to the proxy. The preferred vanilla experience behind Velocity is by using Paper. Paper is a Minecraft game server, designed to improve performance and offer a stable environment and API.

You can easily set up a new paper server by going to Crafty and again creating a new server, with this time the type “minecraft servers” and selecting paper with a version of your preference. Add a name and a server port, where this port is unique. For our case we will make this our lobby server, so we use port 25566, as previously defined in our velocity config. You should allow this port through your local firewall. A remote connection is not needed as all external clients are always connected through our single proxy port.

Now that the server has been created, go to the files tab and edit the server.properties. Since the backend servers will always connect through velocity, the online-mode must be set to false. The server ip should be 0.0.0.0, since you are hosting it locally and letting Velocity do the work.
Before we can configure it further, we should first start and stop it once, to let it generate files.

Since Paper is tightly related to Velocity, is has build in functionality to connecting Velocity by using the secret. Other server may need a plugin or mod in order to facilitate this.
Paper should have created a folder called Config in the root, where a file called paper-global.yml is available. In this file there is a “proxies” section, where you can enable velocity by setting enabled to true and inputting our secret we copied some time ago. The online-mode should still be false.

Since we have already configured this server in our velocity configuration, we can now start velocity and this server. After we join by entering the local ip and port of velocity, or if you have port forwarding set up, through your hostname, you should now be able to join the vanilla server through Velocity.

Since for our purpose we use this server as a lobby, we can also add some plugins to make this possible. Note that not all modded instances can join this lobby, only the correct modded server directly. Some plugins for the lobby, are for example:

Fabric server

We can also connect a fabric server. Since fabric is natively supported in Crafty, you can add it just like the other servers using the UI. Again make sure you use a correct port and alter the configuration to connect it with velocity.
To connect it to velocity, we will need the FabricProxy-Lite mod. After you have run the server once, a folder called config should have been made, with a FabricProxy-Lite.toml file. In this file you can add our velocity secret.

After you have added the server in velocity, you can for example add it in akropolis, by changing the config/Akropolis/menus/serverselector file in your lobby server. You can add a record here with the name of the server and a mterial, and make sure to add an action with [SERVER] yourservername, with the name set to the name of your server in the velocity configuration. For example, [SERVER] fabric, if the name of your fabric server is fabric, in the velocity configuration.

After you have configured this, you should be able to use the compass in the lobby to forward yourself to the fabric server.

I use a fabric server usually for a server with a nice atmosphere of world. There are many mods for biome and structure additions possible in fabric. Some of the mods you can explore, are:

Tartarus terra nether

Neoforge server

Setting up a neoforge server is not natively possible in Crafty. Thus, we will have to do this one manually. First, get the neoforge version of your wish from neoforged. After you have the installer, make a folder on your local computer and open a terminal in the directory. For windows for example:

mkdir "%USERPROFILE%\neoforgeServer" & explorer "%USERPROFILE%\neoforgeServer"

Now in this folder, copy your downloaded neoforge installer jar.
After you have succesfully added your installer here, open a terminal in this folder (in correct directory, by using cd “%USERPROFILE%\neoforgeServer”), and now use the following command to build the server:

java -jar neoforge-installer.jar -installServer

Instead of the neoforge-installer.jar, use your own installer file name. After you have run this in your terminal, it should build the libraries. Copy these files somewhere to your server.
Now make a new server in crafty through the UI, but use the import an existing server this time, and input the path of your libraries there. You can find the jar in libraries/net/neoforged/neoforge/yourversion/neoforge-yourversion-server.jar.

After is has succesfully imported, it may not boot correctly. You can fix this by changing the Server Execution Command in the Config tab in Crafty for your Neoforge server.
This will also need the correct java version, if the default is not correct. You can just install a new java version and select the correct one. An example execution string is:

"/usr/lib/jvm/jdk-21.0.4-oracle-x64/bin/java" @user_jvm_args.txt @libraries/net/neoforged/neoforge/21.0.167/unix_args.txt neoforge-21.0.167-server.jar nogui 

After you have used the correct java version for your neoforge server, it should boot succesfully.

To get it working with velocity, you will need the NeoForwarding mod. You can just add this to your mod folder, boot the server once, and a configuration file called neoforwarding-server.toml should be greated in your config folder of the server. In here you can add the forwarding secret of velocity again. Also set enableforwarding and crosstitch on true.
Now you can add this server to velocity and your lobby menu in akropolis again and you should be able to join it, if you have the correct mods on your client.

In my opinion one of the most promising mods for neoforge at this time is Aether2. Since at this moment it is still in development, and the official releases don’t have the latest versions yet, you can grab a beta version from CircleCI. You can find one for your version by choosing select branch on the CircleCI website referenced above, and clicking on a build and deploy, deploy and then artifacts. You should find a aether_ii-1.21-0.0.1-neoforge.jar file here, like this one. Download this and put it in both your client mods and the server mods folder. After booting and joining you should be able to enter the aether dimension like below!

Aether 2 dimension

Forge server

Since halloween is around the corner, we will make the forge server horror-themed. Fortunately, forge is supported from the Crafty UI, so you can just create it using the usual steps. Selecting your version, port and memory.

After is has been built succesfully, you will need a plugin to connect it to velocity. For forge servers we can use Proxy Compatible Forge. Also, this time, since we are using horror mods that use 1.20.1, we will be using the Ambassador plugin, which provides proxy compatibility for older versions.
Now start the server once, and fill in the velocity secret in the config/pcf-common.toml file of your forge server. After restarting and adding it to your lobby you should be able to join this server.

For our horror-themed server we can use some plugins:

Fine tuning

There are a couple of important aspects that really need to be perfectly balanced in order to make modded servers work in velocity:

  • Client mod versions must be the exact same as server mods for forge and neoforge
  • Java version must be properly matched to Minecraft version
  • Building the correct version of your curseforge and neoforge, and using the same version in your client.

Compatibility and limitations

As of now, it seems like that Neoforge can not join a paper server (lobby for example). Thus the order for neoforge needs to be that neoforge is first, otherwise it will not join.

For Fabric, joining paper (such as a lobby) works fine. However, joining forge or neoforge will not work with a fabric client.

For Forge, joining the lobby works also fine. However, after you switch to forge from the lobby, you will need to reconnect, which is caused by Ambassador. You can solve this by using Forward Forge Client Reset Packet.

For best compatibility, the recommended velocity order is: “forge”, “neoforge”, “survival”, “lobby”. Since neoforge doesn’t care that it is connecting to forge first, but joining a paper will stop neoforge from joining. Forge doesn’t like neoforge, so having that first is better. Regular vanilla does just fail for forge and neoforge so will always join survival first in this order and the lobby if it is not up. By using /lobby you can go to the lobby server, or /server servername to a server.
Also use ViaVersion and ViaBackwards to allow more client versions to connect.

It is recommended to not put this on the proxy, as this may introduce problems and is less stable. Instead, place this on all the backend servers.


Similar Posts

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments