Что делать, если не проходит подпись по SSH на удалённом Mac в Xcode 27? Диагностика 2026

Руководство для разработчиков, у которых Archive на удалённом Mac проходит в графическом сеансе, но падает при запуске через SSH. Вы последовательно проверите пользователя задания, доступность связки ключей, закрытый ключ и соответствие сертификата профилю, а затем подтвердите исправление реальным Archive.

Apple Developer Technical Support указывает, что errSecInternalComponent может возникать при подписи через SSH или CI; заблокированная связка ключей — лишь одна из возможных причин (разбор Apple DTS). Поэтому, если один и тот же проект подписывается в графическом сеансе, но падает при SSH-сборке, сначала проверьте пользователя задания, состояние связки ключей и доступ codesign к закрытому ключу. Не начинайте с отзыва сертификатов: ошибка сама по себе не указывает на единственную причину.

Материал подойдёт разработчикам, которые запускают xcodebuild archive по SSH на удалённом Mac и получают ошибку на этапе CodeSign.
Он также пригодится небольшой команде, если CI или другой фоновый процесс работает не от того пользователя, чья среда проверялась вручную.
Если сертификат уже найден, но подпись не проходит, здесь можно отделить проблему доступа к ключу от ошибки сертификата или Provisioning Profile.

00Сначала определите этап, на котором падает сборка

Не всякая ошибка после запуска xcodebuild является ошибкой подписи. Сборка может остановиться при компиляции, на этапе CodeSign или позже — например, при загрузке уже собранного приложения. У этих случаев разные причины, поэтому начните с журнала, а не с изменений в сертификатах.

Сохраните полный вывод команды и найдите первое сообщение CodeSign, Signing или errSecInternalComponent. Важен именно первый сбой: последующие сообщения часто лишь показывают, что зависимая операция не состоялась. Если в логе сначала появляется ошибка компилятора или отсутствующего ресурса, устраняйте её до проверки подписи.

Для сравнения запустите сборку того же проекта из графического сеанса и из SSH, используя одинаковые схему, конфигурацию и параметры Archive. Затем сопоставьте сообщения и настройки, а не только итоговый статус. Для Xcode 27 проверьте также замечания о подписи и известных проблемах в официальных Release Notes: поведение конкретной версии нельзя выводить из случая, зафиксированного на другой версии.

Наблюдение Вероятный уровень проблемы Что проверить сначала
Компиляция завершается ошибкой до CodeSign Исходный код, зависимости, настройки сборки Первую ошибку компилятора и различия параметров запуска
Сбой появляется на CodeSign только через SSH Пользователь, контекст сеанса, связка ключей или доступ к закрытому ключу Учетную запись процесса, доступность ключа и сообщения codesign
Archive проходит, но загрузка не выполняется Этап передачи или проверки загружаемого пакета Отдельный лог загрузки и требования к экспортированному артефакту

После определения этапа сопоставьте окружения. В графическом сеансе откройте Terminal и проверьте, кто запускает процесс, какой каталог пользователя используется и какие настройки Xcode применяются. В SSH выполните те же проверки. Команда, которая запускается без ошибки, ещё не доказывает, что у неё тот же пользователь, домашний каталог или доступ к ключу.

01Проверьте пользователя задания и контекст запуска

Как подтвердить, что SSH-сборка работает от нужного пользователя?

Сравните имя учетной записи и домашний каталог в SSH-сеансе с данными процесса, который действительно запускает xcodebuild. В отдельной CI-системе или планировщике важен не только пользователь интерактивного входа, но и учетная запись задания: именно её права определяют, какие пользовательские файлы и связки ключей доступны.

Выполните в SSH-сеансе диагностические команды:

id
printf '%s\n' "$HOME"

Затем проверьте, от какой учетной записи запускается сам процесс сборки. Если задание передаёт выполнение вспомогательному скрипту, службе или планировщику, проверяйте контекст этого процесса, а не только первоначальное SSH-подключение. Техническое описание Apple о контекстах Daemons и Agents помогает понять, почему фоновое выполнение не следует автоматически считать эквивалентом пользовательского графического сеанса.

Не переключайте сборку на root как способ «получить больше прав». Это может изменить домашний каталог, набор доступных связок ключей и расположение пользовательских настроек, то есть создать ещё одно отличие от успешного графического запуска. Запишите фактического исполнителя задачи и сопоставьте его с владельцем связки ключей, где хранится идентичность для подписи.

Если проверяется среда удалённого доступа, а не только локальная команда, сверьте используемый способ подключения с разделом помощи NUKCLOUD. Это поможет не смешивать особенности SSH-сеанса с параметрами доступа к самому удалённому Mac.

Проверка Графический запуск SSH или фоновое задание
Исполнитель процесса Учетная запись текущего сеанса Учетная запись, от имени которой реально запущен xcodebuild
Домашний каталог Каталог активного пользователя Значение $HOME процесса сборки
Связка ключей Видимая пользователю связка Связка, доступная процессу в его контексте
Окружение Xcode Выбранная версия и настройки Фактические параметры задания и путь к инструментам

Переходите дальше, если исполнитель и каталог пользователя совпадают либо их различия уже объяснены. Если не совпадают — сначала исправьте конфигурацию задания и повторите исходную команду. Иначе дальнейшие изменения связки ключей могут затронуть не ту учетную запись.

02Разберите доступ к связке ключей и закрытому ключу

Почему SSH-запуск xcodebuild возвращает errSecInternalComponent?

Такое сообщение не является диагнозом одной конкретной неисправности. Apple DTS указывает, что оно встречается в нестандартном контексте подписи, включая SSH и CI, а заблокированная связка ключей может быть одной из причин. Следовательно, его нужно сопоставить с состоянием ключей и журналом текущего процесса, а не трактовать как доказательство испорченного сертификата.

В графическом режиме система может показать запрос разблокировки или разрешения доступа. SSH-задание не следует считать способным подтвердить такой запрос через интерфейс: если операция ожидает интерактивного ответа, сборка может остановиться или завершиться ошибкой. Это не означает, что каждый SSH-сценарий обязательно требует одинаковой настройки; конкретное поведение зависит от контекста процесса и способа хранения идентичности.

Сначала выясните, в какой связке находится используемая идентичность и доступна ли она именно пользователю сборки. Проверить список настроенных связок и найденные identities можно диагностическими командами:

security list-keychains -d user
security find-identity -v -p codesigning

Сопоставьте результат с графическим сеансом. Пустой список в SSH может означать не отсутствие сертификата на машине, а то, что процесс ищет идентичность в другом пользовательском контексте. Сведения Apple о том, как хранится identity в Keychain, важны для этого различения: для подписи нужна доступная идентичность, а не просто установленный сертификат.

Что проверить, если связка уже разблокирована, но codesign всё равно падает?

Разблокированная связка сама по себе не подтверждает, что процессу разрешено использовать находящийся в ней закрытый ключ. Убедитесь, что выбранная identity содержит соответствующий закрытый ключ, и проверьте, получает ли codesign доступ к нему в контексте задачи. Apple описывает identity как набор, используемый для криптографической подписи; учитывайте эту разницу, когда проверяете состав записи и доступ к ключу.

Если идентичность отображается неполной или нужный процесс не может обратиться к ключу, не применяйте без разбора одну команду изменения ACL или разрешений ко всей связке. Доступ зависит от того, как ключ был импортирован и как настроена среда. Сначала выясните, какой сертификат и ключ нужны конкретному заданию, затем проверьте разрешения для этой пары и повторите тест в том же контексте. Описание типов сертификатов и рекомендаций по их защите следует использовать для проверки типа и обращения с сертификатом, а не как универсальную инструкцию по исправлению любой SSH-ошибки.

Признак в диагностике Что он поддерживает как гипотезу Что не следует заключать без проверки
SSH не видит identity, которая доступна в графическом сеансе Другая учетная запись, связка или пользовательский контекст Что сертификат обязательно удалён
Identity найдена, но подпись завершается ошибкой доступа Недоступность закрытого ключа или запроса разрешения Что любая настройка ACL даст универсальное исправление
Ошибка указывает на несовпадение идентификатора приложения или профиля Проблему согласованности подписываемого приложения и профиля Что причиной непременно является разблокировка Keychain
Сбой возникает до CodeSign Ошибку компиляции, ресурсов или настроек сборки Что нужно менять сертификаты

Как отличить ошибку связки ключей от несовпадения профиля?

Смотрите на конкретный объект, названный в диагностике. Если codesign не может получить доступ к identity или закрытому ключу, продолжайте проверку контекста и разрешений. Если Xcode сообщает о неподходящем Provisioning Profile, неверном идентификаторе приложения или несовместимой команде разработчика, отдельно проверьте подпись, Bundle ID, Team и профиль. Это разные уровни, и исправление одного не гарантирует устранения другого.

Сначала подтвердите, что сертификат действителен и относится к нужной команде. Затем сравните Bundle ID приложения с тем, для которого выпущен Provisioning Profile. Проверьте, что используемый профиль соответствует типу сборки и выбранной схеме. Apple разбирает редактирование, загрузку и повторное создание профилей; обращайтесь к этим действиям только тогда, когда сообщение об ошибке действительно указывает на профиль или его параметры.

Не отзывайте и не создавайте заново сертификаты «на всякий случай». Это может затронуть другие сборки команды, тогда как SSH-причина — например, неверный исполнитель задачи или недоступная связка — останется. Для поиска ошибок по подписи полезен официальный индекс Apple по диагностике проблем iOS Code Signing. Если в итоговом приложении есть ошибка Entitlements, проверяйте её отдельно по инструкции Apple о диагностике Entitlements.

03Условия выбора следующего шага

Используйте эти ветви после сбора логов; каждая из них предполагает проверку конкретного признака, а не попытку угадать причину по одному коду ошибки.

  • Если в графическом сеансе подпись проходит, а SSH-задание работает от другого пользователя или с другим $HOME, сначала исправьте контекст задания и повторите сборку.
  • Если пользователь совпадает, но identity не видна в SSH, выясните, какую связку использует процесс, и проверьте, доступна ли она этому пользователю.
  • Если связка доступна, identity найдена, но codesign не использует закрытый ключ, исследуйте разрешение на доступ к ключу и способ его импорта; не меняйте сертификат до подтверждения проблемы с самой identity.
  • Если лог явно указывает на Bundle ID, Team, сертификат или Provisioning Profile, сверяйте соответствующий параметр с приложением и типом сборки, оставляя проблему SSH-контекста отдельной гипотезой.
  • Если ошибка появляется до этапа CodeSign, вернитесь к первому сообщению компиляции или подготовки Archive: проверки Keychain не исправят сбой, который возникает раньше.
  • Если причина не подтверждена ни одной из ветвей, сохраните исходный лог и зафиксируйте условия запуска, затем сравните их с успешным графическим запуском. Не объявляйте errSecInternalComponent доказательством конкретного дефекта.

Эти условия предотвращают типичную ошибку диагностики: одновременно менять права связки, сертификат, профиль и параметры задания. При таком подходе даже успешный повторный запуск не покажет, какое изменение помогло, и не даст воспроизводимого исправления.

04Подтвердите исправление через Archive

После изменения запускайте не отдельную ручную подпись, а репрезентативный Archive проекта. Используйте тот же SSH-пользователь, рабочую схему и конфигурацию, что применяются в обычном задании. Пример команды с заменяемыми значениями:

xcodebuild \
  -project "<ПУТЬ_К_ПРОЕКТУ>" \
  -scheme "<СХЕМА>" \
  -configuration "<КОНФИГУРАЦИЯ>" \
  -destination "generic/platform=iOS" \
  -archivePath "<ПУТЬ_К_ARCHIVE>" \
  archive

Все значения в угловых скобках — заполнители: подставьте параметры проекта, не публикуя в логе секреты, адреса хостов, идентификаторы сертификатов и персональные пути. Успешный код завершения важен, но для проверки подписи дополнительно изучите журнал на отсутствие ошибок CodeSign и проверьте итоговый артефакт. Если команда собирает пакет для последующей отправки, не смешивайте этот этап с загрузкой: сбой передачи после успешного Archive требует отдельной диагностики.

Проведите итоговую проверку по списку:

  • [ ] В логе подтверждено, что сборка дошла до нужного этапа, а первая ошибка CodeSign устранена.
  • [ ] Задание работает от ожидаемой учетной записи и использует её домашний каталог.
  • [ ] Требуемая identity доступна в контексте SSH, а закрытый ключ можно использовать без незапрошенного интерактивного подтверждения.
  • [ ] Сертификат, Bundle ID, Team и Provisioning Profile проверены только там, где журнал указывает на соответствующую проблему.
  • [ ] Archive повторно собран в условиях, совпадающих с обычным заданием.
  • [ ] Секреты не попали в репозиторий, открытый скрипт или доступный другим пользователям журнал.

После проверки зафиксируйте версию Xcode и macOS, пользователя задания, используемую связку и условия воспроизведения. Не сохраняйте пароль связки в репозитории, командной строке или логе: доступ к секрету должен контролироваться отдельно от кода сборки. Если обновление Xcode изменило сообщения или поведение подписи, повторно сверьте их с официальными Release Notes, а не переносите результат тестирования прежней версии на новую.

Если проблема остаётся привязана к удалённому сеансу, хотя identity и параметры проекта проверены, следующий шаг — оценить саму среду сборки: кто запускает SSH-задачу, как предоставляется доступ к macOS и какие условия нужны для устойчивого Archive. Если локальная машина уже совмещает разработку и сборку, такой процесс может зависеть от доступности пользовательского сеанса, состояния связки и ресурсов этого компьютера; отдельная собственная машина, в свою очередь, требует покупки и обслуживания. Для временных сборок или проверки независимой среды удалённый Mac в аренду у NUKCLOUD может быть практичнее, чем приобретать отдельный компьютер. Перед выбором проверьте условия и доступные варианты аренды. При постоянной тяжёлой нагрузке или необходимости физически подключать устройства собственный Mac может оказаться предпочтительнее; для разовой отладки и тестирования SSH-конфигурации аренда позволяет проверить рабочий процесс без покупки отдельного оборудования.