Documentation/Run your server
Operations5 min read

Operations

On this page

Layout and ownership

text
<data-dir>/SCRIBE_FORMAT     descriptor and versions (required feature auth-ownership-v1 once auth-init ran)
<data-dir>/LOCK              exclusive OS lock held by serve or any maintenance command
<data-dir>/catalog.redb
<data-dir>/auth-state.redb   workspace and operation ownership (only after auth-init)
<data-dir>/repos/<id>/       metadata.redb, objects/, SCRIBE_FORMAT
<log-dir>/                   disposable diagnostics (daily files, bounded retention)
<runtime-dir>/               disposable: scribe-server.pid, listen, shutdown-request

Authoritative data, logs, and runtime files are separate directories. init refuses non-empty directories; serve refuses directories without a recognized descriptor; no command uses the current directory implicitly. The auth service has its own data directory with the same one-owner rule.

Routine health checks

scribe-server doctor --data-dir <data> (alias scan) is the complete read-only check: it takes the ownership lock, so it cannot run beside the server, examines metadata consistency and every pack, and re-hashes every object in parallel. Schedule it before each backup and after any unclean shutdown; --quick skips chunk hashing for a sub-second structural pass. Exit 0 healthy, 1 problems (listed, never repaired), 2 could not run.

scribe-server usage --data-dir <data> (alias df) is the millisecond inventory: per-repository counts and sizes, the root total, and the filesystem's free space. It is the first look when a disk fills up and the way to size a backup destination.

Configuration precedence

Flag, then SCRIBE_LOG (log filter) and SCRIBE_SERVER_CONFIG (config path), then the configuration file, then defaults. Relative paths in the file resolve against the file's directory; relative flag paths against the current directory. Startup logs every resolved non-secret path and limit. The full file is shown in server-usage.md.

Shutdown

SIGINT, SIGTERM, or creating <runtime-dir>/shutdown-request stops admission and closes idle connections. Queued requests stop; started requests get up to drain_timeout_secs for network I/O. The deadline interrupts sockets, then the process waits for started storage jobs before releasing its root lock. A stalled disk can extend shutdown; durable commits are never cancelled. Forced termination leaves recoverable state: acknowledged commits are durable and the next start truncates unreferenced pack tails and removes staging leftovers.

Security

Two deployment modes exist; choose one per data root.

Authenticated (recommended beyond one machine). The storage server serves TLS 1.3 only, users present revocable tokens, and every operation is authorized per repository through the shared scribe-auth service. Commit and lock attribution comes from the token, not from a client-supplied author. Clients pin the server's CA on first use and refuse a changed CA. Setup, roles, token lifetimes, and revocation latency (new admissions within 30 seconds) are in auth.md. Keep CA keys offline; give each server its own leaf certificate and its own service token.

Plaintext (loopback or tunnel only). TCP v2 without auth has no authentication: workspace ids and author labels are self-declared, and any peer that can reach the port can submit, lock, and unlock as anyone. The server refuses non-loopback listen addresses unless allow_non_loopback = true and logs server.plaintext_exposed when it is. Acceptable only behind an authenticated tunnel, for example ssh -L 7447:127.0.0.1:7447 vcs-host on each client with listen = "tcp://127.0.0.1:7447" on the server.

Capacity and performance expectations

Recorded in tools/scribe-perf/baselines/macos-ci.json on a developer MacBook (Apple SSD with F_FULLFSYNC), ci profile:

itemvalue
durable metadata transaction (1000 adds)p50 33 ms, p95 44 ms
durable lock acquire (single transaction)4 ms
accept transaction hold under 32 clientsp50 44 ms, p99 92 ms
publication gate wait under 32 clients (6 concurrent submitters)p50 153 ms, p99 444 ms
small submit latency, idle serverp50 91 ms
initial import 107 MiB / 1544 files0.79 s
initial sync of the same0.63 s (170 MiB/s logical)
no-op sync45 ms, zero payload bytes
20k small objects, packs vs loose files0.3 s vs 100 s

These numbers are dominated by flush cost. Linux ext4 or xfs on a datacenter SSD flushes in 1 to 3 ms and should show roughly an order of magnitude lower transaction and gate times; that is a prediction, not a measurement.

Lock and workspace transactions share the per-repository writer with acceptance, so under load lock operations queue behind submits (lock p50 above 100 ms under load versus 4 ms idle). A separate coordination database is the planned remedy if a Linux measurement confirms it.

Disk: the server archive is roughly the logical size of unique content plus metadata (a few hundred bytes per path revision). Each workspace costs the logical size of its view, plus whatever accumulates in .scribe/recovery/ until the user empties it. The client cache holds only objects up to 256 KiB plus manifests.

Performance profiles of scribe-perf

  • ci: about 107 MiB, 1544 files; runs in about 40 s; deterministic gates; suitable for shared CI.
  • million-paths: 1,000,000 files of 1 to 4 KiB plus 100 medium binaries, about 2.5 GiB dataset, about 10 GiB sandbox; opt-in on dedicated hardware; --quick uses 100,000 files.
  • scale: at least 500 GiB of generated compressible/incompressible data; requires --disk-budget-gib 1100 or more; dedicated hardware only.

Baselines are machine-specific. compare refuses reports whose profile, OS, architecture, seed, dataset size, client count, durability, or build profile differ, and treats sub-millisecond changes below the configured noise floor as noise. Updating a baseline is an explicit commit with an explanation.

Windows notes

Windows is the primary client platform. The client sets the read-only attribute in --readonly workspaces, retries renames and deletes on sharing violations and transient access-denied results from scanners, opens directories without delete sharing, rejects reparse points, and opens long paths with the \\?\ prefix whether or not LongPathsEnabled is set (other tools on the machine may not handle such paths). Directory-handle flushing on NTFS is best effort and reported as such. The Windows-specific tests run in CI on windows-latest; read them from CI before making a Windows claim.

Source docs/operations.mdSnapshot 93d02b17