Back up your database

Backups run on their own. You need access to the server's storyforce_server.cfg and server files.

The backup cvars are read when a backup is due, so a change applies without a restart.

There is no in-game screen for this. You set it in storyforce_server.cfg.

Find your database

Every account, every character and everything attached to them lives in one SQLite file:

<fs_homepath>/<fs_game>/db/storyforce.db

With the shipped launcher that is GameData/StoryForce/db/storyforce.db.

The server prints the resolved path at boot, before the open is attempted, so a failure names the path it tried:

SF_DB_Open: failed to open 'GameData/StoryForce/db/storyforce.db': unable to open database file

After that line nobody can log in, register or load a character.

It is likely a permissions problem on the directory.

Set the backup up

Three cvars, all set by the shipped config to the values the mod already compiles in:

set  sf_dbbackup              "1"
set  sf_dbbackupinterval      "24"
set  sf_dbbackupretention     "7"
  • sf_dbbackup turns automatic backups on. 0 turns them off.
  • sf_dbbackupinterval is hours between snapshots. 0 also disables them.
  • sf_dbbackupretention is days to keep. Older snapshots are deleted after each successful new backup.

Run sf_dbbackup at the server console for an immediate snapshot, even when automatic backups are off.

Restore a backup

Restoring returns accounts, characters and XP to the snapshot's date. It replaces the whole database; it does not merge old records with newer ones. There is no restore command in the game.

  1. Stop the server cleanly, and close any database editor. Keep the server stopped throughout the file changes.
  2. Move the current storyforce.db into a dated folder outside the live db/ directory. Move any remaining storyforce.db-wal and storyforce.db-shm files with it, keeping them together as your rollback copy.
  3. Copy a completed .db snapshot from db/backups/ into the live db/ directory and name the copy storyforce.db. Keep the original snapshot. Do not use a .tmp file.
  4. Make sure the server can write the replacement file and its directory, then restart it with the same launcher and paths.
  5. Check the database path in the boot output, then log in and load a character to check the restored records.

What the backup does not cover

The backup copies the database and nothing else.

Not backed upWhere it lives
Every saved scene: placed props, lights, cameras, triggers, NPCs and spawns, on every map<fs_homepath>/<fs_game>/scenes/
What your AI-driven NPCs remember about people<fs_homepath>/<fs_game>/llm/<persona>/
Engine IP bans and exceptions<fs_homepath>/<fs_game>/serverbans.dat
StoryForce /sfban records<fs_homepath>/<fs_game>/bannedips.cfg
The shared prop library<fs_homepath>/<fs_game>/props/
Your own storyforce_server.cfg and anything you exec from itwherever you put it

Back those up yourself. They are all plain files, so any ordinary file-level backup of the mod folder covers them.

Mirror to Cloudflare D1

StoryForce can push accounts, characters, the item catalogue, item ownership and the XP award log to a Cloudflare D1 database so a website can read them. Containers and the private pending-XP draft queue stay local.

The whole block is commented out in the shipped config, so the mirror is off until you uncomment it.

set  sf_d1sync                "1"
set  sf_d1syncinterval        "0"
set  sf_d1syncpassword        "0"
set  sf_d1account             "<your Cloudflare account ID>"
set  sf_d1database            "<your D1 database UUID>"
set  sf_d1token               "<your scoped API token>"

The mirror is one-way and the game never reads back from it.

It pushes at map start, at a map change and at quit, and sf_d1syncinterval adds an optional push every so many seconds.

Only changed rows are sent.

Check sf_sync_meta before treating the mirror as updated. A finished cycle has in_progress = 0 and matching completed_cycle and cycle_id values.

An interrupted cycle can leave partial data.

sf_d1resync at the server console forces a full re-push. When it is enabled, the console replies:

SF_D1Sync: full reload queued

sf_d1syncpassword is a decision, not a default to copy. At 0 your players' password hashes never leave the server. At 1 the salted hash is mirrored too, which is what lets a website offer a login against the same account.

You will need to take appropriate steps to secure it.