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) AUTH_BEARER_TOKEN=""
# CLOUDFLARE_BUCKET_DOMAIN=https://cdn.example.com AUTH_COOKIE_DOMAIN=""
# CLOUDFLARE_ACCESS_KEY=
# CLOUDFLARE_SECRET_ACCESS_KEY=
# CLOUDFLARE_ACCOUNT_ID=
# CLOUDFLARE_IMAGE_BUCKET_DOMAIN=https://media.example.com
# Option B: MinIO or other S3-compatible storage (on-premise, data residency) SMTP_HOST=""
# When API runs locally: use localhost. When API runs in Docker: use http://minio:9000 SMTP_PORT=""
# OBJECT_STORAGE_ENDPOINT=http://localhost:9000 SMTP_USER=""
# OBJECT_STORAGE_PUBLIC_ENDPOINT=http://localhost:9000 SMTP_SENDER=""
# OBJECT_STORAGE_ACCESS_KEY_ID=minioadmin SMTP_PASSWORD=""
# OBJECT_STORAGE_SECRET_ACCESS_KEY=minioadmin
# OBJECT_STORAGE_FORCE_PATH_STYLE=true
# OBJECT_STORAGE_MEDIA_PUBLIC_BASE_URL=http://localhost:9000/media
# Email # Optional - MinIO (S3-compatible, for Docker / on-premise self-hosting)
SMTP_HOST= # When API runs in Docker: use http://minio:9000. For local API: use http://localhost:9000
SMTP_USER= MINIO_ROOT_USER=""
SMTP_PASSWORD= MINIO_ROOT_PASSWORD=""
SMTP_PORT= OBJECT_STORAGE_ENDPOINT=""
SMTP_SENDER= 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) # Optional - Cloudflare R2 (for hosted deployments)
# Request a key from ClassroomIO. Leave empty if you do not use Enterprise-only features. CLOUDFLARE_BUCKET_ID=""
LICENSE_KEY= CLOUDFLARE_ACCESS_KEY=""
CLOUDFLARE_ACCOUNT_ID=""
CLOUDFLARE_BUCKET_DOMAIN=""
CLOUDFLARE_SECRET_ACCESS_KEY=""
SENTRY_DNS=""
# Sentry DNS # Enterprise (Optional)
SENTRY_DNS= # Required only when using Enterprise-only features (SSO, token-auth, no-tracking)
LICENSE_KEY=""
OPENAPI_URL= # SSO (Optional)
# For enterprise SSO with SAML (future support)
PRIVATE_SERVER_KEY= # SSO_ENCRYPTION_KEY="your-32-character-secret-key"
# Public API URL (used for absolute URLs in emails, redirects, etc.)
PUBLIC_SERVER_URL=
+1 -1
View File
@@ -3,9 +3,9 @@ import 'dotenv/config';
import { API_PORT } from '@api/constants'; import { API_PORT } from '@api/constants';
import { app } from '@api/app'; import { app } from '@api/app';
import { configureOpenAPI } from '@api/utils/openapi'; import { configureOpenAPI } from '@api/utils/openapi';
import { connectRedis } from '@api/utils/redis/redis';
import { serve } from '@hono/node-server'; import { serve } from '@hono/node-server';
import { showRoutes } from 'hono/dev'; import { showRoutes } from 'hono/dev';
import { connectRedis } from '@api/utils/redis/redis';
// Start server // Start server
async function startServer() { 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" 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: 3. **Callback URLs**: Ensure your `PUBLIC_SERVER_URL` is correctly set. SSO callbacks will be:
- `{SERVER_URL}/api/auth/sso/callback/{providerId}` - `{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. 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" ```zsh title="env"
# Required # Required
DATABASE_URL="" DATABASE_URL=""
PRIVATE_DATABASE_URL=""
REDIS_URL="" REDIS_URL=""
SERVER_URL="" PUBLIC_SERVER_URL=""
TRUSTED_ORIGINS="" TRUSTED_ORIGINS=""
BETTER_AUTH_SECRET="" BETTER_AUTH_SECRET=""
AUTH_BEARER_TOKEN="" AUTH_BEARER_TOKEN=""
AUTH_COOKIE_DOMAIN="" AUTH_COOKIE_DOMAIN=""
PRIVATE_SERVER_KEY=""
SMTP_HOST="" SMTP_HOST=""
SMTP_PORT="" SMTP_PORT=""
SMTP_USER="" SMTP_USER=""
SMTP_SENDER="" SMTP_SENDER=""
SMTP_PASSWORD="" 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_BUCKET_ID=""
CLOUDFLARE_ACCESS_KEY="" CLOUDFLARE_ACCESS_KEY=""
CLOUDFLARE_ACCOUNT_ID="" CLOUDFLARE_ACCOUNT_ID=""
@@ -327,11 +338,20 @@ PRIVATE_SERVER_KEY=
# Required only for Enterprise-only features (SSO, token-auth, no-tracking) # Required only for Enterprise-only features (SSO, token-auth, no-tracking)
LICENSE_KEY= LICENSE_KEY=
SERVER_URL=
PUBLIC_SERVER_URL= PUBLIC_SERVER_URL=
PRIVATE_SERVER_URL= PRIVATE_SERVER_URL=
TRUSTED_ORIGINS= TRUSTED_ORIGINS=
AUTH_COOKIE_DOMAIN= 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"> <Callout title="Important">
+1 -1
View File
@@ -8,7 +8,7 @@ POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres POSTGRES_PASSWORD=postgres
# API runtime # API runtime
SERVER_URL=https://api.domain.com PUBLIC_SERVER_URL=https://api.domain.com
TRUSTED_ORIGINS=https://app.domain.com TRUSTED_ORIGINS=https://app.domain.com
# Optional: cookie domain for Better Auth cross-subdomain cookies. # Optional: cookie domain for Better Auth cross-subdomain cookies.
# Use either .domain.com (shared across subdomains) or your API host. # 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. 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 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`:
2. We send an email verification to the current, permitting the change
3. Meanwhile the frontend reverts to the previous email. ```.env
4. User clicks approve link in email DATABASE_URL=what-you-copied-from-railway
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. ### 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": { "build": {
"dependsOn": ["^build"], "dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**", ".vercel/**", "dist/**"] "outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**", ".vercel/**", "dist/**", "build/**"]
}, },
"start": { "start": {
"cache": false, "cache": false,