leev / ngx_http_geoip2_module

Nginx GeoIP2 module
BSD 2-Clause "Simplified" License
983 stars 186 forks source link

is not binary compatible #82

Closed measwel closed 5 years ago

measwel commented 5 years ago

I have build the module with the same nginx version (1.14.0) and the same build flags like this: ./configure --add-dynamic-module=/home/marek/ngx_http_geoip2_module $(nginx -V)

nginx -t shows: nginx: [emerg] module "/usr/share/nginx/modules/ngx_http_geoip2_module.so" is not binary compatible in /etc/nginx/nginx.conf:5

what could be wrong?

porjo commented 5 years ago

I'm seeing this also using Nginx 1.16 source, then attempting to use the resulting module with Centos/Rhel nginx-1.16 package. Sorry, I don't have any suggested workarounds.

leev commented 5 years ago

You need to build nginx and the module with the same build flags. So compiling nginx, then taking its flags and adding --add-dynamic-module to now build the module, unless you also take the nginx binary produced by that build, they will have been built differently.

measwel commented 5 years ago

Thank you leev. Are you saying the module build failed because nginx itself was not compiled before it?

leev commented 5 years ago

No. To my knowledge, nginx and the modules need to be compiled with the same flags. Eg, if you did: ./configure -flag1 to build nginx. Then you do ./configure --add-dynamic-module=/home/marek/ngx_http_geoip2_module $(nginx -V) to build the module.

You have built nginx with -flag1 and the module with -flag1 --add-dynamic-module..., which is different. They need to be built with the same flags.

measwel commented 5 years ago

$(nginx -V) outputs all the flags of the currently system installed nginx. I never built nginx from source to use it ( only as part of building the module). I use the system installed nginx.

leev commented 5 years ago

Yes, I don't believe that is possible. You aren't compiling them with the same flags. Your nginx binary has no knowledge of the module. Please consult the nginx documentation for dynamic modules.

measwel commented 5 years ago

Leev. You have completely lost me I'm afraid. I have no idea anymore how the module should be compiled.

measwel commented 5 years ago

The steps I have taken are:

  1. Checked my system installed version: nginx version: nginx/1.14.0 (Ubuntu)
  2. Downloaded sources for that version.
  3. ./configure --add-dynamic-module=/home/marek/ngx_http_geoip2_module $(nginx -V)
  4. make && make install
  5. copied the module to the modules directory
  6. loaded it in /etc/nginx/nginx.conf : load_module modules/ngx_http_geoip2_module.so;

I don't know where I went wrong. Maybe I should specify the flags explicitly.

measwel commented 5 years ago

Specifying the flags explicitly at the build step ( instead of using $(nginx -V) ) solved the problem. The module loads now. Thank you.

measwel commented 5 years ago

Thank you for developing this module. Very useful.

majaray commented 5 years ago

Specifying the flags explicitly at the build step ( instead of using $(nginx -V) ) solved the problem. The module loads now. Thank you.

Hi @measwel I having the same issue on the same ubuntu version u have. May I know what's the flags that u specify explicitly now?

measwel commented 5 years ago

Hi. I just used the command nginx -V and copied all flags output by it:

--with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-DUghaW/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --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 --modules-path=/usr/lib/nginx/modules --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-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module

Then I configured the build: ./configure --add-dynamic-module=/home/marek/ngx_http_geoip2_module {plus the flags shown above}

Some of these are not necessary, as they define the build of other modules, but I just kept them all.

joaompinto commented 4 years ago

The following method allows automation:

nginx -V 2>&1 | egrep  "^configure" | cut -d: -f2 > /tmp/nginx_build_options.txt
sh -c "./configure $(cat /tmp/nginx_build_options.txt) --add-dynamic-module=..."
centminmod commented 4 years ago

AFAIK, if you want to drop in dynamic built nginx modules, nginx needs to be compiled with --with-compat flag too https://www.nginx.com/blog/nginx-dynamic-modules-how-they-work/#compatibility. That's how I build Nginx and dynamic modules. HTH

First, compatibility between builds.

This is actually related to signature checking. It’s a pain to compile dynamic modules if you do it outside of NGINX itself. You have to use the same configure options, or signature checking prevents you from loading the module.

We are currently working to make this easier. With a special option to configure, perhaps something like --with-compat, NGINX will just compile in all the structure fields it knows about, so that modules will be compatible even with different configure options. You will be able to load them even if you compile NGINX and the module with a different set of configure options.

@joaompinto that method may not work depending how Nginx is compiled.

For instance all i'd get would be

nginx -V 2>&1 | egrep  "^configure" | cut -d: -f2
 --with-ld-opt='-Wl,-E -L/usr/local/zlib-cf/lib -L/usr/local/lib -ljemalloc -lpcre -Wl,-z,relro -Wl,-rpath,/usr/local/zlib-cf/lib

as opposed to my full Nginx configure on CentOS 7.7 64bit

nginx -V
nginx version: nginx/1.17.8 (230120-223604-centos7-50774ee)
built by gcc 8.3.1 20190311 (Red Hat 8.3.1-3) (GCC) 
built with OpenSSL 1.1.1d  10 Sep 2019
TLS SNI support enabled

configure arguments: --with-ld-opt='-Wl,-E -L/usr/local/zlib-cf/lib -L/usr/local/lib -ljemalloc -lpcre -Wl,-z,relro -Wl,-rpath,/usr/local/zlib-cf/lib:/usr/local/lib -flto=8 -fuse-ld=gold' --with-cc-opt='-I/usr/local/zlib-cf/include -I/usr/local/include -m64 -march=native -DTCP_FASTOPEN=23 -falign-functions=32 -g -O3 -Wno-error=strict-aliasing -fstack-protector-strong -flto=8 -fuse-ld=gold --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wimplicit-fallthrough=0 -fcode-hoisting -Wp,-D_FORTIFY_SOURCE=2 -Wno-deprecated-declarations -gsplit-dwarf' --sbin-path=/usr/local/sbin/nginx --conf-path=/usr/local/nginx/conf/nginx.conf --build=230120-223604-centos7-50774ee --with-compat --with-http_stub_status_module --with-http_secure_link_module --with-http_flv_module --with-http_mp4_module --add-module=../nginx-rtmp-module --with-libatomic --with-http_gzip_static_module --add-dynamic-module=../ngx_brotli --add-dynamic-module=../ngx_http_geoip2_module --with-http_sub_module --with-http_addition_module --with-http_image_filter_module=dynamic --with-http_geoip_module --with-stream_geoip_module --with-stream_realip_module --with-stream_ssl_preread_module --with-threads --with-stream --with-stream_ssl_module --with-http_slice_module --with-http_realip_module --add-dynamic-module=../ngx-fancyindex-0.4.2 --add-module=../ngx_cache_purge-2.5 --add-dynamic-module=../ngx_devel_kit-0.3.0 --add-dynamic-module=../set-misc-nginx-module-0.32 --add-dynamic-module=../echo-nginx-module-0.61 --add-module=../redis2-nginx-module-0.15 --add-module=../ngx_http_redis-0.3.7 --add-dynamic-module=../lua-nginx-module-0.10.15 --add-module=../memc-nginx-module-0.18 --add-module=../srcache-nginx-module-0.31 --add-dynamic-module=../headers-more-nginx-module-0.33 --with-pcre-jit --with-zlib=../zlib-cloudflare-1.3.0 --with-http_ssl_module --with-http_v2_module --with-http_v2_hpack_enc --with-openssl=../openssl-1.1.1d --with-openssl-opt='enable-ec_nistp_64_gcc_128 enable-tls1_3 -fuse-ld=gold'

joaompinto commented 4 years ago

On my specific case I had the requirement to use a RedHat provided nginx image which was built without --compat, and yes that egrep | cut needs some love :)

Stef-33560 commented 4 years ago

Hi !

With nginx-1.14.2 on debian 10 buster (nginx already installed with apt), I've done the following steps:

git clone https://github.com/leev/ngx_http_geoip2_module.git
version=$(nginx -v 2>&1|cut -d"/" -f 2)
wget http://nginx.org/download/nginx-$version.tar.gz && tar zxfv nginx-$version.tar.gz && cd nginx-$version
apt install libmaxminddb0 libmaxminddb-dev mmdb-bin geoipupdate 
apt install libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev
./configure  --add-dynamic-module=../ngx_http_geoip2_module $(nginx -V) --with-compat
make modules
echo "load_module modules/ngx_http_geoip2_module.so;" > /etc/nginx/modules-available/mod-http-geoip2.conf
ln -s /etc/nginx/modules-available/mod-http-geoip2.conf /etc/nginx/modules-enabled/60-mod-http-geoip2.conf
cp objs/ngx_http_geoip2_module.so /usr/share/nginx/modules/ngx_http_geoip2_module.so

nginx -t gives :

nginx: [emerg] module "/usr/share/nginx/modules/ngx_http_geoip2_module.so" is not binary compatible in /etc/nginx/modules-enabled/60-mod-http-geoip2.conf:1
nginx: configuration file /etc/nginx/nginx.conf test failed

What the hell I'm doing wrong ?

Thanks a lot :)

trey-jones commented 3 years ago

AFAIK, if you want to drop in dynamic built nginx modules, nginx needs to be compiled with --with-compat flag too

This doesn't seem to be so, at least on my Debian 10 nginx install (1.14.2), nginx -V does not include --with-compat but I was able to successfully build and use this module without replacing the nginx binary.

I also discovered that you needn't include any of the --add-dynamic-modules from the binary you are using in order to build another dynamic module. I got the options like so, though if there's anything after --add-dynamic-module then it will probably fail:

NGINX_CONFIGURE_OPTIONS=$(nginx -V 2>&1 | grep configure | sed -e 's/^configure arguments: //' -e 's/ --add-dynamic-module.*$//')

adrian-green commented 2 years ago

This process of configuring by discovering existing flags should be added into the readme. Once it's understood - and easily findable in the main doc, most people will immediately be able to fix their specific variation of the issue.

Many people only compile modules such as this on an ad-hoc basis - having the knowhow to match compile flags exactly does not sit at the top of mind.

Admittedly the readme does say to compile direct from source, but it would be super helpful (I think) to add in a small aside in the docs to assist those who might need to contend with alternative build scenarios.

I had the same issue - but as soon as I found the flags (nginx -V) and could add them to the --add-dynamic-module during configure, all worked fine. Please consider updating the readme, it may save a few headaches for those who are do this infrequently.

Btw - I had the exact same issue a year ago - but had already forgotten (no notes!) - the readme would help enormously for people like me. :-)

kilvn commented 1 year ago
nginx -V 2>&1 | egrep  "^configure" | cut -d: -f2

like this:

./configure $(nginx -V 2>&1 | egrep  "^configure" | cut -d: -f2) --add-dynamic-module=../ngx_brotli

if error: ./configure: error: invalid option "-fomit-frame-pointer"

./configure \
$(nginx -V 2>&1 | tail -1 | sed -e 's/configure arguments://' -e "s/ --with-cc-opt='-Os -fomit-frame-pointer -g'//" -e 's| --add-dynamic-module=[^ ]*||g') \
--add-dynamic-module=../ngx_brotli
lincyim commented 11 months ago

Specifying the flags explicitly at the build step ( instead of using $(nginx -V) ) solved the problem. The module loads now. Thank you.

Thanks for saving me tons of time!!

blind-oracle commented 10 months ago

Just FYI e.g. missing a PCRE library during geoip2 module build would also cause this error, even if you use correct flags from nginx -V