diff --git a/.github/workflows/bash-syntax.yml b/.github/workflows/bash-syntax.yml index c205cf7..c9e047b 100644 --- a/.github/workflows/bash-syntax.yml +++ b/.github/workflows/bash-syntax.yml @@ -34,3 +34,6 @@ jobs: - name: Test step 3 SSH configuration parsing run: bash tests/test-step3-sshd-parsing.sh + + - name: Test step 8 AI agent catalog + run: bash tests/test-step8-agent-catalog.sh diff --git a/README.md b/README.md index 54c2d15..ec06c91 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ chmod 700 ./*.sh sudo ./ochenstarik-server-install.sh ``` -The first wizard prompt selects the dialog language. English is the default; Russian, Spanish, German, French, Portuguese, Simplified Chinese, Japanese, Arabic, and Hindi are also available. The wizard then presents steps 1–7 in order. Each step can be installed, skipped, or used to exit the wizard. +The first wizard prompt selects the dialog language. English is the default; Russian, Spanish, German, French, Portuguese, Simplified Chinese, Japanese, Arabic, and Hindi are also available. The wizard then presents steps 1–8 in order. Each step can be installed, skipped, or used to exit the wizard. Keep the current SSH session open while changing the SSH port. Test the new login in a second terminal before disconnecting. @@ -66,6 +66,7 @@ The wizard downloads any missing module from the `main` branch and validates it | `ochenstarik-server-vpn-5.sh` | System VPN through Xray with a selectable subscription port | Optional | | `ochenstarik-server-panel-warp-6.sh` | 3x-ui panel and local Cloudflare WARP proxy | Optional | | `ochenstarik-server-backup-7.sh` | Protected initial snapshot and selected daily, weekly, or monthly schedules | Optional | +| `ochenstarik-server-ai-agents-8.sh` | Installs selected AI agents for a regular user: Hermes, OpenClaw, OpenHands, OpenCode, or Aider | Optional | | `ochenstarik-server-uninstall.sh` | Removes project-managed settings so installation can start again | Use carefully | Every module can be downloaded and run independently: @@ -89,6 +90,13 @@ Replace `SCRIPT_NAME.sh` with the required filename from the table. 6. Optionally configure the system VPN and subscription port. 7. Optionally deploy 3x-ui and Cloudflare WARP with selected panel and subscription ports. 8. Optionally create the permanent initial backup and configure rotating schedules. +9. Optionally install one or more AI agents for the administrative user. + +## Optional AI agents + +Step 8 offers a multiple selection of five popular agents: Hermes Agent, OpenClaw, OpenHands, OpenCode, and Aider. Installers are downloaded only from each project's official HTTPS endpoint, checked with `bash -n`, and executed as the selected regular user rather than `root`. + +The script does not request or store model-provider API keys. After installation, log in as the selected user and run the displayed onboarding command. AI agents can execute commands, access files, install plugins, and use network services; review their permissions and sandbox settings before connecting production data or secrets. ## Firewall and SSH notes diff --git a/docs/readme/README.ar.md b/docs/readme/README.ar.md index 044230d..9c54b18 100644 --- a/docs/readme/README.ar.md +++ b/docs/readme/README.ar.md @@ -17,7 +17,7 @@ chmod 700 ochenstarik-server-install.sh sudo ./ochenstarik-server-install.sh ``` -السؤال الأول يحدد لغة المثبت، واللغة الافتراضية هي English. بعد ذلك يمكن تشغيل كل مرحلة من المراحل السبع أو تخطيها أو إنهاء المثبت. +السؤال الأول يحدد لغة المثبت، واللغة الافتراضية هي English. بعد ذلك يمكن تشغيل كل مرحلة من المراحل الثماني أو تخطيها أو إنهاء المثبت. ## المراحل @@ -28,5 +28,6 @@ sudo ./ochenstarik-server-install.sh 5. VPN للنظام باستخدام Xray. 6. لوحة 3x-ui ووكيل Cloudflare WARP المحلي. 7. النسخة الأولية والنسخ اليومية أو الأسبوعية أو الشهرية. +8. وكلاء ذكاء اصطناعي اختياريون: Hermes أو OpenClaw أو OpenHands أو OpenCode أو Aider. لا تغلق جلسة SSH الحالية أثناء تغيير المنفذ. اختبر الاتصال الجديد أولاً في طرفية أخرى. راجع [الوثائق الإنجليزية الرئيسية](../../README.md) لمزيد من التفاصيل. diff --git a/docs/readme/README.de.md b/docs/readme/README.de.md index 34f45d1..39ee3aa 100644 --- a/docs/readme/README.de.md +++ b/docs/readme/README.de.md @@ -17,7 +17,7 @@ chmod 700 ochenstarik-server-install.sh sudo ./ochenstarik-server-install.sh ``` -Die erste Frage wählt die Sprache des Installers; English ist voreingestellt. Danach kann jeder der sieben Schritte ausgeführt, übersprungen oder zum Beenden verwendet werden. +Die erste Frage wählt die Sprache des Installers; English ist voreingestellt. Danach kann jeder der acht Schritte ausgeführt, übersprungen oder zum Beenden verwendet werden. ## Schritte @@ -28,5 +28,6 @@ Die erste Frage wählt die Sprache des Installers; English ist voreingestellt. D 5. System-VPN über Xray. 6. 3x-ui und lokaler Cloudflare-WARP-Proxy. 7. Erstsicherung sowie tägliche, wöchentliche oder monatliche Sicherungen. +8. Optionale KI-Agenten: Hermes, OpenClaw, OpenHands, OpenCode oder Aider. Schließen Sie die aktuelle SSH-Sitzung während der Portänderung nicht. Testen Sie zuerst die neue Anmeldung in einem zweiten Terminal. Weitere Hinweise enthält die [englische Hauptdokumentation](../../README.md). diff --git a/docs/readme/README.es.md b/docs/readme/README.es.md index 457868d..ed4f7ea 100644 --- a/docs/readme/README.es.md +++ b/docs/readme/README.es.md @@ -17,7 +17,7 @@ chmod 700 ochenstarik-server-install.sh sudo ./ochenstarik-server-install.sh ``` -La primera pregunta selecciona el idioma del instalador; English es el valor predeterminado. Después puede instalar, omitir o detener cada una de las siete etapas. +La primera pregunta selecciona el idioma del instalador; English es el valor predeterminado. Después puede instalar, omitir o detener cada una de las ocho etapas. ## Etapas @@ -28,5 +28,6 @@ La primera pregunta selecciona el idioma del instalador; English es el valor pre 5. VPN del sistema mediante Xray. 6. Panel 3x-ui y proxy local Cloudflare WARP. 7. Instantánea inicial y copias diarias, semanales o mensuales. +8. Agentes de IA opcionales: Hermes, OpenClaw, OpenHands, OpenCode o Aider. No cierre la sesión SSH actual durante el cambio de puerto. Pruebe primero el nuevo acceso en otro terminal. Consulte la [documentación principal en inglés](../../README.md) para la instalación por archivo, actualización y restablecimiento. diff --git a/docs/readme/README.fr.md b/docs/readme/README.fr.md index b86c4e0..1fa834d 100644 --- a/docs/readme/README.fr.md +++ b/docs/readme/README.fr.md @@ -17,7 +17,7 @@ chmod 700 ochenstarik-server-install.sh sudo ./ochenstarik-server-install.sh ``` -La première question sélectionne la langue de l’installateur ; English est la valeur par défaut. Chacune des sept étapes peut ensuite être installée, ignorée ou utilisée pour quitter. +La première question sélectionne la langue de l’installateur ; English est la valeur par défaut. Chacune des huit étapes peut ensuite être installée, ignorée ou utilisée pour quitter. ## Étapes @@ -28,5 +28,6 @@ La première question sélectionne la langue de l’installateur ; English est l 5. VPN système via Xray. 6. Panneau 3x-ui et proxy local Cloudflare WARP. 7. Instantané initial et sauvegardes quotidiennes, hebdomadaires ou mensuelles. +8. Agents IA facultatifs : Hermes, OpenClaw, OpenHands, OpenCode ou Aider. Ne fermez pas la session SSH actuelle pendant le changement de port. Testez d’abord la nouvelle connexion dans un autre terminal. Consultez la [documentation principale en anglais](../../README.md) pour plus de détails. diff --git a/docs/readme/README.hi.md b/docs/readme/README.hi.md index 0a69f30..04e3930 100644 --- a/docs/readme/README.hi.md +++ b/docs/readme/README.hi.md @@ -17,7 +17,7 @@ chmod 700 ochenstarik-server-install.sh sudo ./ochenstarik-server-install.sh ``` -पहला प्रश्न इंस्टॉलर की भाषा चुनता है; डिफ़ॉल्ट English है। इसके बाद सातों चरणों को चलाया, छोड़ा या इंस्टॉलर बंद किया जा सकता है। +पहला प्रश्न इंस्टॉलर की भाषा चुनता है; डिफ़ॉल्ट English है। इसके बाद आठों चरणों को चलाया, छोड़ा या इंस्टॉलर बंद किया जा सकता है। ## चरण @@ -28,5 +28,6 @@ sudo ./ochenstarik-server-install.sh 5. Xray के माध्यम से सिस्टम VPN। 6. 3x-ui पैनल और स्थानीय Cloudflare WARP प्रॉक्सी। 7. प्रारंभिक स्नैपशॉट और दैनिक, साप्ताहिक या मासिक बैकअप। +8. वैकल्पिक AI एजेंट: Hermes, OpenClaw, OpenHands, OpenCode या Aider। SSH पोर्ट बदलते समय मौजूदा सत्र बंद न करें। पहले दूसरे टर्मिनल में नया लॉगिन जाँचें। अधिक जानकारी के लिए [मुख्य अंग्रेज़ी दस्तावेज़](../../README.md) देखें। diff --git a/docs/readme/README.ja.md b/docs/readme/README.ja.md index 8e15e1e..aabd977 100644 --- a/docs/readme/README.ja.md +++ b/docs/readme/README.ja.md @@ -17,7 +17,7 @@ chmod 700 ochenstarik-server-install.sh sudo ./ochenstarik-server-install.sh ``` -最初の質問でインストーラーの言語を選択します。既定値は English です。その後、7 つの各ステップを実行、スキップ、または終了できます。 +最初の質問でインストーラーの言語を選択します。既定値は English です。その後、8 つの各ステップを実行、スキップ、または終了できます。 ## ステップ @@ -28,5 +28,6 @@ sudo ./ochenstarik-server-install.sh 5. Xray によるシステム VPN。 6. 3x-ui パネルとローカル Cloudflare WARP プロキシ。 7. 初回スナップショットと日次、週次、月次バックアップ。 +8. オプションの AI エージェント:Hermes、OpenClaw、OpenHands、OpenCode、Aider。 SSH ポートの変更中は現在のセッションを閉じないでください。別のターミナルで新しい接続を先に確認してください。詳細は[英語のメイン文書](../../README.md)を参照してください。 diff --git a/docs/readme/README.pt.md b/docs/readme/README.pt.md index 0e8d360..f1e3b48 100644 --- a/docs/readme/README.pt.md +++ b/docs/readme/README.pt.md @@ -17,7 +17,7 @@ chmod 700 ochenstarik-server-install.sh sudo ./ochenstarik-server-install.sh ``` -A primeira pergunta seleciona o idioma do instalador; English é o padrão. Depois, cada uma das sete etapas pode ser instalada, ignorada ou usada para sair. +A primeira pergunta seleciona o idioma do instalador; English é o padrão. Depois, cada uma das oito etapas pode ser instalada, ignorada ou usada para sair. ## Etapas @@ -28,5 +28,6 @@ A primeira pergunta seleciona o idioma do instalador; English é o padrão. Depo 5. VPN do sistema por Xray. 6. Painel 3x-ui e proxy local Cloudflare WARP. 7. Snapshot inicial e backups diários, semanais ou mensais. +8. Agentes de IA opcionais: Hermes, OpenClaw, OpenHands, OpenCode ou Aider. Não feche a sessão SSH atual durante a alteração da porta. Teste primeiro o novo login em outro terminal. Consulte a [documentação principal em inglês](../../README.md) para obter detalhes adicionais. diff --git a/docs/readme/README.ru.md b/docs/readme/README.ru.md index 2a3a022..5746914 100644 --- a/docs/readme/README.ru.md +++ b/docs/readme/README.ru.md @@ -32,7 +32,7 @@ chmod 700 ./*.sh sudo ./ochenstarik-server-install.sh ``` -Первым запросом мастер предлагает выбрать язык диалога и только затем показывает этапы 1–7 по порядку. На каждом этапе можно выбрать установку, пропуск или завершение. В первом этапе пустой ввод устанавливает все рекомендуемые наборы программ. Во время изменения SSH-порта не закрывайте текущую сессию — сначала проверьте новый вход во втором терминале. +Первым запросом мастер предлагает выбрать язык диалога и только затем показывает этапы 1–8 по порядку. На каждом этапе можно выбрать установку, пропуск или завершение. В первом этапе пустой ввод устанавливает все рекомендуемые наборы программ. Во время изменения SSH-порта не закрывайте текущую сессию — сначала проверьте новый вход во втором терминале. Если нужен только мастер без скачивания полного архива: @@ -62,6 +62,7 @@ sudo ./ochenstarik-server-install.sh | `ochenstarik-server-vpn-5.sh` | Устанавливает Xray и направляет системный трафик через VLESS + REALITY | Да; зависимости устанавливаются автоматически | | `ochenstarik-server-panel-warp-6.sh` | Устанавливает 3x-ui и Cloudflare WARP, настраивает и проверяет их порты | Ubuntu 22.04/24.04/26.04 или Debian 12/13 | | `ochenstarik-server-backup-7.sh` | Создаёт неизменяемый первичный снимок и настраивает выбранные расписания резервного копирования | Да; зависимости устанавливаются автоматически | +| `ochenstarik-server-ai-agents-8.sh` | Устанавливает выбранных AI-агентов для обычного пользователя: Hermes, OpenClaw, OpenHands, OpenCode или Aider | Да; API-ключи настраиваются отдельно | | `ochenstarik-server-uninstall.sh` | Удаляет настройки, службы и данные проекта для повторной установки с начала | Да; запускать только из сохранённой SSH-сессии | Файлы `*.env.example` являются только примерами. Не записывайте настоящие пароли, токены и приватные SSH-ключи в Git. @@ -398,9 +399,25 @@ sudo ./ochenstarik-server-tg-4.sh sudo ./ochenstarik-server-vpn-5.sh sudo ./ochenstarik-server-panel-warp-6.sh sudo ./ochenstarik-server-backup-7.sh +sudo ./ochenstarik-server-ai-agents-8.sh ``` -VPN, 3x-ui, WARP, Telegram-уведомления и автоматические расписания резервного копирования являются необязательными этапами. +## 8. AI-агенты на выбор + +Файл: `ochenstarik-server-ai-agents-8.sh`. + +Скрипт предлагает множественный выбор из Hermes Agent, OpenClaw, OpenHands, OpenCode и Aider. Агенты устанавливаются только для выбранного обычного пользователя, а не для `root`. Каждый официальный установщик сначала загружается по HTTPS во временный файл и проходит проверку `bash -n`. + +API-ключи скрипт не запрашивает и не сохраняет. После установки нужно войти под выбранным пользователем и выполнить показанную команду первоначальной настройки. AI-агенты могут запускать команды, изменять файлы, использовать сеть и устанавливать плагины, поэтому перед подключением рабочих данных необходимо проверить разрешения, песочницу и доступ к секретам. + +```bash +curl -fLO https://raw.githubusercontent.com/ochenstarik-ui/lightweight-server/main/ochenstarik-server-ai-agents-8.sh +chmod 700 ochenstarik-server-ai-agents-8.sh +bash -n ochenstarik-server-ai-agents-8.sh +sudo ./ochenstarik-server-ai-agents-8.sh +``` + +VPN, 3x-ui, WARP, Telegram-уведомления, автоматические расписания резервного копирования и AI-агенты являются необязательными этапами. ## Удаление и повторная установка с начала diff --git a/docs/readme/README.zh-CN.md b/docs/readme/README.zh-CN.md index c6b826c..09e2c6e 100644 --- a/docs/readme/README.zh-CN.md +++ b/docs/readme/README.zh-CN.md @@ -17,7 +17,7 @@ chmod 700 ochenstarik-server-install.sh sudo ./ochenstarik-server-install.sh ``` -安装程序的第一个问题用于选择界面语言,默认是 English。随后七个步骤都可以运行、跳过或用于退出安装程序。 +安装程序的第一个问题用于选择界面语言,默认是 English。随后八个步骤都可以运行、跳过或用于退出安装程序。 ## 安装步骤 @@ -28,5 +28,6 @@ sudo ./ochenstarik-server-install.sh 5. 通过 Xray 配置系统 VPN。 6. 3x-ui 面板和本地 Cloudflare WARP 代理。 7. 初始快照以及每日、每周或每月备份。 +8. 可选 AI 代理:Hermes、OpenClaw、OpenHands、OpenCode 或 Aider。 更改 SSH 端口时不要关闭当前会话。请先在另一个终端中测试新连接。更多说明请参阅[英文主文档](../../README.md)。 diff --git a/ochenstarik-server-ai-agents-8.sh b/ochenstarik-server-ai-agents-8.sh new file mode 100644 index 0000000..68cb9b4 --- /dev/null +++ b/ochenstarik-server-ai-agents-8.sh @@ -0,0 +1,231 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +readonly CONFIG_DIR="/etc/ochenstarik-server" +readonly AGENT_CONFIG="${CONFIG_DIR}/ai-agents.conf" +readonly STEP3_ENV="/root/setup-data/env.txt" + +readonly -a AGENT_IDS=(hermes openclaw openhands opencode aider) +readonly -a AGENT_NAMES=( + "Hermes Agent" + "OpenClaw" + "OpenHands" + "OpenCode" + "Aider" +) +readonly -a AGENT_DESCRIPTIONS=( + "Personal self-improving agent with memory, skills, schedules, and messaging gateways" + "Personal assistant with persistent memory and Telegram, WhatsApp, Discord, Slack, and other channels" + "Software-development agent with terminal, headless, web, and IDE modes" + "Terminal coding agent with multiple model providers and parallel sessions" + "Git-oriented coding agent for editing and reviewing an existing repository" +) +readonly -a AGENT_INSTALL_URLS=( + "https://hermes-agent.nousresearch.com/install.sh" + "https://openclaw.ai/install.sh" + "https://install.openhands.dev/install.sh" + "https://opencode.ai/install" + "https://aider.chat/install.sh" +) +readonly -a AGENT_COMMANDS=(hermes openclaw openhands opencode aider) +readonly -a AGENT_SETUP_HINTS=( + "hermes setup" + "openclaw onboard --install-daemon" + "openhands" + "opencode" + "aider" +) + +TEMP_INSTALLER="" + +log() { printf '[+] %s\n' "$*"; } +warn() { printf '[!] %s\n' "$*" >&2; } +die() { printf '[x] %s\n' "$*" >&2; exit 1; } + +cleanup() { + if [[ -n "$TEMP_INSTALLER" && "$TEMP_INSTALLER" == /tmp/ochenstarik-ai-installer.* \ + && -f "$TEMP_INSTALLER" && ! -L "$TEMP_INSTALLER" ]]; then + rm -f -- "$TEMP_INSTALLER" + fi +} +trap cleanup EXIT + +require_command() { + command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1" +} + +default_target_user() { + local username="" + if [[ -f "$STEP3_ENV" && ! -L "$STEP3_ENV" ]]; then + username="$(awk -F= '$1 == "NEW_USERNAME" && !found { sub(/\r$/, "", $2); print $2; found=1 }' "$STEP3_ENV")" + if [[ "$username" =~ ^[a-z_][a-z0-9_-]{0,31}$ ]] && id "$username" >/dev/null 2>&1; then + printf '%s' "$username" + return 0 + fi + fi + getent passwd | awk -F: '$3 >= 1000 && $3 != 65534 && $1 != "nobody" && !found { print $1; found=1 }' +} + +select_target_user() { + local default_user username uid home owner + default_user="$(default_target_user)" + + printf '\nAI agents must be installed for a regular user, never for root.\n' + while :; do + if [[ -n "$default_user" ]]; then + read -rp "Installation user [${default_user}]: " username || die "Input was interrupted" + username="${username:-$default_user}" + else + read -rp 'Installation user: ' username || die "Input was interrupted" + fi + + [[ "$username" =~ ^[a-z_][a-z0-9_-]{0,31}$ ]] || { warn "Invalid username"; continue; } + [[ "$username" != root ]] || { warn "Root cannot be used for AI agents"; continue; } + id "$username" >/dev/null 2>&1 || { warn "User does not exist: $username"; continue; } + uid="$(id -u "$username")" + ((uid >= 1000 && uid != 65534)) || { warn "System accounts are not allowed"; continue; } + home="$(getent passwd "$username" | cut -d: -f6)" + [[ -n "$home" && "$home" == /* && -d "$home" && ! -L "$home" ]] \ + || { warn "A safe home directory was not found for $username"; continue; } + owner="$(stat -c %U "$home")" + [[ "$owner" == "$username" ]] || { warn "$home must be owned by $username"; continue; } + + TARGET_USER="$username" + TARGET_HOME="$home" + TARGET_GROUP="$(id -gn "$username")" + return 0 + done +} + +select_agents() { + local input token index + local -A seen=() + SELECTED_INDEXES=() + + printf '\nSelect one or more AI agents to install:\n' + for index in "${!AGENT_IDS[@]}"; do + printf ' %d) %s\n %s\n Official installer: %s\n' \ + "$((index + 1))" "${AGENT_NAMES[index]}" "${AGENT_DESCRIPTIONS[index]}" \ + "${AGENT_INSTALL_URLS[index]}" + done + printf ' 0) Do not install AI agents\n' + printf '\nEnter numbers separated by spaces, for example: 1 2 4.\n' + + while :; do + read -rp 'Selection [0]: ' input || die "Input was interrupted" + input="${input//,/ }" + input="${input:-0}" + if [[ "$input" =~ ^[[:space:]]*0[[:space:]]*$ ]]; then + return 0 + fi + + SELECTED_INDEXES=() + seen=() + for token in $input; do + if [[ ! "$token" =~ ^[1-5]$ ]]; then + warn "Enter agent numbers from 1 to 5, or 0 to skip" + SELECTED_INDEXES=() + break + fi + index="$((token - 1))" + if [[ -z "${seen[$index]:-}" ]]; then + SELECTED_INDEXES+=("$index") + seen["$index"]=1 + fi + done + ((${#SELECTED_INDEXES[@]} > 0)) && return 0 + done +} + +install_agent() { + local index="$1" name url command_name path_value + name="${AGENT_NAMES[index]}" + url="${AGENT_INSTALL_URLS[index]}" + command_name="${AGENT_COMMANDS[index]}" + path_value="${TARGET_HOME}/.local/bin:${TARGET_HOME}/.opencode/bin:${TARGET_HOME}/.hermes/bin:${TARGET_HOME}/.local/share/pnpm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + + log "Downloading the official ${name} installer" + TEMP_INSTALLER="$(mktemp /tmp/ochenstarik-ai-installer.XXXXXX)" + chmod 600 "$TEMP_INSTALLER" + curl -fL --retry 5 --retry-delay 5 --connect-timeout 30 \ + --proto '=https' --tlsv1.2 "$url" -o "$TEMP_INSTALLER" + [[ -s "$TEMP_INSTALLER" && ! -L "$TEMP_INSTALLER" ]] \ + || die "The downloaded ${name} installer is empty or unsafe" + bash -n "$TEMP_INSTALLER" || die "The official ${name} installer failed Bash syntax validation" + + # Keep the validated file root-owned until execution so the target account + # cannot replace it between validation and launch. + chown root:root "$TEMP_INSTALLER" + chmod 555 "$TEMP_INSTALLER" + log "Installing ${name} for ${TARGET_USER}" + runuser -u "$TARGET_USER" -- env \ + HOME="$TARGET_HOME" USER="$TARGET_USER" LOGNAME="$TARGET_USER" SHELL=/bin/bash PATH="$path_value" \ + bash "$TEMP_INSTALLER" + + rm -f -- "$TEMP_INSTALLER" + TEMP_INSTALLER="" + + if runuser -u "$TARGET_USER" -- env HOME="$TARGET_HOME" PATH="$path_value" \ + bash -lc "command -v '$command_name' >/dev/null 2>&1"; then + log "${name} command is available: ${command_name}" + else + warn "${name} installer completed, but ${command_name} is not visible in a new login shell yet" + warn "Log in again or reload the user's shell configuration before running it" + fi +} + +write_state() { + local ids="" index + install -d -m 700 -o root -g root "$CONFIG_DIR" + [[ ! -L "$AGENT_CONFIG" ]] || die "$AGENT_CONFIG must not be a symbolic link" + for index in "${SELECTED_INDEXES[@]}"; do + ids+="${ids:+ }${AGENT_IDS[index]}" + done + umask 077 + printf 'TARGET_USER=%s\nAGENTS=%s\n' "$TARGET_USER" "$ids" > "$AGENT_CONFIG" + chown root:root "$AGENT_CONFIG" + chmod 600 "$AGENT_CONFIG" +} + +[[ "$EUID" -eq 0 ]] || die "Run this script as root" +require_command awk +require_command apt-get +require_command bash +require_command getent +require_command runuser +require_command stat + +((${#AGENT_IDS[@]} == 5 && ${#AGENT_NAMES[@]} == 5 \ + && ${#AGENT_DESCRIPTIONS[@]} == 5 && ${#AGENT_INSTALL_URLS[@]} == 5 \ + && ${#AGENT_COMMANDS[@]} == 5 && ${#AGENT_SETUP_HINTS[@]} == 5)) \ + || die "Invalid AI agent catalog" + +select_target_user +select_agents +if ((${#SELECTED_INDEXES[@]} == 0)); then + log "AI agent installation was skipped" + exit 0 +fi + +export DEBIAN_FRONTEND=noninteractive +apt-get update +apt-get install -y curl ca-certificates git +require_command curl + +printf '\nThe selected agents can execute commands, access files, and use network services.\n' +printf 'Review permissions, tools, plugins, mounted directories, and API-key access during onboarding.\n' +read -rp "Type INSTALL to continue for user ${TARGET_USER}: " confirmation || die "Input was interrupted" +[[ "$confirmation" == INSTALL ]] || die "AI agent installation was cancelled" + +for selected_index in "${SELECTED_INDEXES[@]}"; do + install_agent "$selected_index" +done +write_state + +printf '\nInstalled AI agents for %s:\n' "$TARGET_USER" +for selected_index in "${SELECTED_INDEXES[@]}"; do + printf ' - %s\n Next step: %s\n' \ + "${AGENT_NAMES[selected_index]}" "${AGENT_SETUP_HINTS[selected_index]}" +done +printf '\nRun the setup commands while logged in as %s, not as root.\n' "$TARGET_USER" +printf 'API keys are managed by each agent and were not requested or stored by this script.\n' diff --git a/ochenstarik-server-install.sh b/ochenstarik-server-install.sh index c6f7b4b..8727c9b 100644 --- a/ochenstarik-server-install.sh +++ b/ochenstarik-server-install.sh @@ -12,6 +12,7 @@ declare -a STEP_FILES=( "ochenstarik-server-vpn-5.sh" "ochenstarik-server-panel-warp-6.sh" "ochenstarik-server-backup-7.sh" + "ochenstarik-server-ai-agents-8.sh" ) declare -a STEP_TITLES=( @@ -22,6 +23,7 @@ declare -a STEP_TITLES=( "System VPN through Xray" "3x-ui panel and Cloudflare WARP" "Initial snapshot and backup schedules" + "Optional AI agents for a regular user" ) TEMP_FILE="" @@ -156,15 +158,15 @@ master_msg() { localize_step_titles() { case "$UI_LANG" in - ru) STEP_TITLES=("Часовой пояс, язык терминала, программы и swap" "Базовые пакеты, SSH-порт, IPv4/IPv6 и UFW" "Администратор, перенос SSH и fail2ban" "Telegram-уведомления о входах по SSH" "Системный VPN через Xray" "Панель 3x-ui и Cloudflare WARP" "Первичный снимок и расписания бэкапов") ;; - es) STEP_TITLES=("Zona horaria, idioma del terminal, programas y swap" "Paquetes base, puerto SSH, IPv4/IPv6 y UFW" "Administrador, migración SSH y fail2ban" "Notificaciones de Telegram para accesos SSH" "VPN del sistema mediante Xray" "Panel 3x-ui y Cloudflare WARP" "Instantánea inicial y copias programadas") ;; - de) STEP_TITLES=("Zeitzone, Terminalsprache, Programme und Swap" "Basispakete, SSH-Port, IPv4/IPv6 und UFW" "Administrator, SSH-Umstellung und fail2ban" "Telegram-Benachrichtigungen für SSH-Anmeldungen" "System-VPN über Xray" "3x-ui und Cloudflare WARP" "Erstsicherung und Sicherungspläne") ;; - fr) STEP_TITLES=("Fuseau horaire, langue du terminal, programmes et swap" "Paquets de base, port SSH, IPv4/IPv6 et UFW" "Administrateur, migration SSH et fail2ban" "Notifications Telegram des connexions SSH" "VPN système via Xray" "Panneau 3x-ui et Cloudflare WARP" "Instantané initial et sauvegardes planifiées") ;; - pt) STEP_TITLES=("Fuso horário, idioma do terminal, programas e swap" "Pacotes básicos, porta SSH, IPv4/IPv6 e UFW" "Administrador, migração SSH e fail2ban" "Notificações Telegram de logins SSH" "VPN do sistema via Xray" "Painel 3x-ui e Cloudflare WARP" "Snapshot inicial e backups agendados") ;; - zh) STEP_TITLES=("时区、终端语言、程序和交换文件" "基础软件包、SSH 端口、IPv4/IPv6 和 UFW" "管理员、SSH 迁移和 fail2ban" "SSH 登录的 Telegram 通知" "通过 Xray 的系统 VPN" "3x-ui 面板和 Cloudflare WARP" "初始快照和备份计划") ;; - ja) STEP_TITLES=("タイムゾーン、端末言語、プログラム、スワップ" "基本パッケージ、SSH ポート、IPv4/IPv6、UFW" "管理者、SSH 移行、fail2ban" "SSH ログインの Telegram 通知" "Xray によるシステム VPN" "3x-ui パネルと Cloudflare WARP" "初回スナップショットとバックアップ予定") ;; - ar) STEP_TITLES=("المنطقة الزمنية ولغة الطرفية والبرامج وswap" "الحزم الأساسية ومنفذ SSH وIPv4/IPv6 وUFW" "المسؤول ونقل SSH وfail2ban" "إشعارات Telegram لدخول SSH" "VPN للنظام عبر Xray" "لوحة 3x-ui وCloudflare WARP" "النسخة الأولية وجداول النسخ الاحتياطي") ;; - hi) STEP_TITLES=("समय क्षेत्र, टर्मिनल भाषा, प्रोग्राम और swap" "मूल पैकेज, SSH पोर्ट, IPv4/IPv6 और UFW" "प्रशासक, SSH स्थानांतरण और fail2ban" "SSH लॉगिन की Telegram सूचनाएँ" "Xray द्वारा सिस्टम VPN" "3x-ui पैनल और Cloudflare WARP" "प्रारंभिक स्नैपशॉट और बैकअप अनुसूचियाँ") ;; + ru) STEP_TITLES=("Часовой пояс, язык терминала, программы и swap" "Базовые пакеты, SSH-порт, IPv4/IPv6 и UFW" "Администратор, перенос SSH и fail2ban" "Telegram-уведомления о входах по SSH" "Системный VPN через Xray" "Панель 3x-ui и Cloudflare WARP" "Первичный снимок и расписания бэкапов" "AI-агенты на выбор для обычного пользователя") ;; + es) STEP_TITLES=("Zona horaria, idioma del terminal, programas y swap" "Paquetes base, puerto SSH, IPv4/IPv6 y UFW" "Administrador, migración SSH y fail2ban" "Notificaciones de Telegram para accesos SSH" "VPN del sistema mediante Xray" "Panel 3x-ui y Cloudflare WARP" "Instantánea inicial y copias programadas" "Agentes de IA opcionales para un usuario normal") ;; + de) STEP_TITLES=("Zeitzone, Terminalsprache, Programme und Swap" "Basispakete, SSH-Port, IPv4/IPv6 und UFW" "Administrator, SSH-Umstellung und fail2ban" "Telegram-Benachrichtigungen für SSH-Anmeldungen" "System-VPN über Xray" "3x-ui und Cloudflare WARP" "Erstsicherung und Sicherungspläne" "Optionale KI-Agenten für einen normalen Benutzer") ;; + fr) STEP_TITLES=("Fuseau horaire, langue du terminal, programmes et swap" "Paquets de base, port SSH, IPv4/IPv6 et UFW" "Administrateur, migration SSH et fail2ban" "Notifications Telegram des connexions SSH" "VPN système via Xray" "Panneau 3x-ui et Cloudflare WARP" "Instantané initial et sauvegardes planifiées" "Agents IA facultatifs pour un utilisateur standard") ;; + pt) STEP_TITLES=("Fuso horário, idioma do terminal, programas e swap" "Pacotes básicos, porta SSH, IPv4/IPv6 e UFW" "Administrador, migração SSH e fail2ban" "Notificações Telegram de logins SSH" "VPN do sistema via Xray" "Painel 3x-ui e Cloudflare WARP" "Snapshot inicial e backups agendados" "Agentes de IA opcionais para um usuário comum") ;; + zh) STEP_TITLES=("时区、终端语言、程序和交换文件" "基础软件包、SSH 端口、IPv4/IPv6 和 UFW" "管理员、SSH 迁移和 fail2ban" "SSH 登录的 Telegram 通知" "通过 Xray 的系统 VPN" "3x-ui 面板和 Cloudflare WARP" "初始快照和备份计划" "为普通用户安装可选 AI 代理") ;; + ja) STEP_TITLES=("タイムゾーン、端末言語、プログラム、スワップ" "基本パッケージ、SSH ポート、IPv4/IPv6、UFW" "管理者、SSH 移行、fail2ban" "SSH ログインの Telegram 通知" "Xray によるシステム VPN" "3x-ui パネルと Cloudflare WARP" "初回スナップショットとバックアップ予定" "一般ユーザー向けのオプション AI エージェント") ;; + ar) STEP_TITLES=("المنطقة الزمنية ولغة الطرفية والبرامج وswap" "الحزم الأساسية ومنفذ SSH وIPv4/IPv6 وUFW" "المسؤول ونقل SSH وfail2ban" "إشعارات Telegram لدخول SSH" "VPN للنظام عبر Xray" "لوحة 3x-ui وCloudflare WARP" "النسخة الأولية وجداول النسخ الاحتياطي" "وكلاء ذكاء اصطناعي اختياريون لمستخدم عادي") ;; + hi) STEP_TITLES=("समय क्षेत्र, टर्मिनल भाषा, प्रोग्राम और swap" "मूल पैकेज, SSH पोर्ट, IPv4/IPv6 और UFW" "प्रशासक, SSH स्थानांतरण और fail2ban" "SSH लॉगिन की Telegram सूचनाएँ" "Xray द्वारा सिस्टम VPN" "3x-ui पैनल और Cloudflare WARP" "प्रारंभिक स्नैपशॉट और बैकअप अनुसूचियाँ" "सामान्य उपयोगकर्ता के लिए वैकल्पिक AI एजेंट") ;; esac } diff --git a/tests/test-master-language.sh b/tests/test-master-language.sh index dc58172..9f4e551 100644 --- a/tests/test-master-language.sh +++ b/tests/test-master-language.sh @@ -18,5 +18,9 @@ choose_dialog_language <<< '' >/dev/null choose_dialog_language <<< '2' >/dev/null [[ "$(master_msg install)" == 'Установить / запустить этот этап' ]] [[ "${STEP_TITLES[0]}" == 'Часовой пояс, язык терминала, программы и swap' ]] +[[ "${#STEP_FILES[@]}" == 8 ]] +[[ "${#STEP_TITLES[@]}" == 8 ]] +[[ "${STEP_FILES[7]}" == 'ochenstarik-server-ai-agents-8.sh' ]] +[[ "${STEP_TITLES[7]}" == 'AI-агенты на выбор для обычного пользователя' ]] printf 'Master language selection tests passed.\n' diff --git a/tests/test-step8-agent-catalog.sh b/tests/test-step8-agent-catalog.sh new file mode 100644 index 0000000..488fa53 --- /dev/null +++ b/tests/test-step8-agent-catalog.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." +source <(awk '/^\[\[ "\$EUID"/{exit} {print}' ochenstarik-server-ai-agents-8.sh) + +[[ "${#AGENT_IDS[@]}" == 5 ]] +[[ "${AGENT_IDS[*]}" == 'hermes openclaw openhands opencode aider' ]] + +expected_urls=( + 'https://hermes-agent.nousresearch.com/install.sh' + 'https://openclaw.ai/install.sh' + 'https://install.openhands.dev/install.sh' + 'https://opencode.ai/install' + 'https://aider.chat/install.sh' +) + +for index in "${!expected_urls[@]}"; do + [[ "${AGENT_INSTALL_URLS[index]}" == "${expected_urls[index]}" ]] +done + +select_agents <<< '1 3 5' >/dev/null +[[ "${SELECTED_INDEXES[*]}" == '0 2 4' ]] +select_agents <<< '' >/dev/null +[[ "${#SELECTED_INDEXES[@]}" == 0 ]] + +if grep -E 'curl[^|]*\|[[:space:]]*(ba)?sh' ochenstarik-server-ai-agents-8.sh; then + printf 'Direct curl-to-shell execution found.\n' >&2 + exit 1 +fi + +printf 'Step 8 AI agent catalog tests passed.\n'