Running Local Models

Running Ollama Behind an OpenAI-Compatible Endpoint

⏱ 15 min

Lesson 1 established when self-hosting is worth doing. This lesson gets a real model running on your own machine, reachable over HTTP in a shape that later lessons can plug straight into the PHP AI Client SDK. Ollama is the easiest on-ramp for this: it packages model management, a local server process, and an OpenAI-compatible API surface into one tool, which means the custom provider you build in Lesson 4 talks to it using the exact same request shape it would use for OpenAI itself.

What you'll learn in this lesson
Installing Ollama and pulling a model
Getting a real, running local model, not just the server process.
Where the OpenAI-compatible endpoint actually lives
http://localhost:11434/v1, and which routes it exposes.
Confirming it responds to a real chat-completions-shaped request
A curl call proving the round trip works before any PHP is involved.
The API key quirk
Why Ollama accepts (and ignores) any string as an API key, and why that still matters for later lessons.
Prerequisites

Lesson 1’s decision framework, and a machine with enough RAM (and ideally a GPU) to run a local model at usable speed. This lesson doesn’t require WordPress yet, everything here runs and is tested independently first.

Step 1: Install Ollama and start the server

Ollama installs as a single binary and runs a local server process:

# File: terminal - macOS/Linux install
curl -fsSL https://ollama.com/install.sh | sh

Windows and macOS users can also download an installer directly from ollama.com. Once installed, start the server if it isn’t already running as a background service:

# File: terminal
ollama serve

By default this listens on port 11434 on localhost. Leave it running in its own terminal, or confirm it’s already running as a system service before continuing.

Step 2: Pull a model

Ollama’s model library covers a range of open-weight models. Pull one that fits your hardware, this lesson doesn’t depend on any specific model, only that one is downloaded and available:

# File: terminal
ollama pull llama3.1

Confirm it’s available locally:

# File: terminal
ollama list
Check the current model library before picking one

Ollama’s library changes as new open-weight models are released and older ones are superseded. Check ollama.com’s model library for what’s current and what fits your available RAM or VRAM before committing to a specific model for a real project.

Step 3: Find the OpenAI-compatible endpoint

Ollama exposes an OpenAI-compatible API surface at http://localhost:11434/v1, alongside its own native API. The route that matters most for this course is chat completions:

Ollama's OpenAI-compatible surface
1
Base URL
http://localhost:11434/v1, the same shape a PHP AI Client SDK provider expects to call against.
2
POST /v1/chat/completions
The chat-completions route this course's custom provider (Lesson 4) will call.
3
GET /v1/models
Lists locally available models in OpenAI's models-listing shape, used for the model metadata directory in Lesson 4.

Step 4: Confirm it with a real request

Before writing any PHP, confirm the endpoint actually responds to a standard chat-completions-shaped request:

# File: terminal
curl http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3.1",
    "messages": [
      { "role": "user", "content": "Reply with exactly the word: connected" }
    ]
  }'

A working setup returns a JSON response with a choices array whose first entry’s message.content is connected, the same response shape an OpenAI-compatible client expects from any provider.

Ollama accepts (and ignores) any Authorization header

Ollama’s OpenAI-compatible endpoint doesn’t check the Authorization header at all; you can send Bearer anything or omit it entirely and get the same result. That matters in Lesson 4: the PHP AI Client SDK’s OpenAI-compatible base classes always attach an API-key authentication header to every request, since that’s the only authentication method the SDK currently implements. For Ollama, that header is real, present, and simply ignored on the receiving end, not a security control.

Test it: confirm from outside your own terminal session

If WordPress and Ollama run on different machines or containers (a Docker-based WordPress setup calling a host-machine Ollama instance, for example), confirm the endpoint is reachable from where your PHP code will actually run, not just from the same shell you started ollama serve in:

# File: terminal, run from your WordPress environment
curl http://host.docker.internal:11434/v1/models

Adjust the hostname to whatever your actual network setup requires. A local wp-env-based setup, a separate VM, and a bare-metal install can all need a different hostname here, and this is the single most common point of failure before any PHP code is even involved.

A model responding to curl isn't the same as it being production-ready

This lesson confirms the endpoint works. It says nothing about how the model handles your actual prompts, at what latency, or under real concurrent traffic. Treat this as plumbing verification, not a readiness signal for a production feature.

Recap

Ollama installs as a single binary, runs a local server on port 11434, and exposes an OpenAI-compatible API at /v1, including /v1/chat/completions and /v1/models. A plain curl request against that endpoint, shaped exactly like a call to OpenAI’s own API, is the fastest way to confirm the whole chain works before any WordPress or PHP AI Client SDK code is written. The Authorization header Ollama ignores today becomes relevant again in Lesson 4, where the SDK sends one on every request regardless.

Resources & further reading

← When Self-Hosting AI Actually Makes Sense vLLM and llama.cpp as Alternatives →