Skip to main content
You need a Velocity, BungeeCord or Waterfall proxy and at least one Paper or Folia backend with Nexo already installed and working.
1

Install NexoHub on the proxy

Drop the jar for your proxy into its plugins/ folder and start it: NexoHubVelocity.jar on Velocity, NexoHubBungee.jar on BungeeCord or Waterfall.On first start it creates plugins/nexohub/config.yml and generates a secret into it. On BungeeCord the folder is plugins/NexoHub/; everything else is the same, and the rest of this site writes it plugins/nexohub/ for both. Copy that value; you need it on every backend.
2

Decide where the pack is hosted, or do not

Nothing to do here on a fresh install. The pack is uploaded to Hermes, Nexo’s own host, and every backend hands players that link, so there is no port to open and no address to get right.
To serve the pack from the proxy itself instead, set host: proxy and fill in the address players will use:
Under host: proxy that address ends up in the resource pack link sent to every player, so it has to be reachable from the internet and the port has to be open in your firewall. Left blank, NexoHub falls back to localhost, which only works for testing on your own machine.
See where the pack is hosted for the other hosts and for what multipack needs.
3

Install the bridge on each backend

Drop NexoHubBridge.jar into each backend’s plugins/ folder, next to Nexo.In plugins/NexoHubBridge/config.yml:
That is the only file you edit. Nexo’s own Pack.server.type is set to HUB for you on the first start that finds a settings.yml, before Nexo has read it.Restart the backends. The hub is still empty and nobody has joined yet, so each one says so and waits:
Written once, then left alone. Setting it back by hand at any point takes that backend out of the network and the bridge will not undo it. On a backend where Nexo has never run there is no settings.yml to write into yet, so the bridge says it will do it on the next start and does.
Leave server_name: auto. The proxy tells each backend what it is called the first time a player joins, so the name only ever lives in your proxy’s own server list: velocity.toml, or BungeeCord’s config.yml.
4

Fill the hub from one backend

Join the network, then on the proxy name the backend whose plugins/Nexo/ the whole network should build from:
That backend sends its folder up:
Join the network before you run this. On server_name: auto a backend does not know its own name until a player joins, and it cannot be adopted from until it does. The request expires after five minutes.
Adopting overwrites _shared/ with that one backend’s files, so every other backend is about to be given them. If your servers have drifted apart, decide which one to name first: see moving an existing network.
You can fill nexo-data/ over SFTP instead, at any point. Copy the contents of one backend’s plugins/Nexo/ folder into plugins/nexohub/nexo-data/_shared/, keeping the same layout:
Skip anything generated: pack/pack.zip, everything under pack/external_packs/, and hidden folders such as .assetCache/. NexoHub handles plugin packs separately, see plugin packs.
5

Check every backend picked it up

The hub pushes the moment it has files, so every other backend receives them without a restart:
On the second and later backends the upload turns into a skip:
Then run /nexohub status on the proxy:
6

Check the rest of it

This tests the things you cannot see from where you are standing. On host: proxy the most important of them is whether the address in your resource pack link answers from outside your own network; on the default delegated hosting there is no address of yours to test and it says so.

From now on

Edit any file under nexo-data/ and save. Within a few seconds every backend pulls the change, reloads Nexo, and players get the updated pack. You do not need to run a command or restart anything.
Nothing is pushed unless it parses first. If you mistype a line, your backends stay on the last files that worked and the error goes to your console instead of to your players. See not breaking your network.
A backend with nobody on it cannot be sent a message, so it asks the hub for changes on its own every minute. It reports what it has on the same request, so an empty server still shows up correctly in /nexohub status.