# server.cfg for ESX Legacy (/docs/getting-started/server-cfg)

`server.cfg` is the file FXServer executes on startup. For ESX Legacy it must do four things: enable OneSync, tell `oxmysql` how to reach the database, start the resources in the right order and grant admin permissions. This page walks through a complete ESX `server.cfg` and lists every convar that ESX actually reads.

## Complete example [#complete-example]

This is a cleaned-up version of the file the official recipe generates. Replace the placeholder values.

```bash title="server.cfg"
## Network
endpoint_add_tcp "0.0.0.0:30120"
endpoint_add_udp "0.0.0.0:30120"
sv_endpointPrivacy true

## Server identity
sv_licenseKey "your-license-key"
sv_hostname "My Server | ESX Legacy"
sets sv_projectName "My Server"
sets sv_projectDesc "Serious roleplay on ESX Legacy"
sets tags "esx, esx legacy, roleplay"
sets locale "en-US"
load_server_icon esxLogo.png
sv_maxclients 48
sv_enforceGameBuild 3258

## Required by ESX
set onesync on
set mysql_connection_string "mysql://esx:change-me@localhost:3306/es_extended?charset=utf8mb4"
set resources_useSystemChat true

## ESX options
setr esx:locale "en"
#setr esx:identifier "license"

## Security convars from the recipe
sv_enableNetworkedSounds false
sv_enableNetworkedScriptEntityStates false
sv_enableNetworkedPhoneExplosions false
sv_filterRequestControl 2

## Admin permissions
add_principal group.admin group.user
add_ace group.admin command allow
add_ace group.admin command.quit deny
add_ace resource.es_extended command.add_ace allow
add_ace resource.es_extended command.add_principal allow
add_ace resource.es_extended command.remove_principal allow
add_ace resource.es_extended command.stop allow
add_principal identifier.license:0123456789abcdef0123456789abcdef01234567 group.admin

## pma-voice
setr voice_useNativeAudio true
setr voice_useSendingRangeOnly true
setr voice_enableRadioAnim 1
setr voice_enableUi 0

## esx_whitelist (only if you use it)
set discord:botToken ""
set whitelist:webhook ""

## Start order
ensure chat
ensure oxmysql
ensure esx_lib
ensure es_extended
ensure [core]
ensure [standalone]
ensure [esx_addons]
## your own resources below
```

## OneSync [#onesync]

```bash title="server.cfg"
set onesync on
```

ESX Legacy needs OneSync **Infinity**, which is what `on` means. When a player connects, `es_extended` checks the `onesync` convar and rejects the connection with `ESX Requires Onesync Infinity to work` if it is `off` or `legacy`. The server-side helpers in [ESX.OneSync](/docs/es_extended/server/onesync) also depend on it.

If you run the server through txAdmin, OneSync is controlled in **Settings > FXServer** (the recipe enables it). A value set by txAdmin on the command line overrides `server.cfg`.

## Database connection [#database-connection]

`oxmysql` reads `mysql_connection_string`. Two formats work:

```bash title="server.cfg"
# URI format (recommended)
set mysql_connection_string "mysql://esx:change-me@localhost:3306/es_extended?charset=utf8mb4"

# Key-value format
set mysql_connection_string "user=esx;password=change-me;host=localhost;port=3306;database=es_extended"
```

| Part | Meaning |
| --- | --- |
| `esx` / `change-me` | database user and password. With no password, use `mysql://root@localhost/es_extended`. |
| `localhost:3306` | host and port of MariaDB |
| `es_extended` | database name, the one you imported `legacy.sql` into |
| `charset=utf8mb4` | needed for names and messages with emoji or non-Latin characters |

`esx_multicharacter` also reads this convar to find the database name (it parses the path of the URI or the `database=` key). If the convar is empty, it stops with `unable to determine database from mysql_connection_string`.

<Callout type="warn" title="Special characters in passwords">
In the URI format, characters like `@`, `:`, `/`, `#` or `?` in the password break parsing. URL-encode them (`@` becomes `%40`) or use the key-value format. Also never paste your connection string into Discord or GitHub; it contains the password.
</Callout>

Useful oxmysql convars such as `mysql_ui` (in-game query viewer for admins) and `mysql_slow_query_warning` are documented by [overextended](https://overextended.dev/oxmysql). See also our [oxmysql guide](/docs/guides/oxmysql).

## Start order [#start-order]

```bash title="server.cfg"
ensure chat
ensure oxmysql
ensure esx_lib
ensure es_extended
ensure [core]
ensure [standalone]
ensure [esx_addons]
```

- `oxmysql` and `esx_lib` must run before `es_extended`, which loads files from both.
- `es_extended` must run before every resource that uses `ESX`.
- `[core]` is a category folder. FiveM starts all resources inside it and respects their declared dependencies.
- Put your own resources **after** the core and addons.

`chat` refers to the chat that is built into recent server builds; `set resources_useSystemChat true` tells FXServer to use it. The recipe deletes the old `chat` resource from `[cfx-default]` for that reason, and `esx_chat_theme` in `[core]` styles it.

## Admin permissions (ACE) [#admin-permissions-ace]

ESX has two permission layers that work together:

1. **FiveM ACE principals** decide who may run which command. `ESX.RegisterCommand` adds `add_ace group.<name> command.<command> allow` for every group a command allows.
2. **The ESX group** (`user`, `admin` and any you add) is stored in the `group` column of `users` and returned by `xPlayer.getGroup()`. When a group is set, ESX also runs `add_principal identifier.<license> group.<group>` for that player, so the ACE layer follows the ESX group.

The lines from the recipe:

```bash title="server.cfg"
add_principal group.admin group.user          # admins inherit everything users can do
add_ace group.admin command allow             # admins may run every command
add_ace group.admin command.quit deny         # ...except shutting down the server
add_ace resource.es_extended command.add_ace allow
add_ace resource.es_extended command.add_principal allow
add_ace resource.es_extended command.remove_principal allow
add_ace resource.es_extended command.stop allow
```

The four `resource.es_extended` lines are required. ESX runs `add_ace` and `add_principal` itself to grant command permissions to groups and to link each player to their ESX group. Without these lines those calls are denied, so a player whose ESX group is `admin` (set with `/setgroup` or in the database) gets no command permissions unless you also listed them in `server.cfg`.

To make yourself admin, add your license as a principal of `group.admin`:

```bash title="server.cfg"
add_principal identifier.license:0123456789abcdef0123456789abcdef01234567 group.admin
```

Players who have the `command` ACE get the `admin` group when their character is **created**. For an existing character, run `setgroup <id> admin` in the server console once. Details and custom groups: [Admin permissions](/docs/guides/admin-permissions).

<Callout type="error" title="sv_lan makes everyone admin">
`es_extended` treats every player as admin when `sv_lan` is `true`. That is convenient for local testing, but never leave it on for a public server.
</Callout>

## Convars read by ESX [#convars-read-by-esx]

These are all the convars read by `es_extended` and the `[core]` resources in 1.16.4.

### es_extended [#es_extended]

| Convar | Default | Description |
| --- | --- | --- |
| `esx:locale` | not set | Language code, e.g. `en`, `de`, `fr`. Use `setr`. If not set, ESX uses `txAdmin-locale`, then `en`. |
| `esx:localeFallback` | `true` | When a translation key is missing, show the English text. Set to `false` while writing a new translation to see missing keys. |
| `esx:identifier` | `license` | Identifier type used to store players (`license`, `steam`, `discord`, `fivem`, ...). Use `setr`. Changing it on a live server makes all existing players appear as new players. |
| `onesync` | `off` | Must be `on`. |
| `sv_lan` | not set | `true` grants admin to everyone (see above). |
| `sv_enforceGameBuild` | `1604` | Read and returned to clients through a callback. Set it to the game build your server uses. |
| `sv_projectName`, `sv_maxClients` | | Used for the Discord rich presence text. |
| `inventory:accounts` | `["money"]` | Only with `ox_inventory`: which ESX accounts are stored as inventory items. Defined by ox_inventory. |
| `mysql_connection_string` | | Read by `oxmysql` and by `esx_multicharacter`. |

### esx_lib [#esx_lib]

| Convar | Default | Description |
| --- | --- | --- |
| `xLib:debug` | `false` | Extra debug output from esx_lib. |
| `xLib:callbackTimeout` / `esx:callbackTimeout` | not set | Timeout for ESX callbacks. `xLib:` takes priority. |
| `xLib:callbackMaxPayloadBytes` | `65536` | Maximum callback payload size (minimum 1024). |
| `xLib:streamingTimeout` | `10000` | Milliseconds to wait when loading models, animations and other assets. |
| `xLib:nuiDeferTimeout` | `10000` | Milliseconds to wait for NUI pages to be ready. |
| `esx:ui:primaryColor`, `esx:ui:secondaryColor`, `esx:ui:backgroundColor`, `esx:ui:accentColor`, `esx:ui:logoUrl` | ESX brand colors | Theme for ESX UIs (for example `esx_whitelist`). Use `setr`. |

### Other core resources [#other-core-resources]

| Convar | Read by | Description |
| --- | --- | --- |
| `discord:botToken` | `esx_whitelist` | Discord bot token for whitelist verification. Keep it secret; use `set`, never `setr`. |
| `whitelist:webhook` | `esx_whitelist` | Optional Discord webhook for whitelist logs. |
| `esx:locale` | `esx_multicharacter`, `esx_skin`, `skinchanger`, `esx_inventory`, `esx_whitelist` | Same language convar, default `en`. |

<Callout type="info" title="set, setr and sets">
`set` is server-only. `setr` is also sent to clients, which is required for anything read in client or shared files. `sets` is public and shows up in the server list. Never use `setr` or `sets` for tokens, webhooks or passwords.
</Callout>

## Common mistakes [#common-mistakes]

- **Wrong quotes.** Windows editors sometimes insert smart quotes. Use plain `"`.
- **Editing the wrong file.** txAdmin may be configured to use a `server.cfg` in another folder. Check **Settings > FXServer > CFG Path**.
- **Your resource above `es_extended`.** It starts before ESX exists. Move it below `ensure [esx_addons]`.
- **Two `ensure` lines for different copies of the same resource.** FiveM loads the first folder it finds; delete old copies like `es_extended_old`.

## Related [#related]

- [Admin permissions](/docs/guides/admin-permissions)
- [es_extended config](/docs/es_extended/config)
- [Manual installation](/docs/getting-started/manual-installation)
- [Troubleshooting](/docs/getting-started/troubleshooting)
