---
name: orca-vps-setup
description: Автоматическое развертывание и настройка Orca Server и AI-агентов (Codex, Claude Code, Antigravity, GitHub CLI, Skills, Swap, изолированный прокси) на чистом VPS (Ubuntu 24.04/22.04) с одного запуска.
---

# Скилл: Развертывание Orca Server и AI-агентов на VPS

Используйте этот скилл, когда нужно развернуть с нуля сервер **Orca**, настроить рабочее окружение для параллельной работы AI-агентов (**OpenAI Codex**, **Claude Code**, **Antigravity CLI**), пробросить **GitHub CLI**, настроить **Swap**, зарегистрировать **Orca Skills** и, при необходимости, настроить изолированный прокси для Antigravity.

---

## 1. Запрос доступов у пользователя (Интерактивный старт)

Перед запуском команд запросите у пользователя следующие данные (если они не переданы в контексте):
1. **IP-адрес сервера** (например, `185.58.204.8`).
2. **Пользователь и пароль / SSH-ключ** (по умолчанию `root`).
3. **GitHub Personal Access Token** (для авторизации `gh` и бесшовного клонирования репозиториев; опционально).
4. **Прокси для Antigravity** (URL вида `http://user:pass@ip:port` или `socks5://...`; опционально, если VPS в РФ).

---

## 2. Пошаговый сценарий автоматического выполнения

Агент подключается по SSH (через `ssh` с ключами или `expect` для пароля) и выполняет следующие шаги:

### Шаг 1: Настройка Swap и памяти
```bash
if [ ! -f /swapfile ]; then
    fallocate -l 2G /swapfile || dd if=/dev/zero of=/swapfile bs=1M count=2048
    chmod 600 /swapfile
    mkswap /swapfile
    swapon /swapfile
    echo "/swapfile none swap sw 0 0" >> /etc/fstab
    sysctl vm.swappiness=10
    echo "vm.swappiness=10" >> /etc/sysctl.conf
fi
```

### Шаг 2: Системные пакеты и зависимости для Electron/Chromium
```bash
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y \
  curl wget file jq git ca-certificates build-essential \
  xvfb zlib1g-dev libfuse2t64 \
  libnss3 libatk1.0-0t64 libatk-bridge2.0-0t64 libcups2t64 libdrm2 \
  libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 \
  libpango-1.0-0 libcairo2 libasound2t64 \
  libgtk-3-0t64 libnotify4 libsecret-1-0 libxss1
```

### Шаг 3: Системный пользователь `orca` и права
```bash
id -u orca &>/dev/null || useradd --system --create-home --shell /bin/bash orca
mkdir -p /home/orca/.ssh /home/user/projects /home/orca/projects
cp /root/.ssh/authorized_keys /home/orca/.ssh/authorized_keys 2>/dev/null || true
chown -R orca:orca /home/orca/.ssh /home/user /home/orca/projects
chmod 700 /home/orca/.ssh
chmod 600 /home/orca/.ssh/authorized_keys 2>/dev/null || true
chmod -R 775 /home/user

usermod -aG sudo orca
echo "orca ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/orca
```

### Шаг 4: Установка Orca AppImage и systemd-сервиса
```bash
mkdir -p /opt/orca
curl -L https://github.com/stablyai/orca/releases/latest/download/orca-linux.AppImage -o /opt/orca/orca-linux.AppImage
chmod 755 /opt/orca/orca-linux.AppImage

SERVER_IP=$(curl -s https://ifconfig.me || ip route get 1 | awk '{print $(NF-2);exit}')

cat << EOF > /etc/systemd/system/orca-serve.service
[Unit]
Description=Orca runtime server
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Type=simple
User=orca
WorkingDirectory=/home/orca
Environment=LIBGL_ALWAYS_SOFTWARE=1
ExecStart=/opt/orca/orca-linux.AppImage serve --port 6768 --pairing-address $SERVER_IP
StandardOutput=journal
StandardError=journal
KillMode=mixed
Restart=on-failure
RestartPreventExitStatus=3
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now orca-serve.service
```

### Шаг 5: Node.js 20, pnpm, GitHub CLI и AI-агенты
```bash
# Node.js
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
npm install -g pnpm

# GitHub CLI (gh)
mkdir -p -m 755 /etc/apt/keyrings
wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null
chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null
apt-get update -y
apt-get install -y gh

# Git Credential Helper
git config --system credential.helper ""
git config --system --add credential.helper "/usr/bin/gh auth git-credential"

# Claude Code & Codex CLI
npm install -g @anthropic-ai/claude-code @openai/codex

# Antigravity CLI
curl -fsSL https://antigravity.google/cli/install.sh | bash
ln -sf /home/orca/.local/bin/agy /usr/local/bin/agy
ln -sf /home/orca/.local/bin/agy /usr/local/bin/antigravity
```

### Шаг 6: Глобальный Orca CLI и валидация Skills
```bash
cat << 'EOF' > /usr/local/bin/orca
#!/bin/bash
if [ -x /home/orca/.local/bin/orca ]; then
    exec /home/orca/.local/bin/orca "$@"
else
    LIBGL_ALWAYS_SOFTWARE=1 exec /opt/orca/orca-linux.AppImage "$@"
fi
EOF
chmod 755 /usr/local/bin/orca

# Установка навыков
orca skills install --all

# Валидация YAML frontmatter в SKILL.md
python3 - << 'EOF'
import os
skills = {
    "computer-use": ("computer-use", "Use Orca computer-use CLI to inspect and operate desktop app windows."),
    "linear-tickets": ("linear-tickets", "Use Orca Linear CLI to read ticket context and post completion updates."),
    "orca-cli": ("orca-cli", "Use public orca CLI to operate worktrees, terminals, repos, and browser."),
    "orca-emulator": ("orca-emulator", "Control a mobile (iOS) emulator stream from inside Orca."),
    "orca-emulator-android": ("orca-emulator-android", "Control an Android emulator/device from inside Orca."),
    "orca-linear": ("orca-linear", "Use Orca Linear CLI through orca linear commands."),
    "orca-per-workspace-env": ("orca-per-workspace-env", "Manage Orca per-workspace environment recipes."),
    "orchestration": ("orchestration", "Use Orca orchestration for structured multi-agent coordination.")
}

for base in ["/root/.agents/skills", "/home/orca/.agents/skills"]:
    for skill_name, (name, desc) in skills.items():
        skill_file = os.path.join(base, skill_name, "SKILL.md")
        if os.path.exists(skill_file):
            with open(skill_file, "r", encoding="utf-8") as f:
                content = f.read()
            if not content.startswith("---"):
                frontmatter = f"---\nname: {name}\ndescription: {desc}\n---\n\n"
                with open(skill_file, "w", encoding="utf-8") as f:
                    f.write(frontmatter + content)
EOF

chown -R orca:orca /home/orca/.agents
```

### Шаг 7: Опциональная изоляция прокси для Antigravity
Если предоставлен прокси-адрес:
```bash
if [ ! -f /home/orca/.local/bin/agy-real ]; then
    mv /home/orca/.local/bin/agy /home/orca/.local/bin/agy-real
fi

cat << EOF > /usr/local/bin/agy
#!/bin/bash
PROXY_URL="$PROXY_URL"
export HTTP_PROXY="\$PROXY_URL"
export HTTPS_PROXY="\$PROXY_URL"
export http_proxy="\$PROXY_URL"
export https_proxy="\$PROXY_URL"
export ALL_PROXY="\$PROXY_URL"
export all_proxy="\$PROXY_URL"
export NO_PROXY="localhost,127.0.0.1,::1"
export no_proxy="localhost,127.0.0.1,::1"

exec /home/orca/.local/bin/agy-real "\$@"
EOF

chmod 755 /usr/local/bin/agy
ln -sf /usr/local/bin/agy /usr/local/bin/antigravity
ln -sf /usr/local/bin/agy /home/orca/.local/bin/agy
```

---

## 3. Финальный вывод для пользователя

После завершения агент извлекает Pairing URL и выдаёт отчёт:
```bash
journalctl -u orca-serve.service -n 30 --no-pager | grep -E "Web client URL|Pairing URL"
```

Выдать пользователю:
1. Кликабельную ссылку на веб-клиент Orca.
2. Pairing URL для Desktop / Mobile клиентов.
3. Список установленных инструментов (`agy`, `claude`, `codex`, `orca`, `gh`, `pnpm`).
