Summary (Co-Authored by Claude code)
The dashboard's Settings page always fails to save with "Failed to save settings.
Check backend connection." — but it's not actually a backend/API connectivity issue.
The Next.js API route that handles the save writes to a path that only resolves
correctly in local dev (next dev from a git checkout), not in the Docker deployment
that docker-compose.yml documents as the standard way to run the dashboard.
Root Cause
dashboard/app/api/settings/route.ts:5:
const ENV_PATH = path.resolve(process.cwd(), '../.env')
This assumes process.cwd() is the dashboard/ directory inside a full monorepo
checkout, so ../.env resolves to the repo root's .env. That's true for local dev.
But dashboard/Dockerfile sets WORKDIR /app and copies only the built dashboard
output into the image — there's no monorepo layout inside the container, no sibling
.env one directory up, and /.env (where the path resolves to from /app) doesn't
exist and isn't writable by the non-root nextjs user the container runs as.
Result: any Docker-based deployment (i.e. docker-compose.yml as shipped) gets a
write failure on every settings save attempt, surfaced as a generic backend-connection
error that has nothing to do with the actual cause.
Reproducer
docker compose --profile ui up (per the repo's own docker-compose.yml)
- Open the dashboard → Settings
- Change any field, click "Save to .env"
- Server-side error (visible via
docker compose logs dashboard):
[Settings API] write error: Error: EACCES: permission denied, open '/.env'
- UI shows: "Failed to save settings. Check backend connection." — misleading, since
the backend (:8080) was never involved; this route writes directly to a file on
the dashboard container's own filesystem.
Suggested Fix
The settings route shouldn't write to a file inside the dashboard container's
filesystem at all when running in Docker — that file isn't shared with the backend
container and doesn't persist across image rebuilds either way. Options:
- Have the dashboard call the backend server's own config/settings API (if one
exists) instead of writing a local .env, so the write actually reaches the process
that reads it.
- If a shared
.env truly needs editing, mount it as a volume into the dashboard
container at a fixed path and reference that path (not a relative ../) so it
doesn't depend on cwd.
Happy to open a PR if a preferred direction is confirmed.
Environment
- Deployment:
docker compose --profile ui up (repo's own compose file, unmodified
aside from a local override for uid/gid and Ollama host networking)
- Images built from current
main via the repo's Dockerfiles
- Dashboard on
:3000, backend on :8080
Summary (Co-Authored by Claude code)
The dashboard's Settings page always fails to save with "Failed to save settings.
Check backend connection." — but it's not actually a backend/API connectivity issue.
The Next.js API route that handles the save writes to a path that only resolves
correctly in local dev (
next devfrom a git checkout), not in the Docker deploymentthat
docker-compose.ymldocuments as the standard way to run the dashboard.Root Cause
dashboard/app/api/settings/route.ts:5:This assumes
process.cwd()is thedashboard/directory inside a full monorepocheckout, so
../.envresolves to the repo root's.env. That's true for local dev.But
dashboard/DockerfilesetsWORKDIR /appand copies only the built dashboardoutput into the image — there's no monorepo layout inside the container, no sibling
.envone directory up, and/.env(where the path resolves to from/app) doesn'texist and isn't writable by the non-root
nextjsuser the container runs as.Result: any Docker-based deployment (i.e.
docker-compose.ymlas shipped) gets awrite failure on every settings save attempt, surfaced as a generic backend-connection
error that has nothing to do with the actual cause.
Reproducer
docker compose --profile ui up(per the repo's owndocker-compose.yml)docker compose logs dashboard):the backend (
:8080) was never involved; this route writes directly to a file onthe dashboard container's own filesystem.
Suggested Fix
The settings route shouldn't write to a file inside the dashboard container's
filesystem at all when running in Docker — that file isn't shared with the backend
container and doesn't persist across image rebuilds either way. Options:
exists) instead of writing a local
.env, so the write actually reaches the processthat reads it.
.envtruly needs editing, mount it as a volume into the dashboardcontainer at a fixed path and reference that path (not a relative
../) so itdoesn't depend on
cwd.Happy to open a PR if a preferred direction is confirmed.
Environment
docker compose --profile ui up(repo's own compose file, unmodifiedaside from a local override for uid/gid and Ollama host networking)
mainvia the repo'sDockerfiles:3000, backend on:8080