chore: update environment configuration and build outputs

- Added new output path for build artifacts in turbo.json to include "build/**".
- Updated .env.example to include required environment variables for database and Redis connections, enhancing clarity for setup.
- Refined self-hosting documentation to ensure accurate configuration for public server URLs and object storage options.
This commit is contained in:
Rotimi Best
2026-03-11 07:43:24 +01:00
parent 58347850ea
commit 09abbc3cb4
6 changed files with 91 additions and 50 deletions
+36 -33
View File
@@ -1,40 +1,43 @@
DATABASE_URL=
# Required
DATABASE_URL=""
REDIS_URL=""
PUBLIC_SERVER_URL=""
## Object storage - choose one option below
TRUSTED_ORIGINS=""
BETTER_AUTH_SECRET=""
# Option A: Cloudflare R2 (legacy)
# CLOUDFLARE_BUCKET_DOMAIN=https://cdn.example.com
# CLOUDFLARE_ACCESS_KEY=
# CLOUDFLARE_SECRET_ACCESS_KEY=
# CLOUDFLARE_ACCOUNT_ID=
# CLOUDFLARE_IMAGE_BUCKET_DOMAIN=https://media.example.com
AUTH_BEARER_TOKEN=""
AUTH_COOKIE_DOMAIN=""
# Option B: MinIO or other S3-compatible storage (on-premise, data residency)
# When API runs locally: use localhost. When API runs in Docker: use http://minio:9000
# OBJECT_STORAGE_ENDPOINT=http://localhost:9000
# OBJECT_STORAGE_PUBLIC_ENDPOINT=http://localhost:9000
# OBJECT_STORAGE_ACCESS_KEY_ID=minioadmin
# OBJECT_STORAGE_SECRET_ACCESS_KEY=minioadmin
# OBJECT_STORAGE_FORCE_PATH_STYLE=true
# OBJECT_STORAGE_MEDIA_PUBLIC_BASE_URL=http://localhost:9000/media
SMTP_HOST=""
SMTP_PORT=""
SMTP_USER=""
SMTP_SENDER=""
SMTP_PASSWORD=""
# Email
SMTP_HOST=
SMTP_USER=
SMTP_PASSWORD=
SMTP_PORT=
SMTP_SENDER=
# Optional - MinIO (S3-compatible, for Docker / on-premise self-hosting)
# When API runs in Docker: use http://minio:9000. For local API: use http://localhost:9000
MINIO_ROOT_USER=""
MINIO_ROOT_PASSWORD=""
OBJECT_STORAGE_ENDPOINT=""
OBJECT_STORAGE_PUBLIC_ENDPOINT=""
OBJECT_STORAGE_ACCESS_KEY_ID=""
OBJECT_STORAGE_SECRET_ACCESS_KEY=""
OBJECT_STORAGE_FORCE_PATH_STYLE=""
OBJECT_STORAGE_MEDIA_PUBLIC_BASE_URL=""
# Enterprise features (optional for self-hosted deployments)
# Request a key from ClassroomIO. Leave empty if you do not use Enterprise-only features.
LICENSE_KEY=
# Optional - Cloudflare R2 (for hosted deployments)
CLOUDFLARE_BUCKET_ID=""
CLOUDFLARE_ACCESS_KEY=""
CLOUDFLARE_ACCOUNT_ID=""
CLOUDFLARE_BUCKET_DOMAIN=""
CLOUDFLARE_SECRET_ACCESS_KEY=""
SENTRY_DNS=""
# Sentry DNS
SENTRY_DNS=
# Enterprise (Optional)
# Required only when using Enterprise-only features (SSO, token-auth, no-tracking)
LICENSE_KEY=""
OPENAPI_URL=
PRIVATE_SERVER_KEY=
# Public API URL (used for absolute URLs in emails, redirects, etc.)
PUBLIC_SERVER_URL=
# SSO (Optional)
# For enterprise SSO with SAML (future support)
# SSO_ENCRYPTION_KEY="your-32-character-secret-key"
+1 -1
View File
@@ -3,9 +3,9 @@ import 'dotenv/config';
import { API_PORT } from '@api/constants';
import { app } from '@api/app';
import { configureOpenAPI } from '@api/utils/openapi';
import { connectRedis } from '@api/utils/redis/redis';
import { serve } from '@hono/node-server';
import { showRoutes } from 'hono/dev';
import { connectRedis } from '@api/utils/redis/redis';
// Start server
async function startServer() {
@@ -150,8 +150,8 @@ For Enterprise SSO support, you need to configure the following:
TRUSTED_ORIGINS="https://app.classroomio.com,https://your-org.okta.com,https://accounts.google.com"
```
3. **Callback URLs**: Ensure your `SERVER_URL` and `PUBLIC_SERVER_URL` are correctly set. SSO callbacks will be:
- `{SERVER_URL}/api/auth/sso/callback/{providerId}`
3. **Callback URLs**: Ensure your `PUBLIC_SERVER_URL` is correctly set. SSO callbacks will be:
- `{PUBLIC_SERVER_URL}/api/auth/sso/callback/{providerId}`
4. **License Check**: The system will verify your Enterprise license before allowing SSO configuration. Without a valid license, the SSO settings page will show an upgrade prompt.
@@ -170,20 +170,31 @@ Go ahead and click this button to get started.
```zsh title="env"
# Required
DATABASE_URL=""
PRIVATE_DATABASE_URL=""
REDIS_URL=""
SERVER_URL=""
PUBLIC_SERVER_URL=""
TRUSTED_ORIGINS=""
BETTER_AUTH_SECRET=""
AUTH_BEARER_TOKEN=""
AUTH_COOKIE_DOMAIN=""
PRIVATE_SERVER_KEY=""
SMTP_HOST=""
SMTP_PORT=""
SMTP_USER=""
SMTP_SENDER=""
SMTP_PASSWORD=""
# Optional
# Optional - MinIO (S3-compatible, for Docker / on-premise self-hosting)
# When API runs in Docker: use minio service name. For local API: use http://localhost:9000
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
OBJECT_STORAGE_ENDPOINT=http://minio:9000
OBJECT_STORAGE_PUBLIC_ENDPOINT=http://localhost:9000
OBJECT_STORAGE_ACCESS_KEY_ID=minioadmin
OBJECT_STORAGE_SECRET_ACCESS_KEY=minioadmin
OBJECT_STORAGE_FORCE_PATH_STYLE=true
OBJECT_STORAGE_MEDIA_PUBLIC_BASE_URL=http://localhost:9000/media
# Optional - Cloudflare R2 (for hosted deployments)
CLOUDFLARE_BUCKET_ID=""
CLOUDFLARE_ACCESS_KEY=""
CLOUDFLARE_ACCOUNT_ID=""
@@ -327,11 +338,20 @@ PRIVATE_SERVER_KEY=
# Required only for Enterprise-only features (SSO, token-auth, no-tracking)
LICENSE_KEY=
SERVER_URL=
PUBLIC_SERVER_URL=
PRIVATE_SERVER_URL=
TRUSTED_ORIGINS=
AUTH_COOKIE_DOMAIN=
# MinIO (object storage, when using ./run-docker-full-stack.sh with MinIO)
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
OBJECT_STORAGE_ENDPOINT=http://minio:9000
OBJECT_STORAGE_PUBLIC_ENDPOINT=http://localhost:9000
OBJECT_STORAGE_ACCESS_KEY_ID=minioadmin
OBJECT_STORAGE_SECRET_ACCESS_KEY=minioadmin
OBJECT_STORAGE_FORCE_PATH_STYLE=true
OBJECT_STORAGE_MEDIA_PUBLIC_BASE_URL=http://localhost:9000/media
```
<Callout title="Important">
+1 -1
View File
@@ -8,7 +8,7 @@ POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
# API runtime
SERVER_URL=https://api.domain.com
PUBLIC_SERVER_URL=https://api.domain.com
TRUSTED_ORIGINS=https://app.domain.com
# Optional: cookie domain for Better Auth cross-subdomain cookies.
# Use either .domain.com (shared across subdomains) or your API host.
+26 -8
View File
@@ -34,12 +34,30 @@ Now when I am ready to deploy the feature, I can use [option 2](https://orm.driz
I can make changes directly to the schema file and run `pnpm db push` to push the changes to the source db.
## Change email flow
## Setting up a new DB on Railway
1. User changes email on dashboard to new email
2. We send an email verification to the current, permitting the change
3. Meanwhile the frontend reverts to the previous email.
4. User clicks approve link in email
5. User is redirected to settings page with message that another email has been sent to the new email
6. User goes to new email inbox and clicks approve link in email
7. User is taken to the settings page with new email address.
Once you setup a Postgres DB on Railway, you should copyt the `DATABASE_PUBLIC_URL` and paste into your `.env`. In the `.env` we expect `DATABASE_URL`:
```.env
DATABASE_URL=what-you-copied-from-railway
```
### Commands
#### db:setup
Prepares the database so the application can run. Run this for new databases or after provisioning Postgres.
```
pnpm db:setup
```
It performs three steps in order:
1. **Schema sync** – Runs `drizzle-kit push` to apply the TypeScript schema to the database (creates/updates tables, enums, etc.).
2. **PostgreSQL roles** – Creates the `authenticated` and `anon` roles if missing (used by RLS policies).
3. **Essential seed data** – Inserts required reference data: roles (ADMIN, TUTOR, STUDENT), submission statuses, and question types.
**Optional:** Add `--seed` (or `-s`) to run the full seed, including demo users, organizations, courses, and other example data.
Requires `DATABASE_URL` or `PRIVATE_DATABASE_URL` in the environment.
+1 -1
View File
@@ -7,7 +7,7 @@
},
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**", ".vercel/**", "dist/**"]
"outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**", ".vercel/**", "dist/**", "build/**"]
},
"start": {
"cache": false,