Skip to content

Instantly share code, notes, and snippets.

@tfennelly
Last active June 29, 2026 07:36
Show Gist options
  • Select an option

  • Save tfennelly/588a5873cfa3cf57f045991ded11dc42 to your computer and use it in GitHub Desktop.

Select an option

Save tfennelly/588a5873cfa3cf57f045991ded11dc42 to your computer and use it in GitHub Desktop.
Unify Demo Installer
#!/usr/bin/env bash
#
# Unify Demo Installer
#
# Downloads and unpacks the Unify demo stack, then prints getting-started
# instructions. Requires Docker and a GitHub PAT with read:packages + repo scopes.
#
# Usage (one-liner):
# curl -fsSL https://gist.githubusercontent.com/tfennelly/588a5873cfa3cf57f045991ded11dc42/raw/installer.sh | bash
#
set -euo pipefail
ASSET_URL="https://api.github.com/repos/calculi-corp/unify-service/releases/assets/460885692"
ASSET="unify-demo-dist.tar.gz"
INSTALL_DIR="$PWD"
# ── Colour helpers ────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; AMBER='\033[0;33m'; NC='\033[0m'
MARK_SUCCESS='\xE2\x9C\x94'; MARK_FAIL='\xE2\x9D\x8C'
fail() { echo -e "${RED}${MARK_FAIL} $1${NC}" >&2; exit 1; }
success() { echo -e "${GREEN}${MARK_SUCCESS}${NC} $1"; }
amber() { echo -e "${AMBER}$1${NC}"; }
# ── Preflight checks ──────────────────────────────────────────────────────────
echo "==> Checking prerequisites ..."
if ! command -v docker &>/dev/null; then
fail "Docker is not installed. Install it from https://docs.docker.com/get-docker/ and try again."
fi
if ! docker compose version &>/dev/null; then
fail "Docker Compose v2 is not available. Update Docker Desktop or install the compose plugin."
fi
if ! docker info &>/dev/null 2>&1; then
fail "Docker daemon is not running. Start Docker and try again."
fi
success "Docker is ready."
# ── GitHub PAT ────────────────────────────────────────────────────────────────
echo ""
amber "A GitHub Personal Access Token is required to:"
amber " • Download the installer archive (repo scope)"
amber " • Pull Docker images from GHCR (read:packages scope)"
amber ""
amber "For now, you need to request this from Tom Fennelly"
echo ""
printf "Enter your GitHub PAT: " >/dev/tty
read -rs GITHUB_TOKEN </dev/tty
echo >/dev/tty
# Strip any stray carriage returns that can sneak in when piping
GITHUB_TOKEN="${GITHUB_TOKEN//$'\r'/}"
if [[ -z "$GITHUB_TOKEN" ]]; then
fail "No token provided."
fi
# ── Check access to calculi-corp org ─────────────────────────────────────────
HTTP_STATUS=$(curl -sL -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
"https://api.github.com/repos/calculi-corp/unify-service")
if [[ "$HTTP_STATUS" == "403" ]]; then
fail "Access denied (403) to the calculi-corp GitHub org. Ensure you are connected to the CloudBees VPN and try again."
elif [[ "$HTTP_STATUS" == "401" ]]; then
fail "Invalid token (401). Check your GitHub PAT is correct and has 'repo' scope."
elif [[ "$HTTP_STATUS" != "200" ]]; then
fail "Could not access calculi-corp/unify-service (HTTP $HTTP_STATUS). Check your token and VPN connection."
fi
success "GitHub org access verified."
# ── Check for existing install ───────────────────────────────────────────────
if [[ -n "$(ls -A "$INSTALL_DIR" 2>/dev/null)" ]]; then
fail "Directory $INSTALL_DIR is not empty. The installer must be run from an empty directory."
fi
# ── Download release asset ────────────────────────────────────────────────────
echo ""
echo "==> Downloading installer package ..."
curl -fL \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/octet-stream" \
-o "$ASSET" \
"$ASSET_URL" \
|| fail "Download failed. Ensure you are connected to the CloudBees VPN and the token you are using has 'repo' scope permissions for calculi-corp/unify-service."
file "$ASSET" | grep -q 'gzip' || fail "Downloaded file is not a gzip archive — the token may be invalid or lack 'repo' scope."
success "Downloaded installer package."
# ── Extract ───────────────────────────────────────────────────────────────────
echo "==> Extracting into $INSTALL_DIR ..."
tar -xzf "$ASSET" -C "$INSTALL_DIR"
rm -f "$ASSET"
success "Extracted to $INSTALL_DIR."
# ── Save token into .env so start.sh skips the GHCR prompt ───────────────────
echo "GHCR_TOKEN=$GITHUB_TOKEN" > "$INSTALL_DIR/.env"
# ── Done ─────────────────────────────────────────────────────────────────────
cat <<'EOF'
____ _ _ ____
/ ___|| | ___ _ _ __| | __ ) ___ ___ ___
| | | |/ _ \| | | |/ _` | _ \ / _ \/ _ \/ __|
| |___ | | (_) | |_| | (_| | |_) | __/ __/\__ \
\____||_|\___/ \__,_|\__,_|____/ \___|\___||___/
Welcome to CloudBees Unify
EOF
echo "CloudBees Unify has been installed to: $INSTALL_DIR"
echo ""
echo "NOTE: On first run you will be prompted for a domain name. This is the hostname"
echo "your browser will use to reach Unify. Press Enter to use the default"
echo "(your machine's hostname: $(hostname)), or type a custom hostname."
echo ""
echo "If the hostname doesn't resolve, start.sh will offer to add it to /etc/hosts."
echo ""
echo "To start Unify, run the following command and wait for further instructions:"
echo ""
echo " ./start.sh"
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment