I'm trying to put Mercure hub into production in a Symfony project, but without success.
I downloaded Mercure on the releases page and unzipped it in a mercure folder at the root of my Symfony project in /var/www/locfac/public_html/mercure. I've configured everything locally and it works fine. But, in production on my Nginx server, it returns an 400 error.
I manage to start the hub in the terminal, but it's not accessible on the link via the browser and requests never come to it.
The hub link should be https://locfac.com/hub.
I'd appreciate it if someone could help me. Here is my code:
#serveur configuration
server {
server_name locfac.com www.locfac.com;
root /var/www/locfac/public_html/public;
location /hub {
proxy_pass http://localhost:8500;
proxy_read_timeout 24h;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
# try to serve file directly, fallback to index.php
try_files $uri /index.php$is_args$args;
}
# optionally disable falling back to PHP script for the asset directories;
# nginx will return a 404 error when files are not found instead of passing the
# request to Symfony (improves performance but Symfony's 404 page is not displayed)
# location /bundles {
# try_files $uri =404;
# }
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
# optionally set the value of the environment variables used in the application
# fastcgi_param APP_ENV prod;
# fastcgi_param APP_SECRET <app-secret-id>;
# fastcgi_param DATABASE_URL "mysql://db_user:db_pass@host:3306/db_name";
# When you are using symlinks to link the document root to the
# current version of your application, you should pass the real
# application path instead of the path to the symlink to PHP
# FPM.
# Otherwise, PHP's OPcache may not properly detect changes to
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
# for more information).
# Caveat: When PHP-FPM is hosted on a different machine from nginx
# $realpath_root may not resolve as you expect! In this case try using
# $document_root instead.
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/index.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}
# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
# return 404;
}
error_log /var/log/nginx/locfac.log;
access_log /var/log/nginx/locfac.log;
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/locfac.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/locfac.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.locfac.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = locfac.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name locfac.com www.locfac.com;
return 404; # managed by Certbot
}
#Caddyfile
{
{$DEBUG:debug}
https_port 8500
auto_https off
}
{$SERVER_NAME:localhost}
# tls internal
tls /etc/letsencrypt/live/locfac.com/fullchain.pem /etc/letsencrypt/live/locfac.com/privkey.pem
route {
encode zstd gzip
mercure {
# Transport to use (default to Bolt)
transport_url {$MERCURE_TRANSPORT_URL:bolt://mercure.db}
# Publisher JWT key
publisher_jwt "{$MERCURE_PUBLISHER_JWT_KEY}" {$MERCURE_PUBLISHER_JWT_ALG}
# Subscriber JWT key
subscriber_jwt "{$MERCURE_SUBSCRIBER_JWT_KEY}" {$MERCURE_SUBSCRIBER_JWT_ALG}
# Permissive configuration for the development environment
cors_origins *
publish_origins *
ui
anonymous
subscriptions
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
}
header / Content-Type "text/html; charset=utf-8"
respond / `<!DOCTYPE html>
<html lang=en>
<meta charset="utf-8">
<meta name="robots" content="noindex">
<title>Welcome to Mercure</title>
<h1>Welcome to Mercure</h1>
<p>The URL of your hub is <code>/.well-known/mercure</code>.
Read the documentation on <a href="https://mercure.rocks">Mercure.rocks, real-time apps made easy</a>.`
respond /healthz 200
respond "Not Found" 404
}
log {
output file /var/log/mercure/mercure.log {
roll_local_time
roll_keep 7
}
}
I've written a hub start file whose contents are as follows :
#!/bin/bash
SYMFONY_ROOT="/var/www/locfac/public_html"
MERCURE_PATH="$SYMFONY_ROOT/mercure/mercure"
MERCURE_PUBLISHER_JWT_KEY="$(cat $SYMFONY_ROOT/config/jwt/public.pem)" \
MERCURE_PUBLISHER_JWT_ALG="RS256" \
MERCURE_SUBSCRIBER_JWT_KEY="$(cat $SYMFONY_ROOT/config/jwt/public.pem)" \
MERCURE_SUBSCRIBER_JWT_ALG="RS256" \
$MERCURE_PATH run