# Deployment with Portainer and Traefik This guide covers deploying MerchBay Admin using your existing Portainer and Traefik setup. ## Prerequisites - ✅ Gitea self-hosted with Gitea runners configured - ✅ Portainer installed and accessible - ✅ Traefik reverse proxy running with: - `web` entrypoint (port 80) - `websecure` entrypoint (port 443) - Let's Encrypt certificate resolver named `letsencrypt` - External network named `traefik` ## Deployment Methods ### Method 1: Portainer Stack Deployment (Recommended) #### Step 1: Prepare the Image Build the Docker image via Gitea Actions or manually: ```bash # Using Gitea Actions (will build automatically on push) git push origin main # OR build manually docker build -t merchbay_admin:latest . ``` #### Step 2: Deploy in Portainer 1. **Access Portainer** → `Stacks` → `Add stack` 2. **Stack Configuration:** - Name: `merchbay-admin` - Build method: `Web editor` 3. **Paste the content from `docker-compose.portainer.yml`** and update: - `APP_URL`: Your domain (e.g., `https://merchbay-admin.yourdomain.com`) - `DB_HOST`: Your MySQL host - `DB_DATABASE`: Database name - `DB_USERNAME`: Database username - `DB_PASSWORD`: Database password - Traefik Host rule: Replace `merchbay-admin.yourdomain.com` with your actual domain 4. **Deploy the stack** 5. **Run Initial Setup:** - Go to `Containers` → Find `merchbay_admin_app` - Click `Console` → Connect with `/bin/bash` - Run: ```bash php artisan migrate --force php artisan config:cache php artisan route:cache ``` ### Method 2: Gitea Actions CI/CD (Automated) #### Step 1: Configure Gitea Secrets In your Gitea repository → `Settings` → `Secrets` → `Actions`, add: | Secret Name | Value | Description | |------------|-------|-------------| | `DEPLOY_HOST` | `192.168.1.100` | Your server IP/hostname | | `DEPLOY_USER` | `deploy` | SSH username | | `DEPLOY_SSH_KEY` | `-----BEGIN RSA...` | Private SSH key | | `DEPLOY_PORT` | `22` | SSH port (optional) | | `DEPLOY_DIR` | `/var/www/merchbay_admin` | Deployment directory | | `DOMAIN` | `merchbay-admin.yourdomain.com` | Your domain for Traefik | #### Step 2: Prepare Deployment Server ```bash # SSH into your server ssh deploy@your-server # Create deployment directory sudo mkdir -p /var/www/merchbay_admin sudo chown $USER:$USER /var/www/merchbay_admin cd /var/www/merchbay_admin # Create .env file nano .env ``` Add to `.env`: ```env APP_ENV=production APP_DEBUG=false APP_URL=https://merchbay-admin.yourdomain.com DB_HOST=your-mysql-host DB_PORT=3306 DB_DATABASE=merchbay_admin DB_USERNAME=your-mysql-user DB_PASSWORD=your-mysql-password DOMAIN=merchbay-admin.yourdomain.com ``` #### Step 3: Ensure Traefik Network Exists ```bash docker network inspect traefik >/dev/null 2>&1 || docker network create traefik ``` #### Step 4: Deploy Simply push to your main branch: ```bash git add . git commit -m "Deploy application" git push origin main ``` Gitea Actions will automatically: 1. Build the Docker image 2. Transfer to your server 3. Deploy with docker-compose 4. Connect to Traefik network 5. Run migrations 6. Cache configurations ### Method 3: Manual Deployment with Script ```bash # On your server cd /var/www/merchbay_admin # Pull latest code git pull origin main # Run deployment script ./deploy.sh ``` ## Traefik Configuration ### Verify Traefik Setup Ensure your Traefik configuration includes: ```yaml # traefik.yml or docker-compose.yml entryPoints: web: address: ":80" websecure: address: ":443" certificatesResolvers: letsencrypt: acme: email: your-email@example.com storage: /letsencrypt/acme.json httpChallenge: entryPoint: web ``` ### External Network Ensure Traefik network exists and is external: ```bash # Create network if it doesn't exist docker network create traefik # Verify docker network inspect traefik ``` ## DNS Configuration Point your domain to your server: ``` Type: A Record Name: merchbay-admin (or @ for root domain) Value: YOUR_SERVER_IP TTL: 3600 ``` ## Verification ### 1. Check Container Status **Via Portainer:** - Navigate to `Containers` - Verify `merchbay_admin_app` is running **Via CLI:** ```bash docker ps | grep merchbay_admin ``` ### 2. Check Traefik Dashboard If you have Traefik dashboard enabled: - Look for `merchbay-admin@docker` router - Verify it's connected to the correct service ### 3. Test Application ```bash # Test HTTPS curl -I https://merchbay-admin.yourdomain.com # Should return: HTTP/2 200 ``` ### 4. Check Logs **Via Portainer:** - `Containers` → `merchbay_admin_app` → `Logs` **Via CLI:** ```bash docker logs merchbay_admin_app -f ``` ## Troubleshooting ### Issue: Container not accessible via domain **Check Traefik labels:** ```bash docker inspect merchbay_admin_app | grep -A 20 Labels ``` **Verify network connection:** ```bash docker network inspect traefik | grep merchbay_admin ``` **Solution:** ```bash # Reconnect to Traefik network docker network connect traefik merchbay_admin_app ``` ### Issue: SSL certificate not generating **Check Traefik logs:** ```bash docker logs traefik | grep letsencrypt ``` **Common fixes:** 1. Ensure port 80 is accessible (Let's Encrypt HTTP challenge) 2. Verify DNS is pointing to your server 3. Check email in Traefik's ACME configuration 4. Ensure `acme.json` has correct permissions (600) ### Issue: Database connection failed **Check environment variables:** ```bash docker exec merchbay_admin_app env | grep DB_ ``` **Test connection:** ```bash docker exec merchbay_admin_app php artisan tinker >>> DB::connection()->getPdo(); ``` ### Issue: 502 Bad Gateway **Possible causes:** 1. Application not fully started 2. Wrong port in Traefik label (should be 80) 3. Application crashed **Check:** ```bash # Container status docker ps -a | grep merchbay_admin # Application logs docker logs merchbay_admin_app --tail 100 # Restart container docker restart merchbay_admin_app ``` ## Updating the Application ### Via Gitea Actions (Automatic) ```bash git add . git commit -m "Update application" git push origin main ``` ### Via Portainer 1. Go to `Stacks` → `merchbay-admin` 2. Click `Editor` 3. Update image or configuration 4. Click `Update the stack` 5. Enable "Re-pull image and redeploy" ### Manual Update ```bash ssh deploy@your-server cd /var/www/merchbay_admin ./deploy.sh ``` ## Rollback ### Via Portainer 1. Go to `Stacks` → `merchbay-admin` 2. Click on the stack 3. Find previous version in `Stack History` (if available) 4. Revert to previous version ### Manual Rollback ```bash # List available backups ls -lh /var/www/merchbay_admin/backups/ # Restore from backup cd /var/www/merchbay_admin tar -xzf backups/backup_YYYYMMDD_HHMMSS.tar.gz # Restart docker compose restart ``` ## Security Best Practices 1. **Use Strong Database Passwords**: Generate with `openssl rand -base64 32` 2. **Restrict SSH Access**: Use key-based authentication only 3. **Firewall Rules**: Only allow necessary ports (80, 443, 22) 4. **Regular Backups**: Automated backups of database and storage 5. **Keep Docker Updated**: Regularly update Docker and images 6. **Monitor Logs**: Set up log monitoring/alerting 7. **Use Secrets**: Never commit sensitive data to repository 8. **HTTPS Only**: Ensure HTTP redirects to HTTPS ## Performance Optimization ### PHP-FPM Configuration Consider switching to PHP-FPM for better performance: ```dockerfile FROM php:7.4-fpm-alpine # ... additional configuration ``` ### Use Redis for Cache/Sessions ```env CACHE_DRIVER=redis SESSION_DRIVER=redis REDIS_HOST=redis ``` Add Redis service to docker-compose: ```yaml services: redis: image: redis:alpine networks: - default ``` ### Enable OPcache Already included in Dockerfile, verify: ```bash docker exec merchbay_admin_app php -i | grep opcache ``` ## Monitoring ### View Real-time Logs in Portainer 1. Navigate to `Containers` 2. Click on `merchbay_admin_app` 3. Select `Logs` tab 4. Enable `Auto-refresh` ### Set Up Alerts Configure Portainer notifications: 1. `Settings` → `Notifications` 2. Add webhook or email notification 3. Set up container health checks ## Support For issues: 1. Check application logs in Portainer 2. Verify Traefik configuration 3. Test database connectivity 4. Review Gitea Actions logs if using CI/CD