nginx+django serving static files
I have followed instruction for setting up django with nginx from the django wiki (https://code.djangoproject.com/wiki/DjangoAndNginx) and have nginx setup as follows (a few name changes to fit my setup).
user nginx nginx;
worker_processes 2;
error_log /var/log/nginx/error_log info;
events {
worker_connections 1024;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main
'$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
client_header_timeout 10m;
client_body_timeout 10m;
send_timeout 10m;
connection_pool_size 256;
client_header_buffer_size 1k;
large_client_header_buffers 4 2k;
request_pool_size 4k;
gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_types text/plain;
output_buffers 1 32k;
postpone_output 1460;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 75 20;
ignore_invalid_headers on;
index index.html;
server {
listen 80;
server_name localhost;
location /static/ {
root /srv/static/;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mov) {
access_log off;
expires 30d;
}
location / {
# host and port to fastcgi server
fastcgi_pass 127.0.0.1:8080;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
fastcgi_param REMOTE_ADDR $remote_addr;
}
access_log /var/log/nginx/localhost.access_log main;
error_log /var/log/nginx/localhost.error_log;
}
}
Static files aren't being served (nginx 404). If I look in the access log it seems nginx is looking in /etc/nginx/html/static... rather than /srv/static/ as specified in the config.
I've no clue why it's doing this, any help would be hugely appreciated.
Solution 1:
Short answer: see the last location in the long version. Technically, the setup described in that page is wrong. See the end of the answer for reasons.
Long answer: you porbably have /etc/nginx...
path in your logs because requests for static files don't match your static location(the regex location takes precedense) an you have not specified root
for the server
block itself.
When your request matches the regex location, nginx will search files under /etc/nginx
. To fix this you might want to add root
directive directly inside server
block as described above, or under each non-proxied location (the same goes to fastCGI as well).
Also spotted: if you specify root
directive under location nginx will search for files under $document_root/$location
, e.g. in /srv/static/static
which is 99% not you might want. You may use alias
directive but nginx documentation prefers to redefine root
directive if this is possible:
location /static {
root /srv;
}
The alias
directive works just like you expected, so you might want to write this instead:
location /static {
alias /srv/static;
}
As to the regex location, you might want to put it inside /static
location. Also since there will be only static files, you can get rid of ther regex location, and final location will look like this:
location /static {
root /srv;
access_log off;
expires 30d;
}
Why the described setup is wrong and how to fix this
According to the commands the user provided, he likes to have most of the components as fresh as possible running on a Debian-like Linux. But instead of correctly installing everything by hand or just using aptitude he starts mixing and installing software from packages as well. This will work for some development box but this is a no-go for any production. So here are some points:
- Please install software in one way, preferrably from packages. If you need bleeding edge, build packages for them (that's not so hard ;) ) or use some environment to separate it from system like
virtualenv
. - You don't need to manually add nginx user and group. Web-servers run from
www-data:www-data
in Debian. Since your setup does not intend to run any code within web-server context, adding more users is useless. - The article suggests to redefine the whole
/etc/nginx/nginx.conf
file which is totally wrong, especially on Debian-like systems. Instead of doing this you might want to createsample_project
file in/etc/nginx/sites-available
and link it to/etc/nginx/sites-enabled
to make nginx attach your configuration`:# cd /etc/nginx/sites-enabled && ln -s ../sites-available/sample_project sample_project
- The
sample_project
file in this case should contain onlyserver
block itself, nothing more. - Most of the directives (except
log_format
and maybe some others) should have context of your virtualhost and thus should be placed underserver
block in yoursample_project
file. You will not affect the work of other services running on this web-server. You may placelog_format
directive in your file but outside of any block and before theserver
block itself. - Instead of writing all that
fastcgi_pass
directives one should writeinclude fastcgi_params
and only redefine those that not correct to current setup. - To have your log files automatically rotating by logrotate you should name them to match
*access.log
or*error.log
wildcard.
Giving this the minimal working host configuration file /etc/nginx/sites-available/sample_project
might look like:
server {
listen 80;
server_name myhostname.com;
root /home/user/django/sample_project;
location /static {
root /srv;
access_log off;
expires 30d;
}
location / {
include fastcgi_params;
fastcgi_pass 127.0.0.1:8080;
}
access_log /var/log/nginx/sample_project.access.log combined;
error_log /var/log/nginx/sample_project.error.log warn;
}