Root-Core install guide
Root-Core is the connection spine for RootMC Paper servers — shared plugins/RootMC/ folder, product-key licensing, My Servers presence, and optional suite updates.
Download jar bStats metrics → Get a product key →
Requirements
- Paper 26.x (or compatible) Minecraft server you control
- Outbound HTTPS to
api.rootmc.net(license bind + presence) - A free developer account + product key from rootmc.net/developer
- Operator access to edit files under
plugins/
What Root-Core does
On enable, Root-Core:
- Creates or repairs the shared
plugins/RootMC/folder (notplugins/Root-Core/) - Reads
server-name+product-keyfromroot-core.yml - Binds to the Worker at
license.api-base(default api.rootmc.net) and fills blankcloud.server-id/server-secretintocloud.ymlonly - Sends license presence on a timer so My Servers shows online
- Optionally polls manifest.json for suite jar updates
Existing non-blank secrets are never overwritten. Missing YAML keys are merged only.
1. Download the jar
- Open the plugins catalog or use the download button above.
- Copy
root-core-<version>.jarinto your server’splugins/folder. - Delete older
root-core-*.jarfiles first so Paper loads only one Core.
Do not rename the jar in a way that breaks the root-core- prefix if you use the suite updater later.
2. Get a product key
- Register or sign in at the developer portal (Discord).
- Open My Keys and generate one free account key.
- Copy the plaintext key when shown — it is displayed once.
Use one key per Paper server. Deleting a key also removes My Servers rows bound to that key.
3. Configure root-core.yml
After the first start (or before, if you create the folder yourself), edit:
plugins/RootMC/root-core.yml
Minimum required fields:
# plugins/RootMC/root-core.yml
server-name: "My Network Server"
product-key: "RMCDEV-XXXX-XXXX-XXXX-XXXX"
cloud:
api-base: "https://api.rootmc.net"
server-id: ""
server-secret: "" # leave blank — secrets live in cloud.yml
license:
mode: operator
verify-remote: false
api-base: "https://api.rootmc.net"
force-local-edge: false
presence-interval-minutes: 5
server-address: ""
site:
base: "https://rootmc.net"
keys-path: "/developer/keys/"
plugins-manifest: "https://rootmc.net/plugins/manifest.json"
updater:
enabled: true
manifest-url: ""
interval-hours: 6
plugins: []
only-installed: true
require-product-key: false
server-name— label shown on My Servers (pick something unique)product-key— paste the key from My Keys- Leave
cloud.server-id/server-secretblank on first bind — Core writes identity intocloud.yml license.api-basedefaults tohttps://api.rootmc.netfor developer keys (override only if you mirror the Worker)server-address— optional public host:port; leave empty unless you want it recorded
Legacy license.yml with server-name / product-key still works as a fallback, but prefer root-core.yml.
Cloudflare / edge URLs
Third-party hosts normally keep these RootMC defaults and use a free product key. Override the same keys only if you run your own Worker or Pages mirror. Cloudflare account tokens are never configured in the plugin.
Key (in root-core.yml) | Default | Purpose |
|---|---|---|
cloud.api-base |
https://api.rootmc.net |
Worker data plane (heartbeat, economy sync, …). Precedence: root-core → cloud.yml → this default |
license.api-base |
https://api.rootmc.net |
Product-key bind + presence |
license.force-local-edge |
false |
Opt-in remap to the local tunnel edge (operator PCs only) |
site.base / site.keys-path |
https://rootmc.net / /developer/keys/ |
Marketing site + keys portal (operator messages) |
site.plugins-manifest |
https://rootmc.net/plugins/manifest.json |
Suite catalog for the updater |
updater.manifest-url |
(blank) | Blank = use site.plugins-manifest |
Secrets (server-secret, Discord bot token) stay in plugins/RootMC/cloud.yml — not in root-core.yml.
Paper Discord / Slack is built into Root-Core comms (JDA chat bridge, reachout, server-log uploads). Set cloud.yml discord.* / slack.* and chat flags under root-core.yml comms:. Remove any legacy root-discord-*.jar. Without Core, suite plugins drop Discord sends. Worker/API Discord destinations stay in Cloudflare wrangler DISCORD_ROOTMC_* vars.
Discord bot & channels
Paper Discord is Root-Core comms (optional; enable via config). Without Core, reachout and chat posts are dropped. The Cloudflare Worker configures network Discord separately.
| Surface | Where | What |
|---|---|---|
| Paper JDA (Root-Core comms) | cloud.yml discord.* + root-core.yml comms: |
Bot token, guild, ingame-chat / server-logs channels; chat relay flags |
| Worker API / cron posts | Cloudflare wrangler DISCORD_ROOTMC_* vars + bot secret |
Updates, governance, economy posts — not overridden by Paper |
| Legacy flags | rootmc.yml discord-chat.* / old root-discord.yml |
Migrated into root-core.yml comms: on first Core boot |
# plugins/RootMC/cloud.yml
discord:
bot-token: ""
guild-id: ""
channels:
ingame-chat: ""
server-logs: ""
roles:
linked: ""
Run /rootcore comms status. /rootcore status still shows Discord secrets present without printing tokens. Do not install a separate Root-Discord jar.
4. Start Paper
- Start (or restart) the Paper server.
- Watch the console for Root-Core bind / presence lines (no secrets are logged).
- Confirm
plugins/RootMC/now containsroot-core.yml,cloud.yml,database.yml, and related files.
In-game or console, run:
/rootcore connect
Expect NETWORK CONNECTED. For a verbose dump use /rootcore status. Full checklist: network setup.
5. Verify on My Servers
- Open My Servers while signed in.
- Your
server-nameshould appear after first successful presence (within a few minutes; default interval is 5 minutes). - Online means license presence was seen within about 10 minutes.
If the server is missing, re-check the product key, run /rootcore reload, then /rootcore connect.
Files created under plugins/RootMC/
| File | Purpose |
|---|---|
root-core.yml | Primary operator file — name, key, public Cloudflare/site URLs, license, updater |
cloud.yml | Shared secrets + identity + Discord bot/channels for Paper JDA |
database.yml | Shared MySQL settings for feature plugins |
license.yml | Legacy fallback for name/key (optional) |
.core-meta.yml | Internal connection/version stamp |
Self-repair merges missing keys only and never overwrites non-blank passwords, server secrets, or Discord bot tokens.
Commands
| Command | Action |
|---|---|
/rootcore status | Folder, DB (password masked), cloud identity, key present?, bound id, last presence, updater |
/rootcore connect | Pass/fail network checklist — prints NETWORK CONNECTED or INCOMPLETE |
/rootcore reload | Reload configs, re-ensure files, rebind + reschedule presence/updater |
/rootcore license | License gate + bind summary (no secrets) |
/rootcore update | Run suite updater now (on by default; set updater.enabled: false to disable) |
/goto <server> | Transfer to another mesh peer (see Transfer mesh) |
/toclaims · /gen2 | Shortcut → Claims peer |
/totowny · /gen1 | Shortcut → Towny peer |
Transfer mesh (/goto)
Players move between linked Paper hosts with vanilla Player.transfer (no Bungee/Velocity required). The peer list normally comes from GET /api/rootmc/transfer-mesh.
When the API edge is down (HTTP 530 / tunnel), set local peers in root-core.yml so /goto still works:
transfer:
enabled: true
advertise: "your.host:25565"
evacuate-to: claims
local-peers:
claims:
host: 51.81.176.61
port: 24945
label: Claims
aliases: [gen2, g2, c]
towny:
host: 15.204.13.9
port: 25565
label: Towny
aliases: [gen1, g1, t]
Aliases gen2/c resolve to claims; gen1/t to towny. After editing, run /rootcore reload (or restart).
Not the same as land /claims (Root-Claims). Use /goto claims or /toclaims for server transfer.
Suite updater
On by default. Root-Core polls the public manifest and downloads newer jars for already-installed Root plugins, then prunes older same-plugin jars. Restart Paper to load new jars. Secrets are never touched. Set updater.enabled: false to opt out.
updater:
enabled: true
manifest-url: "" # blank = site.plugins-manifest
interval-hours: 6
plugins: [] # empty = all manifest entries
only-installed: true
require-product-key: false
Manual check: /rootcore update.
MySQL (optional for Core alone)
Root-Core itself does not require a live MySQL connection on enable. Feature plugins later read plugins/RootMC/database.yml.
When you add economy/sync plugins, set host, database, user, and password there. Leave password blank only if you intentionally rely on another shared source your stack already documents — blank passwords will warn in logs.
Troubleshooting
| Symptom | What to check |
|---|---|
| Server never appears on My Servers | product-key exact match; /rootcore status; outbound HTTPS to api.rootmc.net; wait one presence interval or /rootcore reload |
| Shows offline after being online | Paper still running? Presence interval; firewall; key not deleted/revoked |
| cloud id/secret stay blank | Bind failed — check console; ensure key is active; blank fields only fill on successful bind |
| Two Root-Core jars loading | Remove older root-core-*.jar from plugins/ |
| Updater does nothing | updater.enabled: true; compare local versions to manifest.json; restart after download |
/goto says no peers / unknown server |
API mesh down — add transfer.local-peers (see Transfer mesh); /rootcore reload; confirm destination host:port accepts Minecraft |
Next plugins
Install Root-Core first, then add suite jars from the catalog. Typical order:
- Root-Times — Minecraft-day clock, playtime, AFK, welcome
- Root-Perms — groups / tracks (before ranks & loans)
- Root-Essentials — economy, homes, shops, loans
- Root-Play — ranks, votes, help, road
- Root-Claims — Claims hosts only
- Root-Ops — admin / restart / announcer
- Root-Territories — influence overlays
- RootMC — sync & realm features
- RootMC-Official — Towny↔Claims progression link (official hosts only)