Локальный интерфейс Open WebUI удобно настроить так, чтобы после перезапуска приложения вы возвращались к тем же чатам и своей учётной записи без повторного ввода длинных команд. Если на компьютере с Linux используется Podman, сам движок запускает контейнер и подключает хранилище. Для постоянной пользовательской службы управление запуском и перезапуском в этом примере поручим менеджеру служб systemd.
В этом уроке мы сразу опишем постоянную службу через Quadlet. Так называется встроенный в Podman генератор, который превращает лаконичное описание контейнера в понятную для systemd службу. Варианты с одиночной командой podman run и локальным манифестом podman kube play мы разберём в конце как самостоятельные альтернативы для других задач. Конфигурации и команды ниже составлены по документации и исходному коду проекта. При подготовке текста мы не запускали контейнеры, не выходили из системы и не перезагружали хост.
Где будем запускать Open WebUI
Примеры опираются на документацию для Debian 13 (trixie) на архитектуре amd64. В этой среде уже должны быть настроены пользовательский режим Podman (пакет podman 5.4.2 есть в репозитории дистрибутива), сетевой стек pasta, иерархия cgroup v2, пользовательский менеджер systemd и утилита curl для проверки HTTP-ответа. Пользовательский менеджер должен быть активен. Версия 5.4.2 задаёт базовую среду примера по документации; мы не утверждаем, что это минимальная подходящая версия. Браузер будем открывать на этом же компьютере с Linux.
Мы используем rootless-режим. Это означает, что Podman запускает контейнеры от имени вашей обычной учётной записи на хосте, без прав суперпользователя root и без обязательного центрального фонового демона. По умолчанию данные контейнеров, образы и тома находятся в хранилище внутри домашнего каталога пользователя. Поэтому все команды podman и systemctl --user в уроке выполняются от одной учётной записи. Добавлять перед ними sudo не нужно: вызов sudo podman переключит вас в отдельное хранилище пользователя root, где не будет видно ни ваших контейнеров, ни созданных томов. Rootless-режим определяет владельца процессов и файлов на хосте. Он не заменяет настройку сетевого доступа и не означает, что процессы внутри контейнера работают под тем же числовым идентификатором (UID).
Понятия образа, проброса портов и постоянного тома уже знакомы вам по уроку про запуск через Docker Compose, но установленный Docker не заменяет подготовку Podman. Если Podman ещё не установлен или для вашей учётной записи не подготовлено пользовательское окружение (включая диапазоны подчинённых идентификаторов subuid и subgid), перед началом сверьтесь со страницей пакета в своём дистрибутиве и официальным руководством по настройке rootless Podman.
Проверим версию Podman, версию cgroups и состояние пользовательского менеджера служб:
Во второй строке ожидаем увидеть v2, так как работа пользовательских служб Podman с systemd опирается на cgroup v2. Команда systemctl --user status показывает состояние пользовательского менеджера. Даже если она возвращает ненулевой код завершения из-за другой проблемной службы в системе, сам менеджер при этом работает.
Перед созданием файлов убедитесь, что выбранный локальный порт свободен, а в выводе podman ps -a, podman pod ps и podman volume ls нет чужих ресурсов с именами из нашего примера. Если имя или порт уже заняты прежней установкой, остановитесь и не удаляйте старые контейнеры или тома наугад. Именованные тома из Docker или данные из прежней Python-установки в Podman автоматически не переносятся даже при полном совпадении имён.
Для основного маршрута проверим и имя пользовательской службы open-webui.service: команда systemctl --user status open-webui.service не должна указывать на уже существующую установку. Файл ~/.config/containers/systemd/open-webui.container тоже не должен принадлежать другому экземпляру. Этот пример рассчитан на новую службу; имеющийся файл или службу мы им не заменяем.
Ниже приведены три независимых способа запуска. Выберите только один:
| Вариант | Имя контейнера или pod | Том | Локальный порт |
|---|---|---|---|
| Основной Quadlet | open-webui | open-webui-data | 3000 |
Необязательный run | open-webui-once | open-webui-once-data | 3001 |
Необязательный kube play | open-webui-kube | open-webui-kube-data | 3002 |
Разные имена и порты позволяют избежать конфликтов между примерами. Это отдельные установки, а не последовательные обновления одной базы: у каждой будет своё хранилище, ключ и учётные записи. Если вам нужна постоянная управляемая служба, выполняйте основной раздел с Quadlet. Два альтернативных маршрута в конце урока можно прочитать для сравнения или пропустить.
Описываем контейнер в Quadlet
Чтобы не запускать контейнер вручную перед настройкой службы, сразу опишем его для генератора Quadlet. В пользовательском режиме Podman ищет такие файлы в каталоге ~/.config/containers/systemd/.
Создадим этот каталог, если его ещё нет:
Сохраним в файл ~/.config/containers/systemd/open-webui.container следующее описание:
Разберём строки этого файла:
Image=ghcr.io/open-webui/open-webui:v0.12.3выбирает конкретный выпуск Open WebUIv0.12.3вместо плавающих тегов вроде:mainили:latest. Как отмечено в руководстве по запуску контейнера Open WebUI, точный тег версии позволяет сохранить предсказуемое поведение при следующих перезапусках.ContainerName=open-webuiзадаёт постоянное имя создаваемого контейнера в Podman.PublishPort=127.0.0.1:3000:8080связывает внутренний порт8080, который слушает приложение в штатном образе, с портом3000на локальном интерфейсе127.0.0.1хоста. Если опустить IP-адрес и написать просто3000:8080, порт будет опубликован на всех сетевых интерфейсах машины. Явная привязка к127.0.0.1публикует порт на loopback-интерфейсе хоста. В этом уроке мы обращаемся к нему браузером иcurlна том же Linux-компьютере.Volume=open-webui-data:/app/backend/dataподключает именованный том Podman (named volume) к каталогу/app/backend/dataвнутри контейнера, где хранятся база данных и файлы приложения. В отличие от временного записываемого слоя самого контейнера, именованный том сохраняется при пересоздании контейнера. Podman создаст томopen-webui-dataавтоматически при первом старте службы, поэтому отдельный файл.volumeдля этой задачи не нужен.Environment=WEBUI_SECRET_KEY_FILE=/app/backend/data/.webui_secret_keyуказывает путь к файлу секретного ключа внутри только что подключённого постоянного тома. Это настройка для чистой установки, основанная на логике стартового скриптаstart.shверсииv0.12.3: если переменныеWEBUI_SECRET_KEYиWEBUI_JWT_SECRET_KEYне заданы отдельно, штатный скрипт при первом запуске сам создаёт файл по пути изWEBUI_SECRET_KEY_FILEи при следующих стартах читает ключ из него. Поскольку путь ведёт в томopen-webui-data, ключ остаётся на месте после пересоздания контейнера. Генерировать значение ключа вручную, выводить этот файл на экран или применять такой приём к старой базе с другим ключом не нужно.Restart=alwaysиTimeoutStartSec=900в секции[Service]передаются напрямую менеджеруsystemd. Первая директива поручаетsystemdперезапускать службу после завершения процесса, кроме явной остановки через менеджер служб; сам образ она при этом не обновляет. Вторая увеличивает предел ожидания старта до 900 секунд, как показано в примере документации Podman по Quadlet: при первом запуске Podman должен скачать образ из реестра, и стандартного тайм-аута может не хватить. Лимит в900секунд даёт запуску больше времени, чем стандартный тайм-аут, но при его превышении попытка всё равно может завершиться ошибкой.WantedBy=default.targetв секции[Install]сообщает генератору Quadlet, что службу нужно связать со стандартной целью запуска пользовательского менеджера.
Здесь есть отличие от обычных unit-файлов, которые мы создавали вручную в уроке про запуск Python-версии как службы. Службы, сгенерированные через Quadlet, нельзя включать или выключать командами systemctl --user enable или disable. Как прямо объясняет документация генератора podman-systemd.unit, генератор сам считывает секцию [Install] во время перезагрузки конфигурации и создаёт нужные связи в памяти systemd. Появление сгенерированной службы ещё не запускает контейнер в текущем сеансе.
Попросим пользовательский менеджер перечитать конфигурацию, чтобы генератор создал службу open-webui.service, и сразу запустим её:
После этих команд проверим, как прошёл запуск службы и самого веб-приложения.
Проверяем службу, интерфейс и подключение модели
Состояние процесса в systemd, готовность внутренней логики Open WebUI и связь с языковой моделью проверяются отдельно. Статус active у службы говорит лишь о том, что процесс контейнера запущен, но ещё не означает, что внутренний сервер завершил миграции базы данных и готов отвечать браузеру.
Проверим текущее состояние службы и посмотрим последние 50 строк её журнала:
При самом первом запуске служба может некоторое время находиться в состоянии активации (activating), пока скачивается образ v0.12.3 и распаковываются его слои. При успешном запуске контейнера статус сменится на active (running), а в журнале journalctl появятся сообщения о подготовке приложения. Если служба вообще не находится после daemon-reload, проверьте точность пути ~/.config/containers/systemd/open-webui.container и отсутствие синтаксических опечаток в секциях файла.
Когда процесс контейнера работает, проверим HTTP-готовность backend-сервера через маршрут /ready:
Согласно коду маршрутов main.py в выпуске v0.12.3, маршрут /ready проверяет три условия: завершилась ли стартовая инициализация приложения, проходит ли проверочный запрос к базе данных и отвечает ли Redis (только если Redis специально настроен в окружении). Пока приложение ещё загружается или база не готова, сервер возвращает код 503, а когда всё готово к работе, отвечает JSON-объектом со статусом true. Более простой маршрут /health, который используется и во встроенной проверке HEALTHCHECK самого образа, возвращает положительный ответ без проверки завершения старта и базы данных. Если curl сообщает об ошибке соединения или коде 503, подождите немного и повторно посмотрите вывод journalctl.
Получив успешный ответ от /ready, откройте в браузере на этом же компьютере адрес http://127.0.0.1:3000. Так как мы используем новый пустой том open-webui-data, откроется страница создания первой учётной записи администратора. Порядок регистрации и базовых настроек подробно разобран в уроке про первый вход в Open WebUI. Аккаунты из ваших прежних установок в Docker или Python здесь не появятся.
Доступность веб-интерфейса и успешный ответ /ready не проверяют связь с сервером языковых моделей. Если вы подключаете к Open WebUI локальный сервер моделей (например, Ollama, запущенную на том же Linux-хосте), учитывайте устройство контейнерной сети. Адрес localhost или 127.0.0.1 внутри контейнера указывает на сам контейнер open-webui, а не на компьютер с Linux, где он запущен.
Для обращения из rootless-контейнера к сервису на хосте в руководстве Open WebUI по Podman используется специальное имя host.containers.internal (например, адрес подключения может выглядеть как OLLAMA_BASE_URL=http://host.containers.internal:11434). В Podman 5.4.2 со стеком pasta внутренние имена хоста добавляются автоматически, если сетевой шлюз определён. Но само разрешение имени host.containers.internal ещё не гарантирует, что сервер моделей запущен, принимает запросы или уже загрузил нужную модель. Если чат не видит модель, проверяйте настройки подключения в интерфейсе и работу самого модельного сервера на хосте; переводить Ollama на прослушивание всех сетевых интерфейсов (0.0.0.0) просто ради локальной проверки не следует.
Управляем перезапуском и автозапуском
Когда интерфейс работает, можно перейти к управлению службой. Сначала разберём остановку и перезапуск контейнера, затем условия, при которых работает пользовательский менеджер systemd.
Останавливаем и запускаем свой экземпляр
Для управления работающей службой используются команды systemctl с флагом --user. Выполнять их подряд не нужно; выбирайте команду под текущую задачу.
Чтобы штатно остановить службу и контейнер:
При явной остановке через stop политика Restart=always не запускает контейнер обратно: менеджер systemd отличает действие пользователя от сбоя.
Чтобы снова запустить остановленную службу:
Если нужно перезапустить работающий экземпляр:
Если вы изменили параметры в файле ~/.config/containers/systemd/open-webui.container, сначала выполните systemctl --user daemon-reload, чтобы генератор обновил определение службы, и только затем перезапустите её через systemctl --user restart open-webui.service. После любого перезапуска дождитесь готовности приложения по /ready, прежде чем обновлять страницу в браузере.
Остановка и перезапуск службы не удаляют именованный том open-webui-data. Поскольку база данных и файл .webui_secret_key лежат внутри этого тома, после следующего старта вы сможете войти в ту же учётную запись. Сохранение тома на диске не заменяет отдельного резервного копирования перед обновлениями и не позволяет безопасно откатить базу на более старую версию образа.
Если служба нужна без входа пользователя
Закрытие одного окна терминала при продолжающемся графическом или SSH-сеансе не останавливает службу open-webui.service, так как пользовательский менеджер systemd продолжает работать. Без linger время жизни пользовательского менеджера связано с сеансами и настройками logind: после полного выхода из всех сеансов (logout) менеджер может быть остановлен. Директива WantedBy=default.target в нашем файле указывает, что службу нужно запустить вместе с пользовательским менеджером, но она не заставляет систему включать сам этот менеджер при загрузке компьютера до вашего входа.
Если вам нужно, чтобы пользовательский менеджер запускался сразу при включении компьютера и продолжал держать службы после полного выхода из учётной записи, в systemd используется режим linger (буквально «задерживаться»), управляемый через loginctl.
Проверить текущее состояние этой настройки для своего пользователя можно командой:
Если в выводе указано Linger=no, а вам действительно нужна работа службы до входа в систему и после выхода из всех сессий, этот режим включается командой:
В зависимости от политики безопасности конкретной системы вызов enable-linger может потребовать прав администратора (проверки через Polkit). Режим linger действует на всю вашу учётную запись, а не на один контейнер Open WebUI: он меняет время жизни пользовательского менеджера целиком. Вместе с ним смогут запускаться службы, включённые в его цели, а ошибки их настройки linger не исправляет. Если вы работаете с Open WebUI только во время своего обычного сеанса за компьютером, включать linger не обязательно.
Когда нужен другой способ запуска Podman
Если постоянная служба systemd вам не нужна или вы хотите описывать локальную нагрузку в формате манифестов Kubernetes, Podman предлагает два других инструмента. Оба варианта ниже описывают самостоятельные чистые установки со своими портами и томами. Они не продолжают настройку Quadlet.
Разовый запуск без службы
Чтобы запустить отдельный экземпляр Open WebUI без регистрации службы в systemd, используем команду podman run. Для этого независимого маршрута мы берём имя контейнера open-webui-once, том open-webui-once-data и локальный порт 3001:
Флаг -d переводит контейнер в фоновый режим и освобождает терминал, но не создаёт службу systemd. Такой контейнер не встроен в систему управления службами пользователя и не запустится сам после перезагрузки компьютера.
После завершения стартовой инициализации этот экземпляр открывается в локальном браузере по адресу http://127.0.0.1:3001. Готовность backend можно проверить запросом к http://127.0.0.1:3001/ready. Внутри тома open-webui-once-data создаются собственные база данных, секретный ключ и учётные записи, никак не связанные с томом из раздела про Quadlet.
Этим контейнером управляют прямые команды Podman. Чтобы остановить контейнер, сохранив его самого и том с данными, выполните:
Чтобы снова запустить этот же остановленный контейнер без пересоздания:
Kubernetes YAML через kube play без кластера
Команда podman kube play позволяет прочитать поддерживаемое подмножество манифеста Kubernetes YAML и развернуть описанные в нём объекты прямо в локальном Podman. Для этого не требуются ни кластер Kubernetes, ни kubectl, ни Helm. В то же время это именно локальная интерпретация файла силами Podman, а не полноценный контроллер кластера.
В Kubernetes минимальную единицу развёртывания называют Pod. Это группа из одного или нескольких контейнеров с общим сетевым пространством и возможностью подключать общие тома. Запрос на подключение постоянного тома описывается через PersistentVolumeClaim (PVC). Когда Podman читает секцию persistentVolumeClaim в локальном YAML, он сопоставляет указанное имя claimName со своим обычным именованным томом (named volume). Писать для этого отдельный манифест PVC с размером хранилища вроде 5Gi не нужно: Podman создаст локальный том по одному лишь имени claimName, а декларативные квоты размера из Kubernetes на обычный локальный том всё равно автоматически не накладываются.
Если вы выбрали этот независимый маршрут, создадим отдельный рабочий каталог и перейдём в него:
Сохраним в этом каталоге файл open-webui-kube.yaml (для этой ветки используются имя open-webui-kube, том open-webui-kube-data и локальный порт 3002):
Внутри манифеста указан только внутренний порт контейнера containerPort: 8080, а привязку к локальному адресу и порту хоста мы передадим через флаг --publish в командной строке. Запустим pod из каталога ~/open-webui-podman:
Podman создаст том open-webui-kube-data, поднимет pod open-webui-kube и опубликует интерфейс по адресу http://127.0.0.1:3002. Как и podman run, самостоятельный вызов podman kube play запускает контейнеры локально, но не создаёт службу systemd для автозапуска. В Quadlet существуют отдельные .kube-единицы. Мы не смешиваем их с этим примером, чтобы не создавать вторую службу в системе.
Если вы изменили файл open-webui-kube.yaml и хотите применить новые параметры, простой повтор kube play не работает как фоновая сверка состояния в кластере. Для пересоздания pod по обновлённому файлу используйте флаг --replace, обязательно повторив флаг публикации порта (так как внешний порт 3002 не записан внутри YAML):
Флаг --replace сначала полностью удаляет старый pod и его контейнеры и только затем создаёт новые, поэтому работа интерфейса на время пересоздания прерывается.
Когда нужно остановить и удалить pod и контейнеры, созданные по этому манифесту, выполните из того же каталога команду podman kube down:
Вызов podman kube down без флага --force удаляет сам pod и его контейнеры, но сохраняет именованный том open-webui-kube-data со всеми данными и ключом. Если выполнить down повторно, когда pod уже удалён, команда может сообщить об отсутствии объекта. В отличие от контроллеров кластера, она не гарантирует одинаковый результат при повторных вызовах.
Для своей установки придерживайтесь одного выбранного маршрута. В Quadlet процессом контейнера управляет пользовательский systemd, а в run и kube play вы управляете им прямыми командами. Именованный том хранит базу и файл ключа, поэтому остановка процесса не означает потерю данных. Проверяйте состояние процесса, HTTP-ответ /ready и подключение модели отдельно: они отвечают на разные вопросы.

