nginx

Install the latest version of NGinx, pagespeed and other modules

published on

This guide will show you how to create your own version of NGinx using the latest version at the time (1.25.2). This version supports HTTP3. We will also add in the latest version of zlib and libressl, brotli, redis, fast_cache_purge, more_headers and pagespeed (or ngx_pagespeed as it is also known).

Install prerequisites

First run the following commands to update your server and add some software we will need to download and compile everything later on.

cd ~
sudo apt update && sudo apt upgrade
sudo apt install apt-utils autoconf automake build-essential libpcre2-dev libpcre3 libpcre3-dev libssl-dev zlib1g zlib1g-dev libgd-dev libcurl4-openssl-dev liblmdb-dev libpcre++-dev libtool libxml2-dev libyajl-dev pkgconf unzip git redis-server

Now download the NGinx source code

Use the following commands to download and extract the NGinx source code:

export NGX_VER=1.25.2
wget http://nginx.org/download/nginx-$NGX_VER.tar.gz
tar -xzvf nginx-$NGX_VER.tar.gz
cd nginx-$NGX_VER/src/http/modules

Changing the version of NGinx you wish to use is as easy as changing the value in the first line above.

Download zlib, brotli, redis, fast_cache_purge, libressl and more_headers

Executing the following commands will download the source for all of the packages we will be compiling along with NGinx. Pagespeed will be added later as a dynamic module.

# download zlib
wget https://www.zlib.net/zlib-1.3.tar.gz
tar -xzvf zlib-1.3.tar.gz

 # download brotli
  git clone https://github.com/google/ngx_brotli.git
  cd ngx_brotli
  git submodule update --init
  cd ..

# download the redis module
git clone https://github.com/openresty/redis2-nginx-module.git

# download fast_cache_purge
wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
tar -xzvf ngx_cache_purge-2.3.tar.gz

# download libressl
wget https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.8.0.tar.gz
tar -xzvf libressl-3.8.0.tar.gz

# download more_headers
wget https://github.com/openresty/headers-more-nginx-module/archive/refs/tags/v0.34.tar.gz
tar -xzvf v0.34.tar.gz

Now we will configure our custom NGinx

Execute the following two commands to configure the NGinx software installation ready to be compiled and installed.

cd ../../..
./configure --with-cc-opt='-g -O2 -march=westmere -flto -funsafe-math-optimizations -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -I../libressl/build/include' --with-ld-opt='-Wl,-z,relro -Wl,--as-needed,-L../libressl/build/lib' --prefix=/var/www/html --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --modules-path=/etc/nginx/modules --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=www-data --group=www-data --with-threads --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_gunzip_module --with-http_auth_request_module --with-stream=dynamic --with-stream_ssl_module --with-stream_realip_module --with-openssl=./src/http/modules/libressl-3.8.0 --with-zlib=./src/http/modules/zlib-1.3 --with-compat --add-module=./src/http/modules/redis2-nginx-module --add-module=./src/http/modules/ngx_cache_purge-2.3 --add-module=./src/http/modules/headers-more-nginx-module-0.34

Now we need to create some directories

sudo mkdir -p /var/cache/nginx/client_temp
sudo mkdir -p /var/cache/nginx/proxy_temp
sudo mkdir -p /var/cache/nginx/fastcgi_temp
sudo mkdir -p /var/cache/nginx/uwsgi_temp
sudo mkdir -p /var/cache/nginx/scgi_temp
sudo mkdir -p /var/cache/nginx/redis_temp

Compile and install your custom version of NGinx

Now we need to execute the make command to compile your version of NGinx. Once this is complete run sudo make install to install it.

Once NGinx is installed we need to create a systemd service file by executing sudo nano /etc/systemd/system/nginx.service and adding in the following lines:

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
        
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
        
[Install]
WantedBy=multi-user.target

We now start NGinx and set it up to automatically start on a reboot of your server:

sudo systemctl daemon-reload
sudo systemctl start nginx
sudo systemctl enable nginx

Compile and install pagespeed (or ngx_pagespeed)

Now it is time to create the pagespeed object file as a dynamic module. Execute the following set of commands to make the pagespeed module and set it up in the correct place.

cd ./src/http/modules
export PSOL="jammy"
wget http://www.tiredofit.nl/psol-${PSOL}.tar.xz
git clone --depth=1 https://github.com/apache/incubator-pagespeed-ngx.git
tar xvf psol-${PSOL}.tar.xz
mv psol incubator-pagespeed-ngx
cd ../../..
./configure --with-compat --add-dynamic-module=./src/http/modules/incubator-pagespeed-ngx
make modules
sudo cp objs/ngx_pagespeed.so /etc/nginx/modules
sudo mkdir /var/ngx_pagespeed_cache
sudo chown www-data:www-data /var/ngx_pagespeed_cache

Now set up NGinx

Now that all of the compiling is done we need to configure NGinx so that we can start using it.

Create a new nginx.conf file by executing the following two lines and inserting the instructions just below them:

sudo rm /etc/nginx/nginx.conf
sudo nano /etc/nginx/nginx.conf

--- custom nginx.conf ---

user www-data;
worker_processes auto;
worker_rlimit_core 120540;
worker_rlimit_nofile 120540;
pid /var/run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

# load the pagespeed module
load_module "/etc/nginx/modules/ngx_pagespeed.so";

events {
    worker_connections  20000;
    multi_accept        on;
}

http {
  server_tokens off;

  sendfile        on;
  tcp_nopush      on;
  tcp_nodelay     on;

  reset_timedout_connection on;
  send_timeout 30s;
  keepalive_timeout 30s;
  keepalive_requests 1000;

  client_header_timeout 30;
  client_body_timeout 30;
  client_body_buffer_size 16K;
  client_max_body_size 100m;

  open_file_cache max=1000 inactive=10s; 
  open_file_cache_valid 30s; 
  open_file_cache_min_uses 2; 
  open_file_cache_errors on; 

  include       mime.types;
  default_type  application/octet-stream;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_buffer_size 4k;
  ssl_session_tickets off;
  ssl_session_timeout 1h;
  ssl_session_cache shared:SSL:50m;
  ssl_ecdh_curve X25519:prime256v1:secp384r1;
  ssl_prefer_server_ciphers on;
  ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';

  charset utf-8;
  charset_types
    text/css
    text/plain
    text/vnd.wap.wml
    text/javascript
    text/markdown
    text/calendar
    text/x-component
    text/vcard
    text/cache-manifest
    text/vtt
    application/json
    application/manifest+json;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
     '$status $body_bytes_sent "$http_referer" '
     '"$http_user_agent" "$http_x_forwarded_for"';

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

    gzip            on;
    gzip_vary       on;
    gzip_proxied    any;
    gzip_comp_level 6;
    gzip_buffers    16 8k;
    gzip_min_length 256;
    gzip_http_version 1.1;
    gzip_types
      application/atom+xml
      application/geo+json
      application/javascript
      application/x-javascript
      application/json
      application/ld+json
      application/manifest+json
      application/rdf+xml
      application/rss+xml
      application/vnd.ms-fontobject
      application/wasm
      application/x-web-app-manifest+json
      application/xhtml+xml
      application/xml
      font/eot
      font/opentype
      font/otf
      font/ttf
      image/bmp
      image/x-icon
      image/svg+xml
      text/cache-manifest
      text/calendar
      text/css
      text/javascript
      text/markdown
      text/plain
      text/xml
      text/vcard
      text/vnd.rim.location.xloc
      text/vtt
      text/x-component
      text/x-cross-domain-policy;
    gzip_disable    "MSIE [1-6]\.";

    # aio on;
    directio 4m;
    directio_alignment 512;

    # make sure to update path and zone name
    proxy_cache_path /var/cache/nginx/redis_temp levels=1:2 keys_zone=my_cache:10m inactive=60m;
    proxy_cache_key "$scheme$request_method$host$request_uri";
    proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;

include ./sites/*;

}

--- custom nginx.conf ---

Now execute the following two lines to help prevent using your NGinx installation as an open proxy:

sudo echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi.conf
sudo echo 'fastcgi_param HTTP_PROXY "";' | sudo tee -a /etc/nginx/fastcgi_params

Create a default NGinx site server block

Run the following commands to set up the default site configuration:

Execute sudo nano /etc/nginx/sites/default.conf and add the following lines of code to set up the default server block:

 

server {
    # Listen on port 80.
    listen 80 default_server;
    listen [::]:80 default_server;
 
    # The document root.
    root /var/www/html;
 
# Add index.php if you are using PHP.
    index index.html index.htm;
 
    # The server name, which isn't relevant in this case, because we only have one.
    server_name _;
 
}
 
Now run the following commands to finish off setting up a default site:
 
sudo echo "<html><head><body></body></head></html>" > /var/www/html/index.html
sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html
sudo systemctl restart nginx
 

Conclusion

You should now have a working custom NGinx installation that supports http3, brotli, fast_cache_purge, more_headers and pagespeed (along with custom versions of zlib and libressl).

All that is left is for you to create your own server block for your site and configure it the way you would like.

Notes

To use http3 in your server blocks you will need to use the following instructions which differ slightly from the older http2 and http1 versions:

server {
  listen 443 quic reuseport; 
  listen 443 ssl;
  listen [::]:443 quic reuseport;
  listen [::]:443 ssl;
  http2 on;

 
Also, at the start of any location block for the root of your site you will need to add the following:
 
location / {
   # required for browsers to direct them into quic port
   add_header Alt-Svc 'h3=":$server_port"; ma=86400';
   # signal whether we are using QUIC+HTTP/3
   add_header X-protocol $server_protocol always;
}
 
For redis to work you need to add the following code into your server block:
 
# the redis stuff - copy this into every location block you want to use it in
# change cache name and validty as suits
proxy_cache my_cache;
proxy_cache_lock on;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
 
And, in order to use pagespeed with your site you will need to add the following to your server block:
 
# this next section needs to be in every server block where pagespeed is required
pagespeed on;

# Needs to exist and be writable by nginx.  Use tmpfs for best performance.
pagespeed FileCachePath /var/ngx_pagespeed_cache;

# Ensure requests for pagespeed optimized resources go to the pagespeed handler
# and no extraneous headers get set.
location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" {
  add_header "" "";
}
location ~ "^/pagespeed_static/" { }
location ~ "^/ngx_pagespeed_beacon$" { }