Skip to content

fix(docker): expand 0.0.0.0/0 trusted-proxy CIDR for mod_remoteip - #1531

Merged
rumblefrog merged 2 commits into
sbpp:mainfrom
maxijabase:fix/railway-trusted-proxy-cidr
Jul 28, 2026
Merged

fix(docker): expand 0.0.0.0/0 trusted-proxy CIDR for mod_remoteip#1531
rumblefrog merged 2 commits into
sbpp:mainfrom
maxijabase:fix/railway-trusted-proxy-cidr

Conversation

@maxijabase

@maxijabase maxijabase commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Context

Found while deploying the published ghcr.io/sbpp/sourcebans-pp image to Railway, right after the MPM fix in #1530. With that fix applied and SBPP_TRUSTED_PROXIES=0.0.0.0/0 set (the value Railway needs, since its edge proxy IP is not fixed), Apache still refused to start:

AH00526: Syntax error on line 3 of /etc/apache2/conf-enabled/zz-sbpp-trusted-proxy.conf:
RemoteIP: Error parsing IP 0.0.0.0/0 (The specified network mask is invalid. error) for RemoteIPInternalProxy

Same crash loop as before, different cause.

Summary

SBPP_TRUSTED_PROXIES=0.0.0.0/0 is the documented way to say "trust every proxy", needed on platforms like Railway where the edge proxy's IP is not fixed or published. The entrypoint writes this straight into a RemoteIPInternalProxy 0.0.0.0/0 line for mod_remoteip.

mod_remoteip rejects a /0 netmask outright at parse time (apr_ipsubnet_create fails on it), so Apache never starts.

The fix splits 0.0.0.0/0 into the two /1 halves that cover the exact same IP range but that mod_remoteip accepts: 0.0.0.0/1 and 128.0.0.0/1. Same applies to the IPv6 equivalent, ::/0, split into ::/1 and 8000::/1. Same trust-everyone behavior, valid syntax.

Also included: a .gitattributes fix. While testing this locally on Windows with Docker Desktop, docker/php/prod-entrypoint.sh had CRLF line endings on disk from a normal Windows git checkout (core.autocrlf=true). A CRLF shebang line breaks the script at exec time with a confusing "no such file or directory" instead of a parse error. This does not affect the real GHCR image, since CI builds on Linux where the checkout is already LF, but it silently breaks local image builds for any contributor on Windows. Forcing LF on docker/**/*.sh closes that gap for good.

Testing

Tested locally with Docker Desktop (not Podman).

  • Reproduced the exact AH00526 error with a bare apache2ctl configtest against a RemoteIPInternalProxy 0.0.0.0/0 line.
  • Confirmed the 0.0.0.0/1 + 128.0.0.0/1 split passes configtest, same for the IPv6 ::/1 + 8000::/1 split.
  • Rebuilt the full production image, started a real MariaDB container, and booted the web container end to end with SBPP_TRUSTED_PROXIES=0.0.0.0/0: schema installed, updater migrations ran to the latest version, Apache started with no errors, container reported healthy, health.php returned 200, login page returned 200.

RemoteIPInternalProxy 0.0.0.0/0 (the natural way to spell 'trust every proxy' on a platform like Railway where the edge proxy IP isn't fixed) fails Apache's config parser with 'The specified network mask is invalid', because mod_remoteip's apr_ipsubnet_create() rejects a /0 mask outright. Apache then refuses to start and the container crash-loops forever.

Split 0.0.0.0/0 (and the IPv6 equivalent ::/0) into the two /1 halves that cover the identical IP range but that mod_remoteip does accept: 0.0.0.0/1 + 128.0.0.0/1, or ::/1 + 8000::/1. Same trust-everyone semantics, valid syntax.

Reproduced the exact AH00526 error with apache2ctl configtest, confirmed the /1+/1 split passes configtest for both address families, then rebuilt the full prod image and booted it end to end against a real MariaDB container with SBPP_TRUSTED_PROXIES=0.0.0.0/0: schema installed, migrations ran, Apache started, container reported healthy, health.php returned 200.
docker/php/prod-entrypoint.sh had CRLF line endings on disk (a Windows git checkout artifact from core.autocrlf=true). A CRLF shebang line breaks the interpreter lookup at exec time (#!/bin/sh followed by a stray \\r makes the kernel look for a nonexistent /bin/sh\\r), which surfaces as a confusing 'exec: no such file or directory' instead of a parse error.

This does not affect the published GHCR image, since CI builds on Linux where the checkout is already LF, but it silently breaks local Docker/Podman builds for any contributor on Windows. Force LF on docker/**/*.sh so Docker COPY always reads a working script regardless of the host OS or git config.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@maxijabase maxijabase left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Self-review completed against the full PR diff and surrounding production-Docker configuration.

The implementation is functionally sound:

  • 0.0.0.0/1 plus 128.0.0.0/1 exactly covers IPv4 /0.
  • ::/1 plus 8000::/1 exactly covers IPv6 /0.
  • Other space-separated proxy entries retain the existing pass-through behavior.
  • docker/**/*.sh text eol=lf is the correct Git attribute for Linux-executed Docker scripts.
  • No whitespace errors were found in the diff.

One item should be addressed before merge. docs/src/content/docs/getting-started/quickstart-docker.mdx still says, “The entrypoint passes the value through verbatim” in its RemoteIPInternalProxy troubleshooting row. That statement becomes false for the two /0 aliases. This PR also changes an operator-visible production Docker behavior, so the repository rules require the matching Docker quickstart documentation to change in the same PR. The docs should explain that 0.0.0.0/0 and ::/0 are expanded into Apache-compatible /1 pairs. It should also warn that trusting all proxies is safe only when direct access to the container is blocked.

I found no code-level correctness defect in the expansion itself. The existing successful E2E check and the documented full production-image boot test support the implementation. GitHub does not allow an author to approve their own PR, so this is submitted as a commented self-review.

@maxijabase

Copy link
Copy Markdown
Contributor Author

Self-review completed against the full PR diff and surrounding production-Docker configuration.

The implementation is functionally sound:

  • 0.0.0.0/1 plus 128.0.0.0/1 exactly covers IPv4 /0.
  • ::/1 plus 8000::/1 exactly covers IPv6 /0.
  • Other space-separated proxy entries retain the existing pass-through behavior.
  • docker/**/*.sh text eol=lf is the correct Git attribute for Linux-executed Docker scripts.
  • No whitespace errors were found in the diff.

One item should be addressed before merge. docs/src/content/docs/getting-started/quickstart-docker.mdx still says, “The entrypoint passes the value through verbatim” in its RemoteIPInternalProxy troubleshooting row. That statement becomes false for the two /0 aliases. This PR also changes an operator-visible production Docker behavior, so the repository rules require the matching Docker quickstart documentation to change in the same PR. The docs should explain that 0.0.0.0/0 and ::/0 are expanded into Apache-compatible /1 pairs. It should also warn that trusting all proxies is safe only when direct access to the container is blocked.

I found no code-level correctness defect in the expansion itself. The existing successful E2E check and the documented full production-image boot test support the implementation. GitHub does not allow an author to approve their own PR, so this is submitted as a commented self-review.

When you're locally reviewing your own changes and it decides to randomly post the findings in the PR...

@Rushaway
Rushaway requested a review from rumblefrog July 28, 2026 13:57
@rumblefrog
rumblefrog added this pull request to the merge queue Jul 28, 2026
Merged via the queue into sbpp:main with commit 57f6c12 Jul 28, 2026
1 check passed
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.

3 participants