# Taskboard Deployment Guide This guide will help you deploy the Taskboard application using Docker and Portainer with nginx-proxy-manager. ## Prerequisites - Docker installed - Portainer running on your Ubuntu server - nginx-proxy-manager set up and running - Docker Hub account (for image hosting) - Existing `.env` file with your configuration ## Key Features ✅ **Automatic Database Migrations**: Migrations run automatically on app startup ✅ **Production-Ready**: Multi-stage build with security hardening ✅ **Health Checks**: Built-in health monitoring ✅ **Comprehensive Logging**: Structured logs with rotation ✅ **nginx-proxy-manager Integration**: Seamless proxy setup ✅ **Build Issues Fixed**: File API and bcryptjs compatibility resolved ✅ **Peer Dependency Issues Fixed**: date-fns conflicts resolved with --legacy-peer-deps ## Deployment Steps ### 1. Build Docker Image Build your Docker image locally: ```bash # Replace 'yourusername' with your Docker Hub username docker build -t yourusername/taskboard:latest . ``` **What happens during build:** - Installs all dependencies (including dev dependencies for build) - **Fixed**: Uses `--legacy-peer-deps` to resolve date-fns version conflicts - Generates Prisma client - **Fixed**: File API compatibility during build process - **Fixed**: bcryptjs Node.js API compatibility - Builds Next.js application with standalone output - Creates production image with only necessary files - Includes Prisma CLI for database migrations - Sets up automatic migration on startup **Build Environment Variables Set:** - `NODE_ENV=production` - Production build mode - `NEXT_TELEMETRY_DISABLED=1` - Disable telemetry during build - `SKIP_ENV_VALIDATION=1` - Skip environment validation during build **Dependency Resolution:** - Uses `--legacy-peer-deps` to handle date-fns v4 with react-day-picker v8 compatibility - Safe backward compatibility maintained for all date/calendar functionality ### 2. Push to Docker Hub Login and push your image: ```bash # Login to Docker Hub docker login # Push the image docker push yourusername/taskboard:latest ``` ### 3. Deploy with Portainer #### Using Portainer UI: 1. **Login to Portainer** 2. **Navigate to Stacks** 3. **Click "Add Stack"** 4. **Enter Stack Name**: `taskboard` 5. **Copy the contents of `portainer-stack.yml`** into the web editor 6. **Set Environment Variables** (click "Environment variables" section): **Required Variables:** - `POSTGRES_PASSWORD` - Your database password (e.g., `mySecurePassword123`) - `NEXTAUTH_URL` - Your application URL (e.g., `https://taskboard.yourdomain.com`) - `AUTH_SECRET` - NextAuth secret key (32+ characters random string) - `DOCKER_IMAGE` - Your Docker image (e.g., `yourusername/taskboard:latest`) - `VIRTUAL_HOST` - Your domain name (e.g., `taskboard.yourdomain.com`) - `LETSENCRYPT_HOST` - Domain for SSL certificate (same as VIRTUAL_HOST) - `LETSENCRYPT_EMAIL` - Your email for Let's Encrypt (e.g., `admin@yourdomain.com`) **Optional Variables (if using Authentik):** - `AUTHENTIK_ID` - Your Authentik client ID - `AUTHENTIK_SECRET` - Your Authentik client secret 7. **Deploy the Stack** ### 4. Configure nginx-proxy-manager 1. **Login to nginx-proxy-manager** 2. **Add Proxy Host**: - **Domain Name**: `taskboard.yourdomain.com` - **Scheme**: `http` - **Forward Hostname/IP**: `taskboard-app` (container name) - **Forward Port**: `3000` - **Enable SSL**: Yes (Let's Encrypt) - **Email**: Your email for Let's Encrypt ### 5. Verify Deployment 1. **Check Container Status**: ```bash docker ps ``` 2. **Check Logs** (migrations will run automatically): ```bash docker logs taskboard-app ``` You should see: ``` Running database migrations... Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma Starting application... ``` 3. **Test Health Endpoint**: ```bash curl https://taskboard.yourdomain.com/api/health ``` 4. **Access Application**: Navigate to `https://taskboard.yourdomain.com` ## How Migrations Work **Automatic Migration Process:** 1. Container starts up 2. Runs `npx prisma migrate deploy` automatically 3. If migrations succeed, starts the Next.js application 4. If migrations fail, logs error but continues (for debugging) **Migration Logs:** ```bash docker logs taskboard-app ``` ## Environment Variables Required Make sure your `.env` file contains these variables (or set them in Portainer): | Variable | Description | Example | Required | |----------|-------------|---------|----------| | `POSTGRES_PASSWORD` | Database password | `secure_password_123` | ✅ | | `NEXTAUTH_URL` | Application URL | `https://taskboard.yourdomain.com` | ✅ | | `AUTH_SECRET` | NextAuth secret | `32+ character random string` | ✅ | | `DOCKER_IMAGE` | Docker image name | `yourusername/taskboard:latest` | ✅ | | `VIRTUAL_HOST` | Domain for proxy | `taskboard.yourdomain.com` | ✅ | | `LETSENCRYPT_HOST` | SSL certificate domain | `taskboard.yourdomain.com` | ✅ | | `LETSENCRYPT_EMAIL` | Email for SSL cert | `admin@yourdomain.com` | ✅ | | `AUTHENTIK_ID` | Authentik client ID | `your_client_id` | ❌ | | `AUTHENTIK_SECRET` | Authentik client secret | `your_client_secret` | ❌ | ## Troubleshooting ### Common Issues #### 1. Build Failures ✅ **FIXED** - **File API Issues**: Fixed by adding runtime checks for File API availability - **bcryptjs Issues**: Fixed with webpack externals and serverComponentsExternalPackages - **Next.js Config Issues**: Removed invalid `dynamicIO` option - **Peer Dependency Conflicts**: Fixed with `--legacy-peer-deps` flag #### 2. Peer Dependency Issues ✅ **FIXED** - **date-fns Conflict**: `react-day-picker@8.10.1` requires `date-fns@^2.28.0 || ^3.0.0` but project uses `date-fns@^4.1.0` - **Solution**: Uses `--legacy-peer-deps` during install - safe backward compatibility - **Calendar Functionality**: Works perfectly with date-fns v4 due to backward compatibility #### 3. Database Connection Issues - **Check if PostgreSQL container is running**: `docker ps` - **Verify database credentials** in environment variables - **Check network connectivity**: Both containers should be on `taskboard-network` #### 4. Migration Issues - **Check migration logs**: `docker logs taskboard-app` - **Look for migration output**: Shows during container startup - **Manual migration**: If needed, run `docker exec taskboard-app npx prisma migrate deploy` #### 5. NextAuth Issues - **Verify `AUTH_SECRET`**: Must be 32+ characters and secure - **Check `NEXTAUTH_URL`**: Must match your domain exactly (including https://) - **Authentik configuration**: Ensure Authentik settings are correct (if using) #### 6. nginx-proxy-manager Issues - **Verify network**: Check if `nginx-proxy-manager_default` network exists - **Container connectivity**: Ensure containers can communicate - **Domain matching**: VIRTUAL_HOST must match your domain exactly #### 7. File Upload Issues ✅ **FIXED** - **File API compatibility**: Fixed with conditional File type checking - **Server-side file handling**: Properly handles File objects in API routes - **Build-time errors**: Resolved with runtime type guards ### Log Analysis **Container Logs:** ```bash # App logs (includes migration output) docker logs -f taskboard-app # Database logs docker logs -f taskboard-postgres ``` **What to look for in logs:** - Migration success/failure messages - Database connection status - Application startup messages - Health check results - **No more File API errors during build** - **No more peer dependency conflicts** ### Health Checks **Application Health Check:** - **Endpoint**: `https://yourdomain.com/api/health` - **Returns**: Status, timestamp, uptime - **Frequency**: Every 30 seconds **Database Health Check:** - **Method**: PostgreSQL ping - **Frequency**: Every 30 seconds ## Architecture ``` Internet ↓ nginx-proxy-manager (SSL termination, domain routing) ↓ taskboard-app (Next.js application on port 3000) ↓ (on startup) Database Migrations ↓ taskboard-postgres (PostgreSQL database on port 5432) ``` ## Networks - `nginx-proxy-manager_default`: External network for proxy access - `taskboard-network`: Internal network for app-database communication ## Volumes - `postgres_data`: PostgreSQL data persistence - `app_uploads`: File uploads storage - `app_logs`: Application logs storage ## Security Considerations 1. **Environment Variables**: - Use strong, unique passwords (12+ characters) - Keep `AUTH_SECRET` secure and random (32+ characters) - Don't commit `.env` files to version control 2. **Database**: - Use non-default database credentials - Regular backups recommended 3. **Network**: - Containers isolated on dedicated networks - SSL/TLS handled by nginx-proxy-manager ## Backup Strategy 1. **Database Backup**: ```bash docker exec taskboard-postgres pg_dump -U taskboard_user taskboard > backup.sql ``` 2. **File Uploads Backup**: ```bash docker cp taskboard-app:/app/uploads ./uploads-backup ``` ## Quick Commands Summary ```bash # Build image docker build -t yourusername/taskboard:latest . # Push to Docker Hub docker login docker push yourusername/taskboard:latest # Check running containers docker ps # View logs (includes migration output) docker logs taskboard-app # Health check curl https://yourdomain.com/api/health # Manual migration (if needed) docker exec taskboard-app npx prisma migrate deploy ``` ## What's Fixed ✅ ✅ **Build Issues**: Proper dependency installation for Next.js build ✅ **Migration Issues**: Automatic migrations on startup ✅ **Health Check Issues**: Curl properly installed ✅ **Prisma Issues**: CLI available for migrations ✅ **Production Optimization**: Multi-stage build with security hardening ✅ **File API Issues**: Runtime type guards for File objects ✅ **bcryptjs Issues**: Webpack externals and server components config ✅ **Next.js Config Issues**: Removed invalid experimental options ✅ **Peer Dependency Issues**: date-fns v4 compatibility with --legacy-peer-deps ✅ **Calendar Functionality**: Works perfectly with date-fns v4 due to backward compatibility ## Build Error Solutions | Error | Solution | |-------|----------| | `File is not defined` | ✅ Fixed with runtime File API checks | | `bcryptjs Node.js API` warnings | ✅ Fixed with webpack externals | | `Invalid dynamicIO option` | ✅ Removed from next.config.mjs | | `Cannot find module 'zod'` | ✅ Proper dependency installation | | `ERESOLVE date-fns conflict` | ✅ Using `--legacy-peer-deps` flag | | `react-day-picker peer deps` | ✅ Safe backward compatibility maintained | | Build failing on dependencies | ✅ Using npm install with legacy-peer-deps |