How MonoAdmin Is Secured

How MonoAdmin keeps your server and panel safe: an outbound-only link, no credentials in convars, fixed game events and checked permissions.

MonoAdmin runs next to a game server that you own, and it can act on that server. That deserves a plain account of what it can and cannot do. This page covers the parts that matter to a server owner: how the link to your server is protected, what the cloud can ask your server to do, what a player’s game can send back, who counts as staff in game, and how accounts and MonoAdmin’s own staff are handled. For what is stored, see Data, Privacy and Retention.

Your Server Connects Out

The resource on your server opens the connection to MonoAdmin, over an encrypted HTTPS and WebSocket connection. Nothing connects in. You do not open a port, forward anything or expose your server to the cloud. Your firewall only needs to allow outgoing connections to ws.monoadmin.net. The same connection carries the errors of MonoAdmin’s own code to us, and we pass them on to our error-reporting service. The resource never contacts that service itself, and what it sends is listed under Data, Privacy and Retention.

The Credential Never Touches a Convar

When you run monoadmin link, your server receives a long random credential. MonoAdmin keeps only a hash of it, so even MonoAdmin cannot show it to you again. Your server keeps it in KVP, the key-value storage that FXServer keeps separately for each resource. It is never written to a convar (a setting in server.cfg that other resources can read) or to any file you edit. The resource reads only eight convars in total: sv_hostname, sv_maxclients, onesync and sv_icon, and four that txAdmin sets on a server it runs (txAdminServerMode, txAdmin-version, sv_appearAllowlisted and txAdmin-checkPlayerJoin), so the panel can warn you when txAdmin’s own allowlist is on. See Whitelist.

Because of this, the credential does not appear in server.cfg or in any file you edit. Settings > Server Link can only create new pairing codes and unlink. It cannot show the credential.

monoadmin link and monoadmin unlink run only from the server console, which includes the txAdmin live console and RCON. A player is refused, even with command permissions, and so is another resource that tries to run them. A refused attempt is written to the server log.

The pairing code that starts a link is short-lived: it works once and for 10 minutes. Creating one needs the Manage Server Link permission and a fresh confirmation that it is you, and the project owner is emailed every time a server is linked.

If the credential connects from a different address while your server is already connected with it, MonoAdmin treats that as a possible copy. The owner gets an email, “The server link of {project} was used from another address”, and the Audit Logs record “Server link used from another address”. Notices like this are limited to one an hour for each project. If you did not move your server, run monoadmin unlink on it, then monoadmin link with a new code from Settings > Server Link. That replaces the credential and the old one stops working.

What MonoAdmin Can Make Your Server Do

No Generic Commands

The cloud cannot send your server a command line or a “run this” instruction. It sends named actions from a fixed list, such as heal, teleport, freeze or announce. Each one is handled by a fixed piece of code in the resource, with arguments checked first. The only code that ever reaches your server is the optional custom revive code described below. The cloud names a target by server ID and sets a deadline, and your server answers with what it verified. When it cannot tell whether something worked, the panel says “unknown” instead of “ok”.

Cloud messages are handled inside the resource by fixed handlers. They are not turned into global FiveM events that any script could trigger or listen for. The few events the server does send to a player’s game go to that one player, and the game accepts them only when they come from the server.

On a server run by txAdmin, the resource also listens for two events that txAdmin fires, one when its settings change and one when its allowlist refuses a player. It accepts them only when they come from txAdmin’s own resource, monitor.

The One Place Another Script Is Triggered

Revive is the single exception, and it has two parts.

The presets. Some ambulance scripts have no export for it, so the resource has a fixed table of each supported script’s own revive event or export. With a preset, the cloud only picks a name from that table in Settings > Advanced. It cannot name an event of its own.

Custom revive code. A project can instead choose Custom and write its own Lua in Settings > Advanced. That is different in kind: until now the cloud only ever sent a script’s name, never an event or code, and with Custom the project’s own code is sent to your game server and run there every time staff revive a player. The code is written by someone with the Advanced Settings permission, and anyone who can change it can run Lua on your game server. Give Advanced Settings only to people you trust as much as someone with access to your server’s files. The project owner has it, and the default Admin role does not.

Some things limit it. The resource compiles the code as text only, with these blocked inside it: the file system, OS commands (apart from reading the time), debug, loading other code, Citizen, console commands, convars, the resource’s stored data (KVP, where the link credential is kept), HTTP requests, registering events, commands and exports, starting and stopping resources, and MonoAdmin’s own exports and internals. The code is at most 8192 bytes, and every change of it is recorded in the Audit Logs with who made it and the new code. It is not a full sandbox: the code can still call other resources’ exports and trigger events, which can do whatever those resources allow. Nothing runs it unless the project has picked Custom and saved code.

See Revive and Ambulance Scripts for the full list and how to write it.

Scripts That May Punish

A script on your server can ban, warn or kick through MonoAdmin only if you list its resource name on Settings > Game Settings. No resource may by default. The cloud checks the name the resource reports, and the resource checks who is calling. These punishments are attributed to the game server, never to a staff member. See Project Settings.

What Players’ Games Can Send

A player’s game can send your server only eight events, and the list is fixed. Each is validated and rate limited, and the player’s identity is always the one FXServer reports for the connection, never a name inside the message.

Event What it is for
monoadmin:ready The game has loaded and asks to be set up.
monoadmin:ticket Asks for a fresh single-use ticket for its own telemetry connection.
monoadmin:ack Reports the result of an action the server asked the game to do, such as a screenshot.
monoadmin:warnAck The player pressed “I understand” on a warning.
monoadmin:csDone The player finished a community service task.
monoadmin:admin A request from the in-game menu. It is accepted only from recognised staff.
monoadmin:report A request from the report window (/report unless you renamed it). It also carries the player’s game listing the other resources that register that command there. The server checks the list, never answers it, and uses it only to warn you; see Features and Modules.
monoadmin:command A command the player ran, sent for Server Logs by the logging line and used for nothing else.

A player’s own connection to MonoAdmin uses a ticket that works once, for 60 seconds, tied to that player and that visit. It carries telemetry such as position and health and no commands. What a player’s game reports is treated as a hint: it is checked and never used to decide what anyone is allowed to do.

Who Counts as Staff in Game

The in-game menu is off until the project owner switches it on, and even then it works only for staff who linked their game account. When a staff member types /madmin link with a code from the panel, MonoAdmin records the identifiers that FXServer vouches for on that visit. Only these count: the Rockstar license and license2 identifiers and the Cfx.re fivem identifier. Steam and Discord identifiers do not make anyone staff.

If a game account matches more than one staff member, or none, the menu refuses to open. Signing out everywhere, changing your password, changing your email or turning on two-factor ends your game account links, so a link made with a stolen session does not outlive it. The staff member whose account it is gets an email, “A game account was linked to you in {project}”, so a link made with a stolen session is noticed. See Turn On and Open the Menu.

Every Action Is Checked Against Roles

MonoAdmin does not use FiveM’s ACE permissions. Roles in the panel decide everything, and they are checked again on every request, in the panel and in game, so a role change or a removal takes effect on the next action.

  • A member can only manage roles ranked below theirs, can only give out permissions they hold themselves, and cannot change their own role.
  • A feature switched off in Settings > Features removes its permissions from everyone, including the owner.
  • If the link to MonoAdmin drops, staff powers in game end after about a minute.
  • Every staff action lands in the Audit Logs.

Permission Reference explains how rank, ownership, features and framework combine.

Accounts and the Panel

  • Passwords are stored only as salted argon2id hashes. Two-factor secrets are stored encrypted, and recovery codes only as hashes. There are no passwords or codes MonoAdmin can read back.
  • Sign-in uses a random session token kept in a cookie that scripts on a page cannot read. MonoAdmin stores only a hash of the token. Sessions are never signed tokens that stay valid on their own, so signing out or revoking one takes effect at once.
  • Sign-in and sign-up have a bot check, and attempts are rate limited per address and per account.
  • Changes that affect who can get into an account ask you to confirm it is you first.
  • Webhook URLs, pairing codes and recovery codes are secrets. They are shown once or work only briefly, and the credentials behind them are stored only as hashes. Treat a webhook URL like a password: anyone who has it can post lines to your project, and Rotate URL replaces it.
  • Screenshots, attachments and Discord ticket files have long random addresses that cannot be guessed, and the panel gives them only to staff allowed to see the file. Anyone who has an address can open the file until it expires or is deleted, so treat a file link like a secret. Deleting a file ends its address at once. Files that are not images are always downloaded, never opened as a page.
  • Your project’s data is separate from every other project’s. Someone who is not a member gets the same answer as for a project that does not exist.
  • A purchase changes a plan only when Tebex’s signed confirmation arrives, never because a browser says so. Otherwise a plan changes only when its paid period ends or MonoAdmin staff set or end one.

Two-Factor and Sessions covers the controls you have.

MonoAdmin’s Own Staff

MonoAdmin’s support staff use a back office that is separate from the panel: its own address, its own sign-in and its own session. Every sign-in needs a password and an authenticator code. Staff accounts are created only by the people who run the service, from the server itself, never through a web page.

Everything staff change on a project is recorded with a reason. A change to your project also appears in your Audit Logs, shown as done by MonoAdmin.

To help you, support can open a session as your account. It needs a recorded reason, lasts 30 minutes and cannot be extended. Such a session cannot do personal things: it cannot change your password, email, two-factor or Discord link, manage your sessions, touch billing, accept invitations or save or connect your own Discord bot. It also cannot hand out lasting access, such as sending invitations, creating or rotating webhooks, creating projects, linking game accounts or creating pairing codes. It can do support work inside a project, for example reading settings or adjusting a role. What it does in your project is written to the Audit Logs under your account’s name.

Support opens such a session only to answer your support request or to look into abuse or a security problem. The sign-in is recorded in MonoAdmin’s own staff log with its reason, and changes made in the session are recorded in your project’s Audit Logs. The session is not shown in your Sessions list or in your Security Activity, and you are not notified each time one is opened. The Privacy Policy says the same.

What Does Not Exist

  • There is no customer API and there are no API keys. The panel works through your signed-in browser session.
  • MonoAdmin sends no outbound or signed webhooks. Webhooks are inbound only: your scripts send lines in.
  • MonoAdmin cannot run commands on your server or read its files. Character and vehicle edits go through the resource and your own database connection, and only for staff who hold the matching permission. The nearest thing is the custom revive code above, which runs the Lua your own team wrote, with console commands and file access blocked.