On this page
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
Create a user for the server
sudo useradd -m -d /home/teamspeak -s /bin/bash teamspeak sudo -u teamspeak -iDownload and unpack it
Set
VERSIONto 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.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_amd64Accept the licence
The server refuses to start until you have accepted its licence agreement. The marker is an empty file in the server directory:
touch .ts3server_license_acceptedIf your first start exits immediately having said nothing useful, this is usually why.
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.
./ts3server createinifile=1That writes
ts3server.iniand exits. The keys worth knowing arevoice_ipanddefault_voice_port,filetransfer_ipandfiletransfer_port,query_ipandquery_port, thequery_ip_whitelistandquery_ip_blacklistfile paths,logpath, andlicensepath.Start it once, and do not walk away
./ts3server_startscript.sh start inifile=ts3server.iniThis 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 underlogs/, so if the terminal has already scrolled, look there before you panic.Stop it again once you have them:
./ts3server_startscript.sh stopRun it under systemd
Write
/etc/systemd/system/teamspeak.service:[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.targetThen:
sudo systemctl daemon-reload sudo systemctl enable --now teamspeak sudo journalctl -u teamspeak -fUse
ts3server_minimal_runscript.shhere, notts3server_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 whatType=simpleexpects.
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.
If the key is lost or already used
First, look in the log. The first-run output is written there:
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:
telnet 127.0.0.1 10011nc 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=0Read 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:
sudo systemctl stop teamspeak
sudo -u teamspeak /home/teamspeak/teamspeak3-server_linux_amd64/ts3server_startscript.sh start serveradmin_password=NEW_PASSWORDThe 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
| Port | Protocol | What it carries | What breaks if it is closed |
|---|---|---|---|
| 9987 | UDP | Voice, and everything a client does in normal use: connecting, moving between channels, text chat. | Nobody can connect at all. |
| 10011 | TCP | ServerQuery, the text admin interface used by bots, web panels, and scripts. | Nothing a normal user does. This one should not be open. |
| 30033 | TCP | File 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.
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:
sudo ss -lntup | grep ts3serverSecuring ServerQuery
Keep it off the internet. Bind it to the loopback address in
ts3server.ini:
query_ip=127.0.0.1Then reach it through an SSH tunnel from your own machine when you need it:
ssh -L 10011:127.0.0.1:10011 root@203.0.113.10Your 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.txtblocks the addresses listed in it.query_ip_whitelist.txtdoes 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.
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.iniandlicensekey.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:
sudo systemctl stop teamspeak
sudo tar -czf ~/ts3-backup-$(date +%F).tar.gz -C /home/teamspeak teamspeak3-server_linux_amd64
sudo systemctl start teamspeakKeep a copy off the machine. See Backups for what is kept for you and how a restore is requested.
Related
Opening UDP 9987 and TCP 30033, and leaving the query port closed.
Rate limitsPacket-rate ceilings for a voice port, sized from your own traffic.
Connecting to your serverGetting the SSH session everything above assumes.
Opening a ticketWhen the machine, rather than the server on it, is the problem.