#!/usr/bin/env bash # Deploy kez-chat to a remote Linux host via rsync + ssh. # # Usage: # ./deploy.sh [-h host] [-p path] [-s server-domain] # # Defaults match what we agreed in the design doc: # host = tudisco@10.5.2.5 # path = /home/tudisco/kez-chat # server-domain= kez.lat (the KEZ_CHAT_SERVER env var the chat-server uses) # # What it does: # 1. Rsync the three directories the build needs (rust/, kez-chat/, # rust-sig-server/) to on the target. # 2. SSH in and run `docker compose up -d --build` from # /kez-chat/deploy/. # 3. Hit /v1/healthz to confirm the chat-server came up. # # This script does NOT install Docker or configure the firewall. Run # install-docker.sh once on a fresh host first if needed. set -euo pipefail HOST="${HOST:-tudisco@10.5.2.5}" REMOTE_PATH="${REMOTE_PATH:-/home/tudisco/kez-chat}" KEZ_CHAT_SERVER="${KEZ_CHAT_SERVER:-kez.lat}" while [[ $# -gt 0 ]]; do case "$1" in -h|--host) HOST="$2"; shift 2;; -p|--path) REMOTE_PATH="$2"; shift 2;; -s|--server) KEZ_CHAT_SERVER="$2"; shift 2;; *) echo "Unknown flag: $1" >&2; exit 1;; esac done REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" cd "$REPO_ROOT" echo "==> Repo root: $REPO_ROOT" echo "==> Target: $HOST" echo "==> Remote path: $REMOTE_PATH" echo "==> Server domain: $KEZ_CHAT_SERVER" echo # 1. Make sure the remote dir exists. echo "==> Ensuring remote directory exists" ssh "$HOST" "mkdir -p '$REMOTE_PATH'" # 2. Rsync the three subdirs the build needs. echo "==> Syncing rust/, kez-chat/, rust-sig-server/" rsync -avz --delete \ --exclude target/ \ --exclude node_modules/ \ --exclude '*.db' --exclude '*.db-*' \ --exclude .DS_Store \ rust/ kez-chat/ rust-sig-server/ \ "$HOST:$REMOTE_PATH/" \ --files-from=<( find rust kez-chat rust-sig-server -type f \ -not -path '*/target/*' \ -not -path '*/node_modules/*' \ -not -name '*.db' -not -name '*.db-*' \ -not -name '.DS_Store' ) 2>/dev/null || { # Fallback: simpler rsync without --files-from if find pipe is awkward rsync -avz --delete \ --exclude target/ \ --exclude node_modules/ \ --exclude '*.db' --exclude '*.db-*' \ --exclude .DS_Store \ "$REPO_ROOT/rust/" "$HOST:$REMOTE_PATH/rust/" rsync -avz --delete \ --exclude target/ \ --exclude node_modules/ \ --exclude '*.db' --exclude '*.db-*' \ --exclude .DS_Store \ "$REPO_ROOT/kez-chat/" "$HOST:$REMOTE_PATH/kez-chat/" rsync -avz --delete \ --exclude target/ \ --exclude node_modules/ \ --exclude '*.db' --exclude '*.db-*' \ --exclude .DS_Store \ "$REPO_ROOT/rust-sig-server/" "$HOST:$REMOTE_PATH/rust-sig-server/" } # 3. Build and start the stack. echo "==> Building + starting docker compose stack on remote" ssh "$HOST" bash < Containers:" docker compose ps EOF # 4. Healthcheck via the chat-server's own port. echo "==> Waiting for chat-server to come up…" for i in {1..15}; do if ssh "$HOST" 'curl -fsS http://127.0.0.1:6969/v1/healthz' > /dev/null 2>&1; then echo echo "==> chat-server healthcheck:" ssh "$HOST" 'curl -s http://127.0.0.1:6969/v1/healthz' echo echo "✓ Deployed." exit 0 fi sleep 2 done echo "✗ chat-server did not become healthy within 30s" >&2 ssh "$HOST" "cd '$REMOTE_PATH/kez-chat/deploy' && docker compose logs --tail=50 chat-server" >&2 exit 1