refactor(web-app-shopware): externalize trusted proxy and host configuration with mounted framework.yaml

- added new file roles/web-app-shopware/files/framework.yaml defining trusted_proxies and trusted_headers for Symfony
 - mounted framework.yaml into /var/www/html/config/packages/ in docker-compose
 - exposed new role vars SHOPWARE_FRAMEWORK_HOST/DOCKER for mounting path
 - rendered framework.yaml via Ansible copy task with proper permissions
 - adjusted env.j2 to set TRUSTED_PROXIES and TRUSTED_HOSTS dynamically from domains and networks
 - added SHOPWARE_DOMAIN var to vars/main.yml
 - removed inline framework.yaml creation from Dockerfile (now managed via mount)
 - updated proxy template (html.conf.j2) to include X-Forwarded-Ssl header
 - improved init.sh permission handling for shared volumes

See ChatGPT conversation for implementation details and rationale:
https://chatgpt.com/share/690d4fe7-2830-800f-8b6d-b868e7fe0e97
This commit is contained in:
2025-11-07 02:48:49 +01:00
parent 2fcbae8fc7
commit 493d5bbbda
8 changed files with 34 additions and 11 deletions

View File

@@ -15,6 +15,7 @@ location {{location}}
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port {{ WEB_PORT }};
proxy_set_header X-Forwarded-Ssl on;
proxy_pass_request_headers on;
{% include 'roles/sys-svc-proxy/templates/headers/content_security_policy.conf.j2' %}

View File

@@ -0,0 +1,7 @@
framework:
trusted_proxies: '%env(TRUSTED_PROXIES)%'
trusted_headers:
- x-forwarded-for
- x-forwarded-proto
- x-forwarded-host
- x-forwarded-port

View File

@@ -29,8 +29,14 @@ if [ "$(id -u)" -eq 0 ]; then
"$APP_ROOT/var"
log "Fixing permissions on shared volumes..."
chown -R www-data:www-data "$APP_ROOT/public" "$APP_ROOT/var" || true
chmod -R 775 "$APP_ROOT/public" "$APP_ROOT/var" || true
chown -R www-data:www-data \
"$APP_ROOT/public" \
"$APP_ROOT/var" \
"$APP_ROOT/.infinito" || true
chmod -R 775 \
"$APP_ROOT/public" \
"$APP_ROOT/var" \
"$APP_ROOT/.infinito" || true
# Switch to www-data for all subsequent operations
exec su -s /bin/sh www-data "$0" "$@"

View File

@@ -14,6 +14,14 @@
- docker compose up
- docker compose build
- name: "Render framework.yaml (trusted proxies/headers/hosts)"
copy:
src: "framework.yaml"
dest: "{{ SHOPWARE_FRAMEWORK_HOST }}"
mode: "0644"
notify:
- docker compose up
- name: "Flush docker compose handlers"
meta: flush_handlers

View File

@@ -76,12 +76,5 @@ RUN set -eux; \
/var/www/html/public/theme; \
chown -R www-data:www-data /var/www/html
# Add trusted proxies wiring (Symfony reads env TRUSTED_PROXIES)
RUN set -eux; \
mkdir -p /var/www/html/config/packages; \
if [ ! -f /var/www/html/config/packages/framework.yaml ]; then \
printf "framework:\n trusted_proxies: '%%env(TRUSTED_PROXIES)%%'\n" > /var/www/html/config/packages/framework.yaml; \
fi
# Drop back to the app user
USER www-data

View File

@@ -8,6 +8,7 @@ x-environment: &shopware
- sitemap:/var/www/html/public/sitemap
- "{{ SHOPWARE_INIT_HOST }}:{{ SHOPWARE_INIT_DOCKER }}:ro"
- bundles:/var/www/html/public/bundles
- "{{ SHOPWARE_FRAMEWORK_HOST }}:{{ SHOPWARE_FRAMEWORK_DOCKER }}:ro"
working_dir: {{ SHOPWARE_ROOT }}
{% include 'roles/docker-compose/templates/base.yml.j2' %}

View File

@@ -1,13 +1,16 @@
# DOMAIN/URL
DOMAIN={{ domains | get_domain(application_id) }}
DOMAIN={{ SHOPWARE_DOMAIN }}
APP_URL="{{ domains | get_url(application_id, WEB_PROTOCOL) }}"
APP_DEBUG="{{ MODE_DEBUG | ternary(1, 0) }}"
# Shopware
APP_ENV={{ 'dev' if (ENVIRONMENT | lower) == 'development' else 'prod' }}
TRUSTED_PROXIES=*
INSTANCE_ID={{ application_id }}
# Proxy
TRUSTED_PROXIES="{{ networks.internet.values() | select | join(',') }},127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
TRUSTED_HOSTS="{{ SHOPWARE_DOMAIN }}"
# Database
DATABASE_URL="mysql://{{ database_username }}:{{ database_password }}@{{ database_host }}:{{ database_port }}/{{ database_name }}"

View File

@@ -7,6 +7,8 @@ entity_name: "{{ application_id | get_entity_name }}"
container_port: "{{ applications | get_app_conf(application_id, 'docker.services.web.port') }}"
docker_compose_flush_handlers: true
SHOPWARE_DOMAIN: "{{ domains | get_domain(application_id) }}"
# Shopware container/image vars
SHOPWARE_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.shopware.version') }}"
SHOPWARE_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.shopware.image') }}"
@@ -22,6 +24,8 @@ SHOPWARE_WORKER_CONTAINER: "{{ applications | get_app_conf(application_id,
SHOPWARE_SCHED_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.scheduler.name') }}"
SHOPWARE_INIT_HOST: "{{ [ docker_compose.directories.volumes, 'init.sh' ] | path_join }}"
SHOPWARE_INIT_DOCKER: "/usr/local/bin/init.sh"
SHOPWARE_FRAMEWORK_HOST: "{{ [ docker_compose.directories.config, 'framework.yaml' ] | path_join }}"
SHOPWARE_FRAMEWORK_DOCKER: "/var/www/html/config/packages/framework.yaml"
# Entrypoints & replicas
SHOPWARE_WORKER_ENTRYPOINT: "{{ applications | get_app_conf(application_id, 'docker.services.worker.entrypoint') }}"