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| Option | Meaning |
|---|---|
--listen ADDRESS | gRPC (HTTP/2) listener for remote clients; port 0 picks a free port |
--socket PATH | local IPC listener (Unix domain socket, mode 0600) |
--data DIR | data directory: shared object store (cas/), metadata (meta/), evidence (evidence/) |
--auth FILE | machine identities and grants |
--tls-cert-file PEM --tls-key-file PEM | terminate TLS in the daemon |
--allow-plaintext-remote | explicit exception for plain HTTP on a non-loopback address |
--git-listen ADDRESS, --git-project PROJECT=REPOSITORY | the Git HTTP endpoint; see Git interoperability |
--retention-interval-ms MS | run 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.
| Option | Default |
|---|---|
--journal-quota-bytes N|none | 1 GiB per workspace journal |
--concurrent-rpcs N | 256 (also the maximum) |
--resident-repositories N | 32 |
--resident-workspaces N | 256 |
--reply-memory-bytes N | one eighth of machine or cgroup memory, capped at 1 GiB |
--save-path-components N | 2049 (Git's 2048 directory levels plus a leaf) |
--store-presence-max-bytes N | 256 MiB per store; 0 disables the presence hint |
--git-bundle-bytes N | unset (no cap) |
--git-envelope-bytes N | 1 MiB |
--git-pending N | 4 |
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.v1field 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" capabilitiesOr 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" capabilitiesGIN_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" capabilitiesA 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 DIRcertifies 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 DIRrecovers 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.