diff --git a/kez-chat/deploy/deploy.sh b/kez-chat/deploy/deploy.sh new file mode 100755 index 0000000..e1ada24 --- /dev/null +++ b/kez-chat/deploy/deploy.sh @@ -0,0 +1,115 @@ +#!/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 diff --git a/kez-chat/deploy/install-docker.sh b/kez-chat/deploy/install-docker.sh new file mode 100755 index 0000000..c2cc182 --- /dev/null +++ b/kez-chat/deploy/install-docker.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# Run this ONCE on a fresh Ubuntu host to install Docker + Compose v2 and +# add the current user to the `docker` group so subsequent commands don't +# need sudo. +# +# Requires sudo. Idempotent — safe to re-run. +# +# Usage: +# ssh tudisco@host 'bash -s' < install-docker.sh +# or: +# scp install-docker.sh tudisco@host:~/ +# ssh tudisco@host 'bash ~/install-docker.sh' + +set -euo pipefail + +echo "==> Updating apt" +sudo apt-get update -y + +echo "==> Installing prerequisites" +sudo apt-get install -y --no-install-recommends \ + ca-certificates curl gnupg + +echo "==> Adding Docker's official GPG key" +sudo install -m 0755 -d /etc/apt/keyrings +if [[ ! -f /etc/apt/keyrings/docker.gpg ]]; then + curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ + | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg + sudo chmod a+r /etc/apt/keyrings/docker.gpg +fi + +echo "==> Adding Docker apt repo" +. /etc/os-release +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ +https://download.docker.com/linux/ubuntu ${VERSION_CODENAME} stable" \ + | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + +echo "==> Installing Docker Engine + Compose plugin" +sudo apt-get update -y +sudo apt-get install -y \ + docker-ce docker-ce-cli containerd.io \ + docker-buildx-plugin docker-compose-plugin + +echo "==> Adding $USER to docker group" +sudo usermod -aG docker "$USER" + +echo "==> Enabling + starting Docker" +sudo systemctl enable --now docker + +echo +echo "==> Versions:" +docker --version +docker compose version + +echo +echo "✓ Docker installed." +echo " IMPORTANT: log out and back in (or run 'newgrp docker') for the" +echo " group change to take effect; otherwise 'docker' commands need sudo."