Skip to content

Feature/docker beta - #477

Draft
Neophytis wants to merge 32 commits into
masterfrom
feature/docker-beta
Draft

Feature/docker beta#477
Neophytis wants to merge 32 commits into
masterfrom
feature/docker-beta

Conversation

@Neophytis

@Neophytis Neophytis commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

This is WIP please ignore and do not merge to master

…e preload, config split; fix mailer Reply-To

- Production PHP-FPM/Nginx Docker image with Manticore 6.3.8 and geonames column fix
- Enable OPcache preload for Symfony prod container
- Split prod-only framework settings into config/packages/prod/framework.yaml
- Remove freemail Reply-To header to prevent rspamd SPOOF_REPLYTO false positives
The Twig Extension reads ../VERSION (relative to PHP CWD /srv/bewelcome)
to populate the footer revision link. The build workflow already passes
APP_VERSION and APP_VERSION_TIMESTAMP as build args but the Dockerfile
never declared or used them, so the footer always showed an empty revision.

Write the short SHA to /srv/VERSION and touch its mtime to the commit
timestamp so the footer displays both the commit link and the build date.
The relative path 'build/entrypoints.json' resolves to
/srv/bewelcome/build/entrypoints.json (the PHP templates dir),
not /srv/bewelcome/public/build/entrypoints.json (webpack output).
When EntrypointLookup can't find the file it silently returns empty,
so getCssFiles/getJavaScriptFiles emit no tags — causing old-MVC pages
(profile, forum, etc.) to render completely without CSS or JS.
CVE-2026-54164 is fixed in api-platform/core v4.1.30, v4.2.26, v4.3.12.
Upgrading from v2 is a breaking change requiring a full code migration.
Ignored alongside the existing v2.x CVEs (CVE-2025-31481, -31485, -26-49858).
Traefik terminates TLS and forwards requests to nginx as HTTP. Without
these two changes Symfony sees http:// as the scheme and generates http://
base URLs for all absolute URLs (redirects, forms, assets).

- nginx: add fastcgi_param HTTP_X_FORWARDED_PROTO so the header Traefik
  sets reaches PHP-FPM (the default fastcgi_params file does not include it)
- .env: change TRUSTED_PROXIES from 127.0.0.1 to REMOTE_ADDR so Symfony
  trusts the immediate upstream (nginx container) and reads the forwarded
  scheme correctly
api-platform is not used — no API endpoints are exposed. Keeping it meant
adding a new .trivyignore entry for every new CVE in the v2.x branch
(4 entries accumulated; v2 receives no security backports).

Removes:
- api-platform/core from composer.json + composer.lock
- config/packages/api_platform.yaml
- src/ApiPlatform/ (JWTAuthorizationDecorator, MemberExtension)
- src/Serializer/MemberContextBuilder (implements api-platform interface)
- services.yaml decorator entries for both classes
- all 4 api-platform CVE ignores from .trivyignore
…ayload

The merge-nginx job only tagged the Nginx manifest as docker-beta-web (no
SHA-based tag), making it impossible to deploy PHP and Nginx as a
deterministically-paired build. Add sha-xxx-web tag so both images share
the same commit identifier.

Also add web_image to the rox-beta-image-pushed repository_dispatch payload
so the sysadmins-infra deploy workflow can pull the matching Nginx image.
The previous removal of api-platform/core (composer.json + core classes)
missed three files that still referenced the bundle:
- config/bundles.php: ApiPlatformBundle registration (crashes kernel on boot)
- config/routes/api_platform.yaml: route type api_platform (no-op without bundle)
- src/Entity/Member.php: @ApiResource, @ApiProperty, @APIFilter annotations

These leftovers cause a PHP fatal on every container start, making the
beta deploy fail immediately with exit 255.


AddressNormalizer and MemberNormalizer were introduced in da0714c
(Install API Platform) and depend on ContextAwareNormalizerInterface /
NormalizerAwareTrait from symfony/serializer. After api-platform/core was
removed in 3dd46fc, these files were accidentally left in src/. The DI
container scans all of src/Serializer/ as services and tries to load the
trait/interface via the classmap-authoritative autoloader; since
symfony/serializer has no hard requirer after the api-platform removal
its classes are absent from the classmap, causing a fatal ReflectionException
on every container compile.

Also removes the dead `use SerializerInterface` import from SearchController
(the controller only calls PHP's native serialize()/unserialize(), not
Symfony's Serializer component).
symfony/serializer has no hard requirer after api-platform/core was
removed. With classmap-authoritative autoloading the serializer's annotation
class can't be found at runtime, causing Doctrine's annotation reader to throw
a AnnotationException on every container compile:

  [Semantical Error] The annotation "@symfony\Component\Serializer\Annotation
  \Groups" in property App\Entity\Member::$username was never imported.

The Symfony Serializer component is disabled in config/packages/framework.yaml
(serializer: line is commented out), so these @groups annotations have been
dead code since api-platform was removed. Remove the annotations and use
statements from all affected entities.
The default alpine PHP-FPM image ships with pm.max_children=5, which is
completely inadequate for a 500K+ member site. With ~104 MB RSS per worker
on a 16 GB host, 25 workers costs ~2.6 GB — well within budget.

New pool config (z-workers.conf):
  pm = dynamic
  pm.max_children = 25
  pm.start_servers = 5
  pm.min_spare_servers = 3
  pm.max_spare_servers = 10
  pm.max_requests = 500
…ation dep

- ManticoreIndicesGeonamesCommand: g.geonameid → g.geoname_id (column
  was renamed in preflight Fix 2; the old name caused Unknown column errors)
- ManticoreIndicesForumCommand: replace forum_trads JOIN with fp.message
  directly — forum_trads was removed from bewelcome_fixed; post content
  now lives in forums_posts.message
- composer.json: declare willdurand/negotiation ^3.1 as a direct dep so
  composer dump-autoload includes it in autoload_psr4.php (was a transitive
  dep that Symfony Flex excluded from the classmap)
Webpack build files carry content-hash suffixes — safe to cache for 1 year
with Cache-Control: immutable. Without compression, CSS files were 300+ KB
raw; gzip cuts that to ~60 KB. Missing cache headers forced every page reload
to re-download all assets.
…ptyAvatar check

emptyAvatar() looks for empty_avatar_<N>_<N>.png but createEmptyAvatarImage() was
saving without the extension, causing an infinite NotWritableException retry loop
on every request for members without an avatar.
Legacy PHP setBaseUri() checks $_SERVER['HTTPS'] which nginx does not set
by default. Without it the base URI renders as http://, causing relative
script paths to load over HTTP (mixed content, blocked by browsers).

All beta traffic terminates TLS at Traefik; nginx always receives the
request over HTTP internally. Setting fastcgi_param HTTPS on; unconditionally
is safe for this stack.
@thisismeonmounteverest

Copy link
Copy Markdown
Contributor

Running docker-compose up -d to build a dev environment doesn't expose any port on the nginx image.

…ke test

- fixtures/members.yml: fix member_suspended username to match auth.feature
  expectation (member-taken-out); add member_host (Accommodation: anytime)
  and member_guest fixtures for upcoming hosting-request Behat scenarios
- behat.yml.dist: add docker profile (base_url: http://web, mailer: http://mailer:1080)
  for running Behat inside the Docker Compose network
- tests/Model/PasswordResetTest.php: unit tests for PasswordModel — token
  generation (64-char hex, unique per call, clears existing tokens),
  removePasswordResetTokens, getPasswordHash
- .github/workflows/build-image-beta.yml: add smoke-test job that pulls the
  amd64 PHP+Nginx images by digest after build, starts the full stack, and
  checks GET /login → 200 before the multi-arch manifest is pushed to GHCR;
  merge-php now depends on smoke-test so a broken image never reaches the registry
Fresh CI DB has no base schema; migrations fail trying to create views
against non-existent legacy tables. SKIP_DOCTRINE_MIGRATIONS=1 is set
in the smoke compose env and guarded in the entrypoint so the PHP
container reaches healthy without a pre-seeded DB.
cache:clear during post-install-cmd warmup queries bewelcome.words,
which also doesn't exist on a blank CI DB. Guard both the migration
and the warmup under SKIP_DOCTRINE_MIGRATIONS so the smoke test can
reach healthy using the build-time cache.
Smoke test requires cache:warmup which queries the translations DB on a
blank CI database.  K6 will cover this once the platform is stable.
Remove the smoke-test job and the SKIP_DOCTRINE_MIGRATIONS entrypoint
guards that were added solely to work around the blank-DB failure.
…ilises

Remove PasswordResetTest.php, behat.yml.dist docker profile, and
member_host/member_guest fixtures added by PR 480.  The DB schema is
still in flux so DB-dependent tests would break constantly; K6 will
cover integration testing once the stack is stable.
Keeps the member-taken-out username fix (required for existing auth.feature).
@Neophytis

Copy link
Copy Markdown
Contributor Author

Running docker-compose up -d to build a dev environment doesn't expose any port on the nginx image.

please use branch neophytis/docker-infra-only and make all the modifications you want. This branch is for my testing purposes

Both showOnlyPostsInMyGroups and showPostsInAllGroups redirect to the
Referer after toggling a preference. When called without a Referer header
(direct link, API client) the header is null and redirect() throws a
TypeError. Fall back to the forums list route instead.
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