From b9755187cfd2503a975c6e69261912b8e2fed682 Mon Sep 17 00:00:00 2001 From: Simbiot Harness Date: Fri, 16 Oct 2026 13:04:02 +0000 Subject: [PATCH] =?UTF-8?q?deploy-claude-code:=20bypass=20permissions=20+?= =?UTF-8?q?=20root=20=D0=BF=D0=BE=20=D1=83=D0=BC=D0=BE=D0=BB=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8E=20(t-261016120111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/deploy-claude-code.sh | 49 +++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/scripts/deploy-claude-code.sh b/scripts/deploy-claude-code.sh index 7989d66..4973ec2 100755 --- a/scripts/deploy-claude-code.sh +++ b/scripts/deploy-claude-code.sh @@ -11,14 +11,19 @@ # 5) daemon-reload + enable --now + финальная проверка версий и здоровья # # Использование (root или sudo): -# bash scripts/deploy-claude-code.sh # дефолты: :7681, юзер claude, токен сгенерится +# bash scripts/deploy-claude-code.sh # дефолты: :7681, root + bypass permissions # bash scripts/deploy-claude-code.sh --port 7681 --user lunar --token MySecret +# bash scripts/deploy-claude-code.sh --run-as claude # ограниченный режим: юзер claude # bash scripts/deploy-claude-code.sh --dry-run --port 9000 --user bob --token x # bash scripts/deploy-claude-code.sh --check # только здоровье, без установки # # Опции: # --port N порт ttyd (по умолчанию 7681, как на Лунаре) -# --user NAME OS-юзер сервиса И логин basic-auth (по умолчанию claude) +# --user NAME логин basic-auth (по умолчанию claude) +# --run-as NAME юзер сервиса ttyd (по умолчанию root — агенту нужны +# права на редактирование любых файлов; t-261016120111) +# --ask-permissions НЕ прокидывать --dangerously-skip-permissions +# (по умолчанию флаг прокидывается всегда — bypass) # --token SECRET пароль basic-auth (по умолчанию: openssl rand -hex 12) # --service NAME имя systemd-юнита (по умолчанию ttyd-claude) # --ttyd-version V версия ttyd (по умолчанию 1.7.7) @@ -32,14 +37,17 @@ # --check только проверка здоровья (версии + HTTP + сервис) # -h | --help эта справка # -# Безопасность: веб-терминнал закрыт basic-auth (-c user:token) — как на Лунаре -# (логин lunar / Zm9yZXZ0b25lClaude01). Сервис работает от непривилегированного -# юзера (User=), никакого root-shell в браузере. +# Безопасность: веб-терминал закрыт basic-auth (-c user:token). ПО УМОЛЧАНИЮ +# сервис работает от root и claude запускается с --dangerously-skip-permissions +# (мандат t-261016120111: агент должен уметь редактировать любые файлы). +# Для ограниченной развёртки: --run-as --ask-permissions. # ============================================================================ set -euo pipefail PORT="7681" USER_NAME="claude" +RUN_AS="root" +ASK_PERMISSIONS=0 TOKEN="" SERVICE="ttyd-claude" TTYD_VERSION="1.7.7" @@ -62,6 +70,8 @@ while [ $# -gt 0 ]; do case "$1" in --port) PORT="${2:-}"; shift 2 ;; --user) USER_NAME="${2:-}"; shift 2 ;; + --run-as) RUN_AS="${2:-}"; shift 2 ;; + --ask-permissions) ASK_PERMISSIONS=1; shift ;; --token) TOKEN="${2:-}"; shift 2 ;; --service) SERVICE="${2:-}"; shift 2 ;; --ttyd-version) TTYD_VERSION="${2:-}"; shift 2 ;; @@ -79,6 +89,7 @@ while [ $# -gt 0 ]; do opt="${1%%=*}"; val="${1#*=}" case "$opt" in --port) PORT="$val" ;; --user) USER_NAME="$val" ;; + --run-as) RUN_AS="$val" ;; --ask-permissions) ASK_PERMISSIONS=1 ;; --token) TOKEN="$val" ;; --service) SERVICE="$val" ;; --ttyd-version) TTYD_VERSION="$val" ;; --node-version) NODE_VERSION="$val" ;; --claude-version) CLAUDE_VERSION="$val" ;; --interface) INTERFACE="$val" ;; @@ -93,6 +104,10 @@ done || die "--port должен быть числом 1..65535 (получили: '$PORT')" [[ "$USER_NAME" =~ ^[a-z_][a-z0-9_-]{0,31}$ ]] \ || die "--user должен быть валидным unix-логином (a-z, 0-9, _, -; получили: '$USER_NAME')" +[[ "$RUN_AS" =~ ^[a-z_][a-z0-9_-]{0,31}$ ]] \ + || die "--run-as должен быть валидным unix-логином (получили: '$RUN_AS')" +id -u "$RUN_AS" >/dev/null 2>&1 || [ "$DRY_RUN" -eq 1 ] || [ "$CHECK_ONLY" -eq 1 ] \ + || die "--run-as: юзер '$RUN_AS' не существует (скрипт его не создаёт — создай сам или запусти без --run-as для root)" [[ "$SERVICE" =~ ^[a-zA-Z0-9_.@-]+$ ]] || die "--service: некорректное имя юнита '$SERVICE'" case "$TOKEN" in *:*) die "--token не может содержать ':' (ломает -c user:token)" ;; @@ -223,17 +238,22 @@ else bash -c "set -e; curl -fsSL -o /usr/local/bin/ttyd https://github.com/tsl0922/ttyd/releases/download/$TTYD_VERSION/ttyd.$TARCH && chmod +x /usr/local/bin/ttyd" fi -# ── 4) OS-юзер и systemd-юнит ──────────────────────────────────────────────── -if [ "$DRY_RUN" -eq 0 ]; then - if ! id -u "$USER_NAME" >/dev/null 2>&1; then - log "создаю юзера $USER_NAME (без root-shell в веб-терминале)" - useradd -m -s /bin/bash "$USER_NAME" - fi +# ── 4) systemd-юнит ────────────────────────────────────────────────────────── +# По умолчанию сервис работает от root (RUN_AS=root): агент получает право +# редактировать любые файлы (мандат t-261016120111). Ограниченный режим: +# --run-as (+ можно --ask-permissions). +if [ "$DRY_RUN" -eq 0 ] && [ "$RUN_AS" != "root" ]; then + id -u "$RUN_AS" >/dev/null 2>&1 || { log "создаю юзера $RUN_AS (без root-shell в веб-терминале)"; useradd -m -s /bin/bash "$RUN_AS"; } fi WRITABLE='-W'; [ "$READONLY" -eq 1 ] && WRITABLE='' +# bypass permissions: --dangerously-skip-permissions прокидывается ПО УМОЛЧАНИЮ +CLAUDE_ARGS='' +[ "$ASK_PERMISSIONS" -eq 0 ] && CLAUDE_ARGS='--dangerously-skip-permissions' UNIT_PATH="/etc/systemd/system/${SERVICE}.service" -ENV_LINES="Environment=HOME=/home/${USER_NAME} +SERVICE_HOME="/home/${RUN_AS}" +[ "$RUN_AS" = "root" ] && SERVICE_HOME="/root" +ENV_LINES="Environment=HOME=${SERVICE_HOME} Environment=PATH=/usr/local/bin:/usr/bin:/bin" if [ ${#UNIT_ENV[@]} -gt 0 ]; then for e in "${UNIT_ENV[@]}"; do ENV_LINES+=" @@ -245,9 +265,9 @@ After=network-online.target Wants=network-online.target [Service] -User=${USER_NAME} +User=${RUN_AS} ${ENV_LINES} -ExecStart=/usr/local/bin/ttyd ${WRITABLE} -c ${USER_NAME}:${TOKEN} -p ${PORT} -i ${INTERFACE} claude +ExecStart=/usr/local/bin/ttyd ${WRITABLE} -c ${USER_NAME}:${TOKEN} -p ${PORT} -i ${INTERFACE} claude ${CLAUDE_ARGS} Restart=always RestartSec=3 @@ -286,4 +306,5 @@ log " URL : http://${IP}:${PORT}" log " логин : ${USER_NAME}" log " пароль : ${TOKEN}" log " сервис : systemctl status ${SERVICE}" +log " режим : User=${RUN_AS}; claude-флаги: ${CLAUDE_ARGS:-—} (bypass permissions по умолчанию, t-261016120111)" log " первый вход: открой URL, пройди авторизацию claude (или передай --env ANTHROPIC_BASE_URL=... при развёртке)"