As mentioned in my older article on the subject, for many years Nginx had no hook for dynamically adding new modules, which meant having to recompile Nginx to add functionality. But the Nginx company has worked to address that issue: as of version 1.9.11, Nginx supports dynamic module loading.
Still, there may be cases where you want to recompile Nginx to permanently change its startup parameters or add/remove modules. This article presents two approaches to recompile Nginx 1.9+: one using the current version of Nginx installed from the Ubuntu 16.04 main repos, and one using the latest developmental (“mainline”) version of Nginx from the Nginx PPA. As before, we’re going to be compiling in the nginx-http-push-stream module as an example.
Method 1: Recompile Nginx from the Ubuntu.com Repos
Starting with a bare image of Ubuntu 16.04 Server, we install Nginx, gcc, and make:
root@ubuntu:/# apt-get install nginx build-essential
Let’s check our Nginx version and compile flags. We’re going to be using this almost as-is to recompile.
root@ubuntu:/# nginx -V nginx version: nginx/1.10.0 (Ubuntu) built with OpenSSL 1.0.2g-fips 1 Mar 2016 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads
We’ll be adding two new compilation flags:
--sbin-path=/usr/sbin/nginx --add-module=/opt/nginx-push-stream-module
The first ensures that our Nginx binary lives in the same location as before, while the second ensures that our push-stream module is compiled in.
Get the latest source code for our Nginx version:
root@ubuntu:/# cd /opt root@ubuntu:/opt/# wget http://nginx.org/download/nginx-1.10.1.tar.gz root@ubuntu:/opt/# tar -xvzf nginx-1.10.1.tar.gz
Get the push-stream module:
root@ubuntu:/opt/# git clone http://github.com/wandenberg/nginx-push-stream-module.git
Install some prerequisites:
root@ubuntu:/# apt-get install libpcre3-dev libssl-dev libxml2-dev libxslt-dev libgd-dev libgeoip-dev
Stop Nginx:
root@ubuntu:/# /etc/init.d/nginx stop
Start our recompilation:
root@ubuntu:/opt/nginx-1.10.1# ./configure --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --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 --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads --add-module=/opt/nginx-push-stream-module
The MakeFile created by ./configure lives in /opt/nginx-1.10.1/objs/. If everything worked correctly, ngx-http-push-stream-module.c and ngx-http-push-stream-module.o will be referenced in the MakeFile.
Finish things up:
root@ubuntu:/opt/nginx-1.10.1# make root@ubuntu:/opt/nginx-1.10.1# make install
Start Nginx and check the version and compile flags:
root@ubuntu:/opt/nginx-1.10.1# /etc/init.d/nginx start [ ok ] Starting nginx (via systemctl): nginx.service.
root@ubuntu:/opt/nginx-1.10.1# nginx -V nginx version: nginx/1.10.1 built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.1) built with OpenSSL 1.0.2g-fips 1 Mar 2016 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --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 --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads --add-module=/opt/nginx-push-stream-module
What we’ve effectively done here is to compile a drop-in replacement for the nginx binary supplied from the Ubuntu main repos. Our new binary lives in the same location as the old one — /usr/sbin/nginx — and runs from the /etc/init.d/nginx startup file with no changes. The paths to the lock and log files, and the default config directory, are also the same as before.
Next, we probably want to lock Nginx so the package manager won’t overwrite our custom binary:
root@ubuntu:/opt/nginx-1.10.1# apt-mark hold nginx nginx set on hold.
Finally, we can test our module, per the push-stream documentation.
root@ubuntu:/opt/nginx-push-stream-module/misc# NGINX_PUSH_STREAM_MODULE_PATH=/opt/nginx-push-stream-module root@ubuntu:/opt/nginx-push-stream-module/misc# nginx -c $NGINX_PUSH_STREAM_MODULE_PATH/misc/nginx.conf -t nginx: the configuration file /opt/nginx-push-stream-module/misc/nginx.conf syntax is ok nginx: configuration file /opt/nginx-push-stream-module/misc/nginx.conf test is successful
[In our configuration, the nginx-push-stream-module/misc/nginx.conf file requires a few tweaks to pass, but that’s not really the point here. The point is that Nginx recognizes our module.]
Method 2: Recompile Nginx from the Nginx PPA
The procedure here is largely as before, but we’re specifying a different version of Nginx.
Add the Nginx Mainline PPA:
root@ubuntu:/# add-apt-repository ppa:nginx/development
Let’s see what’s available:
root@ubuntu:/# apt-cache madison nginx nginx | 1.11.2-0+xenial0 | http://ppa.launchpad.net/nginx/development/ubuntu xenial/main amd64 Packages nginx | 1.11.2-0+xenial0 | http://ppa.launchpad.net/nginx/development/ubuntu xenial/main i386 Packages nginx | 1.10.0-0ubuntu0.16.04.2 | http://us.archive.ubuntu.com/ubuntu xenial-updates/main amd64 Packages nginx | 1.10.0-0ubuntu0.16.04.2 | http://us.archive.ubuntu.com/ubuntu xenial-updates/main i386 Packages nginx | 1.10.0-0ubuntu0.16.04.2 | http://security.ubuntu.com/ubuntu xenial-security/main amd64 Packages nginx | 1.10.0-0ubuntu0.16.04.2 | http://security.ubuntu.com/ubuntu xenial-security/main i386 Packages nginx | 1.9.15-0ubuntu1 | http://us.archive.ubuntu.com/ubuntu xenial/main amd64 Packages nginx | 1.9.15-0ubuntu1 | http://us.archive.ubuntu.com/ubuntu xenial/main i386 Packages
Get the latest Nginx mainline version, and check our compiler flags:
root@ubuntu:/# apt-get install nginx=1.11.2-0+xenial
root@ubuntu:/# nginx -V nginx version: nginx/1.11.2 built with OpenSSL 1.0.2g-fips 1 Mar 2016 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads --add-module=/build/nginx-EdIIgW/nginx-1.11.2/debian/modules/nginx-auth-pam --add-module=/build/nginx-EdIIgW/nginx-1.11.2/debian/modules/nginx-dav-ext-module --add-module=/build/nginx-EdIIgW/nginx-1.11.2/debian/modules/nginx-echo --add-module=/build/nginx-EdIIgW/nginx-1.11.2/debian/modules/nginx-upstream-fair --add-module=/build/nginx-EdIIgW/nginx-1.11.2/debian/modules/ngx_http_substitutions_filter_module
Grab the latest source code and our push-stream module:
root@ubuntu:/opt# wget http://nginx.org/download/nginx-1.11.3.tar.gz root@ubuntu:/opt# tar -xvzf nginx-1.11.3.tar.gz root@ubuntu:/opt# git clone http://github.com/wandenberg/nginx-push-stream-module.git
Install some dependencies:
root@ubuntu:/# apt-get install libpcre3-dev libssl-dev libxml2-dev libxslt-dev libgd-dev libgeoip-dev
Recompile Nginx:
root@ubuntu:/opt/nginx-1.11.3# ./configure --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --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 --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads --add-module=/opt/nginx-push-stream-module
Note: if you want to retain the other modules added in by add-module above, you can snag them from the Nginx wiki. I haven’t bothered here in the interest of saving time.
As before, our MakeFile lives in /opt/nginx-1.11.3/objs/. Let’s finish things up:
root@ubuntu:/opt/nginx-1.11.3# make root@ubuntu:/opt/nginx-1.11.3# make install
Start up Nginx and check our new compiler flags:
root@ubuntu:/opt/nginx-1.11.3# /etc/init.d/nginx start [ ok ] Starting nginx (via systemctl): nginx.service. root@ubuntu:/opt/nginx-1.11.3# nginx -V nginx version: nginx/1.11.3 built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.1) built with OpenSSL 1.0.2g-fips 1 Mar 2016 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --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 --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads --add-module=/opt/nginx-push-stream-module
Finally, we probably want to lock Nginx so the package manager won’t overwrite our custom binary:
root@ubuntu:/opt/nginx-1.11.3# apt-mark hold nginx nginx set on hold.