Skip to content

Commit 43b1aa2

Browse files
committed
chore: merge main into release for new releases
2 parents 26d25f0 + 5912194 commit 43b1aa2

37 files changed

+1778
-666
lines changed

Dockerfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ COPY package.json bun.lock ./
1212
COPY packages/kv/package.json ./packages/kv/
1313
COPY packages/ui/package.json ./packages/ui/
1414
COPY packages/email/package.json ./packages/email/
15+
COPY packages/integration-platform/package.json ./packages/integration-platform/
1516
COPY packages/integrations/package.json ./packages/integrations/
1617
COPY packages/utils/package.json ./packages/utils/
1718
COPY packages/tsconfig/package.json ./packages/tsconfig/
@@ -22,7 +23,7 @@ COPY apps/app/package.json ./apps/app/
2223
COPY apps/portal/package.json ./apps/portal/
2324

2425
# Install all dependencies
25-
RUN PRISMA_SKIP_POSTINSTALL_GENERATE=true bun install
26+
RUN PRISMA_SKIP_POSTINSTALL_GENERATE=true bun install --ignore-scripts
2627

2728
# =============================================================================
2829
# STAGE 2: Ultra-Minimal Migrator - Only Prisma
@@ -91,7 +92,7 @@ ENV NEXT_PUBLIC_BETTER_AUTH_URL=$NEXT_PUBLIC_BETTER_AUTH_URL \
9192
NEXT_OUTPUT_STANDALONE=true \
9293
NODE_OPTIONS=--max_old_space_size=6144
9394

94-
# Build the app (schema already combined above)
95+
# Build the app
9596
RUN cd apps/app && SKIP_ENV_VALIDATION=true bun run build:docker
9697

9798
# =============================================================================
@@ -106,7 +107,6 @@ COPY --from=app-builder /app/apps/app/.next/standalone ./
106107
COPY --from=app-builder /app/apps/app/.next/static ./apps/app/.next/static
107108
COPY --from=app-builder /app/apps/app/public ./apps/app/public
108109

109-
110110
EXPOSE 3000
111111
CMD ["node", "apps/app/server.js"]
112112

@@ -135,7 +135,7 @@ ENV NEXT_PUBLIC_BETTER_AUTH_URL=$NEXT_PUBLIC_BETTER_AUTH_URL \
135135
NEXT_OUTPUT_STANDALONE=true \
136136
NODE_OPTIONS=--max_old_space_size=6144
137137

138-
# Build the portal (schema already combined above)
138+
# Build the portal
139139
RUN cd apps/portal && SKIP_ENV_VALIDATION=true bun run build:docker
140140

141141
# =============================================================================

SELF_HOSTING.md

Lines changed: 50 additions & 240 deletions
Original file line numberDiff line numberDiff line change
@@ -1,272 +1,82 @@
11
## Self-hosting Comp (Apps + Portal)
22

3-
This guide walks you through running the Comp app and portal with Docker.
3+
This file is a brief overview for Docker-based self-hosting.
44

5-
### Overview
5+
**For the detailed, up-to-date guide, see:**
66

7-
- You will run two services: `app` (primary) and `portal` (customer portal).
8-
- You must bring your own externally hosted PostgreSQL database. The stack does not run a local DB in production mode.
9-
- You must provide email (Resend) and Trigger.dev credentials for email login and automated workflows.
7+
- [Docker Self-Hosting Guide](https://trycomp.ai/docs/self-hosting/docker)
8+
- [Environment Reference](https://trycomp.ai/docs/self-hosting/env-reference)
109

11-
### Prerequisites
12-
13-
- Docker Desktop (or Docker Engine) installed
14-
- Externally hosted PostgreSQL 14+ (e.g., DigitalOcean, Neon, RDS) with SSL
15-
- Resend account and API key for transactional email (magic links, OTP)
16-
- Trigger.dev account and project for automated workflows
17-
18-
### Required environment variables
19-
20-
Set these in `docker-compose.yml` under each service as shown below.
21-
22-
App (`apps/app`):
23-
24-
- `DATABASE_URL` (required): External Postgres URL. Example: `postgresql://user:pass@host:5432/db?sslmode=require`
25-
- `AUTH_SECRET` (required): 32-byte base64. Generate with `openssl rand -base64 32`
26-
- `RESEND_API_KEY` (required): From Resend dashboard
27-
- `REVALIDATION_SECRET` (required): Any random string
28-
- `BETTER_AUTH_URL` (required): Base URL of the app server (e.g., `http://localhost:3000`)
29-
- `NEXT_PUBLIC_BETTER_AUTH_URL` (required): Same as above for client code
30-
- `NEXT_PUBLIC_PORTAL_URL` (required): Base URL of the portal server (e.g., `http://localhost:3002`)
31-
- `TRIGGER_SECRET_KEY` (required for workflows): From Trigger.dev project settings
32-
- Optional (infrastructure): `UPSTASH_REDIS_REST_URL`, `UPSTASH_REDIS_REST_TOKEN`
33-
34-
Portal (`apps/portal`):
35-
36-
- `DATABASE_URL` (required): Same external Postgres URL
37-
- `BETTER_AUTH_SECRET` (required): A secret used by portal auth (distinct from app `AUTH_SECRET`)
38-
- `BETTER_AUTH_URL` (required): Base URL of the portal (e.g., `http://localhost:3002`)
39-
- `NEXT_PUBLIC_BETTER_AUTH_URL` (required): Same as portal base URL for client code
40-
- `RESEND_API_KEY` (required): Same Resend key
41-
42-
### Optional environment variables
43-
44-
App (`apps/app`):
45-
46-
- **APP_AWS_REGION**, **APP_AWS_ACCESS_KEY_ID**, **APP_AWS_SECRET_ACCESS_KEY**, **APP_AWS_BUCKET_NAME**: AWS S3 credentials for file storage (attachments, general uploads).
47-
- **APP_AWS_QUESTIONNAIRE_UPLOAD_BUCKET**: AWS S3 bucket name specifically for questionnaire file uploads. Required for the Security Questionnaire feature. If not set, users will see an error when trying to parse questionnaires.
48-
- **APP_AWS_KNOWLEDGE_BASE_BUCKET**: AWS S3 bucket name specifically for knowledge base documents. Required for the Knowledge Base feature in Security Questionnaire. If not set, users will see an error when trying to upload knowledge base documents.
49-
- **APP_AWS_ORG_ASSETS_BUCKET**: AWS S3 bucket name for organization static assets (e.g., company logos, compliance certificates). Required for logo uploads in organization settings and Trust Portal compliance certificate uploads. If not set, these features will fail.
50-
- **OPENAI_API_KEY**: Enables AI features that call OpenAI models.
51-
- **UPSTASH_REDIS_REST_URL**, **UPSTASH_REDIS_REST_TOKEN**: Optional Redis (Upstash) used for rate limiting/queues/caching.
52-
- **NEXT_PUBLIC_POSTHOG_KEY**, **NEXT_PUBLIC_POSTHOG_HOST**: Client analytics via PostHog; leave unset to disable.
53-
- **NEXT_PUBLIC_GTM_ID**: Google Tag Manager container ID for client tracking.
54-
- **NEXT_PUBLIC_LINKEDIN_PARTNER_ID**, **NEXT_PUBLIC_LINKEDIN_CONVERSION_ID**: LinkedIn insights/conversion tracking.
55-
- **NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL**: Google Ads conversion tracking label.
56-
- **DUB_API_KEY**, **DUB_REFER_URL**: Dub.co link shortener/referral features.
57-
- **FIRECRAWL_API_KEY**: Optional LLM/crawling providers for research features.
58-
- **SLACK_SALES_WEBHOOK**: Slack webhook for sales/lead notifications.
59-
- **GA4_API_SECRET**, **GA4_MEASUREMENT_ID**: Google Analytics 4 server/client tracking.
60-
- **NEXT_PUBLIC_API_URL**: Override client API base URL (defaults to same origin).
61-
62-
API (`apps/api`):
63-
64-
- **APP_AWS_REGION**, **APP_AWS_ACCESS_KEY_ID**, **APP_AWS_SECRET_ACCESS_KEY**, **APP_AWS_BUCKET_NAME**: AWS S3 credentials for file storage (attachments, general uploads).
65-
- **APP_AWS_QUESTIONNAIRE_UPLOAD_BUCKET**: AWS S3 bucket name specifically for questionnaire file uploads. Required for the Security Questionnaire feature.
66-
- **APP_AWS_KNOWLEDGE_BASE_BUCKET**: AWS S3 bucket name specifically for knowledge base documents. Required for the Knowledge Base feature in Security Questionnaire.
67-
- **APP_AWS_ORG_ASSETS_BUCKET**: AWS S3 bucket name for organization static assets (e.g., company logos, compliance certificates). Required for Trust Portal compliance certificate uploads and organization logo uploads. If not set, these features will fail.
68-
- **OPENAI_API_KEY**: Enables AI features that call OpenAI models.
69-
- **UPSTASH_VECTOR_REST_URL**, **UPSTASH_VECTOR_REST_TOKEN**: Required for vector database operations (questionnaire auto-answer, SOA auto-fill, knowledge base search).
70-
- **BETTER_AUTH_URL**: URL of the Better Auth instance (usually the same as the app URL).
71-
- **DATABASE_URL**: PostgreSQL database connection string.
72-
73-
Portal (`apps/portal`):
10+
### Quick Summary
7411

75-
- **NEXT_PUBLIC_POSTHOG_KEY**, **NEXT_PUBLIC_POSTHOG_HOST**: Client analytics via PostHog for portal.
76-
- **UPSTASH_REDIS_REST_URL**, **UPSTASH_REDIS_REST_TOKEN**: Optional Redis if you enable portal-side rate limiting/queues.
12+
Docker uses **separate env files** (not a root `.env`):
7713

78-
### docker-compose.yml uses `.env` (no direct edits needed)
14+
| File | Services |
15+
|------|----------|
16+
| `packages/db/.env` | migrator, seeder |
17+
| `apps/app/.env` | app |
18+
| `apps/portal/.env` | portal |
7919

80-
We keep `docker-compose.yml` generic and read values from `.env`:
20+
### Minimal Required Environment
8121

82-
```yaml
83-
services:
84-
migrator:
85-
build:
86-
context: .
87-
dockerfile: Dockerfile
88-
target: migrator
89-
env_file:
90-
- .env
22+
For a functional deployment:
9123

92-
seeder:
93-
build:
94-
context: .
95-
dockerfile: Dockerfile
96-
target: migrator
97-
env_file:
98-
- .env
99-
command: sh -lc "bunx prisma generate --schema=node_modules/@trycompai/db/dist/schema.prisma && bun packages/db/prisma/seed/seed.js"
100-
101-
app:
102-
build:
103-
context: .
104-
dockerfile: Dockerfile
105-
target: app
106-
args:
107-
NEXT_PUBLIC_BETTER_AUTH_URL: ${BETTER_AUTH_URL}
108-
ports: ['3000:3000']
109-
env_file: [.env]
110-
restart: unless-stopped
111-
healthcheck:
112-
test: ['CMD-SHELL', 'curl -f http://localhost:3000/api/health || exit 1']
113-
interval: 30s
114-
timeout: 10s
115-
retries: 3
116-
117-
portal:
118-
build:
119-
context: .
120-
dockerfile: Dockerfile
121-
target: portal
122-
args:
123-
NEXT_PUBLIC_BETTER_AUTH_URL: ${BETTER_AUTH_URL_PORTAL}
124-
ports: ['3002:3000']
125-
env_file: [.env]
126-
restart: unless-stopped
127-
healthcheck:
128-
test: ['CMD-SHELL', 'curl -f http://localhost:3002/ || exit 1']
129-
interval: 30s
130-
timeout: 10s
131-
retries: 3
132-
```
133-
134-
#### `.env` example
135-
136-
Create a `.env` file at the repo root with your values (never commit real secrets):
137-
138-
```bash
139-
# External PostgreSQL (required)
140-
DATABASE_URL=postgresql://user:pass@host:5432/db?sslmode=require
141-
142-
# App auth + URLs (required)
143-
AUTH_SECRET=
144-
BETTER_AUTH_URL=http://localhost:3000
145-
NEXT_PUBLIC_BETTER_AUTH_URL=http://localhost:3000
146-
NEXT_PUBLIC_PORTAL_URL=http://localhost:3002
147-
REVALIDATION_SECRET=
148-
149-
# Email (required)
150-
RESEND_API_KEY=
151-
152-
# Workflows (Trigger.dev hosted)
153-
TRIGGER_SECRET_KEY=
154-
155-
# Portal auth + URLs (required)
156-
BETTER_AUTH_SECRET=
157-
BETTER_AUTH_URL_PORTAL=http://localhost:3002
158-
NEXT_PUBLIC_BETTER_AUTH_URL_PORTAL=http://localhost:3002
159-
160-
# Optional
161-
# AWS S3 (for file storage)
162-
# APP_AWS_REGION=
163-
# APP_AWS_ACCESS_KEY_ID=
164-
# APP_AWS_SECRET_ACCESS_KEY=
165-
# APP_AWS_BUCKET_NAME=
166-
# APP_AWS_QUESTIONNAIRE_UPLOAD_BUCKET=
167-
# APP_AWS_KNOWLEDGE_BASE_BUCKET=
168-
# APP_AWS_ORG_ASSETS_BUCKET=
169-
# OPENAI_API_KEY=
170-
# UPSTASH_REDIS_REST_URL=
171-
# UPSTASH_REDIS_REST_TOKEN=
172-
# NEXT_PUBLIC_POSTHOG_KEY=
173-
# NEXT_PUBLIC_POSTHOG_HOST=
174-
# NEXT_PUBLIC_GTM_ID=
175-
# NEXT_PUBLIC_LINKEDIN_PARTNER_ID=
176-
# NEXT_PUBLIC_LINKEDIN_CONVERSION_ID=
177-
# NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL=
178-
# DUB_API_KEY=
179-
# DUB_REFER_URL=
180-
# FIRECRAWL_API_KEY=
181-
# SLACK_SALES_WEBHOOK=
182-
# GA4_API_SECRET=
183-
# GA4_MEASUREMENT_ID=
184-
# NEXT_PUBLIC_API_URL=
185-
```
24+
- **Database**: `DATABASE_URL` in all three env files
25+
- **Auth**: `AUTH_SECRET`, `SECRET_KEY`, `BETTER_AUTH_URL`, `NEXT_PUBLIC_BETTER_AUTH_URL` (app); `BETTER_AUTH_SECRET` (portal)
26+
- **Email**: `RESEND_API_KEY` in app and portal
27+
- **Workflows**: `TRIGGER_SECRET_KEY` in app
28+
- **Misc**: `REVALIDATION_SECRET`, `NEXT_PUBLIC_PORTAL_URL` in app
18629

187-
#### What the `migrator` and `seeder` services do
188-
189-
- **migrator**: Runs `prisma migrate deploy` using the combined schema from `@trycompai/db`.
190-
- Purpose: create/update tables, indexes, and constraints in your hosted Postgres.
191-
- Safe to run repeatedly (Prisma applies only pending migrations).
192-
193-
- **seeder**: Generates a Prisma client from the same combined schema and executes the app’s seed script.
194-
- Purpose: load application reference data (frameworks, controls, relations).
195-
- Behavior: idempotent upserts by `id`. It does not delete rows; existing rows with matching ids are updated, and relations are connected if missing.
196-
197-
Notes:
198-
199-
- The stack migrates with `@trycompai/db` combined Prisma schema and then seeds. Seeding is idempotent: records are upserted by id and relations are connected; nothing is deleted.
200-
- Ensure your DB user has privileges to create/alter tables in the target database.
201-
202-
### Trigger.dev (hosted runner)
203-
204-
Trigger.dev powers AI automations and background workflows.
205-
206-
Steps:
207-
208-
1. Create an account at `https://cloud.trigger.dev`
209-
2. Create a project and copy `TRIGGER_SECRET_KEY`
210-
3. From your workstation (not inside Docker):
211-
```bash
212-
cd apps/app
213-
bunx trigger.dev@latest login
214-
bunx trigger.dev@latest deploy
215-
```
216-
4. Set `TRIGGER_SECRET_KEY` in the `app` service environment.
217-
218-
### Resend (email)
219-
220-
- Create a Resend account and get `RESEND_API_KEY`
221-
- Add a domain if you plan to send emails from a custom domain
222-
- Set `RESEND_API_KEY` in both `app` and `portal` services
223-
224-
### Build & run
225-
226-
#### Prepare environment
227-
228-
Copy the example and fill real values (kept out of git):
30+
### Prerequisites
22931

230-
```bash
231-
cp .env.example .env
232-
# edit .env with your production secrets and URLs
233-
```
32+
- Docker Desktop or Docker Engine
33+
- External PostgreSQL 14+ with SSL
34+
- [Resend](https://resend.com) account for email
35+
- [Trigger.dev](https://cloud.trigger.dev) account for workflows
23436

235-
#### Fresh install (optional clean):
37+
### Build & Run
23638

23739
```bash
238-
docker compose down --rmi all --volumes --remove-orphans
239-
docker builder prune --all --force
240-
```
40+
# 1. Create env files from examples
41+
cp packages/db/.env.example packages/db/.env
42+
cp apps/app/.env.example apps/app/.env
43+
cp apps/portal/.env.example apps/portal/.env
44+
# Edit each with your production values
24145

242-
#### Build images:
46+
# 2. Export build args
47+
export BETTER_AUTH_URL="https://app.yourdomain.com"
48+
export BETTER_AUTH_URL_PORTAL="https://portal.yourdomain.com"
24349

244-
```bash
50+
# 3. Build
24551
docker compose build --no-cache
246-
```
247-
248-
#### Run migrations & seed (against your hosted DB):
24952

250-
```bash
53+
# 4. Migrate & seed
25154
docker compose run --rm migrator
25255
docker compose run --rm seeder
56+
57+
# 5. Start
58+
docker compose up -d app portal
25359
```
25460

255-
#### Start the apps:
61+
### Trigger.dev Deployment
62+
63+
Deploy tasks from your workstation (not inside Docker):
25664

25765
```bash
258-
docker compose up -d app portal
66+
cd apps/app
67+
bunx trigger.dev@latest login
68+
bunx trigger.dev@latest deploy
25969
```
26070

261-
Verify health:
71+
### Troubleshooting
72+
73+
View logs to debug missing env vars:
26274

26375
```bash
264-
curl -s http://localhost:3000/api/health
76+
docker compose logs app
77+
docker compose logs portal
26578
```
26679

267-
### Production tips
80+
The Dockerfile sets `SKIP_ENV_VALIDATION=true` at build time, so missing variables only cause errors at runtime.
26881

269-
- Set real domains and HTTPS (behind a reverse proxy / load balancer)
270-
- Update `BETTER_AUTH_URL`, `NEXT_PUBLIC_BETTER_AUTH_URL`, and portal equivalents to the public domains
271-
- Use strong secrets and rotate them periodically
272-
- Ensure the hosted Postgres requires SSL and restricts network access (VPC, IP allowlist, or private networking)
82+
See the [full troubleshooting guide](https://trycomp.ai/docs/self-hosting/docker#troubleshooting) for common issues.

0 commit comments

Comments
 (0)