Keeping game servers updated is the most consistent maintenance task in self-hosted game hosting. Missing a game update means players cannot connect after the patch drops. Running updates manually at 3 AM is unsustainable. The solution is automation: systemd timers and cron jobs that handle SteamCMD updates, server restarts, and post-update verification without human intervention. This guide covers both approaches and shows which one fits each game server type.
If you are setting up automation on a new machine, compare dedicated server hardware on our homepage to ensure your server has the CPU and RAM to handle updates without disrupting active gameplay.
Why Automate Server Updates?
Game updates fall into three categories with different urgency levels:
- Mandatory patches: Steam-wide updates that break the game protocol. Players cannot connect to an outdated server. These must be applied within hours of release.
- Optional updates: Bug fixes, balance changes, and new features. Can be delayed 24–48 hours for community notice.
- Server-only updates: Configuration changes, mod updates, and plugin patches. These are on your schedule.
Automation ensures mandatory patches are applied before your players notice the server is outdated. Without automation, you either wake up at odd hours or leave your community locked out until morning.
Method 1: systemd Timers (Recommended for Modern Linux)
systemd timers are the preferred approach for systems running systemd (Ubuntu 16.04+, Debian 8+, CentOS 7+). They provide better logging, dependency management, and integration with systemd services than cron.
Step 1: Create the Update Script
Create /usr/local/bin/update-game-server.sh:
#!/bin/bash
# Update script for game servers via SteamCMD
set -euo pipefail
SERVER_NAME="$1"
APP_ID="$2"
INSTALL_DIR="/opt/game-servers/$SERVER_NAME"
LOG_FILE="/var/log/game-updates/$SERVER_NAME.log"
# Stop the server before updating
systemctl stop "$SERVER_NAME" || true
# Run SteamCMD update
/usr/games/steamcmd +force_install_dir "$INSTALL_DIR" \
+login anonymous \
+app_update "$APP_ID" validate \
+quit >> "$LOG_FILE" 2>&1
# Start the server after update
systemctl start "$SERVER_NAME"
# Log the update timestamp
echo "$(date): $SERVER_NAME updated (app $APP_ID)" >> "$LOG_FILE"
Step 2: Create the systemd Timer Unit
Create /etc/systemd/system/palworld-update.timer:
[Unit]
Description=Palworld server update timer
Requires=palworld-update.service
[Timer]
OnCalendar=*-*-* 04:00:00
RandomizedDelaySec=300
Persistent=true
[Install]
WantedBy=timers.target
Step 3: Create the systemd Service Unit
Create /etc/systemd/system/palworld-update.service:
[Unit]
Description=Palworld server update
[Service]
Type=oneshot
ExecStart=/usr/local/bin/update-game-server.sh palworld 2394010
User=steam
Group=steam
Step 4: Enable and Start the Timer
sudo systemctl daemon-reload
sudo systemctl enable palworld-update.timer
sudo systemctl start palworld-update.timer
sudo systemctl status palworld-update.timer
The server will now update daily at 4:00 AM with a random 5-minute delay to prevent update stampedes. The Persistent=true flag ensures the update runs immediately after boot if the machine was offline at 4:00 AM.
Method 2: Cron (Simple and Ubiquitous)
For systems without systemd, or for simpler setups, cron is the traditional choice. The same update script works with a cron entry:
# Edit the crontab for the steam user
sudo crontab -u steam -e
# Add these lines for different game servers
# Palworld update at 4:00 AM daily
0 4 * * * /usr/local/bin/update-game-server.sh palworld 2394010
# Minecraft Paper update at 5:00 AM daily (check API for latest build)
0 5 * * * /usr/local/bin/update-minecraft.sh
Cron advantages: simple, portable, and works on every Unix-like system. Disadvantages: no logging integration, no dependency management, and no way to prevent overlapping runs.
SteamCMD App IDs for Common Games
| Game | Steam App ID | Update Frequency | Notes |
|---|---|---|---|
| Palworld | 2394010 | Weekly–monthly | Large download (15+ GB) |
| Valheim | 896660 | Monthly–quarterly | Small patches |
| 7 Days to Die | 294420 | Monthly | Alpha/beta branches available |
| Rust | 258550 | Monthly (forced wipe) | First Thursday of month |
| ARK: SA | 2430930 | Weekly–monthly | Very large (40+ GB per map) |
| Enshrouded | 2278520 | Monthly | Moderate download |
| Project Zomboid | 380870 | Monthly–quarterly | Small patches |
| Counter-Strike 2 | 730 | Weekly | Use srcds_run instead |
| Sons of the Forest | 2465200 | Monthly | Moderate download |
Graceful Restart: Don’t Kick Players Mid-Game
A hard restart during an update kicks players with no warning. For a better experience, use a graceful shutdown that notifies players before stopping the server:
#!/bin/bash
# Graceful restart script for Palworld
SERVER_NAME="palworld"
RCON_PORT=25575
RCON_PASS="your-rcon-password"
# Send warning via RCON
echo "Broadcast: Server restarting in 5 minutes for update" | rcon -a 127.0.0.1:$RCON_PORT -p $RCON_PASS
sleep 240
echo "Broadcast: Server restarting in 60 seconds. Save your progress!" | rcon -a 127.0.0.1:$RCON_PORT -p $RCON_PASS
sleep 60
echo "Broadcast: Server restarting NOW" | rcon -a 127.0.0.1:$RCON_PORT -p $RCON_PASS
# Save world before shutdown
systemctl stop "$SERVER_NAME"
# Update
/usr/local/bin/update-game-server.sh "$SERVER_NAME" 2394010
# Start is handled by the update script or watchdog
Update Verification: Did It Work?
After each update, verify that the server is running and responding:
#!/bin/bash
# Post-update health check
SERVER_NAME="$1"
# Check if process is running
if pgrep -f "$SERVER_NAME" > /dev/null; then
echo "$(date): $SERVER_NAME is running after update"
else
echo "$(date): ERROR - $SERVER_NAME failed to start after update"
systemctl restart "$SERVER_NAME"
# Send alert via email or webhook
curl -s -X POST "https://hooks.example.com/alert" \
-H "Content-Type: application/json" \
-d "{\"text\":\"$SERVER_NAME failed to start after update\"}"
fi
Multi-Game Server Update Orchestration
If you run multiple game servers on one machine, stagger the update times to avoid saturating the network link and disk I/O. A staggered schedule:
| Time | Server | App ID |
|---|---|---|
| 4:00 AM | Palworld | 2394010 |
| 4:30 AM | Valheim | 896660 |
| 5:00 AM | Minecraft (Paper) | N/A (curl check) |
| 5:15 AM | 7 Days to Die | 294420 |
Use RandomizedDelaySec=300 in systemd timers or a random sleep in cron to further spread the load.
Testing the Automation
Before trusting the automation in production, test it:
- Run the update script manually:
sudo /usr/local/bin/update-game-server.sh palworld 2394010 - Check the log:
cat /var/log/game-updates/palworld.log - Trigger the timer manually:
sudo systemctl start palworld-update.service - Verify the server starts and players can connect
- Simulate a failed update: remove the SteamCMD binary and confirm the alert fires
Summary
Automating game server updates with systemd timers or cron eliminates the most common maintenance burden of self-hosted game servers. systemd timers are the recommended approach for modern Linux distributions, offering better logging and integration with systemd services. Cron is a simpler alternative that works everywhere. Pair the automation with graceful shutdown notices and post-update verification to ensure updates happen without disrupting your players.
Review our dedicated server hosting options to find a machine with enough storage and bandwidth to handle unattended game updates.


Leave a Reply
You must be logged in to post a comment.