Schedule a Counter-Strike 2 server restart

A Counter-Strike 2 server holds no persistent world, so a scheduled restart is purely about clearing accumulated state and picking up configuration changes. Every day is generous; every few days is usually enough.

When should it restart?

Use {{minutes}} where the countdown number should go.

What happens, in order

  1. Job startsWarnsay Server restarting in 15 min
  2. 10 min beforeWarnsay Server restarting in 10 min
  3. 5 min beforeWarnsay Server restarting in 5 min
  4. 1 min beforeWarnsay Server restarting in 1 min
  5. Restart timeStopquit

Nothing to save. Restart between matches rather than mid-round — a scheduled restart that lands in the middle of a competitive game is worse than no restart at all.

The crontab line

Shifted 15 minutes earlier than your chosen time, so the restart itself lands on it rather than 15 minutes after.

45 3 * * *  /opt/restart-cs2.sh

The script it runs

Save as /opt/restart-cs2.sh and make it executable. It assumes rcon-cli is on the path and reads the password from the environment rather than embedding it.

#!/usr/bin/env bash
set -euo pipefail

# Scheduled restart for Counter-Strike 2.
# Generated by spawnly.net/tools/restart-scheduler

# The password stays out of this file. Put it in the environment, or in a
# file only root can read, and export it before this script runs.
RCON_HOST="${RCON_HOST:-127.0.0.1}"
RCON_PORT="${RCON_PORT:-27015}"
: "${RCON_PASSWORD:?set RCON_PASSWORD before running}"

send() {
  rcon-cli --host "$RCON_HOST" --port "$RCON_PORT" --password "$RCON_PASSWORD" "$1"
}

# 15 minute warning
send 'say Server restarting in 15 min'

sleep 300
# 10 minute warning
send 'say Server restarting in 10 min'

sleep 300
# 5 minute warning
send 'say Server restarting in 5 min'

sleep 240
# 1 minute warning
send 'say Server restarting in 1 min'

sleep 70
# Shut down cleanly
send 'quit'

# Give the process time to finish writing before anything restarts it.
sleep 30
systemctl start cs2 2>/dev/null || true

Cron uses the server’s timezone, not yours. Check it with timedatectl before assuming 04:00 means 04:00 where you are — a container in UTC and an admin in Europe are two hours apart in summer and one in winter.

The part specific to Counter-Strike 2

Timing is the whole problem. A restart landing mid-round on a competitive server is worse than no restart at all, and cron has no idea what a round is. Schedule for a genuinely dead hour, and if your population never has one, drive the restart from a plugin that waits for a map change instead of from a timer.

Support & Help