Запуск агента Hermes локально в Podman без рут-доступа с использованием Ollama на GPU AMD
Запуск агента Hermes локально и безопасно: Podman без прав root, одна монтируемая папка, внутренняя сеть, Ollama на GPU AMD с ROCm и единица systemd.
Источники: Run Hermes Agent Locally (and securely) with Ollama and Rootless Podman on Arch Linux
Использование ИИ-агента для работы с локальными записями в формате Markdown и Obsidian кажется простым, пока не возникает вопрос об доступе. Hermes Agent от Nous Research может выполнять команды терминала, редактировать файлы, запускать код и вызывать другие инструменты. Однако передача ему модели с указанием работать только с одной папкой не создаёт защитных барьеров, поскольку инструкция представляет собой лишь текст. Сама документация Hermes подтверждает это: параметр HERMES_WRITE_SAFE_ROOT защищает обычные инструменты редактирования файлов, но инструменты терминала всё равно могут обращаться ко всему, к чему имеет доступ учётная запись операционной системы, на которой запущен Hermes.
Приведённая ниже конфигурация размещает сам Hermes внутри Podman без прав root, рядом с сервером Ollama, который запускает локальную модель на GPU AMD. Hermes может редактировать только одну специально монтируемую папку. Все остальные элементы файловой системы хоста просто отсутствуют в пространстве имён контейнера, поэтому он не может туда попасть. Hermes официально поддерживает работу в контейнерах, сохраняет постоянное состояние в папке /opt/data и работает с самостоятельно размещёнными серверами инференса, такими как Ollama, через конечную точку, совместимую с OpenAI.
Инструкция была протестирована на EndeavourOS, производном от Arch. Команды установки необходимо адаптировать под другие дистрибутивы.
Установка Podman без прав root
На Arch или EndeavourOS установите Podman с помощью Pacman:
sudo pacman -Syu podman
Pacman может спросить, какой OCI-среда выполнения использовать, предлагая три варианта:
1) crun
2) krun
3) runc
Выбранный здесь вариант — первый:
1
Этот движок выполнения — crun. Это окупается позже, поскольку функция Podman «keep-groups», которая передаёт дополнительные группы хоста в контейнер без корня, работает с crun.
Подтвердите установку, выведя версию и спросив у Podman, какой движок выполнения он использует:
podman --version
podman info --format '{{.Host.OCIRuntime.Name}}'
Вторая команда должна вернуть имя во время выполнения:
crun
Контейнерам без корня также требуются подчинённые сопоставления UID и GID для пользователя, поэтому убедитесь, что соответствующие записи существуют в обоих файлах:
grep "^$USER:" /etc/subuid
grep "^$USER:" /etc/subgid
Отныне все команды Podman выполняйте от имени обычного пользователя. Не добавляйте к ним префикс sudo.
Восстановление rootless OverlayFS при необходимости
Первая попытка загрузки образа на этом устройстве завершилась ошибкой: ядро не поддерживает использование overlay на файловой системе ext:
kernel does not support overlay fs:
'overlay' is not supported over extfs
Когда это произойдёт, установите реализацию в пользовательском пространстве:
sudo pacman -S fuse-overlayfs
Podman рекомендует использовать fuse-overlayfs в средах без корня, где не доступен встроенный overlay, и его можно явно указать в качестве программы монтирования для таких сред. Проверьте, установлен ли он:
which fuse-overlayfs
Ожидаемый путь:
/usr/bin/fuse-overlayfs
Конфигурация хранится в файле для каждого пользователя:
~/.config/containers/storage.conf
Если он уже существует, отредактируйте его вместо того, чтобы слепо заменять. В разделе хранения необходимо выбрать драйвер оверлея:
[storage]
driver = "overlay"
Во втором разделе следует указать имя программы монтирования:
[storage.options.overlay]
mount_program = "/usr/bin/fuse-overlayfs"
Затем проверьте действующие настройки, отфильтровав вывод информации о отладке Podman:
podman info --debug | grep -Ei 'graphDriverName|mount_program|overlay'
Перенос хранилища на более большой диск
Для этого проекта эта мера стала необходимой практически сразу. Одна только образ-контейнер Ollama занимает несколько гигабайт, модели часто добавляют ещё от 5 до 20 ГБ или даже больше, а Podman также использует временное пространство диска во время загрузки и распаковки слоев. Первая попытка загрузки Ollama в итоге завершилась с ошибкой о недостатке места в папке внутри временного каталога:
write /var/tmp/container_images_storage...:
no space left on device
Здесь задействованы два отдельных местоположения, что легко упустить из виду. Постоянное хранилище без корневой директории для изображений, контейнеров и томов обычно находится в поддиректории home:
$HOME/.local/share/containers/storage
Загруженные слои временно хранятся в следующем месте:
/var/tmp
Изменение параметра --tmpdir в Podman не приводит к перемещению каталога загрузки. В документации Podman рекомендуется вместо этого использовать переменную окружения TMPDIR.
При наличии более объемной локальной файловой системы создайте структуру, в которой будет один каталог для хранения данных и один — для временных файлов:
/path/to/large-drive/podman/
├── storage/
└── tmp/
Создать оба элемента и передать права владения текущему пользователю:
sudo mkdir -p /path/to/large-drive/podman/storage
sudo mkdir -p /path/to/large-drive/podman/tmp
sudo chown -R "$USER:$USER" /path/to/large-drive/podman
Затем откройте настройки хранилища для редактирования:
mkdir -p ~/.config/containers
nano ~/.config/containers/storage.conf
Укажите корень графика на новый каталог хранения, сохраняя драйвер накладки:
[storage]
driver = "overlay"
graphroot = "/path/to/large-drive/podman/storage"
И сохраните настройку программы монтирования fuse-overlayfs:
[storage.options.overlay]
mount_program = "/usr/bin/fuse-overlayfs"
Выберите для этого локальную файловую систему. В документации Podman предупреждается, что NFS и другие сетевые файловые системы могут некорректно функционировать в качестве хранилища для контейнеров без прав root.
Временные загрузки также требуют переноса, поэтому укажите TMPDIR для текущей оболочки:
export TMPDIR=/path/to/large-drive/podman/tmp
Чтобы сделать это постоянным в Bash, добавьте его в профиль и перезагрузите его:
echo 'export TMPDIR=/path/to/large-drive/podman/tmp' >> ~/.bashrc
source ~/.bashrc
Проверьте новые местоположения перед тем, как удалять что-либо из старого. Выполните вывод корня дерева и отфильтруйте вывод отладки для временной директории и программы монтирования:
podman info --format 'GraphRoot: {{.Store.GraphRoot}}'
podman info --debug | grep -Ei 'graphRoot|imageCopyTmpDir|mount_program'
Только при свежей установке Podman и только тогда, когда новый корень графа определённо верен, следует рассмотреть возможность удаления заброшенных данных, хранящихся на старом месте:
~/.local/share/containers/storage
Не делайте этого бездумно на существующей установке. Именно поэтому место хранения следует определить заранее перед созданием тома модели Ollama.
Один папка для Hermes, два тома для состояния
Выберите единственный хост-каталог, к которому может обращаться Hermes, и сделайте это осознанно. Экспортируйте его путь в переменную и создайте папку:
export HERMES_WORKSPACE="$HOME/path/to/Hermes-Workspace"
mkdir -p "$HERMES_WORKSPACE"
В Obsidian хорошим вариантом является отдельная папка внутри хранилища, например, папка для исследований, расположенная рядом с личными и рабочими папками:
Obsidian Vault/
├── Personal/
├── Work/
├── Research/
└── Agent Workspace/ ← only this folder is exposed
Все остальное в хранилище остаётся невидимым для агента.
Далее создайте два тома, которыми будет управлять сам Podman:
podman volume create hermes-data
podman volume create ollama-models
Первый хранит конфигурацию, память и постоянное состояние Hermes. Второй хранит локальную модель. Ни тот, ни другой не требуют предоставления агенту дополнительных каталогов хоста.
Предоставление контейнеру доступа к GPU AMD
Эта настройка предназначена для AMD ROCm, а не для NVIDIA CUDA. На карте AMD не устанавливайте nvidia-container-toolkit — это был обходной путь, использовавшийся ранее до того, как была обнаружена ошибка. Инструкции Ollama для контейнеров используют образ ollama/ollama:rocm для GPU AMD и передают в контейнер два узла устройств:
/dev/kfd
/dev/dri
Проверьте, существуют ли они на хосте:
ls -l /dev/kfd
ls -l /dev/dri/render*
Затем посмотрите на группы учётной записи:
groups
Если учётная запись отсутствует в группах видео и рендеринга, добавьте её:
sudo usermod -aG video,render "$USER"
Затем полностью выйдите из системы и снова войдите. Повторная загрузка списка групп в том же старом терминале не покажет новых участников, что приводит к ненужным затруднениям:
groups
После нового входа в систему запустите его ещё раз:
groups
Теперь результат должен включать обе группы:
video render
Параметр --group-add keep-groups в Podman позже передаёт эти дополнительные группы в контейнер без корня, чтобы тот мог использовать устройства GPU.
Проверка устройства TUN
Ещё одна проблема возникла из-за сетевой среды без корня. Pasta, стандартный механизм сети без корня в Podman, сообщил о невозможности открыть устройство TUN:
pasta failed with exit code 1:
Failed to open() /dev/net/tun: No such device
Ищите узел устройства:
ls -l /dev/net/tun
Если его нет, загрузите модуль ядра:
sudo modprobe tun
Затем проверьте снова. Если команда modprobe сообщает, что модуль отсутствует для текущей версии ядра, и система недавно обновлялась, сравните версию текущего ядра с содержимым каталогов модулей:
uname -r
ls /usr/lib/modules/
В дистрибутивах с гибкой настройкой, таких как Arch, у устройства может по-прежнему работать старый ядро, модули которого были удалены во время обновления. Перезагрузите устройство и попробуйте снова.
Выбор локальной модели
Для карт с объемом VRAM около 16 ГБ Ollama в настоящее время рекомендует использовать gemma4 в качестве локальной модели для Hermes, а для систем с объемом около 24 ГБ можно рассмотреть модели вроде qwen3.6. В приведенном примере используется вариант gemma4 с 12 миллиардами параметров:
gemma4:12b
Храните его в переменной, настраивая модель под конкретное оборудование:
export HERMES_MODEL="gemma4:12b"
Другим важным показателем является длина контекста. Ollama по умолчанию настраивает GPU с объемом VRAM менее 24 ГБ только на контекст 4K, тогда как оба проекта рекомендуют минимум 64 000 токенов при использовании агентов. Это настраивается более подробно далее.
Загрузка изображений и модели
Требуются три изображения: обычное изображение Ollama, версия для ROCm и изображение Hermes:
podman pull docker.io/ollama/ollama:latest
podman pull docker.io/ollama/ollama:rocm
podman pull docker.io/nousresearch/hermes-agent:latest
Обычная версия Ollama обеспечивает однократную загрузку модели. Версия для ROCm служит постоянным сервером инференса от AMD.
Загрузите модель в её постоянный том с помощью временного контейнера. Сначала удаляйте любые устаревшие контейнеры:
podman rm -f ollama-bootstrap 2>/dev/null
Затем запустите программу загрузки с монтированным томом модели и ничем больше:
podman run -d \
--name ollama-bootstrap \
-v ollama-models:/root/.ollama \
docker.io/ollama/ollama:latest
Если сетевая связь без root-доступа по-прежнему не работает, для этого временного загрузчика подойдёт сетевая связь хоста. Снова удалите контейнер:
podman rm -f ollama-bootstrap 2>/dev/null
Начните с сети хоста:
podman run -d \
--network host \
--name ollama-bootstrap \
-v ollama-models:/root/.ollama \
docker.io/ollama/ollama:latest
В этот контейнер не подключено никакое рабочее пространство Hermes. Загрузите модель через него:
podman exec -it ollama-bootstrap \
ollama pull "$HERMES_MODEL"
Подтвердите с помощью списка:
podman exec ollama-bootstrap ollama list
Выбранный модель должен отобразиться:
gemma4:12b
Удалите временный контейнер. Модель останется в том же объеме:
podman rm -f ollama-bootstrap
Если Podman сообщает, что имя контейнера уже занято:
container name "ollama-bootstrap" is already in use
Не придумывайте новые имена. Лучше очистите устаревший контейнер:
podman rm -f ollama-bootstrap
или укажите флаг --replace.
Внутренняя сеть и под
В первом варианте проектирования сеть вообще не использовалась:
--network none
Это было изменено на специальный внутренний мост Podman. Hermes и Ollama получают общий пространство имен сети, в котором они могут взаимодействовать друг с другом, в то время как Podman ограничивает доступ извне. Опция --internal существует именно для ограничения внешнего доступа в сетях с мостом. Создайте её:
podman network create \
--ignore \
--internal \
hermes-internal
Затем создайте под в той сети:
podman pod create \
--name hermes-local \
--network hermes-internal \
--userns=keep-id:uid=10000,gid=10000
Параметр keep-id помещает учетную запись хоста с ограниченными правами в пространство имен пользователя контейнера, причем числа, которые она там получает, можно выбрать. Контейнер Hermes запускается с параметрами 10000:10000, именно поэтому и отображаются эти значения.
Запуск Ollama с ROCm
Здесь возникла одна из менее очевидных проблем. Команда, которая в итоге сработала, выглядит следующим образом:
podman run -d \
--name ollama \
--pod hermes-local \
--device /dev/kfd \
--device /dev/dri \
--group-add keep-groups \
-e HOME=/root \
-e OLLAMA_MODELS=/root/.ollama/models \
-e OLLAMA_CONTEXT_LENGTH=64000 \
-v ollama-models:/root/.ollama \
docker.io/ollama/ollama:rocm
Его линейки, предназначенные специально для AMD, следующие:
--device /dev/kfd
--device /dev/dri
--group-add keep-groups
ollama/ollama:rocm
В этой конфигурации Podman не следует опускать две переменные окружения:
HOME=/root
OLLAMA_MODELS=/root/.ollama/models
Причиной стало загадочное сбой. Модель была загружена корректно, файлы blobs и manifest существовали, а том был правильно подключен. Однако при перечислении моделей не было найдено ничего:
podman exec ollama ollama list
Лог-файл контейнера рассказал всю историю:
podman logs ollama
В нём показано, что Ollama использует корневой каталог файловой системы в качестве домашнего каталога, а путь к моделям определяется на его основе:
HOME=/
OLLAMA_MODELS=/.ollama/models
в то время как модель на самом деле находилась в:
/root/.ollama/models
Ollama формирует путь к своей стандартной модели из домашней директории плюс .ollama/models, если только переменная OLLAMA_MODELS не задаёт иной путь. Поэтому модель никогда не отсутствовала — Ollama просто искал её в неверном месте. Явное установление обеих переменных сразу же решило проблему:
HOME=/root
OLLAMA_MODELS=/root/.ollama/models
Теперь в описании должна отображаться модель:
podman exec ollama ollama list
Подтверждение использования GPU
Поищите в журнале записи, содержащие ROCm и информацию о GPU:
podman logs ollama 2>&1 | grep -Ei 'gpu|rocm|amd|gfx'
Рабочая конфигурация AMD определяет вычислительное устройство ROCm. Затем запускается краткий тестовый запрос, требующий от модели точного ответа:
podman exec -it ollama \
ollama run gemma4:12b \
"Reply with exactly: AMD GPU test successful"
Сразу после этого посмотрите на работающие модели:
podman exec ollama ollama ps
Два столбца заслуживают внимания:
PROCESSOR
CONTEXT
В идеале в столбце с процессором должна отображаться информация о GPU, а не о переносе нагрузки на CPU, причем контекст должен быть следующим:
64000
Сама Ollama рекомендует проверять список своих процессов, чтобы увидеть как выделенный контекст, так и процесс переноса данных. Модель, заявляющая о большом объеме нативного контекста, не обязательно получает на самом деле столько же ресурсов.
Запуск Hermes с одним монтированием
Теперь создайте контейнер Hermes внутри того же пода:
podman run -d \
--name hermes \
--pod hermes-local \
--security-opt=no-new-privileges \
--pids-limit 512 \
-v hermes-data:/opt/data \
-v "$HERMES_WORKSPACE:/opt/data/workspace:rw,nodev,nosuid" \
-w /opt/data/workspace \
docker.io/nousresearch/hermes-agent:latest \
sleep infinity
Важно то, чего в нём не хватает. Ничего из этого не присутствует:
/:/host
/home:/home
~/.ssh
~/.config
Docker socket
Podman socket
Единственное произвольное привязывание хоста — это папка рабочего пространства, которая мапируется в каталог данных контейнера:
$HERMES_WORKSPACE
↓
/opt/data/workspace
Собственное состояние Hermes находится в указанном томе, который монтируется по его пути к данным:
hermes-data
↓
/opt/data
Официальный контейнер использует /opt/data для хранения постоянного состояния и автоматически устанавливает в него значение HERMES_WRITE_SAFE_ROOT. Этот механизм защиты от записи считается частью многократной защиты, а не основной сандбоксом, поскольку в документации Hermes предупреждается, что команды терминала могут обойти ограничения, связанные с работой с файлами. Настоящей границей является пространство имен файловой системы Podman.
Проверка границы монтирования
Ознакомьтесь с тем, что хост фактически предоставляет Hermes:
podman inspect hermes \
--format '{{range .Mounts}}{{println .Type .Source "->" .Destination}}{{end}}'
Ожидайте две строки: одну для объема данных и одну для разрешенной папки:
Podman volume -> /opt/data
your allowed folder -> /opt/data/workspace
Домашняя директория и сокет container-runtime не должны отображаться. Проверьте сокет явно:
podman exec hermes sh -c \
'test ! -S /var/run/docker.sock && echo "No Docker socket exposed"'
Можно также проверять пути, чувствительные к хосту, например, узнавать, виден ли каталог SSH:
podman exec hermes sh -lc \
'test -e "$HOME/.ssh" && echo "SSH directory visible" || echo "Host SSH directory not visible"'
Помните, что у контейнера есть собственные системные каталоги. Их наличие — это нормально, поскольку они принадлежат контейнеру, а не хосту.
Hermes и Ollama
Оба контейнера используют общий сетевой пространство имён пода, поэтому они взаимодействуют через луп-бэк. Проверьте API Ollama, совместимое с OpenAI, изнутри контейнера Hermes:
podman exec hermes python -c \
'import urllib.request; print(urllib.request.urlopen("http://127.0.0.1:11434/v1/models").read().decode())'
Ответ должен быть в формате JSON, содержащем локальную модель. При первой попытке использовался heredoc в Python, но ничего не было выведено:
podman exec hermes python - <<'PY'
...
PY
Причина была проста. Python читает свою программу из stdin в таком формате, но команде podman exec не было указано подключить stdin. Добавление флага интерактивного режима позволяет версии с heredoc корректно работать:
podman exec -i hermes python - <<'PY'
import urllib.request
print(
urllib.request.urlopen(
"http://127.0.0.1:11434/v1/models"
).read().decode()
)
PY
Отсутствие этого флага стоило нескольких дополнительных минут.
Доказательство недоступности внешнего мира
Попробуйте загрузить внешний веб-сайт изнутри контейнера Hermes:
podman exec hermes python -c \
'import urllib.request; print(urllib.request.urlopen("https://example.com", timeout=5).read())'
Это должно сработать некорректно, и это сделано намеренно. Hermes может получить доступ к Ollama внутри контейнера, но сеть не предоставляет никакого нормального внешнего доступа.
Не паникуйте, если список контейнеров будет выглядеть так:
podman ps
показывает порт рядом с Ollama:
11434/tcp
Это не означает, что порт был опубликован на хосте. Опубликованный порт будет выглядеть примерно так:
0.0.0.0:11434->11434/tcp
В данной конфигурации нигде не используется -p 11434:11434.
Направление Hermes на локальный Ollama
Запустите настройку Hermes от имени пользователя контейнера в рабочей среде:
podman exec -it \
--user 10000:10000 \
-w /opt/data/workspace \
hermes \
hermes model
В списке поставщиков приведено множество облачных сервисов. Не выбирайте вариант облака:
Ollama Cloud
Вместо этого выберите ручное введение конечной точки:
Custom endpoint (enter URL manually)
Для базового URL используйте адрес обратной связи и путь v1:
http://127.0.0.1:11434/v1
Если требуется API-ключ, оставьте его пустым. В текущих инструкциях по интеграции Hermes от Ollama используется именно такой формат с пользовательским конечным пунктом и пустым ключом для локального сервера. При вопросах об совместимости API выберите вариант чат-комплетаций, совместимый с OpenAI. Для имени модели введите:
gemma4:12b
А что касается длины контекста:
64000
В документации поставщика Hermes говорится, что локальная версия Ollama должна использовать конечную точку v1 и требует как минимум 64 Кб контекста для рабочих процессов агентов, использующих инструменты.
Использование локального терминального бэкенда внутри контейнера
Сначала это может показаться странным. Обычно Hermes предупреждает о настройке локального терминального бэкенда:
terminal:
backend: local
экзекутирует команды терминала непосредственно на том же компьютере, что и Hermes, без какой-либо изоляции. При прямой установке Hermes это могло бы быть опасно. Однако сам Hermes уже находится внутри Podman, поэтому локальный бэкенд соотносится с контейнером Hermes:
Hermes "local"
↓
Hermes container
а не к рабочей станции:
Hermes "local"
↓
your Arch workstation
Установите серверную часть:
podman exec --user 10000:10000 hermes \
hermes config set terminal.backend local
А рабочая директория:
podman exec --user 10000:10000 hermes \
hermes config set terminal.cwd /opt/data/workspace
Также стоит установить предпочтение в пользу режима домашнего экрана на основе профиля:
podman exec --user 10000:10000 hermes \
hermes config set terminal.home_mode profile
Не настраивайте Docker-бэкенд Hermes для данной схемы. Это потребует предоставления Hermes доступа к среде выполнения контейнеров, что сводит на нет одно из основных принципов изоляции.
Запуск Hermes
Интерактивная сессия начинается с того же шаблона выполнения, что и при настройке:
podman exec -it \
--user 10000:10000 \
-w /opt/data/workspace \
hermes \
hermes
Для улучшения структуры заметок запрос может предложить Hermes просмотреть Markdown-заметки в рабочем пространстве, упорядочить структуру и заголовки, исправить форматирование и грамматику, сохранить все технические детали, команды, ссылки и викиссылки Obsidian в неизменном виде, а также никогда не удалять реальный контент лишь для того, чтобы сократить заметку. Изменения сохраняются непосредственно в папке единственного подключенного хоста.
Запуск среды при загрузке
Как только всё будет работать интерактивно, под должен будет автоматически восстанавливаться после перезагрузки без необходимости вручную запускать Ollama и Hermes. Создайте пользовательскую единицу systemd:
mkdir -p ~/.config/systemd/user
nano ~/.config/systemd/user/hermes-local.service
Этот раздел начинается с описания и строки с номером заказа:
[Unit]
Description=Hermes Local AI Pod
After=default.target
Режим обслуживания — это одноразовая операция, которая запускает под, останавливает его с 30-секундным периодом торможения и предоставляет две минуты на его повторный запуск:
[Service]
Type=oneshot
RemainAfterExit=yesExecStart=/usr/bin/podman pod start hermes-local
ExecStop=/usr/bin/podman pod stop -t 30 hermes-localTimeoutStartSec=120
TimeoutStopSec=60[Install]
WantedBy=default.target
Если корень графа Podman находится на отдельном диске, этот диск должен монтироваться надежно при загрузке системы, а не интерактивно после входа в рабочий стол. Можно добавить необязательную проверку монтирования ExecStartPre, адаптированную под конкретную файловую систему.
Перезагрузите systemd:
systemctl --user daemon-reload
Включите единицу измерения:
systemctl --user enable hermes-local.service
Начните его:
systemctl --user start hermes-local.service
И проверьте это:
systemctl --user status hermes-local.service
Поскольку речь идет о одноразовом сервисе с включенным параметром RemainAfterExit, такое состояние является нормальным:
Active: active (exited)
В Podman существует более современный механизм Quadlet для декларативного определения контейнеров в рамках systemd. Однако при наличии уже собранной и проверенной вручную среды минимальным вмешательством оказалось использование небольшой пользовательской службы, запускающей под, которая уже доказала свою работоспособность.
Чтобы пользовательская служба без прав root запускалась при загрузке системы ещё до входа в рабочий стол, включите опцию lingering:
sudo loginctl enable-linger "$USER"
Проверьте это:
loginctl show-user "$USER" -p Linger
Ожидаемый результат:
Linger=yes
Функция linger в Systemd позволяет менеджеру служб пользователя запускаться при загрузке системы и оставаться доступным вне обычных сессий входа. После перезагрузки список контейнеров будет выглядеть так:
podman ps
Здесь уже должен отображаться под с запущенными Ollama и Hermes. Интерактивная сессия Hermes всё равно запускается с помощью команды exec:
podman exec -it \
--user 10000:10000 \
-w /opt/data/workspace \
hermes \
hermes
Служба загрузки запускает среду. Она не открывает интерактивный чат.
Фактически возникшие проблемы
Здесь приведён краткий список возникших на пути сбоев, каждый с описанием проблемы и способом её решения.
Ошибка оверлея от ядра:
Problem:
kernel does not support overlay fs
Проблема была решена путем установки fuse-overlayfs и настройки его в качестве программы монтирования overlay:
Fix:
Install fuse-overlayfs and configure it as the overlay mount program.
Не хватает места во временной директории:
Problem:
no space left on device under /var/tmp
Требовались как перемещение корня графа там, где это уместно, так и настройка TMPDIR, поскольку флаг tmpdir в Podman — это отдельная вещь:
Fix:
Move Podman's graphroot if needed AND set TMPDIR.
Changing Podman's --tmpdir is not the same thing.
Конфликт имён у контейнера bootstrap:
Problem:
ollama-bootstrap name already in use
Проблема устраняется путем удаления устаревшего контейнера:
Fix:
podman rm -f ollama-bootstrap
Приложение Pasta не может открыть устройство TUN:
Problem:
pasta cannot open /dev/net/tun
Проблема устраняется путем загрузки модуля tun или перезагрузки, если установленные модули не совпадают с действующим ядром:
Fix:
sudo modprobe tun
If the installed modules don't match the running kernel, reboot.
Инструментарий NVIDIA, установленный на компьютере с процессором AMD:
Problem:
Installed nvidia-container-toolkit on an AMD machine
Это просто не следует делать — вместо этого используйте изображение ROCm с устройствами kfd и dri:
Fix:
Don't.
Use ollama/ollama:rocm with /dev/kfd and /dev/dri.
Новые участники группы в разделе видео и рендеринга, которые не отображались в списке групп:
Problem:
Added myself to video/render but `groups` still didn't show them
Необходимо выход из системы и вход заново, поскольку существующая сессия сохраняет свои первоначальные группы:
Fix:
Log out and back in.
The existing login session retains its original supplementary groups.
Файлы моделей и манифест присутствуют, в то время как список Ollama пуст:
Problem:
Ollama model files and manifest exist, but `ollama list` is empty
Диагностика осуществляется путем просмотра журнала, и если пути к домашней директории и моделям указывают на корень файловой системы, в то время как том монтируется внутри каталога пользователя root, необходимо явно установить обе переменные:
Fix:
Check:
podman logs ollamaIf Ollama is using:
OLLAMA_MODELS=/.ollama/modelswhile the volume is mounted under:
/root/.ollamaset explicitly:
HOME=/root
OLLAMA_MODELS=/root/.ollama/models
Тест на Python от Hermes к Ollama, который бесшумно ничего не вывел:
Problem:
Hermes → Ollama Python test silently prints nothing
Проблема была устранена путем добавления флага интерактивного режима при использовании heredoc или простым использованием формы встроенной команды:
Fix:
If using `python -` with a heredoc, add `podman exec -i`.
Or simply use `python -c`.
Меню поставщика без очевидной локальной записи Ollama:
Problem:
The Hermes provider menu doesn't contain "local Ollama"
Проблема была решена путем выбора ручного пользовательского конечного точки и ввода локального URL версии v1:
Fix:
Choose:
Custom endpoint (enter URL manually)Then:
http://127.0.0.1:11434/v1
И Гермес жалуется на недостаточную ширину окна контекста, хотя всё остальное работало нормально:
Problem:
Everything works, but Hermes reports an inadequate context window
Проблема решается путем установки длины контекста с серверной стороны на 64000, настройки Hermes на то же значение и проверки фактического выделения памяти с помощью списка процессов Ollama:
Fix:
Set OLLAMA_CONTEXT_LENGTH=64000 server-side and configure Hermes for the same value.
Verify the real allocation with:
ollama ps
Где должна находиться граница доверия
Основной урок здесь не связан ни с Ollama, ни с ROCm. Речь идет о том, чтобы определить, где располагается граница доверия. Инструкция, запрещающая читать любые файлы вне определенной директории, представляет собой поведенческое указание. Контейнер Podman, в котором не предусмотрен доступ к остальной файловой системе хоста, служит границей операционной системы. Функция безопасного записи данных в корневую директорию у Hermes полезна, но сам Hermes считает ее дополнительным слоем, а не настоящей «песочницей», поскольку команды оболочки могут обойти механизмы защиты файлов.
В результате получаемая модель доверия складывает слои от самого слабого к самому сильному: начиная с ограничений, заданных через инструкции, и защиты от записи файлов в Hermes, и заканчивая границей контейнера:
Prompt restrictions
↓
Hermes file write protections
↓
Hermes container filesystem
↓
Rootless Podman user namespace
↓
Host filesystem permissions
Даже если модель получает злонамеренную инструкцию, скрытую в файле Markdown, интересный вопрос заключается не в том, будет ли она подчиняться первоначальному запросу, а в том, до чего на самом деле сможет добраться скомпрометированный агент. В данной конфигурации ответ намеренно ограничен.
Отладка по слоям
И Hermes, и Ollama быстро развиваются. Текущая документация Hermes поддерживает самостоятельно размещаемые конечные точки, совместимые с OpenAI, включая Ollama, но также поступали сообщения о поведении инструментов через пользовательские конечные точки Ollama. Если обычный чат работает, но Hermes, по-видимому, описывает вызовы инструментов без их выполнения, проверьте текущий трекер проблем Hermes, прежде чем предполагать, что среда Podman сбойна.
Именно поэтому необходимо тестировать всю стек-систему как цепочку вопросов: сначала проверяется, видит ли Podman GPU, затем — видит ли Ollama модель, и, наконец, может ли Hermes взаимодействовать с Ollama.
Does Podman see the GPU?
↓
Does Ollama see the model?
↓
Does Ollama actually use the GPU?
↓
Is the context really 64K?
↓
Can Hermes reach /v1/models?
↓
Can Hermes perform an actual file operation?
↓
Can Hermes reach anything it shouldn't?
Не пытайтесь отлаживать все шесть слоев одновременно.
Что даёт готовая настройка
Результатом такой конфигурации являются возможности локальных вычислений, ускорение с помощью GPU AMD, постоянная память Hermes и одно рабочее пространство хоста с возможностью записи:
Local inference YES
AMD GPU acceleration YES
Hermes persistent memory YES
One writable host workspace YES
Он не требует облачной модели, не открывает файловую систему хоста, не предоставляет сокеты Podman или Docker и не имеет обычного выхода в Интернет:
Cloud LLM required NO
Host filesystem exposed NO
Podman/Docker socket exposed NO
Normal Internet egress NO
Entire Obsidian vault exposed NO
Это гораздо более удобный способ экспериментировать с мощным локальным агентом. У Hermes всё ещё достаточно прав на доступ, чтобы быть полезным. Просто он не может самостоятельно решать, что означает достаточный уровень доступа.