github kossakovsky/selfhost-ai v1.9.0

5 hours ago

Added

  • n8n-MCP - New optional service (n8n-mcp profile): a Model Context Protocol server that exposes n8n's full node catalogue, property schemas and workflow templates to AI coding assistants, plus workflow-management tools once an n8n API key is configured. Served at n8n-mcp.<domain> behind a generated N8N_MCP_AUTH_TOKEN Bearer token. Caddy gates on the same token the service itself validates, because HTTP carries a single Authorization header and MCP clients send only a Bearer token - basic auth would make the endpoint unusable for every client. Ships in documentation-only mode; create an API key in n8n under Settings > n8n API, set N8N_API_KEY in .env and run make restart to unlock workflow management. Connect with npx -y mcp-remote https://n8n-mcp.<domain>/mcp --header "Authorization: Bearer <token>". Note that outside n8n Enterprise an API key grants full account access (#104).
  • Ollama - Optional multiple instances for multi-GPU hosts. Set OLLAMA_INSTANCE_COUNT in .env (1-8) to run ollama2, ollama3, ... alongside the existing ollama container, each pinnable to its own GPU so a large model stays resident instead of being swapped out. The runtime tuning variables (KEEP_ALIVE, NUM_PARALLEL, MAX_LOADED_MODELS, CONTEXT_LENGTH, KV_CACHE_TYPE, GPU_OVERHEAD, SCHED_SPREAD) can be set per instance with an OLLAMA<N>_ prefix (e.g. OLLAMA2_KEEP_ALIVE=-1) and fall back to the global value when unset, taking effect on the next make restart. OLLAMA<N>_GPU_DEVICES is the exception: it selects that instance's GPU, defaults to GPU N-1, and does not read the global OLLAMA_GPU_DEVICES. All instances share one model store, so each model is downloaded once. Extra instances are internal only (http://ollama2:11434) with no published ports, matching the rest of the stack; use caddy-addon/site-*.conf to expose one externally. The default of 1 generates nothing, so existing installs are unchanged. Set OLLAMA_GPU_DEVICES as well when running several instances, otherwise the first one is unpinned and may collide with ollama2 - make doctor warns about this (#107).

Changed

  • Open WebUI - New installations now store chats, users and settings in the stack's shared PostgreSQL instead of SQLite, removing the sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) database is locked failures that appear with several tabs or devices open, and placing the data in the same backup as the rest of the stack. Existing installations are deliberately left on SQLite: Open WebUI does not migrate data between backends, so switching would present an empty interface while the old chats stayed in webui.db. To opt in, set OPEN_WEBUI_DATABASE=postgres in .env and run make restart; see the README for the required volume backup and the migration tooling. Uploaded files and the vector store stay in the open-webui volume in both modes (#105).

Fixed

  • NocoDB - Fix "Connection to internal hosts is not allowed" (older builds: "Forbidden host name or IP address") when adding the stack's own PostgreSQL, or any container, as an external data source. NocoDB 2026.05.2 added SSRF protection that rejects any data-source host resolving to a private IP range, which covers every hostname on the Docker network, so this broke silently for anyone who updated after that release. NC_ALLOW_LOCAL_EXTERNAL_DBS=true is now set for the nocodb service; its webhook and data-import SSRF protections are deliberately left enabled. Connect with host postgres, port 5432, user postgres and the POSTGRES_PASSWORD from .env (#106).

Security

  • Supabase - The API gateway host port is now bound to loopback by default (API_GW_HTTP_PORT=127.0.0.1:8000) instead of 0.0.0.0:8000, where it attracted continuous internet-wide scanning for no functional benefit. External access already went through Caddy, which reaches the gateway over the Docker network via the kong alias upstream kept after switching from Kong to Envoy, and host-local tooling on http://localhost:8000 is unaffected. Existing installs are migrated automatically on the next make update or make restart: the new key is force-synced into supabase/docker/.env, which is the file Compose actually interpolates from, and the legacy KONG_HTTP_PORT/KONG_HTTPS_PORT keys are rewritten only when still on their insecure defaults. Set API_GW_HTTP_PORT to a plain port or a LAN address to expose it deliberately. make doctor gains an Exposed Ports section that warns when the gateway binds to all interfaces. Note that Supabase's upstream compose still publishes 0.0.0.0:5432 and 0.0.0.0:6543 for Postgres and the Supavisor pooler, and that Docker's published ports bypass ufw entirely - restrict those at your cloud provider's firewall; see the new Security Notes section in the README (#108).

Upgrade

make update

Existing installations are unchanged unless you opt in. Specifically:

  • Open WebUI stays on SQLite. Only fresh installs get PostgreSQL, because Open WebUI does not migrate data between backends — switching would show an empty interface while your chats stayed in webui.db. See "Open WebUI: SQLite or PostgreSQL" in the README for the backup and migration steps.
  • Ollama still runs one instance. OLLAMA_INSTANCE_COUNT defaults to 1, which generates nothing.
  • n8n-MCP is off until you select it in the wizard.

Two changes do apply automatically:

  • NocoDB gains NC_ALLOW_LOCAL_EXTERNAL_DBS=true, so internal data sources work again. Its webhook and data-import SSRF protections stay on.
  • The Supabase API gateway moves to 127.0.0.1:8000 if you run the supabase profile. Caddy is unaffected. To keep it on all interfaces, set API_GW_HTTP_PORT=0.0.0.0:8000 in .env before updating — an address you set yourself is preserved.

Afterwards, make doctor gains checks for the Open WebUI backend, exposed Supabase ports, the n8n-MCP token and per-instance Ollama containers.

Still exposed after this release

The Supabase profile's supavisor service publishes 0.0.0.0:5432 and 0.0.0.0:6543 from upstream's own compose file, and Docker's published ports bypass ufw entirely. Restrict these at your cloud provider's firewall. The pooler port can be closed by setting POOLER_PROXY_PORT_TRANSACTION=127.0.0.1:6543 in supabase/docker/.env; 5432 cannot, because POSTGRES_PORT is reused as a bare numeric port in Supabase's own connection strings. See the new Security Notes section in the README.

Don't miss a new selfhost-ai release

NewReleases is sending notifications on new releases.