Jak bezpiecznie hostować Ollama na VPS
Instalacja Ollama na VPS wymaga 8 GB RAM dla modelu 7B. Dowiedz się, jak uniknąć otwartego portu 11434 i bezpiecznie korzystać z API przez 127.0.0.1.
Cel projektu
Pojedynczy model językowy typu open-weight działający na własnym serwerze. Model odpowiada poprzez HTTP API oraz opcjonalnie poprzez stronę czatu w przeglądarce. Ollama odpowiada za pobieranie modelu, ładowanie go do pamięci RAM oraz obsługę żądań na porcie http://127.0.0.1:11434. Instalacja wymaga wykonania jednej komendy. Najtrudniejsze aspekty dotyczą innych kwestii: wyboru modelu, który zmieści się w pamięci RAM VPS, oraz uniknięcia przypadkowego udostępnienia niezabezpieczonego serwera wnioskowania do publicznego internetu.
Dwa ostrzeżenia. VPS działający wyłącznie na procesorze (CPU-only) uruchamia małe modele wolno. API nie posiada wbudowanego mechanizmu uwierzytelniania. Oba te problemy zostaną szczegółowo omówione poniżej, ponieważ są to najczęstsze źródła błędów.
Weryfikacja zapotrzebowania na zasoby, w prostych liczbach
Zapotrzebowanie modelu na pamięć to w przybliżeniu rozmiar jego pliku, plus około 1 GB narzutu podczas pracy (runtime overhead), plus dodatkowa ilość na okno kontekstowe. Domyślne modele Ollama są kwantyzowane do 4 bitów (oznaczone jako Q4), co kosztuje około 0,5 GB pamięci RAM na każdy miliard parametrów. Obliczenia są zatem proste i determinują wymagania sprzętowe.
Model 3B, taki jak llama3.2:3b, zajmuje około 2 GB podczas pobierania i wymaga około 4 GB wolnej pamięci RAM do działania. Model 7B lub 8B, taki jak mistral:7b lub llama3.1:8b, zajmuje około 5 GB na dysku i wymaga około 8 GB RAM, przy czym 16 GB zapewnia komfort pracy. Model 13B lub 14B wymaga około 16 GB. Modele z zakresu 30B-70B wymagają maszyny z dużą ilością pamięci RAM lub, w praktyce, jednostki GPU — na VPS z CPU model albo nie zmieści się w pamięci, albo będzie odpowiadał zbyt wolno, aby był użyteczny.
Kwestia prędkości jest często niedoszacowana. Inferencja na CPU jest ograniczona przepustowością pamięci, a nie częstotliwością taktowania; współdzielone vCPU na VPS posiada ograniczoną przepustowość. Należy spodziewać się wydajności rzędu pojedynczych lub niskich dwucyfrowych wartości tokenów na sekundę: model 7-8B Q4 może osiągać od 4 do 10 tokenów na sekundę, a model 3B od 10 do 25 tokenów na sekundę. GPU jest o rząd wielkości szybsze. Są to wartości przybliżone — należy zmierzyć wydajność własnego urządzenia, co pokazuje poniższy krok uruchomieniowy. Należy ufać własnym wynikom eval rate, a nie liczbom w artykułach, w tym w tym tekście.
Wniosek praktyczny: małe modele kwantyzowane na CPU są przydatne do tworzenia szkiców, streszczania i klasyfikacji, jeśli można zaakceptować ich tempo pracy. Dla wszystkiego, co wymaga większej skali lub prędkości, należy zaplanować instancję z GPU.
Aby porównać konkretny model z konkretną maszyną, należy oszacować zapotrzebowanie na pamięć tutaj:
Instalacja Ollama
Dostępne są dwie metody instalacji. Oficjalny skrypt jest najprostszym rozwiązaniem dla czystych instancji VPS:
curl -fsSL https://ollama.com/install.sh | shProces ten tworzy użytkownika systemowego o nazwie ollama, instaluje plik binarny w lokalizacji /usr/local/bin/ollama oraz rejestruje usługę systemd o nazwie ollama.service. Usługa uruchamia się podczas startu systemu i przypisuje port 127.0.0.1:11434. W celu weryfikacji statusu należy użyć polecenia:
systemctl status ollama
ollama --versionW przypadku korzystania z Docker należy użyć kontenera:
docker run -d --name ollama \
-p 127.0.0.1:11434:11434 \
-v ollama:/root/.ollama \
--restart always \
ollama/ollamaNależy zwrócić uwagę na prefiks 127.0.0.1: w mapowaniu portów. Powoduje on przypisanie portu wyłącznie do localhost. Użycie -p 11434:11434 spowoduje publikację portu na wszystkich interfejsach, co stanowi błąd opisany w sekcji dotyczącej bezpieczeństwa. Należy wybrać tylko jedną metodę instalacji; jednoczesne uruchomienie skryptu oraz kontenera spowoduje konflikt procesów o ten sam port.
Pobierz i uruchom swój pierwszy model
ollama pull llama3.2:3b
ollama run llama3.2:3bpull pobiera warstwy modelu na dysk (w tym przypadku około 2 GB). run ładuje je do pamięci i uruchamia interfejs >>>. Wpisz pytanie. Wygenerowanie pierwszego tokenu może zająć kilka sekund, ponieważ wagi są ładowane z dysku do pamięci RAM, a następnie odpowiedź jest przesyłana strumieniowo. Wpisz /bye, aby zakończyć czat; proces Ollama nadal działa w tle.
Sprawdź, co zostało załadowane i jak wykorzystane są zasoby:
ollama psKolumna PROCESSOR zawiera właściwe informacje. 100% CPU oznacza brak użycia GPU, co powoduje spowolnienie działania. Aby zmierzyć rzeczywistą prędkość, użyj flagi verbose:
ollama run --verbose llama3.2:3b "Write two sentences about Linux."Linia eval rate wyświetlana na końcu wskazuje liczbę tokenów na sekundę dla danego sprzętu. Wartość tę należy przyjąć do planowania wydajności.
Lokalizacja modeli oraz wymagana przestrzeń dyskowa
Modele zainstalowane za pomocą skryptu i uruchamiane jako usługa znajdują się w katalogu home użytkownika ollama:
sudo du -sh /usr/share/ollama/.ollama/modelsModele uruchamiane interaktywnie przez własnego użytkownika znajdują się w ~/.ollama/models. W kontenerze modele znajdują się w wolumenie ollama typu named volume. Jest to istotne, ponieważ skwantowane wagi szybko zajmują miejsce: model 3B zajmuje ~2 GB, 7-8B zajmuje ~5 GB, a 14B zajmuje ~9 GB. Pobranie czterech modeli w celu porównania zajmuje 20 GB. Należy dobrać rozmiar dysku pod kątem planowanych modeli, a pozostałe usunąć za pomocą ollama rm <model>.
Uruchomienie jako usługa pod kontrolą użytkownika
Skrypt instalacyjny zarejestrował już ollama.service, więc usługa restartuje się przy uruchomieniu systemu bez dodatkowych działań. Parametrem wymagającym zmiany jest czas retencji modelu oraz, w niektórych konfiguracjach, bind address. Oba parametry należy umieścić w pliku systemd drop-in, aby aktualizacja Ollama ich nie nadpisała:
sudo systemctl edit ollama.servicePod nagłówkiem [Service] wyświetlanym przez edytor należy dodać:
[Service]
Environment="OLLAMA_KEEP_ALIVE=30m"OLLAMA_KEEP_ALIVE określa czas przebywania modelu w pamięci po ostatnim zapytaniu (domyślnie 5 minut). Warto zwiększyć tę wartość na serwerach obsługujących ciągłe zapytania, aby uniknąć ponownego ładowania wag; na urządzeniach o ograniczonej pamięci należy ustawić 0, aby zwolnić RAM natychmiast po zakończeniu zapytania. systemctl edit przeładowuje pliki jednostek, dlatego aby zastosować zmiany, należy wykonać restart:
sudo systemctl restart ollamaNajważniejszy aspekt bezpieczeństwa
Domyślnie Ollama jest przypisane do 127.0.0.1:11434, więc dostęp mają tylko procesy działające na tym samym VPS. To ustawienie jest poprawne. Należy je zachować.
API nie posiada mechanizmu uwierzytelniania. Żadnego. Nie ma klucza API, logowania, limitów zapytań ani list zezwoleń. Każdy, kto ma dostęp do portu 11434, może uruchamiać pobrane modele, pobierać nowe, usuwać je oraz nieustannie obciążać procesor (CPU) lub kartę graficzną (GPU). Skanery takie jak Shodan indeksują tysiące otwartych instancji Ollama; wystawiona instancja zostaje wykryta i wykorzystana w ciągu kilku godzin.
Oto jeden błąd, którego nigdy nie wolno popełniać: nie należy ustawiać OLLAMA_HOST=0.0.0.0 i otwierać portu 11434 w firewallu. Powoduje to udostępnienie serwera wnioskowania bez uwierzytelniania do całego internetu. Żadna konfiguracja nie zapewni bezpieczeństwa portu 11434 na 0.0.0.0, ponieważ Ollama nie posiada funkcji uwierzytelniania.
Istnieją trzy bezpieczne sposoby na dostęp do modelu z zewnętrznego urządzenia:
- Pozostawienie dostępu lokalnego. Jeśli jedynym klientem jest inny program na tym samym VPS — skrypt cron, bot lub serwer MCP łączący narzędzia z modelem — należy pozostawić bind na
127.0.0.1i skonfigurować ten program tak, aby wywoływałhttp://127.0.0.1:11434. Nic nie jest wystawione na zewnątrz i nic więcej nie jest wymagane. - Dostęp przez prywatny tunel. Należy podłączyć VPS do własnego VPN WireGuard, ustawić
OLLAMA_HOSTna adres tunelu (na przykład10.8.0.1, a nie0.0.0.0), a dostęp przyznać wyłącznie klientom VPN. Publiczny internet nadal nie widzi portu 11434. - Zastosowanie reverse proxy z uwierzytelnianiem. Należy skonfigurować terminację TLS oraz wymagać hasła lub tokenu w nginx, Traefik lub Caddy, a następnie przekierować ruch do
127.0.0.1:11434. Ollama zachowuje bind na localhost; proxy jest jedynym elementem nasłuchującym na publicznym porcie. Jest to rozwiązanie analogiczne do instalacji certyfikatu Let's Encrypt na nginx przed dowolną lokalną usługą.
Opcja z reverse proxy jest dokładnie tym, co oferuje następny krok w interfejsie czatu, zintegrowany z systemem logowania.
Dodaj interfejs czatu Open WebUI za serwerem TLS
Open WebUI to interfejs czatu typu self-hosted. Należy uruchomić go w Docker i połączyć z lokalną instancją Ollama:
docker run -d \
--name open-webui \
--network=host \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
-v open-webui:/app/backend/data \
--restart always \
ghcr.io/open-webui/open-webui:mainFlaga --network=host jest kluczowa w przypadku serwerów Linux VPS. Umieszcza ona kontener w przestrzeni nazw sieci hosta (network namespace). Dzięki temu 127.0.0.1 wewnątrz kontenera to pętla zwrotna (loopback) hosta, co pozwala kontenerowi połączyć się z Ollama pod adresem 127.0.0.1:11434 bez konieczności nasłuchiwania Ollama na innych interfejsach. Metoda z wykorzystaniem sieci bridge — --add-host=host.docker.internal:host-gateway z OLLAMA_BASE_URL=http://host.docker.internal:11434 — nie zadziała w tym przypadku. Nazwa ta odnosi się do bramy sieci Docker bridge, a usługa przypisana do 127.0.0.1 na hoście nie jest dostępna przez mostek. W rezultacie Open WebUI zgłasza błąd braku połączenia z Ollama.
Użycie sieci hosta powoduje, że Open WebUI nasłuchuje na porcie 8080 hosta na wszystkich interfejsach. Wszelkie mapowania -p zostają zignorowane, co skutkuje ostrzeżeniem w Dockerze. Należy zamknąć port 8080 na firewallu hosta oraz dostawcy, aby jedynym punktem dostępu był reverse proxy TLS. Podczas pierwszej wizyty Open WebUI wymaga utworzenia konta administratora. Konto to stanowi warstwę uwierzytelniania, dlatego należy ustawić silne hasło.
Aby uzyskać dostęp do czatu z laptopa przez HTTPS, należy umieścić reverse proxy TLS przed 127.0.0.1:8080. Jeśli na serwerze działają już inne aplikacje Docker, Traefik z automatycznym TLS dla wielu aplikacji jest najbardziej optymalnym rozwiązaniem: jeden blok etykiet (label) wystawia certyfikat i przekierowuje chat.example.com do Open WebUI. Zasada z sekcji bezpieczeństwa pozostaje aktualna — proxy obsługuje port publiczny i logowanie, podczas gdy Ollama pozostaje na localhost, a port 8080 aplikacji Open WebUI jest chroniony przez firewall.
Korzystanie z endpointu zgodnego z OpenAI w kodzie
Ollama obsługuje podzbiór API chat OpenAI pod adresem /v1, zatem większość bibliotek klienta OpenAI działa po zmianie dwóch parametrów: base URL oraz klucza API.
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:11434/v1", api_key="ollama")
resp = client.chat.completions.create(
model="llama3.2:3b",
messages=[{"role": "user", "content": "Name three Linux distributions."}],
)
print(resp.choices[0].message.content)Biblioteka klienta wymaga parametru api_key, jednak Ollama go ignoruje, więc można użyć dowolnego ciągu znaków. model musi być nazwą modelu, który został już pobrany; nieznana nazwa powoduje błąd model "x" not found, try pulling it first. Podobnie działa zwykłe wywołanie curl:
curl http://127.0.0.1:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"llama3.2:3b","messages":[{"role":"user","content":"Hello"}]}'W ten sam sposób integruje się model z narzędziami typu agent i editor. Jeśli prowadzona jest lokalna deweloperka, model lokalny może obsługiwać skrypty i wtyczki obok Claude Code działającego na VPS wewnątrz tmux. Pozwala to na wykonywanie tanich i prywatnych zadań edycyjnych poza płatnym API, podczas gdy za zaawansowane wnioskowanie odpowiada model hostowany.
Tryby awarii i dokładne komunikaty błędów
Proces zostaje przerwany ("Killed") w trakcie generowania. Po uruchomieniu dużego modelu terminal wyświetla Killed lub logi serwera wskazują na llama runner process has terminated: signal: killed. Mechanizm Linux OOM killer zakończył proces, ponieważ model wymagał więcej pamięci RAM, niż posiada system. Przyczynę można potwierdzić za pomocą sudo dmesg | grep -i oom, gdzie pojawi się linia typu Out of memory: Killed process ... (ollama). Rozwiązaniem jest użycie mniejszego lub silniej skwantyzowanego modelu — llama3.2:3b zamiast 13B — lub dodanie pamięci swap, co pozwoli na powolne przetwarzanie danych zamiast natychmiastowego błędu przy przekroczeniu limitu RAM. Swap zamienia nagły błąd na wolną odpowiedź; nie sprawia on jednak, że model 70B staje się użyteczny przy 4 GB RAM.
"Error: model requires more system memory". Ollama odmawia uruchomienia modelu i wyświetla Error: model requires more system memory (X GiB) than is available (Y GiB). Jest to kontrolowane przerwanie procesu: Ollama obliczył zapotrzebowanie i zatrzymał działanie, zamiast pozwolić na interwencję OOM killer. Komunikat podaje dwie wartości liczbowe. Należy wybrać model, którego wymagania są niższe niż dostępna pamięć RAM (sprawdzić za pomocą free -h), zmniejszyć długość kontekstu lub przejść na większą instancję VPS. Żadna flaga nie zmieści modelu w pamięci — ograniczenie sprzętowe jest realne.
Pierwszy token generowany jest bardzo długo, potem praca przebiega poprawnie. Przy pierwszym uruchomieniu model nie wyświetla nic przez 5 do 30 sekund, a następnie przesyła dane normalnie. Opóźnienie wynika z ładowania wag z dysku do pamięci RAM; wolny magazyn danych potęguje ten efekt. Po załadowaniu model pozostaje w pamięci przez czas określony przez OLLAMA_KEEP_ALIVE, dzięki czemu na drugi prompt odpowiedź jest generowana natychmiastowo. Jeśli opóźnienia są problemem, należy zwiększyć tę wartość. Aby sprawdzić, czy model jest obecnie załadowany, należy użyć ollama ps.
Wydajność jest ogólnie niska. Generowanie wynosi 10 tokenów na sekundę lub mniej, bez żadnych błędów. Jest to typowe zachowanie dla wnioskowania na procesorze CPU. ollama ps wskazuje na 100% CPU, co oznacza brak procesora GPU. Nie jest to błąd ani problem z konfiguracją, ponieważ ograniczeniem jest przepustowość pamięci. Należy użyć mniejszego modelu, zaakceptować prędkość lub przejść na instancję z GPU — przed stwierdzeniem awarii należy zmierzyć rzeczywistą prędkość za pomocą --verbose.
Połączenie zostało odrzucone ("Connection refused") z innego urządzenia. Z laptopa pojawia się błąd curl: (7) Failed to connect to <ip> port 11434: Connection refused. System działa zgodnie z założeniami: Ollama nasłuchuje wyłącznie na localhost. Nie należy próbować naprawy poprzez ustawienie 0.0.0.0, co stanowi błąd bezpieczeństwa polegający na nadmiernym udostępnianiu usługi. Zamiast tego należy łączyć się z modelem przez VPN lub autoryzowane proxy.
Port 11434 został udostępniony do internetu. Jeśli ustawiono OLLAMA_HOST=0.0.0.0, otwarto firewall i zaobserwowano pobieranie modeli, których nie uruchomiono, lub obciążenie CPU na poziomie 100% przez nieznane klientów, oznacza to nieautoryzowany dostęp. Jest to krytyczny błąd bezpieczeństwa. Należy zmienić adres nasłuchiwania na 127.0.0.1 lub adres VPN, zamknąć port 11434 na firewallu i wprowadzić mechanizm uwierzytelniania. Należy przyjąć założenie, że wszystkie zapytania wysłane do tego adresu w czasie jego otwarcia pochodziły od nieznanych użytkowników.
Backups and upgrades
Ilość danych podlegających utracie jest niewielka. Modele można pobrać ponownie, więc jedyne elementy wymagające kopii zapasowej to wolumen danych Open WebUI (konta, historia czatów, ustawienia) oraz wszelkie pliki konfiguracyjne systemd typu drop-in. Kopię zapasową wolumenu należy wykonać za pomocą tymczasowego kontenera:
docker run --rm -v open-webui:/data -v "$PWD":/backup alpine \
tar czf /backup/open-webui.tgz -C /data .Aktualizację Ollama należy przeprowadzić poprzez ponowne uruchomienie skryptu instalacyjnego; aktualizację Open WebUI należy wykonać za pomocą docker pull ghcr.io/open-webui/open-webui:main, a następnie ponownie utworzyć kontener. Nie należy stosować długoterminowego blokowania wersji (pinning): zarówno jakość modeli, jak i środowisko uruchomieniowe zmieniają się szybko, dlatego należy zapoznać się z opisem zmian (release notes) i przeprowadzić ponowne testy wydajnościowe na własnym sprzęcie, zamiast polegać na wynikach z poprzedniego kwartału.
FAQ
Czy można uruchomić LLM na VPS bez GPU?
Tak, lecz z ograniczeniami. Małe modele skwantyzowane w zakresie 3B do 8B działają na CPU i są użyteczne do tworzenia szkiców, streszczania oraz klasyfikacji. Prędkość wynosi od pojedynczych do kilkunastu tokenów na sekundę na współdzielonym vCPU. Modele powyżej 13B działają bardzo wolno lub nie mieszczą się w pamięci RAM. Do uzyskania wysokiej wydajności lub obsługi większych modeli wymagana jest instancja z GPU.
Ile pamięci RAM wymaga każdy model?
Przybliżona zasada dla domyślnych modeli skwantyzowanych 4-bit: około 0.5 GB RAM na każdy miliard parametrów (wagi), plus około 1 GB na narzut systemowy oraz dodatkową ilość na kontekst. Model 3B wymaga około 4 GB wolnego miejsca, model 7-8B około 8 GB, a model 14B około 16 GB. Sprawdź dostępną pamięć za pomocą free -h i zachowaj zapas dla systemu operacyjnego oraz innych procesów.
Czy API Ollama jest uwierzytelnione?
Nie. Ollama nie posiada wbudowanego uwierzytelniania, klucza API ani limitów zapytań (rate limit). Każdy, kto ma dostęp do portu 11434, ma pełną kontrolę nad usługą. Dlatego domyślnie binduje ona 127.0.0.1 i dlatego nie wolno wystawiać portu 11434 na 0.0.0.0 bezpośrednio do internetu. Należy uzyskiwać do niego dostęp lokalnie, przez prywatny VPN lub poprzez reverse proxy z mechanizmem logowania.
Jak dodać interfejs czatu webowego?
Należy uruchomić Open WebUI w Dockerze z flagą --network=host, aby współdzielić loopback hosta i uzyskiwać dostęp do natywnej usługi Ollama pod adresem http://127.0.0.1:11434. Następnie należy ustawić reverse proxy TLS przed portem 8080 w celu uzyskania dostępu z laptopa. Port 8080 musi pozostać zamknięty w firewallu, aby proxy było jedynym publicznym punktem dostępu. Konto administratora Open WebUI służy do logowania; hasło ustawia się przy pierwszym uruchomieniu.
Jak wywołać API z własnej aplikacji?
Należy użyć endpointu zgodnego z OpenAI pod adresem http://127.0.0.1:11434/v1. Należy skierować dowolne SDK OpenAI na ten adres URL, przekazać dowolny ciąg znaków jako klucz API (jest on ignorowany) oraz ustawić model na nazwę pobranego modelu. Istniejący kod OpenAI zazwyczaj działa bez zmian, poza koniecznością zmiany adresu URL i klucza.