#!/bin/bash # ── IPFS Portal Deploy Script ── # Usage: ./deploy.sh [remote_host] [remote_port] # remote_host: SSH target (default: maik@192.168.1.176) # remote_port: SSH port (default: 22) # # Builds Docker image locally, pushes to Docker Hub or saves as tar, # then deploys to remote server via SSH. # # Prerequisites: # - Docker installed locally and on remote # - SSH key-based auth to remote # - .env.production on remote or pass via env vars # # Server requirements: # - Docker + docker compose plugin # - Port 3444 available # - nginx reverse proxy (optional, for TLS) set -euo pipefail REMOTE_HOST="${1:-maik@192.168.1.176}" REMOTE_PORT="${2:-22}" IMAGE_NAME="maos/ipfs-portal" TAG="$(date +%Y%m%d-%H%M%S)" REMOTE_DIR="/opt/ipfs-portal" echo "═══ IPFS Portal Deploy ═══" echo " Target: ${REMOTE_HOST}" echo " Image: ${IMAGE_NAME}:${TAG}" echo "" # ── Step 1: Build Docker image ── echo "▸ Building Docker image..." docker build \ --build-arg NEXT_PUBLIC_APP_URL="https://maos.dedyn.io" \ -t "${IMAGE_NAME}:${TAG}" \ -t "${IMAGE_NAME}:latest" \ -f Dockerfile \ . echo " ✓ Image built: ${IMAGE_NAME}:${TAG}" echo "" # ── Step 2: Save + compress image ── echo "▸ Saving image..." docker save "${IMAGE_NAME}:${TAG}" | gzip > /tmp/ipfs-portal.tar.gz echo " ✓ Saved to /tmp/ipfs-portal.tar.gz ($(du -h /tmp/ipfs-portal.tar.gz | cut -f1))" echo "" # ── Step 3: Copy to remote ── echo "▸ Copying to ${REMOTE_HOST}:${REMOTE_DIR}/..." ssh -p "${REMOTE_PORT}" "${REMOTE_HOST}" "mkdir -p ${REMOTE_DIR}" scp -P "${REMOTE_PORT}" /tmp/ipfs-portal.tar.gz "${REMOTE_HOST}:${REMOTE_DIR}/image.tar.gz" rm /tmp/ipfs-portal.tar.gz echo " ✓ Image copied" echo "" # ── Step 4: Deploy on remote ── echo "▸ Deploying on remote..." ssh -p "${REMOTE_PORT}" "${REMOTE_HOST}" << REMOTESHELL set -euo pipefail cd ${REMOTE_DIR} # Load new image docker image rm -f ${IMAGE_NAME}:latest 2>/dev/null || true gunzip -c image.tar.gz | docker load rm image.tar.gz # Create docker-compose.yml if not exists if [ ! -f docker-compose.yml ]; then cat > docker-compose.yml << 'COMPOSE' services: ipfs-portal: image: maos/ipfs-portal:latest container_name: ipfs-portal restart: unless-stopped ports: - "3445:3445" environment: - NODE_ENV=production - PORT=3445 - NEXT_TELEMETRY_DISABLED=1 - USER_API_BASE=http://192.168.1.176:8444 - USER_API_ADMIN_KEY=maos-admin-2024 - KUBO_API_URL=http://192.168.1.176:8443 - KUBO_BASIC_AUTH=portal:ipfs-portal-2024 healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3445/api/health"] interval: 30s timeout: 10s retries: 3 COMPOSE fi # Restart container docker compose up -d --force-recreate # Verify sleep 3 if docker ps --filter "name=ipfs-portal" --format "{{.Status}}" | grep -q "Up"; then echo " ✓ Container is running" curl -s http://localhost:3445/api/health echo "" else echo " ✗ Container failed to start" docker logs ipfs-portal --tail 30 exit 1 fi REMOTESHELL echo "" echo "═══ Deploy complete ═══" echo " URL: https://maos.dedyn.io (via nginx) or http://192.168.1.176:3445"