mjl- / mox

modern full-featured open source secure mail server for low-maintenance self-hosted email
https://www.xmox.nl
MIT License
3.69k stars 110 forks source link

Build mox release #201

Closed lmeunier closed 3 months ago

lmeunier commented 3 months ago

According to the README.md file, I can either build mox with the command GOBIN=$PWD CGO_ENABLED=0 go install github.com/mjl-/mox@latest or download it from beta.gobuilds.org where an other build command is given (GO19CONCURRENTCOMPILATION=0 GO111MODULE=on GOPROXY=https://proxy.golang.org/ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOTOOLCHAIN=go1.23.0 go1.23.0 install -trimpath -ldflags='-buildid=' -- github.com/mjl-/mox@v0.0.11);

According to the Docker.release file, the command CGO_ENABLED=0 GOOS=$goos GOARCH=$goarch go install -mod mod -trimpath github.com/mjl-/mox@$moxversion is used to build mox, the result is then copied to the Docker image.

And according to the Makefile, the command make build builds mox twice, builds a nodejs frontend and runs some shell scripts.

So, I'm wondering what is the proper way to build a mox release and what are the differences between methods listed above.

mjl- commented 3 months ago

Ah yes, that's quite some variation. (:

The basic way to compile the latest mox release would be go install github.com/mjl-/mox@latest. That fetches the mox code as Go module through the Go module proxy, resolving "latest" to the current latest version (git tag).

The command in the README adds GOBIN=$PWD so the binary ends up in the working directory instead of the Go default of writing it to $HOME/go/bin. For Go developers, that default probably makes sense, but for non-Go-developers compiling mox themselves it's not helpful if the binary goes to some other location.

CGO_ENABLED=0 is added everywhere to prevent linking with C libraries. Compilation works fine without. But then the binary may depend on a local libc, and may prevent the binary from working on other machines with other libc's. The Go runtime may use the libc DNS resolver for some lookups (those that aren't going through the adns library, with CGO_ENABLED=0 they go through the Go stdlib resolver). This is in all the versions of the commands to compile, so it's probably not causing confusion.

The command shown on beta.gobuilds.org has more options to make the compilation reproducible, resulting in the exact same binary (identical bytes). The command has become a bit obscure, so I think it's not worth the obscurity to put the same command in the mox README. Details about the flags and env vars in the command on beta.gobuilds.org:

The Docker.release file has -trimpath for reproducibility (and the resulting docker image doesn't have the source anyway). The Go toolchain path is the same, so removing the buildid isn't needed. The -mod mod ensures the local vendor/ directory (with all dependencies) isn't used, but all dependencies are downloaded. This is how go install github.com/mjl-/mox@latest would build mox (the mox code is fetched from the Go module proxy, which does not include the vendor/ directory), and it's how the gobuilds.org service builds code. So it's to be closer to those builds.

The Makefile indeed builds twice: After the first build commands, the resulting binary is used to generate help output and API JSON & TS/JS files, and those are included in the binary in the second build. Those generated files are committed to git, so for building using "go install" we don't need to do a second build.

I consider the binaries from gobuilds.org to be the most authoritative releases. The binaries are reproducible, and it's the easiest way to get a binary for the most recent Go toolchain release (its runtime is included in the resulting mox binary). Building it locally is fine too, but there's a small risk that people have a somewhat older local Go toolchain/runtime installed.

lmeunier commented 3 months ago

Many thanks for taking the time to give such a complete and comprehensible reply. It makes sense now.