Mercure Setup
Direct Edit needs a running Mercure hub. This page covers running the hub itself: the Docker image, the reverse proxy, and the questions that come up around both.
Pimcore Studio also uses Mercure, and the Studio Backend bundle documents how Pimcore connects to it. Follow Studio Backend Mercure Setup for the Pimcore-side configuration, then use this page for the hub.
Direct Edit additionally requires the JWT key parameters described in Installation & Configuration.
Start and Configure Mercure
Run an up-to-date Mercure instance, for example the official Docker container. See the Mercure docs for the installation details.
Configure JWT Key(s)
Mercure needs JWT keys to sign and verify the tokens used for authentication. Use one key for both roles (jwt_key),
or separate keys for publisher (publisher_jwt_key) and subscriber (subscriber_jwt_key).
parameters:
mercure:
hub:
jwt_key: 'YOUR_JWT_KEY_FOR_PUBLISHER_AND_SUBSCRIBER'
#publisher_jwt_key: 'YOUR_JWT_KEY_FOR_PUBLISHER'
#subscriber_jwt_key: 'YOUR_JWT_KEY_FOR_SUBSCRIBER'
Configure Mercure URLs (optional)
Configure the URLs for accessing Mercure server-side (for updating state information within application services) and client-side (for receiving updates in Pimcore Studio) through the Symfony configuration tree:
pimcore_direct_edit:
mercure_settings:
# URL of mercure accessible for client. If not set, default will be set to 'http(s)://<PIMCORE_HOST>/hub/.well-known/mercure'. It is possible to use '<PIMCORE_SCHEMA_HOST>' as placeholder for current schema and host.
client_side_url: null
# URL of mercure accessible for server. If not set, default will be set to 'http(s)://<PIMCORE_HOST>/hub/.well-known/mercure'.
server_side_url: null
Configure the full URL including protocol, port and path. client_side_url also accepts <PIMCORE_SCHEMA_HOST> as a
placeholder for the current scheme and host of the client. Left unset, both URLs are derived from the Pimcore host and
the default paths.
JWT Cookie Configuration
To let the JWT cookie cover subdomains as well, set its host and strictness.
pimcore_direct_edit:
mercure_settings:
client_side_url: 'mercure.app.main.domain/hub/.well-known/mercure'
server_side_url: 'mercure.app.main.domain/.well-known/mercure'
jwt_cookie_host: 'app.main.domain' # It can also be a main.domain
jwt_cookie_strictness: false
Example Configuration with docker compose
The snippets below set up Mercure with docker compose. Mercure is exposed only through an nginx reverse proxy running over HTTPS; internal communication runs over HTTP, which helps when working with self-signed certificates in development.
docker-compose.yaml
Add mercure to your docker compose file and make sure to add the configuration for JWT keys.
# add here all the other necessary containers...
# configure nginx to run under https
nginx:
image: nginx:stable-alpine
ports:
- 443:443
depends_on:
- php-fpm
volumes:
- ./demo-px-enterprise:/var/www/html:ro
# mount nginx configuration to be adapted (see below)
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
# certificates for running nginx (for direct edit to work, system has to run with https)
- ~/.certs:/etc/nginx/certs
mercure:
image: dunglas/mercure
restart: unless-stopped
environment:
# Disable HTTPS
SERVER_NAME: ':80'
# Add JWT keys configured
MERCURE_PUBLISHER_JWT_KEY: '<YOUR_JWT_KEY>'
MERCURE_SUBSCRIBER_JWT_KEY: '<YOUR_JWT_KEY>'
nginx.conf
Configure reverse proxy in nginx to route mercure traffic accordingly.
server {
# (...)
location /hub {
proxy_pass http://mercure/.well-known/mercure;
}
# Thumbnails
# (...)
}
config.yaml
Configure Pimcore application with JWT key as well as the client side and server side URLs for mercure.
parameters:
mercure:
hub:
jwt_key: '<YOUR_JWT_KEY>'
pimcore_direct_edit:
mercure_settings:
# URL of mercure accessible for client.
client_side_url: <PIMCORE_SCHEMA_HOST>/hub
# URL of mercure accessible for server.
server_side_url: http://mercure/.well-known/mercure
Check if Mercure is running
Call https://your-app-domain.com/hub/.well-known/mercure (or the client_side_url you configured). The response has
to be:
Missing "topic" parameter.
Run the same request from the server's command line against server_side_url, to confirm the hub is reachable by
Pimcore itself:
curl https://your-app-domain.com/hub/.well-known/mercure
Additional Aspects
Running Mercure with external URL
When running Mercure as external service with external URL, make sure to configure CSP properly.
Pimcore Configuration
pimcore_studio_ui:
csp_header:
additional_urls:
connect-src:
- 'https://<MERCURE_URL>/.well-known/mercure'
Mercure Configuration
Sample based on docker compose, important part is the cors_origins directive.
mercure:
image: dunglas/mercure
restart: unless-stopped
environment:
# All other necessary configs ...
# ...
# Add cors configuration
MERCURE_EXTRA_DIRECTIVES: |-
cors_origins "https://<YOUR_PIMCORE_URL>"
Webserver Reverse Proxy
With the Mercure default URLs, a reverse proxy routes the Mercure requests to the Mercure instance. Communication has to run over HTTPS, so place the Mercure server behind the reverse proxy of the web server that handles the certificates.
Apache Reverse Proxy
Enable http_proxy in Apache and add this reverse proxy to the Apache config:
ProxyPass /hub/ http://mercure/.well-known/mercure
ProxyPassReverse /hub/ http://mercure/.well-known/mercure
Nginx Reverse Proxy
For Nginx:
location /hub {
proxy_pass http://mercure/.well-known/mercure;
}
Legacy Fallback
The bundle ships the Mercure binary for backwards compatibility only. It is untested, may no longer work, and may contain security vulnerabilities. Do not use it in production.
The bundle ships a Mercure executable as a fallback. Run it with:
./vendor/pimcore/direct-edit/bin/mercure --jwt-key=your-256-bit-secret-min-32-chars --addr=':3000' --debug --allow-anonymous --cors-allowed-origins='*' -f --debug
The hub has to stay up permanently. This crontab entry restarts it if it died:
*/5 * * * * /usr/bin/flock -n /tmp/mercure.lockfile /<system-path>/mercure --jwt-key=your-256-bit-secret --addr=':3000' --debug --allow-anonymous --cors-allowed-origins='*' -f