Running Ollama behind a reverse proxy gives you things the raw API doesn’t: a clean domain name instead of an IP and port, HTTPS so connections are encrypted, basic authentication to keep your models private, and the ability to put Ollama on a standard port (80/443) that doesn’t need special firewall rules. If you’re running Ollama on a home server or a VPS and want to access it properly from other devices, a reverse proxy is the right way to set it up.
This guide covers the two most common options: Nginx (widely available, battle-tested, more configuration) and Caddy (modern, automatic HTTPS, less configuration). Both work well — pick based on what you’re comfortable with or already have installed.
The Basic Concept
A reverse proxy sits in front of Ollama and forwards requests to it. Clients connect to the proxy (which handles TLS, authentication, and routing), and the proxy forwards those requests to Ollama on localhost. Ollama itself stays bound to 127.0.0.1:11434 — the proxy is what faces the network.
The setup looks like this: client → [proxy:443 with HTTPS + auth] → [Ollama:11434 on localhost]
Ollama needs to be configured to listen only on localhost (the default) — don’t set OLLAMA_HOST=0.0.0.0 when using a reverse proxy, as that would expose the unauthenticated API directly alongside the proxy.
Setting Up Nginx as a Reverse Proxy
Install Nginx if you haven’t already:
# Ubuntu / Debian
sudo apt update && sudo apt install nginx
# macOS (Homebrew)
brew install nginx
Create a new server block configuration. On Ubuntu, create a file at /etc/nginx/sites-available/ollama:
server {
listen 80;
server_name ollama.yourdomain.com; # or your local hostname / IP
location / {
proxy_pass http://127.0.0.1:11434;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Required for streaming responses
proxy_buffering off;
proxy_read_timeout 300s;
proxy_connect_timeout 10s;
# Increase body size for large model requests
client_max_body_size 100M;
}
}
Enable the site and reload Nginx:
sudo ln -s /etc/nginx/sites-available/ollama /etc/nginx/sites-enabled/
sudo nginx -t # test config for syntax errors
sudo systemctl reload nginx
Test it:
curl http://ollama.yourdomain.com
You should get Ollama is running. If not, check sudo journalctl -u nginx -n 20 for errors.
Adding HTTPS with Let’s Encrypt (Nginx)
For a public-facing server, HTTPS is essential. Certbot automates Let’s Encrypt certificate management:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d ollama.yourdomain.com
Certbot modifies your Nginx config to add the SSL certificate and redirect HTTP to HTTPS automatically. It also sets up automatic renewal via a systemd timer. After running certbot, your config will have listen 443 ssl added and the certificate paths filled in.
Test the HTTPS connection:
curl https://ollama.yourdomain.com
Adding Basic Authentication (Nginx)
Ollama has no built-in auth. If your proxy is internet-facing, add HTTP Basic Auth at the Nginx layer to prevent anyone who finds your URL from using your models.
Create a password file:
sudo apt install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd yourusername
Add the auth directives to your Nginx location block:
location / {
auth_basic "Ollama API";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:11434;
proxy_buffering off;
proxy_read_timeout 300s;
client_max_body_size 100M;
}
Reload Nginx. From now on, any request to the proxy must include credentials. When using the Ollama Python library or API with basic auth:
import ollama
client = ollama.Client(
host='https://ollama.yourdomain.com',
auth=('yourusername', 'yourpassword')
)
response = client.generate(model='llama3.2', prompt='Hello')
Figure 1 — Reverse Proxy Architecture for Ollama
Setting Up Caddy as a Reverse Proxy
Caddy handles HTTPS automatically — it provisions and renews Let’s Encrypt certificates without any extra steps. If you’re setting up a fresh server and don’t already have Nginx, Caddy is the easier path.
Install Caddy on Ubuntu:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install caddy
Edit /etc/caddy/Caddyfile:
ollama.yourdomain.com {
reverse_proxy localhost:11434 {
flush_interval -1
transport http {
read_timeout 5m
}
}
}
Reload Caddy:
sudo systemctl reload caddy
That’s it. Caddy automatically obtains an SSL certificate for your domain, sets up HTTP→HTTPS redirection, and proxies to Ollama. No certbot, no manual certificate management.
To add basic authentication with Caddy, first hash a password:
caddy hash-password --plaintext yourpassword
Then update the Caddyfile:
ollama.yourdomain.com {
basicauth /* {
yourusername <hashed-password-from-above>
}
reverse_proxy localhost:11434 {
flush_interval -1
transport http {
read_timeout 5m
}
}
}
Local Network Setup Without a Domain
If you’re setting up a reverse proxy for local network access only — not public internet — you don’t need a real domain or Let’s Encrypt certificates. Use a self-signed certificate or skip TLS entirely and run on HTTP.
For local HTTP with Nginx (no TLS):
server {
listen 80;
server_name 192.168.1.100; # your machine's local IP
location / {
proxy_pass http://127.0.0.1:11434;
proxy_buffering off;
proxy_read_timeout 300s;
client_max_body_size 100M;
}
}
This gives you a clean port 80 URL on your local network without the complexity of certificate management. Other devices on the network connect to http://192.168.1.100/api/generate rather than http://192.168.1.100:11434/api/generate.
For local HTTPS with a self-signed cert (needed if clients require HTTPS even on the local network):
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/ollama.key -out /etc/nginx/ssl/ollama.crt -subj "/CN=192.168.1.100"
Then reference the certificate in your Nginx server block with ssl_certificate and ssl_certificate_key directives. Clients will need to accept the self-signed cert — most tools have an option to skip certificate verification for local use.
Figure 2 — Nginx vs Caddy: Which to Choose
Handling Streaming Responses
One proxy-specific issue with Ollama is streaming. Ollama’s API sends tokens as they’re generated — a streaming response — rather than waiting for the full output before sending anything. Without proper proxy configuration, the proxy may buffer the entire response before forwarding it, which makes the client wait for the full generation before seeing anything. That defeats one of the key UX benefits of LLM streaming.
The key Nginx directive is proxy_buffering off — included in the config above. This tells Nginx to pass data through as it arrives rather than buffering it. On Caddy, flush_interval -1 achieves the same effect (immediate flushing). Without one of these settings, streaming will appear to “hang” until the full response is generated, then dump all the text at once.
Also set proxy_read_timeout long enough for your longest expected generation. The default Nginx timeout is 60 seconds — a 70B model generating a long response can easily take longer than that on slower hardware. Setting it to 300 seconds or higher prevents timeout errors on long generations.
A reverse proxy is the right infrastructure layer for any Ollama setup that needs to be accessed outside your local machine. Whether you use it for HTTPS, authentication, clean URLs, or just to avoid exposing a high-numbered port directly, the configuration is straightforward and the setup is one that scales — the same Nginx or Caddy config that handles your personal Ollama instance today would handle a team deployment with multiple users without changes.
Rate Limiting and Access Control
If you’re sharing your Ollama instance with others — even on a home network — rate limiting prevents one user from hogging the inference capacity. Nginx supports rate limiting natively. Add a rate limit zone to your Nginx config (in the http block, outside any server block):
http {
limit_req_zone $binary_remote_addr zone=ollama:10m rate=5r/m;
...
}
Then apply it in your location block:
location / {
limit_req zone=ollama burst=10 nodelay;
proxy_pass http://127.0.0.1:11434;
proxy_buffering off;
proxy_read_timeout 300s;
}
This limits each client IP to 5 requests per minute with a burst allowance of 10. For a small group of users running interactive queries, this is usually more than enough. Adjust the rate based on your hardware — if your GPU can handle 20 concurrent inference requests per minute comfortably, set the rate accordingly. Clients that exceed the limit get a 429 Too Many Requests response, which most API clients handle gracefully with a retry.
Combining Tailscale with a Reverse Proxy
For secure remote access without a public domain, Tailscale and a reverse proxy make an excellent combination. Set up Tailscale on your server and any devices that need access — all your Tailscale devices get a *.ts.net hostname automatically. Caddy can then serve HTTPS using Tailscale’s certificate authority, which issues certs for your .ts.net hostnames without requiring a real domain or Let’s Encrypt. The result is a fully private, fully encrypted Ollama API accessible from any of your Tailscale devices anywhere in the world, with zero public exposure. The Caddy documentation has a specific guide for Tailscale integration — search “Caddy Tailscale” — and the setup takes about 15 minutes. This is the setup worth building if you want remote access to your local Ollama instance and don’t want to deal with DNS, public certificates, or firewall configuration.
Troubleshooting Proxy Issues
The most common proxy problem is 502 Bad Gateway — the proxy can’t reach Ollama on localhost. First check that Ollama is actually running (curl http://localhost:11434 directly on the server). If Ollama is running but the proxy still gets 502, check that you’re proxying to http://127.0.0.1:11434 (not localhost, which can resolve to IPv6 on some systems). The second common issue is requests timing out on long generations — increase proxy_read_timeout in Nginx or read_timeout in Caddy’s transport block. The third is streaming appearing broken — ensure proxy_buffering off (Nginx) or flush_interval -1 (Caddy) is in your config. And if you’ve added basic auth and can’t get Python clients to authenticate, check that you’re passing the auth tuple correctly — requests.get(url, auth=('user', 'pass')) for raw HTTP requests, or the auth parameter in the Ollama client constructor.
Complete Nginx Config for Reference
Here’s a complete, production-ready Nginx config for Ollama with HTTPS and basic auth — consolidating all the pieces above into one block you can adapt directly:
server {
listen 80;
server_name ollama.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name ollama.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/ollama.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ollama.yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
auth_basic "Ollama API";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:11434;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering off;
proxy_read_timeout 300s;
proxy_connect_timeout 10s;
client_max_body_size 100M;
}
}
Run certbot first to get the certificate, then paste this config — it gives you HTTPS, HTTP→HTTPS redirect, and basic auth in one block. The streaming and timeout settings are already tuned for Ollama’s response patterns. Adapt the domain, certificate paths, and htpasswd file location to match your setup.
This config is a solid baseline for any internet-facing Ollama deployment and extends easily — add IP allowlisting in the location block if you want to restrict access to specific addresses, or swap basic auth for OAuth using Nginx’s auth_request module if you need more sophisticated access control. The core pattern (Nginx proxying to localhost:11434 with buffering off and a long read timeout) remains the same regardless of how you layer additional security on top of it.
What to Set Up After Your Proxy Is Running
With a reverse proxy in place, the next natural step is connecting services that benefit from a clean HTTPS endpoint. Open WebUI works well pointed at your proxy URL — configure it with OLLAMA_BASE_URL=https://ollama.yourdomain.com and the basic auth credentials if you’ve set them. Tools like LangChain, LlamaIndex, and the Ollama Python library all support custom base URLs, so they can be pointed at your proxy endpoint from any machine that has network access. If you’re building an application that uses Ollama as a backend, having a proper HTTPS endpoint with a real domain name also makes it easier to share with colleagues or use from different environments — no more http://192.168.1.100:11434 that only works when you’re on the same network.