-
Notifications
You must be signed in to change notification settings - Fork 2
Deployment
Nakatomi runs anywhere a Dockerfile + Postgres can run. Four supported paths.
Read this first: docs/DEPLOYMENT_LESSONS.md captures the eleven gotchas we hit on our first Railway deploy (shell wrapping, migration ordering, driver mismatch, duplicate Postgres, mcp
- pydantic version coupling, healthcheck timing, buffered stdout, log CLI quirks). If you're deploying to a new cloud target for the first time, walk the checklist at the top of that doc before anything else.
%%{init: {"look": "handDrawn", "theme": "dark"}}%%
flowchart LR
GH[GitHub repo] -->|push| Build[Railway build]
Build --> Img[Docker image]
Img --> App[Nakatomi service]
Img -.shares vars.-> Worker[same image<br/>webhook worker]
App --> PG[(Railway Postgres)]
App --> Vol[(Railway volume<br/>/app/data)]
App -.->|optional| S3[(S3 / R2)]
- Fork the repo or connect it in the Railway dashboard.
- Add a Postgres plugin — Railway sets
DATABASE_URLautomatically. - Add a Volume mounted at
/app/data(for file storage withSTORAGE_BACKEND=local). Skip if using S3. - Set env vars:
-
SECRET_KEY—openssl rand -hex 32 -
STORAGE_BACKEND—localors3 -
S3_BUCKET,S3_REGION,S3_ENDPOINT_URL,S3_ACCESS_KEY,S3_SECRET_KEY(if S3) -
MEMORY_CONNECTORS— empty or a comma list - any adapter-specific vars (see Memory-Connectors)
-
- Deploy. The Dockerfile runs
alembic upgrade headthenuvicorn.
The railway-template.json
in the repo pre-declares all of this. Once you publish it at
railway.app/new/template, you get a
one-click button for the README.
git clone https://github.com/mrdulasolutions/NakatomiCRM.git
cd NakatomiCRM
cp .env.example .env
# set SECRET_KEY to openssl rand -hex 32
docker compose up -d --buildThe install.sh
wrapper adds --seed and --dashboard conveniences:
./install.sh --seed you@example.com --dashboardThe stack is a single docker-compose.yml with postgres:16-alpine and
the Nakatomi image. Named volumes persist data:
-
nakatomi_pg— Postgres datadir -
nakatomi_files— uploaded files (local backend)
Reset:
docker compose down -v # wipes both volumesFor dev, debugger-friendly:
docker run -d --name nk-pg -e POSTGRES_PASSWORD=nakatomi \
-e POSTGRES_USER=nakatomi -e POSTGRES_DB=nakatomi \
-p 5432:5432 postgres:16
pip install -r requirements.txt
alembic upgrade head
python -m scripts.seed --email you@example.com --password secretpass \
--workspace-name "Demo" --workspace-slug demo
uvicorn app.main:app --reloadrequires-python >=3.12. Earlier versions won't install the mcp
package.
All of these run the same Dockerfile. You supply:
-
DATABASE_URLpointing at a reachable Postgres 13+ SECRET_KEY- A writable volume at
/app/dataif using local file storage - Egress to your memory providers / webhook subscribers
Nakatomi doesn't need much — a single web process + Postgres is enough
for most workloads.
-
One process is fine until 50+ writes/sec. Above that, run multiple
app replicas behind a load balancer; the webhook worker uses
SELECT ... FOR UPDATE SKIP LOCKEDso they don't step on each other. - Postgres sizing. Nakatomi writes 1-3 rows per CRM mutation (the entity + a timeline event + sometimes an audit row + sometimes a webhook delivery). Budget 100-300 row-writes per agent action.
- File storage. Local volume is fine for low volume. Switch to S3 (or R2) when you cross ~100GB or need cross-region access.
- Rate limiting. Protects you from a single agent. See Rate-Limiting.
Nakatomi logs to stdout. Pipe it into whatever you use (Loki, Datadog, OpenTelemetry — OTEL support is on the roadmap). Key signals:
-
/healthshould return 200 in under 100ms - Worker log lines like
webhook worker startedon boot,webhook worker iteration failedon errors - 429s in access logs → rate limit is firing
- 5xx rate → look at recent migrations or Postgres connection pool
Two layers:
-
Postgres — whatever your host provides. Railway takes automated
snapshots; Fly has
fly postgres backup; bare VPS →pg_dumpon cron. -
Workspace —
GET /exporton a schedule, ship to S3. Lets you restore one workspace without a full DB restore. See Export-Import.
- Pull the new image / tag.
- The container runs
alembic upgrade headon startup. - If CI is green on
main, the migration is safe.
Rollbacks: Alembic downgrade -1 works for most migrations; file a GitHub
issue if one doesn't.
Repository · Issues · MIT licensed · maintained by Matt Dula