Skip to content

Commit 87d8596

Browse files
committed
fix(build): statically link zlib to eliminate libz.so.1 runtime dependency
The release binary pulled in libz.so.1 dynamically through rdkafka-sys and other transitive C dependencies. Minimal base images (Chainguard glibc-dynamic, distroless) don't ship libz, causing the server to fail at startup with a missing shared library error. Force libz-sys to its `static` feature via Cargo's dependency unification so zlib is compiled into the binary. The Dockerfile COPY workaround that patched in a Debian-built libz at image build time is removed. Documentation updated to reflect the [server.tls] config section path. Workspace version bumped to 0.1.1.
1 parent b57f19f commit 87d8596

6 files changed

Lines changed: 48 additions & 50 deletions

File tree

Cargo.lock

Lines changed: 23 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ members = [
2626
resolver = "2"
2727

2828
[workspace.package]
29-
version = "0.1.0"
29+
version = "0.1.1"
3030
edition = "2024"
3131
rust-version = "1.94"
3232
license = "BUSL-1.1"
@@ -133,6 +133,13 @@ loro = "=1.10.8"
133133
# Kafka bridge
134134
rdkafka = { version = "0.36", features = ["cmake-build"] }
135135

136+
# zlib: rdkafka-sys (and other transitive C deps) link libz dynamically by
137+
# default, which makes the release binary depend on libz.so.1 at runtime and
138+
# breaks minimal base images (e.g. Chainguard glibc-dynamic). Force the
139+
# `static` feature on libz-sys via Cargo's feature unification so zlib is
140+
# baked into the binary and the runtime image needs no extra .so files.
141+
libz-sys = { version = "1", features = ["static"] }
142+
136143
# Regex
137144
regex = "1"
138145

@@ -152,9 +159,12 @@ serde_json = "1"
152159
sonic-rs = "0.5"
153160
chrono = { version = "0.4", features = ["std"], default-features = false }
154161

155-
# MessagePack
162+
# MessagePack
156163
rmpv = "1"
157-
zerompk = { version = "0.4", git = "https://github.com/farhan-syah/zerompk", rev = "1dd71a0de6b6c99f2c2dbbc69106bb87b1e2cdcb", features = ["std", "derive"] }
164+
zerompk = { version = "0.4", git = "https://github.com/farhan-syah/zerompk", rev = "1dd71a0de6b6c99f2c2dbbc69106bb87b1e2cdcb", features = [
165+
"std",
166+
"derive",
167+
] }
158168

159169
# Bitmap
160170
roaring = "0.11"

Dockerfile

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,6 @@ USER nonroot:nonroot
4545

4646
COPY --from=builder --chown=nonroot:nonroot /build/target/release/nodedb /usr/local/bin/nodedb
4747

48-
# nodedb dynamically links libz.so.1 (transitively via crates that default to
49-
# system zlib — e.g. flate2 with its default `zlib` feature). Chainguard's
50-
# glibc-dynamic ships only glibc + libgcc + ca-certs + tzdata, so the runtime
51-
# fails immediately with: "error while loading shared libraries: libz.so.1:
52-
# cannot open shared object file: No such file or directory".
53-
#
54-
# Copy the Debian builder's libz into a default ld.so search path. The glob
55-
# covers both amd64 and arm64 — per-arch builds only see their own multiarch
56-
# directory, so exactly one match per build.
57-
#
58-
# Long-term cleanup options (any of these would let us drop this COPY):
59-
# * Switch flate2 (and any other zlib-using deps) to the `rust_backend`
60-
# feature so libz becomes a build-time C lib statically linked.
61-
# * Or vendor libz via the `libz-sys` `static` feature.
62-
# * Or move runtime to `cgr.dev/chainguard/wolfi-base` + `apk add zlib`.
63-
COPY --from=builder /lib/*-linux-gnu/libz.so.1 /usr/lib/libz.so.1
64-
6548
# Bind to all interfaces (required for Docker port mapping)
6649
# Point data dir at the declared volume
6750
ENV NODEDB_HOST=0.0.0.0 \

docs/protocols.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -286,24 +286,24 @@ Native opcodes are used internally by the Rust SDK (`nodedb-client`), FFI bindin
286286
### Default behaviour
287287

288288
All five listeners (`pgwire`, `native`, `http`, `resp`, `ilp`) default to
289-
**plaintext** when no `[tls]` section is present in the configuration file.
289+
**plaintext** when no `[server.tls]` section is present in the configuration file.
290290
This is suitable for local development and for deployments where TLS is
291291
terminated at an external load balancer or sidecar proxy.
292292

293-
**Production deployments MUST configure `[tls] cert_path` and
294-
`[tls] key_path`** whenever clients connect over any untrusted network.
293+
**Production deployments MUST configure `[server.tls] cert_path` and
294+
`[server.tls] key_path`** whenever clients connect over any untrusted network.
295295
Without TLS, credentials (including SCRAM-SHA-256 client proofs), query
296296
text, and result data are transmitted in plaintext.
297297

298298
### Enabling TLS
299299

300300
```toml
301-
[tls]
301+
[server.tls]
302302
cert_path = "/etc/nodedb/tls/server.crt"
303303
key_path = "/etc/nodedb/tls/server.key"
304304
```
305305

306-
When `[tls]` is present, TLS is enabled on all five listeners by default.
306+
When `[server.tls]` is present, TLS is enabled on all five listeners by default.
307307
The certificate must be PEM-encoded. Generate a self-signed cert for
308308
testing with `openssl req -x509 -newkey rsa:4096 -nodes ...` or a
309309
production certificate from any ACME-compatible CA.
@@ -313,7 +313,7 @@ production certificate from any ACME-compatible CA.
313313
Individual listeners can opt out of TLS using the per-protocol flags:
314314

315315
```toml
316-
[tls]
316+
[server.tls]
317317
cert_path = "/etc/nodedb/tls/server.crt"
318318
key_path = "/etc/nodedb/tls/server.key"
319319
pgwire = true # default when [tls] is set
@@ -332,7 +332,7 @@ NodeDB watches cert/key files for modification-time changes and atomically
332332
swaps the TLS configuration without restarting listeners:
333333

334334
```toml
335-
[tls]
335+
[server.tls]
336336
cert_path = "/etc/nodedb/tls/server.crt"
337337
key_path = "/etc/nodedb/tls/server.key"
338338
cert_reload_interval_secs = 3600 # default: 1 hour; 0 to disable

docs/security/auth.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ For zero-trust environments. Both client and server present certificates.
7777
Configure in `nodedb.toml`:
7878

7979
```toml
80-
[tls]
80+
[server.tls]
8181
cert = "/path/to/server.crt"
8282
key = "/path/to/server.key"
8383
client_ca = "/path/to/ca.crt" # enables mTLS

nodedb/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ snap = { workspace = true }
8888
flate2 = { workspace = true }
8989
tonic = { workspace = true }
9090
rdkafka = { workspace = true }
91+
# Direct dep purely so the workspace's `libz-sys` feature set (with `static`)
92+
# applies via Cargo feature unification — keeps zlib statically linked into
93+
# the release binary so runtime images don't need libz.so.1.
94+
libz-sys = { workspace = true }
9195

9296
# Password hashing & cryptography
9397
argon2 = { workspace = true }

0 commit comments

Comments
 (0)