Skip to content

docs(docker): document settings.json writable-layer + env-var semantics (#7819)#7827

Open
JohnMcLear wants to merge 1 commit into
developfrom
issue-7819-docker-compose-example
Open

docs(docker): document settings.json writable-layer + env-var semantics (#7819)#7827
JohnMcLear wants to merge 1 commit into
developfrom
issue-7819-docker-compose-example

Conversation

@JohnMcLear
Copy link
Copy Markdown
Member

Summary

Two operator-facing documentation gaps surfaced by issue #7819:

  1. `settings.json` is a template, not the live config. Env-var substitution happens at load time in memory only — the on-disk file always shows `${VAR:default}` placeholders regardless of what the env is set to. Operators repeatedly assume the templated file is stale and try to "fix" it.

  2. `settings.json` lives in the container's writable layer. Admin /settings edits survive `docker restart` but are silently lost on `docker compose down && up`, `pull`, or watchtower. The compose verbs that quietly recreate the container aren't intuitive.

This PR adds:

  • A new section in `doc/docker.md` explaining how `settings.json` and env vars interact (with a callout that the on-disk file is intentionally unchanged by env vars).
  • A second section spelling out which Docker operations preserve or reset `settings.json`, with a recreate-vs-restart table.
  • A commented-out `./settings.json:/opt/etherpad-lite/settings.json` bind mount in both `docker-compose.yml` and the README compose example, so operators who do want persistent on-disk edits have a one-line opt-in.

No runtime change. Default behaviour is identical to today — the bind mount is opt-in.

Companion PR

#7826 covers the corresponding admin-UI side (explanatory banner + Effective tab + auth-error surfacing). The two PRs are independent and can land in any order.

Test plan

  • Doc-only + commented YAML change; no code paths touched
  • Re-read the YAML to confirm the bind-mount line stays commented out by default

🤖 Generated with Claude Code

… semantics (#7819)

Two related operator-facing docs gaps, both surfaced by #7819:

1. settings.json on disk is a *template*; env-var substitution happens
   at load time in memory only. Operators repeatedly mistake the
   templated file for a stale config because the docs never spell out
   that the on-disk file is intentionally unchanged by env vars.

2. The default docker-compose.yml puts settings.json in the container's
   writable layer with no host mount, which means admin /settings edits
   are silently lost on `docker compose down && up`, `pull`, or
   watchtower — but preserved across plain `restart`. Operators don't
   reliably know which compose verbs recreate the container.

Adds two prose sections to doc/docker.md (explaining both gotchas, with
a recreate-vs-restart table) and a commented-out `./settings.json:…`
bind mount in both docker-compose.yml and the README compose example.
Bind mount is opt-in so existing setups behave identically.

No runtime change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Review Summary by Qodo

Document settings.json template semantics and persistence behavior

📝 Documentation

Grey Divider

Walkthroughs

Description
• Documents how settings.json template and env-var substitution interact
• Explains which Docker operations preserve or reset settings.json edits
• Adds optional commented bind mount for persistent admin UI edits
• Clarifies that on-disk file remains unchanged by environment variables
Diagram
flowchart LR
  A["settings.json template<br/>with placeholders"] -->|"env-var substitution<br/>at load time"| B["In-memory<br/>resolved config"]
  A -->|"on-disk file<br/>unchanged"| C["Writable layer<br/>or host mount"]
  D["docker restart"] -->|"preserves"| C
  E["docker compose down/up"] -->|"resets"| C
  F["Optional bind mount"] -->|"enables"| G["Persistent edits<br/>across recreates"]

Loading

File Changes

1. doc/docker.md 📝 Documentation +38/-0

Document settings.json template and persistence semantics

• Added section explaining settings.json as a template with env-var substitution happening only in
 memory
• Added table documenting which Docker operations preserve vs reset settings.json (restart vs
 recreate)
• Documented optional bind mount for persisting admin UI edits across container recreates
• Clarified that on-disk file always shows placeholders regardless of environment values

doc/docker.md


2. docker-compose.yml 📝 Documentation +8/-0

Add optional settings.json bind mount with guidance

• Added commented-out optional bind mount for ./settings.json:/opt/etherpad-lite/settings.json
• Included detailed comment explaining when to uncomment and why (persistent admin UI edits)
• Referenced issue #7819 for additional context

docker-compose.yml


3. README.md 📝 Documentation +0/-0

Add optional settings.json bind mount to README example

• Added commented-out optional bind mount for ./settings.json:/opt/etherpad-lite/settings.json in
 compose example
• Included detailed comment explaining persistence behavior and when to enable
• Referenced issue #7819 for additional context

README.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects Bot commented May 20, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0)

Context used

Grey Divider


Remediation recommended

1. Missing Effective tab 🐞 Bug ≡ Correctness
Description
doc/docker.md claims the admin /settings UI shows a banner and an “Effective” tab for resolved
env-var values, but the current admin UI only has Form/Raw modes and shows resolved values inline
via env pills. Operators will look for a non-existent tab and may miss where to find runtime values.
Code

doc/docker.md[R36-40]

Evidence
The documentation claims a specific UI affordance (“Effective” tab/banner), but the Settings page
renders only a Form/Raw toggle; resolved values are displayed inline by EnvPill’s runtime chip
rather than via a separate tab.

doc/docker.md[32-40]
admin/src/pages/SettingsPage.tsx[60-78]
admin/src/components/settings/widgets/EnvPill.tsx[69-83]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`doc/docker.md` states that the admin /settings page “surfaces a banner and an "Effective" tab” to show resolved (in-memory) env-var values, but the current admin SPA does not have such a tab/banner.

### Issue Context
The admin UI exposes resolved values via the Form view widgets (EnvPill runtime chip), while the Raw view reflects the on-disk file contents.

### Fix Focus Areas
- doc/docker.md[32-40]
- admin/src/pages/SettingsPage.tsx[60-78]
- admin/src/components/settings/widgets/EnvPill.tsx[69-83]

### Expected change
Update the bullet to describe the current behavior (Form view shows an “active value”/runtime chip for env placeholders; Raw shows placeholders), or remove the forward-looking mention and reference the relevant feature/PR only when it exists.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Bind mount may block saves 🐞 Bug ☼ Reliability
Description
The new bind-mount guidance doesn’t mention that docker-compose.yml runs Etherpad as UID 5001 and
adminsettings.ts writes settings.json; a host-mounted settings.json that isn’t writable by that UID
will cause /admin settings saves to fail with EACCES. The comments also incorrectly call this the
image’s writable layer (it’s the container’s).
Code

docker-compose.yml[R10-17]

Evidence
The compose file explicitly sets the container user to 5001:0, and the admin settings endpoint
writes settings.json with no special permission handling—so if the bind-mounted host file is not
writable by that UID, saveSettings deterministically errors. The added comments also contain the
incorrect “image’s writable layer” phrasing.

docker-compose.yml[1-17]
src/node/hooks/express/adminsettings.ts[74-82]
doc/docker.md[54-61]
doc/docker.md[316-322]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The new commented bind mount suggestion for `settings.json` can lead to failed saves via the admin /settings UI when the host file permissions don’t allow writes by the container user (UID 5001 in the provided compose file). The comments also use imprecise terminology (“image’s writable layer”).

### Issue Context
- `docker-compose.yml` runs the app as `user: "5001:0"`.
- The admin settings socket handler writes `settings.settingsFilename` directly; any filesystem permissions problem becomes a save error.

### Fix Focus Areas
- docker-compose.yml[2-17]
- doc/docker.md[54-61]
- doc/docker.md[316-322]
- src/node/hooks/express/adminsettings.ts[74-82]

### Expected change
1. Change “image’s writable layer” to “container’s writable layer” in the new comments.
2. Add a short note near the bind-mount line/snippet that the host file must be writable by the container user (UID 5001 by default in this compose file), with an example such as `chown 5001:0 ./settings.json` (or a permissions-based alternative) so /admin saves work when the mount is enabled.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant