Nginx seem to be ignoring try_files order - ruby-on-rails

Not sure if I'm misunderstanding how try_files work, or if there's something wrong with my config. I'm running Rails on Puma behind Nginx. I'm trying to serve items in my /public folder, after which it should send the requests to Puma.
So, if I go to
https://domain.com/sitemap.xml
it should serve /var/www/live/current/public/sitemap.xml. Then, https://domain.com/rails_index_page should be served from Puma.
The latter works fine, and I can access https://domain.com/public/sitemap.xml, but I would like to access it via https://domain.com/sitemap.xml
My config file looks as follows:
upstream live {
server unix:///var/www/live/shared/puma.sock;
}
server {
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 4 16k;
client_body_timeout 12;
client_header_timeout 12;
keepalive_timeout 15;
send_timeout 10;
server_tokens off;
listen 443;
ssl on;
ssl_certificate /etc/nginx/ssl/ssl-bundle.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_prefer_server_ciphers on;
server_name domain.com; # change to match your URL
root /var/www/live/current/public; # I assume your app is located at this location
try_files $uri #live;
location #live {
add_header Strict-Transport-Security "max-age=31536000";
gzip on;
gzip_static on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 8;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
proxy_pass http://live; # match the name of upstream directive which is defined above
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
root /var/www/live/current/public;
gzip on;
gzip_static on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 8;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
add_header Last-Modified "";
add_header ETag "";
}
set $rootUrl "/var/www/live/current";
location ~* \.(?:ico)$ {
root $rootUrl;
expires 30d;
add_header Cache-Control public;
access_log off;
}
# css and js are tokenized
location ~* \.(?:css|js) {
root $rootUrl;
expires max;
add_header Cache-Control public;
access_log off;
}
# nginx gzip_static does not add Vary header for fonts.
location ~* \.(?:eot|ttf|svg)$ {
root $rootUrl;
expires max;
add_header Access-Control-Allow-Origin *;
add_header Vary Accept-Encoding;
add_header Cache-Control public;
access_log off;
}
# woff fonts should not be zipped.
location ~* \.(?:woff)$ {
root $rootUrl;
add_header Access-Control-Allow-Origin *;
expires max;
add_header Cache-Control public;
access_log off;
}
# tokenized images can be cached forever
location ~* "\.([a-z0-9]{8})\.(?:gif|png|jpe?g)$" {
root $rootUrl;
expires max;
add_header Cache-Control public;
access_log off;
add_header Access-Control-Allow-Origin *;
}
# non tokenized images only cache for 1 week as they are in my context subject to change.
location ~* \.(?:gif|png|jpe?g)$ {
add_header Access-Control-Allow-Origin *;
root $rootUrl;
expires 1w;
add_header Cache-Control public;
access_log off;
}
}
I'm sure the config file can be updated/optimised quite a bit, so please don't shout at me toooo much for that. :)

Does adding a default location block help? Something like
location / {
try_files $uri #live;
root ... ;
}
Try files is valid in the server context, but I don't know what order location directives are matched (and fall through to the server default)
Apologies for no formatting, I'm on mobile, I'll fix it up if it helps.

Related

404 errors when sites-enabled/localhost but not when overriding the default /etc/nginx/nginx.conf

I've got a docker container that's acting as a reverse proxy for local kubernetes services - I know, I should be using real ingress controllers, but at the moment I'm working with others who are using this configuration and I'm trying to troubleshoot it.
When I have no /etc/nginx/sites-enabled files, and /etc/nginx/nginx.conf is configured like this:
worker_processes 1;
events {
worker_connections 1024;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 10;
types_hash_max_size 2048;
add_header Referrer-Policy no-referrer-when-downgrade;
add_header X-Content-Type-Options nosniff;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-XSS-Protection "1; mode=block";
server_tokens off;
server_names_hash_bucket_size 128;
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format artformat '$remote_addr,$remote_user,$time_local,"$request",$status,$body_bytes_sent,"$http_referer","$http_user_agent",$request_time';
access_log /var/log/nginx/access.log artformat;
error_log /var/log/nginx/error.log debug;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types application/javascript text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
include /etc/nginx/sites-enabled/*;
server {
listen 80 default_server;
server_name localhost;
root /usr/share/nginx/html;
charset utf-8;
index index.html;
try_files $uri $uri/ =404;
# Resolve app first.
location /app/ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_app skill-matrix-app.default.svc.cluster.local;
set $skill_matrix_app_port 8080;
proxy_pass http://$skill_matrix_app:$skill_matrix_app_port;
add_header Cache-Control "max-age=0 ,no-cache, no-store, must-revalidate";
}
# Resolve the angular static files second.
location ~* /app/.*\.(js|css|gz|png|svg|jpg|gif|woff|woff2|ttf|otf|eot|json|map|txt)$ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_app skill-matrix-app.default.svc.cluster.local;
set $skill_matrix_app_port 8080;
proxy_pass http://$skill_matrix_app:$skill_matrix_app_port;
add_header Cache-Control "max-age=0 ,no-cache, no-store, must-revalidate";
}
# API resolution after the app resolution
location /api/ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_api skill-matrix-api.default.svc.cluster.local;
set $skill_matrix_api_port 8000;
proxy_pass http://$skill_matrix_api:$skill_matrix_api_port;
add_header Cache-Control "max-age=0 ,no-cache, no-store, must-revalidate";
}
# Admin comes after the app and it's static files.
location /admin/ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_api skill-matrix-api.default.svc.cluster.local;
set $skill_matrix_api_port 8000;
proxy_pass http://$skill_matrix_api:$skill_matrix_api_port;
add_header Cache-Control "max-age=0 ,no-cache, no-store, must-revalidate";
}
# Add static resolution for django files
location ~* /static/.*\.(js|css|gz|png|svg|jpg|gif|woff|woff2|ttf|otf|eot|json|map|txt)$ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_api skill-matrix-api.default.svc.cluster.local;
set $skill_matrix_api_port 8000;
proxy_pass http://$skill_matrix_api:$skill_matrix_api_port;
}
}
}
Things work great - I can get the app:
When I move the server config into /etc/nginx/sites-enabled/localhost like this:
server {
listen 80 default_server;
server_name localhost;
root /usr/share/nginx/html;
charset utf-8;
index index.html;
try_files $uri $uri/ =404;
# Resolve app first.
location /app/ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_app skill-matrix-app.default.svc.cluster.local;
set $skill_matrix_app_port 8080;
proxy_pass http://$skill_matrix_app:$skill_matrix_app_port;
add_header Cache-Control "max-age=0 ,no-cache, no-store, must-revalidate";
}
# Resolve the angular static files second.
location ~* /app/.*\.(js|css|gz|png|svg|jpg|gif|woff|woff2|ttf|otf|eot|json|map|txt)$ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_app skill-matrix-app.default.svc.cluster.local;
set $skill_matrix_app_port 8080;
proxy_pass http://$skill_matrix_app:$skill_matrix_app_port;
add_header Cache-Control "max-age=0 ,no-cache, no-store, must-revalidate";
}
# API resolution after the app resolution
location /api/ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_api skill-matrix-api.default.svc.cluster.local;
set $skill_matrix_api_port 8000;
proxy_pass http://$skill_matrix_api:$skill_matrix_api_port;
add_header Cache-Control "max-age=0 ,no-cache, no-store, must-revalidate";
}
# Admin comes after the app and it's static files.
location /admin/ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_api skill-matrix-api.default.svc.cluster.local;
set $skill_matrix_api_port 8000;
proxy_pass http://$skill_matrix_api:$skill_matrix_api_port;
add_header Cache-Control "max-age=0 ,no-cache, no-store, must-revalidate";
}
# Add static resolution for django files
location ~* /static/.*\.(js|css|gz|png|svg|jpg|gif|woff|woff2|ttf|otf|eot|json|map|txt)$ {
resolver 10.96.0.10 valid=30s;
set $skill_matrix_api skill-matrix-api.default.svc.cluster.local;
set $skill_matrix_api_port 8000;
proxy_pass http://$skill_matrix_api:$skill_matrix_api_port;
}
}
and remove that server configuration from the /etc/nginx/nginx.conf file:
worker_processes 1;
events {
worker_connections 1024;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 10;
types_hash_max_size 2048;
add_header Referrer-Policy no-referrer-when-downgrade;
add_header X-Content-Type-Options nosniff;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-XSS-Protection "1; mode=block";
server_tokens off;
server_names_hash_bucket_size 128;
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format artformat '$remote_addr,$remote_user,$time_local,"$request",$status,$body_bytes_sent,"$http_referer","$http_user_agent",$request_time';
access_log /var/log/nginx/access.log artformat;
error_log /var/log/nginx/error.log debug;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types application/javascript text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
include /etc/nginx/sites-enabled/*;
}
I start getting 404 not found and it looks like it's trying to find these files in the html root instead of proxying them:
2022/06/28 22:47:46 [error] 32#32: *1 "/usr/share/nginx/html/app/index.html" is not found (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /app/ HTTP/1.1", host: "localhost"
127.0.0.1 - - [28/Jun/2022:22:47:46 +0000] "GET /app/ HTTP/1.1" 404 555 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-"
Why is it trying to find app/index.html instead of proxying to the service?
Solved this by adding a removal line to the dockerfile to remove the default.conf based on https://www.nginx.com/blog/deploying-nginx-nginx-plus-docker/:
FROM nginx:1.21
RUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
RUN mkdir /etc/nginx/sites-enabled/
COPY error/ /var/www/html
COPY index.html /var/www/html
COPY favicon.ico /var/www/html
COPY localhost.crt /opt/nginx/ssl_keys/ssl.crt
COPY localhost.key /opt/nginx/ssl_keys/ssl.key
COPY sites-enabled/ /etc/nginx/sites-enabled/
COPY nginx.conf /etc/nginx
Once I did that, the default.conf was no longer overriding and trying to get everything to look at the local host.

Nginx Proxy Pass Always Returning 404s

So I'm working on a POC for a micro-frontend architecture. I am using nginx as the driver for this. In my local environment, I'm testing the docker configuration for the projects. Each micro-frontend will be in its own docker container, and they will share a network. The container names are:
micro-fe-parent
micro-fe-react-wc
The goal is to get micro-fe-parent to be able to load content from micro-fe-react-wc via an nginx proxy. My webpack dev server proxy setup works perfectly with my existing code, but with nginx all I'm getting is 404s.
I can shell into the container and use curl to hit the micro-fe-react-wc application directly, and I can manually request any file successfully this way. So the containers can see each other, the docker network is working. Something in the proxy pass is not working. Unfortunately, nginx logs are no help, and it's debugging tools are really lacking.
The goal of the proxy is that any URI it sees that starts with /react-wc, it will remove the /react-wc part and resolve the rest of the URI against the target host. So let's say I have a file called "app.js", the request I would be making from micro-fe-parent would be /react-wc/assets/app.js, and nginx would proxy that to http://micro-fe-react-wc/assets/app.js, preserving most of the URI but removing that one path element.
I've tried everything I can think of to configure this properly.
Here is my nginx.conf:
worker_processes auto;
events {
worker_connections 1024;
multi_accept on;
}
http {
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $upstream_addr '
'"$http_referer" "$http_user_agent"';
log_format new_format '[$time_local] $remote_addr - $remote_user - $server_name to: $upstream_addr: $request upstream_response_time $upstream_response_time msec $msec request_time $request_time';
include /etc/nginx/mime.types;
default_type text/plain;
gzip on;
gzip_disable "msie6"
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_proxied any;
gunzip on;
gzip_static always;
gzip_types text/plain text/css text/js text/xml text/javascript application/javascript application/x-javascript application/json application/xml application/xml+rss;
gzip_vary on;
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
server {
listen 80;
server_name micro-fe-parent;
access_log /var/log/nginx/access.log new_format;
error_log /var/log/nginx/error.log debug;
rewrite_log on;
root /var/www;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /react-wc {
rewrite '^/react-wc(/.*)$' '$1' break;
proxy_pass http://micro-fe-react-wc;
}
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
location ~* \.(?:css|js)$ {
try_files $uri =404;
expires 1y;
access_log off;
add_header Cache-Control "public";
}
location ~ ^.+\..+$ {
try_files $uri =404;
}
}
}
So the problem was I wasn't using ^~ to treat it like a regex match, so it was looking for a literal /react-wc path instead of as a matcher on the path.
location ^~ /react-wc {
rewrite '^/react-wc(/.*)$' '$1' break;
proxy_pass http://micro-fe-react-wc;
}

Nginx and rails headers don't work

I'm trying to add some headers to nginx config, but now only the one header is working(Strict-Transport-Security).
upstream puma_muninn {
server app:3000;
}
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 default ssl;
server_name production.test.com;
root /var/www/muninn/public;
ssl on;
ssl_certificate /var/www/muninn/test.crt;
ssl_certificate_key /var/www/muninn/test.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
client_max_body_size 4G;
keepalive_timeout 10;
error_page 500 502 504 /500.html;
error_page 503 #503;
try_files $uri/index.html $uri #puma_muninn;
location #puma_muninn {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "default-src 'self';";
add_header 'Referrer-Policy' 'origin';
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
access_log /var/www/muninn/log/nginx.access.log;
error_log /var/www/muninn/log/nginx.error.log;
}
If I add some headers on my rails side:
config.action_dispatch.default_headers = {
'X-Frame-Options' => 'SAMEORIGIN'
}
It turns off any headers from nginx.
Ideas?
To ensure all traffic your application has is treated equally as far as security goes, move those add_header declarations outside the location block and avoid setting headers in your application that are being set on NGINX. Your file should look something like this:
upstream puma_muninn {
server app:3000;
}
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 default ssl;
server_name production.test.com;
root /var/www/muninn/public;
ssl on;
ssl_certificate /var/www/muninn/test.crt;
ssl_certificate_key /var/www/muninn/test.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
client_max_body_size 4G;
keepalive_timeout 10;
error_page 500 502 504 /500.html;
error_page 503 #503;
try_files $uri/index.html $uri #puma_muninn;
# Equal security to all requests
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "default-src 'self';";
add_header 'Referrer-Policy' 'origin';
location #puma_muninn {
# No need to especify security headers here, since global config will take care of the rest.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
access_log /var/www/muninn/log/nginx.access.log;
error_log /var/www/muninn/log/nginx.error.log;
}
If you are enforcing all SSL/TSL, cookies and HSTS security in NGINX you should remove security headers from your Rails application, as you may have followed similar steps as this answer. Duplicate headers can trigger a false negative or even a real one in those automatic site analysis tools.

HTTPS redirect Elastic Beanstalk Environment Puma Rails 5

I am unable to redirect http://example.com to https://example.com. I tried various configurations but nothin works.
Based on the research, I have realized that I need to add this to nginx config.
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
I create a new config file in the ..ebextensions directory with the following content,
upstream my_app {
server unix:///var/run/puma/my_app.sock;
}
log_format healthd '$msec"$uri"'
'$status"$request_time"$upstream_response_time"'
'$http_x_forwarded_for';
server {
listen 80;
server_name _ localhost; # need to listen to localhost for worker tier
if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
}
access_log /var/log/nginx/access.log main;
access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;
location / {
proxy_pass http://my_app; # match the name of upstream directive which is defined above
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /assets {
alias /var/app/current/public/assets;
gzip_static on;
gzip on;
expires max;
add_header Cache-Control public;
}
location /public {
alias /var/app/current/public;
gzip_static on;
gzip on;
expires max;
add_header Cache-Control public;
}
}
save it and do
eb deploy
Goto http://example.com
I still get the "unsure" message.
I also used the content as is from this. But that does not work either.
What am i missing?
Sunil
Nowhere in your code do I see a listen to 443 which is the HTTPS.
This is my SSL script.
upstream puma_production {
server unix:/home/deploy/games.directory/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443;
server_name games.directory;
root /home/deploy/games.directory/current/public;
try_files $uri/index.html $uri #puma_production;
ssl on;
ssl_certificate '';
ssl_certificate_key '';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers ''
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/games.directory/chain.pem;
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
location #puma_production {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://puma_production;
access_log /home/deploy/games.directory/shared/log/nginx.access.log;
error_log /home/deploy/games.directory/shared/log/nginx.error.log;
}
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
return 405;
}
}
Use EB file keys to customise for nginx conf generation template.
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html
Create a file .ebextensions/01_puma_nginx.conf (Configuration files are executed in alphabetical order, so tweak name prefix based on additional requirements) with following content.
files:
"/opt/elasticbeanstalk/support/conf/nginx_config.erb":
mode: "000644"
owner: root
group: root
content: |
Paste your custom nginx configuration template content here....
Instead of building your own template and break things, check the existing template in the current instance and tweak only required things (here just your http redirection part).
Well, if this seems a little complicated, you can use rails force_ssl option by checking 'X-Forwarded-Proto' header
force_ssl if: :ssl_required?
def ssl_required?
if request.headers["X-Forwarded-Proto"]!="https"
true
else
false
end
end
Redirecting HTTP traffic to HTTPS is a very common problem needing to be solved. So AWS have documented the solution here, which covers all their different Elastic Beanstalk platforms:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https-httpredirect.html

Compressing rails assets and nginx gzip

Do I have to configure nginx to compress assets (gzip set to on) if I have compressed rails assets with rake assets:precompile? I mean does it make sense or not? Will performance better or worse? Thank you!
Do rake assets:precompile and you have to configure nginx for send gzip version of files, i use this configuration.
user www-data www-data;
worker_processes 4;
pid /var/run/nginx.pid;
events{
worker_connections 2048;
use epoll;
}
http{
include mime.types;
default_type application/octet-stream;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
server_tokens off;
server_name_in_redirect off;
ignore_invalid_headers on;
gzip off;
sendfile on;
upstream reverse-proxy{
server 127.0.0.1:3000;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}
server{
listen 80;
server_name _;
root /home/www-data/my_website/public;
client_max_body_size 10M;
client_body_buffer_size 512k;
location ~ ^/assets/ {
gzip_static on;
add_header Cache-Control public;
expires 4w;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_disable "MSIE [1-6]\.";
gzip_comp_level 6;
gzip_types application/x-javascript text/css text/html image/x-icon image/png image/jpeg image/gif;
}
location / {
try_files $uri #ruby;
}
location #ruby {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://reverse-proxy;
}
}
}
No, you do not. They are not the same kind of compression. When you run rake assets:precompile, all you're really doing is joining a bunch of files into one file and dumping it to the disk. Actually, according to the official documentation, it is two files:
When files are precompiled, Sprockets also creates a gzipped (.gz)
version of your assets. Web servers are typically configured to use a
moderate compression ratio as a compromise, but since precompilation
happens once, Sprockets uses the maximum compression ratio, thus
reducing the size of the data transfer to the minimum. On the other
hand, web servers can be configured to serve compressed content
directly from disk, rather than deflating non-compressed files
themselves.
This is important for you, because it allows you to use gzip, if you want, but it does not force you to do so. Gzip compression, which is real compression (not just concatenating files) reduces the amount of data you have to transfer, but at the expense of processor power (compressing and decompressing). It is likely to fairly dramatically improve your site, depending on page sizes and your (and your user's) hardware.
Here is a complete configuration(I am using it for my site):
GENERAL CONFIGURATION
http {
passenger_root /usr/local/lib/ruby/gems/1.9.1/gems/passenger-4.0.5;
passenger_ruby /usr/local/bin/ruby;
include mime.types;
default_type application/octet-stream;
server_tokens off;
sendfile on;
keepalive_timeout 70;
gzip on;
gzip_http_version 1.1;
gzip_disable "msie6";
gzip_vary on;
gzip_min_length 1100;
gzip_buffers 64 8k;
gzip_comp_level 3;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml application/xml;
add_header Strict-Transport-Security "max-age=16070400; includeSubdomains";
add_header X-Frame-Options DENY;
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
include /opt/nginx/conf/nginx_host.conf;
}
Content of /opt/nginx/conf/nginx_host.conf;
HOST CONFIGURATION
server {
listen 80;
server_name *.domain.com;
root APP_PATH/current/public;
passenger_enabled on;
access_log off;
error_log /dev/null;
# Cross domain webfont access
location ~* \.(?:ttf|ttc|otf|eot|woff|font.css)$ {
add_header "Access-Control-Allow-Origin" "*";
expires 1M;
access_log off;
add_header Cache-Control "public";
}
location ~* \.(ico|css|gif|jpe?g|png)(\?[0-9]+)?$ {
expires max;
}
location ~ ^/(assets|uploaded_assets|system)/ {
root /home/travelobd/rails_apps/travelobd/current/public;
gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
}
}
For serving assets:
server {
listen 80;
server_name static.domain.com;
root APP_PATH/current/public;
location / {
if ($request_filename ~ "\.(jpg|css|gif|png|swf|ico|js)$") {
break;
}
return 404;
}
}
Yes, you should if you want to improve performance.
Simply add the following block to your site configuration:
location ~ ^/(assets)/ {
root /path/to/public; # CHANGE THIS
gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
}
Change the root path in the configuration. That is all there is to it.
RecommendationFromDocumentation™: http://guides.rubyonrails.org/asset_pipeline.html
What worked for me was configuring Nginx:
location ~ ^/(assets)/ {
gzip_static on;
}
Then in application.rb:
config.middleware.insert_before(Rack::Sendfile, Rack::Deflater)
# Compress JavaScripts and CSS.
config.assets.compress = true
config.assets.js_compressor = Uglifier.new(mangle: false)

Resources