Server Setup and Deployment
Server History
Ricoya was deployed to three different servers during development:
- Home Server (192.168.1.157) — Initial attempt. PM2 process worked but Cloudflare tunnel config required sudo access the dev user didn’t have. Abandoned.
- n8n-worker-1 (159.203.80.93) — DigitalOcean. Successfully deployed with nginx + self-signed SSL. Discovered Turbopack production bundling bug here.
- OVH3 Worker (15.204.11.95) — Final production server. Rebuilt deployment under ubuntu user. This is the current production environment.
Current Production Environment
- Server: OVH3 Worker (16 vCPU, 61GB RAM, 339GB disk)
- OS: Ubuntu
- App Path: /opt/ricoya/
- Process Manager: PM2 (process name: ricoya, port 3000)
- Reverse Proxy: nginx with SSL
- Domain: ricoya.ipnoelp.com
- DNS: Cloudflare-proxied A record
Deployment Process
No git repository on server. Code is synced directly via rsync:
- rsync local code to server (excluding node_modules, .next, .git)
- Run pnpm build on server (with --no-lint flag for Next.js 16 compatibility)
- pm2 restart ricoya
Turbopack Production Bug
Next.js 16 mandates Turbopack for builds. A production-only bug was discovered:
Problem: React error #310 (“Rendered more hooks than during the previous render”) on the root page. Only occurred in production builds, not dev mode.
Root cause: The root page used next/navigation redirect(), which throws internally. Turbopack’s production bundling placed this throw between hook calls in the router component, causing React to see inconsistent hook counts.
Fix: Replaced throw-based redirect with Next.js middleware redirect. Created src/middleware.ts to handle the root redirect via NextResponse.redirect(). The root page now returns null (middleware handles routing before it renders).
nginx Configuration
- SSL configured with certificates (Cloudflare Full mode requires HTTPS on origin)
- Proxies port 443 to localhost:3000 (PM2/Next.js)
- Also proxies n8n traffic on worker1.ipnoelp.com to localhost:5678
Supabase Navigator Lock Fix
Problem: Console errors about acquiring exclusive Navigator LockManager lock with 10-second timeout. Multiple concurrent Supabase queries all competed for the same browser lock during getSession() calls.
Fix: Replaced the default Navigator LockManager with a no-op lock function in the Supabase browser client. Since there’s a single client instance, the lock is unnecessary. Queries execute without blocking each other.
Environment Variables
The server requires these environment variables in .env.local:
- Supabase URL and keys (anon + service role)
- Google Maps API key
- CyberSource credentials (sandbox)
- VAPID keys for web push notifications
- PayPal configuration
- CASH_ONLY flag (enables cash-only mode when payment providers aren’t configured)