That’s interesting… I’m not familiar with that setup, so I checked with chatgpt and got this back:
Short Version
It’s (almost certainly) not s2Member itself. It’s an HTTP/3 + Nginx → PHP-FPM issue where some server variables aren’t passed correctly. This makes WordPress mis-detect the canonical URL and/or HTTPS status, causing a 301/302 redirect loop—and since s2Member’s protected content triggers redirects sooner, you see it there first.
What’s Actually Going Wrong
When you enable HTTP/3 (QUIC), Nginx can handle the :authority
and scheme differently. On some setups it won’t pass the right values for:
HTTP_HOST
SERVER_NAME
SERVER_PORT
HTTPS
to PHP-FPM unless you explicitly set them.
If those are wrong or missing, WordPress:
- Builds canonical URLs with the wrong host/scheme → endless redirect loop.
- Thinks the request is
http
(not https
) → forces an SSL redirect forever.
- Sets/reads cookies for the wrong domain → s2Member thinks you’re logged out.
The Fix (Do All of These)
In your PHP location/block that includes fastcgi_params
, make these explicit:
# inside location ~ \.php$ { ... } or your php include
include fastcgi_params;
# The critical ones for HTTP/3 + PHP-FPM + WordPress
fastcgi_param HTTP_HOST $host; # or $host:$server_port for non-standard ports
fastcgi_param SERVER_NAME $host;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param REQUEST_SCHEME $scheme;
# Ensure WP knows it’s HTTPS
fastcgi_param HTTPS on; # or: fastcgi_param HTTPS $https;
# (optional, but helps in some stacks)
fastcgi_param HTTP_X_FORWARDED_PROTO $scheme;
Notes:
How to Verify Quickly
-
Create phpinfo.php
and load it over HTTP/3:
curl --http3 -I https://example.com/phpinfo.php
Check that:
-
$_SERVER['HTTP_HOST']
= your domain (and port if needed)
-
$_SERVER['HTTPS']
= on
-
$_SERVER['SERVER_PORT']
= 443
-
Check Nginx logs for a host/scheme “ping-pong” in redirect chains (http
https
, www
non-www
).
Why s2Member Shows It First
Protected content triggers redirects earlier—s2Member defers to WP’s auth and canonical checks, so if WP is confused about the host or scheme, it loops instantly on protected URLs.
If It Still Loops After Fix
-
Force server vars in WP (for testing):
add_action('muplugins_loaded', function () {
$_SERVER['HTTPS'] = 'on';
$_SERVER['SERVER_PORT'] = '443';
if (empty($_SERVER['HTTP_HOST'])) {
$_SERVER['HTTP_HOST'] = parse_url(get_option('home'), PHP_URL_HOST);
}
});
-
Disable canonical redirects temporarily:
add_filter('redirect_canonical', '__return_false');
If loop disappears, the cause is definitely server vars.
-
Check cookies: Ensure domain matches and Secure
is set.
Unorthodox but Pragmatic Options
Bottom Line
Explicitly set your FastCGI params for HTTP/3:
fastcgi_param HTTP_HOST $host;
fastcgi_param SERVER_NAME $host;
fastcgi_param SERVER_PORT 443; # or $server_port if needed
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS on;
Once WordPress sees the correct host and HTTPS status, the s2Member 302 loop disappears.
Does that help?
