Files
biztaghavisite/DEPLOY.md
2026-05-19 15:35:04 +03:30

7.1 KiB

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:

# 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@<version> 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

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)

DATABASE_URL=mysql://biztaghavi:STRONG_PASSWORD@db:3306/biztaghavi
SESSION_SECRET=<64-char random hex — run: openssl rand -hex 32>
SETUP_KEY=<secret used once to create admin user>
RESEND_API_KEY=<from resend.com — optional>
CONTACT_EMAIL=ali@biztaghavi.com
NEXT_PUBLIC_SITE_URL=https://biztaghavi.com

# Docker DB credentials (must match DATABASE_URL above)
DB_ROOT_PASSWORD=<strong root password>
DB_NAME=biztaghavi
DB_USER=biztaghavi
DB_PASSWORD=<same as DATABASE_URL password>

3. Build & launch

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).

# 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):

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:

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:

# 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.

# 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 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:

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:

# 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:

docker cp biztaghavi-next-app-1:/app/public/uploads ./uploads-backup/

8. Redeployment (after code changes)

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)

# 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.