Deployment
Graphorin runs in two shapes:
- Library mode — embedded in your existing Node.js process. No deployment story beyond your own application's.
- Daemon mode —
@graphorin/serverrunning as a long-lived process. The rest of this page covers production deployment of the daemon.
Reference templates
The repository ships templates for the three most common production environments:
examples/systemd/— a hardened unit file for systemd-managed servers.examples/docker/— a multi-stageDockerfileanddocker-compose.yml.examples/k8s/— aDeployment+Service+ConfigMapmanifest set.examples/github-actions/— a workflow that exercises Graphorin from CI.
All four templates run Graphorin as a non-root user with the audit log on its own mount and the secrets store unreadable by the application's main filesystem path.
Production checklist
Before promoting a Graphorin deployment to production:
Storage
- Pick a backend (local SQLite, encrypted SQLite, or a custom adapter).
- Schedule a snapshot / replication job. The default SQLite write-ahead log makes online backups via
BACKUP TO …straightforward. - Run
graphorin storage vacuumperiodically on long-lived deployments.
Encryption-at-rest
- The audit log is always encrypted (mandatory).
- Enable database encryption-at-rest via
@graphorin/store-sqlite-encryptedfor any deployment that stores user secrets orsecret-tagged memory rows. - The passphrase resolves through
SecretRef— keep it in the OS keychain or a managed vault, never in plain config files.
Tokens
- Issue tokens with
graphorin token issue --role <role> --ttl <duration>. - Set a TTL appropriate for the role. Admin tokens should be short-lived.
- Rotate the deployment-wide pepper on a schedule.
- Document who holds which token in your incident-response runbook.
- Issue tokens with
Observability
- Wire
OTLP_URL(or another supported exporter). The default is no remote export. - Confirm
withValidation(...)is in the exporter chain — the tracer factory throws if it is missing, so this is a soft check. - Configure the redaction allowlist for any high-cardinality attribute that's safe to ship un-redacted.
- Wire
Triggers
- Decide which triggers run in production and at what cadence.
- Use
graphorin triggers listto review the active configuration. - Configure quotas if you operate against a paid LLM provider.
OAuth
- Pre-register every authorisation server's client metadata.
- Pin the redirect URI to a known loopback port for unattended hosts (no GUI), or to your reverse proxy on hosts with one.
- Audit
graphorin auth statusperiodically.
Hardening
- Run
graphorin doctorafter every deployment. Fix every error before traffic is enabled. - Run as a dedicated service account.
- Confine the secrets store to mode
0600. - Confine the audit log to mode
0600. - Confine the database to mode
0640. - Disable core dumps for the service account.
- Run
Systemd
# /etc/systemd/system/graphorin.service
[Unit]
Description=Graphorin standalone server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=graphorin
Group=graphorin
WorkingDirectory=/var/lib/graphorin
ExecStart=/usr/bin/node /usr/lib/graphorin/cli/dist/cli.js start --config /etc/graphorin/graphorin.config.toml
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/graphorin
PrivateTmp=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictNamespaces=true
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
CapabilityBoundingSet=
[Install]
WantedBy=multi-user.targetDocker
The examples/docker/ template ships a multi-stage build that produces a slim image with only the runtime dependencies. Run with:
docker run -d --name graphorin \
-v graphorin-data:/var/lib/graphorin \
-p 127.0.0.1:8787:8787 \
-e OTLP_URL=https://otel.example.com/v1/traces \
ghcr.io/o-stepper/graphorin:0.1.0Mount the data directory as a named volume so SQLite + the audit log + the secrets store survive container recreation.
Kubernetes
The examples/k8s/ manifest set runs Graphorin as a non-root pod with:
- a
PersistentVolumeClaimfor the data directory; - a
Secretfor the deployment pepper; - a
ConfigMapfor the rest of the configuration; - a
NetworkPolicythat pins egress to the configured provider, MCP, and OTLP endpoints only.
GitHub Actions
The examples/github-actions/ template exercises Graphorin from a CI pipeline — a hermetic pnpm install, a stub-provider agent run, a smoke test against the standalone server, and a JSONL session export.
Health checks
Wire your load balancer / orchestrator's liveness probe to GET /v1/health. The endpoint returns a 200 OK only when storage, the audit log, the secrets store, and the triggers daemon are all healthy.
Next steps
- Standalone server — REST endpoints, configuration.
- CLI —
graphorin doctor,graphorin token. - Security — production hardening checklist.
- Observability — OTLP exporter wiring.
Graphorin · v0.1.0 · MIT License · © 2026 Oleksiy Stepurenko