~/ / AI articles / Local LLMs on a VPS / Put nginx in front of Ollama: basic authentication, HTTPS and streaming settings
Put nginx in front of Ollama: basic authentication, HTTPS and streaming settings
Ollama listens on the server itself by default, which is the safest place for it. When another machine has to reach it, the Ollama FAQ points to a proxy server such as nginx. This article builds that setup from the nginx documentation: a password, HTTPS, the settings that matter for streamed answers, and a firewall that closes the other doors.
Published: · 5 min read · Checked against the official Ollama and nginx documentation on 2026-10-26. Directive defaults depend on the nginx version, so check the version you run.
What the Ollama FAQ says
The Ollama FAQ says that Ollama runs an HTTP server and can be exposed using a proxy server such as Nginx. Its example listens on port 80, sets a server_name, forwards requests with proxy_pass http://localhost:11434 and sets the Host header to localhost:11434.
The FAQ page that we checked does not describe any authentication for the Ollama server. That is why the password has to come from the proxy in front of it. Ollama binds 127.0.0.1 port 11434 by default, so an nginx on the same server can reach it without changing that address.
A password with basic authentication
The ngx_http_auth_basic_module limits access by checking a user name and password. Two directives do the work: auth_basic, whose string is used as the realm and which is off by default, and auth_basic_user_file, which names the password file.
| Directive | Default | What the documentation says |
|---|---|---|
| auth_basic string | off; | off | The parameter is used as the authentication realm. The value off cancels a setting inherited from a previous level. |
| auth_basic_user_file file; | none | The file has one name:password entry per line, and lines starting with # are comments. |
- Supported password types: crypt()-encrypted passwords and apr1 hashes, both generated with the htpasswd utility from Apache or with openssl passwd.
- The {SCHEME}data syntax is also supported. The page says PLAIN is an example only and should not be used, and that SHA, an unsalted SHA-1, should not be used either because it is vulnerable to rainbow table attacks. SSHA is salted SHA-1.
- The documentation's example: location / { auth_basic "closed site"; auth_basic_user_file conf/htpasswd; }
The page names htpasswd and openssl passwd but gives no commands. Commonly used forms, which are ours and not from the page, are htpasswd -c /etc/nginx/ollama.htpasswd alice, which prompts for a password, and openssl passwd -apr1, which prints a hash to paste after the user name and a colon.
HTTPS
Our reading, not a statement from the documents: basic authentication sends the password with every request, so use it only behind HTTPS. According to the nginx documentation, a server needs the ssl parameter on its listening socket, and the locations of the certificate and the private key.
| Directive | Example from the documentation |
|---|---|
| listen | listen 443 ssl; |
| server_name | server_name www.example.com; |
| ssl_certificate | ssl_certificate www.example.com.crt; |
| ssl_certificate_key | ssl_certificate_key www.example.com.key; |
- By default nginx uses ssl_protocols TLSv1.2 TLSv1.3 and ssl_ciphers HIGH:!aNULL:!MD5, so configuring them explicitly is generally not needed.
- The private key should be stored in a file with restricted access, but it must be readable by nginx's master process.
- If browsers report errors for a certificate from a well-known authority, the server may need to send the intermediate certificates. The server certificate must appear before the chained certificates in the combined file, or nginx fails to start with a key values mismatch error.
- Let's Encrypt's getting-started page says that if your provider does not obtain certificates for you and you can administer your server, you can run an ACME client, and that it recommends Certbot for most people.
Settings for streamed and slow answers
A model writes its answer piece by piece, and the first piece can take a while to arrive, for example while a large model is loaded into memory. Three nginx settings decide how this looks from the outside.
| Directive | Default | What the documentation says |
|---|---|---|
| proxy_buffering | on | When buffering is disabled, the response is passed to the client synchronously, immediately as it is received. When it is enabled, nginx saves the response into buffers first. |
| proxy_read_timeout | 60s | The timeout is set only between two successive read operations, not for the whole response. If the proxied server does not transmit anything within this time, the connection is closed. |
| proxy_http_version | 1.1 since nginx 1.29.7 | Before 1.29.7 the default was 1.0. Version 1.1 or 2 is recommended for keepalive connections. |
Our reading, not a statement from the documents: to see an answer appear as it is written, turn proxy_buffering off for the Ollama location, and if the model can stay silent for more than a minute while it loads, raise proxy_read_timeout. Setting proxy_http_version 1.1 explicitly is harmless on every version.
Put it together
This configuration combines the directives above for one server name. It is our composition from the documented directives, so test it with nginx -t before you reload.
| Line | Why |
|---|---|
| server { | one server block for the Ollama name |
| listen 443 ssl; | HTTPS |
| server_name ollama.example.com; | your own name |
| ssl_certificate /etc/ssl/ollama.crt; | the certificate, with intermediates after it |
| ssl_certificate_key /etc/ssl/ollama.key; | the private key, readable only as needed |
| auth_basic "ollama"; | turns the password on |
| auth_basic_user_file /etc/nginx/ollama.htpasswd; | where the users are kept |
| location / { | everything goes to Ollama |
| proxy_pass http://localhost:11434; | from the Ollama FAQ |
| proxy_set_header Host localhost:11434; | from the Ollama FAQ |
| proxy_http_version 1.1; | recommended for keepalive |
| proxy_buffering off; | so the answer streams |
| proxy_read_timeout 300s; | allows a slow first piece |
| } | end of location |
| } | end of server |
Close the other doors
The proxy only helps if people cannot reach Ollama or the application behind it another way. Ollama stays on its default address, and a firewall admits only the addresses you use.
| Task | Command from the Ubuntu documentation |
|---|---|
| Turn the firewall on | sudo ufw enable |
| Allow a port | sudo ufw allow 22 |
| Allow one address to one port | sudo ufw allow proto tcp from 192.168.0.2 to any port 22 |
| Allow a whole subnet | replace the address with 192.168.0.0/24 |
| Check the state | sudo ufw status |
The Ubuntu page says UFW is initially disabled. It has no warning about locking yourself out over SSH. Our recommendation: allow your SSH port before you enable the firewall on a server that you reach remotely, and allow port 443 only from the addresses that need it.
Sources
Read next
- Open WebUI on a VPS: run it in Docker and connect it to OllamaRun Open WebUI with Docker and connect it to Ollama on your own server: the commands, the first account, the two connection types and how to update.
- Calling a local model from your code: structured outputs and the OpenAI-compatible API in OllamaConstrain a local model's output with a JSON Schema and call Ollama from OpenAI-style clients: what the official docs say, and what is not supported.
- What can a local model do? Tools, thinking, vision and embeddings in Ollama, and what fits on a VPSTools, thinking, vision, embeddings: what the labels in the Ollama library mean, which models carry them, and how big the downloads are.
- Install Ollama on a VPS and keep it running: install, systemd service, settings and updatesInstall Ollama on a Linux VPS and keep it running: the install command, the systemd service, environment variables, model storage and updates, from the official docs.