Wagtail admin preview panel not working in production
The page preview in the Wagtail admin is working fine locally on my dev server, but in production, the preview is not displayed, just a spinning wheel. In the Chrome dev tools console, I see the error message:
Uncaught SecurityError: Failed to read a named property 'scroll' from 'Window': Blocked a frame with origin "https://example.com" from accessing a cross-origin frame.
where I replaced my actual domain by "example.com".
In production, I'm using Wagtail 6 with nginx and gunicorn, serving media and static files from the same server.
Here are the relevant parts of my nginx config, with some data XXXXed out:
upstream app_server {
server unix:/opt/example-com/gunicorn.socket fail_timeout=0;
}
server {
listen 80;
server_name example.com;
rewrite ^/(.*) https://example.com/$1 permanent;
}
server {
listen 443 ssl;
server_name example.com;
client_max_body_size 50M;
ssl_certificate XXXX
ssl_certificate_key XXXX
location /static/ {
alias /opt/example-com/static/;
}
location /media/ {
alias /opt/example-com/media/;
}
location / {
include proxy_params;
proxy_pass http://unix:/opt/example-com/gunicorn.socket;
}
location /admin/ {
include proxy_params;
proxy_pass http://unix:/opt/example-com/gunicorn.socket;
}
}
In the base settings, I have set
WAGTAILADMIN_BASE_URL = "https://example.com"
and on /admin/sites/, the have set the site hostname to "example.com".
I'm not sure why I'm running into this cross-site thing at all, and how to fix it.
I'm facing the same problem. As the preview panel is loaded inside an iframe, it can be "solved" by setting your X-Frame-Options.
Solution:
In your settings.py OR base.py, add the following:
X_FRAME_OPTIONS = "SAMEORIGIN"
References:
https://docs.djangoproject.com/en/5.1/ref/clickjacking/
Considerations:
Caution!!. Doing this can reduce your site security against clickjacking attacks.
I would be less concerned if we could manage this with frame-ancestors instead of x_frame_options.
It also would be great if Wagtail devs add a way to configure this using django xframe decorators.