Terraria Server Installation on Linux

Terraria is a 2D sandbox game that supports dedicated multiplayer servers on Linux. This guide covers the complete installation and configuration of a TShock-powered Terraria server, which includes essential administrative tools, permission systems, and plugin support. TShock adds superior server management capabilities including player bans, regions, and extensive command support beyond the vanilla server.

Table of Contents

System Requirements

Before starting, verify your system meets these requirements:

  • Ubuntu 20.04 LTS, CentOS 7+, or compatible Linux distribution
  • 2GB RAM minimum (4GB recommended for 10+ players)
  • 10GB disk space
  • .NET 6.0 Runtime (required for TShock)
  • Root or sudo access

TShock is a .NET application, so the .NET runtime is mandatory for operation.

Installing TShock

Update system packages and install dependencies:

sudo apt-get update
sudo apt-get install -y wget curl git build-essential curl gnupg apt-transport-https ca-certificates

Install .NET 6.0 Runtime:

# Add Microsoft repository
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

# Install .NET runtime
sudo apt-get update
sudo apt-get install -y dotnet-runtime-6.0

Verify .NET installation:

dotnet --version
dotnet --info | grep -A 5 "Runtime"

Create dedicated user for TShock:

sudo useradd -m -s /bin/bash terraria
sudo -u terraria mkdir -p /home/terraria/tshock

Download latest TShock release:

cd /home/terraria/tshock
TSHOCK_VERSION=$(curl -s https://api.github.com/repos/Pryaxis/TShock/releases/latest | grep tag_name | cut -d'"' -f4)
sudo -u terraria wget "https://github.com/Pryaxis/TShock/releases/download/${TSHOCK_VERSION}/TShock-${TSHOCK_VERSION}.zip"

Extract TShock:

sudo -u terraria unzip -o "TShock-${TSHOCK_VERSION}.zip"
sudo -u terraria chmod +x /home/terraria/tshock/TShock.Server

Verify extraction:

ls -la /home/terraria/tshock/
file /home/terraria/tshock/TShock.Server

Create data directory:

sudo -u terraria mkdir -p /home/terraria/terraria-data/{worlds,logs,plugins}

Server Configuration

TShock uses config.json for server configuration. Initialize default configuration:

cd /home/terraria/tshock
sudo -u terraria /bin/bash -c 'timeout 5 dotnet TShock.Server.dll 2>&1' || true
sleep 2

This creates the default config.json. Now customize it:

sudo tee /home/terraria/tshock/config.json > /dev/null <<'EOF'
{
  "InviteCode": "myworld",
  "ServerPassword": "ChangeMeToSecurePassword",
  "ServerPort": 7777,
  "UseSSL": false,
  "RestApiPort": 7878,
  "ShowItemNameInRadius": true,
  "RestApiEnabled": true,
  "LogPath": "logs/",
  "LogFormat": "%sanitizedpath% - [%time%] %level%: %message%",
  "SilentKickOnMissingPassword": false,
  "DisableHardmode": false,
  "DisableDungeonGuardian": false,
  "EnableWhitelist": false,
  "OverrideTShockToServerPassword": false,
  "AutoLock": false,
  "AutoUnlock": false,
  "AutoSave": true,
  "AutoSaveInterval": 300,
  "AutoSaveOnExit": true,
  "NpcStreamFarAwayPlayers": false,
  "StartInvPassword": "",
  "RespawnSeconds": 5,
  "MaxDamage": 1175,
  "MaxProjDamage": 20,
  "KickOnDamageThresholdBreach": false,
  "TilePaintThreshold": 15,
  "CombatBookValidationThreshold": 250,
  "KickOnTilePaintThresholdBreach": false,
  "ForceHalloween": false,
  "ForceChristmas": false,
  "AllowCutTiles": true,
  "AllowPlacingHauntedIceTiles": true,
  "AllowDecorations": true,
  "AllowIce": true,
  "AllowUndergroundDesertCorruption": true,
  "AllowedIceBlocksCount": 9999,
  "MediumcoreThreshold": 5,
  "HardcoreThreshold": 10,
  "AllowRegisteringAccounts": true,
  "MinimumPasswordLength": 4,
  "HashAlgorithm": "sha512",
  "UseServerName": false,
  "ServerFullNoPermission": false,
  "SaveWorldOnLastPlayerExit": true,
  "BCryptWorkFactor": 7,
  "ServerSidedCharacter": false,
  "MediumcoreBanning": false,
  "HardcoreBanning": false,
  "DisableLoginBeforeJoin": false,
  "DisableUUIDLogin": false,
  "KickProxyUsers": true,
  "DisableSpewLogs": false,
  "MaxHP": 500,
  "MaxMP": 250,
  "EnableTokenEndpointAuthentication": false
}
EOF

sudo chown terraria:terraria /home/terraria/tshock/config.json
sudo chmod 600 /home/terraria/tshock/config.json

World Setup and Management

Create startup script for world selection and server launch:

sudo tee /home/terraria/tshock/start_server.sh > /dev/null <<'EOF'
#!/bin/bash

TSHOCK_DIR="/home/terraria/tshock"
DATA_DIR="/home/terraria/terraria-data"
WORLD_PATH="${WORLD_PATH:-$DATA_DIR/worlds/Terraria}"
DIFFICULTY="${DIFFICULTY:-normal}"

cd "$TSHOCK_DIR"

# Create world if it doesn't exist
if [ ! -f "${WORLD_PATH}.wld" ]; then
    echo "Creating new world: $WORLD_PATH"
    mkdir -p "$(dirname $WORLD_PATH)"
fi

export TSHOCK_WORLD_PATH="$WORLD_PATH"
export TSHOCK_LOG_PATH="$DATA_DIR/logs/"

mkdir -p "$DATA_DIR/logs"
mkdir -p "$DATA_DIR/worlds"

exec dotnet TShock.Server.dll \
    -world "$WORLD_PATH" \
    -difficulty "$DIFFICULTY" \
    -logfile "$DATA_DIR/logs/tshock.log" \
    2>&1
EOF

sudo chmod +x /home/terraria/tshock/start_server.sh
sudo chown terraria:terraria /home/terraria/tshock/start_server.sh

Test server startup:

sudo -u terraria timeout 10 bash -c 'WORLD_PATH="/home/terraria/terraria-data/worlds/TestWorld" /home/terraria/tshock/start_server.sh' || true

Check logs:

tail -20 /home/terraria/terraria-data/logs/tshock.log

Permission System

TShock uses a robust permission system. Configure user groups and permissions:

sudo tee /home/terraria/tshock/sscconfig.json > /dev/null <<'EOF'
{
  "Settings": {
    "Enabled": true,
    "MaxDamage": 1175,
    "MaxProjectileDamage": 20,
    "MaxHP": 500,
    "MaxMP": 250,
    "KickOnDamageThresholdBreach": false,
    "IgnorePvpFlag": false,
    "IgnoreSSC": false,
    "LogBans": true
  }
}
EOF

sudo chown terraria:terraria /home/terraria/tshock/sscconfig.json

Create user groups configuration:

sudo tee /home/terraria/tshock/groups.json > /dev/null <<'EOF'
[
  {
    "Name": "default",
    "Parent": null,
    "Permissions": [
      "tshock.world.read",
      "tshock.npc.spawn.boss"
    ]
  },
  {
    "Name": "vip",
    "Parent": "default",
    "Permissions": [
      "tshock.world.build",
      "tshock.npc.spawnheal"
    ]
  },
  {
    "Name": "admin",
    "Parent": null,
    "Permissions": [
      "*"
    ]
  },
  {
    "Name": "moderator",
    "Parent": "default",
    "Permissions": [
      "tshock.kick.self",
      "tshock.ban.self",
      "tshock.mute.self",
      "tshock.whisper",
      "tshock.admin"
    ]
  }
]
EOF

sudo chown terraria:terraria /home/terraria/tshock/groups.json

Plugin Management

Install essential TShock plugins for enhanced functionality:

mkdir -p /home/terraria/tshock/ServerPlugins
cd /home/terraria/tshock/ServerPlugins

# Download useful plugins from TShock community
# Example: BossPresence plugin
sudo -u terraria wget https://github.com/tylerjwatson/BossPresence/releases/download/latest/BossPresence.dll

# Example: AntiCheat plugin
sudo -u terraria wget https://github.com/Pryaxis/TShock/releases/download/AntiCheat/AntiCheat.dll

# Verify plugin installation
ls -la /home/terraria/tshock/ServerPlugins/

Create plugin configuration directory:

sudo -u terraria mkdir -p /home/terraria/tshock/ServerPlugins/
ls -la /home/terraria/tshock/ServerPlugins/

Firewall and Port Configuration

TShock uses TCP for server communication. Default port is 7777, with optional REST API on 7878.

Configure UFW firewall:

sudo ufw allow 7777/tcp
sudo ufw allow 7878/tcp
sudo ufw status numbered

For iptables-based systems:

sudo iptables -A INPUT -p tcp --dport 7777 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 7878 -j ACCEPT
sudo iptables-save | sudo tee /etc/iptables/rules.v4

Verify port binding:

sudo netstat -tlnp | grep dotnet
ss -tlnp | grep 7777

Port forwarding on a router may be required for remote connections.

Running with Systemd

Create systemd service for automatic startup and management:

sudo tee /etc/systemd/system/tshock.service > /dev/null <<'EOF'
[Unit]
Description=TShock Terraria Server
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=terraria
Group=terraria
WorkingDirectory=/home/terraria/tshock
EnvironmentFile=/home/terraria/tshock/server.env

ExecStart=/home/terraria/tshock/start_server.sh

Restart=on-failure
RestartSec=15
StandardOutput=journal
StandardError=journal

# Resource limits
LimitNOFILE=65536
LimitNPROC=4096

# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/home/terraria/terraria-data

[Install]
WantedBy=multi-user.target
EOF

Create environment file:

sudo tee /home/terraria/tshock/server.env > /dev/null <<'EOF'
WORLD_PATH=/home/terraria/terraria-data/worlds/Terraria
DIFFICULTY=normal
EOF

sudo chown terraria:terraria /home/terraria/tshock/server.env
sudo chmod 600 /home/terraria/tshock/server.env

Enable and start service:

sudo systemctl daemon-reload
sudo systemctl enable tshock.service
sudo systemctl start tshock.service
sudo systemctl status tshock.service

Monitor service logs:

sudo journalctl -u tshock.service -f
sudo journalctl -u tshock.service -n 50 --no-pager

Administrative Commands

Once the server is running, use these commands in-game or via console:

List connected players:

# In-game as admin: /users
# Via REST API:
curl http://localhost:7878/v3/players

Ban a player:

# In-game:
# /ban username reason
# /banuserid userid reason
# /ipban ipaddress reason

# Via console:
curl -X POST http://localhost:7878/v3/bans \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{"username":"playerName"}'

Kick a player:

# In-game:
# /kick username reason

Manage world settings:

# In-game:
# /hardmode - Toggle hardmode
# /dungeon - Teleport to dungeon
# /tpnpc npcname - Teleport NPC

Broadcast messages:

# In-game:
# /say message
# /announce message

Reload configuration:

# In-game as admin:
# /reload

Backup and Recovery

Create automated backup script:

sudo tee /home/terraria/backup_tshock.sh > /dev/null <<'EOF'
#!/bin/bash

DATA_DIR="/home/terraria/terraria-data"
BACKUP_DIR="$DATA_DIR/backups"
RETENTION_DAYS=30
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

mkdir -p "$BACKUP_DIR"

# Backup worlds and database
tar -czf "$BACKUP_DIR/tshock_backup_${TIMESTAMP}.tar.gz" \
    -C "$DATA_DIR" worlds/ \
    2>/dev/null

if [ $? -eq 0 ]; then
    echo "[$(date)] Backup created successfully"
else
    echo "[$(date)] Backup failed!" >&2
    exit 1
fi

# Cleanup old backups
find "$BACKUP_DIR" -name "tshock_backup_*.tar.gz" -mtime +${RETENTION_DAYS} -delete
echo "[$(date)] Cleanup complete (retention: ${RETENTION_DAYS} days)"
EOF

sudo chmod +x /home/terraria/backup_tshock.sh
sudo chown terraria:terraria /home/terraria/backup_tshock.sh

Add to crontab:

sudo tee -a /var/spool/cron/crontabs/terraria > /dev/null <<'EOF'
0 2 * * * /home/terraria/backup_tshock.sh >> /home/terraria/terraria-data/logs/backup.log 2>&1
EOF

sudo systemctl restart cron

Restore from backup:

# Stop server
sudo systemctl stop tshock.service

# Restore backup
BACKUP_FILE="/home/terraria/terraria-data/backups/tshock_backup_20240101_020000.tar.gz"
sudo -u terraria tar -xzf "$BACKUP_FILE" -C /home/terraria/terraria-data/

# Start server
sudo systemctl start tshock.service

Monitoring

Create monitoring script:

sudo tee /home/terraria/check_tshock.sh > /dev/null <<'EOF'
#!/bin/bash

# Check if service is running
if sudo systemctl is-active --quiet tshock.service; then
    echo "✓ TShock service is running"
else
    echo "✗ TShock service is NOT running"
    exit 1
fi

# Check port
if sudo netstat -tlnp 2>/dev/null | grep -q 7777; then
    echo "✓ Server listening on port 7777"
else
    echo "✗ Server NOT listening"
    exit 1
fi

# Get player count from REST API
PLAYER_COUNT=$(curl -s http://localhost:7878/v3/players 2>/dev/null | grep -o '"' | wc -l)
echo "Connected players (API check): ~$((PLAYER_COUNT/4))"

# Check recent errors
ERRORS=$(tail -20 /home/terraria/terraria-data/logs/tshock.log 2>/dev/null | grep -i "error\|exception" | wc -l)
echo "Recent errors: $ERRORS"

# Disk usage
USAGE=$(df -h /home/terraria/terraria-data | awk 'NR==2 {print $5}')
echo "Disk usage: $USAGE"
EOF

sudo chmod +x /home/terraria/check_tshock.sh

Update TShock to latest version:

sudo systemctl stop tshock.service
cd /home/terraria/tshock
LATEST_VERSION=$(curl -s https://api.github.com/repos/Pryaxis/TShock/releases/latest | grep tag_name | cut -d'"' -f4)
sudo -u terraria wget "https://github.com/Pryaxis/TShock/releases/download/${LATEST_VERSION}/TShock-${LATEST_VERSION}.zip"
sudo -u terraria unzip -o "TShock-${LATEST_VERSION}.zip"
sudo systemctl start tshock.service

Conclusion

Your TShock Terraria server is now fully configured with proper user management, permission systems, and automated backups. This setup provides a professional multiplayer experience with advanced administrative controls.

Key takeaways:

  • Always use a secure server password
  • Configure permissions groups for different player types
  • Implement regular automated backups
  • Monitor server logs for issues and updates
  • Use plugins carefully to enhance functionality without compromising stability
  • Keep server and plugins updated regularly

A well-managed TShock server can support multiple players with excellent stability and administrative control for many years.