Nginx fails to load css files

I've recently decided to switch from Apache2 to Nginx. I installed Nginx on my CentOS server and setup a basic configuration. When I tried to load my site in browser (FF/Chrome) I noticed that css file is not loaded. I checked the error console and saw this message:

Error: The stylesheet http://example.com/style.css was not loaded because its MIME type, "text/html", is not "text/css".

I checked Nginx configuration and everything seems to be fine:

http {
    include /etc/nginx/mime.types;
    ..........
}

The mime type for css files is correctly set in /etc/nginx/mime.types.

text/css css;

Everything seems to be well configured but my css files are still not loaded. I have no explanation.

Another thing worth mentioning. Initially I installed Nginx using epel repositories and i got an old version: 0.8... It appeared to me that my problem was a bug in that version so I uninstalled 0.8 version, added nginx repository to yum and then installed latest version: 1.0.14. I thought the new version will solve my problem, but unfortunately it didn't so I am running out of ideas.

I appreciate any help.

Configuration files:

/etc/nginx/nginx.conf

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

/etc/nginx/conf.d/default.conf

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
         root    /usr/share/nginx/html;
         index  index.html index.htm index.php;
         fastcgi_pass   127.0.0.1:9000;
         fastcgi_index  index.php;
         fastcgi_param  SCRIPT_FILENAME  /usr/share/nginx/html$fastcgi_script_name;
         include        fastcgi_params;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

/etc/nginx/mime.types

types {
    text/html                             html htm shtml;
    text/css                              css;
    text/xml                              xml;
    image/gif                             gif;
    image/jpeg                            jpeg jpg;
    application/x-javascript              js;
    application/atom+xml                  atom;
    application/rss+xml                   rss;
    ..........................................
    other types here
    ..........................................
}

Solution 1:

Putting the include /etc/nginx/mime.types; under location / { instead of under http { solved the issue for me.

Solution 2:

I found an workaround on the web. I added to /etc/nginx/conf.d/default.conf the following:

location ~ \.css {
    add_header  Content-Type    text/css;
}
location ~ \.js {
    add_header  Content-Type    application/x-javascript;
}

The problem now is that a request to my css file isn't redirected well, as if root is not correctly set. In error.log I see

2012/04/11 14:01:23 [error] 7260#0: *2 open() "/etc/nginx//html/style.css"

So as a second workaround I added the root to each defined location. Now it works, but seems a little redundant. Isn't root inherited from / location ?

Solution 3:

style.css is actually being process via fastcgi due to your "location /" directive. So it is fastcgi that is serving up the file (nginx > fastcgi > filesystem), and not the filesystem directly (nginx > filesystem).

For a reason I have yet to figure out (I'm sure there's a directive somewhere), NGINX applies the mime type text/html to anything being served from fastcgi, unless the backend application explicitly says otherwise.

The culprit is this configuration block specifically:

location / {
     root    /usr/share/nginx/html;
     index  index.html index.htm index.php;
     fastcgi_pass   127.0.0.1:9000;
     fastcgi_index  index.php;
     fastcgi_param  SCRIPT_FILENAME  /usr/share/nginx/html$fastcgi_script_name;
     include        fastcgi_params;
}

It should be:

location ~ \.php$ { # this line
     root    /usr/share/nginx/html;
     index  index.html index.htm index.php;
     fastcgi_split_path_info ^(.+\.php)(/.+)$; #this line
     fastcgi_pass   127.0.0.1:9000;
     fastcgi_index  index.php;
     fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name; # update this too
     include        fastcgi_params;
}

This change makes sure only *.php files are requested from fastcgi. At this point, NGINX will apply the correct MIME type. If you have any URL rewriting happening, you must handle this before the location directive (location ~\.php$) so that the correct extension is derived and properly routed to fastcgi.

Be sure to check out this article regarding additional security considerations using try_files. Given the security implications, I consider this a feature and not a bug.