/nim/lib/wrappers/openssl.nim(373) sslSymNullable
/nim/lib/wrappers/openssl.nim(347) sslModule
Error: unhandled exception: Could not load SSL using libssl.so(.3|.1.1|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|.48|.47|.46|.45|.44|.43|.41|.39|.38|.10|) [LibraryError]
I would like to have an explanation for this error.
I have now played around with different, possible solutions for a very long while & it still does not work.
My program compiles on Debian, but not in an Alpine Docker Container. No matter, which SSL/TLS related package I install, it never works. I have tried at least 10 different SSL/TLS related library editions.
Also tried to provide -L & --path options to the compiler, to no avail.
I don't even know, if the above error means, the loaded library is not as expected or if it is straight up not found.
Am on nimlang/nim:1.6.14-alpine.
How can I make this work?
The easiest way to use SSL with musl (default alpine C library) is this repo: https://github.com/kaushalmodi/hello_musl
Just copy 'config.nims' file to your project directory. Then you could use musl task to build:
nim musl foo.nim
If you add -d:pcre, -d:openssl or -d:libressl arguments, it will download source of these libraries, compile them against musl and link them statically.Thanks for the suggestion. Wasn't easy to apply this fix, as it needed some adjustments.
I'm getting this error, which I had seen before, along my journey to getting this fixed, at some point, already.
@m..@s..@snim@slib@[email protected]:52: undefined reference to `SSL_get1_peer_certificate'
It sounds like a version mismatch, but that wouldn't make sense with Nim.
For now, the issue does not appear anymore.
My program worked. Then TLS stopped working in Alpine. A day later it stopped working on the dev machine, too. Been trying to figure out the solution, since then. I had created a backup of the non-working setup, which has worked before.
Now, it started working, miraculously. I backtracked all changes, I made, but none seemed to make the difference.
I restored the backup of the previously non-working setup. It works now.
Nothing in my environment changed. I literally didn't even run a system package upgrade. Nothing. My environment is literally the same it was when it worked in the beginning, when it did not work anymore & now.
Therefore, this must be some inherent issue in the standard library's smtp library or something, with some race condition & version problem. This library had recent commits, which changed SSL behaviour.
There is no other logical explanation. My environment literally did not change. Besides that, the Docker environment has provably not changed, either. It must be some inherent flaw in Nim's standard library.
Well, SSL_get1_peer_certificate only exists in OpenSSLv3. So it's likely that you somehow were compiling against OpenSSL 1.1 headers.
It may be the case that you only have 1.1 installed; Nim can do either out of the box, but if you were looking for 3, but it wasn't installed, you'd get an error like that.
etc.............
It's a whole mess & in the end I have proven, that it may work on Alpine SSL/TLS editions, but not on Debian's 1.1 version, since the commit in the standard library's smtp module, which changed SSLContext behaviour.
Therefore, those new changes make the module incompatible with some SSL/TLS library editions & versions.
I don't think it'll massively help here, but on the off chance it does: I do use openssl with the smtp module for webdev in an alpine container, but only dynamically linked.
I compile with
...
--gcc.exe:"musl-gcc"
--gcc.linkerexe:"musl-gcc"
--define:ssl
...
And my alpine dockerfile includes instructions to install openssl: RUN apk add openrc nginx sqlite-libs nginx-mod-http-upload-progress openssl bash libsodium
That generally works out for me.
you need --dynliboverride to avoid dlopen and only use static lib
Or use -Wl,-Bstatic -lssl -Wl,-Bdynamic
IIRC, that doesn't work for openssl 3, it still dlopens in all cases.
There are other things like getaddrinfo and dlopen itself where Nim seems to require the dynamic library even if statically linking.
It should be much easier to force static linking, and actually not have dynamic dependencies; lots of places want to be able to drop a binary without dependencies into an alpine container, and the only way we've been able to make that happen is by a lot of low-level hackery.
I take it back, OpenSSL wasn't the issue, it was -lc (for getaddrinfo in particular) and -ldl (for dlopen itself).
So calling either of these two functions in a static binary seems to result in the corresponding library being dlopened even if statically linked, at least according to the compiler's own output. It does seem to load these; our wrapper essentially keeps the .o's in the binary, and we wrap __open64_nocancel to unload and link them if needed. But again, so far that's only been for libc.so and ld-linux-whatever.so.
But OpenSSL3 itself works just fine with (in our nimble file):
var
libDir = staticExec("pwd") & "/lib/"
libs = [""ssl", "crypto"]
flags = ""
when defined(linux):
flags = "--passL:-static"
for item in libs:
let libFile = "lib" & item & ".a"
flags &= " --passL:" & libDir & libFile
flags &= " --dynlibOverride:" & item
task buildit, "Build it for real":
flags = " --define:release --opt:size " & flags
exec "nimble build " & flags
Then you just need to run nimble buildit.
The order does matter; if you put libcrypto before libssl, then the linker fails to resolve symbols.