Add Iran offline deploy: Mac bundle + prebuilt Docker image.

Fix pnpm workspace error during prisma generate, and add bundle-for-iran.sh
so the app is built on Mac (full internet) and the server only copies artifacts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ali Taghavi
2026-05-19 01:08:17 +03:30
parent a352d4e823
commit b7fdae8967
10 changed files with 374 additions and 24 deletions

64
scripts/bundle-for-iran.sh Executable file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# Run on your Mac (unrestricted internet). Produces iran-bundle.tar.gz for the Iran server.
# The server never talks to npmjs / Prisma CDN during docker build.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
BUNDLE_DIR="$ROOT/iran-bundle"
ARCHIVE="$ROOT/iran-bundle.tar.gz"
if ! command -v docker >/dev/null 2>&1; then
echo "ERROR: Docker is required."
exit 1
fi
if [[ ! -f prisma-binaries/libquery_engine-debian-openssl-3.0.x.so.node ]]; then
echo "ERROR: prisma-binaries/ missing. Run: bash scripts/fetch-prisma-binaries.sh"
exit 1
fi
echo "==> Building linux/amd64 app inside Docker (this uses your Mac's internet)..."
rm -rf "$BUNDLE_DIR" "$ARCHIVE"
docker run --rm --platform linux/amd64 \
-v "$ROOT:/app" -w /app \
-e PRISMA_QUERY_ENGINE_LIBRARY=/app/prisma-binaries/libquery_engine-debian-openssl-3.0.x.so.node \
-e PRISMA_SCHEMA_ENGINE_BINARY=/app/prisma-binaries/schema-engine-debian-openssl-3.0.x \
-e PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING=1 \
-e PRISMA_SKIP_POSTINSTALL_GENERATE=1 \
-e NEXT_TELEMETRY_DISABLED=1 \
-e NEXT_SWC_DOWNLOAD_DISABLED=1 \
-e DATABASE_URL="mysql://build:build@127.0.0.1:3306/build" \
node:20-slim bash -c '
set -euo pipefail
apt-get update -qq
apt-get install -y -qq openssl ca-certificates >/dev/null
corepack enable
corepack prepare pnpm@9 --activate
rm -rf node_modules .next iran-bundle
pnpm install --frozen-lockfile
pnpm exec prisma generate
pnpm run build
mkdir -p iran-bundle/standalone iran-bundle/node_modules
cp -a .next/standalone/. iran-bundle/standalone/
cp -a .next/static iran-bundle/static
cp -a public iran-bundle/public
cp -a prisma-binaries iran-bundle/prisma-binaries
cp -a node_modules/.prisma iran-bundle/node_modules/.prisma
cp -a node_modules/@prisma iran-bundle/node_modules/@prisma
'
echo "==> Packing archive..."
tar -czf "$ARCHIVE" -C "$ROOT" iran-bundle
SIZE="$(du -h "$ARCHIVE" | awk '{print $1}')"
echo ""
echo "Created: $ARCHIVE ($SIZE)"
echo ""
echo "Upload to server:"
echo " scp \"$ARCHIVE\" root@193.105.234.35:/srv/nodecloud/apps/biztaghavisite/"
echo ""
echo "On server:"
echo " cd /srv/nodecloud/apps/biztaghavisite"
echo " git pull origin main"
echo " bash scripts/server-deploy.sh"

View File

@@ -3,6 +3,8 @@
set -euo pipefail
APP_DIR="/srv/nodecloud/apps/biztaghavisite"
PORT=3009
COMPOSE_FILE="docker-compose.yml"
DOCKERFILE_NOTE="online build (Liara npm mirror)"
cd "$APP_DIR"
@@ -17,39 +19,62 @@ if [[ ! -f .env ]]; then
exit 1
fi
echo "==> Build image (1020 min on first run; Liara mirror may be slow)"
docker compose build --no-cache
# Offline bundle from Mac (recommended for Iran)
if [[ -f iran-bundle.tar.gz ]]; then
COMPOSE_FILE="docker-compose.prebuilt.yml"
DOCKERFILE_NOTE="prebuilt bundle (no npm on server)"
echo "==> Extract iran-bundle.tar.gz"
rm -rf iran-bundle
mkdir -p iran-bundle
tar -xzf iran-bundle.tar.gz -C .
if [[ ! -f iran-bundle/standalone/server.js ]]; then
echo "ERROR: iran-bundle/standalone/server.js missing — re-run bundle-for-iran.sh on Mac"
exit 1
fi
else
echo "WARN: iran-bundle.tar.gz not found — building on server (needs Liara mirror)."
echo " Recommended: run scripts/bundle-for-iran.sh on Mac and scp iran-bundle.tar.gz here."
fi
echo "==> Build image ($DOCKERFILE_NOTE)"
docker compose -f "$COMPOSE_FILE" build --no-cache
echo "==> Start MariaDB + app"
docker compose up -d
docker compose -f "$COMPOSE_FILE" up -d
echo "==> Wait for MariaDB"
for i in $(seq 1 30); do
if docker compose exec -T db healthcheck.sh --connect --innodb_initialized >/dev/null 2>&1; then
for _ in $(seq 1 30); do
if docker compose -f "$COMPOSE_FILE" exec -T db healthcheck.sh --connect --innodb_initialized >/dev/null 2>&1; then
echo " MariaDB healthy"
break
fi
sleep 2
done
echo "==> Apply database schema (idempotent)"
set -a
# shellcheck disable=SC1091
source .env
set +a
docker compose exec -T db mariadb -u "${DB_USER:-biztaghavi}" -p"${DB_PASSWORD}" "${DB_NAME:-biztaghavi}" \
< prisma/migrations/0_init/migration.sql || true
if [[ -f prisma/migrations/0_init/migration.sql ]] && [[ -s prisma/migrations/0_init/migration.sql ]]; then
echo "==> Apply database schema"
set -a
# shellcheck disable=SC1091
source .env
set +a
docker compose -f "$COMPOSE_FILE" exec -T db mariadb \
-u "${DB_USER:-biztaghavi}" -p"${DB_PASSWORD}" "${DB_NAME:-biztaghavi}" \
< prisma/migrations/0_init/migration.sql || true
else
echo "WARN: prisma/migrations/0_init/migration.sql missing or empty — skip SQL apply"
fi
echo "==> Health check"
sleep 3
curl -sf "http://127.0.0.1:${PORT}/" -o /dev/null && echo "OK: app responds on :${PORT}" || {
if curl -sf "http://127.0.0.1:${PORT}/" -o /dev/null; then
echo "OK: app responds on :${PORT}"
else
echo "FAIL: app not responding"
docker compose logs --tail=80 next-app
docker compose -f "$COMPOSE_FILE" logs --tail=80 next-app
exit 1
}
fi
curl -sI -H "Host: biztaghavi.com" "http://127.0.0.1/" | head -5
docker compose ps
docker compose -f "$COMPOSE_FILE" ps
echo ""
echo "Done. Test https://biztaghavi.com purge ArvanCloud cache if needed."
echo "Create admin once: curl -X POST https://biztaghavi.com/api/admin/setup ..."
echo "Done. Test https://biztaghavi.com (purge ArvanCloud cache if needed)."