Ollama, the slick local LLM runner, doesn’t come with built-in authentication for its API, leaving your local models wide open if exposed.
Let’s see Ollama running without any protection.
curl http://localhost:11434/api/tags
This command, run from any machine on your network (or even the internet if your firewall is permissive), will list all the models you have downloaded. No password, no API key, nothing. If you’ve got a powerful GPU and a few large models, this is a significant security hole.
The common way to fix this is by putting a reverse proxy in front of Ollama. This proxy can then handle authentication before forwarding requests to the actual Ollama API. Nginx is a popular choice for this, but Caddy is even simpler for this specific task due to its automatic HTTPS and straightforward configuration.
Here’s how you can set up Caddy to proxy Ollama and add basic authentication using its http.basicauth directive.
First, ensure you have Caddy installed. You can download it from the official Caddy website.
Next, create a Caddyfile to configure Caddy. Let’s assume Ollama is running on localhost:11434 (the default). We’ll have Caddy listen on port 8080 and proxy requests to Ollama, enforcing basic authentication.
:8080 {
reverse_proxy localhost:11434
handle_path /api/* {
basicauth {
user your_username your_hashed_password
}
}
}
In this Caddyfile:
:8080tells Caddy to listen on port 8080 for incoming HTTP requests.reverse_proxy localhost:11434is the core directive. Any request Caddy receives on port 8080 will be forwarded to Ollama running onlocalhost:11434.handle_path /api/*is crucial. It specifies that thebasicauthdirective should only apply to requests whose path starts with/api/. This is important because Caddy itself might serve other assets or health checks that you don’t want to authenticate.basicauth { ... }enables HTTP Basic Authentication.user your_username your_hashed_passworddefines a user. You need to replaceyour_usernamewith your desired username andyour_hashed_passwordwith a securely hashed version of your password.
To generate the hashed password, you can use the caddy hash-password command:
caddy hash-password
Enter password:
your_secret_password
$2a$14$K.L.s7.4hJ2FfA.iO5.wUu0hW0p0H0q0r0s0t0u0v0w0x0y0z0A0B0C0
Copy the generated hash and paste it into your Caddyfile.
Now, start Caddy with your Caddyfile:
caddy run --config /path/to/your/Caddyfile
Replace /path/to/your/Caddyfile with the actual path to your Caddyfile.
Once Caddy is running, you can access the Ollama API through Caddy. Your curl command will now need to include the -u flag for authentication:
curl -u "your_username:your_secret_password" http://localhost:8080/api/tags
If the username and password are correct, you’ll receive the same output as before, listing your Ollama models. If they are incorrect, you’ll get a 401 Unauthorized error.
This setup provides a fundamental layer of security. It prevents unauthorized access to your Ollama API by requiring a username and password for all API requests. It’s important to note that HTTP Basic Auth sends credentials in a Base64 encoded string, which is not encrypted. For true security, especially if exposing this outside your local network, you should use HTTPS. Caddy makes this incredibly easy.
To enable HTTPS, you would simply change the Caddyfile to listen on port 443 and let Caddy handle certificate acquisition and renewal automatically:
:443 {
tls yourdomain.com # Replace with your actual domain
reverse_proxy localhost:11434
handle_path /api/* {
basicauth {
user your_username your_hashed_password
}
}
}
Then, you would access Ollama via https://yourdomain.com/api/... and the curl command would be:
curl -u "your_username:your_secret_password" https://yourdomain.com/api/tags --insecure # Add --insecure if you don't have a proper DNS setup for testing
The basicauth directive in Caddy is a powerful, yet simple, way to secure HTTP services. It works by intercepting requests, checking for the Authorization: Basic <credentials> header, decoding the credentials, and comparing them against a configured list of users and their hashed passwords. If the credentials match, the request is allowed to proceed to the reverse_proxy directive. If they don’t match, or are missing, Caddy returns a 401 Unauthorized response with a WWW-Authenticate: Basic realm="Restricted" header, prompting the client to provide credentials.
The next hurdle you’ll likely face is managing multiple users or integrating with a more sophisticated authentication system like OAuth2 or JWT.