Ollama API brak uwierzytelniania jak zabezpieczyć serwer
Serwer Ollama na porcie 11434 nie posiada domyślnej autoryzacji. Każdy użytkownik z dostępem do sieci może zarządzać modelami. Poznaj trzy skuteczne metody zabezpieczenia instancji.
Interfejs API Ollama nie posiada hasła
Interfejs API Ollama nie posiada mechanizmów uwierzytelniania. W uruchomionym serwerze nie istnieją użytkownicy, hasła, weryfikacja kluczy ani listy dozwolonych adresów. Każdy podmiot, który może nawiązać połączenie TCP z portem 11434, ma możliwość wyświetlenia listy modeli, ich uruchomienia, pobrania nowych oraz usunięcia już istniejących.
Oficjalna dokumentacja stwierdza to wprost: "Podczas lokalnego dostępu do API Ollama za pośrednictwem http://localhost:11434 nie jest wymagane uwierzytelnianie". Słowo lokalnie stanowi fundament całego modelu bezpieczeństwa. Domyślnie Ollama nasłuchuje na 127.0.0.1, więc w przypadku laptopa to interfejs loopback pełni rolę kontroli dostępu. Przeniesienie nasłuchu na publiczny adres IP powoduje utratę tej kontroli, ponieważ nie wprowadzono żadnego mechanizmu zastępczego.
Dlatego kwestia ta jest istotna w przypadku serwerów VPS (virtual private server). Ustawienia domyślne są bezpieczne. Pierwsza zmiana, którą wprowadza większość użytkowników – udostępnienie nasłuchu w celu umożliwienia korzystania z modelu przez inną maszynę – jest jednocześnie działaniem, które całkowicie znosi wszelkie zabezpieczenia.
Co ujawnia otwarty port 11434
Każdy punkt końcowy. Nie istnieje tryb tylko do odczytu ani oddzielny port administracyjny. Poniżej przedstawiono rzeczywiste żądania, skierowane na adres serwera zamiast na localhost:
# List every model on the box
curl http://SERVER_IP:11434/api/tags
# See what is loaded into memory right now
curl http://SERVER_IP:11434/api/ps
# Run a prompt on your hardware
curl http://SERVER_IP:11434/api/generate -d '{"model":"llama3.2","prompt":"Why is the sky blue?"}'
# Write several gigabytes to your disk
curl http://SERVER_IP:11434/api/pull -d '{"model":"llama3.2"}'
# Remove a model
curl -X DELETE http://SERVER_IP:11434/api/delete -d '{"model":"llama3.2"}'Z perspektywy operatora, cztery kwestie stanowią problem:
- Procesor lub karta graficzna wykonuje obliczenia dla osób trzecich. W planach z limitem wykorzystania CPU, ciągłe obciążenie oznacza, że Twój przydział jest zużywany przez nieznajomą osobę, a kontrola kosztów obciążeń AI na VPS staje się znacznie trudniejsza, gdy nie jesteś jedynym użytkownikiem.
/api/pullzapisuje dane na dysku. Modele zajmują od dwóch do czterdziestu gigabajtów każdy. Pętla operacji pobierania zapełnia wolumen, a pełny dysk powoduje awarię wszystkich pozostałych usług na serwerze, nie tylko Ollama.- Żądania docierają do procesu i są rejestrowane. Przy domyślnym poziomie logowania Ollama zapisuje tylko metadane, więc otrzymujesz punkt końcowy, status, opóźnienie oraz adres klienta, ale nie treść promptu. Jest to jednak zapis informacji o tym, kto korzystał z serwera i w jakim celu, przechowywany w dzienniku, którego nie planowałeś prowadzić.
/api/deleteusuwa modele. Ich przywrócenie wymaga ponownego pobrania, co zużywa Twój transfer.
Żaden z tych scenariuszy nie wymaga wykorzystania luki w zabezpieczeniach. Jest to udokumentowane działanie API, zgodne z jego projektem.
Klucz Ed25519 nie służy do kontroli dostępu
Wyszukanie frazy „Ollama API key” prowadzi do dwóch różnych zagadnień. Żadne z nich nie jest hasłem do serwera, a ich rozróżnienie eliminuje większość nieporozumień.
Pierwszym jest para kluczy tożsamości. Ollama generuje parę kluczy Ed25519 przy pierwszym uruchomieniu. W systemie Linux skrypt instalacyjny tworzy użytkownika systemowego o nazwie ollama z katalogiem domowym w /usr/share/ollama, więc para kluczy znajduje się tutaj:
/usr/share/ollama/.ollama/id_ed25519
/usr/share/ollama/.ollama/id_ed25519.pubTen klucz jest skierowany na zewnątrz. ollama signin rejestruje część publiczną w koncie ollama.com i służy do autoryzacji wysyłania modelu do rejestru lub pobierania modelu prywatnego. Potwierdza on tożsamość maszyny wobec ollama.com. Nie wymaga on niczego od klientów łączących się z maszyną. Usunięcie go, rotacja lub jego brak nie zmieniają zasad dostępu do API.
Drugim jest OLLAMA_API_KEY. Ta zmienna przechowuje klucz utworzony w https://ollama.com/settings/keys, który klient przesyła jako Authorization: Bearer $OLLAMA_API_KEY podczas wywoływania hostowanego API pod adresem https://ollama.com/api. Jest to poświadczenie dla ich usługi, używane przez użytkownika w roli klienta. Własny ollama serve nigdy go nie odczytuje. Ustawienie OLLAMA_API_KEY na VPS nie nakłada hasła na VPS.
Nie ma zatem ustawienia, które można włączyć. Trzy poniższe metody ochrony działają w ten sam sposób: należy utrzymać port w stanie niedostępnym z zewnątrz i umieścić przed nim komponent, który faktycznie weryfikuje dostęp.
Sprawdź, na jakich portach nasłuchuje obecnie serwer
sudo ss -tlnp | grep 11434Bezpieczny wynik wskazuje adres pętli zwrotnej (loopback):
LISTEN 0 4096 127.0.0.1:11434 0.0.0.0:* users:(("ollama",pid=812,fd=3))Wynik wskazujący na wystawienie usługi wymienia wszystkie interfejsy:
LISTEN 0 4096 0.0.0.0:11434 0.0.0.0:* users:(("ollama",pid=812,fd=3))0.0.0.0 oznacza wszystkie adresy IPv4 na maszynie, w tym adres publiczny. *:11434 oraz [::]:11434 oznaczają to samo, uwzględniając również IPv6.
Teraz potwierdź stan z zewnątrz. Uruchom poniższe polecenie na laptopie, a nie na serwerze:
curl -m 5 http://YOUR_SERVER_IP:11434/api/versioncurl: (28) Connection timed out after 5001 milliseconds to oczekiwana odpowiedź; podobnie jest w przypadku curl: (7) Failed to connect ... Connection refused. Obiekt JSON zawierający pole version oznacza, że całe API jest dostępne dla każdego, kto wyśle zapytanie. Testowanie za pomocą curl bezpośrednio na serwerze niczego nie dowodzi, ponieważ interfejs loopback odpowiada zawsze.
Wystawienie usługi na świat zazwyczaj wynika z jednej z dwóch przyczyn. Pierwszą jest celowa edycja konfiguracji, gdy zaistniała potrzeba dostępu do modelu z drugiej maszyny:
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"Ta pojedyncza linia stanowi pełne wystawienie usługi. Drugim sposobem jest Docker, który nie wymaga edycji żadnych plików konfiguracyjnych. Temat ten został omówiony w poniższej sekcji.
Obrona 1: utrzymanie na localhost i tunelowanie
Zastosuj to rozwiązanie jako pierwsze. Nie wymaga ono dodatkowego oprogramowania i nie generuje danych uwierzytelniających, które mogłyby wyciec. Port nie istnieje na publicznym interfejsie, więc skanowanie go nie wykryje.
Ustaw adres powiązania jawnie, zamiast polegać na wartości domyślnej:
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_HOST=127.0.0.1:11434"To zapisuje /etc/systemd/system/ollama.service.d/override.conf. Zastosuj zmianę i sprawdź:
sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo ss -tlnp | grep 11434ss powinno teraz wskazywać 127.0.0.1:11434. Jeśli nadal widnieje 0.0.0.0, oznacza to, że nadrzędny jest drugi plik typu drop-in. Uruchom systemctl cat ollama.service, aby wyświetlić jednostkę wraz ze wszystkimi plikami drop-in i ich ścieżkami, a następnie usuń nieaktualny plik.
Aby korzystać z modelu z laptopa, przekieruj port przez SSH:
ssh -N -L 11434:127.0.0.1:11434 you@your-server-L 11434:127.0.0.1:11434 otwiera port 11434 na laptopie i przesyła cały ruch do 127.0.0.1:11434 z perspektywy serwera. -N instruuje SSH, aby nie uruchamiało zdalnego polecenia, dzięki czemu proces utrzymuje tunel w stanie otwartym. Gdy tunel działa, poniższe polecenie na laptopie zadziała:
curl -s http://localhost:11434/api/tagsNapotkasz dwa typowe błędy. bind [127.0.0.1]:11434: Address already in use oznacza, że na laptopie działa już lokalna instancja Ollama na tym porcie; wybierz inny port lokalny za pomocą -L 11500:127.0.0.1:11434 i skieruj klienta na 11500. Pusta odpowiedź przez poprawnie nawiązany tunel oznacza, że SSH działa, ale Ollama nie nasłuchuje po stronie serwera; sprawdź ss na serwerze przed modyfikacją polecenia SSH.
W przypadku wielu maszyn klienckich sieć prywatna jest lepsza niż jeden tunel na użytkownika. Dodaj maszyny do WireGuard lub Tailscale, a następnie powiąż Ollama z adresem w tej sieci zamiast z 0.0.0.0:
[Service]
Environment="OLLAMA_HOST=10.8.0.1:11434"Port istnieje wtedy tylko na interfejsie, do którego dostęp wymaga klucza. Rozwiązanie to jest odporne na błędy w konfiguracji firewalla, ponieważ reguła, która przypadkowo otwiera dostęp dla całego świata, nadal nie ujawni usługi, która nie nasłuchuje na publicznym interfejsie.
Obrona 2: reverse proxy sprawdzający token bearer
Jeśli usługa w publicznym Internecie musi wywołać model, należy pozostawić Ollama na interfejsie loopback i umieścić przed nim proxy. Proxy kończy połączenie TLS (transport layer security) i odrzuca żądania bez odpowiedniego nagłówka. Ollama nadal akceptuje połączenia tylko z 127.0.0.1, więc proxy jest jedyną drogą dostępu.
Najpierw wygeneruj właściwy token. Nie twórz go ręcznie:
openssl rand -base64 36Konfiguracja serwera nginx, która go weryfikuje:
map $http_authorization $ollama_ok {
default 0;
"Bearer PASTE_YOUR_GENERATED_TOKEN_HERE" 1;
}
server {
listen 443 ssl;
server_name llm.example.com;
ssl_certificate /etc/letsencrypt/live/llm.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/llm.example.com/privkey.pem;
location = /api/pull { return 403; }
location = /api/delete { return 403; }
location = /api/push { return 403; }
location / {
if ($ollama_ok = 0) { return 401; }
proxy_pass http://127.0.0.1:11434;
proxy_set_header Host 127.0.0.1:11434;
proxy_buffering off;
proxy_read_timeout 600s;
}
}Pięć linii wykonuje tutaj kluczową pracę, a każda z nich zapobiega awarii, która w przeciwnym razie mogłaby wystąpić.
if wewnątrz bloku location jest zazwyczaj złym pomysłem w nginx, ale treść o długości dokładnie return jest jedną z dwóch form, które zachowują się przewidywalnie, więc to użycie jest bezpieczne.
location = /api/pull to dopasowanie dokładne, a nginx szereguje dopasowania dokładne wyżej niż prefiks location /, więc te trzy punkty końcowe są odrzucane, zanim token zostanie w ogóle sprawdzony. Ważny token pozwala na wnioskowanie, a nie na zapełnienie dysku.
proxy_set_header Host 127.0.0.1:11434; ma znaczenie, ponieważ Ollama sprawdza przychodzące nagłówki Host oraz Origin. Przekazywanie publicznej nazwy hosta proxy bezpośrednio może spowodować powstanie 403 Forbidden, który pochodzi z Ollama, a nie z nginx, co utrudnia debugowanie. OLLAMA_ORIGINS to drugi mechanizm, przydatny dla klienta przeglądarkowego, który wymaga zezwolenia na konkretne źródło (origin).
proxy_buffering off; ma znaczenie, ponieważ Ollama przesyła odpowiedź strumieniowo, token po tokenie. Przy włączonym buforowaniu nginx wstrzymuje strumień i dostarcza go w całości dopiero na końcu, przez co klient sprawia wrażenie zawieszonego przez cały czas trwania generowania.
proxy_read_timeout 600s; ma znaczenie, ponieważ domyślny limit nginx wynosi 60 sekund. Długie generowanie na CPU łatwo przekracza ten czas, klient otrzymuje 504 Gateway Time-out, a /var/log/nginx/error.log rejestruje upstream timed out (110: Connection timed out) while reading response header from upstream. Żądanie nadal było przetwarzane, ale nginx zrezygnował z oczekiwania.
Przeładuj i przetestuj obie ścieżki:
sudo nginx -t && sudo systemctl reload nginx
curl -s -o /dev/null -w '%{http_code}\n' https://llm.example.com/api/tags
curl -s -H "Authorization: Bearer YOUR_TOKEN" https://llm.example.com/api/tagsPierwsza powinna wyświetlić 401. Druga powinna wyświetlić listę modeli. Jeśli pierwsza również zwraca listę modeli, blok map znajduje się w niewłaściwym zakresie. Powinien znajdować się na poziomie http, więc umieść go w pliku w /etc/nginx/conf.d/ lub powyżej bloku server, nigdy wewnątrz server.
Caddy wykonuje to samo zadanie przy użyciu uwierzytelniania podstawowego (basic authentication) w czterech liniach, co lepiej sprawdza się w przypadku klienta przeglądarkowego niż token bearer:
llm.example.com {
basic_auth {
apiuser PASTE_BCRYPT_HASH_HERE
}
reverse_proxy 127.0.0.1:11434
}Uruchom caddy hash-password, aby wygenerować wymagany skrót bcrypt. Pułapka nazewnictwa: dyrektywa nazywała się basicauth przed wersją Caddy v2.8, a obecnie nazywa się basic_auth, więc konfiguracja skopiowana ze starszego poradnika nie zostanie załadowana, a Caddy wskaże nierozpoznaną dyrektywę.
Niezależnie od wybranego proxy, jest to jeden wspólny sekret dla wszystkich. Każdy klient posiadający go ma identyczny dostęp, a jego unieważnienie oznacza edycję konfiguracji i jednoczesną aktualizację wszystkich wywołujących go klientów.
Obrona 3: bramka wydająca klucze dla każdego klienta
Gdy z modelu korzysta więcej niż jedna osoba lub aplikacja, współdzielony token przestaje wystarczać. Nie można określić, który klient generuje obciążenie, ani odciąć dostępu jednemu z nich bez blokowania pozostałych. Bramka (gateway) zajmuje miejsce, w którym wcześniej znajdowało się proxy, obsługuje to samo API zgodne z OpenAI, wydaje osobny klucz dla każdego klienta i rejestruje zużycie dla każdego z nich. Samodzielnie hostowana bramka LiteLLM jest standardowym rozwiązaniem, które dodaje limity budżetowe na klucz oraz logi żądań do kontroli dostępu.
Zasada z obrony 1 pozostaje niezmienna. Ollama wiąże się z 127.0.0.1, bramka jest jedynym procesem, który się z nią komunikuje, a bramka jest jedyną usługą z publicznym portem nasłuchującym. Bramka na serwerze, na którym port 11434 pozostaje otwarty dla świata, jest jedynie dekoracją, ponieważ klienci mogą ją po prostu ominąć.
Pułapka firewalla: opublikowany port kontenera pomija UFW
Dlatego właśnie istnieją publicznie dostępne instancje na serwerach, których właściciele poprawnie skonfigurowali firewall.
UFW (uncomplicated firewall) zapisuje swoje reguły w łańcuchu INPUT tablicy filter jądra systemu, a INPUT obsługuje pakiety adresowane bezpośrednio do hosta. Flaga -p Dockera zapisuje regułę docelowego NAT (network address translation) w łańcuchu PREROUTING tablicy nat, którą jądro analizuje, zanim podejmie decyzję o kierunku ruchu pakietu. W momencie podejmowania decyzji o routingu, adres docelowy został już przepisany na adres kontenera, więc pakiet jest przekazywany (forwarded), a nie dostarczany lokalnie, przez co przechodzi przez FORWARD zamiast INPUT. Reguły INPUT w UFW nigdy nie są sprawdzane, więc pakiet omija firewall, zamiast przez niego przechodzić.
Dlatego poniższa sekwencja pozostawia port 11434 otwarty na świat:
sudo ufw default deny incoming
sudo ufw enable
docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollamaa sudo ufw status nadal raportuje, że firewall jest aktywny z domyślną polityką odrzucania (deny). Oba odczyty są jednocześnie poprawne, co jest głównym powodem, dla którego użytkownicy ufają błędnym informacjom. Można sprawdzić regułę, która to powoduje:
sudo iptables -t nat -L DOCKER -nRozwiązaniem jest dodanie adresu we flagze publikowania portu:
docker rm -f ollama
docker run -d -v ollama:/root/.ollama -p 127.0.0.1:11434:11434 --name ollama ollama/ollama-p 11434:11434 to skrót od -p 0.0.0.0:11434:11434. Wskazanie 127.0.0.1 wiąże stronę hosta mapowania z interfejsem loopback, dzięki czemu tunel SSH i reverse proxy nadal mają dostęp do usługi, a Internet nie. Odtworzenie kontenera jest w tym przypadku bezpieczne, ponieważ modele znajdują się w nazwanym wolumenie ollama, a nie wewnątrz kontenera.
Należy potwierdzić, że oba widoki są zgodne:
docker port ollama
sudo ss -tlnp | grep 11434docker port ollama powinno wyświetlić 11434/tcp -> 127.0.0.1:11434. Jeśli wyświetli 0.0.0.0:11434, usługa jest nadal wystawiona na świat. Zrozumienie tego mechanizmu pozwala stosować go do każdego publikowanego kontenera: dlaczego opublikowane porty Dockera omijają UFW omawia łańcuch DOCKER-USER oraz reguły, które pozostają aktywne po restarcie Dockera. Jeśli dopiero budowana jest polityka hosta, reguły UFW wymagane dla nowego VPS opisują podstawy konfiguracji. W systemach Rocky lub AlmaLinux nie ma UFW do skonfigurowania, więc należy zacząć od tej samej polityki bazowej zapisanej w firewalld.
Z jakim użytkownikiem uruchomiony jest proces
Skrypt instalacyjny systemu Linux tworzy dedykowane konto i uruchamia usługę w jego kontekście:
useradd -r -s /bin/false -U -m -d /usr/share/ollama ollamaJednostka w /etc/systemd/system/ollama.service ustawia następnie User=ollama oraz Group=ollama. Nie należy zmieniać tych ustawień. Szybkie polecenie ollama serve uruchomione ręcznie w terminalu działa z uprawnieniami aktualnie zalogowanego użytkownika. Jeśli jest to root, nieuwierzytelnione API zapisuje pliki jako root. Należy sprawdzić, który przypadek ma miejsce:
ps -o user= -C ollamaWynikiem powinno być ollama. Każda inna wartość oznacza, że ręcznie uruchomiony proces działa równolegle lub zamiast jednostki systemowej. Ta sama zasada dotyczy każdego demona dodawanego w przyszłości, a uruchamianie usług z uprawnieniami ograniczonego użytkownika szczegółowo wyjaśnia to zagadnienie.
Jak sprawdzić, czy punkt końcowy Ollama API jest zabezpieczony
Niezależnie od wybranej metody, jeden test rozstrzyga kwestię bezpieczeństwa i musi zostać wykonany z innej maszyny:
curl -m 5 http://YOUR_SERVER_IP:11434/api/version
curl -m 5 http://YOUR_SERVER_IP:11434/api/tagsOba polecenia powinny zwrócić błąd przekroczenia czasu lub odmowy połączenia. Jeśli skonfigurowano proxy, te same dwie ścieżki pod adresem hosta proxy powinny zwracać 401 bez poświadczeń oraz poprawne dane w formacie JSON po ich podaniu.
Następnie należy jednorazowo przejrzeć dziennik dostępu, ponieważ informuje on, czy ktokolwiek wykrył port w czasie, gdy był on otwarty:
journalctl -u ollama --since "-30 days" | grep GIN | grep -v 127.0.0.1Ollama zapisuje jeden wiersz dla każdego żądania i uwzględnia adres klienta:
[GIN] 2026/08/12 - 14:01:10 | 200 | 103.965898ms | 127.0.0.1 | POST "/api/generate"Każdy wiersz powinien wskazywać 127.0.0.1, gdy Ollama jest powiązana z interfejsem loopback, ponieważ jest to jedyny adres, z którego może nadejść połączenie. Publiczny adres w tej kolumnie oznacza żądanie z zewnątrz, a znacznik czasu wskazuje moment wystąpienia zdarzenia. Brak jakichkolwiek wyników po wykonaniu tego polecenia jest pożądanym rezultatem. Jeśli kwestie związane z modelami są nowe, artykuł uruchamianie Ollama na VPS omawia instalację, dobór rozmiaru modelu oraz limity pamięci, które decydują o tym, co faktycznie zostanie załadowane.
FAQ
Does Ollama have an API key or a password?
No. The server you run has no authentication of any kind, and the official documentation states that no authentication is required to reach the API. Both things called an "Ollama API key" point the other way. The Ed25519 pair in /usr/share/ollama/.ollama/ proves your machine to ollama.com so you can push models and pull private ones. OLLAMA_API_KEY is a credential your client sends to the hosted API at https://ollama.com/api. Your own ollama serve reads neither one, so access control has to come from the network or from a proxy in front.
Is OLLAMA_HOST=0.0.0.0 safe if I have a firewall?
Only while nothing else writes firewall rules on that box. 0.0.0.0 means the listener really exists on the public interface, and you are trusting the firewall alone to keep it unreachable. That trust breaks the moment Docker publishes a port, because the DNAT rule Docker adds to the nat table is evaluated before the packet would reach the INPUT chain where UFW lives, so the packet is forwarded and UFW never sees it. Binding to 127.0.0.1 or to a private tunnel address removes the listener from the public interface, so a firewall mistake has nothing left to expose.
How do I check whether my Ollama port is open to the internet?
Run sudo ss -tlnp | grep 11434 on the server, and curl -m 5 http://YOUR_SERVER_IP:11434/api/version from a different machine. ss showing 127.0.0.1:11434 and the remote curl timing out is the pair of answers you want. ss showing 0.0.0.0:11434 or *:11434 while the remote curl returns JSON means the full API is reachable. Never test with curl on the server itself, because loopback answers whatever the bind address happens to be.
Can I just move the port from 11434 to something random?
No, and the reason is worth stating. A different port slows down nothing except a scan of one single port. Scanners walk the whole range, and one request to /api/tags identifies the service whatever port it arrived on. Moving the port also breaks every client default and makes your own setup harder to reason about later. Bind to loopback instead, which removes the listener rather than relocating it.
Someone reached my open Ollama. What should I check?
Bind it to 127.0.0.1 and restart the service first, so the exposure stops before you start investigating. Then run journalctl -u ollama --since "-30 days" | grep GIN | grep -v 127.0.0.1 to see which outside addresses called which endpoints and when. Compare ollama list against the models you meant to have, since /api/pull is unauthenticated and a model you did not pull is both disk usage and evidence. Check free space with df -h. Ollama does not record prompt text at the default log level, so you have a record of who asked and for which model, not of what was generated.