diff --git a/.env.production.example b/.env.production.example new file mode 100644 index 0000000..b16026f --- /dev/null +++ b/.env.production.example @@ -0,0 +1,12 @@ +# Production Environment Variables +# Copy this file to .env.production and fill in your values + +# Supabase Configuration (REQUIRED) +# Get these from your Supabase project settings +NUXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co +NUXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here + +# Server Configuration (optional) +# HOST=0.0.0.0 +# PORT=3000 +# NODE_ENV=production diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..aa136d2 --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,347 @@ +# Deployment Guide + +## Prerequisites + +- Supabase project (managed or self-hosted) +- Docker and Docker Compose installed +- Domain name (optional, for production) +- SSL certificate (for HTTPS, recommended) + +## Quick Start (Docker Compose) + +### 1. Clone the repository + +```bash +git clone https://gitea.jeanlucmakiola.de/pantry-app/pantry.git +cd pantry +``` + +### 2. Configure environment + +```bash +cp .env.production.example .env.production +# Edit .env.production with your Supabase credentials +nano .env.production +``` + +Required environment variables: +- `NUXT_PUBLIC_SUPABASE_URL` - Your Supabase project URL +- `NUXT_PUBLIC_SUPABASE_ANON_KEY` - Your Supabase anonymous key + +### 3. Build and run + +```bash +docker-compose -f docker-compose.prod.yml --env-file .env.production up -d +``` + +The app will be available at `http://localhost:3000` + +### 4. Verify deployment + +```bash +# Check health +curl http://localhost:3000/api/health + +# View logs +docker-compose -f docker-compose.prod.yml logs -f app + +# Check status +docker-compose -f docker-compose.prod.yml ps +``` + +## Supabase Setup + +### Option 1: Supabase Cloud (Recommended) + +1. Create a free account at [supabase.com](https://supabase.com) +2. Create a new project +3. Run migrations: `supabase/migrations/*.sql` +4. Copy project URL and anon key to `.env.production` + +### Option 2: Self-Hosted Supabase + +Use the included `docker-compose.yml` for local Supabase: + +```bash +# Create .env file +cp .env.example .env +# Edit .env with secure passwords +nano .env + +# Start Supabase stack +docker-compose up -d + +# Wait for services to be ready +docker-compose ps + +# Run migrations +docker-compose exec db psql -U postgres -f /docker-entrypoint-initdb.d/001_initial_schema.sql +``` + +Supabase will be available at: +- API: http://localhost:54321 +- Studio: http://localhost:54323 + +## Production Deployment Options + +### Option 1: Coolify (Recommended) + +1. Add new Resource → Docker Compose +2. Paste `docker-compose.prod.yml` +3. Add environment variables in Coolify UI +4. Deploy + +### Option 2: Docker Standalone + +```bash +# Build image +docker build -t pantry:latest . + +# Run container +docker run -d \ + --name pantry \ + -p 3000:3000 \ + -e NUXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co \ + -e NUXT_PUBLIC_SUPABASE_ANON_KEY=your-key \ + --restart unless-stopped \ + pantry:latest +``` + +### Option 3: Kubernetes + +Example deployment manifest: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pantry +spec: + replicas: 2 + selector: + matchLabels: + app: pantry + template: + metadata: + labels: + app: pantry + spec: + containers: + - name: pantry + image: pantry:latest + ports: + - containerPort: 3000 + env: + - name: NUXT_PUBLIC_SUPABASE_URL + valueFrom: + secretKeyRef: + name: pantry-secrets + key: supabase-url + - name: NUXT_PUBLIC_SUPABASE_ANON_KEY + valueFrom: + secretKeyRef: + name: pantry-secrets + key: supabase-key + livenessProbe: + httpGet: + path: /api/health + port: 3000 + initialDelaySeconds: 40 + periodSeconds: 30 + resources: + limits: + memory: "512Mi" + cpu: "1000m" + requests: + memory: "256Mi" + cpu: "500m" +``` + +### Option 4: VPS with Nginx + +```nginx +# /etc/nginx/sites-available/pantry +server { + listen 80; + server_name pantry.yourdomain.com; + + location / { + proxy_pass http://localhost:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + 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; + } +} +``` + +## HTTPS/SSL + +### Using Let's Encrypt (Certbot) + +```bash +# Install Certbot +sudo apt install certbot python3-certbot-nginx + +# Get certificate +sudo certbot --nginx -d pantry.yourdomain.com + +# Auto-renewal +sudo certbot renew --dry-run +``` + +### Using Cloudflare + +1. Add your domain to Cloudflare +2. Enable "Full (strict)" SSL/TLS mode +3. Point DNS A record to your server IP +4. Cloudflare handles SSL automatically + +## Monitoring + +### Health Checks + +```bash +# Manual check +curl http://localhost:3000/api/health + +# With watch +watch -n 5 'curl -s http://localhost:3000/api/health | jq' +``` + +### Docker Stats + +```bash +docker stats pantry-app +``` + +### Logs + +```bash +# Follow logs +docker-compose -f docker-compose.prod.yml logs -f + +# Last 100 lines +docker logs --tail 100 pantry-app + +# Since timestamp +docker logs --since "2024-01-01T00:00:00" pantry-app +``` + +## Updating + +### Pull latest changes + +```bash +cd pantry +git pull origin main + +# Rebuild and restart +docker-compose -f docker-compose.prod.yml build +docker-compose -f docker-compose.prod.yml up -d +``` + +### Rolling back + +```bash +# Tag before upgrading +docker tag pantry:latest pantry:backup-20240101 + +# Rollback if needed +docker-compose -f docker-compose.prod.yml down +docker tag pantry:backup-20240101 pantry:latest +docker-compose -f docker-compose.prod.yml up -d +``` + +## Backup + +### Database (Supabase) + +```bash +# Manual backup +pg_dump -h localhost -U postgres -d postgres > backup.sql + +# Restore +psql -h localhost -U postgres -d postgres < backup.sql +``` + +### Docker Volumes + +```bash +# Backup +docker run --rm -v pantry_db-data:/data -v $(pwd):/backup ubuntu tar czf /backup/db-backup.tar.gz /data + +# Restore +docker run --rm -v pantry_db-data:/data -v $(pwd):/backup ubuntu tar xzf /backup/db-backup.tar.gz -C / +``` + +## Troubleshooting + +### Container won't start + +```bash +# Check logs +docker logs pantry-app + +# Verify environment variables +docker exec pantry-app env | grep NUXT + +# Inspect container +docker inspect pantry-app +``` + +### Supabase connection issues + +1. Verify Supabase URL and key +2. Check network connectivity +3. Verify RLS policies in Supabase +4. Check CORS settings + +### Performance issues + +1. Check resource limits +2. Monitor with `docker stats` +3. Increase memory/CPU limits in docker-compose +4. Enable compression in Nginx + +### PWA not updating + +1. Clear browser cache +2. Unregister service worker +3. Check that service worker is being served with correct headers +4. Verify manifest.json is accessible + +## Security Checklist + +- [ ] Use HTTPS (SSL certificate) +- [ ] Set secure environment variables +- [ ] Don't commit .env files +- [ ] Use strong Supabase passwords +- [ ] Enable RLS policies in Supabase +- [ ] Keep Docker images updated +- [ ] Use firewall rules +- [ ] Regular backups +- [ ] Monitor logs for suspicious activity + +## Performance Optimization + +- Enable CDN (Cloudflare) +- Use HTTP/2 +- Enable gzip/brotli compression +- Set proper cache headers +- Optimize images +- Use Supabase CDN for assets + +## Support + +- Documentation: [docs/](docs/) +- Issues: [Gitea Issues](https://gitea.jeanlucmakiola.de/pantry-app/pantry/issues) +- Wiki: Coming soon + +--- + +**Happy hosting! 🚀** diff --git a/docker-compose.yml b/docker-compose.dev.yml similarity index 100% rename from docker-compose.yml rename to docker-compose.dev.yml diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..754025b --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,52 @@ +# Production Docker Compose for Pantry App +# +# This compose file only runs the Nuxt frontend. +# Supabase should be hosted separately (managed service or self-hosted). + +version: '3.8' + +services: + app: + build: + context: . + dockerfile: Dockerfile + image: pantry:latest + container_name: pantry-app + restart: unless-stopped + + ports: + - "3000:3000" + + environment: + # Supabase connection (REQUIRED - set these in .env.production) + NUXT_PUBLIC_SUPABASE_URL: ${NUXT_PUBLIC_SUPABASE_URL} + NUXT_PUBLIC_SUPABASE_ANON_KEY: ${NUXT_PUBLIC_SUPABASE_ANON_KEY} + + # Server configuration + NODE_ENV: production + HOST: 0.0.0.0 + PORT: 3000 + + healthcheck: + test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"] + interval: 30s + timeout: 3s + start_period: 40s + retries: 3 + + networks: + - pantry + + # Resource limits (adjust based on your needs) + deploy: + resources: + limits: + memory: 512M + cpus: '1.0' + reservations: + memory: 256M + cpus: '0.5' + +networks: + pantry: + driver: bridge