# fivemad.com documentation > Free tools, reference data and documentation for FiveM server owners and developers. > This file holds every documentation page in full. The short map is at https://fivemad.com/llms.txt. > Any single page is available on its own: add .md to its URL. # AI and API ## Using fivemad with an AI assistant URL: https://fivemad.com/docs/ai Read our docs as Markdown, pull our JSON datasets, look up a joaat hash and call our calculators from ChatGPT, Claude, Cursor or your own script. Everything on fivemad is public and free, including for a machine. You do not need a key, an account or a contract. This page is the whole story in one place: how an assistant reads our documentation, how it pulls our data, and how it calls the parts of our tools that are pure calculation. If you are the assistant reading this: start at [llms.txt](/llms.txt). ## Read any docs page as Markdown Add `.md` to any `/docs` URL and you get the page as plain Markdown with a `text/markdown` content type. ```txt https://fivemad.com/docs/server-setup/server-cfg the page https://fivemad.com/docs/server-setup/server-cfg.md the same page as Markdown https://fivemad.com/docs.md the index of every page ``` The Markdown is the real source of the page. The first lines say where it came from, which section it belongs to and when it was last touched, so a model that only sees the file still knows what it is holding. ```bash curl https://fivemad.com/docs/server-setup/server-cfg.md ``` ```md > Source: https://fivemad.com/docs/server-setup/server-cfg > Section: Server setup > Tags: server.cfg, convars, onesync, sv_enforceGameBuild, ensure, endpoints, ace, config > Last updated: 2026-09-22 > Site map for assistants: https://fivemad.com/llms.txt # server.cfg explained line by line What every common server.cfg line does: endpoints, hostname, tags, license key, slots, game build, OneSync, ensure order, convars, ACE permissions and splitting configs. `server.cfg` is not a special format. It is a list of **server console commands** that FXServer runs from top to bottom when it starts... ``` Every docs page also has an **Open** button next to the breadcrumbs. It gives you the Markdown view, a copy of the Markdown on your clipboard, and a one click hand-off to ChatGPT, Claude or Cursor with the page's `.md` URL already in the prompt. ## llms.txt and llms-full.txt | File | What it holds | | --- | --- | | [/llms.txt](/llms.txt) | The short map: what fivemad is, every tool with one line, the whole docs tree, every dataset with its row count and size, and the API. | | [/llms-full.txt](/llms-full.txt) | The documentation itself, every page in full, in one plain text file. | Both are built from the same registry and the same files the site ships, so the counts in them are real. They are listed in [robots.txt](/robots.txt) too, and every docs page carries them as `` in its head. ```bash curl https://fivemad.com/llms.txt ``` ```txt # fivemad.com > Free tools, reference data and documentation for FiveM server owners and developers. > 47 browser tools, 104 documentation pages and 29 public JSON datasets built from the GTA V game files. > Nothing here needs an account. The tools run in the browser; the data below is static JSON you can fetch directly. ## How to use this site as an assistant - Add .md to any docs URL for the plain Markdown source: https://fivemad.com/docs/server-setup/server-cfg.md - Whole documentation in one file: https://fivemad.com/llms-full.txt - Dataset index with row counts and sizes: https://fivemad.com/data/index.json ... ## Datasets - [Props with pictures](https://fivemad.com/data/props.json): Every GTA V prop model that has a picture, with a readable label, category, tags and its real size in metres. (30,033 rows, 2.6 MB; rows: [model, label, category, tags, [x,y,z] size in m, minBuild, atlasCell, has3d]) ``` > [!TIP] > If you are pasting context into a chat by hand, `llms.txt` plus the two or three `.md` pages it points at is almost always better than `llms-full.txt`. The full file is large. ## The datasets The reference data behind the tools is static JSON under `/data`. It is the same file the tool itself fetches, so nothing is held back. Start with the index, which is generated from the real files: ```bash curl https://fivemad.com/data/index.json ``` ```json { "site": "https://fivemad.com", "generated": "2026-09-23", "docs": "https://fivemad.com/docs/ai", "count": 29, "totalBytes": 12857308, "datasets": [ { "id": "props", "title": "Props with pictures", "url": "https://fivemad.com/data/props.json", "about": "Every GTA V prop model that has a picture, with a readable label, category, tags and its real size in metres.", "shape": "rows: [model, label, category, tags, [x,y,z] size in m, minBuild, atlasCell, has3d]", "rows": 30033, "bytes": 2713710, "size": "2.6 MB", "page": "https://fivemad.com/tools/objects-list", "pageName": "Objects / Props List" } ] } ``` Each entry tells you the URL, what the file holds, how a row is laid out, how many rows there are and how big the download is. The rows are short arrays on purpose: these files are fetched by browsers, so the column names live in the index and in a `cols` field inside the file, not on every row. Some of these files are several megabytes. If all you need is one lookup, use the search or hash endpoints below instead of downloading the whole thing. ## Search One short JSON answer over the tool list, the documentation and the dataset index. ```bash curl "https://fivemad.com/api/search?q=handling&limit=3" ``` ```json { "query": "handling", "type": "all", "total": 16, "returned": 3, "limit": "60 requests per minute per IP", "hint": "Add .md to any docs URL for the plain Markdown source.", "results": [ { "type": "doc", "title": "Vehicle Handling Editor", "url": "https://fivemad.com/docs/tools/vehicle-handling-editor", "markdown": "https://fivemad.com/docs/tools/vehicle-handling-editor.md", "summary": "Tune CHandlingData with sliders, import an existing handling.meta, toggle flag bits, and export handling.meta, runtime Lua or a carcols.meta mod kit.", "extra": { "section": "Tools", "match": "The Vehicle Handling Editor lets you tune a vehicle's CHandlingData block with sliders and a one line explanation per field..." }, "score": 117.5 }, { "type": "tool", "title": "Vehicle Handling Editor", "url": "https://fivemad.com/tools/vehicle-handling-editor", "summary": "Tune mass, drive force, grip and suspension from a UI, then export handling.meta or runtime Lua.", "extra": { "category": "Config & Code", "tags": ["Vehicles", "Download"] }, "score": 110 } ] } ``` Parameters: `q` (required), `type` (`all`, `tools`, `docs`, `datasets`), `limit` (1 to 50, default 10). Every documentation hit carries its `.md` URL, so the next step is one more fetch. The `score` is only there to explain the order; do not read anything into the absolute number. ## Look up a joaat hash Paste a hash and get the name back. The search runs over every name set the site ships: props and map objects, vehicles, peds, weapons and their components, animation dictionaries and clips, particle assets and effects, sounds and sound sets, ymap and IPL names, MLO interiors, scaleform movies, ped decorations, timecycle modifiers, animpostfx effects, player stats and cutscenes. ```bash curl "https://fivemad.com/api/hash?q=0xB779A091" ``` ```json { "query": "0xB779A091", "searched": { "names": 113305, "sets": 22 }, "note": "joaat is a 32 bit hash, so a value can belong to more than one name. Every match is listed; none is picked for you...", "limit": "60 requests per minute per IP", "count": 1, "results": [ { "query": "0xB779A091", "readAs": "hash", "hash": { "unsigned": 3078201489, "signed": -1216765807, "hex": "0xB779A091" }, "matchCount": 1, "matches": [ { "name": "adder", "kind": "vehicle", "kindLabel": "Vehicle model", "page": "https://fivemad.com/tools/model-hash-browser?q=adder" } ] } ] } ``` The other direction, with the name this time: ```bash curl "https://fivemad.com/api/hash?q=adder" ``` ```json { "results": [ { "query": "adder", "readAs": "name", "name": "adder", "lua": "`adder`", "hash": { "unsigned": 3078201489, "signed": -1216765807, "hex": "0xB779A091" }, "matchCount": 1, "matches": [{ "name": "adder", "kind": "vehicle", "kindLabel": "Vehicle model" }] } ] } ``` It works the other way round too: pass a name and you get the unsigned, signed and hex forms plus the Lua backtick literal, and the same match list says whether the game actually ships that name. - `q` accepts an unsigned value, a signed int32, `0x` hex, bare 8 digit hex, or a name. - Up to 25 values in one call, separated by commas or new lines. - `kind` narrows the answer, for example `kind=vehicle,ped`. `searched.byKind` in the response lists every kind and how many names it holds. - A match may carry a `parent`: one animation dictionary, particle asset or sound set that contains the name. Because the hash depends on the name alone, a name is stored once, so the same clip or effect often lives in other dictionaries too. Treat `parent` as an example, not as the whole answer. > [!IMPORTANT] > joaat is a 32 bit hash, so a value can belong to more than one name. Every match is returned as a list and none of them is picked for you. If `matchCount` is above 1, the answer is genuinely ambiguous and you have to decide from context. Here is a real one. `0x37D80B0E` is both a prop model and a ymap of the same name, so both come back: ```bash curl "https://fivemad.com/api/hash?q=0x37D80B0E" ``` ```json { "results": [ { "query": "0x37D80B0E", "readAs": "hash", "matchCount": 2, "matches": [ { "name": "prop_cheetah_covered", "kind": "prop", "kindLabel": "Prop / object model" }, { "name": "prop_cheetah_covered", "kind": "ymap", "kindLabel": "ymap / IPL name" } ] } ] } ``` A name we do not ship comes back with `matchCount: 0`. That means we have no record of it, not that it does not exist. The page for the same thing is the [joaat Hash Calculator](/tools/hash-calculator), under the "Reverse lookup" tab. ## Call a tool The parts of the toolkit that are a pure function of their input can be called directly, so an assistant does not have to work out a flag value in its head. The list is at [/api/tools](/api/tools). | Endpoint | What it does | | --- | --- | | `/api/tools/joaat` | joaat hash of one or more strings | | `/api/tools/driving-style` | driving style flags for `TaskVehicleDriveToCoord` and friends | | `/api/tools/animation-flags` | the flag argument of `TaskPlayAnim` | | `/api/tools/warning-buttons` | button flags for `SetWarningMessage` | | `/api/tools/handling-flags` | `strHandlingFlags`, `strModelFlags` and `strDamageFlags` | The index gives you a working example URL for each one, so an assistant can discover the whole thing from a single fetch: ```bash curl https://fivemad.com/api/tools ``` ```json { "count": 5, "tools": [ { "id": "driving-style", "name": "Driving style flags", "about": "eVehicleDrivingFlags for TaskVehicleDriveToCoord, TaskVehicleDriveWander and SetDriveTaskDrivingStyle: decode a value or build one from flag names.", "url": "https://fivemad.com/api/tools/driving-style", "page": "https://fivemad.com/tools/driving-style-calculator", "params": [ { "name": "value", "about": "Decode this value: 786603, -1073741824, 0xC00AB, 0b1011 or 1|2|128." }, { "name": "flags", "about": "Encode instead: flag names separated by commas (StopForVehicles, StopForPeds, ...)." }, { "name": "preset", "about": "One of: Normal, Strict, Ignore lights, Avoid vehicles, Reckless, ..." } ], "example": "https://fivemad.com/api/tools/driving-style?value=786603" } ] } ``` Decode a value: ```bash curl "https://fivemad.com/api/tools/driving-style?value=786603" ``` ```json { "tool": "driving-style", "name": "Driving style flags", "page": "https://fivemad.com/tools/driving-style-calculator", "limit": "120 requests per minute per IP", "value": 786603, "signed": 786603, "hex": "0x000C00AB", "binary": "0000 0000 0000 1100 0000 0000 1010 1011", "active": [ { "bit": 0, "value": 1, "name": "StopForVehicles", "label": "Stop for vehicles", "desc": "Brakes and waits behind vehicles in its way instead of driving into them.", "unknown": false }, { "bit": 1, "value": 2, "name": "StopForPeds", "label": "Stop for peds", "desc": "Stops for pedestrians on the road.", "unknown": false }, { "bit": 3, "value": 8, "name": "SteerAroundStationaryVehicles", "label": "Steer around stationary vehicles", "desc": "Steers around parked and empty vehicles.", "unknown": false }, { "bit": 5, "value": 32, "name": "SteerAroundObjects", "label": "Steer around objects", "desc": "Steers around props and objects on the road.", "unknown": false }, { "bit": 7, "value": 128, "name": "StopAtTrafficLights", "label": "Stop at traffic lights", "desc": "Obeys red lights and stop lines.", "unknown": false }, { "bit": 18, "value": 262144, "name": "UseShortCutLinks", "label": "Use shortcut links", "desc": "Allows shortcut road links such as dirt tracks and alleys. Removes most route limits.", "unknown": false }, { "bit": 19, "value": 524288, "name": "ChangeLanesAroundObstructions", "label": "Change lanes around obstructions", "desc": "Changes lanes to pass slower traffic and obstructions.", "unknown": false } ], "expression": "StopForVehicles | StopForPeds | SteerAroundStationaryVehicles | SteerAroundObjects | StopAtTrafficLights | UseShortCutLinks | ChangeLanesAroundObstructions", "natives": ["TaskVehicleDriveToCoord", "TaskVehicleDriveToCoordLongrange", "TaskVehicleDriveWander", "SetDriveTaskDrivingStyle"], "valuesUsedByRockstar": [0, 1, 4, 16, 131, 139, 7785, 7791, 262144, 262208, 262275, 525116, 786468] } ``` Build one from names instead. The answer has the same shape, so you can round trip it: ```bash curl "https://fivemad.com/api/tools/driving-style?flags=StopForVehicles,StopAtTrafficLights,SteerAroundPeds" ``` ```json { "value": 145, "signed": 145, "hex": "0x00000091", "binary": "0000 0000 0000 0000 0000 0000 1001 0001", "expression": "StopForVehicles | SteerAroundPeds | StopAtTrafficLights" } ``` Hashing, in bulk: ```bash curl "https://fivemad.com/api/tools/joaat?text=adder,WEAPON_PISTOL" ``` ```json { "tool": "joaat", "note": "The game lower-cases a string before hashing it, so ADDER and adder give the same value.", "results": [ { "input": "adder", "unsigned": 3078201489, "signed": -1216765807, "hex": "0xB779A091", "lua": "`adder`" }, { "input": "WEAPON_PISTOL", "unsigned": 453432689, "signed": 453432689, "hex": "0x1B06D571", "lua": "`weapon_pistol`" } ] } ``` handling.meta writes its flag fields as bare hex, so that is how this endpoint reads a value, and it gives you the line back ready to paste: ```bash curl "https://fivemad.com/api/tools/handling-flags?set=strHandlingFlags&value=440010" ``` ```json { "set": "strHandlingFlags", "label": "Handling flags", "value": 4456464, "hex": "440010", "metaValue": "", "binary": "0000 0000 0100 0100 0000 0000 0001 0000", "active": [ { "bit": 4, "value": 16, "name": "HF_NO_HANDBRAKE", "desc": "Handbrake disabled." }, { "bit": 18, "value": 262144, "name": "HF_REDUCED_DRIVE_OVER_DAMAGE", "desc": "Takes less damage driving over things." }, { "bit": 22, "value": 4194304, "name": "HF_TYRES_RAISE_SIDE_IMPACT_THRESHOLD", "desc": "Tyres resist side impacts better." } ], "expression": "HF_NO_HANDBRAKE | HF_REDUCED_DRIVE_OVER_DAMAGE | HF_TYRES_RAISE_SIDE_IMPACT_THRESHOLD" } ``` Call an endpoint with no parameters and it answers with its full flag list, its presets and what each bit means, which is enough for a model to pick the right flags on its own: ```bash curl "https://fivemad.com/api/tools/animation-flags" ``` `POST` with a JSON body works the same as the query string: ```bash curl -X POST https://fivemad.com/api/tools/animation-flags \ -H "content-type: application/json" \ -d '{"flags":"AF_LOOPING,AF_UPPERBODY"}' ``` These use the exact same code as the tool pages, so the two can never give different answers. ## Rate limits Per IP, in a fixed one minute window: | Endpoint | Limit | | --- | --- | | `/api/search` | 60 per minute | | `/api/hash` | 60 per minute | | `/api/tools` and `/api/tools/*` | 120 per minute | | All of the above together | 240 per minute | Over the limit you get `429` with a `retry-after` header in seconds and a JSON body that says which limit you hit: ```json { "error": "rate_limited", "message": "Too many requests. This endpoint allows 60 requests per minute per IP (240 across the whole API). Try again in 41s.", "docs": "https://fivemad.com/docs/ai" } ``` The static files (`/data/*.json`, the `.md` pages, `llms.txt`) are served straight off disk and are not rate limited. Please cache them rather than refetching: they change when we rebuild, not per request. The older endpoints keep their own limits: `/api/server` allows 30 lookups per minute per IP and `/api/blacklist` allows 20. ## CORS, caching and errors - The `/api/*` endpoints on this page answer with `access-control-allow-origin: *` and handle a preflight, so a browser based agent can call them from any page. - The static files (`/data/*.json`, `/data/index.json`, the `.md` pages, `llms.txt`) are served by the front end web server, not by the app, so whether they carry that header depends on the deployment. From a server side script, curl or an assistant's own fetcher this makes no difference. If you are calling them from a browser and get a CORS error, use `/api/search` or `/api/hash` instead, or proxy the file yourself. - Errors are JSON with an `error` code, a `message` written for a human, and a link back to this page. Status codes are the ordinary ones: `400` bad input, `404` unknown tool, `429` rate limited, `503` when an index is not loaded yet. - `/api/*` answers are cached for 60 seconds. The static files carry a longer cache. ## What an assistant can and cannot do here It can: - read any documentation page as Markdown, and the whole set at once; - list and download every dataset, with the row shape given up front; - resolve a joaat hash to a name, or a name to a hash, across the whole game; - compute the flag values the natives want, and get the flag meanings back with them; - link a person straight to the page that shows the same thing. It cannot: - run the tools that need a file, a browser or the game files. The texture editor, the clothing designer, the ymap and ytyp builders, the profiler and the 3D viewers all work on data you drop into the page, in your own browser, and there is no upload endpoint for them. - write anything. Everything here is read only. - look up a name we do not ship. Our data comes from the game files and from public FiveM sources; a model, sound or animation that a custom resource adds is not in it. - be treated as a live game API. Nothing here talks to a running server, except `/api/server`, which reports what a FiveM server publishes about itself. ## A worked example "What driving style should I use for an ambulance that runs red lights but still avoids traffic?" ```bash # 1. see what the flags mean curl "https://fivemad.com/api/tools/driving-style" # 2. build the value curl "https://fivemad.com/api/tools/driving-style?flags=SwerveAroundAllVehicles,SteerAroundStationaryVehicles,SteerAroundPeds,SteerAroundObjects,AllowGoingWrongWay" # 3. check the vehicle model exists and get its hash curl "https://fivemad.com/api/hash?q=ambulance" ``` The answer to step 2 carries the value, its signed and hex forms and the native names it belongs to, which is everything needed to write the `TaskVehicleDriveToCoord` call. _Last updated: 2026-09-23_ --- # Video tutorials ## FiveM video tutorial archive URL: https://fivemad.com/docs/videos A hand-picked training set of FiveM YouTube tutorials, grouped into courses from first server to Lua, NUI, streaming assets, CodeWalker and Blender with Sollumz. Some things are easier to learn by watching someone do them. This archive collects FiveM tutorials from YouTube and puts them in order, so you get a course instead of a search results page. Every video was checked to exist and picked because it's clear, accurate enough and still useful today. ## How it's organised The archive has ten courses. Each has a level and its lessons in a sensible order: | Course | Level | For | | --- | --- | --- | | Run your first server | Beginner | Getting a server online on Windows, Linux or a VPS, license key, database, ports, updates, vMenu | | txAdmin in depth | Beginner | The in-game menu, admins, the Discord bot, whitelisting | | Frameworks: QBCore, Qbox and ESX | Beginner | Choosing and installing a framework, jobs, items, ox_inventory | | Lua scripting for FiveM: the basics | Beginner | Editor setup, first resource, commands, natives, events, callbacks, threads | | Scripting in depth | Intermediate | State bags, routing buckets, databases, exports, full job systems, JavaScript and C# | | NUI and user interfaces | Intermediate | HTML UIs, focus and callbacks, React, loading screens | | Streaming assets: vehicles, clothing and MLOs | Intermediate | Car packs and their meta files, textures, clothing packs, MLO installs | | CodeWalker and map editing | Intermediate | YMAPs, adding and removing props, merging maps, MLO collisions | | 3D modelling with Blender and Sollumz | Advanced | Props, collisions, lights, vehicles, clothing and MLO interiors | | Performance, security and workflow | Intermediate | resmon, optimisation, stopping cheaters, git | ## How to use it - **Pair videos with the written guides.** Each course matches a section of these docs: watch the video, then use the guide as the reference. For example the Lua course goes with [Your first resource](/docs/development/first-resource) and [Client, server and events](/docs/development/client-server-events). - **Follow the order inside a course**, but skip what you already know. - **Code along.** Keep a local dev server running (see [Windows setup](/docs/server-setup/windows)) and type the code yourself instead of just watching. - **Check the date.** Every lesson shows when it was published. FiveM changes: older videos may show old txAdmin screens, `GetPlayerPed(-1)` instead of `PlayerPedId()`, or framework code from earlier versions. The ideas still hold, and the written guides show the current way. > [!NOTE] > The videos belong to their creators and are embedded from YouTube. The descriptions are ours. Many creators also sell resources or hosting; being listed here isn't an endorsement of anything but the video. ## About Vespura and the official channels Tom Grobbe (Vespura), the author of vMenu, documents his work in writing at [docs.vespura.com](https://docs.vespura.com/) rather than on YouTube, so his projects appear here through other creators' install videos and in our [recommended resources](/docs/resources/recommended#vmenu) page. Cfx.re's own documentation is written too, at [docs.fivem.net](https://docs.fivem.net/docs/). The official [txAdmin channel](https://www.youtube.com/@txAdmin) has a few short videos, included in the txAdmin course. ## Missing something? If a video goes private or a better one comes out, we update the archive. Suggestions are welcome through the fivemad Discord. _Last updated: 2026-09-22_ --- # Getting started ## Getting started with FiveM servers and development URL: https://fivemad.com/docs/getting-started What FiveM, FXServer, txAdmin and Cfx.re are, how the pieces fit together, and the order to read these docs in to run a server or write scripts. These docs take you from "I want a FiveM server" to running one, managing it with txAdmin, installing resources and frameworks, and writing your own scripts. Everything here is checked against the official Cfx.re documentation and the source repositories on GitHub. When something depends on a version, the page says so. If you only want to get a server online today, jump to [Setting up a server on Windows](/docs/server-setup/windows) or [on Linux](/docs/server-setup/linux). If you want to write code, start with [Your first resource](/docs/development/first-resource). Come back to this page when a word stops making sense. ## The pieces and who makes them FiveM is a modification framework for Grand Theft Auto V that lets people run their own multiplayer servers with custom code, maps, vehicles and game modes. A few names show up everywhere: | Name | What it is | | --- | --- | | **Cfx.re** | The team and platform behind FiveM (GTA V) and RedM (Red Dead Redemption 2). Cfx.re is owned by Rockstar Games. The forum is [forum.cfx.re](https://forum.cfx.re), the docs are [docs.fivem.net](https://docs.fivem.net/docs/). | | **FiveM client** | What players install. It launches their own copy of GTA V and connects to servers. | | **FXServer** | The server program you run. Also called the "Cfx platform server". On Windows it is `FXServer.exe`, on Linux you start it through `run.sh`. | | **Server artifacts** | The FXServer builds you download. Each build has a number, for example `2xxxx`. See [Updating artifacts safely](/docs/server-setup/updating-artifacts) and our [Artifacts page](/artifacts). | | **txAdmin** | The web panel and in-game admin menu that ships inside FXServer. It deploys servers from recipes, restarts them, bans players and more. | | **Cfx.re Portal** | [portal.cfx.re](https://portal.cfx.re), where you create the free server license key that every server needs. | | **Resources** | Folders of scripts and assets that FXServer loads. Everything a server does beyond vanilla GTA is a resource. | | **Frameworks** | Big sets of resources that add players, jobs, money and inventories, for example QBCore, Qbox and ESX Legacy. See [Frameworks](/docs/frameworks). | > [!NOTE] > In July 2026 Cfx.re opened early access for **FiveM for GTA V Enhanced**, which runs on the newer Enhanced edition of the game with a separate server build called **Cfx Server**. The classic FiveM, now called **Legacy**, keeps running and is still what almost every server and resource targets. These docs cover Legacy FXServer unless a page says otherwise. See [FiveM Legacy and Enhanced](/docs/server-setup#fivem-legacy-and-fivem-for-gta-v-enhanced) for what changes. ## How it fits together When you start a server, this is what happens: 1. You run FXServer. With no arguments it starts **txAdmin**, which opens a web panel on port `40120`. 2. txAdmin (or you, by hand) starts FXServer with a `server.cfg`. That file sets the server name, the license key, player slots, endpoints and which resources to start. 3. FXServer reads the `resources` folder, loads every resource you `ensure`, and runs their **server scripts**. 4. A player connects on port `30120`. Their client downloads the **client scripts**, NUI pages and streamed assets (models, textures, maps) of your resources, then joins. 5. Client scripts and server scripts talk to each other with **events**, and to the game through **natives**. ```text title="A typical server folder after a txAdmin deploy" FXServer/ ├─ server/ the artifact: FXServer.exe (Windows) or run.sh + alpine/ (Linux) └─ txData/ ├─ admins.json txAdmin accounts └─ MyServer.base/ your server data folder (any name you pick in the deployer) ├─ server.cfg └─ resources/ ├─ [cfx-default]/ mapmanager, spawnmanager, chat... └─ [local]/ your own resources ``` ## A learning path through these docs Follow the sections in this order. Each page links to the next one. ### 1. Understand what you need - [Glossary](/docs/getting-started/glossary): every term you will meet, in one place. - [Requirements](/docs/getting-started/requirements): hardware, Windows or Linux, and the legal basics (license, Rockstar content, monetisation). ### 2. Get a server online - [Server setup overview](/docs/server-setup), then [Windows](/docs/server-setup/windows) or [Linux](/docs/server-setup/linux). - [server.cfg explained](/docs/server-setup/server-cfg) line by line. You can also build one with the [server.cfg Generator](/tools/server-cfg-generator). - [Ports and networking](/docs/server-setup/ports-and-networking) and [Database setup](/docs/server-setup/database) if you plan to run a framework. - [Common errors and fixes](/docs/server-setup/common-errors) and [Security basics](/docs/server-setup/security). ### 3. Run it day to day with txAdmin - [txAdmin overview](/docs/txadmin), [first setup and the deployer](/docs/txadmin/first-setup), [recipes](/docs/txadmin/recipes), [everyday admin](/docs/txadmin/everyday-admin) and the [Discord bot](/docs/txadmin/discord-bot). ### 4. Add content - [Installing resources](/docs/resources), [recommended open source resources](/docs/resources/recommended), [maps, MLOs and clothing](/docs/resources/maps-mlos-clothing) and [vehicle packs](/docs/resources/vehicle-packs). - Pick a framework, or none: [Frameworks compared](/docs/frameworks). ### 5. Write your own scripts - [Development overview](/docs/development) (tools and setup), then [Your first resource](/docs/development/first-resource). - [Client, server and events](/docs/development/client-server-events), [natives](/docs/development/natives), [state bags and OneSync](/docs/development/state-bags-onesync), [NUI](/docs/development/nui). - [Threads and performance](/docs/development/threads-performance), [exports and dependencies](/docs/development/exports-dependencies), [debugging](/docs/development/debugging). - [Streaming custom assets](/docs/development/streaming-assets) and [publishing a resource](/docs/development/publishing). ### 6. Watch instead of read The [video tutorial archive](/docs/videos) groups hand-picked YouTube tutorials into courses: running your first server, txAdmin, frameworks, Lua scripting, NUI, streaming assets, CodeWalker and Blender with Sollumz. ## Where to get help - **Official docs**: [docs.fivem.net](https://docs.fivem.net/docs/) for server setup, the scripting manual and the [natives reference](https://docs.fivem.net/natives/). - **Forum**: [forum.cfx.re](https://forum.cfx.re) has Server Discussion, Development and Releases categories. Search before you post, most errors have been seen before. - **Framework communities**: QBCore, Qbox, ESX and Overextended each run their own Discord and docs, linked from the [frameworks pages](/docs/frameworks). - **txAdmin**: the [txAdmin Discord](https://discord.gg/txAdmin) and the docs folder in the [txAdmin repository](https://github.com/citizenfx/txAdmin/tree/master/docs). > [!TIP] > When you ask for help, paste the exact error from the server console or the F8 client console, your artifact build number and your `server.cfg` (with the license key and database password removed). That answers half the questions people will ask you. _Last updated: 2026-09-22_ --- ## FiveM glossary URL: https://fivemad.com/docs/getting-started/glossary Plain definitions of the FiveM terms you will meet: resources, artifacts, OneSync, natives, state bags, NUI, ymap, ytyp, ydr, yft, ytd, streaming, convars, ACE. FiveM has its own vocabulary, and GTA V adds a second one for its file formats. This page explains each term in a sentence or two and points to the page that goes deeper. Terms are grouped by topic, not alphabetically, so related ideas sit together. ## Platform and server **Cfx.re**: The company and platform behind FiveM and RedM, owned by Rockstar Games. "Cfx" shows up in the forum (`forum.cfx.re`), the portal (`portal.cfx.re`) and join links (`cfx.re/join/abc123`). **FXServer**: The dedicated server program. You download it as an **artifact** and run `FXServer.exe` on Windows or `run.sh` on Linux. **Artifact**: One numbered build of FXServer, published at `runtime.fivem.net/artifacts`. There is a *recommended* build and a *latest* build. Some builds are known to be broken, so check our [Artifacts page](/artifacts) before you update. More in [Updating artifacts safely](/docs/server-setup/updating-artifacts). **Legacy and Enhanced**: Since July 2026 there are two FiveM platforms. **Legacy** is the classic FiveM on the original PC version of GTA V and uses FXServer. **FiveM for GTA V Enhanced** runs on the Enhanced edition and uses a separate server build called **Cfx Server**. They are separate: a Legacy client cannot join an Enhanced server. **txAdmin**: The web panel and in-game menu built into FXServer. It deploys servers from **recipes**, restarts on crash, schedules restarts, bans and warns players and runs a Discord bot. See [txAdmin](/docs/txadmin). **Recipe**: A YAML file that tells the txAdmin deployer how to build a server: which repositories to download, which files to move, which SQL to run. See [Recipes explained](/docs/txadmin/recipes). **License key**: The free key from [portal.cfx.re](https://portal.cfx.re) that every server must set with `sv_licenseKey`. Keys look like `cfxk_...`. **server.cfg**: The config file FXServer executes on start. It is a list of console commands and convars. See [server.cfg explained](/docs/server-setup/server-cfg). **Convar**: A console variable, like `sv_hostname` or `sv_maxclients`. You set it with `set`, `sets` (also shows in the server list info) or `setr` (also replicated to clients so client scripts can read it). **Endpoint**: The IP and port FXServer listens on, set with `endpoint_add_tcp` and `endpoint_add_udp`. The default is `0.0.0.0:30120`. **Game build**: The GTA V update your server asks clients to run, set with `sv_enforceGameBuild` (for example `3751`). Newer builds unlock newer DLC vehicles, clothes and maps. **Pure mode**: `sv_pureLevel` blocks modified client game files. Level 1 still allows audio files and known graphics mods, level 2 blocks all modified files. **OneSync**: FiveM's server side sync system. With `onesync on` the server knows about every entity and player and decides who gets what, which allows more than 32 players and server side entity control. Without a Cfx.re subscription the slot limit is 48. Up to 2048 slots are possible with OneSync and the right tier. **Routing bucket**: A separate "dimension" on a OneSync server. Players and entities in different buckets cannot see each other. Used for instanced interiors, character selection and races. **Entity lockdown**: `sv_entityLockdown` stops clients from creating networked entities themselves, which blocks a common cheat. Modes are `inactive`, `relaxed` and `strict`. ## Resources and scripting **Resource**: A folder with an `fxmanifest.lua` file. It can contain Lua, JavaScript or C# scripts, a web UI, streamed assets and data files. You start it with `ensure name` where `name` is the folder name. **fxmanifest.lua**: The resource manifest. It declares `fx_version`, `game`, which scripts run on the client or server, which files to send to clients, `data_file` entries and dependencies. Generate one with the [fxmanifest Generator](/tools/fxmanifest-generator). **Category folder**: A folder in brackets, like `[local]` or `[qb]`. It only groups resources, it is not a resource itself. `ensure [qb]` starts every resource inside it. **Client script / server script / shared script**: Client scripts run on each player's game. Server scripts run once, in FXServer. Shared scripts run on both. See [Client, server and events](/docs/development/client-server-events). **Event**: A named message. `TriggerEvent` fires one on the same side, `TriggerServerEvent` sends one from a client to the server, `TriggerClientEvent` sends one from the server to one or all clients. Network events must be registered with `RegisterNetEvent`. **Callback**: A request that expects an answer, for example "server, how much money does this player have?". FiveM has no built in callback between client and server, so libraries like `ox_lib` (`lib.callback`) and the frameworks provide one on top of events. **Native**: A function of the GTA V engine or of FiveM itself, like `GetEntityCoords` or `SetPedIntoVehicle`. There are thousands, listed at [docs.fivem.net/natives](https://docs.fivem.net/natives/). See [Natives](/docs/development/natives). **Hash / joaat**: GTA identifies models, weapons and many other things by a 32 bit hash of their name, computed with Jenkins one-at-a-time (joaat). `GetHashKey('adder')` or `` `adder` `` in FiveM Lua gives you the number. Try the [joaat Hash Calculator](/tools/hash-calculator). **Export**: A function one resource makes callable from other resources, like `exports.ox_inventory:AddItem(...)`. See [Exports and dependencies](/docs/development/exports-dependencies). **State bag**: A key/value store attached to the server (`GlobalState`), a player (`Player(src).state`) or an entity (`Entity(ent).state`) that FiveM syncs for you. See [State bags and OneSync](/docs/development/state-bags-onesync). **NUI**: "New UI", FiveM's embedded Chromium browser. It lets you build HUDs, menus and phones in HTML, CSS and JavaScript (React, Vue, Svelte and so on). See [NUI basics](/docs/development/nui). **DUI**: Direct-rendered UI. A web page drawn onto a texture in the world, like a TV screen or a billboard. **KVP**: Key value pairs, a small built in storage (`SetResourceKvp`, `GetResourceKvpString`) on the client or server. Good for settings, not for large data. **Tick / thread**: A Lua loop created with `CreateThread` that runs every frame or every `Wait(ms)`. Code that runs every frame costs performance. See [Threads and performance](/docs/development/threads-performance). **resmon**: The resource monitor. Type `resmon` in the F8 console to see how much CPU time and memory each client resource uses. **Profiler**: The built in FiveM profiler (`profiler record`, `profiler saveJSON`) that records exactly which resource and function uses time. Read its output with the [Profiler Analyzer](/tools/profiler-analyzer). **Framework**: A shared base for roleplay style servers: player data, characters, jobs, money, items. QBCore, Qbox, ESX Legacy, ox_core and ND_Core are the common ones. See [Frameworks](/docs/frameworks). **Asset escrow**: Cfx.re's system that encrypts paid resources sold on Tebex so they only run on the buyer's license key. See [Publishing a resource](/docs/development/publishing). ## Permissions **ACE**: Access Control Entry. A rule like `add_ace group.admin command allow` that allows or denies an **object** (for example `command.ban`) for a **principal**. **Principal**: Who a rule applies to: a group (`group.admin`), an identifier (`identifier.fivem:123456`, `identifier.license:abc...`, `identifier.discord:...`) or a resource (`resource.myresource`). `add_principal child parent` makes one principal inherit another. **Identifier**: A player ID that FXServer receives on connect: `license:` (Rockstar license), `fivem:` (Cfx.re account), `discord:`, `steam:` (needs a Steam Web API key), `xbl:`, `live:` and `ip:`. ## GTA V file formats **RPF**: Rockstar's archive format. Singleplayer mods ship as `dlc.rpf`. FiveM does not load RPFs from resources, you extract their contents into a `stream` folder and meta files instead. **Streaming**: Loading assets into the game as they are needed. In FiveM, any supported file in a resource's `stream` folder is sent to clients and registered with the game automatically. **YDR**: A single drawable model (props, simple objects). **YDD**: A drawable dictionary, several drawables in one file. Used for clothing and ped parts. **YFT**: A fragment model, a model that can break or has moving parts. Vehicles are `.yft` files (plus a `_hi.yft` high detail version). **YTD**: A texture dictionary. Holds the textures for a model. Oversized YTDs are the most common cause of texture loss on busy servers. Shrink them with the [YTD Optimizer](/tools/ytd-optimizer). **YBN**: Static collision (bounds). Without it players fall through your map. **YMAP**: A map placement file. It lists which objects (entities) are placed where, with rotation and LOD distance. Build one with the [YMAP Builder](/tools/ymap-builder) or in CodeWalker. **YTYP**: An archetype definition file. It tells the game about new model names, their bounding boxes and LOD distances, and defines MLO interiors. Create one with the [YTYP Creator](/tools/ytyp-creator). **MLO**: "Map Loaded Object", an interior with rooms and portals, defined in a `.ytyp` and placed by a `.ymap`. Custom shops, police stations and houses are usually MLOs. **YMT**: A binary metadata file. For clothing, the ped variation `.ymt` lists how many drawables and textures each component has. Generate one with the [YMT Creator](/tools/ymt-creator). **YNV / YND**: Navmesh and path nodes. They tell peds and traffic where they can walk and drive. **.meta files**: XML data files the game reads, like `vehicles.meta`, `handling.meta`, `carcols.meta`, `carvariations.meta` and `weapons.meta`. You register them in the manifest with `data_file`. **AWC / dat54.rel**: Audio: `.awc` holds the sound data, `dat54.rel` (and friends) define how the game plays it. The [Native Audio Builder](/tools/native-audio-builder) turns WAV, MP3 or OGG files into this format. **CodeWalker**: The free community tool for browsing the GTA V world and editing YMAPs, YTYPs and many other formats. Get it from [github.com/dexyfex/CodeWalker](https://github.com/dexyfex/CodeWalker). **Sollumz**: The free Blender add-on for importing and exporting GTA V models (YDR, YDD, YFT, YBN) as CodeWalker XML. Get it from [github.com/Sollumz/Sollumz](https://github.com/Sollumz/Sollumz). **LOD**: Level of detail. Models have simpler versions for far away views, and the game switches between them by distance. _Last updated: 2026-09-22_ --- ## Requirements: hardware, OS and the rules URL: https://fivemad.com/docs/getting-started/requirements What you need to run a FiveM server: realistic hardware sizing, Windows or Linux, network, and the legal basics of the Cfx.re license, Rockstar content and Tebex. Before you rent a machine or promise a community a launch date, check three things: the hardware you need for the kind of server you want, the operating system you are comfortable with, and the rules you agree to when you run a FiveM server. ## What you need no matter what - **A legal copy of GTA V** on the PC you play from. The server itself does not need GTA V installed. - **A Cfx.re account** and a free **server license key** from [portal.cfx.re](https://portal.cfx.re). One key per server. - **A machine that stays online**: your own PC for testing, or a VPS or dedicated server for a public server. - **Open ports**: `30120` TCP and UDP for players, and `40120` TCP for the txAdmin web panel (keep that one private if you can). See [Ports and networking](/docs/server-setup/ports-and-networking). - **MariaDB** if you plan to run a framework like QBCore, Qbox or ESX. A plain server with vMenu does not need a database. See [Database setup](/docs/server-setup/database). ## Hardware sizing Cfx.re does not publish official hardware requirements, and the real load depends far more on your resources than on your player count. A server with 40 well written scripts behaves very differently from one with 300 leaked ones. Use the table below as a starting point, then measure with txAdmin's performance chart and the [profiler](/docs/development/threads-performance). | Server type | CPU | RAM | Storage | Notes | | --- | --- | --- | --- | --- | | Local test server on your PC | Any modern 4 core | 4 GB free | 10 GB | Fine for development. Run the game and the server on the same machine. | | Small public server, up to ~48 players, light scripts | 2 to 4 fast cores | 4 to 8 GB | 30 to 60 GB SSD | vMenu or a light framework, a few car packs. | | Roleplay server, 48 to 128 players, full framework | 4+ cores with high single core speed | 8 to 16 GB | 60 to 120 GB NVMe | MariaDB on the same machine is common at this size. | | Large server, 128+ players, heavy streaming | 6 to 8+ high clock cores | 16 to 32 GB | NVMe, plus a CDN or separate file server for assets | Needs a paid Cfx.re tier for the slots, and careful script work. | A few things matter more than raw numbers: - **Single core speed.** The main server thread runs on one core. A high clock CPU beats a many core, low clock one. - **Upload bandwidth.** Every joining player downloads all your streamed assets. A 2 GB car pack times 50 players joining after a restart is 100 GB of upload. Keep packs lean, shrink textures with the [YTD Optimizer](/tools/ytd-optimizer), and consider a file server or CDN for big servers. - **Disk speed.** MariaDB and txAdmin logs like fast disks. Avoid spinning disks. - **Clean IP.** Some hosting IP ranges are blocked on the Cfx.re platform. Check a VPS IP with the [Cfx Blacklist Checker](/tools/cfx-blacklist-checker) before you pay for a year. > [!IMPORTANT] > The free slot limit is **48 players**. Going above 48 needs a Cfx.re Element Club tier (Argentum or higher), bought on the Cfx.re Portal. Setting `sv_maxclients 64` without it does not work. ## Windows or Linux Both are fully supported by FXServer and txAdmin. | | Windows | Linux | | --- | --- | --- | | Setup | Download `server.7z`, extract, double click `FXServer.exe`. | Download `fx.tar.xz`, extract, run `bash run.sh`. Needs basic shell skills. | | Cost | Windows Server licenses make VPS plans pricier. | Usually cheaper for the same hardware. | | Tools | HeidiSQL, CodeWalker and Windows only tools run on the same box. | Everything is done over SSH. Run the game tools on your own PC. | | Running as a service | Scheduled task or a service wrapper. | `systemd`, `screen` or `tmux`. | | C# resources | Supported. | Supported. | If you have never used a Linux shell, start on Windows (even your own PC) and move to Linux later. Your resources and `server.cfg` work the same on both, just watch out for **case sensitive file names** on Linux: `ensure MyResource` will not find a folder called `myresource`. > [!TIP] > Develop on a local Windows server, deploy to a Linux VPS. Keep the whole server folder in git so moving between them is a `git pull`. See [Security basics](/docs/server-setup/security) for what never to commit. ## Game server providers vs your own VPS Game server providers (GSPs) give you a panel with FXServer and txAdmin preinstalled. That is the fastest way to get online, and many of them can host MariaDB for you. A VPS or dedicated server gives you full control and usually more hardware for the money, but you handle updates, backups and security yourself. These docs work for both: txAdmin looks the same everywhere. ## The rules you agree to Running a FiveM server means agreeing to the **Cfx.re Platform License Agreement** (the "terms", at [fivem.net/terms](https://fivem.net/terms)). It has been updated several times, including a new Creator Platform License Agreement that took effect on 12 January 2026, so read the current version yourself. This section is a plain summary, not legal advice. ### What the platform allows - Running a server with your own game mode, scripts, maps and vehicles. - Making and sharing resources, free or paid. - Accepting money from players, but only through **Tebex**, Cfx.re's authorised commerce partner, and only for things the terms allow. ### What gets servers and creators in trouble Commonly cited points from the current agreement and Cfx.re's guidance: - **Selling Rockstar's content.** You cannot sell access to GTA V assets, vehicles, clothing or maps that Rockstar made, or charge for things that are just the base game. - **Loot boxes and gambling.** Chance based purchases and real money gambling mechanics are not allowed. - **Selling in-game currency** or anything that can be converted back into real money. - **Using other people's IP.** Real world brands, logos, copyrighted cars and characters. "Everyone else does it" is not a defence when a takedown arrives. - **Leaked resources.** Running or sharing leaked paid scripts is a licence violation, can get your server delisted, and leaked code is a common place to hide backdoors. - **Hosting other people's servers commercially** without authorisation. Only authorised game server providers may do that. ### Tebex and asset escrow - **Tebex** is the store you connect on the Cfx.re Portal. Players buy packages, and Tebex can run commands on your server to deliver them. - **Asset escrow** is how paid resources are protected. When a creator sells a resource on Tebex with escrow, the files are encrypted and only run for the buyer's Cfx.re account. As a buyer you download them from the assets section of the Cfx.re Portal, logged in with the account that bought them. Escrowed resources usually leave a `config.lua` and a few "open" files readable so you can configure them. - If you sell your own work, see [Publishing a resource](/docs/development/publishing). > [!CAUTION] > If a "free" copy of a paid script shows up on a random Discord, it is leaked. Beyond the licence issue, leaked resources are one of the most common ways servers get backdoored (remote code that gives someone else admin, or drains your Tebex). Don't run them. ## Checklist before you start - [ ] GTA V installed and FiveM working on your PC. - [ ] Cfx.re account created, license key generated on the Portal. - [ ] Machine chosen (local PC, VPS or GSP) and its IP checked with the [Cfx Blacklist Checker](/tools/cfx-blacklist-checker). - [ ] Ports `30120` TCP/UDP reachable, `40120` reachable at least from your own IP. - [ ] MariaDB installed if you want a framework. - [ ] A text editor (VS Code) and git. Next: [Server setup overview](/docs/server-setup). _Last updated: 2026-09-22_ --- # Server setup ## Server setup overview URL: https://fivemad.com/docs/server-setup The ways to set up a FiveM server (txAdmin, vanilla, hosting provider), what you download, the folder layout, and the difference between Legacy and Enhanced. Setting up a FiveM server comes down to four steps: get a license key, download a server build (an **artifact**), run it, and give it a `server.cfg` with resources to start. txAdmin, which ships inside every build, does most of this for you. ## Pick a setup method The official docs list four ways. They all end up with the same FXServer running the same resources. | Method | Best for | Guide | | --- | --- | --- | | **txAdmin on Windows** | First server, local development, Windows VPS | [Windows setup](/docs/server-setup/windows) | | **txAdmin on Linux** | VPS and dedicated servers, cheaper hosting | [Linux setup](/docs/server-setup/linux) | | **Vanilla (no txAdmin)** | Minimal dev servers, containers, people who want full control | Covered at the end of both guides | | **Game server provider** | People who don't want to manage a machine | Your provider's panel, then the [txAdmin](/docs/txadmin) pages | We recommend txAdmin for almost everyone. It is maintained by Cfx.re, restarts the server when it crashes, schedules restarts, and its deployer can install QBCore, Qbox or ESX from a recipe in a few minutes. ## Before you start 1. **Create a license key.** Log in at [portal.cfx.re](https://portal.cfx.re), open the server registration keys page (the dashboard has a "Create a Key" quick link), click **Generate Key**, give it a display name and copy the key. It starts with `cfxk_`. Store it somewhere safe, you will paste it into txAdmin or `server.cfg`. 2. **Pick an artifact.** Download the **recommended** build from the official [server download page](https://docs.fivem.net/docs/server-download/) or `runtime.fivem.net/artifacts`. Our [Artifacts page](/artifacts) shows the recommended build and flags builds known to be broken. 3. **Decide where the server lives.** Your PC is fine for testing. For a public server read [Requirements](/docs/getting-started/requirements) first. 4. **Install MariaDB** if you will run a framework. See [Database setup](/docs/server-setup/database). ## What you download | Platform | File | What is inside | | --- | --- | --- | | Windows | `server.7z` | `FXServer.exe`, `citizen/` (scripting runtimes, txAdmin, system resources) and DLLs | | Linux | `fx.tar.xz` | `run.sh` and an `alpine/` folder with the server and its own libraries | The artifact is the program. Your **server data** (the `server.cfg` and the `resources` folder) lives somewhere else. Keeping them apart is what makes updating easy: you swap the artifact folder and your data stays untouched. ```text title="Recommended layout" C:\FXServer\ ├─ server\ artifact, replace this folder when you update └─ txData\ created by txAdmin on first start ├─ admins.json ├─ default\ txAdmin's own data (config, player database, logs) └─ QBCore_A1B2C3.base\ your server data folder: server.cfg + resources\ (the deployer suggests a name like this, you can pick any) ``` On Linux the same idea applies, usually under `/home/fivem/` or `/opt/fivem/`. ## How txAdmin and FXServer start - Run FXServer **without** `+exec server.cfg` and it starts **txAdmin** on port `40120`. txAdmin then starts FXServer for you with your config. This is the normal way. - Run FXServer **with** `+exec server.cfg` from inside your server data folder and it starts directly, with no txAdmin. This is the "vanilla" way. Both guides cover both ways. ## FiveM Legacy and FiveM for GTA V Enhanced In March 2026 Cfx.re announced FiveM for the Enhanced edition of GTA V, and early access for server owners opened on **21 July 2026**. What you need to know as a server owner: - It is a **separate platform**. The client is separate, and the server is a separate program called **Cfx Server** with its own download on the [server download page](https://docs.fivem.net/docs/server-download/) (files are named `cfx-server.exe` on Windows). Legacy and Enhanced players cannot join each other's servers, so moving is a decision for your whole community. - Legacy is **not going away**. Upgrading is optional and Legacy support continues. - Cfx.re's [What's changed](https://docs.fivem.net/docs/developers/legacy-vs-enhanced/) page lists the breaking changes. The big ones: Mono is replaced by .NET 10 for C# resources, pure mode is always on, OneSync is always the full mode (no "legacy" or P2P mode), only the latest game build is supported, KVP files must be migrated, asset escrow was not yet available at launch, and dev tools need `sv_devMode true`. - Existing streamed assets may need converting with Cfx.re's **Alchemist** tool. - txAdmin has a separate "FiveM Basic Server (Enhanced)" recipe. The rest of these docs describe **Legacy FXServer**, which is what almost all resources, frameworks and tutorials target today. Where Enhanced differs in a way that bites, the page says so. [FiveM Enhanced: Everything That Changed For Server Owners (TraseDev)](https://www.youtube.com/watch?v=WOgYKmAqptg) (YouTube video) ## The pages in this section 1. [Windows setup](/docs/server-setup/windows): step by step with txAdmin, plus vanilla. 2. [Linux setup](/docs/server-setup/linux): Ubuntu or Debian, systemd service, firewall. 3. [server.cfg explained](/docs/server-setup/server-cfg): every common line and what it does. 4. [Updating artifacts safely](/docs/server-setup/updating-artifacts): how to update without breaking things. 5. [Ports and networking](/docs/server-setup/ports-and-networking): port forwarding, server list, proxies. 6. [Database setup](/docs/server-setup/database): MariaDB, HeidiSQL and oxmysql. 7. [Common errors and fixes](/docs/server-setup/common-errors): the errors everyone hits, and the fix. 8. [Security basics](/docs/server-setup/security): ACE, txAdmin accounts, the database, secrets. > [!TIP] > Want a ready config instead of writing one? The [server.cfg Generator](/tools/server-cfg-generator) builds a full `server.cfg` with hostname, slots, OneSync, endpoints, tags, resources and ACE permissions. _Last updated: 2026-09-22_ --- ## Set up a FiveM server on Windows URL: https://fivemad.com/docs/server-setup/windows Step by step: download the FXServer artifact, extract it, run txAdmin, link your Cfx.re account, deploy a recipe with your license key, and connect. Plus the vanilla way. This guide sets up a FiveM server on Windows 10, 11 or Windows Server with txAdmin. It works the same on your own PC (for development) and on a Windows VPS. Plan about 15 minutes. [How to Make a FiveM Server in 2026! (HighwayTrooper)](https://www.youtube.com/watch?v=NjVwsBinE10) (YouTube video) ## What you need - A Cfx.re account and a **license key** from [portal.cfx.re](https://portal.cfx.re) (see [Server setup overview](/docs/server-setup#before-you-start)). - [7-Zip](https://www.7-zip.org/) or WinRAR to open `.7z` files. - **Git for Windows** is optional but useful later. - **MariaDB** only if you want a framework (QBCore, Qbox, ESX). Install it first, see [Database setup](/docs/server-setup/database). ## 1. Create the folders Make a folder with a short path and no spaces, for example: ```text C:\FXServer\server ``` Short paths avoid problems with long resource paths and some tools. Don't put the server in `Program Files`, `Downloads` or a OneDrive synced folder. ## 2. Download the artifact 1. Open the official [server download page](https://docs.fivem.net/docs/server-download/) (or `https://runtime.fivem.net/artifacts/fivem/build_server_windows/master/`). 2. Pick **FiveM / RedM**, **Windows**, **Recommended** and download `server.7z`. 3. Check the build number against our [Artifacts page](/artifacts), which flags builds with known problems. > [!NOTE] > The Enhanced platform (Cfx Server) is a different download on the same page. Pick the FiveM / RedM (Legacy) build unless you know you want Enhanced. See [Legacy and Enhanced](/docs/server-setup#fivem-legacy-and-fivem-for-gta-v-enhanced). ## 3. Extract it Open `server.7z` with 7-Zip and extract everything into `C:\FXServer\server`. You should now have `C:\FXServer\server\FXServer.exe` and a `citizen` folder next to it. > [!TIP] > Windows Defender scanning every file makes FXServer start slowly. The official FAQ suggests excluding the folder: open PowerShell as administrator and run `Add-MpPreference -ExclusionPath 'C:\FXServer\'`. ## 4. Start txAdmin Double click `FXServer.exe`. A console window opens and, because you did not pass `+exec server.cfg`, FXServer starts **txAdmin**. It creates `C:\FXServer\txData` and opens `http://localhost:40120` in your browser. The console also prints a 4 digit **PIN**. If the browser does not open, go to `http://localhost:40120` yourself. On a VPS, use `http://YOUR_VPS_IP:40120` from your own PC (and open TCP 40120 in the Windows firewall, ideally only for your IP). ## 5. Link your account 1. Check that the PIN is filled in and click **Link Account**. 2. Log in with your Cfx.re (forum) account and click **Yes, Allow**. 3. Create a **backup password**. You will use it if Cfx.re login is ever down, so save it in a password manager. This makes you the **master admin** of this txAdmin. ## 6. Run the setup and deployer 1. Enter a **server name** and click **Next**. 2. Choose **Popular Recipes**. 3. Pick a recipe: - **FiveM Basic Server (Legacy)**, sometimes shown as CFX Default: a clean, framework free server. Best for learning and for vMenu servers. - **QBCore**, **Qbox** or **ESX Legacy**: full roleplay frameworks. These need MariaDB running. See [Popular recipes](/docs/txadmin/popular-recipes). 4. Confirm the **data location** (the default `txData\.base` is fine) and click **Save**. 5. The **Recipe Deployer** shows the recipe YAML. Click **Next**. 6. Paste your **license key**. For framework recipes, fill in the **database** host (`localhost`), port (`3306`), user (`root`) and password. Leave the database name empty and txAdmin generates one. 7. Click **Run Recipe**. txAdmin downloads the resources and, for frameworks, imports the SQL. This takes a minute or two. 8. Review the generated `server.cfg` and click **Save & Run Server**. The live console in txAdmin now shows the server starting. When you see resources starting and no red errors, it is up. > [!IMPORTANT] > QBCore and some other recipes install NPM packages with yarn on first start. Let that finish before you restart. The QBCore docs say this explicitly. ## 7. Connect 1. Start FiveM. 2. Press F8 to open the client console. 3. Type `connect localhost:30120` (same PC) or `connect YOUR_PUBLIC_IP:30120` and press Enter. You can also use the direct connect box in the FiveM main menu with the same address. To let friends connect, see [Ports and networking](/docs/server-setup/ports-and-networking). ## 8. Make it start on its own txAdmin restarts FXServer on crashes, but not the whole machine. On a VPS, start FXServer when Windows boots: 1. Create `C:\FXServer\start.bat`: ```bat title="C:\FXServer\start.bat" @echo off cd /d C:\FXServer\server FXServer.exe ``` 2. Open **Task Scheduler**, create a task that runs `start.bat` **At startup**, "Run whether user is logged on or not", with the account that owns the folder. 3. In txAdmin, **Settings > FXServer**, turn on starting the server automatically when txAdmin starts. ## Folder layout after setup ```text C:\FXServer\ ├─ server\ FXServer.exe + citizen\ (replace to update) ├─ start.bat └─ txData\ ├─ admins.json txAdmin accounts ├─ default\ txAdmin config, logs, player database └─ MyServer.base\ ├─ server.cfg └─ resources\ ``` Your own resources go in `resources\[local]\` and get an `ensure` line in `server.cfg`. See [Installing resources](/docs/resources). ## The vanilla way (no txAdmin) Useful for a throwaway dev server or when you want to see exactly what runs. From the official vanilla guide: ```bat cd /d C:\FXServer git clone https://github.com/citizenfx/cfx-server-data.git server-data ``` Create `C:\FXServer\server-data\server.cfg`: ```cfg title="server-data/server.cfg" endpoint_add_tcp "0.0.0.0:30120" endpoint_add_udp "0.0.0.0:30120" ensure mapmanager ensure chat ensure spawnmanager ensure sessionmanager ensure basic-gamemode ensure hardcap sv_hostname "My dev server" sv_maxclients 8 sv_licenseKey "cfxk_your_key_here" sv_enforceGameBuild 3751 set onesync on ``` Then start it from inside the data folder: ```bat cd /d C:\FXServer\server-data C:\FXServer\server\FXServer.exe +exec server.cfg ``` > [!WARNING] > Always start FXServer from inside the server data folder (or tell txAdmin where it is). If you start it from somewhere else, it cannot find `resources` and you get "no resources found" or "couldn't find resource" errors. ## Next steps - Read [server.cfg explained](/docs/server-setup/server-cfg) so you know what every line does. - Set up [txAdmin admins, bans and scheduled restarts](/docs/txadmin/everyday-admin). - Add [vMenu or other resources](/docs/resources/recommended). - Write [your first resource](/docs/development/first-resource). _Last updated: 2026-09-22_ --- ## Set up a FiveM server on Linux URL: https://fivemad.com/docs/server-setup/linux Run FXServer and txAdmin on Ubuntu or Debian: dependencies, a dedicated user, the Linux artifact, a systemd service or tmux, the ufw firewall and MariaDB. This guide sets up FXServer with txAdmin on a fresh **Ubuntu 22.04 / 24.04** or **Debian 12** VPS. Other distributions work too, since the Linux artifact ships its own libraries in an `alpine` folder, but the package commands below are for Debian based systems. You need SSH access with a user that can run `sudo`. [Linux-Ubuntu FiveM Server Install Guide (Enix Hosting)](https://www.youtube.com/watch?v=kz1TozHDa5Q) (YouTube video) ## 1. Update the system and install tools ```bash sudo apt update && sudo apt upgrade -y sudo apt install -y xz-utils git curl wget tmux ufw ``` `xz-utils` is required to extract the artifact. `git` is for cloning resources, `tmux` for running the server in a detachable session, `ufw` for the firewall. ## 2. Create a user for the server Never run a game server as `root`. Create a dedicated user and switch to it: ```bash sudo adduser --disabled-password --gecos "" fivem sudo -iu fivem mkdir -p ~/server cd ~/server ``` Everything below runs as `fivem` unless it starts with `sudo`. ## 3. Download the Linux artifact 1. Open `https://runtime.fivem.net/artifacts/fivem/build_proot_linux/master/` in your browser. 2. Pick the **recommended** build (check it on our [Artifacts page](/artifacts)) and copy the link to its `fx.tar.xz`. 3. Download and extract it on the server: ```bash cd ~/server wget https://runtime.fivem.net/artifacts/fivem/build_proot_linux/master/XXXXX-/fx.tar.xz tar xf fx.tar.xz rm fx.tar.xz ls # alpine run.sh ``` Replace the URL with the one you copied. The build folder name changes with every release, so don't reuse an old link from a tutorial. ## 4. Open the firewall Allow SSH first so you don't lock yourself out, then the game ports: ```bash sudo ufw allow OpenSSH sudo ufw allow 30120/tcp sudo ufw allow 30120/udp # txAdmin web panel: better to allow only your own IP sudo ufw allow from YOUR_HOME_IP to any port 40120 proto tcp sudo ufw enable sudo ufw status ``` If your home IP changes often, you can open 40120 to everyone (`sudo ufw allow 40120/tcp`), but then use a strong password and 2FA on every txAdmin account. See [Security basics](/docs/server-setup/security). Many VPS providers also have a firewall in their web panel: open the same ports there. ## 5. First start with txAdmin ```bash cd ~/server bash run.sh ``` FXServer starts txAdmin and prints something like: ```text [txAdmin] Use the PIN below to register: [txAdmin] 1234 [txAdmin] http://YOUR_VPS_IP:40120/ ``` Open that address in your browser on your own PC and follow the same steps as on Windows: **Link Account** with your Cfx.re login, create a backup password, pick a recipe, paste your license key, run the recipe, then **Save & Run Server**. The full walkthrough is in [First setup and the deployer](/docs/txadmin/first-setup). On Linux, txAdmin creates `txData` next to `run.sh` by default (`~/server/txData`). You can change it with the `TXHOST_DATA_PATH` environment variable. Press Ctrl+C to stop it once setup is done. Next we make it run in the background. ## 6. Keep it running ### Option A: tmux (simple) ```bash tmux new -s fivem cd ~/server && bash run.sh ``` Detach with Ctrl+B then D. Reattach later with `tmux attach -t fivem`. The server keeps running after you log out, but not after a reboot. `screen` works the same way (`screen -S fivem`, detach with Ctrl+A then D, reattach with `screen -r fivem`). ### Option B: systemd service (starts on boot) Create the unit file as root: ```ini title="/etc/systemd/system/fivem.service" [Unit] Description=FiveM server (txAdmin) After=network-online.target mariadb.service Wants=network-online.target [Service] Type=simple User=fivem Group=fivem WorkingDirectory=/home/fivem/server ExecStart=/bin/bash /home/fivem/server/run.sh Restart=on-failure RestartSec=10 # Optional txAdmin settings, see the txAdmin env-config docs # Environment=TXHOST_TXA_PORT=40120 [Install] WantedBy=multi-user.target ``` Enable and start it: ```bash sudo systemctl daemon-reload sudo systemctl enable --now fivem sudo systemctl status fivem journalctl -u fivem -f # follow the console output ``` txAdmin still restarts FXServer itself when it crashes. systemd restarts txAdmin if the whole process dies, and starts everything on boot. In txAdmin **Settings > FXServer**, enable starting the server when txAdmin starts, so a reboot brings the game server back without you logging in. > [!NOTE] > With systemd you do not have an interactive console. Use txAdmin's **Live Console** page to type server commands. ## 7. MariaDB (for frameworks) ```bash sudo apt install -y mariadb-server sudo mariadb-secure-installation ``` Then open the MariaDB shell with `sudo mariadb` and create a database user for FiveM instead of using `root`: ```sql CREATE USER 'fivem'@'localhost' IDENTIFIED BY 'a-long-random-password'; GRANT ALL PRIVILEGES ON *.* TO 'fivem'@'localhost'; FLUSH PRIVILEGES; EXIT; ``` `GRANT ALL ON *.*` lets the txAdmin deployer create the database for you. After deploying you can tighten it to the one database (`GRANT ALL ON yourdb.* ...`). Keep MariaDB bound to `127.0.0.1` (the default on Debian and Ubuntu) and never open port 3306 in the firewall. More in [Database setup](/docs/server-setup/database). ## Linux gotchas - **File names are case sensitive.** `ensure qb-Core` will not find `qb-core`. Stream files referenced in metas must match their exact case too. - **Line endings.** Scripts edited on Windows work fine, but shell scripts (`.sh`) with Windows line endings fail with `bad interpreter`. Convert with `sed -i 's/\r$//' script.sh`. - **Permissions.** If you upload files as `root` (for example with SFTP as root), the `fivem` user cannot read them. Fix with `sudo chown -R fivem:fivem /home/fivem/server`. - **Paths with spaces or brackets.** Quote them in the shell: `cd "resources/[local]"`. ## The vanilla way (no txAdmin) From the official guide: ```bash git clone https://github.com/citizenfx/cfx-server-data.git ~/server-data cd ~/server-data nano server.cfg # same content as the Windows vanilla example bash ~/server/run.sh +exec server.cfg ``` You must start it from inside the data folder, with `+exec server.cfg`. See the [Windows guide](/docs/server-setup/windows#the-vanilla-way-no-txadmin) for a minimal `server.cfg`. ## Updating later Stop the server, move the old `alpine` folder and `run.sh` aside, extract the new `fx.tar.xz` in the same place, start again. Your `txData` is untouched. The full routine, including rollback, is in [Updating artifacts safely](/docs/server-setup/updating-artifacts). _Last updated: 2026-09-22_ --- ## server.cfg explained line by line URL: https://fivemad.com/docs/server-setup/server-cfg What every common server.cfg line does: endpoints, hostname, tags, license key, slots, game build, OneSync, ensure order, convars, ACE permissions and splitting configs. `server.cfg` is not a special format. It is a list of **server console commands** that FXServer runs from top to bottom when it starts, exactly as if you typed them into the console. That explains most of its behaviour: order matters, a typo is an "unknown command", and anything you can type in the console you can put in the file. > [!TIP] > Don't want to write it by hand? The [server.cfg Generator](/tools/server-cfg-generator) builds a complete file with hostname, slots, OneSync, endpoints, tags, resources and ACE permissions. ## A complete example This is a sensible config for a small public server without a framework. The sections below explain each part. ```cfg title="server.cfg" ## Network endpoint_add_tcp "0.0.0.0:30120" endpoint_add_udp "0.0.0.0:30120" ## Server list info sv_hostname "^2My Server ^7| Custom cars | Discord in desc" sets sv_projectName "My Server" sets sv_projectDesc "A small freeroam server with custom cars and friendly admins." sets tags "freeroam, drift, cars" sets locale "en-US" load_server_icon myLogo.png sets banner_detail "https://example.com/banner_detail.png" sets banner_connecting "https://example.com/banner_connecting.png" ## Core settings sv_licenseKey "cfxk_xxxxxxxxxxxxxxxxxxxx_xxxxxx" sv_maxclients 32 sv_enforceGameBuild 3751 set onesync on sv_endpointPrivacy true sv_scriptHookAllowed 0 set steam_webApiKey "none" set resources_useSystemChat true ## Resources (order matters) ensure mapmanager ensure chat ensure spawnmanager ensure basic-gamemode ensure hardcap ensure [local] ## Permissions add_ace group.admin command allow add_ace group.admin command.quit deny add_principal identifier.fivem:123456 group.admin ``` ## Network: endpoints ```cfg endpoint_add_tcp "0.0.0.0:30120" endpoint_add_udp "0.0.0.0:30120" ``` These bind the server to port `30120` on every network interface, TCP for HTTP (connection info, downloads) and UDP for game traffic. Both lines are needed. Change `30120` to run a second server on the same machine (for example `30121`). When txAdmin deploys a server, it writes these lines for you (the `{{serverEndpoints}}` placeholder in recipes), and the `TXHOST_FXS_PORT` variable can force a port. See [Ports and networking](/docs/server-setup/ports-and-networking). ## Server list info | Line | What it does | | --- | --- | | `sv_hostname "..."` | The name in the server browser. Supports colour codes like `^1` red, `^2` green, `^7` white. Preview them with [Draw Text Colors](/tools/text-colors). | | `sets sv_projectName "..."` | Your community's name. Shown in the server browser details. Required for proper listing. | | `sets sv_projectDesc "..."` | One sentence describing the server. Also required for proper listing. | | `sets tags "a, b, c"` | Comma separated tags for server browser search. | | `sets locale "en-US"` | The server's main language. The default recipes use `root-AQ`, which means "not set", so change it. | | `load_server_icon file.png` | Server icon, a **96x96 PNG** in the server data folder. | | `sets banner_detail` / `sets banner_connecting` | Image URLs for the server detail page and the connecting screen. | `set` stores a convar, `sets` also publishes it in the server info (so the server browser can show it), and `setr` replicates it to clients so client scripts can read it with `GetConvar`. Use `setr` for things like `voice_useNativeAudio` that client code needs. ## Core settings ### `sv_licenseKey` Your key from [portal.cfx.re](https://portal.cfx.re). Without a valid key the server will not start. Never paste it in screenshots or public repos. If it leaks, regenerate it on the Portal. ### `sv_maxclients` Maximum players, 1 to 2048. Up to **48** is free. Anything above 48 needs a Cfx.re Element Club tier (Argentum or higher) on the account that owns the key. ### `sv_enforceGameBuild` Forces clients to run a specific GTA V update, which unlocks that update's vehicles, clothing, weapons and map changes. It can only be set at startup. Valid builds for FiveM include: | Build | DLC | | --- | --- | | 2699 | The Criminal Enterprises | | 2802 | Los Santos Drug Wars | | 2944 | San Andreas Mercenaries | | 3095 | The Chop Shop | | 3258 | Bottom Dollar Bounties | | 3407 | Agents of Sabotage | | 3570 | Money Fronts | | 3751 | A Safehouse in the Hills | | 3889 | The Kortz Center Heist | Every build includes everything before it. The txAdmin default recipes currently set `3751`. Pick the build your resources support: some older scripts and MLOs break on the newest build, and players have to download the matching game data the first time they join. You can check a build's content in the [Model & Hash Browser](/tools/model-hash-browser) (vehicles, peds and weapons). > [!NOTE] > FiveM for GTA V Enhanced only supports the latest game build, so this setting works differently there. ### `onesync` ```cfg set onesync on ``` Turns on OneSync, the server side sync. Values are `on`, `legacy` (compatibility mode, not recommended) and `off`. Every current framework needs `on`, and you need it for more than 32 players, routing buckets, server side entity creation and state bags on entities. Use `set onesync on` in the cfg (or `+set onesync on` on the command line). txAdmin also exposes it in its settings. ### Privacy and client mods | Line | Meaning | | --- | --- | | `sv_endpointPrivacy true` | Hides player IP addresses in the public player list output. Turn it on. | | `sv_scriptHookAllowed 0` | Blocks clients with ScriptHookV (singleplayer mod menus). Default is off, keep it off. | | `sv_pureLevel 1` | Blocks modified game files except audio and known graphics mods. `2` blocks all modified files. Leave it out to allow anything. | | `sv_entityLockdown strict` | Clients cannot create networked entities, only the server can. Great against cheaters, but many older scripts spawn things client side and will break. Test first. | ### Steam and chat - `set steam_webApiKey "none"` disables Steam identifiers. If your scripts need `steam:` identifiers, put a key from [steamcommunity.com/dev/apikey](https://steamcommunity.com/dev/apikey). - `set resources_useSystemChat true` makes `ensure chat` use the chat resource built into the artifact instead of an old copy in your resources folder. The default txAdmin recipe sets this. ## Resources: `ensure`, `start` and order ```cfg ensure mapmanager ensure chat ensure spawnmanager ensure [local] ``` - `ensure name` starts a resource, or restarts it if it is already running. It is the one you want in `server.cfg`. - `start name` starts it only if it is stopped. `stop name` stops it. `restart name` restarts a running one. - `ensure [folder]` starts every resource inside a bracketed category folder. - `name` is the **folder name**, not what the manifest says. **Order matters.** Resources start in the order of the lines. Libraries and databases first, then the framework, then everything that depends on it: ```cfg ensure oxmysql ensure ox_lib ensure qbx_core # or qb-core, es_extended ensure ox_target ensure ox_inventory ensure [qbx] ensure [standalone] ensure [local] # your own stuff last ``` If a resource lists `dependencies` in its manifest, FXServer starts those first anyway, but explicit order saves you confusing errors. More in [Installing resources](/docs/resources). ## Splitting the config with `exec` Big servers split their config. `exec` runs another file: ```cfg exec permissions.cfg exec resources.cfg exec @vMenu/config/permissions.cfg ``` Paths are relative to the server data folder, and `@resource/path` points into a resource. The Qbox recipe, for example, splits settings into `permissions.cfg`, `ox.cfg`, `voice.cfg` and `misc.cfg`. A common trick is a `secrets.cfg` that holds the license key and database password and is **not** in git: ```cfg title="secrets.cfg" sv_licenseKey "cfxk_..." set mysql_connection_string "mysql://fivem:password@localhost/fivem?charset=utf8mb4" ``` ```cfg title="server.cfg" exec secrets.cfg ``` ## Database connection Frameworks use `oxmysql`, which reads one convar: ```cfg set mysql_connection_string "mysql://user:password@localhost:3306/database?charset=utf8mb4" ``` The key value form `"user=root;password=12345;host=localhost;port=3306;database=fivem"` also works. Avoid special characters like `@ : / ? # & =` in the password. See [Database setup](/docs/server-setup/database). ## Permissions (ACE) ```cfg add_ace group.admin command allow # admins can run any command add_ace group.admin command.quit deny # except quit add_principal identifier.fivem:123456 group.admin add_principal identifier.discord:111111111111111111 group.admin ``` - `add_ace ` creates a rule. - `add_principal ` puts a player (or group) into a group. - Identifiers: `identifier.fivem:` (Cfx.re account ID), `identifier.license:`, `identifier.discord:`, `identifier.steam:`. The txAdmin recipes add `{{addPrincipalsMaster}}`, which the deployer replaces with your own identifiers, so the master admin gets `group.admin` automatically. More in [Security basics](/docs/server-setup/security). ## Listing, private servers and proxies | Line | Use | | --- | --- | | `sv_master1 ""` | Makes the server private: it will not appear in the server list. Leave it commented out (`#sv_master1 ""`) for a public server. | | `sv_lan true` | LAN only server. | | `sv_listingIpOverride "1.2.3.4"` | Overrides the IP sent to the server list, for NAT setups. | | `sv_forceIndirectListing true` | Don't advertise the server with its real IP. | | `sv_listingHostOverride "play.example.com"` | Overrides the host name sent to the list, for proxy setups. | | `sv_proxyIPRanges "a.b.c.d/24"` | IP ranges of your own proxies, so the real player IP is used. | These are advanced. See [Ports and networking](/docs/server-setup/ports-and-networking) before touching them. ## Things that don't belong in server.cfg - `rcon_password`: RCON is off when unset, and txAdmin's live console replaces it. Leave it unset. - Old lines copied from ancient tutorials, like `start essentialmode`, or a `sv_master1 ""` left over from a private test server. - Anything with your password if the file is shared or in git: move it to `secrets.cfg`. ## After editing Changes to `server.cfg` apply on the next server restart. In txAdmin you can edit the file under **CFG Editor** and restart from the dashboard. To pick up a new resource without a restart, type `refresh` then `ensure name` in the live console. _Last updated: 2026-09-22_ --- ## Updating FXServer artifacts safely URL: https://fivemad.com/docs/server-setup/updating-artifacts How to pick a server artifact, avoid broken builds, update on Windows and Linux without losing data, test first, and roll back when something goes wrong. An **artifact** is one build of FXServer. Cfx.re publishes new builds all the time, and some of them break things. Updating is easy, updating *safely* takes five extra minutes and saves you a broken Saturday night. [How to update FiveM Server Artifacts / TXAdmin (HighwayTrooper)](https://www.youtube.com/watch?v=UZXnK8IjT20) (YouTube video) ## Which build to use | Branch | What it means | Use it for | | --- | --- | --- | | **Recommended** | The build Cfx.re currently recommends for production. | Your live server. | | **Latest** | The newest build that passed CI. May contain fresh bugs. | Testing new features, dev servers. | | **Optional / other** | Older or newer numbered builds in the list. | Rolling back, or when a resource requires a minimum build. | Download from the official [server download page](https://docs.fivem.net/docs/server-download/) or directly: - Windows: `https://runtime.fivem.net/artifacts/fivem/build_server_windows/master/` - Linux: `https://runtime.fivem.net/artifacts/fivem/build_proot_linux/master/` Before you update, open our [Artifacts page](/artifacts). It shows the current recommended build, the full list of builds, and flags the ones the community has reported as **broken** (crashes, broken OneSync, broken txAdmin and so on). It is based on the JG Scripts artifacts database. > [!IMPORTANT] > Old artifacts stop working. Cfx.re blocks very old builds from the server list and eventually from starting at all, and new game builds need new artifacts. "Never update" is not an option, but "update carefully" is. ## Why updates break things - A resource uses a native or behaviour that changed. - A build has a regression (it happens, that's why the broken list exists). - The new build bumps the bundled **txAdmin** version and something in its config changed. - Resources that require a minimum build (`dependency '/server:XXXX'` in their manifest) or newer runtimes (for example `node_version '22'`) only work on newer builds, and the other way around. ## The safe routine ### 1. Read before you download - Check the build on [/artifacts](/artifacts). - Skim the Announcements category on [forum.cfx.re](https://forum.cfx.re) and the txAdmin Discord for anything about the build. ### 2. Back up - Your **server data folder** (`server.cfg`, `resources`) is not touched by an update, but back it up anyway, or better, keep it in git. - **txData** (txAdmin accounts, bans, warns, player database, settings). Copy the whole folder. - Your **database**. Dump it with HeidiSQL (Tools > Export database as SQL) or on Linux: ```bash mysqldump -u fivem -p --single-transaction yourdb > backup-$(date +%F).sql ``` ### 3. Test on a copy (for big servers) Run the new artifact against a copy of your server data on another port with `TXHOST_FXS_PORT` and a separate `TXHOST_DATA_PATH`, join it, and click through the core features: character select, inventory, a job, a vehicle shop, the phone. Five minutes of testing finds most breakage. ### 4. Swap the artifact **Windows** 1. Stop the server in txAdmin and close the FXServer window. 2. Rename `C:\FXServer\server` to `C:\FXServer\server-old`. 3. Extract the new `server.7z` to a fresh `C:\FXServer\server`. 4. Start `FXServer.exe` (or your `start.bat` / scheduled task) again. **Linux** ```bash sudo systemctl stop fivem # or stop it in tmux cd /home/fivem mv server server-old mkdir server && cd server wget https://runtime.fivem.net/artifacts/fivem/build_proot_linux/master/XXXXX-/fx.tar.xz tar xf fx.tar.xz && rm fx.tar.xz # if your txData lived inside the old folder, move it back: mv ../server-old/txData ./ 2>/dev/null sudo systemctl start fivem ``` > [!WARNING] > On Linux the default `txData` location is **next to `run.sh`**, so it sits inside the artifact folder. Move it back after swapping (as above), or set `TXHOST_DATA_PATH` to a folder outside the artifact so this never bites you. Never extract a new artifact **over** the old one. Leftover files from the previous build cause strange errors. ### 5. Check it - The txAdmin dashboard shows the new FXServer version. - The live console has no new red errors during startup. - Join and test the same things as in step 3. - Look at txAdmin's performance chart after an hour with players. ### 6. Roll back if needed Stop the server, delete the new artifact folder, rename `server-old` back to `server`, start. That's why you kept it. Once the new build has been fine for a few days, delete `server-old`. ## Updating txAdmin txAdmin is part of the artifact. There is nothing separate to download: when you update FXServer, you update txAdmin. See [Updating txAdmin and FXServer](/docs/txadmin/updating). ## Game build updates When Rockstar ships a GTA V update, FiveM adds the new build to `sv_enforceGameBuild`. You usually need a recent artifact to use it. Update the artifact first, then change `sv_enforceGameBuild` in [server.cfg](/docs/server-setup/server-cfg), then restart. Players download the new game data on their next join. ## Quick checklist - [ ] Build checked on [/artifacts](/artifacts), not on the broken list. - [ ] txData, server data and database backed up. - [ ] Old artifact folder renamed, not overwritten. - [ ] txData location checked (Linux). - [ ] Server starts cleanly, core features tested. - [ ] Old folder kept for a few days. _Last updated: 2026-09-22_ --- ## Ports and networking URL: https://fivemad.com/docs/server-setup/ports-and-networking Which ports FiveM and txAdmin use, how to port forward at home, why a server is missing from the list, multiple servers on one IP, proxies and the listing convars. Most "my friends can't join" and "my server isn't in the list" problems are network problems, not FiveM problems. This page covers the ports, home port forwarding, the server list and the more advanced proxy options. [How To Port Forward A FiveM Server! (HTNetwork)](https://www.youtube.com/watch?v=Y0jLMc_zEDw) (YouTube video) ## The ports | Port | Protocol | Used by | Who needs to reach it | | --- | --- | --- | --- | | `30120` | **TCP and UDP** | FXServer: TCP for HTTP (info, file downloads, connection handshake), UDP for game traffic | Every player | | `40120` | TCP | txAdmin web panel | Only you and your admins | | `3306` | TCP | MariaDB / MySQL | Only the server itself. Never open it to the internet. | Both TCP **and** UDP must be open on `30120`. Opening only TCP gives the classic symptom: the server shows up and players can see the player count, but joining hangs or times out. You can change the game port with the `endpoint_add_tcp` / `endpoint_add_udp` lines in [server.cfg](/docs/server-setup/server-cfg), and the txAdmin port with the `TXHOST_TXA_PORT` environment variable. txAdmin refuses to use `30120` for its panel, and the game port cannot be `40120`, to avoid mixing them up. ## Hosting from home: port forwarding If the server runs on a PC at home, your router must forward the port to that PC. 1. Give the server PC a fixed local IP (a DHCP reservation in the router, or a static IP in Windows), for example `192.168.1.50`. 2. In the router's admin page, find **Port Forwarding** (sometimes "Virtual Server" or "NAT"). 3. Add a rule: external port `30120`, internal port `30120`, protocol **TCP and UDP** (or two rules), target `192.168.1.50`. 4. Allow FXServer in **Windows Defender Firewall** (Windows asks the first time you run it, allow both private and public if you're unsure, or add inbound rules for port 30120 TCP and UDP). 5. Test from outside: ask a friend to `connect YOUR_PUBLIC_IP:30120` in the F8 console, or use a port checker like canyouseeme.org while the server runs. > [!WARNING] > Some ISPs use **CGNAT**: your router doesn't have a real public IP, so port forwarding can't work. If the WAN IP in your router differs from what "what is my IP" sites show, you are probably behind CGNAT. Ask your ISP for a public IP, or rent a VPS. Don't forward `40120` at home unless you really need remote access, and if you do, use strong passwords and 2FA. ## Why isn't my server in the list? Straight from the official server FAQ, plus experience: 1. **Ports.** Bad port forwarding or firewall rules are the usual cause. Test with direct connect first: `connect IP:30120` in F8. If that fails, it's the network. 2. **Private mode.** Make sure `sv_master1 ""` is commented out (`#sv_master1 ""`) or not present. 3. **Project info.** Set `sets sv_projectName` and `sets sv_projectDesc`. 4. **Time.** It can take **up to 8 minutes** after start for a server to appear. 5. **Blacklisted IP.** Some hosting ranges are blocked from the platform. Check with the [Cfx Blacklist Checker](/tools/cfx-blacklist-checker). 6. **Outdated artifact.** Very old builds are refused. Update, see [Updating artifacts safely](/docs/server-setup/updating-artifacts). To see what the world sees, enter your IP:port or join code in the [Server Status Checker](/tools/server-status-checker). It shows players, build, resources and map as reported by your server. ## Join links Every listed server gets a `cfx.re/join/xxxxxx` code tied to its license key. You can share it instead of an IP, and it keeps working if the IP changes. Find it in the server browser details, in txAdmin, or in the Discord status embed (`{{serverJoinUrl}}`). To show your live status on a website or Discord, use a [Server Status Badge](/tools/server-uptime-badge). ## Running more than one server on one machine Give each server its own: - **game port**: `endpoint_add_tcp "0.0.0.0:30121"` and `endpoint_add_udp "0.0.0.0:30121"`, - **license key** (one key per server), - **txData** (`TXHOST_DATA_PATH`) and **txAdmin port** (`TXHOST_TXA_PORT=40121`), - **database**. txAdmin's docs strongly recommend separate txData folders per server, otherwise `admins.json` conflicts. ```bat title="start-dev.bat (Windows example from the txAdmin docs pattern)" @echo off set TXHOST_DATA_PATH=C:\FXServer\txData-dev set TXHOST_TXA_PORT=40121 set TXHOST_FXS_PORT=30121 set TXHOST_MAX_SLOTS=8 C:\FXServer\server\FXServer.exe ``` ## OneSync and networking OneSync (`set onesync on`) is the server side sync model: the server tracks all entities and decides which client sees what, culling entities to a radius (424 units by default) around each player. It lowers bandwidth per client compared to the old peer to peer model, allows up to 2048 slots with the right tier, and enables routing buckets and entity state bags. Every modern framework expects it. See [State bags and OneSync](/docs/development/state-bags-onesync) for what it means for scripts. ## Proxies, DDoS protection and Cloudflare Large servers often put a proxy or DDoS filter in front of FXServer so the real IP stays hidden. This is advanced and easy to get wrong. The relevant convars (from the official server commands reference): | Convar | What it does | | --- | --- | | `sv_forceIndirectListing true` | Prevents the server from being advertised with its real IP. | | `sv_listingIpOverride "1.2.3.4"` | Overrides the IP sent to the server list (useful behind NAT or a proxy). | | `sv_listingHostOverride "play.example.com"` | Overrides the host name sent to the list (useful behind a proxy). | | `sv_proxyIPRanges "1.2.3.0/24 5.6.7.0/24"` | Space separated CIDR ranges of your own proxies, so FXServer trusts forwarded client IPs from them. | | `sv_requestParanoia 0-3` | Extra checks against proxy based HTTP floods. | | `sv_endpointPrivacy true` | Hides player IPs in public output. | Some things to know before you try: - **Cloudflare's normal (orange cloud) proxy only handles HTTP(S) traffic**, not the UDP game traffic, so you can't just point a proxied DNS record at FXServer. Setups that proxy FiveM traffic use a proxy that supports both TCP and UDP (Cloudflare Spectrum on paid plans, or a dedicated game DDoS provider), or a separate file server/CDN for downloads. - If you set up a proxy without `sv_proxyIPRanges`, every player appears to come from the proxy's IP, which breaks IP bans and some anticheats. - Test with a small group first. A broken proxy config makes the server invisible or unjoinable. For the **txAdmin panel**, the txAdmin team's advice is not to expose it with SSL inside txAdmin but to put a reverse proxy (nginx, Caddy) or a Cloudflare Tunnel in front of it if you want HTTPS. ## Quick diagnosis | Symptom | Likely cause | | --- | --- | | Nobody can connect, not even with direct connect | Port closed, wrong IP, firewall, CGNAT | | Server in list, joining times out at "handshaking" or "connecting" | UDP 30120 blocked | | Works on LAN (`192.168.x.x`), not from outside | Router port forward or ISP | | Direct connect works, not in list | `sv_master1`, missing project name/desc, wait 8 minutes, blacklisted IP | | Everyone shows the same IP in txAdmin | Proxy without `sv_proxyIPRanges` | _Last updated: 2026-09-22_ --- ## Database setup: MariaDB, HeidiSQL and oxmysql URL: https://fivemad.com/docs/server-setup/database Install MariaDB on Windows or Linux, manage it with HeidiSQL, connect FiveM with oxmysql and mysql_connection_string, import SQL files and back up your data. Frameworks like QBCore, Qbox and ESX store characters, money, vehicles and inventories in a SQL database. FiveM talks to it through a resource, almost always **oxmysql**. A plain vMenu server does not need any of this. [How to Setup a Database for Your FiveM Server (TraseDev)](https://www.youtube.com/watch?v=lIlFkSaNACU) (YouTube video) ## Use MariaDB, not XAMPP - **MariaDB** is what the frameworks target. The oxmysql docs say MariaDB is "highly recommended for compatibility and improved performance" over MySQL 8 (which has reserved keyword and default value differences that break some scripts). - **Qbox** requires at least MariaDB 10.9 and recommends a current LTS release. The **ESX** docs say to use MariaDB only. - **XAMPP** bundles an old MariaDB with a web server you don't need. Both the ESX and Qbox docs tell you not to use it. If you're on XAMPP now, dump your database and move it to a real MariaDB install. ## Install on Windows 1. Download the MSI from [mariadb.org/download](https://mariadb.org/download/) (pick the current LTS). 2. Run it. Set a **root password** and keep "Install as service" checked. Leave "Enable access from remote machines for root" **unchecked**. 3. The Windows installer includes **HeidiSQL**, a free GUI for the database. Keep it selected. 4. Default port is `3306`. Keep it unless something else uses it. ## Install on Linux ```bash sudo apt install -y mariadb-server sudo mariadb-secure-installation ``` Then create a dedicated user in the MariaDB shell (`sudo mariadb`): ```sql CREATE USER 'fivem'@'localhost' IDENTIFIED BY 'a-long-random-password'; GRANT ALL PRIVILEGES ON *.* TO 'fivem'@'localhost'; FLUSH PRIVILEGES; ``` The broad grant lets the txAdmin deployer create a database. After deploying, you can restrict it to one database: `GRANT ALL PRIVILEGES ON qbox_4f2a.* TO 'fivem'@'localhost';` and revoke the rest. Manage it from your PC with HeidiSQL over an **SSH tunnel** (HeidiSQL supports "MariaDB or MySQL (SSH tunnel)") instead of opening port 3306. ## HeidiSQL basics 1. Open HeidiSQL, click **New**, network type **MariaDB or MySQL (TCP/IP)**, host `127.0.0.1`, user `root` (or `fivem`), your password, port `3306`. Save and **Open**. 2. **Create a database**: right click the connection > **Create new > Database**. Collation `utf8mb4_unicode_ci` or `utf8mb4_general_ci`. 3. **Import a `.sql` file** (a resource's install SQL): select the database, then **File > Run SQL file...** and pick the file. 4. **Browse data**: click a table, then the **Data** tab. Handy for checking a player's money or job while testing. 5. **Back up**: right click the database > **Export database as SQL**, tick "Create" for tables and "Insert" for data. ## Let txAdmin create it When you deploy a framework recipe in txAdmin, the deployer asks for host, port, user and password and **creates the database for you** if you leave the name empty (it generates a random name like `QBCore_A1B2C3`). It also imports the framework's SQL and writes the connection string into `server.cfg` through the `{{dbConnectionString}}` placeholder. That's the easiest path. ## Connect with oxmysql oxmysql reads one convar. Put it in `server.cfg` (or better, in a `secrets.cfg` you `exec`) **before** `ensure oxmysql`: ```cfg title="server.cfg" set mysql_connection_string "mysql://fivem:password@localhost:3306/qbox_4f2a?charset=utf8mb4" ensure oxmysql ``` Both formats from the oxmysql docs work: ```cfg # URI set mysql_connection_string "mysql://root:12345@localhost:3306/fivem" # key=value set mysql_connection_string "user=root;password=12345;host=localhost;port=3306;database=fivem" ``` > [!WARNING] > Don't use these characters in the database password: `; , / ? : @ & = + $ #`. They break the connection string parsing. Use a long password made of letters and numbers instead. Useful oxmysql convars: ```cfg set mysql_slow_query_warning 150 # warn about queries slower than 150 ms set mysql_debug false # true, or a list like ["ox_inventory"] to log queries ``` ## Using the database in your own resource Add oxmysql's library to your manifest: ```lua title="fxmanifest.lua" server_scripts { '@oxmysql/lib/MySQL.lua', 'server/main.lua', } dependency 'oxmysql' ``` Then query from server scripts. Always use placeholders (`?`) for values, never string concatenation: ```lua title="server/main.lua" -- one row local row = MySQL.single.await('SELECT money FROM my_accounts WHERE identifier = ?', { identifier }) -- one value local count = MySQL.scalar.await('SELECT COUNT(*) FROM my_accounts') -- many rows local rows = MySQL.query.await('SELECT * FROM my_accounts WHERE money > ?', { 1000 }) -- insert, returns the new id local id = MySQL.insert.await('INSERT INTO my_accounts (identifier, money) VALUES (?, ?)', { identifier, 500 }) -- update, returns affected rows local changed = MySQL.update.await('UPDATE my_accounts SET money = money + ? WHERE identifier = ?', { 250, identifier }) ``` > [!CAUTION] > Never build SQL from strings a client sent you: `'... WHERE name = "' .. name .. '"'` is an SQL injection waiting to happen. Placeholders escape values for you. Database code only runs on the **server**. Clients must never talk to the database directly. They ask the server with an event or callback, and the server checks and queries. See [Client, server and events](/docs/development/client-server-events). ## Backups Set these up before you have players, not after the first disaster. **Windows**: a scheduled task that runs `mariadb-dump` (or `mysqldump`, both ship with MariaDB) every night: ```bat title="backup-db.bat" @echo off set STAMP=%DATE:~-4%-%DATE:~3,2%-%DATE:~0,2% "C:\Program Files\MariaDB 11.4\bin\mariadb-dump.exe" -u root -pYOURPASSWORD --single-transaction qbox_4f2a > C:\Backups\db-%STAMP%.sql ``` Adjust the MariaDB folder and date format to your system. **Linux**: a cron job for the `fivem` user: ```bash crontab -e # every night at 04:30, keep 14 days 30 4 * * * mariadb-dump --single-transaction qbox_4f2a | gzip > /home/fivem/backups/db-$(date +\%F).sql.gz && find /home/fivem/backups -name 'db-*.sql.gz' -mtime +14 -delete ``` Put credentials in `~/.my.cnf` (mode 600) so they don't appear in the crontab: ```ini title="~/.my.cnf" [client] user=fivem password=a-long-random-password ``` Copy backups **off the machine** too (another server, object storage). A backup on the same disk doesn't help when the disk dies. ## Common database errors | Error / symptom | Fix | | --- | --- | | `ECONNREFUSED 127.0.0.1:3306` | MariaDB isn't running, or it's on another port. Start the service. | | `ER_ACCESS_DENIED_ERROR` | Wrong user or password in `mysql_connection_string`, or the user has no rights on that database. | | `ER_BAD_DB_ERROR: Unknown database` | The database name in the string doesn't exist. Create it or fix the name. | | `ER_NO_SUCH_TABLE` | You didn't import the resource's `.sql` file. | | Emojis or special names turn into `????` | Use `utf8mb4` for the database and add `?charset=utf8mb4` to the URI. | | Framework loads, but nothing saves | oxmysql started after the framework. Put `ensure oxmysql` first. | Next: [Common errors and fixes](/docs/server-setup/common-errors). _Last updated: 2026-09-22_ --- ## Common server errors and fixes URL: https://fivemad.com/docs/server-setup/common-errors Fixes for the errors every FiveM server owner hits: license key, resources that won't load, server not in list, game build and pure mode, oversized assets, escrow and SQL. Start every diagnosis in the same place: the **server console** (txAdmin > Live Console) for server errors, and the **F8 console** in the game for client errors. Scroll up to the **first** red line. Later errors are often just a result of the first one. The messages below are paraphrased where their exact wording changes between builds. Search the console for the key words. ## License key problems **Symptoms:** the server stops right after starting and mentions the license key, "invalid", "failed to verify" or a missing `sv_licenseKey`. - Check the key is on its own line: `sv_licenseKey "cfxk_..."` with no extra spaces or quotes inside. - Make sure it is not commented out and that no later `exec`'d file overrides it with an old key. - Each server needs its **own** key. Two servers with one key fight each other. - If you pasted the key into a public place, it may have been abused. **Regenerate** it on [portal.cfx.re](https://portal.cfx.re) and update your config. - On a VPS, a system clock that is far off can break verification. The txAdmin team has a short video on syncing the Windows VPS clock, linked in the [video archive](/docs/videos). ## "Couldn't find resource" / "Couldn't start resource" **Symptoms:** `Couldn't find resource myresource.` or a failed start for a resource you just added. 1. **Folder name.** `ensure` uses the folder name. `ensure my-car` does not find `My-Car` on Linux (case sensitive) and does not find `my-car-main` (GitHub zip downloads add `-main` or `-master`, rename the folder). 2. **Nested folder.** Unzipping often gives `resources/[local]/mycar/mycar/fxmanifest.lua`. The manifest must be directly inside the folder you ensure. 3. **No manifest.** The folder needs `fxmanifest.lua` (or the ancient `__resource.lua`). Generate a correct one with the [fxmanifest Generator](/tools/fxmanifest-generator). 4. **Wrong working directory.** Starting FXServer from the wrong folder (vanilla setups) means it can't see `resources` at all. Start it from your server data folder. 5. **Not refreshed.** Added the folder while the server runs? Type `refresh`, then `ensure name`. ## Manifest and script errors **Symptoms:** `Couldn't load resource x` followed by a Lua error in `fxmanifest.lua`, or `SCRIPT ERROR: @resource/file.lua:12: ...`. - A syntax error in the manifest (missing quote or comma in a `{ }` list) stops the whole resource. The error names the line. - `SCRIPT ERROR` lines show `@resource/path:line`. Open that file at that line. Common ones: - `attempt to index a nil value (global 'QBCore')`: the framework object was never fetched, or the framework started after this resource. Fix `ensure` order. - `attempt to call a nil value (field 'xyz')`: calling an export or function that doesn't exist (wrong resource name, wrong version). - `No such export xyz in resource abc`: the resource isn't started, has another name, or doesn't export that function in your version. - `Could not find dependency x for resource y`: install and `ensure` the dependency first. More on reading errors in [Debugging](/docs/development/debugging). ## Server not in the server list 1. Test direct connect: `connect IP:30120` in F8. If it fails, it's ports or firewall, see [Ports and networking](/docs/server-setup/ports-and-networking). 2. Remove or comment out `sv_master1 ""`. 3. Set `sets sv_projectName` and `sets sv_projectDesc`. 4. Wait up to 8 minutes after start. 5. Check the IP isn't blocked with the [Cfx Blacklist Checker](/tools/cfx-blacklist-checker). 6. Check what your server reports with the [Server Status Checker](/tools/server-status-checker). ## Players get stuck while connecting | Where it hangs | Usual cause | | --- | --- | | "Handshaking with server" | UDP 30120 blocked, or the server is under heavy load at start. | | "Downloading assets" for ages | Huge streamed packs. Shrink textures with the [YTD Optimizer](/tools/ytd-optimizer), remove unused packs, consider a file server. | | Loading screen never ends | A loadscreen with `loadscreen_manual_shutdown 'yes'` that never calls `ShutdownLoadingScreenNui()`, or a framework spawn script erroring. Check F8. | | Kicked with a timeout after joining | A client script erroring in a loop, or a resource sending huge events. Check F8 and the server console. | ## Game build mismatch **Symptoms:** players are told they need to download game data or a different build, or DLC vehicles and clothes don't appear. - `sv_enforceGameBuild` must be set at startup, in `server.cfg`, and requires a restart to change. - A build number that your artifact doesn't know yet does nothing. Update the artifact first. - DLC content (vehicles, clothes) from a newer build than the one you enforce won't spawn. Check the build in [server.cfg explained](/docs/server-setup/server-cfg#sv_enforcegamebuild). - Some old MLOs and clothing packs break on newer builds because Rockstar changed the base files. Look for an updated version from the author. ## Pure mode kicks **Symptoms:** players are refused because of modified game files. `sv_pureLevel 1` allows audio mods and known graphics mods, `sv_pureLevel 2` blocks everything modified. If legitimate players with graphics mods can't join, lower it to 1 or remove it. On FiveM for GTA V Enhanced, pure mode is always on and can't be disabled. ## Oversized assets and texture loss **Symptoms:** a console warning that an asset "uses XX MiB of physical memory" and that oversized assets can lead to streaming issues. In game: blurry or missing textures, the city not loading when you drive fast, invisible cars. - Usually a `.ytd` with 4K textures in a car or clothing pack. - Resize textures to 2048 or 1024, use DXT compression, generate mipmaps. The [YTD Optimizer](/tools/ytd-optimizer) does this for many files at once. - Check a whole vehicle resource for broken references with the [Vehicle Pack Validator](/tools/vehicle-pack-validator). - Remove packs nobody uses. Every streamed MB costs every player memory. ## Escrow errors **Symptoms:** "Failed to verify protected resource" or an escrowed resource refusing to start. - The resource was bought on a **different Cfx.re account** than the one that owns the server's license key. Escrowed assets are tied to the buying account. - Re-download it from the Cfx.re Portal. Files changed or re-zipped by hand (for example opened and saved in an editor) fail verification. Only edit the files the creator left open (usually `config.lua`). - Too old an artifact: escrow needs a reasonably recent build. - Some escrowed resources need a minimum game build or OneSync. ## Database errors See the table at the end of [Database setup](/docs/server-setup/database#common-database-errors). The top three: MariaDB not running, wrong password in `mysql_connection_string`, forgot to import the resource's `.sql`. ## Port already in use **Symptoms:** FXServer can't bind to `0.0.0.0:30120`, or txAdmin can't use 40120. Another FXServer (or an old one that didn't close) is running. Close it (Task Manager on Windows, `pkill -f FXServer` or `systemctl stop` on Linux) or use different ports for the second server. ## txAdmin says the server is not responding - A resource is blocking the main thread (an infinite loop without `Wait`, a slow synchronous query). txAdmin's **hang detection** restarts it. Find the culprit with the profiler: see [Threads and performance](/docs/development/threads-performance) and the [Profiler Analyzer](/tools/profiler-analyzer). - Server hitches in the console (`server thread hitch warning: timer interval of X milliseconds`) mean the same thing on a smaller scale. ## Still stuck? Post on [forum.cfx.re](https://forum.cfx.re) (Server Discussion) or the relevant framework Discord with: - the first red error, copied as text, - your artifact build and game build, - what you changed last, - your `server.cfg` without the license key and passwords. _Last updated: 2026-09-22_ --- ## Security basics for FiveM servers URL: https://fivemad.com/docs/server-setup/security Lock down a FiveM server: ACE permissions, txAdmin accounts and 2FA, a private database, secrets out of git, safe events, leaked resources, entity lockdown and backups. Most FiveM servers that get "hacked" are not hacked at all. Someone found an unprotected event that gives money, a leaked resource with a backdoor, an exposed database, or an admin password reused from a leaked site. This page covers the basics that stop most of it. ## 1. Accounts and the txAdmin panel - **Log in with Cfx.re** and turn on two factor authentication on your Cfx.re account (forum account settings). Every admin should do the same. - **Give each admin their own txAdmin account** (Admin Manager). Never share the master account. - **Least privilege.** txAdmin has fine grained permissions: `console.write`, `control.server`, `players.ban`, `server.cfg.editor`, `manage.admins` and more. A moderator needs `players.warn`, `players.kick`, `players.ban` and maybe `players.spectate`, not the console. See [Everyday admin](/docs/txadmin/everyday-admin#admins-and-permissions). - **Remove admins who leave**, the same day. - **Keep port 40120 private** if you can: allow it only from your IP in the firewall. If it must be public, strong passwords and 2FA are not optional. For HTTPS, put a reverse proxy (nginx, Caddy) or a Cloudflare Tunnel in front, as the txAdmin team recommends. - The txAdmin **backup password** is a real password. Make it long and unique. ## 2. ACE permissions in server.cfg FiveM's built in permission system is ACE. Keep it tight: ```cfg title="server.cfg" # a group that can use every command except quit add_ace group.admin command allow add_ace group.admin command.quit deny # a smaller group for moderators add_ace group.mod command.kick allow add_ace group.mod myresource.moderate allow # a custom permission your scripts check # people add_principal identifier.fivem:123456 group.admin add_principal identifier.discord:111111111111111111 group.mod ``` - Prefer `identifier.fivem:` (the Cfx.re account ID, visible in txAdmin) or `identifier.license:` over `identifier.ip:`, which changes and can be shared. - `add_ace resource.myresource command.stop allow` lets a resource run a command. Only give resources what they need. Some resources ask for `add_ace resource.x command allow` (everything): think twice. - In your own code, protect commands with `RegisterCommand(name, fn, true)` (restricted: requires the `command.name` ACE) or check `IsPlayerAceAllowed(source, 'myresource.admin')`. ## 3. Never trust the client This is the most important rule for anyone who writes or installs scripts. Anything a client sends can be faked by a cheater with an executor. They can trigger **any** server event you registered, with any arguments. Bad: ```lua title="server.lua (DON'T)" RegisterNetEvent('shop:giveMoney', function(amount) local player = GetPlayer(source) player.addMoney(amount) -- a cheater sends 999999999 end) ``` Better: ```lua title="server.lua" local PRICE = { bread = 5, water = 3 } RegisterNetEvent('shop:buy', function(item) local src = source local price = PRICE[item] if not price then return end -- unknown item, ignore local player = GetPlayer(src) if not player or not isNearShop(src) then return end -- check position server side if player.getMoney() < price then return end player.removeMoney(price) player.addItem(item, 1) end) ``` - Decide prices, rewards and amounts on the **server**. - Validate every argument: type, range, whether the player can do this right now (distance, job, cooldown). - Use `source` (copied into a local at the top of the handler), never a player ID sent as an argument, to know who is asking. - Rate limit events that could be spammed. More in [Client, server and events](/docs/development/client-server-events#security-never-trust-the-client). ## 4. The database - MariaDB listens on `127.0.0.1` only. **Never** open port 3306 to the internet. - Use a dedicated database user with a strong password, not `root` with an empty one. - Manage it remotely through an SSH tunnel. - Use parameterised queries (`?` placeholders) everywhere. See [Database setup](/docs/server-setup/database#using-the-database-in-your-own-resource). - Back it up every night, and keep copies off the server. ## 5. Secrets out of git and screenshots Keep your license key, database password, Discord bot tokens, Tebex secret and webhook URLs in a separate `secrets.cfg` that you `exec` from `server.cfg`, and add it to `.gitignore`: ```gitignore title=".gitignore" secrets.cfg txData/ cache/ *.log ``` If a key leaks: regenerate the license key on the Portal, change the database password, reset the bot token. Webhook URLs are secrets too: anyone with the URL can post to your channel. ## 6. What you install - **No leaked resources.** Besides breaking the platform license, leaked paid scripts are a favourite place to hide backdoors: obfuscated code that downloads and runs remote Lua, gives admin to a stranger, or empties your Tebex. - **Read what you install**, at least quickly. Red flags in Lua: `load(` or `assert(load(` with downloaded or encoded strings, `PerformHttpRequest` to unknown domains combined with `load`, long lines of escaped bytes (`\x..`), or files that are unreadable on purpose in a supposedly open resource. - Prefer well known open source resources from GitHub (see [Recommended resources](/docs/resources/recommended)) and paid ones from reputable creators who use Cfx.re escrow. - Keep them updated: security fixes land in `ox_inventory`, frameworks and txAdmin regularly. ## 7. Server settings that help ```cfg title="server.cfg" sv_scriptHookAllowed 0 # block singleplayer mod menus sv_endpointPrivacy true # hide player IPs in public output sv_entityLockdown strict # only the server may create networked entities # rcon_password is left unset, so RCON is disabled ``` - **Entity lockdown** stops a big class of cheats (spawning objects and peds). It also breaks scripts that create networked entities on the client, so test it on a dev copy. `relaxed` is a middle ground. - **`sv_filterRequestControl`** can block clients from taking control of entities they don't own, another common cheat vector. Read its modes in the [server commands reference](https://docs.fivem.net/docs/server-manual/server-commands/) before using it. - **State bags**: set `sv_stateBagStrictMode true` if your resources only set state from the server, so clients can't write to state bags. ## 8. Anticheat, realistically No anticheat is perfect, and a paid one does not fix unsafe events. In order of value: 1. Safe server side code (section 3). 2. Entity lockdown and the settings above. 3. Good logging: txAdmin's action log and server log, plus logs of money and item changes in your framework. 4. Active moderators with txAdmin. 5. Then, if you still need it, a reputable anticheat. [FiveM Scripting: How to Stop Cheaters (Twisle)](https://www.youtube.com/watch?v=FRVuFB0peU0) (YouTube video) ## 9. The machine itself - Keep the OS updated. On Linux, enable unattended security upgrades. - SSH with keys, not passwords. Disable root login over SSH. - Run FXServer as its own user, not root or Administrator. - Firewall: only 30120 TCP/UDP public, 40120 restricted, SSH restricted if possible. - Backups of `txData`, the server folder and the database, stored elsewhere. ## Quick checklist - [ ] Every admin has their own txAdmin account with only the permissions they need. - [ ] 2FA on every Cfx.re account with admin access. - [ ] 40120 restricted, 3306 closed. - [ ] Secrets in `secrets.cfg`, not in git. - [ ] No leaked or unreadable resources. - [ ] Server events validate everything and use `source`. - [ ] `sv_scriptHookAllowed 0`, `sv_endpointPrivacy true`, entity lockdown tested. - [ ] Nightly backups copied off the machine. _Last updated: 2026-09-22_ --- # txAdmin ## txAdmin overview URL: https://fivemad.com/docs/txadmin What txAdmin is and does: the recipe deployer, web panel, in-game menu, bans and warns, whitelist, scheduled restarts, Discord bot, live console and monitoring. txAdmin is the web panel and in-game admin menu for FiveM and RedM servers. It was created by tabarra in 2019, has been part of FXServer since early 2020, and is now maintained under the Cfx.re GitHub organisation ([citizenfx/txAdmin](https://github.com/citizenfx/txAdmin), MIT licensed). The project says it runs on over 29,000 servers at any given time. You don't install it. **Run FXServer without `+exec server.cfg` and txAdmin starts**, creates a `txData` folder, and serves its panel on port `40120`. ## What it does ### Deploy servers The **recipe deployer** builds a complete server from a YAML recipe: downloads resources from GitHub, creates and imports the database, writes `server.cfg`. The setup page lists "Popular Recipes" (a basic FiveM server, ESX Legacy, Qbox, QBCore and a few game modes) and accepts any recipe URL. See [Recipes explained](/docs/txadmin/recipes) and [Popular recipes](/docs/txadmin/popular-recipes). ### Run and watch the server - Start, stop and restart FXServer, and start or stop single resources. - **Auto restart** on crash or hang. - **Scheduled restarts** at fixed times, with in-game warnings 30, 15, 10, 5, 4, 3, 2 and 1 minutes before. - **Live Console** with a log file, command history and search. - **Performance chart** of server thread times against player count, plus CPU and memory use. - **Server activity log**: joins, leaves, kills, chat, explosions and custom commands. - A **CFG editor** for `server.cfg`. ### Manage players - Real time player list, player search and player info (play time, identifiers, notes). - **Warns** (players must acknowledge them in game), **kicks** and **bans**, temporary or permanent, including hardware ID bans. - **Whitelist** modes: approved license, Discord server member, Discord role, or admin only. - A self contained player database, no MySQL needed. ### In-game menu Type `/tx` (or `/txadmin`) in game to open it. It has NoClip, god mode, super jump, teleport (waypoint, coords, back), vehicle spawn, fix, delete and boost, heal, announcements, world area reset, player IDs, and player actions: go to, bring, spectate, freeze, warn, ban, DM and a few troll options. Access requires a txAdmin account linked to your Cfx.re or Discord identifier. ### Discord bot An optional bot posts a **persistent status embed** that updates every minute, and has commands to whitelist players and show player info. See [Discord bot](/docs/txadmin/discord-bot). ### Access control Login with Cfx.re or password, per admin **permissions**, and an **action log** of what every admin did. ## Pages in this section 1. [First setup and the deployer](/docs/txadmin/first-setup): from first start to a running server. 2. [Recipes explained](/docs/txadmin/recipes): the YAML format, every task action, variables. 3. [Writing your own recipe](/docs/txadmin/writing-recipes): a complete example that installs a small framework stack. 4. [Popular recipes](/docs/txadmin/popular-recipes): what the Basic Server, QBCore, Qbox and ESX Legacy recipes install. 5. [Everyday admin](/docs/txadmin/everyday-admin): players, bans, warns, whitelist, restarts, backups, console, logs, admins. 6. [Discord bot](/docs/txadmin/discord-bot): setup, status embed, whitelist. 7. [Updating txAdmin and FXServer](/docs/txadmin/updating). ## Settings that live outside the panel Since txAdmin v8, host level settings are **environment variables** named `TXHOST_*`, set before FXServer starts (in your `.bat`, `run.sh`, systemd unit or Docker env file). The ones you are most likely to need: | Variable | Default | Use | | --- | --- | --- | | `TXHOST_DATA_PATH` | Windows: folder next to the artifact folder. Linux: next to `run.sh`. | Where `txData` lives. Use one per server. | | `TXHOST_TXA_PORT` | `40120` | txAdmin web port. Cannot be 30120. | | `TXHOST_FXS_PORT` | not set | Forces the game port by rewriting `endpoint_add_*`. Cannot be 40120. | | `TXHOST_INTERFACE` | `0.0.0.0` | Interface txAdmin (and FXServer) bind to. | | `TXHOST_MAX_SLOTS` | not set | Caps `sv_maxclients`. | | `TXHOST_DEFAULT_CFXKEY` / `TXHOST_DEFAULT_DB*` | not set | Prefills the deployer, handy when you redeploy dev servers often. | The old convars `txAdminPort`, `txAdminInterface` and `txDataPath` are deprecated. Full list in the [env-config docs](https://github.com/citizenfx/txAdmin/blob/master/docs/env-config.md). ## For script developers txAdmin broadcasts server events you can listen to, named `txAdmin:events:`, for example: - `txAdmin:events:scheduledRestart` (with `secondsRemaining`), useful to save players before a restart, - `txAdmin:events:serverShuttingDown`, - `txAdmin:events:playerBanned`, `playerKicked`, `playerWarned`, `playerDirectMessage`, - `txAdmin:events:playerHealed`, which frameworks use to revive a downed player when an admin heals them, - `txAdmin:events:announcement`. ```lua title="server/main.lua" AddEventHandler('txAdmin:events:scheduledRestart', function(data) if data.secondsRemaining == 60 then print('Restart in one minute, saving everything') -- save your resource's data here end end) ``` The full list is in [events.md](https://github.com/citizenfx/txAdmin/blob/master/docs/events.md). _Last updated: 2026-09-22_ --- ## txAdmin first setup and the deployer URL: https://fivemad.com/docs/txadmin/first-setup Walk through txAdmin's first start: the PIN, linking your Cfx.re account, choosing a recipe or existing server, the deployer steps, license key, database and first launch. This page goes through txAdmin's first run screen by screen. It is the same on Windows and Linux. If you haven't downloaded an artifact yet, start with [Windows setup](/docs/server-setup/windows) or [Linux setup](/docs/server-setup/linux). [How to Create a FiveM Server with txAdmin (Alfa)](https://www.youtube.com/watch?v=FCIM7FlTA1g) (YouTube video) ## Before you click anything Have these ready: - Your **license key** from [portal.cfx.re](https://portal.cfx.re) (starts with `cfxk_`). - For a framework recipe: MariaDB running, and its **host, port, user and password**. See [Database setup](/docs/server-setup/database). - Optional: your **Discord user ID** if you want txAdmin to know it right away. ## Step 1: start FXServer and open the panel Run `FXServer.exe` (Windows) or `bash run.sh` (Linux) with no arguments. The console prints the panel address and a **PIN**: ```text [txAdmin] Use the PIN below to register: [txAdmin] 5820 [txAdmin] http://localhost:40120/ ``` Open the address. On a VPS use the server's public IP. The PIN proves you have access to the console, so nobody else who finds the page first can claim your server. ## Step 2: link your account 1. The PIN field should be filled already. Click **Link Account**. 2. Log in with your **Cfx.re** account (the forum account) and approve txAdmin. 3. Set a **backup password**. You'll use it only if Cfx.re login is down. You are now the **master account**. It can't be removed by other admins and has every permission. ## Step 3: name the server Type the name you want txAdmin to use (in the panel, Discord embed and logs). You can change it later in **Settings > General**. This is not `sv_hostname`, which lives in `server.cfg`. ## Step 4: choose how to set up You get these options: | Option | Pick it when | | --- | --- | | **Popular Recipes** (some versions say "Popular Template") | You want a fresh server from one of the listed recipes. Most people. | | **Existing Server Data** | You already have a folder with `server.cfg` and `resources` (moving a server, or a vanilla setup). | | **Remote URL Template** | You have the URL of a recipe YAML that isn't in the list. | | **Custom Template** | You want to paste or edit a recipe yourself. | ### Existing server data Point txAdmin to the folder that contains `server.cfg` and `resources`, then to the cfg file. txAdmin checks both and starts it. Nothing is downloaded. ## Step 5: pick a recipe The Popular Recipes list comes from the [txAdmin-recipes index](https://github.com/citizenfx/txAdmin-recipes). At the time of writing it includes: - **FiveM Basic Server** (Legacy and an Enhanced variant): the default Cfx resources, no framework. - **ESX Legacy**, **Qbox**, **QBCore**: roleplay frameworks. Need MariaDB. - **vMenu** (via a recipe patch), **StreetKings** (racing), **WarfareTacticsV** (RTS) and RedM's **VORP Core**. See [Popular recipes](/docs/txadmin/popular-recipes) for what each one installs. ## Step 6: choose the data location txAdmin suggests a folder inside `txData` named after the recipe with a random suffix, like `txData/QBCore_4F2A1C.base`. You can change it. The folder must be empty or not exist yet. Click **Save**. > [!NOTE] > The ESX docs point out that txAdmin will not create missing parent directories for you. If you pick a path outside `txData`, create the parent folder first. ## Step 7: the Recipe Deployer This screen shows the recipe YAML. Read it once: it tells you exactly what will be downloaded. Click **Next**. Now fill in the inputs: - **License key**: paste your `cfxk_` key. - **Database** (framework recipes only): host `localhost`, port `3306`, user, password. Leave **database name** empty to let txAdmin create one with a random name. The **delete database if it exists** option exists for redeploys, careful with it. - Some recipes ask for extra values, like a Steam Web API key (recipes with `$steamRequired`). Click **Run Recipe**. The deployer runs each task in order and shows a log. A failure stops it and shows which task failed. Common failures: | Failure | Fix | | --- | --- | | GitHub `403` / `429` on a `download_github` task | GitHub rate limited your IP. Wait a few minutes and retry. It happens more on shared hosting IPs. | | `connect_database` fails | MariaDB not running, wrong password, or the user can't create databases. | | `query_database` fails | Usually MySQL instead of MariaDB, or a very old MariaDB. Use a current MariaDB. | | Timeout on a big download | Retry. Recipes can raise `timeoutSeconds` on slow tasks. | ## Step 8: review server.cfg and start txAdmin shows the generated `server.cfg`. The recipe placeholders are already filled in: your key, `endpoint_add_*` lines, `sv_maxclients` (48 by default), and `add_principal` lines that make **your** identifiers admin. Change `sv_hostname`, `sets tags`, `sets locale` if you like, then click **Save & Run Server**. The panel switches to the **Live Console**. First boot takes longer: - The artifact caches files. - Some recipes (QBCore in particular) build resources with **yarn** on first start. Let it finish. - Framework resources run database migrations. When the console settles and shows resources started without red errors, connect with F8 > `connect localhost:30120` (or your IP). ## Step 9: first things to set 1. **Settings > FXServer**: turn on starting the server automatically when txAdmin boots. 2. **Settings > Restarter**: add scheduled restart times (for example `06:00` and `18:00`). See [Everyday admin](/docs/txadmin/everyday-admin#scheduled-restarts). 3. **Admin Manager**: add your staff with only the permissions they need. 4. **Settings > Discord Bot** if you want the status embed. See [Discord bot](/docs/txadmin/discord-bot). 5. In game, type `/tx` to check the menu works for you. ## Starting over To redeploy from scratch: stop the server, delete (or move) the server data folder, and use txAdmin's **Master Actions** page (master account only), which has an option to reset the FXServer settings and bring you back to the setup page. Keep `txData/default` if you want to keep your bans and player database. > [!TIP] > If you redeploy dev servers often, set `TXHOST_DEFAULT_CFXKEY` and the `TXHOST_DEFAULT_DB*` variables so the deployer inputs are prefilled. _Last updated: 2026-09-22_ --- ## txAdmin recipes explained URL: https://fivemad.com/docs/txadmin/recipes The anatomy of a txAdmin recipe: metadata, $engine and $onesync, context variables, every task action (download_github, unzip, move_path, query_database...) with examples. A **recipe** is a YAML file that tells txAdmin's deployer how to build a server: what to download, where to put it, which SQL to run and how to fill in `server.cfg`. Every server in the "Popular Recipes" list is just a recipe file on GitHub, and you can deploy any recipe by URL. This page is the reference, based on txAdmin's [recipe.md](https://github.com/citizenfx/txAdmin/blob/master/docs/recipe.md). To see what the listed recipes install, read [Popular recipes](/docs/txadmin/popular-recipes). To write one yourself, see [Writing your own recipe](/docs/txadmin/writing-recipes). ## A real recipe This is the official **FiveM Basic Server** recipe from [citizenfx/txAdmin-recipes](https://github.com/citizenfx/txAdmin-recipes/tree/main/default-fivem), exactly as published: ```yaml title="default-fivem/recipe.yaml" $engine: 3 $onesync: on name: FiveM Basic Server description: Recipe for the base resources required to run a minimal FiveM server. tasks: # Download default resources - action: download_github src: https://github.com/citizenfx/cfx-server-data ref: master subpath: resources dest: ./resources # Remove the old chat resource - action: remove_path path: ./resources/[gameplay]/chat # Download default server.cfg for FiveM - action: download_file url: https://raw.githubusercontent.com/citizenfx/txAdmin-recipes/refs/heads/main/default-fivem/server.cfg path: ./server.cfg ``` Three tasks: copy the `resources` folder of `cfx-server-data`, delete its old chat resource (the artifact has a built in one, enabled with `set resources_useSystemChat true`), and download a `server.cfg` template. The template uses placeholders that the deployer fills in: ```cfg title="default-fivem/server.cfg (excerpt)" sv_hostname "{{serverName}} built with {{recipeName}}!" sets sv_projectName "[{{recipeName}}] {{serverName}}" sets sv_projectDesc "{{recipeDescription}}" sv_enforceGameBuild 3751 #mp2025_02 - A Safehouse in the Hills sv_licenseKey "{{svLicense}}" sv_maxclients {{maxClients}} {{serverEndpoints}} add_ace group.admin command allow add_ace group.admin command.quit deny {{addPrincipalsMaster}} ``` ## How the deployer runs a recipe 1. It reads the metadata and checks engine version and requirements. 2. It asks the user for inputs (license key, database, extra variables). 3. It runs the **tasks** one by one, in order. **Any failure stops the whole process.** 4. Every path is **jailed** to the target folder: a recipe can't write outside it (so it can't touch your `admins.json`). 5. At the end it checks that the target folder has a `server.cfg` and a `resources` folder, and replaces `{{svLicense}}` in `server.cfg`. ## Metadata | Key | Required | Meaning | | --- | --- | --- | | `name` | recommended | Short name, under 24 characters. | | `version` | recommended | Your recipe's version. | | `author` | recommended | Short author name, under 24 characters. | | `description` | recommended | Under 256 characters. YAML multiline strings work. | | `$engine` | optional | Recipe engine version the recipe targets. Current recipes use `3`. | | `$minFxVersion` | optional | Minimum FXServer build required. | | `$onesync` | optional | OneSync value to set after deploy: `off`, `legacy` or `on`. | | `$steamRequired` | optional | `true` if the `steam_webApiKey` variable must be provided. | ## Context variables The deployer keeps a shared **context** of variables. You use them as `{{varName}}` in `replace_string` tasks and in files processed with `all_vars`. | Variable | Filled from | | --- | --- | | `deploymentID` | Short recipe name plus a hex timestamp, like `PlumeESX_BBC957`. | | `serverName` | The name entered on the setup page. | | `recipeName`, `recipeAuthor`, `recipeVersion`, `recipeDescription` | Recipe metadata. | | `dbHost`, `dbPort`, `dbUsername`, `dbPassword`, `dbName`, `dbDelete`, `dbConnectionString` | The database inputs. | | `svLicense` | The license key input. Replaced in `server.cfg` automatically at the end. | | `serverEndpoints` | The `endpoint_add_tcp/udp` lines (default `0.0.0.0:30120`, or from `TXHOST_INTERFACE` / `TXHOST_FXS_PORT`). | | `maxClients` | 48 by default, or `TXHOST_MAX_SLOTS`. | | `addPrincipalsMaster` | `add_principal` lines for the master admin's identifiers (used in `server.cfg` templates). | Define your own under `variables:`: ```yaml variables: frameworkLocale: en dbName: null # null means "let txAdmin create a database" ``` ## Task actions Every task is a list item with an `action` and its options. Every task accepts `timeoutSeconds` to raise its default timeout. Indentation matters in YAML: use spaces, not tabs. ### `download_github` Downloads a GitHub repository, optionally at a ref and only a subpath. | Option | Meaning | | --- | --- | | `src` | Repo URL or `owner/repo`. | | `ref` | Optional branch, tag or commit. Without it, txAdmin asks the GitHub API for the default branch. | | `subpath` | Optional folder inside the repo to copy. | | `dest` | Destination folder. Created if missing. | ```yaml - action: download_github src: https://github.com/citizenfx/cfx-server-data ref: 6eaa3525a6858a83546dc9c4ce621e59eae7085c subpath: resources dest: ./resources - action: download_github src: esx-framework/es_extended dest: ./resources/[esx]/es_extended ``` > [!NOTE] > Without `ref`, each download makes an extra GitHub API call. With more than ~30 downloads, users hit rate limits (401/403 errors). Set `ref` on every task in big recipes, ideally to a **commit hash** (tags can move). ### `download_file` ```yaml - action: download_file url: https://github.com/overextended/ox_lib/releases/latest/download/ox_lib.zip path: ./tmp/ox_lib.zip ``` `path` must be a file name, not a folder. ### `unzip` ```yaml - action: unzip src: ./tmp/ox_lib.zip dest: ./resources/[ox] ``` ZIP only, no `.tar` files. ### `move_path`, `copy_path`, `remove_path`, `ensure_dir` ```yaml - action: move_path src: ./tmp/cfx-server-data-master/resources dest: ./resources overwrite: true # replace dest if it exists - action: copy_path src: ./tmp/configs/ dest: ./resources/[local]/myconfig # copies the CONTENTS of a src folder; overwrite defaults to true # errorOnExist: true makes it fail instead of silently skipping when overwrite is false - action: remove_path path: ./tmp # does nothing if the path doesn't exist - action: ensure_dir path: ./resources/[local] ``` None of these accept the root path `./` as source or target. ### `write_file` ```yaml - action: write_file file: ./server.cfg append: true data: | ensure my_resource ensure another_one - action: write_file file: ./resources/[local]/myres/config.json data: | { "enabled": true } ``` Without `append`, the file is overwritten and missing folders are created. ### `replace_string` Search and replace in one file or a list of files. | `mode` | Behaviour | | --- | --- | | `template` (default) | Replaces `search` with `replace`, and `replace` can contain `{{vars}}`. | | `all_vars` | Replaces every `{{var}}` in the file(s). `search` and `replace` are ignored. | | `literal` | Plain search and replace, no variables. | ```yaml - action: replace_string file: ./server.cfg search: 'FXServer, but unconfigured' replace: '{{serverName}} built with {{recipeName}} by {{recipeAuthor}}!' - action: replace_string mode: all_vars file: - ./server.cfg - ./resources/[local]/myres/config.json ``` ### `connect_database` and `query_database` `connect_database` has no options. It uses the database inputs, and **creates the database** if `dbName` is null. It must run before any `query_database`. ```yaml - action: connect_database - action: query_database file: ./tmp/qbcore/qbcore.sql - action: query_database query: | CREATE TABLE IF NOT EXISTS `my_table` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(64) NOT NULL ); ``` Use `file` **or** `query`, never both. ### `load_vars` Loads extra context variables from a JSON file (for example one shipped in a repo you downloaded): ```yaml - action: load_vars src: ./tmp/recipe-vars.json ``` ### `waste_time` The txAdmin-recipes guidelines ask big recipes to pause with a `waste_time` task of 10 seconds every 25 `download_github` actions (50 if you set `ref`), so GitHub doesn't rate limit users. It isn't in the main recipe reference, but the official QBCore and Qbox recipes use it like this: ```yaml - action: waste_time # prevent github throttling seconds: 10 ``` ## How big recipes are organised Open the [QBCore](https://github.com/qbcore-framework/txAdminRecipe), [Qbox](https://github.com/Qbox-project/txAdminRecipe) or [ESX](https://github.com/esx-framework/ESX-recipes) recipe and you'll see the same pattern: 1. **Database first** (`connect_database`, then `query_database` with the framework SQL). It's the step most likely to fail, so failing early saves time. 2. **Download the recipe repo** itself into `./tmp`, which holds `server.cfg`, extra `.cfg` files, a logo and the SQL. 3. **Move** those files into place (`move_path` from `./tmp/...` to `./server.cfg`). 4. **Default Cfx resources** from `cfx-server-data` into `./resources/[cfx-default]`. 5. **Libraries** as release zips (`download_file` + `unzip`): oxmysql, ox_lib, ox_target, ox_inventory... 6. **Framework resources** with `download_github` into category folders like `[qb]` or `[qbx]`. 7. `remove_path` on `./tmp`. 8. `replace_string` with `all_vars` on `server.cfg` so `{{dbConnectionString}}` and friends are filled in. ## Where recipes come from - The "Popular Recipes" list comes from the index files (`indexv4.json`, `indexv5.json`...) in the [txAdmin-recipes](https://github.com/citizenfx/txAdmin-recipes) repository. [Popular recipes](/docs/txadmin/popular-recipes) walks through every recipe in it. - Any public raw URL to a `.yaml` works with **Remote URL Template**. - You can paste YAML directly with **Custom Template**. > [!WARNING] > A recipe runs downloads and SQL on your machine. Only deploy recipes from sources you trust, and read the YAML on the deployer screen before clicking Next. _Last updated: 2026-09-22_ --- ## Writing your own txAdmin recipe URL: https://fivemad.com/docs/txadmin/writing-recipes Build a txAdmin recipe step by step: an example that installs oxmysql, ox_lib, ox_target, pma-voice and a starter resource, creates a table and writes server.cfg. A recipe is the best way to make your server reproducible. Your dev server, your test server and a fresh live server can all come from the same file, and new developers on your team get a working setup in two minutes. This page builds a complete example recipe and explains each decision. The task reference is in [Recipes explained](/docs/txadmin/recipes). > [!IMPORTANT] > The recipe below is an **example** written for these docs. The resource URLs are real (they are the same ones the official Qbox and ESX recipes use), but pin versions you have tested before you rely on it. ## What we'll build A lean, framework free base for a custom game mode: - the default Cfx resources (mapmanager, spawnmanager, basic-gamemode...), - **oxmysql** (database), **ox_lib** (UI and utilities), **ox_target** (third eye interactions), - **pma-voice** (proximity voice) and **bob74_ipl** (loads GTA's online interiors), - one starter resource of our own, created by the recipe, - a database with one table, - a `server.cfg` with everything wired up. ## Plan the folder layout ```text resources/ ├─ [cfx-default]/ from citizenfx/cfx-server-data ├─ [ox]/ oxmysql, ox_lib, ox_target ├─ [standalone]/ pma-voice, bob74_ipl └─ [local]/ my_starter (our own) server.cfg ``` ## The recipe ```yaml title="my-base.yaml" $engine: 3 $onesync: on name: My Base version: 1.0.0 author: YourName description: | A lean base with oxmysql, ox_lib, ox_target, pma-voice and a starter resource. No framework. Example recipe from the fivemad docs. variables: dbName: null # let txAdmin create the database with a random name tasks: # 1. Database first: the most likely step to fail - action: connect_database - action: query_database query: | CREATE TABLE IF NOT EXISTS `player_stats` ( `license` VARCHAR(60) NOT NULL PRIMARY KEY, `playtime` INT UNSIGNED NOT NULL DEFAULT 0, `last_seen` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # 2. Default Cfx resources, minus the old chat (the artifact has a built in one) - action: download_github src: https://github.com/citizenfx/cfx-server-data ref: master subpath: resources dest: ./resources/[cfx-default] - action: remove_path path: ./resources/[cfx-default]/[gameplay]/chat # 3. Overextended libraries from their release zips - action: download_file url: https://github.com/overextended/oxmysql/releases/latest/download/oxmysql.zip path: ./tmp/oxmysql.zip - action: unzip src: ./tmp/oxmysql.zip dest: ./resources/[ox] - action: download_file url: https://github.com/overextended/ox_lib/releases/latest/download/ox_lib.zip path: ./tmp/ox_lib.zip - action: unzip src: ./tmp/ox_lib.zip dest: ./resources/[ox] - action: download_file url: https://github.com/overextended/ox_target/releases/latest/download/ox_target.zip path: ./tmp/ox_target.zip - action: unzip src: ./tmp/ox_target.zip dest: ./resources/[ox] # 4. Standalone resources straight from GitHub - action: download_github src: https://github.com/AvarianKnight/pma-voice dest: ./resources/[standalone]/pma-voice - action: download_github src: https://github.com/Bob74/bob74_ipl dest: ./resources/[standalone]/bob74_ipl # 5. Our own starter resource, written by the recipe - action: write_file file: ./resources/[local]/my_starter/fxmanifest.lua data: | fx_version 'cerulean' game 'gta5' name 'my_starter' description 'Starter resource created by the My Base recipe' version '1.0.0' shared_script '@ox_lib/init.lua' server_scripts { '@oxmysql/lib/MySQL.lua', 'server.lua', } client_script 'client.lua' dependencies { 'oxmysql', 'ox_lib' } - action: write_file file: ./resources/[local]/my_starter/server.lua data: | AddEventHandler('playerJoining', function() local src = source local license = GetPlayerIdentifierByType(src, 'license') if not license then return end MySQL.insert('INSERT INTO player_stats (license) VALUES (?) ON DUPLICATE KEY UPDATE last_seen = NOW()', { license }) end) - action: write_file file: ./resources/[local]/my_starter/client.lua data: | RegisterCommand('hello', function() lib.notify({ title = 'My Base', description = 'Hello from my_starter!', type = 'success' }) end, false) # 6. server.cfg with placeholders - action: write_file file: ./server.cfg data: | ## Generated by the My Base recipe {{serverEndpoints}} sv_hostname "{{serverName}} | My Base" sets sv_projectName "{{serverName}}" sets sv_projectDesc "{{recipeDescription}}" sets tags "custom, base" sets locale "en-US" sv_licenseKey "{{svLicense}}" sv_maxclients {{maxClients}} sv_enforceGameBuild 3751 set steam_webApiKey "none" set resources_useSystemChat true sv_endpointPrivacy true set mysql_connection_string "{{dbConnectionString}}" setr voice_useNativeAudio true setr voice_useSendingRangeOnly true ensure mapmanager ensure chat ensure spawnmanager ensure basic-gamemode ensure hardcap ensure oxmysql ensure ox_lib ensure ox_target ensure pma-voice ensure bob74_ipl ensure [local] add_ace group.admin command allow add_ace group.admin command.quit deny {{addPrincipalsMaster}} # 7. Fill in every {{placeholder}} in server.cfg - action: replace_string mode: all_vars file: ./server.cfg # 8. Clean up - action: remove_path path: ./tmp ``` ## Why it's built this way - **Database first.** The official guidelines say to put database tasks at the start, because they fail most often (wrong password, no MariaDB). Better to fail in the first second than after two minutes of downloads. - **`dbName: null`.** The guidelines require recipes to accept txAdmin's random database name instead of forcing one like `es_extended`. We never hard code a name: the connection string comes from `{{dbConnectionString}}`. - **Release zips for Overextended.** Their GitHub repos hold source code with a web UI that must be built. The release zip contains the built resource. Always use the release for ox_lib, ox_inventory, ox_target. - **Placeholders in server.cfg.** The guidelines require `{{maxClients}}`, `{{addPrincipalsMaster}}`, `{{serverEndpoints}}` and `{{svLicense}}`. `{{svLicense}}` is replaced automatically at the end, the others by our `replace_string` with `all_vars`. - **The chat resource** is removed from `cfx-server-data` because `set resources_useSystemChat true` uses the artifact's built in chat, as the official default recipe does. - **`$onesync: on`** tells txAdmin to set OneSync on. ox_lib, ox_target and pma-voice all assume it. ## Pin your versions `releases/latest/download/...` and `download_github` without `ref` always fetch the newest version. That's convenient, but a breaking update will break your next deploy. For a recipe you share or use for production: ```yaml - action: download_github src: https://github.com/AvarianKnight/pma-voice ref: 0123456789abcdef0123456789abcdef01234567 # a commit you tested dest: ./resources/[standalone]/pma-voice - action: download_file url: https://github.com/overextended/ox_lib/releases/download/v3.30.0/ox_lib.zip # a tagged release you tested path: ./tmp/ox_lib.zip ``` The version numbers above are placeholders: look up the current release on each project's Releases page. The guidelines prefer commit hashes over tags, because tags can be moved. ## Test it 1. Push the YAML to a public GitHub repo (or a gist) and copy the **raw** URL. 2. Start a throwaway txAdmin: a separate `TXHOST_DATA_PATH` and `TXHOST_TXA_PORT` so you don't touch your main one. 3. Choose **Remote URL Template**, paste the URL, deploy. 4. Check: the server starts with no red errors, `/hello` shows a notification in game, `player_stats` gets a row when you join. Or paste the YAML into **Custom Template** to test without hosting it. ## Guidelines if you want your recipe listed The [txAdmin-recipes README](https://github.com/citizenfx/txAdmin-recipes) lists the rules for recipes in the Popular list. The main ones: - Start from the CFX Default recipe structure. - It must "just work": no editing files before the first start. - Only open source or sharable resources. No leaked content. - OneSync compatible, `$onesync: on` if supported. - Admins in the `admin` ACE group must be recognised as admins by your framework. - NUI that opens on Tab must check `IsNuiFocused()` so it doesn't steal focus from the txAdmin menu. - txAdmin menu actions (noclip, god mode, teleport) must not trigger your anticheat, and txAdmin's Heal should revive downed players (listen to `txAdmin:events:playerHealed`). - Good onboarding: a loading screen that explains the framework, plenty of comments in `server.cfg`. - Use the same game build as the CFX Default recipes. _Last updated: 2026-09-22_ --- ## Popular txAdmin recipes URL: https://fivemad.com/docs/txadmin/popular-recipes Every recipe in the official txAdmin-recipes index: what CFX Default, QBCore, Qbox, ESX Legacy, vMenu and the others install, what they need, and how to deploy them. The "Popular Recipes" list on txAdmin's setup page is not built into txAdmin. It is downloaded from the official **[citizenfx/txAdmin-recipes](https://github.com/citizenfx/txAdmin-recipes)** repository, which holds the index of listed recipes and the files for the "Basic Server" recipes. The framework recipes themselves live in each framework's own repository. This page goes through every recipe in that index. For each one: what it installs, what it needs, the recipe URL, the notable tasks it runs and what to do after deploying. Everything below was read from the recipe files on GitHub in September 2026. Recipes change as projects update, so always read the YAML on the deployer screen before you click Next. ## Comparison | Recipe | Game | Database | Game build set in its `server.cfg` | OneSync | What you get | | --- | --- | --- | --- | --- | --- | | **FiveM Basic Server (CFX Default)** | FiveM Legacy | No | `3751` | on | Default Cfx resources, no framework | | **FiveM Basic Server (Enhanced)** | FiveM Enhanced | No | none (Enhanced uses the latest build) | always on | Minimal Enhanced server | | **ESX Legacy** | FiveM | Yes (MariaDB) | `3258` | on | ESX core, ESX addons, ox_lib, oxmysql, pma-voice, a phone | | **Qbox** | FiveM | Yes (MariaDB 10.9+) | `3258` | on | qbx_core and about 50 qbx resources on the ox stack, npwd phone | | **QBCore** | FiveM | Yes (MariaDB) | `3095` | on | qb-core and about 60 qb resources | | **vMenu** | FiveM | No | its own `sv_enforceGameBuild` line | on | Default Cfx resources plus vMenu | | **StreetKings** | FiveM | Yes | see its `server.cfg` | on | Street racing game mode | | **WarfareTacticsV** | FiveM | Yes | see its `server.cfg` | on | Real-time strategy game mode | | **RedM Basic Server (CFX Default)** | RedM | No | n/a | on | Default Cfx resources for RedM | | **VORP Core** | RedM | Yes | n/a | see recipe | RedM roleplay framework | All of these set `$onesync: on` in their YAML (except where noted), and all framework recipes connect to the database **before** downloading anything else, as the repository's guidelines recommend. ## Which list you see The repository keeps several index files, one per txAdmin generation: `indexv1.json` to `indexv5.json`. Your txAdmin version decides which one it reads. - **`indexv4.json`** lists: FiveM Basic Server (CFX Default), ESX Legacy, Qbox, QBCore, vMenu, StreetKings, WarfareTacticsV, RedM Basic Server (CFX Default) and VORP Core. - **`indexv5.json`**, the newest, starts with **FiveM Basic Server (Enhanced)** and lists ESX Legacy, Qbox, QBCore, StreetKings and WarfareTacticsV. The repository README also lists the Legacy basic server, vMenu (with a recipe patch), VORP, and two deprecated entries (ZAP-Hosting ESX Pack and PlumeESX Legacy) that you should not use for new servers. ## How to deploy any of them 1. Start FXServer without `+exec` so txAdmin runs, link your Cfx.re account (see [First setup](/docs/txadmin/first-setup)). 2. On the setup page choose **Popular Recipes** and click the recipe. For a recipe that isn't listed (or to pin a specific file), choose **Remote URL Template** and paste the raw YAML URL from the sections below. 3. Pick the data folder (txAdmin suggests `txData/_.base`). 4. Read the YAML, click **Next**, paste your license key, and for framework recipes fill in the MariaDB host, port, user and password. Leave the database name empty so txAdmin creates one. 5. **Run Recipe**, review `server.cfg`, **Save & Run Server**. The task types used below (`download_github`, `query_database` and so on) are explained in [Recipes explained](/docs/txadmin/recipes). ## FiveM Basic Server (CFX Default) - **Recipe URL**: `https://raw.githubusercontent.com/citizenfx/txAdmin-recipes/refs/heads/main/default-fivem/recipe.yaml` - **Source**: [txAdmin-recipes/default-fivem](https://github.com/citizenfx/txAdmin-recipes/tree/main/default-fivem) - **Needs**: a license key. No database. **What it does.** Three tasks: copy the `resources` folder of [cfx-server-data](https://github.com/citizenfx/cfx-server-data), delete the old `chat` resource from it (the artifact's built in chat is used instead, via `set resources_useSystemChat true`), and download a minimal `server.cfg`. ```yaml title="default-fivem/recipe.yaml (excerpt, citizenfx/txAdmin-recipes)" - action: download_github src: https://github.com/citizenfx/cfx-server-data ref: master subpath: resources dest: ./resources - action: remove_path path: ./resources/[gameplay]/chat ``` **The server.cfg** starts `mapmanager`, `chat`, `spawnmanager`, `basic-gamemode` and `hardcap`, sets `sv_enforceGameBuild 3751` (A Safehouse in the Hills), `steam_webApiKey "none"`, and gives `group.admin` every command except `quit`. The file itself says it is "NOT supposed to be enough for most servers". **After installing.** Change `sets locale "root-AQ"` to your language (for example `en-US`), set a real `sv_hostname`, and start adding resources: [Installing resources](/docs/resources), [vMenu](/docs/resources/recommended#vmenu), or your own code from [Your first resource](/docs/development/first-resource). **Good for**: learning, development servers, freeroam, anything that isn't roleplay. ## FiveM Basic Server (Enhanced) - **Recipe URL**: `https://raw.githubusercontent.com/citizenfx/txAdmin-recipes/refs/heads/main/default-fivem-enhanced/recipe.yaml` - **Source**: [txAdmin-recipes/default-fivem-enhanced](https://github.com/citizenfx/txAdmin-recipes/tree/main/default-fivem-enhanced) - **Needs**: the **Cfx Server** (Enhanced) artifact and a license key. **What it does.** Downloads `cfx-server-data` into `./tmp`, then moves only what it needs into `resources`: `basic-gamemode`, `mapmanager`, `spawnmanager` and two example maps (`fivem-map-hipster`, `fivem-map-skater`), and deletes `./tmp`. There is no `$onesync` line (OneSync is always on in Enhanced) and no game build line (Enhanced only supports the latest build). Its `server.cfg` starts `mapmanager`, `spawnmanager` and `basic-gamemode` and uses the tags `enhanced, default, deployer`. **Good for**: trying FiveM for GTA V Enhanced. Read [Legacy and Enhanced](/docs/server-setup#fivem-legacy-and-fivem-for-gta-v-enhanced) first. ## ESX Legacy - **Recipe URL**: `https://raw.githubusercontent.com/esx-framework/ESX-recipes/legacy/recipe.yaml` - **Source**: [esx-framework/ESX-recipes](https://github.com/esx-framework/ESX-recipes) (branch `legacy`) - **Needs**: MariaDB (the ESX docs say MariaDB only, not XAMPP), a license key. **What it installs.** - Default Cfx resources into `[cfx-default]` (minus the old chat). - ESX core: the `[core]` folder of [esx-framework/esx_core](https://github.com/esx-framework/esx_core), including `es_extended`. - ESX addons: the `[esx_addons]` folder of ESX-Legacy-Addons (jobs, shops, society and more). - `[standalone]`: bob74_ipl, pma-voice, oxmysql, ox_lib, and sd-phone with sd-phone-props. **Notable tasks.** It downloads the core repo, then imports its SQL from inside it. The addons download gets a long timeout because the repository is big: ```yaml title="recipe.yaml (excerpt, esx-framework/ESX-recipes)" - action: connect_database - action: download_github src: https://github.com/esx-framework/esx-core ref: main dest: ./tmp/core - action: query_database file: ./tmp/core/[SQL]/legacy.sql - action: download_github src: https://github.com/esx-framework/ESX-Legacy-Addons/ ref: main dest: ./tmp/addons timeoutSeconds: 900 ``` **The server.cfg** sets `sv_enforceGameBuild 3258`, the connection string from `{{dbConnectionString}}`, pma-voice settings (`voice_useNativeAudio true`, `voice_useSendingRangeOnly true`), and some security convars (`sv_filterRequestControl 2`, networked sounds, script entity states and phone explosions disabled). It lets `es_extended` run `add_ace`, `add_principal`, `remove_principal` and `stop`, which ESX uses to sync its admin groups. Start order: `chat`, `oxmysql`, `esx_lib`, `es_extended`, `[core]`, `[standalone]`, `[esx_addons]`. **After installing.** Set `setr esx:locale` if you want a language other than the one picked in txAdmin (the line is commented out by default). See the [ESX quick start](/docs/frameworks/esx) for jobs, items and admin. ## Qbox - **Recipe URL**: `https://raw.githubusercontent.com/Qbox-project/txAdminRecipe/refs/heads/main/qbox.yaml` - **Source**: [Qbox-project/txAdminRecipe](https://github.com/Qbox-project/txAdminRecipe) - **Needs**: MariaDB 10.9 or newer (Qbox's docs say MySQL and XAMPP are not supported), a license key. **What it installs.** - Config files: `server.cfg`, `permissions.cfg`, `ox.cfg`, `voice.cfg`, `misc.cfg` and a logo. - `[ox]`: ox_lib, ox_target, oxmysql, ox_doorlock, ox_inventory (with Qbox's `items.lua` and the item images from qbx_invimages) and ox_fuel. - `[standalone]`: bob74_ipl, safecracker, screencapture, mhacking, scully_emotemenu, ultra-voltlab, Renewed-Banking, illenium-appearance, MugShotBase64, Renewed-Weathersync, xt-prison, vehiclehandler, a loading screen and mana_audio. - `[voice]`: pma-voice and mm_radio. - `[qbx]`: qbx_core and around 50 `qbx_*` resources (garages, vehicle shop and sales, police, ambulance and medical, mechanic, properties, vehicle keys, spawn, HUD, radial menu, management, city hall, customs, density, jobs and robberies). - `[npwd]` and `[npwd-apps]`: the npwd phone (pinned to release 3.16.0) with Qbox garage and mail apps. - `[assets]`: a Pillbox hospital map. **Notable tasks.** It imports a base `qbox.sql`, then each resource's own SQL right after downloading it, and pauses between batches of GitHub downloads so users don't get rate limited: ```yaml title="qbox.yaml (excerpt, Qbox-project/txAdminRecipe)" - action: query_database file: ./resources/[qbx]/qbx_drugs/qbx_drugs.sql - action: waste_time # prevent github throttling seconds: 10 ``` It also moves the item images into `ox_inventory/web/images` with `overwrite: true` and copies the Qbox npwd config over npwd's default one. **The server.cfg** uses `set sv_enforceGameBuild 3258` and has many `qbx:` convars, including `qbx:enableBridge "true"` (the qb-core compatibility bridge), `qbx:enableQueue`, `qbx:max_jobs_per_player`, `qbx:enableVehiclePersistence` and a chat MOTD. Start order: `ox_lib`, `qbx_core`, `ox_target`, `[ox]`, `[qbx]`, `[standalone]`, `[voice]`, `[assets]`, then npwd. Permissions come from `{{addPrincipalsMaster}}` and `exec permissions.cfg`. **After installing.** Change the locale lines (`sets locale`, `setr qb_locale`, `setr illenium-appearance:locale`), set `qbx:discordLink`, and fill in `SCREENSHOT_BASIC_TOKEN` / `NPWD_AUDIO_TOKEN` only if you want npwd's camera and audio features. See the [Qbox quick start](/docs/frameworks/qbox). ## QBCore - **Recipe URL**: `https://raw.githubusercontent.com/qbcore-framework/txAdminRecipe/main/qbcore.yaml` - **Source**: [qbcore-framework/txAdminRecipe](https://github.com/qbcore-framework/txAdminRecipe) (version 2.2.4 at the time of writing) - **Needs**: MariaDB (the QBCore install guide pairs it with HeidiSQL), a license key. **What it installs.** - Default Cfx resources into `[cfx-default]` (minus the old chat). - `[standalone]`: oxmysql (pinned to v2.14.1), menuv (v1.4.1), bob74_ipl, safecracker, screencapture, progressbar, interact-sound, connectqueue, PolyZone. - `[voice]`: pma-voice and qb-radio. - `[defaultmaps]`: hospital, dealer and prison maps. - `[qb]`: qb-core and around 60 `qb-*` resources: multicharacter, target, inventory, phone, garages, vehicle shop and sales, police, ambulance, mechanic, houses, apartments, banking, clothing, doorlock, fuel, HUD, menu, input, loading screen, admin menu, management, weather sync, many jobs and robberies. **Notable tasks.** The database goes first with one SQL file from the recipe repository, and the recipe pauses 10 seconds between batches of downloads (`waste_time`, eight times in total) to avoid GitHub throttling. ```yaml title="qbcore.yaml (excerpt, qbcore-framework/txAdminRecipe)" - action: connect_database - action: query_database file: ./tmp/qbcore/qbcore.sql - action: download_file path: ./tmp/files/oxmysql.zip url: https://github.com/overextended/oxmysql/releases/download/v2.14.1/oxmysql.zip ``` **The server.cfg** sets `sv_enforceGameBuild 3095` (The Chop Shop), pma-voice settings (`voice_useNativeAudio true`, default cycle key `GRAVE`), `setr qb_locale "en"` and `setr UseTarget false`. It defines a permission chain: `qbcore.god` inherits `group.admin` and `qbcore.admin`, and `qbcore.admin` inherits `qbcore.mod`. It also lets `resource.qb-core` run commands. **After installing.** Let the first start finish: QBCore's docs warn to let **yarn install** run all the way through on the initial startup. Then give yourself QBCore admin by adding your identifier to the god group, for example `add_principal identifier.fivem:123456 qbcore.god`. Switch `UseTarget` to `true` if you want qb-target interactions instead of key prompts. See the [QBCore quick start](/docs/frameworks/qbcore). ## vMenu - **Recipe URL** (as listed in `indexv4.json`): `https://raw.githubusercontent.com/tabarra/vMenu-recipe/refs/heads/main/recipe.yaml`. The README links the recipe patch at [feelfreetofee/vMenu-recipe](https://github.com/feelfreetofee/vMenu-recipe). - **Needs**: a license key. No database. **What it does.** Copies `cfx-server-data`, removes the old chat and the `[builders]` folder, downloads its `server.cfg`, then downloads a pinned vMenu release (v3.8.61 in the patch at the time of writing) and unzips it into `resources/[local]/vMenu`. **The server.cfg** runs `exec @vMenu/config/permissions.cfg` **before** `ensure vMenu`, which is exactly the order the vMenu docs require. **After installing.** Edit `resources/[local]/vMenu/config/permissions.cfg` to decide who can use which menu options. Newer vMenu releases may exist: see [vMenu](/docs/resources/recommended#vmenu) for updating it by hand. ## StreetKings - **Recipe URL**: `https://raw.githubusercontent.com/streetkings-fivem/txAdminRecipe/refs/heads/main/streetkings.yaml` - **Needs**: MariaDB, a license key. A freeroam street racing game mode by 919DESIGN and Envi-Scripts: solo or up to 20 player races, XP for character and vehicle across five classes, daily races and a short story campaign. The recipe imports `streetkings.sql`, downloads bob74_ipl, pma-voice, the `streetkings` resource with its audio and blips assets, and ox_lib and oxmysql. Note that at the time of writing it downloads ox_lib and oxmysql from the **CommunityOx** GitHub organisation, whose copies of those repositories are now archived; the maintained versions are under [overextended](https://github.com/overextended). ## WarfareTacticsV (Real-Time Strategy) - **Recipe URL**: `https://raw.githubusercontent.com/FiveM-RTS-WarfareTactics/txAdminRecipe/refs/heads/main/recipe.yaml` - **Needs**: MariaDB, a license key. A standalone RTS game mode by EnyoScripts (version 2.1.1 at the time of writing): platoon combat, 5 maps, 24 unit types, CPU opponents and matchmaking. The recipe pins `cfx-server-data` to a specific commit and only moves the pieces it needs (sessionmanager, baseevents, hardcap, the yarn and webpack builders, spawnmanager), then downloads its `[rts]` resources with 900 second timeouts because they are large. ## RedM Basic Server and VORP Core For Red Dead Redemption 2 servers on RedM: - **RedM Basic Server (CFX Default)**: `https://raw.githubusercontent.com/citizenfx/txAdmin-recipes/refs/heads/main/default-redm/recipe.yaml`, the same three tasks as the FiveM basic recipe with a RedM `server.cfg`. - **VORP Core**: `https://raw.githubusercontent.com/VORPCORE/VORP_txAdmin/main/vorp_recipe.yaml`, the most used RedM roleplay framework. Needs MariaDB. These docs focus on FiveM, but txAdmin works the same way for RedM. ## Common issues with recipe deploys | Problem | Cause and fix | | --- | --- | | GitHub `401`, `403` or `429` during download | GitHub rate limits by IP, worse on shared hosting. Wait 10 to 15 minutes and retry. Big recipes pause with `waste_time` to reduce this. | | `connect_database` fails | MariaDB not running, wrong password, or the user can't create databases. See [Database setup](/docs/server-setup/database). | | `query_database` fails on a framework SQL | MySQL 8 or an old MariaDB (XAMPP). Qbox and ESX require MariaDB. | | A task times out | Slow connection or a large repository. Retry. Recipe authors can raise `timeoutSeconds`. | | Server starts but resources error on first boot | Resources that build with yarn (QBCore) need the first start to finish. Wait, then restart once. | | Everything is in English | Change the locale convars in `server.cfg` (`sets locale`, `setr qb_locale`, `setr esx:locale`). | | Target path error | txAdmin will not create missing parent folders outside `txData`. Create the parent first. | | You deployed the wrong recipe | Stop the server, delete the data folder and the generated database, and deploy again. | ## Writing or listing your own Anyone can deploy a recipe from a URL. To have one included in the Popular list, it must follow the [txAdmin-recipes guidelines](https://github.com/citizenfx/txAdmin-recipes#recipe-making-guidelines-and-best-practices): start from the CFX Default structure, "just work" without manual edits, use only open source or sharable resources, support OneSync, use the `{{maxClients}}`, `{{addPrincipalsMaster}}`, `{{serverEndpoints}}` and `{{svLicense}}` placeholders, and accept txAdmin's random database name. See [Writing your own recipe](/docs/txadmin/writing-recipes) for a full example. _Last updated: 2026-09-22_ --- ## Everyday admin with txAdmin URL: https://fivemad.com/docs/txadmin/everyday-admin Run a FiveM server day to day with txAdmin: players, warns, kicks and bans, whitelist modes, scheduled restarts, live console, logs, backups and admin permissions. Once the server is running, txAdmin is where you spend your time: dealing with players, restarting, reading logs and managing staff. This page covers the features you'll use every day and the settings worth changing early. [txAdmin Menu Beta: Introduction (Project Error)](https://www.youtube.com/watch?v=jWKg0VQK0sc) (YouTube video) ## The dashboard The dashboard shows server status, player count, uptime, the next scheduled restart and the **performance chart**: server thread tick times plotted against the number of players. Spikes that line up with player joins or specific times often point to a resource doing heavy work. Pair it with the profiler (see [Threads and performance](/docs/development/threads-performance)). From the dashboard you can **start, stop and restart** the server and send an **announcement** to everyone. ## Players ### Finding a player The **Players** page searches everyone who has ever joined, by name, identifier or notes, not just who is online. Click a player to open their **player modal**: play time, first and last join, identifiers (license, Discord, Cfx.re, Steam), hardware IDs, their history of warns and bans, and **notes** your staff left. In game, `/tx` opens the menu's player list, sortable by ID, name or distance. `/tx 12` jumps straight to player 12. ### Warn, kick, ban | Action | What happens | | --- | --- | | **DM** | A private message on the player's screen. | | **Warn** | A full screen warning the player must acknowledge (holding a key) before they can continue. Recorded in their history. Works for offline players too: they see it when they next join. | | **Kick** | Disconnects them with your reason. | | **Ban** | Temporary (hours, days, weeks) or permanent. txAdmin bans every identifier it knows for the player, plus hardware IDs, so a new Rockstar account alone doesn't get around it. | Always write a clear reason. The player sees it, and your team sees it months later. By default txAdmin hides the admin's name in bans and warns (`txAdmin-hideAdminInPunishments`). You can **revoke** a ban or warn from the player's history, and **ban by identifier** for someone who isn't online. ### Freeze, spectate, bring, go to Menu only, from the player's page in `/tx`: freeze their ped, spectate them, bring them to you, go to them, heal them. Troll actions (drunk, fire, wild attack) exist too and are behind their own permission. Give that permission to nobody you wouldn't trust with a ban hammer. ## Whitelist **Settings > Player Manager** has the whitelist mode: | Mode | Who can join | | --- | --- | | Disabled | Everyone (except banned players). | | Admin only | Only txAdmin admins. Handy during maintenance. | | Approved license | Players whose Rockstar license an admin approved. New players appear as **whitelist requests** with a short ID they can give you. | | Discord member | Players who are members of your Discord server (needs the [Discord bot](/docs/txadmin/discord-bot)). | | Discord role | Players who have one of the roles you pick in your Discord server. | With **Approved license**, a rejected player sees a request ID on the connect screen. Approve it on the **Whitelist** page or with the bot's whitelist command. ## Scheduled restarts FiveM servers run better with regular restarts: memory from leaky scripts is freed and state is reset. In **Settings > Restarter**, add times in 24 hour format: ```text 06:00, 12:00, 18:00, 00:00 ``` Players get warnings at 30, 15, 10, 5, 4, 3, 2 and 1 minutes. Resources can react to the `txAdmin:events:scheduledRestart` event (for example to save data), and frameworks usually save players on shutdown. From the dashboard you can **skip** the next restart or schedule a one off **temporary** restart. > [!TIP] > Pick restart times when fewest people play, and announce them in Discord. Every 6 to 12 hours is common for RP servers with many scripts. Small, clean servers can go much longer. ## Crash and hang handling txAdmin restarts FXServer automatically when it **crashes** or **hangs** (stops responding to txAdmin's checks). If it keeps restarting in a loop, open the Live Console, scroll to the last lines before the crash, and look at [Common errors](/docs/server-setup/common-errors). ## Live Console The **Live Console** shows everything FXServer prints and lets you type server commands (`ensure myresource`, `restart ox_inventory`, `refresh`). It keeps a command history and has search. The same log is written to files in `txData`, so you can read yesterday's output. Handy commands: ```text refresh rescan the resources folder ensure my_resource start or restart a resource stop my_resource status list connected players clientkick 12 reason kick player 12 say Hello everyone message from the console ``` ## Logs - **Server log** (**Server Log** page): joins, leaves, deaths, chat, explosions, menu actions, plus custom lines resources add. Filter by player to see what someone did. - **Action log** (System logs): what every **admin** did in txAdmin: bans, warns, restarts, settings changes, console commands. This is how you keep staff honest. - **Console log files** in `txData`. ## Resources page Lists every resource with its state. Start, stop and restart single resources without touching the console. Useful for a quick `restart` after editing a config on a live server (if the resource supports restarting cleanly). ## CFG editor **CFG Editor** edits `server.cfg` (and other cfg files it references) in the browser. Changes apply on the next restart. Restrict it with the `server.cfg.editor` permission: whoever can edit the cfg can effectively run any command. ## Admins and permissions **Admin Manager** (needs `manage.admins` or the master account): 1. **Add admin**: a name, and their **Cfx.re** username and/or **Discord ID**. The identifiers let them use the in-game menu and log in with Cfx.re. 2. Give them a **backup password** or let them set one on first login. 3. Pick permissions. From txAdmin's permission list: | Permission | Allows | | --- | --- | | `all_permissions` | Everything. Give it to almost nobody. | | `manage.admins` | Add, edit and remove admins. | | `settings.view` / `settings.write` | View / change settings. | | `console.view` / `console.write` | See / type in the live console. `console.write` is effectively full control. | | `control.server` | Start, stop, restart the server. | | `commands.resources` | Start and stop resources. | | `server.cfg.editor` | Read and write server.cfg. | | `announcement` | Send announcements. | | `txadmin.log.view` / `server.log.view` | View logs. | | `players.direct_message`, `players.warn`, `players.kick`, `players.ban` | Player actions. | | `players.whitelist` | Approve whitelist requests. | | `players.freeze`, `players.heal`, `players.spectate`, `players.teleport`, `players.playermode`, `players.troll` | Menu actions. | | `menu.vehicle`, `menu.clear_area`, `menu.viewids` | Menu vehicle spawn/fix, area reset, show player IDs. | | `players.remove_ids` | Remove identifiers and hardware IDs from the database. | A sensible **moderator**: `players.direct_message`, `players.warn`, `players.kick`, `players.ban`, `players.spectate`, `players.freeze`, `players.teleport`, `menu.viewids`, `server.log.view`. A **senior admin** adds `control.server`, `commands.resources`, `announcement`, `players.whitelist`. Permissions are stored in `txData/admins.json`. ## Backups txAdmin keeps its own data (players, bans, warns, whitelist, settings) in `txData`, not in MariaDB. It does **not** back up your server folder or your framework database. Back up: - `txData` (whole folder), - your server data folder (`server.cfg`, `resources`, ideally in git), - your MariaDB database, nightly (see [Database setup](/docs/server-setup/database#backups)). Copy them off the machine. txAdmin also has a **database cleanup** action (on the master admin's **Master Actions** page) that removes old players with little play time, old warns and expired bans, to keep its player database small on busy servers. ## Settings worth changing early - **Game > Menu**: enable or disable the in-game menu, align it right, change the page key. - **Game > Notifications**: hide the default announcement, DM, warning or restart UI if a resource of yours shows them instead (it listens to the txAdmin events). - **Player Manager**: whitelist mode, ban templates, and the message players see when banned or not whitelisted (put your Discord link there). - **Restarter**: schedule. - **Discord Bot**: see the [Discord bot page](/docs/txadmin/discord-bot). _Last updated: 2026-09-22_ --- ## txAdmin Discord bot URL: https://fivemad.com/docs/txadmin/discord-bot Set up txAdmin's built in Discord bot: create the application, token and intents, invite it, add the live status embed with /status add, and use Discord whitelisting. txAdmin has a Discord bot built in. You don't host anything extra: txAdmin itself logs in as your bot. It gives you: - a **persistent status embed** that updates every minute (online state, players, next restart, uptime, connect buttons), - **Discord based whitelisting** (member of your server, or has a role), - slash commands for staff, like whitelisting a player and looking up player info, - an optional **announcements channel** where txAdmin posts server events such as restarts. [txAdmin Discord Bot setup: status and whitelist (Brave Development)](https://www.youtube.com/watch?v=pfEtkIcRdHg) (YouTube video) ## 1. Create the Discord application 1. Go to the [Discord Developer Portal](https://discord.com/developers/applications) and click **New Application**. Name it after your server. 2. Open the **Bot** page. 3. Click **Reset Token** and copy the token. Treat it like a password: anyone with it controls your bot. 4. Under **Privileged Gateway Intents**, enable **Server Members Intent**. Without it the bot can't see who is in your Discord, and member or role whitelisting fails. 5. Optional: turn off **Public Bot** so nobody else can invite it. ## 2. Invite it to your Discord 1. Open **OAuth2 > URL Generator**. 2. Scopes: `bot` and `applications.commands`. 3. Bot permissions: at least **View Channels**, **Send Messages**, **Embed Links** and **Read Message History** (the status embed is a message the bot edits). 4. Open the generated URL and add the bot to your server. ## 3. Configure txAdmin In txAdmin, **Settings > Discord Bot**: | Field | Value | | --- | --- | | Enabled | On | | Token | The bot token from step 1 | | Guild / Server ID | Right click your server icon in Discord > **Copy Server ID** (enable Developer Mode in Discord's Advanced settings first) | | Announcements channel | Optional. Right click a channel > **Copy Channel ID**. txAdmin posts server events (like restarts) there. | Save. The txAdmin **System Logs** page shows whether the bot logged in or why it failed. ## 4. Add the status embed In the channel where you want the status, type: ```text /status add ``` The bot posts an embed and keeps editing it every minute. It needs permission to send messages in that channel. To move it, run `/status add` in the new channel and delete the old message. ### Customise the embed **Settings > Discord Bot** has two JSON editors, the **embed JSON** and the **config JSON**. The embed supports these placeholders (from txAdmin's [discord-status docs](https://github.com/citizenfx/txAdmin/blob/master/docs/discord-status.md)): | Placeholder | Value | | --- | --- | | `{{serverName}}` | txAdmin's name for the server | | `{{serverClients}}` / `{{serverMaxClients}}` | Players online / slots | | `{{serverJoinUrl}}` | `https://cfx.re/join/xxxxxx` | | `{{serverBrowserUrl}}` | Server browser page | | `{{serverCfxId}}` | Your server's Cfx.re ID | | `{{statusString}}` / `{{statusColor}}` | Online, partial or offline text and colour from the config JSON | | `{{uptime}}` | For example `1 hr, 50 mins` | | `{{nextScheduledRestart}}` | For example `in 2 hrs, 48 mins` | A minimal embed: ```json title="Embed JSON" { "title": "{{serverName}}", "url": "{{serverBrowserUrl}}", "description": "Press Connect below, or F8 and `connect cfx.re/join/xxxxxx`.", "fields": [ { "name": "> STATUS", "value": "```\n{{statusString}}\n```", "inline": true }, { "name": "> PLAYERS", "value": "```\n{{serverClients}}/{{serverMaxClients}}\n```", "inline": true }, { "name": "> NEXT RESTART", "value": "```\n{{nextScheduledRestart}}\n```", "inline": true }, { "name": "> UPTIME", "value": "```\n{{uptime}}\n```", "inline": true } ] } ``` And the config, which sets the status texts, colours and up to 5 link buttons: ```json title="Config JSON" { "onlineString": "Online", "onlineColor": "#0BA70B", "partialString": "Partial", "partialColor": "#FFF100", "offlineString": "Offline", "offlineColor": "#A70B28", "buttons": [ { "emoji": "1062338355909640233", "label": "Connect", "url": "{{serverJoinUrl}}" }, { "emoji": "1062339910654246964", "label": "Rules", "url": "https://example.com/rules" } ] } ``` `color` and `footer` are set by txAdmin, so leave them out. txAdmin can't validate the embed until Discord accepts it: if it doesn't appear, check **System Logs**. A visual editor like [discohook.org](https://discohook.org/) helps (paste the object inside its `embeds` array). The `emoji` fields take a unicode emoji or a custom emoji ID; replace the example IDs above with your own. ## 5. Discord whitelisting In **Settings > Player Manager**, set the whitelist mode: - **Discord member**: anyone in your Discord server can join. Good against random joiners and ban evaders who don't want to rejoin your Discord. - **Discord role**: only members with one of the roles you pick. The classic "Whitelisted" role for RP servers. Your application team gives the role, the player can join. Players must have **Discord running and linked** to FiveM so the server receives their `discord:` identifier. If they get "not whitelisted" while having the role, it's almost always that: Discord wasn't open when they launched FiveM. For **Approved license** mode, staff can approve requests from Discord with the bot's whitelist command instead of opening the panel. ## Troubleshooting | Problem | Fix | | --- | --- | | Bot offline | Wrong token (reset it and paste again), or the bot is disabled in settings. Check System Logs. | | Whitelist says everyone is not a member | **Server Members Intent** not enabled, or wrong Guild ID. | | `/status add` does nothing | Slash commands take a moment to register after the bot joins. Also check the bot has permission in that channel. | | Embed never updates | Someone deleted the message. Run `/status add` again. | | Custom emoji don't show | The bot must be in the server that owns the emoji, and the ID must be right. | The official txAdmin channel also has a short video on removing an admin from the bot, linked in the [video archive](/docs/videos). _Last updated: 2026-09-22_ --- ## Updating txAdmin and FXServer URL: https://fivemad.com/docs/txadmin/updating txAdmin ships inside FXServer, so updating the artifact updates txAdmin. How to update, what to back up, migrating old start.bat configs to TXHOST variables, and rollbacks. Since early 2020 txAdmin is a component of FXServer. There is no separate txAdmin download and no separate update button: **each FXServer artifact contains a specific txAdmin version**. Update the artifact and you update txAdmin. ## How to tell which version you run - The txAdmin panel shows its version in the sidebar or footer, and the FXServer build number on the dashboard. - The console prints both on start. When a new txAdmin version is out, it arrives in a new artifact. The recommended artifact may lag behind the latest one by a few builds. ## The update, step by step The artifact update routine is the same one described in [Updating artifacts safely](/docs/server-setup/updating-artifacts). Short version: 1. Check the build on our [Artifacts page](/artifacts), avoid builds flagged as broken. 2. Back up `txData` (it holds `admins.json`, player database, bans, warns and settings) and your database. 3. Stop the server and close FXServer. 4. Rename the old artifact folder, extract the new one to a fresh folder. 5. On Linux, make sure `txData` is where txAdmin expects it (by default next to `run.sh`, which is inside the artifact folder), or set `TXHOST_DATA_PATH`. 6. Start FXServer. txAdmin migrates its own config and database automatically on first start. 7. Check the dashboard, live console and in-game menu. > [!WARNING] > Going **back** to an older artifact after txAdmin migrated its data can fail, because the old version may not read the new format. That's why you back up `txData` before updating, not after. ## Migrating old start scripts (txAdmin v8) Older guides start txAdmin with convars on the command line: ```bat title="start.bat (old style)" @echo off "C:/FXServer/server/FXServer.exe" +set serverProfile "server2" +set txAdminPort "40125" pause ``` Since **txAdmin v8.0.0**, host settings are `TXHOST_*` environment variables. The `txAdminPort`, `txAdminInterface` and `txDataPath` convars (and the `txAdminZapConfig.json` file) are deprecated and will stop working in a future update. The txAdmin docs give this replacement: ```bat title="start.bat (current)" @echo off set TXHOST_DATA_PATH=C:\FXServer\txData-server2 set TXHOST_TXA_PORT=40125 "C:/FXServer/server/FXServer.exe" pause ``` On Linux, add `export TXHOST_...=...` lines to a small `env.sh` and start with `source env.sh && ./run.sh`, or use `Environment=` lines in your systemd unit. If both old and new configs exist, the new one wins. `TXHOST_IGNORE_DEPRECATED_CONFIGS=true` silences the warnings. The concept of **profiles** (`serverProfile`) will likely be deprecated too, so use one `txData` per server instead. ## What usually changes after an update - New settings with default values (check the Settings pages after big updates). - The in-game menu may look different or have new permissions: review your admins' permissions in the Admin Manager. - Discord bot: new permissions or intents are occasionally needed. Check **System Logs** if the bot stops working. - Deprecated features disappear. The [feature graveyard](https://github.com/citizenfx/txAdmin/blob/master/docs/feature-graveyard.md) lists what was removed and why (for example built in SSL: use a reverse proxy or Cloudflare Tunnel instead). ## Keeping up with changes - The txAdmin [GitHub releases](https://github.com/citizenfx/txAdmin/releases) and the txAdmin Discord announce new versions. - The official [txAdmin YouTube channel](https://www.youtube.com/@txAdmin) has short videos for some features. - Cfx.re's forum announces artifact changes that affect server owners. ## FiveM for GTA V Enhanced Enhanced uses a different server build (Cfx Server) with its own downloads, and txAdmin has a separate "FiveM Basic Server (Enhanced)" recipe. Don't point an Enhanced artifact at your Legacy `txData` and server folder and expect it to work: read the [Legacy and Enhanced notes](/docs/server-setup#fivem-legacy-and-fivem-for-gta-v-enhanced) and test on a copy. _Last updated: 2026-09-22_ --- # Development ## Start developing for FiveM URL: https://fivemad.com/docs/development How to start writing FiveM scripts: choosing Lua, JavaScript or C#, setting up VS Code with Lua language server and FiveM natives, git, a dev server and a learning plan. Writing FiveM scripts is one of the most rewarding ways to learn programming: you change a line, type `ensure`, and see the result in a game world a second later. This section takes you from zero to publishing your own resource. ## How FiveM code works, in one minute - Your code lives in **resources**: folders with an `fxmanifest.lua` and some scripts. - **Client scripts** run on every player's PC, inside their game. They draw things, read keys, spawn local effects, and call game **natives**. - **Server scripts** run once, in FXServer. They own the truth: money, inventories, database, permissions. - The two sides talk with **events**. The client can never be trusted, so the server checks everything. - A web page (**NUI**) can be your UI, written in HTML, CSS and JavaScript (or React, Vue, Svelte...). That's the whole model. Every page in this section expands one piece. ## Pick a language FiveM runs three scripting runtimes, and a resource can mix them. | Language | Runtime | Pros | Cons | | --- | --- | --- | --- | | **Lua 5.4** (CfxLua) | Built in | What 90% of resources, frameworks and tutorials use. Simple, fast to iterate. | Dynamic typing: mistakes show up at runtime. | | **JavaScript / TypeScript** | V8 (client), Node.js (server, 16 by default, 22 with `node_version '22'`) | npm packages on the server, TypeScript types, familiar to web devs. | Fewer examples, some framework APIs are Lua first. | | **C#** | Mono on Legacy (the Enhanced platform uses .NET 10) | Strong typing, big projects stay tidy, vMenu is written in C#. | Needs a build step, fewer community examples. | **Start with Lua.** Frameworks (QBCore, Qbox, ESX), libraries (ox_lib) and almost every tutorial and forum answer are Lua. You can always add a React UI or a TypeScript server later. > [!NOTE] > Since June 2025, all Lua scripts run on Lua 5.4 and Lua 5.3 is deprecated. You'll still see `lua54 'yes'` in manifests: it's no longer required on current artifacts but it's harmless, and some tools and older guides still expect it. ## Tools you need ### 1. A local dev server Develop on your own PC, never on the live server. Set one up with txAdmin in ten minutes: [Windows setup](/docs/server-setup/windows). Use the **FiveM Basic Server** recipe for learning, or the framework you target. Keep `sv_maxclients` low and consider a separate license key for it. ### 2. Visual Studio Code [VS Code](https://code.visualstudio.com/) is what most FiveM developers use. Install these extensions: | Extension | Why | | --- | --- | | **Lua** by sumneko (Lua Language Server) | Autocomplete, type checking, go to definition, diagnostics. | | **CfxLua IntelliSense** (`overextended/cfxlua-vscode`) | Sets up [fivem-lls-addon](https://github.com/overextended/fivem-lls-addon): declarations for every FiveM and GTA native, plus CfxLua syntax like `` `backtick hashes` `` and compound operators. | | **GitLens** or the built in Git panel | See what changed, when, and why. | | **ESLint / Prettier** | If you write JavaScript or NUI. | With the native declarations installed, typing `GetEntityCoo` completes to `GetEntityCoords(entity, alive)` with parameter hints. That alone saves hours of alt tabbing to the docs. The ox libraries also ship Lua type definitions ([ox_types](https://github.com/overextended/ox_types)). [Setting up VSCode for FiveM Lua Development (CharlesHacks)](https://www.youtube.com/watch?v=JOnYzPzrzXI) (YouTube video) ### 3. Git Put every resource (or your whole server folder) in git from day one. It's your undo button, your backup, and how you work with other developers. Keep secrets out of it: see [Security basics](/docs/server-setup/security#5-secrets-out-of-git-and-screenshots). ### 4. The docs, bookmarked - [Scripting manual](https://docs.fivem.net/docs/scripting-manual/) and [scripting reference](https://docs.fivem.net/docs/scripting-reference/) on docs.fivem.net. - [Natives reference](https://docs.fivem.net/natives/): every function the game gives you. - [Resource manifest reference](https://docs.fivem.net/docs/scripting-reference/resource-manifest/). - For UI and game data lookups, fivemad has references for [controls](/tools/controls-reference), [blips and markers](/tools/blip-marker-browser), [models and hashes](/tools/model-hash-browser), [props](/tools/objects-list), [particles](/tools/particles-list), [sounds](/tools/sound-browser) and the [map with coordinates](/tools/interactive-map). ## A learning plan Work through these in order. Each page ends with something that runs. 1. [Your first resource](/docs/development/first-resource): folder, manifest, a `/hello` command, restarting, reading the F8 console. 2. [Client, server and events](/docs/development/client-server-events): the two sides and how they talk safely. 3. [Natives](/docs/development/natives): finding and using game functions, hashes, common natives. 4. [Threads and performance](/docs/development/threads-performance): loops, `Wait`, resmon and the profiler. 5. [State bags and OneSync](/docs/development/state-bags-onesync): syncing data, entity ownership, routing buckets. 6. [NUI basics](/docs/development/nui): HTML UIs, messages, callbacks, focus. 7. [Exports and dependencies](/docs/development/exports-dependencies): reusing code between resources, working with frameworks and libraries. 8. [Debugging](/docs/development/debugging): reading errors, print debugging, dev tools, common bugs. 9. [Streaming custom assets](/docs/development/streaming-assets): cars, clothes, maps, props and sounds. 10. [Publishing a resource](/docs/development/publishing): versioning, README, license, the forum, Tebex and escrow. If you prefer video, the [Lua scripting course](/docs/videos) in the video archive follows a similar path. ## Habits that make you better fast - **Read other people's code.** Open ox_lib, a Qbox resource or vMenu's source on GitHub and see how they solve things. - **Keep the F8 console open** while testing. Errors tell you the file and line. - **Small steps.** Change one thing, `ensure`, test. Don't write 300 lines and then start the server. - **Server decides, client displays.** If you remember one rule, remember that one. - **Don't copy paste from leaked scripts.** Bad habits, license trouble, and sometimes backdoors. - **Ask good questions** on the [forum](https://forum.cfx.re): what you tried, the exact error, the code (formatted), what you expected. _Last updated: 2026-09-22_ --- ## Your first FiveM resource URL: https://fivemad.com/docs/development/first-resource Build a FiveM resource from scratch: folder, fxmanifest.lua, client and server scripts, a /hello command, a car spawner, ensure and restart, and reading the F8 console. In this tutorial you build a resource with a client script and a server script, add chat commands, spawn a car, and learn the edit, `ensure`, test loop you'll use every day. You need a local server (see [Windows setup](/docs/server-setup/windows)) and VS Code (see [Start developing](/docs/development)). [FiveM Scripting: Creating Your First Script (Twisle)](https://www.youtube.com/watch?v=dkqbgV2KUKw) (YouTube video) ## 1. Create the folder Inside your server data folder, go to `resources`. Create a category folder `[local]` for your own work if it doesn't exist, and inside it a folder for the resource: ```text resources/ └─ [local]/ └─ hello_world/ ├─ fxmanifest.lua ├─ client.lua └─ server.lua ``` The folder name **is** the resource name. Use lowercase, no spaces: `hello_world`, not `Hello World`. ## 2. Write the manifest `fxmanifest.lua` tells FXServer what the resource is and which files run where: ```lua title="resources/[local]/hello_world/fxmanifest.lua" fx_version 'cerulean' game 'gta5' name 'hello_world' author 'You' description 'My first FiveM resource' version '1.0.0' client_script 'client.lua' server_script 'server.lua' ``` - `fx_version 'cerulean'` is the current manifest version. Always use it for new resources. - `game 'gta5'` says this is for FiveM (RedM uses `rdr3`). - `client_script` and `server_script` list the files for each side. Use the plural forms with `{ }` for several files, and globs like `'client/*.lua'` work. You can generate manifests with the [fxmanifest Generator](/tools/fxmanifest-generator), which also warns about common mistakes. ## 3. A client command ```lua title="resources/[local]/hello_world/client.lua" RegisterCommand('hello', function(source, args, rawCommand) local name = args[1] or 'world' TriggerEvent('chat:addMessage', { color = { 0, 200, 255 }, args = { 'Hello', ('Hello, %s!'):format(name) }, }) end, false) ``` - `RegisterCommand(name, handler, restricted)` creates `/hello`. On the client, `source` is always 0. `args` is a table of the words after the command. - `TriggerEvent('chat:addMessage', ...)` sends a local event to the chat resource, which shows the message. - `false` means anyone can use it. `true` would require the `command.hello` ACE permission. ## 4. A server command ```lua title="resources/[local]/hello_world/server.lua" RegisterCommand('whoami', function(source, args) if source == 0 then print('This command was run from the server console.') return end local name = GetPlayerName(source) local license = GetPlayerIdentifierByType(source, 'license') print(('[hello_world] %s (id %d) asked who they are'):format(name, source)) TriggerClientEvent('chat:addMessage', source, { args = { 'Server', ('You are %s, player id %d, %s'):format(name, source, license or 'no license') }, }) end, false) ``` On the server, `source` is the **server ID** of the player who typed the command, or `0` for the console. `print` goes to the server console (txAdmin Live Console), and `TriggerClientEvent(name, target, ...)` sends an event to one player (`-1` sends to everyone). ## 5. Start it In the txAdmin **Live Console** (or the server window), type: ```text refresh ensure hello_world ``` - `refresh` rescans the resources folder, so FXServer notices your new folder. - `ensure` starts it (or restarts it if it's running). You should see `Started resource hello_world`. To start it on every boot, add it to `server.cfg`: ```cfg title="server.cfg" ensure hello_world # or, to start everything in [local]: ensure [local] ``` ## 6. Test in game Connect to your server, press T to open chat, and type `/hello` or `/hello Bob`. Then `/whoami`. You should see both messages, and the server console shows the `print` line. ## 7. The edit loop Change the message in `client.lua`, save, then in the server console: ```text ensure hello_world ``` The resource restarts and every connected client reloads it. Test again. This loop (edit, save, `ensure`, test) is how you'll work. You only need `refresh` again when you **add** a resource or change `fxmanifest.lua`. > [!TIP] > You can also type `ensure hello_world` in the **F8 console** in game if your account has permission to run server commands (the txAdmin master admin does, through `add_ace group.admin command allow`). ## 8. Read the F8 console Press F8 in game. This is the **client console**. Client `print` output and client errors show here. Add a print to `client.lua`: ```lua print('hello_world client loaded') ``` `ensure` again and look for the line in F8. Now break something on purpose: ```lua RegisterCommand('broken', function() local ped = nil print(ped.health) -- indexing nil end, false) ``` Run `/broken` and F8 shows something like: ```text SCRIPT ERROR: @hello_world/client.lua:14: attempt to index a nil value (local 'ped') ``` It tells you the resource, the file, the **line**, and what went wrong. Server errors look the same in the server console. More in [Debugging](/docs/development/debugging). ## 9. Spawn a car Now use some game natives. This is the example from the official "creating your first script" guide: ```lua title="client.lua" RegisterCommand('car', function(source, args) local vehicleName = args[1] or 'adder' if not IsModelInCdimage(vehicleName) or not IsModelAVehicle(vehicleName) then TriggerEvent('chat:addMessage', { args = { 'Invalid vehicle model: ' .. vehicleName } }) return end RequestModel(vehicleName) while not HasModelLoaded(vehicleName) do Wait(500) end local playerPed = PlayerPedId() local pos = GetEntityCoords(playerPed) local vehicle = CreateVehicle(vehicleName, pos.x, pos.y, pos.z, GetEntityHeading(playerPed), true, false) SetPedIntoVehicle(playerPed, vehicle, -1) SetEntityAsNoLongerNeeded(vehicle) SetModelAsNoLongerNeeded(vehicleName) TriggerEvent('chat:addMessage', { args = { 'Enjoy your new ' .. vehicleName .. '!' } }) end, false) ``` What's going on: - `IsModelInCdimage` / `IsModelAVehicle` check the model exists and is a vehicle. Natives accept a model name string and hash it for you. - `RequestModel` + `HasModelLoaded` loads the model. `Wait(500)` gives the game time, without it the loop would freeze the game. - `PlayerPedId()` is your character, `GetEntityCoords` its position (a `vector3`). - `CreateVehicle(model, x, y, z, heading, isNetwork, netMissionEntity)` spawns it, networked so others see it. - `SetPedIntoVehicle(ped, vehicle, -1)` seats you as the driver (`-1`). - `SetModelAsNoLongerNeeded` frees the model from memory. Try `/car sultan` or `/car zentorno`. Find spawn names in the [Model & Hash Browser](/tools/model-hash-browser). > [!WARNING] > Spawning vehicles from the client is fine for a learning server, but on a real server anyone could trigger it. Real resources spawn vehicles on the server, after checking permissions and money. See [Client, server and events](/docs/development/client-server-events). ## 10. Organise as it grows When the resource gets bigger, split it: ```text hello_world/ ├─ fxmanifest.lua ├─ config.lua shared settings ├─ client/ │ └─ main.lua └─ server/ └─ main.lua ``` ```lua title="fxmanifest.lua" fx_version 'cerulean' game 'gta5' shared_script 'config.lua' client_scripts { 'client/*.lua' } server_scripts { 'server/*.lua' } ``` ```lua title="config.lua" Config = {} Config.DefaultCar = 'adder' Config.Greeting = 'Hello' ``` Shared scripts load first, on both sides, so `Config` is available in client and server files. ## What you learned - A resource is a folder with `fxmanifest.lua`. - `refresh` finds new resources, `ensure` starts or restarts them. - Client scripts run in the game, server scripts in FXServer, and `print` goes to F8 or the server console. - Errors show file and line. - Natives do the game work, and loading models needs a wait loop. Next: [Client, server and events](/docs/development/client-server-events). _Last updated: 2026-09-22_ --- ## Client, server and events URL: https://fivemad.com/docs/development/client-server-events How FiveM client and server scripts talk: local and net events, TriggerServerEvent, TriggerClientEvent, source, callbacks with ox_lib, and why you never trust the client. Every FiveM script runs on one of two sides, and the sides can only talk through **events**. Getting this right is the difference between a script that works and a script that gives cheaters free money. [FiveM Lua Scripting Network Events (CharlesHacks, Zero to Hero Ep. 4)](https://www.youtube.com/watch?v=6-M5o_wiQP0) (YouTube video) ## The two sides | | Client | Server | | --- | --- | --- | | Runs | On each player's PC, inside their game | Once, inside FXServer | | Knows | Its own player, what's near them, input, the screen | All players, the database, the truth | | Can do | Draw, read keys, play animations, local effects, most game natives | Kick, ban, save data, send events to anyone, server natives | | Trust | **None.** Cheaters control it. | Full. | A resource can have client, server and shared scripts. Shared scripts (config, utility functions) run on both sides, but each side has its own copy: changing `Config.x` on the client does nothing on the server. ## Local events `TriggerEvent` fires an event on the **same side**, to every resource that listens: ```lua -- any resource on the same side AddEventHandler('myres:somethingHappened', function(what) print('It happened: ' .. what) end) TriggerEvent('myres:somethingHappened', 'a thing') ``` Prefix event names with your resource name (`myres:...`) so they don't clash with other resources. ## Network events To cross from client to server or back, the receiving side must **register** the event as a net event. ### Client to server ```lua title="client.lua" RegisterCommand('report', function(_, args) local message = table.concat(args, ' ') TriggerServerEvent('myres:report', message) end, false) ``` ```lua title="server.lua" RegisterNetEvent('myres:report', function(message) local src = source -- who sent it, copy it right away if type(message) ~= 'string' or #message == 0 or #message > 200 then return end print(('[report] %s (%d): %s'):format(GetPlayerName(src), src, message)) end) ``` `source` is a global that FiveM sets to the **server ID of the player who triggered the event**. Copy it into a local at the top of the handler. After any `Wait` or async call, the global may belong to a different event. ### Server to client ```lua title="server.lua" TriggerClientEvent('myres:notify', src, 'Your report was sent') -- one player TriggerClientEvent('myres:notify', -1, 'Server restart in 5 min') -- everyone ``` ```lua title="client.lua" RegisterNetEvent('myres:notify', function(text) BeginTextCommandThefeedPost('STRING') AddTextComponentSubstringPlayerName(text) EndTextCommandThefeedPostTicker(false, false) end) ``` `RegisterNetEvent(name, handler)` both allows the event over the network and adds the handler. The older two step form (`RegisterNetEvent(name)` then `AddEventHandler(name, fn)`) does the same thing. > [!NOTE] > Without `RegisterNetEvent`, network triggers of that event are ignored. That's a safety feature: only events you explicitly register can be called from the other side. ### Big payloads Events are for small data. For large data (a big table, a long string), use `TriggerLatentClientEvent(name, target, bytesPerSecond, ...)` or `TriggerLatentServerEvent`, which send it in the background without choking the connection. Or rethink: maybe the client only needs part of it. ## Getting an answer back: callbacks Events are fire and forget. When the client needs an answer ("can I afford this?"), use a **callback**. FiveM has no built in client/server callback, so use ox_lib's: ```lua title="server.lua" lib.callback.register('myres:getBalance', function(source) local player = exports.qbx_core:GetPlayer(source) -- or your framework return player and player.PlayerData.money.bank or 0 end) ``` ```lua title="client.lua" local balance = lib.callback.await('myres:getBalance', false) print('Bank balance: ' .. balance) ``` Both files need `shared_script '@ox_lib/init.lua'` in the manifest and `ox_lib` started. QBCore (`QBCore.Functions.CreateCallback` / `TriggerCallback`) and ESX (`ESX.RegisterServerCallback` / `ESX.TriggerServerCallback`) have their own versions. ## Security: never trust the client A cheater with an executor can call **any** net event you registered, with **any** arguments, as often as they like. So every server handler must assume the worst. ### Bad ```lua title="server.lua (DON'T)" RegisterNetEvent('fishing:sell', function(amount, price) local player = GetPlayer(source) player.addMoney(amount * price) -- client decided the price and the amount end) ``` ### Good ```lua title="server.lua" local FISH_PRICE = 25 local SELL_POINT = vector3(-1847.0, -1195.0, 14.3) local lastSell = {} RegisterNetEvent('fishing:sell', function() local src = source local player = GetPlayer(src) if not player then return end -- rate limit local now = os.time() if lastSell[src] and now - lastSell[src] < 2 then return end lastSell[src] = now -- position check on the server (OneSync) local ped = GetPlayerPed(src) if #(GetEntityCoords(ped) - SELL_POINT) > 5.0 then return end -- the server counts what the player has local count = player.getItemCount('fish') if count <= 0 then return end player.removeItem('fish', count) player.addMoney(count * FISH_PRICE) end) AddEventHandler('playerDropped', function() lastSell[source] = nil end) ``` The rules: 1. **The server decides values**: prices, rewards, amounts, item names come from server config, not from arguments. 2. **Use `source`** to know who's asking. Never accept a player ID as an argument to act on "yourself". 3. **Validate arguments**: type, range, length, whitelist (`if not ALLOWED[item] then return end`). 4. **Check the situation**: distance (OneSync lets the server read `GetEntityCoords(GetPlayerPed(src))`), job, cooldown, whether they actually have the item. 5. **Rate limit** anything that gives something. 6. **Don't trigger server events from client "loops"** that give rewards. Give rewards when the server confirms the action. 7. **Log** money and item changes, so you can find abuse later. ## Useful built in events | Event | Side | When | | --- | --- | --- | | `playerConnecting` | Server | A player starts connecting. Lets you defer, check bans, show adaptive cards. | | `playerJoining` | Server | The player got a server ID and is joining. | | `playerDropped` | Server | A player left. `source` is the player, first argument is the reason. | | `onResourceStart` / `onResourceStop` | Both | Any resource started or stopped. Check `GetCurrentResourceName() == resourceName` to react to your own. | | `onClientResourceStart` | Client | A resource started on this client. | | `gameEventTriggered` | Client | Game events like `CEventNetworkEntityDamage`. See [Game Damage Events](/tools/damage-events) for kills, deaths and vehicle damage. | ```lua title="server.lua" AddEventHandler('playerDropped', function(reason) local src = source print(('%s left: %s'):format(GetPlayerName(src), reason)) end) AddEventHandler('onResourceStop', function(resourceName) if resourceName ~= GetCurrentResourceName() then return end -- save state before the resource stops end) ``` ## Commands as the entry point `RegisterCommand` works on both sides. A client command that needs the server should just send an event, and let the server check permissions: ```lua title="server.lua" RegisterCommand('heal', function(source, args) local target = tonumber(args[1]) or source if not IsPlayerAceAllowed(source, 'myres.heal') then return end TriggerClientEvent('myres:heal', target) end, false) ``` ```cfg title="server.cfg" add_ace group.admin myres.heal allow ``` ## Common mistakes - Registering a client event with `AddEventHandler` only, then triggering it from the server: nothing happens, it isn't a net event. - Using `source` after a `Wait()` or inside a callback: copy it first. - Sending the full player list or huge tables every second: send changes only, or use [state bags](/docs/development/state-bags-onesync). - Trusting `GetPlayerName` for identity: names can be anything. Use identifiers or your framework's citizen ID. Next: [Natives](/docs/development/natives). _Last updated: 2026-09-22_ --- ## Natives: talking to the game URL: https://fivemad.com/docs/development/natives What FiveM natives are, how to find them on docs.fivem.net, read their signatures, use hashes and joaat, handle entities, and a cheat sheet of the natives you use most. **Natives** are the functions the game engine exposes: `GetEntityCoords`, `SetPedIntoVehicle`, `DrawMarker` and thousands more. FiveM adds its own **CFX natives** on top (`GetPlayerIdentifierByType`, `SetResourceKvp`, state bags...). Almost everything your scripts do in the game world goes through a native. [FiveM Lua Scripting Commands and Natives (CharlesHacks, Zero to Hero Ep. 3)](https://www.youtube.com/watch?v=CDzz67tp8FU) (YouTube video) ## Finding natives The reference is at **[docs.fivem.net/natives](https://docs.fivem.net/natives/)**. It lists every known native, grouped by namespace (`PLAYER`, `PED`, `VEHICLE`, `ENTITY`, `OBJECT`, `HUD`, `GRAPHICS`, `STREAMING`, `TASK`, `CFX`...), with parameters, return values and often community notes. The data comes from the open [citizenfx/natives](https://github.com/citizenfx/natives) repository. Tips for searching: - Guess the verb and the thing: `SetVehicle...`, `GetPed...`, `IsEntity...`, `Create...`, `Delete...`. - Filter by **client** or **server** on the page. Some natives exist only on the server (`GetPlayerIdentifierByType`, `DropPlayer`), most game natives only on the client. - Natives without a proper name show as `_0x1234ABCD` or `N_0x...`. They work, they just haven't been named yet. - Read the **examples and notes** at the bottom of a native's page. That's where people document the quirks. With the [VS Code setup](/docs/development#2-visual-studio-code) (Lua Language Server plus the FiveM native declarations), you get autocomplete and parameter hints for all of them. ## Reading a signature The docs show natives in C style: ```c Vehicle CREATE_VEHICLE(Hash modelHash, float x, float y, float z, float heading, BOOL isNetwork, BOOL netMissionEntity); ``` In Lua you call the PascalCase name: ```lua local veh = CreateVehicle(modelHash, x, y, z, heading, true, false) ``` - `Hash` is a number (see below), but most natives also accept a model name string and hash it. - `Vehicle`, `Ped`, `Object`, `Entity` are **entity handles**: numbers valid on this client only. - `BOOL` is `true` / `false` in Lua. - Parameters marked with `*` are pointers (outputs). In Lua they come back as extra return values: `local found, groundZ = GetGroundZFor_3dCoord(x, y, z, false)`. - `Vector3` returns are `vector3` values in Lua: `pos.x`, `pos.y`, `pos.z`, and you can subtract them and use `#(a - b)` for distance. ## Hashes and joaat GTA identifies models, weapons, animations sets and much more by a 32 bit **hash** of the name, computed with Jenkins one-at-a-time (**joaat**). ```lua local h1 = GetHashKey('adder') -- native, works everywhere local h2 = joaat('adder') -- CfxLua helper, same result local h3 = `adder` -- CfxLua backtick syntax, hashed at compile time print(h1 == h2, h2 == h3) -- true true ``` Hashes can be shown as signed or unsigned numbers, or as hex. `adder` is the same model whether you see it as a negative or positive number. Use the [joaat Hash Calculator](/tools/hash-calculator) to convert a name to all three forms, and the [Model & Hash Browser](/tools/model-hash-browser) to look up vehicles, peds and weapons with pictures. > [!TIP] > Hashes are case insensitive: `joaat('ADDER') == joaat('adder')`. That's why spawn names work in any case. ## Entities, handles and network IDs - An **entity handle** is a local number. Handle `123` on your client is not the same entity on another client or on the server. - To tell another machine about an entity, send its **network ID**: `NetworkGetNetworkIdFromEntity(entity)` on one side, `NetworkGetEntityFromNetworkId(netId)` on the other (use `NetToVeh` / `NetToPed` on the client if you like). - Check it still exists before using it: `DoesEntityExist(entity)`. - With OneSync, the **server** can read and create entities too: `GetEntityCoords(GetPlayerPed(src))`, `CreateVehicleServerSetter(...)`. See [State bags and OneSync](/docs/development/state-bags-onesync). ## Loading things before using them Models, animation dictionaries, particle assets, texture dictionaries and scaleforms must be **requested and loaded** before use: ```lua local function loadModel(model) local hash = type(model) == 'number' and model or joaat(model) if not IsModelInCdimage(hash) then return nil end RequestModel(hash) local timeout = GetGameTimer() + 5000 while not HasModelLoaded(hash) do if GetGameTimer() > timeout then return nil end Wait(0) end return hash end local function loadAnimDict(dict) RequestAnimDict(dict) while not HasAnimDictLoaded(dict) do Wait(0) end end ``` Release them when done (`SetModelAsNoLongerNeeded`, `RemoveAnimDict`). ox_lib has ready made helpers: `lib.requestModel`, `lib.requestAnimDict`, `lib.requestNamedPtfxAsset`. ## A cheat sheet of common natives ### Player and ped | Native | Use | | --- | --- | | `PlayerPedId()` | Your character's ped (client). Also available as `cache.ped` with ox_lib. | | `PlayerId()` | Your local player index (client). | | `GetPlayerServerId(PlayerId())` | Your server ID (client). | | `GetPlayerPed(serverId)` | A player's ped on the server (OneSync). | | `GetEntityCoords(ped)` / `GetEntityHeading(ped)` | Position and heading. | | `SetEntityCoords(ped, x, y, z, false, false, false, false)` | Teleport. | | `GetEntityHealth(ped)` / `SetEntityHealth(ped, 200)` | Health (peds: 100 dead, 200 full for the freemode ped). | | `IsPedInAnyVehicle(ped, false)` / `GetVehiclePedIsIn(ped, false)` | Vehicle checks. | | `GiveWeaponToPed(ped, joaat('weapon_pistol'), 50, false, true)` | Give a weapon. | | `TaskPlayAnim(ped, dict, name, 8.0, -8.0, -1, flags, 0, false, false, false)` | Play an animation. Build the flags with the [Animation Flags Calculator](/tools/animation-flags-calculator). | ### Vehicles | Native | Use | | --- | --- | | `CreateVehicle(model, x, y, z, heading, true, false)` | Spawn (client). | | `SetPedIntoVehicle(ped, veh, -1)` | Seat as driver. | | `SetVehicleNumberPlateText(veh, 'FIVEMAD')` | Plate. | | `SetVehicleFixed(veh)` / `SetVehicleEngineHealth(veh, 1000.0)` | Repair. | | `SetVehicleModKit(veh, 0)` then `SetVehicleMod(veh, modType, index, false)` | Tuning. | | `TaskVehicleDriveToCoord(...)` | AI driving. The driving style flag comes from the [Driving Style Calculator](/tools/driving-style-calculator). | | `DeleteEntity(veh)` | Remove. | ### World and UI | Native | Use | | --- | --- | | `AddBlipForCoord(x, y, z)` + `SetBlipSprite`, `SetBlipColour` | Map blips. Browse sprites and colours in the [Blip, Marker & Checkpoint Browser](/tools/blip-marker-browser). | | `DrawMarker(type, x, y, z, ...)` | 3D markers, must be called every frame. | | `IsControlJustPressed(0, 38)` | Key input. Control 38 is E. Find indexes in the [Controls Reference](/tools/controls-reference). | | `BeginTextCommandDisplayHelp('STRING')` ... | Help text top left. Colour codes like `~g~` preview in [Draw Text Colors](/tools/text-colors). | | `PlaySoundFrontend(-1, name, set, true)` | UI sounds. Find names in the [Sound Browser](/tools/sound-browser). | | `UseParticleFxAsset(asset)` + `StartParticleFxNonLoopedAtCoord(...)` | Particles. Names and dictionaries in the [Particle Effects List](/tools/particles-list) and with video previews on [/particles](/particles). | | `CreateObject(joaat(model), x, y, z, true, false, false)` | Props. Search models with pictures in the [Objects / Props List](/tools/objects-list). | ### CFX natives (FiveM specific) | Native | Use | | --- | --- | | `GetPlayerIdentifierByType(src, 'license')` | A player's identifier (server). | | `GetPlayers()` | All player server IDs (server). | | `DropPlayer(src, reason)` | Kick (server). | | `GetConvar('name', 'default')` | Read a convar. | | `SetResourceKvp` / `GetResourceKvpString` | Small persistent storage. | | `GetCurrentResourceName()` | Your resource's name. | | `PerformHttpRequest(url, cb, method, data, headers)` | HTTP from the server. | ## Coordinates Most natives take world coordinates. Get them in game by printing `GetEntityCoords(PlayerPedId())`, or pick them on the [Interactive Map](/tools/interactive-map), which shows coordinates as you move over the map. ## Common native mistakes - **Forgetting to load a model**: the entity doesn't appear or the game returns 0. - **Calling a per frame native once**: `DrawMarker`, `DrawText`, `DisableControlAction` must run every frame in a loop with `Wait(0)`. - **Using a client native on the server** (or the other way round): the docs page tells you which side it's for. - **Passing an integer where a float is expected** in C# or JS is an error, in Lua it's usually fine, but write `1.0` for clarity. - **Old names**: natives get renamed as people learn what they do. If a tutorial's native doesn't exist, search the hash on the natives page. Next: [Threads and performance](/docs/development/threads-performance). _Last updated: 2026-09-22_ --- ## Threads and performance URL: https://fivemad.com/docs/development/threads-performance Write FiveM scripts that don't eat frames: CreateThread and Wait, dynamic waits, distance checks, ox_lib points, resmon, the profiler and reading its results. Every client script shares the same game frame with GTA itself and every other resource. A resource that uses 1 ms per frame on a 60 FPS client is taking 6% of the frame budget. Ten of those and players feel it. This page shows how loops work, the patterns that keep them cheap, and how to measure. [FiveM Lua Scripting Threads and Controls (CharlesHacks, Zero to Hero Ep. 5)](https://www.youtube.com/watch?v=9Mg-AO-YtUA) (YouTube video) ## Threads and Wait Lua in FiveM uses coroutines. `CreateThread` starts one, and `Wait(ms)` pauses it and gives control back to the game: ```lua CreateThread(function() while true do -- do something Wait(1000) -- sleep one second end end) ``` - `Wait(0)` means "run again next frame". Needed for things drawn or checked every frame (markers, text, disabling controls). - A `while true` loop **without** a `Wait` freezes the game (client) or the server (server side). txAdmin will eventually restart a server stuck like this. - `Wait` only works inside a thread or an event/command handler, which already run as coroutines. - `SetTimeout(ms, fn)` runs a function once after a delay, without a loop. ## The classic mistake ```lua title="client.lua (slow)" CreateThread(function() while true do Wait(0) local pos = GetEntityCoords(PlayerPedId()) for _, shop in ipairs(Config.Shops) do -- 40 shops if #(pos - shop.coords) < 20.0 then DrawMarker(2, shop.coords.x, shop.coords.y, shop.coords.z, 0,0,0, 0,0,0, 0.3,0.3,0.3, 255,255,255,150, false,true,2, nil,nil,false) end end end end) ``` It checks 40 distances **every frame** even when you're on the other side of the map. Multiply by every resource written like this. ## Pattern 1: dynamic wait Sleep long when nothing is near, go per frame only when needed: ```lua title="client.lua" CreateThread(function() while true do local sleep = 1000 local pos = GetEntityCoords(PlayerPedId()) for _, shop in ipairs(Config.Shops) do local dist = #(pos - shop.coords) if dist < 20.0 then sleep = 0 DrawMarker(2, shop.coords.x, shop.coords.y, shop.coords.z, 0,0,0, 0,0,0, 0.3,0.3,0.3, 255,255,255,150, false,true,2, nil,nil,false) if dist < 1.5 and IsControlJustPressed(0, 38) then -- E openShop(shop) end end end Wait(sleep) end end) ``` Far from every shop, the loop runs once a second. That's usually a 20 to 50x cut in cost. ## Pattern 2: ox_lib points and zones ox_lib does the distance bookkeeping for you and only calls your code near the point: ```lua title="client.lua" for _, shop in ipairs(Config.Shops) do lib.points.new({ coords = shop.coords, distance = 20, nearby = function(self) -- runs every frame only while within 20 units DrawMarker(2, self.coords.x, self.coords.y, self.coords.z, 0,0,0, 0,0,0, 0.3,0.3,0.3, 255,255,255,150, false,true,2, nil,nil,false) if self.currentDistance < 1.5 and IsControlJustPressed(0, 38) then openShop(shop) end end, }) end ``` `lib.zones` does the same for boxes, spheres and polygons with `onEnter` / `onExit`. Interaction resources like **ox_target** avoid loops entirely: players aim at something and pick an option. ## Pattern 3: events instead of polling Don't check "is the player in a vehicle?" every frame if you can react to a change. ox_lib's `cache` updates values and fires events when they change: ```lua lib.onCache('vehicle', function(vehicle) if vehicle then print('Entered vehicle', vehicle) else print('Left vehicle') end end) ``` On the server, react to `playerDropped`, `onResourceStop`, state bag change handlers (see [State bags](/docs/development/state-bags-onesync)) instead of loops. ## More habits that matter - **Cache what doesn't change within a loop**: call `PlayerPedId()` once per iteration, not five times. (ox_lib's `cache.ped` keeps it for you.) - **Use vector math**: `#(a - b)` is faster and simpler than `GetDistanceBetweenCoords`. - **Don't create entities, blips or threads in loops** without cleaning them up. - **Avoid string building and table creation every frame**: they create garbage for the Lua GC. - **Server side, never block**: use async database calls (`MySQL.query` with a callback, or `.await` inside a thread), not busy waits. - **Don't send events every frame.** Send on change, or at most a few times per second, and batch. - **Unload what you load**: models, anim dicts, ptfx assets, scaleforms. ## Measuring: resmon Press F8 and type: ```text resmon 1 ``` The resource monitor shows each client resource's **CPU time in ms per frame** and memory. Rough guide: | ms | Meaning | | --- | --- | | `0.00` to `0.02` | Idle, great. | | `0.02` to `0.10` | Fine for most resources. | | `0.10` to `0.50` | Worth a look, especially if it's constant while nothing happens. | | `> 0.50` constant | Something runs every frame that shouldn't. | Test in the situations that matter: standing still, driving, near the resource's zone, with the UI open. A HUD or a target system will naturally use a bit more. On the server, txAdmin's performance chart shows tick times, and the server console prints `hitch` warnings when a tick takes too long. ## Measuring: the profiler For "which function exactly?", use the built in profiler. It works on the client (F8) and the server console: ```text profiler record 500 profiler view ``` - `profiler record 500` records 500 frames (the docs recommend 500). - `profiler status` shows whether it's still recording. - `profiler view` opens the result in Chrome's performance view (on the server, it prints a link you open yourself). - `profiler saveJSON myprofile.json` saves it to a file. In the view, the green graph is FPS and the yellow one CPU time. Spikes are hitches. Hover a frame to see which resource and which line took the time. To skip reading flame charts, drop the saved JSON into the [Profiler Analyzer](/tools/profiler-analyzer): it shows which resources and threads use your frame or tick time and suggests fixes. [Fivem Resmon & Event Log Tutorial (Lith Studios)](https://www.youtube.com/watch?v=yTSm2ba4RBk) (YouTube video) ## Server performance - **Tick time**: the server runs its main loop on one thread. Long running Lua on the server delays everything, including sync. - **Database**: slow queries show up as `mysql_slow_query_warning` messages when you set that convar. Add indexes to columns you search by (identifier, citizenid, plate). - **Entities**: thousands of networked objects hurt everyone. Clean up what your scripts spawn. - **Scheduled restarts** hide memory leaks but don't fix them. Find them with resmon's memory column and the profiler. ## Assets are performance too A perfectly coded server still stutters if it streams 4K textures on every car. Oversized `.ytd` files cause texture loss and memory pressure. See [Streaming custom assets](/docs/development/streaming-assets#keep-it-light) and the [YTD Optimizer](/tools/ytd-optimizer). Next: [State bags and OneSync](/docs/development/state-bags-onesync). _Last updated: 2026-09-22_ --- ## State bags, OneSync and entity ownership URL: https://fivemad.com/docs/development/state-bags-onesync Sync data the FiveM way: GlobalState, Player and Entity state bags, change handlers, replication rules, OneSync entity ownership, server side entities and routing buckets. With OneSync on, the server knows about every player and entity and decides which clients see what. On top of that, FiveM gives you **state bags**: key/value data attached to the server, a player or an entity, synced to clients automatically. Together they replace a lot of hand written event syncing. [How to use State Bags (CharlesHacks, FiveM Lua Scripting Master Series)](https://www.youtube.com/watch?v=6CSXtJpH0qQ) (YouTube video) ## OneSync in two minutes - Enabled with `set onesync on` in `server.cfg`. Every current framework requires it. - The server tracks all networked entities. Clients only receive entities near them: the culling radius is 424 units around each player. - Each networked entity has an **owner**: the client that simulates it (usually the closest or the one who created it). The owner sends updates, the server forwards them. - The server can **read** entity state (`GetEntityCoords(GetPlayerPed(src))`, `GetVehicleNumberPlateText`) and **create** entities. - **Routing buckets** split the world into separate dimensions. - Up to 48 slots free, up to 2048 with the right Cfx.re tier. ## State bags There are three kinds, all with the same API: | Bag | Where | Who can write (default) | | --- | --- | --- | | `GlobalState` | Server wide | Server only | | `Player(serverId).state` (server) / `LocalPlayer.state` (client) | One player | The server, or that player's client | | `Entity(entity).state` | One networked entity | The server, or the entity's owner | ### Set and read ```lua title="server.lua" GlobalState.weather = 'RAIN' GlobalState.maintenance = false Player(src).state:set('job', 'police', true) -- true = replicate to clients local veh = CreateVehicleServerSetter(`police3`, 'automobile', 441.0, -1019.0, 28.5, 90.0) Entity(veh).state:set('fuel', 100.0, true) ``` ```lua title="client.lua" print(GlobalState.weather) -- 'RAIN' print(LocalPlayer.state.job) -- 'police' local veh = GetVehiclePedIsIn(PlayerPedId(), false) if veh ~= 0 then print(Entity(veh).state.fuel) end ``` Setting with `.key = value` uses the default replication: values set by the server replicate to clients, values set by a client do **not** replicate. `state:set(key, value, replicated)` lets you choose. The server can also keep private data on a bag with `replicated = false`. ### React to changes ```lua title="client.lua" AddStateBagChangeHandler('fuel', nil, function(bagName, key, value, _reserved, replicated) local entity = GetEntityFromStateBagName(bagName) if entity == 0 then return end print(('Fuel of %d is now %.1f'):format(entity, value)) end) ``` - The second argument filters by bag name (`nil` for all bags). Bag names look like `player:12`, `entity:345` or `global`. - `GetEntityFromStateBagName` and `GetPlayerFromStateBagName` turn a bag name back into a handle. - The entity may not exist yet on this client when the handler fires, so check for `0`. ### Rules and limits - **Flat keys only.** Nested writes like `Entity(x).state.car.fuel = 5` don't sync, the getters and setters are naive. Use `Entity(x).state['car:fuel']` or set the whole table again. - **Keep values small.** Every replicated change goes to every client that can see the bag. - **Security**: by default a client can write its own player bag and bags of entities it owns (not replicated unless it chooses to). If your resources only set state from the server, set `sv_stateBagStrictMode true` so clients can't write at all. Never trust a value a client could have written. ## When to use what | You want | Use | | --- | --- | | A value everyone can read, changes rarely (weather, server flags) | `GlobalState` | | Per player data other scripts or clients need (job, duty, radio channel, is dead) | `Player(src).state` | | Data that belongs to a car or object (fuel, locked, owner, siren mode) | `Entity(ent).state` | | A one off action ("play this sound now") | An event | | A request with an answer | A callback | | Large or private data | Server memory or database, send only what's needed | ## Entity ownership - `NetworkGetEntityOwner(entity)` (server) returns the server ID of the client that owns it. - Ownership moves as players move. Scripts that change an entity (freeze it, set its velocity) should do it on the owner, or on the server with the server setters. - Before changing a networked entity on a client that doesn't own it, request control: `NetworkRequestControlOfEntity(entity)` and wait for `NetworkHasControlOfEntity(entity)`. It can fail or take time. - `SetEntityOrphanMode` (server) controls what happens to an entity when its owner leaves, so server created vehicles don't vanish. ## Creating entities on the server With OneSync the server can create entities, which is safer than trusting clients to spawn things: ```lua title="server.lua" RegisterNetEvent('garage:takeOut', function(plate) local src = source -- ...check that src owns this car and is near the garage... local coords = vector4(215.0, -810.0, 30.7, 157.0) local veh = CreateVehicleServerSetter(`sultan`, 'automobile', coords.x, coords.y, coords.z, coords.w) while not DoesEntityExist(veh) do Wait(0) end SetVehicleNumberPlateText(veh, plate) Entity(veh).state:set('owner', GetPlayerIdentifierByType(src, 'license'), true) TriggerClientEvent('garage:enter', src, NetworkGetNetworkIdFromEntity(veh)) end) ``` The client then gets the entity from the network ID: ```lua title="client.lua" RegisterNetEvent('garage:enter', function(netId) local veh = NetworkGetEntityFromNetworkId(netId) local timeout = GetGameTimer() + 3000 while not DoesEntityExist(veh) and GetGameTimer() < timeout do Wait(0) veh = NetworkGetEntityFromNetworkId(netId) end if DoesEntityExist(veh) then SetPedIntoVehicle(PlayerPedId(), veh, -1) end end) ``` `CreateVehicleServerSetter` is the recommended server vehicle native (it takes the vehicle type, like `automobile`, `bike`, `heli`). `CreateVehicle`, `CreatePed` and `CreateObjectNoOffset` also exist on the server. If you enable `sv_entityLockdown strict`, the server is the **only** place entities can be created, so this pattern becomes required. ## Routing buckets A routing bucket is a separate world. Players and entities in different buckets can't see or interact with each other. Bucket `0` is the default. ```lua title="server.lua" -- put a player in their own apartment instance SetPlayerRoutingBucket(src, 1000 + src) SetRoutingBucketPopulationEnabled(1000 + src, false) -- no ambient peds and traffic there SetRoutingBucketEntityLockdownMode(1000 + src, 'strict') -- back to the main world SetPlayerRoutingBucket(src, 0) ``` Use cases: character selection, apartments and instanced interiors, races, events, admin testing. Entities created by a player in a bucket stay in that bucket (`SetEntityRoutingBucket` moves them). [How to use Routing Buckets (CharlesHacks)](https://www.youtube.com/watch?v=Bh2JuQoWbno) (YouTube video) ## Common mistakes - Expecting a client written state value to show up on other clients: it doesn't unless replicated, and the server should be the writer anyway. - Nested table writes to state bags (see limits above). - Keeping entity handles across machines: send network IDs. - Deleting or changing an entity you don't own and wondering why it comes back. - Forgetting that players in another routing bucket are invisible to each other, then debugging "sync bugs". Next: [NUI basics](/docs/development/nui). _Last updated: 2026-09-22_ --- ## NUI basics: HTML interfaces in FiveM URL: https://fivemad.com/docs/development/nui Build FiveM UIs with NUI: ui_page and files, SendNUIMessage, RegisterNUICallback with fetch, SetNuiFocus, dev tools, React or Vue with a build step, and common pitfalls. **NUI** is FiveM's built in Chromium (CEF) browser. Every resource can have a web page that sits on top of the game: HUDs, menus, phones, inventories, loading screens. You write it with HTML, CSS and JavaScript, or any framework that builds to static files (React, Vue, Svelte, Solid...). [How to Create HUDs and UIs using NUI (CharlesHacks, Zero to Hero Ep. 7)](https://www.youtube.com/watch?v=Z2yUTkE94pQ) (YouTube video) ## How it fits together ```text Lua client script ── SendNUIMessage({...}) ──► your page (window 'message' event) Lua client script ◄── RegisterNUICallback ──── fetch('https:///') ``` - Lua sends data **to** the page with `SendNUIMessage`. - The page sends data **back** with an HTTP style `fetch` to `https:///`, which triggers a `RegisterNUICallback` handler in Lua. - `SetNuiFocus` decides whether the page gets the mouse and keyboard. - The page never talks to the server directly. If the server needs to know, Lua forwards it with an event. ## A minimal example ```text nui_demo/ ├─ fxmanifest.lua ├─ client.lua └─ html/ ├─ index.html ├─ style.css └─ app.js ``` ```lua title="fxmanifest.lua" fx_version 'cerulean' game 'gta5' client_script 'client.lua' ui_page 'html/index.html' files { 'html/index.html', 'html/style.css', 'html/app.js', } ``` Every file the page loads must be listed in `files`, or the client never downloads it and you get a blank or broken UI. ```html title="html/index.html" ``` ```css title="html/style.css" html, body { margin: 0; background: transparent; font-family: sans-serif; } .hidden { display: none; } #panel { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 24px; background: rgba(15, 15, 15, 0.9); color: #fff; border-radius: 8px; } ``` Keep the `body` background **transparent**, or the page covers the game. ```js title="html/app.js" const panel = document.getElementById('panel'); const title = document.getElementById('title'); window.addEventListener('message', (event) => { const data = event.data; if (data.action === 'open') { title.textContent = data.title; panel.classList.remove('hidden'); } else if (data.action === 'close') { panel.classList.add('hidden'); } }); function post(name, body = {}) { return fetch(`https://${GetParentResourceName()}/${name}`, { method: 'POST', headers: { 'Content-Type': 'application/json; charset=UTF-8' }, body: JSON.stringify(body), }).then((r) => r.json()); } document.getElementById('close').addEventListener('click', () => post('close')); document.addEventListener('keyup', (e) => { if (e.key === 'Escape') post('close'); }); ``` `GetParentResourceName()` is available inside NUI pages and returns your resource name, so the callback URL stays right if someone renames the folder. ```lua title="client.lua" local open = false local function setOpen(state) open = state SetNuiFocus(state, state) -- keyboard focus, mouse cursor SendNUIMessage({ action = state and 'open' or 'close', title = 'Hello from Lua' }) end RegisterCommand('demo', function() setOpen(not open) end, false) RegisterNUICallback('close', function(data, cb) setOpen(false) cb({ ok = true }) -- always answer, or fetch() hangs end) ``` `ensure nui_demo`, type `/demo`, and the panel appears with a mouse cursor. Esc or the button closes it. ## Focus `SetNuiFocus(hasFocus, hasCursor)`: - `SetNuiFocus(true, true)`: the page gets keyboard and mouse. The player can't move or use game controls. Use for menus. - `SetNuiFocus(false, false)`: the page is display only (HUDs). The game keeps control. - `SetNuiFocusKeepInput(true)` lets the game still receive keyboard input while the page has focus, for UIs where the player keeps walking. Disable the controls you don't want yourself. > [!WARNING] > Always give the player a way out (Esc, a close button) and release focus on close. A UI that keeps focus traps the player, who has to quit the game. Also release focus on `onResourceStop`. If your UI opens with Tab (inventories do), check `IsNuiFocused()` first so it doesn't steal focus from another open UI like the txAdmin menu. ## Debugging NUI Type `nui_devtools` in the F8 console to open Chrome DevTools for NUI: console logs, element inspector, network tab. Errors in your JavaScript show there, not in F8. Other tips: - Develop the page in a normal browser first, faking the `message` events with `window.postMessage({ action: 'open', title: 'test' })`. - `ui_page` can point to a dev server URL (`ui_page 'http://localhost:5173'`) while you work, so hot reload works. Switch back to the built file before you ship. ## React, Vue and friends Frameworks work fine. You build to static files and point `ui_page` at the built `index.html`: ```lua title="fxmanifest.lua" ui_page 'web/build/index.html' files { 'web/build/index.html', 'web/build/**/*', } ``` - Use **relative** asset paths in your build (Vite: `base: './'`), because the page is served from `https://cfx-nui-/`. - Starters save setup time: [project-error/fivem-react-boilerplate-lua](https://github.com/project-error/fivem-react-boilerplate-lua) (React + TypeScript + Lua) and [overextended/fivem-typescript-boilerplate](https://github.com/overextended/fivem-typescript-boilerplate). - Ship the **built** folder in releases. Server owners shouldn't need Node to run your resource. ## Loading screens A loading screen is a special NUI page shown while the player joins: ```lua title="fxmanifest.lua" loadscreen 'html/index.html' files { 'html/**/*' } -- optional: keep it until you close it yourself loadscreen_manual_shutdown 'yes' ``` With manual shutdown, call `ShutdownLoadingScreenNui()` from a client script when your spawn is ready, or players stay on the loading screen forever. ## Performance - NUI pages that animate constantly (CSS animations, requestAnimationFrame, big videos) cost GPU and CPU on every client. Pause them when hidden. - Don't `SendNUIMessage` every frame. Send when data changes, or a few times per second for HUD values. - Keep images reasonable in size. Every file in `files` is downloaded by every player. ## Common mistakes | Symptom | Cause | | --- | --- | | Blank UI | `ui_page` or its assets not listed in `files`, wrong path, or absolute asset paths in a framework build. | | `fetch` never resolves | The Lua `RegisterNUICallback` handler didn't call `cb()`. | | UI shows but clicks do nothing | `SetNuiFocus(true, true)` not called. | | Player stuck with a cursor | Focus not released on close or on resource stop. | | White or black background over the game | `body` or `html` background isn't transparent. | | Works in browser, not in game | Using APIs NUI doesn't allow, or the callback URL doesn't match the resource name. Use `GetParentResourceName()`. | Next: [Exports and dependencies](/docs/development/exports-dependencies). _Last updated: 2026-09-22_ --- ## Exports and dependencies URL: https://fivemad.com/docs/development/exports-dependencies Share code between FiveM resources with exports, call framework functions, declare dependencies in fxmanifest, import @resource files and bridge frameworks. Resources are isolated from each other: a global variable in one resource doesn't exist in another. To share functionality you use **exports** (call a function in another resource) and **shared files** (load another resource's file into yours with `@resource/path`). **Dependencies** make sure the resource you rely on is there and starts first. [FiveM Scripting 15: Server and Client Sided Exports (Jeva)](https://www.youtube.com/watch?v=7VvwSEXYO-w) (YouTube video) ## Exports ### Defining an export ```lua title="banking/server.lua" local accounts = {} exports('getBalance', function(identifier) return accounts[identifier] or 0 end) exports('addBalance', function(identifier, amount) if type(amount) ~= 'number' or amount <= 0 then return false end accounts[identifier] = (accounts[identifier] or 0) + amount return true end) ``` `exports(name, fn)` works in Lua without any manifest entry. Exports are per side: a server export is only callable from server scripts, a client export only from client scripts. ### Calling an export ```lua title="another_resource/server.lua" local balance = exports.banking:getBalance(identifier) exports['banking']:addBalance(identifier, 500) ``` Use the bracket form when the resource name has a dash: `exports['qb-core']:GetCoreObject()`. Note the **colon**: exports are called like methods. If the resource isn't started, the call errors with `No such export getBalance in resource banking`. Guard with `GetResourceState('banking') == 'started'` if it's optional. ### JavaScript and C# ```js exports('getBalance', (identifier) => accounts[identifier] ?? 0); const balance = exports.banking.getBalance(identifier); ``` C# resources call them through `Exports["banking"].getBalance(identifier)`. ## Using a framework through exports Frameworks expose their core object or functions as exports: ```lua -- QBCore local QBCore = exports['qb-core']:GetCoreObject() local Player = QBCore.Functions.GetPlayer(source) -- Qbox local player = exports.qbx_core:GetPlayer(source) exports.qbx_core:AddMoney(source, 'cash', 100, 'fishing') -- ESX Legacy local ESX = exports['es_extended']:getSharedObject() local xPlayer = ESX.GetPlayerFromId(source) -- ox_inventory exports.ox_inventory:AddItem(source, 'water', 1) ``` See the [Frameworks](/docs/frameworks) pages for more. ## Importing files with @resource A manifest can load another resource's file as if it were yours: ```lua title="fxmanifest.lua" shared_script '@ox_lib/init.lua' server_script '@oxmysql/lib/MySQL.lua' ``` - `@ox_lib/init.lua` sets up the `lib` global and `cache` in your resource. - `@oxmysql/lib/MySQL.lua` gives you the `MySQL` global. - `@qbx_core/modules/lib.lua` and `@qbx_core/modules/playerdata.lua` are Qbox helpers. - `@es_extended/imports.lua` sets up `ESX` in your resource. The file runs inside **your** resource's environment, so this is faster than calling an export for every small helper. The other resource must be present (and for ox_lib, started first). ## Dependencies List what your resource needs in the manifest: ```lua title="fxmanifest.lua" dependencies { 'oxmysql', 'ox_lib', '/onesync', -- requires OneSync '/server:12913', -- requires at least this server artifact '/gameBuild:3095', -- requires at least this game build (name like 'h4' works too) } ``` FXServer then: - starts listed resources before yours, and refuses to start yours if one is missing, - refuses to start it if the server or game requirements aren't met, with a clear error. This is much more reliable than hoping `ensure` order in `server.cfg` is right. The `/server:`, `/onesync`, `/gameBuild:`, `/policy:` and `/native:` forms come from the official manifest reference. The build numbers above are just examples: use the ones your resource really needs. ## `provide`: replacing another resource ```lua title="fxmanifest.lua" provide 'mysql-async' ``` Tells FXServer this resource satisfies dependencies on `mysql-async`. oxmysql uses it so old resources that depend on mysql-async or ghmattimysql keep working. Only use `provide` if you really implement the same API. ## Writing framework independent resources If you want your resource to work on QBCore, Qbox and ESX, don't sprinkle framework calls everywhere. Put them behind a small **bridge**: ```lua title="bridge/server.lua" Bridge = {} local function detect() if GetResourceState('qbx_core') == 'started' then return 'qbx' end if GetResourceState('qb-core') == 'started' then return 'qb' end if GetResourceState('es_extended') == 'started' then return 'esx' end return 'standalone' end local fw = detect() local QBCore = fw == 'qb' and exports['qb-core']:GetCoreObject() or nil local ESX = fw == 'esx' and exports['es_extended']:getSharedObject() or nil function Bridge.addMoney(src, amount) if fw == 'qbx' then return exports.qbx_core:AddMoney(src, 'cash', amount) elseif fw == 'qb' then local p = QBCore.Functions.GetPlayer(src) return p and p.Functions.AddMoney('cash', amount) elseif fw == 'esx' then local x = ESX.GetPlayerFromId(src) if x then x.addMoney(amount) return true end end return false end ``` The rest of your code calls `Bridge.addMoney(src, 100)` and never cares which framework runs. Paid resources on Tebex use exactly this pattern, often leaving the bridge files open under `escrow_ignore`. (Qbox also ships QBCore compatibility, so many `qb-core` calls work on Qbox too.) ## Load order inside a resource - `shared_scripts` load first, on both sides. - Then `client_scripts` (client) or `server_scripts` (server), in the order listed. - Globs (`client/*.lua`) load in alphabetical order. So put `config.lua` and library imports at the top of `shared_scripts`. ## Common mistakes - `No such export`: wrong resource name (check the folder name), resource not started, calling a server export from the client (or the reverse), or the export was renamed in a new version. - `attempt to index a nil value (global 'lib')`: you forgot `shared_script '@ox_lib/init.lua'`. - Circular dependencies: A depends on B and B on A. Move shared code into a third resource. - Exporting huge tables every call: exports copy data between resources. Return what's needed. Next: [Debugging](/docs/development/debugging). _Last updated: 2026-09-22_ --- ## Debugging FiveM resources URL: https://fivemad.com/docs/development/debugging Find and fix bugs in FiveM scripts: read SCRIPT ERROR lines, print and dump tables, the F8 and server consoles, NUI devtools, common Lua errors and a debugging routine. Most FiveM bugs are found in minutes if you know where to look. This page is the routine: where errors show up, how to read them, how to narrow down a bug, and the errors you'll see most. ## Where output goes | Output from | Shows in | | --- | --- | | Server scripts (`print`, errors) | The server console / txAdmin **Live Console**, and txAdmin's log files | | Client scripts | The **F8** console in game, and `CitizenFX.log` in the FiveM application data `logs` folder | | NUI JavaScript | NUI DevTools (`nui_devtools` in F8) | | Resource start/stop messages | Server console | Keep the F8 console and the Live Console open side by side while you test. ## Reading a script error ```text SCRIPT ERROR: @my_shop/server/main.lua:42: attempt to perform arithmetic on a nil value (local 'price') > handler (@my_shop/server/main.lua:42) > fn (@ox_lib/imports/callback/server.lua:28) ``` - `@my_shop/server/main.lua:42`: resource, file, **line**. Go there first. - `attempt to perform arithmetic on a nil value (local 'price')`: what went wrong and which variable. `price` is `nil` on line 42. - The lines starting with `>` are the **stack trace**: how the code got there. Here an ox_lib callback called our handler. Now ask: why is `price` nil? Usually a table lookup with a key that doesn't exist (`Config.Prices[item]` with a typo in `item`), or an argument the other side didn't send. ## Print debugging Plain `print` is still the most used tool: ```lua print('buy called', src, item, amount) print(json.encode(data, { indent = true })) -- dump a table ``` - `json.encode` turns tables into readable text. `print(someTable)` alone prints only `table: 0x...`. - ox_lib has `lib.print.info(...)`, `lib.print.debug(...)` with log levels you can switch with a convar (`ox:printlevel`). - Prefix your prints with the resource or function name so you can find them among other output. - Remove debug prints (or put them behind a `Config.Debug` flag) before release. Spamming the console costs performance. ## A debugging routine 1. **Reproduce it.** Find the exact steps that trigger the bug. 2. **Read the first error**, not the last. Later errors are often side effects. 3. **Check which side** the problem is on: does the server get the event? Put a print at the top of the server handler. Does the client get the reply? Print in the client handler. 4. **Check the inputs**: print the arguments at the start of the function. Half of all bugs are "the value wasn't what I thought". 5. **Cut it in half**: comment out half of the suspicious code, see if the bug stays, repeat. 6. **Restart just your resource** (`ensure name`) instead of the whole server, it's faster. But if things behave oddly after many restarts, restart the server: some resources don't clean up on stop. 7. **Check the load order**: framework not started yet, dependency missing, `ensure` order in `server.cfg`. 8. **Change one thing at a time**, then test. ## The errors you'll see most | Error | Usually means | | --- | --- | | `attempt to index a nil value (global 'QBCore')` / `'ESX'` / `'lib'` | You never got the framework or library object in this file or resource. Add `local QBCore = exports['qb-core']:GetCoreObject()`, `shared_script '@ox_lib/init.lua'`, or `@es_extended/imports.lua`. | | `attempt to index a nil value (local 'Player')` | `GetPlayer(source)` returned nil: wrong `source` (used after a `Wait`), player not loaded yet, or the player left. Check before using. | | `attempt to call a nil value (field 'X')` | Calling a function that doesn't exist: typo, wrong framework version, or a method renamed in an update. | | `No such export X in resource Y` | Resource not started, wrong name, wrong side, or the export doesn't exist in that version. | | `attempt to compare number with nil` | A value you compare is missing. Often a config key typo. | | `bad argument #1 to 'X'` | Wrong type passed to a function or native (a string where a number is expected, a nil). | | `Couldn't load resource X` | Manifest syntax error or missing file. | | `SCRIPT ERROR ... stack overflow` | A function calls itself forever, or two events trigger each other. | | `json.decode` error | The string isn't valid JSON, often an HTML error page from `PerformHttpRequest`. | | Nothing happens, no error | The event isn't registered as a net event, the handler name has a typo, or the code never runs. Add a print at the entry point. | ## Client debugging tools - **F8 console commands**: `resmon 1` (resource CPU and memory), `netgraph` (network graph), `cl_drawfps true`, `profiler record` (see [Threads and performance](/docs/development/threads-performance)). - **`nui_devtools`**: Chrome DevTools for NUI. Your JavaScript errors and `console.log` appear there. - **Draw it**: draw a marker or text at the coordinates your code uses, to see where it thinks things are. - **Coordinates**: print `GetEntityCoords(PlayerPedId())` and `GetEntityHeading(PlayerPedId())` to grab positions for configs, or pick them on the [Interactive Map](/tools/interactive-map). ## Server debugging tools - The txAdmin **Live Console** with search, and the log files in `txData`. - `status` lists players and their IDs. - `mysql_debug` and `mysql_slow_query_warning` convars for oxmysql. - The server **profiler** (`profiler record 500` in the server console, then `profiler saveJSON file.json`) for slow ticks. Drop the file into the [Profiler Analyzer](/tools/profiler-analyzer) to see which resources use the most time. - txAdmin's performance chart for hitches over time. ## Debugging streamed assets - Missing model or texture: check the file is in `stream/`, the name matches exactly (case matters on Linux), and the resource is started. The [Vehicle Pack Validator](/tools/vehicle-pack-validator) checks a vehicle resource for broken links between metas, stream files and the manifest. - A `data_file` path that doesn't match a file listed in `files` is silently ignored. - Oversized asset warnings in the server console point to textures that need shrinking. More in [Streaming custom assets](/docs/development/streaming-assets). ## Tools that make debugging easier - The Lua Language Server in VS Code flags undefined globals and wrong argument counts **before** you run the code. See [Start developing](/docs/development#2-visual-studio-code). - Git: `git diff` shows exactly what changed since it last worked. `git stash` lets you test the old version in seconds. ## Asking for help When you're stuck, a good question gets an answer fast: - What you're trying to do, in one sentence. - The exact error text (copied, not a phone photo of the screen). - The relevant code, formatted, with line numbers matching the error. - What you already tried. - Artifact build, framework and version. Post it on [forum.cfx.re](https://forum.cfx.re) in the Development category or in the framework's Discord support channel. Next: [Streaming custom assets](/docs/development/streaming-assets). _Last updated: 2026-09-22_ --- ## Streaming custom assets URL: https://fivemad.com/docs/development/streaming-assets Add custom vehicles, clothing, props, maps, MLOs and sounds to FiveM: the stream folder, data_file entries, YDR, YFT, YTD, YMAP and YTYP files, naming rules and size limits. "Streaming" means sending game assets (models, textures, maps, sounds) from your server to players and loading them into the game. In FiveM it is mostly automatic: put the files in a resource's `stream` folder, add the right `data_file` lines for metadata, and `ensure` the resource. [FiveM Vehicle Development: Spawning FiveM ready, add-on and replace vehicles (Snowy Aura)](https://www.youtube.com/watch?v=XLfHruC_hv8) (YouTube video) ## The two halves of an asset 1. **Binary assets** go in `stream/`: `.yft` (vehicles and fragments), `.ydr` (props), `.ydd` (clothing and ped parts), `.ytd` (textures), `.ybn` (collisions), `.ymap` (placements), `.ytyp` (archetypes), `.ycd` (animations) and friends. Everything under `stream/`, including subfolders, is registered with the game automatically. 2. **Metadata** (`.meta` XML files like `vehicles.meta`) goes anywhere else in the resource, listed in `files` and registered with a `data_file` line. This tells the game what the new things **are**. ```text my_asset_pack/ ├─ fxmanifest.lua ├─ stream/ binary assets, auto streamed │ ├─ mycar.yft │ ├─ mycar_hi.yft │ └─ mycar.ytd └─ data/ metadata, registered with data_file ├─ vehicles.meta ├─ handling.meta ├─ carcols.meta └─ carvariations.meta ``` ## Common data_file types | data_file | File | For | | --- | --- | --- | | `VEHICLE_METADATA_FILE` | `vehicles.meta` | Vehicle definitions (model name, handling id, layout, class) | | `HANDLING_FILE` | `handling.meta` | Driving physics | | `CARCOLS_FILE` | `carcols.meta` | Mod kits, sirens, lights | | `VEHICLE_VARIATION_FILE` | `carvariations.meta` | Colours, liveries, extras, kits per model | | `VEHICLE_LAYOUTS_FILE` | `vehiclelayouts.meta` | Seat and entry animations (custom layouts) | | `DLCTEXT_FILE` | `dlctext.meta` | Text labels | | `SHOP_PED_APPAREL_META_FILE` | `_.meta` | Add-on clothing collections | | `DLC_ITYP_REQUEST` | `*.ytyp` | Custom archetypes (props and MLOs) | | `WEAPONINFO_FILE`, `WEAPON_ANIMATIONS_FILE`, `WEAPONCOMPONENTSINFO_FILE` | weapon metas | Add-on or edited weapons | | `AUDIO_GAMEDATA`, `AUDIO_SOUNDDATA`, `AUDIO_SYNTHDATA`, `AUDIO_WAVEPACK` | audio `.rel` data and `.awc` folders | Custom sounds and engine audio | | `TIMECYCLEMOD_FILE` | timecycle modifiers | Visual effects and interior lighting | Every `data_file` path must also be in `files { }`, or clients never download it. ## Vehicles ```lua title="fxmanifest.lua" fx_version 'cerulean' game 'gta5' files { 'data/**/vehicles.meta', 'data/**/handling.meta', 'data/**/carcols.meta', 'data/**/carvariations.meta', } data_file 'VEHICLE_METADATA_FILE' 'data/**/vehicles.meta' data_file 'HANDLING_FILE' 'data/**/handling.meta' data_file 'CARCOLS_FILE' 'data/**/carcols.meta' data_file 'VEHICLE_VARIATION_FILE' 'data/**/carvariations.meta' client_script 'names.lua' ``` ```lua title="names.lua" AddTextEntry('mycar', 'My Custom Car') -- the name shown in game ``` Things that break vehicle packs: - The `modelName` in `vehicles.meta` must match the `.yft` file name. - The `handlingId` in `vehicles.meta` must exist in `handling.meta`. - `kits` in `carvariations.meta` must reference a mod kit ID that exists in `carcols.meta`, and **mod kit IDs and siren IDs must be unique** across all your packs. Clashes make tuning parts or sirens show up on the wrong car. - Duplicate model names across two packs: one silently wins. The [Vehicle Pack Validator](/tools/vehicle-pack-validator) finds these broken links in a whole vehicle resource. The [Vehicle Handling Editor](/tools/vehicle-handling-editor) edits handling from a UI, and the [Vehicle Sirens Editor](/tools/vehicle-sirens) edits `carcols.meta` sirens and finds free or clashing siren IDs. Installation steps for server owners are in [Vehicle packs](/docs/resources/vehicle-packs). ## Clothing There are two ways: - **Replace** clothing: files named like the game's own (`jbib_003_u.ydd`) replace a base game item for everyone. Simple but destructive, and conflicts between packs are common. - **Add-on** clothing (recommended): a new collection that adds new drawables on top of the base game. An add-on clothing pack for the male freemode ped looks like this: ```text my_clothes/ ├─ fxmanifest.lua ├─ mp_m_freemode_01_mp_m_mypack.meta collection metadata └─ stream/ ├─ mp_m_freemode_01_mp_m_mypack.ymt ped variation data ├─ mp_m_freemode_01_mp_m_mypack^jbib_000_u.ydd └─ mp_m_freemode_01_mp_m_mypack^jbib_diff_000_a_uni.ytd ``` ```lua title="fxmanifest.lua" fx_version 'cerulean' game 'gta5' files { 'mp_m_freemode_01_mp_m_mypack.meta' } data_file 'SHOP_PED_APPAREL_META_FILE' 'mp_m_freemode_01_mp_m_mypack.meta' ``` The file names encode the ped, the collection, the component (`jbib` = tops, `lowr` = legs, `feet`, `accs`, `hair`...), the drawable number and texture variants, and the `.ymt` must match the drawables exactly. Getting this right by hand is tedious, which is why most people use a tool: community tools like Durty Cloth Tool or grzyClothTool build whole packs, and the [YMT Creator](/tools/ymt-creator) generates the `.ymt` for a pack from its drawable and texture file names. Server owner steps are in [Maps, MLOs and clothing](/docs/resources/maps-mlos-clothing). ## Props A custom prop needs: - the model `.ydr` (and its `.ytd` if textures aren't embedded) and usually a `.ybn` collision, - a `.ytyp` that defines the archetype (name, bounding box, LOD distance, textures), - a `.ymap` if you want it placed in the world, or `CreateObject` from a script. ```lua title="fxmanifest.lua" fx_version 'cerulean' game 'gta5' data_file 'DLC_ITYP_REQUEST' 'stream/my_props.ytyp' ``` Create the `.ytyp` with the [YTYP Creator](/tools/ytyp-creator), which calculates the bounds from your model's XML, and find base game props to reuse in the [Objects / Props List](/tools/objects-list). ## Maps (YMAP) and MLOs - A `.ymap` places entities (props, buildings) with position, rotation and LOD distance. Drop it in `stream/` and it loads with the resource. - Map resources traditionally add `this_is_a_map 'yes'` to the manifest. - An **MLO** is an interior: a `.ytyp` with rooms, portals and entity sets, plus a `.ymap` that places it, plus models and collisions. Most MLO resources declare their `.ytyp` with `DLC_ITYP_REQUEST`. - Many MLOs replace or edit parts of the base map, so two MLOs in the same spot conflict. Only use one per location. Build simple placements with the [YMAP Builder](/tools/ymap-builder) (props by coordinates, with correct rotations, extents and LOD distances), or use CodeWalker for full map editing. The [Interactive Map](/tools/interactive-map) helps you find coordinates. ## Sounds Custom sounds in FiveM use the game's native audio system: an `.awc` wave bank plus `.dat54.rel` data, registered with `AUDIO_WAVEPACK` and `AUDIO_SOUNDDATA` entries, then played with natives like `PlaySoundFromEntity`. The [Native Audio Builder](/tools/native-audio-builder) turns WAV, MP3 or OGG files into a ready resource (bank, data, `fxmanifest.lua` and Lua). For simple UI sounds, NUI audio (an `