# Its own file in ./logs, alongside every other component. error_log /logs/vmgw.error.log warn; # ===================================================================== # owuitools-vmgw - the agent's entire outbound surface. # # WHY THIS EXISTS AT ALL # # Ollama has NO authentication and serves DELETE /api/delete, POST # /api/pull and POST /api/create. Anything that can reach # 172.17.0.1:11434 can delete qwen3.8 and take the whole assistant down. # So the agent does not reach it: owuitools-vmguard's filter permits this # container and nothing else, and this container exposes one exact Ollama # path plus a read-only one. # # This is also the concrete reason the agent is not simply added to the # api container's netguard allowlist: that would put "delete the model" # one SSRF away from fetch_page. # # WHAT USED TO BE HERE AND IS NOT ANY MORE # # A third location proxied live status and screenshots to Open WebUI's # /api/v1/chats/{id}/messages/{id}/event, with an Open WebUI ADMIN key # injected here as a header. It had to be an admin key: anyone may invoke # vm_agent and the chat belongs to whoever is talking, so that endpoint # refuses anything less. Keeping it out of the agent container was not # the same as it not existing. # # It is gone. The agent writes progress to the job volume it already # shares with the api container, and the `vm_agent_progress` filter - # running INSIDE Open WebUI, where the event emitter is already bound to # the requesting user's session - reads it and emits the events itself. # No Open WebUI credential exists anywhere in this stack now. # ===================================================================== server { listen 8000; server_name _; # A thinking model answering with 160k of context is slow, and the # agent's whole loop is these calls. The gateway must not be the # thing that gives up first. proxy_connect_timeout 10s; proxy_send_timeout 3600s; proxy_read_timeout 3600s; proxy_buffering off; client_max_body_size 64m; # --- the model ----------------------------------------------------- # `location =` for an exact match. /api/chat and nothing else: not # /api/delete, not /api/pull, not /api/create, and no prefix that # could be walked out of. location = /ollama/api/chat { proxy_pass http://${OWUITOOLS_OLLAMA_HOST}/api/chat; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $host; } # A read-only endpoint so the agent can confirm the model is loaded # and see its context length without guessing. location = /ollama/api/ps { proxy_pass http://${OWUITOOLS_OLLAMA_HOST}/api/ps; proxy_http_version 1.1; proxy_set_header Connection ""; } location = /health { access_log /logs/vmgw.access.log combined; return 200 "ok\n"; } location / { return 404 "owuitools-vmgw serves two paths and this is not one of them\n"; } }