# Alpine-based MUSL static binary builder for C-Relay # Produces truly portable binaries with zero runtime dependencies FROM alpine:3.19 AS builder # Install build dependencies RUN apk add --no-cache \ build-base \ musl-dev \ git \ cmake \ pkgconfig \ autoconf \ automake \ libtool \ openssl-dev \ openssl-libs-static \ zlib-dev \ zlib-static \ curl-dev \ curl-static \ sqlite-dev \ sqlite-static \ linux-headers \ wget \ bash # Set working directory WORKDIR /build # Build libsecp256k1 static RUN cd /tmp && \ git clone https://github.com/bitcoin-core/secp256k1.git && \ cd secp256k1 && \ ./autogen.sh && \ ./configure --enable-static --disable-shared --prefix=/usr \ CFLAGS="-fPIC" && \ make -j$(nproc) && \ make install && \ rm -rf /tmp/secp256k1 # Build libwebsockets static with minimal features RUN cd /tmp && \ git clone --depth 1 --branch v4.3.3 https://github.com/warmcat/libwebsockets.git && \ cd libwebsockets && \ mkdir build && cd build && \ cmake .. \ -DLWS_WITH_STATIC=ON \ -DLWS_WITH_SHARED=OFF \ -DLWS_WITH_SSL=ON \ -DLWS_WITHOUT_TESTAPPS=ON \ -DLWS_WITHOUT_TEST_SERVER=ON \ -DLWS_WITHOUT_TEST_CLIENT=ON \ -DLWS_WITHOUT_TEST_PING=ON \ -DLWS_WITH_HTTP2=OFF \ -DLWS_WITH_LIBUV=OFF \ -DLWS_WITH_LIBEVENT=OFF \ -DLWS_IPV6=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_C_FLAGS="-fPIC" && \ make -j$(nproc) && \ make install && \ rm -rf /tmp/libwebsockets # Copy c-relay source COPY . /build/ # Clean up any stale submodule references (nips directory is not a submodule) RUN git rm --cached nips 2>/dev/null || true # Initialize submodules and build nostr_core_lib with required NIPs # Disable fortification in build.sh to prevent __*_chk symbol issues # NIPs: 001(Basic), 006(Keys), 013(PoW), 017(DMs), 019(Bech32), 044(Encryption), 059(Gift Wrap - required by NIP-17) RUN git submodule update --init --recursive && \ cd nostr_core_lib && \ chmod +x build.sh && \ sed -i 's/CFLAGS="-Wall -Wextra -std=c99 -fPIC -O2"/CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -Wall -Wextra -std=c99 -fPIC -O2"/' build.sh && \ rm -f *.o *.a 2>/dev/null || true && \ ./build.sh --nips=1,6,13,17,19,44,59 # Build c-relay with full static linking # Disable fortification to avoid __*_chk symbols that don't exist in MUSL RUN gcc -static -O2 -Wall -Wextra -std=c99 \ -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \ -I. -Inostr_core_lib -Inostr_core_lib/nostr_core \ -Inostr_core_lib/cjson -Inostr_core_lib/nostr_websocket \ src/main.c src/config.c src/dm_admin.c src/request_validator.c \ src/nip009.c src/nip011.c src/nip013.c src/nip040.c src/nip042.c \ src/websockets.c src/subscriptions.c src/api.c src/embedded_web_content.c \ -o /build/c_relay_static_musl \ nostr_core_lib/libnostr_core_x64.a \ -lwebsockets -lssl -lcrypto -lsqlite3 -lsecp256k1 \ -lcurl -lz -lpthread -lm -ldl # Strip binary to reduce size RUN strip /build/c_relay_static_musl # Verify it's truly static RUN echo "=== Binary Information ===" && \ file /build/c_relay_static_musl && \ ls -lh /build/c_relay_static_musl && \ echo "=== Checking for dynamic dependencies ===" && \ (ldd /build/c_relay_static_musl 2>&1 || echo "Binary is static") && \ echo "=== Build complete ===" # Output stage - just the binary FROM scratch AS output COPY --from=builder /build/c_relay_static_musl /c_relay_static_musl