Running a TeamSpeak server

Installing TeamSpeak 3 on Linux, its three ports, capturing the privilege key on the first run, and locking down ServerQuery.

Game servers8 min read

On this page
  1. The licence, in outline
  2. Installing on Linux
  3. Claiming the server with the privilege key
  4. If the key is lost or already used
  5. The ports
  6. Securing ServerQuery
  7. Backing it up
  8. Related

A TeamSpeak server is a single binary with an SQLite database beside it. It is undemanding compared with a game server and will run happily alongside other things on the same machine. What catches people out is not the resources, it is three specific things: the licence, the privilege key you are shown exactly once, and ServerQuery.

This covers the self-hosted TeamSpeak 3 server, which is what newer TeamSpeak clients connect to as well.

The licence, in outline

The server is free to download and to run for non-commercial use. An unlicensed server has a cap on how many slots it will accept and how many virtual servers it will host, and that cap is enough for a small community and not enough for a large one.

Do not take a slot number from a guide, including this one. The limits are TeamSpeak's to set and they have changed over the years, so check them for your own case in two places: TeamSpeak's licensing terms, and your own server's startup output, which states the licence in force on the build you are running.

Three situations, in outline:

  • Your own community, unlicensed. Works out of the box, up to the slot cap.
  • A community bigger than the cap. TeamSpeak has offered a non-profit licence that raises it, granted on application to them. Whether you qualify is their decision, not something you can configure.
  • Hosting servers for other people. Selling or bundling TeamSpeak servers to customers is commercial use and needs an arrangement with TeamSpeak under their authorised host programme. Running one server for your own community on a VPS you rent is not that. Renting TeamSpeak servers out to others is.

A licence, when you have one, is a file named licensekey.dat placed in the server directory. Put it there and restart.

Installing on Linux

  1. Create a user for the server

    Shell
    sudo useradd -m -d /home/teamspeak -s /bin/bash teamspeak
    sudo -u teamspeak -i
  2. Download and unpack it

    Set VERSION to the current release, which is on TeamSpeak's downloads page. A version that no longer exists gives you a 404 here rather than a subtle problem later, so this is safe to get wrong once.

    Shell
    VERSION=3.13.7
    curl -LO "https://files.teamspeak-services.com/releases/server/${VERSION}/teamspeak3-server_linux_amd64-${VERSION}.tar.bz2"
    tar -xjf "teamspeak3-server_linux_amd64-${VERSION}.tar.bz2"
    cd teamspeak3-server_linux_amd64
  3. Accept the licence

    The server refuses to start until you have accepted its licence agreement. The marker is an empty file in the server directory:

    Shell
    touch .ts3server_license_accepted

    If your first start exits immediately having said nothing useful, this is usually why.

  4. Write a configuration file

    The server runs on defaults with no config file at all, but generating one makes every port and path explicit, which is what you want the first time something does not bind where you expected.

    Shell
    ./ts3server createinifile=1

    That writes ts3server.ini and exits. The keys worth knowing are voice_ip and default_voice_port, filetransfer_ip and filetransfer_port, query_ip and query_port, the query_ip_whitelist and query_ip_blacklist file paths, logpath, and licensepath.

  5. Start it once, and do not walk away

    Shell
    ./ts3server_startscript.sh start inifile=ts3server.ini

    This first start prints three things you will never be shown again: the ServerQuery account name, which is serveradmin, its password, and the ServerAdmin privilege key. Copy all three into your password manager before you do anything else. They are also written into the log file under logs/, so if the terminal has already scrolled, look there before you panic.

    Stop it again once you have them:

    Shell
    ./ts3server_startscript.sh stop
  6. Run it under systemd

    Write /etc/systemd/system/teamspeak.service:

    Config
    [Unit]
    Description=TeamSpeak 3 server
    After=network-online.target
    Wants=network-online.target
     
    [Service]
    Type=simple
    User=teamspeak
    Group=teamspeak
    WorkingDirectory=/home/teamspeak/teamspeak3-server_linux_amd64
    ExecStart=/home/teamspeak/teamspeak3-server_linux_amd64/ts3server_minimal_runscript.sh inifile=ts3server.ini
    Restart=on-failure
    RestartSec=10
     
    [Install]
    WantedBy=multi-user.target

    Then:

    Shell
    sudo systemctl daemon-reload
    sudo systemctl enable --now teamspeak
    sudo journalctl -u teamspeak -f

    Use ts3server_minimal_runscript.sh here, not ts3server_startscript.sh. The start script puts the server into the background and manages its own pid file, which fights with systemd. The minimal script stays in the foreground, which is what Type=simple expects.

Claiming the server with the privilege key

The privilege key from the first start is a single-use token that grants the Server Admin group. Connect to the server with your TeamSpeak client and paste the key when it asks for one, or use the client's option to enter a privilege key afterwards.

The key attaches the group to your client identity, not to you as a person. If you later reinstall your client and it generates a new identity, that new identity has no rights on your own server. Export your identity from the client and keep it with your other credentials.

One key, one identityThe first start prints three thingsShown once on screen, and written to thelog under logs/.serveradminits passwordprivilege keyYou redeem the key in your clientIt works once.Server Admin attaches to your client identityNot to you as a person. Export the identityand keep it with your credentials.If the client is reinstalledA new identity, with no rightsUnless you restore the exported one, ormint a new key over ServerQuery.
One key, one identity. The key is shown once and works once, and the group it grants belongs to the client identity that redeemed it, which is why the exported identity is worth keeping with your other credentials. Illustration.

If the key is lost or already used

First, look in the log. The first-run output is written there:

Shell
grep -ri token /home/teamspeak/teamspeak3-server_linux_amd64/logs/

If it is not there or it has already been redeemed, mint a new one over ServerQuery from the server itself:

Shell
telnet 127.0.0.1 10011

nc 127.0.0.1 10011 does the same job if telnet is not installed. Inside that session:

login serveradmin YOUR_PASSWORD
use 1
servergrouplist
tokenadd tokentype=0 tokenid1=6 tokenid2=0

Read the id of the Server Admin group out of the servergrouplist output and use that number as tokenid1. It is 6 on a default install, but a server whose groups have been reorganised may differ, and a token for the wrong group is issued perfectly happily and then grants nothing useful. use 1 selects the first virtual server; if you run more than one, select the one you mean.

If the serveradmin password is lost as well, the server can set a new one at startup. Stop the service, run the binary once with the parameter, then start the service again:

Shell
sudo systemctl stop teamspeak
sudo -u teamspeak /home/teamspeak/teamspeak3-server_linux_amd64/ts3server_startscript.sh start serveradmin_password=NEW_PASSWORD

The password is visible in your shell history and in the process list while that runs, so clear the history line afterwards and do not use a password you use anywhere else.

The ports

PortProtocolWhat it carriesWhat breaks if it is closed
9987UDPVoice, and everything a client does in normal use: connecting, moving between channels, text chat.Nobody can connect at all.
10011TCPServerQuery, the text admin interface used by bots, web panels, and scripts.Nothing a normal user does. This one should not be open.
30033TCPFile transfer: avatars, channel and group icons, and any file uploaded into a channel.Voice works, but avatars and icons never appear and uploads time out, which reads as a broken client rather than a firewall.

Only UDP 9987 needs to face the internet. Add a rule for it under Port rules, and add TCP 30033 as well if you use icons or file uploads, which most communities do.

Three ports, three jobsVoiceUDP 9987Faces the internet. Closed, nobody canconnect at all.TeamSpeak 3 preset writes itFile transferTCP 30033Open it if you use icons or uploads. Closed,avatars and icons never appear and uploadstime out.TeamSpeak 3 preset writes itServerQueryTCP 10011query_ip=127.0.0.1Keep it off the internet and reach it over anSSH tunnel. Closed, nothing a normal userdoes breaks.TeamSpeak 3 preset writes itRestrict by source
What each port is for and what breaks without it. Voice is the one that must face the internet and ServerQuery the one that must not. The TeamSpeak 3 preset writes a rule for all three, ServerQuery included, so binding query_ip to 127.0.0.1 is what keeps it off the internet. Illustration; ports from this page, preset contents from the Game presets page.

The voice port is per virtual server: a second virtual server on the same machine takes its own port, conventionally the next number up. File transfer and ServerQuery are shared by the whole instance.

Newer server builds also listen on additional query transports, an SSH-based one and an HTTP one, on their own ports. You do not have to use them, but you should know what your build has opened, because a port you did not know about is a port you did not firewall. The server logs every socket it binds when it starts, and you can confirm directly:

Shell
sudo ss -lntup | grep ts3server

Securing ServerQuery

Keep it off the internet. Bind it to the loopback address in ts3server.ini:

Config
query_ip=127.0.0.1

Then reach it through an SSH tunnel from your own machine when you need it:

Shell
ssh -L 10011:127.0.0.1:10011 root@203.0.113.10

Your bot or panel then connects to 127.0.0.1 on port 10011 on your side, and the query port is never exposed. If something on a different machine genuinely needs query access, do not open the port to everyone: allow only that one address in the port rule, and prefer the SSH query transport over the raw one.

Know what the two list files actually do, because their names mislead almost everyone:

  • query_ip_blacklist.txt blocks the addresses listed in it.
  • query_ip_whitelist.txt does not restrict access to the addresses listed in it. It exempts them from the flood and brute-force protection. Putting your own bot in there is correct, because a busy bot otherwise trips the flood limits and gets itself banned. It is not an access control and it keeps nobody else out.
query_ip_blacklist.txtBlocks what is listedListed198.51.100.7Blocked.Anyone else203.0.113.50Reaches ServerQuery,under flood andbrute-forceprotection.query_ip_whitelist.txtExempts what is listed, keeps nobody outYour bot198.51.100.20ReachesServerQuery, exemptfrom the floodlimits.Anyone else203.0.113.50Still reachesServerQuery. The listkeeps nobody out.
The two files do different kinds of job. The blacklist keeps the addresses on it out; the whitelist only lifts the flood and brute-force limits for the addresses on it, and everyone else still reaches ServerQuery. Illustration; example addresses.

Leave query_skipbruteforcecheck at 0. It disables the throttling on repeated failed logins, which is the only thing standing between a weak password and a scanner working through a list.

Do not hand out serveradmin. The server can create additional query logins with their own permissions, which is what a bot or a web panel should use. Connect over query and run help queryloginadd on your own build to see the form it takes there.

Turn on query command logging while you are investigating. Setting logquerycommands=1 in ts3server.ini records what query logins actually did, which is the difference between suspecting something and knowing it.

Backing it up

Everything that matters is inside the server directory and it is small:

  • ts3server.sqlitedb, which holds channels, groups, permissions, and every registered identity. Lose it and your server is a fresh install.
  • files/, which holds uploads, avatars, and icons.
  • ts3server.ini and licensekey.dat.

Stop the server before you copy the database. Copying a SQLite file while the server is writing to it can give you a file that will not open, and you will not find out until the day you need it:

Shell
sudo systemctl stop teamspeak
sudo tar -czf ~/ts3-backup-$(date +%F).tar.gz -C /home/teamspeak teamspeak3-server_linux_amd64
sudo systemctl start teamspeak

Keep a copy off the machine. See Backups for what is kept for you and how a restore is requested.

Need a server, or a hand with one?

Pick a plan to deploy a server, or open a ticket in the panel. Support runs 24/7/365.