Skip to main content

Install with Docker


You can install Bag of Words with a single docker command. By default, it will use SQLite as the database. You can also configure it to use PostgreSQL by passing BOW_DATABASE_URL environment variable.
To use PostgreSQL, you need to set the BOW_DATABASE_URL environment variable. For example: BOW_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/bagofwords

Update

  • Re-run the same docker run --pull always ... command to fetch and start the latest image.
  • Optionally, pull explicitly and restart:

Install with Docker Compose


Run Bag of Words with Docker Compose and Caddy (built-in TLS on port 443). We recommend using the canonical files from the repo to avoid drift:

Steps

  1. Make sure Docker and Docker Compose are installed.
  2. Clone the repo:
  3. Create a .env file (for domain and credentials). Example:
    Generate BOW_ENCRYPTION_KEY with OpenSSL:
  4. Start services:
  5. Point your domain to the server’s public IP:
    • Create an A record for yourdomain.com → your instance public IP.
    • Caddy will automatically obtain/renew the TLS certificate and serve on port 443.
  6. Open https://yourdomain.com
Caddy is included by default as a reverse proxy on port 443. If you prefer to run without Caddy, remove the caddy service from docker-compose.yaml and expose the app directly on port 3000. For local, no-SSL testing, you can also use docker-compose.dev.yaml.

Update

Other configurations


You can also configure additional settings in the bow-config.yaml file.
To use the custom config file, you can run the following command:

Install with Kubernetes


You can install Bag of Words on a Kubernetes cluster. The Helm chart can deploy the app with a bundled PostgreSQL instance or connect to an external managed database such as AWS Aurora with IAM authentication.

1. Add the Helm Repository

2. Install or Upgrade the Chart

Here are a few examples of how to install or upgrade the Bag of Words Helm chart: Deploy with a bundled PostgreSQL instance:
Deploy without TLS with a custom hostname:
Deploy with TLS, cert-manager, and Google OAuth:

Deploy with AWS Aurora and IAM Authentication

When using a managed database like AWS Aurora PostgreSQL, the chart skips the bundled PostgreSQL subchart and connects directly to your Aurora cluster. Passwords are never stored — short-lived IAM tokens are generated at runtime for every new database connection. Prerequisites:
  • An Aurora PostgreSQL cluster with IAM database authentication enabled
  • A database user created with: GRANT rds_iam TO <username>
  • An IAM role/policy with rds-db:connect permission
  • In EKS: an IRSA (IAM Roles for Service Accounts) annotation on the pod’s service account so the app can assume the IAM role
Or use a values file:
When database.auth.provider is set to aws_iam, the bundled PostgreSQL subchart is automatically skipped. The app uses boto3 to call generate_db_auth_token() before each new connection, so tokens rotate automatically and no static database password is needed.

Update

AWS Aurora Configuration


Bag of Words supports connecting to AWS Aurora PostgreSQL using IAM database authentication. This eliminates static database passwords entirely — the application generates short-lived tokens (valid for 15 minutes) at connection time using AWS IAM.

How it works

  1. The app’s service account assumes an IAM role (via IRSA in EKS, or instance profile on EC2)
  2. On every new database connection, the app calls generate_db_auth_token() to get a temporary password
  3. The token is used as the PostgreSQL password — established connections are not affected when it expires
  4. SSL is required (require or verify-full)

AWS Setup

1. Enable IAM authentication on the Aurora cluster:
2. Create the database user with IAM grants:
3. Create an IAM policy allowing rds-db:connect:
4. For EKS — create an IRSA-enabled service account:
Then set the IRSA annotation in the Helm chart:

bow-config.yaml for Aurora (non-Kubernetes)

If you are running Bag of Words on EC2 or ECS (not Kubernetes), you can configure Aurora IAM auth directly in bow-config.yaml:
The EC2 instance or ECS task must have an IAM role with the rds-db:connect policy attached.

Google OAuth

To enable Google OAuth authentication, configure the following parameters in your bow config (or in env/k8s configmap):
You should also set the following in your Google OAuth configurations:
  1. Callback URL: https://yourbaseurl.com/api/auth/google/callback
  2. Scopes: /auth/userinfo.email, /auth/userinfo.profile, openid
  3. Enable People API

OpenID Connect (OIDC)

For Okta

  1. Set a new OIDC application: web
  2. Set callback URL https://your-base-bow-url.com/api/auth/okta/callback

For Microsoft Entra ID (Azure AD)

  1. In the Azure portal, register a new application under Microsoft Entra ID → App registrations.
  2. Set the redirect URI (type: Web) to https://your-base-bow-url.com/api/auth/entra/callback.
  3. Copy the Directory (tenant) ID into ${ENTRA_TENANT_ID} and the Application (client) ID into ${BOW_ENTRA_CLIENT_ID}.
  4. Under Certificates & secrets, create a client secret and set it as ${BOW_ENTRA_CLIENT_SECRET}.
  5. Use client_auth_method: post — Entra ID expects credentials in the request body rather than the Authorization header.
Group sync When sync_groups: true, group memberships from the groups claim are synced to Bag of Words on each login. To make Entra ID emit the claim, edit the app’s Token configuration → Add groups claim and select the group types you want.
  • group_claim — the token claim that carries group membership (default groups).
  • resolve_group_names: true — by default Entra ID emits group object IDs, not display names. Enabling this resolves the IDs to human-readable names via Microsoft Graph (requires the app to have the GroupMember.Read.All or Directory.Read.All permission granted).

LDAP / Active Directory

For environments that authenticate against an on-premises directory, enable the LDAP provider:
  • url — the directory endpoint. Use ldaps:// (port 636) for TLS; avoid plain ldap:// (port 389) outside a trusted network.
  • bind_dn — the distinguished name of a read-only service account used to look up users.
  • bind_password — the service account password, supplied via the ${BOW_LDAP_BIND_PASSWORD} environment variable rather than committed to the config.

SMTP Settings

Configure an outbound mail server to enable email features — dashboard and conversation share notifications, scheduled report and prompt results (with optional PDF attachments), password-reset and email-verification links, and the AI send_email tool. Define the smtp_settings block in bow-config.yaml:
Email is enabled only when credentials are present (or use_credentials: false for anonymous relays). If no mail client can be built at startup, email features are silently inert — outgoing notifications are skipped and the send_email tool stays disabled.