#!/usr/bin/env bash set -euo pipefail if [[ "$(id -u)" -ne 0 ]]; then echo "INSTALL_REQUIRES_ROOT" >&2 exit 1 fi SOURCE_DIR="${1:-}" AUTHORIZED_KEY_FILE="${2:-}" if [[ -z "$SOURCE_DIR" || ! -f "$SOURCE_DIR/remote/zhulan_guard.py" ]]; then echo "SOURCE_DIR_INVALID" >&2 exit 1 fi if [[ -z "$AUTHORIZED_KEY_FILE" || ! -s "$AUTHORIZED_KEY_FILE" ]]; then echo "AUTHORIZED_KEY_REQUIRED" >&2 exit 1 fi if grep -qvE '^ssh-ed25519 [A-Za-z0-9+/=]+( .*)?$' "$AUTHORIZED_KEY_FILE"; then echo "AUTHORIZED_KEY_INVALID" >&2 exit 1 fi EXPECTED_HOST="${ZHULAN_EXPECTED_HOST:-VM-12-12-ubuntu}" EXPECTED_DMI="${ZHULAN_EXPECTED_DMI:-7a500f2d-9aed-4b93-b3b8-59c87c65d031}" ACTUAL_HOST="$(hostname)" ACTUAL_DMI="$(tr '[:upper:]' '[:lower:]' &2 exit 1 fi REMOTE_USER="zhulan-codex" REMOTE_HOME="/srv/guanghu/zhulan-codex/home" REMOTE_ROOT="/srv/guanghu/zhulan-codex" WORKSPACE_ROOT="$REMOTE_ROOT/workspaces" CANDIDATE_ROOT="$REMOTE_ROOT/candidates" POLICY_ROOT="/etc/guanghu/zhulan-codex" HOOK_ROOT="$POLICY_ROOT/hooks" REQUIREMENTS_ROOT="/etc/codex" SSHD_DROPIN="/etc/ssh/sshd_config.d/60-zhulan-codex.conf" REPOSITORY_URL="https://guanghulab.com/code/bingshuo/guanghu-ice-heart.git" REPOSITORY_DIR="$WORKSPACE_ROOT/guanghu-ice-heart" CODEX_VERSION="${ZHULAN_CODEX_VERSION:-0.147.0}" SOURCE_COMMIT="${ZHULAN_SOURCE_COMMIT:-}" if [[ ! "$SOURCE_COMMIT" =~ ^[0-9a-f]{40}$ ]]; then echo "SOURCE_COMMIT_REQUIRED" >&2 exit 1 fi getent passwd "$REMOTE_USER" >/dev/null || useradd \ --home-dir "$REMOTE_HOME" \ --create-home \ --shell /bin/bash \ --comment "Zhulan Codex Remote restricted developer" \ "$REMOTE_USER" passwd -l "$REMOTE_USER" >/dev/null gpasswd -d "$REMOTE_USER" sudo >/dev/null 2>&1 || true gpasswd -d "$REMOTE_USER" adm >/dev/null 2>&1 || true install -d -o root -g root -m 0755 "$REMOTE_ROOT" install -d -o "$REMOTE_USER" -g "$REMOTE_USER" -m 0700 "$REMOTE_HOME" "$WORKSPACE_ROOT" "$CANDIDATE_ROOT" install -d -o "$REMOTE_USER" -g "$REMOTE_USER" -m 0700 "$REMOTE_HOME/.ssh" install -d -o "$REMOTE_USER" -g "$REMOTE_USER" -m 0700 "$REMOTE_HOME/.codex" { printf 'restrict,pty ' cat "$AUTHORIZED_KEY_FILE" } >"$REMOTE_HOME/.ssh/authorized_keys.tmp" chown "$REMOTE_USER:$REMOTE_USER" "$REMOTE_HOME/.ssh/authorized_keys.tmp" chmod 0600 "$REMOTE_HOME/.ssh/authorized_keys.tmp" mv "$REMOTE_HOME/.ssh/authorized_keys.tmp" "$REMOTE_HOME/.ssh/authorized_keys" install -d -o root -g root -m 0755 "$POLICY_ROOT" "$HOOK_ROOT" "$REQUIREMENTS_ROOT" install -o root -g root -m 0444 "$SOURCE_DIR/remote/LANE.hdlp" "$POLICY_ROOT/LANE.hdlp" install -o root -g root -m 0555 "$SOURCE_DIR/remote/zhulan_guard.py" "$HOOK_ROOT/zhulan_guard.py" install -o root -g root -m 0444 "$SOURCE_DIR/remote/requirements.toml" "$REQUIREMENTS_ROOT/requirements.toml" cat >"$SSHD_DROPIN.tmp" <<'EOF' Match User zhulan-codex AuthenticationMethods publickey PasswordAuthentication no KbdInteractiveAuthentication no PubkeyAuthentication yes AllowAgentForwarding no AllowTcpForwarding no X11Forwarding no PermitTunnel no PermitTTY yes PermitUserEnvironment no EOF chmod 0644 "$SSHD_DROPIN.tmp" mv "$SSHD_DROPIN.tmp" "$SSHD_DROPIN" /usr/sbin/sshd -t systemctl reload ssh if ! command -v codex >/dev/null 2>&1 || [[ "$(codex --version 2>/dev/null)" != *"$CODEX_VERSION"* ]]; then npm install --global "@openai/codex@$CODEX_VERSION" fi if [[ ! -d "$REPOSITORY_DIR/.git" ]]; then runuser -u "$REMOTE_USER" -- git clone "$REPOSITORY_URL" "$REPOSITORY_DIR" fi runuser -u "$REMOTE_USER" -- git -C "$REPOSITORY_DIR" fetch --prune origin main runuser -u "$REMOTE_USER" -- git -C "$REPOSITORY_DIR" remote set-url --push origin DISABLED_CENTRAL_PUSH if [[ ! -d "$CANDIDATE_ROOT/guanghu-ice-heart.git" ]]; then runuser -u "$REMOTE_USER" -- git init --bare "$CANDIDATE_ROOT/guanghu-ice-heart.git" fi if runuser -u "$REMOTE_USER" -- git -C "$REPOSITORY_DIR" remote get-url candidate >/dev/null 2>&1; then runuser -u "$REMOTE_USER" -- git -C "$REPOSITORY_DIR" remote set-url candidate "$CANDIDATE_ROOT/guanghu-ice-heart.git" else runuser -u "$REMOTE_USER" -- git -C "$REPOSITORY_DIR" remote add candidate "$CANDIDATE_ROOT/guanghu-ice-heart.git" fi install -o "$REMOTE_USER" -g "$REMOTE_USER" -m 0644 "$SOURCE_DIR/remote/AGENTS.md" "$REMOTE_HOME/.codex/AGENTS.md" install -d -o "$REMOTE_USER" -g "$REMOTE_USER" -m 0700 "$REPOSITORY_DIR/.zhulan/continuity" if ! grep -qxF '/.zhulan/' "$REPOSITORY_DIR/.git/info/exclude"; then printf '%s\n' '/.zhulan/' >>"$REPOSITORY_DIR/.git/info/exclude" fi chown "$REMOTE_USER:$REMOTE_USER" "$REPOSITORY_DIR/.git/info/exclude" runuser -u "$REMOTE_USER" -- git -C "$REPOSITORY_DIR" config user.name "Zhulan Remote Candidate" runuser -u "$REMOTE_USER" -- git -C "$REPOSITORY_DIR" config user.email "zhulan-remote@localhost" if id -nG "$REMOTE_USER" | tr ' ' '\n' | grep -qx sudo; then echo "REMOTE_USER_HAS_SUDO" >&2 exit 1 fi if sudo -n -u "$REMOTE_USER" sudo -n true >/dev/null 2>&1; then echo "REMOTE_USER_CAN_SUDO" >&2 exit 1 fi RECEIPT="$REMOTE_ROOT/install-receipt.json" cat >"$RECEIPT.tmp" <