> ## Documentation Index
> Fetch the complete documentation index at: https://www.towbar.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Ollama

> Ollama serves downloadable AI models through a local API.

export const UseCaseNavigation = () => {
  useLayoutEffect(() => {
    const storageKey = "towbar-use-case-open-groups";
    const groupSelector = "#sidebar li[data-title] > button[aria-expanded]";
    let restoring = false;
    let frame = 0;
    function storedGroups() {
      try {
        return new Set(JSON.parse(sessionStorage.getItem(storageKey) || "[]"));
      } catch {
        return new Set();
      }
    }
    function save(groups) {
      try {
        sessionStorage.setItem(storageKey, JSON.stringify([...groups]));
      } catch {}
    }
    function groupName(button) {
      return button.parentElement?.dataset.title;
    }
    function rememberOpenGroups() {
      const groups = new Set();
      for (const button of document.querySelectorAll(groupSelector)) {
        if (button.getAttribute("aria-expanded") === "true") {
          const name = groupName(button);
          if (name) groups.add(name);
        }
      }
      save(groups);
    }
    function restoreOpenGroups() {
      frame = 0;
      const groups = storedGroups();
      if (!groups.size) return;
      restoring = true;
      for (const button of document.querySelectorAll(groupSelector)) {
        if (groups.has(groupName(button)) && button.getAttribute("aria-expanded") === "false") {
          button.click();
        }
      }
      restoring = false;
    }
    function scheduleRestore() {
      if (!frame) frame = requestAnimationFrame(restoreOpenGroups);
    }
    function onClick(event) {
      if (restoring || !(event.target instanceof Element)) return;
      const button = event.target.closest(groupSelector);
      if (button) {
        const name = groupName(button);
        if (!name) return;
        const groups = storedGroups();
        if (button.getAttribute("aria-expanded") === "true") groups.delete(name); else groups.add(name);
        save(groups);
        return;
      }
      if (event.target.closest('a[href^="/docs/use-cases/"]')) {
        rememberOpenGroups();
      }
    }
    const observer = new MutationObserver(scheduleRestore);
    document.addEventListener("click", onClick, true);
    observer.observe(document.getElementById("sidebar") || document.body, {
      childList: true,
      subtree: true
    });
    scheduleRestore();
    return () => {
      document.removeEventListener("click", onClick, true);
      observer.disconnect();
      cancelAnimationFrame(frame);
    };
  }, []);
  return null;
};

<UseCaseNavigation />

<img className="towbar-doc-brand-logo" src="https://mintcdn.com/avgeek/EGkEWLTQnOwecqNx/assets/use-case-logos/ollama.svg?fit=max&auto=format&n=EGkEWLTQnOwecqNx&q=85&s=e9f7414de63a8fdf112d3169bee22726" alt="Ollama logo" aria-hidden="true" width="24" height="24" data-path="assets/use-case-logos/ollama.svg" />

**Upstream source:** [Current installation guide](https://docs.ollama.com/docker).

This CPU-only image stores downloaded models under `/root/.ollama`. Ollama's API has no built-in authentication, so the example stays on the server's private application network. Model size and speed depend on available RAM and CPU.

## Towbar manifest

```yaml title=".towbar/services/ollama.service.yml" theme={"system"}
id: ollama
name: Ollama
buildServer: null
deployment:
  type: image
  image: ollama/ollama@sha256:8262851b2846b87c649eddf3e76beb270c52f4d1bc94559f47efde16b0841551
container:
  port: 11434
  resources:
    cpus: 4
    memory: 8g
  network: application
  networkAlias: ollama
  volumes:
    - name: ollama
      mountPath: /root/.ollama
      initialData: image
environments:
  production:
    server: 192.0.2.10
rollout:
  type: recreate
  maintenanceMode: true
  reason: Persistent application data uses a single writer
```

## Configure

1. Prepare the example server, connect the repository, and map `production` to the branch containing these manifests. Replace the example server IP. Commit the manifests, then sync the repository and inspect the resolved configuration.
2. Keep the Service's named volumes attached across deployments. Towbar's Datastore backup policy does not back up Service volumes, so include them in your own recovery plan.
3. This manifest has no public domain. Use a trusted connection to the server for the first check. Add a public route only after configuring the product's authentication or an access gateway.
4. Deploy the Service, then perform the checks below before enabling auto-deploy.

## Verify

From a trusted shell on the server, pull a small model in the running container and query `/api/tags`. Redeploy and confirm the model is still listed.

For field constraints, see [Service manifest](/docs/services/manifest).
