Self-Hosting n8n + Baserow with Docker: The Networking Bug Nobody Documents
If you're running n8n and Baserow together in the same docker-compose.yml, you'll likely hit this exact error the first time n8n's Baserow node tries to talk to Baserow: the credential test fails, or you get a raw 404 Server Error / "Site not found" page when hitting http://baserow/api/... from inside the n8n container.
The cause isn't what most guides assume.
What's actually happening
Baserow's all-in-one Docker image ships its own internal Caddy reverse proxy in front of the Django backend and the frontend. That proxy only forwards /api/* requests to the backend for hostnames it explicitly recognizes. Any other Host header — like the internal Docker network name baserow that n8n uses to reach it — gets routed to the frontend instead, which doesn't know what to do with an API call and returns a 404.
Two environment variables look like they should fix this, and don't:
BASEROW_CADDY_ADDRESSES— controls which addresses Caddy listens on, not which hostnames it routes.BASEROW_EXTRA_ALLOWED_HOSTS— this is a Django-level setting (ALLOWED_HOSTS). It stops Django from rejecting the request outright, but it does nothing for Caddy's routing, so you never even reach Django.
The actual fix
Add the internal hostname to BASEROW_EXTRA_PUBLIC_URLS:
services:
baserow:
image: baserow/baserow:latest
environment:
- BASEROW_PUBLIC_URL=http://localhost:8080
- BASEROW_CADDY_ADDRESSES=:80
- BASEROW_EXTRA_PUBLIC_URLS=http://baserow,http://127.0.0.1:8080
- BASEROW_EXTRA_ALLOWED_HOSTS=baserow,127.0.0.1
BASEROW_EXTRA_PUBLIC_URLS is what Caddy's internal matcher actually checks before proxying /api/* to the backend. List every hostname another container will use to reach Baserow here — including the plain Docker Compose service name (baserow) that other containers on the same network use by default.
After adding this and restarting the stack, the n8n Baserow credential test (and any HTTP request from another container) starts working immediately — no other change needed.
How to verify it yourself
From inside any other container on the same Docker network:
curl -s http://baserow/api/settings/
If you get back JSON instead of an HTML 404 page, the routing is fixed.