#!/usr/bin/env bash # deploy-to-nas.sh — Mac → NAS cross-build deploy in één commando. # # Voert in volgorde uit: # 1. docker buildx build (linux/amd64, --load) # 2. docker save | gzip → scrum4me-agent-runner-amd64.tar.gz # 3. scp tarball + docker-compose.yml + (eerste keer) .env naar NAS # 4. ssh: docker load + sed-patch .env paths (eerste keer) + compose up --force-recreate # 5. ssh: docker compose logs -f voor verificatie # # Gebruik: # bin/deploy-to-nas.sh # gebruikt env vars uit .env.deploy # NAS_HOST=admin@nas bin/deploy-to-nas.sh # # Vereisten: # - docker buildx geïnstalleerd # - .env aanwezig in repo-root (deze wordt naar NAS gestuurd op eerste run) # - .env.deploy met NAS_HOST + NAS_REMOTE_DIR (optioneel — anders prompted) # - SSH-key access naar de NAS (geen password-prompts) set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$REPO_ROOT" # ----- config ----------------------------------------------------------- if [[ -f .env.deploy ]]; then # shellcheck disable=SC1091 source .env.deploy fi : "${NAS_HOST:?NAS_HOST not set — bv. admin@nas.local. Zet 'm in .env.deploy of als env-var.}" : "${NAS_REMOTE_DIR:=/share/Agent/scrum4me-agent-runner}" : "${IMAGE_TAG:=scrum4me-agent-runner:local}" : "${TARBALL:=scrum4me-agent-runner-amd64.tar.gz}" : "${MCP_GIT_REF:=main}" : "${CLAUDE_CODE_VERSION:=latest}" : "${AGENT_UID:=1000}" : "${AGENT_GID:=1000}" log() { echo "[deploy-to-nas] $*"; } # ----- pre-flight ------------------------------------------------------- if [[ ! -f .env ]]; then log "FAIL: .env ontbreekt in repo-root. Maak 'm aan via: cp .env.example .env" exit 1 fi # ----- 1. buildx -------------------------------------------------------- log "1/5 docker buildx build (linux/amd64, MCP_GIT_REF=$MCP_GIT_REF)" docker buildx build \ --platform linux/amd64 \ --build-arg "MCP_GIT_REF=${MCP_GIT_REF}" \ --build-arg "CLAUDE_CODE_VERSION=${CLAUDE_CODE_VERSION}" \ --build-arg "AGENT_UID=${AGENT_UID}" \ --build-arg "AGENT_GID=${AGENT_GID}" \ -t "$IMAGE_TAG" \ --load \ . # ----- 2. tarball ------------------------------------------------------- log "2/5 docker save | gzip → $TARBALL" docker save "$IMAGE_TAG" | gzip > "$TARBALL" ls -lh "$TARBALL" # ----- 3. scp ----------------------------------------------------------- log "3/5 scp tarball + compose naar $NAS_HOST:$NAS_REMOTE_DIR" ssh "$NAS_HOST" "mkdir -p '$NAS_REMOTE_DIR'" # Check of er al een .env op de NAS staat. Zo niet: stuur de Mac-versie en # patch hem. Zo wel: laat 'm met rust (kan NAS-specifiek aangepast zijn). if ssh "$NAS_HOST" "test -f '$NAS_REMOTE_DIR/.env'" 2>/dev/null; then log " (.env bestaat al op NAS — niet overschreven)" else log " geen .env op NAS, kopiëren + patchen" scp .env "$NAS_HOST:$NAS_REMOTE_DIR/.env" ssh "$NAS_HOST" " cd '$NAS_REMOTE_DIR' chmod 600 .env sed -i \\ -e 's|^NAS_BASE=.*|NAS_BASE=/share/Agent|' \\ -e 's|^AGENT_BASE=.*|AGENT_BASE=/share/Agent|' \\ -e 's|^AGENT_PLATFORM=.*|AGENT_PLATFORM=linux/amd64|' \\ -e 's|^AGENT_UID=.*|AGENT_UID=${AGENT_UID}|' \\ -e 's|^AGENT_GID=.*|AGENT_GID=${AGENT_GID}|' \\ -e 's|^AGENT_HEALTH_PORT_HOST=.*|AGENT_HEALTH_PORT_HOST=18080|' \\ .env " fi scp "$TARBALL" docker-compose.yml package.json README.md \ "$NAS_HOST:$NAS_REMOTE_DIR/" # ----- 4. load + restart ------------------------------------------------ log "4/5 docker load + compose up --force-recreate op NAS" ssh "$NAS_HOST" " set -eu source /etc/profile cd '$NAS_REMOTE_DIR' # Sanity: env-vars die check-tokens.sh nodig heeft grep -qE '^(CLAUDE_CODE_OAUTH_TOKEN|ANTHROPIC_API_KEY)=' .env || { echo 'FAIL: anthropic credential ontbreekt in .env'; exit 1; } grep -qE '^SCRUM4ME_TOKEN=' .env || { echo 'FAIL: SCRUM4ME_TOKEN ontbreekt in .env'; exit 1; } grep -qE '^DATABASE_URL=' .env || { echo 'FAIL: DATABASE_URL ontbreekt in .env'; exit 1; } gunzip -c '$TARBALL' | docker load docker compose up -d --force-recreate " # ----- 5. tail logs ------------------------------------------------------ log "5/5 docker compose logs (Ctrl-C om te stoppen)" ssh "$NAS_HOST" "cd '$NAS_REMOTE_DIR' && docker compose logs -f --tail=50"