# Профили proxy-client и системная служба Дата: 2026-11-02 Статус: реализовано; запуск после загрузки ОС и восстановление настоящей службы systemd требуют отдельной проверки на Linux-ВМ. ## Задача и границы На Linux-ВМ, компьютерах и ноутбуках нужен прокси, доступный после загрузки без входа пользователя и ручного запуска. Приложения уже знают его адрес. Одновременно пользователь должен иметь возможность запустить другой прокси на другом порту в открытом терминале. Это расширяет [первоначальный дизайн](2026-07-15-proxy-client-design.md): добавляет системную службу и несколько пользовательских профилей. Остальные ограничения и принцип личного инструмента сохраняются. Термины определены в [CONTEXT.md](../../CONTEXT.md). Не добавляем несколько системных экземпляров, фоновый пользовательский режим, TUN, системную маршрутизацию, автоматический выбор прокси или поддержку Windows. Для системного режима требуется systemd; ручной режим сохраняет независимость от него. Пакет по-прежнему можно использовать отдельно от остальных dotfiles. ## Пользовательские профили Профиль по умолчанию сохраняет нынешние файлы `~/.config/proxy-client/config` и `default.url`. Отсутствие выбора профиля не меняет поведения существующих команд, включая прежний внешний прокси при отсутствии конфигурации. Учитываются существующие настройки XDG. Дополнительные профили размещаются в `~/.config/proxy-client/profiles/<имя>/`, каждый со своими `config` и `default.url`. Имя `default` обозначает существующий профиль по умолчанию. Неизвестное имя даёт ошибку, а не переход к другому профилю. Один общий параметр выбора профиля действует на запуск, остановку, проверку, вывод окружения и запуск дочерних команд. Существующий выбор файла VLESS-ссылки через `start -f` остаётся разовым переопределением ссылки выбранного профиля. Bash-команды без явного выбора продолжают использовать профиль по умолчанию. Каждый профиль получает собственные сведения о процессе, блокировку и сгенерированный JSON. Запуск и остановка одного не затрагивают остальные. Два экземпляра могут работать одновременно, если их локальные порты различны. Занятый порт даёт ошибку; чужой процесс не останавливается. Ручной запуск остаётся на переднем плане, с выводом в терминал и остановкой через Ctrl+C либо команду остановки выбранного профиля. Само обращение к прокси через `run` или `env` ничего не запускает. ## Bash-команды `proxy_on` без параметров выбирает профиль по умолчанию, с `--profile` — именованный. Он меняет только окружение текущего терминала после успешной проверки. `proxy_off` очищает переменные, но не останавливает процессы. `myip` использует текущее окружение. `pclaude` и `pcodex` принимают ведущий `--proxy-profile` для выбора профиля. Без него остаётся профиль по умолчанию; остальные аргументы и код возврата дочерней программы сохраняются. Обычный `--profile` относится к дочерней программе. Bash-модуль передаёт выбор CLI и не дублирует правила профилей. Выбор через `proxy_on` не меняет профиль по умолчанию: обычная команда наследует окружение, а обёртка с префиксом `p` явно выбирает свой профиль. Это различие должно быть показано в README пакета. ## Системная служба Одна служба `proxy-client.service` читает один комплект настроек из `/etc/proxy-client/`. Ей не нужны именованные профили или домашний каталог пользователя. Исполняемые файлы устанавливаются в системное расположение, без ссылок на пользовательский каталог исходников. Xray работает под отдельной непривилегированной учётной записью и слушает только loopback. Временные файлы процесса, блокировка и сгенерированный JSON находятся в закрытом `/run/proxy-client/`. Секреты доступны только администратору и служебной учётной записи. Пользовательские команды остановки не управляют системным экземпляром: за него отвечает systemd. Установка оформляется одной подкомандой `service install`. В терминале она собирает недостающие настройки, показывает план и после подтверждения выполняет полный переход на службу. `--yes` (`--auto-yes`) принимает план без вопроса. Без терминала для нового подключения нужен закрытый `--file`; секрет не передаётся в argv или окружении. В терминале применяется скрытый ввод. Новый профиль получает адрес `127.0.0.1` и порт `12334` по умолчанию. Для переноса используются сохранённые `config` и `default.url` выбранного профиля; `--file` переопределяет ссылку. Xray ищется в `~/.local/bin`, затем в `PATH` и системной установке. Если его нет, скачивается закреплённая версия с проверкой SHA-256. Параметр `--xray` позволяет указать бинарник явно. Полный переход состоит из подготовки снимка, проверки Xray, установки системных файлов, остановки выбранного ручного процесса и запуска службы. Домашний `config` меняется на `external` только после проверки активного состояния службы и доступности её порта; прежний файл сохраняется рядом. Остановка пользовательского процесса и изменение домашнего профиля выполняются без повышения прав. Sudo применяется только к системной части. Закрытый снимок `service-setup.json` в каталоге состояния профиля позволяет продолжить незавершённый переход. Он содержит исходный домашний config, подготовленный config, VLESS-ссылку и путь для ручного восстановления; права файла `600`, каталога `700`. При повторе домашние и системные настройки сверяются со снимком до остановки процессов. Изменённые настройки не перезаписываются, исходный файл VLESS-ссылки тоже проверяется. Ошибка конфликта указывает команду удаления снимка, чтобы начать заново с текущими настройками; этот сброс не меняет сами настройки и процессы. После успеха снимок удаляется. Ошибка запуска сохраняет прежний домашний профиль; восстановление ручного процесса требует явной команды, прежние соединения не восстанавливаются. Наличие системных файлов само по себе не означает завершённый переход: если домашний профиль ещё `xray`, мастер сверяет его с системным и завершает перенос. Другой профиль не заменяет существующие системные настройки. После завершённого перехода настройки службы самостоятельны. Обычное обновление сохраняет их и включает перезапуск в подтверждаемый план; домашний профиль не меняется и может отсутствовать. `--install-only`, `--config-dir` и `--root` сохраняют режим установки файлов без мастера. Он требует готовых настроек и Xray. Флаги `--enable`, `--start`, `--restart` задают действия явно. `--root` не допускает действий с systemd. В этом режиме установка сама домашний профиль не меняет и ручной процесс не останавливает. Без терминала и без явного выбора режима команда завершается с подсказкой. Systemd отвечает за запуск, остановку и перезапуск после аварии. Явная остановка должна оставлять службу остановленной до следующего запуска. Если автозапуск включён, после перезагрузки она запускается снова. Отсутствие внешней сети при загрузке не должно приводить к окончательному отказу службы. Готовность локального порта и доступность удалённого маршрута различаются: автозапуск не гарантирует успешность первого запроса любого приложения. Для приложений, не умеющих повторять запрос, порядок запуска и ожидание готовности потребуют отдельной настройки. ## Журналы и совместная работа Вывод службы направляется в journald. Отдельный текстовый журнал и собственная ротация не нужны. Хранение между загрузками зависит от настройки journald; установщик проверяет её и сообщает результат, не меняя глобальную политику журналирования машины. Секреты не должны попадать в журнал. Если системная служба занимает порт прежнего пользовательского Xray, второй запуск на этом порту завершается ошибкой. Чтобы использовать системный прокси через пользовательские команды, подходит профиль типа `external`. Для второго Xray нужен другой порт. Мастер меняет домашний профиль по подтверждённому плану; режим установки только файлов его не меняет. ## Устройство модулей Применяем `codebase-design`: выбор профиля и все его пути должны определяться в одном месте, чтобы команды не повторяли правила размещения файлов. Пути, правила доступа к профилю, вывод Xray и подсказка остановки собраны в неизменяемый контекст запуска. Он создаётся при выборе пользовательского или системного режима и явно передаётся функциям. Управление процессом использует готовые значения, без глобального переключателя режима. Системная установка скрывает размещение, права и взаимодействие с systemd за небольшим интерфейсом; не копирует разбор VLESS и управление Xray. Внутри модуль отделяет подготовку плана от его применения: план хранит снимок настроек и исходного процесса, применение управляет порядком действий и возобновлением. Проверки проходят через публичный CLI. Внешние команды подменяются через `PATH`, терминальный ввод, сокеты и загрузка архива — подменой функций стандартной библиотеки в тестовом `sitecustomize`. Разбор настроек и работа с файлами выполняются настоящим кодом. Не вводим обобщённую поддержку других менеджеров служб и дополнительные слои ради возможного будущего использования. Реально различаются пользовательское и системное размещение, а также способ управления процессом. ## Проверки Согласованы три интерфейса для новых тестов TDD: 1. CLI пользовательских профилей: прежнее поведение без имени, выбор именованного профиля, два одновременных процесса, независимая остановка, отказ при занятом порте и правильное окружение дочерней команды. 2. Установка службы через CLI и управление через systemd: размещение файлов, сохранение настроек при повторной установке, явное включение автозапуска, запуск и остановка, восстановление после аварии и доступность журналов. 3. Bash-команды: выбор профиля, передача аргументов и кода возврата, сохранение окружения при ошибке и отсутствие остановки процессов. Тесты проверяют наблюдаемое поведение через эти интерфейсы, а не внутренние функции и последовательности их вызовов. Идём по одному сценарию: падающий тест, минимальная реализация, следующий сценарий. Локальные проверки используют временные каталоги, синтетические профили и подставные внешние программы. Это не доказывает работу настоящего systemd. Окончательная проверка системного режима нужна в отдельной Linux-среде с systemd: запуск до входа пользователя после загрузки, восстановление после аварии, явная остановка и одновременная работа ручного экземпляра. Изменение текущей машины или её перезагрузка не входят в проверку по умолчанию. Проверка после cross-review 2026-11-04: полный набор под псевдотерминалом прошёл на Python 3.8 и 3.14 — по 108 тестов, ещё 12 проверок Bash-команд и 6 проверок пользовательского установщика. Мастер проверен через CLI: настройка с нуля, перенос, обновление, отмена, отказы и продолжение перехода. Скрытый ввод проверен в псевдотерминале. Системные действия и скачивание в этих тестах подменены; настоящие службы не запускались. Shellcheck в среде отсутствует. При первоначальной реализации отдельно проверены Bash-команды вместе с настоящим CLI и двумя локальными тестовыми портами. Unit прошёл статическую проверку в изолированном корне с тестовыми базовыми target-файлами. Эти результаты не заменяют проверку загрузки ОС. ## Документация и альтернативы Подробные инструкции размещены в [`proxy-client/README.md`](../../proxy-client/README.md): профили, системная установка и обновление, управление, автозапуск, журналы и диагностика. В корневом README достаточно существующей ссылки на пакет. Этот документ хранит причины решений; рабочие команды и примеры живут в README пакета. Пользовательская служба с linger позволила бы запускать прокси до входа, но выбрано явное разделение системных и домашних настроек. Несколько именованных системных служб пока не нужны. Запуск в терминале сохраняется для дополнительных прокси, но сам по себе не решает задачу загрузки машины. Правила systemd сверены с документацией [каталогов службы](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#RuntimeDirectory=), [перезапуска](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#Restart=) и [хранения журналов](https://www.freedesktop.org/software/systemd/man/latest/journald.conf.html#Storage=).