I’ve been using a vanilla apache install until recently with no major problems.
Today I installed Nginx Admin (the cpanel nginx plugin) which acts as a reverse proxy for Apache to deliver static files.
This all works very well and there is a noticable performance boost which I am pleased with.
However my site hosts a large amount of MP3 files which prior to using Nginx would all get cached by the browser meaning that a user only had to download them once and subsequent listens were instananeous.
Now, with Nginx Admin installed the browser requests the file from the server every time.
I have tried adding the following to my nginx config file:-
location ~* \.(mp3)$ {
expires max;
}
But even this had no effect. What might be causing this and what else can I try to rectify this issue?
Strangely under apache my header looks like this:-
Server Apache
Connection Keep-Alive
Keep-Alive timeout=5, max=98
Vary Accept-Encoding,User-Agent
This returns a 304 Not Modified response after being cached
and with nginx admin installed the headers are as follows:-
Server nginx admin
Date Thu, 24 Nov 2011 12:46:27 GMT
Content-Type audio/mpeg
Content-Length 5263187
Last-Modified Mon, 26 Sep 2011 18:29:39 GMT
Connection keep-alive
Expires Thu, 01 Dec 2011 12:46:27 GMT
Cache-Control max-age=604800
X-Cache HIT from Backend
Accept-Ranges bytes
Which no matter what always returns a 200 OK.
My nginx config file is as follows:-
user nobody;
# no need for more workers in the proxy mode
worker_processes 4;
error_log /var/log/nginx/error.log info;
worker_rlimit_nofile 20480;
events {
worker_connections 5120; # increase for busier servers
use epoll; # you should use epoll here for Linux kernels 2.6.x
}
http {
server_name_in_redirect off;
server_names_hash_max_size 10240;
server_names_hash_bucket_size 1024;
include mime.types;
default_type application/octet-stream;
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 5;
gzip on;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
gzip_proxied any;
gzip_http_version 1.1;
gzip_min_length 1000;
gzip_comp_level 6;
gzip_buffers 16 8k;
# You can remove image/png image/x-icon image/gif image/jpeg if you have slow CPU
gzip_types text/plain text/xml text/css application/x-javascript application/xml image/png image/x-icon image/gif image/jpeg application/xml+rss text/javascript application/atom+xml;
ignore_invalid_headers on;
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
reset_timedout_connection on;
connection_pool_size 256;
client_header_buffer_size 256k;
large_client_header_buffers 4 256k;
client_max_body_size 200M;
client_body_buffer_size 128k;
request_pool_size 32k;
output_buffers 4 32k;
postpone_output 1460;
proxy_temp_path /tmp/nginx_proxy/;
client_body_in_file_only on;
log_format bytes_log "$msec $bytes_sent .";
include "/etc/nginx/vhosts/*";
}
With this domain specific file being included:-
server {
error_log /var/log/nginx/vhost-error_log warn;
listen x.x.x.x:x;
server_name songbanc.com www.songbanc.com;
access_log /usr/local/apache/domlogs/mydomain.com-bytes_log bytes_log;
access_log /usr/local/apache/domlogs/mydomain.com combined;
root /home/mydomain/public_html;
location / {
location ~.*\.(3gp|gif|jpg|jpeg|png|ico|wmv|avi|asf|asx|mpg|mpeg|mp4|pls|mp3|mid|wav|swf|flv|html|htm|txt|js|css|exe|zip|tar|rar|gz|tgz|bz2|uha|7z|doc|docx|xls|xlsx|pdf|iso)$ {
expires 7d;
try_files $uri @backend;
}
error_page 405 = @backend;
add_header X-Cache "HIT from Backend";
proxy_pass http://x.x.x.x:8081;
include proxy.inc;
}
location @backend {
internal;
proxy_pass http://x.x.x.x:8081;
include proxy.inc;
}
location ~ .*\.(php|jsp|cgi|pl|py)?$ {
proxy_pass http://x.x.x.x:8081;
include proxy.inc;
}
location ~ /\.ht {
deny all;
}
location ~* \.(mp3)$ {
expires max;
}
}
I believe the reason may be because your conf file was unnecessarily complex and errors start to creep into such configs.
location ~ .*\.(php|jsp|cgi|pl|py)?$should belocation ~ .*\.(php|jsp|cgi|pl|py)$.The long nested if block under location / is similarly not required.
The
add_header X-Cachedirective should be in proxy.inc.Named locations such as “@backend” do not need “internal” directives.
Anyway, after striping things down, we are left with:
This should have the static files cached and dynamic ones not cached. requires rewrite rules for the mp3 block to be translated from the backend.
Alternatively, you can just pass the mp3 requests to the backend.
I am not 100% certain if directives such as “expires” and “add_header” are not cleared when a redirect is triggered. If you find that you are not getting the you headers with the config above, this slightly longer one should do it.