I've got a webserver running a Laravel (Statamic) website served with nginx. There is a CMS portion of this site that uses local storage to serve up images from the project folder. However, when the browser tries to pull those images, it fails (404 errors) for the assets only.
The request tab in my chrome dev console is showing that the URL for this asset is wrong. When I actually hit my server, the url looks like staging.site.com/staging.site.com/storage/images/image.png. I checked the URL in the HTML itself and it does not match that pattern, instead it looks like staging.site.com/storage/images/image.png (as expected). For some reason that I don't understand, it seems to be doubling the subdomain, domain, and TLD once it hits nginx (I think?).
Stuff I've Checked
- Laravel's symbolic links are set; I've double checked by running
php artisan storage:link, which confirmed it had already been run. The images are on the server, I can see them in the terminal when I SSH in andcdinto the correct folder - If I manually remove the first domain chunk it renders the image, so the image is accessible on the server, it's just setting the URL wrong.
- I checked my nginx and laravel logs on my server and I'm not seeing any error messages in either of them that look even remotely relevant
Extra info
- I used certbot for SSL
- Everything works as-expected in local development environments. The fact that this issue is only present on the server leads me to believe it's an nginx configuration issue
- I don't think this is a ufw issue because I can access the file fine as long as the URL is correct
What in the world is going on here? Why is my domain getting duplicated?
nginx configs
nginx.conf
user username; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; } http { sendfile on; tcp_nopush on; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; gzip on; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; client_max_body_size 50M; } laravel (sites-enabled)
server { # server_name _; server_name staging.site.com; root /var/www/site/public; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; index index.html index.htm index.php; charset utf-8; proxy_busy_buffers_size 512k; proxy_buffers 4 512k; proxy_buffer_size 256k; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/staging.site.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/staging.site.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 = staging.site.com) { return 301 https://$host$request_uri; } # managed by Certbot server_name staging.site.com; listen 80; return 404; # managed by Certbot } 
staging.server.com/foldersinstead of just/folders