A proxy in front of a model is not a proxy in front of a web page — cheat sheet
ollama, ai-services, networking
# split the problem in two, first
curl -s -m 5 localhost:11434/api/tags # the backend directly (exit 7 = could not connect)
curl -si -m 5 localhost:8080/api/tags # through the proxy
sudo ss -lntp | grep ollama # what is ACTUALLY listening, and on which port
sudo journalctl -u ollama -b --no-pager | tail
sudo tail -5 /var/log/nginx/error.log # nginx names the upstream address it tried
# the service account and its model store
systemctl show -p User -p Environment --value ollama
chown -R ollama:ollama /srv/models ; chmod 755 /srv/models
sudo -u ollama ls /srv/models # a permissions test
ollama list # a SERVER test: it is an HTTP client, it reads nothing from disk
find /srv/models \! -user ollama # after any root-run maintenance: should be silent
# an nginx proxy for a model API
# proxy_pass http://127.0.0.1:11434; (NO trailing slash = pass the URI through unchanged)
# proxy_http_version 1.1; (default 1.0)
# proxy_read_timeout 600s; (default 60s: the max GAP between reads, not the total —
# and a stream:false request is one long gap)
# proxy_buffering off; (default on: nginx MAY hold and spool; off guarantees it won't)
# proxy_send_timeout 600s ; proxy_request_buffering off ; client_max_body_size 32m
nginx -t && systemctl reload nginx ; sleep 1 # reload returns before the old workers are gone
# errnos in an upstream error
# 111 ECONNREFUSED nothing is listening there
# 110 ETIMEDOUT proxy_read_timeout ("while reading response header"), or a firewall dropping
# 13 EACCES a policy: SELinux httpd_can_network_connect, or AppArmor
# reproduce a timeout on purpose: time the backend, then the proxy
curl -s -o /dev/null -w '%{http_code} %{time_total}\n' localhost:11434/api/generate -d "$LONG"
curl -s -o /dev/null -w '%{http_code} %{time_total}\n' localhost:8080/api/generate -d "$LONG"
# a 504 whose time equals proxy_read_timeout is that timeout
# measure a stream instead of guessing: when did each line arrive?
curl -N -s localhost:8080/api/generate -d "$STREAM" | python3 -u /tmp/gaps.py
# log format: add $request_time $upstream_response_time