Serving static website in nginx, wrong path for static files - nginx

I'm trying to use nginx to serve a static website that was given to me. Its folder structure is like this:
static_website/
index.html
www.example.com/
resources.example.com/
uploads.example.com/
The index.html file in the root is the one generated by httrack and it simply contains a redirect to www.example.com/index.html.
Inside the folder www.example.com are all the html files, in the other two folders are the css, javascript and image files.
Here is the nginx configuration:
server {
index index.php index.html index.htm;
server_name example.com;
location / {
root /var/www/static_website/www.example.com;
try_files $uri $uri/ =404;
index index.html;
}
}
I can navigate through the pages, but the css, javascript and image files are not loaded.
The path to one of the css files inside the html is like this:
href="../resources.example.com/style.css"
The only way I managed to get this working was to have the have the url like this:
example.com/www.example.com/
This way, all the path are correct. I'd like to avoid this and have simply example.com.
Is there a way to do this?

It looks like the site was originally intended to operate with ugly URLs like //example.com/www.example.com/.
But the path-relative URIs for the resources should work just fine relative to /, you just need to provide a location block which matches /resources.example.com/.
For example:
location / {
root /var/www/static_website/www.example.com;
try_files $uri $uri/ =404;
index index.html;
}
location /resources.example.com/ {
root /var/www/static_website;
}
I originally commented that you should try this:
location ~ \.(css|js|jpg|png|svg)$ {
root /var/www/static_website;
}
Which achieves a similar goal, but Nginx will process prefix locations more efficiently that regular expression locations.

I want to share my experience with this problem for others encountering similar issues as the solution was not so obvious to me
My setup and problem in particular had to do with cloudlflare settings which i was using to leverage TLS instead of handling it on the origin server for one of my 2 sites. if you are serving your site from a CDN that supports encryption and you use nginx on your origin consider the following setup:
# static1.conf
{ server_name static1.com; root: /var/www/static1/public; listen 80; listen 443; }
# static2.conf - no tls setup in nginx, figured id let cloudflare handle it
{ server_name static2.com; root: /var/www/static2/public; listen 80; }
static1 was setup at the origin with letsencrypt to handle tls connections
static2 was setup at the origin without any tls configuration
from left to right, here are the appropriate cloudlfare TLS modes which allowed me to access the correct files thru nginx
The distinction between full and flexible is that full mode lets the origin handle the certificate.
Initially I had the static2 site misconfigured as full, which lacked a listen directive for 443 causing nginx to serve static1 instead.
I realize the original question has nothing to do with cdn's or cloudflare but this scheme / protocol mismatch cost me a few hours and I am hoping to save someone else from similar grief
Honestly I am surprised nginx doesn't stick to matching on server_name and that oit implicitly matches on scheme as a fallback (or atleast appears to), even without a default_server specified - and without any meaningful messages in the logs to boot! Debugging nginx is a nightmare sometimes.

Related

Prevent NGINX from serving local index.html instead of passing to proxied server

Found other similar questions, but none seem to work in my circumstance.
I am attempting to proxy from NGINX to an IIS server which is hosting an archived website in its entirety. The site is coded with some hard index.html links and I don't want to go in and modify the site at all.
Any time the site is called with the /index.html in the URL directly it appears that NGINX is not proxying the location, but instead serving out a local index.html page.
Additionally, I am trying to default instead of to the index.html page when no page is entered (i.e. domain only) instead to pass to a default.htm page (set as default in IIS) which provides a disclaimer page that will require reading before continuing on to the original index.html of the website.
This is my nginx configuration file for the site. I do not want to change my overall structure around because it is what multiple sites use. I need a solution that I can add in.
upstream my_backend {
server 10.10.10.102:1011;
include snippets/shared_upstream_settings.conf;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name server.mydomain.com;
include snippets/shared_server_proxy_settings.conf;
location #proxy {
proxy_pass http://my_backend;
}
location / {
satisfy any;
allow 10.16.0.0/24;
deny all;
auth_basic "Authorized Users Only";
auth_basic_user_file secure/.htpasswd;
auth_request /auth-1;
try_files $uri #proxy;
}
(I don't believe any of the includes should matter for this particular issue)
This configuration works for about 15 other sites I have, but none of them apparently have a hardcoded index.html. Until today I never realized that NGINX will not proxy a direct link to index.html. So I need to either disable or work around that "feature" as well as direct no indicated pages to the disclaimer page.
thanks
The $uri argument in your try_files statement instructs Nginx to test for the existence of a file before branching to the #proxy block. There exists a local index.html file that satisfies that test.
You have two options:
Replace the try_files $uri #proxy; line with proxy_pass http://my_backend; as there is no need for a separate location #proxy block.
Or:
If you want to keep the second location block, change the try_files statement to:
try_files __nonexistent__ #proxy;
try_files requires a minimum of two arguments. All arguments before the final argument are filenames to be tested. __nonexistent__ is just one such name that probably does not exist on your file system (and also helps to document the author's intent).

nginx how to serve pictures or media files?

I'm having issues serving pictures with nginx. I originally started with a Django project and I wanted to serve the user uploaded media files via nginx but I wasn't able to get it working no matter what I tried.
So, I've make a second temporary droplet/server and am trying a bare bones setup with no Django project, just Nginx, to see if I can get it to simply serve an index and a couple pictures in a folder called 'media'. Here is the server block:
server {
listen 80;
listen [::]:80;
root /var/www/example.com/html;
index index.html;
server_name 159.89.141.121;
location / {
try_files $uri $uri/ =404;
}
location /media/ {
root /var/www/example.com/media;
}
}
Now, the index.html is served fine but if I try to go to 159.89.141.121/media/testpic.jpg it still doesn't work and returns a 404 error. I'm at a complete loss here, I've tried using alias instead of root, I've tried changing the folder structure and setting all permissions to 777 and changing folder and file ownership, permissions shouldn't be a problem because the index.html works fine with the same permissions; I just cant seem to figure out what I'm doing wrong. The picture is in the folder but nothing I try allows me to access it via the uri. Are there any obvious problems with my server block?
Well I decided to read the documentation and realized that the location block adds to the root directory specified..
So the pathing of
`location /media/ {
root /var/www/example.com/media;
}`
would end up routing example.com/media/testpic.jpg to /var/www/example.com/media/media/testpic.jpg
I've changed the location block to look like this
location /images/ {
root /var/www/example.com/media;
}
and it will now route example.com/images/testpic.jpg to /var/www/example.com/media/images/testpic.jpg
I'm not sure why it didn't work when I tried the alias directive, though...

NGINX multiple server_name, but have robots.txt file for each server_name?

I have to create a server_name as a listener for origin pulls by my CDN.
The CDN wants to pull from origin.mydomain.com
I already have 100s of lines of code under www.mydomain.com that showcases all the rewrites, rules and such, and I need to use all this code again.
My easy solution would be to have
server_name www.mydomain.com origin.mydomain.com
To easily have NGINX listen for the requests to the "origin" subdomain.
My fear is that google discovers the subdomain and starts crawling it. I'd like to block google from the "origin" subdomain somehow. Since declaring multiple server_name, I am not sure I can just place robots.txt file somewhere, since using same root folder as live site.
Is there an easy way to do this?
All feedback appreciated.
Cheers
Ryan
Use two server blocks and use the include directive to pull in the common code. For example:
server {
server_name www.mydomain.com;
include /path/to/common/config;
location = /robots.txt {
root /path/to/friendly/dir;
}
}
server {
server_name origin.mydomain.com;
include /path/to/common/config;
location = /robots.txt {
root /path/to/unfriendly/dir;
}
}
So you have two robot.txt files in different directories - or use rewrite ... last to map the URI to different local files.

Nginx match location for root path and all other paths separately

I am running Play framework server behind nginx server. At the root path, I am serving static website and all other paths should be redirected to the Play server. I have the following default.conf file in /etc/nginx/conf.d (The system is RHEL 6.7)
# to match the root path only to serve static website
location = / {
root /usr/share/nginx/html;
index index.html index.htm;
# try_files $uri $uri.html $uri/ /index.html;
}
# to match the cms login page
location /cms/ {
proxy_pass http://localhost:9000/;
}
# to match all the requests from the cms
location / {
proxy_pass http://localhost:9000/;
}
However, this configuration doesn't match the root path request. It gives 404 error. However, if I remove the third location rule, then it serves the static page at the root path.
Also, I noticed that first time I tried this, it worked. But now, it's not working any more. Please help.
The result you are getting is most likely due to the 2nd and 3rd location blocks not having "index" directives set. Except for well understood specific reasons, such as overriding the default index file type(s), the "index" should always be set at least within the server context or, preferably, within the http context. Similarly, the "root" directive should be set in the server context.
With your config, when a request hits the 3rd location block, there is no information your what to do with it. Actually, the 2nd block should not be needed from what you have described.
Also, as you are proxying to what appears to be another webserver, you need to ensure that this has the equivalent of "index" and "root" set.
Not sure exactly how the backend you are using works with respect to these. If not configurable there, then you must ensure that that every request hitting it has the URI spelt out fully.
To start with, depending on how exactly things are set up on your server, I will move the "index" and "root" directives up to the "server" level

Nginx add sites

I am new to Nginx and webservers overall and I need some help to realise my dream.
Currently I store my htdocs in /srv/www/
I have one page on /srv/www/foo/public_html and another one at /srv/www/bar/public_html.
The idea is that I want to reach them by visiting myip/foo and myip/bar.
Currently when I visit myip I'm being sent to /srv/www/foo/public_html which is something I found a bit wierd. I've looked around on "server blocks" but failed to understand and implement it.
well if you're going to use only 1 IP, then it's 1 server block ( 1 virtual host )
server {
server_name [domain name or ip];
index index.html; # or php or whatever
location /foo {
root /var/www/foo/public_html;
try_files $uri $uri/;
}
location /bar {
root /srv/www/bar/public_html;
try_files $uri $uri/;
}
}
You haven't mentioned what kind of application this is, so it probably need some changes depending if its a php site or rails or any thing else, this would work for static content only like html and images.

Resources