Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .env.prod.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MONGO_DB_URI=mongodb+srv://<user>:<password>@<cluster>/<db>?retryWrites=true&w=majority
QDRANT_URL=https://<cluster-id>.<region>.aws.cloud.qdrant.io:6333
QDRANT_API_KEY=<qdrant-api-key>

JWT_SECRET=<long-random-secret>
JWT_EXPIRATION_TIME=3600
AUTH_COOKIE_NAME=access_token

KAFKA_BROKERS=kafka:29092
KAFKA_CLIENT_ID=paperstack-backend
KAFKA_TOPIC=document-processing
KAFKA_HOST_PORT=19092

EMBEDDING_PROVIDER=fastembed
LLM_PROVIDER=groq
GROQ_API_KEY=<groq-api-key>
GEMINI_API_KEY=

BACKEND_HOST_PORT=8001
FRONTEND_HOST_PORT=3000
VITE_API_BASE_URL=http://<your-server-or-domain>:8001/api/v1
9 changes: 9 additions & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
node_modules
dist
coverage
uploads
.env
.env.*
npm-debug.log*
pnpm-debug.log*
.git
6 changes: 4 additions & 2 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ PORT=8001
NODE_ENV=development

#MONGO DB
MONGO_DB_URI=your_mongo_db_uri
MONGO_INITDB_ROOT_USERNAME=paperstack_admin
MONGO_INITDB_ROOT_PASSWORD=change-me-mongo-password
MONGO_DB_URI=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017/paperstack?authSource=admin
Comment thread
SAHIL-Sharma21 marked this conversation as resolved.

#JWT
#JWT (required before running docker compose)
JWT_SECRET=your_jwt_secret
# JWT expiry in seconds (3600 = 1h, 86400 = 1d)
JWT_EXPIRATION_TIME=3600
Expand Down
128 changes: 122 additions & 6 deletions backend/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,129 @@ services:
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,PLAINTEXT_INTERNAL://0.0.0.0:29092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:${KAFKA_HOST_PORT:-19092},PLAINTEXT_INTERNAL://kafka:29092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_INTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT_INTERNAL
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:29092,PLAINTEXT_HOST://0.0.0.0:9092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:${KAFKA_HOST_PORT:-19092}
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
healthcheck:
test: ['CMD', 'kafka-topics', '--bootstrap-server', 'localhost:9092', '--list']
test: ['CMD', 'kafka-topics', '--bootstrap-server', 'localhost:29092', '--list']
interval: 10s
timeout: 10s
retries: 5
retries: 12

mongo:
image: mongo:7.0
container_name: paperstack-mongo
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME:-paperstack_admin}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD:-change-me-mongo-password}
volumes:
- mongo_data:/data/db
healthcheck:
test:
[
'CMD',
'mongosh',
'--quiet',
'--username',
'${MONGO_INITDB_ROOT_USERNAME:-paperstack_admin}',
'--password',
'${MONGO_INITDB_ROOT_PASSWORD:-change-me-mongo-password}',
'--authenticationDatabase',
'admin',
'--eval',
'db.adminCommand("ping").ok',
]
interval: 10s
timeout: 10s
retries: 10
Comment thread
SAHIL-Sharma21 marked this conversation as resolved.

qdrant:
image: qdrant/qdrant:v1.13.5
container_name: paperstack-qdrant
restart: unless-stopped
healthcheck:
test:
[
'CMD-SHELL',
'if command -v curl >/dev/null 2>&1; then curl -fsS http://localhost:6333/readyz >/dev/null; elif command -v wget >/dev/null 2>&1; then wget -q -O- http://localhost:6333/readyz >/dev/null; else exit 1; fi',
]
interval: 10s
timeout: 5s
retries: 12
start_period: 10s
volumes:
- qdrant_data:/qdrant/storage
Comment thread
SAHIL-Sharma21 marked this conversation as resolved.

backend:
platform: linux/amd64
build:
context: .
dockerfile: dockerfile
target: api
container_name: paperstack-backend
restart: unless-stopped
depends_on:
kafka:
condition: service_healthy
mongo:
condition: service_healthy
qdrant:
condition: service_healthy
environment:
NODE_ENV: production
PORT: 8001
UPLOAD_DIR: /app/uploads
MONGO_DB_URI: ${MONGO_DB_URI:-mongodb://${MONGO_INITDB_ROOT_USERNAME:-paperstack_admin}:${MONGO_INITDB_ROOT_PASSWORD:-change-me-mongo-password}@mongo:27017/paperstack?authSource=admin}
QDRANT_URL: ${QDRANT_URL:-http://qdrant:6333}
QDRANT_API_KEY: ${QDRANT_API_KEY:-}
KAFKA_BROKERS: ${KAFKA_BROKERS:-kafka:29092}
KAFKA_CLIENT_ID: ${KAFKA_CLIENT_ID:-paperstack-backend}
KAFKA_TOPIC: ${KAFKA_TOPIC:-document-processing}
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required}
JWT_EXPIRATION_TIME: ${JWT_EXPIRATION_TIME:-3600}
AUTH_COOKIE_NAME: ${AUTH_COOKIE_NAME:-access_token}
EMBEDDING_PROVIDER: ${EMBEDDING_PROVIDER:-fastembed}
LLM_PROVIDER: ${LLM_PROVIDER:-groq}
GROQ_API_KEY: ${GROQ_API_KEY:-}
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
ports:
- '8001:8001'
volumes:
- uploads_data:/app/uploads

consumer:
platform: linux/amd64
build:
context: .
dockerfile: dockerfile
target: consumer
container_name: paperstack-consumer
restart: unless-stopped
depends_on:
kafka:
condition: service_healthy
mongo:
condition: service_healthy
qdrant:
condition: service_healthy
environment:
NODE_ENV: production
UPLOAD_DIR: /app/uploads
MONGO_DB_URI: ${MONGO_DB_URI:-mongodb://${MONGO_INITDB_ROOT_USERNAME:-paperstack_admin}:${MONGO_INITDB_ROOT_PASSWORD:-change-me-mongo-password}@mongo:27017/paperstack?authSource=admin}
QDRANT_URL: ${QDRANT_URL:-http://qdrant:6333}
QDRANT_API_KEY: ${QDRANT_API_KEY:-}
KAFKA_BROKERS: ${KAFKA_BROKERS:-kafka:29092}
KAFKA_CLIENT_ID: ${KAFKA_CLIENT_ID:-paperstack-backend}
KAFKA_TOPIC: ${KAFKA_TOPIC:-document-processing}
EMBEDDING_PROVIDER: ${EMBEDDING_PROVIDER:-fastembed}
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
volumes:
- uploads_data:/app/uploads

volumes:
mongo_data:
qdrant_data:
uploads_data:
58 changes: 58 additions & 0 deletions backend/dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
FROM node:22-bookworm-slim AS base

ENV PNPM_HOME=/pnpm
ENV PATH=$PNPM_HOME:$PATH

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
python3 \
make \
g++ \
&& rm -rf /var/lib/apt/lists/* \
&& corepack enable

WORKDIR /app

FROM base AS deps

COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

FROM deps AS build

COPY nest-cli.json tsconfig.json tsconfig.build.json ./
COPY src ./src
RUN pnpm build

FROM base AS prod-deps

COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod

FROM node:22-bookworm-slim AS runtime-base

ENV NODE_ENV=production
ENV PORT=8001
ENV UPLOAD_DIR=/app/uploads

WORKDIR /app

COPY --from=prod-deps /pnpm /pnpm
ENV PNPM_HOME=/pnpm
ENV PATH=$PNPM_HOME:$PATH

COPY --from=prod-deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY package.json ./

RUN mkdir -p /app/uploads && chown -R node:node /app

USER node

FROM runtime-base AS api
EXPOSE 8001
CMD ["node", "dist/main"]

FROM runtime-base AS consumer
CMD ["node", "dist/consumer/main"]
6 changes: 5 additions & 1 deletion backend/src/consumer/consumer.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import { DocumentConsumerService } from './document-consumer/document-consumer.s

@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true, envFilePath: '.env' }),
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.env',
expandVariables: true,
}),
DbModule,
KafkaModule,
DocumentsModule,
Expand Down
6 changes: 5 additions & 1 deletion backend/src/main/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import { ChatModule } from 'src/modules/chat/chat.module';

@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true, envFilePath: '.env' }),
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.env',
expandVariables: true,
}),
DbModule,
UserModule,
AuthModule,
Expand Down
118 changes: 118 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
services:
zookeeper:
image: confluentinc/cp-zookeeper:7.5.0
container_name: paperstack-zookeeper
restart: unless-stopped
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
healthcheck:
test: ['CMD', 'nc', '-z', 'localhost', '2181']
interval: 5s
timeout: 5s
retries: 5
volumes:
- zookeeper_data:/var/lib/zookeeper/data

kafka:
image: confluentinc/cp-kafka:7.5.0
container_name: paperstack-kafka
restart: unless-stopped
depends_on:
zookeeper:
condition: service_healthy
ports:
- '127.0.0.1:${KAFKA_HOST_PORT:-19092}:9092'
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:29092,PLAINTEXT_HOST://0.0.0.0:9092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:${KAFKA_HOST_PORT:-19092}
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
healthcheck:
test: ['CMD', 'kafka-topics', '--bootstrap-server', 'localhost:29092', '--list']
interval: 10s
timeout: 10s
retries: 12
volumes:
- kafka_data:/var/lib/kafka/data

backend:
platform: linux/amd64
build:
context: ./backend
dockerfile: dockerfile
target: api
container_name: paperstack-backend
restart: unless-stopped
depends_on:
kafka:
condition: service_healthy
environment:
NODE_ENV: production
PORT: 8001
UPLOAD_DIR: /app/uploads
MONGO_DB_URI: ${MONGO_DB_URI:?MONGO_DB_URI is required}
QDRANT_URL: ${QDRANT_URL:?QDRANT_URL is required}
QDRANT_API_KEY: ${QDRANT_API_KEY:-}
KAFKA_BROKERS: ${KAFKA_BROKERS:-kafka:29092}
KAFKA_CLIENT_ID: ${KAFKA_CLIENT_ID:-paperstack-backend}
KAFKA_TOPIC: ${KAFKA_TOPIC:-document-processing}
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required}
JWT_EXPIRATION_TIME: ${JWT_EXPIRATION_TIME:-3600}
AUTH_COOKIE_NAME: ${AUTH_COOKIE_NAME:-access_token}
EMBEDDING_PROVIDER: ${EMBEDDING_PROVIDER:-fastembed}
LLM_PROVIDER: ${LLM_PROVIDER:-groq}
GROQ_API_KEY: ${GROQ_API_KEY:-}
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
ports:
- '127.0.0.1:${BACKEND_HOST_PORT:-8001}:8001'
volumes:
- uploads_data:/app/uploads

consumer:
platform: linux/amd64
build:
context: ./backend
dockerfile: dockerfile
target: consumer
container_name: paperstack-consumer
restart: unless-stopped
depends_on:
kafka:
condition: service_healthy
environment:
NODE_ENV: production
UPLOAD_DIR: /app/uploads
MONGO_DB_URI: ${MONGO_DB_URI:?MONGO_DB_URI is required}
QDRANT_URL: ${QDRANT_URL:?QDRANT_URL is required}
QDRANT_API_KEY: ${QDRANT_API_KEY:-}
KAFKA_BROKERS: ${KAFKA_BROKERS:-kafka:29092}
KAFKA_CLIENT_ID: ${KAFKA_CLIENT_ID:-paperstack-backend}
KAFKA_TOPIC: ${KAFKA_TOPIC:-document-processing}
EMBEDDING_PROVIDER: ${EMBEDDING_PROVIDER:-fastembed}
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
volumes:
- uploads_data:/app/uploads

frontend:
platform: linux/amd64
build:
context: ./frontend
dockerfile: dockerfile
args:
VITE_API_BASE_URL: ${VITE_API_BASE_URL:?VITE_API_BASE_URL is required}
container_name: paperstack-frontend
restart: unless-stopped
depends_on:
backend:
condition: service_started
ports:
- '${FRONTEND_HOST_PORT:-3000}:80'

volumes:
zookeeper_data:
kafka_data:
uploads_data:
7 changes: 7 additions & 0 deletions frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules
dist
.env
.env.*
npm-debug.log*
pnpm-debug.log*
.git
Loading