Files
picpeak/DEPLOYMENT_GUIDE.md
T
paul 2c9a56f217
Mirror to GitHub / mirror (push) Successful in 39s
Test and Lint / backend-test (push) Successful in 1m42s
Test and Lint / frontend-test (push) Successful in 2m20s
Version and Release / version-bump (push) Successful in 1m9s
Version and Release / trigger-drone (push) Successful in 3s
docs: update deployment guide with GitHub Container Registry images
- Added instructions for using pre-built images from ghcr.io
- Created docker-compose.production.yml for quick deployment with official images
- Updated deployment guide with two methods:
  1. Using pre-built images (fastest, recommended)
  2. Building from source (for customization)
- Updated SIMPLE_SETUP references to use new unified script
- Added specific version deployment instructions
- Maintained backward compatibility with local build process

The pre-built images eliminate build time and ensure consistent deployments
across environments. Users can now deploy PicPeak in minutes using:
- ghcr.io/the-luap/picpeak/backend:latest
- ghcr.io/the-luap/picpeak/frontend:latest

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-29 22:22:40 +02:00

738 lines
20 KiB
Markdown

# 🚀 PicPeak Deployment Guide
This guide covers multiple deployment options for PicPeak, from simple local setups to production-ready configurations.
## 🎯 Quick Start - Simple Setup (Recommended for Beginners)
For the easiest installation without Docker or complex configurations, use our **unified setup script**:
```bash
curl -fsSL https://raw.githubusercontent.com/the-luap/picpeak/main/scripts/setup.sh -o setup.sh && \
chmod +x setup.sh && \
sudo ./setup.sh
```
This automated script handles everything including:
- Choice between Docker or Native installation
- OS detection and dependency installation
- Database setup and service configuration
- SSL/HTTPS setup (optional)
Perfect for:
- Small to medium deployments
- Local or VPS installations
- Users new to server management
- Quick testing and evaluation
👉 **See [SIMPLE_SETUP.md](./SIMPLE_SETUP.md) for detailed instructions.**
---
## 🐳 Docker Compose Deployment
### Option 1: Using Pre-built Images (Recommended)
PicPeak provides official Docker images via GitHub Container Registry for quick deployment without building:
```bash
# Clone repository for configuration files
git clone https://github.com/the-luap/picpeak.git
cd picpeak
# Copy and configure environment
cp .env.example .env
nano .env # Edit with your values
# Use pre-built images deployment
docker compose -f docker-compose.production.yml up -d
```
The production compose file uses:
- **Backend**: `ghcr.io/the-luap/picpeak/backend:latest`
- **Frontend**: `ghcr.io/the-luap/picpeak/frontend:latest`
Available tags:
- `latest` - Latest stable release
- `main` - Latest main branch build
- `develop` - Development branch (may be unstable)
- `v1.0.0` - Specific version tags
### Option 2: Building from Source
If you need to customize the application or the pre-built images aren't available, you can build locally:
## 📋 Table of Contents
- [Prerequisites](#prerequisites)
- [Quick Start](#quick-start)
- [Configuration](#configuration)
- [Deployment](#deployment)
- [First Login](#first-login)
- [Reverse Proxy Setup](#reverse-proxy-setup)
- [Maintenance](#maintenance)
- [Troubleshooting](#troubleshooting)
## Prerequisites
- Docker and Docker Compose installed
- Domain name (for production)
- SMTP server credentials for emails
- At least 2GB RAM and 20GB storage
## 🚀 Quick Start
### Method 1: Using Pre-built Images (Fastest)
1. **Clone the repository for configs**
```bash
git clone https://github.com/the-luap/picpeak.git
cd picpeak
```
2. **Set up environment**
```bash
cp .env.example .env
nano .env # Edit with your values
```
3. **Create required directories**
```bash
mkdir -p events/active events/archived data logs backup storage
chmod -R 755 events data logs backup storage
```
4. **Deploy using pre-built images**
```bash
docker compose -f docker-compose.production.yml up -d
```
5. **Check logs**
```bash
docker compose -f docker-compose.production.yml logs -f
```
### Method 2: Building from Source
1. **Clone the repository**
```bash
git clone https://github.com/the-luap/picpeak.git
cd picpeak
```
2. **Set up environment**
```bash
cp .env.example .env
nano .env # Edit with your values
```
3. **Create required directories**
```bash
mkdir -p events/active events/archived data logs backup storage
chmod -R 755 events data logs backup storage
```
4. **Build and deploy**
```bash
docker compose build
docker compose up -d
```
5. **Check logs**
```bash
docker compose logs -f
```
## 🔧 Configuration
### Essential Environment Variables
Generate secure values:
```bash
# JWT Secret
openssl rand -base64 64
# Database Password (avoid $ character - see warning below)
openssl rand -base64 32 | tr -d '$'
# Redis Password (avoid $ character - see warning below)
openssl rand -base64 32 | tr -d '$'
```
⚠️ **PASSWORD WARNING**: Docker Compose interprets `$` as variable substitution. Either:
- Avoid `$` in passwords (recommended - use the commands above)
- Escape `$` as `$$` (e.g., `Pass$$word` instead of `Pass$word`)
- Quote the entire value: `DB_PASSWORD='Pass$word'` (less reliable)
### Backend Configuration (.env)
Update `.env` with:
- `JWT_SECRET` - Authentication secret (REQUIRED - generate a secure random value)
- `DB_PASSWORD` - PostgreSQL password
- `REDIS_PASSWORD` - Redis password
- `SMTP_*` - Email configuration
- **URL Configuration** (for backend CORS):
- `FRONTEND_URL` - Frontend URL (e.g., `http://localhost:3000` for Docker)
- `ADMIN_URL` - Admin URL (e.g., `http://localhost:3000` for Docker)
### Frontend Configuration (frontend/.env)
Create `frontend/.env` from `frontend/.env.example`:
```bash
cp frontend/.env.example frontend/.env
```
Update `frontend/.env` with:
- `VITE_API_URL` - Backend API URL
- For Docker deployment: `http://localhost:3001/api`
- For non-Docker local dev: `http://localhost:3001`
- For production with reverse proxy: `/api`
⚠️ **IMPORTANT PORT CONFIGURATION**:
- The frontend runs on port **3000** in Docker (exposed via nginx)
- The backend API runs on port **3001**
- The frontend `.env` file MUST point to the correct backend port (3001)
- Default `.env.example` is configured for Docker deployment
### Email Configuration Examples
#### Gmail
```env
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-specific-password
```
#### SendGrid
```env
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=apikey
SMTP_PASS=your-sendgrid-api-key
```
## 📦 Deployment
### Using Pre-built Images (Fastest)
```bash
# Pull latest images from GitHub Container Registry
docker pull ghcr.io/the-luap/picpeak/backend:latest
docker pull ghcr.io/the-luap/picpeak/frontend:latest
# Start services using production compose file
docker compose -f docker-compose.production.yml up -d
# View running containers
docker compose ps
```
### Building from Source (For Customization)
```bash
# Build images locally
docker compose build
# Or build with no cache for clean build
docker compose build --no-cache
# Start all services
docker compose up -d
# View running containers
docker compose ps
```
### Access Points
By default, services are exposed on:
- Frontend: http://localhost:3000
- Backend/API: http://localhost:3001
- PostgreSQL: localhost:5432 (if needed)
- Redis: localhost:6379 (if needed)
### Initial Admin Setup
When deploying for the first time, an admin account is automatically created with a secure, randomly generated password. This password is displayed in the Docker logs during initialization and **must be changed** on first login.
#### Finding the Auto-Generated Admin Password
The admin password is automatically generated during the first startup and displayed in the backend container logs. Here's how to find it:
**Option 1: Search Docker logs for admin password** (recommended)
```bash
# Find the auto-generated admin password in logs
docker compose logs backend | grep "Admin password"
```
You should see output like:
```
✅ Admin password generated: BraveTiger6231!
```
**Option 2: View the complete initialization logs**
```bash
# View the complete admin setup logs
docker compose logs backend | grep -A 10 "Admin user created"
```
**Option 3: Check the saved credentials file**
```bash
# The password is also saved in the backend container
docker exec picpeak-backend cat data/ADMIN_CREDENTIALS.txt
```
**Option 4: Use the helper script**
```bash
# Show current admin username and email (password is hidden)
docker exec picpeak-backend node scripts/show-admin-credentials.js
# Reset the admin password to a new random password
docker exec picpeak-backend node scripts/show-admin-credentials.js --reset
```
#### Important Security Notes
- **Login requires the email address**, not username
- The admin password is only displayed once during initial setup
- **Password change is MANDATORY** on first login - the system will force you to change it
- If you lose the password before first login, use the `--reset` option to generate a new one
- New password requirements: minimum 12 characters, mixed case, numbers, and special characters
## 🔐 First Login
After deployment, you must complete the first login process which includes mandatory password change for security.
### Step 1: Locate Your Admin Password
1. **Find the auto-generated password** from the credentials file:
```bash
# Docker deployment
docker compose exec backend cat /app/data/ADMIN_CREDENTIALS.txt
# Or directly from the host (if you have access)
cat data/ADMIN_CREDENTIALS.txt
```
2. **Note the admin email** (default: `admin@example.com` unless customized)
### Step 2: Access Admin Panel
1. Navigate to your admin panel URL (e.g., `http://your-domain.com:3001/admin` or `https://your-domain.com/admin`)
2. Login using:
- **Email**: `admin@example.com` (or your custom admin email)
- **Password**: The auto-generated password from the logs
### Step 3: Mandatory Password Change
Upon first login, the system will **automatically redirect** you to change your password:
1. **You cannot skip this step** - it's enforced for security
2. Enter the current auto-generated password
3. Create a new secure password meeting these requirements:
- Minimum 12 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
- At least one special character (!@#$%^&*)
### Security Best Practices for New Password
- **Use a unique password** not used elsewhere
- **Consider a password manager** for generation and storage
- **Include mixed characters**: `MySecureP@ssw0rd2024!`
- **Avoid personal information** (names, dates, etc.)
- **Save securely** - you cannot recover this password easily
### If You Lose Access
If you lose your admin credentials after the first login, you'll need to manually reset the password in the database or create a new admin user through the database.
**Note**: The credentials file (`ADMIN_CREDENTIALS.txt`) is only created during initial deployment and contains the first admin password. After changing the password, this file becomes outdated but is kept for reference.
#### Configuring Admin Email
By default, the admin email is `admin@example.com`. To use a different email address, set it in your `.env` file before first deployment:
```env
# .env
ADMIN_EMAIL=your-email@yourdomain.com
```
**Note**: This only works on first deployment. To change the admin email after deployment, you'll need to update it in the database or create a new admin user through the admin panel.
## 🔒 Reverse Proxy Setup
For production deployments, you should use a reverse proxy for SSL/HTTPS. The application exposes ports directly, allowing you to use any reverse proxy solution.
### Option 1: Nginx
Install nginx and create `/etc/nginx/sites-available/picpeak`:
```nginx
server {
listen 80;
server_name your-domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# Frontend
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Backend API
location /api {
proxy_pass http://localhost:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Protected photos and uploads
location ~ ^/(photos|thumbnails|uploads) {
proxy_pass http://localhost:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Admin routes
location /admin {
proxy_pass http://localhost:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
Enable the site:
```bash
sudo ln -s /etc/nginx/sites-available/picpeak /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
### Option 2: Traefik
Add labels to `docker-compose.override.yml`:
```yaml
version: '3.8'
services:
frontend:
labels:
- "traefik.enable=true"
- "traefik.http.routers.picpeak.rule=Host(`your-domain.com`)"
- "traefik.http.routers.picpeak.entrypoints=websecure"
- "traefik.http.routers.picpeak.tls.certresolver=letsencrypt"
- "traefik.http.services.picpeak.loadbalancer.server.port=80"
backend:
labels:
- "traefik.enable=true"
- "traefik.http.routers.picpeak-api.rule=Host(`your-domain.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.picpeak-api.entrypoints=websecure"
- "traefik.http.routers.picpeak-api.tls.certresolver=letsencrypt"
- "traefik.http.services.picpeak-api.loadbalancer.server.port=3001"
```
### Option 3: Caddy
Create a `Caddyfile`:
```caddyfile
your-domain.com {
# Frontend
handle /* {
reverse_proxy localhost:3000
}
# Backend API and admin
handle /api/* {
reverse_proxy localhost:3001
}
handle /admin/* {
reverse_proxy localhost:3001
}
# Protected resources
handle /photos/* {
reverse_proxy localhost:3001
}
handle /thumbnails/* {
reverse_proxy localhost:3001
}
handle /uploads/* {
reverse_proxy localhost:3001
}
}
```
### SSL Certificates
For any reverse proxy, you can use Let's Encrypt:
```bash
# With Certbot
sudo certbot certonly --webroot -w /var/www/certbot -d your-domain.com
# Or use your reverse proxy's built-in ACME support
```
## 🔧 Maintenance
### Viewing Logs
```bash
# All services
docker compose logs -f
# Specific service
docker compose logs -f backend
docker compose logs -f frontend
```
### Backup
#### Manual Backup
```bash
# Database backup
docker exec picpeak-postgres pg_dump -U picpeak picpeak_prod > backup/db_$(date +%Y%m%d_%H%M%S).sql
# Files backup
tar -czf backup/photos_$(date +%Y%m%d_%H%M%S).tar.gz events/
```
#### Automated Backup
The application includes a built-in backup service. Configure it in the admin panel:
1. Login to admin panel
2. Go to Settings → Backup
3. Configure destination and schedule
4. Enable backup service
### Updates
#### Method 1: Using Pre-built Images (Recommended)
```bash
# Pull latest changes (for configuration updates)
git pull
# Pull latest images from GitHub Container Registry
docker compose -f docker-compose.production.yml pull
# Restart with new images
docker compose -f docker-compose.production.yml down
docker compose -f docker-compose.production.yml up -d
# Verify services are healthy
docker compose -f docker-compose.production.yml ps
```
#### Method 2: Building from Source
```bash
# Pull latest changes
git pull
# Rebuild and restart
docker compose down
docker compose build --no-cache
docker compose up -d
# Verify services are healthy
docker compose ps
```
#### Specific Version Updates
To use a specific version of the images:
```bash
# Edit docker-compose.production.yml to specify version tags
# Change: ghcr.io/the-luap/picpeak/backend:latest
# To: ghcr.io/the-luap/picpeak/backend:v1.0.0
# Then pull and restart
docker compose -f docker-compose.production.yml pull
docker compose -f docker-compose.production.yml up -d
```
### Database Migrations
Migrations run automatically on startup, but you can run them manually:
```bash
docker exec picpeak-backend npm run migrate
```
## 🚨 Troubleshooting
### Common Issues
#### 502 Bad Gateway / Login Failures
**This is the most common deployment issue!** Usually caused by misconfigured URLs or network problems:
1. **CORS Configuration Errors**:
```bash
# WRONG - Missing port will cause CORS errors
FRONTEND_URL=http://10.0.252.12
# CORRECT - Include the port you're accessing from
FRONTEND_URL=http://10.0.252.12:3000
```
The backend validates Origin headers against `FRONTEND_URL` for CORS. If they don't match exactly, you'll get 500 errors on login.
2. **After Container Restarts**:
- Nginx may have cached old container IPs
- Solution: `docker restart picpeak-frontend`
- Always wait 30-60 seconds for health checks
3. **Backend Not Starting After Migrations**:
- The logs may only show migrations completed
- Check if server is actually running: `docker exec picpeak-backend ps aux | grep node`
- Should see `node server.js` process
4. **Login After Fresh Install**:
- Check backend logs for auto-generated admin password: `docker compose logs backend | grep "Admin password"`
- Email: `admin@example.com` (or your custom admin email from .env)
- Password: Auto-generated and shown in logs (e.g., `BraveTiger6231!`)
- Remember: Password MUST be changed on first login
5. **Complete Fix Sequence**:
```bash
# 1. Fix your .env file URLs
# 2. Full restart
docker-compose down
docker-compose up -d
# 3. Wait for healthy status
sleep 60
docker ps # All should show (healthy)
# 4. Test backend directly
curl http://localhost:3001/health
# 5. Test through frontend
curl http://localhost:3000/api/public/settings
```
#### Port Already in Use
```bash
# Check what's using the port
sudo lsof -i :3000
sudo lsof -i :3001
# Change ports in .env
FRONTEND_PORT=3002
BACKEND_PORT=3003
```
#### Docker Compose Variable Substitution Errors
If you see warnings like:
```
WARN[0000] The "fgbf" variable is not set. Defaulting to a blank string.
```
This means your password contains `$` which Docker Compose interprets as a variable. Solutions:
1. **Best**: Generate passwords without `$`: `openssl rand -base64 32 | tr -d '$'`
2. **Alternative**: Escape `$` as `$$` in your .env file
3. **Example**: `DB_PASSWORD=Pass@#$$fgbf` instead of `DB_PASSWORD=Pass@#$fgbf`
#### Permission Errors
```bash
# Fix ownership
sudo chown -R 1000:1000 events data logs backup storage
chmod -R 755 events data logs backup storage
```
#### Database Connection Issues
```bash
# Check if database is running
docker compose ps
docker compose logs postgres
# Test connection
docker exec picpeak-postgres pg_isready
```
#### Email Not Sending
- Verify SMTP settings in .env
- Check email queue: `docker exec picpeak-backend psql -U picpeak -d picpeak_prod -c "SELECT * FROM email_queue ORDER BY created_at DESC LIMIT 10;"`
- For Gmail, use app-specific password
- Check logs: `docker compose logs backend | grep email`
### Health Checks
```bash
# Backend health
curl http://localhost:3001/api/health
# Frontend health
curl http://localhost:3000
# Database health
docker exec picpeak-postgres pg_isready
```
### Useful Commands
```bash
# Enter backend container
docker exec -it picpeak-backend sh
# Enter database
docker exec -it picpeak-postgres psql -U picpeak picpeak_prod
# Reset admin password
docker exec picpeak-backend node scripts/show-admin-credentials.js --reset
# Check disk usage
df -h
du -sh events/ storage/ backup/
# View running processes
docker compose top
```
## Security Recommendations
1. **Use HTTPS**: Always use a reverse proxy with SSL in production
2. **Firewall**: Only expose necessary ports (80, 443)
3. **Secure passwords**: Use strong, unique passwords for all services
4. **Regular updates**: Keep Docker images and system packages updated
5. **Backup strategy**: Set up automated backups and test restoration
6. **Monitor logs**: Regularly check logs for suspicious activity
7. **Rate limiting**: The app includes built-in rate limiting, configure as needed
## Support
For issues and questions:
- Check logs first: `docker compose logs`
- Review documentation in the repository
- Check existing issues on GitHub
- Create a new issue with:
- Error messages
- Log output
- Environment details (without secrets)
- Steps to reproduce