DEV Community

Cover image for Self-Hosted AI Security: What Every Ollama User Should Know
Mike
Mike

Posted on • Originally published at techiemike.com

Self-Hosted AI Security: What Every Ollama User Should Know

Self-Hosted AI Security: What Every Ollama User Should Know

Last week, a researcher publicly disclosed five Ollama and LiteLLM issues after a 90-day responsible disclosure window: two affecting Ollama directly and three affecting LiteLLM.

That is not the same as "instant remote code execution on every homelab Ollama server", but it is still a warning sign. Self-hosted AI tools are now being researched, fingerprinted, and probed like any other internet-facing service.

For most self-hosted AI setups, these are the kind of bugs that sit in the background until someone actually exploits them. And the thing about homelabs is that "someone" doesn't have to be a nation-state. It can be a scanner bot that found port 11434 on Shodan.

I've been running Docker, Ollama, and Open WebUI on my homelab for months. The setup works well: local models, no API bills, no rate limits. But security was an afterthought when I first set it up, and I suspect that's true for most people. I've tightened up my own setup since reading the disclosures, and there are five things every Ollama user should do right now.

What got disclosed

The recent disclosure covered five Ollama and LiteLLM issues:

  • Ollama GGUF string length panic — a crafted model file could trigger a crash, causing denial of service.
  • Ollama unbounded vocab_size resource exhaustion — a malicious model could consume excessive CPU or memory.
  • LiteLLM pass-the-hash authentication bypass — a weakness in authentication handling could allow access under specific conditions.
  • LiteLLM SSRF through custom guardrails — an attacker could make the server reach internal or unintended services.
  • LiteLLM Unicode normalization issue — a parsing or sandboxing weakness that could contribute to sandbox escape scenarios.

None of these should be described as "instant remote code execution on every homelab Ollama server". The practical lesson is simpler: if your AI stack is exposed without authentication, every parser bug, model-loading bug, and proxy bug becomes much more dangerous.

Diagram showing the Ollama and LiteLLM vulnerability attack surface: Docker containers, exposed API ports, and network attack vectors

Ollama has also had other recent security issues. CVE-2026-5530 (GitHub advisory) is reported as an SSRF flaw in the Model Pull API, and CVE-2026-7482 (CVE.org) is a heap out-of-bounds read in the GGUF model loader that could disclose server process memory. Those are separate from the five-issue Ollama/LiteLLM disclosure, but they reinforce the same point: exposed local AI services are now part of the attack surface.

Why your homelab is exposed

The Ollama service itself is designed as a local API, but Docker port publishing can easily expose it. In Compose, 11434:11434 publishes the container port on all host interfaces, which means LAN access — and possibly internet access if your firewall or router allows it.

If you followed a typical setup guide, you probably have this in your docker-compose.yml:

ollama:
  image: ollama/ollama:latest
  container_name: ollama
  ports:
    - "11434:11434"
Enter fullscreen mode Exit fullscreen mode

That "11434:11434" is the problem. It binds to 0.0.0.0:11434 on the host. Every device on your network can reach your Ollama API. If you've forwarded ports on your router (which most homelab users do for services like Plex or Nextcloud), then anyone on the internet can reach it too.

I checked my own setup while researching this post. I had the Docker Compose configuration from my Ollama guide with 127.0.0.1:11434:11434 (binding to localhost only) in the standalone docker run command, but the Compose version had the default 11434:11434. I'd fixed it in one place and not the other. This is exactly the kind of inconsistency that creates security gaps.

Five things to do today

1. Bind Ollama to localhost

The simplest fix, and the one that eliminates the largest attack surface:

ollama:
  image: ollama/ollama:latest
  container_name: ollama
  ports:
    - "127.0.0.1:11434:11434"
Enter fullscreen mode Exit fullscreen mode

That 127.0.0.1: prefix means Ollama only listens on localhost. Services running on the same machine can still reach it: Open WebUI, n8n, anything that talks to http://ollama:11434 inside the Docker network. But nothing outside the host can touch it.

If you're using the standalone docker run command:

docker run -d \
  --name ollama \
  -p 127.0.0.1:11434:11434 \
  -v ollama_data:/root/.ollama \
  ollama/ollama
Enter fullscreen mode Exit fullscreen mode

Verify it worked:

# Should show 127.0.0.1:11434, not 0.0.0.0:11434
docker port ollama
Enter fullscreen mode Exit fullscreen mode

Comparison diagram: 0.0.0.0 binding exposes Ollama to the network vs 127.0.0.1 localhost-only binding

2. Put a reverse proxy with authentication in front

Binding to localhost is good, but if you want to access Ollama from other devices on your network or remotely, you need a middle layer. A reverse proxy with authentication (Nginx, Caddy, or Traefik) sits between the outside world and Ollama.

The simplest approach: if you already use Cloudflare for your domain (I do for techiemike.com), add Cloudflare Access in front of your Ollama endpoint. It's free for up to 50 users, adds an email-based authentication gate, and you can set it up in about ten minutes. (I wrote about Cloudflare's new self-managed OAuth recently — it's worth reading if you're building anything that talks to the Cloudflare API from your homelab.)

If you want a self-hosted auth solution, Authentik or Authelia work well with Nginx. Here's the Nginx config pattern:

server {
    listen 443 ssl;
    server_name ollama.yourdomain.com;

    location / {
        auth_request /auth;
        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host $host;
    }

    location = /auth {
        proxy_pass http://127.0.0.1:9091/api/verify;  # Authentik
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
    }
}
Enter fullscreen mode Exit fullscreen mode

Even basic auth (a username and password) is better than an open API endpoint. But Cloudflare Access or Authentik with SSO is the proper solution.

3. Isolate Ollama on its own Docker network

Ollama doesn't need to be on the default bridge network with all your other containers. Put it on a dedicated network so that even if someone compromises it, they can't pivot to your other services:

networks:
  ai_network:
    driver: bridge
    internal: true  # No outbound internet from this network

services:
  ollama:
    networks:
      - ai_network
    # ... rest of config

  open-webui:
    networks:
      - ai_network
      - proxy_network  # Only Open WebUI can reach the reverse proxy
Enter fullscreen mode Exit fullscreen mode

The internal: true flag on the AI network means containers on it can talk to each other but can't reach the internet. Ollama doesn't need internet access after you've pulled your models. If someone exploits an SSRF vulnerability, the network layer stops the request before it leaves the Docker host.

The trade-off: you can't pull new models while the network is internal. When you need to pull a model, temporarily switch internal to false, pull the model, then switch it back. It's a minor inconvenience for a significant security gain.

4. Run Ollama as a non-root user

The official Ollama Docker image runs as root by default. If someone finds a container escape vulnerability, they land as root on your host. Running as a non-root user limits the damage:

ollama:
  image: ollama/ollama:latest
  container_name: ollama
  user: "1000:1000"
  ports:
    - "127.0.0.1:11434:11434"
  volumes:
    - ollama_data:/home/user/.ollama  # Non-root home directory
Enter fullscreen mode Exit fullscreen mode

You'll need to adjust the volume path since the default /root/.ollama won't be writable by user 1000. Ollama supports the OLLAMA_MODELS environment variable for this:

ollama:
  image: ollama/ollama:latest
  container_name: ollama
  user: "1000:1000"
  environment:
    - OLLAMA_MODELS=/home/user/.ollama/models
  ports:
    - "127.0.0.1:11434:11434"
  volumes:
    - ollama_data:/home/user/.ollama
Enter fullscreen mode Exit fullscreen mode

If you're on a single-user homelab where you're the only person with SSH access, the risk of container escape is low. But it costs a few extra lines of config and follows a security principle that every CS student should learn: least privilege. Don't give a process more access than it needs.

5. Monitor API usage and set rate limits

You can't secure what you can't see. Ollama doesn't have built-in access logging beyond stdout, but you can add it at the reverse proxy layer.

With Nginx, add a log format that captures the request body size, user agent, and response time:

log_format ollama_log '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      '"$http_user_agent" $request_time';

server {
    access_log /var/log/nginx/ollama_access.log ollama_log;
    # ... rest of config
}
Enter fullscreen mode Exit fullscreen mode

Then set up rate limiting. No legitimate user needs to fire hundreds of requests per second at a local model:

limit_req_zone $binary_remote_addr zone=ollama_limit:10m rate=10r/s;

server {
    location / {
        limit_req zone=ollama_limit burst=20 nodelay;
        # ... proxy config
    }
}
Enter fullscreen mode Exit fullscreen mode

For homelab use, 10 requests per second with a burst of 20 is generous. You can tighten it if you're the only user.

What this teaches about security

Every one of these issues follows a pattern that shows up in CS syllabi worldwide. And every one of them was preventable with basic security hygiene.

The SSRF vulnerability exists because the code trusts user input (a URL in a guardrail config) and requests whatever it points to. The Ollama GGUF parsing bugs exist because the code doesn't validate model file headers before processing them. The auth bypass exists because the middleware checks one header but the application logic reads another.

These aren't exotic zero-days. They're the same class of bug that's been appearing in web applications for twenty years. What's new is the context: self-hosted AI tools are being deployed by people who aren't security engineers, in environments that weren't designed for the threat model they're now facing.

If you're a CS student reading this (and a chunk of my readers are), these disclosures are a better education than any textbook. Look up the actual reports on Huntr. Read the patch diffs on the Ollama GitHub. You'll learn more about real-world security from one vulnerability analysis than from a semester of theory.

The bigger picture

Ollama isn't uniquely dangerous. It's the same story we've seen with every self-hosted service: people deploy it, it works, and security gets deferred. I did it myself. My Docker + Ollama setup guide has been one of the most popular posts on this site, and I originally wrote it with the 127.0.0.1 binding in one code block but not the Compose version. I only noticed the gap while researching this post.

The difference with self-hosted AI is the data. Your conversations with a local model might include code from private repos, personal documents you're summarising, or API keys you're debugging. That data lives in your request logs, your model outputs, and potentially in whatever an attacker exfiltrates. It's not just compute you're protecting. It's context.

I wrote recently about why running AI on your own hardware matters: the privacy, the cost, the independence from cloud platforms. All of that is still true. But independence comes with responsibility. When you're the cloud, you're also the security team.

The five steps above take about twenty minutes to implement. They close the most common attack vectors without breaking anything. Do them today, before someone else's scanner bot finds your Ollama instance before you do.

Top comments (0)