Skip to content

Optimum config for NodeBB under NGINX

Performance
  • I noticed that my v3 instance of NodeBB in test was so much slower than live, but was using the same database etc. On closer inspection, the nginx configuration needed a tweak, so I’m posting my settings here so others can benefit from it. Note, that various aspects have been redacted for obvious privacy and security reasons, and to this end, you will need to substitute these values for those that exist in your own environment.

    server {
        # Ensure you put your server name here, such as example.com www.example.com etc.
    	server_name sservername;
    	listen x.x.x.x:443 ssl http2;
    	access_log /path/to/access.log;
    	error_log /path/to/error.log;
    
    	ssl_certificate /path/to/ssl.combined;
    	ssl_certificate_key /path/to/ssl.key;
        # You may not need the below values, so feel free to remove these if not required
    	rewrite ^\Q/mail/config-v1.1.xml\E(.*) $scheme://$host/cgi-bin/autoconfig.cgi$1 break;
    	rewrite ^\Q/.well-known/autoconfig/mail/config-v1.1.xml\E(.*) $scheme://$host/cgi-bin/autoconfig.cgi$1 break;
    	rewrite ^\Q/AutoDiscover/AutoDiscover.xml\E(.*) $scheme://$host/cgi-bin/autoconfig.cgi$1 break;
    	rewrite ^\Q/Autodiscover/Autodiscover.xml\E(.*) $scheme://$host/cgi-bin/autoconfig.cgi$1 break;
    	rewrite ^\Q/autodiscover/autodiscover.xml\E(.*) $scheme://$host/cgi-bin/autoconfig.cgi$1 break;
        # You may not need the above values, so feel free to remove these if not required
    
    	client_body_buffer_size 10K;
    	client_header_buffer_size 1k;
    	client_max_body_size 8m;
    	large_client_header_buffers 4 4k;
    
    	client_body_timeout 12;
    	client_header_timeout 12;
    	keepalive_timeout 15;
    	send_timeout 10;
    
    
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    
        # Socket.io Support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    	gzip on;
    	gzip_disable "msie6";
    	gzip_vary on;
    	gzip_proxied any;
    	gzip_min_length 1024;
    	gzip_comp_level 6;
    	gzip_buffers 16 8k;
    	gzip_http_version 1.1;
    	gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Download-Options "noopen" always;
        add_header Content-Security-Policy "upgrade-insecure-requests" always;
        add_header Referrer-Policy 'no-referrer' always;
        add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()" always;
        # This is the string that will show in the headers if requested, so you can put what you want in here. Keep it clean :)
        add_header X-Powered-By "<whatever you want here>" always;
        add_header X-Permitted-Cross-Domain-Policies "none" always;
        location / {
        # Don't forget to change the port to the one you use. I have a non-standard one :)
        proxy_pass http://127.0.0.1:5000;
        }
    
        location @nodebb {
            # Don't forget to change the port to the one you use. I have a non-standard one :)
            proxy_pass http://127.0.0.1:5000;
        }
    
        location ~ ^/assets/(.*) {
            root /path/to/nodebb/;
            try_files /build/public/$1 /public/$1 @nodebb;
            add_header Cache-Control "max-age=31536000";
        }
    
        location /plugins/ {
            root /path/to/nodebb/build/public/;
            try_files $uri @nodebb;
            add_header Cache-Control "max-age=31536000";
        }
    
    	if ($scheme = http) {
            # Ensure you set your actual domain here
    		rewrite ^/(?!.well-known)(.*) https://yourdomain/$1 break;
    	}
    }
    
    

    I’ve added comments at the obvious places where you need to make changes. Depending on how your server is configured, and it’s capabilities, this should improve performance no end.

    There is a caveat though, and it’s an important one

    Don’t use insane levels in the below section

    	client_body_buffer_size 10K;
    	client_header_buffer_size 1k;
    	client_max_body_size 8m;
    	large_client_header_buffers 4 4k;
    
    	client_body_timeout 12;
    	client_header_timeout 12;
    	keepalive_timeout 15;
    	send_timeout 10;
    

    Keep to these values, and if anything, adjust them DOWN to suit your server.

  • Further configuration changes can be made to the nginx core itself, although my recommendation here is to leave this alone unless you are sure you know what you are doing.

    https://webdock.io/en/docs/webdock-control-panel/optimizing-performance/optimizing-nginx-high-traffic-websites

  • phenomlabundefined phenomlab marked this topic as a regular topic on
  • hi @phenomlab , is there any reason that you do not use 4567?

    Additionally, do you scale your forum up to 3 ports?

    https://docs.nodebb.org/configuring/scaling/

  • @crazycells hi - no security reason, or anything specific in this case. However, the nginx.conf I posted was from my Dev environment which uses this port as a way of not interfering with production.

    And yes, I use clustering on this site with three instances.


Related Topics
  • configure ghost and wordpress combo

    Moved Solved WordPress
    9
    7 Votes
    9 Posts
    132 Views

    @Madchatthew I’d always post for the reasons I stated above. It’s useful information and could save someone else the headache.

  • 3 Votes
    6 Posts
    595 Views

    @DownPW said in Nginx core developer quits project in security dispute, starts “freenginx” fork:

    Maybe virtualmin implement it in the future…

    I don’t think they will - my guess is that they will stick with the current branch of NGINX. I’ve not personally tested it, but the GIT page seems to be very active. This is equally impressive

    8ac0d197-68fa-4bd8-bfa3-87237bf8f1f4-image.png

    I think the most impressive on here is the native support of HTTP 3

  • Error certification on virtualmin/Nginx

    Solved Linux
    17
    0 Votes
    17 Posts
    777 Views

    @DownPW anytime

  • Is nginx necessary to use?

    Moved Solved Hosting
    2
    1 Votes
    2 Posts
    382 Views

    @Panda said in Cloudflare bot fight mode and Google search:

    Basic question again, is nginx necessary to use?

    No, but you’d need something at least to handle the inbound requests, so you could use Apache, NGINX, Caddy… (there are plenty of them, but I tend to prefer NGINX)

    @Panda said in Cloudflare bot fight mode and Google search:

    Do these two sites need to be attached to different ports, and the ports put in the DNS record?

    No. They will both use ports 80 (HTTP) and 443 (HTTPS) by default.

    @Panda said in Cloudflare bot fight mode and Google search:

    Its not currently working, but how would the domain name know which of the two sites to resolve to without more info?
    Currently it only says the IP of the whole server.

    Yes, that’s correct. Domain routing is handled (for example) at the NGINX level, so whatever you have in DNS will be presented as the hostname, and NGINX will expect a match which once received, will then be forwarded onto the relevant destination.

    As an example, in your NGINX config, you could have (at a basic level used in reverse proxy mode - obviously, the IP addresses here are redacted and replaced with fakes). We assume you have created an A record in your DNS called “proxy” which resolves to 192.206.28.1, so fully qualified, will be proxy.sudonix.org in this case.

    The web browser requests this site, which is in turn received by NGINX and matches the below config

    server { server_name proxy.sudonix.org; listen 192.206.28.1; root /home/sudonix.org/domains/proxy.sudonix.org/ogproxy; index index.php index.htm index.html; access_log /var/log/virtualmin/proxy.sudonix.org_access_log; error_log /var/log/virtualmin/proxy.sudonix.org_error_log; location / { proxy_set_header Access-Control-Allow-Origin *; proxy_set_header Host $host; proxy_pass http://localhost:2000; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Api-Key $http_x_api_key; } location /images { index index.php index.htm index.html; root /home/sudonix.org/domains/proxy.sudonix.org/ogproxy; } fastcgi_split_path_info "^(.+\.php)(/.+)$"; listen 192.206.28.1:443 ssl http2; ssl_certificate /home/sudonix.org/domains/proxy.sudonix.org/ssl.combined; ssl_certificate_key /home/sudonix.org/ssl.key; }

    The important part here is server_name proxy.sudonix.org; as this is used to “map” the request to the actual domain name, which you can see in the root section as root /home/sudonix.org/domains/proxy.sudonix.org/ogproxy;

    As the DNS record you specified matches this hostname, NGINX then knows what to do with the request when it receives it.

  • NodeBB v3.0.0-rc.1

    Performance
    1
    1 Votes
    1 Posts
    131 Views
    No one has replied
  • NodeBB slow after DB recovery

    Solved Performance
    1
    5 Votes
    1 Posts
    293 Views
    No one has replied
  • nginx seo urls

    Solved Configure
    15
    3 Votes
    15 Posts
    1k Views

    @riekmedia that looks fine to me

  • Digitalocean Ubuntu configuration

    Solved Linux
    33
    12 Votes
    33 Posts
    3k Views

    @phenomlab thank you! not me 🙂