How to Expose Ollama Securely with systemd & a Reverse Proxy

Updated on Aug 18, 2026
Mila H
7 MINS READ
Table of Contents
How to Expose Ollama Securely

As you must know, Ollama has no built-in authentication. If you open port 11434 to the internet, anyone can use your GPU, pull models, and send requests at your cost. This guide shows you exactly how to expose Ollama securely, keeping the raw port locked down, running it as a proper systemd service, and putting Nginx in front with HTTPS and a password.

If you want a server that is already built for this kind of workload, check out PerLod AI Hosting for GPU-optimized plans.

What You Will Need to Expose Ollama Securely

Before starting to expose Ollama securely, make sure you have the following ready:

  • A remote Linux server running Ubuntu 22.04 or newer.
  • A domain name points to your server's public IP.
  • Root or sudo access over SSH.
  • Ollama is already installed. You can also check the Open WebUI with Ollama setup guide if you haven't done that yet.
  • Nginx and Certbot are available via apt.

Why not just open port 11434? Ollama has no built-in access control. Any exposed instance allows unauthenticated model usage, resource hijacking, and prompt injection from anyone who finds the port. The right way is to keep Ollama on localhost and let Nginx handle the public-facing side.

Before starting, here is the security model you are building:

HTML/XML
Internet → Nginx (HTTPS + Basic Auth, port 443) → Ollama (localhost:11434)

Ollama listens only on 127.0.0.1:11434. Nginx sits in front, handles SSL termination, checks credentials, and forwards clean requests to Ollama internally.

For more details on platform-specific options and flags, you can also check the official Ollama Linux documentation.

Step 1: Install Ollama and Run It as a systemd Service

If you do not have Ollama installed yet, run the official installer with the command below:

Bash
curl -fsSL https://ollama.com/install.sh | sh

The install script automatically creates a systemd service file at /etc/systemd/system/ollama.service. It looks like this:

Bash
[Unit]Description=Ollama ServiceAfter=network-online.target [Service]ExecStart=/usr/bin/ollama serveUser=ollamaGroup=ollamaRestart=alwaysRestartSec=3Environment="PATH=$PATH" [Install]WantedBy=multi-user.target

Enable and start the service:

Bash
sudo systemctl daemon-reloadsudo systemctl enable ollamasudo systemctl start ollama

Verify it is running:

Bash
sudo systemctl status ollama

Now, follow the steps below to expose Ollama securely.

Step 2: Lock Ollama to Localhost Only

By default, Ollama listens on 127.0.0.1:11434. You want to make sure this does not accidentally change. The safe way is to set the OLLAMA_HOST environment variable explicitly in the systemd service override, not in the main service file, which gets overwritten on updates.

To do this, run the command below:

Bash
sudo systemctl edit ollama

This opens a blank override file. Add the following:

Bash
[Service]Environment="OLLAMA_HOST=127.0.0.1:11434"

Save and exit. Reload and restart:

Bash
sudo systemctl daemon-reloadsudo systemctl restart ollama

Important Note: Never set OLLAMA_HOST=0.0.0.0 unless Ollama is inside a private Docker network. Setting it to 0.0.0.0 binds to all interfaces and exposes the API to everyone. That is the unsafe pattern this guide avoids.

Confirm Ollama is only listening on localhost:

Bash
ss -tlnp | grep 11434

You should only see 127.0.0.1:11434, not 0.0.0.0:11434.

Step 3: Understand Key Ollama Environment Variables

When you need to expose Ollama securely, understanding these variables helps you control its behavior through systemd:

Variable Default What It Does
OLLAMA_HOST 127.0.0.1:11434 The address and port Ollama listens on
OLLAMA_ORIGINS localhost Comma-separated list of allowed CORS origins
OLLAMA_MODELS ~/.ollama/models Path where models are stored
OLLAMA_DEBUG 0 Set to 1 for verbose logging

To set any of these, add them as Environment= lines inside sudo systemctl edit ollama, then reload and restart.

For example, restrict CORS to your domain only:

Bash
[Service]Environment="OLLAMA_HOST=127.0.0.1:11434"Environment="OLLAMA_ORIGINS=https://yourdomain.com"

Step 4: Block Port 11434 at the Firewall

Even though Ollama is bound to localhost, it is good practice to block port 11434 at the firewall level too. This adds a second layer of protection:

Bash
sudo ufw default deny incomingsudo ufw default allow outgoingsudo ufw allow 22/tcp       # SSHsudo ufw allow 80/tcp       # HTTP (for Certbot)sudo ufw allow 443/tcp      # HTTPSsudo ufw enable

Make sure port 11434 is NOT in the allow list. Check your rules:

Bash
sudo ufw status

Step 5: Install Nginx and Set Up Basic Auth Password

Install Nginx if it is not already on your server:

Bash
sudo apt updatesudo apt install nginx -y

Start and enable it:

Bash
sudo systemctl enable nginxsudo systemctl start nginx

Because this is how you expose Ollama securely to specific users, you need a password file. Install apache2-utils to get the htpasswd tool:

Bash
sudo apt install apache2-utils -y

Create the password file and your first user:

Bash
sudo htpasswd -c /etc/nginx/.htpasswd yourusername

You will be prompted to enter and confirm a password. The file stores a hashed version of it.

To add more users later, you can omit the -c so you do not overwrite the file:

Bash
sudo htpasswd /etc/nginx/.htpasswd anotheruser

Step 6: Configure Nginx as a Reverse Proxy

Create a new Nginx config file for your domain:

Bash
sudo nano /etc/nginx/sites-available/ollama

Paste the following content with your domain:

Bash
server {    listen 80;    server_name yourdomain.com;     location / {        auth_basic "Ollama API – Restricted";        auth_basic_user_file /etc/nginx/.htpasswd;         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;        proxy_set_header Origin "";        proxy_set_header Referer "";        proxy_buffering off;        proxy_read_timeout 300s;        proxy_connect_timeout 60s;    }}

What each directive does:

HTML/XML
auth_basic with auth_basic_user_file  #Enforces username and password before any request reaches Ollama. proxy_pass http://127.0.0.1:11434     #Sends the request to Ollama on localhost. proxy_buffering off                   #Required for streaming responses so tokens appear in real time. proxy_read_timeout 300s               #Gives large models enough time to generate long outputs. Origin "" and Referer ""              #Strips headers that can cause CORS issues from the proxy side.

Enable the site and test the config:

Bash
sudo ln -s /etc/nginx/sites-available/ollama /etc/nginx/sites-enabled/sudo nginx -tsudo systemctl reload nginx

Step 7: Get a Free SSL Certificate with Certbot

Now you can take your setup from HTTP to proper HTTPS by using Certbot:

Bash
sudo apt install certbot python3-certbot-nginx -ysudo certbot --nginx -d yourdomain.com

Follow the prompts. Certbot will:

  • Issue a free Let's Encrypt certificate.
  • Automatically update your Nginx config to use HTTPS.
  • Set up auto-renewal via a systemd timer.

Test auto-renewal to make sure it works:

Bash
sudo certbot renew --dry-run

After Certbot finishes, your Nginx config will have an updated listen 443 ssl block and HTTP-to-HTTPS redirect, all handled automatically.

Step 8: How to Expose Ollama Securely | Test the Setup

Now test that the setup works correctly. From your local machine, not the server, you can run:

Test authentication, which should return 401 without credentials:

Bash
curl -I https://yourdomain.com/api/tags

You should get 401 Unauthorized.

Test with credentials:

Bash
curl -u yourusername:yourpassword https://yourdomain.com/api/tags

You should get a JSON response listing your installed models.

Test a generate request:

Bash
curl -u yourusername:yourpassword https://yourdomain.com/api/generate \  -d '{"model": "llama3.2", "prompt": "Hello!", "stream": false}'

If you get a valid JSON response, your setup to expose Ollama securely is working correctly.

How to Check Ollama Logs

When something does not work, knowing where the logs are is essential.

To check Ollama service logs, you can use:

Bash
journalctl -u ollama -f

View logs from the last hour only:

Bash
journalctl -u ollama --since "1 hour ago"

You can enable debug mode for more details by adding this to your systemd override:

Bash
sudo systemctl edit ollama

Add:

Bash
[Service]Environment="OLLAMA_DEBUG=1"

Then restart:

Bash
sudo systemctl restart ollamajournalctl -u ollama -f

To check Nginx access and error logs, you can use:

Bash
sudo tail -f /var/log/nginx/access.logsudo tail -f /var/log/nginx/error.log

Safe API Usage Patterns

Once you expose Ollama securely behind Nginx, here is how to use the API correctly from your applications or scripts:

Python example using requests:

Python
import requests url = "https://yourdomain.com/api/generate"auth = ("yourusername", "yourpassword")payload = {    "model": "llama3.2",    "prompt": "Explain Docker in one sentence.",    "stream": False} response = requests.post(url, json=payload, auth=auth)print(response.json()["response"])

Using the Ollama Python library with a remote host:

Python
import ollama client = ollama.Client(    host="https://yourdomain.com",    auth=("yourusername", "yourpassword")) response = client.generate(model="llama3.2", prompt="Hello!")print(response["response"])

Passing credentials in curl for quick tests:

Bash
curl -u user:pass https://yourdomain.com/api/tagscurl -u user:pass https://yourdomain.com/api/generate \  -H "Content-Type: application/json" \  -d '{"model":"llama3.2","prompt":"Hi","stream":false}'

Note: Never hard-code credentials in scripts. Use environment variables or a .env file with restricted permissions:

Bash
chmod 600 .env

Conclusion

Getting Ollama to work on localhost is the easy part. The hard part is making it accessible from the internet without creating a security hole. By following this guide, you have the right way to expose Ollama securely for real-world use. You keep full control, your API is password-protected and encrypted, and you can check everything through journalctl when something needs debugging.

For heavy models, multi-user inference, or always-on deployments, a dedicated GPU server makes a real difference. You can check out the best GPU Dedicated Servers, built to run LLMs at scale.

No, as long as you used sudo systemctl edit ollama to create an override file. The override lives in /etc/systemd/system/ollama.service.d/override.conf and is not changed by updates.

Yes. In your Nginx config, replace the single location / block with specific location /api/generate and location /api/chat blocks, and return 403 for everything else.

Run ss -tlnp | grep 11434 on the server. You should only see 127.0.0.1:11434. If you see 0.0.0.0:11434, fix the OLLAMA_HOST variable immediately.