diff --git a/DOCKER_DEPLOYMENT.md b/DOCKER_DEPLOYMENT.md index 87bb7ca..d4e9d3e 100644 --- a/DOCKER_DEPLOYMENT.md +++ b/DOCKER_DEPLOYMENT.md @@ -26,6 +26,8 @@ MinIO console: `http://localhost:9001` (minioadmin / minioadmin) ## Production Deployment +## Production Deployment + ### 1. Prepare Environment Copy and configure the production environment file: @@ -34,7 +36,13 @@ Copy and configure the production environment file: cp docker/.env.production .env.production ``` -Edit `.env.production` and set: +Or for Portainer deployment, copy the stack environment file: + +```bash +cp docker/stack.env stack.env.local +``` + +Edit the file and set: - `POSTGRES_PASSWORD` - Strong random password - `REDIS_PASSWORD` - Strong random password - `MINIO_ROOT_PASSWORD` - Strong random password @@ -44,6 +52,7 @@ Edit `.env.production` and set: - `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` - OAuth credentials - `OPENROUTER_API_KEY` - AI provider key - `SMTP_*` - Email configuration +- `NEXT_PUBLIC_VAPID_PUBLIC_KEY` / `VAPID_PRIVATE_KEY` - Push notification keys ### 2. Build Docker Image @@ -59,7 +68,67 @@ Or let Docker Compose build it automatically. docker compose -f docker/docker-compose.deploy.yml --env-file .env.production up -d ``` -### 4. Verify Deployment +## Portainer Deployment + +Portainer provides a web UI for managing Docker containers and deploying stacks easily. + +### Portainer Setup + +1. **Prepare Environment File** + + Copy the stack environment template: + ```bash + cp docker/stack.env stack.env.local + ``` + + Edit `stack.env.local` with your production values. + +2. **Access Portainer** + + Open your Portainer instance (typically `https://portainer.your-domain.com`). + +3. **Deploy Stack** + + - Go to **Stacks** → **Add Stack** + - Choose **Docker Compose** mode + - Select **Upload** to upload the compose file, or use **Editor** to paste the contents of `docker/docker-compose.deploy.yml` + - Copy the contents of `docker/stack.env` into the **Environment variables** section + - Click **Deploy the stack** + + **Alternative: Using Environment File UI** + - In the stack creation form, there's an "Environment file" option + - You can paste the entire `stack.env` content there + - Portainer will parse and use all variables + +4. **Verify Deployment** + + - Check the **Containers** tab to see all services running + - View logs by clicking on each container + - Verify the app is accessible at `https://your-domain.com` + +### Portainer Stack Update + +To update the application after code changes: + +1. Build new Docker image locally: + ```bash + docker build -f Dockerfile -t epicure-web:latest . + docker push your-registry/epicure-web:latest + ``` + +2. In Portainer: + - Go to your stack + - Click **Editor** + - Update the image reference if needed + - Click **Update the stack** + +### Portainer Secrets (Optional) + +For better security, use Portainer Secrets instead of environment variables: + +1. Create a secret in Portainer with sensitive values +2. Reference it in the compose file: `${POSTGRES_PASSWORD}` +3. Portainer will inject the secret value during deployment ```bash # Check all services are running diff --git a/Dockerfile b/Dockerfile index e2a2736..d25da66 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,17 +12,23 @@ RUN pnpm install --frozen-lockfile --prod # Build stage FROM base AS builder RUN apk add --no-cache libc6-compat git postgresql-client + +# Accept build arguments for Next.js environment +ARG NEXT_PUBLIC_VAPID_PUBLIC_KEY=dummy_key_for_build +ARG BETTER_AUTH_SECRET=dummy_secret_for_build +ARG BETTER_AUTH_URL=http://localhost:3000 + +# Set environment variables for build +ENV NEXT_PUBLIC_VAPID_PUBLIC_KEY=${NEXT_PUBLIC_VAPID_PUBLIC_KEY} +ENV BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET} +ENV BETTER_AUTH_URL=${BETTER_AUTH_URL} + COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./ RUN pnpm install --frozen-lockfile # Copy source code COPY . . -# Set required build-time environment variables -ENV NEXT_PUBLIC_VAPID_PUBLIC_KEY=dummy_key_for_build -ENV BETTER_AUTH_SECRET=dummy_secret_for_build -ENV BETTER_AUTH_URL=http://localhost:3000 - # Build the app RUN pnpm build 2>&1 diff --git a/docker/docker-compose.deploy.yml b/docker/docker-compose.deploy.yml index a0654af..c985334 100644 --- a/docker/docker-compose.deploy.yml +++ b/docker/docker-compose.deploy.yml @@ -68,6 +68,10 @@ services: build: context: .. dockerfile: Dockerfile + args: + NEXT_PUBLIC_VAPID_PUBLIC_KEY: ${NEXT_PUBLIC_VAPID_PUBLIC_KEY} + BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET} + BETTER_AUTH_URL: ${BETTER_AUTH_URL} restart: always environment: DATABASE_URL: postgresql://${POSTGRES_USER:-epicure}:${POSTGRES_PASSWORD:-changeme}@postgres:5432/${POSTGRES_DB:-epicure} diff --git a/docker/stack.env b/docker/stack.env new file mode 100644 index 0000000..499d423 --- /dev/null +++ b/docker/stack.env @@ -0,0 +1,68 @@ +# Portainer Stack Environment Variables +# Copy this file to stack.env.local and fill in your production values +# Portainer will read this file when deploying the stack + +# ============================================ +# Database Configuration +# ============================================ +POSTGRES_DB=epicure +POSTGRES_USER=epicure +POSTGRES_PASSWORD=changeme_strong_password_here +DB_HOST=postgres + +# ============================================ +# Redis Configuration +# ============================================ +REDIS_PASSWORD=changeme_strong_password_here + +# ============================================ +# MinIO / S3 Storage Configuration +# ============================================ +MINIO_ROOT_USER=minioadmin +MINIO_ROOT_PASSWORD=changeme_strong_password_here + +# ============================================ +# Better Auth Configuration +# ============================================ +BETTER_AUTH_SECRET=changeme_generate_with_openssl_rand_base64_32 +BETTER_AUTH_URL=https://your-domain.com + +# ============================================ +# Domain Configuration +# ============================================ +DOMAIN=your-domain.com + +# ============================================ +# OAuth Configuration +# ============================================ +GOOGLE_CLIENT_ID=your-google-client-id +GOOGLE_CLIENT_SECRET=your-google-client-secret + +# ============================================ +# AI Provider Configuration +# ============================================ +OPENROUTER_API_KEY=your-openrouter-api-key +OPENROUTER_DEFAULT_MODEL=nvidia/nemotron-3-ultra-550b-a55b:free +OPENAI_API_KEY= +ANTHROPIC_API_KEY= + +# ============================================ +# Email / SMTP Configuration +# ============================================ +SMTP_HOST=smtp.eu.mailgun.org +SMTP_PORT=587 +SMTP_SECURE=false +SMTP_USER=your-email@example.com +SMTP_PASS=your-smtp-password +SMTP_FROM=Epicure + +# ============================================ +# Push Notifications +# ============================================ +NEXT_PUBLIC_VAPID_PUBLIC_KEY=your-vapid-public-key +VAPID_PRIVATE_KEY=your-vapid-private-key + +# ============================================ +# Node Environment +# ============================================ +NODE_ENV=production