#!/usr/bin/env bash # Run on the Linux production host (CI SSHs here after pushing :v* images). # Usage: ./prod-remote-deploy.sh v1.0.1 set -euo pipefail TAG="${1:?usage: prod-remote-deploy.sh v1.0.1}" INFRA="${PROD_INFRA_DIR:-/opt/dyolink/infrastructure}" cd "$INFRA" if [ ! -f .env ]; then echo "Missing $INFRA/.env — copy deploy.prod.env.example and set DOMAIN=nudentic.ir REGISTRY_PREFIX=wixur.ir:3000/" exit 1 fi if ! grep -q '^REGISTRY_PREFIX=.\+' .env; then echo "Set REGISTRY_PREFIX in .env (Gitea registry, e.g. wixur.ir:3000/admin). Do not use Docker Hub :latest for tag deploys." exit 1 fi export TAG # Windows Gitea often RSTs concurrent or long pulls (connection reset by peer). # Pull one image at a time with backoff so a flake does not fail the whole tag. pull_one() { local service="$1" local attempt=1 local max=5 local delay=8 while [ "$attempt" -le "$max" ]; do echo "Pulling $service :$TAG (attempt $attempt/$max)" if docker compose -f docker-compose.prod.yml --env-file .env pull "$service"; then return 0 fi if [ "$attempt" -eq "$max" ]; then echo "Failed to pull $service after $max attempts" return 1 fi echo "Pull of $service failed; retrying in ${delay}s..." sleep "$delay" delay=$((delay * 2)) attempt=$((attempt + 1)) done } echo "Pulling backend/frontend :$TAG from Gitea (REGISTRY_PREFIX in .env)" pull_one backend pull_one frontend docker compose -f docker-compose.prod.yml --env-file .env up -d echo "=== Status ===" docker compose -f docker-compose.prod.yml --env-file .env ps echo "Health: https://nudentic.ir/api/health"