Podman Quadlet: запуск контейнеров как служб systemd
Podman Quadlet превращает короткий файл .container в обычную службу systemd: положите его в ~/.config/containers/systemd/, выполните systemctl --user daemon-reload и запустите службу. Автозапуск задаётся секцией [Install], а для работы без входа пользователя включается linger.

Содержание
Что такое Quadlet и почему не podman generate systemd
Quadlet это генератор systemd, встроенный в Podman. Вы пишете короткий декларативный файл web.container в формате unit-файла, а при systemctl daemon-reload генератор превращает его в полноценную службу web.service. Дальше контейнер живёт как любая служба: запускается при загрузке, перезапускается при падении, пишет логи в journald, управляется через systemctl.
Раньше для того же использовали podman generate systemd: команда выдавала длинный unit-файл для уже созданного контейнера. Её объявили устаревшей ещё в Podman 4.7, а документация прямо отправляет пользователей к Quadlet. Причина понятна: сгенерированный файл приходилось перегенерировать при каждом изменении, а файл Quadlet вы правите руками, и он остаётся коротким.
Quadlet появился в Podman 4.4. В октябре 2026 года актуальны ветки 5.8 и 6.1. В Debian 13 стоит Podman 5.4, в Ubuntu 26.04 LTS и Fedora 44 версии свежее, так что всё описанное ниже работает в любом из этих дистрибутивов. Проверить версию можно командой podman --version.
Где хранятся файлы Quadlet и какие бывают типы
Каталог зависит от того, от чьего имени работает контейнер:
- Rootless, для своего пользователя:
~/.config/containers/systemd/. Подкаталоги читаются рекурсивно, так что проекты можно раскладывать по папкам. - Системные службы от root:
/etc/containers/systemd/, а пакеты дистрибутива кладут свои файлы в/usr/share/containers/systemd/. - Для всех пользователей при входе:
/etc/containers/systemd/users/, а для одного пользователя подкаталог с его UID.
| Расширение | Что описывает | Служба, которая получится |
|---|---|---|
.container | Один контейнер | имя.service |
.volume | Именованный том Podman | имя-volume.service |
.network | Сеть Podman | имя-network.service |
.pod | Под из нескольких контейнеров с общей сетью | имя-pod.service |
.kube | Запуск YAML в формате Kubernetes | имя.service |
.image, .build | Загрузка или сборка образа | имя-image.service, имя-build.service |
.artifact | OCI-артефакт, экспериментальный тип | имя-artifact.service |
Файлы ссылаются друг на друга по имени: строка Network=app.network в контейнере автоматически добавит зависимость от службы сети.
Первый контейнер как служба: веб-сервер nginx
Поднимем nginx от обычного пользователя, отдающий статический сайт из домашнего каталога. Создайте каталоги и файл:
mkdir -p ~/.config/containers/systemd ~/site
echo '<h1>Hello from Quadlet</h1>' > ~/site/index.html
nano ~/.config/containers/systemd/web.containerСодержимое web.container:
[Unit]
Description=Static site on nginx
[Container]
Image=docker.io/library/nginx:stable
ContainerName=web
PublishPort=8080:80
Volume=%h/site:/usr/share/nginx/html:ro,Z
AutoUpdate=registry
[Service]
Restart=on-failure
[Install]
WantedBy=default.targetОбязательный ключ в секции [Container] только один: Image. Указывайте полное имя образа с реестром, иначе Podman может спросить, откуда его брать, а автообновление откажется работать. Суффикс Z у тома нужен на системах с SELinux, то есть в Fedora: Podman перемаркирует каталог, и контейнер получит к нему доступ.
Запуск:
systemctl --user daemon-reload
systemctl --user start web.service
systemctl --user status web.service
curl http://localhost:8080Команда systemctl --user enable web.service здесь не нужна и выдаст ошибку: сгенерированные службы считаются временными. Автозапуск задаёт секция [Install], генератор сам создаёт нужные ссылки. Об общих приёмах работы с юнитами читайте в статье systemctl: управление службами.
Rootless-контейнеры и автозапуск без входа в систему
Пользовательские службы systemd запускаются, когда пользователь входит в систему, и останавливаются после выхода. Для домашнего сервера это неудобно: после перезагрузки сайт не поднимется, пока вы не зайдёте по SSH. Решение называется linger:
sudo loginctl enable-linger $USER
loginctl show-user $USER --property=LingerТеперь менеджер служб пользователя стартует при загрузке, и контейнеры с WantedBy=default.target поднимаются сами.
Ещё два ограничения rootless-режима. Порты ниже 1024 обычному пользователю недоступны, поэтому мы публикуем 8080, а не 80. Если очень нужен порт 80, либо поставьте впереди обратный прокси от root, либо понизьте порог sysctl net.ipv4.ip_unprivileged_port_start, понимая последствия. Второе: подсистема cgroups v2 и пакет passt (или slirp4netns в старых версиях) должны быть на месте, в современных дистрибутивах это так по умолчанию. Сравнение с аналогичным режимом Docker есть в статье Docker Rootless.
Приложение из нескольких контейнеров: тома, сеть и секреты
Реальная задача сложнее одного nginx. Допустим, нужно приложение с базой PostgreSQL. Вместо одного compose-файла создаётся набор маленьких файлов в каталоге ~/.config/containers/systemd/app/.
Сеть app.network и том pgdata.volume могут быть почти пустыми:
# app.network
[Network]
# pgdata.volume
[Volume]Пароль базы не стоит писать в файл открытым текстом. Создайте секрет Podman:
printf '%s' 'сложный-пароль' | podman secret create pg_pass -Контейнер базы db.container:
[Container]
Image=docker.io/library/postgres:17
ContainerName=db
Network=app.network
Volume=pgdata.volume:/var/lib/postgresql/data
Secret=pg_pass,type=env,target=POSTGRES_PASSWORD
[Install]
WantedBy=default.targetКонтейнер приложения подключается к той же сети и обращается к базе по имени db. Порядок запуска задаётся обычными директивами systemd в секции [Unit]: Requires=db.service и After=db.service. Если зависимостей много, подумайте о файле .pod: контейнеры в поде делят сетевое пространство и видят друг друга через localhost.
Переносите проект из Docker Compose по одному сервису: сначала том и сеть, потом база, потом приложение, проверяя каждый шаг через systemctl --user status. Есть сторонний конвертер podlet, который делает черновые файлы Quadlet из compose.yaml, но результат всё равно стоит прочитать глазами. Как устроен compose.yaml, описано в материале Docker Compose plugin.
Автоматическое обновление образов
Ключ AutoUpdate=registry в файле контейнера разрешает Podman проверять реестр на новую версию тега. Сама проверка выполняется отдельной командой или таймером, который входит в пакет Podman:
# посмотреть, что обновилось бы
podman auto-update --dry-run
# включить ежедневную проверку для своего пользователя
systemctl --user enable --now podman-auto-update.timer
systemctl --user list-timersЕсли после обновления служба не стартует, Podman откатывает контейнер на предыдущий образ: эта логика включена по умолчанию. Поэтому тег лучше выбирать предсказуемый. Плавающий latest для базы данных плохая идея, мажорное обновление PostgreSQL требует миграции данных. Для баз ставьте конкретную мажорную версию, как postgres:17, а AutoUpdate оставьте для веб-сервисов без состояния.
Если служба не появилась или упала
Самая частая жалоба: после daemon-reload команда systemctl --user start web.service отвечает Unit web.service not found. Это значит, что генератор отбраковал файл: опечатка в ключе, ключ из более новой версии Podman или файл лежит не в том каталоге. Причину покажет пробный прогон генератора:
/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun
# дополнительные проверки готового юнита
systemd-analyze --user --generators=true verify web.serviceГенератор выводит итоговые unit-файлы целиком, и по ним видно, какую команду podman run он собрал. Если служба создаётся, но падает, смотрите журнал и состояние контейнера:
journalctl --user -u web.service -e
podman ps -a
podman logs webОбщая методика разбора упавших юнитов описана в статье как найти и исправить упавшую службу. В свежих версиях Podman появилась команда podman quadlet с подкомандами install, list, print и rm: она устанавливает файлы в нужный каталог и показывает, какие Quadlet уже есть. Полный список ключей с примерами есть в справке podman-systemd.unit(5) или локально в man 5 podman-systemd.unit, причём локальная справка соответствует именно вашей версии.
Когда Quadlet удобен, а когда нет
Quadlet хорошо подходит для домашнего сервера, VPS и рабочей станции, где несколько долгоживущих сервисов должны стартовать при загрузке и переживать сбои: медиасервер, Nextcloud, мониторинг, локальная база для разработки. Логи собраны в journald, перезапуск и зависимости задаёт systemd, отдельный демон вроде dockerd не нужен.
Хуже он подходит для быстрых экспериментов, где контейнеры создаются и удаляются десятками за вечер: тут проще podman run или Distrobox. И для кластеров из многих машин, где нужен оркестратор. Если вы собираете домашний сервер с нуля, общий план есть в материале домашний сервер на Linux.
Частые вопросы
Почему systemctl enable не работает для службы Quadlet?
Сгенерированные службы считаются временными. Автозапуск задаётся секцией [Install] с WantedBy=default.target прямо в файле .container.
Служба не найдена после daemon-reload. Что проверить?
Запустите podman-system-generator --user --dryrun: он покажет ошибку в файле. Частые причины: опечатка в ключе, ключ из новой версии Podman, неверный каталог.
Как запустить rootless-контейнер при загрузке без входа в систему?
Включите linger командой sudo loginctl enable-linger $USER, тогда пользовательские службы стартуют при загрузке.
Чем Quadlet лучше podman generate systemd?
podman generate systemd устарела с Podman 4.7. Файлы Quadlet короткие, правятся руками и не требуют перегенерации.
Можно ли перенести проект из Docker Compose?
Да, каждый сервис становится файлом .container, тома и сети отдельными файлами .volume и .network. Черновик можно получить конвертером podlet.
Документация и источники
- podman-systemd.unit(5), Podman, 2026
- podman-quadlet(1), Podman, 2026
- podman-auto-update(1), Podman, 2026
Читайте также
- Docker Rootless: установка, настройка и ограничения
- Docker Compose plugin в Linux: современная работа с compose.yaml
- systemctl в Linux: управление службами и автозагрузкой
- Упавшая служба systemd: поиск причины и исправление
- Distrobox: несколько дистрибутивов Linux в одной системе
- Домашний сервер на Linux: хранение, резервные копии и сервисы
Команды проверены на актуальных версиях дистрибутивов на момент обновления. Перед изменением системных настроек сделайте резервную копию.