nginxsafariraspberry-pisingle-page-applicationself-hosting

Why won't Safari and other WebKit-based browsers load site being served from Raspberry Pi 4 running NGINX?


I have a Raspberry Pi 4B running Raspberry Pi OS Lite/Debian 11 (64 bit version) with NGINX version 1.18.0 installed. NGINX is serving a small (~400KB) website, and I have my router set up to forward HTTP requests to the Raspberry Pi. From my local network, the site works just fine in all the browsers I've tried: Chrome, Edge, Safari, and iOS browsers.

However, Safari and iOS browsers fail to load the whole site when I try to visit it through the internet. In other words, there are no issues navigating to the site in Safari or on iOS using the local IP address for the Raspberry Pi, but when I navigate to the site using the site's domain name or the router's public IP address, the site only loads partially, and the rest times out. The site loads fine in Chrome and Edge, both locally and on the internet.

I understand Safari and all iOS browsers are based on WebKit and that Chrome and Edge use a different engine, and I have some sense that that might be a part of the issue, but I have no idea how to go about fixing it. I'm an amateur and pretty new to web development. My goal is to self-host a website from the Raspberry Pi and make it available to the internet, preferably via Safari as well as Chrome.

I've looked around on Stack Overflow and other forums for similar posts and didn't find any resolutions; apologies if I missed one and this is a redundant post though. I'd appreciate any insights or references! The site uses some fairly straightforward JavaScript for routing between views, and like I said, Safari renders it without any problems locally, so I don't think it's an issue with the site's resources. Maybe something to do with NGINX? Anyway, let me know if I should provide any configuration details or anything like that. Thanks!


Solution

  • For other noobs seeing this: enabling http/2 in the NGINX virtual host config seems to have worked. See here for a short guide how to do that. Again, the server setup is Raspberry Pi OS Lite/Debian 11 (64 bit) with NGINX v1.18.0 installed, so not sure if this applies to more recent versions of NGINX. Here's my NGINX virtual host config from the sites-available directory:

    server {
            root /var/www/{PATH_TO_SITE_DIST};
            index index.html;
            server_name {SERVER_NAME};
    
            location / {
                try_files $uri $uri/ /;
            }
    
            listen [::]:443 ssl http2 ipv6only=on; # managed by Certbot
            listen 443 ssl http2; # managed by Certbot
            ssl_certificate /etc/letsencrypt/live/{PATH_TO_SSL_CERT}/fullchain.pem; # managed by Certbot
            ssl_certificate_key /etc/letsencrypt/live/{PATH_TO_SSL_KEY}/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
    
            add_header Cache-Control "public, max-age=604800";
            add_header Strict-Transport-Security "max-age=604800; includeSubDomains" always;
            add_header Content-Security-Policy "default-src 'self' https://cdn.jsdelivr.net/";      
            add_header X-Content-Type-Options "nosniff" always;
            add_header X-Frame-Options SAMEORIGIN always;
            add_header X-XSS-Protection "1; mode=block" always;
    }
    
    server {
            if ($host = {SERVER_NAME}) {
                return 301 https://$host$request_uri;
            } # managed by Certbot
    
            listen 80 default_server;
            listen [::]:80 default_server;
    
            server_name {SERVER_NAME};
            return 404; # managed by Certbot
    }
    

    The configuration includes HTTPS/SSL managed by Certbot, and sets several response headers, but the part that's most relevant to http/2 is the http2 keyword following the two listen directives on port 443. Once I added those keywords, the server started using http/2, and the site now seems to work fine in Safari 15.2 and WebKit-based iOS browsers. Hope this is helpful to someone!