Skip to content

Running the daemon ​

gin serve runs Gin as a service. It owns the shared object store, the metadata store, the evidence store and the workers' journals, and serves the gin.v1 API to authenticated clients. Embedded mode and the daemon share one core, so validation, envelopes and behaviour are identical.

Starting gin serve ​

sh
gin serve --listen 127.0.0.1:7400 --data /var/lib/gin --auth /etc/gin/auth.conf
OptionMeaning
--listen ADDRESSgRPC (HTTP/2) listener for remote clients; port 0 picks a free port
--socket PATHlocal IPC listener (Unix domain socket, mode 0600)
--data DIRdata directory: shared object store (cas/), metadata (meta/), evidence (evidence/)
--auth FILEmachine identities and grants
--tls-cert-file PEM --tls-key-file PEMterminate TLS in the daemon
--allow-plaintext-remoteexplicit exception for plain HTTP on a non-loopback address
--git-listen ADDRESS, --git-project PROJECT=REPOSITORYthe Git HTTP endpoint; see Git interoperability
--retention-interval-ms MSrun a background retention worker

The daemon logs to stderr and announces its address when ready, for example gin serve: gRPC on 127.0.0.1:7400. Run it as an unprivileged user that owns only its data directory. Do not open the data directory from another process while the daemon runs: its stores are exclusively locked.

Resource limits ​

All limits have defaults; set them only when you need to.

OptionDefault
--journal-quota-bytes N|none1 GiB per workspace journal
--concurrent-rpcs N256 (also the maximum)
--resident-repositories N32
--resident-workspaces N256
--reply-memory-bytes None eighth of machine or cgroup memory, capped at 1 GiB
--save-path-components N2049 (Git's 2048 directory levels plus a leaf)
--store-presence-max-bytes N256 MiB per store; 0 disables the presence hint
--git-bundle-bytes Nunset (no cap)
--git-envelope-bytes N1 MiB
--git-pending N4

Idle owners are evicted least-recently-used; active owners are never evicted. Other tuning flags (--content-memory-bytes, --descriptor-budget, --descriptor-queue, --store-proof-bookkeeping, --ancestry-*) are listed by gin help.

Authentication and authorisation ​

Every client is a configured machine identity with one bearer token. The identity's name is the principal the metadata store checks. The auth file names identities and grants:

text
identity controller token-file /run/secrets/gin-controller
identity builder    token-env  GIN_TOKEN_BUILDER
grant controller repository gin:blake3:v1:repository:<hex> operations *
grant builder    repository gin:blake3:v1:repository:<hex> operations read_manifest,read_blobs,pin_snapshot,renew_pin,release_pin
grant builder    repository gin:blake3:v1:repository:<hex> workspace gin:blake3:v1:workspace:<hex> operations save,publish
local 1000 controller     # local IPC peers running as uid 1000
embedded controller       # the process embedding the library
  • Tokens are 32 to 1024 visible ASCII bytes, never written inline, and never shared between identities. The daemon keeps only a digest of each token.
  • Remote callers send authorization: Bearer <token> on every call.
  • Local IPC peers are admitted by kernel peer credentials and act as the identity bound to their uid.
  • Grants name operations by their gin.v1 field name (save, read_blobs, ...) or *, a repository, and optionally one workspace.
  • The principal always comes from the transport, never from a request payload.

Grant only what each identity needs. For lifecycle work that is fork,save,publish,preview,advance,context,read_path; for published content, read_manifest,read_blobs.

Not yet built

There is no mTLS, key-pair enrolment, short-lived token, rotation or live revocation. Replacing a leaked token means editing the auth file and restarting the daemon.

Remote sessions ​

The CLI and gin mcp connect to a daemon with an endpoint and a token file instead of local options:

sh
gin --endpoint https://gin.example:7400 --token-file /private/client.token \
  --repository "$repository" --workspace "$workspace" capabilities

Or with environment variables: GIN_ENDPOINT, GIN_TOKEN_FILE, GIN_REPOSITORY, GIN_WORKSPACE. Remote sessions refuse --host, --data and --principal (including their environment variables) before opening any local store, and never fall back to local stores after a failed call.

Use gin capabilities to discover what the server supports and what you are granted. Never infer support from a tool's presence: an unsupported operation is a server refusal.

Timeouts ​

There is no whole-call deadline by default; pass --timeout SECONDS before the command to opt in. Connection setup times out after 10 seconds, and HTTP/2 keepalive probes detect an unresponsive connection. A timed-out mutation has an unknown outcome: see Recovering from a lost reply.

TLS ​

Supply a PEM certificate chain (leaf first) and an unencrypted PEM key:

sh
gin serve --listen 0.0.0.0:7400 --data /var/lib/gin --auth /etc/gin/auth.conf \
  --tls-cert-file /etc/gin/server-chain.pem --tls-key-file /etc/gin/server-key.pem
  • On Unix the key must be a regular file owned by the daemon's user with no group or other permissions (chmod 600).
  • Files are read once at startup. To rotate, replace the pair and restart.
  • TLS 1.2 and 1.3 with safe defaults. There is no plaintext fallback.

Clients verify the server against bundled Mozilla roots. Machine-installed CAs are not inherited. For a private CA, and when the address differs from the certificate name:

sh
gin --endpoint https://192.0.2.10:7400 --tls-server-name gin.internal \
  --ca-file /etc/gin/private-ca.pem --token-file /private/client.token \
  --repository "$repository" --workspace "$workspace" capabilities

GIN_CA_FILE and GIN_TLS_SERVER_NAME are the environment equivalents; flags override them.

Plaintext is refused beyond loopback ​

Plain HTTP is allowed by default only to numeric loopback addresses and localhost (pinned to 127.0.0.1). A non-loopback or wildcard address is refused before connecting or binding. For an explicitly trusted link, opt in on each side; there is deliberately no environment variable for this:

sh
gin serve --listen 192.0.2.10:7400 --data /var/lib/gin --auth /etc/gin/auth.conf \
  --allow-plaintext-remote
gin --endpoint http://192.0.2.10:7400 --allow-plaintext-remote \
  --token-file /private/client.token --repository "$repository" --workspace "$workspace" capabilities

A TLS proxy in front of a loopback Gin backend needs no exception.

Debugging only

--insecure-skip-tls-verify skips chain, validity and hostname checks. An attacker can then impersonate the server and receive your token and source. It has no environment variable, warns on every connection, and cannot be combined with --ca-file or --tls-server-name. Use --ca-file for a private CA instead.

When a TLS pair is supplied, the Git listener (--git-listen) uses the same identity and also serves HTTPS, including on loopback.

Operations and maintenance ​

  • Verification: gin verify --data DIR certifies the stopped store's objects and references. It performs normal recovery first; preserve a separate copy if you need untouched crash evidence.
  • Repair: gin repair --data DIR recovers worker journals and rebuilds the immutable-pack index.
  • Retention: gin retention report|collect --data DIR; see CLI reference.
  • Upgrades: every store records its format version. A binary refuses a store newer than it understands; it never downgrades data silently. Snapshot the data directory before switching versions.

Part of the Tama toolchain.