{"title":"SSH-доступ через проксі","slug":"ssh-proxy-access","category":"llm-cookbook","summary":"Як LLM-агент безпечно виконує команди на віддалених машинах через HTTP-API SSH-проксі замість сирих SSH-ключів.","audience":["llm"],"tags":["cookbook","ssh","proxy","infrastructure","remote-execution"],"difficulty":"intermediate","updated":"2026-09-26","word_count":341,"read_minutes":2,"llm_context":"НІКОЛИ не тримайте сирі приватні SSH-ключі як LLM. Використовуйте HTTP-API SSH-проксі:\n1) POST /connect?target=<name> → session_id (постійна, живе годинами).\n2) POST /<session_id>/exec {command, timeout} → exec_id.\n3) GET /<session_id>/exec/<exec_id> → вивід після завершення.\n4) Для завантаження/відправлення файлів використовуйте SFTP-ендпоінти замість cat/heredoc.\nЦілі — попередньо зареєстровані імена (напр. \"vps1\"), не IP — проксі — єдине\nмісце, де живуть облікові дані.\n","lang":"uk","translated":true,"requested_lang":"uk","content_markdown":"\n# SSH-доступ через проксі\n\nАгентам потрібно виконувати команди на віддалених машинах — розгорнути контейнер, прочитати лог, виправити конфіг. Давати сирі приватні SSH-ключі LLM — погана ідея: ключі потрапляють у вікна контексту, логи й транскрипти. SSH-проксі вирішує це: облікові дані зберігає він, агент говорить лише HTTP.\n\n## Модель\n\n```\nLLM ──HTTPS──► SSH-проксі ──SSH──► цільові машини\n                (зберігає ключі,\n                 журнал аудиту,\n                 ліміти частоти)\n```\n\nПроксі віддає постійні сесії через просту REST-поверхню:\n\n| Ендпоінт | Призначення |\n|---|---|\n| `POST /connect?target=vps1` | відкрити сесію → `session_id` |\n| `POST /<sid>/exec` `{command, timeout}` | виконати команду (async) → `exec_id` |\n| `GET /<sid>/exec/<exec_id>` | опитати вивід |\n| SFTP-ендпоінти | завантаження/відправлення файлів, `ls`, `mkdir`, `rm` |\n\nАутентифікація — Bearer-токен, той самий патерн, що й в усіх інших API, які ви використовуєте.\n\n## Патерн виконання\n\n```bash\n# 1. підключіться один раз, перевикористайте сесію для всієї задачі\nSID=$(curl -s -H \"Authorization: Bearer $KEY\" \\\n  \"https://ssh-proxy.example/connect?target=vps1\" | jq -r .session_id)\n\n# 2. виконайте команду\nEID=$(curl -s -H \"Authorization: Bearer $KEY\" -H \"Content-Type: application/json\" \\\n  -X POST \"https://ssh-proxy.example/$SID/exec\" \\\n  -d '{\"command\": \"docker ps --format \\\"{{.Names}}\\\"\", \"timeout\": 120}' | jq -r .exec_id)\n\n# 3. опитайте результат\ncurl -s -H \"Authorization: Bearer $KEY\" \"https://ssh-proxy.example/$SID/exec/$EID\"\n```\n\n## Правила поведінки\n\n1. **Перевикористовуйте сесії.** Підключення на кожну команду марнує ресурси й ловить ліміти частоти. Збережіть `session_id` (напр. `/tmp/vps1_sid`) і перевіряйте його heartbeat перед повторним використанням.\n2. **Називайте цілі, а не відкривайте їх.** Цілі попередньо зареєстровані (`vps1`, `pi`, …). Проксі — єдине джерело правди; ніколи не зашивайте IP-адреси в код агента.\n3. **Надавайте перевагу SFTP замість cat/heredoc для файлів.** Екранування бінарних даних через `exec` псує навантаження. Використовуйте виділені ендпоінти завантаження/відправлення.\n4. **Кавичте свої команди.** Тіло JSON парситься двічі (HTTP + shell). Обгортайте віддалені команди в одинарні лапки й тримайте їх в один рядок.\n5. **Вважайте, що аудит ведеться.** Кожен exec потрапляє в журнал аудиту проксі — ведіть себе так, ніби людина читає все (вона може).\n\n## Коли exec використовувати НЕ варто\n\n- Читання структурованого стану, який має API (Docker, бази даних, Mind API Synapse) — завжди надавайте перевагу API розбору виводу CLI.\n- Довгі інтерактивні процеси. `exec` — це fire-and-forget з таймаутом; натомість використовуйте `nohup` + файл статусу на цільовій машині.\n- Будь-яке деструктивне дійство без явної інструкції. Проксі дає вам владу — людина дає вам дозвіл.\n\n## Відновлення після помилок\n\n| Симптом | Рішення |\n|---|---|\n| 401 при connect | токен минув — перечитайте його з memory/settings, ніколи з транскрипту |\n| сесія 404 | сесія минула (ліміт 24 год) — перепідключіться |\n| таймаут exec | підніміть `timeout` або розділіть команду; перевірте навантаження цільової машини |\n| зіпсований вміст файлу | ви використали `exec` замість SFTP — перейдіть на SFTP-ендпоінти |\n","content_html":"<h1>SSH-доступ через проксі</h1>\n<p>Агентам потрібно виконувати команди на віддалених машинах — розгорнути контейнер, прочитати лог, виправити конфіг. Давати сирі приватні SSH-ключі LLM — погана ідея: ключі потрапляють у вікна контексту, логи й транскрипти. SSH-проксі вирішує це: облікові дані зберігає він, агент говорить лише HTTP.</p>\n<h2>Модель</h2>\n<pre><code class=\"hljs language-plaintext\">LLM ──HTTPS──► SSH-проксі ──SSH──► цільові машини\n                (зберігає ключі,\n                 журнал аудиту,\n                 ліміти частоти)</code></pre><p>Проксі віддає постійні сесії через просту REST-поверхню:</p>\n<table>\n<thead>\n<tr>\n<th>Ендпоінт</th>\n<th>Призначення</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>POST /connect?target=vps1</code></td>\n<td>відкрити сесію → <code>session_id</code></td>\n</tr>\n<tr>\n<td><code>POST /&lt;sid&gt;/exec</code> <code>{command, timeout}</code></td>\n<td>виконати команду (async) → <code>exec_id</code></td>\n</tr>\n<tr>\n<td><code>GET /&lt;sid&gt;/exec/&lt;exec_id&gt;</code></td>\n<td>опитати вивід</td>\n</tr>\n<tr>\n<td>SFTP-ендпоінти</td>\n<td>завантаження/відправлення файлів, <code>ls</code>, <code>mkdir</code>, <code>rm</code></td>\n</tr>\n</tbody></table>\n<p>Аутентифікація — Bearer-токен, той самий патерн, що й в усіх інших API, які ви використовуєте.</p>\n<h2>Патерн виконання</h2>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># 1. підключіться один раз, перевикористайте сесію для всієї задачі</span>\nSID=$(curl -s -H <span class=\"hljs-string\">&quot;Authorization: Bearer <span class=\"hljs-variable\">$KEY</span>&quot;</span> \\\n  <span class=\"hljs-string\">&quot;https://ssh-proxy.example/connect?target=vps1&quot;</span> | jq -r .session_id)\n\n<span class=\"hljs-comment\"># 2. виконайте команду</span>\nEID=$(curl -s -H <span class=\"hljs-string\">&quot;Authorization: Bearer <span class=\"hljs-variable\">$KEY</span>&quot;</span> -H <span class=\"hljs-string\">&quot;Content-Type: application/json&quot;</span> \\\n  -X POST <span class=\"hljs-string\">&quot;https://ssh-proxy.example/<span class=\"hljs-variable\">$SID</span>/exec&quot;</span> \\\n  -d <span class=\"hljs-string\">&#x27;{&quot;command&quot;: &quot;docker ps --format \\&quot;{{.Names}}\\&quot;&quot;, &quot;timeout&quot;: 120}&#x27;</span> | jq -r .exec_id)\n\n<span class=\"hljs-comment\"># 3. опитайте результат</span>\ncurl -s -H <span class=\"hljs-string\">&quot;Authorization: Bearer <span class=\"hljs-variable\">$KEY</span>&quot;</span> <span class=\"hljs-string\">&quot;https://ssh-proxy.example/<span class=\"hljs-variable\">$SID</span>/exec/<span class=\"hljs-variable\">$EID</span>&quot;</span></code></pre><h2>Правила поведінки</h2>\n<ol>\n<li><strong>Перевикористовуйте сесії.</strong> Підключення на кожну команду марнує ресурси й ловить ліміти частоти. Збережіть <code>session_id</code> (напр. <code>/tmp/vps1_sid</code>) і перевіряйте його heartbeat перед повторним використанням.</li>\n<li><strong>Називайте цілі, а не відкривайте їх.</strong> Цілі попередньо зареєстровані (<code>vps1</code>, <code>pi</code>, …). Проксі — єдине джерело правди; ніколи не зашивайте IP-адреси в код агента.</li>\n<li><strong>Надавайте перевагу SFTP замість cat/heredoc для файлів.</strong> Екранування бінарних даних через <code>exec</code> псує навантаження. Використовуйте виділені ендпоінти завантаження/відправлення.</li>\n<li><strong>Кавичте свої команди.</strong> Тіло JSON парситься двічі (HTTP + shell). Обгортайте віддалені команди в одинарні лапки й тримайте їх в один рядок.</li>\n<li><strong>Вважайте, що аудит ведеться.</strong> Кожен exec потрапляє в журнал аудиту проксі — ведіть себе так, ніби людина читає все (вона може).</li>\n</ol>\n<h2>Коли exec використовувати НЕ варто</h2>\n<ul>\n<li>Читання структурованого стану, який має API (Docker, бази даних, Mind API Synapse) — завжди надавайте перевагу API розбору виводу CLI.</li>\n<li>Довгі інтерактивні процеси. <code>exec</code> — це fire-and-forget з таймаутом; натомість використовуйте <code>nohup</code> + файл статусу на цільовій машині.</li>\n<li>Будь-яке деструктивне дійство без явної інструкції. Проксі дає вам владу — людина дає вам дозвіл.</li>\n</ul>\n<h2>Відновлення після помилок</h2>\n<table>\n<thead>\n<tr>\n<th>Симптом</th>\n<th>Рішення</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>401 при connect</td>\n<td>токен минув — перечитайте його з memory/settings, ніколи з транскрипту</td>\n</tr>\n<tr>\n<td>сесія 404</td>\n<td>сесія минула (ліміт 24 год) — перепідключіться</td>\n</tr>\n<tr>\n<td>таймаут exec</td>\n<td>підніміть <code>timeout</code> або розділіть команду; перевірте навантаження цільової машини</td>\n</tr>\n<tr>\n<td>зіпсований вміст файлу</td>\n<td>ви використали <code>exec</code> замість SFTP — перейдіть на SFTP-ендпоінти</td>\n</tr>\n</tbody></table>\n","urls":{"html":"/docs/llm-cookbook/ssh-proxy-access","text":"/docs/llm-cookbook/ssh-proxy-access?format=text","json":"/docs/llm-cookbook/ssh-proxy-access?format=json","llm":"/docs/llm-cookbook/ssh-proxy-access?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"],"wordCount":341,"readMinutes":2,"llmContext":"НІКОЛИ не тримайте сирі приватні SSH-ключі як LLM. Використовуйте HTTP-API SSH-проксі:\n1) POST /connect?target=<name> → session_id (постійна, живе годинами).\n2) POST /<session_id>/exec {command, timeout} → exec_id.\n3) GET /<session_id>/exec/<exec_id> → вивід після завершення.\n4) Для завантаження/відправлення файлів використовуйте SFTP-ендпоінти замість cat/heredoc.\nЦілі — попередньо зареєстровані імена (напр. \"vps1\"), не IP — проксі — єдине\nмісце, де живуть облікові дані.\n","requestedLang":"uk","contentMarkdown":"\n# SSH-доступ через проксі\n\nАгентам потрібно виконувати команди на віддалених машинах — розгорнути контейнер, прочитати лог, виправити конфіг. Давати сирі приватні SSH-ключі LLM — погана ідея: ключі потрапляють у вікна контексту, логи й транскрипти. SSH-проксі вирішує це: облікові дані зберігає він, агент говорить лише HTTP.\n\n## Модель\n\n```\nLLM ──HTTPS──► SSH-проксі ──SSH──► цільові машини\n                (зберігає ключі,\n                 журнал аудиту,\n                 ліміти частоти)\n```\n\nПроксі віддає постійні сесії через просту REST-поверхню:\n\n| Ендпоінт | Призначення |\n|---|---|\n| `POST /connect?target=vps1` | відкрити сесію → `session_id` |\n| `POST /<sid>/exec` `{command, timeout}` | виконати команду (async) → `exec_id` |\n| `GET /<sid>/exec/<exec_id>` | опитати вивід |\n| SFTP-ендпоінти | завантаження/відправлення файлів, `ls`, `mkdir`, `rm` |\n\nАутентифікація — Bearer-токен, той самий патерн, що й в усіх інших API, які ви використовуєте.\n\n## Патерн виконання\n\n```bash\n# 1. підключіться один раз, перевикористайте сесію для всієї задачі\nSID=$(curl -s -H \"Authorization: Bearer $KEY\" \\\n  \"https://ssh-proxy.example/connect?target=vps1\" | jq -r .session_id)\n\n# 2. виконайте команду\nEID=$(curl -s -H \"Authorization: Bearer $KEY\" -H \"Content-Type: application/json\" \\\n  -X POST \"https://ssh-proxy.example/$SID/exec\" \\\n  -d '{\"command\": \"docker ps --format \\\"{{.Names}}\\\"\", \"timeout\": 120}' | jq -r .exec_id)\n\n# 3. опитайте результат\ncurl -s -H \"Authorization: Bearer $KEY\" \"https://ssh-proxy.example/$SID/exec/$EID\"\n```\n\n## Правила поведінки\n\n1. **Перевикористовуйте сесії.** Підключення на кожну команду марнує ресурси й ловить ліміти частоти. Збережіть `session_id` (напр. `/tmp/vps1_sid`) і перевіряйте його heartbeat перед повторним використанням.\n2. **Називайте цілі, а не відкривайте їх.** Цілі попередньо зареєстровані (`vps1`, `pi`, …). Проксі — єдине джерело правди; ніколи не зашивайте IP-адреси в код агента.\n3. **Надавайте перевагу SFTP замість cat/heredoc для файлів.** Екранування бінарних даних через `exec` псує навантаження. Використовуйте виділені ендпоінти завантаження/відправлення.\n4. **Кавичте свої команди.** Тіло JSON парситься двічі (HTTP + shell). Обгортайте віддалені команди в одинарні лапки й тримайте їх в один рядок.\n5. **Вважайте, що аудит ведеться.** Кожен exec потрапляє в журнал аудиту проксі — ведіть себе так, ніби людина читає все (вона може).\n\n## Коли exec використовувати НЕ варто\n\n- Читання структурованого стану, який має API (Docker, бази даних, Mind API Synapse) — завжди надавайте перевагу API розбору виводу CLI.\n- Довгі інтерактивні процеси. `exec` — це fire-and-forget з таймаутом; натомість використовуйте `nohup` + файл статусу на цільовій машині.\n- Будь-яке деструктивне дійство без явної інструкції. Проксі дає вам владу — людина дає вам дозвіл.\n\n## Відновлення після помилок\n\n| Симптом | Рішення |\n|---|---|\n| 401 при connect | токен минув — перечитайте його з memory/settings, ніколи з транскрипту |\n| сесія 404 | сесія минула (ліміт 24 год) — перепідключіться |\n| таймаут exec | підніміть `timeout` або розділіть команду; перевірте навантаження цільової машини |\n| зіпсований вміст файлу | ви використали `exec` замість SFTP — перейдіть на SFTP-ендпоінти |\n","contentHtml":"<h1>SSH-доступ через проксі</h1>\n<p>Агентам потрібно виконувати команди на віддалених машинах — розгорнути контейнер, прочитати лог, виправити конфіг. Давати сирі приватні SSH-ключі LLM — погана ідея: ключі потрапляють у вікна контексту, логи й транскрипти. SSH-проксі вирішує це: облікові дані зберігає він, агент говорить лише HTTP.</p>\n<h2>Модель</h2>\n<pre><code class=\"hljs language-plaintext\">LLM ──HTTPS──► SSH-проксі ──SSH──► цільові машини\n                (зберігає ключі,\n                 журнал аудиту,\n                 ліміти частоти)</code></pre><p>Проксі віддає постійні сесії через просту REST-поверхню:</p>\n<table>\n<thead>\n<tr>\n<th>Ендпоінт</th>\n<th>Призначення</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>POST /connect?target=vps1</code></td>\n<td>відкрити сесію → <code>session_id</code></td>\n</tr>\n<tr>\n<td><code>POST /&lt;sid&gt;/exec</code> <code>{command, timeout}</code></td>\n<td>виконати команду (async) → <code>exec_id</code></td>\n</tr>\n<tr>\n<td><code>GET /&lt;sid&gt;/exec/&lt;exec_id&gt;</code></td>\n<td>опитати вивід</td>\n</tr>\n<tr>\n<td>SFTP-ендпоінти</td>\n<td>завантаження/відправлення файлів, <code>ls</code>, <code>mkdir</code>, <code>rm</code></td>\n</tr>\n</tbody></table>\n<p>Аутентифікація — Bearer-токен, той самий патерн, що й в усіх інших API, які ви використовуєте.</p>\n<h2>Патерн виконання</h2>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># 1. підключіться один раз, перевикористайте сесію для всієї задачі</span>\nSID=$(curl -s -H <span class=\"hljs-string\">&quot;Authorization: Bearer <span class=\"hljs-variable\">$KEY</span>&quot;</span> \\\n  <span class=\"hljs-string\">&quot;https://ssh-proxy.example/connect?target=vps1&quot;</span> | jq -r .session_id)\n\n<span class=\"hljs-comment\"># 2. виконайте команду</span>\nEID=$(curl -s -H <span class=\"hljs-string\">&quot;Authorization: Bearer <span class=\"hljs-variable\">$KEY</span>&quot;</span> -H <span class=\"hljs-string\">&quot;Content-Type: application/json&quot;</span> \\\n  -X POST <span class=\"hljs-string\">&quot;https://ssh-proxy.example/<span class=\"hljs-variable\">$SID</span>/exec&quot;</span> \\\n  -d <span class=\"hljs-string\">&#x27;{&quot;command&quot;: &quot;docker ps --format \\&quot;{{.Names}}\\&quot;&quot;, &quot;timeout&quot;: 120}&#x27;</span> | jq -r .exec_id)\n\n<span class=\"hljs-comment\"># 3. опитайте результат</span>\ncurl -s -H <span class=\"hljs-string\">&quot;Authorization: Bearer <span class=\"hljs-variable\">$KEY</span>&quot;</span> <span class=\"hljs-string\">&quot;https://ssh-proxy.example/<span class=\"hljs-variable\">$SID</span>/exec/<span class=\"hljs-variable\">$EID</span>&quot;</span></code></pre><h2>Правила поведінки</h2>\n<ol>\n<li><strong>Перевикористовуйте сесії.</strong> Підключення на кожну команду марнує ресурси й ловить ліміти частоти. Збережіть <code>session_id</code> (напр. <code>/tmp/vps1_sid</code>) і перевіряйте його heartbeat перед повторним використанням.</li>\n<li><strong>Називайте цілі, а не відкривайте їх.</strong> Цілі попередньо зареєстровані (<code>vps1</code>, <code>pi</code>, …). Проксі — єдине джерело правди; ніколи не зашивайте IP-адреси в код агента.</li>\n<li><strong>Надавайте перевагу SFTP замість cat/heredoc для файлів.</strong> Екранування бінарних даних через <code>exec</code> псує навантаження. Використовуйте виділені ендпоінти завантаження/відправлення.</li>\n<li><strong>Кавичте свої команди.</strong> Тіло JSON парситься двічі (HTTP + shell). Обгортайте віддалені команди в одинарні лапки й тримайте їх в один рядок.</li>\n<li><strong>Вважайте, що аудит ведеться.</strong> Кожен exec потрапляє в журнал аудиту проксі — ведіть себе так, ніби людина читає все (вона може).</li>\n</ol>\n<h2>Коли exec використовувати НЕ варто</h2>\n<ul>\n<li>Читання структурованого стану, який має API (Docker, бази даних, Mind API Synapse) — завжди надавайте перевагу API розбору виводу CLI.</li>\n<li>Довгі інтерактивні процеси. <code>exec</code> — це fire-and-forget з таймаутом; натомість використовуйте <code>nohup</code> + файл статусу на цільовій машині.</li>\n<li>Будь-яке деструктивне дійство без явної інструкції. Проксі дає вам владу — людина дає вам дозвіл.</li>\n</ul>\n<h2>Відновлення після помилок</h2>\n<table>\n<thead>\n<tr>\n<th>Симптом</th>\n<th>Рішення</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>401 при connect</td>\n<td>токен минув — перечитайте його з memory/settings, ніколи з транскрипту</td>\n</tr>\n<tr>\n<td>сесія 404</td>\n<td>сесія минула (ліміт 24 год) — перепідключіться</td>\n</tr>\n<tr>\n<td>таймаут exec</td>\n<td>підніміть <code>timeout</code> або розділіть команду; перевірте навантаження цільової машини</td>\n</tr>\n<tr>\n<td>зіпсований вміст файлу</td>\n<td>ви використали <code>exec</code> замість SFTP — перейдіть на SFTP-ендпоінти</td>\n</tr>\n</tbody></table>\n","translationsAvailable":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}