Why Plugin Permissions Are Still the Hardest Part of Running a Paper Server
Why most plugin problems on a small Paper server are really permission problems, how LuckPerms groups, inheritance, wildcards and contexts work, and the habits that make permissions easier to manage.
ChunkPod Team · · 9 min read
Why Plugin Permissions Are Still the Hardest Part of Running a Paper Server
Most plugin bugs on a small Paper server aren't bugs. A player types /home, gets told they don't have permission, and the admin spends an hour looking for a broken plugin that is doing exactly what it was told to do.
Permissions sit between every plugin and every player on the server. When they're set up well, nobody notices them. When they're set up badly, they show up as a pile of problems that look unrelated: missing commands, missing chat prefixes, protections that don't protect, features that work in one world and not another. Permission plugins like LuckPerms are good at what they do, but the mental model behind them isn't obvious, and that's where new admins get stuck.
Why permissions confuse new admins
Being op hides the problem
On Bukkit-based servers like Spigot and Paper, every plugin lists its permissions in its plugin.yml file, and each one gets a default: true, false, op or not op. A lot of plugins set their commands to default to op, including commands you'd expect everyone to have.
Most admins test their server while they're opped. As an operator, you pass almost every one of those checks without a permission plugin giving you anything. Your friends don't. That's where the classic report comes from: it works for me, but nobody else can use it.
The vanilla op levels 1 to 4 in ops.json control vanilla commands. For plugin permissions that default to op, what usually matters is whether you're op at all. So the fact that a command works for you tells you almost nothing about whether it works for a regular player.
Nodes are just strings
A permission node is a dotted string like essentials.home or worldedit.wand. When a player runs a command, the plugin asks the server whether that player has that string. That's the whole check.
The trouble is that nothing forces plugins to name their nodes the same way. One plugin uses pluginname.command.home, another uses pluginname.home, a third splits one command into several nodes for different options. You can't guess them. The plugin's documentation or its plugin.yml is the only reliable source.
The tool that manages permissions is itself a plugin
Paper doesn't come with a real group system. Bukkit has a permissions.yml file, but hardly anyone uses it for day-to-day work. So you install LuckPerms, a plugin whose job is to answer permission questions for every other plugin. That extra layer is useful, but it means a problem can live in the plugin, in LuckPerms, or in how the two meet. Things like chat prefixes often go through a third piece, Vault, which lets other plugins read LuckPerms data.
The mental model that makes it click
Once a few ideas land, LuckPerms stops feeling like a wall of commands and starts feeling predictable.
Stop thinking about players, think about groups
You can give permissions to a single player, but on anything bigger than a two-person server that gets messy fast. Six months later you won't remember why one friend can fly and another can't.
Groups fix that. You describe roles once, such as default, member, helper, mod and admin, and put players in them. Every player starts in the default group in LuckPerms, so anything you want every single player to have belongs there. When someone becomes a mod, you change their group, not a list of 40 nodes.
A good rule: if you're adding a permission to one player directly, ask yourself whether it should be a group instead. Most of the time it should.
Inheritance: groups stack on top of each other
In LuckPerms, a group can have parent groups. If member has default as a parent, members get everything default players get, plus whatever you add to member. If mod has member as a parent, mods get all of that plus their own nodes. Under the hood, a parent is stored as a node too, group.member for example.
This is the part that makes the system small. Instead of copying essentials.home into five groups, you give it to the lowest group that should have it and let everyone above inherit it.
It's also where confusion starts. When a player has a permission you didn't expect, the answer is usually somewhere up the inheritance chain. A long or tangled tree, where groups inherit from several parents at once, makes this hard to trace. A straight line from default to admin is easy to reason about.
Groups also have a weight. When two groups disagree, for example about which chat prefix to show, the higher weight wins. If your admins keep showing a member prefix, weight is the first thing to look at.
Wildcards are powerful and blunt
LuckPerms supports wildcard nodes. essentials.* grants every node that starts with essentials., and a bare * grants every node on the server.
That sounds like an easy way to set up an admin group, and it's the source of a lot of strange problems. Many plugins use permissions to turn things off as well as on. WorldGuard, for example, has bypass permissions that let a player ignore region protection. Give yourself * and you get every bypass node, every exemption and every debug option. Then you test your spawn protection, break a block without trouble, and decide WorldGuard is broken.
The fix is to be more specific. Give admins wildcards for the plugins they manage, like essentials.*, instead of *. And when a wildcard gives too much, you can set a specific node to false. In LuckPerms a node set directly to false beats a wildcard that would have granted it, so essentials.* plus a denied essentials.fly means everything except flying.
Contexts: the same player, different rules
LuckPerms can limit a node to a context, most often a server or a world. You might let players use /fly in a creative world but not in survival, or give different nodes on each backend server behind a Velocity proxy.
Contexts are useful, and they're also the reason a permission that looks correct in the editor can still fail. If a node was set with world=world_nether, it does nothing in the overworld. When something works in one place and not another, check the context before anything else.
Why almost every plugin problem turns out to be a permissions problem
After enough time running a small SMP, you start to see the same pattern. Here are the reports that come up again and again, and what's usually behind them.
- A player gets a no permission message. The node is missing, or it's set in the wrong context, or it's on a group the player isn't in.
- A command doesn't show up in tab complete. Commands a player can't use are hidden from their command list, so a missing node looks like a missing command.
- A new plugin does nothing for players, but works for you. Its commands default to
op, and you're op. - A chat prefix is missing or wrong. The player is in the wrong group, two groups are fighting over weight, or the chat plugin isn't reading LuckPerms through Vault.
- A protection plugin doesn't stop staff. Someone has a bypass node, often through
*. - Something works in one world and not another. A context is limiting the node.
- A player can do something they shouldn't. They're inheriting it from a parent group you forgot about.
The plugin itself is rarely the problem. It's asking the question it was built to ask, and the answer is coming back wrong.
Habits that make permissions less painful
None of this needs a big system. A few habits cover most of it.
Test as a normal player
Deop yourself or use a second account in the default group when you check a new plugin. If it works there, it works for your players. If you only ever test as op, you'll keep finding problems through player reports.
Let LuckPerms tell you what's being checked
/lp verbose on shows permission checks as they happen. Run the command that fails and you'll see the exact node the plugin asked for and whether it passed. That beats guessing node names from memory or from an old forum post.
When you want to know why one player has or lacks a node, /lp user <name> permission check <node> shows the result and where it came from. For bigger changes, /lp editor opens a web editor where the whole group tree is easier to read than in chat.
Keep the tree short
Four or five groups in a straight line is plenty for most SMPs. Every extra parent and every per-player node is something you'll have to trace later.
Be careful with *
Keep the full wildcard for the owner account, if anyone. Give staff wildcards for specific plugins, and deny the handful of nodes they shouldn't have.
Write down what each group is for
A short note in your staff channel with each group, what it's for and who's in it saves a lot of confusion when a new mod joins or when you come back to the server after a break.
Where ops still fits
LuckPerms doesn't replace ops.json. Op levels still control vanilla commands, and some admins keep a small op list for the owner and one trusted person. If you manage that file by hand, the Ops.json Creator builds it with each player's UUID and permission level.
ChunkPod is a Minecraft hosting service in early access. Join the waitlist to get notified when hosting opens.