Running TeamSpeak 6 Server with Podman Rootless & Auto-Updates
rwxd February 23, 2026 #podman #systemd #rootless #quadlets #teamspeakThis guide shows how to run a TeamSpeak 6 server using rootless Podman with Quadlets and automatic container updates.
Why containers?
- Easy updates and rollbacks
- Isolated from your host system
- Same setup works on any Linux distribution
Why Podman rootless?
- Runs without root privileges for better security
- If compromised, attacker can't access the whole system
Architecture
Prerequisites
Create Podman User
Create a dedicated user for running containers:
# Create podman user if it doesn't exist
if ! id -u podman &> /dev/null; then
sudo useradd -r -m -d /home/podman -s /bin/bash podman
fiInstall Podman
Ubuntu:
sudo apt-get update
sudo apt-get install -y podman
AlmaLinux:
sudo dnf install -y podmanEnable Lingering
Enable lingering to allow rootless containers to run without an active user session:
sudo loginctl enable-linger podmanSetup
All following commands should be run as the podman user:
sudo -iu podman
We will do the following:
Create Directory Structure
mkdir -p ~/.config/containers/systemdCreate Network Quadlet
We need a new network to run the container in with enabled IPv6.
Create ~/.config/containers/systemd/teamspeak.network:
cat > ~/.config/containers/systemd/teamspeak.network <<'EOF'
[Network]
IPv6=true
[Service]
ExecStop=/usr/bin/podman network rm teamspeak
[Unit]
Description=Podman network for teamspeak
EOFCreate Volume Quadlet
To persist the teamspeak database we need a new volume.
Create ~/.config/containers/systemd/teamspeak-data.volume:
cat > ~/.config/containers/systemd/teamspeak-data.volume <<'EOF'
[Volume]
[Service]
[Unit]
Description=Podman volume for teamspeak data
EOFCreate Container Quadlet
Create ~/.config/containers/systemd/teamspeak.container:
cat > ~/.config/containers/systemd/teamspeak.container <<'EOF'
[Container]
AutoUpdate=registry
Environment=TSSERVER_DATABASE_PLUGIN=sqlite3
Environment=TSSERVER_LICENSE_ACCEPTED=accept
Environment=TSSERVER_QUERY_HTTP_ENABLED=1
Image=docker.io/teamspeaksystems/teamspeak6-server:latest
Network=teamspeak.network
PublishPort=9987:9987/udp
PublishPort=30033:30033/tcp
PublishPort=10080:10080/tcp
Volume=teamspeak-data.volume:/var/tsserver
[Service]
Restart=always
TimeoutStartSec=900
[Unit]
Description=Podman teamspeak container
EOF
Port mapping:
9987/udp- Voice server - required30033/tcp- Filetransfer - required10080/tcp- ServerQuery (HTTP) - not required
Enable and Start
# Reload systemd to recognize new or changed Quadlets
systemctl --user daemon-reload
# Enable auto-start on boot
systemctl --user enable teamspeak
# Start the service
systemctl --user start teamspeak
# Check status
systemctl --user status teamspeakAuto-Updates
Enable automatic container updates with a systemd timer:
# Enable auto-update timer
systemctl --user enable --now podman-auto-update.timer
This checks for image updates daily and restarts updated containers with AutoUpdate=registry.
To manually trigger an update:
podman auto-updateFirewall Configuration
Open required ports:
Ubuntu (ufw):
sudo ufw allow 9987/udp comment 'TeamSpeak Voice'
sudo ufw allow 30033/tcp comment 'TeamSpeak Filetransfer'
sudo ufw allow 10080/tcp comment 'TeamSpeak HTTP Query'
AlmaLinux (firewalld):
sudo firewall-cmd --permanent --add-port=9987/udp
sudo firewall-cmd --permanent --add-port=30033/tcp
sudo firewall-cmd --permanent --add-port=10080/tcp
sudo firewall-cmd --reloadFirst-Time Setup
On first run, TeamSpeak generates an admin token. Retrieve it from the logs:
podman logs teamspeak | grep -i "token"
Connect to your server at <your-ip> and use the token to claim admin privileges.
Troubleshooting
Check Service Status
# Check if service is running
systemctl --user status teamspeak
# Check if container is running
podman ps -a | grep teamspeakLogs
# Get logs on failing start
journalctl --user -xeu teamspeak
# Follow logs
journalctl --user -feu teamspeak
# Get logs with podman
podman logs -f teamspeakPort Binding Issues
If ports are already in use:
# Check what's using the ports
sudo ss -tulpn | grep -E '9987|30033|10080'Permission Issues
Ensure the podman user has proper subuid/subgid mappings:
# Check mappings
grep podman /etc/subuid /etc/subgid
# If missing, add them (as root)
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 podman
To view and modify real UIDs/GIDs of files in volumes, use podman unshare:
# Check which user runs the TeamSpeak process
podman exec teamspeak ps aux
## USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
## tsserver 1 0.9 0.1 2417440 19996 ? Ssl Feb18 65:56 tsserver
## tsserver 52 0.0 0.0 7064 2864 pts/0 Rs+ 19:09 0:00 ps aux
# Find the UID/GID used inside the container
podman exec teamspeak id tsserver
## uid=9987(tsserver) gid=9987(tsserver) groups=9987(tsserver)
# Enter user namespace to see real UIDs/GIDs
podman unshare
# Now you can see and change ownership to the teamspeak user in the container
ls -ln ~/.local/share/containers/storage/volumes/teamspeak-data/_data/
chown -R 9987:9987 ~/.local/share/containers/storage/volumes/teamspeak-data/_data/
# Exit namespace
exit