Skip to content

docker-compose: harden default credentials and proxy trust (draft, under discussion)#7907

Merged
SamTV12345 merged 1 commit into
ether:developfrom
JohnMcLear:harden-docker-compose-defaults
Jun 7, 2026
Merged

docker-compose: harden default credentials and proxy trust (draft, under discussion)#7907
SamTV12345 merged 1 commit into
ether:developfrom
JohnMcLear:harden-docker-compose-defaults

Conversation

@JohnMcLear
Copy link
Copy Markdown
Member

Draft — under discussion. Splitting the deployment-default changes out of #7905 so the non-breaking fixes there can merge independently.

Changes

  • Require ADMIN_PASSWORD and the database password to be set explicitly (no admin fallback).
  • Default TRUST_PROXY to false.

⚠️ Breaking changes (open questions)

  1. ADMIN_PASSWORD / DB password required. docker compose up will fail until they're set (e.g. in .env). Keeps the reference compose from booting with admin/admin.
    • Open: the postgres ports: are not published here, so the DB is internal-only — requiring the DB password is more hygiene than exposure fix. Keep it required, or revert just the DB part?
  2. TRUST_PROXY default true → false. Likely to be reverted: this compose is typically run behind a reverse proxy, where true is correct; flipping it can break HTTPS detection (cookie.secure: "auto") and client-IP/rate-limiting for those users. The risk it addresses (IP spoofing) only applies to a directly-exposed instance.

Decisions to make before un-drafting

  • Keep ADMIN_PASSWORD required, or auto-generate + print on first run instead?
  • Keep DB password required, or revert (internal-only network)?
  • Revert the TRUST_PROXY flip (lean yes) and document instead?

🤖 Generated with Claude Code

- Require ADMIN_PASSWORD and the database password to be provided explicitly
  (no implicit fallback).
- Default TRUST_PROXY to false.

Co-Authored-By: Claude Opus 4.8 (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

qodo-free-for-open-source-projects Bot commented Jun 7, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0)

Grey Divider


Action required

1. Docs mismatch compose 🐞 Bug ⚙ Maintainability
Description
docker-compose.yml now requires DOCKER_COMPOSE_APP_ADMIN_PASSWORD and
DOCKER_COMPOSE_POSTGRES_PASSWORD and defaults TRUST_PROXY to false, but README.md and doc/docker.md
still show admin/admin defaults and TRUST_PROXY defaulting to true. Users copy-pasting the
documented compose snippets will either fail at docker compose up (missing required vars) or
deploy with different behavior than documented.
Code

docker-compose.yml[R22-38]

+      # Required — set a strong value (e.g. in .env). No fallback, so misconfig
+      # surfaces at `docker compose up` rather than at runtime.
+      ADMIN_PASSWORD: "${DOCKER_COMPOSE_APP_ADMIN_PASSWORD:?Set DOCKER_COMPOSE_APP_ADMIN_PASSWORD to a strong value}"
      DB_CHARSET: ${DOCKER_COMPOSE_APP_DB_CHARSET:-utf8mb4}
      DB_HOST: postgres
      DB_NAME: ${DOCKER_COMPOSE_POSTGRES_DATABASE:-etherpad}
-      DB_PASS: ${DOCKER_COMPOSE_POSTGRES_PASSWORD:-admin}
+      DB_PASS: "${DOCKER_COMPOSE_POSTGRES_PASSWORD:?Set DOCKER_COMPOSE_POSTGRES_PASSWORD to a strong value}"
      DB_PORT: ${DOCKER_COMPOSE_POSTGRES_PORT:-5432}
      DB_TYPE: "postgres"
      DB_USER: ${DOCKER_COMPOSE_POSTGRES_USER:-admin}
      # For now, the env var DEFAULT_PAD_TEXT cannot be unset or empty; it seems to be mandatory in the latest version of etherpad
      DEFAULT_PAD_TEXT: ${DOCKER_COMPOSE_APP_DEFAULT_PAD_TEXT:- }
      DISABLE_IP_LOGGING: ${DOCKER_COMPOSE_APP_DISABLE_IP_LOGGING:-false}
      SOFFICE: ${DOCKER_COMPOSE_APP_SOFFICE:-null}
-      TRUST_PROXY: ${DOCKER_COMPOSE_APP_TRUST_PROXY:-true}
+      # Default off: only enable when actually behind a trusted reverse proxy
+      # that sets the X-Forwarded-* headers.
+      TRUST_PROXY: ${DOCKER_COMPOSE_APP_TRUST_PROXY:-false}
Evidence
The compose file change makes certain env vars required and flips TRUST_PROXY’s default, but the
published compose examples still show old fallbacks and defaults, so the documentation no longer
matches the actual runtime behavior.

docker-compose.yml[20-49]
README.md[102-157]
doc/docker.md[335-395]
.env.default[7-18]

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

## Issue description
`docker-compose.yml` was hardened (required secrets + TRUST_PROXY default flip), but the repo’s Docker Compose documentation snippets are now stale. This causes immediate breakage for users following docs and undermines the intent of the hardening.

## Issue Context
- The compose file now uses `${VAR:?message}` for `DOCKER_COMPOSE_APP_ADMIN_PASSWORD` and `DOCKER_COMPOSE_POSTGRES_PASSWORD`, so `docker compose up` fails if they’re unset/empty.
- Docs still show `:-admin` fallbacks and `TRUST_PROXY` defaulting to `true`.

## Fix Focus Areas
- docker-compose.yml[20-38]
- README.md[102-157]
- doc/docker.md[335-395]
- .env.default[7-18]

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


2. Proxy default breaks HTTPS 🐞 Bug ≡ Correctness
Description
docker-compose.yml now defaults TRUST_PROXY to false, which prevents Express from trusting
X-Forwarded-* headers and breaks secure-cookie auto detection when Etherpad is behind an
SSL-terminating reverse proxy. This can lead to incorrect HTTPS detection (express-session `secure:
'auto'`), affecting login/session behavior and deployments that require secure cookies.
Code

docker-compose.yml[R36-38]

+      # Default off: only enable when actually behind a trusted reverse proxy
+      # that sets the X-Forwarded-* headers.
+      TRUST_PROXY: ${DOCKER_COMPOSE_APP_TRUST_PROXY:-false}
Evidence
The server enables Express’s trust proxy behavior only when settings.trustProxy is true, and it
explicitly states that reverse-proxy SSL termination requires trustProxy for extracting SSL status
from X-Forwarded-Proto used by secure cookie auto configuration. Therefore defaulting TRUST_PROXY
to false will break those deployments unless operators override it.

docker-compose.yml[36-41]
src/node/hooks/express.ts[157-165]
src/node/hooks/express.ts[221-238]
doc/docker.md[240-254]

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

## Issue description
`TRUST_PROXY` defaulting to `false` is likely to break common production setups where Etherpad is behind an SSL-terminating reverse proxy and relies on `X-Forwarded-Proto` and related headers.

## Issue Context
- Etherpad only enables Express `trust proxy` when `settings.trustProxy` is true.
- The code explicitly documents that SSL termination requires `trustProxy=true` for cookie `secure: 'auto'` detection via `X-Forwarded-Proto`.

## Fix Focus Areas
- docker-compose.yml[36-38]
- src/node/hooks/express.ts[157-165]
- src/node/hooks/express.ts[221-238]
- doc/docker.md[240-254]

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



Remediation recommended

3. Admin opt-out removed 🐞 Bug ≡ Correctness
Description
Requiring DOCKER_COMPOSE_APP_ADMIN_PASSWORD via ${...:?} removes the documented ability to leave
ADMIN_PASSWORD unspecified to avoid provisioning the admin user. This is a behavioral change for
deployments that intentionally run without a built-in admin account (admin user is only omitted when
the password resolves to null).
Code

docker-compose.yml[R22-24]

+      # Required — set a strong value (e.g. in .env). No fallback, so misconfig
+      # surfaces at `docker compose up` rather than at runtime.
+      ADMIN_PASSWORD: "${DOCKER_COMPOSE_APP_ADMIN_PASSWORD:?Set DOCKER_COMPOSE_APP_ADMIN_PASSWORD to a strong value}"
Evidence
The docs and settings template explicitly support omitting the admin user by leaving its password
null/unset, but the compose file now errors if the operator doesn’t provide
DOCKER_COMPOSE_APP_ADMIN_PASSWORD, removing that documented behavior. The settings loader also shows
that the string "null" is coerced to null, which is relevant if an explicit opt-out is desired.

docker-compose.yml[20-28]
doc/docker.md[108-119]
settings.json.docker[666-672]
src/node/utils/Settings.ts[971-1005]

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 compose change forces `ADMIN_PASSWORD` to be provided, but the container’s documented behavior supports leaving it unset to avoid creating the admin user. This breaks an existing documented deployment mode.

## Issue Context
- Docker docs say leaving `ADMIN_PASSWORD` unspecified means the admin user is not created.
- settings.json.docker notes that a null password prevents user creation.
- Settings env expansion coerces the string `"null"` to JS null, so a safe opt-out could be supported/documented without using weak defaults.

## Fix Focus Areas
- docker-compose.yml[22-24]
- doc/docker.md[108-119]
- settings.json.docker[666-672]
- src/node/utils/Settings.ts[971-1005]

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


Grey Divider

Qodo Logo

@SamTV12345 SamTV12345 merged commit 3e76450 into ether:develop Jun 7, 2026
19 checks passed
@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Review Summary by Qodo

Harden docker-compose defaults with required credentials

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Require explicit ADMIN_PASSWORD and database password configuration
• Default TRUST_PROXY to false for security
• Add inline documentation for credential requirements
• Prevent insecure defaults from being used silently
Diagram
flowchart LR
  A["docker-compose.yml"] -->|Remove insecure defaults| B["ADMIN_PASSWORD required"]
  A -->|Remove insecure defaults| C["DB_PASS required"]
  A -->|Change default| D["TRUST_PROXY false"]
  B -->|Fail fast| E["docker compose up fails without config"]
  C -->|Fail fast| E
  D -->|Reduce IP spoofing risk| F["Enhanced security posture"]

Loading

Grey Divider

File Changes

1. docker-compose.yml Security hardening +8/-4

Enforce explicit credentials and disable proxy trust by default

• Replace ADMIN_PASSWORD default admin with required explicit configuration using bash parameter
 expansion error syntax
• Replace DB_PASS default admin with required explicit configuration using bash parameter
 expansion error syntax
• Replace POSTGRES_PASSWORD default admin with required explicit configuration using bash
 parameter expansion error syntax
• Change TRUST_PROXY default from true to false with explanatory comments
• Add inline documentation clarifying credential requirements and security rationale

docker-compose.yml


Grey Divider

Qodo Logo

Comment thread docker-compose.yml
Comment on lines +22 to +38
# Required — set a strong value (e.g. in .env). No fallback, so misconfig
# surfaces at `docker compose up` rather than at runtime.
ADMIN_PASSWORD: "${DOCKER_COMPOSE_APP_ADMIN_PASSWORD:?Set DOCKER_COMPOSE_APP_ADMIN_PASSWORD to a strong value}"
DB_CHARSET: ${DOCKER_COMPOSE_APP_DB_CHARSET:-utf8mb4}
DB_HOST: postgres
DB_NAME: ${DOCKER_COMPOSE_POSTGRES_DATABASE:-etherpad}
DB_PASS: ${DOCKER_COMPOSE_POSTGRES_PASSWORD:-admin}
DB_PASS: "${DOCKER_COMPOSE_POSTGRES_PASSWORD:?Set DOCKER_COMPOSE_POSTGRES_PASSWORD to a strong value}"
DB_PORT: ${DOCKER_COMPOSE_POSTGRES_PORT:-5432}
DB_TYPE: "postgres"
DB_USER: ${DOCKER_COMPOSE_POSTGRES_USER:-admin}
# For now, the env var DEFAULT_PAD_TEXT cannot be unset or empty; it seems to be mandatory in the latest version of etherpad
DEFAULT_PAD_TEXT: ${DOCKER_COMPOSE_APP_DEFAULT_PAD_TEXT:- }
DISABLE_IP_LOGGING: ${DOCKER_COMPOSE_APP_DISABLE_IP_LOGGING:-false}
SOFFICE: ${DOCKER_COMPOSE_APP_SOFFICE:-null}
TRUST_PROXY: ${DOCKER_COMPOSE_APP_TRUST_PROXY:-true}
# Default off: only enable when actually behind a trusted reverse proxy
# that sets the X-Forwarded-* headers.
TRUST_PROXY: ${DOCKER_COMPOSE_APP_TRUST_PROXY:-false}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Docs mismatch compose 🐞 Bug ⚙ Maintainability

docker-compose.yml now requires DOCKER_COMPOSE_APP_ADMIN_PASSWORD and
DOCKER_COMPOSE_POSTGRES_PASSWORD and defaults TRUST_PROXY to false, but README.md and doc/docker.md
still show admin/admin defaults and TRUST_PROXY defaulting to true. Users copy-pasting the
documented compose snippets will either fail at docker compose up (missing required vars) or
deploy with different behavior than documented.
Agent Prompt
## Issue description
`docker-compose.yml` was hardened (required secrets + TRUST_PROXY default flip), but the repo’s Docker Compose documentation snippets are now stale. This causes immediate breakage for users following docs and undermines the intent of the hardening.

## Issue Context
- The compose file now uses `${VAR:?message}` for `DOCKER_COMPOSE_APP_ADMIN_PASSWORD` and `DOCKER_COMPOSE_POSTGRES_PASSWORD`, so `docker compose up` fails if they’re unset/empty.
- Docs still show `:-admin` fallbacks and `TRUST_PROXY` defaulting to `true`.

## Fix Focus Areas
- docker-compose.yml[20-38]
- README.md[102-157]
- doc/docker.md[335-395]
- .env.default[7-18]

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

Comment thread docker-compose.yml
Comment on lines +36 to +38
# Default off: only enable when actually behind a trusted reverse proxy
# that sets the X-Forwarded-* headers.
TRUST_PROXY: ${DOCKER_COMPOSE_APP_TRUST_PROXY:-false}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Proxy default breaks https 🐞 Bug ≡ Correctness

docker-compose.yml now defaults TRUST_PROXY to false, which prevents Express from trusting
X-Forwarded-* headers and breaks secure-cookie auto detection when Etherpad is behind an
SSL-terminating reverse proxy. This can lead to incorrect HTTPS detection (express-session `secure:
'auto'`), affecting login/session behavior and deployments that require secure cookies.
Agent Prompt
## Issue description
`TRUST_PROXY` defaulting to `false` is likely to break common production setups where Etherpad is behind an SSL-terminating reverse proxy and relies on `X-Forwarded-Proto` and related headers.

## Issue Context
- Etherpad only enables Express `trust proxy` when `settings.trustProxy` is true.
- The code explicitly documents that SSL termination requires `trustProxy=true` for cookie `secure: 'auto'` detection via `X-Forwarded-Proto`.

## Fix Focus Areas
- docker-compose.yml[36-38]
- src/node/hooks/express.ts[157-165]
- src/node/hooks/express.ts[221-238]
- doc/docker.md[240-254]

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

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.

2 participants