From b056d826bea24b30fad818f9b70e16a1702db087 Mon Sep 17 00:00:00 2001 From: BroUnion Date: Sun, 29 Mar 2026 19:30:33 +0000 Subject: [PATCH] fix: resolve local Docker setup issues - Simplify docker-compose.yml for local dev with hot-reload - Update self-hosted compose with proper services - Add Dashboard Dockerfile for production - Update .env.example with all required variables - Create docker-setup.md documentation - Update installation.md with Docker prerequisites - Update server Dockerfile to Bun 1.3.9 Fixes #43 --- .env.example | 119 ++++++++++---------- apps/dashboard/Dockerfile | 53 +++++++++ docker-compose.self-hosted.yml | 95 ++++++++-------- docker-compose.yml | 128 ++++++---------------- docs/docker-setup.md | 157 +++++++++++++++++++++++++++ docs/getting-started/installation.md | 120 +++++++++++--------- packages/server/Dockerfile | 12 +- 7 files changed, 420 insertions(+), 264 deletions(-) create mode 100644 apps/dashboard/Dockerfile create mode 100644 docs/docker-setup.md diff --git a/.env.example b/.env.example index c917b6c..d286b4c 100644 --- a/.env.example +++ b/.env.example @@ -6,98 +6,89 @@ # ============================================================================ # ---------------------------------------------------------------------------- -# Required: Database +# Database (PostgreSQL) # ---------------------------------------------------------------------------- -# PostgreSQL connection string (for postgres, neon, supabase) -# Format: postgresql://user:password@host:port/database -DATABASE_URL=postgres://user:password@localhost:5432/betterbase +POSTGRES_USER=betterbase +POSTGRES_PASSWORD=your_secure_password_here +POSTGRES_DB=betterbase -# Or for Neon (serverless PostgreSQL) -# DATABASE_URL=postgres://user:password@ep-xxx.us-east-1.aws.neon.tech/neondb?sslmode=require - -# Or for Turso (libSQL) -# TURSO_URL=libsql://your-database.turso.io -# TURSO_AUTH_TOKEN=your-auth-token +DATABASE_URL=postgresql://betterbase:your_secure_password_here@localhost:5432/betterbase # ---------------------------------------------------------------------------- -# Required: Authentication +# Authentication # ---------------------------------------------------------------------------- -# Generate a secure secret: openssl rand -base64 32 -AUTH_SECRET=your-super-secret-key-min-32-chars-long-change-in-production +# Generate: openssl rand -base64 32 +AUTH_SECRET=your-super-secret-key-min-32-chars-long AUTH_URL=http://localhost:3000 # ---------------------------------------------------------------------------- -# Optional: Storage (S3-compatible) +# MinIO (S3-compatible storage) # ---------------------------------------------------------------------------- -# Provider: s3, r2, backblaze, minio -STORAGE_PROVIDER=r2 -STORAGE_BUCKET=betterbase-storage -STORAGE_REGION=auto -STORAGE_ENDPOINT=https://your-r2-endpoint.r2.cloudflarestorage.com -STORAGE_ACCESS_KEY_ID=your-access-key -STORAGE_SECRET_ACCESS_KEY=your-secret-key +MINIO_ROOT_USER=minioadmin +MINIO_ROOT_PASSWORD=minioadmin_password + +STORAGE_ENDPOINT=http://localhost:9000 +STORAGE_ACCESS_KEY=minioadmin +STORAGE_SECRET_KEY=minioadmin_password +STORAGE_BUCKET=betterbase # ---------------------------------------------------------------------------- -# Optional: Email (SMTP) +# Inngest (Durable Workflow Engine) # ---------------------------------------------------------------------------- -SMTP_HOST=smtp.example.com -SMTP_PORT=587 -SMTP_USER=your-smtp-user -SMTP_PASS=your-smtp-password -SMTP_FROM=noreply@your-domain.com +INNGEST_LOG_LEVEL=info +# Generate: openssl rand -hex 32 +INNGEST_SIGNING_KEY= +# Generate: openssl rand -hex 16 +INNGEST_EVENT_KEY= # ---------------------------------------------------------------------------- -# Optional: OAuth Providers +# Application Settings # ---------------------------------------------------------------------------- -# GitHub -# GITHUB_CLIENT_ID=your-github-client-id -# GITHUB_CLIENT_SECRET=your-github-client-secret +NODE_ENV=development +PORT=3001 +HOST=0.0.0.0 -# Google -# GOOGLE_CLIENT_ID=your-google-client-id -# GOOGLE_CLIENT_SECRET=your-google-client-secret +CORS_ORIGIN=http://localhost:3000,http://localhost:5173 -# Discord -# DISCORD_CLIENT_ID=your-discord-client-id -# DISCORD_CLIENT_SECRET=your-discord-client-secret +LOG_LEVEL=debug # ---------------------------------------------------------------------------- -# Optional: Phone Auth (Twilio) +# Storage (S3-compatible - for production with external services) # ---------------------------------------------------------------------------- -# TWILIO_ACCOUNT_SID=your-twilio-sid -# TWILIO_AUTH_TOKEN=your-twilio-token -# TWILIO_PHONE_NUMBER=+1234567890 +# STORAGE_PROVIDER=r2 +# STORAGE_BUCKET=betterbase-storage +# STORAGE_REGION=auto +# STORAGE_ENDPOINT=https://your-r2-endpoint.r2.cloudflarestorage.com +# STORAGE_ACCESS_KEY_ID=your-access-key +# STORAGE_SECRET_ACCESS_KEY=your-secret-key # ---------------------------------------------------------------------------- -# Application Settings +# Email (optional) # ---------------------------------------------------------------------------- -NODE_ENV=development -PORT=3000 -HOST=0.0.0.0 +# SMTP_HOST=smtp.example.com +# SMTP_PORT=587 +# SMTP_USER=your-smtp-user +# SMTP_PASS=your-smtp-password +# SMTP_FROM=noreply@your-domain.com -# Comma-separated list of allowed CORS origins -CORS_ORIGIN=http://localhost:3000,http://localhost:5173 +# ---------------------------------------------------------------------------- +# OAuth Providers (optional) +# ---------------------------------------------------------------------------- +# GITHUB_CLIENT_ID=your-github-client-id +# GITHUB_CLIENT_SECRET=your-github-client-secret -# Logging -LOG_LEVEL=debug +# GOOGLE_CLIENT_ID=your-google-client-id +# GOOGLE_CLIENT_SECRET=your-google-client-secret # ---------------------------------------------------------------------------- -# Vector Search (optional) +# Phone Auth (optional - Twilio) # ---------------------------------------------------------------------------- -# VECTOR_PROVIDER=openai -# OPENAI_API_KEY=your-openai-api-key +# TWILIO_ACCOUNT_SID=your-twilio-sid +# TWILIO_AUTH_TOKEN=your-twilio-token +# TWILIO_PHONE_NUMBER=+1234567890 # ---------------------------------------------------------------------------- -# Inngest (Durable Workflow Engine) +# Vector Search (optional) # ---------------------------------------------------------------------------- -# For local development with Inngest Docker: -# INNGEST_BASE_URL=http://localhost:8288 -# -# For self-hosted production: -# INNGEST_BASE_URL=http://inngest:8288 -# Generate signing key: openssl rand -hex 32 -# INNGEST_SIGNING_KEY=change-me-to-a-random-hex-string -# Generate event key: openssl rand -hex 16 -# INNGEST_EVENT_KEY=change-me-to-another-random-hex-string -# Log level (debug | info | warn | error) -# INNGEST_LOG_LEVEL=info +# VECTOR_PROVIDER=openai +# OPENAI_API_KEY=your-openai-api-key \ No newline at end of file diff --git a/apps/dashboard/Dockerfile b/apps/dashboard/Dockerfile new file mode 100644 index 0000000..5cf0545 --- /dev/null +++ b/apps/dashboard/Dockerfile @@ -0,0 +1,53 @@ +# ============================================================================ +# Betterbase Dashboard Dockerfile +# +# Builds the React dashboard and serves it with nginx. +# Used in production self-hosted deployments. +# +# Build: +# docker build -f apps/dashboard/Dockerfile -t betterbase-dashboard . +# ============================================================================ + +FROM oven/bun:1.3.9-debian AS builder + +WORKDIR /app + +COPY package.json bun.lock* ./ + +RUN bun install --frozen-lockfile + +COPY . . + +ARG VITE_API_URL=http://localhost:3001 +ENV VITE_API_URL=$VITE_API_URL + +RUN bun run build + +FROM nginx:alpine + +COPY --from=builder /app/dist /usr/share/nginx/html + +RUN cat > /etc/nginx/conf.d/default.conf << 'EOF' +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + location /assets/ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + location / { + try_files $uri $uri/ /index.html; + } + + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; +} +EOF + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/docker-compose.self-hosted.yml b/docker-compose.self-hosted.yml index d00a15a..f792916 100644 --- a/docker-compose.self-hosted.yml +++ b/docker-compose.self-hosted.yml @@ -1,34 +1,49 @@ -version: "3.9" +# ============================================================================ +# Betterbase Self-Hosted Production Docker Compose +# +# Full self-hosted deployment with all services. +# No external dependencies required. +# +# Usage: +# 1. Build: bun run build +# 2. cp .env.example .env && edit .env +# 3. docker compose -f docker-compose.self-hosted.yml up -d +# +# Services: +# - PostgreSQL: localhost:5432 +# - MinIO: localhost:9000 (console: localhost:9001) +# - Inngest: localhost:8288 +# - Server: localhost:3001 +# - Dashboard: localhost (via nginx) +# ============================================================================ services: - # ─── Postgres ────────────────────────────────────────────────────────────── postgres: image: postgres:16-alpine container_name: betterbase-postgres restart: unless-stopped environment: - POSTGRES_USER: betterbase + POSTGRES_USER: ${POSTGRES_USER:-betterbase} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-betterbase} - POSTGRES_DB: betterbase + POSTGRES_DB: ${POSTGRES_DB:-betterbase} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U betterbase"] + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-betterbase}"] interval: 10s timeout: 5s retries: 5 networks: - betterbase-internal - # ─── MinIO (S3-compatible storage) ───────────────────────────────────────── minio: - image: minio/minio:RELEASE.2024-01-16T16-07-38Z + image: minio/minio:latest container_name: betterbase-minio restart: unless-stopped command: server /data --console-address ":9001" environment: - MINIO_ROOT_USER: ${STORAGE_ACCESS_KEY:-minioadmin} - MINIO_ROOT_PASSWORD: ${STORAGE_SECRET_KEY:-minioadmin} + MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin} volumes: - minio_data:/data healthcheck: @@ -39,41 +54,33 @@ services: networks: - betterbase-internal - # ─── MinIO bucket init (runs once, exits) ────────────────────────────────── minio-init: - image: minio/mc:RELEASE.2024-01-06T18-51-57Z + image: minio/mc:latest container_name: betterbase-minio-init depends_on: minio: condition: service_healthy entrypoint: > /bin/sh -c " - mc alias set local http://minio:9000 ${STORAGE_ACCESS_KEY:-minioadmin} ${STORAGE_SECRET_KEY:-minioadmin}; + mc alias set local http://minio:9000 ${MINIO_ROOT_USER:-minioadmin} ${MINIO_ROOT_PASSWORD:-minioadmin}; mc mb --ignore-existing local/betterbase; echo 'MinIO bucket initialized.'; " networks: - betterbase-internal - # ─── Inngest (Durable Workflow Engine) ──────────────────────────────────── inngest: - image: inngest/inngest:latest + image: inngest/inngest:v1.17.5 container_name: betterbase-inngest restart: unless-stopped - command: inngest start --host 0.0.0.0 --port 8288 + command: inngest dev --host 0.0.0.0 --port 8288 environment: INNGEST_LOG_LEVEL: ${INNGEST_LOG_LEVEL:-info} volumes: - inngest_data:/data - healthcheck: - test: ["CMD-SHELL", "wget -qO- http://localhost:8288/health || exit 1"] - interval: 10s - timeout: 5s - retries: 5 networks: - betterbase-internal - # ─── Betterbase Server ───────────────────────────────────────────────────── betterbase-server: build: context: . @@ -88,64 +95,58 @@ services: minio-init: condition: service_completed_successfully inngest: - condition: service_healthy + condition: service_started environment: - DATABASE_URL: postgresql://betterbase:${POSTGRES_PASSWORD:-betterbase}@postgres:5432/betterbase - BETTERBASE_JWT_SECRET: ${BETTERBASE_JWT_SECRET:?JWT secret required - set BETTERBASE_JWT_SECRET in .env} - BETTERBASE_ADMIN_EMAIL: ${BETTERBASE_ADMIN_EMAIL:-} - BETTERBASE_ADMIN_PASSWORD: ${BETTERBASE_ADMIN_PASSWORD:-} - BETTERBASE_PUBLIC_URL: ${BETTERBASE_PUBLIC_URL:-http://localhost} + DATABASE_URL: postgresql://${POSTGRES_USER:-betterbase}:${POSTGRES_PASSWORD:-betterbase}@postgres:5432/${POSTGRES_DB:-betterbase} + AUTH_SECRET: ${AUTH_SECRET:?JWT secret required - set AUTH_SECRET in .env} + AUTH_URL: ${AUTH_URL:-http://localhost:3000} STORAGE_ENDPOINT: http://minio:9000 - STORAGE_ACCESS_KEY: ${STORAGE_ACCESS_KEY:-minioadmin} - STORAGE_SECRET_KEY: ${STORAGE_SECRET_KEY:-minioadmin} + STORAGE_ACCESS_KEY: ${MINIO_ROOT_USER:-minioadmin} + STORAGE_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-minioadmin} + STORAGE_BUCKET: betterbase PORT: "3001" NODE_ENV: production - CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost} + CORS_ORIGIN: ${CORS_ORIGIN:-http://localhost} INNGEST_BASE_URL: http://inngest:8288 - INNGEST_SIGNING_KEY: ${INNGEST_SIGNING_KEY} - INNGEST_EVENT_KEY: ${INNGEST_EVENT_KEY} - networks: - - betterbase-internal + INNGEST_SIGNING_KEY: ${INNGEST_SIGNING_KEY:-} + INNGEST_EVENT_KEY: ${INNGEST_EVENT_KEY:-} healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:3001/health || exit 1"] interval: 10s timeout: 5s retries: 5 + networks: + - betterbase-internal - # ─── Dashboard ───────────────────────────────────────────────────────────── - betterbase-dashboard: - build: - context: . - dockerfile: apps/dashboard/Dockerfile # Dashboard Dockerfile — see SH-25 - args: - VITE_API_URL: ${BETTERBASE_PUBLIC_URL:-http://localhost} + dashboard: + image: nginx:alpine container_name: betterbase-dashboard restart: unless-stopped + volumes: + - ./apps/dashboard/dist:/usr/share/nginx/html:ro depends_on: - betterbase-server: - condition: service_healthy + - betterbase-server networks: - betterbase-internal - # ─── Nginx Reverse Proxy ─────────────────────────────────────────────────── nginx: image: nginx:alpine container_name: betterbase-nginx restart: unless-stopped depends_on: - betterbase-server - - betterbase-dashboard + - dashboard ports: - "${HTTP_PORT:-80}:80" volumes: - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro - networks: - - betterbase-internal healthcheck: test: ["CMD", "nginx", "-t"] interval: 30s timeout: 10s retries: 3 + networks: + - betterbase-internal volumes: postgres_data: diff --git a/docker-compose.yml b/docker-compose.yml index 02dc018..e76a2c1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,132 +1,66 @@ # ============================================================================ -# Betterbase Docker Compose +# Betterbase Local Development Docker Compose # -# Development environment with PostgreSQL and the Betterbase application. +# Quick start for local development. Starts PostgreSQL, MinIO, and Inngest. +# Betterbase server runs locally with hot-reload. # # Usage: -# docker-compose up -d # Start all services -# docker-compose logs -f app # View app logs -# docker-compose down # Stop all services -# docker-compose down -v # Stop and remove volumes +# docker compose up -d +# bun run dev # ============================================================================ services: - # -------------------------------------------------------------------------- - # Betterbase Application - # -------------------------------------------------------------------------- - app: - build: - context: . - dockerfile: Dockerfile.project - ports: - - "3000:3000" - environment: - # Database - connect to postgres service - DATABASE_URL: postgres://betterbase:betterbase_secret@postgres:5432/betterbase - - # Auth - AUTH_SECRET: ${AUTH_SECRET:-your-super-secret-key-min-32-chars-long-change-in-production} - AUTH_URL: http://localhost:3000 - - # Storage (MinIO for S3-compatible storage) - STORAGE_PROVIDER: minio - STORAGE_ENDPOINT: http://minio:9000 - STORAGE_BUCKET: betterbase - STORAGE_ACCESS_KEY: minioadmin - STORAGE_SECRET_KEY: minioadmin - - # Node environment - NODE_ENV: ${NODE_ENV:-development} - PORT: "3000" - - # CORS - CORS_ORIGIN: http://localhost:3000,http://localhost:5173 - - volumes: - # Mount source for hot reload in development - - ./src:/app/src - # Storage volume for uploaded files - - betterbase_storage:/app/storage - depends_on: - postgres: - condition: service_healthy - minio: - condition: service_started - restart: unless-stopped - networks: - - betterbase-network - - # -------------------------------------------------------------------------- # PostgreSQL Database - # -------------------------------------------------------------------------- postgres: image: postgres:16-alpine + container_name: betterbase-postgres-local + restart: unless-stopped environment: POSTGRES_USER: betterbase - POSTGRES_PASSWORD: betterbase_secret + POSTGRES_PASSWORD: betterbase_dev_password POSTGRES_DB: betterbase - volumes: - - postgres_data:/var/lib/postgresql/data - # Initialize with schema on first run (optional) - # - ./init-schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro ports: - "5432:5432" + volumes: + - postgres_local_data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U betterbase -d betterbase"] + test: ["CMD-SHELL", "pg_isready -U betterbase"] interval: 5s timeout: 5s retries: 5 - restart: unless-stopped - networks: - - betterbase-network - # -------------------------------------------------------------------------- - # MinIO for S3-compatible storage (development) - # -------------------------------------------------------------------------- + # MinIO (S3-compatible storage) minio: image: minio/minio:latest + container_name: betterbase-minio-local + restart: unless-stopped command: server /data --console-address ":9001" environment: - MINIO_ROOT_USER: minioadmin - MINIO_ROOT_PASSWORD: minioadmin - volumes: - - minio_data:/data + MINIO_ROOT_USER: betterbase + MINIO_ROOT_PASSWORD: betterbase_dev_password ports: - "9000:9000" - "9001:9001" + volumes: + - minio_local_data:/data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 10s timeout: 5s retries: 5 - networks: - - betterbase-network - # -------------------------------------------------------------------------- - # Optional: Mailhog for email testing (development) - # -------------------------------------------------------------------------- - # mailhog: - # image: mailhog/mailhog:latest - # ports: - # - "1025:1025" # SMTP - # - "8025:8025" # Web UI - # networks: - # - betterbase-network - -# ---------------------------------------------------------------------------- -# Networks -# ---------------------------------------------------------------------------- -networks: - betterbase-network: - driver: bridge + # Inngest (Durable Workflow Engine) + inngest: + image: inngest/inngest:v1.17.5 + container_name: betterbase-inngest-local + restart: unless-stopped + command: inngest dev --host 0.0.0.0 --port 8288 + ports: + - "8288:8288" + volumes: + - inngest_local_data:/data -# ---------------------------------------------------------------------------- -# Volumes -# ---------------------------------------------------------------------------- volumes: - postgres_data: - driver: local - betterbase_storage: - driver: local - minio_data: - driver: local + postgres_local_data: + minio_local_data: + inngest_local_data: \ No newline at end of file diff --git a/docs/docker-setup.md b/docs/docker-setup.md new file mode 100644 index 0000000..8148b17 --- /dev/null +++ b/docs/docker-setup.md @@ -0,0 +1,157 @@ +# Docker Setup Guide + +Quick start guides for running Betterbase with Docker. + +## Quick Start (Local Development) + +The simplest way to get started: + +```bash +# Start infrastructure (PostgreSQL, MinIO, Inngest) +docker compose up -d + +# Run Betterbase server locally with hot-reload +bun run dev +``` + +That's it! Your server will be available at `http://localhost:3001`. + +### Services Started + +| Service | URL | Purpose | +|---------|-----|---------| +| PostgreSQL | localhost:5432 | Database | +| MinIO | localhost:9000 | S3-compatible storage | +| MinIO Console | localhost:9001 | Storage management UI | +| Inngest | localhost:8288 | Workflow engine | +| Betterbase | localhost:3001 | API server | + +### Environment Variables + +For local development, the default values in `docker-compose.yml` should work. +Create a `.env` file if you need custom values: + +```bash +cp .env.example .env +``` + +## Production Self-Hosted + +Deploy all services on your own infrastructure: + +```bash +# 1. Build the project +bun run build + +# 2. Configure environment +cp .env.example .env +# Edit .env with your values + +# 3. Start all services +docker compose -f docker-compose.self-hosted.yml up -d +``` + +### Required Environment Variables + +```bash +# Generate a secure auth secret +AUTH_SECRET=$(openssl rand -base64 32) + +# Generate Inngest keys (optional for development) +INNGEST_SIGNING_KEY=$(openssl rand -hex 32) +INNGEST_EVENT_KEY=$(openssl rand -hex 16) +``` + +### Accessing Services + +| Service | URL | Credentials | +|---------|-----|--------------| +| Betterbase API | http://localhost | Through nginx | +| Dashboard | http://localhost | Admin login | +| MinIO Console | http://localhost:9001 | minioadmin/minioadmin_password | + +## Common Issues + +### PostgreSQL Connection Failed + +```bash +# Check if PostgreSQL is running +docker compose ps postgres + +# View logs +docker compose logs postgres +``` + +### MinIO Bucket Not Found + +The `minio-init` service creates the bucket automatically. If it fails: + +```bash +# Manually create bucket +docker compose exec minio mc alias set local http://localhost:9000 minioadmin minioadmin_password +docker compose exec minio mc mb local/betterbase +``` + +### Port Already in Use + +If a port is already bound: + +```bash +# Check what's using the port +lsof -i :5432 + +# Change the port in docker-compose.yml +``` + +### Build Fails with "Cannot find module" + +Make sure to run `bun install` before building: + +```bash +bun install +bun run build +``` + +### Permission Issues + +On Linux, you may need to set ownership: + +```bash +sudo chown -R $(id -u):$(id -g) . +``` + +## Docker Commands Reference + +```bash +# Start services +docker compose up -d + +# Stop services +docker compose down + +# Stop and remove volumes (clean slate) +docker compose down -v + +# View logs +docker compose logs -f + +# View logs for specific service +docker compose logs -f postgres + +# Restart a service +docker compose restart postgres + +# Rebuild a service +docker compose up -d --build betterbase-server +``` + +## Development vs Production + +| Feature | Development | Production | +|---------|-------------|------------| +| Runs locally | Yes | Self-hosted server | +| Hot reload | Yes (server runs in terminal) | No | +| Database | Docker PostgreSQL | Docker or managed | +| Storage | Docker MinIO | Docker, R2, S3, or B2 | +| SSL/TLS | Not needed | Required (use Traefik/Caddy) | +| Inngest | Dev mode | Production mode | \ No newline at end of file diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index c28cb2f..6219169 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -1,14 +1,14 @@ # Installation -This guide covers how to install and set up BetterBase in your development environment. +This guide covers how to install and set up Betterbase in your development environment. ## Prerequisites -Before installing BetterBase, ensure you have the following: +Before installing Betterbase, ensure you have the following: -- **Bun** (v1.0+) - The JavaScript runtime powering BetterBase +- **Docker** & **Docker Compose** - For running infrastructure services +- **Bun** (v1.0+) - The JavaScript runtime powering Betterbase - **Git** - For version control -- **Node.js** (v18+) - Required for some optional tools ### Installing Bun @@ -34,6 +34,21 @@ Verify the installation: bun --version ``` +### Installing Docker + +BetterBase uses Docker for local development infrastructure (PostgreSQL, MinIO, Inngest). + +Install Docker Desktop for macOS/Windows, or on Linux: + +```bash +# Ubuntu/Debian +curl -fsSL https://get.docker.com | sh + +# Verify Docker +docker --version +docker compose version +``` + ## Installing BetterBase CLI The BetterBase CLI (`bb`) is your primary tool for managing projects and deployments. @@ -88,49 +103,56 @@ bun add @betterbase/client ## Project Initialization -Create your first BetterBase project: +Clone and set up the project: ```bash -# Create a new project -bb init my-app - -# Navigate to the project -cd my-app +# Clone the repository +git clone https://github.com/betterbase/betterbase.git +cd betterbase # Install dependencies bun install + +# Start infrastructure (PostgreSQL, MinIO, Inngest) +docker compose up -d + +# Start development server with hot-reload +bun run dev ``` This creates the following project structure: ``` -my-app/ -├── betterbase.config.ts # Project configuration -├── drizzle.config.ts # Database configuration -├── src/ -│ ├── db/ -│ │ ├── schema.ts # Database schema -│ │ └── migrate.ts # Migration utilities -│ ├── functions/ # Serverless functions -│ ├── auth/ # Authentication setup -│ └── routes/ # API routes -└── package.json +betterbase/ +├── packages/ +│ ├── core/ # Core framework +│ ├── cli/ # CLI tools +│ ├── client/ # Client SDK +│ ├── server/ # Server implementation +│ └── shared/ # Shared utilities +├── apps/ +│ └── dashboard/ # Admin dashboard +├── docker-compose.yml # Local development services +└── docs/ # Documentation ``` -## Environment Setup +## Quick Start with Docker -### Development Environment - -For local development, BetterBase uses SQLite by default: +For the simplest setup, start infrastructure services with Docker: ```bash -# Start development server -bb dev +# Start PostgreSQL, MinIO, and Inngest +docker compose up -d + +# Run the server locally (with hot-reload) +bun run dev ``` -Your API will be available at `http://localhost:3000`. +Your API will be available at `http://localhost:3001`. + +See [Docker Setup Guide](../docker-setup.md) for detailed instructions. -### Production Environment +## Production Environment Set up environment variables for production: @@ -138,11 +160,11 @@ Set up environment variables for production: # Database DATABASE_URL=postgresql://user:password@host:5432/db -# Authentication +# Authentication - Generate: openssl rand -base64 32 AUTH_SECRET=your-secret-key-min-32-chars AUTH_URL=https://your-domain.com -# Storage (optional) +# Storage (optional - uses MinIO by default) STORAGE_PROVIDER=s3 STORAGE_BUCKET=your-bucket AWS_ACCESS_KEY_ID=your-key @@ -151,33 +173,31 @@ AWS_SECRET_ACCESS_KEY=your-secret See the [Configuration Guide](./configuration.md) for all available options. -## Supported Databases - -BetterBase supports multiple database providers: - -| Provider | Use Case | Connection String | -|----------|----------|-------------------| -| **SQLite** | Local development | `file:./dev.db` | -| **PostgreSQL** | Production | `postgres://...` | -| **Neon** | Serverless | `postgres://...` | -| **Turso** | Edge/Serverless | libSQL URL | -| **PlanetScale** | Serverless MySQL | MySQL URL | -| **Supabase** | Supabase hosted | `postgres://...` | - ## Verifying Your Setup -Run the health check to verify everything is working: +Once Docker services are running and the server is started: ```bash -# The development server should show: -# - http://localhost:3000 - API root -# - http://localhost:3000/graphql - GraphQL playground -# - http://localhost:3000/api/auth/* - Auth endpoints -# - http://localhost:3000/storage/* - Storage endpoints +# Check Docker services are healthy +docker compose ps + +# Check the server is running +curl http://localhost:3001/health ``` +You should see: +- Docker services: `postgres`, `minio`, `inngest` - all running +- Server health check: returns successful response + +Available endpoints: +- `http://localhost:3001` - API root +- `http://localhost:3001/graphql` - GraphQL playground +- `http://localhost:3001/api/auth/*` - Auth endpoints +- `http://localhost:3001/storage/*` - Storage endpoints + ## Next Steps - [Quick Start Guide](./quick-start.md) - Get running in 5 minutes - [Your First Project](./your-first-project.md) - Build a complete application - [Configuration](./configuration.md) - Customize your setup +- [Docker Setup Guide](../docker-setup.md) - Detailed Docker configuration diff --git a/packages/server/Dockerfile b/packages/server/Dockerfile index 1a0cf9b..53a5941 100644 --- a/packages/server/Dockerfile +++ b/packages/server/Dockerfile @@ -1,8 +1,9 @@ -FROM oven/bun:1.2-alpine AS builder +FROM oven/bun:1.3.9-alpine AS builder WORKDIR /app -# Copy monorepo structure (only what server needs) +RUN apk add --no-cache git + COPY package.json turbo.json bun.lock ./ COPY packages/server/package.json ./packages/server/ COPY packages/core/package.json ./packages/core/ @@ -17,15 +18,14 @@ COPY tsconfig.base.json ./ RUN cd packages/server && bun build src/index.ts --outdir dist --target bun -# --- Runtime stage --- -FROM oven/bun:1.2-alpine +FROM oven/bun:1.3.9-alpine WORKDIR /app +RUN apk add --no-cache wget + COPY --from=builder /app/packages/server/dist ./dist -COPY --from=builder /app/packages/server/migrations ./migrations -# Health check HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=3 \ CMD wget -qO- http://localhost:3001/health || exit 1