diff --git a/.env.example b/.env.example index 1cc0bcc55..74b25fbef 100644 --- a/.env.example +++ b/.env.example @@ -6,7 +6,9 @@ FLOWER_PORT=5555 # Frontend Configuration FRONTEND_PORT=3000 -NEXT_PUBLIC_API_URL=http://backend:8000 +NEXT_PUBLIC_FASTAPI_BACKEND_URL=http://localhost:8000 (Default: http://localhost:8000) +NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE=LOCAL or GOOGLE (Default: LOCAL) +NEXT_PUBLIC_ETL_SERVICE=UNSTRUCTURED or LLAMACLOUD or DOCLING (Default: DOCLING) # Backend Configuration BACKEND_PORT=8000 diff --git a/docker-compose.yml b/docker-compose.yml index 48de1f4e5..a48187733 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,7 +38,8 @@ services: ports: - "${BACKEND_PORT:-8000}:8000" volumes: - - ./surfsense_backend:/app + - ./surfsense_backend/app:/app/app + - ./surfsense_backend/scripts:/app/scripts:ro - shared_temp:/tmp env_file: - ./surfsense_backend/.env @@ -111,17 +112,17 @@ services: # - celery_worker frontend: - # build: ./surfsense_web - image: ghcr.io/modsetter/surfsense_ui:latest + build: + context: ./surfsense_web + # image: ghcr.io/modsetter/surfsense_ui:latest + args: + NEXT_PUBLIC_FASTAPI_BACKEND_URL: ${NEXT_PUBLIC_FASTAPI_BACKEND_URL:-http://localhost:8000} + NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE: ${NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE:-LOCAL} + NEXT_PUBLIC_ETL_SERVICE: ${NEXT_PUBLIC_ETL_SERVICE:-DOCLING} ports: - "${FRONTEND_PORT:-3000}:3000" - volumes: - - ./surfsense_web:/app - - /app/node_modules env_file: - ./surfsense_web/.env - environment: - - NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-http://backend:8000} depends_on: - backend diff --git a/surfsense_backend/scripts/docker/entrypoint.sh b/surfsense_backend/scripts/docker/entrypoint.sh index 85376c49b..32754d3e9 100644 --- a/surfsense_backend/scripts/docker/entrypoint.sh +++ b/surfsense_backend/scripts/docker/entrypoint.sh @@ -11,17 +11,23 @@ cleanup() { trap cleanup SIGTERM SIGINT -echo "Starting Celery Beat..." -celery -A app.celery_app beat --loglevel=info & -celery_beat_pid=$! +echo "Starting FastAPI Backend..." +python main.py & +backend_pid=$! + +# Wait a bit for backend to initialize +sleep 5 echo "Starting Celery Worker..." celery -A app.celery_app worker --loglevel=info --concurrency=1 --pool=solo & celery_worker_pid=$! -echo "Starting FastAPI Backend..." -python main.py --reload & -backend_pid=$! +# Wait a bit for worker to initialize +sleep 3 + +echo "Starting Celery Beat..." +celery -A app.celery_app beat --loglevel=info & +celery_beat_pid=$! echo "All services started. PIDs: Backend=$backend_pid, Worker=$celery_worker_pid, Beat=$celery_beat_pid" diff --git a/surfsense_web/.dockerignore b/surfsense_web/.dockerignore index 73361d68a..7d48982c9 100644 --- a/surfsense_web/.dockerignore +++ b/surfsense_web/.dockerignore @@ -8,8 +8,7 @@ npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* -.env -.env.local -.env.development.local -.env.test.local -.env.production.local \ No newline at end of file +Dockerfile +.dockerignore +node_modules +README.md diff --git a/surfsense_web/Dockerfile b/surfsense_web/Dockerfile index 4b3c97af8..e0ecb1225 100644 --- a/surfsense_web/Dockerfile +++ b/surfsense_web/Dockerfile @@ -1,32 +1,79 @@ -FROM node:20-alpine +# syntax=docker.io/docker/dockerfile:1 +FROM node:20-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat WORKDIR /app # Install pnpm -RUN npm install -g pnpm +RUN corepack enable pnpm # Copy package files -COPY package.json pnpm-lock.yaml ./ +COPY package.json pnpm-lock.yaml* .npmrc* ./ -# First copy the config file to avoid fumadocs-mdx postinstall error +# First copy the config file and content to avoid fumadocs-mdx postinstall error COPY source.config.ts ./ COPY content ./content -# Install dependencies with --ignore-scripts to skip postinstall -RUN pnpm install --ignore-scripts +# Install dependencies with frozen lockfile +RUN pnpm i --frozen-lockfile -# Now run the postinstall script manually -RUN pnpm fumadocs-mdx -# Copy source code +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app + +# Enable pnpm +RUN corepack enable pnpm + +# Accept build arguments for Next.js public env vars +ARG NEXT_PUBLIC_FASTAPI_BACKEND_URL +ARG NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE +ARG NEXT_PUBLIC_ETL_SERVICE + +# Set them as environment variables for the build +ENV NEXT_PUBLIC_FASTAPI_BACKEND_URL=$NEXT_PUBLIC_FASTAPI_BACKEND_URL +ENV NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE=$NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE +ENV NEXT_PUBLIC_ETL_SERVICE=$NEXT_PUBLIC_ETL_SERVICE + +COPY --from=deps /app/node_modules ./node_modules COPY . . -# Build app for production -# For development, we'll mount the source code as a volume -# so the build step will be skipped in development mode +# Next.js collects completely anonymous telemetry data about general usage. +# Learn more here: https://nextjs.org/telemetry +# Uncomment the following line in case you want to disable telemetry during the build. +# ENV NEXT_TELEMETRY_DISABLED=1 + +RUN pnpm run build + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +# Uncomment the following line in case you want to disable telemetry during runtime. +# ENV NEXT_TELEMETRY_DISABLED=1 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs EXPOSE 3000 -# Start Next.js in development mode by default -# This will be faster for development since we're mounting the code as a volume -CMD ["pnpm", "dev"] \ No newline at end of file +ENV PORT=3000 + +# server.js is created by next build from the standalone output +# https://nextjs.org/docs/pages/api-reference/config/next-config-js/output +ENV HOSTNAME="0.0.0.0" +CMD ["node", "server.js"] \ No newline at end of file diff --git a/surfsense_web/content/docs/docker-installation.mdx b/surfsense_web/content/docs/docker-installation.mdx index 0394bd2c6..535325b50 100644 --- a/surfsense_web/content/docs/docker-installation.mdx +++ b/surfsense_web/content/docs/docker-installation.mdx @@ -71,7 +71,11 @@ Before you begin, ensure you have: | POSTGRES_DB | PostgreSQL database name | surfsense | | PGADMIN_DEFAULT_EMAIL | Email for pgAdmin login | admin@surfsense.com | | PGADMIN_DEFAULT_PASSWORD | Password for pgAdmin login | surfsense | -| NEXT_PUBLIC_API_URL | URL of the backend API (used by frontend) | http://backend:8000 | +| NEXT_PUBLIC_FASTAPI_BACKEND_URL | URL of the backend API (used by frontend during build and runtime) | http://localhost:8000 | +| NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE | Authentication method for frontend: `LOCAL` or `GOOGLE` | LOCAL | +| NEXT_PUBLIC_ETL_SERVICE | Document parsing service for frontend UI: `UNSTRUCTURED`, `LLAMACLOUD`, or `DOCLING` | DOCLING | + +**Note:** Frontend environment variables with the `NEXT_PUBLIC_` prefix are embedded into the Next.js production build at build time. Since the frontend now runs as a production build in Docker, these variables must be set in the root `.env` file (Docker-specific configuration) and will be passed as build arguments during the Docker build process. **Backend Environment Variables:** @@ -148,11 +152,13 @@ For more details, see the [Uvicorn documentation](https://www.uvicorn.org/#comma ### Frontend Environment Variables -| ENV VARIABLE | DESCRIPTION | -| ------------------------------- | ---------------------------------------------------------- | -| NEXT_PUBLIC_FASTAPI_BACKEND_URL | URL of the backend service (e.g., `http://localhost:8000`) | -| NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE | Same value as set in backend AUTH_TYPE i.e `GOOGLE` for OAuth with Google, `LOCAL` for email/password authentication | -| NEXT_PUBLIC_ETL_SERVICE | Document parsing service (should match backend ETL_SERVICE): `UNSTRUCTURED`, `LLAMACLOUD`, or `DOCLING` - affects supported file formats in upload interface | +**Important:** Frontend environment variables are now configured in the **Docker-Specific Environment Variables** section above since the Next.js application runs as a production build in Docker. The following `NEXT_PUBLIC_*` variables should be set in your root `.env` file: + +- `NEXT_PUBLIC_FASTAPI_BACKEND_URL` - URL of the backend service +- `NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE` - Authentication method (`LOCAL` or `GOOGLE`) +- `NEXT_PUBLIC_ETL_SERVICE` - Document parsing service (should match backend `ETL_SERVICE`) + +These variables are embedded into the application during the Docker build process and affect the frontend's behavior and available features. 2. **Build and Start Containers** diff --git a/surfsense_web/next.config.ts b/surfsense_web/next.config.ts index 460ef5d2a..b7d37d469 100644 --- a/surfsense_web/next.config.ts +++ b/surfsense_web/next.config.ts @@ -2,6 +2,7 @@ import { createMDX } from "fumadocs-mdx/next"; import type { NextConfig } from "next"; const nextConfig: NextConfig = { + output: "standalone", typescript: { ignoreBuildErrors: true, },