#!/usr/bin/env bash set -euo pipefail if [[ "$(id -u)" -ne 0 ]]; then echo "INSTALL_REQUIRES_ROOT" >&2 exit 1 fi SOURCE_DIR="${1:-}" TUNNEL_PUBLIC_KEY_FILE="${2:-}" if [[ -z "$SOURCE_DIR" || ! -f "$SOURCE_DIR/deploy/guanghulab-zhulan.nginx.conf" ]]; then echo "SOURCE_DIR_INVALID" >&2 exit 1 fi if [[ -z "$TUNNEL_PUBLIC_KEY_FILE" || ! -f "$TUNNEL_PUBLIC_KEY_FILE" ]]; then echo "TUNNEL_PUBLIC_KEY_FILE_INVALID" >&2 exit 1 fi EXPECTED_HOST="${ZHULAN_EXPECTED_HOST:-VM-0-16-ubuntu}" EXPECTED_DMI="${ZHULAN_EXPECTED_DMI:-b2ecf109-1999-4643-b223-e67e24d7667d}" ACTUAL_HOST="$(hostname)" ACTUAL_DMI="$(tr '[:upper:]' '[:lower:]' &2 exit 1 fi SITE_FILE="/etc/nginx/sites-enabled/guanghulab" SNIPPET_FILE="/etc/nginx/snippets/guanghu-zhulan.conf" SSHD_DROPIN="/etc/ssh/sshd_config.d/80-zhulan-proxy.conf" PROXY_HOME="/var/lib/guanghu/zhulan-proxy" AUTH_KEYS="$PROXY_HOME/.ssh/authorized_keys" BACKUP_ROOT="/var/backups/guanghu/zhulan-front" STAMP="$(date -u +%Y%m%dT%H%M%SZ)" if [[ ! -f "$SITE_FILE" ]]; then echo "GUANGHULAB_SITE_NOT_FOUND" >&2 exit 1 fi if ! grep -q 'include /etc/nginx/snippets/guanghu-ai-discovery.conf;' "$SITE_FILE"; then echo "GUANGHULAB_INCLUDE_ANCHOR_NOT_FOUND" >&2 exit 1 fi getent passwd zhulan-proxy >/dev/null || { echo "PROXY_USER_MUST_BE_PRECREATED" >&2 exit 1 } PUBLIC_KEY="$(tr -d '\r\n' <"$TUNNEL_PUBLIC_KEY_FILE")" if [[ "$PUBLIC_KEY" != ssh-ed25519\ * ]]; then echo "TUNNEL_PUBLIC_KEY_NOT_ED25519" >&2 exit 1 fi install -d -o root -g root -m 0700 "$BACKUP_ROOT" install -m 0644 "$SITE_FILE" "$BACKUP_ROOT/guanghulab-$STAMP" [[ ! -f "$SNIPPET_FILE" ]] || install -m 0644 "$SNIPPET_FILE" "$BACKUP_ROOT/snippet-$STAMP" [[ ! -f "$SSHD_DROPIN" ]] || install -m 0600 "$SSHD_DROPIN" "$BACKUP_ROOT/sshd-$STAMP" install -d -o zhulan-proxy -g zhulan-proxy -m 0700 "$PROXY_HOME" "$PROXY_HOME/.ssh" { printf '%s %s\n' \ 'restrict,port-forwarding,permitlisten="127.0.0.1:17631"' \ "$PUBLIC_KEY" } >"$AUTH_KEYS.tmp" chown zhulan-proxy:zhulan-proxy "$AUTH_KEYS.tmp" chmod 0600 "$AUTH_KEYS.tmp" mv "$AUTH_KEYS.tmp" "$AUTH_KEYS" cat >"$SSHD_DROPIN.tmp" <<'EOF' Match User zhulan-proxy AuthenticationMethods publickey PasswordAuthentication no KbdInteractiveAuthentication no AllowAgentForwarding no AllowTcpForwarding remote GatewayPorts no PermitListen 127.0.0.1:17631 PermitOpen none PermitTTY no X11Forwarding no PermitTunnel no PermitUserRC no MaxSessions 0 EOF chown root:root "$SSHD_DROPIN.tmp" chmod 0600 "$SSHD_DROPIN.tmp" mv "$SSHD_DROPIN.tmp" "$SSHD_DROPIN" sshd -t install -o root -g root -m 0644 \ "$SOURCE_DIR/deploy/guanghulab-zhulan.nginx.conf" "$SNIPPET_FILE" if ! grep -q 'include /etc/nginx/snippets/guanghu-zhulan.conf;' "$SITE_FILE"; then sed -i \ '/include \/etc\/nginx\/snippets\/guanghu-ai-discovery.conf;/a\ include /etc/nginx/snippets/guanghu-zhulan.conf;' \ "$SITE_FILE" fi if ! nginx -t; then install -m 0644 "$BACKUP_ROOT/guanghulab-$STAMP" "$SITE_FILE" nginx -t echo "NGINX_VALIDATION_FAILED_ROLLED_BACK" >&2 exit 1 fi systemctl reload ssh systemctl reload nginx printf '{"schema":"guanghu.zhulan-front-install-receipt/v1","development_id":"DEV-20260813-005","front_node":"BS-GZ-006","role":"DOMAIN_TLS_REVERSE_PROXY_ONLY","listener":"127.0.0.1:17631","installed_at":"%s"}\n' "$STAMP"