# biztaghavi.com — Deployment Guide > Server: `193.105.234.35` (NODE-Cloud, Iran) > Stack: Next.js 16 · MariaDB 11 · Prisma · pnpm · Docker · Nginx > Domain: `biztaghavi.com` (behind ArvanCloud CDN) --- ## 0. Pre-flight — do this ONCE on your Mac ### Download Prisma engine binaries Prisma cannot download its binaries on the server (`binaries.prisma.sh` is blocked). Run this on your Mac: ```bash # Find your exact Prisma version first cat package.json | grep '"prisma"' # e.g. "6.x.x" # Download for Alpine Linux (linux-musl-openssl-3.0.x) npx prisma@ fetch-engines --version linux-musl-openssl-3.0.x # The binaries land in ~/.prisma/engines/ — copy them to the repo mkdir -p prisma-binaries cp ~/.prisma/engines/libquery_engine-linux-musl-openssl-3.0.x.so.node prisma-binaries/ cp ~/.prisma/engines/schema-engine-linux-musl-openssl-3.0.x prisma-binaries/ # Commit them git add prisma-binaries/ git commit -m "add prisma engine binaries for linux-musl" ``` > These files are ~50 MB. They must be in git before deployment. --- ## 1. First-time server setup ```bash ssh root@193.105.234.35 # Create app directory mkdir -p /srv/nodecloud/apps/biztaghavisite cd /srv/nodecloud/apps/biztaghavisite # Clone from Gitea git clone http://git.nodecloud.ir/nodegroup/biztaghavi.git . # Create environment file cp .env.example .env nano .env # fill in real values — see section 2 ``` --- ## 2. Environment variables (`.env`) ```env DATABASE_URL=mysql://biztaghavi:STRONG_PASSWORD@db:3306/biztaghavi SESSION_SECRET=<64-char random hex — run: openssl rand -hex 32> SETUP_KEY= RESEND_API_KEY= CONTACT_EMAIL=ali@biztaghavi.com NEXT_PUBLIC_SITE_URL=https://biztaghavi.com # Docker DB credentials (must match DATABASE_URL above) DB_ROOT_PASSWORD= DB_NAME=biztaghavi DB_USER=biztaghavi DB_PASSWORD= ``` --- ## 3. Build & launch ```bash cd /srv/nodecloud/apps/biztaghavisite # Build (first time is slow — ~5-10 min due to Liara mirror rate limiting) docker compose build --no-cache # Launch docker compose up -d # Verify containers are running docker compose ps # Check logs docker compose logs -f next-app ``` --- ## 4. Run database migrations Prisma migrations run via direct SQL (not `prisma migrate` — that would need network). ```bash # Generate migration SQL from schema # (run this on your Mac, then copy the SQL to the server) npx prisma migrate diff \ --from-empty \ --to-schema-datamodel prisma/schema.prisma \ --script > migration.sql # Copy SQL to server scp migration.sql root@193.105.234.35:/tmp/ # Apply on server docker exec -i biztaghavi-db-1 mariadb \ -u biztaghavi -p'STRONG_PASSWORD' biztaghavi < /tmp/migration.sql ``` Or use `prisma db push` directly on the container (doesn't require migrations directory): ```bash docker exec -it biztaghavi-next-app-1 sh -c \ "DATABASE_URL=mysql://biztaghavi:STRONG_PASSWORD@db:3306/biztaghavi \ npx prisma db push --skip-generate" ``` --- ## 5. Create admin user (one-time) After containers are running: ```bash curl -X POST https://biztaghavi.com/api/admin/setup \ -H "Content-Type: application/json" \ -H "x-setup-key: YOUR_SETUP_KEY" \ -d '{"username":"ali","password":"YOUR_STRONG_PASSWORD"}' ``` Then **remove `SETUP_KEY` from `.env`** and restart the app: ```bash # Edit .env — delete the SETUP_KEY line docker compose restart next-app ``` Admin panel: `https://biztaghavi.com/admin` --- ## 6. Nginx config Port: **3009** The config file lives at `nginx/biztaghavi.conf` in this repo. ```bash # Install on server cp /srv/nodecloud/apps/biztaghavisite/nginx/biztaghavi.conf /etc/nginx/sites-available/biztaghavi ln -sf /etc/nginx/sites-available/biztaghavi /etc/nginx/sites-enabled/biztaghavi nginx -t && systemctl reload nginx ``` **SSL (ArvanCloud CDN — recommended):** The repo nginx config listens on **80 and 443** with the shared NODE Cloud self-signed cert (same as khanehbaan.ir). ArvanCloud terminates public HTTPS. ```bash bash scripts/nginx-ssl-setup.sh ``` In **ArvanCloud dashboard**: SSL mode = **Full**, origin = `193.105.234.35`, purge cache. **SSL (direct DNS only):** If the domain does *not* use ArvanCloud, use certbot instead of the self-signed block: ```bash certbot --nginx -d biztaghavi.com -d www.biztaghavi.com ``` > Port **3009** must match the `ports` binding in `docker-compose.yml` — verify it's `"127.0.0.1:3009:3000"`. --- ## 6b. Gitea CI/CD Secrets In the Gitea repo → **Settings → Secrets → Actions**, add: | Secret name | Value | |-------------|-------| | `SERVER_HOST` | `193.105.234.35` | | `SERVER_USER` | `root` | | `SERVER_SSH_KEY` | Contents of private SSH key (ed25519 recommended) | Generating a deploy key: ```bash # On your Mac ssh-keygen -t ed25519 -C "gitea-deploy" -f ~/.ssh/biztaghavi_deploy ssh-copy-id -i ~/.ssh/biztaghavi_deploy.pub root@193.105.234.35 cat ~/.ssh/biztaghavi_deploy # paste this into SERVER_SSH_KEY secret ``` Every push to `main` runs: lint → typecheck → SSH deploy → health check. --- ## 7. Uploaded images volume Images uploaded via the admin panel land in `/app/public/uploads/` inside the container. The `uploads` Docker volume keeps them across redeployments. To back up uploads manually: ```bash docker cp biztaghavi-next-app-1:/app/public/uploads ./uploads-backup/ ``` --- ## 8. Redeployment (after code changes) ```bash cd /srv/nodecloud/apps/biztaghavisite git pull # Re-apply Iran Dockerfile is already correct — no extra steps needed docker compose build --no-cache docker compose up -d ``` > If Prisma schema changed, re-run the migration SQL step (section 4). --- ## 9. Troubleshooting | Problem | Fix | |---|---| | Build hangs / 429 from Liara mirror | Wait 15 min, retry. Or transfer `node_modules` from Mac. | | Prisma "engine not found" | Check `prisma-binaries/` has both files and is committed. | | Container starts but site 502 | `docker compose logs -f next-app` — likely DB connection timeout. | | Images not showing | Make sure `uploads` volume is mounted and `client_max_body_size 20M` is in nginx. | | Admin login fails | Double-check `SESSION_SECRET` is 32+ chars and consistent across restarts. | | DB won't start | MariaDB 11 healthcheck takes ~30s on first boot — wait and retry. | --- ## 10. Transferring `node_modules` from Mac (fallback if Liara mirror fails) ```bash # On Mac — install for Linux Alpine npm install \ --platform=linux --arch=x64 --libc=musl \ --ignore-scripts # Also install musl-specific native binaries npm install \ @next/swc-linux-x64-musl \ lightningcss-linux-x64-musl \ @tailwindcss/oxide-linux-x64-musl \ --platform=linux --arch=x64 --libc=musl # Tar it tar -czf node_modules.tar.gz node_modules/ # Upload to server scp node_modules.tar.gz root@193.105.234.35:/srv/nodecloud/apps/biztaghavisite/ # On server — extract and build without install tar -xzf node_modules.tar.gz docker compose build --no-cache # Dockerfile will skip pnpm install if node_modules exists ``` > You may need to modify the Dockerfile's `RUN pnpm install` step to skip if `node_modules/` already exists when using this approach.