diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..f60e22b --- /dev/null +++ b/.env.example @@ -0,0 +1,23 @@ +# Database +DATABASE_URL=postgresql://legalai:legalai@localhost:5432/legalai + +# Authentication +NEXTAUTH_URL=http://localhost:3000 +NEXTAUTH_SECRET=your-secret-here + +# AI Providers (set the one you use: anthropic, openai, ollama) +AI_PROVIDER=anthropic +ANTHROPIC_API_KEY= +OPENAI_API_KEY= + +# Ollama (local LLM) +OLLAMA_URL=http://localhost:11434 +OLLAMA_MODEL=llama3 + +# Search +MEILISEARCH_URL=http://localhost:7700 +MEILISEARCH_API_KEY=masterKey + +# Encryption (required for per-tenant API key storage) +# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" +ENCRYPTION_KEY= diff --git a/.gitignore b/.gitignore index 5ef6a52..7b8da95 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* +!.env.example # vercel .vercel diff --git a/Dockerfile b/Dockerfile index 53d6c9c..21d646c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,8 +19,12 @@ RUN adduser --system --uid 1001 nextjs COPY --from=builder /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +COPY --from=builder --chown=nextjs:nodejs /app/drizzle ./drizzle +COPY --from=builder --chown=nextjs:nodejs /app/migrate.mjs ./migrate.mjs +COPY --from=builder --chown=nextjs:nodejs /app/entrypoint.sh ./entrypoint.sh +RUN chmod +x ./entrypoint.sh USER nextjs EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0" -CMD ["node", "server.js"] +ENTRYPOINT ["./entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml index ee8effc..e453948 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,7 @@ services: - AI_PROVIDER=${AI_PROVIDER:-anthropic} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - OPENAI_API_KEY=${OPENAI_API_KEY} + - ENCRYPTION_KEY=${ENCRYPTION_KEY} depends_on: postgres: condition: service_healthy diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 988d291..e8a8f65 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -22,6 +22,13 @@ "when": 1775729813628, "tag": "0002_wide_grandmaster", "breakpoints": true + }, + { + "idx": 3, + "version": "7", + "when": 1775775900000, + "tag": "0003_tenant_api_keys", + "breakpoints": true } ] } \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..3bbfc32 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/sh +set -e +node migrate.mjs +exec node server.js diff --git a/migrate.mjs b/migrate.mjs new file mode 100644 index 0000000..76dc308 --- /dev/null +++ b/migrate.mjs @@ -0,0 +1,20 @@ +// Runtime migration script — runs drizzle SQL migrations against the database. +// Used by the Docker entrypoint before starting the app. + +import { drizzle } from 'drizzle-orm/node-postgres'; +import { migrate } from 'drizzle-orm/node-postgres/migrator'; +import pg from 'pg'; + +const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL }); + +try { + const db = drizzle(pool); + console.log('Running database migrations...'); + await migrate(db, { migrationsFolder: './drizzle' }); + console.log('Migrations complete.'); +} catch (err) { + console.error('Migration failed:', err); + process.exit(1); +} finally { + await pool.end(); +}