Чтобы работать с Codex в консоли удалённого сервера, нужно арендовать VPS с Ubuntu, подключиться по SSH, установить Codex CLI и войти в свой аккаунт ChatGPT. После этого можно просить помощника разбирать проект, менять файлы и запускать тесты прямо на сервере.
Я покажу весь путь на небольшом учебном проекте: подготовим CSV с расходами и поручим Codex написать программу для подсчёта итогов. В конце проверим результат и научимся возвращаться в рабочий сеанс после закрытия терминала.
Инструкция рассчитана на Ubuntu 24.04 LTS, процессор x86_64 и Codex CLI 0.155.0. Документация и версия CLI сверены 18 сентября 2026 года. На компьютере подойдут Терминал в macOS или Linux и PowerShell в Windows 10/11. Покупку VPS выполняете вы в своём аккаунте; вид панели и доступность тарифов могут отличаться.
Что будет работать на сервере
VPS — виртуальный сервер: отдельная Linux-система с собственным адресом и диском. На нём будут храниться проект и история терминальных сеансов. Codex CLI получает ваше задание, обращается к модели OpenAI и выполняет разрешённые действия в рабочем каталоге.
Саму модель на VPS мы не устанавливаем. Поэтому для этого упражнения не нужна видеокарта. Потребность в памяти и процессоре определяется прежде всего программами, которые вы запускаете: маленький Python-скрипт и сборка большого приложения требуют разных ресурсов.
Вход через ChatGPT использует доступ и лимиты вашего аккаунта. Это не безлимитный режим: доступные модели и объём работы зависят от плана и настроек рабочего пространства. Перед арендой сервера проверьте, что можете войти в ChatGPT и что Codex доступен вашему аккаунту. API-ключ для этой инструкции не нужен.
VPS удобен, когда хочется возвращаться к одной рабочей среде с разных компьютеров или оставлять задачу выполняться после отключения SSH. Для знакомства с Codex можно обойтись собственным компьютером, но ниже я разбираю именно удалённый сервер.
1. Выбираем VPS и готовим оплату
Для первого учебного проекта я бы взял обычный VPS с общими процессорными ресурсами: 2 vCPU, 4 ГБ RAM и 40 ГБ SSD, публичным IPv4 и доступом по SSH. Это конфигурация с запасом для небольших экспериментов, а не официальный минимум Codex. Платная панель управления, GPU и предустановленный веб-сервер здесь не нужны.
Перед заказом проверьте три вещи:
- Провайдер регистрирует клиентов из вашей страны, принимает доступный вам способ оплаты и показывает итоговую сумму с налогами.
- Есть образ Ubuntu 24.04 LTS x86_64, SSH-ключи и консоль восстановления на случай ошибки в настройках доступа.
- Понятна полная стоимость: сервер, IPv4, резервные копии и дополнительные диски. Известно, как удалить ресурсы и остановить начисления.
Также проверьте доступность сервисов OpenAI для своей страны и выбранного региона сервера. Зарубежный IP сам по себе не гарантирует доступность аккаунта.
В качестве примера панели я использую Hetzner Cloud. Если регистрация или оплата вам недоступна, выбирайте другого провайдера по тем же параметрам. Команды после получения Ubuntu останутся такими же, но первоначальный пользователь может называться ubuntu, а не root.
Не оплачивайте год вперёд ради первого эксперимента. Сначала проверьте короткий период использования, доступ к серверу и вход в Codex. У Hetzner выключение виртуальной машины не прекращает оплату: выделенные ресурсы продолжают учитываться до удаления. Снимки, диски и IP тоже проверяйте отдельно.
2. Создаём SSH-ключ на своём компьютере
SSH — зашифрованное подключение к командной строке сервера. Для входа подготовим пару ключей. Открытую часть загрузим провайдеру, закрытая останется на компьютере.
На своём компьютере откройте терминал и проверьте клиент:
ssh -V
В Windows, если команда не найдена, установите компонент OpenSSH Client через дополнительные компоненты Windows и заново откройте PowerShell.
Создайте ключ:
ssh-keygen -t ed25519 -C "codex-vps"
Программа спросит путь сохранения. Если ключей ещё нет, примите предложенный путь Enter. Если файл уже существует, не подтверждайте перезапись: укажите другое имя, например id_ed25519_codex, в том же каталоге .ssh. Ниже команды предполагают имя id_ed25519; для другого имени замените его везде, включая путь после -i.
Задайте парольную фразу и повторите её. Вводимые символы не отображаются — это нормально. Парольная фраза защищает закрытый ключ на вашем компьютере.
Выведите открытый ключ. В macOS и Linux:
cat ~/.ssh/id_ed25519.pub
В PowerShell:
Get-Content "$HOME\.ssh\id_ed25519.pub"
Скопируйте всю строку, начинающуюся с ssh-ed25519. Файл без окончания .pub никуда не загружайте: это закрытый ключ.
3. Заказываем сервер с Ubuntu
В браузере откройте официальный сайт Hetzner, перейдите в Cloud → Console, зарегистрируйтесь и завершите проверку аккаунта. Заполните платёжные данные и выберите предложенный в вашем аккаунте способ оплаты. Если сервис запрашивает подтверждение личности, завершите его до заказа.
В панели создайте проект, например codex-lab. Внутри проекта откройте Servers → Add server и заполните параметры:
- Location: доступный вам регион с подходящими условиями доступа к OpenAI.
- Image: Ubuntu 24.04 LTS, обычный образ ОС.
- Type: x86_64, общие vCPU, не менее выбранных 2 vCPU и 4 ГБ памяти; сверяйте объём диска в карточке.
- Networking: публичный IPv4; IPv6 можно оставить дополнительно.
- SSH keys: добавьте скопированную строку
.pubи отметьте этот ключ для нового сервера. - Name:
codex-lab.
Дополнительный диск и приложение из каталога для упражнения не нужны. Если подключаете облачный Firewall, разрешите входящий TCP-порт 22 со своего IP. Исходящие соединения должны позволять загрузку пакетов и HTTPS-запросы к OpenAI. Для первого запуска не добавляйте неизвестные вам ограничивающие правила.
Перед Create & Buy now сверьте итоговую стоимость и все платные дополнения. Эта кнопка создаёт оплачиваемый ресурс. Дождитесь запуска сервера и скопируйте его публичный IPv4.
Дальше в командах я использую 203.0.113.10 — это адрес для примера. В каждой команде заменяйте его на адрес своего VPS.
4. Подключаемся и создаём рабочего пользователя
На своём компьютере выполните:
ssh -i ~/.ssh/id_ed25519 root@203.0.113.10
В PowerShell при необходимости запишите путь явно:
ssh -i "$HOME\.ssh\id_ed25519" root@203.0.113.10
При первом подключении SSH покажет отпечаток ключа сервера и попросит подтвердить доверие. Сверьте его с данными провайдера или через доверенную веб-консоль сервера. В консоли отпечаток Ed25519 можно получить командой:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
После совпадения введите yes в SSH-клиенте. Если потребуется, введите парольную фразу своего ключа. После входа команды выполняются уже на VPS.
На сервере, под root, проверьте ОС и архитектуру:
cat /etc/os-release
uname -m
Ожидаем Ubuntu 24.04 и x86_64. При другом образе остановитесь и проверьте заказ: дальше команды рассчитаны на Ubuntu.
Обновите пакеты и установите инструменты:
apt update
apt upgrade -y
apt install -y ca-certificates curl git tmux python3 nodejs npm ufw bubblewrap
git сохранит версии проекта, tmux удержит терминальный сеанс после отключения SSH, Python понадобится для учебной программы. Node.js и npm используем для установки CLI. Если обновление просит перезагрузку, выполните reboot, дождитесь запуска сервера и подключитесь снова.
Не будем работать с Codex под root. Создайте пользователя dev:
adduser dev
usermod -aG sudo dev
install -d -m 700 -o dev -g dev /home/dev/.ssh
install -m 600 -o dev -g dev /root/.ssh/authorized_keys /home/dev/.ssh/authorized_keys
adduser попросит новый пароль: он понадобится для sudo. Не путайте его с парольной фразой SSH-ключа. Необязательные поля имени и телефона можно пропустить Enter. Копирование authorized_keys подходит для нового сервера, созданного с вашим SSH-ключом; если файла нет, сначала выясните, какой способ входа настроил провайдер.
Не закрывая root-сессию, откройте второе окно терминала на своём компьютере:
ssh -i ~/.ssh/id_ed25519 dev@203.0.113.10
В новом соединении проверьте:
whoami
sudo -v
Первая команда должна показать dev, вторая — принять пароль нового пользователя. Если вход не работает, исправляйте его в оставленной root-сессии.
На VPS, под dev, разрешите SSH перед включением межсетевого экрана:
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
Подтвердите включение. В выводе должны быть активный firewall и правило OpenSSH ALLOW. Мы используем стандартный порт 22; если вы его меняли, правило нужно адаптировать. Снова проверьте подключение из отдельного окна. Только после этого закрывайте исходную root-сессию командой exit.
5. Устанавливаем Codex без sudo
Все дальнейшие команды выполняйте на VPS под dev. Проверим зависимости:
node --version
npm --version
python3 --version
Для указанной версии npm-пакета Codex требуется Node.js не ниже 16. Пакет Node.js из Ubuntu 24.04 подходит для этой установки. Для будущих версий CLI требования нужно сверять заново.
Установим зафиксированную версию в личный каталог, чтобы не выдавать npm права администратора:
mkdir -p "$HOME/.local/bin"
npm install --global --prefix "$HOME/.local" @openai/codex@0.155.0
export PATH="$HOME/.local/bin:$PATH"
Сохраним путь для следующих SSH-сеансов:
printf '\nexport PATH="$HOME/.local/bin:$PATH"\n' >> "$HOME/.bashrc"
Эту строку добавляют один раз. Проверьте установку:
command -v codex
codex --version
codex login --help
Путь должен вести в /home/dev/.local/bin, версия — codex-cli 0.155.0. Номер зафиксирован, чтобы инструкция воспроизводилась; это не обещание, что он всегда останется последним.

Проверка установленного CLI в учебной среде Ubuntu 24.04. Справка показывает команды входа; она ещё не подтверждает авторизацию.
6. Входим через аккаунт ChatGPT
На VPS нет графического браузера, поэтому используем вход по коду устройства. В настройках безопасности своего аккаунта ChatGPT разрешите Device code login, если эта настройка доступна. В рабочем пространстве разрешением может управлять администратор.
На VPS запустите:
codex login --device-auth
CLI покажет адрес страницы входа и временный код. Откройте выданную страницу в браузере своего компьютера, войдите в нужный аккаунт ChatGPT и введите код. Оставьте команду на сервере работающей до подтверждения. Не отправляйте код в переписку и не используйте код из чужой инструкции.
Проверьте результат:
codex login status
Ожидаемый статус:
Logged in using ChatGPT

Так выглядит подтверждённый вход через ChatGPT. Одноразовый код и данные аккаунта на скриншот не попадают.
Если вход по коду устройства недоступен, используйте SSH-туннель. На своём компьютере откройте новое подключение:
ssh -i ~/.ssh/id_ed25519 -L 1455:localhost:1455 dev@203.0.113.10
Внутри этого соединения на VPS выполните:
codex login
Откройте напечатанный адрес в браузере своего компьютера. Туннель доставит ответ браузера на серверный порт 1455. Не открывайте 1455 в публичном firewall: он нужен только внутри SSH-туннеля. После входа снова проверьте codex login status.
Не переносите на сервер историю браузера и cookies. Если CLI сохраняет данные входа в ~/.codex/auth.json, относитесь к этому файлу как к паролю: не добавляйте в Git и не показывайте в скриншотах.
7. Готовим проект и запускаем рабочий сеанс
На VPS под dev создайте каталог:
mkdir -p ~/projects/codex-demo
cd ~/projects/codex-demo
tmux new -s codex
Вы окажетесь внутри нового терминального сеанса. Снаружи почти ничего не изменится, но внизу появится строка состояния tmux. Даже если SSH-соединение пропадёт, сеанс продолжит работать, пока работает сервер.
Создайте учебные данные. Блок нужно вставлять полностью, включая последнюю строку EOF:
cat > expenses.csv <<'EOF'
category,amount
hosting,200
software,100
hosting,50
EOF
Здесь расходы в условных денежных единицах: 250 на хостинг и 100 на программы. Ожидаемый общий итог — 350. Это вымышленные данные для упражнения.
Добавьте инструкции проекту:
cat > AGENTS.md <<'EOF'
# Учебный проект
Используй Python 3 и только стандартную библиотеку.
Работай только в текущем каталоге. Не используй сеть и sudo.
Не читай файлы за пределами проекта и не обращайся к секретам.
Денежные суммы считай через decimal.Decimal.
После изменений запусти тесты и покажи результат.
Не создавай коммиты: я просмотрю изменения сам.
EOF
Codex читает AGENTS.md как инструкции проекта. Это удобное место для требований к работе, но сам файл не заменяет ограничения доступа. Режим доступа будем задавать явно при запуске CLI.
Сохраним исходное состояние в Git — локальной истории изменений:
printf '__pycache__/\n.venv/\n' > .gitignore
git init -b main
git config user.name "Ваше имя"
git config user.email "you@example.com"
git add expenses.csv AGENTS.md .gitignore
git commit -m "Initial demo data"
В двух строках git config укажите своё имя и адрес: они попадут в подпись коммитов. Это настройка только текущего проекта, регистрации на GitHub не требуется.
8. Получаем код от Codex и проверяем его
Начнём с последовательности, в которой хорошо видны границы действий: Codex подготовит программу по запросу, CLI сохранит ответ в файл, а запускать и проверять программу будем мы сами. Для этой задачи агенту не требуется читать файлы или выполнять команды.
В каталоге проекта создайте файл с заданием. Вставьте весь блок:
cat > task.txt <<'PROMPT'
Ответь только исходным кодом Python, без Markdown и пояснений. Не
вызывай инструменты, не читай файлы и не запускай команды: все
требования ниже. Скрипт summarize.py запускается как python3
summarize.py expenses.csv. CSV содержит category,amount. Используй
только стандартную библиотеку и decimal.Decimal. Группируй суммы по
category, печатай категории по алфавиту в формате hosting: 250.00, затем
TOTAL: 350.00. Суммы выводи с двумя знаками. Для CSV category,amount с
тремя строками hosting,200 и software,100 и hosting,50 ожидается
hosting: 250.00 затем software: 100.00 затем TOTAL: 350.00. Для файла
только с заголовком — TOTAL: 0.00. При неверной, бесконечной или NaN
сумме, пустой категории, неверных колонках, отсутствии файла или
аргумента выведи понятную ошибку в stderr и верни ненулевой exit code
без traceback. Отрицательные конечные суммы разрешены. Программа ничего
не меняет в файловой системе. Не создавай тесты или коммиты.
PROMPT
В запросе заданы формат входных данных, ожидаемый результат и обработка ошибок. Decimal нужен для десятичных сумм: так мы избегаем характерных для float погрешностей представления. Данные упражнения переданы прямо в запросе, поэтому чтение проекта агентом не требуется.
В терминале VPS выполните:
codex exec --sandbox read-only --output-last-message summarize.py - < task.txt
exec выполняет один запрос без интерактивного диалога. Знак - передаёт текст задания из стандартного ввода; < task.txt подставляет содержимое файла. --output-last-message сохраняет заключительный ответ Codex в summarize.py. Этот файл записывает сам CLI; режим read-only ограничивает инструменты агента и не запрещает сохранение явно указанного выходного файла.
Дождитесь окончания команды. Информация о ходе работы может отображаться в терминале, но в summarize.py должен попасть только Python-код. Команда использует уже выполненный вход через ChatGPT; нового API-ключа не нужно. Повторный запуск с тем же именем перезапишет файл — после ручных правок сохраняйте новый ответ под другим именем.
Сначала прочитайте код, затем проверьте синтаксис:
cat summarize.py
python3 -m py_compile summarize.py
Проверьте, что файл содержит Python без Markdown-ограждений, читает только переданный CSV и ничего не удаляет, не отправляет в сеть и не запускает через оболочку. Не запускайте непонятный код с sudo. Успешный py_compile подтверждает синтаксис, но ещё не правильность подсчёта.
Теперь запустите программу:
python3 summarize.py expenses.csv
Ожидаемый вывод:
hosting: 250.00
software: 100.00
TOTAL: 350.00
Добавим независимую от сгенерированной реализации проверку: она запускает программу как отдельную команду и сравнивает выход. Скопируйте готовый тест:
cat > test_summarize.py <<'PYTEST'
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
SCRIPT = Path(__file__).with_name("summarize.py")
class SummaryTests(unittest.TestCase):
def run_csv(self, content):
with tempfile.TemporaryDirectory() as directory:
path = Path(directory) / "input.csv"
path.write_text(content, encoding="utf-8")
return subprocess.run(
[sys.executable, str(SCRIPT), str(path)],
capture_output=True, text=True, timeout=10,
)
def test_normal(self):
result = self.run_csv(
"category,amount\nhosting,200\nsoftware,100\nhosting,50\n"
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout,
"hosting: 250.00\nsoftware: 100.00\nTOTAL: 350.00\n")
def test_decimal(self):
result = self.run_csv("category,amount\nhosting,1.10\nhosting,2.20\n")
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout, "hosting: 3.30\nTOTAL: 3.30\n")
def test_empty(self):
result = self.run_csv("category,amount\n")
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout, "TOTAL: 0.00\n")
def test_invalid(self):
for amount in ("oops", "NaN", "Infinity"):
with self.subTest(amount=amount):
result = self.run_csv(f"category,amount\nhosting,{amount}\n")
self.assertNotEqual(result.returncode, 0)
self.assertTrue(result.stderr.strip())
self.assertNotIn("Traceback", result.stderr)
if __name__ == "__main__":
unittest.main()
PYTEST
python3 -m unittest -v
Проверяем обычный CSV, дробные суммы, файл только с заголовком и неправильные суммы, включая NaN и бесконечность. В конце должно быть OK. Если вывод отличается, не сохраняйте результат как рабочую версию: дополните задание конкретной ошибкой и повторите генерацию в новый файл, например summarize-fixed.py. Просмотрите его и только затем замените исходный.

Реальный запуск учебного примера на Ubuntu 24.04. Codex сгенерировал код; программу и тесты запустили отдельными командами в терминале. У вас реализация может отличаться, но проверяемый результат тот же.
Теперь посмотрите состояние Git:
git status --short
git diff
Новые файлы помечаются ?? и не отображаются обычным git diff. Добавьте только ожидаемые файлы в область подготовки коммита и посмотрите их содержимое:
git add task.txt summarize.py test_summarize.py
git diff --cached
git add ещё не сохраняет коммит. Он позволяет увидеть новые файлы в git diff --cached. Если в каталоге появились другие файлы, сначала разберитесь, зачем они нужны. Когда код просмотрен, а проверки пройдены:
git commit -m "Add expense summary and tests"
Локальный Git помогает вернуться к проверенной версии, но не заменяет резервную копию. Для настоящего проекта отдельно настройте сохранение кода за пределами VPS.
Как перейти к диалогу и изменениям файлов
Для разговора с Codex откройте интерактивный режим:
codex --sandbox read-only --ask-for-approval on-request
Например, попросите: «Объясни разницу между CSV и JSON на коротком примере. Не используй инструменты». Это обычный диалог в терминале. Для выхода в оболочку используйте /quit.
Codex также умеет сам читать проект, менять файлы и запускать проверки. Для этого в каталоге проекта запускают:
codex --sandbox workspace-write --ask-for-approval on-request
Если CLI запросит доверие каталогу, проверьте путь. workspace-write разрешает изменения в рабочем каталоге; on-request означает запрос подтверждения там, где он требуется, а не перед каждой записью файла.
Пример следующего задания: «Добавь в summarize.py аргумент --category для фильтра по категории. Сначала объясни план, затем внеси изменение и добавь тест. Сохрани прежнее поведение без аргумента. Не используй сеть и sudo, не создавай коммиты».
Этот режим требует работоспособной Linux-песочницы. В ограниченном контейнере она может не запуститься даже при правильной установке Codex. Если возникает ошибка bwrap, не отключайте защиту ради упражнения: используйте уже показанную генерацию кода без инструментов и запускайте проверки самостоятельно. Самостоятельные действия агента — отдельный шаг после проверки совместимости среды.
9. Отключаемся и возвращаемся к работе
Чтобы оставить tmux-сеанс работающим, нажмите Ctrl+B, отпустите клавиши, затем нажмите D. Это последовательность, а не три клавиши одновременно.
Вы вернётесь во внешнюю оболочку SSH. Теперь можно завершить соединение:
exit
Позже на своём компьютере снова подключитесь:
ssh -i ~/.ssh/id_ed25519 dev@203.0.113.10
На VPS проверьте сеансы и войдите в нужный:
tmux ls
tmux attach -t codex

На скриншоте проверка выполнена в отдельном тестовом сокете tmux (-L article-demo), чтобы не затрагивать другие сеансы. В своих командах этот параметр добавлять не нужно. Имя codex — метка терминального сеанса. tmux сохраняет запущенные процессы при отключении SSH, но не переживает перезагрузку VPS.
Если сервер перезагрузился, создайте tmux-сеанс заново, перейдите в проект и откройте предыдущий разговор Codex:
cd ~/projects/codex-demo
tmux new -s codex
codex resume
Выберите нужный разговор в списке. История Codex и живой процесс tmux — разные вещи: восстановление разговора не возвращает оборванную команду в память. Проверьте git status и состояние файлов перед продолжением.
Что делать при ошибке
SSH отвечает Permission denied (publickey). Проверьте пользователя (root при первом входе или dev после настройки), адрес и файл после -i. Ключ должен быть выбран при создании сервера. Добавление ключа в панель после покупки не означает, что он автоматически появился внутри уже созданной Ubuntu. Для dev проверьте authorized_keys из оставленной root-сессии.
SSH долго ждёт и завершается с timeout. Проверьте, запущен ли VPS, выбран ли публичный IPv4 и открыт ли TCP 22 в облачном firewall. Если ошиблись в UFW, используйте консоль восстановления провайдера. Не удаляйте правила наугад через единственное оставшееся соединение.
После повторного входа codex: command not found. Проверьте наличие файла ~/.local/bin/codex и строку PATH в ~/.bashrc. Для текущего сеанса выполните:
export PATH="$HOME/.local/bin:$PATH"
codex --version
Вход по коду устройства не разрешён. Проверьте настройку Device code login и права рабочего пространства. Если она недоступна, используйте описанный SSH-туннель. При Address already in use порт 1455 уже занят: закройте старый туннель или приложение, которое его использует, и повторите подключение.
Codex сообщает о лимите аккаунта. Проверьте план, доступные модели и время восстановления лимита в своём аккаунте. Более мощный VPS лимит ChatGPT не увеличит. Для продолжения не требуется переходить на API, если вы хотите работать через аккаунт ChatGPT.
Команда заблокирована песочницей. Прочитайте причину и проверьте, требуется ли действие задаче. Для учебного CSV достаточно файлов проекта и Python. Не устраняйте любую ошибку запуском под root или отключением всех ограничений. Если сам механизм изоляции не запускается, сохраните текст ошибки и проверьте совместимость окружения с Codex.
Как пользоваться этой средой дальше
Начинайте новую задачу с отдельного каталога и сохранённого состояния Git. В запросе указывайте конкретный результат, ограничения и способ проверки: например, «найди причину ошибки, добавь тест, исправь, покажи изменённые файлы». Не начинайте с просьбы «настрой весь сервер»: сначала освоите контроль одной небольшой задачи.
Для обычного возвращения к работе достаточно SSH, tmux attach -t codex и текущего проекта. В интерактивном режиме команда /status показывает состояние сеанса; codex resume помогает выбрать сохранённый разговор. Обновлять CLI лучше между задачами, сохранив рабочую версию кода:
npm install --global --prefix "$HOME/.local" @openai/codex@latest
codex --version
Это установит версию, актуальную на момент запуска; её поведение может отличаться от показанного. Если закончили пользоваться сервером, сохраните нужные файлы вне VPS, выполните codex logout и удалите ненужные ресурсы в панели провайдера, проверив оставшиеся начисления.