Advantages / disadvantages of a fully static binary?

The default Go build will create a slightly dynamically linked when using net stuff;

jb@build2:~$ ldd /usr/local/bin/go
        lx_vdso.so.1 =>  (0x00007fffff0b0000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ffffee00000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffffea00000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fffff200000)

I know we do this to get access to the system DNS resolver, among other things. I’m not sure about libpthread - I guess that’s always the underlying thread library, and we just link it statically when building static binaries?

But what are the disadvantages to a fully static binary, on Linux1? Is the built in resolver noticeably worse at some things (perhaps like v6/v4 preference things or so)? Are there other differences? I’m assuming there is a disadvantage, or the default would be to build fully static?

1) I know there are other differences on other systems, in particular with loading root certs on Mac etc.

I saw a fully static binary fail this week on Linux when that distro had the root certificates stored in an odd location; the system resolver of course knew where they were but the Go std lib was not able to find them. (But the user was able to fix it by installing the distro’s root certs at the standard place.) At least, I think that’s what happened based on the error message and how the user told me he fixed it.

But that kind of error is rare.

Huge advantage of fully static binary that I keep hearing is ability to run in stripped down containers.

This isn’t related to a static binary unless the target is OSX which requires cgo (and hence dynamic linking) to access the system keystore.

1 Like

So no real disadvantages on Linux any more, that we are aware of? Merely a historic artifact that we link against libc?

For server deployments, none that I can think of.

1 Like

Fully static binary is only good for web development and deployment. It’s not good for desktop applications, as it will add software distribution size that uses more bandwidth and hard disk.

what’s the most serious problem is that when there’s a security bug in a dependency library, users and system administrators don’t know what packages are affected because there’s only one static binary no other info about its dependence. And even if they know they would upgrade all related packages and that maybe much bigger than dynamically linked packages. With dynamically linked packages, only the buggy library need to be upgraded

1 Like

Any you can think of for more client style software deployments? That’s my target demographic. :wink:

That’s all sound in general, but in practice the binary is rather large to begin with and the difference doesn’t much matter. And the only real external deps we link against is libpthread and libc for the resolver (as I understand it), so not that much to update.

1 Like

The main disadvantage of using static linking – which in my mind means “disable cgo” means

a. you don’t get access to a few functions in the os package, mainly those that integrate with libnss to lookup usernames via ldap or the other nsswitch mechanisms
b. you don’t get access to the libc name resolver. For server processes this is almost certainly a win, Go has shown bugs on every single dns resolution library on every platform, some remain unfixed today. But on the client, you might need avahi/mdbs/bonjour and that is again via libnss and the nsswitch mechanisms. If you build statically your client may not be able to resolve names like jacob-borgs-macboox-pro.local. I cannot judge how big an issue this will be in practice.

My 5 second summary; link statically everywhere but OSX.

3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.