SSD Nodes Learn Hosting plans →
Посібники Matt ConnorВід Matt Connor · Оновлено 2026-09-04

Ollama у rootless Podman на VPS: налаштування

Налаштуйте Ollama у rootless Podman на VPS: окремий користувач, lingering, Quadlet після перезавантаження, SELinux і закритий порт 11434.

Запуск Ollama у rootless Podman на VPS

Щоб запустити Ollama у rootless Podman на сервері, мають виконуватися п’ять умов, які можна пропустити в інструкції для desktop. Окремий непривілейований користувач має володіти контейнером. Для цього користувача потрібно ввімкнути lingering, щоб контейнер продовжував працювати після виходу із системи. Файл Quadlet передає керування контейнером systemd, тому контейнер запускається знову після перезавантаження. Каталог моделей має правильну мітку SELinux у дистрибутивах, де SELinux увімкнено. API прослуховує лише loopback, а доступ до нього здійснюється через SSH (secure shell) tunnel.

Ollama — це сервер для великих мовних моделей (LLM). Він зберігає ваги моделей на диску, завантажує їх у пам’ять і обробляє HTTP-запити на порту 11434. У ньому немає входу, API key або облікових записів користувачів, тому мережа є єдиним засобом контролю доступу. Podman запускає контейнери без daemon і без root, тому все, що вийде за межі контейнера, спочатку працює від імені звичайного непривілейованого користувача. Якщо спочатку потрібне порівняння runtime, прочитайте чим Podman відрізняється від Docker на VPS. Якщо ви хочете повністю відмовитися від контейнерів, встановлення Ollama безпосередньо на VPS буде коротшим шляхом.

SSD Nodes надає Fedora серед доступних образів, а Fedora типово постачається з Podman і SELinux (security-enhanced Linux). Усі наведені нижче команди працюють у будь-якому дистрибутиві з Podman 5 або новішої версії.

Чому версія для ноутбука потребує змін на сервері

5 August 2026 року Fedora Magazine опублікував зрозумілий посібник із цим стеком: Локальний запуск Ollama за допомогою Podman у Fedora Linux, автор — Yazan Monshed. Це хороший спосіб познайомитися з інструментами протягом першої години. Водночас посібник орієнтований на ноутбук, а чотири його рішення працюють інакше на машині з публічною IP-адресою.

  • Контейнер запускається за допомогою звичайного podman run -d. Контейнер, запущений вручну, не запускається після перезавантаження, оскільки його ніколи не налаштовували на автоматичний запуск.
  • Використовується рухомий тег ollama/ollama. На ноутбуці ви помітите день, коли поведінка зміниться. На сервері першою ознакою може стати скрипт, який раптово перестав працювати.
  • Публікація виконується за допомогою -p 11434:11434, який прив’язує сервіс до всіх інтерфейсів. За домашнім маршрутизатором сервіс недоступний з інтернету. На VPS це публічний API для інференсу без пароля.
  • Контейнер запускається від вашого облікового запису. На сервері обліковий запис, якому належить контейнер, не повинен володіти нічим іншим, щоб у разі виходу з контейнера зловмисник потрапив у порожній домашній каталог.

Для машини, для якої це було написано, жоден із цих підходів не є неправильним. Кожне з цих рішень просто потрібно переглянути, коли сервер доступний з будь-якої мережі, а поруч немає користувача, який може одразу втрутитися.

Створіть непривілейованого користувача та перевірте subuid

Rootless Podman зіставляє внутрішні ідентифікатори користувачів контейнера (UID) із блоком невикористаних ідентифікаторів на хості. Цей блок визначається у /etc/subuid і /etc/subgid. Без нього rootless-контейнери взагалі не можуть запуститися.

sudo dnf install -y podman        # or: sudo apt install -y podman
sudo useradd --create-home --shell /bin/bash --comment "Ollama container owner" ollama
sudo passwd --lock ollama
grep ollama /etc/subuid /etc/subgid

Команда grep має вивести два рядки, по одному з кожного файла. У кожному рядку має бути вказано діапазон із 65536 ідентифікаторів:

/etc/subuid:ollama:100000:65536
/etc/subgid:ollama:100000:65536

Початкове число у вас буде іншим, і це нормально. Якщо команда grep нічого не виводить, useradd не виділив діапазон, тому перша команда podman від імені цього користувача завершується такою помилкою:

Error: cannot find UID/GID for user ollama: no subuid ranges found for user "ollama" in /etc/subuid

Призначте діапазон, який не належить жодному іншому користувачу, а потім повідомте Podman, що його старе зіставлення застаріло:

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 ollama
sudo -iu ollama podman system migrate

Блокування пароля означає, що ніхто не може безпосередньо увійти під обліковим записом ollama. Перехід до цього облікового запису з облікового запису адміністратора виконується за допомогою sudo -iu ollama.

Увімкнення lingering, щоб сервіс працював після виходу із системи

Екземпляр systemd користувача зазвичай запускається під час входу в систему та зупиняється під час виходу, а разом із ним видаляється /run/user/<uid>. Усі rootless-контейнери, що належать цьому користувачу, зупиняються в той самий момент. Lingering підтримує екземпляр користувача запущеним без активної сесії.

sudo loginctl enable-linger ollama
loginctl show-user ollama --property=Linger

Команда має вивести Linger=yes. Увімкніть lingering до створення unit, оскільки каталог, потрібний цьому unit, /run/user/<uid>, існує лише після ввімкнення lingering.

Є ще один крок, якого ніхто не очікує. sudo -iu ollama надає shell, але не session bus, тому systemctl --user негайно завершується з помилкою:

Failed to connect to bus: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined

systemd шукає user bus у $XDG_RUNTIME_DIR/bus, а sudo -i не встановлює цю змінну. Установіть її вручну в кожному адміністративному shell, у якому керуєте цим сервісом:

sudo -iu ollama
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user status

Де зберігаються файли моделей і скільки дискового простору потрібно запланувати

Ollama записує ваги в /root/.ollama/models усередині контейнера. Підключіть каталог із домашнього каталогу користувача до цього шляху, і файли зберігатимуться в місці, розмір якого можна виміряти: /home/ollama/ollama-data/models. Б blobs зберігаються в models/blobs як файли з адресацією за вмістом, а models/manifests містить невеликий індекс, у якому вони названі. Якщо замість цього використати іменований том, як у публікації Fedora Magazine, те саме дерево каталогів буде розташоване в /home/ollama/.local/share/containers/storage/volumes/<volume>/_data. У будь-якому разі ollama pull і ollama run записують ваги в одне й те саме дерево, а різниця між цими двома командами полягає лише в тому, чи відкривається сеанс чату після завершення завантаження.

Оцініть потрібний дисковий простір до завантаження будь-яких файлів. Опубліковані розміри завантажень визначають мінімальну потребу.

ChartPublished download size per Ollama model tag, ollama.com/library, checked 13 August 2026
The data behind this chart
[
  {
    "label": "gemma3:4b",
    "download_gb": 3.3
  },
  {
    "label": "mistral:7b",
    "download_gb": 4.4
  },
  {
    "label": "qwen3:8b",
    "download_gb": 5.2
  },
  {
    "label": "gemma3:12b",
    "download_gb": 8.1
  },
  {
    "label": "qwen3:14b",
    "download_gb": 9.3
  },
  {
    "label": "gemma3:27b",
    "download_gb": 17
  },
  {
    "label": "qwen3:30b",
    "download_gb": 19
  }
]

Усі 7 рядків містять дані, опубліковані на ollama.com/library, а не розміри, виміряні на диску. Найменший тег у цьому списку, gemma3:4b, завантажує 3.3 GB. Найбільший, qwen3:30b, завантажує 19 GB. Сам образ контейнера додатково зберігається у власному сховищі Podman, тому перевірте обидва показники за допомогою podman system df і df -h /home. Для завантаження модель також потребує в RAM приблизно стільки місця, скільки займає її файл, а також додаткового простору для контекстного вікна. Тому модель розміром 19 GB не запуститься на VPS із 16 GB RAM.

Зафіксуйте тег образу та використовуйте повне ім’я реєстру

sudo -iu ollama
export XDG_RUNTIME_DIR=/run/user/$(id -u)
mkdir -p ~/ollama-data ~/.config/containers/systemd
podman pull docker.io/ollama/ollama:0.32.9

Використовуйте тег випущеної версії 0.32.9 станом на August 2026, а не latest. Зафіксований тег означає, що після перезапуску о 04:00 ви отримаєте той самий бінарний файл, який тестували. Тому будь-яка зміна поведінки буде наслідком внесених вами змін. Docker Hub також публікує теги -rc і -rocm для тих самих версій. Використовуйте звичайний тег, якщо у вас немає AMD GPU.

Також указуйте хост реєстру. У Fedora коротке ім’я в unit systemd не може запитати підтвердження в терміналі, тому unit завершується з помилкою:

Error: short-name "ollama/ollama" did not resolve to an alias and no unqualified-search registries are defined

Попередньо завантажити образ вручну необов’язково, але це корисно. Так багатогігабайтне завантаження не враховується в тайм-ауті запуску unit.

Юніт Quadlet, який переживає перезавантаження

Quadlet — це генератор systemd для Podman. Ви створюєте файл .container, systemd перетворює його на сервіс під час завантаження, і podman generate systemd більше не потрібен. Збережіть його як /home/ollama/.config/containers/systemd/ollama.container. Власником файлу має бути користувач ollama.

[Unit]
Description=Ollama API (rootless)
After=network-online.target
Wants=network-online.target

[Container]
Image=docker.io/ollama/ollama:0.32.9
ContainerName=ollama
PublishPort=127.0.0.1:11434:11434
Volume=/home/ollama/ollama-data:/root/.ollama:Z
Environment=OLLAMA_KEEP_ALIVE=30m
Environment=OLLAMA_MAX_LOADED_MODELS=1

[Service]
Restart=always
TimeoutStartSec=900

[Install]
WantedBy=default.target

Ім’я файлу визначає ім’я сервісу, тому ollama.container стає ollama.service.

systemctl --user daemon-reload
systemctl --user start ollama.service
systemctl --user status ollama.service

status має показати active (running). Не запускайте systemctl --user enable ollama.service. Цей юніт не існує на диску як файл, тому systemd відмовляється:

Failed to enable unit: Unit file /run/user/1001/systemd/generator/ollama.service is transient or generated.

Секція [Install] уже виконує цю функцію. Quadlet сам створює посилання для запуску під час завантаження в межах daemon-reload, тому ця команда є обов’язковою. TimeoutStartSec=900 охоплює перший запуск, під час якого ще потрібно завантажити образ, оскільки стандартних 90 секунд недостатньо для завантаження обсягом два гігабайти, і systemd завершить запуск з помилкою. OLLAMA_KEEP_ALIVE=30m зберігає модель у пам’яті між запитами замість вивантаження через п’ять хвилин; компроміси описано в матеріалі як залишити модель Ollama завантаженою в пам’ять. Якщо деякі терміни systemd тут вам незнайомі, у матеріалі як працюють сервіси й таймери systemd на VPS описано самі юніти.

Чому каталог моделей повертає permission denied у SELinux

У Fedora, RHEL, Rocky та AlmaLinux SELinux типово працює в режимі enforcing. Процес контейнера працює в домені container_t, а каталог у домашньому каталозі користувача має мітку user_home_t. Політика не дозволяє цим контекстам взаємодіяти, тому Ollama не може створити дерево моделей, і контейнер завершує роботу. У цих системах getenforce виводить Enforcing, а відмову доступу записано в журнал:

sudo ausearch -m avc -ts recent

Ви побачите рядок із назвою домену та цільової мітки:

avc:  denied  { write } for  pid=1842 comm="ollama" name="models" dev="vda1" ino=131077 scontext=system_u:system_r:container_t:s0:c214,c827 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=dir permlisted=0

:Z наприкінці рядка Volume= усуває цю проблему. Команда повторно маркує каталог хоста як container_file_t і призначає йому приватну категорію MCS (multi-category security), яку має лише цей контейнер. Варіант :z у нижньому регістрі використовує спільну мітку. Він потрібен, коли два контейнери читають один і той самий каталог.

Врахуйте особливості :Z, оскільки ця команда рекурсивно змінює мітки без додаткового повідомлення. Якщо вказати їй /home/ollama, буде повторно перемарковано кожен файл у цьому домашньому каталозі. Це порушить доступ до SSH-ключів користувача. Завжди передавайте :Z окремий підкаталог, у якому немає інших даних. Іменованим томам ця команда не потрібна, оскільки Podman правильно маркує їх під час створення. Докладніше про це написано в матеріалі Основи SELinux для сервера, де пояснюються контексти та булеві параметри. В Ubuntu та Debian натомість використовується AppArmor, :Z там нічого не робить, тому його наявність у unit-файлі не створює проблем.

Закрийте порт 11434 і звертайтеся до API через SSH

PublishPort=127.0.0.1:11434:11434 прив’язує порт на стороні хоста до loopback. Перевірте це:

ss -ltnp | grep 11434
curl http://127.0.0.1:11434

У виведенні ss має бути показано 127.0.0.1:11434. 0.0.0.0:11434 або *:11434 означає, що порт відкритий для Інтернету, а curl має відповісти на Ollama is running.

Точно визначте, до якого боку виконується прив’язування. Адреса в PublishPort є адресою хоста. Усередині контейнера Ollama має й надалі слухати на всіх інтерфейсах — це значення за замовчуванням образу. Якщо Environment=OLLAMA_HOST=127.0.0.1 прив’язує Ollama до loopback самого контейнера, Podman натомість перенаправляє опублікований трафік на мережеву адресу контейнера, тому кожен запит відхиляється навіть із хоста.

Відкритий порт 11434 створює дві проблеми. Ollama не має автентифікації, тому будь-хто, хто отримує доступ до порту, може переглянути список ваших моделей через /api/tags, запускати інференс на вашому CPU і використовувати доступний вам обсяг трафіку через /api/generate, завантажувати нові моделі на диск і видаляти наявні. Крім того, звичайний HTTP до віддаленого порту передає промпти та результати в незашифрованому вигляді, тому кожна машина на цьому шляху може їх прочитати. Обидві проблеми зникають, якщо порт не виходить за межі цього хоста.

З робочої станції перенаправте порт через SSH:

ssh -N -L 11434:127.0.0.1:11434 you@vps.example.com

Тепер http://127.0.0.1:11434 на вашому ноутбуці є Ollama на сервері, доступна в межах шифрування SSH-сеансу. Якщо на ноутбуці вже запущена Ollama, локальне прив’язування завершиться помилкою bind [127.0.0.1]:11434: Address already in use. Використайте -L 11435:127.0.0.1:11434 і вкажіть клієнту порт 11435.

Якщо доступ потрібен браузерному клієнту, натомість розмістіть перед ним reverse proxy із паролем. Блок сайту Caddy складається з чотирьох рядків, а caddy hash-password виводить потрібний йому bcrypt-хеш:

ollama.example.com {
  basic_auth {
    you $2a$14$replace_with_the_generated_hash
  }
  reverse_proxy 127.0.0.1:11434
}

Caddy самостійно отримує сертифікат через TLS (transport layer security), тому трафік шифрується. Спочатку перевірте клієнт: багато інструментів, які взаємодіють з Ollama, не мають поля для заголовка Authorization і не працюватимуть із basic auth, якщо отримають лише 401 Unauthorized. SSH-тунель не має цієї проблеми, тому саме його тут рекомендовано використовувати за замовчуванням.

Завантажте модель і перевірте весь шлях

podman exec -it ollama ollama pull gemma3:4b
curl -s http://127.0.0.1:11434/api/tags
curl -s http://127.0.0.1:11434/api/generate -d '{"model":"gemma3:4b","prompt":"Reply with the single word: ready","stream":false}'
du -sh ~/ollama-data/models

/api/tags повертає JSON зі списком gemma3:4b. /api/generate повертає JSON-об’єкт із полем response після паузи, поки ваги завантажуються з диска. du має містити число, близьке до опублікованого розміру завантаження. Потім перевірте саме те, заради чого написано весь цей посібник:

sudo reboot
# reconnect, then:
sudo -iu ollama
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user is-active ollama.service

active означає, що з’єднання не розривається, розділ [Install] і daemon-reload виконали свою роботу. inactive означає, що бракує одного з трьох компонентів.

Відмови, а також повідомлення, які ви побачите

Контейнер зникає після перезавантаження. Спочатку перевірте loginctl show-user ollama --property=Linger, оскільки без Linger=yes екземпляр systemd користувача не запускається під час завантаження. Якщо ввімкнено lingering, у файлі .container відсутній розділ [Install] або ви відредагували файл, але не виконали systemctl --user daemon-reload.

Error: statfs /home/ollama/ollama-data: no such file or directory. Джерело bind mount має існувати до запуску контейнера. Podman не створює каталоги на хості автоматично. Виконайте mkdir -p ~/ollama-data від імені користувача ollama.

Запуск завершується помилкою через 90 секунд. journalctl --user -u ollama.service показує Start operation timed out. Terminating., оскільки завантаження образу ще тривало. Завантажте образ вручну або залиште TimeoutStartSec=900.

Контейнер запускається та завершує роботу. podman logs ollama і sudo ausearch -m avc -ts recent разом показують, чи пов’язана проблема з міткою SELinux. Повідомлення AVC із зазначенням container_t і user_home_t означає, що відсутній :Z.

Запити з хоста відхиляються. Виконання curl: (7) Failed to connect to 127.0.0.1 port 11434: Connection refused для сервісу active зазвичай означає, що OLLAMA_HOST було налаштовано на loopback-адресу всередині контейнера. Видаліть цей рядок.

Генерація дуже повільна або контейнер завершується примусово. Без GPU інференс виконується на CPU, тому велика модель за своєю природою працює повільно. Якщо контейнер завершується під час запиту, а в журналах є signal: killed, це означає, що спрацював kernel out-of-memory killer. Виберіть менший тег із наведеної вище таблиці.

Оновлення зафіксованого образу

Фіксація версії означає, що оновлення виконуєте ви, а не воно відбувається автоматично. Відредагуйте Image= у ollama.container, потім перезавантажте конфігурацію та перезапустіть сервіс:

systemctl --user daemon-reload
systemctl --user restart ollama.service
podman exec ollama ollama --version

Моделі зберігаються у bind mount, тому після зміни образу вони залишаються без змін. AutoUpdate=registry у розділі [Container] потрібен для запуску з рухомим тегом і не дає користі поруч із тегом фіксованої версії, оскільки вміст такого тега не змінюється. Створіть резервну копію /home/ollama/ollama-data/models/manifests і файла .container, а blobs не копіюйте: вони великі, і ollama pull повторно завантажить їх на новому сервері.

FAQ

Чому rootless-контейнер Podman зупиняється, коли я виходжу із системи?

Екземпляр systemd користувача та його каталог /run/user/<uid> видаляються, коли завершується останній сеанс цього користувача. Разом із ними зупиняється кожен rootless-контейнер. Виконайте sudo loginctl enable-linger ollama і переконайтеся, що loginctl show-user ollama --property=Linger виводить Linger=yes. Увімкніть lingering до створення unit Quadlet, оскільки каталог runtime, потрібний unit, існує лише після ввімкнення lingering.

Чи потрібні SELinux-мітки для каталогу моделей Ollama?

У Fedora, RHEL, Rocky та AlmaLinux — так, якщо ви монтуєте каталог хоста через bind mount. Контейнер працює в домені container_t, а каталог у домашній теці має мітку user_home_t. Тому запис забороняється, і Ollama завершує роботу. Додайте :Z до рядка Volume= і вкажіть для нього окремий підкаталог, оскільки перемаркування виконується рекурсивно, а вказування :Z на весь домашній каталог порушує доступ цього користувача до SSH-ключів. Іменовані томи Podman маркує правильно, тому додаткові налаштування не потрібні.

Скільки дискового простору потребує модель Ollama?

Орієнтуйтеся на опублікований розмір завантаження на ollama.com/library: від 3.3 GB для gemma3:4b до 19 GB для qwen3:30b. Додайте до цього розмір образу Podman і залиште запас, оскільки друга модель не замінює першу на диску. Перевірте df -h /home перед завантаженням і du -sh ~/ollama-data/models після нього. Плануйте RAM так само: під час завантаження моделі потрібно приблизно стільки пам’яті, скільки займає її файл, плюс пам’ять для context window.

Чи безпечно відкривати порт 11434 на VPS?

Ні. Ollama не має вбудованої автентифікації, тому кожен, хто отримує доступ до порту, може переглядати ваші моделі, видаляти їх, завантажувати нові на диск і запускати inference, використовуючи ваш CPU та дозволений обсяг трафіку. Звичайний HTTP через інтернет також передає кожен prompt і completion у відкритому тексті. Прив’яжіть сторону хоста до 127.0.0.1 за допомогою PublishPort=127.0.0.1:11434:11434, перевірте це через ss -ltnp | grep 11434 і підключайтеся через SSH-тунель або reverse proxy, який вимагає пароль.