#!/usr/bin/env bash # install.sh — install Busbar Designer on Debian / Ubuntu. # # Runs inside an LXC, VM, or bare-metal host. Idempotent (safe to re-run). # # Required env: # REPO_URL Git URL of the busbar-designer repo # (e.g. https://gitea.local/me/busbar-designer.git) # # Optional env: # BRANCH git branch to track (default: main) # INSTALL_DIR install location (default: /opt/busbar-designer) # SVC_USER systemd service user (default: busbar) # PORT HTTP port (default: 5000) # GIT_SSL_NO_VERIFY=1 skip TLS verify for self-signed Gitea certs set -euo pipefail REPO_URL="${REPO_URL:-}" BRANCH="${BRANCH:-main}" INSTALL_DIR="${INSTALL_DIR:-/opt/busbar-designer}" SVC_USER="${SVC_USER:-busbar}" PORT="${PORT:-5000}" # ---- helpers --------------------------------------------------------------- GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m' log() { echo -e "${GREEN}▸${NC} $*"; } warn() { echo -e "${YELLOW}!${NC} $*"; } die() { echo -e "${RED}✗ $*${NC}" >&2; exit 1; } [[ $EUID -eq 0 ]] || die "Run as root (or via sudo)." [[ -n "$REPO_URL" ]] || die "REPO_URL is required (export REPO_URL=https://gitea.local/me/busbar-designer.git)" if [[ "${GIT_SSL_NO_VERIFY:-0}" == "1" ]]; then warn "GIT_SSL_NO_VERIFY=1 — skipping TLS verification for git." export GIT_SSL_NO_VERIFY=true fi # ---- system packages ------------------------------------------------------- log "Installing system packages..." export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq \ git ca-certificates curl \ python3 python3-venv python3-pip \ libgl1 libglu1-mesa libxrender1 libxext6 libsm6 libgomp1 # ---- service user ---------------------------------------------------------- if ! id "$SVC_USER" >/dev/null 2>&1; then log "Creating service user '$SVC_USER'..." useradd --system --create-home --shell /usr/sbin/nologin "$SVC_USER" else log "Service user '$SVC_USER' already exists." fi # ---- source tree ----------------------------------------------------------- mkdir -p "$(dirname "$INSTALL_DIR")" if [[ -d "$INSTALL_DIR/.git" ]]; then log "Updating existing checkout at $INSTALL_DIR..." chown -R "$SVC_USER:$SVC_USER" "$INSTALL_DIR" sudo -u "$SVC_USER" git -C "$INSTALL_DIR" remote set-url origin "$REPO_URL" sudo -u "$SVC_USER" git -C "$INSTALL_DIR" fetch --depth 1 origin "$BRANCH" sudo -u "$SVC_USER" git -C "$INSTALL_DIR" reset --hard "origin/$BRANCH" else log "Cloning $REPO_URL (branch $BRANCH) into $INSTALL_DIR..." rm -rf "$INSTALL_DIR" git clone --depth 1 --branch "$BRANCH" "$REPO_URL" "$INSTALL_DIR" chown -R "$SVC_USER:$SVC_USER" "$INSTALL_DIR" fi # ---- virtualenv + python deps --------------------------------------------- if [[ ! -x "$INSTALL_DIR/.venv/bin/python" ]]; then log "Creating Python venv..." sudo -u "$SVC_USER" python3 -m venv "$INSTALL_DIR/.venv" fi log "Installing Python dependencies (build123d pulls OpenCASCADE — may take a few minutes)..." sudo -u "$SVC_USER" "$INSTALL_DIR/.venv/bin/pip" install --quiet --upgrade pip sudo -u "$SVC_USER" "$INSTALL_DIR/.venv/bin/pip" install --quiet \ -r "$INSTALL_DIR/requirements.txt" gunicorn # ---- data dir (for SQLite) ------------------------------------------------- sudo -u "$SVC_USER" mkdir -p "$INSTALL_DIR/data" # ---- systemd unit ---------------------------------------------------------- log "Installing systemd unit..." UNIT_SRC="$INSTALL_DIR/deploy/busbar-designer.service" UNIT_DST="/etc/systemd/system/busbar-designer.service" [[ -f "$UNIT_SRC" ]] || die "deploy/busbar-designer.service missing in the repo." # Substitute paths / user / port into the unit. sed -e "s|/opt/busbar-designer|$INSTALL_DIR|g" \ -e "s|User=busbar|User=$SVC_USER|g" \ -e "s|Group=busbar|Group=$SVC_USER|g" \ -e "s|--bind=0.0.0.0:5000|--bind=0.0.0.0:$PORT|g" \ -e "s|Environment=PORT=5000|Environment=PORT=$PORT|g" \ "$UNIT_SRC" > "$UNIT_DST" systemctl daemon-reload systemctl enable --now busbar-designer sleep 2 if ! systemctl is-active --quiet busbar-designer; then warn "Service is not active. Last 30 log lines:" journalctl -u busbar-designer -n 30 --no-pager die "Service failed to start." fi IP_ADDR=$(hostname -I 2>/dev/null | awk '{print $1}') [[ -n "$IP_ADDR" ]] || IP_ADDR="$(hostname)" echo log "================================================================" log " ✓ Busbar Designer installed." log "" log " URL: http://$IP_ADDR:$PORT" log " Logs: journalctl -u busbar-designer -f" log " Update: sudo bash $INSTALL_DIR/deploy/update.sh" log " Backup: cp $INSTALL_DIR/data/busbar.db ..." log "================================================================"