15 октября 2017

Компиляция динамических модулей для NGINX (на примере HTTP Redis)

Алексей Доронин
Руководитель, разработчик, дизайнер

Подключение дополнительных модулей к NGINX не самая тривиальная вещь для веб-разработчиков. Рассмотрим эту задачу на примере сборки NGINX с модулем HTTP Redis (ngx_http_redis).

Раньше, для подключения модулей к NGINX, нужно было полностью компилировать и веб-сервер и желаемые модули, но начиная с версии 1.9.11 можно этого не делать, а обойтись командой make modules, но для этого необходимо правильно сконфигурировать всю сборку NGINX.

Итак, сначала нужно узнать какая версия NGINX установлена. Если меньше 1.9.11, то читаем Установка последней версии NGINX

nginx -v

##
nginx version: nginx/1.13.5

Скачиваем и распаковываем в домашнюю директорию ту же самую версию NGINX (в нашем случае 1.13.5):

wget https://nginx.ru/download/nginx-1.13.5.tar.gz
tar -xzvf nginx-1.13.5.tar.gz

Скачиваем и распаковываем модуль HTTP Redis:

wget https://people.freebsd.org/~osa/ngx_http_redis-0.3.8.tar.gz
tar -xzvf ngx_http_redis-0.3.8.tar.gz

Итого, у нас должны быть:

1. Установленный и работающий NGINX >= 1.9.11

2. Скаченный дистрибутив NGINX той же версии, что в пункте 1

3. Скаченный дистрибутив модуля HTTP Redis

Теперь мы можем скомпилировать модуль и подключить его в файле nginx.conf командой load_module my_module.so.

Нужно узнать текущую конфигурацию билда NGINX, смотрим его командой:

nginx -V

Заходим в директорию, куда распаковался скаченный NGINX:

cd nginx-1.13.5/

Готовимся к билду. Он проходит в два этапа: «configure» и «make».

Configure

Нужно после команды ./configure поставить то, что показано у вас в команде nginx -V. В моём случае (Ubuntu 16, nginx 1.13.5) получается:

./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --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=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie' --add-dynamic-module=../ngx_http_redis-0.3.8

В конце добавлен путь к динамическому модулю, который нужно скомпилировать (мы находимся в директории nginx ~/nginx-1.13.5), не забудьте его добавить:

--add-dynamic-module=../ngx_http_redis-0.3.8

Нажимаем Enter. Если вам повезло и на выходе нет ошибок, отлично.

Make

Дальше создаём модуль командой:

make modules

Если опять нет ошибок, то вы получите файл:

nginx-1.13.5/objs/ngx_http_redis_module.so

Подключаем его к NGINX, для этого в /etc/nginx/nginx.conf добавляем в самый верх строку с load_module, указываем полный путь до файла:

sudo nano /etc/nginx/nginx.conf
 
## Load our module:
load_module /home/vagrant/nginx-1.13.5/objs/ngx_http_redis_module.so;

Перезагружаем:

sudo nginx -s reload

Если нет сообщения об ошибке, значит модуль подключился! Можно переписать ngx_http_redis_module.so в более подходящее место и не забыть изменить путь к нему в nginx.conf.

Обновление NGINX

Модуль привязан к конкретной версии NGINX, если мы её обновим, то, скорее всего, он перестанет работать. Поэтому нужно пакет NGINX поставить на холд — заблокировать от обновления:

## sudo apt-mark hold <package>
sudo apt-mark hold nginx

## Remove HOLD
# sudo apt-mark unhold <package-name>

## Check HOLD
#apt-mark showhold

Ошибки и проблемы

Проблемы «configure»

1. Не проходит конфигурация билда, команда ./configure возвращает ошибку (после этого нельзя запустить make modules)

Ошибки такого вида:

./configure: error: the HTTP gzip module requires the zlib library.
You can either disable the module by using --without-http_gzip_module
option, or install the zlib library into the system, or build the zlib library
statically from the source with nginx by using --with-zlib=<path> option.

В данном примере, если мы изменим конфигурацию (чтобы проходил ./configure) и поставим --without-http_gzip_module, скорее всего, на этапе подключения модуль не подойдёт к nginx (см. ниже)

В процессе могут вылетать разные требования к библиотекам, которые нужны для билда nginx (или не вылетать). Эти пакеты может понадобиться установить самостоятельно (а могут уже стоять):

1. "./configure: error: C compiler cc is not found"

sudo apt-get install build-essential

2. PCRE

sudo apt-get install libpcre3
sudo apt-get install libpcre3-dev

3. OpenSSL

sudo apt-get install libssl-dev

4. HTTP XSLT module requires the libxml2/libxslt

sudo apt-get install libxml2
sudo apt-get install libxml2-dev
sudo apt-get install libxslt-dev

5. «...the HTTP image filter module requires the GD library»

sudo apt-get install libgd-dev

6. GeoIP

sudo apt-get install libgeoip-dev

7. PAM authentication module

sudo apt-get install libpam-dev

Проблемы подключения

Когда удалось скомпилировать модуль, но не работает подключение в NGINX:

— Модуль module-name.so компилируется, но при перезагрузке nginx пишет, что не та версия — перепроверить и скачать соответствующую версию.

— «is not binary compatible» ошибка примерно такая:

nginx: [emerg] module "/usr/share/nginx/modules/ngx_http_redis_module.so" is not binary compatible in /etc/nginx/nginx.conf:1

Это значит неправильно сконфигурирован билд модуля. Разбираемся с опциями ./configure: неправильно скопировали, не все зависимости установлены и так далее.