suiteCRM nginx config

following we want share our https(443) nginx config. at least we have a performance boost about 200-400% with suitecrm

Ubuntu 12.04 - minimal
nginx version: nginx/1.6.2
php-fpm: PHP 5.6.6-1
mySQL 5.5.41

nginx vhost config:

server {
  listen yourdomain.com:443;

    root /var/www/yourdomain;
    index index.php index.html index.htm;
    server_name yourdomain.com.de;
     location = /favicon.ico {
                log_not_found off;
                access_log off;
       }
       location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
       }
       # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
       location ~ /\. {
                deny all;
                access_log off;
                log_not_found off;
       }

       # Add trailing slash to */wp-admin requests.
       rewrite /wp-admin$ $scheme://$host$uri/ permanent;
       location ~*  \.(jpg|jpeg|png|gif|css|js|ico)$ {
                expires max;
                log_not_found off;
       }
    error_log /var/log/nginx/yourdomain_error.log;

    ssl on;
        ssl_certificate /etc/ssl/com/yourdomain/yourdomain_com_de_bundle.crt;
        ssl_certificate_key /etc/ssl/com/yourdomain/yourdomain_com_de.key; 
#enables all versions of TLS, but not SSLv2 or 3 which are weak and now deprecated.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

#Disables all weak ciphers
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

ssl_prefer_server_ciphers on;

location / {
    if (!-d $request_filename){
        set $rule_0 true; 
    }
    if (!-f $request_filename){
        set $rule_0 true;
    }
    if ($rule_0){
        rewrite ^/rest/(.*)$ /api/rest.php?__sugar_url=$1 last;
        rewrite ^/cache/api/metadata/lang_(.._..)_(.*)_public.json$ /rest/v10/lang/public/$1?platform=$2 last;
        rewrite ^/cache/api/metadata/lang_(.._..)_([^_]*).json$ /rest/v10/lang/$1?platform=$2 last;
        rewrite ^/portal/(.*)$ /portal2/$1 last;
        rewrite ^/portal$ /portal/? permanent;
    }

    try_files $uri $uri/ index.php;
}


  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_pass   unix:/var/run/php5-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include /etc/nginx/fastcgi_params;
    fastcgi_param  QUERY_STRING     $query_string;
    fastcgi_param  REQUEST_METHOD   $request_method;
    fastcgi_param  CONTENT_TYPE     $content_type;
    fastcgi_param  CONTENT_LENGTH   $content_length;
    fastcgi_intercept_errors        on;
    fastcgi_ignore_client_abort     off;
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
  }   
}

nginx.conf

user www-data;
worker_processes 8;
pid /run/nginx.pid;

events {
	worker_connections 768;
	 multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 2;
	types_hash_max_size 2048;
	server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;
	##
	# File Cache Settings
	##

	open_file_cache max=5000 inactive=20s;
	open_file_cache_valid 30s;
	open_file_cache_min_uses 2;
	open_file_cache_errors on;
	fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=microcache:10m max_size=1000m inactive=60m;
	# set client body size to 2M #
	client_max_body_size 200M;

	##
	# SSL Settings
	##
	ssl_session_cache shared:SSL:10m;
	ssl_session_timeout 10m;
	ssl_ciphers HIGH:!aNULL:!MD5;
	ssl_prefer_server_ciphers on;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;
	gzip_static on;
	gzip_disable "msie6";
	gzip_http_version 1.1;
	gzip_vary on;
	gzip_comp_level 6;
	gzip_proxied any;
	gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
	gzip_buffers 16 8k;
	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}


#mail {
#	# See sample authentication script at:
#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
# 
#	# auth_http localhost/auth.php;
#	# pop3_capabilities "TOP" "USER";
#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
# 
#	server {
#		listen     localhost:110;
#		protocol   pop3;
#		proxy      on;
#	}
# 
#	server {
#		listen     localhost:143;
#		protocol   imap;
#		proxy      on;
#	}
#}

hope it helps to speed up.

6 Likes

Sticky please!

Hmmm, there seems to be a few problems with that config. The nginx.conf doesn’t need to be touched, there’s some irrelevant stuff about fastcgi_cache which isn’t used, a stray Wordpress directive and so on. Here’s the key parts that worked for me:

server {
 
# .... usual stuff goes here

	index index.php index.html index.htm;

	# Block access to stuff in the root
	location ~* \.(pl|cgi|py|sh|lua|log|md5)$ {
        return 444;
}
	
	# Block access to data folders
	location ~ /(soap|cache|upload|xtemplate|data|examples|include|log4php|metadata|modules|diagnostic|blowfish|emailmandelivery)/.*\.(php|pl|py|jsp|asp|sh|cgi|tpl|log|md5)$ {
    return 444;
}
	
	
	include snippets/gzip_expires_etc.conf;


location / { 
	try_files $uri $uri/ =404; 
	index index.html index.htm index.php; 
} 	
	

  location ~ \.php$ {
    try_files $uri =404;
	fastcgi_pass unix:/var/run/fpm.sock;
  }   
}

Does all that make sense? No need for all those rewrites and IFs.

Getting " Server response time: 0.12 seconds" on a $5 VPS with A+ class SSL running.

If you’d like a more full and complete config, please let me know.

Gah! I spotted an ommision in there - I didn’t realise you couldn’t edit after a certain period. I’ll make a link as a “gist” on github which I can keep up to date, and then ask to edit the page to reflect that.

Interested to know if you are still on nginx and have not had issues over the last 10 months? thanks in advance

Can I have link to gist please

Hi there; try something like this:

https://gist.github.com/lardconcepts/ae8ca9f248842be067141a9e7a505a98

Not sure if it works now - I gave up on SuiteCRM as the support in the forums seemed non-existant and the software was too quirky.

I now use a different CRM which is free up to 100 customers and it just works great with nothing to install.

Good luck!

I have a similar setup. We are currently developing on SuiteCRM 7.8.3 to enhance and migrate our current SuiteCRM 7.4.3 install. Our dev and future production environment will consist of:

CentOS7
PHP7
Nginx
php-fpm
MariaDB (Separate server on CentOS7)

I used letsencrypt/certbot to generate ssl certs.

My config files change as I install letsencrypt.

No SSL
/etc/nginx/conf.d/sub.mydomain.tld.conf
The server is only accesible from a specific IP except for the ./well-known directory


server {


        listen   [::]:80;
	listen 80;

        root /var/www/vhosts/sub.mydomain.tld/httpdocs;
        index index.php index.html index.htm;
        server_name  sub.mydomain.tld;
	client_max_body_size 500m;#allows file uploads up to 500 megs

        location / {
                try_files $uri $uri/ /index.html;
		allow x.x.x.x;
		allow 127.0.0.1;
	        deny all;
		#allow all;
        }

        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
              root /usr/share/nginx/www;
        }

        location ~ .php$ {
                try_files $uri =404;
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }

	location /.well-known {
               allow all;
	}
}

I run letsencrypt certonly command with the webroot plugin. Plenty of docs online on how to do this.


letsencrypt certonly -a webroot --webroot-path=/var/www/vhosts/sub.mydomain.tld/httpdocs -d sub.mydomain.tld

Once this is done. I remove or rename /etc/nginx/conf.d/sub.mydomain.tld.conf to
/etc/nginx/conf.d/ssl_sub.mydomain.tld.conf

With contents of


server {


        listen   [::]:443;
	listen 443 http2 ssl;

	server_name  sub.mydomain.tld;
	ssl_certificate /etc/letsencrypt/live/sub.mydomain.tld/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/sub.mydomain.tld/privkey.pem;        

	########################################################################
	# from https://cipherli.st/                                            #
	# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html #
	########################################################################

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_prefer_server_ciphers on;
	ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
	ssl_ecdh_curve secp384r1;
	ssl_session_cache shared:SSL:10m;
	ssl_session_tickets off;
	ssl_stapling on;
	ssl_stapling_verify on;
	resolver 8.8.8.8 8.8.4.4 valid=300s;
	resolver_timeout 5s;
	# Disable preloading HSTS for now.  You can use the commented out header line that includes
	# the "preload" directive if you understand the implications.
	#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
	add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
	add_header X-Frame-Options DENY;
	add_header X-Content-Type-Options nosniff;

	##################################
	# END https://cipherli.st/ BLOCK #
	##################################
	
	ssl_dhparam /etc/ssl/certs/dhparam.pem;	

	root /var/www/vhosts/sub.mydomain.tld/httpdocs;
        index index.php index.html index.htm;
	client_max_body_size 500m;#allows file uploads up to 500 megs

        location / {
                try_files $uri $uri/ /index.html;
		allow x.x.x.x;
		allow 127.0.0.1;
	        deny all;
		#allow all;
        }

        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
              root /usr/share/nginx/www;
        }

        location ~ .php$ {
                try_files $uri =404;
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }

	location /.well-known {
               allow all;
	}

}

This works excellent, it was a pain to wrap my head around nginx and php7 and php-fpm. Once it was running it was a noticeable difference.

1 Like
  1. nginx.conf

    location ~ /Api/ {
    index index.php;
    try_files $uri @rewrite_api;

    location ~ .php {
    include fastcgi.conf;
    fastcgi_pass 127.0.0.1:9000; // according to server in my case its localhost ip In case server you should the fastcgi_pass url
    }
    }
    location @rewrite_api {
    rewrite ^/Api/(.*)?$ /Api/index.php/$1 last;
    }

  2. Go to root dir run these command

    composer install
    cd Api/V8/OAuth2/
    openssl genrsa -out private.key 2048
    openssl rsa -in private.key -pubout -out public.key
    chmod 600 private.key public.key
    composer dump-autoload

3 . sudo cd vendor/slim/slim/Slim/Http
open Uri.php

public static function createFromEnvironment(Environment $env)

    {

        // Scheme

        $isSecure = $env->get('HTTPS');

        $scheme = (empty($isSecure) || $isSecure === 'off') ? 'http' : 'https';

        // Authority: Username and password

        $username = $env->get('PHP_AUTH_USER', '');

        $password = $env->get('PHP_AUTH_PW', '');

        // Authority: Host and Port

        if ($env->has('HTTP_HOST')) {

            $host = $env->get('HTTP_HOST');

            // set a port default

            $port = null;

        } else {

            $host = $env->get('SERVER_NAME');

            // set a port default

            $port = (int)$env->get('SERVER_PORT', 80);

        }

        if (preg_match('/^(\[[a-fA-F0-9:.]+\])(:\d+)?\z/', $host, $matches)) {

            $host = $matches[1];

            if (isset($matches[2])) {

                $port = (int) substr($matches[2], 1);

            }

        } else {

            $pos = strpos($host, ':');

            if ($pos !== false) {

                $port = (int) substr($host, $pos + 1);

                $host = strstr($host, ':', true);

            }

        }

        // Path

        $requestScriptName = (string) parse_url($env->get('SCRIPT_NAME'), PHP_URL_PATH);

        $requestScriptDir = dirname($requestScriptName);

        // parse_url() requires a full URL. As we don't extract the domain name or scheme,

        // we use a stand-in.

        $requestUri = (string) parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_PATH);

        $string= "/index.php";

        $index_exit = strpos($requestScriptName ,$string);

        if($index_exit){

            $requestScriptName =  substr($requestScriptName ,0,$index_exit+ strlen($string));

        }

        $basePath = '';

        $virtualPath = $requestUri;

        if (stripos($requestUri, $requestScriptName) === 0) {

            $basePath = $requestScriptName;

        } elseif ($requestScriptDir !== '/' && stripos($requestUri, $requestScriptDir) === 0) {

            $basePath = $requestScriptDir;

        }

        if ($basePath) {

            $virtualPath = ltrim(substr($requestUri, strlen($basePath)), '/');

        }

        $is_index = strpos($basePath,"/index.php");

        if($is_index){

        }

        // Query string

        $queryString = $env->get('QUERY_STRING', '');

        if ($queryString === '') {

            $queryString = parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_QUERY);

        }

        // Fragment

        $fragment = '';

        // Build Uri

        $uri = new static($scheme, $host, $port, $virtualPath, $queryString, $fragment, $username, $password);

        if ($basePath) {

            $uri = $uri->withBasePath($basePath);

        }

        return $uri;

    }

step 4. php.ini

uncomment 1.extension=openssl
comment 2. ;cgi.fix_pathinfo=1

step 5 . composer dump-autoload (if branch changed)
then restart server

step6 . use index.php after Api for api hit
eg {root url}/Api/index.php/access_token

@abhishek07456
Hi

I’m trying to setting Nginx for supporting SuiteCRM API V8
I have 404 page when access to /Api/index.php/access_token or /Api/access_token
As I understood you have found a solution for it?

I did all steps you wrote but in doesn’t work

Also, I just wanted to ask what I shlud do on step 3?
My vendor/slim/slim/Slim/Http/open Uri.php already has the same createFromEnvironment funcion

4 posts were split to a new topic: SuiteCRM v8.0 nginx config