Category: Nginx

  • Nginx Rails Origin header didn’t match request.base_url

    Nginx Rails Origin header didn’t match request.base_url

    After installing SSL on Nginx server, rails application login page stopped working.

    On log file (log/production.log), found following error

    HTTP Origin header (https://domain.com) didn't match request.base_url (http://domain.com)

    The Nginx config used was

    upstream app {
       server unix:/var/www/public/shared/sockets/unicorn.sock fail_timeout=0;
    }
    
    server {
       listen 443 ssl;
       root /var/www/public;
       ssl_certificate /etc/ssl/ssl.crt;
       ssl_certificate_key /etc/ssl/ssl.key;
       server_name domain.com;
       try_files $uri/index.html $uri @app;
       location @app {
           proxy_pass http://app;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header Host $http_host;
           proxy_redirect off;
       }
       error_page 500 502 503 504 /500.html;
       client_max_body_size 4G;
       keepalive_timeout 10;
    }
    

    The problem is solved by adding following to nginx config.

    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_set_header  X-Forwarded-Ssl on;
    proxy_set_header  X-Forwarded-Port $server_port;
    proxy_set_header  X-Forwarded-Host $host;
    

    The new config is

    server {
       listen 443 ssl;
       root /var/www/public;
       ssl_certificate /etc/ssl/ssl.crt;
       ssl_certificate_key /etc/ssl/ssl.key;
       server_name domain.com;
       try_files $uri/index.html $uri @app;
       location @app {
           proxy_pass http://app;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header Host $http_host;
           proxy_set_header  X-Forwarded-Proto $scheme;
           proxy_set_header  X-Forwarded-Ssl on;
           proxy_set_header  X-Forwarded-Port $server_port;
           proxy_set_header  X-Forwarded-Host $host;
           proxy_redirect off;
       }
       error_page 500 502 503 504 /500.html;
       client_max_body_size 4G;
       keepalive_timeout 10;
    }
    

    See Nginx

  • Nginx Disable Access log

    Nginx Disable Access log

    On a high traffic web site, i want to disable access log as we are hitting I/O Limit. Since we don’t use this access log for anything now, there is no point keep writing it to a file. To disable, you need to add following to server entry for your web site.

    access_log off;
    

    Here is an example nginx config with access logs disabled.

    server {
        server_name server3.serverok.in www.server3.serverok.in;
        listen 80;
        listen 443 ssl;
        ssl_certificate /etc/ssl/ssl.cert;
        ssl_certificate_key /etc/ssl/ssl.key;
        root /home/server3/public_html;
        index index.html;
        limit_rate_after 10m;
        limit_rate 512k;
        access_log off;
        location / {
            valid_referers none serverok.in www.serverok.in;
            if ($invalid_referer) {
                return 403;
            }
        }
    }
    
  • Enable Directory Listing in Nginx

    To enable directory listing in Nginx, add following to server configuration.

    autoindex on;
    

    Example

    server {
    	listen 80 default_server;
    	listen [::]:80 default_server;
    	root /var/www/html;
    	autoindex on;
    	index index.php index.html index.htm;
    
    	server_name _;
    
        location / {
                try_files $uri $uri/ /index.php?$args;
        }
    
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            proxy_read_timeout 600;
            fastcgi_read_timeout 600;
            fastcgi_send_timeout 600;
            fastcgi_intercept_errors on;
            fastcgi_buffers 16 16k;
            fastcgi_buffer_size 32k;
            fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }
    
    }
    

    If you need it for a specific folder, add

    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/html;
        index index.php index.html index.htm;
        
        server_name _;
    
        location / {
                try_files $uri $uri/ /index.php?$args;
        }
    
        location /myfiles {
                autoindex on;
        }
    
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            proxy_read_timeout 600;
            fastcgi_read_timeout 600;
            fastcgi_send_timeout 600;
            fastcgi_intercept_errors on;
            fastcgi_buffers 16 16k;
            fastcgi_buffer_size 32k;
            fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }
    
    }
    
  • Nginx Configuration for Video Streaming With Secure Link

    here is nginx configuration i used for a video site that have secure link.

        server {
            listen   188.40.131.92:80;
            server_name s1.video.bizhat.com;
            access_log /var/log/nginx/s1.video.bizhat.com.log;
            error_log /var/log/nginx/s1.video.bizhat.com.error_log;
            location ~ ^/media/(?[\w\-=]+,\d+)(?/.*\.flv)$ {
                secure_link $secure;
                secure_link_md5 $secure_link_expires.$file.hjAGhAJKAKAHJ89AHJ00AM;
                if ($secure_link = "") { return 403; }
                if ($secure_link = "0") { return 410; }
                alias  /home/s1.video.bizhat.com/private/$file;
                flv;
            }
            location ~ ^/media/(?[\w\-=]+,\d+)(?/.*\.mp4)$ {
                secure_link $secure;
                secure_link_md5 $secure_link_expires.$file.hjAGhAJKAKAHJ89AHJ00AM;
                if ($secure_link = "") { return 403; }
                if ($secure_link = "0") { return 410; }
                alias  /home/s1.video.bizhat.com/private/$file;
            }
        }
    

    This video server is a storage server in vShare Youtube Clone script.

  • Nginx 413 Request Entity Too Large

    On Nginx server, when uploading large file, i get error

    413 Request Entity Too Large
    

    On nginx error log

    2018/10/10 18:15:34 [error] 25787#0: *184 client intended to send too large body: 31354043 bytes, client: 15.17.7.27, server: _, request: "POST /phpmyadmin/import.php HTTP/1.1", host: "13.16.28.19"
    

    To fix, edit nginx config for the web site, under the server section of the web site, add

    client_max_body_size 800M;
    

    Restart nginx.

    service nginx restart
    
  • Nginx CloudFlare restore real ip

    When using Nginx Behind Cloudflare, logs and web applications show Cloudflare sever IP instead of visitor IP.

    To fix this, edit

    vi /etc/nginx/nginx.conf

    Inside “http” section, add

    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 104.16.0.0/12;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 131.0.72.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 2400:cb00::/32;
    set_real_ip_from 2606:4700::/32;
    set_real_ip_from 2803:f800::/32;
    set_real_ip_from 2405:b500::/32;
    set_real_ip_from 2405:8100::/32;
    set_real_ip_from 2c0f:f248::/32;
    set_real_ip_from 2a06:98c0::/29;
    
    real_ip_header CF-Connecting-IP;

    You can get updated list of CloudFlare IPs from

    https://www.cloudflare.com/ips

    Restart Nginx with

    service nginx restart

    Example Nginx Config

    https://gist.github.com/serverok/fef5c76bf96f8e016bf64095da4a64dc

    Back to Nginx

  • Disable Access to a folder in Nginx

    To disable access to folder /admin in Nginx, add following to server block of your web site.

    location /admin {
        deny all;
        return 404;
    }
    

    To disable access to some common virtual control software, use

    location ~ /\.ht    {return 404;}
    location ~ /\.svn/  {return 404;}
    location ~ /\.git/  {return 404;}
    location ~ /\.hg/   {return 404;}
    location ~ /\.bzr/  {return 404;}
    
  • Nginx Config for rtmp streaming

    Here is nginx config used for RTMP streaming.

    user  nginx;
    worker_processes  1;
    
    worker_rlimit_nofile 300000;
    events {
        worker_connections  16000;
        use epoll;
    }
    
    rtmp_auto_push on;
    
    rtmp {
       server {
         listen 25462;
         interleave on;
         wait_video on;
         idle_streams off;
         chunk_size 4096;
         notify_method get;
         application live{
            live on;
            record off;
            on_play http://localhost:25461/streaming/rtmp.php;
            on_publish http://localhost:25461/streaming/rtmp.php;
            on_play_done http://localhost:25461/streaming/rtmp.php;
         }
       }
    }
    
    http {
    	allow 127.0.0.1;
    	deny all;
    	server {
                listen 31210;
                server_name  localhost;
                location /control {
                    rtmp_control all;
                }
                location /stat {
                    rtmp_stat all;
                }
           }
    }
    
  • Nginx wildcard virtualhost

    wildcard virtual host allow you to host multiple web sites with one configuration file.

    Here is what i use for bizhat.com free hosting sub domains.

    server {
        listen   167.114.61.119:80;
        server_name *.bizhat.com;
        autoindex on;
        access_log /var/log/nginx/free_access.log;
        error_log /var/log/nginx/free_error.log;
        root /home/vhosts/$host;
    
        index index.html index.htm default.htm default.html;
    
        location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
            access_log off;
            expires max;
        }
    
        location ~ /\.ht {
            deny  all;
        }
    
        error_page 302  /302.html;
        location = /302.html {
            root  /home/free.bizhat.com/error;
        }
    
        error_page 404 /404.html;
        location = /404.html {
              root  /home/free.bizhat.com/error;
        }
    }
    

    Nginx

  • Moving from Apache PHP 5 to Nginx PHP 7

    Moving from Apache PHP 5 to Nginx PHP 7

    Today i moved a high traffic WordPress web using from Apache + PHP 5 to Nginx + PHP 7.2.

    Here is a graph provided by LiquidWeb (server provider).

    With Apache, load was like 8.

    root@host:/etc/php# uptime
    12:35:01 up 14:33, 1 user, load average: 8.03, 6.66, 5.84
    root@host:/etc/php#

    After switching to Nginx + PHP-FPM, load come down to 2.

    root@host:~# uptime
    17:26:20 up 19:24, 1 user, load average: 1.13, 1.07, 1.21
    root@host:~#

    Here is sar result.

    With Apache idle CPU was approx 72. With Nginx we have 90%+ idle CPU most of the time.

    Here is NewRelic Web transactions graph. The break in data is due to PHP 7.2 have no newrelic module installed. So i just switched back to Apache for a while, reinstalled NewRelic for PHP 7.2, then turned Nginx back on.

    NewRelic Apdex Score went from poor to fair.

  • Nginx Proxy Configuration

    To configure Nginx as a proxy, use the following configuration

    server {
        listen *:80;
        client_max_body_size 100M;
        proxy_read_timeout 600s;
        proxy_buffer_size   128k;
        proxy_buffers   4 256k;
        proxy_busy_buffers_size   256k;
        location / {
            proxy_set_header X-Real-IP  $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://127.0.0.1:81;
        }
    }

    If you need to serve images using static files, add the following block to Nginx config

        location ~ ^/(images|javascript|js|css|flash|media|static)/ {
            root /home/domain.com/html/;
            index index.php index.html;
            expires 30d;
        }

    Rule to handle SSL verification

    If you are proxying traffic to an application server, you may need Nginx to handle requests for SSL verification. In that case, add the following to the server block, above location / entry.

        location ~ ^/.well-known/ {
            allow all;
            autoindex on;
            root /var/www/html;
        }

    Example

    https://gist.github.com/serverok/8fb73df8135774f292bb2cc86446ae2c

    Nginx Rails Origin header didn’t match request.base_url

    HTTP to HTTPS Redirect

    If you do proxying on HTTPS, then you can use the following config for HTTP to handle SSL verification and redirect to HTTPS.

    server {
        listen 80;
        server_name YOURDOMAIN.TLD;
        location ~ ^/.well-known/ {
            allow all;
            autoindex on;
            root /var/www/html;
        }
        location / {
            return 301 https://$host$request_uri;
        }
    }

    Nginx Proxy Config with Caching

    Here is Nginx proxy config with caching.

    proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=cache:30m max_size=250m;
    proxy_temp_path /tmp/nginx_proxy 1 2;
    
    server {
        client_max_body_size 100M;
        location / {
            proxy_pass http://127.0.0.1:8000/;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_cache cache;
            proxy_cache_bypass $myCookie;
            proxy_no_cache $myCookie;
            proxy_cache_valid 30m;
            proxy_cache_key $host$scheme$proxy_host$request_uri;
            # force caching
            # proxy_ignore_headers X-Accel-Expires Expires Cache-Control;
        }
    }

    If cookie “myCookie” is present, nginx won’t serve the cached page to that visitor.

    Back to Nginx

  • Magento 1.9 Nginx Configuration

    Here is Nginx + php-fpm config for Magento 1.9 on Ubuntu 16.04/Debian 9.

    server {
        listen 80;
    
        server_name mysite.com www.mysite.com;
        root /home/mysite.com/public_html/;
    
        listen 443 ssl http2;
        ssl on;
        ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain1.pem;
        ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey1.pem;
    
        location / {
            index   index.html  index.php; 
            try_files $uri $uri/ @handler; 
            expires 30d; 
        }
    
        ## These locations would be hidden by .htaccess normally
        location /app/                { deny all; }
        location /includes/           { deny all; }
        location /lib/                { deny all; }
        location /media/downloadable/ { deny all; }
        location /pkginfo/            { deny all; }
        location /report/config.xml   { deny all; }
        location /var/                { deny all; }
    
    
        ## Disable .htaccess and other hidden files
        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }
    
        location @handler { 
            rewrite / /index.php;
        }
    
        location ~ \.php/ { 
            rewrite ^(.*\.php)/ $1 last;
        }
    
        location ~ \.php$ { 
            if (!-e $request_filename) { 
                rewrite / /index.php last; 
            } 
    
            expires         off; 
            fastcgi_pass    unix:/run/php/php7.0-fpm.sock;
            include         snippets/fastcgi-php.conf;
        }
    }