Сервер TeamSpeak 3 на VPS: установка, ключ администратора, порты и бэкапы
TeamSpeak 3 Server на Debian 12 / Ubuntu 24.04 под systemd: лицензия, ключ привилегий и пароль ServerQuery из журнала, UFW, проверка портов снаружи, бэкап SQLite через .backup, обновление и TeamSpeak 6 в Docker.

Голосовой сервер на VPS работает всегда, а не только пока включён чей-то компьютер. Ниже — установка TeamSpeak 3 Server из официального архива, запуск под systemd от отдельного пользователя, поиск ключа администратора и пароля ServerQuery, порты, резервные копии и обновление. В конце — бета TeamSpeak 6 в Docker. Проверено на Debian 12 с версией 3.13.8.
Как это работает
Сервер принимает голос от говорящего и рассылает его всем в том же канале, не смешивая потоки. Входящий трафик маленький, исходящий растёт с числом слушателей — именно исходящий канал ограничивает размер сервера. Голос идёт по UDP на порт 9987, файлы и аватары — по 30033/tcp, а по 10011/tcp работает ServerQuery — текстовая консоль управления. Обязательны только 9987/udp и 30033/tcp.
Учётных записей с логином и паролем в TeamSpeak нет: клиент при первом запуске создаёт пару ключей, и сервер узнаёт человека по идентификатору из публичного ключа. Пока на новом сервере нет ни одного администратора, назначить его некому. Для этого при первом старте сервер печатает одноразовый ключ привилегий (privilege key): кто введёт его в клиенте, попадает в группу Server Admin. Второй секрет — пароль ServerQuery для serveradmin, тоже печатается один раз. Оба нужно сохранить.
Лицензия. Без ключа сервер бесплатен: один виртуальный сервер и 32 слота, но только для частных лиц и некоммерческих сообществ. Компании нужна коммерческая лицензия от TeamSpeak. Встроенная лицензия версии 3.13.8 действует до 1 июля 2027 года — к этому сроку понадобится обновление.
Что нужно
- Сервер на tanaka.host с Debian 12 или Ubuntu 24.04, 1 ГБ памяти хватит с запасом: сам сервер в простое занимает ~17 МБ.
- Доступ по SSH под root.
- Клиент TeamSpeak 3 на компьютерах участников.
- Второй компьютер (или второй VPS) для проверки портов снаружи.
1. Пользователь и архив
Пользователь teamspeak без возможности входа, домашняя папка /opt/teamspeak:
useradd -r -m -d /opt/teamspeak -s /usr/sbin/nologin teamspeak
apt install -y wget bzip2
Скачайте архив со страницы загрузок TeamSpeak; если версия новее — замените 3.13.8 в обоих местах:
cd /root
wget https://files.teamspeak-services.com/releases/server/3.13.8/teamspeak3-server_linux_amd64-3.13.8.tar.bz2
tar -xjf teamspeak3-server_linux_amd64-3.13.8.tar.bz2 -C /opt/teamspeak --strip-components=1
chown -R teamspeak:teamspeak /opt/teamspeak
--strip-components=1 убирает внешнюю папку, и ts3server оказывается прямо в /opt/teamspeak.
2. Лицензия
Без явного согласия сервер не стартует. Прочитать текст можно в терминале (листать Space, выход Q):
cd /opt/teamspeak
runuser -u teamspeak -- env TS3SERVER_LICENSE=view ./ts3server | less
Согласие — пустой файл в рабочей папке. Он переживает обновления, в отличие от параметра командной строки:
runuser -u teamspeak -- touch /opt/teamspeak/.ts3server_license_accepted
3. Служба systemd
nano /etc/systemd/system/teamspeak.service
[Unit]
Description=TeamSpeak 3 server
After=network-online.target
Wants=network-online.target
[Service]
User=teamspeak
WorkingDirectory=/opt/teamspeak
ExecStart=/opt/teamspeak/ts3server
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
WorkingDirectory обязателен: именно там сервер ищет файл согласия и хранит базу. Сервер работает не в фоновом режиме, поэтому всё, что он печатает, попадает в журнал systemd — это пригодится на следующем шаге.
systemctl daemon-reload
systemctl enable --now teamspeak
systemctl status teamspeak
Управление: systemctl stop|start|restart teamspeak, журнал — journalctl -u teamspeak -f.
4. Ключ привилегий и пароль ServerQuery
Оба секрета напечатаны при первом запуске и лежат в журнале службы:
journalctl -u teamspeak --no-pager -o cat | grep -E "loginname|apikey|token="
Четыре строки: логин serveradmin с паролем ServerQuery, ключ API для HTTP-управления (нужен только авторам ботов) и дважды — ключ привилегий. Сохраните всё в менеджер паролей. Ключ привилегий дублируется в файле лога в logs/, а вот пароль ServerQuery — только в журнале systemd. Потеряли — способ сброса есть в «Частых ошибках».
Не показывайте ключ и пароль никому. Ключ даёт права администратора, пароль ServerQuery — полное управление сервером. Если ключ утёк до использования, создайте новый (см. ниже).
5. Порты в брандмауэре
ufw allow 9987/udp
ufw allow 30033/tcp
Порт ServerQuery 10011 открывать всему интернету не стоит: пароль в нём передаётся открытым текстом. Если доступ нужен с домашнего компьютера — только для своего адреса:
ufw allow from IP-вашего-компьютера to any port 10011 proto tcp
ufw status
Сервер слушает больше: ServerQuery по SSH на 10022 и по HTTP на 10080. Их в брандмауэре не открываем. Проверка:
ss -tuln | grep -E "Netid|:(9987|10011|10022|10080|30033) "
Подробнее — Брандмауэр UFW и firewalld.
6. Проверка снаружи
С самого сервера проверять бесполезно — локальный трафик брандмауэр не ограничивает. С другого компьютера (Linux или macOS):
nc -vz IP-адрес-сервера 30033
succeeded — порт открыт. UDP так не проверить, поэтому короткий скрипт, который отправляет первый пакет рукопожатия клиента и ждёт ответ три секунды:
nano ts3-udp-check.py
import os, socket, struct, sys, time
host = sys.argv[1]
port = int(sys.argv[2]) if len(sys.argv) > 2 else 9987
# Первый пакет рукопожатия TeamSpeak, как его отправляет клиент
data = struct.pack('>IBI', 1566914096, 0, int(time.time())) + os.urandom(4) + bytes(8)
packet = b'TS3INIT1' + struct.pack('>HH', 101, 0) + b'\x88' + data
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(3)
s.sendto(packet, (host, port))
try:
reply, addr = s.recvfrom(2048)
print('Сервер ответил, порт доступен')
except socket.timeout:
print('Ответа нет, порт закрыт или сервер не запущен')
python3 ts3-udp-check.py IP-адрес-сервера 9987
ServerQuery: подключитесь к 10011, сервер поздоровается строкой TS3, дальше команды по одной:
nc IP-адрес-сервера 10011
login serveradmin ПАРОЛЬ
version
quit
error id=0 msg=ok на login — пароль принят. После проверки уберите временное правило:
ufw delete allow from IP-вашего-компьютера to any port 10011 proto tcp
7. Подключение и права администратора
В клиенте TeamSpeak 3: Connections → Connect, адрес сервера (порт не нужен, если стандартный, иначе IP:ПОРТ), ник, пароль пусто. Вы зайдёте без прав. Затем Permissions → Use Token, вставьте ключ привилегий — рядом с ником появится значок SA. Ключ одноразовый. Выдать права ещё кому-то: Permissions → Token Manager → Add Token → тип Server Group, группа Server Admin → Create.
Настройки сервера — правой кнопкой по имени сервера → Edit Virtual Server, там же общий пароль. Ссылка для друзей: ts3server://IP-адрес-сервера?port=9987.
Клиент TeamSpeak 6 к серверу третьей версии подключается, но получит только её возможности.
Резервные копии
Всё лежит в /opt/teamspeak. Для переноса нужны: ts3server.sqlitedb (каналы, группы, права, пользователи — главный файл), папка files, query_ip_allowlist.txt, query_ip_denylist.txt, licensekey.dat (если куплена лицензия) и ssh_host_rsa_key, чтобы ключ SSH-варианта ServerQuery не менялся после восстановления.
Простое cp базы на работающем сервере ненадёжно: SQLite пишет изменения сначала в соседний WAL-файл. Используем sqlite3 .backup — согласованная копия без остановки:
apt install -y sqlite3
nano /opt/teamspeak/backup.sh
#!/bin/sh
# Копия базы и файлов TeamSpeak без остановки сервера, хранит 7 последних архивов
set -e
cd /opt/teamspeak
mkdir -p backups
tmp=$(mktemp -d)
sqlite3 ts3server.sqlitedb ".backup '$tmp/ts3server.sqlitedb'"
cp -a files query_ip_allowlist.txt query_ip_denylist.txt ssh_host_rsa_key "$tmp"/
[ -f licensekey.dat ] && cp -a licensekey.dat "$tmp"/
tar -czf "backups/teamspeak-$(date +%F-%H%M).tar.gz" -C "$tmp" .
rm -rf "$tmp"
ls -1t backups/teamspeak-*.tar.gz | tail -n +8 | xargs -r rm --
chmod +x /opt/teamspeak/backup.sh
chown teamspeak:teamspeak /opt/teamspeak/backup.sh
runuser -u teamspeak -- /opt/teamspeak/backup.sh
echo "0 4 * * * /opt/teamspeak/backup.sh" | crontab -u teamspeak -
Архивы уносите с сервера — Резервные копии VPS. Восстановление:
systemctl stop teamspeak
rm -rf /opt/teamspeak/ts3server.sqlitedb* /opt/teamspeak/files
tar -xzf /opt/teamspeak/backups/ИМЯ-АРХИВА.tar.gz -C /opt/teamspeak
chown -R teamspeak:teamspeak /opt/teamspeak
systemctl start teamspeak
rm заодно убирает -wal и -shm, чтобы сервер стартовал с чистого состояния.
Сервер без базы стартует как новый — с новыми паролем и ключом. Не удаляйте
ts3server.sqlitedbбез свежего архива.
Обновление
Новые файлы распаковываются поверх старых, база не затрагивается:
systemctl stop teamspeak
runuser -u teamspeak -- /opt/teamspeak/backup.sh
cd /root
wget https://files.teamspeak-services.com/releases/server/НОВАЯ-ВЕРСИЯ/teamspeak3-server_linux_amd64-НОВАЯ-ВЕРСИЯ.tar.bz2
tar -xjf teamspeak3-server_linux_amd64-НОВАЯ-ВЕРСИЯ.tar.bz2 -C /opt/teamspeak --strip-components=1
chown -R teamspeak:teamspeak /opt/teamspeak
systemctl start teamspeak
chown обязателен — после распаковки от root файлы принадлежат root. Версия после запуска:
journalctl -u teamspeak -n 80 --no-pager -o cat | grep "TeamSpeak 3 Server"
TeamSpeak 6 (бета) в Docker
TeamSpeak рекомендует для шестой версии Docker — см. Установка Docker. Порты те же, ServerQuery по умолчанию выключен. Лицензия — переменной окружения, данные — в томе:
docker run -d --name teamspeak-server --restart unless-stopped \
-p 9987:9987/udp -p 30033:30033 \
-e TSSERVER_LICENSE_ACCEPTED=accept \
-v teamspeak-data:/var/tsserver \
teamspeaksystems/teamspeak6-server:latest
Секреты — в логе контейнера:
docker logs teamspeak-server 2>&1 | grep -E "loginname|apikey|token="
Обновление: docker pull, docker stop teamspeak-server, docker rm teamspeak-server, снова docker run. Данные остаются в томе.
Docker открывает порты в обход UFW. Всё, что опубликовано через
-p, доступно снаружи независимо от правил UFW. Публикуйте только то, что должно быть открыто всем.
Бета неполная, встроенная лицензия на 32 места продлевается новыми сборками, лицензии TS3 не подходят, миграции данных нет.
Частые ошибки
Please set the environment variable TS3SERVER_LICENSE to "accept" — нет файла согласия или неверный WorkingDirectory. Шаг 2.
local accounting reports an already running instance — без лицензии на машине может работать только одна копия. Вы запустили сервер вручную при работающей службе.
error id=520 msg=invalid\sloginname\sor\spassword — пароль ServerQuery не подошёл (\s = пробел). Сброс:
systemctl stop teamspeak
cd /opt/teamspeak
runuser -u teamspeak -- ./ts3server serveradmin_password=НОВЫЙ-ПАРОЛЬ
systemctl start teamspeak
После старта остановите ручной запуск Ctrl+C. Пароль останется в истории shell — после входа выполните в ServerQuery clientsetserverquerylogin client_login_name=serveradmin, сервер выдаст новый.
error id=3329 … you may retry in 600 seconds — защита от подбора после трёх неверных паролей. Подождите или systemctl restart teamspeak. Адреса из query_ip_allowlist.txt (по умолчанию 127.0.0.1 и ::1) не блокируются.
No reply from server / Connection Error [0x705] — проверьте по порядку: systemctl status teamspeak, ufw status с правилом 9987/udp, скрипт из шага 6.
Потерян или использован ключ привилегий — новый создаётся через ServerQuery прямо на сервере:
nc 127.0.0.1 10011
login serveradmin ПАРОЛЬ
use 1
servergrouplist
Найдите name=Server\sAdmin с type=1 (обычно id 6) и подставьте его:
privilegekeyadd tokentype=0 tokenid1=6 tokenid2=0 tokendescription=new\sadmin
Ответ token=… — новый ключ. Выход — quit.
Unable to open licensekey.dat, falling back to limited functionality — не ошибка, а напоминание о работе без купленной лицензии: один сервер, 32 слота.
Дальше — fail2ban для SSH и Uptime Kuma, чтобы узнавать о падении сервера раньше друзей.