Backup and restore

One file matters. Everything else under instance.dataDir is a clone or a derived index, and will be rebuilt from your code hosts and your configuration.

/var/lib/searchcode/
  subjects.db          <- back this up
  repos/               <- clones. Rebuildable.
  analysis/            <- derived. Rebuildable.
  audit/               <- if audit.output: file. See below.

subjects.db

One SQLite file holding five tables, and it is the enterprise binary's only durable state:

Table What is lost if it goes
subjects Every principal this instance has authenticated, in every auth mode, with first-seen and last-seen. This is what the seat meter reads.
local_accounts Password records for auth.mode: local. Everybody has to be recreated.
api_keys Personal API keys. Every agent integration that uses one breaks until it is reissued.
oauth_refresh_tokens The refresh tokens OAuth-connected agents hold, as digests. Every such agent has to sign in through the browser again.
connections Code-host connections created on the connect screen, with their tokens sealed under the connection key. Back up that key with this file: restoring one without the other leaves connections that cannot be decrypted (see connections).

In auth.mode: open no store is opened at all, so an open instance has no database under dataDir. That is deliberate rather than an oversight.

Backing it up

SQLite in WAL mode, so do not copy the file with cp while the process is running — you will get a torn read. Use the online backup:

sqlite3 /var/lib/searchcode/subjects.db ".backup '/backup/subjects-$(date +%F).db'"

Or stop the service and copy it. It is a few megabytes for a few thousand users; a nightly job is ample.

In Kubernetes, a volume snapshot of the PVC is the simplest correct answer. The file is consistent from a snapshot in the same way it is consistent after a power cut, which SQLite is designed for.

Configuration

Your searchcode.yaml and conf.d/ fragments are the other thing you cannot regenerate — and they belong in git rather than in a backup, which is what the no-inline-secrets rule buys you. There is no field anywhere in the file that takes a secret value, so the whole configuration directory is safe to commit, review and diff.

What is not in git: the files those *File references point at — SSH keys, proxy shared secrets, the licence. Those come from your secret manager and should already be in whatever backup covers it.

Restoring

  1. Install the same product version, or a newer one. State is forward-compatible.
  2. Restore searchcode.yaml and conf.d/ from git.
  3. Restore the secret files your config references.
  4. Restore subjects.db into instance.dataDir.
  5. Start it.

Clones and analysis rebuild on their own. The instance serves while that is happening — it binds and answers before ingestion finishes, and a repository that is not ready yet is reported as a coverage gap rather than as an empty result. Depending on estate size, expect full coverage in minutes to hours; see Sizing.

Restoring without subjects.db

Recoverable, but not silently:

Audit records

If audit.output is file, those files are your compliance artefact and your retention policy applies to them, not ours. They are written one file per UTC day, which is what makes retention a whole-file delete rather than a rewrite of a file being appended to.

If audit.output is stdout (the default), stderr or syslog, the records are already in whatever collects them and nothing under dataDir needs backing up.

Disaster recovery drill

Worth doing once, and it takes an afternoon:

  1. Snapshot subjects.db.
  2. Stand up a second instance with the same config and the restored file.
  3. Sign in, issue a search, call one MCP tool with an existing key.
  4. Watch the estate rebuild and time it. That number is your recovery time objective, and it is dominated by clone throughput rather than by anything this product does.

What is deliberately not here

There is no backup command, no snapshot subcommand and no restore wizard. One SQLite file and a directory of configuration is a backup story your existing tooling already covers, and a bespoke one would be a second thing to test.

Generated from the documentation that ships with searchcode enterprise. Questions: ben@boyter.org