#!/usr/bin/env bash set -euo pipefail # Deploy Umami to the hetzner host via a remote Docker context. # Same convention as humanai-web: build/run remotely, attach to NPM's network. CONTEXT="hetzner" REMOTE="ssh://oskar@135.181.153.108" NETWORK="npm_default" cd "$(dirname "$0")" if [[ ! -f .env ]]; then echo "ERROR: .env missing. Copy .env.example to .env and fill in secrets." >&2 exit 1 fi # Create docker context if missing docker context inspect "$CONTEXT" &>/dev/null || \ docker context create "$CONTEXT" --docker "host=$REMOTE" D="docker --context $CONTEXT" # The external NPM network must exist on the remote host. if ! $D network inspect "$NETWORK" &>/dev/null; then echo "ERROR: docker network '$NETWORK' not found on $CONTEXT." >&2 echo " Start Nginx Proxy Manager first (it owns that network)." >&2 exit 1 fi echo "==> Pulling images and starting Umami on $CONTEXT" $D compose --env-file .env up -d --pull always --remove-orphans echo "==> Waiting for umami to become healthy..." for i in $(seq 1 30); do STATUS=$($D inspect -f '{{.State.Health.Status}}' umami 2>/dev/null || echo "starting") if [[ "$STATUS" == "healthy" ]]; then echo " OK: umami is healthy" break fi if [[ "$i" == "30" ]]; then echo "FAIL: umami did not become healthy in time" >&2 $D logs --tail 50 umami >&2 || true exit 1 fi sleep 5 done echo "==> Smoke test: /api/heartbeat must return 200" CODE=$($D exec umami curl -s -o /dev/null -w '%{http_code}' http://localhost:3000/api/heartbeat) if [[ "$CODE" != "200" ]]; then echo "FAIL: heartbeat returned $CODE" >&2 exit 1 fi echo " OK: heartbeat 200" echo "" echo "Deploy complete." echo "Next steps (manual):" echo " 1. In NPM: add Proxy Host stats.gethumanai.pl -> http://umami:3000 (scheme http)" echo " enable WebSockets + Force SSL (Let's Encrypt)." echo " 2. Open https://stats.gethumanai.pl and log in (default admin / umami)." echo " 3. CHANGE the default admin password immediately."