Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
159 lines
7.5 KiB
Docker
159 lines
7.5 KiB
Docker
# Start with a base image and install system dependencies
|
|
# Pinned to Node 24 because the monorepo enforces ">=20 <25" in package.json engines.
|
|
FROM node:24-alpine AS base
|
|
RUN apk add \
|
|
graphicsmagick \
|
|
imagemagick \
|
|
ghostscript \
|
|
postgresql-client \
|
|
redis \
|
|
curl \
|
|
nano \
|
|
bash
|
|
WORKDIR /app
|
|
|
|
# Stage for installing dependencies (cache-friendly)
|
|
FROM base AS deps
|
|
# Copy package files for both root and server parts of the project
|
|
COPY package.json package-lock.json ./
|
|
COPY server/package.json ./server/
|
|
COPY shared/package.json ./shared/
|
|
COPY ee/packages/workflows/package.json ./ee/packages/workflows/
|
|
COPY tsconfig.base.json ./
|
|
COPY server/src/invoice-templates/assemblyscript ./server/src/invoice-templates/assemblyscript
|
|
|
|
|
|
# Builder stage for compiling the application
|
|
FROM deps AS builder
|
|
# Fallback secret values ensure edge-auth guards pass during build; real values come from runtime secrets.
|
|
ARG NEXTAUTH_SECRET_BUILD="dev-placeholder-nextauth-secret-32"
|
|
ARG NEXT_BUILD_MAX_OLD_SPACE_SIZE="12288"
|
|
# Keep every Node-based build step in this stage on the same heap limit. The
|
|
# set-image-tag.sh helper passes NEXT_BUILD_MAX_OLD_SPACE_SIZE as a build arg.
|
|
ENV NODE_OPTIONS="--max-old-space-size=${NEXT_BUILD_MAX_OLD_SPACE_SIZE}"
|
|
# Copy all project files and build the server
|
|
|
|
WORKDIR /app
|
|
|
|
COPY . .
|
|
|
|
# Remove only the EE server tree for CE builds.
|
|
# The workflows workspace now lives under ee/packages/workflows and must remain
|
|
# present because node_modules/@alga-psa/workflows is a workspace symlink.
|
|
RUN rm -rf /app/ee/server
|
|
|
|
# Copy CE stubs from server/src/empty to ee/server/src for @ee alias resolution
|
|
# This ensures both TypeScript and webpack can resolve @ee imports during CE builds
|
|
RUN mkdir -p /app/ee/server/src && \
|
|
cp -r /app/server/src/empty/. /app/ee/server/src/
|
|
|
|
# Create a dummy file for the relative import that webpack tries to resolve
|
|
RUN mkdir -p /app/ee/server/src/lib/extensions && \
|
|
echo "export const initializeExtensions = async () => { console.log('CE build - extensions not available'); };" > /app/ee/server/src/lib/extensions/initialize.js
|
|
|
|
# Create minimal stubs for packages that use relative paths (not @ee alias)
|
|
# packages/product-chat/ee/entry.tsx uses ../../../ee/server/src/services/*
|
|
RUN mkdir -p /app/ee/server/src/services && \
|
|
printf "export class ChatStreamService {\n static async handleChatStream(req) {\n return new Response(JSON.stringify({ error: 'Chat streaming is only available in Enterprise Edition' }), {\n status: 404,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n static async handleTitleStream(req) {\n return new Response(JSON.stringify({ error: 'Chat streaming is only available in Enterprise Edition' }), {\n status: 404,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n}\n" > /app/ee/server/src/services/chatStreamService.js && \
|
|
printf "export class TemporaryApiKeyService {\n static async cleanupExpiredAiKeys() {\n return 0;\n }\n}\n" > /app/ee/server/src/services/temporaryApiKeyService.js && \
|
|
printf "export class ChatCompletionsService {\n static async handleRequest(req) {\n return new Response(JSON.stringify({ error: 'Chat completions are only available in Enterprise Edition' }), {\n status: 404,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n static async handleExecute(req) {\n return new Response(JSON.stringify({ error: 'Chat completions are only available in Enterprise Edition' }), {\n status: 404,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n}\n" > /app/ee/server/src/services/chatCompletionsService.js
|
|
|
|
# Remove EE-specific scripts that shouldn't be in CE build
|
|
RUN rm -f /app/server/src/scripts/check-extension.ts
|
|
|
|
RUN npm install --include=optional
|
|
|
|
# Build all upstream packages (shared + pre-built) via Nx (handles dependency ordering)
|
|
WORKDIR /app
|
|
RUN npx nx build-deps server
|
|
ENV USE_PREBUILT="true"
|
|
|
|
# Set edition to community for proper module resolution
|
|
ENV EDITION="ce"
|
|
ENV NEXT_PUBLIC_EDITION="community"
|
|
|
|
WORKDIR /app/server
|
|
RUN NEXTAUTH_SECRET="${NEXTAUTH_SECRET_BUILD}" \
|
|
AUTH_SECRET="${NEXTAUTH_SECRET_BUILD}" \
|
|
NODE_ENV=production \
|
|
npm exec -- next build --webpack
|
|
|
|
# Create secrets directory and populate with secure placeholder values
|
|
RUN mkdir -p /app/secrets && \
|
|
echo "secure-admin-password-placeholder" > /app/secrets/postgres_password && \
|
|
echo "secure-app-password-placeholder" > /app/secrets/db_password_server && \
|
|
echo "secure-hocuspocus-password-placeholder" > /app/secrets/db_password_hocuspocus && \
|
|
echo "secure-redis-password-placeholder" > /app/secrets/redis_password && \
|
|
echo "secure-32char-auth-key-placeholder-xxxxx" > /app/secrets/alga_auth_key && \
|
|
echo "secure-32char-crypto-key-placeholder-xxxx" > /app/secrets/crypto_key && \
|
|
echo "secure-32char-token-key-placeholder-xxxx" > /app/secrets/token_secret_key && \
|
|
echo "secure-32char-nextauth-key-placeholder-xx" > /app/secrets/nextauth_secret && \
|
|
echo "secure-email-password-placeholder" > /app/secrets/email_password && \
|
|
echo "secure-oauth-client-id-placeholder" > /app/secrets/google_oauth_client_id && \
|
|
echo "secure-oauth-client-secret-placeholder" > /app/secrets/google_oauth_client_secret && \
|
|
echo "secure-gmail-client-id-placeholder" > /app/secrets/GOOGLE_CLIENT_ID && \
|
|
echo "secure-gmail-client-secret-placeholder" > /app/secrets/GOOGLE_CLIENT_SECRET && \
|
|
echo "secure-ms-client-id-placeholder" > /app/secrets/MICROSOFT_CLIENT_ID && \
|
|
echo "secure-ms-client-secret-placeholder" > /app/secrets/MICROSOFT_CLIENT_SECRET && \
|
|
chmod 600 /app/secrets/*
|
|
# Copy example environment file
|
|
COPY .env.example /app/.env
|
|
COPY .env.example /app/server/.env
|
|
|
|
# Final production image with minimal runtime artifacts
|
|
FROM node:24-alpine
|
|
RUN apk add --no-cache bash \
|
|
postgresql-client \
|
|
redis \
|
|
graphicsmagick \
|
|
imagemagick \
|
|
ghostscript \
|
|
curl \
|
|
nano \
|
|
bash
|
|
|
|
WORKDIR /app
|
|
COPY tsconfig.base.json ./
|
|
COPY server/setup /app/server/setup
|
|
COPY .env.example /app/.env
|
|
COPY .env.example /app/server/.env
|
|
|
|
# Copy built application and node_modules from earlier stages -- minimalist approach
|
|
COPY --from=builder /app/shared ./shared
|
|
COPY --from=builder /app/ee/packages/workflows ./ee/packages/workflows
|
|
COPY --from=builder /app/server/.next ./server/.next
|
|
COPY --from=builder /app/server/public ./server/public
|
|
COPY --from=builder /app/server/next.config.mjs ./server/
|
|
COPY --from=builder /app/server/package.json ./server/
|
|
COPY --from=builder /app/package.json ./
|
|
COPY --from=builder /app/package-lock.json ./
|
|
COPY --from=builder /app/server/knexfile.cjs ./server/
|
|
COPY --from=builder /app/server/tsconfig.json ./server/
|
|
COPY --from=builder /app/server/index.ts ./server/
|
|
COPY --from=builder /app/server/migrations/ ./server/migrations/
|
|
COPY --from=builder /app/server/seeds/ ./server/seeds/
|
|
COPY --from=builder /app/server/src/ ./server/src/
|
|
COPY --from=builder /app/node_modules ./node_modules
|
|
COPY --from=builder /app/server/node_modules ./server/node_modules
|
|
|
|
RUN npm install -g tsx
|
|
|
|
# Copy core package.json for version info
|
|
COPY packages/core/package.json /app/packages/core/package.json
|
|
|
|
COPY server/entrypoint.sh /app/entrypoint.sh
|
|
RUN chmod +x /app/entrypoint.sh
|
|
|
|
EXPOSE 3000
|
|
|
|
# Environment configuration
|
|
ENV NODE_ENV=production
|
|
|
|
# Secret provider configuration
|
|
# Default configuration for composite secret system
|
|
# Can be overridden in docker-compose or deployment environments
|
|
ENV SECRET_READ_CHAIN="env,filesystem"
|
|
ENV SECRET_WRITE_PROVIDER="filesystem"
|
|
|
|
ENTRYPOINT ["/app/entrypoint.sh"]
|