#!/usr/bin/env bash # # Install the BookStack MCP server into a Debian/Ubuntu LXC container. # Run as root, from inside the container, in the directory containing pyproject.toml: # # bash deploy/lxc/install.sh # set -euo pipefail APP_DIR=/opt/bookstack-mcp CONF_DIR=/etc/bookstack-mcp SVC_USER=bookstack-mcp SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; } die() { printf '\033[1;31mERROR:\033[0m %s\n' "$*" >&2; exit 1; } [[ $EUID -eq 0 ]] || die "Run this as root (or with sudo)." [[ -f "$SRC_DIR/pyproject.toml" ]] || die "Can't find pyproject.toml next to this script." # --- Python version check ------------------------------------------------- # Needs 3.11+. Debian 12/13 and Ubuntu 24.04 are fine; Debian 11 and # Ubuntu 22.04 ship something older and need a newer python installed first. log "Checking Python version" if ! command -v python3 >/dev/null; then die "python3 not installed. Try: apt install -y python3 python3-venv" fi PY_OK=$(python3 -c 'import sys; print(1 if sys.version_info >= (3,11) else 0)') if [[ "$PY_OK" != "1" ]]; then die "Python $(python3 -V | cut -d' ' -f2) found, but 3.11+ is required. Debian 12+/Ubuntu 24.04+ work out of the box. On older releases install a newer python3 first (e.g. via deadsnakes) and re-run." fi # --- Dependencies --------------------------------------------------------- log "Installing system packages" export DEBIAN_FRONTEND=noninteractive # A single broken third-party repo shouldn't abort the whole install, so the # update is advisory; only the install itself is allowed to fail the script. apt-get update -qq || log "apt update reported errors, continuing" apt-get install -y -qq python3-venv python3-pip ca-certificates >/dev/null # --- Service user --------------------------------------------------------- if ! id -u "$SVC_USER" >/dev/null 2>&1; then log "Creating service user $SVC_USER" useradd --system --home-dir "$APP_DIR" --shell /usr/sbin/nologin "$SVC_USER" fi # --- Application ---------------------------------------------------------- log "Installing application to $APP_DIR" mkdir -p "$APP_DIR" rm -rf "$APP_DIR/bookstack_mcp" cp -r "$SRC_DIR/bookstack_mcp" "$APP_DIR/" cp "$SRC_DIR/pyproject.toml" "$APP_DIR/" if [[ ! -d "$APP_DIR/venv" ]]; then log "Creating virtualenv" python3 -m venv "$APP_DIR/venv" fi log "Installing Python dependencies (this takes a minute)" "$APP_DIR/venv/bin/pip" install --quiet --upgrade pip "$APP_DIR/venv/bin/pip" install --quiet "$APP_DIR" chown -R "$SVC_USER:$SVC_USER" "$APP_DIR" # --- Configuration -------------------------------------------------------- mkdir -p "$CONF_DIR" if [[ ! -f "$CONF_DIR/env" ]]; then log "Creating $CONF_DIR/env from the template" # systemd EnvironmentFile does not understand quotes or inline comments the # way a shell does, so strip comments and blank lines out of the example. grep -vE '^\s*(#|$)' "$SRC_DIR/.env.example" > "$CONF_DIR/env" NEW_CONFIG=1 else log "Keeping existing $CONF_DIR/env" NEW_CONFIG=0 fi chown root:"$SVC_USER" "$CONF_DIR/env" chmod 640 "$CONF_DIR/env" # --- systemd -------------------------------------------------------------- log "Installing systemd unit" install -m 644 "$SRC_DIR/deploy/lxc/bookstack-mcp.service" \ /etc/systemd/system/bookstack-mcp.service systemctl daemon-reload systemctl enable bookstack-mcp >/dev/null echo log "Install complete." echo if [[ "$NEW_CONFIG" == "1" ]]; then cat <