Install and configure
Product Exec runs Spend for most agencies. Agencies that want it in their own cloud account run the same build; this page is for them and for the IT teams who review the design.
Requirements
Section titled “Requirements”- The container image (Node.js 22), or Node.js 22 with pnpm 10.
- Postgres 15 or later with encryption at rest and TLS (Amazon RDS or Aurora, Azure Database for PostgreSQL, Cloud SQL).
- An S3-compatible bucket for documents with versioning and a lifecycle rule matching the records retention schedule.
- An OpenID Connect or SAML app registration at the identity provider.
- A TLS certificate, or a load balancer that terminates TLS.
docker run -p 8080:8080 --env-file spend.env <spend image>The server serves the web app and the API on one port. It refuses to start without TLS unless told a load balancer terminates it (TLS_TERMINATED_UPSTREAM=1).
Core settings
Section titled “Core settings”| Variable | Meaning |
|---|---|
DATABASE_URL | Postgres connection string; tables are created on first start |
S3_BUCKET, S3_REGION, S3_ENDPOINT | Document storage; S3_ENDPOINT for MinIO or another S3-compatible service |
KMS_KEY_ID | AWS KMS key that wraps each tenant’s data key; can be a customer-owned key by ARN |
MASTER_KEY | Instead of KMS, for small installs: 32 random bytes, base64 |
SSO_CONFIG_FILE | Each tenant’s sign-in; see Single sign-on |
PUBLIC_URL | The https:// origin users reach |
TLS_CERT_FILE, TLS_KEY_FILE or TLS_TERMINATED_UPSTREAM=1 | TLS |
BOOTSTRAP_ADMIN_EMAIL | First administrator of a new tenant |
APPROVAL_LINK_SECRET | Turns on signed one-tap approval links in emails |
MAIL_WEBHOOK_URL, MAIL_FROM | Mail relay for notices |
ANTHROPIC_API_KEY, or workload identity federation settings | Turns on Claude for capture and agents |
SESSION_TTL_MINUTES | Default 480 |
LEDGER_CHECKPOINT_MINUTES | How often ledger heads are signed, default 60 |
Connector settings are on Oracle EBS and other systems; inbound channels on Inbound channels.
More than one instance
Section titled “More than one instance”Several instances can serve one tenant set behind a load balancer when they share the database. Background jobs (approval clock, risk sweep, webhooks, agents, e-invoice responses, price indices and connector jobs) each hold a Postgres advisory lock, so one instance runs each job at a time and another takes over if it stops.
Operate
Section titled “Operate”| Task | How |
|---|---|
| Back up | Point-in-time recovery on the database, versioning and cross-region replication on the bucket. Keep the master key separate from backups. |
| Rotate the master key | Turn on KMS automatic rotation, or re-wrap every tenant’s data key to a new key in one transaction. |
| Restore drill | Restore to a scratch environment and run GET /api/audit/verify for each tenant. |
| Export a tenant | GET /api/admin/export |
| Health check | GET /api/health |
| Logs | JSON lines on stdout, one per request and job |