diff --git a/docker-compose.yaml b/docker-compose.yaml index 0bd27178..6a9be2cf 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -209,15 +209,24 @@ services: - app-network ui: - image: ${REGISTRY:-dograhai}/dograh-ui:latest + build: + context: . + dockerfile: ui/Dockerfile + args: + # Backend URL for server-side proxying (Next.js rewrites, SSR) + BACKEND_URL: "${BACKEND_URL:-http://api:8000}" + # Backend URL for client-side code (browser API calls) + NEXT_PUBLIC_BACKEND_URL: "${NEXT_PUBLIC_BACKEND_URL:-http://localhost:3010}" environment: - # Server-side URL (SSR, internal Docker network) + # Runtime overrides for server-side proxying (if needed for custom deployments) BACKEND_URL: "${BACKEND_URL:-http://api:8000}" + # Runtime config for client-side code (available in browser console) + NEXT_PUBLIC_BACKEND_URL: "${NEXT_PUBLIC_BACKEND_URL:-http://localhost:3010}" NODE_ENV: "oss" - # Flag to enable/ disable posthog + # Flag to enable/disable posthog telemetry ENABLE_TELEMETRY: "${ENABLE_TELEMETRY:-true}" - # Posthog + # Posthog analytics configuration POSTHOG_KEY: "phc_ItizB1dP6yv7ZYobbcqrpxTdbomDA8hJFSEmAMdYvIr" POSTHOG_HOST: "https://us.posthog.com" ports: diff --git a/docs/deployment/BACKEND_URL_CONFIGURATION.md b/docs/deployment/BACKEND_URL_CONFIGURATION.md new file mode 100644 index 00000000..a33311cb --- /dev/null +++ b/docs/deployment/BACKEND_URL_CONFIGURATION.md @@ -0,0 +1,347 @@ +# Dograh UI Deployment Guide: Backend URL Configuration + +## Overview + +The Dograh UI (Next.js) requires proper configuration of backend URLs for both server-side and client-side communication. This guide explains how to configure it for different deployment scenarios. + +## Architecture: Two Backend URLs + +Dograh UI uses **two separate backend URL configurations**: + +### 1. `BACKEND_URL` (Server-side) +- **Purpose**: Used by Next.js server for API rewrites and Server-Side Rendering (SSR) +- **When it's used**: When requests go through the Next.js server +- **Scope**: Server-side only (not exposed to browsers) +- **Example values**: + - Local Docker Compose: `http://api:8000` + - CapRover: `http://srv-captain--dograh-api:8000` + - Remote server: `https://api.internal.company.com:8000` + +### 2. `NEXT_PUBLIC_BACKEND_URL` (Client-side) +- **Purpose**: Used by browser-side JavaScript for API calls +- **When it's used**: When React components/JavaScript make direct API requests +- **Scope**: Embedded in browser JavaScript, visible in client code +- **Example values**: + - Local: `http://localhost:3010` or `http://localhost:8000` + - Production: `https://dograh.company.com` (same domain to avoid CORS) + +--- + +## Deployment Scenarios + +### Scenario 1: Docker Compose (Local Development) + +**Default behavior**: Everything is auto-configured. + +```bash +# Just run it! +docker compose up +``` + +**What happens**: +- UI builds with `BACKEND_URL=http://api:8000` (internal Docker network) +- UI builds with `NEXT_PUBLIC_BACKEND_URL=http://localhost:3010` +- Browser requests go through localhost +- Server requests use Docker service name + +--- + +### Scenario 2: Docker Compose with Custom Backend URL + +**Use case**: Backend running on different host or port + +```bash +# Option A: Using environment variables +export BACKEND_URL=http://dograh-api.internal:9000 +export NEXT_PUBLIC_BACKEND_URL=https://dograh.company.com +docker compose up + +# Option B: Using .env file +cat > .env << EOF +BACKEND_URL=http://dograh-api.internal:9000 +NEXT_PUBLIC_BACKEND_URL=https://dograh.company.com +EOF +docker compose up +``` + +**How it works**: +- docker-compose.yaml passes variables as build args to Dockerfile +- Dockerfile uses these values at build time +- Variables are also available at runtime for configuration + +--- + +### Scenario 3: CapRover Deployment (Pre-built Images) + +**Issue**: CapRover uses pre-built registry images, can't modify build args. + +**Solution**: Set environment variables that are read by the entrypoint script. + +#### Step 1: Add Environment Variables in CapRover UI + +Go to your dograh-ui Captain Definition: + +```json +{ + "schemaVersion": 2, + "dockerfilePath": "./Dockerfile", + "sourceType": "image", + "imageName": "dograhai/dograh-ui:latest", + "env": { + "BACKEND_URL": "http://srv-captain--dograh-api:8000", + "NEXT_PUBLIC_BACKEND_URL": "https://dograh-api.voices.shifo.org", + "NODE_ENV": "oss", + "ENABLE_TELEMETRY": "false" + }, + "ports": ["3010/http"], + "volumes": [] +} +``` + +#### Step 2: Verify Configuration + +SSH into the running container: + +```bash +docker exec dograh-ui env | grep BACKEND +# Should output: +# BACKEND_URL=http://srv-captain--dograh-api:8000 +# NEXT_PUBLIC_BACKEND_URL=https://dograh-api.voices.shifo.org +``` + +#### Step 3: Check Server Logs + +View container logs to confirm correct configuration: + +```bash +docker logs dograh-ui + +# Expected output: +# [2026-06-02 12:34:56] Configuration: +# [2026-06-02 12:34:56] Backend URL (Server-side): http://srv-captain--dograh-api:8000 +# [2026-06-02 12:34:56] Backend URL (Client-side): https://dograh-api.voices.shifo.org +``` + +--- + +### Scenario 4: Kubernetes Deployment + +**Use case**: Deploying with Helm or raw K8s manifests + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: dograh-ui-config +data: + BACKEND_URL: "http://dograh-api:8000" + NEXT_PUBLIC_BACKEND_URL: "https://dograh.company.com" + NODE_ENV: "oss" + ENABLE_TELEMETRY: "true" + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dograh-ui +spec: + replicas: 2 + template: + spec: + containers: + - name: ui + image: dograhai/dograh-ui:latest + envFrom: + - configMapRef: + name: dograh-ui-config + ports: + - containerPort: 3010 + livenessProbe: + httpGet: + path: / + port: 3010 + initialDelaySeconds: 30 + periodSeconds: 10 +``` + +--- + +### Scenario 5: Docker Build with Custom Backend + +**Use case**: Building your own image with specific backend URL + +```bash +# Build with custom backend URL +docker build \ + --build-arg BACKEND_URL=https://api.internal.company.com \ + --build-arg NEXT_PUBLIC_BACKEND_URL=https://dograh.company.com \ + -t my-dograh-ui:latest \ + -f ui/Dockerfile . + +# Run the image +docker run \ + -e BACKEND_URL=https://api.internal.company.com \ + -e NEXT_PUBLIC_BACKEND_URL=https://dograh.company.com \ + -p 3010:3010 \ + my-dograh-ui:latest +``` + +--- + +## Troubleshooting + +### Issue: "Failed to proxy http://api:8000" Error + +**Cause**: `BACKEND_URL` contains service name `api` that doesn't resolve in your environment. + +**Fix for CapRover**: +```json +{ + "env": { + "BACKEND_URL": "http://srv-captain--dograh-api:8000" // Use your actual service name + } +} +``` + +### Issue: Browser Can't Reach Backend (CORS Error) + +**Cause**: `NEXT_PUBLIC_BACKEND_URL` points to unreachable URL from browser. + +**Solution**: Ensure the URL is accessible from your browser's network: +```json +{ + "env": { + "NEXT_PUBLIC_BACKEND_URL": "https://dograh-api.voices.shifo.org" // External URL + } +} +``` + +### Issue: Server Works, But Client Requests Fail + +**Cause**: Mismatch between server-side and client-side URLs. + +**Solution**: +- **Server requests** use `BACKEND_URL` (internal network) +- **Browser requests** use `NEXT_PUBLIC_BACKEND_URL` (external URL) +- These can be different, but ensure both URLs reach the same backend + +```json +{ + "env": { + "BACKEND_URL": "http://srv-captain--dograh-api:8000", // Internal + "NEXT_PUBLIC_BACKEND_URL": "https://dograh-api.voices.shifo.org" // External + } +} +``` + +### Issue: Health Check Fails on Startup + +**Cause**: Backend not running when UI starts. + +**Fix**: Increase startup delay in your orchestration tool: +- Docker Compose: Set `start_period` in healthcheck +- CapRover: Increase "Initial Delay (s)" in health checks +- Kubernetes: Increase `initialDelaySeconds` + +--- + +## Environment Variable Reference + +| Variable | Usage | Required | Example | +|----------|-------|----------|---------| +| `BACKEND_URL` | Next.js server-side API proxying | Yes | `http://api:8000` | +| `NEXT_PUBLIC_BACKEND_URL` | Browser-side API calls | Yes | `https://dograh.company.com` | +| `NODE_ENV` | Node.js environment | No | `production` | +| `ENABLE_TELEMETRY` | Enable/disable telemetry | No | `true` | +| `POSTHOG_KEY` | PostHog analytics key | No | (auto-configured) | +| `CHECK_BACKEND` | Verify backend on startup | No | `false` | + +--- + +## Quick Reference: Common Deployments + +### Docker Compose (Default) +```bash +docker compose up +``` +✅ Auto-configured for localhost development + +### CapRover with HTTP Backend +```json +"env": { + "BACKEND_URL": "http://srv-captain--dograh-api:8000", + "NEXT_PUBLIC_BACKEND_URL": "https://dograh.company.com" +} +``` + +### Remote Server (HTTPS) +```bash +BACKEND_URL=https://api.internal.company.com:8443 \ +NEXT_PUBLIC_BACKEND_URL=https://dograh.company.com \ +docker compose up +``` + +### Kubernetes +```bash +kubectl set env deployment/dograh-ui \ + BACKEND_URL=http://dograh-api:8000 \ + NEXT_PUBLIC_BACKEND_URL=https://dograh.company.com +``` + +--- + +## Testing Your Configuration + +### 1. Check Server-side Configuration + +```bash +# SSH into container +docker exec dograh-ui env | grep BACKEND + +# Check server logs for config output +docker logs dograh-ui | grep "Backend URL" +``` + +### 2. Check Client-side Configuration + +```bash +# Open browser developer console +# Go to http://localhost:3010 +# Run in console: +console.log(window.__CONFIG__) // Or check Network tab for API requests +``` + +### 3. Test API Connectivity + +From browser console: +```javascript +// Test server-side proxying (through Next.js) +fetch('/api/v1/health').then(r => r.json()).then(console.log) + +// Test client-side backend (direct) +fetch('https://dograh-api.voices.shifo.org/api/v1/health') + .then(r => r.json()) + .then(console.log) + .catch(e => console.error('CORS or connection error:', e)) +``` + +--- + +## Best Practices + +1. **Use Internal URLs for Server**: `BACKEND_URL` can be internal service names (Docker/K8s specific) +2. **Use External URLs for Client**: `NEXT_PUBLIC_BACKEND_URL` must be reachable from browsers +3. **HTTPS in Production**: Always use HTTPS URLs in production deployments +4. **CORS Configuration**: If server and client URLs differ, ensure backend CORS is configured correctly +5. **Environment Parity**: Keep dev, staging, and production configurations consistent + +--- + +## Support + +For issues with backend URL configuration: +1. Check container logs: `docker logs dograh-ui` +2. Verify environment variables: `docker exec dograh-ui env | grep BACKEND` +3. Test connectivity: Use the "Testing Your Configuration" section above +4. Join Slack: [Dograh Community Slack](https://join.slack.com/t/dograh-community/shared_invite/zt-3zjb5vwvl-j7hRz3_F1SOn5cH~jm5f5g) +5. Open issue: [GitHub Issues](https://github.com/dograh-hq/dograh/issues) diff --git a/docs/deployment/CAPROVER_QUICK_START.md b/docs/deployment/CAPROVER_QUICK_START.md new file mode 100644 index 00000000..7527951b --- /dev/null +++ b/docs/deployment/CAPROVER_QUICK_START.md @@ -0,0 +1,207 @@ +# CapRover Quick Start: Dograh UI with Custom Backend URLs + +## For @gaurovsoni-bit and Similar CapRover Deployments + +This guide solves the exact issue you encountered in [#400](https://github.com/dograh-hq/dograh/issues/400). + +### The Problem You Experienced +``` +Failed to proxy http://api:8000/api/v1/auth/login [Error: getaddrinfo ENOTFOUND api] +``` + +You set `BACKEND_URL: http://srv-captain--dograh-api:8000` in CapRover, but the UI kept trying to reach `http://api:8000` (the hardcoded Docker Compose service name). + +### The Solution + +With the fix in this PR, you now have **two ways** to deploy in CapRover: + +--- + +## Option 1: Simplest - Use Pre-built Image with Environment Variables + +This works immediately with the updated code. + +### Step 1: Add Environment Variables in CapRover + +In your **dograh-ui Captain Definition**: + +```json +{ + "schemaVersion": 2, + "dockerfilePath": "./Dockerfile", + "sourceType": "image", + "imageName": "dograhai/dograh-ui:latest", + "env": { + "BACKEND_URL": "http://srv-captain--dograh-api:8000", + "NEXT_PUBLIC_BACKEND_URL": "https://dograh-api.voices.shifo.org", + "NODE_ENV": "oss", + "ENABLE_TELEMETRY": "false" + }, + "ports": ["3010/http"] +} +``` + +### Step 2: Verify Configuration + +SSH into the running container: + +```bash +# SSH into dograh-ui container +docker exec dograh-ui env | grep -E "BACKEND|NEXT_PUBLIC" + +# Should output: +# BACKEND_URL=http://srv-captain--dograh-api:8000 +# NEXT_PUBLIC_BACKEND_URL=https://dograh-api.voices.shifo.org +``` + +### Step 3: Check Logs for Confirmation + +```bash +docker logs dograh-ui | head -20 + +# Should show: +# [2026-06-02 12:34:56] 🚀 Dograh UI Server - Production Ready +# [2026-06-02 12:34:56] Configuration: +# [2026-06-02 12:34:56] Backend URL (Server-side): http://srv-captain--dograh-api:8000 +# [2026-06-02 12:34:56] Backend URL (Client-side): https://dograh-api.voices.shifo.org +``` + +✅ **Done!** UI will now use your custom backend URLs. + +--- + +## Option 2: Build Custom Image in CapRover + +If you want to bake the URLs into the image itself. + +### Step 1: Push Custom Dockerfile to Your Git Repo + +Update your docker-compose.yaml section in the repo with your custom URLs, then push to git. + +### Step 2: Configure CapRover to Build from Git + +In Captain Definition, change from `sourceType: "image"` to: + +```json +{ + "schemaVersion": 2, + "sourceType": "github", + "repo": "your-org/your-fork", + "branch": "main", + "dockerfilePath": "./ui/Dockerfile", + "build": { + "args": { + "BACKEND_URL": "http://srv-captain--dograh-api:8000", + "NEXT_PUBLIC_BACKEND_URL": "https://dograh-api.voices.shifo.org" + } + }, + "env": { + "NODE_ENV": "oss", + "ENABLE_TELEMETRY": "false" + }, + "ports": ["3010/http"] +} +``` + +### Step 3: Deploy + +CapRover will clone your repo, build the Dockerfile with the specified args, and deploy. + +--- + +## Environment Variables Reference + +| Variable | Purpose | Your Value | +|----------|---------|-----------| +| `BACKEND_URL` | Server-side API proxying (internal network) | `http://srv-captain--dograh-api:8000` | +| `NEXT_PUBLIC_BACKEND_URL` | Browser API calls (external URL) | `https://dograh-api.voices.shifo.org` | +| `NODE_ENV` | Node.js environment | `oss` or `production` | +| `ENABLE_TELEMETRY` | Anonymous usage telemetry | `true` or `false` | + +--- + +## Testing Your Setup + +### Test 1: Verify Server Can Reach Backend + +```bash +# SSH into dograh-ui container +docker exec dograh-ui wget -qO- http://srv-captain--dograh-api:8000/api/v1/health + +# Should return JSON response +``` + +### Test 2: Check Browser-side Configuration + +1. Open https://dograh.uivcoded.com in your browser +2. Open Developer Console (F12 → Console tab) +3. Run: `fetch('/api/v1/health').then(r => r.json()).then(console.log)` +4. Should return success response + +### Test 3: Try Login + +Navigate to login page and try to sign up/login. Should work now! + +--- + +## Troubleshooting + +### Still Getting "Failed to proxy" Error? + +1. **Check BACKEND_URL is set**: `docker exec dograh-ui env | grep BACKEND_URL` +2. **Verify server is reachable**: `docker exec dograh-ui wget -qO- http://srv-captain--dograh-api:8000/health` +3. **Check container logs**: `docker logs dograh-ui | tail -50` + +### CORS Errors in Browser? + +Ensure your backend API has CORS configured to accept requests from your UI domain: +```python +# In your backend API configuration +CORS_ORIGINS = [ + "https://dograh.uivcoded.com", + "http://localhost:3010" # for local dev +] +``` + +### "Cannot GET /" Error? + +Make sure the UI container actually started: +```bash +docker ps | grep dograh-ui +docker logs dograh-ui +``` + +--- + +## What Changed (In This Fix) + +### Before +- Dockerfile hardcoded `BACKEND_URL=http://api:8000` +- No way to override without rebuilding image +- CapRover users had to fork the repo and modify Dockerfile +- Error: "getaddrinfo ENOTFOUND api" because `api` service doesn't exist in CapRover + +### After +- Dockerfile accepts `BACKEND_URL` as build arg with sensible default +- Entrypoint script reads URL from environment at runtime +- Can deploy with pre-built image + environment variables +- Clear logging shows what URLs are being used +- Works in Docker Compose, CapRover, Kubernetes, etc. + +--- + +## Next Steps + +1. ✅ Upgrade dograh-ui to latest version +2. ✅ Set environment variables in CapRover Captain Definition +3. ✅ Verify configuration in container logs +4. ✅ Test login/signup flow +5. ✅ Enjoy your working Dograh UI! + +--- + +## Still Having Issues? + +Join us on [Dograh Community Slack](https://join.slack.com/t/dograh-community/shared_invite/zt-3zjb5vwvl-j7hRz3_F1SOn5cH~jm5f5g) - we're happy to help debug CapRover deployments! + +Reference this issue: [#400 - dograh-ui docker image not pointing to BACKEND_URL](https://github.com/dograh-hq/dograh/issues/400) diff --git a/ui/.env.example b/ui/.env.example index 741790e5..d0452970 100644 --- a/ui/.env.example +++ b/ui/.env.example @@ -1,3 +1,18 @@ +# Backend Configuration +# ===================== +# BACKEND_URL: Used by Next.js server-side rewrites (SSR, API proxying) +# - Should point to your backend API service +# - In Docker Compose: http://api:8000 (internal network) +# - In CapRover/custom: http://srv-captain--dograh-api:8000 or https://api.yourdomain.com:8000 BACKEND_URL=http://localhost:8000 + +# NEXT_PUBLIC_BACKEND_URL: Used by client-side JavaScript (browser API calls) +# - Available in browser console and React components +# - For local dev: http://localhost:8000 or http://localhost:3010 (if proxied) +# - For production: Use external URL that browsers can reach NEXT_PUBLIC_BACKEND_URL=http://localhost:8000 + +# Node Environment +# ================ +# development | production | oss (default for self-hosted) NEXT_PUBLIC_NODE_ENV=development diff --git a/ui/Dockerfile b/ui/Dockerfile index 80dac3fb..509abe74 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -35,12 +35,19 @@ COPY ui/postcss.config.mjs ./ COPY ui/public ./public COPY ui/src ./src +# Accept backend URL as build argument (allow customization during image build) +ARG BACKEND_URL=http://api:8000 +ARG NEXT_PUBLIC_BACKEND_URL=http://localhost:3010 + # Set build-time environment variables (needed for Next.js build) ENV NEXT_PUBLIC_NODE_ENV="oss" ENV NEXT_TELEMETRY_DISABLED="1" ENV NEXT_PUBLIC_CHATWOOT_URL="https://chat.dograh.com" ENV NEXT_PUBLIC_CHATWOOT_TOKEN="3fkFx2mCEjNHjM9gaNc4A82X" -ENV BACKEND_URL="http://api:8000" +# Server-side backend URL (used by Next.js rewrites for SSR/API proxying) +ENV BACKEND_URL=${BACKEND_URL} +# Client-side backend URL (used by browser-side API calls) +ENV NEXT_PUBLIC_BACKEND_URL=${NEXT_PUBLIC_BACKEND_URL} # Build the application with standalone mode # Increase Node.js heap size to prevent out-of-memory errors during build @@ -64,11 +71,15 @@ 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/public ./public +# Copy entrypoint script for runtime configuration +COPY --chown=nextjs:nodejs ui/entrypoint.sh /app/entrypoint.sh +RUN chmod +x /app/entrypoint.sh + # Switch to non-root user USER nextjs # Expose the port Next.js runs on EXPOSE 3010 -# Start the production server using the standalone Node.js server -CMD sh -c "echo '🚀 Application ready at http://localhost:3010' && PORT=3010 node server.js" +# Use entrypoint script to enable runtime configuration of backend URLs +ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/ui/entrypoint.sh b/ui/entrypoint.sh new file mode 100644 index 00000000..e4808d52 --- /dev/null +++ b/ui/entrypoint.sh @@ -0,0 +1,56 @@ +#!/bin/sh +# Dograh UI Entrypoint Script +# This script enables runtime configuration of backend URLs for flexible deployments +# Supports: Docker Compose, Docker Swarm, Kubernetes, CapRover, and custom orchestration + +set -e + +# Configuration +UI_PORT="${PORT:-3010}" +BACKEND_URL="${BACKEND_URL:-http://api:8000}" +NEXT_PUBLIC_BACKEND_URL="${NEXT_PUBLIC_BACKEND_URL:-http://localhost:3010}" + +# Logging +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" +} + +log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +log "🚀 Dograh UI Server - Production Ready" +log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +# Validate and display configuration +log "📋 Configuration:" +log " UI Port: $UI_PORT" +log " Backend URL (Server-side): $BACKEND_URL" +log " Backend URL (Client-side): $NEXT_PUBLIC_BACKEND_URL" +log " Node Environment: ${NODE_ENV:-production}" +log " Telemetry: ${ENABLE_TELEMETRY:-true}" + +# Health check for backend connectivity (informational only) +if [ "$CHECK_BACKEND" = "true" ] || [ "$CHECK_BACKEND" = "1" ]; then + log "🔍 Verifying backend connectivity..." + if command -v curl > /dev/null 2>&1; then + if curl -sf "${BACKEND_URL}/api/v1/health" > /dev/null 2>&1; then + log "✅ Backend is reachable at ${BACKEND_URL}" + else + log "⚠️ Warning: Backend may not be reachable at ${BACKEND_URL}" + log " This could be normal if backend is not yet started" + fi + fi +fi + +log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +log "✅ Starting Next.js server on port $UI_PORT..." +log "📍 Access UI at: http://localhost:$UI_PORT" +log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +# Export variables for Node.js process +export PORT=$UI_PORT +export BACKEND_URL=$BACKEND_URL +export NEXT_PUBLIC_BACKEND_URL=$NEXT_PUBLIC_BACKEND_URL +export NODE_ENV=${NODE_ENV:-production} + +# Start the Next.js server +# Using the standalone server (specified in next.config.ts) +exec node server.js