#!/usr/bin/env bash # Install or update the shared wecom-excel MCP server on a Linux host with systemd, as root. Nothing is # compiled: it downloads the prebuilt executable from the GitHub release. # # curl -fsSL https://github.com/Doone-skser/wecom-excel-mcp/releases/latest/download/install.sh | sudo bash # # By default the server listens on port 8765 of every interface (http://:8765/). Settings # (environment variables, e.g. `| sudo PORT=9000 bash`): # PORT the port, default 8765 # DOMAIN serve https://DOMAIN/ through nginx with a Let's Encrypt certificate instead (Debian / Ubuntu; # the domain must resolve to this host, ports 80 and 443 open); the port is then local only # EMAIL for Let's Encrypt expiry mail (with DOMAIN, optional) # SKIP_NGINX=1 with DOMAIN: your own proxy (宝塔, Caddy, ...) forwards https://DOMAIN to 127.0.0.1:PORT # ADMIN_USER the /admin account, default admin # ADMIN_PASSWORD its password; when unset and no login exists yet, a random one is made and shown once # VERSION a release tag such as v0.2.0, default the latest # GITHUB_PROXY a prefix for downloading the executable when github.com is slow, e.g. https://ghfast.top/; # the checksum still comes from github.com itself, so the proxy cannot swap the executable # SHA256 the executable's checksum, copied from the release page (SHA256SUMS), when github.com itself # cannot be reached to fetch it # BINARY install this local executable instead of downloading one set -euo pipefail REPO_URL=https://github.com/Doone-skser/wecom-excel-mcp PORT="${PORT:-8765}" DOMAIN="${DOMAIN:-}" ADMIN_USER="${ADMIN_USER:-admin}" APP=/opt/wecom-excel STATE=/var/lib/wecom-excel SVC=wecom-excel-http SVC_USER=wecom-excel log() { printf '\n==> %s\n' "$*"; } die() { printf 'error: %s\n' "$*" >&2; exit 1; } [ "$(id -u)" = 0 ] || die "run as root (sudo)" command -v systemctl >/dev/null || die "needs systemd" [[ "$PORT" =~ ^[0-9]+$ ]] || die "PORT looks wrong: $PORT" [ -z "$DOMAIN" ] || [[ "$DOMAIN" =~ ^[A-Za-z0-9.-]+$ ]] || die "DOMAIN looks wrong: $DOMAIN" case "$(uname -m)" in x86_64 | amd64) ARCH=x86_64 ;; aarch64 | arm64) ARCH=arm64 ;; *) die "no prebuilt executable for $(uname -m); see DEPLOY.md to build from source" ;; esac command -v curl >/dev/null || die "needs curl" log "executable -> $APP/wecom-excel-mcp" mkdir -p "$APP" if [ -n "${BINARY:-}" ]; then install -m 755 "$BINARY" "$APP/wecom-excel-mcp.new" else name="wecom-excel-mcp-linux-$ARCH" if [ -n "${VERSION:-}" ]; then base="$REPO_URL/releases/download/$VERSION"; else base="$REPO_URL/releases/latest/download"; fi tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' EXIT # The checksums always come straight from github.com (small; reachable where the big download is slow), # never through GITHUB_PROXY: a proxy that served both could swap the executable unnoticed. if [ -n "${SHA256:-}" ]; then printf '%s %s\n' "$SHA256" "$name" > "$tmp/SHA256SUMS" else # a loop, not --retry-all-errors: curl on Debian 10 / EL8 is older than that option for _ in 1 2 3 4 5 6 7 8; do curl -fsSL --connect-timeout 10 --max-time 30 -o "$tmp/SHA256SUMS" "$base/SHA256SUMS" 2>/dev/null && break sleep 2 done [ -s "$tmp/SHA256SUMS" ] || die "cannot reach github.com for $base/SHA256SUMS (needed to check the download); try again, or pass SHA256=" fi curl -fL --retry 3 --progress-bar -o "$tmp/$name" "${GITHUB_PROXY:-}$base/$name" (cd "$tmp" && grep " $name\$" SHA256SUMS | sha256sum -c --quiet -) || die "checksum mismatch for $name" install -m 755 "$tmp/$name" "$APP/wecom-excel-mcp.new" fi "$APP/wecom-excel-mcp.new" --version >/dev/null || die "the executable does not run on this system" mv -f "$APP/wecom-excel-mcp.new" "$APP/wecom-excel-mcp" "$APP/wecom-excel-mcp" --version log "service user and data directory $STATE" id "$SVC_USER" >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin "$SVC_USER" 2>/dev/null \ || useradd --system --no-create-home --shell /sbin/nologin "$SVC_USER" mkdir -p "$STATE" chown "$SVC_USER:$SVC_USER" "$STATE" chmod 700 "$STATE" shown="" if [ ! -s "$STATE/admin-password" ] || [ -n "${ADMIN_PASSWORD:-}" ]; then log "/admin login for $ADMIN_USER" if [ -z "${ADMIN_PASSWORD:-}" ]; then ADMIN_PASSWORD="$(head -c 18 /dev/urandom | base64 | tr -d '/+=')" shown="$ADMIN_PASSWORD" fi printf '%s\n' "$ADMIN_PASSWORD" | "$APP/wecom-excel-mcp" passwd --user "$ADMIN_USER" --file "$STATE/admin-password" >/dev/null chown "$SVC_USER:$SVC_USER" "$STATE/admin-password" fi if [ -n "$DOMAIN" ]; then HOST=127.0.0.1 URL="https://$DOMAIN" PUBLIC="--public-url $URL" else HOST=0.0.0.0 ip="$(curl -fsS --max-time 5 https://ipinfo.io/ip 2>/dev/null || hostname -I 2>/dev/null | awk '{print $1}' || true)" URL="http://${ip:-}:$PORT" PUBLIC="" fi log "systemd service $SVC ($HOST:$PORT)" cat > "/etc/systemd/system/$SVC.service" </dev/null && ufw status 2>/dev/null | grep -q "Status: active"; then log "firewall: ufw allow $PORT/tcp"; ufw allow "$PORT/tcp" >/dev/null elif command -v firewall-cmd >/dev/null && firewall-cmd --state >/dev/null 2>&1; then log "firewall: firewalld port $PORT/tcp"; firewall-cmd -q --permanent --add-port="$PORT/tcp"; firewall-cmd -q --reload fi elif [ -z "${SKIP_NGINX:-}" ]; then command -v apt-get >/dev/null || die "the nginx setup needs Debian / Ubuntu; use SKIP_NGINX=1 and your own proxy" log "nginx and certbot" export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq nginx certbot >/dev/null CONF=/etc/nginx/conf.d/wecom-excel.conf ACME=/var/www/wecom-excel-acme mkdir -p "$ACME" if [ ! -f "/etc/letsencrypt/live/$DOMAIN/fullchain.pem" ]; then log "certificate for $DOMAIN (Let's Encrypt)" cat > "$CONF" < /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh log "nginx -> $CONF" cat > "$CONF" <