
Publishing Ollama straight to the public internet is a fast way to burn bandwidth, run up compute bills, and expose prompts. This walkthrough shows how to put a secure Ollama endpoint on your own VPS. You’ll use Nginx as a reverse proxy with TLS, Basic Auth, and tight firewall rules.
The result feels like a private, OpenAI-style API. You can call it from scripts, apps, and automations without leaving the front door open.
The steps below assume Ubuntu Server on a VPS with a public IP.
If you want fewer late-night “why is this broken?” moments, start with a managed VPS hosting plan. Updates, security baselines, and recovery become shared responsibilities—not a solo hobby.
What you’ll build (and what this does not solve)
- Nginx terminates TLS and proxies a single hostname (for example,
ollama.example.com) to a local Ollama service. - Basic Auth blocks drive-by scans and prevents unauthenticated usage.
- Firewall rules keep Ollama reachable only on
127.0.0.1(or a private interface). From the public side, only 443 is exposed. - Optional hardening: rate limiting, request size caps, and API-friendly logging.
This setup does not give you per-user billing, fine-grained tokens, or prompt-level authorization.
Basic Auth is a solid “first gate,” but it’s still a shared credential. If you need per-user control, add user management in your application layer.
Prerequisites and resource sizing
You’ll need:
- An Ubuntu VPS with root access (or a sudo user)
- A domain/subdomain pointing to your VPS IP (A/AAAA record)
- Ollama installed and running
Minimum practical specs depend on the model. For a small-to-mid model with quantization, 2–4 vCPU and 8–16 GB RAM is a sensible baseline.
CPU-only inference works, but latency rises quickly once you add concurrency.
If you expect multiple users or long generations, plan for a larger VPS or a dedicated box.
If Ollama isn’t installed yet, follow Install Ollama on Ubuntu VPS With Nginx and TLS for the base install.
Then come back for the Basic Auth + firewall lock-down. This guide focuses on safe public exposure.
Step 1: Confirm Ollama is only listening locally
Start by confirming what address and port Ollama is listening on. The default is usually 11434.
sudo ss -lntp | grep 11434 || true
You want 127.0.0.1:11434 (loopback), not 0.0.0.0:11434 (all interfaces).
If it’s bound to all interfaces, fix that before you put Nginx in front of it.
If you installed Ollama as a systemd service, add an override so it binds to loopback only. Create the drop-in:
sudo systemctl edit ollama
Paste a configuration like this (adjust only if your service differs):
[Service]
Environment="OLLAMA_HOST=127.0.0.1:11434"
Reload and restart:
sudo systemctl daemon-reload
sudo systemctl restart ollama
Re-check the listener:
sudo ss -lntp | grep 11434
If your install doesn’t use a systemd unit named ollama, find the actual unit name:
systemctl list-units --type=service | grep -i ollama
Step 2: Install Nginx and tooling for TLS + Basic Auth
Install Nginx, Certbot (Let’s Encrypt), and the Apache htpasswd utility (used to generate Basic Auth files):
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx apache2-utils
Allow web traffic in UFW (we’ll keep it tight later):
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
If you already run a web stack, UFW may already be enabled.
The key requirement is that ports 80 and 443 are open for Nginx.
For a deeper TLS checklist and common fixes, keep this nearby: TLS setup guide tutorial (2026).
Step 3: Create a Basic Auth password file
Create a dedicated directory for Nginx secrets. Then set sane permissions:
sudo install -d -m 0750 /etc/nginx/secrets
sudo chown root:www-data /etc/nginx/secrets
Create an htpasswd file. You’ll be prompted for a password:
sudo htpasswd -c /etc/nginx/secrets/ollama.htpasswd ollamaadmin
Then lock down the file:
sudo chmod 0640 /etc/nginx/secrets/ollama.htpasswd
sudo chown root:www-data /etc/nginx/secrets/ollama.htpasswd
Tip: For multiple users, omit -c
sudo htpasswd /etc/nginx/secrets/ollama.htpasswd developer1
Step 4: Create an Nginx site for Ollama (reverse proxy)
Create a new server block. Replace ollama.example.com with your real hostname.
sudo nano /etc/nginx/sites-available/ollama
Paste this configuration:
server {
listen 80;
listen [::]:80;
server_name ollama.example.com;
# Let’s Encrypt validation and HTTP to HTTPS redirect
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
Enable the site and test Nginx:
sudo ln -s /etc/nginx/sites-available/ollama /etc/nginx/sites-enabled/ollama
sudo nginx -t
sudo systemctl reload nginx
Step 5: Issue a TLS certificate with Certbot
Run Certbot with the Nginx plugin:
sudo certbot --nginx -d ollama.example.com
When prompted, choose the redirect option.
Certbot will update your Nginx config and add the TLS server block.
Confirm renewals are scheduled:
sudo systemctl status certbot.timer --no-pager
Step 6: Add Basic Auth + proxy settings to the HTTPS server block
Edit the TLS server block Certbot created:
sudo nano /etc/nginx/sites-available/ollama
Inside the server { listen 443 ssl; ... } block, add (or adjust) the location / section.
Nginx should proxy to Ollama and require Basic Auth.
A practical config looks like this:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ollama.example.com;
# Certbot will manage these paths
ssl_certificate /etc/letsencrypt/live/ollama.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ollama.example.com/privkey.pem;
# Keep requests reasonable for an LLM API.
client_max_body_size 25m;
# Basic Auth gate
auth_basic "Ollama API";
auth_basic_user_file /etc/nginx/secrets/ollama.htpasswd;
location / {
proxy_pass http://127.0.0.1:11434;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Avoid buffering large streamed responses.
proxy_buffering off;
proxy_read_timeout 300;
proxy_send_timeout 300;
}
}
Validate and reload:
sudo nginx -t
sudo systemctl reload nginx
Step 7: Tighten firewall rules so port 11434 is never public
If Ollama binds to 127.0.0.1, it’s already unreachable from the internet.
Still, enforce the intent at the firewall level. Also make sure you never opened 11434 in UFW.
List rules:
sudo ufw status verbose
If you ever added a rule like ufw allow 11434, remove it:
sudo ufw delete allow 11434
For a clean baseline web firewall setup, see Set Up UFW Firewall on Ubuntu for a Web Server.
Step 8: Verify the secure endpoint end-to-end
From your laptop (or any external machine), confirm you get an auth challenge:
curl -I https://ollama.example.com/
You should see HTTP/2 401 and a WWW-Authenticate header.
Now authenticate and hit a simple API call. A safe check is listing local models:
curl -u ollamaadmin 'https://ollama.example.com/api/tags'
To test generation, send a short prompt. That makes it easier to confirm streaming and timeouts:
curl -u ollamaadmin https://ollama.example.com/api/generate \
-H 'Content-Type: application/json' \
-d '{"model":"llama3","prompt":"Write a one-sentence status update.","stream":false}'
If you don’t have the model yet, pull it on the server first:
ollama pull llama3
Limitations you’ll notice: CPU-only inference can stall under load.
Nginx will keep the connection open, but users will feel it if RAM is tight or the box starts swapping.
Step 9: Add rate limiting (basic bot protection without breaking your app)
Basic Auth stops anonymous access, but credentials can still leak.
Common causes include saved browser credentials, copied curl snippets, or a stray commit. Rate limiting caps the blast radius when that happens.
Create a small Nginx snippet with a limit zone:
sudo nano /etc/nginx/conf.d/ollama_rate_limit.conf
Add:
limit_req_zone $binary_remote_addr zone=ollama_per_ip:10m rate=10r/m;
Now apply it inside the TLS server block, within location /:
limit_req zone=ollama_per_ip burst=20 nodelay;
Test and reload:
sudo nginx -t
sudo systemctl reload nginx
If your app does legitimate bursts (for example, RAG pipelines that call the model several times per user action), raise the burst or rate.
The goal is to slow credentialed scraping, not throttle normal usage. For more detail, see Nginx Rate Limiting Tutorial (2026).
Step 10: Operational checks (logs, timeouts, and safe updates)
Self-hosted AI endpoints usually fail in boring ways.
Timeouts go unnoticed until users complain. Patching slips for “later.”
- Watch Nginx logs:
/var/log/nginx/access.logand/var/log/nginx/error.log. For quick tailing:
sudo tail -f /var/log/nginx/access.log
- Watch the Ollama service:
sudo journalctl -u ollama -f --no-pager
If generations get cut off, bump proxy_read_timeout.
Also confirm your client isn’t imposing a shorter timeout.
For unattended security patching on Ubuntu, follow Set Up Automated Security Updates on Ubuntu VPS.
If this host is reachable from the internet, weeks-long patch gaps are an own goal.
Common mistakes and quick fixes
- 401 loops in your client: the client isn’t sending the Basic Auth header. With curl, use
-u useror-u user:pass. In apps, setAuthorization: Basic .... - 504 Gateway Timeout: inference took too long. Increase
proxy_read_timeout, then reconsider model size and quantization. - “Connection refused” from Nginx: Ollama is down or not listening on
127.0.0.1:11434. Confirm withss -lntpandsystemctl status. - Certbot fails validation: DNS isn’t pointing to the VPS, or port 80 is blocked. Verify A/AAAA records and firewall rules.
- Accidentally exposed 11434: delete the firewall allow rule and ensure Ollama binds only to loopback.
Where to run this: VPS vs dedicated (honest guidance)
A small private LLM API for internal tooling fits nicely on a VPS.
If you need steady throughput, you’ll start caring about sustained CPU, extra RAM headroom, and sometimes GPU access.
- VPS: best for single-user or small-team endpoints, RAG experiments, and low concurrency. It’s also the easiest place to start while you learn the operational edges.
- Dedicated server: best for a team workload, larger models, or performance that stays stable under load.
If you want a clean Linux box with full control for this stack, a HostMyCode VPS is the straightforward option.
If you don’t want to own patching and recovery drills, go managed.
If you’re building a private LLM API for your apps, run it where you control the network edge and the logs. Start with a HostMyCode VPS, then upgrade to managed VPS hosting if you want help with patching, hardening, and recovery drills.
FAQ: Run Ollama Behind Nginx With Basic Auth
Is Basic Auth enough for a secure Ollama endpoint?
It’s a solid first layer if you also use TLS and keep Ollama bound to loopback.
If you need multi-user access or you’re exposing this to untrusted clients, put an application gateway in front with per-user tokens and audit trails.
Can I restrict access to only my office IPs?
Yes. Add allow/deny rules in the TLS server block or enforce it with UFW.
IP allowlists are great for admin-only endpoints, but they get annoying fast if users travel or your ISP IP changes.
Why disable proxy buffering?
Ollama can stream tokens. Buffering makes Nginx batch chunks and flush less predictably, which makes streaming clients feel sluggish. Disabling buffering keeps responses responsive.
How do I rotate credentials without downtime?
Edit /etc/nginx/secrets/ollama.htpasswd (add a new user, test), then remove the old entry. Reload Nginx with sudo systemctl reload nginx.
What’s the safest way to expose this API to automation tools?
Use private networking (VPN) when you can.
If it must be public, keep it behind TLS + Basic Auth, add rate limiting, and store credentials in a secret manager rather than in source code.
Summary
You now have Ollama behind Nginx with HTTPS, Basic Auth, and firewall boundaries that keep the raw Ollama port private. This combination prevents most accidental exposure and blocks unauthenticated scraping.
If you later add a chat UI or a RAG layer, keep the same edge pattern.
Terminate TLS at Nginx, authenticate early, and limit traffic.
If you want a stable place to run this long-term—alongside your other services—use a HostMyCode VPS for full control, or choose managed VPS hosting if you want help keeping the endpoint secure over time.