Reduce nginx size when compiled with openssl on embedded target - nginx

I need to reduce the size of nginx when compiled with openssl on an embedded target.
I am able to compile the nginx with ssl using the steps given in the http://wiki.nginx.org/InstallOptions. It compiles well, but the problem I am facing its size, i.e nginx binary coming to almost 6MB.
Since I have to run the nginx on the embedded target, I tried cross compiling with for arm based board. I am to cross compile and the size is coming to 1.3MB for the target.
If I disable openssl and compile its coming to 400KB, I think nginx is statically linking the openssl .
If so how to dynamically include the openssl to nginx, because my target libs already has the support for crypto and ssl libs. I tried all the option but could not succeeded.

If so how to dynamically include the openssl to nginx
You need to specify OpenSSL with:
--with-http_ssl_module
The above command will effective link against the OpenSSL shared object if available.
ngingx can also build OpenSSL for you with:
--with-openssl
I seem to recall some problems with --with-openssl (but I think they were related to the FIPS Capable OpenSSL Library).
To be certain you link against the shared object, you can run the following script on the nginx sources:
OPENSSL_INSTALL_DIR=/usr/local/ssl
OPENSSL_LIB_DIR="$OPENSSL_INSTALL_DIR/lib"
...
for FILE in "auto/lib/sha1/conf" "auto/lib/md5/conf" "auto/lib/openssl/conf"
do
TFILE=`mktemp /tmp/fix.XXXXXXXXXX`
sed -e "s|-lssl|$OPENSSL_LIB_DIR/libssl.so|g" "$FILE" > "$TFILE"
mv "$TFILE" "$FILE"
TFILE=`mktemp /tmp/fix.XXXXXXXXXX`
sed -e "s|-lcrypto|$OPENSSL_LIB_DIR/libcrypto.so|g" "$FILE" > "$TFILE"
mv "$TFILE" "$FILE"
done
That will ensure the linker links against a specific OpenSSL, and not just the one it finds (I've had a lot of trouble with -L, -l, -static and -shared in the past when cross compiling).
nginx binary coming to almost 6MB.
...
and the size is coming to 1.3MB for the target.
I'm not sure how small the size can get with OpenSSL present. The following may (or may not) reduce it further.
If you compile and link with the static archive, then you also have some compiler and linker options available to you. Specifically, you can discard unused functions with gc-sections:
--with-cc-opt="-ffunction-sections -fdata-sections"
--with-ld-opt="-Wl,--gc-sections"
You also have the strip option. You can run strip -s on the final binary or pass it to the linker though options:
--with-ld-opt="-Wl,-s"
See ld(1) and --strip-debug and --strip-all options.
-Bsymbolic might also help by reducing an ELF section size (I think its either the GOT or PLT, but I don't recall at the moment).

Related

Compiling Jaeger gRPC proto files with Python

I'm currently playing around with Jaeger Query and trying to access its content through the API, which uses gRPC. I'm not familiar with gRPC, but my understanding is that I need to use the Python gRPC compiler (grpcio_tools.protoc) on the relevant proto file to get useful Python definitions. What I'm trying to do is find out ways to access Jaeger Query by API, without the frontend UI.
Currently, I'm very stuck on compiling the proto files. Every time I try, I get dependency issues (Import "fileNameHere" was not found or has errors.). The Jaeger query.proto file contains import references to files outside the repo. Whilst I can find these and manually collect them, they also have dependencies. I get the impression that following through and collecting each of these one by one is not how this was intended to be done.
Am I doing something wrong here? The direct documentation through Jaeger is limited for this. The below is my basic terminal session, before including any manually found files (which themselves have dependencies I would have to go and find the files for).
$ python -m grpc_tools.protoc --grcp_python_out=. --python_out=. --proto_path=. query.proto
model.proto: File not found.
gogoproto/gogo.proto: File not found.
google/api/annotations.proto: File not found.
protoc-gen-swagger/options/annotations.proto: File not found.
query.proto:20:1: Import "model.proto" was not found or had errors.
query.proto:21:1: Import "gogoproto/gogo.proto" was not found or had errors.
query.proto:22:1: Import "google/api/annotations.proto" was not found or had errors.
query.proto:25:1: Import "protoc-gen-swagger/options/annotations.proto" was not found or had errors.
query.proto:61:12: "jaeger.api_v2.Span" is not defined.
query.proto:137:12: "jaeger.api_v2.DependencyLink" is not defined.
Thanks for any help.
A colleague of mine provided the answer... It was hidden in the Makefile, which hadn't worked for me as I don't use Golang (and it had been more complex than just installing Golang and running it, but I digress...).
The following .sh will do the trick. This assumes the query.proto file is a subdirectory from the same location as the script below, under model/proto/api_v2/ (as it appears in the main Jaeger repo).
#!/usr/bin/env sh
set +x
rm -rf ./js_out 2> /dev/null
mkdir ./js_out
PROTO_INCLUDES="
-I model/proto \
-I idl/proto \
-I vendor/github.com/grpc-ecosystem/grpc-gateway \
-I vendor/github.com/gogo/googleapis \
-I vendor/github.com/gogo/protobuf/protobuf \
-I vendor/github.com/gogo/protobuf"
python -m grpc_tools.protoc ${PROTO_INCLUDES} --grpc_python_out=./python_out --python_out=./python_out model/proto/api_v2/query.proto
This will definitely generate the needed Python file, but it will still be missing dependencies.
I did the following to get the Jaeger gRPC Python APIs:
git clone --recurse-submodules https://github.com/jaegertracing/jaeger-idl
cd jaeger-idl/
make proto
Use the files inside proto-gen-python/.
Note:
While importing the generated code, if you face the error:
AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'
Do:
pip3 install --upgrade pip
pip3 install --upgrade protobuf

How do I know if Qt links against openssl, and which one?

Looking at the libs (:/Qt/5.11.0/5.11.0/gcc_64/lib/) of Qt5.11.0, I was wondering which one was linking openssl. So I ran the following:
for lib in `ls *.so`; do ldd $lib | grep ssl; done
And I got no output, suggesting that none of the libraries are linking against openssl. But I believe that Qt must link against it somehow (e.g. for networking).
How is the linking done? And where does it look for openssl? Do I have a way to know which one Qt found on my system (e.g. given I have multiple ones)?
Qt links some libraries dynamically at runtime. In order to see which libraries are loaded, one can check the diagnostic output of the dynamic linker, as hinted by Matteo:
Say my executable is called QGroundcontrol:
On Linux:
LD_DEBUG=libs ./QGroundcontrol 2>&1 | grep -E "ssl|crypto"
On macOS:
DYLD_PRINT_LIBRARIES=1 ./QGroundcontrol 2>&1 | grep -E "ssl|crypto"
From this I could see that Qt finds openssl on the system.
Now, I still don't know how I can tell Qt to look somewhere else (in case I want to link another openssl), but that's another question.

libcrypto.so.10: cannot open shared object file: No such file or directory

I am trying to install ODBC driver for Debian arrording to these instructions: https://blog.afoolishmanifesto.com/posts/install-and-configure-the-ms-odbc-driver-on-debian/
However trying to run:
sqlcmd -S localhost
I get the error
libcrypto.so.10: cannot open shared object file: No such file or
directory
What could be the cause?
So far I have tried
1.
$ cd /usr/lib
$ sudo ln -s libssl.so.0.9.8 libssl.so.10
$ sudo ln -slibcrypto.so.0.9.8 libcrypto.so.10
2.
/usr/local/lib64 to the /etc/ld.so.conf.d/doubango.conf file
3.
sudo apt-get update
sudo apt-get install libssl1.0.0 libssl-dev
cd /lib/x86_64-linux-gnu
sudo ln -s libssl.so.1.0.0 libssl.so.10
sudo ln -s libcrypto.so.1.0.0 libcrypto.so.10
4. Sudo apt-get install libssl0.9.8:i386
None of these have helped.
As I'm quite familiar with Debian and programming, here is some advice:
if you have questions about setting up your system, ask on SuperUser and/or (if your question is specific to a Un*x flavour) on Unix&Linux
when fuddling around with symlinks to shared-libraries, you should have a thorough understanding of what you are doing. these files are named for a reason - and the reason is to protect you (the user of the system) from weird crashes, because an application is using a wrong/incompatible library.
a tutorial that tells you to do so, should give proper warning and explanation about what you are to do.
So, why are these instructions in the tutorial you are following?
The application you are trying to run, has been linked against libcrypto.so.
On the developer machine (that was used to produce the application binary), libcrypto.so was a symlink to libcrypto.so.10, but this is missing on Debian: maybe because the library has been removed (and replaced by a new and incompatible version), or because Debian uses a different naming scheme as compared to the system that was used to compile the application.
If it is the former, then you cannot solve the issue by using symlinks.
You have to get the right library (or the application linked against the correct libraries).
If it is the latter, you may get away with symlinking the expected library name with the correct library files found on your system. (This is assuming that the only difference between the two systems is indeed the so-naming scheme).
So, how to do it?
first of all, you should find out, against which libraries your application was really linked, and which of these libraries are missing.
$ ldd /path/to/my/app | grep -i "not found"
libfoo.so.10 => not found
then find out, whether you have a (hopefully compatible) library on your system. A good place to start is /usr/lib/. but not-so-recently, Debian has started moving the libraries to /usr/lib/<host-triplet>, with <host-triplet> describing a target architecture. You can find out the default value if your application was indeed built for the architecture you are running (e.g. for linux-amd64) you can get the string by running something like:
$ gcc -print-multiarch
Imagine you discover that you have /usr/lib/x86_64-linux-gnu/libfoo.so.1.0.0.
if you have good reason to believe that this can act as a replacement for libfoo.so.10, you can go make the found library available to your application by means of a symlink, e.g.
# cd /usr/local/lib/
# ln -s /usr/lib/x86_64-linux-gnu/libfoo.so.1.0.0 libfoo.so.10
Finally, you might need to refresh the cache of the dynamic linker so it starts using the new library, by running ldconfig as root/superuser.

Unix CouchDB installation + KERL

I am attempting to install CouchDB on my planetlab Unix machines from the source packages.
I installed Erlang r16b01 using Kerl: http://docs.basho.com/riak/1.3.0/tutorials/installation/Installing-Erlang/#Install-using-kerl
I installed openssl from the source package.
So, I ran "./configure --with-erlang=path/to/erlang/using/kerl" and I get the error
"configure: error: Could not find the Erlang crypto library"
This error indicates that Erlang was not compiled with OpenSSL support.
So, I tried using
"KERL_CONFIGURE_OPTIONS=--with-ssl=path/to/openssl/lib"
(Not sure if I'm using the above command correctly)
Then, reinstalled and reactivated Erlang.
This still brings up the same error.
I checked if Erlang if it could execute "crypto.start()", and it let me type the command, but it doesn't have a reply "ok" like in the documention: http://dennisreimann.de/blog/installing-couchdb-and-erlang-on-ubuntu-hardy/
Please help!
1) Did you first create a user couchdb and then do everything as that user? Including erlang build and install? That might be easier.
2) There is an error in your test, you need to terminate your command in the erl shell with a dot, otherwise you get no responce, like you already noticed. crypto:start(). is correct:
$ erl
Eshell V6.1 (abort with ^G)
1> crypto:start().
** exception error: undefined function crypto:start/0
After a successful build and installation it will respond ok:
$ erl
Eshell V6.1 (abort with ^G)
1> crypto:start().
ok
And you can also stop it afterwards:
2> crypto:stop().
ok
3>
=INFO REPORT==== 10-Aug-2014::20:22:06 ===
application: crypto
exited: stopped
type: temporary
3) You need the development package of OpenSSL including the header files as well as the binary command program openssl. At least version 0.9.8 of OpenSSL is required. As a sidenote for people who are on debian and ubuntu, it is usually enough to run:
sudo apt-get install openssl libssl-dev
In your case, you should somehow make sure that your openssl source install includes all the above (openssl binaries, header files).
4) Most probably it could be an issue with finding the libraries. I recommend reading this answer, which deals with a unix based system, and it could point you to the right direction:
https://stackoverflow.com/a/14776521/362951
Depending on the error message after the crypto:start(). you could try to somehow add the path and logout of the shell and relogin and then activate kerl and try again. No need to rebuild if it was present and found at compile time.
5) Your kerl configuration looks good. Again using debian/ubuntu paths a ~/.kerlrc could look like
KERL_CONFIGURE_OPTIONS="--with-ssl=/usr/lib/ssl"
And hopefully the ssl path you are inserting is the correct one.
You could also try and omit the path, maybe it finds the correct one by itself. On http://www.erlang.org/doc/installation_guide/INSTALL.html it looks like it is valid to do so:
KERL_CONFIGURE_OPTIONS="--with-ssl"
Currently kerl silently produces a build without crypto if it fails to find the headers https://github.com/yrashk/kerl/issues/31
6) I see you are giving the --with-erlang parameter to couchdb, does it point to the right directory? Or maybe it needs to go one level deeper or one level up.
Otherwise possibly an older, system. wide erlang could be used, if found.
Also I am not sure if the combination of a kerl environment and passing the erlang location using the --with-erlang parameter to couchdb works. I did not try the --with-erlang parameter with kerl, because I activate the kerl environment before compiling couchdb and then again before the couchdb start script.

Compiling an OpenCL program using a CL/cl.h file

I have sample "Hello, World!" code from the net and I want to run it on the GPU on my university's server. When I type "gcc main.c," it responds with:
CL/cl.h: No such file or directory
What should I do? How can I have this header file?
Are you using Ubuntu or Debian distro? Then you could use this package to solve the problem with missing header file:
apt-get install opencl-headers
You must install opencl library to solve linking issues using that Debian and Ubuntu package:
apt-get install ocl-icd-libopencl1
You can also use these nonfree libraries: nvidia-libopencl1 (Debian) or nvidia-libopencl1-xx (Ubuntu).
Make sure you have the appropriate toolkit installed.
This depends on what you intend running your code on. If you have an NVidia card then you need to download and install the CUDA-toolkit which also contains the necessary binaries and libraries for opencl.
Are you running Linux? If you believe you already have OpenCL installed it could be that it is found at a different location than the standard /usr/include. Type the following and see what results you get:
find / -iname cl.h 2>/dev/null
On my laptop for example, the header is found at /usr/local/cuda-5.5/include. If its the case were your header file is at a different location you simply have to specify the path during complication
g++ -I/usr/local/cuda-5.5/include main.c -lOpenCL
Alternatively, you can create a symbolic link from the path to /usr/include:
ln -s /usr/local/cuda-5.5/include/CL /usr/include

Resources