Menjalankan Ollama di Podman Rootless pada VPS
Panduan menjalankan Ollama sebagai container Podman rootless di VPS, dengan user khusus, lingering, Quadlet setelah reboot, label SELinux, dan port tertutup.
Menjalankan Ollama dalam Podman rootless pada VPS
Untuk menjalankan Ollama dalam Podman rootless pada server, lima hal harus terpenuhi yang dapat diabaikan dalam panduan desktop. Pengguna tanpa hak istimewa khusus memiliki container tersebut. Lingering diaktifkan untuk pengguna itu agar container tetap berjalan setelah Anda logout. File Quadlet menyerahkan container kepada systemd agar container berjalan kembali setelah reboot. Direktori model memiliki label SELinux pada distribusi yang menerapkan SELinux. API hanya mendengarkan pada loopback, dan Anda mengaksesnya melalui tunnel SSH (secure shell).
Ollama adalah server untuk large language models (LLM). Ollama menyimpan bobot model di disk, memuatnya ke memory, dan menjawab HTTP request pada port 11434. Ollama tidak memiliki login, API key, atau akun pengguna, sehingga jaringan menjadi satu-satunya kontrol akses yang tersedia. Podman menjalankan container tanpa daemon dan tanpa root, sehingga apa pun yang keluar dari container pada awalnya berjalan sebagai pengguna biasa tanpa hak istimewa. Jika Anda ingin membaca perbandingan runtime terlebih dahulu, baca perbedaan Podman dan Docker pada VPS. Jika Anda ingin melewati container sepenuhnya, menginstal Ollama langsung pada VPS adalah langkah yang lebih singkat.
SSD Nodes menyediakan Fedora dalam daftar image-nya, dan Fedora secara default menyertakan Podman serta SELinux (security-enhanced Linux). Setiap perintah di bawah ini berjalan pada distribusi apa pun yang menyediakan Podman 5 atau yang lebih baru.
Mengapa versi laptop memerlukan perubahan di server
Fedora Magazine menerbitkan panduan yang jelas tentang stack ini pada 5 Agustus 2026: Menjalankan Ollama Secara Lokal dengan Podman di Fedora Linux, oleh Yazan Monshed. Panduan itu cocok untuk satu jam pertama mempelajari alat-alat tersebut. Namun, panduan itu ditujukan untuk laptop, dan empat pilihannya berperilaku berbeda pada mesin dengan alamat IP publik.
- Container dijalankan dengan
podman run -dbiasa. Container yang dijalankan secara manual tidak akan berjalan kembali setelah reboot karena tidak ada konfigurasi yang memintanya untuk start. - Panduan tersebut menggunakan tag yang terus berubah, yaitu
ollama/ollama. Pada laptop, Anda akan menyadari perubahan perilakunya pada hari perubahan itu terjadi. Di server, tanda pertama biasanya berupa script yang tiba-tiba berhenti bekerja pada malam sebelumnya. - Publikasi dilakukan dengan
-p 11434:11434, yang mengikat semua interface. Di belakang router rumah, layanan tersebut tidak dapat dijangkau dari Internet. Di VPS, konfigurasi ini menjadi API inference publik tanpa password. - Container dijalankan sebagai user login Anda sendiri. Di server, account yang memiliki container seharusnya tidak memiliki resource lain, sehingga jika terjadi container breakout, penyerang masuk ke home directory yang kosong.
Tidak ada yang salah dengan pilihan tersebut untuk mesin yang menjadi sasaran panduan. Setiap pilihan hanya perlu ditinjau kembali ketika server dapat dijangkau dari mana saja dan tidak ada orang yang duduk di depannya.
Buat pengguna tanpa hak istimewa, lalu periksa subuid
Rootless Podman memetakan ID pengguna internal (UID) container ke blok ID yang belum digunakan pada host. Blok tersebut dideklarasikan dalam /etc/subuid dan /etc/subgid. Tanpa blok ini, container rootless sama sekali tidak dapat dimulai.
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/subgidgrep seharusnya menampilkan dua baris, masing-masing dari satu file, dan setiap baris mencantumkan rentang 65536 ID:
/etc/subuid:ollama:100000:65536
/etc/subgid:ollama:100000:65536Nomor awal Anda akan berbeda, dan itu tidak masalah. Jika grep tidak menampilkan apa pun, useradd belum mengalokasikan rentang, dan perintah podman pertama sebagai pengguna tersebut akan gagal seperti ini:
Error: cannot find UID/GID for user ollama: no subuid ranges found for user "ollama" in /etc/subuidTetapkan rentang yang tidak digunakan oleh pengguna lain, lalu beri tahu Podman bahwa pemetaan lamanya sudah tidak berlaku:
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 ollama
sudo -iu ollama podman system migrateMengunci kata sandi berarti tidak ada yang dapat login langsung sebagai ollama. Anda mengakses akun tersebut dari pengguna admin dengan sudo -iu ollama.
Aktifkan lingering agar service tetap berjalan setelah logout
Instance systemd milik pengguna biasanya dimulai saat login dan dihentikan saat logout, dan /run/user/<uid> ikut dihapus. Setiap container rootless milik pengguna tersebut berhenti pada saat yang sama. Lingering membuat instance pengguna tetap berjalan tanpa sesi yang terhubung.
sudo loginctl enable-linger ollama
loginctl show-user ollama --property=LingerPerintah tersebut harus menampilkan Linger=yes. Aktifkan lingering sebelum membuat unit, karena direktori yang diperlukan unit, /run/user/<uid>, hanya tersedia setelah lingering aktif.
Ada satu langkah lain yang sering tidak terduga. sudo -iu ollama memberikan shell, tetapi tidak memberikan session bus, sehingga systemctl --user langsung gagal:
Failed to connect to bus: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not definedsystemd mencari user bus di $XDG_RUNTIME_DIR/bus, dan sudo -i tidak menetapkan variabel tersebut. Tetapkan variabel itu secara manual di setiap shell admin yang digunakan untuk mengelola service ini:
sudo -iu ollama
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user statusLokasi blob model dan perencanaan kapasitas disk
Ollama menulis bobot model ke /root/.ollama/models di dalam container. Kaitkan sebuah direktori dari home pengguna ke path tersebut agar file tersimpan di lokasi yang dapat Anda ukur: /home/ollama/ollama-data/models. Blob disimpan di models/blobs sebagai file berbasis alamat konten, sedangkan models/manifests berisi indeks kecil yang memberi nama pada file tersebut. Jika Anda menggunakan named volume, seperti dalam artikel Fedora Magazine, tree yang sama berada di bawah /home/ollama/.local/share/containers/storage/volumes/<volume>/_data. Dalam kedua kasus, ollama pull dan ollama run menulis bobot ke tree yang sama. Perbedaan kedua perintah tersebut hanya terletak pada apakah sesi chat dibuka setelah proses download selesai.
Tentukan kapasitas disk sebelum mengunduh apa pun. Ukuran download yang dipublikasikan memberikan batas minimum.
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
}
]Seluruh 7 baris adalah angka yang dipublikasikan di ollama.com/library, bukan ukuran yang diukur langsung dari disk. Tag terkecil di sini, gemma3:4b, memerlukan download sebesar 3.3 GB. Tag terbesar, qwen3:30b, memerlukan download sebesar 19 GB. Image container menggunakan ruang tambahan di storage milik Podman, jadi periksa kedua angka tersebut secara bersamaan dengan podman system df dan df -h /home. Model juga memerlukan RAM kira-kira sebesar ukuran filenya saat dimuat, ditambah ruang untuk context window. Karena itu, model berukuran 19 GB tidak akan berjalan pada VPS dengan RAM 16 GB.
Tetapkan tag image, dan gunakan nama registry lengkap
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.9Gunakan tag versi yang telah dirilis, yaitu 0.32.9 per Agustus 2026, bukan latest. Tag yang ditetapkan memastikan restart pada pukul 04:00 menggunakan binary yang sama dengan yang Anda uji. Dengan demikian, setiap perubahan perilaku berasal dari perubahan yang Anda buat. Docker Hub juga menerbitkan tag -rc dan -rocm untuk versi yang sama. Pilih tag biasa, kecuali Anda memiliki GPU AMD.
Tuliskan host registry juga. Di Fedora, nama pendek dalam unit systemd tidak memiliki terminal untuk menampilkan prompt. Akibatnya, unit gagal dengan pesan:
Error: short-name "ollama/ollama" did not resolve to an alias and no unqualified-search registries are definedMenjalankan pull secara manual terlebih dahulu bersifat opsional, tetapi berguna karena proses tersebut memindahkan pengunduhan berukuran beberapa gigabyte ke luar batas waktu start unit.
Unit Quadlet yang tetap berfungsi setelah reboot
Quadlet adalah systemd generator milik Podman. Anda menulis file .container, lalu systemd mengubahnya menjadi service saat boot, sehingga podman generate systemd tidak lagi diperlukan. Simpan file ini sebagai /home/ollama/.config/containers/systemd/ollama.container dan tetapkan kepemilikannya kepada user 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.targetNama file menentukan nama service, sehingga ollama.container menjadi ollama.service.
systemctl --user daemon-reload
systemctl --user start ollama.service
systemctl --user status ollama.servicestatus seharusnya menampilkan active (running). Jangan jalankan systemctl --user enable ollama.service. Unit tersebut tidak ada sebagai file di disk, sehingga systemd menolaknya:
Failed to enable unit: Unit file /run/user/1001/systemd/generator/ollama.service is transient or generated.Bagian [Install] sudah menjalankan tugas tersebut. Quadlet membuat link untuk menjalankan service saat boot selama daemon-reload. Karena itu, perintah tersebut wajib dijalankan. TimeoutStartSec=900 memberikan waktu yang cukup untuk proses start pertama yang masih harus mengunduh image. Nilai default 90 detik tidak cukup untuk mengunduh file berukuran dua gigabyte, sehingga systemd akan menghentikan proses start dan menandainya sebagai gagal. OLLAMA_KEEP_ALIVE=30m mempertahankan model di memory di antara request, bukan membongkarnya setelah lima menit. Trade-off-nya dijelaskan dalam mempertahankan model Ollama di memory. Jika ada istilah systemd di sini yang belum Anda kenal, cara kerja service dan timer systemd pada VPS menjelaskan unit tersebut.
Mengapa direktori model menghasilkan penolakan izin di SELinux
Di Fedora, RHEL, Rocky, dan AlmaLinux, SELinux secara default berada dalam mode enforcing. Proses container berjalan dalam domain container_t, sedangkan direktori di home pengguna memiliki label user_home_t. Kebijakan SELinux tidak mengizinkan keduanya saling mengakses. Akibatnya, Ollama tidak dapat membuat struktur direktori model dan container berhenti. Pada sistem ini, getenforce menampilkan Enforcing, dan penolakan tersebut dicatat:
sudo ausearch -m avc -ts recentAnda akan melihat baris yang mencantumkan domain dan label target:
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 di akhir baris Volume= adalah perbaikannya. Perintah tersebut memberi label ulang pada direktori host menjadi container_file_t dan menetapkan kategori MCS (multi-category security) privat yang hanya digunakan oleh container ini. Huruf kecil :z menggunakan label bersama. Gunakan opsi tersebut jika dua container perlu membaca direktori yang sama.
Perhatikan :Z karena perintah ini bersifat destruktif dan tidak menampilkan banyak informasi. Pelabelan ulang dilakukan secara rekursif. Jika diarahkan ke /home/ollama, setiap file di dalam direktori home tersebut akan diberi label ulang. Hal ini dapat menyebabkan akses ke kunci SSH pengguna tersebut gagal. Selalu berikan :Z subdirektori khusus yang tidak berisi file lain. Named volume tidak memerlukannya karena Podman memberi label yang benar saat membuat volume tersebut. Untuk penjelasan yang lebih luas, dasar-dasar SELinux untuk server menjelaskan context dan boolean. Ubuntu dan Debian menggunakan AppArmor. Di sana, :Z tidak melakukan apa pun, dan membiarkannya di dalam unit tidak menimbulkan masalah.
Tutup port 11434 dan akses API melalui SSH
PublishPort=127.0.0.1:11434:11434 mengikat sisi host ke loopback. Konfirmasikan dengan perintah berikut:
ss -ltnp | grep 11434
curl http://127.0.0.1:11434Output ss harus menampilkan 127.0.0.1:11434. 0.0.0.0:11434 atau *:11434 berarti port terbuka ke Internet, dan curl harus merespons Ollama is running.
Pastikan Anda memahami sisi yang diikat. Alamat dalam PublishPort adalah alamat host. Di dalam container, Ollama harus tetap mendengarkan pada semua interface, sesuai default image. Menetapkan Environment=OLLAMA_HOST=127.0.0.1 akan mengikat Ollama ke loopback milik container sendiri. Podman kemudian meneruskan trafik yang dipublikasikan ke alamat jaringan container, sehingga setiap permintaan ditolak, termasuk permintaan dari host.
Port 11434 yang terbuka menimbulkan dua risiko. Ollama tidak memiliki autentikasi. Siapa pun yang dapat menjangkau port tersebut dapat mencantumkan model Anda melalui /api/tags, menjalankan inferensi menggunakan CPU dan kuota bandwidth Anda melalui /api/generate, mengunduh model baru ke disk, serta menghapus model yang tersedia. Kedua, HTTP biasa ke port remote mengirimkan prompt dan hasil inferensi dalam teks biasa. Setiap mesin di sepanjang jalur dapat membacanya. Kedua masalah ini hilang jika port tidak pernah meninggalkan server.
Dari workstation, teruskan port melalui SSH:
ssh -N -L 11434:127.0.0.1:11434 you@vps.example.comSekarang http://127.0.0.1:11434 pada laptop Anda adalah Ollama milik server, di dalam enkripsi sesi SSH. Jika laptop Anda sudah menjalankan Ollama, pengikatan lokal gagal dengan bind [127.0.0.1]:11434: Address already in use. Gunakan -L 11435:127.0.0.1:11434 dan arahkan client Anda ke 11435.
Jika client browser memerlukannya, gunakan reverse proxy dengan kata sandi di depannya. Site block Caddy terdiri dari empat baris, dan caddy hash-password mencetak hash bcrypt yang diperlukan:
ollama.example.com {
basic_auth {
you $2a$14$replace_with_the_generated_hash
}
reverse_proxy 127.0.0.1:11434
}Caddy memperoleh sertifikat melalui TLS (transport layer security) secara mandiri, sehingga trafik terenkripsi. Uji client Anda terlebih dahulu. Banyak tool yang berkomunikasi dengan Ollama tidak memiliki kolom untuk header Authorization, sehingga akan gagal terhadap basic auth dengan 401 Unauthorized kosong. Tunnel SSH tidak memiliki masalah tersebut, sehingga menjadi rekomendasi default di sini.
Unduh model dan periksa seluruh jalur
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 mengembalikan JSON yang mencantumkan gemma3:4b. /api/generate mengembalikan objek JSON dengan kolom response setelah jeda saat bobot dimuat dari disk. du seharusnya melaporkan angka yang mendekati ukuran unduhan yang dipublikasikan. Selanjutnya, buktikan bagian yang menjadi fokus seluruh panduan ini:
sudo reboot
# reconnect, then:
sudo -iu ollama
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user is-active ollama.serviceactive berarti proses tetap berjalan, bagian [Install] dan daemon-reload telah menjalankan fungsinya. inactive berarti salah satu dari ketiganya tidak ada.
Mode kegagalan dan string yang akan Anda lihat
Container hilang setelah reboot. Periksa loginctl show-user ollama --property=Linger terlebih dahulu, karena tanpa Linger=yes instance systemd milik pengguna tidak pernah dimulai saat boot. Jika lingering aktif, bagian [Install] tidak ada dalam file .container, atau Anda mengedit file tersebut tetapi tidak menjalankan systemctl --user daemon-reload.
Error: statfs /home/ollama/ollama-data: no such file or directory. Sumber bind mount harus ada sebelum container dimulai. Podman tidak membuat direktori host untuk Anda. Jalankan mkdir -p ~/ollama-data sebagai pengguna ollama.
Start gagal setelah 90 detik. journalctl --user -u ollama.service menampilkan Start operation timed out. Terminating. karena image masih di-pull. Lakukan pull secara manual, atau pertahankan TimeoutStartSec=900.
Container dimulai lalu berhenti. podman logs ollama dan sudo ausearch -m avc -ts recent secara bersama-sama menunjukkan apakah penyebabnya adalah label SELinux. AVC yang menyebut container_t dan user_home_t berarti :Z tidak ada.
Permintaan dari host ditolak. curl: (7) Failed to connect to 127.0.0.1 port 11434: Connection refused dengan service active biasanya berarti OLLAMA_HOST ditetapkan ke alamat loopback di dalam container. Hapus baris tersebut.
Generation sangat lambat, atau container dihentikan. Tanpa GPU, inference berjalan pada CPU dan model berukuran besar memang lambat. Container yang berhenti di tengah permintaan dengan signal: killed dalam log menunjukkan kernel out-of-memory killer, jadi pilih tag yang lebih kecil dari chart di atas.
Memperbarui image yang dipatok
Pinning berarti pembaruan dilakukan secara sengaja, bukan terjadi tanpa kendali. Edit Image= di ollama.container, lalu muat ulang dan mulai ulang:
systemctl --user daemon-reload
systemctl --user restart ollama.service
podman exec ollama ollama --versionModel berada di bind mount, sehingga tetap utuh saat image diganti. AutoUpdate=registry di bagian [Container] ditujukan bagi pengguna yang menjalankan tag yang berubah, dan tidak berguna jika digunakan bersama tag versi tetap karena isi tag tersebut tidak pernah berubah. Cadangkan /home/ollama/ollama-data/models/manifests dan file .container, lalu lewati blob: ukurannya besar, dan ollama pull akan mengambilnya lagi di mesin baru.
FAQ
Mengapa container Podman rootless berhenti saat saya logout?
Instance systemd milik pengguna dan direktori /run/user/<uid> miliknya dibongkar saat sesi terakhir pengguna tersebut berakhir, sehingga semua container rootless ikut berhenti. Jalankan sudo loginctl enable-linger ollama dan pastikan loginctl show-user ollama --property=Linger menampilkan Linger=yes. Aktifkan lingering sebelum membuat unit Quadlet, karena direktori runtime yang diperlukan unit hanya tersedia setelah lingering aktif.
Apakah saya memerlukan label SELinux pada direktori model Ollama?
Di Fedora, RHEL, Rocky, dan AlmaLinux, ya, jika Anda melakukan bind mount direktori host. Container berjalan dalam domain container_t, sedangkan direktori di folder home memiliki label user_home_t, sehingga operasi tulis ditolak dan Ollama berhenti. Tambahkan :Z ke baris Volume= dan gunakan subdirektori khusus, karena pelabelan ulang dilakukan secara rekursif dan mengarahkan :Z ke seluruh direktori home akan mengganggu akses kunci SSH pengguna tersebut. Named volume diberi label yang benar oleh Podman dan tidak memerlukan pengaturan tambahan.
Berapa banyak ruang disk yang diperlukan model Ollama?
Mulailah dari ukuran download yang dipublikasikan di ollama.com/library, yang berkisar dari 3.3 GB untuk gemma3:4b hingga 19 GB untuk qwen3:30b. Tambahkan ukuran image Podman, lalu sisakan ruang cadangan, karena model kedua tidak menggantikan model pertama di disk. Periksa df -h /home sebelum melakukan pull dan du -sh ~/ollama-data/models sesudahnya. Rencanakan RAM dengan cara yang sama: model memerlukan memori kira-kira sebesar ukuran filenya saat dimuat, ditambah ukuran context window.
Apakah aman mengekspos port 11434 pada VPS?
Tidak. Ollama tidak menyediakan autentikasi apa pun secara bawaan, sehingga siapa pun yang dapat mengakses port tersebut dapat mencantumkan model Anda, menghapusnya, melakukan pull model baru ke disk, serta menjalankan inference menggunakan CPU dan kuota bandwidth Anda. HTTP biasa melalui internet juga mengirim setiap prompt dan completion dalam teks biasa. Bind sisi host ke 127.0.0.1 menggunakan PublishPort=127.0.0.1:11434:11434, konfirmasikan dengan ss -ltnp | grep 11434, lalu akses melalui SSH tunnel atau reverse proxy yang mewajibkan password.