AkurAI Build
Menu

Public repository / b4fe8663e5af6be441dafce506787af75d7ec4f1

AkurAI-Mail / deploy.sh

Latest change 649b86b3a6fb87df3c82b4df0a648ffe81b6a053 - Rewrite deploy.sh for local-build + scp to AWS VM by Ólafur Búi Ólafsson

#!/usr/bin/env bash
set -euo pipefail

# ---------------------------------------------------------------------------
# AkurAI Mail UI — build locally, deploy artifacts to AWS VM
# ---------------------------------------------------------------------------

APP_NAME="akurai-mail-ui"
SSH_HOST="${AKURAI_MAIL_SSH:-akurai-mail}"
DEPLOY_DIR="/opt/${APP_NAME}"
SERVICE="${APP_NAME}"

VERSION="$(cat VERSION | tr -d '\n')"
RELEASE_ID="$(date -u +%Y%m%dT%H%M%SZ)-$(git rev-parse --short HEAD 2>/dev/null || echo nogit)"
STAGING_DIR="${PWD}/.deploy-staging/${RELEASE_ID}"

log()  { echo "[deploy] $*"; }
step() { echo; echo "── $* ──"; }

remote() { ssh "${SSH_HOST}" "$@"; }

# ---------------------------------------------------------------------------
# Parse
# ---------------------------------------------------------------------------
COMMAND="${1:-prod}"
case "${COMMAND}" in
  status)
    git status --short --branch
    remote "sudo systemctl status ${SERVICE} --no-pager" || true
    exit 0
    ;;
  --help|-h|help)
    echo "Usage: deploy.sh [prod|status|help]"
    exit 0
    ;;
esac

# ---------------------------------------------------------------------------
# Step 1: Install + build locally
# ---------------------------------------------------------------------------
step "1/5  Local build"
bun install --frozen-lockfile 2>&1 || bun install
bun run build
log "Build complete"

# ---------------------------------------------------------------------------
# Step 2: Package artifacts
# ---------------------------------------------------------------------------
step "2/5  Package"
mkdir -p "${STAGING_DIR}"
TARBALL="${STAGING_DIR}/${APP_NAME}-${RELEASE_ID}.tar.gz"
tar czf "${TARBALL}" \
  build/ \
  package.json \
  bun.lock \
  scripts/ \
  backup.sh \
  rollback.sh \
  VERSION \
  CHANGELOG.md
log "Tarball: $(du -sh "${TARBALL}" | cut -f1)"

# ---------------------------------------------------------------------------
# Step 3: Upload
# ---------------------------------------------------------------------------
step "3/5  Upload to ${SSH_HOST}"
remote "mkdir -p /tmp/akurai-mail-deploy"
scp -q "${TARBALL}" "${SSH_HOST}:/tmp/akurai-mail-deploy/"

# ---------------------------------------------------------------------------
# Step 4: Remote install
# ---------------------------------------------------------------------------
step "4/5  Remote install"
ARCHIVE_BASENAME="$(basename "${TARBALL}")"
remote "sudo bash -s" <<INSTALL
set -euo pipefail

# Backup current
if [ -d ${DEPLOY_DIR}/build ]; then
  BACKUP_DIR="/opt/${APP_NAME}-backups/${RELEASE_ID}"
  mkdir -p "\${BACKUP_DIR}"
  tar czf "\${BACKUP_DIR}/app.tar.gz" -C ${DEPLOY_DIR} build/ package.json VERSION 2>/dev/null || true
  echo "  [backup] \${BACKUP_DIR}"
fi

# Extract new release (overwrite build/ and support files)
tar xzf /tmp/akurai-mail-deploy/${ARCHIVE_BASENAME} -C ${DEPLOY_DIR}

# Install production runtime deps
cd ${DEPLOY_DIR}
/home/ubuntu/.bun/bin/bun install --frozen-lockfile --production 2>/dev/null || /home/ubuntu/.bun/bin/bun install --production

# Install helper scripts
install -m 755 scripts/akurai-mail-server /usr/local/sbin/akurai-mail-server
install -m 755 backup.sh /usr/local/sbin/akurai-mail-backup
install -m 755 rollback.sh /usr/local/sbin/akurai-mail-rollback

# Ensure state file
install -d -o ubuntu -g ubuntu /var/lib/akurai-mail
if [ ! -s /var/lib/akurai-mail/state.json ]; then
  printf '{"domain":"olibuijr.com","hostname":"mail.olibuijr.com","publicIp":"3.94.46.219","users":[],"aliases":[],"events":[],"metricsHistory":[]}\n' > /var/lib/akurai-mail/state.json
fi
chown ubuntu:ubuntu /var/lib/akurai-mail/state.json

# Restart
systemctl daemon-reload
systemctl restart ${SERVICE}

# Cleanup
rm -rf /tmp/akurai-mail-deploy

# Prune old backups (keep 10)
ls -dt /opt/${APP_NAME}-backups/*/ 2>/dev/null | tail -n +11 | xargs -r rm -rf

echo "  [done] ${APP_NAME} ${VERSION} installed"
INSTALL

# ---------------------------------------------------------------------------
# Step 5: Healthcheck
# ---------------------------------------------------------------------------
step "5/5  Healthcheck"
sleep 2

if remote "curl -fsS -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/login" | grep -q 200; then
  log "Healthcheck passed"
else
  echo "ERROR: healthcheck failed"
  echo "Check: ssh ${SSH_HOST} 'sudo journalctl -u ${SERVICE} -n 50'"
  exit 1
fi

rm -rf "${STAGING_DIR}"

echo
echo "════════════════════════════════════════════════════"
echo "  AkurAI Mail UI deployed"
echo "════════════════════════════════════════════════════"
echo "  Version  : ${VERSION}"
echo "  Release  : ${RELEASE_ID}"
echo "  Host     : ${SSH_HOST}"
echo "  Public   : https://mail.olibuijr.com"
echo "════════════════════════════════════════════════════"