# ESX Legacy Addons (/docs/addons)

ESX Legacy Addons is the official collection of optional resources that sit on top of `es_extended`: jobs, shops, vehicles, housing, HUD, chat and admin tools. Install the whole folder for a ready-to-play roleplay server, or pick single addons and respect their dependencies.

## Overview [#overview]

| Fact | Value |
|------|-------|
| Repository | [esx-framework/ESX-Legacy-Addons](https://github.com/esx-framework/ESX-Legacy-Addons) |
| Folder | `[esx_addons]` (39 resources) |
| Required by all | `esx_lib`, `es_extended` (most also need `oxmysql`) |
| Installed by | The txAdmin ESX recipe, or manually |

Every addon lists its hard dependencies in `fxmanifest.lua`. FiveM refuses to start a resource whose dependencies are missing, and prints `Couldn't start resource ... dependency ... not found` in the console.

## All addons [#all-addons]

| Addon | What it does | Category |
|-------|--------------|----------|
| [esx_accessories](/docs/addons/esx_accessories) | Shops for masks, helmets, glasses and ear accessories, saved per player | player |
| [esx_accessorymanager](/docs/addons/esx_accessorymanager) | Radial menu to take off and restore clothing and props | player |
| [esx_addonaccount](/docs/addons/esx_addonaccount) | Extra money accounts, such as society funds and property black money | economy |
| [esx_addoninventory](/docs/addons/esx_addoninventory) | Shared and personal item storage for societies and properties | economy |
| [esx_adminmenu](/docs/addons/esx_adminmenu) | Admin menu with player actions, bans and action logs | admin |
| [esx_ambulancejob](/docs/addons/esx_ambulancejob) | EMS job: revive, heal, pharmacy, job vehicles | jobs |
| [esx_animations](/docs/addons/esx_animations) | Emote menu with animations, scenarios and walk styles | player |
| [esx_banking](/docs/addons/esx_banking) | Banks and ATMs with PIN codes, transfers and history | economy |
| [esx_barbershop](/docs/addons/esx_barbershop) | Paid hair, beard and makeup changes | player |
| [esx_basicneeds](/docs/addons/esx_basicneeds) | Hunger and thirst, food and drink items | player |
| [esx_billing](/docs/addons/esx_billing) | Invoices and fines between players and jobs | economy |
| [esx_boat](/docs/addons/esx_boat) | Boat shop, boat license and boat garages | vehicles |
| [esx_clotheshop](/docs/addons/esx_clotheshop) | Clothing stores and saved outfits | player |
| [esx_cruisecontrol](/docs/addons/esx_cruisecontrol) | Cruise control and seatbelt | vehicles |
| [esx_datastore](/docs/addons/esx_datastore) | JSON data storage per player or per society | economy |
| [esx_death](/docs/addons/esx_death) | Death state, death screen, respawn and revive | player |
| [esx_dmvschool](/docs/addons/esx_dmvschool) | Theory and practical driving tests | vehicles |
| [esx_drugs](/docs/addons/esx_drugs) | Harvest, process and sell cannabis for black money | economy |
| [esx_garage](/docs/addons/esx_garage) | Garages and impound lots with a React UI | vehicles |
| [esx_hud](/docs/addons/esx_hud) | Default HUD: status bars, money, speedometer, mileage | player |
| [esx_joblisting](/docs/addons/esx_joblisting) | Job center where players pick a non-whitelisted job | jobs |
| [esx_jobs](/docs/addons/esx_jobs) | Simple civilian jobs: miner, lumberjack, fisherman and more | jobs |
| [esx_license](/docs/addons/esx_license) | Stores licenses like driving and weapon licenses | player |
| [esx_lscustom](/docs/addons/esx_lscustom) | Los Santos Customs vehicle tuning | vehicles |
| [esx_mechanicjob](/docs/addons/esx_mechanicjob) | Mechanic job: repairs, towing, crafting | jobs |
| [esx_optionalneeds](/docs/addons/esx_optionalneeds) | Drunk status and a beer item | player |
| [esx_pausemenu](/docs/addons/esx_pausemenu) | Custom pause menu with character and job info | player |
| [esx_policejob](/docs/addons/esx_policejob) | Police job: armory, handcuffs, fines, vehicles | jobs |
| [esx_property](/docs/addons/esx_property) | Buy, furnish and share houses, real estate job | world |
| [esx_rpchat](/docs/addons/esx_rpchat) | `/me`, `/do`, OOC, `/twt` and private messages | player |
| [esx_scoreboard](/docs/addons/esx_scoreboard) | Player list with job counts and live activities | player |
| [esx_service](/docs/addons/esx_service) | On/off duty system with per-job limits | jobs |
| [esx_shops](/docs/addons/esx_shops) | 24/7, liquor and LTD stores with a cart UI | economy |
| [esx_society](/docs/addons/esx_society) | Job bank accounts, boss menu, salaries, money washing | economy |
| [esx_status](/docs/addons/esx_status) | Status engine behind hunger, thirst and drunk | player |
| [esx_taxijob](/docs/addons/esx_taxijob) | Taxi job with NPC fares | jobs |
| [esx_vehicleshop](/docs/addons/esx_vehicleshop) | Car dealership, car dealer job, rentals | vehicles |
| [esx_weaponshop](/docs/addons/esx_weaponshop) | Ammu-Nation and black market weapon shops | economy |
| [esx_weather](/docs/addons/esx_weather) | Per-zone weather and time sync with admin panel | world |

## Installing addons [#installing-addons]

<Steps>
<Step>
### Get the resources [#get-the-resources]

The [txAdmin ESX recipe](/docs/getting-started/installation) clones the repository and copies `[esx_addons]` into `resources/` for you. For a manual setup, download the repository from GitHub and copy either the whole `[esx_addons]` folder or single addon folders into your `resources` directory.
</Step>
<Step>
### Import the SQL [#import-the-sql]

Most addons ship a `<name>.sql` file that creates their tables and inserts jobs, items or society accounts. Import it into your ESX database once. If you installed with the txAdmin recipe, skip this step: `legacy.sql` already contains these rows, and re-importing causes duplicate key errors.

Some addons (`esx_addonaccount`, `esx_billing`, `esx_banking`, `esx_license`, `esx_garage`, `esx_vehicleshop`, `esx_property`, `esx_death`, `esx_adminmenu`, `esx_society`) also create or migrate their own tables on startup.
</Step>
<Step>
### Ensure them in server.cfg [#ensure-them-in-servercfg]

Start addons after the framework. Folder names in brackets start every resource inside them:

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

ensure [esx_addons]
```

To run only a few addons, ensure them by name and list storage addons before the jobs that use them:

```bash title="server.cfg"
ensure esx_addonaccount
ensure esx_addoninventory
ensure esx_datastore
ensure esx_society
ensure esx_billing
ensure esx_policejob
```
</Step>
<Step>
### Configure [#configure]

Every addon has a `config.lua` (some also a `config/` folder). Change locations, prices and job settings there and restart the resource. See the addon page for every key and its default.
</Step>
</Steps>

## Dependencies between addons [#dependencies-between-addons]

The table combines the hard dependencies from `fxmanifest.lua` with soft dependencies found in the code (exports, events and callbacks into another addon). Soft dependencies do not block startup, but the related feature breaks without them.

| Addon | Hard dependencies (fxmanifest) | Also uses at runtime |
|-------|-------------------------------|----------------------|
| esx_society | `esx_addonaccount`, `cron` | `esx_datastore` (society garage) |
| esx_policejob | `esx_billing`, `esx_vehicleshop` | `esx_society`, `esx_addoninventory`, `esx_datastore`, `esx_license`, `esx_service`, `esx_status`, `esx_skin` |
| esx_ambulancejob | `esx_death`, `esx_skin`, `esx_vehicleshop` | `esx_society` |
| esx_mechanicjob | `esx_society`, `esx_billing` | `esx_addonaccount`, `esx_addoninventory`, `esx_service`, `esx_skin` |
| esx_taxijob | — | `esx_society`, `esx_billing`, `esx_addonaccount`, `esx_addoninventory`, `esx_datastore`, `esx_service`, `esx_skin` |
| esx_vehicleshop | — | `esx_addonaccount`, `esx_addoninventory`, `esx_billing`, `esx_license`, `esx_society` |
| esx_property | `oxmysql` | `esx_addonaccount`, `esx_datastore`, `esx_society`, `esx_skin`, `esx_context` |
| esx_weaponshop | `esx_license`, OneSync | — |
| esx_dmvschool | `esx_license` | — |
| esx_boat | `esx_vehicleshop` | `esx_license` |
| esx_basicneeds | `esx_status` | — |
| esx_optionalneeds | — | `esx_status` |
| esx_hud | `esx_status`, `oxmysql` | — |
| esx_billing | — | `esx_addonaccount` (society bills) |
| esx_accessories | `esx_skin`, `esx_datastore` | — |
| esx_clotheshop, esx_barbershop | `esx_skin` | `esx_datastore` (clotheshop outfits) |
| esx_jobs | OneSync | `esx_addonaccount` (vehicle deposit) |

The chain most servers hit is **job → esx_society → esx_addonaccount / esx_datastore / esx_addoninventory**. Every society needs a row in `addon_account` (money), and jobs with a stash also need rows in `addon_inventory` and `datastore`. If a job's boss menu shows no money or the armory is empty, those rows are usually missing.

<Callout type="info" title="esx_phone references">
Several job addons still trigger `esx_phone` events for dispatch messages. `esx_phone` is not part of the repository; without it those calls do nothing and no error is shown.
</Callout>

## Security hardening SQL [#security-hardening-sql]

The repository root contains two SQL files related to the October 2026 security audit.

### security_indexes.sql [#security_indexessql]

This file is **superseded**. It only contains comments and a `SELECT` that prints a note pointing to `sql/security_hardening_2026_10_02.sql`. Running it changes nothing. The comments also warn against blindly adding indexes such as `(identifier, id)` on `billing` or `(owner, plate)` on `owned_vehicles`, because InnoDB secondary indexes already include the primary key.

### sql/security_hardening_2026_10_02.sql [#sqlsecurity_hardening_2026_10_02sql]

This migration enforces data integrity for the economy tables that `esx_billing`, `esx_license`, `esx_addonaccount` and `esx_banking` rely on. It runs as a temporary stored procedure and is safe to run more than once. Each step is skipped when it is already applied.

It first **refuses to run** (raises an error) when it finds:

- duplicate `user_licenses` rows for the same `owner` and `type`
- duplicate `addon_account_data` rows for the same account and owner
- `addon_account_data` rows with a `NULL` account name or an empty-string owner
- `billing`, `users` or `addon_account_data` tables that are not InnoDB

Then it:

| Change | Purpose |
|--------|---------|
| Creates `billing_payments` | Payment journal with a unique `operation_id`, so a bill cannot be paid twice |
| Unique key on `user_licenses (owner, type)` | A player can hold each license type only once |
| Index on `billing (identifier)` | Fast lookup of a player's bills |
| Generated column `addon_account_data.owner_key` plus unique key `(account_name, owner_key)` | One row per account and owner, including shared accounts where `owner` is `NULL` |
| Index on `banking (time)` | Fast transaction history queries |

Finally, it lists `billing_payments` rows still in state `claimed` (payments that started but were never applied). Review them manually; the script never refunds or replays them.

<Callout type="warn" title="Before you run it">
Back up the database and run it in a maintenance window. DDL statements commit immediately, so there is no rollback. It needs MySQL 8 or MariaDB 10.6+ and a client that understands `DELIMITER` (HeidiSQL, the `mysql` CLI). Resolve duplicate rows yourself: the script never merges or deletes financial data. Recent versions of billing, license, addonaccount and banking apply the same schema changes on startup, so the manual script is optional.
</Callout>

## Common issues [#common-issues]

- **`Couldn't start resource esx_xxx`**: a hard dependency is missing or starts later. Check the dependency table above.
- **Duplicate entry errors on SQL import**: the rows already exist, usually from the txAdmin `legacy.sql`. Skip that import.
- **Boss menu shows $0 or no society found**: the `society_<job>` row is missing in `addon_account` / `addon_account_data`, or `esx_society` started before `esx_addonaccount`.
- **Hardening script stops with "Duplicate ..."**: find the duplicates with a `GROUP BY ... HAVING COUNT(*) > 1` query, merge balances by hand, then run it again.

## Related [#related]

- [Installation](/docs/getting-started/installation)
- [server.cfg](/docs/getting-started/server-cfg)
- [esx_society](/docs/addons/esx_society)
- [Create a job](/docs/guides/create-a-job)
- [Database schema](/docs/guides/database-schema)
