- Posted on
- • Artificial Intelligence
Artificial Intelligence ARK Server Backups
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence ARK Server Backups (with Bash): Smarter, Safer, and Hands-Off
If you run an ARK: Survival Evolved server, you already know the pain: world saves are huge, players are unpredictable, and a single crash can cost days of progress. Traditional “set a cron and pray” backups work—until they don’t. This post shows how to build a resilient, Bash-first backup pipeline that’s AI‑aware: it adapts backup frequency to real player activity, detects anomalies, verifies integrity, and ships your data offsite.
You’ll get:
A ready-to-use Bash backup script for ARK
Installation steps for apt, dnf, and zypper
Cloud sync via rclone and versioned, deduplicated storage via restic
Optional AI logic (local, via Ollama) to vary backup intervals and flag suspicious changes
Why AI for ARK backups?
Load-aware scheduling: Back up more during peak times, less during off-hours—without guessing. AI can summarize logs, predict high-activity windows, and adjust intervals.
Anomaly detection: Sudden drops in backup size usually mean corruption, unintended wipes, or misconfigurations. A model can flag this for you in plain language.
Cost control: Versioned dedup backups are cheap; useless frequent full tars are not. Smart schedules plus dedup keep you safe and thrifty.
What we’ll build
restic for incremental, encrypted, verifiable backups
rclone to sync those backups to your preferred cloud
A Bash script that:
- Triggers a save (optionally via your RCON client)
- Runs a restic backup + retention + health check
- Optionally uses a local LLM (Ollama) to adjust the next backup interval from ARK logs
- Syncs the repository to cloud storage
Prerequisites and installation
We’ll use restic, rclone, jq, and cron (or systemd timers). Install them with your package manager:
- Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y restic rclone jq cron
sudo systemctl enable --now cron
- Fedora/RHEL/CentOS Stream (dnf):
sudo dnf install -y restic rclone jq cronie
sudo systemctl enable --now crond
- openSUSE (zypper):
sudo zypper refresh
sudo zypper install -y restic rclone jq cron
sudo systemctl enable --now cron
Optional local AI (Ollama). This uses a small, local LLM—no cloud keys needed:
curl -fsSL https://ollama.com/install.sh | sh
# Start Ollama service if not auto-started:
sudo systemctl enable --now ollama
# Pull a compact, capable model:
ollama pull llama3:8b
Note: If you don’t want AI, keep AI_MODE=off in the script below.
One-time setup
1) Choose where your ARK server data lives (example paths):
ARK directory: /opt/ark/ShooterGame
Saves: /opt/ark/ShooterGame/Saved
Config: /opt/ark/ShooterGame/Saved/Config/LinuxServer
2) Create a local restic repository and a password file:
sudo mkdir -p /srv/ark-backups/repo
sudo mkdir -p /srv/ark-backups/state
sudo install -m 600 /dev/null /srv/ark-backups/restic-password
echo "A-Strong-Unique-Password" | sudo tee /srv/ark-backups/restic-password >/dev/null
export RESTIC_REPOSITORY=/srv/ark-backups/repo
export RESTIC_PASSWORD_FILE=/srv/ark-backups/restic-password
restic init
3) Create and configure an rclone remote (S3, Backblaze, Google Drive, etc.):
rclone config
# Follow the prompts to create a remote, e.g. name it: arkremote
# Example backup target: arkremote:ark-backups/restic-repo
4) Verify permissions. Ensure the user that will run backups can read ARK saves and write to the repo.
The AI‑aware Bash backup script
Save as /usr/local/bin/ark-backup.sh and make it executable.
#!/usr/bin/env bash
set -euo pipefail
# ========= Config =========
# Paths
ARK_DIR="${ARK_DIR:-/opt/ark/ShooterGame}" # adjust to your server path
SAVES_DIR="$ARK_DIR/Saved"
CONFIG_DIR="$ARK_DIR/Saved/Config/LinuxServer"
# Restic
RESTIC_REPOSITORY="${RESTIC_REPOSITORY:-/srv/ark-backups/repo}"
RESTIC_PASSWORD_FILE="${RESTIC_PASSWORD_FILE:-/srv/ark-backups/restic-password}"
# rclone remote (set to "" to disable cloud sync)
RCLONE_REMOTE="${RCLONE_REMOTE:-arkremote:ark-backups/restic-repo}"
# State and logs
STATE_DIR="${STATE_DIR:-/srv/ark-backups/state}"
LOG_DIR="${LOG_DIR:-$STATE_DIR/logs}"
mkdir -p "$STATE_DIR" "$LOG_DIR"
# AI controls
AI_MODE="${AI_MODE:-off}" # off | ollama
AI_MODEL="${AI_MODEL:-llama3:8b}" # ollama model tag
DEFAULT_INTERVAL_MIN="${DEFAULT_INTERVAL_MIN:-60}" # fallback interval
NEXT_RUN_FILE="$STATE_DIR/next_run_epoch"
# Optional pre-backup save trigger (if you have an rcon client or admin tool installed)
# Example: PRE_BACKUP_CMD="rcon-cli -a 127.0.0.1:27020 -p 'RCONPASS' command SaveWorld"
PRE_BACKUP_CMD="${PRE_BACKUP_CMD:-}"
# Retention policy for restic
RETENTION_ARGS=(
--keep-hourly 24
--keep-daily 7
--keep-weekly 4
--keep-monthly 6
)
# ========= Helpers =========
now_epoch() { date +%s; }
log() {
echo "[$(date -Is)] $*" | tee -a "$LOG_DIR/ark-backup.log"
}
require() {
command -v "$1" >/dev/null 2>&1 || { log "Missing dependency: $1"; exit 1; }
}
# ========= Dependencies =========
require restic
require rclone
require jq
# ========= AI interval recommendation (optional) =========
recommend_interval_minutes() {
# Simple heuristic if AI is off: more frequent when players were active in the last 2 hours
# You can replace this with your own logic if you don’t use AI.
local activity_lines
activity_lines=$(grep -h -E 'Join|Logout|SaveGame' "$SAVES_DIR"/Logs/*.log 2>/dev/null | tail -n 500 || true)
if [[ "$AI_MODE" == "ollama" ]]; then
command -v ollama >/dev/null 2>&1 || { log "AI_MODE=ollama but ollama not found; falling back."; AI_MODE=off; }
fi
if [[ "$AI_MODE" == "ollama" ]]; then
# Compose a compact prompt; ask for a plain integer in minutes.
local prompt
prompt=$(cat <<'P'
You analyze ARK server log snippets that include player joins/leaves and saves.
Decide the next backup interval in minutes:
- Heavy activity -> 10-15 minutes
- Moderate -> 30-45 minutes
- Light/idle -> 60-120 minutes
Only output a single integer number of minutes. No extra text.
P
)
local minutes
# Send to ollama; pass logs as context
minutes=$(printf "%s\n\nLogs:\n%s\n" "$prompt" "$activity_lines" \
| ollama run "$AI_MODEL" 2>/dev/null \
| tr -cd '0-9' | head -c 4)
if [[ -n "$minutes" && "$minutes" -gt 0 ]]; then
echo "$minutes"
return 0
fi
# Fall through to heuristic on parse failure
log "AI recommendation parse failed; using heuristic."
fi
# Heuristic: if we saw recent joins/logouts/saves, back up more often.
if [[ -n "$activity_lines" ]]; then
echo 30
else
echo "$DEFAULT_INTERVAL_MIN"
fi
}
# ========= Scheduling guard =========
guard_next_run() {
local now
now=$(now_epoch)
if [[ -f "$NEXT_RUN_FILE" ]]; then
local next
next=$(cat "$NEXT_RUN_FILE" || echo 0)
if [[ "$now" -lt "$next" ]]; then
log "Not time yet (next run at epoch $next). Exiting."
exit 0
fi
fi
}
set_next_run() {
local mins="$1"
local now next
now=$(now_epoch)
next=$(( now + mins*60 ))
echo "$next" > "$NEXT_RUN_FILE"
log "Next backup scheduled in ${mins}m (epoch $next)."
}
# ========= Core backup tasks =========
trigger_save_if_configured() {
if [[ -n "$PRE_BACKUP_CMD" ]]; then
log "Triggering pre-backup save..."
# shellcheck disable=SC2086
bash -c "$PRE_BACKUP_CMD" || log "Warning: PRE_BACKUP_CMD failed; continuing."
# Give the server a brief moment to flush
sleep 5
fi
}
run_backup() {
log "Starting restic backup..."
# Use JSON for machine-readable stats; tee to a run log
local runlog="$LOG_DIR/backup-$(date +%s).jsonl"
if restic backup \
--tag ark \
--host "$(hostname -s)" \
--json \
"$SAVES_DIR" "$CONFIG_DIR" | tee "$runlog"
then
log "Backup completed."
else
log "Backup failed."
exit 2
fi
# Extract totals from the last JSON line with a summary
local total_bytes files_new
total_bytes=$(tac "$runlog" | jq -r 'select(.message_type=="summary") | .total_bytes_processed' | head -n1)
files_new=$(tac "$runlog" | jq -r 'select(.message_type=="summary") | .files_new' | head -n1)
log "Bytes processed: ${total_bytes:-unknown}, new files: ${files_new:-unknown}"
}
apply_retention() {
log "Applying retention: ${RETENTION_ARGS[*]}"
# shellcheck disable=SC2068
restic forget ${RETENTION_ARGS[@]} --prune
log "Retention done."
}
verify_health() {
log "Verifying repository integrity (restic check)..."
if restic check --read-data-subset=1/20; then
log "Repository check OK."
else
log "Repository check reported issues."
fi
}
sync_remote() {
if [[ -n "$RCLONE_REMOTE" ]]; then
log "Syncing repository to $RCLONE_REMOTE ..."
rclone sync --fast-list --stats=60s "$RESTIC_REPOSITORY" "$RCLONE_REMOTE"
log "Cloud sync complete."
else
log "RCLONE_REMOTE not set; skipping cloud sync."
fi
}
# ========= Main =========
guard_next_run
trigger_save_if_configured
run_backup
apply_retention
verify_health
sync_remote
# Set next run from AI or heuristic
mins=$(recommend_interval_minutes)
set_next_run "$mins"
log "All tasks complete."
Make it executable:
sudo chmod +x /usr/local/bin/ark-backup.sh
Environment variables you may want to set system-wide (for the backup user):
ARK_DIR=/opt/ark/ShooterGame
RESTIC_REPOSITORY=/srv/ark-backups/repo
RESTIC_PASSWORD_FILE=/srv/ark-backups/restic-password
RCLONE_REMOTE=arkremote:ark-backups/restic-repo
AI_MODE=ollama or off
PRE_BACKUP_CMD="your RCON save command" (optional)
You can place them in /etc/environment or a dedicated file you source from cron.
Schedule it
Cron approach: run every 5 minutes; the script self-throttles using its state file and AI/heuristics.
crontab -e
# Every 5 minutes, with environment sourced for safety
*/5 * * * * . /etc/environment; /usr/local/bin/ark-backup.sh >> /var/log/ark-backup.cron.log 2>&1
Systemd timer (alternative): Create /etc/systemd/system/ark-backup.service
[Unit]
Description=ARK Smart Backup
[Service]
Type=oneshot
Environment=ARK_DIR=/opt/ark/ShooterGame
Environment=RESTIC_REPOSITORY=/srv/ark-backups/repo
Environment=RESTIC_PASSWORD_FILE=/srv/ark-backups/restic-password
Environment=RCLONE_REMOTE=arkremote:ark-backups/restic-repo
Environment=AI_MODE=ollama
ExecStart=/usr/local/bin/ark-backup.sh
And /etc/systemd/system/ark-backup.timer
[Unit]
Description=Run ARK Smart Backup often (self-scheduled)
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.target
Enable:
sudo systemctl daemon-reload
sudo systemctl enable --now ark-backup.timer
Real-world tips and examples
Consistent saves: Ideally, trigger ARK’s SaveWorld before backup. If you already use an RCON client, set PRE_BACKUP_CMD to run it a few seconds before restic.
Test restores regularly:
# List snapshots
restic snapshots
# Restore latest to a safe location for validation
restic restore latest --target ~/ark-restore-test --path "/opt/ark/ShooterGame/Saved"
Remote-first repositories: You can point RESTIC_REPOSITORY directly to cloud (e.g., an S3 URL) using restic’s native backends, or keep local + rclone sync as shown. Native remotes are simpler but may hit provider API limits during peaks; local+sync can be friendlier for busy servers.
Anomaly watch: The script logs “Bytes processed.” Sudden changes (e.g., near-zero or 10x spikes) warrant investigation. You can extend the script to compare to a rolling median and send alerts via mailx or Discord webhooks.
Troubleshooting
Permission denied: Make sure the backup user can read the ARK directories and write to the repo and state/log dirs.
Long runs: Increase DEFAULT_INTERVAL_MIN if your worlds are huge; restic dedup drastically reduces time after the first run.
Ollama not responding: Ensure the service is running:
systemctl status ollama
Conclusion and next steps
Backups shouldn’t be set-and-forget; they should be set-and-adapt. With a few portable tools and a pinch of AI, your ARK backups can become:
Safer (versioned, verified, offsite)
Smarter (activity-aware intervals)
Simpler (one Bash script, cron/systemd)
Next steps: 1) Install the tools and initialize your restic repo. 2) Drop in the script, set PRE_BACKUP_CMD if you have an RCON client, and enable cron or a timer. 3) Flip AI_MODE=ollama, pull a model, and watch your schedule auto-tune. 4) Do a test restore—then sleep better.
Have ideas for improvements, like Discord alerts or snapshot diff summaries? Add them as small functions—the script is built to be extended.