Skip to content

Dashboard Settings page always fails to save (EACCES on /.env inside Docker) #197

Description

@ViolinKaine

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

  1. docker compose --profile ui up (per the repo's own docker-compose.yml)
  2. Open the dashboard → Settings
  3. Change any field, click "Save to .env"
  4. Server-side error (visible via docker compose logs dashboard):
    [Settings API] write error: Error: EACCES: permission denied, open '/.env'
    
  5. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions