Securely Expose Your Ollama Server: A macOS Guide with Caddy and Bearer Tokens

Running Ollama locally is straightforward: visit http://localhost:11434 and connect from your Python scripts or other tools.

If you plan to expose your machine to the internet, though, you should add basic protections to prevent unauthorized use of your CPU and GPU.

In my setup, I run an Ollama server on macOS and want secure access from my iPhone while away from home, as well as from a few trusted servers by IP or domain name.

Below is a quick guide to setting up Caddy as a reverse proxy that enforces a Bearer token and validates specific headers before forwarding requests to Ollama. You’ll need Homebrew installed, and you’ll need to port-forward 8081 on your home router to the macOS machine running this service.

What you’ll need

  • macOS with Ollama running locally (default at http://localhost:11434)
  • Homebrew installed
  • Router access to forward external port 8081 to your Mac
  • A Bearer token you’ll use for authentication

Why Caddy?

  • Simple, readable config
  • Built-in HTTPS when using a domain (optional)
  • Easy header checks and request filtering

High-level approach

  • Run Ollama locally on its default port (11434).
  • Put Caddy in front as a reverse proxy on port 8081.
  • Require a Bearer token in the Authorization header.
  • Optionally restrict by IP or Host header (domain name).
  • Forward only allowed requests to Ollama.
# Install Caddy
brew install caddy

# Generate a secure API key
echo "sk-ollama-$(openssl rand -hex 16)"

# You will get a key like sk-ollama-78834bcb4c76d97d35a0c1acd0d938c6

# Create the Caddy config directory
sudo mkdir -p /usr/local/etc/caddy

# Create the Caddyfile into the config directory, remember to change the key

cat > /usr/local/etc/caddy/Caddyfile << 'EOF'
{
    auto_https off
    admin off
}

:8081 {
    @validAuth expression `
        {header.Authorization} == "Bearer sk-ollama-YOUR-SECRET-KEY-HERE" ||
        {header.Referer}.contains("example.com") ||
        {header.Origin}.contains("example.com") ||
		{remote_host} == "168.79.218.237"
    `
    
    handle @validAuth {
        reverse_proxy 127.0.0.1:11434
    }
    
    handle {
        respond "Unauthorized" 401
    }
}
EOF

# Set proper permissions
sudo chown root:wheel /usr/local/etc/caddy/Caddyfile
sudo chmod 644 /usr/local/etc/caddy/Caddyfile

Then make it into a service so it starts with your computer:

# 1. Create user service
mkdir -p ~/Library/LaunchAgents

cat > ~/Library/LaunchAgents/homebrew.mxcl.caddy.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>homebrew.mxcl.caddy</string>
    <key>ProgramArguments</key>
    <array>
        <string>/opt/homebrew/bin/caddy</string>
        <string>run</string>
        <string>--config</string>
        <string>/usr/local/etc/caddy/Caddyfile</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/tmp/caddy-stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/caddy-stderr.log</string>
    <key>EnvironmentVariables</key>
    <dict>
        <key>HOME</key>
        <string>/Users/$USER</string>
        <key>PATH</key>
        <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
    </dict>
</dict>
</plist>
EOF

# 2. Replace YOUR_USERNAME
sed -i '' "s/YOUR_USERNAME/$USER/g" ~/Library/LaunchAgents/homebrew.mxcl.caddy.plist

# 3. Load it
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.caddy.plist

# 4. Start it
launchctl start homebrew.mxcl.caddy

# 5. Verify
launchctl list | grep caddy
curl http://localhost:11438/api/tags -H "Authorization: Bearer YOUR-TOKEN"

With this setup, you can now use your Ollama server remotely on your iPhone with client apps like Enchanted or have your WordPress plugin to safely access your AI server with fixed domain name or IP address.