Back to tutorials
Tutorial

Run Ollama Behind Nginx With Basic Auth

Secure Ollama endpoint on your VPS with Nginx, TLS, Basic Auth, and tight firewall rules—hands-on, command-by-command.

By Anurag Singh
Updated on Oct 26, 2026
Category: Tutorial
Share article
Run Ollama Behind Nginx With Basic Auth

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.log and /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 user or -u user:pass. In apps, set Authorization: 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 with ss -lntp and systemctl 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.