325 lines
11 KiB
Markdown
325 lines
11 KiB
Markdown
# 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 | |