Skip to main content

Installing Bowrain Server

A Bowrain deployment is several cooperating services, not a single binary:

  • bowrain-server: the REST + gRPC API (one process; gRPC is multiplexed onto the HTTP port).
  • bowrain-worker: the async worker that ingests pushes and runs the drafting jobs a run enqueues against an upstream AI provider.
  • PostgreSQL: the authoritative store (projects, blocks, workspaces, users, jobs). The server requires PostgreSQL; there is no SQLite or file backend.
  • A job queue (Amazon SQS, or an SQS-compatible broker such as ElasticMQ) and Redis for the event bus (Redis Streams), shared by the server and worker.
  • bowrain-web: the static web UI, served as its own container.
  • An OIDC identity provider (for example Keycloak) and an SMTP sender.

This page covers local evaluation. For a production stack with TLS, backups, and a reverse proxy, see Self-Hosting, which is the canonical reference for the full architecture and the complete environment-variable set.

One-command local stack

The repository ships a self-contained local stack at bowrain/compose.full.yaml: server, worker, PostgreSQL, ElasticMQ (SQS-compatible job queue), Redis, MinIO, Keycloak (with a pre-imported realm), and Mailpit. It defaults to the offline demo provider, so the full push → draft → pull cycle works with no API keys and no OIDC setup:

docker compose -f bowrain/compose.full.yaml up -d --build --wait

Endpoints once it is up:

URLService
http://localhost:8080bowrain-server API (and the web UI with --profile web)
http://localhost:8080/api/v1/healthHealth check
http://localhost:8180Keycloak admin console (admin / admin)
http://localhost:8025Mailpit (captured emails)

To serve the web UI from the server, add the web profile:

docker compose -f bowrain/compose.full.yaml --profile web up -d --build

For real drafts, set BOWRAIN_PLATFORM_PROVIDER (for example gemini) and the matching API key in a .env file; see Self-Hosting.

Tear down with docker compose -f bowrain/compose.full.yaml down -v.

Self-hosting from published images

To run from the published ghcr.io/neokapi/ images against your own OIDC provider, use the reference stack at bowrain/deploy/docker/compose.yaml: Traefik, PostgreSQL, ElasticMQ, Redis, the server, the worker, and the web UI.

docker compose -f deploy/docker/compose.yaml up -d

At minimum, provide an external OIDC issuer, a JWT secret, and (for drafting) an upstream provider:

POSTGRES_PASSWORD=... # database password
BOWRAIN_JWT_SECRET=$(openssl rand -base64 32) # JWT signing secret
BOWRAIN_OIDC_ISSUER_URL=... # your realm's issuer URL
BOWRAIN_OIDC_CLIENT_SECRET=... # the bowrain client's secret
BOWRAIN_PLATFORM_PROVIDER=gemini # or bedrock / openai / anthropic / ollama
BOWRAIN_PLATFORM_API_KEY=... # provider API key

See Self-Hosting for the full production walkthrough, including TLS, backups, and the complete service topology.

Building the binaries

The server and worker are built from source. Neither is published as a download: the GitHub Releases for this repository carry the kapi CLI, the kapi-bowrain plugin and the Bowrain desktop app, and no server artifact. The compose stack above builds the server image locally for the same reason.

git clone https://github.com/neokapi/neokapi.git
cd neokapi
make -C bowrain build-server

Both still require a reachable PostgreSQL, plus a shared job queue (SQS or an SQS-compatible broker) and Redis when the server and worker run as separate processes.

Run the server (PostgreSQL is required; the connection string must use the postgres:// scheme):

bowrain-server \
--database-url postgres://bowrain:password@localhost/bowrain \
--jwt-secret change-me-in-production \
--oidc-issuer-url https://keycloak.example.com/realms/bowrain \
--oidc-client-id bowrain \
--oidc-client-secret your-client-secret \
--port 8080

The schema is created automatically on first start; migrations run on startup. The async worker is configured entirely through environment variables; see Configuration.

systemd service

/etc/systemd/system/bowrain-server.service:

[Unit]
Description=Bowrain Server
After=network.target

[Service]
Type=simple
User=bowrain
Group=bowrain
Environment=BOWRAIN_DATABASE_URL=postgres://bowrain:password@localhost/bowrain
Environment=BOWRAIN_QUEUE_BACKEND=sqs
Environment=SQS_ENDPOINT=http://localhost:9324
Environment=BOWRAIN_EVENT_BACKEND=redis
Environment=BOWRAIN_REDIS_URL=redis://localhost:6379
ExecStart=/usr/local/bin/bowrain-server \
--jwt-secret ${BOWRAIN_JWT_SECRET} \
--oidc-issuer-url https://keycloak.example.com/realms/bowrain \
--oidc-client-id bowrain \
--oidc-client-secret ${BOWRAIN_OIDC_CLIENT_SECRET} \
--port 8080
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now bowrain-server
sudo systemctl status bowrain-server

OIDC provider setup

Bowrain Server requires an OIDC provider for authentication. Any OIDC-compliant provider works (Keycloak, Auth0, Okta, Azure AD, Dex). The local stack above imports a pre-configured Keycloak realm automatically; for your own provider see the OIDC provider setup in Self-Hosting.

Health check

Verify the server is running:

curl http://localhost:8080/api/v1/health

Next steps