Docs · Every setting

In STYGION Keystone

Every setting

All 151 settings, module by module: what each is, what it expects, its default and what it does.

Updated

Every setting

This list is not written from memory. Every module declares its settings along with what each one means, the mod hands the list over at GET /v1/settings, and this page was pulled out of that with scripts/reference.sh in the mod's repository.

Current for 0.1.1. There are 151 settings.

How to change one

/keystone set <full name> <value>     # from the console or in game
/keystone set <full name>             # what it holds now
/keystone set                         # everything there is

A name is always the whole path — bench.share-live, not share-live. Get it wrong and the console names the nearest thing that does exist. The same goes from the editor (/keystone panel → Settings), from the file config/keystone/<module>.toml, and over the interface.

Saving applies immediately, nobody is kicked, and every change keeps the value it replaced:

keystone set history
keystone set undo <number>

One trap: a changed default does not reach a server that already stored the old value in its file.


keystone.toml — the mod itself

Setting Expects Default What it does
keystone.debug true or false false Extra detail in the log. Useful once, noisy afterwards; leave it off unless somebody asked.
keystone.mask-commands a comma-separated list (empty) Extra commands whose arguments never appear in a log, a console feed or an audit line (S-83). Keystone already masks its own and the usual login and registration commands; this is for another mod on this server.
keystone.api.enabled true or false true The local HTTP API. Everything the mod can do, for programs, behind scoped keys.
keystone.api.port a whole number 25586 Which port the local API listens on.
keystone.api.address any text 127.0.0.1 What to listen on. Loopback unless you mean otherwise — anything else is reachable by whoever can reach this machine.
keystone.api.reachable-at any text (empty) The address to hand people, when it is not the one being listened on. Listening on 0.0.0.0 means every interface, which is a fine thing to bind and a useless thing to type: a link saying http://0.0.0.0:25586 opens nowhere. Empty and listening on a real address, the link uses that; empty and listening on everything, it uses this machine's own address on the network. Write a host name or an address here when the way in is neither — behind a router, a tunnel, or a name you gave it.

Example — this machine only (the default and the safe one): change nothing.

Example — from your home network:

/keystone set keystone.api.address 0.0.0.0
/keystone set keystone.api.reachable-at 192.168.1.100

and open the port to the LAN only in ufw: sudo ufw allow from 192.168.1.0/24 to any port 25586 proto tcp.

Example — from outside: leave api.address on loopback, put a reverse proxy with TLS in front of it, and set only reachable-at to that name. In detail on the interface page.


discord.toml — the bridge

Setting Expects Default What it does
discord.enabled true or false true Set to false and this module is never built at all — no memory, no CPU, no tables.
discord.token a token, stored but never shown again (empty) The bot's token, from discord.com/developers. Nothing else on this server may read it, and it is never logged or answered over the API. Blank leaves the whole bridge off. The bot also needs Message Content and Server Members switched on there, or it connects and hears nothing.
discord.server any text (empty) The id of your Discord server. Right-click its name with Developer Mode on and copy it.
discord.chat-channel any text (empty) The channel the game's chat appears in, and whose messages appear in game.
discord.events-channel any text (empty) Where joins and leaves go, when you would rather they were not in the chat channel. Blank puts them in the chat channel.
discord.game-to-discord true or false true Whether what is said in game appears on Discord.
discord.discord-to-game true or false true Whether what is said on Discord appears in game.
discord.speak-as-players true or false true Each player speaks under their own name and face rather than everything arriving from the bot. The bot makes its own webhook for this, which needs Manage Webhooks in that channel; without the permission the bridge still works and every line comes from the bot instead.
discord.joins-and-leaves true or false true Whether joining and leaving are announced.
discord.avatar any text https://mc-heads.net/avatar/{name}/64 The face beside a player's name on Discord. {name} and {uuid} are filled in. It has to be a picture Discord can fetch, which is why it is a service rather than the skin the server already knows. Blank leaves the webhook without one.
discord.webhook-name any text Keystone What the bridge's webhook is called in the channel's settings, so somebody looking at it can tell what made it.
discord.topic true or false true Keep the channel's topic showing who is online and how long the server has been up.
discord.topic-every a length of time 5m How often the topic is rewritten. Discord allows two changes per ten minutes per channel and quietly ignores the rest, so shorter than this buys nothing.
discord.roles.follow a comma-separated list (empty) Which rank wears which Discord role, written as group=roleid. It works both ways, and not symmetrically. A rank given or ended in game puts the role on or takes it off. A role added on Discord is written into the same ledger every other rank lives in, with Discord as its source, and comes off when the role does. A rank somebody already holds from a shop or a quest is never overwritten, because a second entry would outlive the first one's expiry date.
discord.alerts.channel any text (empty) Where the server says it is struggling, and where it says it is fine again. What counts as low and how long it has to last are in operations.toml, because that is where the measuring happens.
discord.alerts.ping-role any text (empty) A Discord role id to notify when something is wrong — not when it comes back. Worth setting: a channel nobody is told about is a channel nobody reads at three in the morning.
discord.alerts.runs-channel any text (empty) Where a finished load test goes, when somebody chooses to share it. Deliberately not the alert channel: an alert wants reading now, a measurement is something a team comes back to.
discord.console.channel any text (empty) The server's console, in a Discord channel. For watching a machine you are not sitting at. Make it a channel your team can read and nobody else can — a console says what mods are installed, what went wrong and where.
discord.console.levels a comma-separated list INFO, WARN, ERROR Which lines go. Drop INFO on a busy server and the channel becomes only the things that need somebody.
discord.console.ignoring a comma-separated list (empty) Logger names to leave out, for one mod that will not stop talking.
discord.console.every a length of time 5s How often a batch goes out. A line per message is fifty messages a second on a starting server, and Discord answers that with a rate limit that becomes a ban on the whole bot.
discord.console.most-lines a whole number 200 How many lines wait for the next batch before the oldest are dropped.
discord.ban.game-to-discord true or false false Somebody banned in the game is banned on Discord too, if their account is linked. Off by default because it is a real decision.
discord.ban.discord-to-game true or false false And the other way. Turn both on and a ban is a ban in both places, whichever side it started on.
discord.ban.who-may a comma-separated list (empty) Discord role ids whose holders may use /ban and /unban at the bot. Empty means the bot has no ban command at all.
discord.link.required-to-join true or false false Nobody gets in until they have linked their Discord account. On an offline-mode server this is the difference between anybody walking in wearing anybody's name and a server where every player is a person you can find.
discord.screens.not-linked any text This server needs your Discord account linked… What somebody reads when they are turned away for not having linked. Available: {code}, {left}, {player}, {invite}. Leave {code} in it — it is the only place they will see one.
discord.link.invite any text (empty) Your Discord invite, written into {invite}. A server that asks somebody to link on Discord without saying which Discord has asked them to guess.
discord.link.accounts-per-user a whole number 1 How many Minecraft accounts one Discord user may link. It is also how many players one banned person can come back as.
discord.link.rename-nickname true or false false Rename somebody on Discord to their in-game name when they link. Needs Manage Nicknames, and cannot touch anybody whose highest role is above the bot's.
discord.link.code-lasts a length of time 10m How long a linking code is good for. Short on purpose: a code is a key to somebody's account, and the person holding it is already looking at it.
discord.ask.fallback-channel any text (empty) Where a question goes when the person it is for has direct messages closed. Nothing private is written in a channel, and only the person it is about can press the button.
discord.tickets.category any text (empty) Where a ticket's channel is made. Only its team and the person who opened it can see it, and the channel is deleted when the ticket closes — the conversation is kept in the mod.
discord.tickets.roles a comma-separated list (empty) Who can see which sort of ticket, one line each as kind -> role id. A kind with no line gets a channel only the person who opened it can see.
discord.queue a whole number 500 How many messages wait for Discord before the oldest start being dropped. The game is never held up either way.

operations.toml — everything on a clock

Setting Expects Default What it does
operations.enabled true or false true Set to false and this module is never built at all.
operations.timezone a time zone, or blank (empty) Which clock the times below are read in. Blank means this machine's own.
operations.restart.when "06:00, 18:00", "every 6h", "90m after start", "off" off When to consider restarting. Off by default: a mod that starts restarting a server nobody asked it to restart is a mod nobody installs twice.
operations.restart.warn-at lengths of time, largest first 15m, 5m, 1m, 30s, 10s How long before a restart to tell people. A bar counts down for the whole of the first one.
operations.restart.after-uptime a length of time 12h Restart only once the server has been up this long. 0 ignores uptime.
operations.restart.above-memory-percent a whole number 85 Restart when memory in use passes this. 0 to ignore it. This is the measurement that usually decides.
operations.restart.below-tps a whole number 0 Restart when ticks per second fall under this. Careful — a server that restarts because it is struggling comes back and struggles again.
operations.restart.wait-for-empty true or false true When a restart is due and somebody is playing, wait for the world to empty first.
operations.restart.wait-at-most a length of time 2h How long to wait for that. 0 waits forever, which means a busy server never restarts.
operations.restart.supervised any text auto Whether something outside starts this server again after it stops. auto looks for systemd and the hosting panels; yes if you run it in a loop of your own; no makes the mod start the server itself.
operations.backup.when a schedule off When to back the world up. Off by default because where the backups go is a decision only you can make.
operations.backup.warn-at lengths of time 1m How long before a backup to tell people. Saving pauses for as long as the copy takes.
operations.backup.directory a folder backups Where they go. Put this on a different disk if you have one — a backup on the same disk as the world survives exactly the failures that do not matter.
operations.backup.keep-everything-for a length of time 1d Every backup newer than this is kept.
operations.backup.keep-one-a-day-for a length of time 7d Older than that, one a day survives up to this age.
operations.backup.keep-one-a-week-for a length of time 90d Older than that, one a week survives up to this age. A fixed number of backups would mean an hourly schedule gives you seven hours of history, and what you want to undo happened yesterday.
operations.backup.keep-free-megabytes a whole number 2048 Skip a backup rather than fill the disk under it.
operations.announce.when a schedule off How often to say something. every 30m is the usual answer.
operations.announce.notices a comma-separated list (empty) What to say. A plain line goes to everybody in chat; audience | where | the text narrows it — for example no-rank | chat | /vote helps the server. Where is chat, actionbar or title.
operations.metrics.keep-for a length of time 7d How much history to keep. One row a minute, so a week is about ten thousand rows.
operations.alerts.tps-below a number 15.0 Say something when the server drops under this many ticks a second.
operations.alerts.memory-above-percent a whole number 90 Say something when this much of the memory is in use.
operations.alerts.must-last a length of time 1m How long a reading has to stay wrong before anybody is told. One bad tick is a chunk loading, not a problem.
operations.alerts.quiet-for a length of time 15m How long before the same alert may be sent again.
operations.screens.appeal any text (empty) Where somebody can say a punishment was wrong. Written into any screen that uses {appeal}. A ban with nowhere to appeal is a ban you never hear was a mistake.
operations.screens.maintenance any text The server is closed for maintenance.… What somebody reads during maintenance. Available: {reason}, {by}, {until}, {left}, {player}, {appeal}.
operations.screens.full any text The server is full.… What somebody reads on a full server.
operations.screens.full-reserved any text The server is full.… The same, when the last places are kept for supporters.
operations.join.reserved-places a whole number 0 Keep this many of the server's places for whoever holds keystone.join.reserved.
operations.clean.when a schedule every 1m How often to look at how much is loaded. This costs nothing and says nothing — it is the check, not the cleanup. off switches the cleaner off entirely.
operations.clean.over-entities a whole number 1200 Start caring above this many loaded entities. Merging happens first and usually ends it there.
operations.clean.below-tps a whole number 0 Also start caring when ticks per second fall under this.
operations.clean.merge-radius a number 3.0 How close two stacks of the same item have to be to become one. This is the part that costs nobody anything.
operations.clean.warn-at lengths of time 30s, 10s, 5s How long before a sweep to warn, once merging was not enough.
operations.clean.older-than a length of time 30s Leave alone anything dropped more recently than this.
operations.clean.items true or false true Remove loose items.
operations.clean.experience true or false true Remove experience orbs.
operations.clean.arrows true or false true Remove arrows lying on the ground. One in flight is never touched.
operations.clean.hostile-mobs true or false false Remove monsters. Off, and think before turning it on — a mob farm is somebody's afternoon.
operations.clean.passive-mobs true or false false Remove animals. Off, for the same reason and more so.
operations.clean.named true or false false Remove things somebody put a name tag on. Off.
operations.clean.tamed true or false false Remove tamed animals. Off.
operations.clean.keep-entities ids from the game minecraft:villager, minecraft:item_frame, minecraft:armor_stand, minecraft:boat Entity ids never removed, whatever else is switched on.
operations.clean.keep-items ids from the game minecraft:netherite_ingot, minecraft:netherite_block, minecraft:elytra Item ids never removed. Netherite on the floor is not litter.

Example — a restart at three in the morning, only when there is a reason, interrupting nobody:

/keystone set operations.restart.when 03:00
/keystone set operations.restart.after-uptime 12h
/keystone set operations.restart.wait-for-empty true
/keystone set operations.restart.wait-at-most 2h

Example — a daily backup on another disk:

/keystone set operations.backup.directory /mnt/backups/mc
/keystone set operations.backup.when 04:00

moderation.toml — bans and kicks

Setting Expects Default What it does
moderation.enabled true or false true Set to false and this module is never built at all.
moderation.take-over-vanilla true or false true /ban, /pardon and /kick do what Keystone does. Off, they are the game's own — which means a ban typed as /ban is invisible to /keystone bans, never expires, and shows "You are banned from this server." Leaving this off is choosing to have two ban lists.
moderation.screens.appeal any text (empty) Where somebody can appeal. Written into {appeal}.
moderation.screens.banned any text You are banned from this server.… A ban with no end. Available: {reason}, {by}, {until}, {left}, {player}, {appeal}.
moderation.screens.banned-until any text You are banned … until {until}.… A ban with a date.
moderation.screens.kicked any text You were removed from the server.… A kick.

accounts.toml — who you are on an offline server

Setting Expects Default What it does
accounts.enabled true or false true Set to false and this module is never built at all.
accounts.require true or false false Nobody plays until they have said who they are. For a server in offline mode, where whoever types a name gets that name — including yours. It does nothing on a server that checks with Mojang.
accounts.ask-on-discord true or false true Ask on Discord instead of asking for a password. Somebody linked to a Discord account gets a message the moment anybody joins under their name — who, from where, and two buttons. An attempt they did not make reaches them as a warning rather than as a quiet theft.
accounts.protect-bought-names true or false false A name that belongs to somebody who bought the game cannot be worn here by anybody else. When Mojang cannot be reached, nobody is refused — and /keystone accounts allow <name> lets a real owner through once.
accounts.hold-name-for a length of time 15m How long a name is closed after its owner presses No, that is not me. A hold rather than a ban on purpose: an attempt is as likely to come from a school or a shared house as from one person.
accounts.least-length a whole number 8 The shortest password this server accepts. Length is the rule worth having; asking for a capital and a digit produces Password1 on every server that has ever asked.
accounts.remember-for a length of time 1d How long somebody coming back from the same place is let in without typing it again. Zero asks every time. A place is a one-way hash under a key only this server holds — Keystone never writes down an IP address.
accounts.must-prove-within a length of time 2m How long somebody has before they are disconnected.
accounts.most-tries a whole number 5 How many wrong passwords before they are disconnected. They can reconnect; it is there to make guessing slow, not to lock anybody out.
accounts.iterations a whole number 210000 How much work hashing a password costs. Raise it as hardware moves — it is stored beside each password, so raising it invalidates nobody.
accounts.screens.appeal any text (empty) Where somebody can appeal.
accounts.screens.name-held any text That name is closed at the moment.… What somebody reads when a name is being held.
accounts.screens.name-not-yours any text The name {player} belongs to a Minecraft account.… What somebody reads when they took a bought name.

progress.toml — ranks earned by playing

Setting Expects Default What it does
progress.enabled true or false true Set to false and this module is never built at all.
progress.promotions a comma-separated list (empty) Ranks people earn by playing. One line each, shaped rank -> what it takes. Commas mean and; for either, write two lines pointing at the same rank. played and active are lengths of time; everything else is a plain number. Counters come in families — killed, mined, placed, visited — and each counts both the family and the exact thing. Modded ids work as they are. A line that does not make sense is named in the log at start and skipped.
progress.count-idle-time true or false true Whether standing still counts as playing. Off, and the clock stops after idle-after — which is what stops a rank called Veteran being earned by a laptop left on overnight. Both numbers are always kept either way.
progress.idle-after a length of time 5m How long somebody has to not move and not look around before they are counted as standing still. Nobody is kicked and nobody is told.
progress.announce true or false true Say it to the server when somebody earns a rank. Earning something quietly is most of the reason nobody notices the ranks exist. (Up to 0.1.0 this setting was declared under the wrong name and could not be set.)
progress.check-every a length of time 1m How often somebody is checked against the promotions.
progress.write-every a length of time 30s How often what has been counted reaches the database. This is what a crash could cost somebody, and it is thirty seconds.

Example — a ladder on hours played:

/keystone set progress.promotions "wanderer -> played >= 5h, builder -> played >= 24h, veteran -> played >= 168h"
/keystone set progress.count-idle-time false

votes.toml — voting

Setting Expects Default What it does
votes.enabled true or false true Set to false and this module is never built at all.
votes.address any text (empty) Where votes are received. Empty means nothing is listening, which is how this starts: it is the one port Keystone opens to the world, so it opens because somebody decided to. 0.0.0.0 accepts from anywhere, which is what a vote site needs. After setting it, run /keystone votes keys and give a site what it asks for.
votes.port a whole number 8192 The port votes arrive on. 8192 is what vote sites expect.
votes.rewards a comma-separated list (empty) What a vote is worth. A plain line is a command run as the console, with {player} filled in — which covers anything any mod on this server can do. perk and rank go into the same ledger as a bought rank instead, so for 7d ends by itself.
votes.sites a comma-separated list (empty) Where people can vote, as /vote prints it — one line per site, the name and the link.
votes.streaks a comma-separated list (empty) Voting several days running, <days> -> <reward>. A missed day starts the count again.
votes.party-goal a whole number 0 A goal the whole server votes towards. When this many votes arrive inside party-window, everybody online gets the party rewards and the count starts again. 0 is off.
votes.party-window a length of time 1d How long the server has to reach the goal.
votes.party-rewards a comma-separated list (empty) What everybody online gets when the goal is reached.
votes.announce true or false true Say it to the server when somebody votes. A streak is said with it, because that is the half that makes anybody else go and vote.
votes.announce-cooldown a length of time 5m How long before the same person is announced again. Eight sites at breakfast is one piece of news, not eight.
votes.time-zone a time zone (empty) Which midnight a voting day ends at. It only decides when a streak ticks over.

Example — start taking votes:

/keystone set votes.address 0.0.0.0
/keystone set votes.rewards "give {player} minecraft:diamond 3, rank vip for 1d"
/keystone votes keys

and open 8192 to the world in ufw: sudo ufw allow 8192/tcp.


tickets.toml — tickets

Setting Expects Default What it does
tickets.enabled true or false true Set to false and this module is never built at all.
tickets.kinds a comma-separated list help -> , bug -> , report -> What somebody can open, and who answers it, one line each as kind -> group. The group is one of this server's own permission groups, and the ticket goes to whoever in it is carrying the fewest. Leave the group off and the ticket waits in the queue for somebody to take.
tickets.limit-per-person a whole number 3 How many a person may have open at once.
tickets.cooldown a length of time 30s How long before the same person can open another. Against the accident of pressing enter twice as much as against anybody trying.

tablist.toml — the player list

Setting Expects Default What it does
tablist.enabled true or false true Set to false and this module is never built at all.
tablist.header a comma-separated list (empty) What is written above the list, one line each. Names in braces are filled in: {online}, {max}, {tps}, {player}, {rank}, {prefix}, {suffix}, {world}. Colours are written the ordinary way — &b — and && is an ampersand you meant.
tablist.footer a comma-separated list (empty) What is written below it. This is where a server's address, its Discord or what is running this week belongs.
tablist.name any text {prefix}{name}{suffix} How a person's row reads. Empty leaves the plain name.
tablist.order-by-rank true or false true Sort the list by rank rather than alphabetically, heaviest first. Minecraft has had a notion of an order in the list since 1.21.2 and this uses it; on older versions there is no honest way to do it, so there the list keeps its usual order.
tablist.refresh a length of time 3s How often it is redrawn. Only what changed is sent.

skins.toml — skins

Setting Expects Default What it does
skins.enabled true or false true Set to false and this module is never built at all.
skins.restore-on-join true or false true Look a joining player's name up at Mojang and, if it belongs to a real account, put that account's skin on them. On an offline-mode server this is the difference between a server of Steves and a server that looks normal.
skins.allow-own-picture true or false true Whether /skin <link> works. A picture has to be signed by something Mojang trusts before a client will load it, which means sending it to the service below.
skins.signing-service any text https://api.mineskin.org/generate/url Whose service signs a player's own picture. The image goes there — nothing else does, no name, no address, no id. Blank turns /skin <link> off entirely and leaves the two Mojang-only ways working.

bench.toml — measuring performance

Setting Expects Default What it does
bench.enabled true or false true Set to false and this module is never built at all.
bench.share-live true or false true Once a day, five minutes of this server's tick are measured and sent — how long a tick took, how many people were on, and which mod the time was spent in. Nothing that names this server goes with it: no name, no address, nobody's name, and no id of any kind. false turns it off entirely.
bench.send-to any text https://stygion.eu Where a shared run goes. Only ever after somebody says yes to that run. Point it at your own collector if you would rather, or empty it and nothing ever leaves.
bench.radius a whole number 0 How far from the middle the test players stand, in blocks. Zero, the default, works it out: far enough apart that no two of them tick the same piece of the world.
bench.baseline-seconds a whole number 30 How long the server is measured doing nothing before a single test player exists. Every number in a report is a difference from this.
bench.settle-seconds a whole number 10 How long each group of test players is held before the next arrives. Too short and a step is measured while the chunks it asked for are still loading.
bench.step a whole number 5 How many arrive at once. They come in groups so that asking for more than this machine holds gives an answer instead of an out-of-memory kill.
bench.send-to-discord true or false false Put a finished run in the Discord channel without asking first.
bench.send-to-stygion true or false false Send a finished run to the public figures without asking first.

Example — nothing about this server ever leaves it:

/keystone set bench.share-live false
/keystone set bench.send-to ""

assistant.toml — the assistant

Setting Expects Default What it does
assistant.enabled true or false true Set to false and this module is never built at all.
assistant.address any text (empty) Where the model is, up to but not including /chat/completions — https://api.anthropic.com/v1, https://api.openai.com/v1, or http://127.0.0.1:11434/v1 for one running on this machine. Blank leaves the assistant off. Nothing goes through STYGION and there is no key of ours.
assistant.key a token, stored but never shown again (empty) The key for that address. Stored here and sent to nowhere else. Blank is right for a model running on this machine that does not ask for one.
assistant.model any text (empty) Which model, spelled the way that provider spells it.
assistant.scopes a comma-separated list (empty) What the assistant may reach, as the scopes a key would hold. Empty means everything this server offers. It never changes anything on its own whatever this says.

Example — a model on this machine, through Ollama:

/keystone set assistant.address http://127.0.0.1:11434/v1
/keystone set assistant.model llama3.1
/keystone set assistant.scopes "status.read, console.read, settings.read"

Did this page help?

Opens the feedback panel with this page attached, and lands in the same queue as everything else.