Skip to content

Conversation

@AlexTMjugador
Copy link

@AlexTMjugador AlexTMjugador commented Dec 30, 2025

First of all, thank you for your work on this project, which makes convenient administration of SSO homelab Vaultwarden setups possible outside of commercial offerings! ❤️

I think it's easy to agree that first-class ARM64 architecture support for published Docker images is becoming increasingly relevant. Beyond the obvious niche of tinkerers using SBCs like the Raspberry Pi or other embedded devices, ARM64 CPUs are now found in all recent Macs (where they are branded as "Apple Silicon") as well as in several low-cost cloud VM offerings. In fact, I've been running vaultwarden_ldap on an ARM64-based server for a while now, but the convenience was lackluster because it either required building vaultwarden_ldap from source for that architecture or setting up QEMU for runtime emulation (which can be a workable solution in my experience, at the cost of significant CPU usage spikes and overhead).

Therefore, I decided to spend some time adapting the Dockerfile to support transparent cross-compilation of the project, following guidelines from several pieces of authoritative documentation12345. I strived to keep all observable behavior of the resulting binaries intact, but there are a few notable changes in other regards that I'd like to highlight:

  • Due to the use of the xx cross-compilation helpers, clang and lld are now used to compile C code and link the resulting objects. The clang toolchain is much better suited for cross-compilation and otherwise behaves as a mostly drop-in replacement for gcc/ld, though, generating functionally equivalent binaries.
  • For simplicity, I migrated from a two-step (dependency build + project build) to a single step project build process. However, I realized that the original two-step approach was likely intended to improve Docker layer caching efficiency during recompilation, so I added all the cache mounts that Cargo can leverage to avoid unnecessary work. In my testing, the end result is effectively equivalent to repeatedly running cargo build outside a container: dependencies are neither re-downloaded nor recompiled unless required.
  • I switched the final base image from the latest Ubuntu LTS to Wolfi. I chose this image because it best met my desired criteria: being well maintained; already including CA certificates, OpenSSL, and glibc (so no QEMU setup on the build host is required to support RUN instructions that install them, ruling out slim Debian and Ubuntu images as well as Alpine, which is musl-based); providing a shell and basic POSIX utilities (to simplify debugging, health checks, and similar tasks, which ruled out Google's distroless images); and being lightweight (compressed layers of ~6 MiB versus ~28 MiB).
  • I also configured CI's docker/build-push-action to store the layer cache in the GitHub Actions cache. This should help carry some of the benefits of faster recompilation with warm caches over to CI workflows.

While doing the above work, I also stumbled upon two unrelated issues that prevented CI from passing, so I took the liberty of addressing them as well:

  • Bitnami deleted all of their bitnami/openldap images after deciding they were no longer willing to tolerate hassle-free downloads from Docker Hub. Unfortunately, the new bitnamisecure organization does not provide an OpenLDAP image, and every publicly available alternative I could find would have required a relatively large migration effort for the purposes of this PR. Therefore, I switched the image to bitnamilegacy/openldap, which should, for the time being, be recent enough to keep all development workflows running with minimal changes.
  • I also fixed a number of Clippy lints.

Finally, I tested this entire PR by publishing the generated multi-platform Docker image to the GitHub Container Registry of my vaultwarden_ldap fork, where you can verify that all CI steps complete successfully. I've also successfully deployed the new generated ARM64 images to my ARM64 server.

Footnotes

  1. https://docs.docker.com/build/building/multi-platform/

  2. https://doc.rust-lang.org/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci

  3. https://docs.docker.com/reference/dockerfile#run---mounttypecache

  4. https://github.com/tonistiigi/xx/tree/master

  5. https://github.com/rust-lang/pkg-config-rs?tab=readme-ov-file#external-configuration-via-target-scoped-environment-variables

Bitname decided to limit distribution of such an image to a commercial
subscription. Needless to say, this project isn't going to pay for such
a subscription.

There is an alternative image packaged by CleanStart, but it lacks the
amenities used in this codebase for setting up the LDAP server. I'd
also like to avoid migrating to e.g. LLDAP because that's a too big
endeavor for the purposes of getting CI working again.

Therefore, let's switch to the `bitnamilegacy` organization for now, as
having a very up to date OpenLDAP server is not critical for development
and running tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant