How to Create a Tibia (OTServ) Server on Linux with TFS
Practical guide to running an OTServ based on The Forgotten Server (TFS) on Ubuntu Linux: dependencies, compilation, MySQL, login, and firewall.
Running your own Tibia server (OTServ) is a project that mixes C++ compilation, MySQL database configuration, Lua scripting, and Linux network management. This guide focuses on getting a server based on The Forgotten Server (TFS) 1.5 running from scratch on an Ubuntu 24.04 LTS VPS, from cloning the repository to the client connecting.
The persona for this tutorial is the new OTServ owner with basic familiarity with the Linux command line who wants a functional test server before customizing maps, sprites, and scripts. The path is: install dependencies, compile TFS, configure MySQL, adjust config.lua, and open the ports on the firewall. On reasonable hardware, the whole procedure takes between 30 and 45 minutes.
We won’t cover map customization (RME), Lua script creation, or shared login server setup for an OT-list — those are topics for dedicated tutorials. The focus here is the minimum viable path to having a server that accepts real connections.
Prerequisites
Ubuntu 24.04 LTS (or Debian 12) with sudo access, at least 2 GB of RAM, 10 GB of free disk space, and a stable public IP. SSH working, UFW firewall available, and TCP ports 7171/7172 unblockable at the provider.
Ubuntu 24.04 LTS 2 GB 7171 + 7172 Tibia 8.60 Confirm you are logged in as a user with sudo and refresh the package index before starting:
sudo apt update && sudo apt upgrade -y
Installing compilation dependencies
TFS 1.5 is written in C++17 and uses Boost, LuaJIT (or Lua 5.4), the MySQL client library, PugiXML, and CryptoPP. You need all of them, plus the GCC toolchain and CMake to generate the build files.
Install the compilation toolchain and development libraries:
sudo apt install -y build-essential cmake git
sudo apt install -y libluajit-5.1-dev libmariadb-dev libboost-system-dev \
libboost-iostreams-dev libboost-filesystem-dev libboost-date-time-dev \
libpugixml-dev libcrypto++-dev libfmt-devbuild-essential brings GCC, G++, and make. The libboost-*-dev packages are the specific Boost modules TFS actually uses — installing libboost-all-dev works but pulls in ~300 MB of unnecessary code.
Create a dedicated user to run the server (good isolation practice):
sudo adduser --disabled-password --gecos "" otserv
sudo usermod -aG sudo otservThe --disabled-password flag blocks password login — you access it via sudo -iu otserv from your main user.
Cloning and compiling TFS
With dependencies installed, download the source code and build the binary.
Switch to the otserv user and clone the official repository:
sudo -iu otserv
cd ~
git clone --depth 1 https://github.com/otland/forgottenserver.git tfs
cd tfsThe --depth 1 flag downloads only the latest commit (instead of the entire history, which is hundreds of MB). If you need to contribute back to the project, do a full clone later.
Generate the project with CMake and compile using all available cores:
mkdir build && cd build
cmake ..
make -j$(nproc)nproc returns the number of CPU threads — on a VPS with 4 vCPUs, this parallelizes the build into 4 jobs. Compilation takes between 3 and 10 minutes depending on the hardware. When it finishes, the tfs binary appears in ~/tfs/build/.
On VPS instances with less than 2 GB of RAM, make -j$(nproc) can run out of memory while compiling heavy files. If you see internal compiler error: Killed (program cc1plus), retry with make -j1 (serial compilation, slower but stable).
MySQL database configuration
TFS persists accounts, characters, houses, guilds, and items in a relational database. MariaDB is the default implementation on Ubuntu.
Exit the otserv user (back to your sudo shell) and install the MySQL server:
exit
sudo apt install -y mariadb-server
sudo mysql_secure_installationmysql_secure_installation is an interactive wizard: set a strong root password, remove anonymous users, block remote root login, and remove the test database. Accept everything with Y.
Create the database and the OTServ user:
sudo mariadbInside the MySQL prompt:
CREATE DATABASE forgottenserver CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'otserv'@'localhost' IDENTIFIED BY 'CHANGE_THIS_PASSWORD';
GRANT ALL PRIVILEGES ON forgottenserver.* TO 'otserv'@'localhost';
FLUSH PRIVILEGES;
EXIT;Replace CHANGE_THIS_PASSWORD with a strong password (at least 16 random characters — use openssl rand -base64 24 to generate one).
Import the initial TFS schema:
sudo -iu otserv
cd ~/tfs
mariadb -u otserv -p forgottenserver < schema.sqlThe schema.sql file is at the root of the cloned repository and creates all the necessary tables (accounts, players, houses, guilds, etc).
Server configuration
With the database ready, adjust config.lua to point at the correct credentials and define world parameters.
Copy the configuration template:
cd ~/tfs
cp config.lua.dist config.lua
nano config.luaAdjust these essential fields:
ip = "0.0.0.0"
mysqlHost = "127.0.0.1"
mysqlUser = "otserv"
mysqlPass = "CHANGE_THIS_PASSWORD"
mysqlDatabase = "forgottenserver"
mysqlPort = 3306
loginProtocolPort = 7171
gameProtocolPort = 7172
statusProtocolPort = 7171
serverName = "My OTServ"
worldType = "pvp"ip = "0.0.0.0" makes TFS listen on all interfaces — required to accept external connections. If you prefer to restrict to a specific interface, use the VPS public IP.
config.lua stores the MySQL password in plain text. Make sure the file permissions are restricted: chmod 600 config.lua. Never commit that file to a public repository (add it to .gitignore).
Firewall release and first start
TFS uses two TCP ports: 7171 for login (authentication and character selection) and 7172 for the game (movement, chat, real-time combat).
Switch back to your sudo user and open the ports in UFW:
exit
sudo ufw allow 7171/tcp
sudo ufw allow 7172/tcp
sudo ufw reload
sudo ufw statusIf UFW is inactive (Status: inactive), enable it with sudo ufw enable — but first confirm that port 22 (SSH) is open, otherwise you’ll lock yourself out.
Start the server to validate it:
sudo -iu otserv
cd ~/tfs/build
./tfsIf everything went well, you’ll see something like:
The Forgotten Server - Version 1.5
>> Loading config
>> Establishing database connection... MySQL 10.11.x
>> Running database manager
>> Loading vocations
>> Loading items
>> Loading script systems
>> Loading monsters
>> Loading map
>> Loaded map
>> Loaded all modules, server starting up...
>> A server has been started on 0.0.0.0:7171.Verification
On another machine (or your own desktop), open a terminal and test connectivity:
telnet YOUR_VPS_IP 7171
If you see Connected to ... and the terminal hangs waiting for input, the port is open and TFS is listening. Press Ctrl+] and type quit to exit.
For a real test with a Tibia 8.60 client, adjust the Tibia.dat/Tibia.spr files in the client folder to point at your IP instead of the official login.tibia.com — tools like OTClient let you do this via init.lua.
Troubleshooting
MySQL connection failed
If TFS prints MySQL connection failure!, check three things:
- The service is running:
sudo systemctl status mariadb - Credentials match: try manual login with
mariadb -u otserv -p forgottenserver mysqlHostinconfig.luais127.0.0.1, notlocalhost(on some setups the Unix socket fails but TCP works)
Port already in use
The bind: Address already in use error on port 7171 means another process is using it. Identify it with:
sudo ss -tulpn | grep 7171
If it’s an old TFS instance, kill it with pkill tfs and try again.
Client connects but doesn’t pass login
The client connects on 7171 (login) but fails to move to 7172 (game). It’s almost always the firewall blocking 7172 while 7171 is open — re-run sudo ufw status and open the missing port. If the server is behind NAT (uncommon on a VPS), forward both ports.
Next steps
- Configure TFS to run as a
systemdservice instead of a manual process — makes automatic restart easier on crashes - Edit Lua scripts in
data/scripts/to customize quests, NPCs, and events - Use RME (Remere’s Map Editor) on Windows to edit
data/world/forgottenserver.otbm - Set up automated daily database backups with
mysqldumpin cron - If you’re putting this in production for real players, a Hostini VPS already comes with fixed IPv4, DDoS protection, and NVMe storage — eliminating the three most common network issues in home hosting.
Frequently asked questions
Which TFS version should I use for a new OTServ?
The 1.5 branch of The Forgotten Server (master branch on GitHub) is the most widely used today on customized servers and runs on 8.60 clients with adjustments. If you need an older client (7.4, 7.72), look for specific forks like TFS 0.x or OTX — they have different compilation requirements.
How much RAM does a small OTServ consume?
A TFS 1.5 server with up to 100 online players stabilizes between 400 MB and 1 GB of RAM, depending on the map and the number of active Lua scripts. MySQL adds another 200-400 MB. To start with headroom, 2 GB of RAM is sufficient.
Can I run OTServ directly as root?
Technically yes, but it's bad practice. Create a dedicated user (e.g. otserv) and run the binary as them. If an exploit on the server is leveraged, the attacker stays restricted to that user's scope instead of compromising the entire system.
Why doesn't my Tibia client connect even with the server running?
The three most common causes are: firewall blocking 7171/7172 (check with sudo ufw status), wrong server IP in config.lua (the ip field), or the login server crashed silently (check the tfs log). Test the port from outside with telnet IP 7171 before touching the client.
How do I back up the OTServ database?
Use mysqldump to export the schema and the data: mysqldump -u otserv -p forgottenserver > backup.sql. Schedule that command in cron daily and send the backup to another disk or external storage. Restore with mysql -u otserv -p forgottenserver < backup.sql.
Do I need a dedicated IP for OTServ?
Yes, or at least a stable address. The Tibia client connects directly to the IP listed in config.lua and the login server — a residential dynamic IP changes and drops your players. A VPS solves this with a fixed IPv4.