TeamSpeak 6 Server unter Linux installieren
In diesem Guide installieren wir einen eigenen TeamSpeak-6-Server auf einem Linux-System, richten einen sicheren Autostart über systemd ein und erstellen anschließend ein automatisches Update-System inklusive Backup und Rollback.
Was bauen wir in diesem Guide?
Ein TeamSpeak-Server lässt sich theoretisch einfach herunterladen, starten und anschließend in einer offenen SSH-Sitzung laufen lassen. Für einen dauerhaft betriebenen Server ist das allerdings keine besonders elegante Lösung.
Wir richten den Server deshalb so ein, wie man einen dauerhaften Linux-Dienst vernünftig betreiben sollte.
- eigener Linux-Benutzer nur für TeamSpeak
- Installation unter
/opt/teamspeak6 - automatische Ermittlung des neuesten TS6-Releases
- Unterstützung für AMD64 und ARM64
- Autostart über systemd
- automatischer Neustart bei einem Fehler
- sauberes Herunterfahren des Servers
- automatische Update-Prüfung
- Backup vor jedem Update
- automatisches Rollback, wenn das Update nicht startet
Voraussetzungen
Dieser Guide richtet sich an aktuelle Debian- und Ubuntu-Server. Empfehlenswert sind beispielsweise Ubuntu 24.04 LTS oder ein aktuelles Debian-System.
Du benötigst außerdem Root-Zugriff oder einen Benutzer,
der Befehle über sudo ausführen darf.
System prüfen
cat /etc/os-release
uname -m
ldd --version | head -n1
Mit diesen Befehlen sehen wir das installierte Linux, die Prozessorarchitektur und die Version der GNU-C-Bibliothek. Letztere ist wichtig, weil aktuelle TeamSpeak-Binaries eine moderne Linux-Umgebung voraussetzen.
Benötigte Pakete installieren
Zunächst aktualisieren wir die Paketlisten und installieren einige kleine Werkzeuge.
sudo apt update
sudo apt install -y curl jq xz-utils bzip2 ca-certificates tar rsync util-linux
Warum brauchen wir diese Pakete?
- curl lädt die TeamSpeak-Dateien und fragt die GitHub-API ab.
- jq verarbeitet die Antwort der GitHub-API und findet automatisch das richtige Downloadpaket.
- xz-utils und bzip2 ermöglichen das Entpacken verschiedener Archivformate.
- rsync wird für Updates und das sichere Übertragen neuer Serverdateien verwendet.
-
util-linux stellt unter anderem
flockbereit. Damit verhindern wir, dass zwei Update-Prozesse gleichzeitig laufen.
Eigenen TeamSpeak-Benutzer erstellen
Der TeamSpeak-Server sollte niemals dauerhaft als
root ausgeführt werden.
Würde ein Fehler im TeamSpeak-Prozess ausgenutzt, hätte ein als Root gestarteter Dienst im schlimmsten Fall vollständige Kontrolle über das gesamte Betriebssystem.
Deshalb erstellen wir einen eigenen Systembenutzer namens
teamspeak.
sudo useradd --system --home-dir /opt/teamspeak6 --create-home --shell /usr/sbin/nologin teamspeak
Der Benutzer besitzt bewusst keine normale Login-Shell. Er ist ausschließlich dafür vorgesehen, den TeamSpeak-Dienst auszuführen.
Anschließend stellen wir sicher, dass das Installationsverzeichnis korrekt existiert.
sudo install -d -o teamspeak -g teamspeak -m 0750 /opt/teamspeak6
TeamSpeak 6 automatisch herunterladen
Statt eine bestimmte Versionsnummer fest einzutragen, erstellen wir ein kleines Installationsscript.
Das Script fragt direkt das aktuelle Release des offiziellen TeamSpeak-GitHub-Repositories ab und entscheidet automatisch, ob dein Server AMD64 oder ARM64 verwendet.
sudo tee /usr/local/sbin/install-teamspeak6 >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
INSTALL="/opt/teamspeak6"
API="https://api.github.com/repos/teamspeak/teamspeak6-server/releases/latest"
ARCH="$(dpkg --print-architecture)"
case "$ARCH" in
amd64)
PATTERN='linux[-_]amd64'
;;
arm64)
PATTERN='linux[-_]arm64'
;;
*)
echo "Nicht unterstützte Architektur: $ARCH"
exit 1
;;
esac
echo "Suche aktuelles TeamSpeak-6-Release ..."
JSON="$(curl -fsSL "$API")"
TAG="$(jq -r '.tag_name' <<<"$JSON")"
URL="$(
jq -r --arg pattern "$PATTERN" '
.assets[]
| select(.name | test($pattern; "i"))
| select(.name | test("\\.tar\\.(xz|bz2|gz)$"; "i"))
| .browser_download_url
' <<<"$JSON" | head -n1
)"
if [[ -z "$URL" || "$URL" == "null" ]]; then
echo "Kein passendes Linux-Paket gefunden."
exit 1
fi
echo "Gefundene Version: $TAG"
echo "Download: $URL"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
ARCHIVE="$TMP/teamspeak6"
EXTRACT="$TMP/extracted"
mkdir -p "$EXTRACT"
curl -fL "$URL" -o "$ARCHIVE"
case "$URL" in
*.tar.xz)
tar -xJf "$ARCHIVE" -C "$EXTRACT"
;;
*.tar.bz2)
tar -xjf "$ARCHIVE" -C "$EXTRACT"
;;
*.tar.gz)
tar -xzf "$ARCHIVE" -C "$EXTRACT"
;;
*)
echo "Unbekanntes Archivformat."
exit 1
;;
esac
BINARY="$(find "$EXTRACT" -type f -name tsserver -print -quit)"
if [[ -z "$BINARY" ]]; then
echo "tsserver wurde im Archiv nicht gefunden."
exit 1
fi
SOURCE="$(dirname "$BINARY")"
rsync -a "$SOURCE/" "$INSTALL/"
chmod +x "$INSTALL/tsserver"
printf '%s\n' "$TAG" > "$INSTALL/.installed-release"
chown -R teamspeak:teamspeak "$INSTALL"
echo
echo "TeamSpeak 6 wurde erfolgreich installiert."
echo "Installierte Version: $TAG"
EOF
sudo chmod 0755 /usr/local/sbin/install-teamspeak6
Das Script wird unter
/usr/local/sbin/install-teamspeak6
abgelegt. Dieser Pfad ist für lokal installierte
Administrationsprogramme gedacht.
Installation starten
sudo /usr/local/sbin/install-teamspeak6
Nach erfolgreicher Installation befinden sich die Serverdateien unter:
/opt/teamspeak6
TeamSpeak-Lizenz
TeamSpeak verlangt beim Start ausdrücklich die Annahme seiner Lizenzbedingungen.
Unser Startprozess verwendet dafür später den Parameter
--accept-license.
Die aktuelle Serverversion kannst du anschließend prüfen.
sudo -u teamspeak /opt/teamspeak6/tsserver --version
Start- und Stop-Script erstellen
Wir könnten TeamSpeak direkt über systemd starten. Ein separates Control-Script hat jedoch einen großen Vorteil: Start, Stop, Neustart und Status können unabhängig von systemd kontrolliert werden.
Außerdem geben wir dem Server beim Herunterfahren genügend Zeit, seine Daten sauber auf die Festplatte zu schreiben.
sudo tee /opt/teamspeak6/ts6ctl >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
INSTALL="/opt/teamspeak6"
PIDFILE="$INSTALL/tsserver.pid"
cd "$INSTALL"
start_server() {
if [[ -f "$PIDFILE" ]]; then
PID="$(cat "$PIDFILE")"
if kill -0 "$PID" 2>/dev/null; then
echo "TeamSpeak 6 läuft bereits mit PID $PID."
exit 0
fi
rm -f "$PIDFILE"
fi
ARGS=(
--accept-license
--daemon
--pid-file "$PIDFILE"
)
if [[ -f "$INSTALL/tsserver.yaml" ]]; then
ARGS+=(--config-file "$INSTALL/tsserver.yaml")
fi
echo "Starte TeamSpeak 6 ..."
"$INSTALL/tsserver" "${ARGS[@]}"
sleep 2
if [[ -f "$PIDFILE" ]] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; then
echo "TeamSpeak 6 wurde gestartet."
else
echo "TeamSpeak 6 konnte nicht gestartet werden."
exit 1
fi
}
stop_server() {
if [[ ! -f "$PIDFILE" ]]; then
echo "TeamSpeak 6 läuft nicht."
exit 0
fi
PID="$(cat "$PIDFILE")"
if ! kill -0 "$PID" 2>/dev/null; then
rm -f "$PIDFILE"
echo "TeamSpeak 6 läuft nicht."
exit 0
fi
echo "Beende TeamSpeak 6 sauber ..."
kill -TERM "$PID"
for ((i=1; i<=300; i++)); do
if ! kill -0 "$PID" 2>/dev/null; then
rm -f "$PIDFILE"
echo "TeamSpeak 6 wurde beendet."
exit 0
fi
sleep 1
done
echo "Timeout: Server wurde NICHT hart beendet."
echo "Bitte Logs prüfen."
exit 1
}
status_server() {
if [[ ! -f "$PIDFILE" ]]; then
echo "TeamSpeak 6 läuft nicht."
exit 1
fi
PID="$(cat "$PIDFILE")"
if kill -0 "$PID" 2>/dev/null; then
echo "TeamSpeak 6 läuft mit PID $PID."
exit 0
fi
echo "PID-Datei vorhanden, Prozess läuft jedoch nicht."
exit 1
}
case "${1:-}" in
start)
start_server
;;
stop)
stop_server
;;
restart)
stop_server
start_server
;;
status)
status_server
;;
*)
echo "Benutzung: $0 {start|stop|restart|status}"
exit 2
;;
esac
EOF
sudo chmod 0755 /opt/teamspeak6/ts6ctl
sudo chown teamspeak:teamspeak /opt/teamspeak6/ts6ctl
Autostart über systemd einrichten
Jetzt kommt systemd ins Spiel.
systemd ist auf modernen Debian- und Ubuntu-Systemen der zentrale Dienstmanager. Er sorgt unter anderem dafür, dass TeamSpeak automatisch beim Booten gestartet wird.
sudo tee /etc/systemd/system/teamspeak6.service >/dev/null <<'EOF'
[Unit]
Description=TeamSpeak 6 Server
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
User=teamspeak
Group=teamspeak
WorkingDirectory=/opt/teamspeak6
PIDFile=/opt/teamspeak6/tsserver.pid
ExecStart=/opt/teamspeak6/ts6ctl start
ExecStop=/opt/teamspeak6/ts6ctl stop
ExecReload=/opt/teamspeak6/ts6ctl restart
Restart=on-failure
RestartSec=10
TimeoutStartSec=60
TimeoutStopSec=330
SendSIGKILL=no
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=full
ReadWritePaths=/opt/teamspeak6
[Install]
WantedBy=multi-user.target
EOF
Warum diese Einstellungen?
-
User=teamspeakverhindert, dass TeamSpeak als Root läuft. -
Restart=on-failurestartet den Server nach einem unerwarteten Absturz automatisch neu. -
ProtectSystem=fullschützt große Teile des Betriebssystems vor Schreibzugriffen durch den Dienst. -
ReadWritePaths=/opt/teamspeak6erlaubt TeamSpeak trotzdem das Schreiben seiner Daten. -
SendSIGKILL=noverhindert, dass systemd den Prozess nach einem Timeout brutal beendet.
systemd neu laden
sudo systemctl daemon-reload
Autostart aktivieren und Server starten
sudo systemctl enable --now teamspeak6
Das Wort enable aktiviert den Autostart.
Mit --now wird TeamSpeak zusätzlich sofort gestartet.
Status kontrollieren
sudo systemctl status teamspeak6 --no-pager -l
Wenn alles funktioniert, sollte dort unter anderem active (running) angezeigt werden.
TeamSpeak-Prozess prüfen
sudo -u teamspeak /opt/teamspeak6/ts6ctl status
Logs ansehen
sudo find /opt/teamspeak6/logs -type f -name "*.log" -exec tail -n 80 {} \;
Beim ersten Start solltest du die ausgegebenen Administratorinformationen beziehungsweise den ServerAdmin-Privilege-Key sicher aufbewahren.
sudo grep -RniE "privilege|token|serveradmin" /opt/teamspeak6/logs | tail -n 30
Firewall konfigurieren
Ein normaler TeamSpeak-6-Server benötigt für die grundlegende Funktion zwei Ports.
| Port | Protokoll | Funktion |
|---|---|---|
| 9987 | UDP | Voice-Verbindungen |
| 30033 | TCP | Dateitransfer |
Falls UFW bereits aktiv ist, kannst du die beiden Ports folgendermaßen freigeben:
sudo ufw allow 9987/udp comment 'TeamSpeak 6 Voice'
sudo ufw allow 30033/tcp comment 'TeamSpeak 6 File Transfer'
sudo ufw status
Query-Ports
TeamSpeak 6 kann zusätzlich unter anderem eine SSH-Query und Web-Query anbieten. Diese sind standardmäßig nicht notwendig und werden in diesem Guide bewusst nicht nach außen geöffnet.
Öffne zusätzliche Verwaltungsports nur dann, wenn du sie wirklich benötigst und anschließend entsprechend absicherst.
Automatisches Update-Script erstellen
Jetzt kommt der interessantere Teil.
Unser Update-Script prüft das aktuellste TeamSpeak-Release. Ist bereits dieselbe Version installiert, passiert überhaupt nichts.
Existiert eine neue Version, passiert Folgendes:
- neues Release wird heruntergeladen,
- Dateien werden zunächst separat entpackt,
- TeamSpeak wird sauber gestoppt,
- die komplette Installation wird gesichert,
- die neuen Dateien werden eingespielt,
- TeamSpeak wird gestartet,
- der Dienst wird geprüft,
- bei einem Fehler wird automatisch das Backup wiederhergestellt.
sudo tee /usr/local/sbin/teamspeak6-update >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
INSTALL="/opt/teamspeak6"
BACKUP_ROOT="$INSTALL/backups"
API="https://api.github.com/repos/teamspeak/teamspeak6-server/releases/latest"
LOCK="/run/lock/teamspeak6-update.lock"
exec 9>"$LOCK"
if ! flock -n 9; then
echo "Es läuft bereits ein TeamSpeak-Update."
exit 0
fi
ARCH="$(dpkg --print-architecture)"
case "$ARCH" in
amd64)
PATTERN='linux[-_]amd64'
;;
arm64)
PATTERN='linux[-_]arm64'
;;
*)
echo "Nicht unterstützte Architektur: $ARCH"
exit 1
;;
esac
echo "Prüfe TeamSpeak-6-Updates ..."
JSON="$(curl -fsSL "$API")"
REMOTE_TAG="$(jq -r '.tag_name' <<<"$JSON")"
LOCAL_TAG="$(
cat "$INSTALL/.installed-release" 2>/dev/null || echo "unknown"
)"
echo "Installiert: $LOCAL_TAG"
echo "Verfügbar: $REMOTE_TAG"
if [[ "$REMOTE_TAG" == "$LOCAL_TAG" ]]; then
echo "TeamSpeak 6 ist bereits aktuell."
exit 0
fi
URL="$(
jq -r --arg pattern "$PATTERN" '
.assets[]
| select(.name | test($pattern; "i"))
| select(.name | test("\\.tar\\.(xz|bz2|gz)$"; "i"))
| .browser_download_url
' <<<"$JSON" | head -n1
)"
if [[ -z "$URL" || "$URL" == "null" ]]; then
echo "Kein passendes Linux-Paket gefunden."
exit 1
fi
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
ARCHIVE="$TMP/teamspeak6"
EXTRACT="$TMP/extracted"
mkdir -p "$EXTRACT"
echo "Lade $REMOTE_TAG herunter ..."
curl -fL "$URL" -o "$ARCHIVE"
case "$URL" in
*.tar.xz)
tar -xJf "$ARCHIVE" -C "$EXTRACT"
;;
*.tar.bz2)
tar -xjf "$ARCHIVE" -C "$EXTRACT"
;;
*.tar.gz)
tar -xzf "$ARCHIVE" -C "$EXTRACT"
;;
*)
echo "Unbekanntes Archivformat."
exit 1
;;
esac
BINARY="$(
find "$EXTRACT" -type f -name tsserver -print -quit
)"
if [[ -z "$BINARY" ]]; then
echo "tsserver wurde im Update nicht gefunden."
exit 1
fi
SOURCE="$(dirname "$BINARY")"
echo "Stoppe TeamSpeak 6 ..."
systemctl stop teamspeak6
TIMESTAMP="$(date '+%Y-%m-%d_%H-%M-%S')"
BACKUP_DIR="$BACKUP_ROOT/$TIMESTAMP"
mkdir -p "$BACKUP_DIR"
BACKUP_FILE="$BACKUP_DIR/teamspeak6-before-$REMOTE_TAG.tar.gz"
echo "Erstelle Backup ..."
tar \
--exclude='./backups' \
-czf "$BACKUP_FILE" \
-C "$INSTALL" .
echo "Installiere neue Dateien ..."
rsync -a "$SOURCE/" "$INSTALL/"
chmod +x "$INSTALL/tsserver"
printf '%s\n' "$REMOTE_TAG" > "$INSTALL/.installed-release"
chown -R teamspeak:teamspeak "$INSTALL"
echo "Starte TeamSpeak 6 ..."
systemctl start teamspeak6
sleep 8
if systemctl is-active --quiet teamspeak6; then
echo
echo "Update erfolgreich."
echo "$LOCAL_TAG -> $REMOTE_TAG"
else
echo
echo "FEHLER: Neue Version konnte nicht gestartet werden."
echo "Rollback wird durchgeführt ..."
systemctl stop teamspeak6 2>/dev/null || true
find "$INSTALL" \
-mindepth 1 \
-maxdepth 1 \
! -name backups \
-exec rm -rf {} +
tar -xzf "$BACKUP_FILE" -C "$INSTALL"
chown -R teamspeak:teamspeak "$INSTALL"
systemctl start teamspeak6
sleep 5
if systemctl is-active --quiet teamspeak6; then
echo "Rollback erfolgreich."
else
echo "Rollback konnte den Server ebenfalls nicht starten."
echo "Manuelle Prüfung erforderlich."
fi
exit 1
fi
echo "Entferne Backups, die älter als 14 Tage sind ..."
find "$BACKUP_ROOT" \
-mindepth 1 \
-maxdepth 1 \
-type d \
-mtime +14 \
-exec rm -rf {} +
echo "Update abgeschlossen."
EOF
sudo chmod 0755 /usr/local/sbin/teamspeak6-update
Warum erstellen wir vor jedem Update ein Backup?
Ein TeamSpeak-Update ersetzt Programmdateien und kann Änderungen an Datenbankstrukturen oder Berechtigungen mitbringen.
Gerade während einer Beta sollte man deshalb niemals einfach blind Dateien überschreiben und hoffen, dass das Universum gnädig gestimmt ist.
Die Sicherungen befinden sich anschließend unter:
/opt/teamspeak6/backups
Automatische Update-Prüfung aktivieren
Das Update-Script funktioniert bisher nur manuell. Deshalb erstellen wir jetzt einen eigenen systemd-Dienst für den Updatevorgang.
sudo tee /etc/systemd/system/teamspeak6-update.service >/dev/null <<'EOF'
[Unit]
Description=TeamSpeak 6 Automatic Update
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/teamspeak6-update
EOF
systemd-Timer erstellen
Der Timer prüft einmal täglich, ob eine neue TeamSpeak-Version verfügbar ist.
sudo tee /etc/systemd/system/teamspeak6-update.timer >/dev/null <<'EOF'
[Unit]
Description=Daily TeamSpeak 6 Update Check
[Timer] 05:15:00
RandomizedDelaySec=30m
Persistent=true
[Install]
WantedBy=timers.target
EOF
Der Server prüft damit ungefähr um 05:15 Uhr auf Updates.
RandomizedDelaySec=30m verteilt die Ausführung
zusätzlich innerhalb eines kleinen Zeitfensters.
Durch Persistent=true wird eine verpasste
Prüfung nachgeholt, wenn der Server beispielsweise zur
geplanten Uhrzeit ausgeschaltet war.
Timer aktivieren
sudo systemctl daemon-reload
sudo systemctl enable --now teamspeak6-update.timer
Nächste Ausführung anzeigen
systemctl list-timers teamspeak6-update.timer
Update manuell testen
Bevor wir uns darauf verlassen, dass der Timer irgendwann mitten in der Nacht seine Arbeit erledigt, testen wir ihn einmal.
sudo systemctl start teamspeak6-update.service
Update-Protokoll anzeigen
sudo journalctl -u teamspeak6-update.service -n 100 --no-pager
Ist bereits die aktuelle Version installiert, sollte das Script ungefähr melden:
Prüfe TeamSpeak-6-Updates ...
Installiert: 6.0.0-beta13.1
Verfügbar: 6.0.0-beta13.1
TeamSpeak 6 ist bereits aktuell.
In diesem Fall wird TeamSpeak nicht einmal neu gestartet.
Die wichtigsten Befehle im Alltag
TeamSpeak starten
sudo systemctl start teamspeak6
TeamSpeak stoppen
sudo systemctl stop teamspeak6
TeamSpeak neu starten
sudo systemctl restart teamspeak6
Status anzeigen
sudo systemctl status teamspeak6
Autostart prüfen
systemctl is-enabled teamspeak6
Installierte TS6-Version anzeigen
cat /opt/teamspeak6/.installed-release
Manuell nach Updates suchen
sudo /usr/local/sbin/teamspeak6-update
Fertig: TeamSpeak 6 läuft automatisiert
Dein TeamSpeak-6-Server läuft jetzt unter einem eigenen Linux-Benutzer, startet automatisch nach einem Reboot und überprüft einmal täglich das offizielle TeamSpeak-Repository auf neue Versionen. Vor jedem Update wird eine Sicherung erstellt und sollte eine neue Version nicht starten, versucht das Script automatisch auf die vorherige Installation zurückzuwechseln.